diff --git a/.changeset/beige-geckos-explode.md b/.changeset/beige-geckos-explode.md new file mode 100644 index 00000000000..9f06a9c989b --- /dev/null +++ b/.changeset/beige-geckos-explode.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#updated Gracefully fail if CL_DATABASE_URL is not set. diff --git a/.changeset/brave-frogs-greet.md b/.changeset/brave-frogs-greet.md deleted file mode 100644 index 907e8f1ee75..00000000000 --- a/.changeset/brave-frogs-greet.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -update plugin and evm chainwriter to remove evmConfig dependency #updated diff --git a/.changeset/breezy-suits-float.md b/.changeset/breezy-suits-float.md deleted file mode 100644 index 60e061223d8..00000000000 --- a/.changeset/breezy-suits-float.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#added address book remove feature diff --git a/.changeset/clever-knives-tap.md b/.changeset/clever-knives-tap.md new file mode 100644 index 00000000000..8683e89f77d --- /dev/null +++ b/.changeset/clever-knives-tap.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#added Sei config and error mapping diff --git a/.changeset/cold-coats-battle.md b/.changeset/cold-coats-battle.md new file mode 100644 index 00000000000..1a72d025bde --- /dev/null +++ b/.changeset/cold-coats-battle.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal minor rename of various gethwrappers diff --git a/.changeset/cold-pillows-sleep.md b/.changeset/cold-pillows-sleep.md new file mode 100644 index 00000000000..45e4e999111 --- /dev/null +++ b/.changeset/cold-pillows-sleep.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Extract EVM MultiNode to chainlink-framework. #internal diff --git a/.changeset/cool-feet-happen.md b/.changeset/cool-feet-happen.md deleted file mode 100644 index 8d4aa22e79c..00000000000 --- a/.changeset/cool-feet-happen.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Ensure RPCClient with enabled polling respects health check flag #internal diff --git a/.changeset/cool-owls-laugh.md b/.changeset/cool-owls-laugh.md deleted file mode 100644 index a3667ed20e0..00000000000 --- a/.changeset/cool-owls-laugh.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Bump to start the next version diff --git a/.changeset/cuddly-turtles-arrive.md b/.changeset/cuddly-turtles-arrive.md new file mode 100644 index 00000000000..81ceed3e8ff --- /dev/null +++ b/.changeset/cuddly-turtles-arrive.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal adding solana devnet to ccip deployment diff --git a/.changeset/cyan-hairs-obey.md b/.changeset/cyan-hairs-obey.md deleted file mode 100644 index 8bff6c8aad0..00000000000 --- a/.changeset/cyan-hairs-obey.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#added support enable and disable feed manager diff --git a/.changeset/cyan-ladybugs-check.md b/.changeset/cyan-ladybugs-check.md new file mode 100644 index 00000000000..d430890001a --- /dev/null +++ b/.changeset/cyan-ladybugs-check.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +validates response from gateway in workflow/fetcher diff --git a/.changeset/eight-meals-march.md b/.changeset/eight-meals-march.md new file mode 100644 index 00000000000..f2439280063 --- /dev/null +++ b/.changeset/eight-meals-march.md @@ -0,0 +1,7 @@ +--- +"chainlink": patch +--- + +Prevents a panic in test helper for confirming transaction +and adds encrypted public key to a peer before calling addNodes +on CapabilitiesRegistry diff --git a/.changeset/eighty-geckos-switch.md b/.changeset/eighty-geckos-switch.md new file mode 100644 index 00000000000..b67dfb0ec79 --- /dev/null +++ b/.changeset/eighty-geckos-switch.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Reduce PriceMin on Avalanche to 1 gwei #nops diff --git a/.changeset/eleven-cheetahs-care.md b/.changeset/eleven-cheetahs-care.md new file mode 100644 index 00000000000..2ac6417b342 --- /dev/null +++ b/.changeset/eleven-cheetahs-care.md @@ -0,0 +1,7 @@ +--- +"chainlink": patch +--- + +Add panic recovery to wsrpc mercury client + +- Should help to make nodes running wsrpc v0.8.2 more stable #bugfix diff --git a/.changeset/famous-ligers-heal.md b/.changeset/famous-ligers-heal.md deleted file mode 100644 index e469ea85785..00000000000 --- a/.changeset/famous-ligers-heal.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Set `NodePool.EnforceRepeatableRead = true` by default for all chains. This forces Core to stop using RPCs behind on the latest finalized block. #changed #nops diff --git a/.changeset/few-sloths-explain.md b/.changeset/few-sloths-explain.md deleted file mode 100644 index 78efd6cc7f3..00000000000 --- a/.changeset/few-sloths-explain.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#updated ignoring tx type 126 on celo diff --git a/.changeset/five-beds-wait.md b/.changeset/five-beds-wait.md new file mode 100644 index 00000000000..36ee14f49b6 --- /dev/null +++ b/.changeset/five-beds-wait.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#bugfix Add chaintype.ChainZircuit to chaintypes with rollup support in L1 oracle to prevent a nil L1 oracle being used for Zircuit's gas estimator diff --git a/.changeset/fluffy-lizards-laugh.md b/.changeset/fluffy-lizards-laugh.md new file mode 100644 index 00000000000..3d38170c2d8 --- /dev/null +++ b/.changeset/fluffy-lizards-laugh.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Changed RMNRemote and RMNHome parameter f to fObserve and fSign #updated diff --git a/.changeset/forty-foxes-watch.md b/.changeset/forty-foxes-watch.md deleted file mode 100644 index cb118d50021..00000000000 --- a/.changeset/forty-foxes-watch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Updated Solana TXM's in-memory storage to track statuses across the Solana transaction lifecycle. Added a method to translate Solana transaction statuses into states expected by the ChainWriter interface. Made the duration transactions are retained in storage after finality or error configurable using `TxRetentionTimeout`. #added diff --git a/.changeset/four-kangaroos-appear.md b/.changeset/four-kangaroos-appear.md deleted file mode 100644 index b8ef32ff69e..00000000000 --- a/.changeset/four-kangaroos-appear.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Add config validation so it requires ws url when http polling disabled #bugfix diff --git a/.changeset/fresh-boxes-taste.md b/.changeset/fresh-boxes-taste.md deleted file mode 100644 index ab68bdb5cfc..00000000000 --- a/.changeset/fresh-boxes-taste.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Implement secrets interpolation with dummy workflow registry syncer #internal diff --git a/.changeset/fresh-lobsters-fly.md b/.changeset/fresh-lobsters-fly.md new file mode 100644 index 00000000000..12b9c317dcb --- /dev/null +++ b/.changeset/fresh-lobsters-fly.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#internal Refactored ChainComponents tests to run in parallel diff --git a/.changeset/friendly-tigers-argue.md b/.changeset/friendly-tigers-argue.md new file mode 100644 index 00000000000..25aff7e13ae --- /dev/null +++ b/.changeset/friendly-tigers-argue.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal change gethwrapper to allow for foundry based gethwrapper generation diff --git a/.changeset/fuzzy-dodos-travel.md b/.changeset/fuzzy-dodos-travel.md deleted file mode 100644 index 8c79beb73d4..00000000000 --- a/.changeset/fuzzy-dodos-travel.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#changed UI(chainconfig): make admin address optional diff --git a/.changeset/giant-cats-run.md b/.changeset/giant-cats-run.md deleted file mode 100644 index 22a0cde247d..00000000000 --- a/.changeset/giant-cats-run.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal Add tokenDestGasOverhead to CalculateMessageMaxGas diff --git a/.changeset/good-chairs-boil.md b/.changeset/good-chairs-boil.md deleted file mode 100644 index ead73f68103..00000000000 --- a/.changeset/good-chairs-boil.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#added Enable and Disable Feeds Manager mutations diff --git a/.changeset/good-roses-smash.md b/.changeset/good-roses-smash.md deleted file mode 100644 index 3efa2dd439f..00000000000 --- a/.changeset/good-roses-smash.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#internal Fix Contract Reader data word index calculation and change ccip contract reader config for more optimal querying. diff --git a/.changeset/gorgeous-ants-promise.md b/.changeset/gorgeous-ants-promise.md new file mode 100644 index 00000000000..117bc9a85a9 --- /dev/null +++ b/.changeset/gorgeous-ants-promise.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Updated TXM abandon transaction functionality to drop related attempts. #updated diff --git a/.changeset/great-spiders-greet.md b/.changeset/great-spiders-greet.md deleted file mode 100644 index cd8e20a32a6..00000000000 --- a/.changeset/great-spiders-greet.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Fixed outdated headtracker config doc. #internal diff --git a/.changeset/happy-tips-nail.md b/.changeset/happy-tips-nail.md deleted file mode 100644 index ad42dc47beb..00000000000 --- a/.changeset/happy-tips-nail.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#updated bump CTF to v1.50.13, more robust ethereum client compatibility pipeline diff --git a/.changeset/healthy-shirts-remain.md b/.changeset/healthy-shirts-remain.md deleted file mode 100644 index 0ce310e1ce3..00000000000 --- a/.changeset/healthy-shirts-remain.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#removed Remove unused deprecated key interfaces. diff --git a/.changeset/hip-clocks-joke.md b/.changeset/hip-clocks-joke.md deleted file mode 100644 index 21f53718b22..00000000000 --- a/.changeset/hip-clocks-joke.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal OracleFactory error handling change diff --git a/.changeset/honest-bugs-grin.md b/.changeset/honest-bugs-grin.md deleted file mode 100644 index 7d3ff3c7848..00000000000 --- a/.changeset/honest-bugs-grin.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"chainlink": minor ---- - -#updated -update ethkeys, ethtransactions to handle duplicate chain id in different network -introduce network arg input to Chain graphql query to allow better lookup based on network and chain id diff --git a/.changeset/hot-mice-yell.md b/.changeset/hot-mice-yell.md deleted file mode 100644 index 9d170e1f15c..00000000000 --- a/.changeset/hot-mice-yell.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Relocation of the deployment directory into a direct subdir of the root. #internal diff --git a/.changeset/hot-pants-clean.md b/.changeset/hot-pants-clean.md deleted file mode 100644 index efd9a85baa3..00000000000 --- a/.changeset/hot-pants-clean.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Minor fixes to the CCIPChainReader enabling proper serialization #internal diff --git a/.changeset/large-ants-occur.md b/.changeset/large-ants-occur.md new file mode 100644 index 00000000000..81bf4ed5728 --- /dev/null +++ b/.changeset/large-ants-occur.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +add reorg detection for Solana TXM. #added diff --git a/.changeset/large-fishes-enjoy.md b/.changeset/large-fishes-enjoy.md new file mode 100644 index 00000000000..201267e8b64 --- /dev/null +++ b/.changeset/large-fishes-enjoy.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Fix logic for mapping affected files in CI that affects golangci-lint execution diff --git a/.changeset/late-hornets-yell.md b/.changeset/late-hornets-yell.md new file mode 100644 index 00000000000..7d04500cc77 --- /dev/null +++ b/.changeset/late-hornets-yell.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#updated Bump chainlink-common version. diff --git a/.changeset/late-windows-clean.md b/.changeset/late-windows-clean.md deleted file mode 100644 index 261747efa6c..00000000000 --- a/.changeset/late-windows-clean.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -"chainlink": minor ---- - -#internal Updated the TXM confirmation logic to use the mined transaction count to identify re-org'd or confirmed transactions. - -- Confirmer uses the mined transaction count to determine if transactions have been re-org'd or confirmed. -- Confirmer no longer sets transaction states to `confirmed_missing_receipt`. This state is maintained in queries for backwards compatibility. -- Finalizer now responsible for fetching and storing receipts for confirmed transactions. -- Finalizer now responsible for resuming pending task runs. -- Finalizer now responsible for marking old transactions without receipts broadcasted before the finalized head as fatal. diff --git a/.changeset/lemon-ads-fix.md b/.changeset/lemon-ads-fix.md deleted file mode 100644 index f7f3438eb23..00000000000 --- a/.changeset/lemon-ads-fix.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#added Handle Hex String in EA Telemetry diff --git a/.changeset/long-apples-fold.md b/.changeset/long-apples-fold.md new file mode 100644 index 00000000000..ba3e731951f --- /dev/null +++ b/.changeset/long-apples-fold.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +DEVSVCS-958: fix automation v2.3 batching bug #bugfix diff --git a/.changeset/loud-birds-remain.md b/.changeset/loud-birds-remain.md new file mode 100644 index 00000000000..eb1e8f8a9ca --- /dev/null +++ b/.changeset/loud-birds-remain.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#internal Add unexposed shell cmd for updating a bridge diff --git a/.changeset/lovely-glasses-film.md b/.changeset/lovely-glasses-film.md deleted file mode 100644 index 2289c2c0a67..00000000000 --- a/.changeset/lovely-glasses-film.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Use correct OCR2OracleSpecID when setting up RequestedRoundTracker #bugfix diff --git a/.changeset/many-carrots-share.md b/.changeset/many-carrots-share.md deleted file mode 100644 index da22ac6ed4f..00000000000 --- a/.changeset/many-carrots-share.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal Update ccip contract reader cfg for ccip message sent to use output codec wrapper modifier diff --git a/.changeset/mean-ravens-stare.md b/.changeset/mean-ravens-stare.md new file mode 100644 index 00000000000..6b481ae4520 --- /dev/null +++ b/.changeset/mean-ravens-stare.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal add versioned geth wrappers for keystone prod contracts diff --git a/.changeset/metal-forks-arrive.md b/.changeset/metal-forks-arrive.md deleted file mode 100644 index 21b99b3ddb1..00000000000 --- a/.changeset/metal-forks-arrive.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Adds new custom calldata DA oracle #added diff --git a/.changeset/metal-houses-approve.md b/.changeset/metal-houses-approve.md new file mode 100644 index 00000000000..6768c50767e --- /dev/null +++ b/.changeset/metal-houses-approve.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Added TxExpirationRebroadcast feature and config for Solana TXM. #added diff --git a/.changeset/neat-singers-notice.md b/.changeset/neat-singers-notice.md deleted file mode 100644 index 6eff83c0c15..00000000000 --- a/.changeset/neat-singers-notice.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Added multiple blocks history estimator feature and config for Solana TXM. #added diff --git a/.changeset/nine-stingrays-march.md b/.changeset/nine-stingrays-march.md deleted file mode 100644 index c2f88d95663..00000000000 --- a/.changeset/nine-stingrays-march.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Add don_id to Mercury Enhanced EA telemetry #added diff --git a/.changeset/perfect-peaches-work.md b/.changeset/perfect-peaches-work.md deleted file mode 100644 index 9a3b461e1c9..00000000000 --- a/.changeset/perfect-peaches-work.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Fix flaky WS test server #internal diff --git a/.changeset/purple-seas-help.md b/.changeset/purple-seas-help.md deleted file mode 100644 index 01f8b0049b6..00000000000 --- a/.changeset/purple-seas-help.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#removed unused key files and move public_key test file. diff --git a/.changeset/purple-shrimps-invent.md b/.changeset/purple-shrimps-invent.md deleted file mode 100644 index 3db195434de..00000000000 --- a/.changeset/purple-shrimps-invent.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Upgrade go-ethereum to v1.14.11 #internal diff --git a/.changeset/rotten-books-cross.md b/.changeset/rotten-books-cross.md new file mode 100644 index 00000000000..95231ec47f2 --- /dev/null +++ b/.changeset/rotten-books-cross.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Support multiple streamIDs in stream specs #added diff --git a/.changeset/rotten-timers-give.md b/.changeset/rotten-timers-give.md deleted file mode 100644 index ef474a17d56..00000000000 --- a/.changeset/rotten-timers-give.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"chainlink": minor ---- - -Support multiple chains evm clients for TXM gas estimator to fetch L1 gas oracle -#added diff --git a/.changeset/rude-geckos-switch.md b/.changeset/rude-geckos-switch.md deleted file mode 100644 index 866b1c40c63..00000000000 --- a/.changeset/rude-geckos-switch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#bugfix Update Log.Level and MaxSize configs description in the docs diff --git a/.changeset/seven-schools-invent.md b/.changeset/seven-schools-invent.md deleted file mode 100644 index 81b6ce44b99..00000000000 --- a/.changeset/seven-schools-invent.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Integration tests for USDC token transfer #internal diff --git a/.changeset/shaggy-carpets-deliver.md b/.changeset/shaggy-carpets-deliver.md new file mode 100644 index 00000000000..676ad2fb861 --- /dev/null +++ b/.changeset/shaggy-carpets-deliver.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#removed dead transmission tests diff --git a/.changeset/sharp-llamas-compete.md b/.changeset/sharp-llamas-compete.md new file mode 100644 index 00000000000..76808dbdda4 --- /dev/null +++ b/.changeset/sharp-llamas-compete.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#bugfix Fix missing Tron handler diff --git a/.changeset/short-gifts-eat.md b/.changeset/short-gifts-eat.md deleted file mode 100644 index afc171715d4..00000000000 --- a/.changeset/short-gifts-eat.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -use last mined nonce instead of pending nonce to recover from occasional nonce gap issues within nonce tracker. #internal diff --git a/.changeset/silent-goats-jog.md b/.changeset/silent-goats-jog.md deleted file mode 100644 index 3428ee20b17..00000000000 --- a/.changeset/silent-goats-jog.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Fix HeadTracker tests caused by simulated client update #internal diff --git a/.changeset/silver-books-grab.md b/.changeset/silver-books-grab.md new file mode 100644 index 00000000000..2aa20e97f27 --- /dev/null +++ b/.changeset/silver-books-grab.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#add #nops Add soneium config diff --git a/.changeset/six-wombats-shake.md b/.changeset/six-wombats-shake.md deleted file mode 100644 index 448cf03bd51..00000000000 --- a/.changeset/six-wombats-shake.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -CCIP token transfer integration tests #internal diff --git a/.changeset/sixty-queens-wait.md b/.changeset/sixty-queens-wait.md deleted file mode 100644 index cd9fc9ea65c..00000000000 --- a/.changeset/sixty-queens-wait.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#updated chain config: allow chain id and account address to be manually provided when no selections are available diff --git a/.changeset/small-gifts-play.md b/.changeset/small-gifts-play.md deleted file mode 100644 index a9486a033ef..00000000000 --- a/.changeset/small-gifts-play.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#updated Operator UI to support StreamSpec job definition diff --git a/.changeset/soft-rivers-care.md b/.changeset/soft-rivers-care.md new file mode 100644 index 00000000000..22eeea042ba --- /dev/null +++ b/.changeset/soft-rivers-care.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +interface change for plugin to support extra args codec, right now noop #added diff --git a/.changeset/sour-hairs-cross.md b/.changeset/sour-hairs-cross.md new file mode 100644 index 00000000000..fa12a38b5be --- /dev/null +++ b/.changeset/sour-hairs-cross.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal depreciate keystone deployment library diff --git a/.changeset/strange-radios-teach.md b/.changeset/strange-radios-teach.md deleted file mode 100644 index ea84bfbf359..00000000000 --- a/.changeset/strange-radios-teach.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Merge raw configs correctly #bugfix diff --git a/.changeset/swift-fireants-compare.md b/.changeset/swift-fireants-compare.md deleted file mode 100644 index b11c516e7c3..00000000000 --- a/.changeset/swift-fireants-compare.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Add CSA authentication support to Beholder #added diff --git a/.changeset/tall-falcons-yawn.md b/.changeset/tall-falcons-yawn.md new file mode 100644 index 00000000000..98b90e5994b --- /dev/null +++ b/.changeset/tall-falcons-yawn.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#added the ability to define a fallback.toml override config using CL_CHAIN_DEFAULTS env var diff --git a/.changeset/tame-tomatoes-refuse.md b/.changeset/tame-tomatoes-refuse.md deleted file mode 100644 index 530f9d2b519..00000000000 --- a/.changeset/tame-tomatoes-refuse.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#added feat: support creating solana chain config in job distributor page diff --git a/.changeset/tasty-years-behave.md b/.changeset/tasty-years-behave.md deleted file mode 100644 index 08019e3dafa..00000000000 --- a/.changeset/tasty-years-behave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Modify release changelog generation format #internal diff --git a/.changeset/tender-colts-return.md b/.changeset/tender-colts-return.md deleted file mode 100644 index 16c0b2da1ff..00000000000 --- a/.changeset/tender-colts-return.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#updated celo alfajores config diff --git a/.changeset/thick-chefs-deliver.md b/.changeset/thick-chefs-deliver.md deleted file mode 100644 index 67d68d22792..00000000000 --- a/.changeset/thick-chefs-deliver.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Enable AutoPurge feature on all affected chains #nops diff --git a/.changeset/thick-vans-tickle.md b/.changeset/thick-vans-tickle.md new file mode 100644 index 00000000000..a719bf8905b --- /dev/null +++ b/.changeset/thick-vans-tickle.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Add support for flexible schemas #added diff --git a/.changeset/three-mayflies-learn.md b/.changeset/three-mayflies-learn.md deleted file mode 100644 index 1ea4fad3924..00000000000 --- a/.changeset/three-mayflies-learn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#updated Update few incorrect occurences of the password for notreal@fakeemail.ch. diff --git a/.changeset/tricky-candles-matter.md b/.changeset/tricky-candles-matter.md deleted file mode 100644 index 0dc7806703a..00000000000 --- a/.changeset/tricky-candles-matter.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#bugfix Memory leak fix on promwrapper diff --git a/.changeset/two-spies-arrive.md b/.changeset/two-spies-arrive.md deleted file mode 100644 index cb46c46bce6..00000000000 --- a/.changeset/two-spies-arrive.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#updated Use labelers from `chainlink-common` diff --git a/.changeset/warm-panthers-stare.md b/.changeset/warm-panthers-stare.md new file mode 100644 index 00000000000..319a7ad22b3 --- /dev/null +++ b/.changeset/warm-panthers-stare.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Add grpc support for LLO #added diff --git a/.changeset/weak-weeks-grin.md b/.changeset/weak-weeks-grin.md deleted file mode 100644 index df03df2303c..00000000000 --- a/.changeset/weak-weeks-grin.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Bump Solana to include MultiNode integration. #added diff --git a/.changeset/wild-cats-think.md b/.changeset/wild-cats-think.md new file mode 100644 index 00000000000..f56f41b242c --- /dev/null +++ b/.changeset/wild-cats-think.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Added the `EVM.Transactions.Enabled` config to enable or disable the transaction manager. #added diff --git a/.changeset/wild-planes-mix.md b/.changeset/wild-planes-mix.md new file mode 100644 index 00000000000..1a08c2f9d4d --- /dev/null +++ b/.changeset/wild-planes-mix.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Truncates workflow name before starting engine diff --git a/.changeset/wise-buttons-fry.md b/.changeset/wise-buttons-fry.md new file mode 100644 index 00000000000..aa3cb1dab79 --- /dev/null +++ b/.changeset/wise-buttons-fry.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Add TRON integration #added diff --git a/.changeset/yellow-brooms-leave.md b/.changeset/yellow-brooms-leave.md new file mode 100644 index 00000000000..638751814bf --- /dev/null +++ b/.changeset/yellow-brooms-leave.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#updated feat:create tron chain config on operator ui diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 9f19d52b7ea..6e05a6f1c10 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -89,14 +89,11 @@ core/scripts/gateway @smartcontractkit/dev-services /contracts/src/v0.8/automation @smartcontractkit/dev-services /contracts/src/v0.8/ccip @smartcontractkit/ccip-onchain /contracts/src/v0.8/functions @smartcontractkit/dev-services -# TODO: interfaces folder, folder should be removed and files moved to the correct folders /contracts/src/v0.8/l2ep @smartcontractkit/bix-build /contracts/src/v0.8/llo-feeds @smartcontractkit/data-streams-engineers # TODO: mocks folder, folder should be removed and files moved to the correct folders /contracts/src/v0.8/operatorforwarder @smartcontractkit/data-feeds-engineers /contracts/src/v0.8/shared @smartcontractkit/core-solidity -# TODO: tests folder, folder should be removed and files moved to the correct folders -# TODO: transmission folder, owner should be found /contracts/src/v0.8/vrf @smartcontractkit/dev-services /contracts/src/v0.8/keystone @smartcontractkit/keystone /contracts/src/v0.8/workflow @smartcontractkit/dev-services diff --git a/.github/actions/build-sign-publish-chainlink/action.yml b/.github/actions/build-sign-publish-chainlink/action.yml index b0e70b742d5..24d9884d7f7 100644 --- a/.github/actions/build-sign-publish-chainlink/action.yml +++ b/.github/actions/build-sign-publish-chainlink/action.yml @@ -210,12 +210,12 @@ runs: IMAGES_NAME_RAW=${{ fromJSON(steps.buildpush-nonroot.outputs.metadata)['image.name'] }} IMAGE_DIGEST=${{ fromJSON(steps.buildpush-nonroot.outputs.metadata)['containerimage.digest'] }} IMAGE_NAME=$(echo "$IMAGES_NAME_RAW" | cut -d"," -f1) - IMAGE_TAG=$(echo "$IMAGES_NAME_RAW" | cut -d":" -f2) + IMAGE_TAG=$(echo "$IMAGE_NAME" | cut -d":" -f2) echo "nonroot_image_name=${IMAGE_NAME}" >> $GITHUB_ENV echo "nonroot_image_digest=${IMAGE_DIGEST}" >> $GITHUB_ENV echo '### Docker Image' >> $GITHUB_STEP_SUMMARY - echo "Image Name: ${IMAGE_NAME}" >> $GITHUB_STEP_SUMMARY - echo "Image Digest: ${IMAGE_DIGEST}" >> $GITHUB_STEP_SUMMARY + echo "Image Name: ${IMAGE_NAME}" >> $GITHUB_STEP_SUMMARY + echo "Image Digest: ${IMAGE_DIGEST}" >> $GITHUB_STEP_SUMMARY echo "image-tag=${IMAGE_TAG}" >> $GITHUB_OUTPUT echo "image-digest=${IMAGE_DIGEST}" >> $GITHUB_OUTPUT diff --git a/.github/actions/crib/action.yml b/.github/actions/crib/action.yml new file mode 100644 index 00000000000..a877d0ff4b3 --- /dev/null +++ b/.github/actions/crib/action.yml @@ -0,0 +1,158 @@ +name: "CRIB Action" +description: "Spin up a CRIB environment. Optionally run tests and tear it down." + +inputs: + aws-role-duration-seconds: + description: "Duration in seconds for AWS role" + required: false + default: "3600" + aws-role-arn: + description: "AWS Role ARN for CRIB" + required: true + aws-region: + description: "AWS Region" + required: true + aws-account-id: + description: "AWS Account ID" + required: true + api-gw-host-crib: + description: "API Gateway Host for CRIB" + required: true + api-gw-host-k8s: + description: "API Gateway Host for K8s" + required: true + k8s-cluster-name: + description: "Kubernetes cluster name" + required: true + aws-token-issuer-role-arn: + description: "AWS Role ARN for token issuer" + required: true + aws-token-issuer-lambda-url: + description: "AWS Lambda URL for token issuer" + required: true + ingress-base-domain: + description: "Ingress base domain" + required: true + k8s-staging-ingress-suffix: + description: "K8S staging ingress suffix" + required: true + gap-url-integration-tests: + description: "GAP URL for integration tests" + required: true + crib-alert-slack-webhook: + description: "CRIB alert Slack webhook" + required: true + crib-chainlink-docker-image-name: + description: "Docker image name" + required: true + crib-chainlink-docker-image-tag: + description: "Docker image tag" + required: true + crib-cleanup-ttl: + # See: https://kyverno.io/docs/writing-policies/cleanup/ + description: "Time to keep environment up for before destroying it. Examples: 15m, 1h, 3d" + required: false + default: "1h" + crib-destroy-environment: + description: "Whether to destroy the CRIB environment after testing" + required: false + default: "true" + integration-tests-run: + description: "Whether to run integration tests" + required: false + default: "true" + main-dns-zone: + description: + "The DNS zone is used for exposing services. It is required when using the + dynamic local proxy to prevent sending requests and exposing sensitive + information to random external endpoints. This ensures that the dynamic + local proxy is used only for the specific DNS zone." +runs: + using: "composite" + steps: + - uses: cachix/install-nix-action@ba0dd844c9180cbf77aa72a116d6fbc515d0e87b # v27 + with: + nix_path: nixpkgs=channel:nixos-unstable + + - name: setup-gap crib + uses: smartcontractkit/.github/actions/setup-gap@00b58566e0ee2761e56d9db0ea72b783fdb89b8d # setup-gap@0.4.0 + with: + aws-role-duration-seconds: ${{ inputs.aws-role-duration-seconds }} + aws-role-arn: ${{ inputs.aws-role-arn }} + api-gateway-host: ${{ inputs.api-gw-host-crib }} + aws-region: ${{ inputs.aws-region }} + ecr-private-registry: ${{ inputs.aws-account-id }} + k8s-cluster-name: ${{ inputs.k8s-cluster-name }} + gap-name: crib + use-private-ecr-registry: true + use-tls: true + proxy-port: 8080 + + - name: setup-gap k8s + uses: smartcontractkit/.github/actions/setup-gap@00b58566e0ee2761e56d9db0ea72b783fdb89b8d # setup-gap@0.4.0 + with: + aws-role-duration-seconds: ${{ inputs.aws-role-duration-seconds }} + aws-role-arn: ${{ inputs.aws-role-arn }} + api-gateway-host: ${{ inputs.api-gw-host-k8s }} + aws-region: ${{ inputs.aws-region }} + ecr-private-registry: ${{ inputs.aws-account-id }} + k8s-cluster-name: ${{ inputs.k8s-cluster-name }} + gap-name: k8s + use-private-ecr-registry: true + use-k8s: true + proxy-port: 8443 + + - name: Setup GitHub token using GATI + id: token + uses: smartcontractkit/.github/actions/setup-github-token@ef78fa97bf3c77de6563db1175422703e9e6674f # setup-github-token@0.2.1 + with: + aws-role-arn: ${{ inputs.aws-token-issuer-role-arn }} + aws-lambda-url: ${{ inputs.aws-token-issuer-lambda-url }} + aws-region: ${{ inputs.aws-region }} + aws-role-duration-seconds: "1800" + + - name: Deploy and validate CRIB Environment for Core + uses: smartcontractkit/.github/actions/crib-deploy-environment@265e28cc322771651688493303785323e3482b15 # crib-deploy-environment@8.2.1 + id: deploy-crib + with: + github-token: ${{ steps.token.outputs.access-token }} + aws-ecr-private-registry: ${{ inputs.aws-account-id }} + aws-region: ${{ inputs.aws-region }} + aws-role-arn: ${{ inputs.aws-role-arn }} + ingress-base-domain: ${{ inputs.ingress-base-domain }} + k8s-cluster-name: ${{ inputs.k8s-cluster-name }} + chainlink-team: releng + chainlink-product: crib + command: "core-dev-simulated-core-ocr1" + crib-alert-slack-webhook: ${{ inputs.crib-alert-slack-webhook }} + product-image: ${{ inputs.crib-chainlink-docker-image-name }} + product-image-tag: ${{ inputs.crib-chainlink-docker-image-tag }} + ns-ttl: ${{ inputs.crib-cleanup-ttl }} + main-dns-zone: ${{ inputs.main-dns-zone }} + + - name: Set up Go + uses: ./.github/actions/setup-go + with: + go-version-file: "go.mod" + + - name: Run CRIB integration test + if: inputs.integration-tests-run == 'true' + shell: bash + working-directory: integration-tests/crib + env: + K8S_STAGING_INGRESS_SUFFIX: ${{ inputs.k8s-staging-ingress-suffix }} + CRIB_NAMESPACE: ${{ steps.deploy-crib.outputs.devspace-namespace }} + CRIB_NETWORK: geth + CRIB_NODES: 5 + GAP_URL: ${{ inputs.gap-url-integration-tests }} + SETH_LOG_LEVEL: info + TEST_PERSISTENCE: true + E2E_TEST_CHAINLINK_IMAGE: public.ecr.aws/chainlink/chainlink + E2E_TEST_CHAINLINK_VERSION: latest + run: go test -v -run TestCRIBChaos + + - name: Destroy CRIB Environment + if: inputs.crib-destroy-environment == 'true' && always() && steps.deploy-crib.outputs.devspace-namespace != '' + uses: smartcontractkit/.github/actions/crib-purge-environment@142671bc21953c8cc3edbd21848c50b5ec201c2a # crib-purge-environment@0.3.0 + with: + namespace: ${{ steps.deploy-crib.outputs.devspace-namespace }} diff --git a/.github/actions/detect-solidity-readonly-file-changes/action.yml b/.github/actions/detect-solidity-readonly-file-changes/action.yml index faca16d53f0..d0890a9f604 100644 --- a/.github/actions/detect-solidity-readonly-file-changes/action.yml +++ b/.github/actions/detect-solidity-readonly-file-changes/action.yml @@ -16,9 +16,13 @@ runs: filters: | read_only_sol: - 'contracts/src/v0.8/interfaces/**/*' + - 'contracts/src/v0.8/automation/interfaces/**/*' + - 'contracts/src/v0.8/automation/upkeeps/**/*' - 'contracts/src/v0.8/automation/v1_2/**/*' - 'contracts/src/v0.8/automation/v1_3/**/*' - 'contracts/src/v0.8/automation/v2_0/**/*' + - 'contracts/src/v0.8/automation/v2_1/**/*' + - 'contracts/src/v0.8/automation/v2_2/**/*' - name: Fail if read-only files have changed if: ${{ steps.changed_files.outputs.read_only_sol == 'true' }} diff --git a/.github/actions/golangci-lint/action.yml b/.github/actions/golangci-lint/action.yml index 20ad2689deb..5fb7865c5e8 100644 --- a/.github/actions/golangci-lint/action.yml +++ b/.github/actions/golangci-lint/action.yml @@ -18,6 +18,11 @@ inputs: description: Set where the go module file is located at default: "go.sum" +outputs: + golang-report-artifact-url: + description: The URL to the uploaded artifact + value: ${{ steps.upload-artifact.outputs.artifact_url }} + runs: using: composite steps: @@ -26,12 +31,16 @@ runs: # Only do a full checkout on merge_groups if: github.event_name == 'merge_group' with: + persist-credentials: false fetch-depth: 0 + - name: Checkout repo uses: actions/checkout@v4.2.1 if: github.event_name != 'merge_group' with: + persist-credentials: false fetch-depth: 1 + - name: Setup Go uses: ./.github/actions/setup-go with: @@ -39,38 +48,67 @@ runs: cache-version: ${{ inputs.cache-version }} go-version-file: ${{ inputs.go-version-file }} go-module-file: ${{ inputs.go-module-file }} + - name: Touching core/web/assets/index.html shell: bash run: mkdir -p core/web/assets && touch core/web/assets/index.html - - name: Build binary - working-directory: ${{ inputs.go-directory }} - shell: bash - run: go build ./... - - name: Set golangci-lint working directory + + - name: Set Golangci-lint working directory shell: bash id: set-working-directory # XXX: Don't use `.` default working directory here due to issues with the golangci-lint-action. run: | if [ "${{ inputs.go-directory }}" == "." ]; then - echo "golangci-lint-working-directory=" | tee -a $GITHUB_OUTPUT + echo "golangci-lint-working-directory=" >> $GITHUB_OUTPUT else - echo "golangci-lint-working-directory=${{ inputs.go-directory }}" | tee -a $GITHUB_OUTPUT + echo "golangci-lint-working-directory=${{ inputs.go-directory }}/" >> $GITHUB_OUTPUT fi - - name: golangci-lint + + - name: Golangci-lint uses: golangci/golangci-lint-action@38e1018663fa5173f3968ea0777460d3de38f256 # v5.3.0 with: - version: v1.61.0 + version: v1.62.2 only-new-issues: true args: --out-format colored-line-number,checkstyle:golangci-lint-report.xml working-directory: ${{ steps.set-working-directory.outputs.golangci-lint-working-directory }} - - name: Print lint report artifact + + - name: Print Golangci-lint report results if: failure() shell: bash - run: cat ${{ inputs.go-directory }}/golangci-lint-report.xml - - name: Store lint report artifact + run: cat ./${{ steps.set-working-directory.outputs.golangci-lint-working-directory }}golangci-lint-report.xml + + # Get a valid name for the upload-artifact step. + # Avoid error: `The artifact name is not valid: ///` caused by `/`. + # Remove trailing `/` from the directory name: `core/scripts/` -> `core/scripts`. + # Replace remaining `/` with `-`: `core/scripts` -> `core-scripts`. + # Assign `root` if the directory name is empty (ref: step.id: set-working-directory). + - name: Get valid suffix for artifact name + if: always() + id: suffix + shell: bash + run: | + go_directory=${{ steps.set-working-directory.outputs.golangci-lint-working-directory }} + echo "Validating if directory name '$go_directory' is empty or has slashes" + + if [[ $go_directory == *\/* ]]; then + suffix=$(echo "$go_directory" | sed 's:\/$::' | tr '/' '-') + echo "Directory name with slashes '$go_directory' updated to a valid artifact suffix '$suffix'" + elif [[ $go_directory == "" ]]; then + suffix="root" + echo "Root directory (empty string) updated to a valid artifact suffix '$suffix'" + else + suffix="$go_directory" + echo "Directory name is valid for the artifact suffix: '$suffix'" + fi + + echo "suffix=${suffix}" >> $GITHUB_OUTPUT + + - name: Store Golangci-lint report artifact if: always() + id: upload-artifact uses: actions/upload-artifact@v4.4.3 with: - name: golangci-lint-report - path: ${{ inputs.go-directory }}/golangci-lint-report.xml - retention-days: 7 + # Use a unique suffix for each lint report artifact to avoid duplication errors + name: golangci-lint-report-${{ steps.suffix.outputs.suffix }} + # N/B: value may be empty (no slash) OR `///` (with slash tat the end) + path: ./${{ steps.set-working-directory.outputs.golangci-lint-working-directory }}golangci-lint-report.xml diff --git a/.github/actions/goreleaser-build-sign-publish/README.md b/.github/actions/goreleaser-build-sign-publish/README.md index afea60e1203..9b520c1741a 100644 --- a/.github/actions/goreleaser-build-sign-publish/README.md +++ b/.github/actions/goreleaser-build-sign-publish/README.md @@ -24,6 +24,8 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4.2.1 + with: + persist-credentials: false - name: Configure aws credentials uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1 with: diff --git a/.github/actions/detect-solidity-foundry-version/action.yml b/.github/actions/install-solidity-foundry/action.yml similarity index 66% rename from .github/actions/detect-solidity-foundry-version/action.yml rename to .github/actions/install-solidity-foundry/action.yml index b37f1e25094..70e425335d9 100644 --- a/.github/actions/detect-solidity-foundry-version/action.yml +++ b/.github/actions/install-solidity-foundry/action.yml @@ -1,5 +1,5 @@ -name: 'Detect Foundry version in GNUmakefile' -description: 'Detects Foundry version in GNUmakefile' +name: 'Install Foundry version in GNUmakefile' +description: 'Install Foundry version in GNUmakefile' inputs: working-directory: description: 'The GNUmakefile directory' @@ -17,10 +17,15 @@ runs: shell: bash working-directory: ${{ inputs.working-directory }} run: | - foundry_version=$(grep -Eo "foundryup --version [^ ]+" GNUmakefile | awk '{print $3}') + foundry_version=$(grep -Eo "foundryup --install [^ ]+" GNUmakefile | awk '{print $3}') if [ -z "$foundry_version" ]; then echo "::error::Foundry version not found in GNUmakefile" exit 1 fi echo "Foundry version found: $foundry_version" echo "foundry-version=$foundry_version" >> $GITHUB_OUTPUT + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@de808b1eea699e761c404bda44ba8f21aba30b2c # v1.3.1 + with: + version: ${{ steps.extract-foundry-version.outputs.foundry-version }} diff --git a/.github/actions/setup-go/action.yml b/.github/actions/setup-go/action.yml index ddd4e28e461..9d395795764 100644 --- a/.github/actions/setup-go/action.yml +++ b/.github/actions/setup-go/action.yml @@ -29,10 +29,22 @@ inputs: runs: using: composite steps: + - name: Get Go Version + shell: bash + id: go-version + run: | + version=$(sed -ne '/^toolchain /s/^toolchain go//p' ${{ inputs.go-version-file }}) + if [ -z "$version" ]; then + version=$(sed -ne '/^go /s/^go //p' ${{ inputs.go-version-file }}) + echo "Toolchain version not found in ${{ inputs.go-version-file }}, using go directive instead." + fi + echo "Go Version: $version" + echo "version=$version" >> "$GITHUB_OUTPUT" + - name: Set up Go uses: actions/setup-go@v5.0.2 with: - go-version-file: ${{ inputs.go-version-file }} + go-version: ${{ steps.go-version.outputs.version }} cache: false check-latest: true @@ -57,7 +69,7 @@ runs: # If multiple jobs call actions/cache, then only one will get priority to create upon a cache miss. # We will only restore the cache by default (by calling actions/cache/restore) and let the # `go-mod-cache.yml` workflow handle the creation. - - uses: actions/cache/restore@v4.1.1 + - uses: actions/cache/restore@v4 if: ${{ inputs.restore-module-cache-only == 'true' }} name: Cache Go Modules with: @@ -71,7 +83,7 @@ runs: # If this is called, then it will create the cache entry upon a cache miss. # The cache is created after a cache miss, and after job completes successfully. - - uses: actions/cache@v4.1.1 + - uses: actions/cache@v4 if: ${{ inputs.restore-module-cache-only != 'true' }} name: Cache Go Modules with: @@ -83,7 +95,7 @@ runs: restore-keys: | ${{ runner.os }}-gomod-${{ inputs.cache-version }}- - - uses: actions/cache/restore@v4.1.1 + - uses: actions/cache/restore@v4 name: Cache Go Build Outputs (restore) # For certain events, we don't necessarily want to create a build cache, but we will benefit from restoring from one. if: ${{ inputs.only-modules == 'false' && (github.event_name == 'merge_group' || inputs.restore-build-cache-only == 'true') }} @@ -97,7 +109,7 @@ runs: ${{ runner.os }}-gobuild-${{ inputs.build-cache-version || inputs.cache-version }}- ${{ runner.os }}-gobuild-${{ inputs.cache-version }}- - - uses: actions/cache@v4.1.1 + - uses: actions/cache@v4 # don't save cache on merge queue events if: ${{ inputs.only-modules == 'false' && (github.event_name != 'merge_group' && inputs.restore-build-cache-only == 'false') }} name: Cache Go Build Outputs diff --git a/.github/actions/setup-hardhat/action.yaml b/.github/actions/setup-hardhat/action.yaml index a61e61bb5c7..03b7fef90bb 100644 --- a/.github/actions/setup-hardhat/action.yaml +++ b/.github/actions/setup-hardhat/action.yaml @@ -11,13 +11,13 @@ runs: using: composite steps: - name: Cache Compilers - uses: actions/cache@v4.1.1 + uses: actions/cache@v4 with: path: ~/.cache/hardhat-nodejs/ key: contracts-compilers-${{ runner.os }}-${{ inputs.cache-version }}-${{ hashFiles('contracts/pnpm-lock.yaml', 'contracts/hardhat.config.ts') }} - name: Cache contracts build outputs - uses: actions/cache@v4.1.1 + uses: actions/cache@v4 with: path: | contracts/cache/ diff --git a/.github/actions/setup-solana/action.yml b/.github/actions/setup-solana/action.yml index de7c4331abc..e353636f805 100644 --- a/.github/actions/setup-solana/action.yml +++ b/.github/actions/setup-solana/action.yml @@ -8,7 +8,7 @@ inputs: runs: using: composite steps: - - uses: actions/cache@v4.1.1 + - uses: actions/cache@v4 id: cache name: Cache solana CLI with: diff --git a/.github/actions/setup-wasmd/action.yml b/.github/actions/setup-wasmd/action.yml index d95e8129260..c1969e82652 100644 --- a/.github/actions/setup-wasmd/action.yml +++ b/.github/actions/setup-wasmd/action.yml @@ -8,7 +8,7 @@ inputs: runs: using: composite steps: - - uses: actions/cache@v4.1.1 + - uses: actions/cache@v4 id: cache name: Cache wasmd-build with: diff --git a/.github/e2e-tests.yml b/.github/e2e-tests.yml index 675fa315dfa..e5c8b8505f3 100644 --- a/.github/e2e-tests.yml +++ b/.github/e2e-tests.yml @@ -977,8 +977,8 @@ runner-test-matrix: test_env_vars: E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 E2E_JD_VERSION: 0.6.0 - E2E_RMN_RAGEPROXY_VERSION: master-f461a9e - E2E_RMN_AFN2PROXY_VERSION: master-f461a9e + E2E_RMN_RAGEPROXY_VERSION: 678509b + E2E_RMN_AFN2PROXY_VERSION: 678509b CCIP_V16_TEST_ENV: docker - id: smoke/ccip/ccip_rmn_test.go:^TestRMN_MultipleMessagesOnOneLaneNoWaitForExec$ @@ -993,8 +993,8 @@ runner-test-matrix: test_env_vars: E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 E2E_JD_VERSION: 0.6.0 - E2E_RMN_RAGEPROXY_VERSION: master-f461a9e - E2E_RMN_AFN2PROXY_VERSION: master-f461a9e + E2E_RMN_RAGEPROXY_VERSION: 678509b + E2E_RMN_AFN2PROXY_VERSION: 678509b CCIP_V16_TEST_ENV: docker - id: smoke/ccip/ccip_rmn_test.go:^TestRMN_NotEnoughObservers$ @@ -1009,8 +1009,8 @@ runner-test-matrix: test_env_vars: E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 E2E_JD_VERSION: 0.6.0 - E2E_RMN_RAGEPROXY_VERSION: master-f461a9e - E2E_RMN_AFN2PROXY_VERSION: master-f461a9e + E2E_RMN_RAGEPROXY_VERSION: 678509b + E2E_RMN_AFN2PROXY_VERSION: 678509b CCIP_V16_TEST_ENV: docker - id: smoke/ccip/ccip_rmn_test.go:^TestRMN_DifferentSigners$ @@ -1025,8 +1025,8 @@ runner-test-matrix: test_env_vars: E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 E2E_JD_VERSION: 0.6.0 - E2E_RMN_RAGEPROXY_VERSION: master-f461a9e - E2E_RMN_AFN2PROXY_VERSION: master-f461a9e + E2E_RMN_RAGEPROXY_VERSION: 678509b + E2E_RMN_AFN2PROXY_VERSION: 678509b CCIP_V16_TEST_ENV: docker - id: smoke/ccip/ccip_rmn_test.go:^TestRMN_NotEnoughSigners$ @@ -1041,8 +1041,8 @@ runner-test-matrix: test_env_vars: E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 E2E_JD_VERSION: 0.6.0 - E2E_RMN_RAGEPROXY_VERSION: master-f461a9e - E2E_RMN_AFN2PROXY_VERSION: master-f461a9e + E2E_RMN_RAGEPROXY_VERSION: 678509b + E2E_RMN_AFN2PROXY_VERSION: 678509b CCIP_V16_TEST_ENV: docker - id: smoke/ccip/ccip_rmn_test.go:^TestRMN_DifferentRmnNodesForDifferentChains$ @@ -1057,8 +1057,8 @@ runner-test-matrix: test_env_vars: E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 E2E_JD_VERSION: 0.6.0 - E2E_RMN_RAGEPROXY_VERSION: master-f461a9e - E2E_RMN_AFN2PROXY_VERSION: master-f461a9e + E2E_RMN_RAGEPROXY_VERSION: 678509b + E2E_RMN_AFN2PROXY_VERSION: 678509b CCIP_V16_TEST_ENV: docker - id: smoke/ccip/ccip_rmn_test.go:^TestRMN_TwoMessagesOneSourceChainCursed$ @@ -1073,8 +1073,8 @@ runner-test-matrix: test_env_vars: E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 E2E_JD_VERSION: 0.6.0 - E2E_RMN_RAGEPROXY_VERSION: master-f461a9e - E2E_RMN_AFN2PROXY_VERSION: master-f461a9e + E2E_RMN_RAGEPROXY_VERSION: 678509b + E2E_RMN_AFN2PROXY_VERSION: 678509b CCIP_V16_TEST_ENV: docker - id: smoke/ccip/ccip_rmn_test.go:^TestRMN_GlobalCurseTwoMessagesOnTwoLanes$ @@ -1089,8 +1089,8 @@ runner-test-matrix: test_env_vars: E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 E2E_JD_VERSION: 0.6.0 - E2E_RMN_RAGEPROXY_VERSION: master-f461a9e - E2E_RMN_AFN2PROXY_VERSION: master-f461a9e + E2E_RMN_RAGEPROXY_VERSION: 678509b + E2E_RMN_AFN2PROXY_VERSION: 678509b CCIP_V16_TEST_ENV: docker # END: CCIPv1.6 tests @@ -1124,6 +1124,34 @@ runner-test-matrix: CHAINLINK_USER_TEAM: CCIP test_config_override_path: integration-tests/ccip-tests/testconfig/tomls/usdc_mock_deployment.toml + - id: ccip-smoke-lbtc-32bytes-destination-pool-data + path: integration-tests/ccip-tests/smoke/ccip_test.go + test_env_type: docker + runs_on: ubuntu-latest + triggers: + - PR E2E CCIP Tests + - Merge Queue E2E CCIP Tests + - Nightly E2E Tests + test_cmd: cd integration-tests/ccip-tests/smoke && go test ccip_test.go -test.run ^TestSmokeCCIPForBidirectionalLane$ -timeout 30m -count=1 -test.parallel=1 -json + test_env_vars: + E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 + CHAINLINK_USER_TEAM: CCIP + test_config_override_path: integration-tests/ccip-tests/testconfig/tomls/lbtc_mock_deployment_with_32bytes_data.toml + + - id: ccip-smoke-lbtc-non32bytes-destination-pool-data + path: integration-tests/ccip-tests/smoke/ccip_test.go + test_env_type: docker + runs_on: ubuntu-latest + triggers: + - PR E2E CCIP Tests + - Merge Queue E2E CCIP Tests + - Nightly E2E Tests + test_cmd: cd integration-tests/ccip-tests/smoke && go test ccip_test.go -test.run ^TestSmokeCCIPForBidirectionalLane$ -timeout 30m -count=1 -test.parallel=1 -json + test_env_vars: + E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 + CHAINLINK_USER_TEAM: CCIP + test_config_override_path: integration-tests/ccip-tests/testconfig/tomls/lbtc_mock_deployment_with_non32bytes_data.toml + - id: ccip-smoke-db-compatibility path: integration-tests/ccip-tests/smoke/ccip_test.go test_env_type: docker diff --git a/.github/integration-in-memory-tests.yml b/.github/integration-in-memory-tests.yml index 9550d74f21f..a23ec5432ee 100644 --- a/.github/integration-in-memory-tests.yml +++ b/.github/integration-in-memory-tests.yml @@ -7,6 +7,13 @@ # runner-test-matrix: # START: CCIPv1.6 tests + - id: smoke/ccip/ccip_migration_to_v_1_6_test.go:* + path: integration-tests/smoke/ccip/ccip_migration_to_v_1_6_test.go.go + test_env_type: in-memory + runs_on: ubuntu-latest + triggers: + - PR Integration CCIP Tests + test_cmd: cd integration-tests/smoke/ccip && go test ccip_migration_to_v_1_6_test.go -timeout 12m -test.parallel=1 -count=1 -json - id: smoke/ccip/ccip_fees_test.go:* path: integration-tests/smoke/ccip/ccip_fees_test.go @@ -47,14 +54,22 @@ runner-test-matrix: triggers: - PR Integration CCIP Tests test_cmd: cd integration-tests/smoke/ccip && go test ccip_batching_test.go -timeout 12m -test.parallel=2 -count=1 -json + + - id: smoke/ccip/ccip_add_chain_test.go:* + path: integration-tests/smoke/ccip/ccip_add_chain_test.go + test_env_type: in-memory + runs_on: ubuntu-latest + triggers: + - PR Integration CCIP Tests + test_cmd: cd integration-tests/smoke/ccip && go test ccip_add_chain_test.go -timeout 15m -test.parallel=1 -count=1 -json - - id: contracts/ccipreader_test.go:* - path: integration-tests/contracts/ccipreader_test.go + - id: smoke/ccip/ccip_reader_test.go:* + path: integration-tests/smoke/ccip/ccip_reader_test.go test_env_type: in-memory runs_on: ubuntu-latest triggers: - PR Integration CCIP Tests - test_cmd: cd integration-tests/contracts && go test ccipreader_test.go -timeout 5m -test.parallel=1 -count=1 -json + test_cmd: cd integration-tests/smoke/ccip && go test ccip_reader_test.go -timeout 5m -test.parallel=1 -count=1 -json - id: smoke/ccip/ccip_usdc_test.go:* path: integration-tests/smoke/ccip/ccip_usdc_test.go diff --git a/.github/scripts/map-affected-files-to-modules.sh b/.github/scripts/map-affected-files-to-modules.sh new file mode 100755 index 00000000000..34f058529cf --- /dev/null +++ b/.github/scripts/map-affected-files-to-modules.sh @@ -0,0 +1,60 @@ +#!/bin/bash +set -e + +# This script: +# 1. Finds all modules. +# 2. Maps changed files (passed as a param) to found modules. +# 3. Prints out the affected modules. +# 4. Output the result (as JSON) to a GitHub Actions environment variable. + +# Get the list of changed files as parameter (from JSON array) +changed_files=$(echo "$1" | jq -r '.[]') +echo "Changed files: $changed_files" + +# 1. Find all modules in the repository, +# - Strip the leading './' from the path +# (necessary for comparison, affected files do not have leading './') +modules=$(find . -name 'go.mod' -exec dirname {} \; | sed 's|^./||' | uniq) +echo "Found modules: $modules" + +# Use a Bash associative array to track unique modules +declare -A unique_modules + +for path_to_file in $changed_files; do + echo "Resolving a module affected by a file: '$path_to_file'" + # the flag that indicates if the path matches any module + is_path_in_modules=false + for module in $modules; do + echo "Validating against module: '$module'" + # if a module's name matches with a file path + # add it, to the affected modules array, skipping the root (`.`) + if [[ $module != "." && $path_to_file =~ ^$module* ]]; then + echo -e "File '$path_to_file' mapped to the module '$module'\n" + unique_modules["$module"]="$module" + is_path_in_modules=true + break + fi + done + # if no matched module default to root module + if [[ $is_path_in_modules == false ]]; then + echo "File '$path_to_file' did not match any module, defaulting to root '.'" + unique_modules["."]="." + is_path_in_modules=false + fi + is_path_in_modules=false +done + +# if the path is empty (for any reason), it will not get to the loop, +# so if the unique_modules array is empty, default to the root module +if [[ ${#unique_modules[@]} -eq 0 ]]; then + echo "No files were changed, defaulting to the root module '.'" + unique_modules["."]="." +fi + +# Convert keys (module names) of the associative array to an indexed array +affected_modules=("${!unique_modules[@]}") +echo "Affected modules: ${affected_modules[@]}" + +# Convert bash array to a JSON array for GitHub Actions +json_array=$(printf '%s\n' "${affected_modules[@]}" | jq -R . | jq -s . | jq -c) +echo "module_names=$json_array" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/automation-benchmark-tests.yml b/.github/workflows/automation-benchmark-tests.yml index 3a826f523a0..ae73a65eb5f 100644 --- a/.github/workflows/automation-benchmark-tests.yml +++ b/.github/workflows/automation-benchmark-tests.yml @@ -5,11 +5,11 @@ on: test_config_override_path: description: Path to a test config file used to override the default test config required: false - type: string + type: string test_secrets_override_key: description: Key to run tests with custom test secrets required: false - type: string + type: string slackMemberID: description: Notifies test results (Not your @) required: true @@ -28,7 +28,7 @@ on: jobs: run-e2e-tests-workflow: name: Run E2E Tests - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0d4a2b2b009c87b5c366d0b97f7a8d7de2f60760 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@61acf908014e2fe42c04f2a507c79f97eb5f8c4d with: test_path: .github/e2e-tests.yml test_ids: '${{ inputs.testType }}/automation_test.go:TestAutomationBenchmark' @@ -36,6 +36,7 @@ jobs: SLACK_USER: ${{ inputs.slackMemberID }} SLACK_CHANNEL: C03KJ5S7KEK team: ${{ inputs.team }} + test_secrets_override_key: ${{ github.event.inputs.test_secrets_override_key }} secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} @@ -43,7 +44,6 @@ jobs: PROD_AWS_ACCOUNT_NUMBER: ${{ secrets.AWS_ACCOUNT_ID_PROD }} QA_PYROSCOPE_INSTANCE: ${{ secrets.QA_PYROSCOPE_INSTANCE }} QA_PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} GRAFANA_INTERNAL_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} GRAFANA_INTERNAL_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} GRAFANA_INTERNAL_HOST: ${{ secrets.GRAFANA_INTERNAL_HOST }} @@ -51,10 +51,12 @@ jobs: LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} LOKI_URL: ${{ secrets.LOKI_URL }} LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} AWS_REGION: ${{ secrets.QA_AWS_REGION }} AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} - AWS_API_GW_HOST_GRAFANA: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} + AWS_API_GW_HOST_GRAFANA: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} TEST_SECRETS_OVERRIDE_BASE64: ${{ secrets[inputs.test_secrets_override_key] }} SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} SLACK_API_KEY: ${{ secrets.QA_SLACK_API_KEY }} + MAIN_DNS_ZONE_PUBLIC_SDLC: ${{ secrets.MAIN_DNS_ZONE_PUBLIC_SDLC }} + AWS_K8S_CLUSTER_NAME_SDLC: ${{ secrets.AWS_K8S_CLUSTER_NAME_SDLC }} diff --git a/.github/workflows/automation-load-tests.yml b/.github/workflows/automation-load-tests.yml index c11e353a7db..42bd47649ef 100644 --- a/.github/workflows/automation-load-tests.yml +++ b/.github/workflows/automation-load-tests.yml @@ -5,7 +5,7 @@ on: test_config_override_path: description: Path to a test config file used to override the default test config required: false - type: string + type: string test_secrets_override_key: description: 'Key to run tests with custom test secrets' required: false @@ -23,7 +23,7 @@ on: jobs: run-e2e-tests-workflow: name: Run E2E Tests - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0d4a2b2b009c87b5c366d0b97f7a8d7de2f60760 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@61acf908014e2fe42c04f2a507c79f97eb5f8c4d with: test_path: .github/e2e-tests.yml test_ids: 'load/automationv2_1/automationv2_1_test.go:TestLogTrigger' @@ -31,6 +31,7 @@ jobs: SLACK_USER: ${{ inputs.slackMemberID }} SLACK_CHANNEL: C03KJ5S7KEK team: ${{ inputs.team }} + test_secrets_override_key: ${{ github.event.inputs.test_secrets_override_key }} secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} @@ -38,7 +39,6 @@ jobs: PROD_AWS_ACCOUNT_NUMBER: ${{ secrets.AWS_ACCOUNT_ID_PROD }} QA_PYROSCOPE_INSTANCE: ${{ secrets.QA_PYROSCOPE_INSTANCE }} QA_PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} GRAFANA_INTERNAL_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} GRAFANA_INTERNAL_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} GRAFANA_INTERNAL_HOST: ${{ secrets.GRAFANA_INTERNAL_HOST }} @@ -46,10 +46,12 @@ jobs: LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} LOKI_URL: ${{ secrets.LOKI_URL }} LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} AWS_REGION: ${{ secrets.QA_AWS_REGION }} AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} - AWS_API_GW_HOST_GRAFANA: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} + AWS_API_GW_HOST_GRAFANA: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} TEST_SECRETS_OVERRIDE_BASE64: ${{ secrets[inputs.test_secrets_override_key] }} SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} SLACK_API_KEY: ${{ secrets.QA_SLACK_API_KEY }} + MAIN_DNS_ZONE_PUBLIC_SDLC: ${{ secrets.MAIN_DNS_ZONE_PUBLIC_SDLC }} + AWS_K8S_CLUSTER_NAME_SDLC: ${{ secrets.AWS_K8S_CLUSTER_NAME_SDLC }} diff --git a/.github/workflows/automation-nightly-tests.yml b/.github/workflows/automation-nightly-tests.yml index c184021f028..753ecd4f2a0 100644 --- a/.github/workflows/automation-nightly-tests.yml +++ b/.github/workflows/automation-nightly-tests.yml @@ -10,7 +10,7 @@ on: jobs: run-e2e-tests-workflow: name: Run E2E Tests - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@61acf908014e2fe42c04f2a507c79f97eb5f8c4d # ctf-run-tests@0.2.0 with: test_path: .github/e2e-tests.yml test_trigger: Automation Nightly Tests @@ -26,7 +26,6 @@ jobs: PROD_AWS_ACCOUNT_NUMBER: ${{ secrets.AWS_ACCOUNT_ID_PROD }} QA_PYROSCOPE_INSTANCE: ${{ secrets.QA_PYROSCOPE_INSTANCE }} QA_PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} GRAFANA_INTERNAL_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} GRAFANA_INTERNAL_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} GRAFANA_INTERNAL_HOST: ${{ secrets.GRAFANA_INTERNAL_HOST }} @@ -40,3 +39,5 @@ jobs: AWS_API_GW_HOST_GRAFANA: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} TEST_SECRETS_OVERRIDE_BASE64: ${{ secrets[inputs.test_secrets_override_key] }} SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} + MAIN_DNS_ZONE_PUBLIC_SDLC: ${{ secrets.MAIN_DNS_ZONE_PUBLIC_SDLC }} + AWS_K8S_CLUSTER_NAME_SDLC: ${{ secrets.AWS_K8S_CLUSTER_NAME_SDLC }} \ No newline at end of file diff --git a/.github/workflows/automation-ondemand-tests.yml b/.github/workflows/automation-ondemand-tests.yml index eef02dcddb2..5b940d867e9 100644 --- a/.github/workflows/automation-ondemand-tests.yml +++ b/.github/workflows/automation-ondemand-tests.yml @@ -36,7 +36,7 @@ on: default: false required: true with_existing_remote_runner_version: - description: 'Tag of the existing remote runner version to use (Leave empty to build from head/ref)' + description: 'Tag of the existing remote runner version to use (Leave empty to build from head/ref)' required: false type: string team: @@ -52,48 +52,59 @@ jobs: outputs: test_list: ${{ steps.set-tests.outputs.test_list }} require_chainlink_image_versions_in_qa_ecr: ${{ steps.determine-chainlink-image-check.outputs.require_chainlink_image_versions_in_qa_ecr }} + env: + GH_INPUTS_CHAINLINK_IMAGE: ${{ inputs.chainlinkImage }} + GH_INPUTS_CHAINLINK_IMAGE_UPDATE: ${{ inputs.chainlinkImageUpdate }} + GH_INPUTS_CHAINLINK_VERSION: ${{ inputs.chainlinkVersion }} + GH_INPUTS_CHAINLINK_VERSION_UPDATE: ${{ inputs.chainlinkVersionUpdate }} steps: - name: Determine build to use id: determine-build shell: bash run: | - if [[ "${{ inputs.chainlinkImage }}" == "QA_ECR" ]]; then + if [[ "$GH_INPUTS_CHAINLINK_IMAGE" == "QA_ECR" ]]; then echo "image='{{ env.QA_CHAINLINK_IMAGE }}'" >> $GITHUB_ENV - else - echo "image=${{ inputs.chainlinkImage }}" >> $GITHUB_ENV + else + echo "image=$GH_INPUTS_CHAINLINK_IMAGE" >> $GITHUB_ENV fi - if [[ "${{ inputs.chainlinkImageUpdate }}" == "QA_ECR" ]]; then + if [[ "$GH_INPUTS_CHAINLINK_IMAGE_UPDATE" == "QA_ECR" ]]; then echo "upgrade_image='{{ env.QA_CHAINLINK_IMAGE }}'" >> $GITHUB_ENV else - echo "upgrade_image=${{ inputs.chainlinkImageUpdate }}" >> $GITHUB_ENV + echo "upgrade_image=$GH_INPUTS_CHAINLINK_IMAGE_UPDATE" >> $GITHUB_ENV fi - if [[ -z "${{ inputs.chainlinkVersion }}" ]] && [[ "${{ inputs.chainlinkImage }}" == "QA_ECR" ]]; then + if [[ -z "$GH_INPUTS_CHAINLINK_VERSION" ]] && [[ "$CHAINLINK_IMAGE" == "QA_ECR" ]]; then echo "version=${{ github.sha }}" >> $GITHUB_ENV - else - echo "version=${{ inputs.chainlinkVersion }}" >> $GITHUB_ENV + else + echo "version=$GH_INPUTS_CHAINLINK_VERSION" >> $GITHUB_ENV fi - if [[ -z "${{ inputs.chainlinkVersionUpdate }}" ]] && [[ "${{ inputs.chainlinkImageUpdate }}" == "QA_ECR" ]]; then + if [[ -z "$GH_INPUTS_CHAINLINK_VERSION_UPDATE" ]] && [[ "$GH_INPUTS_CHAINLINK_IMAGE_UPDATE" == "QA_ECR" ]]; then echo "upgrade_version=${{ github.sha }}" >> $GITHUB_ENV else - echo "upgrade_version=${{ inputs.chainlinkVersionUpdate }}" >> $GITHUB_ENV + echo "upgrade_version=$GH_INPUTS_CHAINLINK_VERSION_UPDATE" >> $GITHUB_ENV fi - name: Check if chainlink image check required id: determine-chainlink-image-check shell: bash - run: | + env: + CHAINLKINK_IMAGE: ${{ github.event.inputs.chainlinkImage }} + CHAINLINK_IMAGE_UPDATE: ${{ github.event.inputs.chainlinkImageUpdate }} + run: | chainlink_image_versions="" - if [ "${{ github.event.inputs.chainlinkImage }}" = "QA_ECR" ]; then + if [ "$CHAINLKINK_IMAGE" = "QA_ECR" ]; then chainlink_image_versions+="${{ env.version }}," fi - if [ "${{ github.event.inputs.chainlinkImageUpdate }}" = "QA_ECR" ]; then + if [ "$CHAINLINK_IMAGE_UPDATE" = "QA_ECR" ]; then chainlink_image_versions+="${{ env.upgrade_version }}" fi - echo "require_chainlink_image_versions_in_qa_ecr=$chainlink_image_versions" >> $GITHUB_OUTPUT + echo "require_chainlink_image_versions_in_qa_ecr=$chainlink_image_versions" >> $GITHUB_OUTPUT - name: Set tests to run id: set-tests + env: + GH_EVENT_INPUTS_ENABLE_REORG: ${{ github.event.inputs.enableReorg }} + GH_EVENT_INPUTS_ENABLE_CHAOS: ${{ github.event.inputs.enableChaos }} run: | - # Always run upgrade tests + # Always run upgrade tests cat > test_list.yaml <> test_list.yaml <> test_list.yaml <- + ${{ + steps.match-some.outputs.core-ci == 'true' || + steps.match-every.outputs.non-ignored == 'true' || + github.event_name == 'schedule' || + github.event_name == 'workflow_dispatch' + }} + should-run-golangci: >- + ${{ + steps.match-some.outputs.golang-ci == 'true' || + steps.match-every.outputs.non-ignored == 'true' + }} + should-run-scripts-test: >- + ${{ + steps.match-some.outputs.scripts == 'true' || + github.event_name == 'schedule' || + github.event_name == 'workflow_dispatch' + }} runs-on: ubuntu-latest steps: - name: Checkout the repo uses: actions/checkout@v4.2.1 with: + persist-credentials: false repository: smartcontractkit/chainlink - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 id: match-some with: # "if any changed file matches one or more of the conditions" (https://github.com/dorny/paths-filter/issues/225) predicate-quantifier: some - # deployment - any changes to files in `deployments/` + # deployment - any changes to files in the `deployments/` + # scripts - any changes to files in the `core/scripts/` # core-ci - any changes that could affect this workflow definition # golang-ci - any changes that could affect the linting result filters: | @@ -60,6 +69,8 @@ jobs: - '.golangci.yml' - '.github/workflows/ci-core.yml' - '.github/actions/**' + scripts: + - 'core/scripts/**' - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 id: match-every with: @@ -67,14 +78,18 @@ jobs: predicate-quantifier: every # non-integration-tests - only changes made outside of the `integration-tests` directory # non-ignored - only changes except for the negated ones + # all - changes in any directory # - This is opt-in on purpose. To be safe, new files are assumed to have an affect on CI Core unless listed here specifically. + # Enable listing of files matching each filter. + # Paths to files will be available in `${FILTER_NAME}_files` output variable. + # Paths will be formatted as JSON array + list-files: json filters: | non-integration-tests: - '**' - '!integration-tests/**' non-ignored: - '**' - - '!docs/**' - '!integration-tests/**' - '!tools/secrets/**' - '!tools/goreleaser-config/**' @@ -91,24 +106,50 @@ jobs: - '!nix-darwin-shell-hook.sh' - '!LICENSE' - '!.github/**' - + all: + - '**' + + - name: Resolve affected files to affected modules + id: resolved-modules + shell: bash + env: + GH_EVENT_NAME: ${{ github.event_name }} + run: | + # if scheduled, run for all modules. Otherwise, run for only affected modules. + if [[ "$GH_EVENT_NAME" == "schedule" ]]; then + json_array=$(find . -name 'go.mod' -exec dirname {} \; | sed 's|^./||' | uniq | jq -R -s -c 'split("\n") | map(select(length > 0))') + echo "module_names=$json_array" >> "$GITHUB_OUTPUT" + else + # Ensure the step uses `with.list-files: json` to get the list of files in JSON format + bash ./.github/scripts/map-affected-files-to-modules.sh '${{ steps.match-every.outputs.all_files }}' + fi + golangci: - # We don't directly merge dependabot PRs, so let's not waste the resources + name: GolangCI Lint + needs: [filter, run-frequency] + # We don't directly merge dependabot PRs to not waste the resources. if: ${{ (github.event_name == 'pull_request' || github.event_name == 'schedule') && github.actor != 'dependabot[bot]' }} - name: lint permissions: - # For golangci-lint-actions to annotate code in the PR. + # To annotate code in the PR. checks: write contents: read # For golangci-lint-action's `only-new-issues` option. pull-requests: read runs-on: ubuntu-24.04-8cores-32GB-ARM - needs: [filter, run-frequency] + strategy: + fail-fast: false + matrix: + modules: ${{ fromJson(needs.filter.outputs.affected-modules) }} steps: - - uses: actions/checkout@v4.2.1 - - name: Golang Lint + - name: Checkout + uses: actions/checkout@v4.2.1 + with: + persist-credentials: false + - name: Golang Lint (${{ matrix.modules }}) + id: golang-lint uses: ./.github/actions/golangci-lint - if: ${{ needs.filter.outputs.should-run-golangci == 'true' }} + with: + go-directory: ${{ matrix.modules }} - name: Notify Slack if: ${{ failure() && needs.run-frequency.outputs.one-per-day-frequency == 'true' }} uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 @@ -116,7 +157,24 @@ jobs: SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} with: channel-id: "#team-core" - slack-message: "golangci-lint failed: \n${{ format('https://github.com/{0}/actions/runs/{1}', github.repository, github.run_id) }}" + slack-message: | + "golangci-lint failed (${{ matrix.modules }}) + - Run: ${{ format('https://github.com/{0}/actions/runs/{1}', github.repository, github.run_id) }}" + - Report: ${{ steps.golang-lint.outputs.golang-report-artifact-url }}" + + # Fails if any golangci-lint matrix jobs fails and silently succeeds otherwise + # Consolidates golangci-lint matrix job results under one required `lint` check + # Inclusive check: all (new) modules are analyzed, but no need to enable "required" checks for each one + golangci-matrix-results-validation: + name: lint + needs: [golangci] + runs-on: ubuntu-latest + steps: + - name: Check Golangci-lint Matrix Results + if: ${{ needs.golangci.result != 'success' }} + run: | + echo "At least one 'GolangCI Lint' matrix job failed. Check the failed lint jobs." + exit 1 core: env: @@ -136,11 +194,11 @@ jobs: - cmd: go_core_ccip_deployment_tests os: ubuntu22.04-32cores-128GB printResults: true + - cmd: go_core_fuzz + os: ubuntu22.04-8cores-32GB - cmd: go_core_race_tests # use 64cores for certain scheduled runs only os: ${{ needs.run-frequency.outputs.two-per-day-frequency == 'true' && 'ubuntu-latest-64cores-256GB' || 'ubuntu-latest-32cores-128GB' }} - - cmd: go_core_fuzz - os: ubuntu22.04-8cores-32GB name: Core Tests (${{ matrix.type.cmd }}) # We don't directly merge dependabot PRs, so let's not waste the resources if: ${{ github.actor != 'dependabot[bot]' }} @@ -152,6 +210,8 @@ jobs: steps: - name: Checkout the repo uses: actions/checkout@v4.2.1 + with: + persist-credentials: false - name: Change Modtime of Files (cache optimization) shell: bash @@ -164,6 +224,9 @@ jobs: with: prod: "true" + - name: Install Foundry + uses: ./.github/actions/install-solidity-foundry + - name: Setup Go if: ${{ needs.filter.outputs.should-run-ci-core == 'true' }} uses: ./.github/actions/setup-go @@ -172,11 +235,6 @@ jobs: restore-build-cache-only: ${{ matrix.type.cmd == 'go_core_fuzz' }} build-cache-version: ${{ matrix.type.cmd }} - - name: Replace chainlink-evm deps - if: ${{ needs.filter.outputs.should-run-ci-core == 'true' && inputs.evm-ref != ''}} - shell: bash - run: go get github.com/smartcontractkit/chainlink-integrations/evm/relayer@${{ inputs.evm-ref }} - - name: Setup Solana if: ${{ needs.filter.outputs.should-run-ci-core == 'true' }} uses: ./.github/actions/setup-solana @@ -209,19 +267,7 @@ jobs: - name: Install LOOP Plugins if: ${{ needs.filter.outputs.should-run-ci-core == 'true' }} - run: | - pushd $(go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-feeds) - go install ./cmd/chainlink-feeds - popd - pushd $(go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-data-streams) - go install ./mercury/cmd/chainlink-mercury - popd - pushd $(go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-solana) - go install ./pkg/solana/cmd/chainlink-solana - popd - pushd $(go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-starknet/relayer) - go install ./pkg/chainlink/cmd/chainlink-starknet - popd + run: make install-plugins - name: Increase Timeouts for Fuzz/Race # Increase timeouts for scheduled runs only @@ -285,136 +331,103 @@ jobs: channel-id: "#topic-data-races" slack-message: "Race tests failed: \n${{ format('https://github.com/{0}/actions/runs/{1}', github.repository, github.run_id) }}" - detect-flakey-tests: - needs: [filter, core] - name: Flakey Test Detection + core-scripts-tests: + name: test-scripts + needs: [filter] runs-on: ubuntu-latest - if: always() && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') - env: - CL_DATABASE_URL: postgresql://postgres:postgres@localhost:5432/chainlink_test?sslmode=disable - permissions: - id-token: write - contents: read + if: ${{ needs.filter.outputs.should-run-scripts-test == 'true' }} steps: - - name: Checkout the repo + - name: Checkout uses: actions/checkout@v4.2.1 - - name: Setup node - uses: actions/setup-node@v4.0.4 - - - name: Setup NodeJS - uses: ./.github/actions/setup-nodejs - with: - prod: "true" - - name: Setup Go uses: ./.github/actions/setup-go - - - name: Setup Postgres - uses: ./.github/actions/setup-postgres - - - name: Touching core/web/assets/index.html - run: mkdir -p core/web/assets && touch core/web/assets/index.html - - - name: Download Go vendor packages - run: go mod download - - - name: Replace chainlink-evm deps - if: ${{ github.event_name == 'workflow_dispatch' && inputs.evm-ref != ''}} - shell: bash - run: go get github.com/smartcontractkit/chainlink-integrations/evm/relayer@${{ inputs.evm-ref }} - - - name: Build binary - run: go build -o chainlink.test . - - - name: Setup DB - run: ./chainlink.test local db preparetest - - - name: Load test outputs - uses: actions/download-artifact@v4.1.8 with: - name: go_core_tests_logs - path: ./artifacts - - - name: Delete go_core_tests_logs/coverage.txt - shell: bash - run: | - # Need to delete coverage.txt so the disk doesn't fill up - rm -f ./artifacts/go_core_tests_logs/coverage.txt - - - name: Build flakey test runner - run: go build ./tools/flakeytests/cmd/runner - - - name: Re-run tests + go-version-file: core/scripts/go.mod + go-module-file: core/scripts/go.sum + + - name: Run Tests env: - GRAFANA_INTERNAL_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - GRAFANA_INTERNAL_HOST: ${{ secrets.GRAFANA_INTERNAL_HOST }} - GITHUB_EVENT_PATH: ${{ github.event_path }} - GITHUB_EVENT_NAME: ${{ github.event_name }} - GITHUB_REPO: ${{ github.repository }} - GITHUB_RUN_ID: ${{ github.run_id }} - run: | - ./runner \ - -grafana_auth=$GRAFANA_INTERNAL_BASIC_AUTH \ - -grafana_host=$GRAFANA_INTERNAL_HOST \ - -gh_sha=$GITHUB_SHA \ - -gh_event_path=$GITHUB_EVENT_PATH \ - -gh_event_name=$GITHUB_EVENT_NAME \ - -gh_run_id=$GITHUB_RUN_ID \ - -gh_repo=$GITHUB_REPO \ - -command=./tools/bin/go_core_tests \ - `ls -R ./artifacts/output.txt` - - name: Store logs artifacts + OUTPUT_FILE: ./output.txt + run: ./tools/bin/go_core_scripts_tests ./... + + - name: Store test report artifacts if: ${{ always() }} uses: actions/upload-artifact@v4.4.3 with: - name: flakey_test_runner_logs + name: go_core_scripts_tests_logs path: | ./output.txt - retention-days: 7 + ./coverage.txt + retention-days: 7 scan: name: SonarQube Scan - needs: [core, run-frequency] - if: ${{ always() && needs.run-frequency.outputs.four-per-day-frequency == 'true' && github.actor != 'dependabot[bot]' }} + needs: [golangci, core, core-scripts-tests] + if: ${{ always() && github.actor != 'dependabot[bot]' }} runs-on: ubuntu-latest steps: - name: Checkout the repo uses: actions/checkout@v4.2.1 with: + persist-credentials: false fetch-depth: 0 # fetches all history for all tags and branches to provide more metadata for sonar reports - - name: Download all workflow run artifacts + - name: Download all workflow artifacts uses: actions/download-artifact@v4.1.8 - name: Check and Set SonarQube Report Paths shell: bash run: | # Check and assign paths for coverage/test reports in go_core_tests_logs - if [ -d "go_core_tests_logs" ]; then - sonarqube_coverage_report_paths=$(find go_core_tests_logs -name coverage.txt | paste -sd "," -) - sonarqube_tests_report_paths=$(find go_core_tests_logs -name output.txt | paste -sd "," -) + core_artifact="go_core_tests_logs" + if [ -d "$core_artifact" ]; then + echo "Found $core_artifact" + sonarqube_coverage_report_paths=$(find "$core_artifact" -name coverage.txt | paste -sd "," -) + sonarqube_tests_report_paths=$(find "$core_artifact" -name output.txt | paste -sd "," -) + echo "Coverage report paths: $sonarqube_coverage_report_paths" + echo "Tests report paths: $sonarqube_tests_report_paths" else + echo "Did not find $core_artifact" sonarqube_coverage_report_paths="" sonarqube_tests_report_paths="" fi # Check and assign paths for coverage/test reports in go_core_tests_integration_logs - if [ -d "go_core_tests_integration_logs" ]; then - integration_coverage_paths=$(find go_core_tests_integration_logs -name coverage.txt | paste -sd "," -) - integration_tests_paths=$(find go_core_tests_integration_logs -name output.txt | paste -sd "," -) + integration_tests_artifact="go_core_tests_integration_logs" + if [ -d "$integration_tests_artifact" ]; then + echo "Found $integration_tests_artifact" + integration_coverage_paths=$(find "$integration_tests_artifact" -name coverage.txt | paste -sd "," -) + integration_tests_paths=$(find "$integration_tests_artifact" -name output.txt | paste -sd "," -) + # Append to existing paths if they are set, otherwise assign directly sonarqube_coverage_report_paths="${sonarqube_coverage_report_paths:+$sonarqube_coverage_report_paths,}$integration_coverage_paths" sonarqube_tests_report_paths="${sonarqube_tests_report_paths:+$sonarqube_tests_report_paths,}$integration_tests_paths" fi - # Check and assign paths for lint reports - if [ -d "golangci-lint-report" ]; then - sonarqube_lint_report_paths=$(find golangci-lint-report -name golangci-lint-report.xml | paste -sd "," -) - else - sonarqube_lint_report_paths="" + # Check and assign paths for coverage/test reports in go_core_scripts_tests_logs + scripts_tests_artifact="go_core_scripts_tests_logs" + if [ -d "$scripts_tests_artifact" ]; then + echo "Found $scripts_tests_artifact" + scripts_coverage_paths=$(find "$scripts_tests_artifact" -name coverage.txt | paste -sd "," -) + scripts_tests_paths=$(find "$scripts_tests_artifact" -name output.txt | paste -sd "," -) + + # Append to existing paths if they are set, otherwise assign directly + sonarqube_coverage_report_paths="${sonarqube_coverage_report_paths:+$sonarqube_coverage_report_paths,}$scripts_coverage_paths" + sonarqube_tests_report_paths="${sonarqube_tests_report_paths:+$sonarqube_tests_report_paths,}$scripts_tests_paths" fi + # Check and assign paths for lint reports + # To find reports in the folders named differently (because of the matrix strategy), + # We need to loop through the artifacts. It allows usage of RegExp folders (skipped if not found). + for golang_lint_artifact in golangci-lint-report* + do + echo "Found golangci-lint-report artifacts" + sonarqube_lint_report_paths=$(find -type f -name 'golangci-lint-report.xml' -printf "%p,") + echo "Lint report paths: $sonarqube_lint_report_paths" + break + done + ARGS="" if [[ -z "$sonarqube_tests_report_paths" ]]; then echo "::warning::No test report paths found, will not pass to sonarqube" @@ -450,58 +463,17 @@ jobs: SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} SONAR_SCANNER_OPTS: "-Xms6g -Xmx8g" - trigger-flaky-test-detection-for-root-project: - name: Flakeguard Root Project - uses: ./.github/workflows/flakeguard.yml - if: ${{ github.event_name == 'pull_request' }} - with: - repoUrl: 'https://github.com/smartcontractkit/chainlink' - projectPath: '.' - baseRef: ${{ github.base_ref }} - headRef: ${{ github.head_ref }} - maxPassRatio: '1.0' - findByTestFilesDiff: true - findByAffectedPackages: false - slackNotificationAfterTestsChannelId: 'C07TRF65CNS' #flaky-test-detector-notifications - extraArgs: '{ "skipped_tests": "TestChainComponents", "run_with_race": "true", "print_failed_tests": "true", "test_repeat_count": "3", "omit_test_outputs_on_success": "true" }' - secrets: - SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - trigger-flaky-test-detection-for-deployment-project: - name: Flakeguard Deployment Project - uses: ./.github/workflows/flakeguard.yml - needs: [filter] - if: ${{ github.event_name == 'pull_request' && needs.filter.outputs.deployment-changes == 'true'}} - with: - repoUrl: 'https://github.com/smartcontractkit/chainlink' - projectPath: 'deployment' - baseRef: ${{ github.base_ref }} - headRef: ${{ github.head_ref }} - maxPassRatio: '1.0' - findByTestFilesDiff: true - findByAffectedPackages: false - slackNotificationAfterTestsChannelId: 'C07TRF65CNS' #flaky-test-detector-notifications - extraArgs: '{ "skipped_tests": "TestAddLane", "run_with_race": "true", "print_failed_tests": "true", "test_repeat_count": "3", "omit_test_outputs_on_success": "true" }' - secrets: - SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - clean: name: Clean Go Tidy & Generate - if: ${{ !contains(join(github.event.pull_request.labels.*.name, ' '), 'skip-smoke-tests') && github.actor != 'dependabot[bot]' }} + if: ${{ github.actor != 'dependabot[bot]' }} runs-on: ubuntu22.04-8cores-32GB defaults: run: shell: bash steps: - - name: Check for Skip Tests Label - if: contains(join(github.event.pull_request.labels.*.name, ' '), 'skip-smoke-tests') - run: | - echo "## \`skip-smoke-tests\` label is active, skipping E2E smoke tests" >>$GITHUB_STEP_SUMMARY - exit 0 - uses: actions/checkout@v4.2.1 with: + persist-credentials: false fetch-depth: 0 - name: Setup Go uses: ./.github/actions/setup-go @@ -511,6 +483,8 @@ jobs: run: curl https://github.com/smartcontractkit/wsrpc/raw/main/cmd/protoc-gen-go-wsrpc/protoc-gen-go-wsrpc --output $HOME/go/bin/protoc-gen-go-wsrpc && chmod +x $HOME/go/bin/protoc-gen-go-wsrpc - name: Setup NodeJS uses: ./.github/actions/setup-nodejs + - name: Install Foundry + uses: ./.github/actions/install-solidity-foundry - name: make generate run: | make rm-mocked diff --git a/.github/workflows/ci-flakeguard.yml b/.github/workflows/ci-flakeguard.yml new file mode 100644 index 00000000000..1bd60b20c94 --- /dev/null +++ b/.github/workflows/ci-flakeguard.yml @@ -0,0 +1,70 @@ +name: Flakeguard CI Core + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +# Run on key branches to make sure integration is good, otherwise run on all PR's +on: + pull_request: + +jobs: + + detect-changes: + name: Detect Changes + permissions: + pull-requests: read + outputs: + deployment-changes: ${{ steps.some.outputs.deployment == 'true' }} + runs-on: ubuntu-latest + steps: + - name: Checkout the repo + uses: actions/checkout@v4.2.1 + with: + persist-credentials: false + - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + id: some + with: + filters: | + deployment: + - 'deployment/**' + + trigger-flaky-test-detection-for-root-project: + name: Flakeguard Root Project + uses: ./.github/workflows/flakeguard.yml + with: + repoUrl: 'https://github.com/smartcontractkit/chainlink' + projectPath: '.' + baseRef: ${{ github.base_ref }} + headRef: ${{ github.head_ref }} + maxPassRatio: '1.0' + findByTestFilesDiff: true + findByAffectedPackages: false + slackNotificationAfterTestsChannelId: 'C07TRF65CNS' #flaky-test-detector-notifications + extraArgs: '{ "skipped_tests": "", "run_with_race": "true", "print_failed_tests": "true", "test_repeat_count": "3", "omit_test_outputs_on_success": "true" }' + secrets: + SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + FLAKEGUARD_SPLUNK_ENDPOINT: ${{ secrets.FLAKEGUARD_SPLUNK_ENDPOINT }} + FLAKEGUARD_SPLUNK_HEC: ${{ secrets.FLAKEGUARD_SPLUNK_HEC }} + + trigger-flaky-test-detection-for-deployment-project: + name: Flakeguard Deployment Project + uses: ./.github/workflows/flakeguard.yml + needs: [detect-changes] + if: ${{ needs.detect-changes.outputs.deployment-changes == 'true'}} + with: + repoUrl: 'https://github.com/smartcontractkit/chainlink' + projectPath: 'deployment' + baseRef: ${{ github.base_ref }} + headRef: ${{ github.head_ref }} + maxPassRatio: '1.0' + findByTestFilesDiff: true + findByAffectedPackages: false + slackNotificationAfterTestsChannelId: 'C07TRF65CNS' #flaky-test-detector-notifications + extraArgs: '{ "skipped_tests": "TestAddLane", "run_with_race": "true", "print_failed_tests": "true", "test_repeat_count": "3", "omit_test_outputs_on_success": "true" }' + secrets: + SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + FLAKEGUARD_SPLUNK_ENDPOINT: ${{ secrets.FLAKEGUARD_SPLUNK_ENDPOINT }} + FLAKEGUARD_SPLUNK_HEC: ${{ secrets.FLAKEGUARD_SPLUNK_HEC }} diff --git a/.github/workflows/ci-protobuf.yml b/.github/workflows/ci-protobuf.yml index 3931ed8d302..1ea44a0ea78 100644 --- a/.github/workflows/ci-protobuf.yml +++ b/.github/workflows/ci-protobuf.yml @@ -9,6 +9,8 @@ jobs: steps: - name: Checkout repo uses: actions/checkout@v4.2.1 + with: + persist-credentials: false - name: Setup buf uses: bufbuild/buf-setup-action@35c243d7f2a909b1d4e40399b348a7fdab27d78d # v1.34.0 diff --git a/.github/workflows/ci-scripts.yml b/.github/workflows/ci-scripts.yml deleted file mode 100644 index 5683641f26b..00000000000 --- a/.github/workflows/ci-scripts.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: CI Scripts - -on: - merge_group: - pull_request: - -jobs: - lint-scripts: - # We don't directly merge dependabot PRs, so let's not waste the resources - if: ${{ (github.event_name == 'pull_request' || github.event_name == 'schedule') && github.actor != 'dependabot[bot]' }} - runs-on: ubuntu-latest - permissions: - # For golangci-lint-actions to annotate code in the PR. - checks: write - contents: read - # For golangci-lint-action's `only-new-issues` option. - pull-requests: read - steps: - - uses: actions/checkout@v4.2.1 - - name: Golang Lint - uses: ./.github/actions/golangci-lint - with: - id: scripts - name: lint-scripts - go-directory: core/scripts - go-version-file: core/scripts/go.mod - go-module-file: core/scripts/go.sum - - test-scripts: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4.2.1 - - name: Setup Go - uses: ./.github/actions/setup-go - with: - go-version-file: core/scripts/go.mod - go-module-file: core/scripts/go.sum - - name: Run Tests - shell: bash - working-directory: core/scripts - run: go test ./... diff --git a/.github/workflows/client-compatibility-tests.yml b/.github/workflows/client-compatibility-tests.yml index 5f986ccf16c..aae8a87f2aa 100644 --- a/.github/workflows/client-compatibility-tests.yml +++ b/.github/workflows/client-compatibility-tests.yml @@ -50,27 +50,30 @@ jobs: - name: Checkout code uses: actions/checkout@v4.2.1 with: + persist-credentials: false fetch-depth: 0 - name: Check for go.mod changes id: changes + env: + GH_BASE_REF: ${{ github.base_ref }} run: | - if [ -z "${{ github.base_ref }}" ]; then + if [ -z "$GH_BASE_REF" ]; then echo "No base branch found, this should not happen in a PR or MQ. Please reach out to the Test Tooling team." echo "Github even that triggered the workflow: $GITHUB_EVENT_NAME" echo "Github ref that triggered the workflow: $GITHUB_REF" exit 1 fi - git fetch origin ${{ github.base_ref }} + git fetch origin $GH_BASE_REF # if no match is found then grep exits with code 1, but if there is a match it exits with code 0 # this will return a match if there are any changes on that corresponding line, for example if spacing was changed - DEPENDENCY_CHANGED=$(git diff -U0 origin/${{ github.base_ref }}...HEAD -- go.mod | grep -q 'github.com/ethereum/go-ethereum'; echo $?) + DEPENDENCY_CHANGED=$(git diff -U0 origin/$GH_BASE_REF...HEAD -- go.mod | grep -q 'github.com/ethereum/go-ethereum'; echo $?) PR_VERSION=$(grep 'github.com/ethereum/go-ethereum' go.mod | awk '{print $2}') # here 0 means a match was found, 1 means no match was found if [ "$DEPENDENCY_CHANGED" -eq 0 ]; then # Dependency was changed in the PR, now compare with the base branch - git fetch origin ${{ github.base_ref }} - BASE_VERSION=$(git show origin/${{ github.base_ref }}:go.mod | grep 'github.com/ethereum/go-ethereum' | awk '{print $2}') + git fetch origin $GH_BASE_REF + BASE_VERSION=$(git show origin/$GH_BASE_REF:go.mod | grep 'github.com/ethereum/go-ethereum' | awk '{print $2}') echo "Base branch version: $BASE_VERSION" echo "PR branch version: $PR_VERSION" @@ -142,6 +145,9 @@ jobs: go install github.com/smartcontractkit/chainlink-testing-framework/tools/ghlatestreleasechecker@v1.0.0 - name: Select EVM implementations to test id: select-implementations + env: + GH_EVENT_INPUTS_BASE64_TEST_LIST: ${{ github.event.inputs.base64TestList }} + GH_EVENT_INPUTS_EVM_IMPLEMENTATIONS: ${{ github.event.inputs.evmImplementations }} run: | PATH=$PATH:$(go env GOPATH)/bin export PATH @@ -184,11 +190,11 @@ jobs: fi echo "evm_implementations=$eth_implementations" >> $GITHUB_OUTPUT elif [ "$GITHUB_EVENT_NAME" = "workflow_dispatch" ]; then - if [ -n "${{ github.event.inputs.base64TestList }}" ]; then + if [ -n "$GH_EVENT_INPUTS_BASE64_TEST_LIST" ]; then echo "Base64-ed Test Input provided, ignoring EVM implementations" else - echo "Will test following EVM implementations: ${{ github.event.inputs.evmImplementations }}" - echo "evm_implementations=${{ github.event.inputs.evmImplementations }}" >> $GITHUB_OUTPUT + echo "Will test following EVM implementations: $GH_EVENT_INPUTS_EVM_IMPLEMENTATIONS" + echo "evm_implementations=$GH_EVENT_INPUTS_EVM_IMPLEMENTATIONS" >> $GITHUB_OUTPUT fi else echo "Will test all EVM implementations" @@ -196,6 +202,12 @@ jobs: fi - name: Select Chainlink version id: select-chainlink-version + env: + GH_EVENT_INPUTS_CHAINLINK_VERSION: ${{ github.event.inputs.chainlinkVersion }} + GH_EVENT_PULL_REQUEST_HEAD_SHA: ${{ github.event.pull_request.head.sha }} + GH_EVENT_MERGE_GROUP_HEAD_SHA: ${{ github.event.merge_group.head_sha }} + GH_REF_NAME: ${{ github.ref_name }} + GH_SHA: ${{ github.sha }} run: | PATH=$PATH:$(go env GOPATH)/bin export PATH @@ -209,9 +221,9 @@ jobs: cl_ref_path="releases" elif [ "$GITHUB_EVENT_NAME" = "workflow_dispatch" ]; then echo "Fetching Chainlink version from input" - if [ -n "${{ github.event.inputs.chainlinkVersion }}" ]; then + if [ -n "$GH_EVENT_INPUTS_CHAINLINK_VERSION" ]; then echo "Chainlink version provided in input" - chainlink_version="${{ github.event.inputs.chainlinkVersion }}" + chainlink_version="$GH_EVENT_INPUTS_CHAINLINK_VERSION" if [[ "$chainlink_version" =~ ^[0-9a-f]{40}$ ]]; then cl_ref_path="commit" chainlink_image_version=$chainlink_version @@ -222,23 +234,23 @@ jobs: fi else echo "Chainlink version not provided in input. Using latest commit SHA." - chainlink_version=${{ github.sha }} + chainlink_version=$GH_SHA chainlink_image_version=$chainlink_version cl_ref_path="commit" fi elif [ "$GITHUB_EVENT_NAME" = "pull_request" ]; then echo "Fetching Chainlink version from PR's head commit" - chainlink_version="${{ github.event.pull_request.head.sha }}" + chainlink_version="$GH_EVENT_PULL_REQUEST_HEAD_SHA" chainlink_image_version=$chainlink_version cl_ref_path="commit" elif [ "$GITHUB_EVENT_NAME" = "merge_queue" ]; then echo "Fetching Chainlink version from merge queue's head commit" - chainlink_version="${{ github.event.merge_group.head_sha }}" + chainlink_version="$GH_EVENT_MERGE_GROUP_HEAD_SHA" chainlink_image_version=$chainlink_version cl_ref_path="commit" elif [ "$GITHUB_REF_TYPE" = "tag" ]; then echo "Fetching Chainlink version from tag" - chainlink_version="${{ github.ref_name }}" + chainlink_version="$GH_REF_NAME" # strip the 'v' from the version, because we tag our Docker images without it chainlink_image_version="${chainlink_version#v}" cl_ref_path="releases" @@ -253,13 +265,16 @@ jobs: echo "cl_ref_path=$cl_ref_path" >> $GITHUB_OUTPUT - name: Get image count id: get-image-count + env: + GH_EVENT_INPUTS_BASE64_TEST_LIST: ${{ github.event.inputs.base64TestList }} + GH_EVENT_INPUTS_LATEST_VERSIONS_NUMBER: ${{ github.event.inputs.latestVersionsNumber }} run: | if [ "$GITHUB_EVENT_NAME" = "workflow_dispatch" ]; then echo "Fetching latest image count from input" - if [ -n "${{ github.event.inputs.base64TestList }}" ]; then + if [ -n "$GH_EVENT_INPUTS_BASE64_TEST_LIST" ]; then echo "Base64-ed Test Input provided, ignoring latest image count" else - image_count="${{ github.event.inputs.latestVersionsNumber }}" + image_count="$GH_EVENT_INPUTS_LATEST_VERSIONS_NUMBER" echo "image_count=$image_count" >> $GITHUB_OUTPUT fi else @@ -326,6 +341,7 @@ jobs: - name: Checkout the repo uses: actions/checkout@v4.2.1 with: + persist-credentials: false ref: ${{ needs.select-versions.outputs.chainlink_version }} - name: Build Chainlink Image uses: ./.github/actions/build-chainlink-image @@ -595,6 +611,7 @@ jobs: - name: Checkout the repo uses: actions/checkout@v4.2.1 with: + persist-credentials: false repository: smartcontractkit/chainlink ref: ${{ needs.select-versions.outputs.chainlink_version }} - name: Setup GAP for Grafana @@ -851,6 +868,7 @@ jobs: - name: Checkout the repo uses: actions/checkout@v4.2.1 with: + persist-credentials: false ref: ${{ needs.select-versions.outputs.chainlink_version }} - name: Get test results for ${{ matrix.product }} id: get-product-results diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index d90139e5292..c0294645465 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -23,6 +23,7 @@ jobs: - name: Checkout the repo uses: actions/checkout@v4.2.1 with: + persist-credentials: false repository: smartcontractkit/chainlink - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 id: changes @@ -55,6 +56,8 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4.2.1 + with: + persist-credentials: false - name: Set up Go if: ${{ matrix.type.language == 'go' && matrix.type.should-run == 'true' }} diff --git a/.github/workflows/crib-integration-test.yml b/.github/workflows/crib-integration-test.yml index 5dd24167ab0..97f87c7d7fc 100644 --- a/.github/workflows/crib-integration-test.yml +++ b/.github/workflows/crib-integration-test.yml @@ -6,9 +6,11 @@ on: schedule: - cron: "0 1 * * *" workflow_call: + concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + jobs: test: runs-on: ubuntu-latest @@ -20,99 +22,24 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4.2.1 - - - uses: cachix/install-nix-action@ba0dd844c9180cbf77aa72a116d6fbc515d0e87b # v27 with: - nix_path: nixpkgs=channel:nixos-unstable + persist-credentials: false - - name: setup-gap crib - uses: smartcontractkit/.github/actions/setup-gap@00b58566e0ee2761e56d9db0ea72b783fdb89b8d # setup-gap@0.4.0 + - name: Run CRIB Integration Tests + uses: ./.github/actions/crib with: - aws-role-duration-seconds: 3600 # 1 hour aws-role-arn: ${{ secrets.AWS_OIDC_CRIB_ROLE_ARN_STAGE }} - api-gateway-host: ${{ secrets.AWS_API_GW_HOST_CRIB_STAGE }} aws-region: ${{ secrets.AWS_REGION }} - ecr-private-registry: ${{ secrets.AWS_ACCOUNT_ID_PROD }} + aws-account-id: ${{ secrets.AWS_ACCOUNT_ID_PROD }} + api-gw-host-crib: ${{ secrets.AWS_API_GW_HOST_CRIB_STAGE }} + api-gw-host-k8s: ${{ secrets.AWS_API_GW_HOST_K8S_STAGE }} k8s-cluster-name: ${{ secrets.AWS_K8S_CLUSTER_NAME_STAGE }} - gap-name: crib - use-private-ecr-registry: true - use-tls: true - proxy-port: 8080 - metrics-job-name: "test" - gc-basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - gc-host: ${{ secrets.GRAFANA_INTERNAL_HOST }} - gc-org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - - - name: setup-gap k8s - uses: smartcontractkit/.github/actions/setup-gap@00b58566e0ee2761e56d9db0ea72b783fdb89b8d # setup-gap@0.4.0 - with: - aws-role-duration-seconds: 3600 # 1 hour - aws-role-arn: ${{ secrets.AWS_OIDC_CRIB_ROLE_ARN_STAGE }} - api-gateway-host: ${{ secrets.AWS_API_GW_HOST_K8S_STAGE }} - aws-region: ${{ secrets.AWS_REGION }} - ecr-private-registry: ${{ secrets.AWS_ACCOUNT_ID_PROD }} - k8s-cluster-name: ${{ secrets.AWS_K8S_CLUSTER_NAME_STAGE }} - gap-name: k8s - use-private-ecr-registry: true - use-k8s: true - proxy-port: 8443 - metrics-job-name: "test" - gc-basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - gc-host: ${{ secrets.GRAFANA_INTERNAL_HOST }} - gc-org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - - - name: Setup GitHub token using GATI - id: token - uses: smartcontractkit/.github/actions/setup-github-token@c0b38e6c40d72d01b8d2f24f92623a2538b3dedb # main - with: - aws-role-arn: ${{ secrets.AWS_OIDC_GLOBAL_READ_ONLY_TOKEN_ISSUER_ROLE_ARN }} - aws-lambda-url: ${{ secrets.AWS_INFRA_RELENG_TOKEN_ISSUER_LAMBDA_URL }} - aws-region: ${{ secrets.AWS_REGION }} - aws-role-duration-seconds: "1800" - - name: Debug workspace dir - shell: bash - run: | - echo ${{ github.workspace }} - echo $GITHUB_WORKSPACE - - - name: Deploy and validate CRIB Environment for Core - uses: smartcontractkit/.github/actions/crib-deploy-environment@d4d9ce3fad044642d8d2f7ae5aca9f8c78b0073a # crib-deploy-environment@2.1.2 - id: deploy-crib - with: - github-token: ${{ steps.token.outputs.access-token }} - api-gateway-host: ${{ secrets.AWS_API_GW_HOST_K8S_STAGE }} - aws-region: ${{ secrets.AWS_REGION }} - aws-role-arn: ${{ secrets.AWS_OIDC_CRIB_ROLE_ARN_STAGE }} - ecr-private-registry: ${{ secrets.AWS_ACCOUNT_ID_PROD }} + aws-token-issuer-role-arn: ${{ secrets.AWS_OIDC_GLOBAL_READ_ONLY_TOKEN_ISSUER_ROLE_ARN }} + aws-token-issuer-lambda-url: ${{ secrets.AWS_INFRA_RELENG_TOKEN_ISSUER_LAMBDA_URL }} ingress-base-domain: ${{ secrets.INGRESS_BASE_DOMAIN_STAGE }} - k8s-cluster-name: ${{ secrets.AWS_K8S_CLUSTER_NAME_STAGE }} - command: "core-dev-simulated-core-ocr1" + k8s-staging-ingress-suffix: ${{ secrets.K8S_STAGING_INGRESS_SUFFIX }} + gap-url-integration-tests: ${{ secrets.GAP_URL }} crib-alert-slack-webhook: ${{ secrets.CRIB_ALERT_SLACK_WEBHOOK }} - product-image: ${{ secrets.AWS_SDLC_ECR_HOSTNAME }}/chainlink - product-image-tag: develop - - uses: actions/checkout@v4.2.1 - - name: Set up Go - uses: ./.github/actions/setup-go - with: - go-version-file: 'go.mod' - - name: Run CRIB integration test - working-directory: integration-tests/crib - env: - K8S_STAGING_INGRESS_SUFFIX: ${{ secrets.K8S_STAGING_INGRESS_SUFFIX }} - CRIB_NAMESPACE: ${{ steps.deploy-crib.outputs.devspace-namespace }} - CRIB_NETWORK: geth - CRIB_NODES: 5 - GAP_URL: ${{ secrets.GAP_URL }} - SETH_LOG_LEVEL: info - # RESTY_DEBUG: true - TEST_PERSISTENCE: true - E2E_TEST_CHAINLINK_IMAGE: public.ecr.aws/chainlink/chainlink - E2E_TEST_CHAINLINK_VERSION: latest - run: |- - go test -v -run TestCRIBChaos - - name: Destroy CRIB Environment - id: destroy - if: always() && steps.deploy-crib.outputs.devspace-namespace != '' - uses: smartcontractkit/.github/actions/crib-purge-environment@c0b38e6c40d72d01b8d2f24f92623a2538b3dedb # crib-purge-environment@0.1.0 - with: - namespace: ${{ steps.deploy-crib.outputs.devspace-namespace }} + crib-chainlink-docker-image-name: ${{ secrets.AWS_SDLC_ECR_HOSTNAME }}/chainlink + crib-chainlink-docker-image-tag: develop + main-dns-zone: ${{ secrets.MAIN_DNS_ZONE_PUBLIC_STAGE }} diff --git a/.github/workflows/delete-caches.yml b/.github/workflows/delete-caches.yml index 64b9e799665..aa714d38815 100644 --- a/.github/workflows/delete-caches.yml +++ b/.github/workflows/delete-caches.yml @@ -21,7 +21,9 @@ jobs: PR_NUMBER: ${{ github.event.pull_request.number }} steps: - name: Check out code - uses: actions/checkout@v4.1.2 + uses: actions/checkout@v4.2.1 + with: + persist-credentials: false - name: Setup gh-actions-cache extension env: diff --git a/.github/workflows/delete-deployments.yml b/.github/workflows/delete-deployments.yml index 547b29bceec..ff24db42229 100644 --- a/.github/workflows/delete-deployments.yml +++ b/.github/workflows/delete-deployments.yml @@ -12,6 +12,8 @@ jobs: steps: - name: Checkout repo uses: actions/checkout@v4.2.1 + with: + persist-credentials: false - name: Clean up integration environment uses: ./.github/actions/delete-deployments diff --git a/.github/workflows/dependency-check.yml b/.github/workflows/dependency-check.yml index 4b2a2f32f79..0b09747f509 100644 --- a/.github/workflows/dependency-check.yml +++ b/.github/workflows/dependency-check.yml @@ -26,6 +26,8 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4.2.1 + with: + persist-credentials: false - name: Set up Go if: needs.changes.outputs.src == 'true' diff --git a/.github/workflows/flakeguard-nightly.yml b/.github/workflows/flakeguard-nightly.yml index 178d43d809a..3d62f1f521d 100644 --- a/.github/workflows/flakeguard-nightly.yml +++ b/.github/workflows/flakeguard-nightly.yml @@ -16,9 +16,10 @@ jobs: projectPath: '.' maxPassRatio: '1.0' runAllTests: true - extraArgs: '{ "skipped_tests": "TestChainComponents", "test_repeat_count": "5", "all_tests_runner": "ubuntu22.04-32cores-128GB", "all_tests_runner_count": "3", "run_with_race": "false" }' + extraArgs: '{ "skipped_tests": "", "test_repeat_count": "5", "all_tests_runner": "ubuntu22.04-32cores-128GB", "all_tests_runner_count": "3", "run_with_race": "false" }' slackNotificationAfterTestsChannelId: 'C07TRF65CNS' #flaky-test-detector-notifications secrets: SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - + FLAKEGUARD_SPLUNK_ENDPOINT: ${{ secrets.FLAKEGUARD_SPLUNK_ENDPOINT }} + FLAKEGUARD_SPLUNK_HEC: ${{ secrets.FLAKEGUARD_SPLUNK_HEC }} diff --git a/.github/workflows/flakeguard-on-demand.yml b/.github/workflows/flakeguard-on-demand.yml index 4508da30e6b..a8a71be3ba2 100644 --- a/.github/workflows/flakeguard-on-demand.yml +++ b/.github/workflows/flakeguard-on-demand.yml @@ -48,7 +48,7 @@ on: extraArgs: required: false type: string - default: '{ "skipped_tests": "TestChainComponents", "test_repeat_count": "5", "all_tests_runner": "ubuntu22.04-32cores-128GB", "all_tests_runner_count": "3", "run_with_race": "false" }' + default: '{ "skipped_tests": "", "test_repeat_count": "5", "all_tests_runner": "ubuntu22.04-32cores-128GB", "all_tests_runner_count": "3", "run_with_race": "false" }' description: 'JSON of extra arguments for the workflow.' jobs: @@ -69,4 +69,5 @@ jobs: secrets: SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - \ No newline at end of file + FLAKEGUARD_SPLUNK_ENDPOINT: ${{ secrets.FLAKEGUARD_SPLUNK_ENDPOINT }} + FLAKEGUARD_SPLUNK_HEC: ${{ secrets.FLAKEGUARD_SPLUNK_HEC }} diff --git a/.github/workflows/flakeguard.yml b/.github/workflows/flakeguard.yml index 3951c356a3b..27cce2f15c8 100644 --- a/.github/workflows/flakeguard.yml +++ b/.github/workflows/flakeguard.yml @@ -6,6 +6,7 @@ on: repoUrl: required: true type: string + default: 'https://github.com/smartcontractkit/chainlink' description: 'The URL of the repository to compare changes for detecting flaky tests.' projectPath: required: true @@ -54,6 +55,12 @@ on: required: false GH_TOKEN: required: true + FLAKEGUARD_SPLUNK_ENDPOINT: + description: "The Splunk HTTP Event Collector (HEC) endpoint." + required: true + FLAKEGUARD_SPLUNK_HEC: + description: "The Splunk HTTP Event Collector (HEC) token." + required: true env: GIT_BASE_REF: ${{ inputs.baseRef }} @@ -84,8 +91,9 @@ jobs: git_base_sha: ${{ steps.get_commit_sha.outputs.git_base_sha }} steps: - name: Checkout repository - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 with: + persist-credentials: false fetch-depth: 0 ref: ${{ env.GIT_HEAD_REF }} @@ -116,14 +124,15 @@ jobs: echo "git_base_sha=" >> $GITHUB_OUTPUT fi - - name: Set up Go 1.21.9 - uses: actions/setup-go@v5.0.2 + - name: Setup Go + uses: ./.github/actions/setup-go with: - cache: false + restore-build-cache-only: "true" - name: Install flakeguard + if: ${{ inputs.runAllTests == false }} shell: bash - run: go install github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard@ea4ffd8c51ce02efebf5ea6bca503fe10b6cee92 # flakguard@0.1.0 + run: go install github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard@96581547bab07e3982df522dd4343c998619ca77 # flakguard@0.1.0 - name: Find new or updated test packages if: ${{ inputs.runAllTests == false }} @@ -132,11 +141,14 @@ jobs: env: # Needed to run go test -list CL_DATABASE_URL: postgresql://postgres@localhost:5432/chainlink_test?sslmode=disable + GH_INPUTS_PROJECT_PATH: ${{ inputs.projectPath }} + GH_INPUTS_FIND_BY_TEST_FILES_DIFF: ${{ inputs.findByTestFilesDiff }} + GH_INPUTS_FIND_BY_AFFECTED_PACKAGES: ${{ inputs.findByAffectedPackages }} run: | PATH=$PATH:$(go env GOPATH)/bin export PATH - PACKAGES=$(flakeguard find --find-by-test-files-diff=${{ inputs.findByTestFilesDiff }} --find-by-affected-packages=${{ inputs.findByAffectedPackages }} --base-ref=origin/${{ env.GIT_BASE_REF }} --project-path=${{ inputs.projectPath }}) + PACKAGES=$(flakeguard find --find-by-test-files-diff=$GH_INPUTS_FIND_BY_TEST_FILES_DIFF --find-by-affected-packages=$GH_INPUTS_FIND_BY_AFFECTED_PACKAGES --base-ref=origin/${{ env.GIT_BASE_REF }} --project-path=${GH_INPUTS_PROJECT_PATH}) echo $PACKAGES echo "packages=$PACKAGES" >> $GITHUB_OUTPUT @@ -147,19 +159,22 @@ jobs: env: # Needed to run go test -list CL_DATABASE_URL: postgresql://postgres@localhost:5432/chainlink_test?sslmode=disable + GH_INPUTS_PROJECT_PATH: ${{ inputs.projectPath }} run: | PATH=$PATH:$(go env GOPATH)/bin export PATH - TEST_FILES=$(flakeguard find --only-show-changed-test-files=true --base-ref=origin/${{ env.GIT_BASE_REF }} --project-path=${{ inputs.projectPath }}) + TEST_FILES=$(flakeguard find --only-show-changed-test-files=true --base-ref=origin/${{ env.GIT_BASE_REF }} --project-path=${GH_INPUTS_PROJECT_PATH}) echo $TEST_FILES echo "test_files=$TEST_FILES" >> $GITHUB_OUTPUT - name: Split test packages into groups id: split-packages shell: bash + env: + GH_INPUTS_RUN_ALL_TESTS: ${{ inputs.runAllTests }} run: | - if [[ "${{ inputs.runAllTests }}" == "true" ]]; then + if [[ "$GH_INPUTS_RUN_ALL_TESTS" == "true" ]]; then # Use ALL_TESTS_RUNNER for a specified number of groups, each with "./..." to run all tests ALL_TESTS_RUNNER_COUNT=${{ env.ALL_TESTS_RUNNER_COUNT }} @@ -227,8 +242,9 @@ jobs: DB_URL: postgresql://postgres:postgres@localhost:5432/chainlink_test?sslmode=disable steps: - name: Checkout repository - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 with: + persist-credentials: false ref: ${{ env.GIT_HEAD_REF }} - name: Setup NodeJS @@ -272,8 +288,10 @@ jobs: - name: Go mod tidy shell: bash + env: + GH_INPUTS_PROJECT_PATH: ${{ inputs.projectPath }} run: | - cd ${{ inputs.projectPath }} + cd $GH_INPUTS_PROJECT_PATH go mod tidy - name: Generate random id @@ -282,13 +300,15 @@ jobs: - name: Install flakeguard shell: bash - run: go install github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard@ea4ffd8c51ce02efebf5ea6bca503fe10b6cee92 # flakguard@0.1.0 + run: go install github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard@96581547bab07e3982df522dd4343c998619ca77 # flakguard@0.1.0 - name: Run tests with flakeguard shell: bash - run: flakeguard run --project-path=${{ inputs.projectPath }} --test-packages=${{ matrix.testPackages }} --run-count=${{ env.TEST_REPEAT_COUNT }} --max-pass-ratio=${{ inputs.maxPassRatio }} --race=${{ env.RUN_WITH_RACE }} --shuffle=${{ env.RUN_WITH_SHUFFLE }} --shuffle-seed=${{ env.SHUFFLE_SEED }} --skip-tests=${{ env.SKIPPED_TESTS }} --output-json=test-result.json --omit-test-outputs-on-success=${{ env.OMIT_TEST_OUTPUTS_ON_SUCCESS }} env: + GH_INPUTS_PROJECT_PATH: ${{ inputs.projectPath }} + GH_INPUTS_MAX_PASS_RATIO: ${{ inputs.maxPassRatio }} CL_DATABASE_URL: ${{ env.DB_URL }} + run: flakeguard run --project-path=$GH_INPUTS_PROJECT_PATH --test-packages=${{ matrix.testPackages }} --run-count=${{ env.TEST_REPEAT_COUNT }} --max-pass-ratio=$GH_INPUTS_MAX_PASS_RATIO --race=${{ env.RUN_WITH_RACE }} --shuffle=${{ env.RUN_WITH_SHUFFLE }} --shuffle-seed=${{ env.SHUFFLE_SEED }} --skip-tests=${{ env.SKIPPED_TESTS }} --output-json=test-result.json --omit-test-outputs-on-success=${{ env.OMIT_TEST_OUTPUTS_ON_SUCCESS }} - name: Upload test result as artifact if: always() @@ -307,17 +327,24 @@ jobs: test_results: ${{ steps.results.outputs.results }} steps: - name: Checkout repository - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 with: + persist-credentials: false ref: ${{ env.GIT_HEAD_REF }} + - name: Setup Go + uses: ./.github/actions/setup-go + with: + restore-build-cache-only: "true" - name: Set Pretty Project Path id: set_project_path_pretty + env: + GH_INPUTS_PROJECT_PATH: ${{ inputs.projectPath }} run: | - if [ "${{ inputs.projectPath }}" = "." ]; then + if [ "$GH_INPUTS_PROJECT_PATH" = "." ]; then echo "path=github.com/${{ github.repository }}" >> $GITHUB_OUTPUT else - echo "path=github.com/${{ github.repository }}/${{ inputs.projectPath }}" >> $GITHUB_OUTPUT + echo "path=github.com/${{ github.repository }}/${GH_INPUTS_PROJECT_PATH}" >> $GITHUB_OUTPUT fi - name: Download all test result artifacts @@ -329,11 +356,14 @@ jobs: - name: Install flakeguard shell: bash - run: go install github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard@ea4ffd8c51ce02efebf5ea6bca503fe10b6cee92 # flakguard@0.1.0 + run: go install github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard@96581547bab07e3982df522dd4343c998619ca77 # flakguard@0.1.0 - name: Aggregate Flakeguard Results id: results shell: bash + env: + GH_INPUTS_REPO_URL: ${{ inputs.repoUrl }} + GH_INPUTS_MAX_PASS_RATIO: ${{ inputs.maxPassRatio }} run: | set -e # Exit immediately if a command exits with a non-zero status. @@ -350,11 +380,15 @@ jobs: --output-path ./flakeguard-report \ --repo-path "${{ github.workspace }}" \ --codeowners-path "${{ github.workspace }}/.github/CODEOWNERS" \ - --max-pass-ratio "${{ inputs.maxPassRatio }}" \ - --repo-url "${{ inputs.repoUrl }}" \ + --max-pass-ratio "$GH_INPUTS_MAX_PASS_RATIO" \ + --repo-url "$GH_INPUTS_REPO_URL" \ --base-sha "${{ needs.get-tests.outputs.git_base_sha }}" \ --head-sha "${{ needs.get-tests.outputs.git_head_sha }}" \ - --github-workflow-name "${{ github.workflow }}" + --github-workflow-name "${{ github.workflow }}" \ + --github-workflow-run-url "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \ + --splunk-url "${{ secrets.FLAKEGUARD_SPLUNK_ENDPOINT }}" \ + --splunk-token "${{ secrets.FLAKEGUARD_SPLUNK_HEC }}" \ + --splunk-event "${{ github.event }}" # Print out the summary file echo -e "\nFlakeguard Summary:" @@ -365,7 +399,7 @@ jobs: echo "summary=$summary" >> $GITHUB_OUTPUT - name: Upload All Test Results as Artifact - if: ${{ fromJSON(steps.results.outputs.summary).total_tests > 0 }} + if: ${{ (success() || failure()) && fromJSON(steps.results.outputs.summary).total_tests > 0 }} uses: actions/upload-artifact@v4.4.3 with: path: ./flakeguard-report/all-test-results.json @@ -373,7 +407,7 @@ jobs: retention-days: 90 - name: Upload Failed Test Results as Artifact - if: ${{ fromJSON(steps.results.outputs.summary).failed_runs > 0 }} + if: ${{ (success() || failure()) && fromJSON(steps.results.outputs.summary).failed_runs > 0 }} uses: actions/upload-artifact@v4.4.3 with: path: ./flakeguard-report/failed-test-results.json @@ -381,7 +415,7 @@ jobs: retention-days: 90 - name: Upload Failed Test Results With Logs as Artifact - if: ${{ fromJSON(steps.results.outputs.summary).failed_runs > 0 }} + if: ${{ (success() || failure()) && fromJSON(steps.results.outputs.summary).failed_runs > 0 }} uses: actions/upload-artifact@v4.4.3 with: path: ./flakeguard-report/failed-test-results-with-logs.json @@ -390,8 +424,13 @@ jobs: - name: Generate Flakeguard Reports shell: bash + if: success() || failure() env: GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + GH_INPUTS_MAX_PASS_RATIO: ${{ inputs.maxPassRatio }} + GH_EVENT_NAME: ${{ github.event_name }} + GH_EVENT_PULL_REQUEST_BASE_REF: ${{ github.event.pull_request.base.ref }} + GH_EVENT_PULL_REQUEST_HEAD_SHA: ${{ github.event.pull_request.head.sha }} run: | set -e # Exit immediately if a command exits with a non-zero status. @@ -400,7 +439,7 @@ jobs: export PATH # Check if the event is a pull request - if [ "${{ github.event_name }}" = "pull_request" ]; then + if [ "$GH_EVENT_NAME" = "pull_request" ]; then flakeguard generate-report \ --aggregated-results-path ./flakeguard-report/all-test-results.json \ --summary-path ./flakeguard-report/all-test-summary.json \ @@ -409,12 +448,12 @@ jobs: --github-run-id "${{ github.run_id }}" \ --failed-tests-artifact-name "failed-test-results-with-logs.json" \ --generate-pr-comment \ - --base-branch "${{ github.event.pull_request.base.ref }}" \ + --base-branch "$GH_EVENT_PULL_REQUEST_BASE_REF" \ --current-branch "${{ github.head_ref }}" \ - --current-commit-sha "${{ github.event.pull_request.head.sha }}" \ + --current-commit-sha "$GH_EVENT_PULL_REQUEST_HEAD_SHA" \ --repo-url "https://github.com/${{ github.repository }}" \ --action-run-id "${{ github.run_id }}" \ - --max-pass-ratio "${{ inputs.maxPassRatio }}" + --max-pass-ratio "$GH_INPUTS_MAX_PASS_RATIO" else flakeguard generate-report \ --aggregated-results-path ./flakeguard-report/all-test-results.json \ @@ -423,15 +462,16 @@ jobs: --github-repository "${{ github.repository }}" \ --github-run-id "${{ github.run_id }}" \ --failed-tests-artifact-name "failed-test-results-with-logs.json" \ - --base-branch "${{ github.event.pull_request.base.ref }}" \ + --base-branch "$GH_EVENT_PULL_REQUEST_BASE_REF" \ --current-branch "${{ github.head_ref }}" \ - --current-commit-sha "${{ github.event.pull_request.head.sha }}" \ + --current-commit-sha "$GH_EVENT_PULL_REQUEST_HEAD_SHA" \ --repo-url "https://github.com/${{ github.repository }}" \ --action-run-id "${{ github.run_id }}" \ - --max-pass-ratio "${{ inputs.maxPassRatio }}" + --max-pass-ratio "$GH_INPUTS_MAX_PASS_RATIO" fi - name: Add Github Summary + if: (success() || failure()) run: | FILE_SIZE=$(wc -c < ./flakeguard-report/all-test-summary.md) echo "File size: $FILE_SIZE bytes" @@ -446,7 +486,7 @@ jobs: fi - name: Post comment on PR if flaky tests found - if: ${{ fromJSON(steps.results.outputs.summary).flaky_tests > 0 && github.event_name == 'pull_request' }} + if: ${{ (success() || failure()) && fromJSON(steps.results.outputs.summary).flaky_tests > 0 && github.event_name == 'pull_request' }} uses: actions/github-script@v7 continue-on-error: true with: @@ -463,7 +503,7 @@ jobs: }); - name: Send Slack message for failed tests - if: ${{ inputs.slackNotificationAfterTestsChannelId != '' && fromJSON(steps.results.outputs.summary).flaky_tests > 0 }} + if: ${{ (success() || failure()) && inputs.slackNotificationAfterTestsChannelId != '' && fromJSON(steps.results.outputs.summary).flaky_tests > 0 }} uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 env: SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} @@ -516,7 +556,7 @@ jobs: - name: Send general Slack message uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 - if: ${{ inputs.slackNotificationAfterTestsChannelId != '' && fromJSON(steps.results.outputs.summary).flaky_tests == 0 && fromJSON(steps.results.outputs.summary).total_tests > 0 }} + if: ${{ (success() || failure()) && inputs.slackNotificationAfterTestsChannelId != '' && fromJSON(steps.results.outputs.summary).flaky_tests == 0 && fromJSON(steps.results.outputs.summary).total_tests > 0 }} id: slack env: SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} diff --git a/.github/workflows/go-mod-cache.yml b/.github/workflows/go-mod-cache.yml index 3caac1eff3f..e90e6a9f285 100644 --- a/.github/workflows/go-mod-cache.yml +++ b/.github/workflows/go-mod-cache.yml @@ -31,6 +31,8 @@ jobs: steps: - name: Checkout the repo uses: actions/checkout@v4.2.1 + with: + persist-credentials: false - name: Setup Go uses: ./.github/actions/setup-go diff --git a/.github/workflows/integration-chaos-tests.yml b/.github/workflows/integration-chaos-tests.yml index c9f7f2661ec..b0e337631a4 100644 --- a/.github/workflows/integration-chaos-tests.yml +++ b/.github/workflows/integration-chaos-tests.yml @@ -15,7 +15,7 @@ on: jobs: run-e2e-tests-workflow-dispatch: name: Run E2E Tests (Workflow Dispatch) - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0d4a2b2b009c87b5c366d0b97f7a8d7de2f60760 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@61acf908014e2fe42c04f2a507c79f97eb5f8c4d if: github.event_name == 'workflow_dispatch' with: test_path: .github/e2e-tests.yml @@ -31,7 +31,6 @@ jobs: PROD_AWS_ACCOUNT_NUMBER: ${{ secrets.AWS_ACCOUNT_ID_PROD }} QA_PYROSCOPE_INSTANCE: ${{ secrets.QA_PYROSCOPE_INSTANCE }} QA_PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} GRAFANA_INTERNAL_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} GRAFANA_INTERNAL_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} GRAFANA_INTERNAL_HOST: ${{ secrets.GRAFANA_INTERNAL_HOST }} @@ -44,10 +43,12 @@ jobs: AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} AWS_API_GW_HOST_GRAFANA: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} + MAIN_DNS_ZONE_PUBLIC_SDLC: ${{ secrets.MAIN_DNS_ZONE_PUBLIC_SDLC }} + AWS_K8S_CLUSTER_NAME_SDLC: ${{ secrets.AWS_K8S_CLUSTER_NAME_SDLC }} run-e2e-tests-workflow: name: Run E2E Tests (Push and Sechedule) - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0d4a2b2b009c87b5c366d0b97f7a8d7de2f60760 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@61acf908014e2fe42c04f2a507c79f97eb5f8c4d if: github.event_name != 'workflow_dispatch' with: test_path: .github/e2e-tests.yml @@ -62,7 +63,6 @@ jobs: PROD_AWS_ACCOUNT_NUMBER: ${{ secrets.AWS_ACCOUNT_ID_PROD }} QA_PYROSCOPE_INSTANCE: ${{ secrets.QA_PYROSCOPE_INSTANCE }} QA_PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} GRAFANA_INTERNAL_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} GRAFANA_INTERNAL_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} GRAFANA_INTERNAL_HOST: ${{ secrets.GRAFANA_INTERNAL_HOST }} @@ -75,4 +75,5 @@ jobs: AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} AWS_API_GW_HOST_GRAFANA: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} - + MAIN_DNS_ZONE_PUBLIC_SDLC: ${{ secrets.MAIN_DNS_ZONE_PUBLIC_SDLC }} + AWS_K8S_CLUSTER_NAME_SDLC: ${{ secrets.AWS_K8S_CLUSTER_NAME_SDLC }} diff --git a/.github/workflows/integration-in-memory-tests.yml b/.github/workflows/integration-in-memory-tests.yml index 341d66f641e..e124b12eb28 100644 --- a/.github/workflows/integration-in-memory-tests.yml +++ b/.github/workflows/integration-in-memory-tests.yml @@ -33,6 +33,7 @@ jobs: - name: Checkout the repo uses: actions/checkout@v4.2.1 with: + persist-credentials: false repository: smartcontractkit/chainlink ref: ${{ inputs.cl_ref }} - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 @@ -134,6 +135,7 @@ jobs: if: ${{ github.event_name == 'pull_request' }} uses: actions/checkout@v4.2.1 with: + persist-credentials: false repository: smartcontractkit/chainlink ref: ${{ inputs.cl_ref }} diff --git a/.github/workflows/integration-tests-publish.yml b/.github/workflows/integration-tests-publish.yml index df07cc1e231..523974b4aed 100644 --- a/.github/workflows/integration-tests-publish.yml +++ b/.github/workflows/integration-tests-publish.yml @@ -23,6 +23,7 @@ jobs: - name: Checkout the repo uses: actions/checkout@v4.2.1 with: + persist-credentials: false ref: ${{ github.event.pull_request.head.sha || github.sha }} - name: Setup Other Tags If Not Workflow Dispatch id: tags @@ -68,6 +69,7 @@ jobs: - name: Checkout the repo uses: actions/checkout@v4.2.1 with: + persist-credentials: false ref: ${{ github.sha }} - name: Build Chainlink Image uses: ./.github/actions/build-chainlink-image diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 27bdfa52243..76a5aa379b4 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -1,3 +1,5 @@ +# N/B: ci-core, which runs on PRs, will trigger linting for affected directories/modules +# no need to run lint twice name: Integration Tests run-name: Integration Tests ${{ inputs.distinct_run_name && inputs.distinct_run_name || '' }} on: @@ -52,6 +54,7 @@ jobs: - name: Checkout the repo uses: actions/checkout@v4.2.1 with: + persist-credentials: false repository: smartcontractkit/chainlink ref: ${{ inputs.cl_ref }} - name: Check Merge Group Condition @@ -86,6 +89,7 @@ jobs: - name: Checkout the repo uses: actions/checkout@v4.2.1 with: + persist-credentials: false repository: smartcontractkit/chainlink ref: ${{ inputs.cl_ref }} - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 @@ -116,47 +120,6 @@ jobs: core_changes: ${{ steps.ignore-filter.outputs.changes || steps.changes.outputs.core_changes }} ccip_changes: ${{ steps.ignore-filter.outputs.changes || steps.changes.outputs.ccip_changes }} - lint-integration-tests: - name: Lint ${{ matrix.project.name }} - runs-on: ubuntu-24.04-8cores-32GB-ARM - # We don't directly merge dependabot PRs, so let's not waste the resources - if: github.actor != 'dependabot[bot]' - strategy: - matrix: - project: - - name: integration-tests - id: e2e-tests - path: ./integration-tests - cache_id: e2e-tests - - name: load - id: load - path: ./integration-tests/load - cache_id: load - steps: - - name: Checkout the repo - uses: actions/checkout@v4.2.1 - with: - repository: smartcontractkit/chainlink - ref: ${{ inputs.cl_ref }} - - name: Setup Go - uses: smartcontractkit/.github/actions/ctf-setup-go@b0d756c57fcdbcff187e74166562a029fdd5d1b9 # ctf-setup-go@0.0.0 - with: - test_download_vendor_packages_command: cd ${{ matrix.project.path }} && go mod download - go_mod_path: ${{ matrix.project.path }}/go.mod - cache_key_id: ${{ matrix.project.cache_id }} - cache_restore_only: "true" - - name: Lint Go - uses: golangci/golangci-lint-action@3cfe3a4abbb849e10058ce4af15d205b6da42804 # v4.0.0 - with: - version: v1.62.0 - # We already cache these directories in setup-go - skip-pkg-cache: true - skip-build-cache: true - # only-new-issues is only applicable to PRs, otherwise it is always set to false - only-new-issues: false # disabled for PRs due to unreliability - args: --out-format colored-line-number,checkstyle:golangci-lint-report.xml - working-directory: ${{ matrix.project.path }} - build-chainlink: environment: integration permissions: @@ -171,6 +134,7 @@ jobs: - name: (plugins) dockerfile: plugins/chainlink.Dockerfile tag-suffix: -plugins + name: Build Chainlink Image ${{ matrix.image.name }} runs-on: ubuntu22.04-8cores-32GB needs: [changes, enforce-ctf-version] @@ -178,6 +142,7 @@ jobs: - name: Checkout the repo uses: actions/checkout@v4.2.1 with: + persist-credentials: false repository: smartcontractkit/chainlink ref: ${{ inputs.cl_ref || github.event.pull_request.head.sha || github.event.merge_group.head_sha }} - name: Setup Github Token @@ -210,7 +175,7 @@ jobs: contents: read needs: [build-chainlink, changes] if: github.event_name == 'pull_request' && ( needs.changes.outputs.core_changes == 'true' || needs.changes.outputs.github_ci_changes == 'true') - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0632b5652dd5eb03bfa87e23a2b3e2911484fe59 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@61acf908014e2fe42c04f2a507c79f97eb5f8c4d with: workflow_name: Run Core E2E Tests For PR chainlink_version: ${{ inputs.evm-ref || github.sha }} @@ -227,7 +192,6 @@ jobs: PROD_AWS_ACCOUNT_NUMBER: ${{ secrets.AWS_ACCOUNT_ID_PROD }} QA_PYROSCOPE_INSTANCE: ${{ secrets.QA_PYROSCOPE_INSTANCE }} QA_PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} GRAFANA_INTERNAL_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} GRAFANA_INTERNAL_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} GRAFANA_INTERNAL_HOST: ${{ secrets.GRAFANA_INTERNAL_HOST }} @@ -240,6 +204,8 @@ jobs: AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} AWS_API_GW_HOST_GRAFANA: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} + MAIN_DNS_ZONE_PUBLIC_SDLC: ${{ secrets.MAIN_DNS_ZONE_PUBLIC_SDLC }} + AWS_K8S_CLUSTER_NAME_SDLC: ${{ secrets.AWS_K8S_CLUSTER_NAME_SDLC }} run-core-e2e-tests-for-merge-queue: name: Run Core E2E Tests For Merge Queue @@ -251,7 +217,7 @@ jobs: contents: read needs: [build-chainlink, changes] if: github.event_name == 'merge_group' && ( needs.changes.outputs.core_changes == 'true' || needs.changes.outputs.github_ci_changes == 'true') - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0632b5652dd5eb03bfa87e23a2b3e2911484fe59 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@61acf908014e2fe42c04f2a507c79f97eb5f8c4d with: workflow_name: Run Core E2E Tests For Merge Queue chainlink_version: ${{ inputs.evm-ref || github.sha }} @@ -272,7 +238,6 @@ jobs: PROD_AWS_ACCOUNT_NUMBER: ${{ secrets.AWS_ACCOUNT_ID_PROD }} QA_PYROSCOPE_INSTANCE: ${{ secrets.QA_PYROSCOPE_INSTANCE }} QA_PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} GRAFANA_INTERNAL_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} GRAFANA_INTERNAL_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} GRAFANA_INTERNAL_HOST: ${{ secrets.GRAFANA_INTERNAL_HOST }} @@ -285,6 +250,8 @@ jobs: AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} AWS_API_GW_HOST_GRAFANA: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} + MAIN_DNS_ZONE_PUBLIC_SDLC: ${{ secrets.MAIN_DNS_ZONE_PUBLIC_SDLC }} + AWS_K8S_CLUSTER_NAME_SDLC: ${{ secrets.AWS_K8S_CLUSTER_NAME_SDLC }} run-ccip-e2e-tests-for-pr: name: Run CCIP E2E Tests For PR @@ -296,7 +263,7 @@ jobs: contents: read needs: [build-chainlink, changes] if: github.event_name == 'pull_request' && (needs.changes.outputs.ccip_changes == 'true' || needs.changes.outputs.github_ci_changes == 'true') - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0632b5652dd5eb03bfa87e23a2b3e2911484fe59 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@61acf908014e2fe42c04f2a507c79f97eb5f8c4d with: workflow_name: Run CCIP E2E Tests For PR chainlink_version: ${{ inputs.evm-ref || github.sha }} @@ -314,7 +281,6 @@ jobs: PROD_AWS_ACCOUNT_NUMBER: ${{ secrets.AWS_ACCOUNT_ID_PROD }} QA_PYROSCOPE_INSTANCE: ${{ secrets.QA_PYROSCOPE_INSTANCE }} QA_PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} GRAFANA_INTERNAL_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} GRAFANA_INTERNAL_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} GRAFANA_INTERNAL_HOST: ${{ secrets.GRAFANA_INTERNAL_HOST }} @@ -327,6 +293,8 @@ jobs: AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} AWS_API_GW_HOST_GRAFANA: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} + MAIN_DNS_ZONE_PUBLIC_SDLC: ${{ secrets.MAIN_DNS_ZONE_PUBLIC_SDLC }} + AWS_K8S_CLUSTER_NAME_SDLC: ${{ secrets.AWS_K8S_CLUSTER_NAME_SDLC }} run-ccip-e2e-tests-for-merge-queue: name: Run CCIP E2E Tests For Merge Queue @@ -338,7 +306,7 @@ jobs: contents: read needs: [build-chainlink, changes] if: github.event_name == 'merge_group' && (needs.changes.outputs.ccip_changes == 'true' || needs.changes.outputs.github_ci_changes == 'true') - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0632b5652dd5eb03bfa87e23a2b3e2911484fe59 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@61acf908014e2fe42c04f2a507c79f97eb5f8c4d with: workflow_name: Run CCIP E2E Tests For Merge Queue chainlink_version: ${{ inputs.evm-ref || github.sha }} @@ -356,7 +324,6 @@ jobs: PROD_AWS_ACCOUNT_NUMBER: ${{ secrets.AWS_ACCOUNT_ID_PROD }} QA_PYROSCOPE_INSTANCE: ${{ secrets.QA_PYROSCOPE_INSTANCE }} QA_PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} GRAFANA_INTERNAL_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} GRAFANA_INTERNAL_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} GRAFANA_INTERNAL_HOST: ${{ secrets.GRAFANA_INTERNAL_HOST }} @@ -369,12 +336,14 @@ jobs: AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} AWS_API_GW_HOST_GRAFANA: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} + MAIN_DNS_ZONE_PUBLIC_SDLC: ${{ secrets.MAIN_DNS_ZONE_PUBLIC_SDLC }} + AWS_K8S_CLUSTER_NAME_SDLC: ${{ secrets.AWS_K8S_CLUSTER_NAME_SDLC }} check-e2e-test-results: if: always() name: ETH Smoke Tests runs-on: ubuntu-latest - needs: [lint-integration-tests, run-core-e2e-tests-for-pr, run-ccip-e2e-tests-for-pr, run-core-e2e-tests-for-merge-queue, run-ccip-e2e-tests-for-merge-queue] + needs: [run-core-e2e-tests-for-pr, run-ccip-e2e-tests-for-pr, run-core-e2e-tests-for-merge-queue, run-ccip-e2e-tests-for-merge-queue] steps: - name: Check Core test results id: check_core_results @@ -414,10 +383,6 @@ jobs: if: always() && needs.run-core-e2e-tests-for-merge-queue.result == 'failure' run: exit 1 - - name: Fail the job if lint not successful - if: always() && needs.lint-integration-tests.result == 'failure' - run: exit 1 - cleanup: name: Clean up integration environment deployments if: always() @@ -428,6 +393,7 @@ jobs: if: ${{ github.event_name == 'pull_request' }} uses: actions/checkout@v4.2.1 with: + persist-credentials: false repository: smartcontractkit/chainlink ref: ${{ inputs.cl_ref }} @@ -447,6 +413,7 @@ jobs: - name: Checkout the repo uses: actions/checkout@v4.2.1 with: + persist-credentials: false repository: smartcontractkit/chainlink ref: ${{ inputs.cl_ref || github.event.pull_request.head.sha || github.event.merge_group.head_sha }} - name: Download All Artifacts @@ -471,6 +438,7 @@ jobs: - name: Checkout the repo uses: actions/checkout@v4.2.1 with: + persist-credentials: false repository: smartcontractkit/chainlink ref: ${{ inputs.cl_ref || github.event.pull_request.head.sha || github.event.merge_group.head_sha }} - name: Setup Go @@ -491,6 +459,7 @@ jobs: - name: Checkout solana uses: actions/checkout@v4.2.1 with: + persist-credentials: false repository: smartcontractkit/chainlink-solana ref: develop fetch-depth: 0 @@ -518,6 +487,7 @@ jobs: - name: Checkout the solana repo uses: actions/checkout@v4.2.1 with: + persist-credentials: false repository: smartcontractkit/chainlink-solana ref: ${{ needs.get_solana_sha.outputs.sha }} - name: Get ProjectSerum Version @@ -566,6 +536,7 @@ jobs: - name: Checkout the solana repo uses: actions/checkout@v4.2.1 with: + persist-credentials: false repository: smartcontractkit/chainlink-solana ref: ${{ needs.get_solana_sha.outputs.sha }} - name: Build contracts @@ -600,6 +571,7 @@ jobs: if: (needs.changes.outputs.core_changes == 'true' || github.event_name == 'workflow_dispatch') && needs.solana-test-image-exists.outputs.exists == 'false' uses: actions/checkout@v4.2.1 with: + persist-credentials: false repository: smartcontractkit/chainlink-solana ref: ${{ needs.get_solana_sha.outputs.sha }} - name: Download Artifacts @@ -648,6 +620,7 @@ jobs: - name: Checkout the repo uses: actions/checkout@v4.2.1 with: + persist-credentials: false repository: smartcontractkit/chainlink-solana ref: ${{ needs.get_solana_sha.outputs.sha }} - name: Run Setup @@ -688,10 +661,13 @@ jobs: yarn --cwd ./gauntlet build yarn --cwd ./gauntlet gauntlet - name: Generate config overrides + env: + GH_INPUTS_EVM_REF: ${{ inputs.evm-ref }} + GH_SHA: ${{ github.sha }} run: | # https://github.com/smartcontractkit/chainlink-testing-framework/lib/blob/main/config/README.md cat << EOF > config.toml [ChainlinkImage] - version="${{ inputs.evm-ref || github.sha }}" + version="${{ env.evm-ref || env.GH_SHA }}" [Common] user="${{ github.actor }}" internal_docker_repo = "${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com" diff --git a/.github/workflows/lint-gh-workflows.yml b/.github/workflows/lint-gh-workflows.yml index 9897c023576..a3aaacb1abe 100644 --- a/.github/workflows/lint-gh-workflows.yml +++ b/.github/workflows/lint-gh-workflows.yml @@ -8,5 +8,7 @@ jobs: steps: - name: Check out Code uses: actions/checkout@v4.2.1 + with: + persist-credentials: false - name: Run actionlint uses: reviewdog/action-actionlint@c6ee1eb0a5d47b2af53a203652b5dac0b6c4016e # v1.43.0 diff --git a/.github/workflows/on-demand-ocr-soak-test.yml b/.github/workflows/on-demand-ocr-soak-test.yml index a9a8c3c2a2f..32284137722 100644 --- a/.github/workflows/on-demand-ocr-soak-test.yml +++ b/.github/workflows/on-demand-ocr-soak-test.yml @@ -39,11 +39,11 @@ on: description: Team to run the tests for (e.g. BIX, CCIP) required: true type: string - + jobs: run-e2e-tests-workflow: name: Run E2E Tests - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0d4a2b2b009c87b5c366d0b97f7a8d7de2f60760 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@61acf908014e2fe42c04f2a507c79f97eb5f8c4d with: test_path: .github/e2e-tests.yml test_ids: ${{ inputs.testToRun}} @@ -51,6 +51,7 @@ jobs: chainlink_version: ${{ inputs.chainlink_version }} SLACK_USER: ${{ inputs.slackMemberID }} team: ${{ inputs.team }} + test_secrets_override_key: ${{ inputs.test_secrets_override_key }} secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} @@ -58,7 +59,6 @@ jobs: PROD_AWS_ACCOUNT_NUMBER: ${{ secrets.AWS_ACCOUNT_ID_PROD }} QA_PYROSCOPE_INSTANCE: ${{ secrets.QA_PYROSCOPE_INSTANCE }} QA_PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} GRAFANA_INTERNAL_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} GRAFANA_INTERNAL_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} GRAFANA_INTERNAL_HOST: ${{ secrets.GRAFANA_INTERNAL_HOST }} @@ -66,10 +66,12 @@ jobs: LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} LOKI_URL: ${{ secrets.LOKI_URL }} LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} AWS_REGION: ${{ secrets.QA_AWS_REGION }} AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} - AWS_API_GW_HOST_GRAFANA: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} + AWS_API_GW_HOST_GRAFANA: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} TEST_SECRETS_OVERRIDE_BASE64: ${{ secrets[inputs.test_secrets_override_key] }} SLACK_API_KEY: ${{ secrets.QA_SLACK_API_KEY }} SLACK_CHANNEL: ${{ secrets.QA_SLACK_CHANNEL }} + MAIN_DNS_ZONE_PUBLIC_SDLC: ${{ secrets.MAIN_DNS_ZONE_PUBLIC_SDLC }} + AWS_K8S_CLUSTER_NAME_SDLC: ${{ secrets.AWS_K8S_CLUSTER_NAME_SDLC }} diff --git a/.github/workflows/on-demand-vrfv2-performance-test.yml b/.github/workflows/on-demand-vrfv2-performance-test.yml index f9aeaa0fa1f..e2ccf70cd32 100644 --- a/.github/workflows/on-demand-vrfv2-performance-test.yml +++ b/.github/workflows/on-demand-vrfv2-performance-test.yml @@ -18,29 +18,33 @@ on: test_config_override_path: description: Path to a test config file used to override the default test config required: false - type: string + type: string test_secrets_override_key: description: 'Key to run tests with custom test secrets' required: false - type: string + type: string notify_user_id_on_failure: description: 'Enter Slack user ID to notify on test failure' required: false - type: string - + type: string + jobs: set-tests-to-run: name: Set tests to run runs-on: ubuntu-latest outputs: test_list: ${{ steps.set-tests.outputs.test_list }} + env: + GH_INPUTS_TEST_LIST_REGEX: ${{ inputs.test_list_regex }} + GH_INPUTS_TEST_CONFIG_OVERRIDE_PATH: ${{ inputs.test_config_override_path }} + GH_INPUTS_PERFORMANCE_TEST_TYPE: ${{ inputs.performanceTestType }} steps: - name: Generate Test List JSON id: set-tests run: | - TEST_CMD='cd integration-tests/load && go test -v -count=1 -timeout 24h -run "${{ inputs.test_list_regex }}" ./vrfv2' - TEST_CONFIG_OVERRIDE_PATH=${{ inputs.test_config_override_path }} - TEST_TYPE=${{ inputs.performanceTestType }} + TEST_CMD='cd integration-tests/load && go test -v -count=1 -timeout 24h -run "$GH_INPUTS_TEST_LIST_REGEX" ./vrfv2' + TEST_CONFIG_OVERRIDE_PATH=$GH_INPUTS_TEST_CONFIG_OVERRIDE_PATH + TEST_TYPE=$GH_INPUTS_PERFORMANCE_TEST_TYPE TEST_LIST=$(jq -n -c \ --arg test_cmd "$TEST_CMD" \ @@ -56,7 +60,7 @@ jobs: "test_cmd": $test_cmd, "test_config_override_path": $test_config_override_path, "test_env_vars": { - "TEST_TYPE": $TEST_TYPE + "TEST_TYPE": $TEST_TYPE } } ] @@ -67,13 +71,13 @@ jobs: run-e2e-tests-workflow: name: Run E2E Tests needs: set-tests-to-run - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0632b5652dd5eb03bfa87e23a2b3e2911484fe59 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@61acf908014e2fe42c04f2a507c79f97eb5f8c4d with: custom_test_list_json: ${{ needs.set-tests-to-run.outputs.test_list }} chainlink_version: ${{ inputs.chainlink_version }} slack_notification_after_tests: always slack_notification_after_tests_name: "VRF V2 Performance Tests with test config: ${{ inputs.test_config_override_path || 'default' }}" - slack_notification_after_tests_notify_user_id_on_failure: ${{ inputs.notify_user_id_on_failure }} + slack_notification_after_tests_notify_user_id_on_failure: ${{ inputs.notify_user_id_on_failure }} secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} @@ -81,7 +85,6 @@ jobs: PROD_AWS_ACCOUNT_NUMBER: ${{ secrets.AWS_ACCOUNT_ID_PROD }} QA_PYROSCOPE_INSTANCE: ${{ secrets.QA_PYROSCOPE_INSTANCE }} QA_PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} GRAFANA_INTERNAL_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} GRAFANA_INTERNAL_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} GRAFANA_INTERNAL_HOST: ${{ secrets.GRAFANA_INTERNAL_HOST }} @@ -89,11 +92,13 @@ jobs: LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} LOKI_URL: ${{ secrets.LOKI_URL }} LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} AWS_REGION: ${{ secrets.QA_AWS_REGION }} AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} - AWS_API_GW_HOST_GRAFANA: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} + AWS_API_GW_HOST_GRAFANA: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} TEST_SECRETS_OVERRIDE_BASE64: ${{ secrets[inputs.test_secrets_override_key] }} SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} SLACK_API_KEY: ${{ secrets.QA_SLACK_API_KEY }} - SLACK_CHANNEL: ${{ secrets.QA_VRF_SLACK_CHANNEL }} + SLACK_CHANNEL: ${{ secrets.QA_VRF_SLACK_CHANNEL }} + MAIN_DNS_ZONE_PUBLIC_SDLC: ${{ secrets.MAIN_DNS_ZONE_PUBLIC_SDLC }} + AWS_K8S_CLUSTER_NAME_SDLC: ${{ secrets.AWS_K8S_CLUSTER_NAME_SDLC }} diff --git a/.github/workflows/on-demand-vrfv2-smoke-tests.yml b/.github/workflows/on-demand-vrfv2-smoke-tests.yml index ad616dea744..5352c64c027 100644 --- a/.github/workflows/on-demand-vrfv2-smoke-tests.yml +++ b/.github/workflows/on-demand-vrfv2-smoke-tests.yml @@ -17,7 +17,7 @@ on: test_config_override_path: description: Path to a test config file used to override the default test config required: false - type: string + type: string test_secrets_override_key: description: 'Key to run tests with custom test secrets' required: false @@ -31,7 +31,7 @@ on: description: 'Enter Slack user ID to notify on test failure' required: false type: string - + jobs: set-tests-to-run: name: Set tests to run @@ -41,13 +41,17 @@ jobs: steps: - name: Generate Test List JSON id: set-tests + env: + GH_INPUTS_TEST_SUITE: ${{ inputs.test_suite }} + GH_INPUTS_TEST_LIST_REGEX: ${{ inputs.test_list_regex }} + GH_INPUTS_TEST_CONFIG_OVERRIDE_PATH: ${{ inputs.test_config_override_path }} run: | - if [[ "${{ inputs.test_suite }}" == "All Tests" ]]; then + if [[ "$GH_INPUTS_TEST_SUITE" == "All Tests" ]]; then TEST_CMD="cd integration-tests/smoke && go test vrfv2_test.go -test.parallel=1 -timeout 3h -count=1 -json -v" else - TEST_CMD='cd integration-tests/smoke && go test -test.run "${{ inputs.test_list_regex }}" -test.parallel=1 -timeout 2h -count=1 -json -v' + TEST_CMD='cd integration-tests/smoke && go test -test.run "$GH_INPUTS_TEST_LIST_REGEX" -test.parallel=1 -timeout 2h -count=1 -json -v' fi - TEST_CONFIG_OVERRIDE_PATH=${{ inputs.test_config_override_path }} + TEST_CONFIG_OVERRIDE_PATH=$GH_INPUTS_TEST_CONFIG_OVERRIDE_PATH TEST_LIST=$(jq -n -c \ --arg test_cmd "$TEST_CMD" \ @@ -70,13 +74,14 @@ jobs: run-e2e-tests-workflow: name: Run E2E Tests needs: set-tests-to-run - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0632b5652dd5eb03bfa87e23a2b3e2911484fe59 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@61acf908014e2fe42c04f2a507c79f97eb5f8c4d with: custom_test_list_json: ${{ needs.set-tests-to-run.outputs.test_list }} chainlink_version: ${{ inputs.chainlink_version }} slack_notification_after_tests: always slack_notification_after_tests_name: "VRF V2 Smoke Tests with test config: ${{ inputs.test_config_override_path || 'default' }}" slack_notification_after_tests_notify_user_id_on_failure: ${{ inputs.notify_user_id_on_failure }} + test_secrets_override_key: ${{ inputs.test_secrets_override_key }} secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} @@ -84,7 +89,6 @@ jobs: PROD_AWS_ACCOUNT_NUMBER: ${{ secrets.AWS_ACCOUNT_ID_PROD }} QA_PYROSCOPE_INSTANCE: ${{ secrets.QA_PYROSCOPE_INSTANCE }} QA_PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} GRAFANA_INTERNAL_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} GRAFANA_INTERNAL_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} GRAFANA_INTERNAL_HOST: ${{ secrets.GRAFANA_INTERNAL_HOST }} @@ -92,10 +96,12 @@ jobs: LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} LOKI_URL: ${{ secrets.LOKI_URL }} LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} AWS_REGION: ${{ secrets.QA_AWS_REGION }} AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} - AWS_API_GW_HOST_GRAFANA: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} + AWS_API_GW_HOST_GRAFANA: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} TEST_SECRETS_OVERRIDE_BASE64: ${{ secrets[inputs.test_secrets_override_key] }} SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} SLACK_NOTIFICATION_AFTER_TESTS_CHANNEL_ID: ${{ secrets.QA_VRF_SLACK_CHANNEL }} + MAIN_DNS_ZONE_PUBLIC_SDLC: ${{ secrets.MAIN_DNS_ZONE_PUBLIC_SDLC }} + AWS_K8S_CLUSTER_NAME_SDLC: ${{ secrets.AWS_K8S_CLUSTER_NAME_SDLC }} diff --git a/.github/workflows/on-demand-vrfv2plus-performance-test.yml b/.github/workflows/on-demand-vrfv2plus-performance-test.yml index b3a820e25a0..82b2d67b616 100644 --- a/.github/workflows/on-demand-vrfv2plus-performance-test.yml +++ b/.github/workflows/on-demand-vrfv2plus-performance-test.yml @@ -13,11 +13,11 @@ on: test_config_override_path: description: Path to a test config file used to override the default test config required: false - type: string + type: string test_secrets_override_key: description: 'Key to run tests with custom test secrets' required: false - type: string + type: string chainlink_version: description: Chainlink image version to use default: develop @@ -26,7 +26,7 @@ on: notify_user_id_on_failure: description: 'Enter Slack user ID to notify on test failure' required: false - type: string + type: string jobs: set-tests-to-run: @@ -34,13 +34,17 @@ jobs: runs-on: ubuntu-latest outputs: test_list: ${{ steps.set-tests.outputs.test_list }} + env: + GH_INPUTS_TEST_LIST_REGEX: ${{ inputs.test_list_regex }} + GH_INPUTS_TEST_CONFIG_OVERRIDE_PATH: ${{ inputs.test_config_override_path }} + GH_INPUTS_PERFORMANCE_TEST_TYPE: ${{ inputs.performanceTestType }} steps: - name: Generate Test List JSON id: set-tests run: | - TEST_CMD='cd integration-tests/load && go test -v -count=1 -timeout 24h -run "${{ inputs.test_list_regex }}" ./vrfv2plus' - TEST_CONFIG_OVERRIDE_PATH=${{ inputs.test_config_override_path }} - TEST_TYPE=${{ inputs.performanceTestType }} + TEST_CMD='cd integration-tests/load && go test -v -count=1 -timeout 24h -run "$GH_INPUTS_TEST_LIST_REGEX" ./vrfv2plus' + TEST_CONFIG_OVERRIDE_PATH=$GH_INPUTS_TEST_CONFIG_OVERRIDE_PATH + TEST_TYPE=$GH_INPUTS_PERFORMANCE_TEST_TYPE TEST_LIST=$(jq -n -c \ --arg test_cmd "$TEST_CMD" \ @@ -56,7 +60,7 @@ jobs: "test_cmd": $test_cmd, "test_config_override_path": $test_config_override_path, "test_env_vars": { - "TEST_TYPE": $TEST_TYPE + "TEST_TYPE": $TEST_TYPE } } ] @@ -67,13 +71,14 @@ jobs: run-e2e-tests-workflow: name: Run E2E Tests needs: set-tests-to-run - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0632b5652dd5eb03bfa87e23a2b3e2911484fe59 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@61acf908014e2fe42c04f2a507c79f97eb5f8c4d with: custom_test_list_json: ${{ needs.set-tests-to-run.outputs.test_list }} chainlink_version: ${{ inputs.chainlink_version }} slack_notification_after_tests: always slack_notification_after_tests_name: "VRF V2 Plus Performance Tests with test config: ${{ inputs.test_config_override_path || 'default' }}" slack_notification_after_tests_notify_user_id_on_failure: ${{ inputs.notify_user_id_on_failure }} + test_secrets_override_key: ${{ inputs.test_secrets_override_key }} secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} @@ -81,7 +86,6 @@ jobs: PROD_AWS_ACCOUNT_NUMBER: ${{ secrets.AWS_ACCOUNT_ID_PROD }} QA_PYROSCOPE_INSTANCE: ${{ secrets.QA_PYROSCOPE_INSTANCE }} QA_PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} GRAFANA_INTERNAL_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} GRAFANA_INTERNAL_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} GRAFANA_INTERNAL_HOST: ${{ secrets.GRAFANA_INTERNAL_HOST }} @@ -89,12 +93,14 @@ jobs: LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} LOKI_URL: ${{ secrets.LOKI_URL }} LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} AWS_REGION: ${{ secrets.QA_AWS_REGION }} AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} - AWS_API_GW_HOST_GRAFANA: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} + AWS_API_GW_HOST_GRAFANA: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} TEST_SECRETS_OVERRIDE_BASE64: ${{ secrets[inputs.test_secrets_override_key] }} SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} SLACK_NOTIFICATION_AFTER_TESTS_CHANNEL_ID: ${{ secrets.QA_VRF_SLACK_CHANNEL }} SLACK_API_KEY: ${{ secrets.QA_SLACK_API_KEY }} - SLACK_CHANNEL: ${{ secrets.QA_VRF_SLACK_CHANNEL }} + SLACK_CHANNEL: ${{ secrets.QA_VRF_SLACK_CHANNEL }} + MAIN_DNS_ZONE_PUBLIC_SDLC: ${{ secrets.MAIN_DNS_ZONE_PUBLIC_SDLC }} + AWS_K8S_CLUSTER_NAME_SDLC: ${{ secrets.AWS_K8S_CLUSTER_NAME_SDLC }} diff --git a/.github/workflows/on-demand-vrfv2plus-smoke-tests.yml b/.github/workflows/on-demand-vrfv2plus-smoke-tests.yml index 8561034b103..48c7cb5a3e5 100644 --- a/.github/workflows/on-demand-vrfv2plus-smoke-tests.yml +++ b/.github/workflows/on-demand-vrfv2plus-smoke-tests.yml @@ -17,7 +17,7 @@ on: test_config_override_path: description: Path to a test config file used to override the default test config required: false - type: string + type: string test_secrets_override_key: description: 'Key to run tests with custom test secrets' required: false @@ -31,7 +31,7 @@ on: description: 'Enter Slack user ID to notify on test failure' required: false type: string - + jobs: set-tests-to-run: name: Set tests to run @@ -41,13 +41,17 @@ jobs: steps: - name: Generate Test List JSON id: set-tests + env: + GH_INPUTS_TEST_SUITE: ${{ inputs.test_suite }} + GH_INPUTS_TEST_LIST_REGEX: ${{ inputs.test_list_regex }} + GH_INPUTS_TEST_CONFIG_OVERRIDE_PATH: ${{ inputs.test_config_override_path }} run: | - if [[ "${{ inputs.test_suite }}" == "All Tests" ]]; then + if [[ "$GH_INPUTS_TEST_SUITE" == "All Tests" ]]; then TEST_CMD="cd integration-tests/smoke && go test vrfv2plus_test.go -test.parallel=1 -timeout 3h -count=1 -json -v" else - TEST_CMD='cd integration-tests/smoke && go test -test.run "${{ inputs.test_list_regex }}" -test.parallel=1 -timeout 2h -count=1 -json -v' + TEST_CMD='cd integration-tests/smoke && go test -test.run "$GH_INPUTS_TEST_LIST_REGEX" -test.parallel=1 -timeout 2h -count=1 -json -v' fi - TEST_CONFIG_OVERRIDE_PATH=${{ inputs.test_config_override_path }} + TEST_CONFIG_OVERRIDE_PATH=$GH_INPUTS_TEST_CONFIG_OVERRIDE_PATH TEST_LIST=$(jq -n -c \ --arg test_cmd "$TEST_CMD" \ @@ -70,13 +74,14 @@ jobs: run-e2e-tests-workflow: name: Run E2E Tests needs: set-tests-to-run - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0632b5652dd5eb03bfa87e23a2b3e2911484fe59 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@61acf908014e2fe42c04f2a507c79f97eb5f8c4d with: custom_test_list_json: ${{ needs.set-tests-to-run.outputs.test_list }} chainlink_version: ${{ inputs.chainlink_version }} slack_notification_after_tests: always slack_notification_after_tests_name: "VRF V2 Plus Smoke Tests with test config: ${{ inputs.test_config_override_path || 'default' }}" slack_notification_after_tests_notify_user_id_on_failure: ${{ inputs.notify_user_id_on_failure }} + test_secrets_override_key: ${{ inputs.test_secrets_override_key }} secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} @@ -84,7 +89,6 @@ jobs: PROD_AWS_ACCOUNT_NUMBER: ${{ secrets.AWS_ACCOUNT_ID_PROD }} QA_PYROSCOPE_INSTANCE: ${{ secrets.QA_PYROSCOPE_INSTANCE }} QA_PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} GRAFANA_INTERNAL_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} GRAFANA_INTERNAL_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} GRAFANA_INTERNAL_HOST: ${{ secrets.GRAFANA_INTERNAL_HOST }} @@ -92,10 +96,12 @@ jobs: LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} LOKI_URL: ${{ secrets.LOKI_URL }} LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} AWS_REGION: ${{ secrets.QA_AWS_REGION }} AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} - AWS_API_GW_HOST_GRAFANA: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} + AWS_API_GW_HOST_GRAFANA: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} TEST_SECRETS_OVERRIDE_BASE64: ${{ secrets[inputs.test_secrets_override_key] }} SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} SLACK_NOTIFICATION_AFTER_TESTS_CHANNEL_ID: ${{ secrets.QA_VRF_SLACK_CHANNEL }} + MAIN_DNS_ZONE_PUBLIC_SDLC: ${{ secrets.MAIN_DNS_ZONE_PUBLIC_SDLC }} + AWS_K8S_CLUSTER_NAME_SDLC: ${{ secrets.AWS_K8S_CLUSTER_NAME_SDLC }} diff --git a/.github/workflows/operator-ui-ci.yml b/.github/workflows/operator-ui-ci.yml index 9bce18f8cff..7ea1cd8327b 100644 --- a/.github/workflows/operator-ui-ci.yml +++ b/.github/workflows/operator-ui-ci.yml @@ -33,6 +33,8 @@ jobs: - name: Checkout repository uses: actions/checkout@v4.2.1 + with: + persist-credentials: false - name: Get operator-ui tag id: get-operator-ui-tag diff --git a/.github/workflows/run-nightly-e2e-tests.yml b/.github/workflows/run-nightly-e2e-tests.yml index 712fb088181..76783601e75 100644 --- a/.github/workflows/run-nightly-e2e-tests.yml +++ b/.github/workflows/run-nightly-e2e-tests.yml @@ -20,7 +20,7 @@ on: jobs: call-run-e2e-tests-workflow: name: Run E2E Tests - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0632b5652dd5eb03bfa87e23a2b3e2911484fe59 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@61acf908014e2fe42c04f2a507c79f97eb5f8c4d with: chainlink_version: ${{ inputs.chainlink_version || 'develop' }} test_path: .github/e2e-tests.yml @@ -35,7 +35,6 @@ jobs: PROD_AWS_ACCOUNT_NUMBER: ${{ secrets.AWS_ACCOUNT_ID_PROD }} QA_PYROSCOPE_INSTANCE: ${{ secrets.QA_PYROSCOPE_INSTANCE }} QA_PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} GRAFANA_INTERNAL_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} GRAFANA_INTERNAL_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} GRAFANA_INTERNAL_HOST: ${{ secrets.GRAFANA_INTERNAL_HOST }} @@ -43,8 +42,10 @@ jobs: LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} LOKI_URL: ${{ secrets.LOKI_URL }} LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} AWS_REGION: ${{ secrets.QA_AWS_REGION }} AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} - AWS_API_GW_HOST_GRAFANA: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} + AWS_API_GW_HOST_GRAFANA: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} + MAIN_DNS_ZONE_PUBLIC_SDLC: ${{ secrets.MAIN_DNS_ZONE_PUBLIC_SDLC }} + AWS_K8S_CLUSTER_NAME_SDLC: ${{ secrets.AWS_K8S_CLUSTER_NAME_SDLC }} diff --git a/.github/workflows/run-selected-e2e-tests.yml b/.github/workflows/run-selected-e2e-tests.yml index e95ce1cef19..3b1efc8c45c 100644 --- a/.github/workflows/run-selected-e2e-tests.yml +++ b/.github/workflows/run-selected-e2e-tests.yml @@ -15,7 +15,7 @@ on: test_secrets_override_key: description: 'Enter the secret key to override test secrets' required: false - type: string + type: string test_config_override_path: description: 'Path to a test config file used to override the default test config' required: false @@ -23,25 +23,26 @@ on: with_existing_remote_runner_version: description: 'Use the existing remote runner version for k8s tests. Example: "d3bf5044af33e08be788a2df31c4a745cf69d787"' required: false - type: string + type: string workflow_run_name: description: 'Enter the name of the workflow run' default: 'Run E2E Tests' required: false type: string - + run-name: ${{ inputs.workflow_run_name }} jobs: call-run-e2e-tests-workflow: name: Run E2E Tests - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0632b5652dd5eb03bfa87e23a2b3e2911484fe59 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@61acf908014e2fe42c04f2a507c79f97eb5f8c4d with: chainlink_version: ${{ github.event.inputs.chainlink_version }} test_path: .github/e2e-tests.yml test_ids: ${{ github.event.inputs.test_ids }} test_config_override_path: ${{ github.event.inputs.test_config_override_path }} with_existing_remote_runner_version: ${{ github.event.inputs.with_existing_remote_runner_version }} + test_secrets_override_key: ${{ github.event.inputs.test_secrets_override_key }} secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} @@ -49,7 +50,6 @@ jobs: PROD_AWS_ACCOUNT_NUMBER: ${{ secrets.AWS_ACCOUNT_ID_PROD }} QA_PYROSCOPE_INSTANCE: ${{ secrets.QA_PYROSCOPE_INSTANCE }} QA_PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} GRAFANA_INTERNAL_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} GRAFANA_INTERNAL_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} GRAFANA_INTERNAL_HOST: ${{ secrets.GRAFANA_INTERNAL_HOST }} @@ -57,9 +57,11 @@ jobs: LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} LOKI_URL: ${{ secrets.LOKI_URL }} LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} AWS_REGION: ${{ secrets.QA_AWS_REGION }} AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} AWS_API_GW_HOST_GRAFANA: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} TEST_SECRETS_OVERRIDE_BASE64: ${{ secrets[inputs.test_secrets_override_key] }} SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} + MAIN_DNS_ZONE_PUBLIC_SDLC: ${{ secrets.MAIN_DNS_ZONE_PUBLIC_SDLC }} + AWS_K8S_CLUSTER_NAME_SDLC: ${{ secrets.AWS_K8S_CLUSTER_NAME_SDLC }} diff --git a/.github/workflows/solidity-foundry-artifacts.yml b/.github/workflows/solidity-foundry-artifacts.yml index 5a971f65174..5665c786057 100644 --- a/.github/workflows/solidity-foundry-artifacts.yml +++ b/.github/workflows/solidity-foundry-artifacts.yml @@ -16,7 +16,6 @@ on: - "llo-feeds" - "operatorforwarder" - "shared" - - "transmission" - "vrf" - "workflow" commit_to_use: @@ -51,6 +50,7 @@ jobs: - name: Checkout the repo uses: actions/checkout@v4.2.1 with: + persist-credentials: false ref: ${{ env.head_ref }} - name: Find modified contracts uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 @@ -69,7 +69,6 @@ jobs: - '!contracts/src/v0.8/**/*.t.sol' - '!contracts/src/v0.8/*.t.sol' - '!contracts/src/v0.8/**/testhelpers/**' - - '!contracts/src/v0.8/testhelpers/**' - '!contracts/src/v0.8/vendor/**' other_shared: - modified|added: 'contracts/src/v0.8/(interfaces/**/*.sol|*.sol)' @@ -87,8 +86,10 @@ jobs: - name: Transform modified files id: changes-transform shell: bash + env: + GH_INPUTS_PRODUCT: ${{ inputs.product }} run: | - if [ "${{ inputs.product }}" = "shared" ]; then + if [ "$GH_INPUTS_PRODUCT" = "shared" ]; then echo "::debug:: Product is shared, transforming changes" if [[ "${{ steps.changes-dorny.outputs.product }}" == "true" && "${{ steps.changes-dorny.outputs.other_shared }}" == "true" ]]; then echo "::debug:: Changes were found in 'shared' folder and in 'interfaces' and root folders" @@ -129,17 +130,18 @@ jobs: steps: - name: Checkout the repo uses: actions/checkout@v4.2.1 - - - name: Extract Foundry version - id: extract-foundry-version - uses: ./.github/actions/detect-solidity-foundry-version with: - working-directory: contracts + persist-credentials: false + + - name: Install Foundry + uses: ./.github/actions/install-solidity-foundry - name: Should skip code coverage report id: skip-code-coverage + env: + GH_INPUTS_PRODUCT: ${{ inputs.product }} run: | - if [[ "${{ inputs.product }}" = "automation" || "${{ inputs.product }}" = "vrf" || "${{ inputs.product }}" = "functions" ]]; then + if [[ "$GH_INPUTS_PRODUCT" = "automation" || "$GH_INPUTS_PRODUCT" = "vrf" || "$GH_INPUTS_PRODUCT" = "functions" ]]; then echo "generate_code_coverage=false" >> $GITHUB_OUTPUT else echo "generate_code_coverage=true" >> $GITHUB_OUTPUT diff --git a/.github/workflows/solidity-foundry.yml b/.github/workflows/solidity-foundry.yml index f94ef29a3b8..c91a1abd086 100644 --- a/.github/workflows/solidity-foundry.yml +++ b/.github/workflows/solidity-foundry.yml @@ -21,7 +21,6 @@ jobs: runs-on: ubuntu-latest outputs: matrix: ${{ steps.define-matrix.outputs.matrix }} - foundry-version: ${{ steps.extract-foundry-version.outputs.foundry-version }} steps: - name: Define test matrix id: define-matrix @@ -38,7 +37,6 @@ jobs: { "name": "llo-feeds", "setup": { "run-coverage": true, "min-coverage": 49.3, "run-gas-snapshot": true, "run-forge-fmt": false }}, { "name": "operatorforwarder", "setup": { "run-coverage": true, "min-coverage": 55.7, "run-gas-snapshot": true, "run-forge-fmt": false }}, { "name": "shared", "setup": { "run-coverage": true, "extra-coverage-params": "--no-match-path='*CallWithExactGas*' --ir-minimum", "min-coverage": 32.6, "run-gas-snapshot": true, "run-forge-fmt": false }}, - { "name": "transmission", "setup": { "run-coverage": true, "min-coverage": 61.5, "run-gas-snapshot": true, "run-forge-fmt": false }}, { "name": "vrf", "setup": { "run-coverage": false, "min-coverage": 98.5, "run-gas-snapshot": false, "run-forge-fmt": false }}, { "name": "workflow", "setup": { "run-coverage": true, "extra-coverage-params": "--ir-minimum", "min-coverage": 96.0, "run-gas-snapshot": true, "run-forge-fmt": true }} ] @@ -49,12 +47,8 @@ jobs: - name: Checkout the repo uses: actions/checkout@v4.2.1 - - - name: Extract Foundry version - id: extract-foundry-version - uses: ./.github/actions/detect-solidity-foundry-version with: - working-directory: contracts + persist-credentials: false changes: name: Detect changes @@ -70,6 +64,8 @@ jobs: steps: - name: Checkout the repo uses: actions/checkout@v4.2.1 + with: + persist-credentials: false - name: Detect changes uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 id: changes @@ -112,8 +108,6 @@ jobs: - 'contracts/src/v0.8/mocks/**/*.sol' - 'contracts/src/v0.8/tests/**/*.sol' - 'contracts/src/v0.8/vendor/**/*.sol' - transmission: - - 'contracts/src/v0.8/transmission/**/*.sol' workflow: - 'contracts/src/v0.8/workflow/**/*.sol' @@ -157,6 +151,7 @@ jobs: || needs.changes.outputs.non_src_changes == 'true' }} uses: actions/checkout@v4.2.1 with: + persist-credentials: false submodules: recursive # Only needed because we use the NPM versions of packages @@ -176,9 +171,7 @@ jobs: ${{ contains(fromJson(needs.changes.outputs.all_changes), matrix.product.name) || contains(fromJson(needs.changes.outputs.all_changes), 'shared') || needs.changes.outputs.non_src_changes == 'true' }} - uses: foundry-rs/foundry-toolchain@8f1998e9878d786675189ef566a2e4bf24869773 # v1.2.0 - with: - version: ${{ needs.define-matrix.outputs.foundry-version }} + uses: ./.github/actions/install-solidity-foundry # If Solc version is not set in foundry.toml, then what `forge build` does is that it lazily-installs required solc versions # using SVM. This is done in parallel, but SVM has a bug and is not thread-safe, which sometimes leads to `Text file busy` error. @@ -330,10 +323,13 @@ jobs: steps: - name: Checkout this repository uses: actions/checkout@v4.2.1 + with: + persist-credentials: false - name: Checkout .github repository uses: actions/checkout@v4.2.1 with: + persist-credentials: false repository: smartcontractkit/.github ref: b6e37806737eef87e8c9137ceeb23ef0bff8b1db # validate-solidity-artifacts@0.1.0 path: ./dot_github @@ -342,9 +338,7 @@ jobs: uses: ./.github/actions/setup-nodejs - name: Install Foundry - uses: foundry-rs/foundry-toolchain@8f1998e9878d786675189ef566a2e4bf24869773 # v1.2.0 - with: - version: ${{ needs.define-matrix.outputs.foundry-version }} + uses: ./.github/actions/install-solidity-foundry - name: Set up Python uses: actions/setup-python@v5.2.0 @@ -418,6 +412,7 @@ jobs: if: needs.changes.outputs.sol_mod_only == 'true' uses: actions/checkout@v4.2.1 with: + persist-credentials: false ref: ${{ github.base_ref }} - name: Download Slither scripts @@ -611,6 +606,7 @@ jobs: if: ${{ (contains(fromJson(needs.changes.outputs.all_changes), matrix.product.name) || needs.changes.outputs.non_src_changes == 'true') && matrix.product.setup.run-forge-fmt }} uses: actions/checkout@v4.2.1 with: + persist-credentials: false submodules: recursive - name: Setup NodeJS @@ -619,9 +615,7 @@ jobs: - name: Install Foundry if: ${{ (contains(fromJson(needs.changes.outputs.all_changes), matrix.product.name) || needs.changes.outputs.non_src_changes == 'true') && matrix.product.setup.run-forge-fmt }} - uses: foundry-rs/foundry-toolchain@8f1998e9878d786675189ef566a2e4bf24869773 # v1.2.0 - with: - version: ${{ needs.define-matrix.outputs.foundry-version }} + uses: ./.github/actions/install-solidity-foundry - name: Run Forge fmt if: ${{ (contains(fromJson(needs.changes.outputs.all_changes), matrix.product.name) || needs.changes.outputs.non_src_changes == 'true') && matrix.product.setup.run-forge-fmt }} diff --git a/.github/workflows/solidity-hardhat.yml b/.github/workflows/solidity-hardhat.yml index 7283e17e13f..e2da95eae6e 100644 --- a/.github/workflows/solidity-hardhat.yml +++ b/.github/workflows/solidity-hardhat.yml @@ -20,12 +20,14 @@ jobs: steps: - name: Checkout the repo uses: actions/checkout@v4.2.1 + with: + persist-credentials: false - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 id: changes with: filters: | src: - - 'contracts/src/!(v0.8/(ccip|functions|keystone|l2ep|liquiditymanager|llo-feeds|transmission|vrf|workflow)/**)/**/*' + - 'contracts/src/!(v0.8/(ccip|functions|keystone|l2ep|liquiditymanager|llo-feeds|vrf|workflow)/**)/**/*' - 'contracts/test/**/*' - 'contracts/package.json' - 'contracts/pnpm-lock.yaml' @@ -40,6 +42,8 @@ jobs: steps: - name: Checkout the repo uses: actions/checkout@v4.2.1 + with: + persist-credentials: false - name: Setup NodeJS uses: ./.github/actions/setup-nodejs - name: Setup Hardhat diff --git a/.github/workflows/solidity-tracability.yml b/.github/workflows/solidity-traceability.yml similarity index 98% rename from .github/workflows/solidity-tracability.yml rename to .github/workflows/solidity-traceability.yml index f0b1166807f..a894175f6f3 100644 --- a/.github/workflows/solidity-tracability.yml +++ b/.github/workflows/solidity-traceability.yml @@ -1,5 +1,5 @@ # This workflow handles the enforcement of code Traceability via changesets and jira issue linking for our Solidity codebase. -name: Solidity Tracability +name: Solidity Traceability on: merge_group: @@ -23,6 +23,8 @@ jobs: steps: - name: Checkout the repo uses: actions/checkout@v4.2.1 + with: + persist-credentials: false - name: Filter paths uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 @@ -59,6 +61,7 @@ jobs: - name: Checkout the repo uses: actions/checkout@v4.2.1 with: + persist-credentials: false ref: ${{ github.event.pull_request.head.sha }} - name: Assume role capable of dispatching action @@ -94,6 +97,7 @@ jobs: - name: Checkout .Github repository uses: actions/checkout@v4.2.1 with: + persist-credentials: false repository: smartcontractkit/.github ref: 6781e048ecc1aadf7d605722c32e8068a5f829ce # jira-tracing@0.3.0 path: ./dot_github diff --git a/.github/workflows/solidity-wrappers.yml b/.github/workflows/solidity-wrappers.yml index b2acdf6ca5e..804a6822a29 100644 --- a/.github/workflows/solidity-wrappers.yml +++ b/.github/workflows/solidity-wrappers.yml @@ -24,6 +24,8 @@ jobs: steps: - name: Checkout the repo uses: actions/checkout@v4.2.1 + with: + persist-credentials: false - name: Detect changes id: ch uses: ./.github/actions/detect-solidity-file-changes @@ -41,6 +43,8 @@ jobs: steps: - name: Checkout the repo uses: actions/checkout@v4.2.1 + with: + persist-credentials: false - name: Setup Go uses: ./.github/actions/setup-go @@ -50,6 +54,9 @@ jobs: with: prod: "true" + - name: Install Foundry + uses: ./.github/actions/install-solidity-foundry + - name: Run native compile and generate wrappers run: make wrappers-all working-directory: ./contracts diff --git a/.github/workflows/solidity.yml b/.github/workflows/solidity.yml index 605b3f2e325..7275f1f6261 100644 --- a/.github/workflows/solidity.yml +++ b/.github/workflows/solidity.yml @@ -17,6 +17,8 @@ jobs: steps: - name: Checkout the repo uses: actions/checkout@v4.2.1 + with: + persist-credentials: false - name: Detect readonly solidity file changes id: ch uses: ./.github/actions/detect-solidity-readonly-file-changes @@ -29,6 +31,8 @@ jobs: steps: - name: Checkout the repo uses: actions/checkout@v4.2.1 + with: + persist-credentials: false - name: Detect changes id: ch uses: ./.github/actions/detect-solidity-file-changes @@ -44,6 +48,8 @@ jobs: pre-release-version: ${{ steps.release-tag-check.outputs.pre-release-version }} steps: - uses: actions/checkout@v4.2.1 + with: + persist-credentials: false - name: Check release tag id: release-tag-check uses: smartcontractkit/chainlink-github-actions/release/release-tag-check@5dd916d08c03cb5f9a97304f4f174820421bb946 # v2.3.11 @@ -62,6 +68,8 @@ jobs: steps: - name: Checkout the repo uses: actions/checkout@v4.2.1 + with: + persist-credentials: false - name: Setup NodeJS uses: ./.github/actions/setup-nodejs - name: Run Prepublish test @@ -77,11 +85,13 @@ jobs: - name: Checkout the repo uses: actions/checkout@v4.2.1 with: + persist-credentials: false path: chainlink - name: Checkout diff-so-fancy uses: actions/checkout@v4.2.1 with: + persist-credentials: false repository: so-fancy/diff-so-fancy ref: a673cb4d2707f64d92b86498a2f5f71c8e2643d5 # v1.4.3 path: diff-so-fancy @@ -100,6 +110,11 @@ jobs: with: go-version-file: "chainlink/go.mod" + - name: Install Foundry + uses: ./chainlink/.github/actions/install-solidity-foundry + with: + working-directory: chainlink/contracts + - name: Run native compile and generate wrappers working-directory: ./chainlink/contracts run: make wrappers-all @@ -128,6 +143,8 @@ jobs: steps: - name: Checkout the repo uses: actions/checkout@v4.2.1 + with: + persist-credentials: false - name: Setup NodeJS uses: ./.github/actions/setup-nodejs - name: Run pnpm lint @@ -148,6 +165,8 @@ jobs: steps: - name: Checkout the repo uses: actions/checkout@v4.2.1 + with: + persist-credentials: false - name: Setup NodeJS uses: ./.github/actions/setup-nodejs - name: Run prettier check @@ -162,6 +181,8 @@ jobs: steps: - name: Checkout the repo uses: actions/checkout@v4.2.1 + with: + persist-credentials: false - name: Setup NodeJS uses: ./.github/actions/setup-nodejs @@ -191,6 +212,8 @@ jobs: steps: - name: Checkout the repo uses: actions/checkout@v4.2.1 + with: + persist-credentials: false - name: Setup NodeJS uses: ./.github/actions/setup-nodejs diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index b2ed7ff36a2..5972519426a 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -2,7 +2,7 @@ # A PR with more than 60 days of inactivity will be marked as stale # A PR that's stale for more than 7 days will be automatically closed # Issues are exempt from auto marking as stale but issues with manually added 'stale' label are eligible for auto closure after 7 days. -# PRs with assignees are exempt from auto stale marking, it's the responsibility of the assignee to get the PR progressed either with review/merge or closure. +# PRs with `exempt-pr-labels` or assignees are exempt from auto stale marking, it's the responsibility of the assignee to get the PR progressed either with review/merge or closure. name: Manage stale Issues and PRs on: @@ -11,16 +11,17 @@ on: jobs: stale: - runs-on: ubuntu-latest permissions: issues: write pull-requests: write steps: - - uses: actions/stale@v9.0.0 - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - exempt-all-pr-assignees: true - stale-pr-message: 'This PR is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days.' - days-before-issue-stale: -1 # disables marking issues as stale automatically. Issues can still be marked as stale manually, in which the closure policy applies. + - uses: actions/stale@v9.0.0 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + exempt-all-pr-assignees: true + stale-pr-message: "This PR is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days." + days-before-issue-stale: -1 # disables marking issues as stale automatically. Issues can still be marked as stale manually, in which the closure policy applies. + # Comma separated list of labels that exempt issues from being considered stale. + exempt-pr-labels: "stale-exempt" diff --git a/.github/workflows/sync-develop-from-smartcontractkit-chainlink.yml b/.github/workflows/sync-develop-from-smartcontractkit-chainlink.yml index e635ce40922..061db3ae7f3 100644 --- a/.github/workflows/sync-develop-from-smartcontractkit-chainlink.yml +++ b/.github/workflows/sync-develop-from-smartcontractkit-chainlink.yml @@ -12,6 +12,7 @@ jobs: steps: - uses: actions/checkout@v4.2.1 with: + persist-credentials: false ref: develop if: env.GITHUB_REPOSITORY != 'smartcontractkit/chainlink' - name: Sync diff --git a/.gitignore b/.gitignore index 34d25ebb472..bf8606a8e30 100644 --- a/.gitignore +++ b/.gitignore @@ -48,9 +48,8 @@ cl_backup_*.tar.gz # Test artifacts core/cmd/TestClient_ImportExportP2PKeyBundle_test_key.json -output.txt race.* -golangci-lint-output.txt +*output.txt /golangci-lint/ .covdata core/services/job/testdata/wasm/testmodule.wasm @@ -116,3 +115,4 @@ vendor/* *.wasm contracts/lcov.info +/cache diff --git a/.golangci.yml b/.golangci.yml index ca8cf4dade5..d35b6459e05 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,5 +1,6 @@ run: - timeout: 15m0s + timeout: 15m + allow-parallel-runners: true linters: enable: - containedctx @@ -7,7 +8,6 @@ linters: - errname - errorlint - exhaustive - - exportloopref - fatcontext - ginkgolinter - gocritic @@ -96,7 +96,7 @@ linters-settings: - name: waitgroup-by-value - name: unconditional-recursion - name: struct-tag - # - name: string-format + - name: string-format - name: string-of-int - name: range-val-address - name: range-val-in-closure diff --git a/.mockery.yaml b/.mockery.yaml index 5777ca1da92..88dcf307d20 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -3,20 +3,6 @@ mockname: "{{ .InterfaceName }}" outpkg: mocks filename: "{{ .InterfaceName | snakecase }}.go" packages: - github.com/smartcontractkit/chainlink/v2/common/client: - config: - dir: "{{ .InterfaceDir }}" - filename: "mock_{{ .InterfaceName | snakecase }}_test.go" - inpackage: true - mockname: "mock{{ .InterfaceName | camelcase }}" - interfaces: - Node: - NodeSelector: - sendOnlyClient: - SendOnlyNode: - RPCClient: - Head: - PoolChainInfoProvider: github.com/smartcontractkit/chainlink/v2/common/headtracker: interfaces: HeadTrackable: @@ -35,9 +21,11 @@ packages: TxStrategy: TxAttemptBuilder: TxStore: - github.com/smartcontractkit/chainlink/v2/common/types: + github.com/smartcontractkit/chainlink-framework/multinode: + config: + dir: common/types/mocks + outpkg: mocks interfaces: - Head: Subscription: github.com/smartcontractkit/chainlink/v2/core/bridges: interfaces: @@ -93,6 +81,12 @@ packages: BalanceMonitor: config: dir: "{{ .InterfaceDir }}/../mocks" + github.com/smartcontractkit/chainlink/v2/core/chains/evm/txm: + interfaces: + Client: + TxStore: + AttemptBuilder: + Keystore: github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr: interfaces: ChainConfig: @@ -127,7 +121,7 @@ packages: FlagsInterface: config: mockname: Flags - github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/aggregator_v3_interface: + github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/aggregator_v3_interface: config: dir: core/services/vrf/mocks filename: aggregator_v3_interface.go @@ -233,6 +227,7 @@ packages: StarkNet: config: filename: starknet.go + Tron: VRF: Workflow: github.com/smartcontractkit/chainlink/v2/core/services/ocr: @@ -501,12 +496,20 @@ packages: PriceRegistryReader: config: filename: price_registry_reader_mock.go + FeeEstimatorConfigReader: + config: + filename: fee_estimator_config_mock.go TokenPoolReader: config: filename: token_pool_reader_mock.go USDCReader: config: filename: usdc_reader_mock.go + github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/estimatorconfig: + interfaces: + GasPriceInterceptor: + config: + filename: gas_price_interceptor_mock.go github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/batchreader: config: filename: token_pool_batched_reader_mock.go @@ -591,4 +594,4 @@ packages: dir: "{{ .InterfaceDir }}" github.com/smartcontractkit/chainlink/v2/core/capabilities/targets: interfaces: - ContractValueGetter: \ No newline at end of file + ContractValueGetter: diff --git a/.tool-versions b/.tool-versions index 49f7ef749d1..bdf11a7ed21 100644 --- a/.tool-versions +++ b/.tool-versions @@ -4,6 +4,7 @@ nodejs 20.13.1 pnpm 9.4.0 postgres 15.1 helm 3.10.3 -golangci-lint 1.61.0 +golangci-lint 1.62.2 protoc 25.1 python 3.10.5 +act 0.2.30 diff --git a/CHANGELOG.md b/CHANGELOG.md index 544cf09e5b4..d5b6332c5a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,122 @@ # Changelog Chainlink Core +## 2.19.0 - 2024-12-12 + +### Minor Changes + +- [#15126](https://github.com/smartcontractkit/chainlink/pull/15126) [`bf9b08c331`](https://github.com/smartcontractkit/chainlink/commit/bf9b08c33119d14a34c4914a3a7cc94ea6cb5481) - update plugin and evm chainwriter to remove evmConfig dependency #updated + +- [#15148](https://github.com/smartcontractkit/chainlink/pull/15148) [`07a2cec532`](https://github.com/smartcontractkit/chainlink/commit/07a2cec532704aebe413a9fa29edc04bd9063677) - #added address book remove feature + +- [#14898](https://github.com/smartcontractkit/chainlink/pull/14898) [`a417740359`](https://github.com/smartcontractkit/chainlink/commit/a41774035961ce88be2fed7c6759758a7f00881d) - Bump to start the next version + +- [#15010](https://github.com/smartcontractkit/chainlink/pull/15010) [`c162226424`](https://github.com/smartcontractkit/chainlink/commit/c1622264243c2ee83ff7ba54989cfe789a8da53c) - #added support enable and disable feed manager + +- [#15104](https://github.com/smartcontractkit/chainlink/pull/15104) [`cf7db16483`](https://github.com/smartcontractkit/chainlink/commit/cf7db164832ea95354a3c953126c2fd32a59afd7) - Updated Solana TXM's in-memory storage to track statuses across the Solana transaction lifecycle. Added a method to translate Solana transaction statuses into states expected by the ChainWriter interface. Made the duration transactions are retained in storage after finality or error configurable using `TxRetentionTimeout`. #added + +- [#14880](https://github.com/smartcontractkit/chainlink/pull/14880) [`af8132361b`](https://github.com/smartcontractkit/chainlink/commit/af8132361b3fbd6858a792c4814d144582e6467b) - Implement secrets interpolation with dummy workflow registry syncer #internal + +- [#14993](https://github.com/smartcontractkit/chainlink/pull/14993) [`883d993dc6`](https://github.com/smartcontractkit/chainlink/commit/883d993dc6f58b561787c0e287ed121a08ce550d) - #changed UI(chainconfig): make admin address optional + +- [#14937](https://github.com/smartcontractkit/chainlink/pull/14937) [`3ad089f664`](https://github.com/smartcontractkit/chainlink/commit/3ad089f6644ed54cb21421e84a01b9628c15e205) - #added Enable and Disable Feeds Manager mutations + +- [#14935](https://github.com/smartcontractkit/chainlink/pull/14935) [`c042b627f1`](https://github.com/smartcontractkit/chainlink/commit/c042b627f1fb3a8e6009314c4c2e4daa3c7659c7) - #internal Fix Contract Reader data word index calculation and change ccip contract reader config for more optimal querying. + +- [#15210](https://github.com/smartcontractkit/chainlink/pull/15210) [`7ff9cf9916`](https://github.com/smartcontractkit/chainlink/commit/7ff9cf9916ae1648ccc3475c86e45c9df6ab8d1f) - #removed Remove unused deprecated key interfaces. + +- [#14791](https://github.com/smartcontractkit/chainlink/pull/14791) [`090063799c`](https://github.com/smartcontractkit/chainlink/commit/090063799cd2fd62646c383bf2d2e42d25225c40) - #updated + update ethkeys, ethtransactions to handle duplicate chain id in different network + introduce network arg input to Chain graphql query to allow better lookup based on network and chain id + +- [#14405](https://github.com/smartcontractkit/chainlink/pull/14405) [`03115e8038`](https://github.com/smartcontractkit/chainlink/commit/03115e80382dc02a7bce66dc16d8bae5bd7de132) - #internal Updated the TXM confirmation logic to use the mined transaction count to identify re-org'd or confirmed transactions. + + - Confirmer uses the mined transaction count to determine if transactions have been re-org'd or confirmed. + - Confirmer no longer sets transaction states to `confirmed_missing_receipt`. This state is maintained in queries for backwards compatibility. + - Finalizer now responsible for fetching and storing receipts for confirmed transactions. + - Finalizer now responsible for resuming pending task runs. + - Finalizer now responsible for marking old transactions without receipts broadcasted before the finalized head as fatal. + +- [#14912](https://github.com/smartcontractkit/chainlink/pull/14912) [`bb6a20a882`](https://github.com/smartcontractkit/chainlink/commit/bb6a20a8825d9f374b99238097b4c9f701336a0c) - Use correct OCR2OracleSpecID when setting up RequestedRoundTracker #bugfix + +- [#15029](https://github.com/smartcontractkit/chainlink/pull/15029) [`99241ec680`](https://github.com/smartcontractkit/chainlink/commit/99241ec68098d818b97b046a1f9b4f5c8f0c5366) - Added multiple blocks history estimator feature and config for Solana TXM. #added + +- [#15197](https://github.com/smartcontractkit/chainlink/pull/15197) [`3b3b86ceae`](https://github.com/smartcontractkit/chainlink/commit/3b3b86ceaed419fa3890be17c8699a3416081fb9) - Add don_id to Mercury Enhanced EA telemetry #added + +- [#15266](https://github.com/smartcontractkit/chainlink/pull/15266) [`a9d6a3f05c`](https://github.com/smartcontractkit/chainlink/commit/a9d6a3f05c2ca8f8efbd909179f06788c356429e) - #removed unused key files and move public_key test file. + +- [#14781](https://github.com/smartcontractkit/chainlink/pull/14781) [`bfd9a3ffe1`](https://github.com/smartcontractkit/chainlink/commit/bfd9a3ffe11484f3dc413bb77a709f2c4bb281b0) - Support multiple chains evm clients for TXM gas estimator to fetch L1 gas oracle + #added + +- [#15244](https://github.com/smartcontractkit/chainlink/pull/15244) [`827e003a0c`](https://github.com/smartcontractkit/chainlink/commit/827e003a0c8c0212c6de0cb330e1f27a9c583dab) - #bugfix Update Log.Level and MaxSize configs description in the docs + +- [#15296](https://github.com/smartcontractkit/chainlink/pull/15296) [`de9868df2c`](https://github.com/smartcontractkit/chainlink/commit/de9868df2c8869bcaf641b06e77dcaa720506263) - #updated chain config: allow chain id and account address to be manually provided when no selections are available + +- [#15160](https://github.com/smartcontractkit/chainlink/pull/15160) [`816dcf814a`](https://github.com/smartcontractkit/chainlink/commit/816dcf814aff1ab5ca043eb47849162a61bc184b) - Add CSA authentication support to Beholder #added + +- [#15237](https://github.com/smartcontractkit/chainlink/pull/15237) [`1f9c07de61`](https://github.com/smartcontractkit/chainlink/commit/1f9c07de618ecfa3f23b8259ce0558941b5c357f) - #added feat: support creating solana chain config in job distributor page + +- [#15299](https://github.com/smartcontractkit/chainlink/pull/15299) [`a2c3da471c`](https://github.com/smartcontractkit/chainlink/commit/a2c3da471cc344a14003f53c2c2f09c937c204c1) - #updated Update few incorrect occurences of the password for notreal@fakeemail.ch. + +### Patch Changes + +- [#14896](https://github.com/smartcontractkit/chainlink/pull/14896) [`38ef1799dc`](https://github.com/smartcontractkit/chainlink/commit/38ef1799dc8dade6882acbafda3f49e942483f6f) - Ensure RPCClient with enabled polling respects health check flag #internal + +- [#14978](https://github.com/smartcontractkit/chainlink/pull/14978) [`65351c3a6f`](https://github.com/smartcontractkit/chainlink/commit/65351c3a6fffcff03d249e64cae223daabd86e3c) - Set `NodePool.EnforceRepeatableRead = true` by default for all chains. This forces Core to stop using RPCs behind on the latest finalized block. #changed #nops + +- [#14875](https://github.com/smartcontractkit/chainlink/pull/14875) [`101fbbc75a`](https://github.com/smartcontractkit/chainlink/commit/101fbbc75a76893d2ebe0c24fa61773876007d76) - #updated ignoring tx type 126 on celo + +- [#14929](https://github.com/smartcontractkit/chainlink/pull/14929) [`da5910eda9`](https://github.com/smartcontractkit/chainlink/commit/da5910eda98882f8a1b9ccc52b99afa223fb3997) - Add config validation so it requires ws url when http polling disabled #bugfix + +- [#14964](https://github.com/smartcontractkit/chainlink/pull/14964) [`7a80f364f9`](https://github.com/smartcontractkit/chainlink/commit/7a80f364f902c46a958021777336d6f6de9203c3) - #internal Add tokenDestGasOverhead to CalculateMessageMaxGas + +- [#15115](https://github.com/smartcontractkit/chainlink/pull/15115) [`f8a6218727`](https://github.com/smartcontractkit/chainlink/commit/f8a62187273bac1f12eeee0fe33355fe1b4faebb) - Fixed outdated headtracker config doc. #internal + +- [#14955](https://github.com/smartcontractkit/chainlink/pull/14955) [`1b8819e518`](https://github.com/smartcontractkit/chainlink/commit/1b8819e5189459a557a981ab115813253cdda919) - #updated bump CTF to v1.50.13, more robust ethereum client compatibility pipeline + +- [#14950](https://github.com/smartcontractkit/chainlink/pull/14950) [`0cd0867140`](https://github.com/smartcontractkit/chainlink/commit/0cd086714086b2a788c54de9aea13d58316518dd) - #internal OracleFactory error handling change + +- [#14893](https://github.com/smartcontractkit/chainlink/pull/14893) [`e116f744b2`](https://github.com/smartcontractkit/chainlink/commit/e116f744b222b7d664a8501566093ca1c1c63aa9) - Relocation of the deployment directory into a direct subdir of the root. #internal + +- [#15024](https://github.com/smartcontractkit/chainlink/pull/15024) [`6b29cdb7f3`](https://github.com/smartcontractkit/chainlink/commit/6b29cdb7f349b370581822ec6f54713faa7ca49e) - Minor fixes to the CCIPChainReader enabling proper serialization #internal + +- [#14827](https://github.com/smartcontractkit/chainlink/pull/14827) [`a9f86b51bf`](https://github.com/smartcontractkit/chainlink/commit/a9f86b51bf8d3a8548d4870c91f3e82669f5f21a) - #added Handle Hex String in EA Telemetry + +- [#15137](https://github.com/smartcontractkit/chainlink/pull/15137) [`7bd35dcea0`](https://github.com/smartcontractkit/chainlink/commit/7bd35dcea04b02ceb2e46a0431eca61ab3b78889) - #internal Update ccip contract reader cfg for ccip message sent to use output codec wrapper modifier + +- [#14710](https://github.com/smartcontractkit/chainlink/pull/14710) [`12174c79c4`](https://github.com/smartcontractkit/chainlink/commit/12174c79c4d1746149d7c89e41e67f9dc6525c18) - Adds new custom calldata DA oracle #added + +- [#14891](https://github.com/smartcontractkit/chainlink/pull/14891) [`12e2eb251c`](https://github.com/smartcontractkit/chainlink/commit/12e2eb251c406b601b2f954ed25ccad369421403) - Fix flaky WS test server #internal + +- [#11809](https://github.com/smartcontractkit/chainlink/pull/11809) [`2e8e16820b`](https://github.com/smartcontractkit/chainlink/commit/2e8e16820b02a9ca83aa46e7ae2deac31eaf08aa) - Upgrade go-ethereum to v1.14.11 #internal + +- [#15279](https://github.com/smartcontractkit/chainlink/pull/15279) [`276d1f3255`](https://github.com/smartcontractkit/chainlink/commit/276d1f3255aeafb1767ee84f697fc4746890a9a6) - Integration tests for USDC token transfer #internal + +- [#14984](https://github.com/smartcontractkit/chainlink/pull/14984) [`1738332823`](https://github.com/smartcontractkit/chainlink/commit/173833282344857b5e7d95863d8dab211db71ad7) - use last mined nonce instead of pending nonce to recover from occasional nonce gap issues within nonce tracker. #internal + +- [#11809](https://github.com/smartcontractkit/chainlink/pull/11809) [`2e8e16820b`](https://github.com/smartcontractkit/chainlink/commit/2e8e16820b02a9ca83aa46e7ae2deac31eaf08aa) - Fix HeadTracker tests caused by simulated client update #internal + +- [#15130](https://github.com/smartcontractkit/chainlink/pull/15130) [`4f0491483c`](https://github.com/smartcontractkit/chainlink/commit/4f0491483c089ee2fd5e7875b0d58b65b304b111) - CCIP token transfer integration tests #internal + +- [#15150](https://github.com/smartcontractkit/chainlink/pull/15150) [`68bff71f20`](https://github.com/smartcontractkit/chainlink/commit/68bff71f201c8d40219aeadea08a49a19f1ba6f1) - #updated Operator UI to support StreamSpec job definition + +- [#14433](https://github.com/smartcontractkit/chainlink/pull/14433) [`340a6bfdf5`](https://github.com/smartcontractkit/chainlink/commit/340a6bfdf54745dd1c6d9f322d9c9515c97060bb) - Merge raw configs correctly #bugfix + +- [#15060](https://github.com/smartcontractkit/chainlink/pull/15060) [`239b3a95d1`](https://github.com/smartcontractkit/chainlink/commit/239b3a95d14dd872a7192de461c33fdc143fb163) - Modify release changelog generation format #internal + +- [#15019](https://github.com/smartcontractkit/chainlink/pull/15019) [`039777ffb8`](https://github.com/smartcontractkit/chainlink/commit/039777ffb8994e0af3a133dd02d9852f4d0a0ae1) - #updated celo alfajores config + +- [#15157](https://github.com/smartcontractkit/chainlink/pull/15157) [`12986aa461`](https://github.com/smartcontractkit/chainlink/commit/12986aa461a86a593dbce422725abf7e05f05332) - Enable AutoPurge feature on all affected chains #nops + +- [#14800](https://github.com/smartcontractkit/chainlink/pull/14800) [`7bac85fdb3`](https://github.com/smartcontractkit/chainlink/commit/7bac85fdb37ed15eb42357b0a0ce06e4febd7494) - #bugfix Memory leak fix on promwrapper + +- [#14867](https://github.com/smartcontractkit/chainlink/pull/14867) [`2d28b4eb9d`](https://github.com/smartcontractkit/chainlink/commit/2d28b4eb9d8635215d953b4f5d256791a9941035) - #updated Use labelers from `chainlink-common` + +- [#15284](https://github.com/smartcontractkit/chainlink/pull/15284) [`7cd17d687a`](https://github.com/smartcontractkit/chainlink/commit/7cd17d687a11fcfe36ad78d6279dc642b6186eaa) - Bump Solana to include MultiNode integration. #added + +- [#15372](https://github.com/smartcontractkit/chainlink/pull/15372) [`d3fa330b1b`](https://github.com/smartcontractkit/chainlink/commit/d3fa330b1b3c275c48ea7ec962b4b8457f940fcd) - fix reported evm node states + +- [#15577](https://github.com/smartcontractkit/chainlink/pull/15577) [`6da84b21c1`](https://github.com/smartcontractkit/chainlink/commit/6da84b21c16f680f86f640df7ac4cfefab5b942e) - Fixes a race condition with the Finalizer when clearing txs #bugfix + ## 2.18.0 - 2024-11-01 ### Minor Changes @@ -50,6 +167,7 @@ Reduced Generics: Significantly less bulky code! #updated #changed #internal + - [#14629](https://github.com/smartcontractkit/chainlink/pull/14629) [`4928e60ddf`](https://github.com/smartcontractkit/chainlink/commit/4928e60ddfe375e4a0c644cb210802b4c4db5dbd) Thanks [@huangzhen1997](https://github.com/huangzhen1997)! - Support Zircuit fraud transactions detection and zk overflow detection #added - [#14334](https://github.com/smartcontractkit/chainlink/pull/14334) [`0ad624673f`](https://github.com/smartcontractkit/chainlink/commit/0ad624673f6f1a8e155fc43c67a8ae6caddefa90) Thanks [@krehermann](https://github.com/krehermann)! - #added keystone contract deployment - [#14709](https://github.com/smartcontractkit/chainlink/pull/14709) [`1560aa9167`](https://github.com/smartcontractkit/chainlink/commit/1560aa9167a812abe3a8370c033b3290dcbcb261) Thanks [@KuphJr](https://github.com/KuphJr)! - Add encryptionPublicKey to CapabilitiesRegistry.sol diff --git a/GNUmakefile b/GNUmakefile index b765c63a3f4..d86b791bbee 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -4,6 +4,7 @@ COMMIT_SHA ?= $(shell git rev-parse HEAD) VERSION = $(shell jq -r '.version' package.json) GO_LDFLAGS := $(shell tools/bin/ldflags) GOFLAGS = -ldflags "$(GO_LDFLAGS)" +GCFLAGS = -gcflags "$(GO_GCFLAGS)" .PHONY: install install: install-chainlink-autoinstall ## Install chainlink and all its dependencies. @@ -38,7 +39,7 @@ docs: ## Install and run pkgsite to view Go docs .PHONY: install-chainlink install-chainlink: operator-ui ## Install the chainlink binary. - go install $(GOFLAGS) . + go install $(GCFLAGS) $(GOFLAGS) . .PHONY: install-chainlink-cover install-chainlink-cover: operator-ui ## Install the chainlink binary with cover flag. @@ -64,6 +65,17 @@ install-medianpoc: ## Build & install the chainlink-medianpoc binary. install-ocr3-capability: ## Build & install the chainlink-ocr3-capability binary. go install $(GOFLAGS) ./plugins/cmd/chainlink-ocr3-capability +.PHONY: install-plugins +install-plugins: ## Build & install LOOPP binaries for products and chains. + cd $(shell go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-feeds) && \ + go install ./cmd/chainlink-feeds + cd $(shell go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-data-streams) && \ + go install ./mercury/cmd/chainlink-mercury + cd $(shell go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-solana) && \ + go install ./pkg/solana/cmd/chainlink-solana + cd $(shell go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-starknet/relayer) && \ + go install ./pkg/chainlink/cmd/chainlink-starknet + .PHONY: docker ## Build the chainlink docker image docker: docker buildx build \ @@ -97,7 +109,7 @@ abigen: ## Build & install abigen. .PHONY: generate generate: abigen codecgen mockery protoc gomods ## Execute all go:generate commands. gomods -w go generate -x ./... - mockery + find . -type f -name .mockery.yaml -execdir mockery \; ## Execute mockery for all .mockery.yaml files .PHONY: rm-mocked rm-mocked: @@ -145,7 +157,7 @@ gomodslocalupdate: gomods ## Run gomod-local-update .PHONY: mockery mockery: $(mockery) ## Install mockery. - go install github.com/vektra/mockery/v2@v2.46.3 + go install github.com/vektra/mockery/v2@v2.50.0 .PHONY: codecgen codecgen: $(codecgen) ## Install codecgen @@ -173,7 +185,7 @@ config-docs: ## Generate core node configuration documentation .PHONY: golangci-lint golangci-lint: ## Run golangci-lint for all issues. [ -d "./golangci-lint" ] || mkdir ./golangci-lint && \ - docker run --rm -v $(shell pwd):/app -w /app golangci/golangci-lint:v1.61.0 golangci-lint run --max-issues-per-linter 0 --max-same-issues 0 | tee ./golangci-lint/$(shell date +%Y-%m-%d_%H:%M:%S).txt + docker run --rm -v $(shell pwd):/app -w /app golangci/golangci-lint:v1.62.2 golangci-lint run --max-issues-per-linter 0 --max-same-issues 0 | tee ./golangci-lint/$(shell date +%Y-%m-%d_%H:%M:%S).txt .PHONY: modgraph modgraph: @@ -182,7 +194,7 @@ modgraph: .PHONY: test-short test-short: ## Run 'go test -short' and suppress uninteresting output - go test -short ./... | grep -v "no test files" | grep -v "\(cached\)" + go test -short ./... | grep -v "\[no test files\]" | grep -v "\(cached\)" help: @echo "" diff --git a/ccip/config/evm/Astar_Mainnet.toml b/ccip/config/evm/Astar_Mainnet.toml index 87808001eb7..5405a67d563 100644 --- a/ccip/config/evm/Astar_Mainnet.toml +++ b/ccip/config/evm/Astar_Mainnet.toml @@ -1,4 +1,5 @@ ChainID = '592' +ChainType = 'astar' FinalityTagEnabled = true FinalityDepth = 100 LogPollInterval = '6s' @@ -6,4 +7,9 @@ LogPollInterval = '6s' [GasEstimator] EIP1559DynamicFees = false PriceMax = '100000 gwei' -LimitDefault = 8000000 \ No newline at end of file +LimitDefault = 8000000 + +[HeadTracker] +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false diff --git a/ccip/config/evm/Astar_Shibuya.toml b/ccip/config/evm/Astar_Shibuya.toml index 5a5df06f6f0..cfcd7c31c75 100644 --- a/ccip/config/evm/Astar_Shibuya.toml +++ b/ccip/config/evm/Astar_Shibuya.toml @@ -6,4 +6,9 @@ LogPollInterval = '6s' [GasEstimator] EIP1559DynamicFees = false PriceMax = '100000 gwei' -LimitDefault = 8000000 \ No newline at end of file +LimitDefault = 8000000 + +[HeadTracker] +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false \ No newline at end of file diff --git a/ccip/config/evm/Avalanche_ANZ_testnet.toml b/ccip/config/evm/Avalanche_ANZ_testnet.toml index 1242e1ec06e..936a82d5092 100644 --- a/ccip/config/evm/Avalanche_ANZ_testnet.toml +++ b/ccip/config/evm/Avalanche_ANZ_testnet.toml @@ -19,4 +19,6 @@ PriceMin = '25 gwei' BlockHistorySize = 24 [HeadTracker] -PersistenceEnabled = false +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false diff --git a/ccip/config/evm/Avalanche_Fuji.toml b/ccip/config/evm/Avalanche_Fuji.toml index 91b8bf6bab8..4340b6b861d 100644 --- a/ccip/config/evm/Avalanche_Fuji.toml +++ b/ccip/config/evm/Avalanche_Fuji.toml @@ -10,13 +10,13 @@ RPCBlockQueryDelay = 2 NoNewFinalizedHeadsThreshold = '1m' [GasEstimator] -PriceDefault = '25 gwei' -PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' -PriceMin = '25 gwei' +PriceMin = '1 gwei' +PriceDefault = '1 gwei' [GasEstimator.BlockHistory] BlockHistorySize = 24 [HeadTracker] +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 FinalityTagBypass = false -PersistenceEnabled = false diff --git a/ccip/config/evm/Avalanche_Mainnet.toml b/ccip/config/evm/Avalanche_Mainnet.toml index f51af60098d..ac73a7b98fa 100644 --- a/ccip/config/evm/Avalanche_Mainnet.toml +++ b/ccip/config/evm/Avalanche_Mainnet.toml @@ -10,13 +10,14 @@ RPCBlockQueryDelay = 2 NoNewFinalizedHeadsThreshold = '1m' [GasEstimator] -PriceDefault = '25 gwei' -PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' -PriceMin = '25 gwei' +PriceMin = '1 gwei' +PriceDefault = '1 gwei' [GasEstimator.BlockHistory] # Average block time of 2s BlockHistorySize = 24 [HeadTracker] -PersistenceEnabled = false +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false diff --git a/ccip/config/evm/BOB_Mainnet.toml b/ccip/config/evm/BOB_Mainnet.toml new file mode 100644 index 00000000000..70cc2fb8ba4 --- /dev/null +++ b/ccip/config/evm/BOB_Mainnet.toml @@ -0,0 +1,28 @@ +ChainID = '60808' +# OP stack https://docs.gobob.xyz/learn/introduction/stack-overview#rollup-layer +ChainType = 'optimismBedrock' +# FinalityDepth in mainnet showed more than 3k +FinalityDepth = 3150 +# block_time was: 2s, adding 1 second buffer +LogPollInterval = '3s' + +# finality_depth * block_time / 60 secs = ~105 min (finality time) +NoNewFinalizedHeadsThreshold = '110m' + +FinalityTagEnabled = true + +[GasEstimator] +EIP1559DynamicFees = true +Mode = 'FeeHistory' + +[GasEstimator.FeeHistory] +# block_time was: 2s, per recommendation skip 1-2 blocks +CacheTimeout = '4s' + +[GasEstimator.BlockHistory] +BlockHistorySize = 100 + +[HeadTracker] +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false diff --git a/ccip/config/evm/BOB_Testnet.toml b/ccip/config/evm/BOB_Testnet.toml new file mode 100644 index 00000000000..bd8505c4e44 --- /dev/null +++ b/ccip/config/evm/BOB_Testnet.toml @@ -0,0 +1,28 @@ +ChainID = '808813' +# OP stack https://docs.gobob.xyz/learn/introduction/stack-overview#rollup-layer +ChainType = 'optimismBedrock' +# FinalityDepth in mainnet showed more than 3k +FinalityDepth = 3150 +# block_time was: 2s, adding 1 second buffer +LogPollInterval = '3s' + +# finality_depth * block_time / 60 secs = ~105 min (finality time) +NoNewFinalizedHeadsThreshold = '110m' + +FinalityTagEnabled = true + +[GasEstimator] +EIP1559DynamicFees = true +Mode = 'FeeHistory' + +[GasEstimator.FeeHistory] +# block_time was: 2s, per recommendation skip 1-2 blocks +CacheTimeout = '4s' + +[GasEstimator.BlockHistory] +BlockHistorySize = 100 + +[HeadTracker] +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false diff --git a/ccip/config/evm/BSC_Mainnet.toml b/ccip/config/evm/BSC_Mainnet.toml index 10f4c570bef..df140e63973 100644 --- a/ccip/config/evm/BSC_Mainnet.toml +++ b/ccip/config/evm/BSC_Mainnet.toml @@ -13,6 +13,8 @@ NoNewFinalizedHeadsThreshold = '45s' [GasEstimator] PriceDefault = '5 gwei' +# Set to the BSC node's default Eth.Miner.GasPrice config +PriceMin = '3 gwei' # 15s delay since feeds update every minute in volatile situations BumpThreshold = 5 @@ -26,3 +28,8 @@ ObservationGracePeriod = '500ms' [NodePool] SyncThreshold = 10 + +[HeadTracker] +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false diff --git a/ccip/config/evm/BSC_Testnet.toml b/ccip/config/evm/BSC_Testnet.toml index bb13501f1a2..9c528f816ea 100644 --- a/ccip/config/evm/BSC_Testnet.toml +++ b/ccip/config/evm/BSC_Testnet.toml @@ -22,8 +22,9 @@ BlockHistorySize = 24 [HeadTracker] HistoryDepth = 100 SamplingInterval = '1s' +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 FinalityTagBypass = false -PersistenceEnabled = false [OCR] DatabaseTimeout = '2s' diff --git a/ccip/config/evm/Base_Mainnet.toml b/ccip/config/evm/Base_Mainnet.toml index da38182b194..0f895e1bc6b 100644 --- a/ccip/config/evm/Base_Mainnet.toml +++ b/ccip/config/evm/Base_Mainnet.toml @@ -20,6 +20,9 @@ ResendAfterThreshold = '30s' [HeadTracker] HistoryDepth = 300 +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false [NodePool] SyncThreshold = 10 diff --git a/ccip/config/evm/Base_Sepolia.toml b/ccip/config/evm/Base_Sepolia.toml index 92f7717b27d..202c544fb4b 100644 --- a/ccip/config/evm/Base_Sepolia.toml +++ b/ccip/config/evm/Base_Sepolia.toml @@ -21,6 +21,9 @@ ResendAfterThreshold = '30s' [HeadTracker] HistoryDepth = 300 +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false [NodePool] SyncThreshold = 10 diff --git a/ccip/config/evm/Berachain_Testnet.toml b/ccip/config/evm/Berachain_Testnet.toml new file mode 100644 index 00000000000..9fc810e8908 --- /dev/null +++ b/ccip/config/evm/Berachain_Testnet.toml @@ -0,0 +1,24 @@ +ChainID = '80084' +# finality_depth: instant +FinalityDepth = 10 +# block_time: 5s, adding 1 second buffer +LogPollInterval = '6s' + +# finality_depth * block_time / 60 secs = ~0.8 min (finality time) +NoNewFinalizedHeadsThreshold = '5m' + +[GasEstimator] +EIP1559DynamicFees = true +Mode = 'FeeHistory' + +[GasEstimator.FeeHistory] +# block_time was: 5s, per recommendation skip 1-2 blocks +CacheTimeout = '10s' + +[GasEstimator.BlockHistory] +BlockHistorySize = 100 + +[HeadTracker] +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false diff --git a/ccip/config/evm/Bitlayer_Mainnet.toml b/ccip/config/evm/Bitlayer_Mainnet.toml new file mode 100644 index 00000000000..f6d669d4f78 --- /dev/null +++ b/ccip/config/evm/Bitlayer_Mainnet.toml @@ -0,0 +1,16 @@ +ChainID = '200901' +FinalityTagEnabled = false +FinalityDepth = 21 # confirmed with Bitlayer team and recommended by docs: https://docs.bitlayer.org/docs/Learn/BitlayerNetwork/AboutFinality/#about-finality-at-stage-bitlayer-pos-bitlayer-mainnet-v1 + +[GasEstimator] +Mode = 'FeeHistory' +EIP1559DynamicFees = false +PriceMax = '1 gwei' # DS&A recommended value +PriceMin = '40 mwei' # During testing, we saw minimum gas prices ~50 mwei +PriceDefault = '1 gwei' # As we set PriceMax to '1 gwei' and PriceDefault must be less than or equal to PriceMax +FeeCapDefault = '1 gwei' # As we set PriceMax to '1 gwei' and FeeCapDefault must be less than or equal to PriceMax + +[HeadTracker] +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false diff --git a/ccip/config/evm/Bitlayer_Testnet.toml b/ccip/config/evm/Bitlayer_Testnet.toml new file mode 100644 index 00000000000..7107527ce2f --- /dev/null +++ b/ccip/config/evm/Bitlayer_Testnet.toml @@ -0,0 +1,16 @@ +ChainID = '200810' +FinalityTagEnabled = false +FinalityDepth = 21 # confirmed with Bitlayer team and recommended by docs: https://docs.bitlayer.org/docs/Learn/BitlayerNetwork/AboutFinality/#about-finality-at-stage-bitlayer-pos-bitlayer-mainnet-v1 + +[GasEstimator] +Mode='FeeHistory' +EIP1559DynamicFees = false +PriceMax = '1 gwei' # DS&A recommended value +PriceMin = '40 mwei' # During testing, we saw minimum gas prices ~50 mwei +PriceDefault = '1 gwei' # As we set PriceMax to '1 gwei' and PriceDefault must be less than or equal to PriceMax +FeeCapDefault = '1 gwei' # As we set PriceMax to '1 gwei' and FeeCapDefault must be less than or equal to PriceMax + +[HeadTracker] +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false diff --git a/ccip/config/evm/Blast_Mainnet.toml b/ccip/config/evm/Blast_Mainnet.toml index f8b501723ff..26ecddeec54 100644 --- a/ccip/config/evm/Blast_Mainnet.toml +++ b/ccip/config/evm/Blast_Mainnet.toml @@ -26,9 +26,12 @@ EIP1559FeeCapBufferBlocks = 0 [HeadTracker] HistoryDepth = 300 +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false [NodePool] # 4 block sync time between nodes to ensure they aren't labelled unreachable too soon PollFailureThreshold = 4 # polls every 4sec to check if there is a block produced, since blockRate is ~3sec -PollInterval = '4s' \ No newline at end of file +PollInterval = '4s' diff --git a/ccip/config/evm/Blast_Sepolia.toml b/ccip/config/evm/Blast_Sepolia.toml index 96dc5c67871..55f2356ad3a 100644 --- a/ccip/config/evm/Blast_Sepolia.toml +++ b/ccip/config/evm/Blast_Sepolia.toml @@ -26,9 +26,12 @@ EIP1559FeeCapBufferBlocks = 0 [HeadTracker] HistoryDepth = 300 +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false [NodePool] # 4 block sync time between nodes to ensure they aren't labelled unreachable too soon PollFailureThreshold = 4 # polls every 4sec to check if there is a block produced, since blockRate is ~3sec -PollInterval = '4s' \ No newline at end of file +PollInterval = '4s' diff --git a/ccip/config/evm/Bsquared_Mainnet.toml b/ccip/config/evm/Bsquared_Mainnet.toml new file mode 100644 index 00000000000..61b0e5337c7 --- /dev/null +++ b/ccip/config/evm/Bsquared_Mainnet.toml @@ -0,0 +1,23 @@ +ChainID = '223' +# OP stack from questionnaire https://docs.google.com/spreadsheets/d/1l8dx1GzxEnjgwH5x3vB60FUr5iFALzPcs6W_wOAiuDs/edit?gid=625078687#gid=625078687 +ChainType = 'optimismBedrock' +# finality_depth was: ~1900 +FinalityDepth = 2000 +# block_time: ~2s, adding 1 second buffer +LogPollInterval = '3s' + +# finality_depth * block_time / 60 secs = ~66 min (finality time) +NoNewFinalizedHeadsThreshold = '70m' + +FinalityTagEnabled = true + +[GasEstimator] +EIP1559DynamicFees = true +Mode = 'FeeHistory' + +[GasEstimator.FeeHistory] +# block_time was: 2s, per recommendation skip 1-2 blocks +CacheTimeout = '4s' + +[GasEstimator.BlockHistory] +BlockHistorySize = 100 diff --git a/ccip/config/evm/Bsquared_Testnet.toml b/ccip/config/evm/Bsquared_Testnet.toml new file mode 100644 index 00000000000..b7cfd35fc41 --- /dev/null +++ b/ccip/config/evm/Bsquared_Testnet.toml @@ -0,0 +1,23 @@ +ChainID = '1123' +# OP stack from questionnaire https://docs.google.com/spreadsheets/d/1l8dx1GzxEnjgwH5x3vB60FUr5iFALzPcs6W_wOAiuDs/edit?gid=625078687#gid=625078687 +ChainType = 'optimismBedrock' +# finality_depth was: ~1900 +FinalityDepth = 2000 +# block_time: ~2s, adding 1 second buffer +LogPollInterval = '3s' + +# finality_depth * block_time / 60 secs = ~66 min (finality time) +NoNewFinalizedHeadsThreshold = '70m' + +FinalityTagEnabled = true + +[GasEstimator] +EIP1559DynamicFees = true +Mode = 'FeeHistory' + +[GasEstimator.FeeHistory] +# block_time was: 2s, per recommendation skip 1-2 blocks +CacheTimeout = '4s' + +[GasEstimator.BlockHistory] +BlockHistorySize = 100 diff --git a/ccip/config/evm/Celo_Mainnet.toml b/ccip/config/evm/Celo_Mainnet.toml index 0ed08986d32..9da7d632d0d 100644 --- a/ccip/config/evm/Celo_Mainnet.toml +++ b/ccip/config/evm/Celo_Mainnet.toml @@ -1,6 +1,10 @@ ChainID = '42220' ChainType = 'celo' +# FT and FD are both present here because the dev effort rely only on FinalityTagEnabled are still in progress. +# We expect to be able to rely only on FinalityTagEnabled=true in the short future. +# https://chainlink-core.slack.com/archives/C05CS33N08N/p1715102940763339?thread_ts=1715102478.537529&cid=C05CS33N08N FinalityDepth = 10 +FinalityTagEnabled = true LogPollInterval = '5s' MinIncomingConfirmations = 1 NoNewHeadsThreshold = '1m' @@ -18,4 +22,6 @@ BlockHistorySize = 12 [HeadTracker] HistoryDepth = 50 -PersistenceEnabled = false +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false diff --git a/ccip/config/evm/Celo_Testnet.toml b/ccip/config/evm/Celo_Testnet.toml index 0e4594150dd..c03d855acf6 100644 --- a/ccip/config/evm/Celo_Testnet.toml +++ b/ccip/config/evm/Celo_Testnet.toml @@ -1,5 +1,8 @@ ChainID = '44787' ChainType = 'celo' +# FT and FD are both present here because the dev effort rely only on FinalityTagEnabled are still in progress. +# We expect to be able to rely only on FinalityTagEnabled=true in the short future. +# https://chainlink-core.slack.com/archives/C05CS33N08N/p1715102940763339?thread_ts=1715102478.537529&cid=C05CS33N08N FinalityTagEnabled = true FinalityDepth = 2750 # mean finality time of ~37 minutes + 500 block buffer LogPollInterval = '1s' # 1 sec block rate diff --git a/ccip/config/evm/Ethereum_Mainnet.toml b/ccip/config/evm/Ethereum_Mainnet.toml index 0bcaf35c648..ec3a78156ed 100644 --- a/ccip/config/evm/Ethereum_Mainnet.toml +++ b/ccip/config/evm/Ethereum_Mainnet.toml @@ -15,3 +15,8 @@ TransactionPercentile = 50 [OCR2.Automation] GasLimit = 10500000 + +[HeadTracker] +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false diff --git a/ccip/config/evm/Ethereum_Sepolia.toml b/ccip/config/evm/Ethereum_Sepolia.toml index 24a0e68f77a..966f091f891 100644 --- a/ccip/config/evm/Ethereum_Sepolia.toml +++ b/ccip/config/evm/Ethereum_Sepolia.toml @@ -14,4 +14,6 @@ TransactionPercentile = 50 GasLimit = 10500000 [HeadTracker] +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 FinalityTagBypass = false diff --git a/ccip/config/evm/Fantom_Mainnet.toml b/ccip/config/evm/Fantom_Mainnet.toml index 7e76d94278d..2af504796e0 100644 --- a/ccip/config/evm/Fantom_Mainnet.toml +++ b/ccip/config/evm/Fantom_Mainnet.toml @@ -9,4 +9,9 @@ RPCBlockQueryDelay = 2 Mode = 'SuggestedPrice' [OCR2.Automation] -GasLimit = 3800000 \ No newline at end of file +GasLimit = 3800000 + +[HeadTracker] +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false diff --git a/ccip/config/evm/Fantom_Testnet.toml b/ccip/config/evm/Fantom_Testnet.toml index 5f24a76c2e7..b361a8d14dd 100644 --- a/ccip/config/evm/Fantom_Testnet.toml +++ b/ccip/config/evm/Fantom_Testnet.toml @@ -9,4 +9,9 @@ RPCBlockQueryDelay = 2 Mode = 'SuggestedPrice' [OCR2.Automation] -GasLimit = 3800000 \ No newline at end of file +GasLimit = 3800000 + +[HeadTracker] +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false diff --git a/ccip/config/evm/Gnosis_Chiado.toml b/ccip/config/evm/Gnosis_Chiado.toml index 379377a2266..320aa087209 100644 --- a/ccip/config/evm/Gnosis_Chiado.toml +++ b/ccip/config/evm/Gnosis_Chiado.toml @@ -8,3 +8,8 @@ NoNewFinalizedHeadsThreshold = '2m' [GasEstimator] EIP1559DynamicFees = true PriceMax = '500 gwei' + +[HeadTracker] +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false diff --git a/ccip/config/evm/Gnosis_Mainnet.toml b/ccip/config/evm/Gnosis_Mainnet.toml index 628646364f5..ec8ac227f78 100644 --- a/ccip/config/evm/Gnosis_Mainnet.toml +++ b/ccip/config/evm/Gnosis_Mainnet.toml @@ -16,3 +16,8 @@ PriceDefault = '1 gwei' PriceMax = '500 gwei' # 1 Gwei is the minimum accepted by the validators (unless whitelisted) PriceMin = '1 gwei' + +[HeadTracker] +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false diff --git a/ccip/config/evm/Harmony_Mainnet.toml b/ccip/config/evm/Harmony_Mainnet.toml new file mode 100644 index 00000000000..1cee98e77c7 --- /dev/null +++ b/ccip/config/evm/Harmony_Mainnet.toml @@ -0,0 +1,13 @@ +ChainID = '1666600000' +LinkContractAddress = '0x218532a12a389a4a92fC0C5Fb22901D1c19198aA' +LogPollInterval = '2s' +MinIncomingConfirmations = 1 +NoNewHeadsThreshold = '30s' + +[GasEstimator] +PriceDefault = '5 gwei' + +[HeadTracker] +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false diff --git a/ccip/config/evm/Harmony_Testnet.toml b/ccip/config/evm/Harmony_Testnet.toml new file mode 100644 index 00000000000..8b7c85b9c28 --- /dev/null +++ b/ccip/config/evm/Harmony_Testnet.toml @@ -0,0 +1,13 @@ +ChainID = '1666700000' +LinkContractAddress = '0x8b12Ac23BFe11cAb03a634C1F117D64a7f2cFD3e' +LogPollInterval = '2s' +MinIncomingConfirmations = 1 +NoNewHeadsThreshold = '30s' + +[GasEstimator] +PriceDefault = '5 gwei' + +[HeadTracker] +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false diff --git a/ccip/config/evm/Hashkey_Mainnet.toml b/ccip/config/evm/Hashkey_Mainnet.toml new file mode 100644 index 00000000000..69450c96f80 --- /dev/null +++ b/ccip/config/evm/Hashkey_Mainnet.toml @@ -0,0 +1,16 @@ +ChainID = '177' +ChainType = 'optimismBedrock' +FinalityTagEnabled = true + +[GasEstimator] +PriceMax = '1000 gwei' +LimitDefault = 8000000 +FeeCapDefault = '1000 gwei' + +[NodePool] +PollFailureThreshold = 2 +PollInterval = '8s' + +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x420000000000000000000000000000000000000F' \ No newline at end of file diff --git a/ccip/config/evm/Hashkey_Testnet.toml b/ccip/config/evm/Hashkey_Testnet.toml new file mode 100644 index 00000000000..c342e503a33 --- /dev/null +++ b/ccip/config/evm/Hashkey_Testnet.toml @@ -0,0 +1,16 @@ +ChainID = '133' +ChainType = 'optimismBedrock' +FinalityTagEnabled = true + +[GasEstimator] +PriceMax = '1000 gwei' +LimitDefault = 8000000 +FeeCapDefault = '1000 gwei' + +[NodePool] +PollFailureThreshold = 2 +PollInterval = '8s' + +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x420000000000000000000000000000000000000F' \ No newline at end of file diff --git a/ccip/config/evm/Heco_Mainnet.toml b/ccip/config/evm/Heco_Mainnet.toml new file mode 100644 index 00000000000..a39e405be31 --- /dev/null +++ b/ccip/config/evm/Heco_Mainnet.toml @@ -0,0 +1,26 @@ +# Heco uses BSC's settings. +ChainID = '128' +LinkContractAddress = '0x404460C6A5EdE2D891e8297795264fDe62ADBB75' +LogPollInterval = '3s' +NoNewHeadsThreshold = '30s' +RPCBlockQueryDelay = 2 + +[GasEstimator] +PriceDefault = '5 gwei' +BumpThreshold = 5 + +[GasEstimator.BlockHistory] +BlockHistorySize = 24 + +[OCR] +DatabaseTimeout = '2s' +ContractTransmitterTransmitTimeout = '2s' +ObservationGracePeriod = '500ms' + +[NodePool] +SyncThreshold = 10 + +[HeadTracker] +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false diff --git a/ccip/config/evm/Hedera_Mainnet.toml b/ccip/config/evm/Hedera_Mainnet.toml new file mode 100644 index 00000000000..fdd6528e0a4 --- /dev/null +++ b/ccip/config/evm/Hedera_Mainnet.toml @@ -0,0 +1,35 @@ +ChainID = '295' +ChainType = 'hedera' +# Considering the 3-5 (6 including a buffer) seconds of finality and 2 seconds block production +# We set the depth to 6/2 = 3 blocks, setting to 10 for safety +FinalityDepth = 10 +# Hedera has high TPS, so polling less often +LogPollInterval = '10s' +MinIncomingConfirmations = 1 + +[BalanceMonitor] +Enabled = true + +[GasEstimator] +Mode = 'SuggestedPrice' +# Since Hedera dont have mempool and there's no way for a node to front run or a user to bribe a node to submit the transaction earlier than it's consensus timestamp, +# But they have automated congesting pricing throttling which would mean at high sustained level the gasPrice itself could be increased to prevent malicious behaviour. +# Disabling the Bumpthreshold as TXM now implicity handles the bumping after checking on-chain nonce & re-broadcast for Hedera chain type +BumpThreshold = 0 +BumpMin = '10 gwei' +BumpPercent = 20 + +[Transactions] +# To hit throttling you'd need to maintain 15 m gas /sec over a prolonged period of time. +# Because Hedera's block times are every 2 secs it's less less likely to happen as compared to other chains +# Setting this to little higher even though Hedera has High TPS, We have seen 10-12s to get the trasaction mined & 20-25s incase of failures +# Accounting for Node syncs & avoid re-sending txns before fetching the receipt, setting to 2m +ResendAfterThreshold = '2m' + +[NodePool] +SyncThreshold = 10 + +[HeadTracker] +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false diff --git a/ccip/config/evm/Hedera_Testnet.toml b/ccip/config/evm/Hedera_Testnet.toml new file mode 100644 index 00000000000..7e9ec3fe2c6 --- /dev/null +++ b/ccip/config/evm/Hedera_Testnet.toml @@ -0,0 +1,35 @@ +ChainID = '296' +ChainType = 'hedera' +# Considering the 3-5 (6 including a buffer) seconds of finality and 2 seconds block production +# We set the depth to 6/2 = 3 blocks, setting to 10 for safety +FinalityDepth = 10 +# Hedera has high TPS, so polling less often +LogPollInterval = '10s' +MinIncomingConfirmations = 1 + +[BalanceMonitor] +Enabled = true + +[GasEstimator] +Mode = 'SuggestedPrice' +# Since Hedera dont have mempool and there's no way for a node to front run or a user to bribe a node to submit the transaction earlier than it's consensus timestamp, +# But they have automated congesting pricing throttling which would mean at high sustained level the gasPrice itself could be increased to prevent malicious behaviour. +# Disabling the Bumpthreshold as TXM now implicity handles the bumping after checking on-chain nonce & re-broadcast for Hedera chain type +BumpThreshold = 0 +BumpMin = '10 gwei' +BumpPercent = 20 + +[Transactions] +# To hit throttling you'd need to maintain 15 m gas /sec over a prolonged period of time. +# Because Hedera's block times are every 2 secs it's less less likely to happen as compared to other chains +# Setting this to little higher even though Hedera has High TPS, We have seen 10-12s to get the trasaction mined & 20-25s incase of failures +# Accounting for Node syncs & avoid re-sending txns before fetching the receipt, setting to 2m +ResendAfterThreshold = '2m' + +[NodePool] +SyncThreshold = 10 + +[HeadTracker] +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false diff --git a/ccip/config/evm/Klaytn_Mainnet.toml b/ccip/config/evm/Klaytn_Mainnet.toml new file mode 100644 index 00000000000..ff8b97de970 --- /dev/null +++ b/ccip/config/evm/Klaytn_Mainnet.toml @@ -0,0 +1,15 @@ +ChainID = '8217' +FinalityDepth = 10 +MinIncomingConfirmations = 1 +NoNewHeadsThreshold = '30s' +OCR.ContractConfirmations = 1 + +[GasEstimator] +Mode = 'SuggestedPrice' +PriceDefault = '750 gwei' # gwei = ston +BumpThreshold = 5 + +[HeadTracker] +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false diff --git a/ccip/config/evm/Klaytn_Testnet.toml b/ccip/config/evm/Klaytn_Testnet.toml new file mode 100644 index 00000000000..599b604f086 --- /dev/null +++ b/ccip/config/evm/Klaytn_Testnet.toml @@ -0,0 +1,15 @@ +ChainID = '1001' +FinalityDepth = 10 +MinIncomingConfirmations = 1 +NoNewHeadsThreshold = '30s' +OCR.ContractConfirmations = 1 + +[GasEstimator] +Mode = 'SuggestedPrice' +PriceDefault = '750 gwei' # gwei = ston +BumpThreshold = 5 + +[HeadTracker] +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false diff --git a/ccip/config/evm/Kroma_Mainnet.toml b/ccip/config/evm/Kroma_Mainnet.toml index 3a48aa8ae1b..21bbe7c357c 100644 --- a/ccip/config/evm/Kroma_Mainnet.toml +++ b/ccip/config/evm/Kroma_Mainnet.toml @@ -1,6 +1,9 @@ ChainID = '255' ChainType = 'kroma' # Kroma is based on the Optimism Bedrock architechture -FinalityDepth = 400 +# FT and FD are both present here because the dev effort rely only on FinalityTagEnabled are still in progress. +# We expect to be able to rely only on FinalityTagEnabled=true in the short future. +# https://chainlink-core.slack.com/archives/C05CS33N08N/p1715102940763339?thread_ts=1715102478.537529&cid=C05CS33N08N +FinalityDepth = 700 FinalityTagEnabled = true LogPollInterval = '2s' NoNewHeadsThreshold = '40s' @@ -19,6 +22,9 @@ ResendAfterThreshold = '30s' [HeadTracker] HistoryDepth = 400 +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false [NodePool] SyncThreshold = 10 diff --git a/ccip/config/evm/Kroma_Sepolia.toml b/ccip/config/evm/Kroma_Sepolia.toml index 9609a09e076..120737df47b 100644 --- a/ccip/config/evm/Kroma_Sepolia.toml +++ b/ccip/config/evm/Kroma_Sepolia.toml @@ -1,6 +1,9 @@ ChainID = '2358' ChainType = 'kroma' # Kroma is based on the Optimism Bedrock architechture -FinalityDepth = 400 +# FT and FD are both present here because the dev effort rely only on FinalityTagEnabled are still in progress. +# We expect to be able to rely only on FinalityTagEnabled=true in the short future. +# https://chainlink-core.slack.com/archives/C05CS33N08N/p1715102940763339?thread_ts=1715102478.537529&cid=C05CS33N08N +FinalityDepth = 700 FinalityTagEnabled = true LogPollInterval = '2s' NoNewHeadsThreshold = '40s' @@ -19,6 +22,9 @@ ResendAfterThreshold = '30s' [HeadTracker] HistoryDepth = 400 +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false [NodePool] SyncThreshold = 10 diff --git a/ccip/config/evm/L3X_Mainnet.toml b/ccip/config/evm/L3X_Mainnet.toml index 9dd33c9e15d..5f14e5e8e8c 100644 --- a/ccip/config/evm/L3X_Mainnet.toml +++ b/ccip/config/evm/L3X_Mainnet.toml @@ -17,5 +17,7 @@ PriceDefault = '0.1 gwei' FeeCapDefault = '1000 gwei' BumpThreshold = 5 -[GasEstimator.DAOracle] -OracleType = 'arbitrum' +[HeadTracker] +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false diff --git a/ccip/config/evm/L3X_Sepolia.toml b/ccip/config/evm/L3X_Sepolia.toml index c0f6a60e943..ca21bc13d6e 100644 --- a/ccip/config/evm/L3X_Sepolia.toml +++ b/ccip/config/evm/L3X_Sepolia.toml @@ -17,5 +17,7 @@ PriceDefault = '0.1 gwei' FeeCapDefault = '1000 gwei' BumpThreshold = 5 -[GasEstimator.DAOracle] -OracleType = 'arbitrum' +[HeadTracker] +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false diff --git a/ccip/config/evm/Linea_Goerli.toml b/ccip/config/evm/Linea_Goerli.toml new file mode 100644 index 00000000000..2c85f9cbc02 --- /dev/null +++ b/ccip/config/evm/Linea_Goerli.toml @@ -0,0 +1,17 @@ +ChainID = '59140' +# Block time 12s, finality < 3m +FinalityDepth = 15 +# Blocks are only emitted when a transaction happens / no empty blocks +NoNewHeadsThreshold = '0' + +[GasEstimator] +BumpPercent = 40 + +[Transactions] +# increase resend time to align with finality +ResendAfterThreshold = '3m' + +[HeadTracker] +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false diff --git a/ccip/config/evm/Linea_Mainnet.toml b/ccip/config/evm/Linea_Mainnet.toml index 5a89873acae..6614fef9d4e 100644 --- a/ccip/config/evm/Linea_Mainnet.toml +++ b/ccip/config/evm/Linea_Mainnet.toml @@ -1,6 +1,6 @@ ChainID = '59144' -# Block time 12s, finality < 60m -FinalityDepth = 300 +#3s block time ~ 20m finality based on committee decision +FinalityDepth = 600 # Blocks are only emitted when a transaction happens / no empty blocks NoNewHeadsThreshold = '0' @@ -15,6 +15,9 @@ ResendAfterThreshold = '3m' # set greater than finality depth [HeadTracker] HistoryDepth = 350 +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false [Transactions.AutoPurge] Enabled = true diff --git a/ccip/config/evm/Linea_Sepolia.toml b/ccip/config/evm/Linea_Sepolia.toml index 8f168ee93a6..2837c7ca601 100644 --- a/ccip/config/evm/Linea_Sepolia.toml +++ b/ccip/config/evm/Linea_Sepolia.toml @@ -1,5 +1,5 @@ ChainID = '59141' -FinalityDepth = 900 +FinalityDepth = 200 NoNewHeadsThreshold = '0' [GasEstimator] @@ -11,6 +11,9 @@ ResendAfterThreshold = '3m' [HeadTracker] HistoryDepth = 1000 +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false [Transactions.AutoPurge] Enabled = true diff --git a/ccip/config/evm/Mantle_Mainnet.toml b/ccip/config/evm/Mantle_Mainnet.toml new file mode 100644 index 00000000000..23d5168a7e9 --- /dev/null +++ b/ccip/config/evm/Mantle_Mainnet.toml @@ -0,0 +1,33 @@ +ChainID = '5000' +FinalityTagEnabled = true +FinalityDepth = 1200 +ChainType = 'optimismBedrock' +LogPollInterval = '2s' +MinIncomingConfirmations = 1 +NoNewFinalizedHeadsThreshold = '40m0s' + +[HeadTracker] +HistoryDepth = 1250 + +[GasEstimator] +PriceMax = '120 gwei' +# Limit values are high as Mantle's GasPrice is in native token (MNT) instead of ETH. Their proprietary TokenRatio parameter is used to adjust fees +LimitDefault = 80_000_000_000 +LimitMax = 100_000_000_000 +BumpMin = '100 wei' +BumpThreshold = 60 +EIP1559DynamicFees = true +FeeCapDefault = '120 gwei' +# Mantle recommends setting Priority Fee to 0 in their docs linked here: https://docs-v2.mantle.xyz/devs/concepts/tx-fee/eip-1559#application-of-eip-1559-in-mantle-v2-tectonic +TipCapDefault = '0 wei' +TipCapMin = '0 wei' + +[GasEstimator.BlockHistory] +# Default is 24, which leads to bumpy gas prices. In CCIP +# we want to smooth out the gas prices, so we increase the sample size. +BlockHistorySize = 200 +# The formula for FeeCap is (current block base fee * (1.125 ^ EIP1559FeeCapBufferBlocks) + tipcap) +# where tipcap is managed by the block history estimators. In the context of CCIP, +# the gas price is relayed to other changes for quotes so we want accurate/avg not pessimistic values. +# So we set this to zero so FeeCap = baseFee + tipcap. +EIP1559FeeCapBufferBlocks = 0 \ No newline at end of file diff --git a/ccip/config/evm/Mantle_Sepolia.toml b/ccip/config/evm/Mantle_Sepolia.toml index ee994a71826..705f91142f2 100644 --- a/ccip/config/evm/Mantle_Sepolia.toml +++ b/ccip/config/evm/Mantle_Sepolia.toml @@ -1,19 +1,34 @@ ChainID = '5003' +FinalityTagEnabled = true +FinalityDepth = 1200 ChainType = 'optimismBedrock' -FinalityDepth = 500 LogPollInterval = '2s' -NoNewHeadsThreshold = '0' MinIncomingConfirmations = 1 +NoNewFinalizedHeadsThreshold = '60m0s' [HeadTracker] -HistoryDepth = 600 +HistoryDepth = 1250 -[GasEstimator] -Mode = 'L2Suggested' -PriceMax = '200 gwei' -LimitDefault = 100000000 -FeeCapDefault = '200 gwei' +[GasEstimator] +PriceMax = '120 gwei' +# Limit values are high as Mantle's GasPrice is in native token (MNT) instead of ETH. Their proprietary TokenRatio parameter is used to adjust fees +LimitDefault = 80000000000 +LimitMax = 100000000000 +BumpMin = '100 wei' +BumpPercent = 20 +BumpThreshold = 60 +EIP1559DynamicFees = true +FeeCapDefault = '120 gwei' +# Mantle reccomends setting Priority Fee to 0 in their docs linked here: https://docs-v2.mantle.xyz/devs/concepts/tx-fee/eip-1559#application-of-eip-1559-in-mantle-v2-tectonic +TipCapDefault = '0 wei' +TipCapMin = '0 wei' [GasEstimator.BlockHistory] +# Default is 24, which leads to bumpy gas prices. In CCIP +# we want to smooth out the gas prices, so we increase the sample size. BlockHistorySize = 200 +# The formula for FeeCap is (current block base fee * (1.125 ^ EIP1559FeeCapBufferBlocks) + tipcap) +# where tipcap is managed by the block history estimators. In the context of CCIP, +# the gas price is relayed to other changes for quotes so we want accurate/avg not pessimistic values. +# So we set this to zero so FeeCap = baseFee + tipcap. EIP1559FeeCapBufferBlocks = 0 \ No newline at end of file diff --git a/ccip/config/evm/Metis_Mainnet.toml b/ccip/config/evm/Metis_Mainnet.toml index f057400d014..a95945e9f1b 100644 --- a/ccip/config/evm/Metis_Mainnet.toml +++ b/ccip/config/evm/Metis_Mainnet.toml @@ -1,8 +1,14 @@ # Metis is an L2 chain based on Optimism. ChainID = '1088' -ChainType = 'metis' +ChainType = 'optimismBedrock' # Sequencer offers absolute finality -FinalityDepth = 10 +# High variation on finality depth triggered a commitee to investigate +# and set 500 as a secure finality depth. +# https://chainlink-core.slack.com/archives/C0725LNLJLA/p1717118469587219 +FinalityDepth = 500 +# FT and FD are both present here because the dev effort rely only on FinalityTagEnabled are still in progress. +# We expect to be able to rely only on FinalityTagEnabled=true in the short future. +# https://chainlink-core.slack.com/archives/C05CS33N08N/p1715102940763339?thread_ts=1715102478.537529&cid=C05CS33N08N FinalityTagEnabled = true MinIncomingConfirmations = 1 NoNewHeadsThreshold = '0' @@ -19,3 +25,8 @@ BlockHistorySize = 0 [NodePool] SyncThreshold = 10 + +[HeadTracker] +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false diff --git a/ccip/config/evm/Metis_Sepolia.toml b/ccip/config/evm/Metis_Sepolia.toml index 4ff4056c75d..65247991d31 100644 --- a/ccip/config/evm/Metis_Sepolia.toml +++ b/ccip/config/evm/Metis_Sepolia.toml @@ -1,6 +1,9 @@ ChainID = '59902' ChainType = 'optimismBedrock' -FinalityDepth = 10 +# FT and FD are both present here because the dev effort rely only on FinalityTagEnabled are still in progress. +# We expect to be able to rely only on FinalityTagEnabled=true in the short future. +# https://chainlink-core.slack.com/archives/C05CS33N08N/p1715102940763339?thread_ts=1715102478.537529&cid=C05CS33N08N +FinalityDepth = 3000 FinalityTagEnabled = true MinIncomingConfirmations = 1 NoNewHeadsThreshold = '0' diff --git a/ccip/config/evm/Mode_Mainnet.toml b/ccip/config/evm/Mode_Mainnet.toml index 69a8e93fecd..b586cdacc78 100644 --- a/ccip/config/evm/Mode_Mainnet.toml +++ b/ccip/config/evm/Mode_Mainnet.toml @@ -24,6 +24,9 @@ EIP1559FeeCapBufferBlocks = 0 [HeadTracker] HistoryDepth = 300 +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false [NodePool] PollFailureThreshold = 2 diff --git a/ccip/config/evm/Mode_Sepolia.toml b/ccip/config/evm/Mode_Sepolia.toml index f7398869beb..d621010b4ef 100644 --- a/ccip/config/evm/Mode_Sepolia.toml +++ b/ccip/config/evm/Mode_Sepolia.toml @@ -24,6 +24,9 @@ EIP1559FeeCapBufferBlocks = 0 [HeadTracker] HistoryDepth = 300 +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false [NodePool] PollFailureThreshold = 2 diff --git a/ccip/config/evm/Optimism_Mainnet.toml b/ccip/config/evm/Optimism_Mainnet.toml index b0f56a49d90..e1398775495 100644 --- a/ccip/config/evm/Optimism_Mainnet.toml +++ b/ccip/config/evm/Optimism_Mainnet.toml @@ -21,6 +21,9 @@ ResendAfterThreshold = '30s' [HeadTracker] HistoryDepth = 300 +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false [NodePool] SyncThreshold = 10 diff --git a/ccip/config/evm/Optimism_Sepolia.toml b/ccip/config/evm/Optimism_Sepolia.toml index 1c71aa5dd83..2590feec51a 100644 --- a/ccip/config/evm/Optimism_Sepolia.toml +++ b/ccip/config/evm/Optimism_Sepolia.toml @@ -20,6 +20,9 @@ ResendAfterThreshold = '30s' [HeadTracker] HistoryDepth = 300 +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false [NodePool] SyncThreshold = 10 diff --git a/ccip/config/evm/Polygon_Amoy.toml b/ccip/config/evm/Polygon_Amoy.toml index b05b3053a8e..eb75eab271b 100644 --- a/ccip/config/evm/Polygon_Amoy.toml +++ b/ccip/config/evm/Polygon_Amoy.toml @@ -11,10 +11,10 @@ NoNewFinalizedHeadsThreshold = '12m' MaxQueued = 5000 [GasEstimator] -EIP1559DynamicFees = true -PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' PriceDefault = '25 gwei' +PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' PriceMin = '25 gwei' +EIP1559DynamicFees = true BumpMin = '20 gwei' BumpThreshold = 5 @@ -23,6 +23,9 @@ BlockHistorySize = 24 [HeadTracker] HistoryDepth = 2000 +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false [NodePool] SyncThreshold = 10 diff --git a/ccip/config/evm/Polygon_Mainnet.toml b/ccip/config/evm/Polygon_Mainnet.toml index bf605cab3c6..555dbfff815 100644 --- a/ccip/config/evm/Polygon_Mainnet.toml +++ b/ccip/config/evm/Polygon_Mainnet.toml @@ -33,6 +33,9 @@ BlockHistorySize = 24 [HeadTracker] # Polygon suffers from a tremendous number of re-orgs, we need to set this to something very large to be conservative enough HistoryDepth = 2000 +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false [NodePool] SyncThreshold = 10 diff --git a/ccip/config/evm/Polygon_Mumbai.toml b/ccip/config/evm/Polygon_Mumbai.toml new file mode 100644 index 00000000000..83f275a0643 --- /dev/null +++ b/ccip/config/evm/Polygon_Mumbai.toml @@ -0,0 +1,31 @@ +ChainID = '80001' +FinalityDepth = 500 +FinalityTagEnabled = true +LinkContractAddress = '0x326C977E6efc84E512bB9C30f76E30c160eD06FB' +LogPollInterval = '1s' +MinIncomingConfirmations = 5 +NoNewHeadsThreshold = '30s' +RPCBlockQueryDelay = 10 +RPCDefaultBatchSize = 100 + +[Transactions] +MaxQueued = 5000 + +[GasEstimator] +PriceDefault = '25 gwei' +PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' +PriceMin = '25 gwei' +BumpMin = '20 gwei' +BumpThreshold = 5 + +[GasEstimator.BlockHistory] +BlockHistorySize = 24 + +[HeadTracker] +HistoryDepth = 2000 +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false + +[NodePool] +SyncThreshold = 10 diff --git a/ccip/config/evm/Polygon_Zkevm_Cardona.toml b/ccip/config/evm/Polygon_Zkevm_Cardona.toml index 5e4861f9d44..146c23a8024 100644 --- a/ccip/config/evm/Polygon_Zkevm_Cardona.toml +++ b/ccip/config/evm/Polygon_Zkevm_Cardona.toml @@ -13,15 +13,20 @@ ContractConfirmations = 1 ResendAfterThreshold = '3m' [GasEstimator] -PriceMin = '1 mwei' +Mode = 'FeeHistory' +# The FeeHistory estimator does not enforce PriceMin, setting it to 0 to not place any limits on the price +PriceMin = '0' BumpPercent = 40 -BumpMin = '20 mwei' -[GasEstimator.BlockHistory] -BlockHistorySize = 12 +[GasEstimator.FeeHistory] +# Refresh the suggested price every 4 seconds, to stay slightly below their polling rate of 5s +CacheTimeout = '4s' [HeadTracker] HistoryDepth = 2000 +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false [Transactions.AutoPurge] Enabled = true diff --git a/ccip/config/evm/Polygon_Zkevm_Mainnet.toml b/ccip/config/evm/Polygon_Zkevm_Mainnet.toml index b38a483ff35..d42ef9b057e 100644 --- a/ccip/config/evm/Polygon_Zkevm_Mainnet.toml +++ b/ccip/config/evm/Polygon_Zkevm_Mainnet.toml @@ -1,6 +1,6 @@ ChainID = '1101' ChainType = 'zkevm' -FinalityDepth = 500 +FinalityDepth = 1000 NoNewHeadsThreshold = '6m' MinIncomingConfirmations = 1 LogPollInterval = '30s' @@ -14,12 +14,14 @@ ContractConfirmations = 1 ResendAfterThreshold = '3m' [GasEstimator] -PriceMin = '100 mwei' +Mode = 'FeeHistory' +# The FeeHistory estimator does not enforce PriceMin, setting it to 0 to not place any limits on the price +PriceMin = '0' BumpPercent = 40 -BumpMin = '100 mwei' -[GasEstimator.BlockHistory] -BlockHistorySize = 12 +[GasEstimator.FeeHistory] +# Refresh the suggested price every 4 seconds, to stay slightly below their polling rate of 5s +CacheTimeout = '4s' [HeadTracker] # Polygon suffers from a tremendous number of re-orgs, we need to set this to something very large to be conservative enough diff --git a/ccip/config/evm/RSK_Mainnet.toml b/ccip/config/evm/RSK_Mainnet.toml new file mode 100644 index 00000000000..8290481a331 --- /dev/null +++ b/ccip/config/evm/RSK_Mainnet.toml @@ -0,0 +1,13 @@ +# RSK prices its txes in sats not wei +ChainID = '30' +LinkContractAddress = '0x14AdaE34beF7ca957Ce2dDe5ADD97ea050123827' +LogPollInterval = '30s' +MinContractPayment = '0.001 link' + +[GasEstimator] +# It's about 100 times more expensive than Wei, very roughly speaking +PriceDefault = '50 mwei' +PriceMax = '50 gwei' +PriceMin = '0' +# rsk does not yet support EIP-1559 but this allows validation to pass +FeeCapDefault = '100 mwei' diff --git a/ccip/config/evm/RSK_Testnet.toml b/ccip/config/evm/RSK_Testnet.toml new file mode 100644 index 00000000000..2fde16aa7cc --- /dev/null +++ b/ccip/config/evm/RSK_Testnet.toml @@ -0,0 +1,10 @@ +ChainID = '31' +LinkContractAddress = '0x8bBbd80981FE76d44854D8DF305e8985c19f0e78' +MinContractPayment = '0.001 link' +LogPollInterval = '30s' + +[GasEstimator] +PriceDefault = '50 mwei' +PriceMax = '50 gwei' +PriceMin = '0' +FeeCapDefault = '100 mwei' diff --git a/ccip/config/evm/Ronin_Mainnet.toml b/ccip/config/evm/Ronin_Mainnet.toml new file mode 100644 index 00000000000..14bb9d1e258 --- /dev/null +++ b/ccip/config/evm/Ronin_Mainnet.toml @@ -0,0 +1,16 @@ +ChainID = "2020" +FinalityTagEnabled = true +LinkContractAddress = "0x3902228D6A3d2Dc44731fD9d45FeE6a61c722D0b" +# Ronin produces blocks every 3 seconds +LogPollInterval = "3s" +NoNewHeadsThreshold = "3m" + +[GasEstimator] +# Ronin uses default gas price of 20 gwei https://docs.skymavis.com/mavis/mpc/guides/estimate-gas#overview +Mode = 'FeeHistory' +PriceMax = "1000 gwei" + +[HeadTracker] +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false diff --git a/ccip/config/evm/Ronin_Saigon.toml b/ccip/config/evm/Ronin_Saigon.toml new file mode 100644 index 00000000000..b775f8f0626 --- /dev/null +++ b/ccip/config/evm/Ronin_Saigon.toml @@ -0,0 +1,16 @@ +ChainID = "2021" +FinalityTagEnabled = true +LinkContractAddress = "0x5bB50A6888ee6a67E22afFDFD9513be7740F1c15" +# Ronin produces blocks every 3 seconds +LogPollInterval = "3s" +NoNewHeadsThreshold = "3m" + +[GasEstimator] +# Ronin uses default gas price of 20 gwei https://docs.skymavis.com/mavis/mpc/guides/estimate-gas#overview +Mode = 'FeeHistory' +PriceMax = "1000 gwei" + +[HeadTracker] +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false diff --git a/ccip/config/evm/Scroll_Mainnet.toml b/ccip/config/evm/Scroll_Mainnet.toml index b8e7bd09e80..f0449ef12be 100644 --- a/ccip/config/evm/Scroll_Mainnet.toml +++ b/ccip/config/evm/Scroll_Mainnet.toml @@ -17,6 +17,9 @@ BlockHistorySize = 24 [HeadTracker] HistoryDepth = 50 +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false [OCR] ContractConfirmations = 1 diff --git a/ccip/config/evm/Scroll_Sepolia.toml b/ccip/config/evm/Scroll_Sepolia.toml index baee2080d96..aca06ae18d3 100644 --- a/ccip/config/evm/Scroll_Sepolia.toml +++ b/ccip/config/evm/Scroll_Sepolia.toml @@ -17,6 +17,9 @@ BlockHistorySize = 24 [HeadTracker] HistoryDepth = 50 +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false [OCR] ContractConfirmations = 1 diff --git a/ccip/config/evm/Sei_Mainnet.toml b/ccip/config/evm/Sei_Mainnet.toml new file mode 100644 index 00000000000..23977756ac1 --- /dev/null +++ b/ccip/config/evm/Sei_Mainnet.toml @@ -0,0 +1,18 @@ +ChainID = '1329' +ChainType = 'sei' +# finality_depth: instant +FinalityDepth = 10 +# block_time: ~0.4s, adding 1 second buffer +LogPollInterval = '2s' +# finality_depth * block_time / 60 secs = ~0.8 min (finality time) +NoNewFinalizedHeadsThreshold = '5m' +# "RPC node returned multiple missing blocks on query for block numbers [31592085 31592084] even though the WS subscription already sent us these blocks. It might help to increase EVM.RPCBlockQueryDelay (currently 1)" +RPCBlockQueryDelay = 5 + +[GasEstimator] +EIP1559DynamicFees = false +Mode = 'BlockHistory' +PriceMax = '3000 gwei' # recommended by ds&a + +[GasEstimator.BlockHistory] +BlockHistorySize = 200 diff --git a/ccip/config/evm/Sei_Testnet_Atlantic.toml b/ccip/config/evm/Sei_Testnet_Atlantic.toml new file mode 100644 index 00000000000..f8c23d95c54 --- /dev/null +++ b/ccip/config/evm/Sei_Testnet_Atlantic.toml @@ -0,0 +1,18 @@ +ChainID = '1328' +ChainType = 'sei' +# finality_depth: instant +FinalityDepth = 10 +# block_time: ~0.4s, adding 1 second buffer +LogPollInterval = '2s' +# finality_depth * block_time / 60 secs = ~0.8 min (finality time) +NoNewFinalizedHeadsThreshold = '5m' +# "RPC node returned multiple missing blocks on query for block numbers [31592085 31592084] even though the WS subscription already sent us these blocks. It might help to increase EVM.RPCBlockQueryDelay (currently 1)" +RPCBlockQueryDelay = 5 + +[GasEstimator] +EIP1559DynamicFees = false +Mode = 'BlockHistory' +PriceMax = '3000 gwei' # recommended by ds&a + +[GasEstimator.BlockHistory] +BlockHistorySize = 200 diff --git a/ccip/config/evm/Simulated.toml b/ccip/config/evm/Simulated.toml index e21dc0990f0..4ec8d962b21 100644 --- a/ccip/config/evm/Simulated.toml +++ b/ccip/config/evm/Simulated.toml @@ -1,5 +1,5 @@ ChainID = '1337' -FinalityDepth = 1 +FinalityDepth = 10 MinIncomingConfirmations = 1 MinContractPayment = '100' NoNewHeadsThreshold = '0s' @@ -19,7 +19,9 @@ PriceMax = '100 micro' HistoryDepth = 10 MaxBufferSize = 100 SamplingInterval = '0s' -PersistenceEnabled = false +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false [OCR] ContractConfirmations = 1 diff --git a/ccip/config/evm/Soneium_Sepolia.toml b/ccip/config/evm/Soneium_Sepolia.toml new file mode 100755 index 00000000000..e0ea59ca22f --- /dev/null +++ b/ccip/config/evm/Soneium_Sepolia.toml @@ -0,0 +1,35 @@ +ChainID = '1946' +ChainType = 'optimismBedrock' +LinkContractAddress = '0x7ea13478Ea3961A0e8b538cb05a9DF0477c79Cd2' +FinalityDepth = 200 +LogPollInterval = '2s' +NoNewHeadsThreshold = '40s' +MinIncomingConfirmations = 1 +NoNewFinalizedHeadsThreshold = '120m' # Soneium can take upto 2Hours to finalize +FinalityTagEnabled = true + +[GasEstimator] +EIP1559DynamicFees = true +PriceMin = '1 wei' +BumpMin = '1 mwei' + +[GasEstimator.BlockHistory] +BlockHistorySize = 60 + +[Transactions] +ResendAfterThreshold = '30s' + +[HeadTracker] +HistoryDepth = 300 +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false + +[NodePool] +SyncThreshold = 10 + +[OCR] +ContractConfirmations = 1 + +[OCR2.Automation] +GasLimit = 6500000 diff --git a/ccip/config/evm/Sonic_Mainnet.toml b/ccip/config/evm/Sonic_Mainnet.toml new file mode 100644 index 00000000000..523a931c8d6 --- /dev/null +++ b/ccip/config/evm/Sonic_Mainnet.toml @@ -0,0 +1,28 @@ +ChainId = '146' +FinalityDepth = 10 +FinalityTagEnabled = false +LogPollInterval = "1s" #1s block rate +MinIncomingConfirmations = 5 +RPCBlockQueryDelay = 10 +RPCDefaultBatchSize = 100 + +[GasEstimator] +Mode = 'FeeHistory' +EIP1559DynamicFees = true +BumpPercent = 10 +LimitDefault = 8000000 # default ccip value + +[GasEstimator.FeeHistory] +CacheTimeout = '2s' + +[GasEstimator.BlockHistory] +BlockHistorySize = 100 + +[HeadTracker] +HistoryDepth = 50 + +[NodePool] +SyncThreshold = 10 + +[Transactions] +MaxQueued = 500 \ No newline at end of file diff --git a/ccip/config/evm/Sonic_Testnet.toml b/ccip/config/evm/Sonic_Testnet.toml new file mode 100644 index 00000000000..ca3ccf8f718 --- /dev/null +++ b/ccip/config/evm/Sonic_Testnet.toml @@ -0,0 +1,28 @@ +ChainId = '57054' +FinalityDepth = 10 +FinalityTagEnabled = false +LogPollInterval = "1s" #1s block rate +MinIncomingConfirmations = 5 +RPCBlockQueryDelay = 10 +RPCDefaultBatchSize = 100 + +[GasEstimator] +Mode = 'FeeHistory' +EIP1559DynamicFees = true +BumpPercent = 10 +LimitDefault = 8000000 # default ccip value + +[GasEstimator.FeeHistory] +CacheTimeout = '2s' + +[GasEstimator.BlockHistory] +BlockHistorySize = 100 + +[HeadTracker] +HistoryDepth = 50 + +[NodePool] +SyncThreshold = 10 + +[Transactions] +MaxQueued = 500 \ No newline at end of file diff --git a/ccip/config/evm/Unichain_Testnet.toml b/ccip/config/evm/Unichain_Testnet.toml new file mode 100644 index 00000000000..5e18f0d4716 --- /dev/null +++ b/ccip/config/evm/Unichain_Testnet.toml @@ -0,0 +1,26 @@ +ChainID = '1301' +# OP stack: https://docs.unichain.org/docs/getting-started/set-up-a-node#overview +ChainType = 'optimismBedrock' +# finality_depth was: ~1900 +FinalityDepth = 2000 +# block_time was: ~1s, adding 1 second buffer +LogPollInterval = '2s' + +# batching_size_finalization_percentage = 30% according to the explorer batching view +# ( batching_size_finalization_percentage * finality_depth) * block_time / 60 secs = ~10 min (finality time) +# After running soak tests using 10m threw issues as there are batchs that take 35m, so we are bumping it to 45m to be sure +NoNewFinalizedHeadsThreshold = '45m' + +FinalityTagEnabled = true + +[GasEstimator] +EIP1559DynamicFees = true +Mode = 'FeeHistory' + +[GasEstimator.FeeHistory] +# block_time was: 1s, per recommendation skip 1-2 blocks +CacheTimeout = '2s' + +[GasEstimator.BlockHistory] +# As we see blocks containing between ~[8-12]tx, to get about ~1000 tx to check we would need to rougly go 100 tx back +BlockHistorySize = 100 diff --git a/ccip/config/evm/WeMix_Mainnet.toml b/ccip/config/evm/WeMix_Mainnet.toml index be7c278f692..a4e742d7300 100644 --- a/ccip/config/evm/WeMix_Mainnet.toml +++ b/ccip/config/evm/WeMix_Mainnet.toml @@ -16,4 +16,6 @@ EIP1559DynamicFees = true TipCapDefault = '100 gwei' [HeadTracker] -PersistenceEnabled = false +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false diff --git a/ccip/config/evm/WeMix_Testnet.toml b/ccip/config/evm/WeMix_Testnet.toml index 4591fc4c572..bfb75f158e3 100644 --- a/ccip/config/evm/WeMix_Testnet.toml +++ b/ccip/config/evm/WeMix_Testnet.toml @@ -16,5 +16,6 @@ EIP1559DynamicFees = true TipCapDefault = '100 gwei' [HeadTracker] +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 FinalityTagBypass = false -PersistenceEnabled = false diff --git a/ccip/config/evm/Worldchain_Mainnet.toml b/ccip/config/evm/Worldchain_Mainnet.toml new file mode 100644 index 00000000000..9b25d89d98c --- /dev/null +++ b/ccip/config/evm/Worldchain_Mainnet.toml @@ -0,0 +1,23 @@ +ChainID = '480' +# OP stack: https://worldcoin.notion.site/World-Chain-Developer-Preview-Guide-23c94a67683f4e71986e5303ab88c9f3 +ChainType = 'optimismBedrock' +# finality_depth was: ~2400 +FinalityDepth = 2500 +# block_time was: 2s, adding 1 second buffer +LogPollInterval = '3s' + +# finality_depth * block_time / 60 secs = ~83 min (finality time) +NoNewFinalizedHeadsThreshold = '90m' + +FinalityTagEnabled = true + +[GasEstimator] +EIP1559DynamicFees = true +Mode = 'FeeHistory' + +[GasEstimator.FeeHistory] +# block_time was: 2s, per recommendation skip 1-2 blocks +CacheTimeout = '4s' + +[GasEstimator.BlockHistory] +BlockHistorySize = 100 diff --git a/ccip/config/evm/Worldchain_Testnet.toml b/ccip/config/evm/Worldchain_Testnet.toml new file mode 100644 index 00000000000..01618322285 --- /dev/null +++ b/ccip/config/evm/Worldchain_Testnet.toml @@ -0,0 +1,23 @@ +ChainID = '4801' +# OP stack: https://worldcoin.notion.site/World-Chain-Developer-Preview-Guide-23c94a67683f4e71986e5303ab88c9f3 +ChainType = 'optimismBedrock' +# finality_depth was: ~2400 +FinalityDepth = 2500 +# block_time was: 2s, adding 1 second buffer +LogPollInterval = '3s' + +# finality_depth * block_time / 60 secs = ~83 min (finality time) +NoNewFinalizedHeadsThreshold = '90m' + +FinalityTagEnabled = true + +[GasEstimator] +EIP1559DynamicFees = true +Mode = 'FeeHistory' + +[GasEstimator.FeeHistory] +# block_time was: 2s, per recommendation skip 1-2 blocks +CacheTimeout = '4s' + +[GasEstimator.BlockHistory] +BlockHistorySize = 100 diff --git a/ccip/config/evm/XLayer_Mainnet.toml b/ccip/config/evm/XLayer_Mainnet.toml index a39a9231ae2..28f7819276c 100644 --- a/ccip/config/evm/XLayer_Mainnet.toml +++ b/ccip/config/evm/XLayer_Mainnet.toml @@ -1,6 +1,6 @@ ChainID = '196' ChainType = 'xlayer' -FinalityDepth = 500 +FinalityDepth = 1000 NoNewHeadsThreshold = '6m' MinIncomingConfirmations = 1 LogPollInterval = '30s' diff --git a/ccip/config/evm/XLayer_Sepolia.toml b/ccip/config/evm/XLayer_Sepolia.toml index 2aa6e58469b..163d909542e 100644 --- a/ccip/config/evm/XLayer_Sepolia.toml +++ b/ccip/config/evm/XLayer_Sepolia.toml @@ -23,6 +23,9 @@ BlockHistorySize = 12 [HeadTracker] HistoryDepth = 2000 +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false [Transactions.AutoPurge] Enabled = true diff --git a/ccip/config/evm/fallback.toml b/ccip/config/evm/fallback.toml new file mode 100644 index 00000000000..fe02f62b433 --- /dev/null +++ b/ccip/config/evm/fallback.toml @@ -0,0 +1,96 @@ +AutoCreateKey = true +BlockBackfillDepth = 10 +BlockBackfillSkip = false +FinalityDepth = 50 +FinalityTagEnabled = false +LogBackfillBatchSize = 1000 +LogPollInterval = '15s' +LogKeepBlocksDepth = 100000 +LogPrunePageSize = 10000 +BackupLogPollerBlockDelay = 100 +MinContractPayment = '.00001 link' +MinIncomingConfirmations = 3 +NonceAutoSync = true +NoNewHeadsThreshold = '3m' +RPCDefaultBatchSize = 250 +RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 +NoNewFinalizedHeadsThreshold = '0' +LogBroadcasterEnabled = true + +[Transactions] +Enabled = true +ForwardersEnabled = false +MaxInFlight = 16 +MaxQueued = 250 +ReaperInterval = '1h' +ReaperThreshold = '168h' +ResendAfterThreshold = '1m' + +[Transactions.AutoPurge] +Enabled = false + +[BalanceMonitor] +Enabled = true + +[GasEstimator] +Mode = 'BlockHistory' +PriceDefault = '20 gwei' +PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' +PriceMin = '1 gwei' +LimitDefault = 8_000_000 +LimitMax = 8_000_000 +LimitMultiplier = '1' +LimitTransfer = 21_000 +BumpMin = '5 gwei' +BumpPercent = 20 +BumpThreshold = 3 +EIP1559DynamicFees = false +FeeCapDefault = '100 gwei' +TipCapDefault = '1' +TipCapMin = '1' +EstimateLimit = false + +[GasEstimator.BlockHistory] +BatchSize = 25 +BlockHistorySize = 8 +CheckInclusionBlocks = 12 +CheckInclusionPercentile = 90 +TransactionPercentile = 60 + +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + +[HeadTracker] +HistoryDepth = 100 +MaxBufferSize = 3 +SamplingInterval = '1s' +FinalityTagBypass = true +MaxAllowedFinalityDepth = 10000 +PersistenceEnabled = true + +[NodePool] +PollFailureThreshold = 5 +PollInterval = '10s' +SelectionMode = 'HighestHead' +SyncThreshold = 5 +LeaseDuration = '0s' +NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' + +[OCR] +ContractConfirmations = 4 +ContractTransmitterTransmitTimeout = '10s' +DatabaseTimeout = '10s' +DeltaCOverride = '168h' +DeltaCJitterOverride = '1h' +ObservationGracePeriod = '1s' + +[OCR2.Automation] +GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400_000 diff --git a/ccip/config/evm/zkSync_Mainnet.toml b/ccip/config/evm/zkSync_Mainnet.toml index a8910a37e4a..a29098690b4 100644 --- a/ccip/config/evm/zkSync_Mainnet.toml +++ b/ccip/config/evm/zkSync_Mainnet.toml @@ -28,4 +28,4 @@ OracleType = 'zksync' [HeadTracker] # tracks top N blocks to keep in heads database table. Should store atleast the same # of blocks as finalityDepth -HistoryDepth = 1500 \ No newline at end of file +HistoryDepth = 1500 diff --git a/ccip/config/evm/zkSync_Sepolia.toml b/ccip/config/evm/zkSync_Sepolia.toml index 6eb4ba4137e..36b0c9282da 100644 --- a/ccip/config/evm/zkSync_Sepolia.toml +++ b/ccip/config/evm/zkSync_Sepolia.toml @@ -1,23 +1,23 @@ ChainID = '300' ChainType = 'zksync' # 200block ~ 20min concurrent with the l1_committed tag -FinalityDepth = 200 +FinalityDepth = 200 # block rate is ~2-5sec, so this ensures blocks are polled correctly LogPollInterval = '5s' # sufficient time for RPC to be labelled out of sync, since blockRate is pretty fast NoNewHeadsThreshold = '1m' [GasEstimator] -# no EIP1559 to ensure our estimator doesnot estimate gas with MaxPriorityFee which will break minFunding requirement -EIP1559DynamicFees = false -# high LimitDefault for worst case pubdata bytes with BatchGasLimit reduced to 4M in OCR2Config +# no EIP1559 to ensure our estimator doesnot estimate gas with MaxPriorityFee which will break minFunding requirement +EIP1559DynamicFees = false +# high LimitDefault for worst case pubdata bytes with BatchGasLimit reduced to 4M in OCR2Config LimitDefault = 2_500_000_000 FeeCapDefault = '500 mwei' PriceDefault = '25 mwei' # p999 value for gasPrice based on historical data PriceMax = '500 mwei' # avg gasPrices are at 0.025 gwei -PriceMin = '25 mwei' +PriceMin = '25 mwei' [GasEstimator.BlockHistory] # increasing this to smooth out gas estimation @@ -28,4 +28,7 @@ OracleType = 'zksync' [HeadTracker] # tracks top N blocks to keep in heads database table. Should store atleast the same # of blocks as finalityDepth -HistoryDepth = 250 \ No newline at end of file +HistoryDepth = 250 +# FinalityDepth < 1k => FinalityTagBypass = false +# https://smartcontract-it.atlassian.net/browse/SHIP-4078 +FinalityTagBypass = false diff --git a/common/client/ctx.go b/common/client/ctx.go deleted file mode 100644 index 57b2fc8a866..00000000000 --- a/common/client/ctx.go +++ /dev/null @@ -1,17 +0,0 @@ -package client - -import "context" - -type multiNodeContextKey int - -const ( - contextKeyHeathCheckRequest multiNodeContextKey = iota + 1 -) - -func CtxAddHealthCheckFlag(ctx context.Context) context.Context { - return context.WithValue(ctx, contextKeyHeathCheckRequest, struct{}{}) -} - -func CtxIsHeathCheckRequest(ctx context.Context) bool { - return ctx.Value(contextKeyHeathCheckRequest) != nil -} diff --git a/common/client/ctx_test.go b/common/client/ctx_test.go deleted file mode 100644 index 822b36c3f81..00000000000 --- a/common/client/ctx_test.go +++ /dev/null @@ -1,16 +0,0 @@ -package client - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" -) - -func TestContext(t *testing.T) { - ctx := tests.Context(t) - assert.False(t, CtxIsHeathCheckRequest(ctx), "expected false for test context") - ctx = CtxAddHealthCheckFlag(ctx) - assert.True(t, CtxIsHeathCheckRequest(ctx), "expected context to contain the healthcheck flag") -} diff --git a/common/client/mock_hashable_test.go b/common/client/mock_hashable_test.go deleted file mode 100644 index d9f1670c073..00000000000 --- a/common/client/mock_hashable_test.go +++ /dev/null @@ -1,18 +0,0 @@ -package client - -import "cmp" - -// Hashable - simple implementation of types.Hashable interface to be used as concrete type in tests -type Hashable string - -func (h Hashable) Cmp(c Hashable) int { - return cmp.Compare(h, c) -} - -func (h Hashable) String() string { - return string(h) -} - -func (h Hashable) Bytes() []byte { - return []byte(h) -} diff --git a/common/client/mock_head_test.go b/common/client/mock_head_test.go deleted file mode 100644 index f75bb340305..00000000000 --- a/common/client/mock_head_test.go +++ /dev/null @@ -1,173 +0,0 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. - -package client - -import ( - big "math/big" - - mock "github.com/stretchr/testify/mock" -) - -// mockHead is an autogenerated mock type for the Head type -type mockHead struct { - mock.Mock -} - -type mockHead_Expecter struct { - mock *mock.Mock -} - -func (_m *mockHead) EXPECT() *mockHead_Expecter { - return &mockHead_Expecter{mock: &_m.Mock} -} - -// BlockDifficulty provides a mock function with given fields: -func (_m *mockHead) BlockDifficulty() *big.Int { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for BlockDifficulty") - } - - var r0 *big.Int - if rf, ok := ret.Get(0).(func() *big.Int); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*big.Int) - } - } - - return r0 -} - -// mockHead_BlockDifficulty_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BlockDifficulty' -type mockHead_BlockDifficulty_Call struct { - *mock.Call -} - -// BlockDifficulty is a helper method to define mock.On call -func (_e *mockHead_Expecter) BlockDifficulty() *mockHead_BlockDifficulty_Call { - return &mockHead_BlockDifficulty_Call{Call: _e.mock.On("BlockDifficulty")} -} - -func (_c *mockHead_BlockDifficulty_Call) Run(run func()) *mockHead_BlockDifficulty_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockHead_BlockDifficulty_Call) Return(_a0 *big.Int) *mockHead_BlockDifficulty_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockHead_BlockDifficulty_Call) RunAndReturn(run func() *big.Int) *mockHead_BlockDifficulty_Call { - _c.Call.Return(run) - return _c -} - -// BlockNumber provides a mock function with given fields: -func (_m *mockHead) BlockNumber() int64 { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for BlockNumber") - } - - var r0 int64 - if rf, ok := ret.Get(0).(func() int64); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(int64) - } - - return r0 -} - -// mockHead_BlockNumber_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BlockNumber' -type mockHead_BlockNumber_Call struct { - *mock.Call -} - -// BlockNumber is a helper method to define mock.On call -func (_e *mockHead_Expecter) BlockNumber() *mockHead_BlockNumber_Call { - return &mockHead_BlockNumber_Call{Call: _e.mock.On("BlockNumber")} -} - -func (_c *mockHead_BlockNumber_Call) Run(run func()) *mockHead_BlockNumber_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockHead_BlockNumber_Call) Return(_a0 int64) *mockHead_BlockNumber_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockHead_BlockNumber_Call) RunAndReturn(run func() int64) *mockHead_BlockNumber_Call { - _c.Call.Return(run) - return _c -} - -// IsValid provides a mock function with given fields: -func (_m *mockHead) IsValid() bool { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for IsValid") - } - - var r0 bool - if rf, ok := ret.Get(0).(func() bool); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(bool) - } - - return r0 -} - -// mockHead_IsValid_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'IsValid' -type mockHead_IsValid_Call struct { - *mock.Call -} - -// IsValid is a helper method to define mock.On call -func (_e *mockHead_Expecter) IsValid() *mockHead_IsValid_Call { - return &mockHead_IsValid_Call{Call: _e.mock.On("IsValid")} -} - -func (_c *mockHead_IsValid_Call) Run(run func()) *mockHead_IsValid_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockHead_IsValid_Call) Return(_a0 bool) *mockHead_IsValid_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockHead_IsValid_Call) RunAndReturn(run func() bool) *mockHead_IsValid_Call { - _c.Call.Return(run) - return _c -} - -// newMockHead creates a new instance of mockHead. 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 newMockHead(t interface { - mock.TestingT - Cleanup(func()) -}) *mockHead { - mock := &mockHead{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/common/client/mock_node_selector_test.go b/common/client/mock_node_selector_test.go deleted file mode 100644 index c01895a0ee7..00000000000 --- a/common/client/mock_node_selector_test.go +++ /dev/null @@ -1,127 +0,0 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. - -package client - -import ( - types "github.com/smartcontractkit/chainlink/v2/common/types" - mock "github.com/stretchr/testify/mock" -) - -// mockNodeSelector is an autogenerated mock type for the NodeSelector type -type mockNodeSelector[CHAIN_ID types.ID, RPC any] struct { - mock.Mock -} - -type mockNodeSelector_Expecter[CHAIN_ID types.ID, RPC any] struct { - mock *mock.Mock -} - -func (_m *mockNodeSelector[CHAIN_ID, RPC]) EXPECT() *mockNodeSelector_Expecter[CHAIN_ID, RPC] { - return &mockNodeSelector_Expecter[CHAIN_ID, RPC]{mock: &_m.Mock} -} - -// Name provides a mock function with given fields: -func (_m *mockNodeSelector[CHAIN_ID, RPC]) Name() string { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Name") - } - - var r0 string - if rf, ok := ret.Get(0).(func() string); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(string) - } - - return r0 -} - -// mockNodeSelector_Name_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Name' -type mockNodeSelector_Name_Call[CHAIN_ID types.ID, RPC any] struct { - *mock.Call -} - -// Name is a helper method to define mock.On call -func (_e *mockNodeSelector_Expecter[CHAIN_ID, RPC]) Name() *mockNodeSelector_Name_Call[CHAIN_ID, RPC] { - return &mockNodeSelector_Name_Call[CHAIN_ID, RPC]{Call: _e.mock.On("Name")} -} - -func (_c *mockNodeSelector_Name_Call[CHAIN_ID, RPC]) Run(run func()) *mockNodeSelector_Name_Call[CHAIN_ID, RPC] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockNodeSelector_Name_Call[CHAIN_ID, RPC]) Return(_a0 string) *mockNodeSelector_Name_Call[CHAIN_ID, RPC] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockNodeSelector_Name_Call[CHAIN_ID, RPC]) RunAndReturn(run func() string) *mockNodeSelector_Name_Call[CHAIN_ID, RPC] { - _c.Call.Return(run) - return _c -} - -// Select provides a mock function with given fields: -func (_m *mockNodeSelector[CHAIN_ID, RPC]) Select() Node[CHAIN_ID, RPC] { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Select") - } - - var r0 Node[CHAIN_ID, RPC] - if rf, ok := ret.Get(0).(func() Node[CHAIN_ID, RPC]); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(Node[CHAIN_ID, RPC]) - } - } - - return r0 -} - -// mockNodeSelector_Select_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Select' -type mockNodeSelector_Select_Call[CHAIN_ID types.ID, RPC any] struct { - *mock.Call -} - -// Select is a helper method to define mock.On call -func (_e *mockNodeSelector_Expecter[CHAIN_ID, RPC]) Select() *mockNodeSelector_Select_Call[CHAIN_ID, RPC] { - return &mockNodeSelector_Select_Call[CHAIN_ID, RPC]{Call: _e.mock.On("Select")} -} - -func (_c *mockNodeSelector_Select_Call[CHAIN_ID, RPC]) Run(run func()) *mockNodeSelector_Select_Call[CHAIN_ID, RPC] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockNodeSelector_Select_Call[CHAIN_ID, RPC]) Return(_a0 Node[CHAIN_ID, RPC]) *mockNodeSelector_Select_Call[CHAIN_ID, RPC] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockNodeSelector_Select_Call[CHAIN_ID, RPC]) RunAndReturn(run func() Node[CHAIN_ID, RPC]) *mockNodeSelector_Select_Call[CHAIN_ID, RPC] { - _c.Call.Return(run) - return _c -} - -// newMockNodeSelector creates a new instance of mockNodeSelector. 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 newMockNodeSelector[CHAIN_ID types.ID, RPC any](t interface { - mock.TestingT - Cleanup(func()) -}) *mockNodeSelector[CHAIN_ID, RPC] { - mock := &mockNodeSelector[CHAIN_ID, RPC]{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/common/client/mock_node_test.go b/common/client/mock_node_test.go deleted file mode 100644 index e5b090ab641..00000000000 --- a/common/client/mock_node_test.go +++ /dev/null @@ -1,563 +0,0 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. - -package client - -import ( - context "context" - - types "github.com/smartcontractkit/chainlink/v2/common/types" - mock "github.com/stretchr/testify/mock" -) - -// mockNode is an autogenerated mock type for the Node type -type mockNode[CHAIN_ID types.ID, RPC any] struct { - mock.Mock -} - -type mockNode_Expecter[CHAIN_ID types.ID, RPC any] struct { - mock *mock.Mock -} - -func (_m *mockNode[CHAIN_ID, RPC]) EXPECT() *mockNode_Expecter[CHAIN_ID, RPC] { - return &mockNode_Expecter[CHAIN_ID, RPC]{mock: &_m.Mock} -} - -// Close provides a mock function with given fields: -func (_m *mockNode[CHAIN_ID, RPC]) Close() error { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Close") - } - - var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// mockNode_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close' -type mockNode_Close_Call[CHAIN_ID types.ID, RPC any] struct { - *mock.Call -} - -// Close is a helper method to define mock.On call -func (_e *mockNode_Expecter[CHAIN_ID, RPC]) Close() *mockNode_Close_Call[CHAIN_ID, RPC] { - return &mockNode_Close_Call[CHAIN_ID, RPC]{Call: _e.mock.On("Close")} -} - -func (_c *mockNode_Close_Call[CHAIN_ID, RPC]) Run(run func()) *mockNode_Close_Call[CHAIN_ID, RPC] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockNode_Close_Call[CHAIN_ID, RPC]) Return(_a0 error) *mockNode_Close_Call[CHAIN_ID, RPC] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockNode_Close_Call[CHAIN_ID, RPC]) RunAndReturn(run func() error) *mockNode_Close_Call[CHAIN_ID, RPC] { - _c.Call.Return(run) - return _c -} - -// ConfiguredChainID provides a mock function with given fields: -func (_m *mockNode[CHAIN_ID, RPC]) ConfiguredChainID() CHAIN_ID { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for ConfiguredChainID") - } - - var r0 CHAIN_ID - if rf, ok := ret.Get(0).(func() CHAIN_ID); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(CHAIN_ID) - } - - return r0 -} - -// mockNode_ConfiguredChainID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ConfiguredChainID' -type mockNode_ConfiguredChainID_Call[CHAIN_ID types.ID, RPC any] struct { - *mock.Call -} - -// ConfiguredChainID is a helper method to define mock.On call -func (_e *mockNode_Expecter[CHAIN_ID, RPC]) ConfiguredChainID() *mockNode_ConfiguredChainID_Call[CHAIN_ID, RPC] { - return &mockNode_ConfiguredChainID_Call[CHAIN_ID, RPC]{Call: _e.mock.On("ConfiguredChainID")} -} - -func (_c *mockNode_ConfiguredChainID_Call[CHAIN_ID, RPC]) Run(run func()) *mockNode_ConfiguredChainID_Call[CHAIN_ID, RPC] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockNode_ConfiguredChainID_Call[CHAIN_ID, RPC]) Return(_a0 CHAIN_ID) *mockNode_ConfiguredChainID_Call[CHAIN_ID, RPC] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockNode_ConfiguredChainID_Call[CHAIN_ID, RPC]) RunAndReturn(run func() CHAIN_ID) *mockNode_ConfiguredChainID_Call[CHAIN_ID, RPC] { - _c.Call.Return(run) - return _c -} - -// HighestUserObservations provides a mock function with given fields: -func (_m *mockNode[CHAIN_ID, RPC]) HighestUserObservations() ChainInfo { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for HighestUserObservations") - } - - var r0 ChainInfo - if rf, ok := ret.Get(0).(func() ChainInfo); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(ChainInfo) - } - - return r0 -} - -// mockNode_HighestUserObservations_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'HighestUserObservations' -type mockNode_HighestUserObservations_Call[CHAIN_ID types.ID, RPC any] struct { - *mock.Call -} - -// HighestUserObservations is a helper method to define mock.On call -func (_e *mockNode_Expecter[CHAIN_ID, RPC]) HighestUserObservations() *mockNode_HighestUserObservations_Call[CHAIN_ID, RPC] { - return &mockNode_HighestUserObservations_Call[CHAIN_ID, RPC]{Call: _e.mock.On("HighestUserObservations")} -} - -func (_c *mockNode_HighestUserObservations_Call[CHAIN_ID, RPC]) Run(run func()) *mockNode_HighestUserObservations_Call[CHAIN_ID, RPC] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockNode_HighestUserObservations_Call[CHAIN_ID, RPC]) Return(_a0 ChainInfo) *mockNode_HighestUserObservations_Call[CHAIN_ID, RPC] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockNode_HighestUserObservations_Call[CHAIN_ID, RPC]) RunAndReturn(run func() ChainInfo) *mockNode_HighestUserObservations_Call[CHAIN_ID, RPC] { - _c.Call.Return(run) - return _c -} - -// Name provides a mock function with given fields: -func (_m *mockNode[CHAIN_ID, RPC]) Name() string { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Name") - } - - var r0 string - if rf, ok := ret.Get(0).(func() string); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(string) - } - - return r0 -} - -// mockNode_Name_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Name' -type mockNode_Name_Call[CHAIN_ID types.ID, RPC any] struct { - *mock.Call -} - -// Name is a helper method to define mock.On call -func (_e *mockNode_Expecter[CHAIN_ID, RPC]) Name() *mockNode_Name_Call[CHAIN_ID, RPC] { - return &mockNode_Name_Call[CHAIN_ID, RPC]{Call: _e.mock.On("Name")} -} - -func (_c *mockNode_Name_Call[CHAIN_ID, RPC]) Run(run func()) *mockNode_Name_Call[CHAIN_ID, RPC] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockNode_Name_Call[CHAIN_ID, RPC]) Return(_a0 string) *mockNode_Name_Call[CHAIN_ID, RPC] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockNode_Name_Call[CHAIN_ID, RPC]) RunAndReturn(run func() string) *mockNode_Name_Call[CHAIN_ID, RPC] { - _c.Call.Return(run) - return _c -} - -// Order provides a mock function with given fields: -func (_m *mockNode[CHAIN_ID, RPC]) Order() int32 { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Order") - } - - var r0 int32 - if rf, ok := ret.Get(0).(func() int32); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(int32) - } - - return r0 -} - -// mockNode_Order_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Order' -type mockNode_Order_Call[CHAIN_ID types.ID, RPC any] struct { - *mock.Call -} - -// Order is a helper method to define mock.On call -func (_e *mockNode_Expecter[CHAIN_ID, RPC]) Order() *mockNode_Order_Call[CHAIN_ID, RPC] { - return &mockNode_Order_Call[CHAIN_ID, RPC]{Call: _e.mock.On("Order")} -} - -func (_c *mockNode_Order_Call[CHAIN_ID, RPC]) Run(run func()) *mockNode_Order_Call[CHAIN_ID, RPC] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockNode_Order_Call[CHAIN_ID, RPC]) Return(_a0 int32) *mockNode_Order_Call[CHAIN_ID, RPC] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockNode_Order_Call[CHAIN_ID, RPC]) RunAndReturn(run func() int32) *mockNode_Order_Call[CHAIN_ID, RPC] { - _c.Call.Return(run) - return _c -} - -// RPC provides a mock function with given fields: -func (_m *mockNode[CHAIN_ID, RPC]) RPC() RPC { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for RPC") - } - - var r0 RPC - if rf, ok := ret.Get(0).(func() RPC); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(RPC) - } - - return r0 -} - -// mockNode_RPC_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RPC' -type mockNode_RPC_Call[CHAIN_ID types.ID, RPC any] struct { - *mock.Call -} - -// RPC is a helper method to define mock.On call -func (_e *mockNode_Expecter[CHAIN_ID, RPC]) RPC() *mockNode_RPC_Call[CHAIN_ID, RPC] { - return &mockNode_RPC_Call[CHAIN_ID, RPC]{Call: _e.mock.On("RPC")} -} - -func (_c *mockNode_RPC_Call[CHAIN_ID, RPC]) Run(run func()) *mockNode_RPC_Call[CHAIN_ID, RPC] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockNode_RPC_Call[CHAIN_ID, RPC]) Return(_a0 RPC) *mockNode_RPC_Call[CHAIN_ID, RPC] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockNode_RPC_Call[CHAIN_ID, RPC]) RunAndReturn(run func() RPC) *mockNode_RPC_Call[CHAIN_ID, RPC] { - _c.Call.Return(run) - return _c -} - -// SetPoolChainInfoProvider provides a mock function with given fields: _a0 -func (_m *mockNode[CHAIN_ID, RPC]) SetPoolChainInfoProvider(_a0 PoolChainInfoProvider) { - _m.Called(_a0) -} - -// mockNode_SetPoolChainInfoProvider_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetPoolChainInfoProvider' -type mockNode_SetPoolChainInfoProvider_Call[CHAIN_ID types.ID, RPC any] struct { - *mock.Call -} - -// SetPoolChainInfoProvider is a helper method to define mock.On call -// - _a0 PoolChainInfoProvider -func (_e *mockNode_Expecter[CHAIN_ID, RPC]) SetPoolChainInfoProvider(_a0 interface{}) *mockNode_SetPoolChainInfoProvider_Call[CHAIN_ID, RPC] { - return &mockNode_SetPoolChainInfoProvider_Call[CHAIN_ID, RPC]{Call: _e.mock.On("SetPoolChainInfoProvider", _a0)} -} - -func (_c *mockNode_SetPoolChainInfoProvider_Call[CHAIN_ID, RPC]) Run(run func(_a0 PoolChainInfoProvider)) *mockNode_SetPoolChainInfoProvider_Call[CHAIN_ID, RPC] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(PoolChainInfoProvider)) - }) - return _c -} - -func (_c *mockNode_SetPoolChainInfoProvider_Call[CHAIN_ID, RPC]) Return() *mockNode_SetPoolChainInfoProvider_Call[CHAIN_ID, RPC] { - _c.Call.Return() - return _c -} - -func (_c *mockNode_SetPoolChainInfoProvider_Call[CHAIN_ID, RPC]) RunAndReturn(run func(PoolChainInfoProvider)) *mockNode_SetPoolChainInfoProvider_Call[CHAIN_ID, RPC] { - _c.Call.Return(run) - return _c -} - -// Start provides a mock function with given fields: _a0 -func (_m *mockNode[CHAIN_ID, RPC]) Start(_a0 context.Context) error { - ret := _m.Called(_a0) - - if len(ret) == 0 { - panic("no return value specified for Start") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context) error); ok { - r0 = rf(_a0) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// mockNode_Start_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Start' -type mockNode_Start_Call[CHAIN_ID types.ID, RPC any] struct { - *mock.Call -} - -// Start is a helper method to define mock.On call -// - _a0 context.Context -func (_e *mockNode_Expecter[CHAIN_ID, RPC]) Start(_a0 interface{}) *mockNode_Start_Call[CHAIN_ID, RPC] { - return &mockNode_Start_Call[CHAIN_ID, RPC]{Call: _e.mock.On("Start", _a0)} -} - -func (_c *mockNode_Start_Call[CHAIN_ID, RPC]) Run(run func(_a0 context.Context)) *mockNode_Start_Call[CHAIN_ID, RPC] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *mockNode_Start_Call[CHAIN_ID, RPC]) Return(_a0 error) *mockNode_Start_Call[CHAIN_ID, RPC] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockNode_Start_Call[CHAIN_ID, RPC]) RunAndReturn(run func(context.Context) error) *mockNode_Start_Call[CHAIN_ID, RPC] { - _c.Call.Return(run) - return _c -} - -// State provides a mock function with given fields: -func (_m *mockNode[CHAIN_ID, RPC]) State() nodeState { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for State") - } - - var r0 nodeState - if rf, ok := ret.Get(0).(func() nodeState); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(nodeState) - } - - return r0 -} - -// mockNode_State_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'State' -type mockNode_State_Call[CHAIN_ID types.ID, RPC any] struct { - *mock.Call -} - -// State is a helper method to define mock.On call -func (_e *mockNode_Expecter[CHAIN_ID, RPC]) State() *mockNode_State_Call[CHAIN_ID, RPC] { - return &mockNode_State_Call[CHAIN_ID, RPC]{Call: _e.mock.On("State")} -} - -func (_c *mockNode_State_Call[CHAIN_ID, RPC]) Run(run func()) *mockNode_State_Call[CHAIN_ID, RPC] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockNode_State_Call[CHAIN_ID, RPC]) Return(_a0 nodeState) *mockNode_State_Call[CHAIN_ID, RPC] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockNode_State_Call[CHAIN_ID, RPC]) RunAndReturn(run func() nodeState) *mockNode_State_Call[CHAIN_ID, RPC] { - _c.Call.Return(run) - return _c -} - -// StateAndLatest provides a mock function with given fields: -func (_m *mockNode[CHAIN_ID, RPC]) StateAndLatest() (nodeState, ChainInfo) { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for StateAndLatest") - } - - var r0 nodeState - var r1 ChainInfo - if rf, ok := ret.Get(0).(func() (nodeState, ChainInfo)); ok { - return rf() - } - if rf, ok := ret.Get(0).(func() nodeState); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(nodeState) - } - - if rf, ok := ret.Get(1).(func() ChainInfo); ok { - r1 = rf() - } else { - r1 = ret.Get(1).(ChainInfo) - } - - return r0, r1 -} - -// mockNode_StateAndLatest_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'StateAndLatest' -type mockNode_StateAndLatest_Call[CHAIN_ID types.ID, RPC any] struct { - *mock.Call -} - -// StateAndLatest is a helper method to define mock.On call -func (_e *mockNode_Expecter[CHAIN_ID, RPC]) StateAndLatest() *mockNode_StateAndLatest_Call[CHAIN_ID, RPC] { - return &mockNode_StateAndLatest_Call[CHAIN_ID, RPC]{Call: _e.mock.On("StateAndLatest")} -} - -func (_c *mockNode_StateAndLatest_Call[CHAIN_ID, RPC]) Run(run func()) *mockNode_StateAndLatest_Call[CHAIN_ID, RPC] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockNode_StateAndLatest_Call[CHAIN_ID, RPC]) Return(_a0 nodeState, _a1 ChainInfo) *mockNode_StateAndLatest_Call[CHAIN_ID, RPC] { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *mockNode_StateAndLatest_Call[CHAIN_ID, RPC]) RunAndReturn(run func() (nodeState, ChainInfo)) *mockNode_StateAndLatest_Call[CHAIN_ID, RPC] { - _c.Call.Return(run) - return _c -} - -// String provides a mock function with given fields: -func (_m *mockNode[CHAIN_ID, RPC]) String() string { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for String") - } - - var r0 string - if rf, ok := ret.Get(0).(func() string); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(string) - } - - return r0 -} - -// mockNode_String_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'String' -type mockNode_String_Call[CHAIN_ID types.ID, RPC any] struct { - *mock.Call -} - -// String is a helper method to define mock.On call -func (_e *mockNode_Expecter[CHAIN_ID, RPC]) String() *mockNode_String_Call[CHAIN_ID, RPC] { - return &mockNode_String_Call[CHAIN_ID, RPC]{Call: _e.mock.On("String")} -} - -func (_c *mockNode_String_Call[CHAIN_ID, RPC]) Run(run func()) *mockNode_String_Call[CHAIN_ID, RPC] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockNode_String_Call[CHAIN_ID, RPC]) Return(_a0 string) *mockNode_String_Call[CHAIN_ID, RPC] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockNode_String_Call[CHAIN_ID, RPC]) RunAndReturn(run func() string) *mockNode_String_Call[CHAIN_ID, RPC] { - _c.Call.Return(run) - return _c -} - -// UnsubscribeAllExceptAliveLoop provides a mock function with given fields: -func (_m *mockNode[CHAIN_ID, RPC]) UnsubscribeAllExceptAliveLoop() { - _m.Called() -} - -// mockNode_UnsubscribeAllExceptAliveLoop_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UnsubscribeAllExceptAliveLoop' -type mockNode_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID types.ID, RPC any] struct { - *mock.Call -} - -// UnsubscribeAllExceptAliveLoop is a helper method to define mock.On call -func (_e *mockNode_Expecter[CHAIN_ID, RPC]) UnsubscribeAllExceptAliveLoop() *mockNode_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID, RPC] { - return &mockNode_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID, RPC]{Call: _e.mock.On("UnsubscribeAllExceptAliveLoop")} -} - -func (_c *mockNode_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID, RPC]) Run(run func()) *mockNode_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID, RPC] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockNode_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID, RPC]) Return() *mockNode_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID, RPC] { - _c.Call.Return() - return _c -} - -func (_c *mockNode_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID, RPC]) RunAndReturn(run func()) *mockNode_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID, RPC] { - _c.Call.Return(run) - return _c -} - -// newMockNode creates a new instance of mockNode. 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 newMockNode[CHAIN_ID types.ID, RPC any](t interface { - mock.TestingT - Cleanup(func()) -}) *mockNode[CHAIN_ID, RPC] { - mock := &mockNode[CHAIN_ID, RPC]{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/common/client/mock_pool_chain_info_provider_test.go b/common/client/mock_pool_chain_info_provider_test.go deleted file mode 100644 index c44f10b3f2f..00000000000 --- a/common/client/mock_pool_chain_info_provider_test.go +++ /dev/null @@ -1,132 +0,0 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. - -package client - -import mock "github.com/stretchr/testify/mock" - -// mockPoolChainInfoProvider is an autogenerated mock type for the PoolChainInfoProvider type -type mockPoolChainInfoProvider struct { - mock.Mock -} - -type mockPoolChainInfoProvider_Expecter struct { - mock *mock.Mock -} - -func (_m *mockPoolChainInfoProvider) EXPECT() *mockPoolChainInfoProvider_Expecter { - return &mockPoolChainInfoProvider_Expecter{mock: &_m.Mock} -} - -// HighestUserObservations provides a mock function with given fields: -func (_m *mockPoolChainInfoProvider) HighestUserObservations() ChainInfo { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for HighestUserObservations") - } - - var r0 ChainInfo - if rf, ok := ret.Get(0).(func() ChainInfo); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(ChainInfo) - } - - return r0 -} - -// mockPoolChainInfoProvider_HighestUserObservations_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'HighestUserObservations' -type mockPoolChainInfoProvider_HighestUserObservations_Call struct { - *mock.Call -} - -// HighestUserObservations is a helper method to define mock.On call -func (_e *mockPoolChainInfoProvider_Expecter) HighestUserObservations() *mockPoolChainInfoProvider_HighestUserObservations_Call { - return &mockPoolChainInfoProvider_HighestUserObservations_Call{Call: _e.mock.On("HighestUserObservations")} -} - -func (_c *mockPoolChainInfoProvider_HighestUserObservations_Call) Run(run func()) *mockPoolChainInfoProvider_HighestUserObservations_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockPoolChainInfoProvider_HighestUserObservations_Call) Return(_a0 ChainInfo) *mockPoolChainInfoProvider_HighestUserObservations_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockPoolChainInfoProvider_HighestUserObservations_Call) RunAndReturn(run func() ChainInfo) *mockPoolChainInfoProvider_HighestUserObservations_Call { - _c.Call.Return(run) - return _c -} - -// LatestChainInfo provides a mock function with given fields: -func (_m *mockPoolChainInfoProvider) LatestChainInfo() (int, ChainInfo) { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for LatestChainInfo") - } - - var r0 int - var r1 ChainInfo - if rf, ok := ret.Get(0).(func() (int, ChainInfo)); ok { - return rf() - } - if rf, ok := ret.Get(0).(func() int); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(int) - } - - if rf, ok := ret.Get(1).(func() ChainInfo); ok { - r1 = rf() - } else { - r1 = ret.Get(1).(ChainInfo) - } - - return r0, r1 -} - -// mockPoolChainInfoProvider_LatestChainInfo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'LatestChainInfo' -type mockPoolChainInfoProvider_LatestChainInfo_Call struct { - *mock.Call -} - -// LatestChainInfo is a helper method to define mock.On call -func (_e *mockPoolChainInfoProvider_Expecter) LatestChainInfo() *mockPoolChainInfoProvider_LatestChainInfo_Call { - return &mockPoolChainInfoProvider_LatestChainInfo_Call{Call: _e.mock.On("LatestChainInfo")} -} - -func (_c *mockPoolChainInfoProvider_LatestChainInfo_Call) Run(run func()) *mockPoolChainInfoProvider_LatestChainInfo_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockPoolChainInfoProvider_LatestChainInfo_Call) Return(_a0 int, _a1 ChainInfo) *mockPoolChainInfoProvider_LatestChainInfo_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *mockPoolChainInfoProvider_LatestChainInfo_Call) RunAndReturn(run func() (int, ChainInfo)) *mockPoolChainInfoProvider_LatestChainInfo_Call { - _c.Call.Return(run) - return _c -} - -// newMockPoolChainInfoProvider creates a new instance of mockPoolChainInfoProvider. 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 newMockPoolChainInfoProvider(t interface { - mock.TestingT - Cleanup(func()) -}) *mockPoolChainInfoProvider { - mock := &mockPoolChainInfoProvider{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/common/client/mock_rpc_client_test.go b/common/client/mock_rpc_client_test.go deleted file mode 100644 index 396914f320b..00000000000 --- a/common/client/mock_rpc_client_test.go +++ /dev/null @@ -1,508 +0,0 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. - -package client - -import ( - context "context" - - types "github.com/smartcontractkit/chainlink/v2/common/types" - mock "github.com/stretchr/testify/mock" -) - -// mockRPCClient is an autogenerated mock type for the RPCClient type -type mockRPCClient[CHAIN_ID types.ID, HEAD Head] struct { - mock.Mock -} - -type mockRPCClient_Expecter[CHAIN_ID types.ID, HEAD Head] struct { - mock *mock.Mock -} - -func (_m *mockRPCClient[CHAIN_ID, HEAD]) EXPECT() *mockRPCClient_Expecter[CHAIN_ID, HEAD] { - return &mockRPCClient_Expecter[CHAIN_ID, HEAD]{mock: &_m.Mock} -} - -// ChainID provides a mock function with given fields: ctx -func (_m *mockRPCClient[CHAIN_ID, HEAD]) ChainID(ctx context.Context) (CHAIN_ID, error) { - ret := _m.Called(ctx) - - if len(ret) == 0 { - panic("no return value specified for ChainID") - } - - var r0 CHAIN_ID - var r1 error - if rf, ok := ret.Get(0).(func(context.Context) (CHAIN_ID, error)); ok { - return rf(ctx) - } - if rf, ok := ret.Get(0).(func(context.Context) CHAIN_ID); ok { - r0 = rf(ctx) - } else { - r0 = ret.Get(0).(CHAIN_ID) - } - - if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// mockRPCClient_ChainID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ChainID' -type mockRPCClient_ChainID_Call[CHAIN_ID types.ID, HEAD Head] struct { - *mock.Call -} - -// ChainID is a helper method to define mock.On call -// - ctx context.Context -func (_e *mockRPCClient_Expecter[CHAIN_ID, HEAD]) ChainID(ctx interface{}) *mockRPCClient_ChainID_Call[CHAIN_ID, HEAD] { - return &mockRPCClient_ChainID_Call[CHAIN_ID, HEAD]{Call: _e.mock.On("ChainID", ctx)} -} - -func (_c *mockRPCClient_ChainID_Call[CHAIN_ID, HEAD]) Run(run func(ctx context.Context)) *mockRPCClient_ChainID_Call[CHAIN_ID, HEAD] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *mockRPCClient_ChainID_Call[CHAIN_ID, HEAD]) Return(_a0 CHAIN_ID, _a1 error) *mockRPCClient_ChainID_Call[CHAIN_ID, HEAD] { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *mockRPCClient_ChainID_Call[CHAIN_ID, HEAD]) RunAndReturn(run func(context.Context) (CHAIN_ID, error)) *mockRPCClient_ChainID_Call[CHAIN_ID, HEAD] { - _c.Call.Return(run) - return _c -} - -// Close provides a mock function with given fields: -func (_m *mockRPCClient[CHAIN_ID, HEAD]) Close() { - _m.Called() -} - -// mockRPCClient_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close' -type mockRPCClient_Close_Call[CHAIN_ID types.ID, HEAD Head] struct { - *mock.Call -} - -// Close is a helper method to define mock.On call -func (_e *mockRPCClient_Expecter[CHAIN_ID, HEAD]) Close() *mockRPCClient_Close_Call[CHAIN_ID, HEAD] { - return &mockRPCClient_Close_Call[CHAIN_ID, HEAD]{Call: _e.mock.On("Close")} -} - -func (_c *mockRPCClient_Close_Call[CHAIN_ID, HEAD]) Run(run func()) *mockRPCClient_Close_Call[CHAIN_ID, HEAD] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockRPCClient_Close_Call[CHAIN_ID, HEAD]) Return() *mockRPCClient_Close_Call[CHAIN_ID, HEAD] { - _c.Call.Return() - return _c -} - -func (_c *mockRPCClient_Close_Call[CHAIN_ID, HEAD]) RunAndReturn(run func()) *mockRPCClient_Close_Call[CHAIN_ID, HEAD] { - _c.Call.Return(run) - return _c -} - -// Dial provides a mock function with given fields: ctx -func (_m *mockRPCClient[CHAIN_ID, HEAD]) Dial(ctx context.Context) error { - ret := _m.Called(ctx) - - if len(ret) == 0 { - panic("no return value specified for Dial") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context) error); ok { - r0 = rf(ctx) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// mockRPCClient_Dial_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Dial' -type mockRPCClient_Dial_Call[CHAIN_ID types.ID, HEAD Head] struct { - *mock.Call -} - -// Dial is a helper method to define mock.On call -// - ctx context.Context -func (_e *mockRPCClient_Expecter[CHAIN_ID, HEAD]) Dial(ctx interface{}) *mockRPCClient_Dial_Call[CHAIN_ID, HEAD] { - return &mockRPCClient_Dial_Call[CHAIN_ID, HEAD]{Call: _e.mock.On("Dial", ctx)} -} - -func (_c *mockRPCClient_Dial_Call[CHAIN_ID, HEAD]) Run(run func(ctx context.Context)) *mockRPCClient_Dial_Call[CHAIN_ID, HEAD] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *mockRPCClient_Dial_Call[CHAIN_ID, HEAD]) Return(_a0 error) *mockRPCClient_Dial_Call[CHAIN_ID, HEAD] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockRPCClient_Dial_Call[CHAIN_ID, HEAD]) RunAndReturn(run func(context.Context) error) *mockRPCClient_Dial_Call[CHAIN_ID, HEAD] { - _c.Call.Return(run) - return _c -} - -// GetInterceptedChainInfo provides a mock function with given fields: -func (_m *mockRPCClient[CHAIN_ID, HEAD]) GetInterceptedChainInfo() (ChainInfo, ChainInfo) { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for GetInterceptedChainInfo") - } - - var r0 ChainInfo - var r1 ChainInfo - if rf, ok := ret.Get(0).(func() (ChainInfo, ChainInfo)); ok { - return rf() - } - if rf, ok := ret.Get(0).(func() ChainInfo); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(ChainInfo) - } - - if rf, ok := ret.Get(1).(func() ChainInfo); ok { - r1 = rf() - } else { - r1 = ret.Get(1).(ChainInfo) - } - - return r0, r1 -} - -// mockRPCClient_GetInterceptedChainInfo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetInterceptedChainInfo' -type mockRPCClient_GetInterceptedChainInfo_Call[CHAIN_ID types.ID, HEAD Head] struct { - *mock.Call -} - -// GetInterceptedChainInfo is a helper method to define mock.On call -func (_e *mockRPCClient_Expecter[CHAIN_ID, HEAD]) GetInterceptedChainInfo() *mockRPCClient_GetInterceptedChainInfo_Call[CHAIN_ID, HEAD] { - return &mockRPCClient_GetInterceptedChainInfo_Call[CHAIN_ID, HEAD]{Call: _e.mock.On("GetInterceptedChainInfo")} -} - -func (_c *mockRPCClient_GetInterceptedChainInfo_Call[CHAIN_ID, HEAD]) Run(run func()) *mockRPCClient_GetInterceptedChainInfo_Call[CHAIN_ID, HEAD] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockRPCClient_GetInterceptedChainInfo_Call[CHAIN_ID, HEAD]) Return(latest ChainInfo, highestUserObservations ChainInfo) *mockRPCClient_GetInterceptedChainInfo_Call[CHAIN_ID, HEAD] { - _c.Call.Return(latest, highestUserObservations) - return _c -} - -func (_c *mockRPCClient_GetInterceptedChainInfo_Call[CHAIN_ID, HEAD]) RunAndReturn(run func() (ChainInfo, ChainInfo)) *mockRPCClient_GetInterceptedChainInfo_Call[CHAIN_ID, HEAD] { - _c.Call.Return(run) - return _c -} - -// IsSyncing provides a mock function with given fields: ctx -func (_m *mockRPCClient[CHAIN_ID, HEAD]) IsSyncing(ctx context.Context) (bool, error) { - ret := _m.Called(ctx) - - if len(ret) == 0 { - panic("no return value specified for IsSyncing") - } - - var r0 bool - var r1 error - if rf, ok := ret.Get(0).(func(context.Context) (bool, error)); ok { - return rf(ctx) - } - if rf, ok := ret.Get(0).(func(context.Context) bool); ok { - r0 = rf(ctx) - } else { - r0 = ret.Get(0).(bool) - } - - if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// mockRPCClient_IsSyncing_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'IsSyncing' -type mockRPCClient_IsSyncing_Call[CHAIN_ID types.ID, HEAD Head] struct { - *mock.Call -} - -// IsSyncing is a helper method to define mock.On call -// - ctx context.Context -func (_e *mockRPCClient_Expecter[CHAIN_ID, HEAD]) IsSyncing(ctx interface{}) *mockRPCClient_IsSyncing_Call[CHAIN_ID, HEAD] { - return &mockRPCClient_IsSyncing_Call[CHAIN_ID, HEAD]{Call: _e.mock.On("IsSyncing", ctx)} -} - -func (_c *mockRPCClient_IsSyncing_Call[CHAIN_ID, HEAD]) Run(run func(ctx context.Context)) *mockRPCClient_IsSyncing_Call[CHAIN_ID, HEAD] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *mockRPCClient_IsSyncing_Call[CHAIN_ID, HEAD]) Return(_a0 bool, _a1 error) *mockRPCClient_IsSyncing_Call[CHAIN_ID, HEAD] { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *mockRPCClient_IsSyncing_Call[CHAIN_ID, HEAD]) RunAndReturn(run func(context.Context) (bool, error)) *mockRPCClient_IsSyncing_Call[CHAIN_ID, HEAD] { - _c.Call.Return(run) - return _c -} - -// Ping provides a mock function with given fields: _a0 -func (_m *mockRPCClient[CHAIN_ID, HEAD]) Ping(_a0 context.Context) error { - ret := _m.Called(_a0) - - if len(ret) == 0 { - panic("no return value specified for Ping") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context) error); ok { - r0 = rf(_a0) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// mockRPCClient_Ping_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Ping' -type mockRPCClient_Ping_Call[CHAIN_ID types.ID, HEAD Head] struct { - *mock.Call -} - -// Ping is a helper method to define mock.On call -// - _a0 context.Context -func (_e *mockRPCClient_Expecter[CHAIN_ID, HEAD]) Ping(_a0 interface{}) *mockRPCClient_Ping_Call[CHAIN_ID, HEAD] { - return &mockRPCClient_Ping_Call[CHAIN_ID, HEAD]{Call: _e.mock.On("Ping", _a0)} -} - -func (_c *mockRPCClient_Ping_Call[CHAIN_ID, HEAD]) Run(run func(_a0 context.Context)) *mockRPCClient_Ping_Call[CHAIN_ID, HEAD] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *mockRPCClient_Ping_Call[CHAIN_ID, HEAD]) Return(_a0 error) *mockRPCClient_Ping_Call[CHAIN_ID, HEAD] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockRPCClient_Ping_Call[CHAIN_ID, HEAD]) RunAndReturn(run func(context.Context) error) *mockRPCClient_Ping_Call[CHAIN_ID, HEAD] { - _c.Call.Return(run) - return _c -} - -// SubscribeToFinalizedHeads provides a mock function with given fields: ctx -func (_m *mockRPCClient[CHAIN_ID, HEAD]) SubscribeToFinalizedHeads(ctx context.Context) (<-chan HEAD, types.Subscription, error) { - ret := _m.Called(ctx) - - if len(ret) == 0 { - panic("no return value specified for SubscribeToFinalizedHeads") - } - - var r0 <-chan HEAD - var r1 types.Subscription - var r2 error - if rf, ok := ret.Get(0).(func(context.Context) (<-chan HEAD, types.Subscription, error)); ok { - return rf(ctx) - } - if rf, ok := ret.Get(0).(func(context.Context) <-chan HEAD); ok { - r0 = rf(ctx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(<-chan HEAD) - } - } - - if rf, ok := ret.Get(1).(func(context.Context) types.Subscription); ok { - r1 = rf(ctx) - } else { - if ret.Get(1) != nil { - r1 = ret.Get(1).(types.Subscription) - } - } - - if rf, ok := ret.Get(2).(func(context.Context) error); ok { - r2 = rf(ctx) - } else { - r2 = ret.Error(2) - } - - return r0, r1, r2 -} - -// mockRPCClient_SubscribeToFinalizedHeads_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SubscribeToFinalizedHeads' -type mockRPCClient_SubscribeToFinalizedHeads_Call[CHAIN_ID types.ID, HEAD Head] struct { - *mock.Call -} - -// SubscribeToFinalizedHeads is a helper method to define mock.On call -// - ctx context.Context -func (_e *mockRPCClient_Expecter[CHAIN_ID, HEAD]) SubscribeToFinalizedHeads(ctx interface{}) *mockRPCClient_SubscribeToFinalizedHeads_Call[CHAIN_ID, HEAD] { - return &mockRPCClient_SubscribeToFinalizedHeads_Call[CHAIN_ID, HEAD]{Call: _e.mock.On("SubscribeToFinalizedHeads", ctx)} -} - -func (_c *mockRPCClient_SubscribeToFinalizedHeads_Call[CHAIN_ID, HEAD]) Run(run func(ctx context.Context)) *mockRPCClient_SubscribeToFinalizedHeads_Call[CHAIN_ID, HEAD] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *mockRPCClient_SubscribeToFinalizedHeads_Call[CHAIN_ID, HEAD]) Return(_a0 <-chan HEAD, _a1 types.Subscription, _a2 error) *mockRPCClient_SubscribeToFinalizedHeads_Call[CHAIN_ID, HEAD] { - _c.Call.Return(_a0, _a1, _a2) - return _c -} - -func (_c *mockRPCClient_SubscribeToFinalizedHeads_Call[CHAIN_ID, HEAD]) RunAndReturn(run func(context.Context) (<-chan HEAD, types.Subscription, error)) *mockRPCClient_SubscribeToFinalizedHeads_Call[CHAIN_ID, HEAD] { - _c.Call.Return(run) - return _c -} - -// SubscribeToHeads provides a mock function with given fields: ctx -func (_m *mockRPCClient[CHAIN_ID, HEAD]) SubscribeToHeads(ctx context.Context) (<-chan HEAD, types.Subscription, error) { - ret := _m.Called(ctx) - - if len(ret) == 0 { - panic("no return value specified for SubscribeToHeads") - } - - var r0 <-chan HEAD - var r1 types.Subscription - var r2 error - if rf, ok := ret.Get(0).(func(context.Context) (<-chan HEAD, types.Subscription, error)); ok { - return rf(ctx) - } - if rf, ok := ret.Get(0).(func(context.Context) <-chan HEAD); ok { - r0 = rf(ctx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(<-chan HEAD) - } - } - - if rf, ok := ret.Get(1).(func(context.Context) types.Subscription); ok { - r1 = rf(ctx) - } else { - if ret.Get(1) != nil { - r1 = ret.Get(1).(types.Subscription) - } - } - - if rf, ok := ret.Get(2).(func(context.Context) error); ok { - r2 = rf(ctx) - } else { - r2 = ret.Error(2) - } - - return r0, r1, r2 -} - -// mockRPCClient_SubscribeToHeads_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SubscribeToHeads' -type mockRPCClient_SubscribeToHeads_Call[CHAIN_ID types.ID, HEAD Head] struct { - *mock.Call -} - -// SubscribeToHeads is a helper method to define mock.On call -// - ctx context.Context -func (_e *mockRPCClient_Expecter[CHAIN_ID, HEAD]) SubscribeToHeads(ctx interface{}) *mockRPCClient_SubscribeToHeads_Call[CHAIN_ID, HEAD] { - return &mockRPCClient_SubscribeToHeads_Call[CHAIN_ID, HEAD]{Call: _e.mock.On("SubscribeToHeads", ctx)} -} - -func (_c *mockRPCClient_SubscribeToHeads_Call[CHAIN_ID, HEAD]) Run(run func(ctx context.Context)) *mockRPCClient_SubscribeToHeads_Call[CHAIN_ID, HEAD] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *mockRPCClient_SubscribeToHeads_Call[CHAIN_ID, HEAD]) Return(_a0 <-chan HEAD, _a1 types.Subscription, _a2 error) *mockRPCClient_SubscribeToHeads_Call[CHAIN_ID, HEAD] { - _c.Call.Return(_a0, _a1, _a2) - return _c -} - -func (_c *mockRPCClient_SubscribeToHeads_Call[CHAIN_ID, HEAD]) RunAndReturn(run func(context.Context) (<-chan HEAD, types.Subscription, error)) *mockRPCClient_SubscribeToHeads_Call[CHAIN_ID, HEAD] { - _c.Call.Return(run) - return _c -} - -// UnsubscribeAllExcept provides a mock function with given fields: subs -func (_m *mockRPCClient[CHAIN_ID, HEAD]) UnsubscribeAllExcept(subs ...types.Subscription) { - _va := make([]interface{}, len(subs)) - for _i := range subs { - _va[_i] = subs[_i] - } - var _ca []interface{} - _ca = append(_ca, _va...) - _m.Called(_ca...) -} - -// mockRPCClient_UnsubscribeAllExcept_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UnsubscribeAllExcept' -type mockRPCClient_UnsubscribeAllExcept_Call[CHAIN_ID types.ID, HEAD Head] struct { - *mock.Call -} - -// UnsubscribeAllExcept is a helper method to define mock.On call -// - subs ...types.Subscription -func (_e *mockRPCClient_Expecter[CHAIN_ID, HEAD]) UnsubscribeAllExcept(subs ...interface{}) *mockRPCClient_UnsubscribeAllExcept_Call[CHAIN_ID, HEAD] { - return &mockRPCClient_UnsubscribeAllExcept_Call[CHAIN_ID, HEAD]{Call: _e.mock.On("UnsubscribeAllExcept", - append([]interface{}{}, subs...)...)} -} - -func (_c *mockRPCClient_UnsubscribeAllExcept_Call[CHAIN_ID, HEAD]) Run(run func(subs ...types.Subscription)) *mockRPCClient_UnsubscribeAllExcept_Call[CHAIN_ID, HEAD] { - _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]types.Subscription, len(args)-0) - for i, a := range args[0:] { - if a != nil { - variadicArgs[i] = a.(types.Subscription) - } - } - run(variadicArgs...) - }) - return _c -} - -func (_c *mockRPCClient_UnsubscribeAllExcept_Call[CHAIN_ID, HEAD]) Return() *mockRPCClient_UnsubscribeAllExcept_Call[CHAIN_ID, HEAD] { - _c.Call.Return() - return _c -} - -func (_c *mockRPCClient_UnsubscribeAllExcept_Call[CHAIN_ID, HEAD]) RunAndReturn(run func(...types.Subscription)) *mockRPCClient_UnsubscribeAllExcept_Call[CHAIN_ID, HEAD] { - _c.Call.Return(run) - return _c -} - -// newMockRPCClient creates a new instance of mockRPCClient. 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 newMockRPCClient[CHAIN_ID types.ID, HEAD Head](t interface { - mock.TestingT - Cleanup(func()) -}) *mockRPCClient[CHAIN_ID, HEAD] { - mock := &mockRPCClient[CHAIN_ID, HEAD]{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/common/client/mock_send_only_client_test.go b/common/client/mock_send_only_client_test.go deleted file mode 100644 index b47b56a8304..00000000000 --- a/common/client/mock_send_only_client_test.go +++ /dev/null @@ -1,171 +0,0 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. - -package client - -import ( - context "context" - - types "github.com/smartcontractkit/chainlink/v2/common/types" - mock "github.com/stretchr/testify/mock" -) - -// mockSendOnlyClient is an autogenerated mock type for the sendOnlyClient type -type mockSendOnlyClient[CHAIN_ID types.ID] struct { - mock.Mock -} - -type mockSendOnlyClient_Expecter[CHAIN_ID types.ID] struct { - mock *mock.Mock -} - -func (_m *mockSendOnlyClient[CHAIN_ID]) EXPECT() *mockSendOnlyClient_Expecter[CHAIN_ID] { - return &mockSendOnlyClient_Expecter[CHAIN_ID]{mock: &_m.Mock} -} - -// ChainID provides a mock function with given fields: _a0 -func (_m *mockSendOnlyClient[CHAIN_ID]) ChainID(_a0 context.Context) (CHAIN_ID, error) { - ret := _m.Called(_a0) - - if len(ret) == 0 { - panic("no return value specified for ChainID") - } - - var r0 CHAIN_ID - var r1 error - if rf, ok := ret.Get(0).(func(context.Context) (CHAIN_ID, error)); ok { - return rf(_a0) - } - if rf, ok := ret.Get(0).(func(context.Context) CHAIN_ID); ok { - r0 = rf(_a0) - } else { - r0 = ret.Get(0).(CHAIN_ID) - } - - if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(_a0) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// mockSendOnlyClient_ChainID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ChainID' -type mockSendOnlyClient_ChainID_Call[CHAIN_ID types.ID] struct { - *mock.Call -} - -// ChainID is a helper method to define mock.On call -// - _a0 context.Context -func (_e *mockSendOnlyClient_Expecter[CHAIN_ID]) ChainID(_a0 interface{}) *mockSendOnlyClient_ChainID_Call[CHAIN_ID] { - return &mockSendOnlyClient_ChainID_Call[CHAIN_ID]{Call: _e.mock.On("ChainID", _a0)} -} - -func (_c *mockSendOnlyClient_ChainID_Call[CHAIN_ID]) Run(run func(_a0 context.Context)) *mockSendOnlyClient_ChainID_Call[CHAIN_ID] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *mockSendOnlyClient_ChainID_Call[CHAIN_ID]) Return(_a0 CHAIN_ID, _a1 error) *mockSendOnlyClient_ChainID_Call[CHAIN_ID] { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *mockSendOnlyClient_ChainID_Call[CHAIN_ID]) RunAndReturn(run func(context.Context) (CHAIN_ID, error)) *mockSendOnlyClient_ChainID_Call[CHAIN_ID] { - _c.Call.Return(run) - return _c -} - -// Close provides a mock function with given fields: -func (_m *mockSendOnlyClient[CHAIN_ID]) Close() { - _m.Called() -} - -// mockSendOnlyClient_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close' -type mockSendOnlyClient_Close_Call[CHAIN_ID types.ID] struct { - *mock.Call -} - -// Close is a helper method to define mock.On call -func (_e *mockSendOnlyClient_Expecter[CHAIN_ID]) Close() *mockSendOnlyClient_Close_Call[CHAIN_ID] { - return &mockSendOnlyClient_Close_Call[CHAIN_ID]{Call: _e.mock.On("Close")} -} - -func (_c *mockSendOnlyClient_Close_Call[CHAIN_ID]) Run(run func()) *mockSendOnlyClient_Close_Call[CHAIN_ID] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockSendOnlyClient_Close_Call[CHAIN_ID]) Return() *mockSendOnlyClient_Close_Call[CHAIN_ID] { - _c.Call.Return() - return _c -} - -func (_c *mockSendOnlyClient_Close_Call[CHAIN_ID]) RunAndReturn(run func()) *mockSendOnlyClient_Close_Call[CHAIN_ID] { - _c.Call.Return(run) - return _c -} - -// Dial provides a mock function with given fields: ctx -func (_m *mockSendOnlyClient[CHAIN_ID]) Dial(ctx context.Context) error { - ret := _m.Called(ctx) - - if len(ret) == 0 { - panic("no return value specified for Dial") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context) error); ok { - r0 = rf(ctx) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// mockSendOnlyClient_Dial_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Dial' -type mockSendOnlyClient_Dial_Call[CHAIN_ID types.ID] struct { - *mock.Call -} - -// Dial is a helper method to define mock.On call -// - ctx context.Context -func (_e *mockSendOnlyClient_Expecter[CHAIN_ID]) Dial(ctx interface{}) *mockSendOnlyClient_Dial_Call[CHAIN_ID] { - return &mockSendOnlyClient_Dial_Call[CHAIN_ID]{Call: _e.mock.On("Dial", ctx)} -} - -func (_c *mockSendOnlyClient_Dial_Call[CHAIN_ID]) Run(run func(ctx context.Context)) *mockSendOnlyClient_Dial_Call[CHAIN_ID] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *mockSendOnlyClient_Dial_Call[CHAIN_ID]) Return(_a0 error) *mockSendOnlyClient_Dial_Call[CHAIN_ID] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockSendOnlyClient_Dial_Call[CHAIN_ID]) RunAndReturn(run func(context.Context) error) *mockSendOnlyClient_Dial_Call[CHAIN_ID] { - _c.Call.Return(run) - return _c -} - -// newMockSendOnlyClient creates a new instance of mockSendOnlyClient. 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 newMockSendOnlyClient[CHAIN_ID types.ID](t interface { - mock.TestingT - Cleanup(func()) -}) *mockSendOnlyClient[CHAIN_ID] { - mock := &mockSendOnlyClient[CHAIN_ID]{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/common/client/mock_send_only_node_test.go b/common/client/mock_send_only_node_test.go deleted file mode 100644 index 98a6f0ba2fb..00000000000 --- a/common/client/mock_send_only_node_test.go +++ /dev/null @@ -1,353 +0,0 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. - -package client - -import ( - context "context" - - types "github.com/smartcontractkit/chainlink/v2/common/types" - mock "github.com/stretchr/testify/mock" -) - -// mockSendOnlyNode is an autogenerated mock type for the SendOnlyNode type -type mockSendOnlyNode[CHAIN_ID types.ID, RPC any] struct { - mock.Mock -} - -type mockSendOnlyNode_Expecter[CHAIN_ID types.ID, RPC any] struct { - mock *mock.Mock -} - -func (_m *mockSendOnlyNode[CHAIN_ID, RPC]) EXPECT() *mockSendOnlyNode_Expecter[CHAIN_ID, RPC] { - return &mockSendOnlyNode_Expecter[CHAIN_ID, RPC]{mock: &_m.Mock} -} - -// Close provides a mock function with given fields: -func (_m *mockSendOnlyNode[CHAIN_ID, RPC]) Close() error { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Close") - } - - var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// mockSendOnlyNode_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close' -type mockSendOnlyNode_Close_Call[CHAIN_ID types.ID, RPC any] struct { - *mock.Call -} - -// Close is a helper method to define mock.On call -func (_e *mockSendOnlyNode_Expecter[CHAIN_ID, RPC]) Close() *mockSendOnlyNode_Close_Call[CHAIN_ID, RPC] { - return &mockSendOnlyNode_Close_Call[CHAIN_ID, RPC]{Call: _e.mock.On("Close")} -} - -func (_c *mockSendOnlyNode_Close_Call[CHAIN_ID, RPC]) Run(run func()) *mockSendOnlyNode_Close_Call[CHAIN_ID, RPC] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockSendOnlyNode_Close_Call[CHAIN_ID, RPC]) Return(_a0 error) *mockSendOnlyNode_Close_Call[CHAIN_ID, RPC] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockSendOnlyNode_Close_Call[CHAIN_ID, RPC]) RunAndReturn(run func() error) *mockSendOnlyNode_Close_Call[CHAIN_ID, RPC] { - _c.Call.Return(run) - return _c -} - -// ConfiguredChainID provides a mock function with given fields: -func (_m *mockSendOnlyNode[CHAIN_ID, RPC]) ConfiguredChainID() CHAIN_ID { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for ConfiguredChainID") - } - - var r0 CHAIN_ID - if rf, ok := ret.Get(0).(func() CHAIN_ID); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(CHAIN_ID) - } - - return r0 -} - -// mockSendOnlyNode_ConfiguredChainID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ConfiguredChainID' -type mockSendOnlyNode_ConfiguredChainID_Call[CHAIN_ID types.ID, RPC any] struct { - *mock.Call -} - -// ConfiguredChainID is a helper method to define mock.On call -func (_e *mockSendOnlyNode_Expecter[CHAIN_ID, RPC]) ConfiguredChainID() *mockSendOnlyNode_ConfiguredChainID_Call[CHAIN_ID, RPC] { - return &mockSendOnlyNode_ConfiguredChainID_Call[CHAIN_ID, RPC]{Call: _e.mock.On("ConfiguredChainID")} -} - -func (_c *mockSendOnlyNode_ConfiguredChainID_Call[CHAIN_ID, RPC]) Run(run func()) *mockSendOnlyNode_ConfiguredChainID_Call[CHAIN_ID, RPC] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockSendOnlyNode_ConfiguredChainID_Call[CHAIN_ID, RPC]) Return(_a0 CHAIN_ID) *mockSendOnlyNode_ConfiguredChainID_Call[CHAIN_ID, RPC] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockSendOnlyNode_ConfiguredChainID_Call[CHAIN_ID, RPC]) RunAndReturn(run func() CHAIN_ID) *mockSendOnlyNode_ConfiguredChainID_Call[CHAIN_ID, RPC] { - _c.Call.Return(run) - return _c -} - -// Name provides a mock function with given fields: -func (_m *mockSendOnlyNode[CHAIN_ID, RPC]) Name() string { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Name") - } - - var r0 string - if rf, ok := ret.Get(0).(func() string); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(string) - } - - return r0 -} - -// mockSendOnlyNode_Name_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Name' -type mockSendOnlyNode_Name_Call[CHAIN_ID types.ID, RPC any] struct { - *mock.Call -} - -// Name is a helper method to define mock.On call -func (_e *mockSendOnlyNode_Expecter[CHAIN_ID, RPC]) Name() *mockSendOnlyNode_Name_Call[CHAIN_ID, RPC] { - return &mockSendOnlyNode_Name_Call[CHAIN_ID, RPC]{Call: _e.mock.On("Name")} -} - -func (_c *mockSendOnlyNode_Name_Call[CHAIN_ID, RPC]) Run(run func()) *mockSendOnlyNode_Name_Call[CHAIN_ID, RPC] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockSendOnlyNode_Name_Call[CHAIN_ID, RPC]) Return(_a0 string) *mockSendOnlyNode_Name_Call[CHAIN_ID, RPC] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockSendOnlyNode_Name_Call[CHAIN_ID, RPC]) RunAndReturn(run func() string) *mockSendOnlyNode_Name_Call[CHAIN_ID, RPC] { - _c.Call.Return(run) - return _c -} - -// RPC provides a mock function with given fields: -func (_m *mockSendOnlyNode[CHAIN_ID, RPC]) RPC() RPC { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for RPC") - } - - var r0 RPC - if rf, ok := ret.Get(0).(func() RPC); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(RPC) - } - - return r0 -} - -// mockSendOnlyNode_RPC_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RPC' -type mockSendOnlyNode_RPC_Call[CHAIN_ID types.ID, RPC any] struct { - *mock.Call -} - -// RPC is a helper method to define mock.On call -func (_e *mockSendOnlyNode_Expecter[CHAIN_ID, RPC]) RPC() *mockSendOnlyNode_RPC_Call[CHAIN_ID, RPC] { - return &mockSendOnlyNode_RPC_Call[CHAIN_ID, RPC]{Call: _e.mock.On("RPC")} -} - -func (_c *mockSendOnlyNode_RPC_Call[CHAIN_ID, RPC]) Run(run func()) *mockSendOnlyNode_RPC_Call[CHAIN_ID, RPC] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockSendOnlyNode_RPC_Call[CHAIN_ID, RPC]) Return(_a0 RPC) *mockSendOnlyNode_RPC_Call[CHAIN_ID, RPC] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockSendOnlyNode_RPC_Call[CHAIN_ID, RPC]) RunAndReturn(run func() RPC) *mockSendOnlyNode_RPC_Call[CHAIN_ID, RPC] { - _c.Call.Return(run) - return _c -} - -// Start provides a mock function with given fields: _a0 -func (_m *mockSendOnlyNode[CHAIN_ID, RPC]) Start(_a0 context.Context) error { - ret := _m.Called(_a0) - - if len(ret) == 0 { - panic("no return value specified for Start") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context) error); ok { - r0 = rf(_a0) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// mockSendOnlyNode_Start_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Start' -type mockSendOnlyNode_Start_Call[CHAIN_ID types.ID, RPC any] struct { - *mock.Call -} - -// Start is a helper method to define mock.On call -// - _a0 context.Context -func (_e *mockSendOnlyNode_Expecter[CHAIN_ID, RPC]) Start(_a0 interface{}) *mockSendOnlyNode_Start_Call[CHAIN_ID, RPC] { - return &mockSendOnlyNode_Start_Call[CHAIN_ID, RPC]{Call: _e.mock.On("Start", _a0)} -} - -func (_c *mockSendOnlyNode_Start_Call[CHAIN_ID, RPC]) Run(run func(_a0 context.Context)) *mockSendOnlyNode_Start_Call[CHAIN_ID, RPC] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *mockSendOnlyNode_Start_Call[CHAIN_ID, RPC]) Return(_a0 error) *mockSendOnlyNode_Start_Call[CHAIN_ID, RPC] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockSendOnlyNode_Start_Call[CHAIN_ID, RPC]) RunAndReturn(run func(context.Context) error) *mockSendOnlyNode_Start_Call[CHAIN_ID, RPC] { - _c.Call.Return(run) - return _c -} - -// State provides a mock function with given fields: -func (_m *mockSendOnlyNode[CHAIN_ID, RPC]) State() nodeState { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for State") - } - - var r0 nodeState - if rf, ok := ret.Get(0).(func() nodeState); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(nodeState) - } - - return r0 -} - -// mockSendOnlyNode_State_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'State' -type mockSendOnlyNode_State_Call[CHAIN_ID types.ID, RPC any] struct { - *mock.Call -} - -// State is a helper method to define mock.On call -func (_e *mockSendOnlyNode_Expecter[CHAIN_ID, RPC]) State() *mockSendOnlyNode_State_Call[CHAIN_ID, RPC] { - return &mockSendOnlyNode_State_Call[CHAIN_ID, RPC]{Call: _e.mock.On("State")} -} - -func (_c *mockSendOnlyNode_State_Call[CHAIN_ID, RPC]) Run(run func()) *mockSendOnlyNode_State_Call[CHAIN_ID, RPC] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockSendOnlyNode_State_Call[CHAIN_ID, RPC]) Return(_a0 nodeState) *mockSendOnlyNode_State_Call[CHAIN_ID, RPC] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockSendOnlyNode_State_Call[CHAIN_ID, RPC]) RunAndReturn(run func() nodeState) *mockSendOnlyNode_State_Call[CHAIN_ID, RPC] { - _c.Call.Return(run) - return _c -} - -// String provides a mock function with given fields: -func (_m *mockSendOnlyNode[CHAIN_ID, RPC]) String() string { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for String") - } - - var r0 string - if rf, ok := ret.Get(0).(func() string); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(string) - } - - return r0 -} - -// mockSendOnlyNode_String_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'String' -type mockSendOnlyNode_String_Call[CHAIN_ID types.ID, RPC any] struct { - *mock.Call -} - -// String is a helper method to define mock.On call -func (_e *mockSendOnlyNode_Expecter[CHAIN_ID, RPC]) String() *mockSendOnlyNode_String_Call[CHAIN_ID, RPC] { - return &mockSendOnlyNode_String_Call[CHAIN_ID, RPC]{Call: _e.mock.On("String")} -} - -func (_c *mockSendOnlyNode_String_Call[CHAIN_ID, RPC]) Run(run func()) *mockSendOnlyNode_String_Call[CHAIN_ID, RPC] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockSendOnlyNode_String_Call[CHAIN_ID, RPC]) Return(_a0 string) *mockSendOnlyNode_String_Call[CHAIN_ID, RPC] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockSendOnlyNode_String_Call[CHAIN_ID, RPC]) RunAndReturn(run func() string) *mockSendOnlyNode_String_Call[CHAIN_ID, RPC] { - _c.Call.Return(run) - return _c -} - -// newMockSendOnlyNode creates a new instance of mockSendOnlyNode. 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 newMockSendOnlyNode[CHAIN_ID types.ID, RPC any](t interface { - mock.TestingT - Cleanup(func()) -}) *mockSendOnlyNode[CHAIN_ID, RPC] { - mock := &mockSendOnlyNode[CHAIN_ID, RPC]{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/common/client/mocks/config.go b/common/client/mocks/config.go deleted file mode 100644 index 95b57cce0c3..00000000000 --- a/common/client/mocks/config.go +++ /dev/null @@ -1,31 +0,0 @@ -package mocks - -import "time" - -type ChainConfig struct { - IsFinalityTagEnabled bool - FinalityDepthVal uint32 - NoNewHeadsThresholdVal time.Duration - FinalizedBlockOffsetVal uint32 - NoNewFinalizedHeadsThresholdVal time.Duration -} - -func (t ChainConfig) NodeNoNewHeadsThreshold() time.Duration { - return t.NoNewHeadsThresholdVal -} - -func (t ChainConfig) FinalityDepth() uint32 { - return t.FinalityDepthVal -} - -func (t ChainConfig) FinalityTagEnabled() bool { - return t.IsFinalityTagEnabled -} - -func (t ChainConfig) FinalizedBlockOffset() uint32 { - return t.FinalizedBlockOffsetVal -} - -func (t ChainConfig) NoNewFinalizedHeadsThreshold() time.Duration { - return t.NoNewFinalizedHeadsThresholdVal -} diff --git a/common/client/models.go b/common/client/models.go deleted file mode 100644 index 526bb25c887..00000000000 --- a/common/client/models.go +++ /dev/null @@ -1,121 +0,0 @@ -package client - -import ( - "bytes" - "fmt" -) - -type SendTxReturnCode int - -// SendTxReturnCode is a generalized client error that dictates what should be the next action, depending on the RPC error response. -const ( - Successful SendTxReturnCode = iota + 1 - Fatal // Unrecoverable error. Most likely the attempt should be thrown away. - Retryable // The error returned by the RPC indicates that if we retry with the same attempt, the tx will eventually go through. - Underpriced // Attempt was underpriced. New estimation is needed with bumped gas price. - Unknown // Tx failed with an error response that is not recognized by the client. - Unsupported // Attempt failed with an error response that is not supported by the client for the given chain. - TransactionAlreadyKnown // The transaction that was sent has already been received by the RPC. - InsufficientFunds // Tx was rejected due to insufficient funds. - ExceedsMaxFee // Attempt's fee was higher than the node's limit and got rejected. - FeeOutOfValidRange // This error is returned when we use a fee price suggested from an RPC, but the network rejects the attempt due to an invalid range(mostly used by L2 chains). Retry by requesting a new suggested fee price. - TerminallyStuck // The error returned when a transaction is or could get terminally stuck in the mempool without any chance of inclusion. - sendTxReturnCodeLen // tracks the number of errors. Must always be last -) - -// sendTxSevereErrors - error codes which signal that transaction would never be accepted in its current form by the node -var sendTxSevereErrors = []SendTxReturnCode{Fatal, Underpriced, Unsupported, ExceedsMaxFee, FeeOutOfValidRange, Unknown} - -// sendTxSuccessfulCodes - error codes which signal that transaction was accepted by the node -var sendTxSuccessfulCodes = []SendTxReturnCode{Successful, TransactionAlreadyKnown} - -func (c SendTxReturnCode) String() string { - switch c { - case Successful: - return "Successful" - case Fatal: - return "Fatal" - case Retryable: - return "Retryable" - case Underpriced: - return "Underpriced" - case Unknown: - return "Unknown" - case Unsupported: - return "Unsupported" - case TransactionAlreadyKnown: - return "TransactionAlreadyKnown" - case InsufficientFunds: - return "InsufficientFunds" - case ExceedsMaxFee: - return "ExceedsMaxFee" - case FeeOutOfValidRange: - return "FeeOutOfValidRange" - case TerminallyStuck: - return "TerminallyStuck" - default: - return fmt.Sprintf("SendTxReturnCode(%d)", c) - } -} - -type NodeTier int - -const ( - Primary = NodeTier(iota) - Secondary -) - -func (n NodeTier) String() string { - switch n { - case Primary: - return "primary" - case Secondary: - return "secondary" - default: - return fmt.Sprintf("NodeTier(%d)", n) - } -} - -// syncStatus - defines problems related to RPC's state synchronization. Can be used as a bitmask to define multiple issues -type syncStatus int - -const ( - // syncStatusSynced - RPC is fully synced - syncStatusSynced = 0 - // syncStatusNotInSyncWithPool - RPC is lagging behind the highest block observed within the pool of RPCs - syncStatusNotInSyncWithPool syncStatus = 1 << iota - // syncStatusNoNewHead - RPC failed to produce a new head for too long - syncStatusNoNewHead - // syncStatusNoNewFinalizedHead - RPC failed to produce a new finalized head for too long - syncStatusNoNewFinalizedHead - syncStatusLen -) - -func (s syncStatus) String() string { - if s == syncStatusSynced { - return "Synced" - } - var result bytes.Buffer - for i := syncStatusNotInSyncWithPool; i < syncStatusLen; i = i << 1 { - if i&s == 0 { - continue - } - result.WriteString(i.string()) - result.WriteString(",") - } - result.Truncate(result.Len() - 1) - return result.String() -} - -func (s syncStatus) string() string { - switch s { - case syncStatusNotInSyncWithPool: - return "NotInSyncWithRPCPool" - case syncStatusNoNewHead: - return "NoNewHead" - case syncStatusNoNewFinalizedHead: - return "NoNewFinalizedHead" - default: - return fmt.Sprintf("syncStatus(%d)", s) - } -} diff --git a/common/client/models_test.go b/common/client/models_test.go deleted file mode 100644 index a10592c3b68..00000000000 --- a/common/client/models_test.go +++ /dev/null @@ -1,50 +0,0 @@ -package client - -import ( - "strings" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestSendTxReturnCode_String(t *testing.T) { - // ensure all the SendTxReturnCodes have proper name - for c := 1; c < int(sendTxReturnCodeLen); c++ { - strC := SendTxReturnCode(c).String() - if strings.Contains(strC, "SendTxReturnCode(") { - t.Errorf("Expected %s to have a proper string representation", strC) - } - } -} - -func TestSyncStatus_String(t *testing.T) { - t.Run("All of the statuses have proper string representation", func(t *testing.T) { - for i := syncStatusNotInSyncWithPool; i < syncStatusLen; i <<= 1 { - // ensure that i's string representation is not equal to `syncStatus(%d)` - assert.NotContains(t, i.String(), "syncStatus(") - } - }) - t.Run("Unwraps mask", func(t *testing.T) { - testCases := []struct { - Mask syncStatus - ExpectedStr string - }{ - { - ExpectedStr: "Synced", - }, - { - Mask: syncStatusNotInSyncWithPool | syncStatusNoNewHead, - ExpectedStr: "NotInSyncWithRPCPool,NoNewHead", - }, - { - Mask: syncStatusNotInSyncWithPool | syncStatusNoNewHead | syncStatusNoNewFinalizedHead, - ExpectedStr: "NotInSyncWithRPCPool,NoNewHead,NoNewFinalizedHead", - }, - } - for _, testCase := range testCases { - t.Run(testCase.ExpectedStr, func(t *testing.T) { - assert.Equal(t, testCase.ExpectedStr, testCase.Mask.String()) - }) - } - }) -} diff --git a/common/client/multi_node.go b/common/client/multi_node.go deleted file mode 100644 index b946fb8fc2a..00000000000 --- a/common/client/multi_node.go +++ /dev/null @@ -1,364 +0,0 @@ -package client - -import ( - "context" - "fmt" - "math/big" - "sync" - "time" - - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promauto" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/services" - - "github.com/smartcontractkit/chainlink/v2/common/types" -) - -var ( - // PromMultiNodeRPCNodeStates reports current RPC node state - PromMultiNodeRPCNodeStates = promauto.NewGaugeVec(prometheus.GaugeOpts{ - Name: "multi_node_states", - Help: "The number of RPC nodes currently in the given state for the given chain", - }, []string{"network", "chainId", "state"}) - ErroringNodeError = fmt.Errorf("no live nodes available") -) - -// MultiNode is a generalized multi node client interface that includes methods to interact with different chains. -// It also handles multiple node RPC connections simultaneously. -type MultiNode[ - CHAIN_ID types.ID, - RPC any, -] struct { - services.Service - eng *services.Engine - - primaryNodes []Node[CHAIN_ID, RPC] - sendOnlyNodes []SendOnlyNode[CHAIN_ID, RPC] - chainID CHAIN_ID - lggr logger.SugaredLogger - selectionMode string - nodeSelector NodeSelector[CHAIN_ID, RPC] - leaseDuration time.Duration - leaseTicker *time.Ticker - chainFamily string - reportInterval time.Duration - deathDeclarationDelay time.Duration - - activeMu sync.RWMutex - activeNode Node[CHAIN_ID, RPC] -} - -func NewMultiNode[ - CHAIN_ID types.ID, - RPC any, -]( - lggr logger.Logger, - selectionMode string, // type of the "best" RPC selector (e.g HighestHead, RoundRobin, etc.) - leaseDuration time.Duration, // defines interval on which new "best" RPC should be selected - primaryNodes []Node[CHAIN_ID, RPC], - sendOnlyNodes []SendOnlyNode[CHAIN_ID, RPC], - chainID CHAIN_ID, // configured chain ID (used to verify that passed primaryNodes belong to the same chain) - chainFamily string, // name of the chain family - used in the metrics - deathDeclarationDelay time.Duration, -) *MultiNode[CHAIN_ID, RPC] { - nodeSelector := newNodeSelector(selectionMode, primaryNodes) - // Prometheus' default interval is 15s, set this to under 7.5s to avoid - // aliasing (see: https://en.wikipedia.org/wiki/Nyquist_frequency) - const reportInterval = 6500 * time.Millisecond - c := &MultiNode[CHAIN_ID, RPC]{ - primaryNodes: primaryNodes, - sendOnlyNodes: sendOnlyNodes, - chainID: chainID, - selectionMode: selectionMode, - nodeSelector: nodeSelector, - leaseDuration: leaseDuration, - chainFamily: chainFamily, - reportInterval: reportInterval, - deathDeclarationDelay: deathDeclarationDelay, - } - c.Service, c.eng = services.Config{ - Name: "MultiNode", - Start: c.start, - Close: c.close, - }.NewServiceEngine(logger.With(lggr, "chainID", chainID.String())) - c.lggr = c.eng.SugaredLogger - - c.lggr.Debugf("The MultiNode is configured to use NodeSelectionMode: %s", selectionMode) - - return c -} - -func (c *MultiNode[CHAIN_ID, RPC]) ChainID() CHAIN_ID { - return c.chainID -} - -func (c *MultiNode[CHAIN_ID, RPC]) DoAll(ctx context.Context, do func(ctx context.Context, rpc RPC, isSendOnly bool)) error { - return c.eng.IfNotStopped(func() error { - callsCompleted := 0 - for _, n := range c.primaryNodes { - select { - case <-ctx.Done(): - return ctx.Err() - default: - if n.State() != nodeStateAlive { - continue - } - do(ctx, n.RPC(), false) - callsCompleted++ - } - } - - for _, n := range c.sendOnlyNodes { - select { - case <-ctx.Done(): - return ctx.Err() - default: - if n.State() != nodeStateAlive { - continue - } - do(ctx, n.RPC(), true) - } - } - if callsCompleted == 0 { - return ErroringNodeError - } - return nil - }) -} - -func (c *MultiNode[CHAIN_ID, RPC]) NodeStates() map[string]string { - states := map[string]string{} - for _, n := range c.primaryNodes { - states[n.Name()] = n.State().String() - } - for _, n := range c.sendOnlyNodes { - states[n.Name()] = n.State().String() - } - return states -} - -// Start starts every node in the pool -// -// Nodes handle their own redialing and runloops, so this function does not -// return any error if the nodes aren't available -func (c *MultiNode[CHAIN_ID, RPC]) start(ctx context.Context) error { - if len(c.primaryNodes) == 0 { - return fmt.Errorf("no available nodes for chain %s", c.chainID.String()) - } - var ms services.MultiStart - for _, n := range c.primaryNodes { - if n.ConfiguredChainID().String() != c.chainID.String() { - return ms.CloseBecause(fmt.Errorf("node %s has configured chain ID %s which does not match multinode configured chain ID of %s", n.String(), n.ConfiguredChainID().String(), c.chainID.String())) - } - n.SetPoolChainInfoProvider(c) - // node will handle its own redialing and automatic recovery - if err := ms.Start(ctx, n); err != nil { - return err - } - } - for _, s := range c.sendOnlyNodes { - if s.ConfiguredChainID().String() != c.chainID.String() { - return ms.CloseBecause(fmt.Errorf("sendonly node %s has configured chain ID %s which does not match multinode configured chain ID of %s", s.String(), s.ConfiguredChainID().String(), c.chainID.String())) - } - if err := ms.Start(ctx, s); err != nil { - return err - } - } - c.eng.Go(c.runLoop) - - if c.leaseDuration.Seconds() > 0 && c.selectionMode != NodeSelectionModeRoundRobin { - c.lggr.Infof("The MultiNode will switch to best node every %s", c.leaseDuration.String()) - c.eng.Go(c.checkLeaseLoop) - } else { - c.lggr.Info("Best node switching is disabled") - } - - return nil -} - -// Close tears down the MultiNode and closes all nodes -func (c *MultiNode[CHAIN_ID, RPC]) close() error { - return services.CloseAll(services.MultiCloser(c.primaryNodes), services.MultiCloser(c.sendOnlyNodes)) -} - -// SelectRPC returns an RPC of an active node. If there are no active nodes it returns an error. -// Call this method from your chain-specific client implementation to access any chain-specific rpc calls. -func (c *MultiNode[CHAIN_ID, RPC]) SelectRPC() (rpc RPC, err error) { - n, err := c.selectNode() - if err != nil { - 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. -func (c *MultiNode[CHAIN_ID, RPC]) selectNode() (node Node[CHAIN_ID, RPC], err error) { - c.activeMu.RLock() - node = c.activeNode - c.activeMu.RUnlock() - if node != nil && node.State() == nodeStateAlive { - return // still alive - } - - // select a new one - c.activeMu.Lock() - defer c.activeMu.Unlock() - node = c.activeNode - if node != nil && node.State() == nodeStateAlive { - return // another goroutine beat us here - } - - var prevNodeName string - if c.activeNode != nil { - prevNodeName = c.activeNode.String() - c.activeNode.UnsubscribeAllExceptAliveLoop() - } - c.activeNode = c.nodeSelector.Select() - if c.activeNode == nil { - c.lggr.Criticalw("No live RPC nodes available", "NodeSelectionMode", c.nodeSelector.Name()) - c.eng.EmitHealthErr(fmt.Errorf("no live nodes available for chain %s", c.chainID.String())) - return nil, ErroringNodeError - } - - c.lggr.Debugw("Switched to a new active node due to prev node heath issues", "prevNode", prevNodeName, "newNode", c.activeNode.String()) - return c.activeNode, err -} - -// LatestChainInfo - returns number of live nodes available in the pool, so we can prevent the last alive node in a pool from being marked as out-of-sync. -// Return highest ChainInfo most recently received by the alive nodes. -// E.g. If Node A's the most recent block is 10 and highest 15 and for Node B it's - 12 and 14. This method will return 12. -func (c *MultiNode[CHAIN_ID, RPC]) LatestChainInfo() (int, ChainInfo) { - var nLiveNodes int - ch := ChainInfo{ - TotalDifficulty: big.NewInt(0), - } - for _, n := range c.primaryNodes { - if s, nodeChainInfo := n.StateAndLatest(); s == nodeStateAlive { - nLiveNodes++ - ch.BlockNumber = max(ch.BlockNumber, nodeChainInfo.BlockNumber) - ch.FinalizedBlockNumber = max(ch.FinalizedBlockNumber, nodeChainInfo.FinalizedBlockNumber) - ch.TotalDifficulty = MaxTotalDifficulty(ch.TotalDifficulty, nodeChainInfo.TotalDifficulty) - } - } - return nLiveNodes, ch -} - -// HighestUserObservations - returns highest ChainInfo ever observed by any user of the MultiNode -func (c *MultiNode[CHAIN_ID, RPC]) HighestUserObservations() ChainInfo { - ch := ChainInfo{ - TotalDifficulty: big.NewInt(0), - } - for _, n := range c.primaryNodes { - nodeChainInfo := n.HighestUserObservations() - ch.BlockNumber = max(ch.BlockNumber, nodeChainInfo.BlockNumber) - ch.FinalizedBlockNumber = max(ch.FinalizedBlockNumber, nodeChainInfo.FinalizedBlockNumber) - ch.TotalDifficulty = MaxTotalDifficulty(ch.TotalDifficulty, nodeChainInfo.TotalDifficulty) - } - return ch -} - -func (c *MultiNode[CHAIN_ID, RPC]) checkLease() { - bestNode := c.nodeSelector.Select() - for _, n := range c.primaryNodes { - // Terminate client subscriptions. Services are responsible for reconnecting, which will be routed to the new - // best node. Only terminate connections with more than 1 subscription to account for the aliveLoop subscription - if n.State() == nodeStateAlive && n != bestNode { - c.lggr.Infof("Switching to best node from %q to %q", n.String(), bestNode.String()) - n.UnsubscribeAllExceptAliveLoop() - } - } - - c.activeMu.Lock() - defer c.activeMu.Unlock() - if bestNode != c.activeNode { - if c.activeNode != nil { - c.activeNode.UnsubscribeAllExceptAliveLoop() - } - c.activeNode = bestNode - } -} - -func (c *MultiNode[CHAIN_ID, RPC]) checkLeaseLoop(ctx context.Context) { - c.leaseTicker = time.NewTicker(c.leaseDuration) - defer c.leaseTicker.Stop() - - for { - select { - case <-c.leaseTicker.C: - c.checkLease() - case <-ctx.Done(): - return - } - } -} - -func (c *MultiNode[CHAIN_ID, RPC]) runLoop(ctx context.Context) { - nodeStates := make([]nodeWithState, len(c.primaryNodes)) - for i, n := range c.primaryNodes { - nodeStates[i] = nodeWithState{ - Node: n.String(), - State: n.State().String(), - DeadSince: nil, - } - } - - c.report(nodeStates) - - monitor := services.NewTicker(c.reportInterval) - defer monitor.Stop() - - for { - select { - case <-monitor.C: - c.report(nodeStates) - case <-ctx.Done(): - return - } - } -} - -type nodeWithState struct { - Node string - State string - DeadSince *time.Time -} - -func (c *MultiNode[CHAIN_ID, RPC]) report(nodesStateInfo []nodeWithState) { - start := time.Now() - var dead int - counts := make(map[nodeState]int) - for i, n := range c.primaryNodes { - state := n.State() - counts[state]++ - nodesStateInfo[i].State = state.String() - if state == nodeStateAlive { - nodesStateInfo[i].DeadSince = nil - continue - } - - if nodesStateInfo[i].DeadSince == nil { - nodesStateInfo[i].DeadSince = &start - } - - if start.Sub(*nodesStateInfo[i].DeadSince) >= c.deathDeclarationDelay { - dead++ - } - } - for _, state := range allNodeStates { - count := counts[state] - PromMultiNodeRPCNodeStates.WithLabelValues(c.chainFamily, c.chainID.String(), state.String()).Set(float64(count)) - } - - total := len(c.primaryNodes) - live := total - dead - c.lggr.Tracew(fmt.Sprintf("MultiNode state: %d/%d nodes are alive", live, total), "nodeStates", nodesStateInfo) - if total == dead { - rerr := fmt.Errorf("no primary nodes available: 0/%d nodes are alive", total) - c.lggr.Criticalw(rerr.Error(), "nodeStates", nodesStateInfo) - c.eng.EmitHealthErr(rerr) - } else if dead > 0 { - c.lggr.Errorw(fmt.Sprintf("At least one primary node is dead: %d/%d nodes are alive", live, total), "nodeStates", nodesStateInfo) - } -} diff --git a/common/client/multi_node_test.go b/common/client/multi_node_test.go deleted file mode 100644 index c1636881dd3..00000000000 --- a/common/client/multi_node_test.go +++ /dev/null @@ -1,517 +0,0 @@ -package client - -import ( - "fmt" - "math/big" - "math/rand" - "testing" - "time" - - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - "go.uber.org/zap" - - "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink/v2/common/types" -) - -type multiNodeRPCClient RPCClient[types.ID, types.Head[Hashable]] - -type testMultiNode struct { - *MultiNode[types.ID, multiNodeRPCClient] -} - -type multiNodeOpts struct { - logger logger.Logger - selectionMode string - leaseDuration time.Duration - nodes []Node[types.ID, multiNodeRPCClient] - sendonlys []SendOnlyNode[types.ID, multiNodeRPCClient] - chainID types.ID - chainFamily string - deathDeclarationDelay time.Duration -} - -func newTestMultiNode(t *testing.T, opts multiNodeOpts) testMultiNode { - if opts.logger == nil { - opts.logger = logger.Test(t) - } - - result := NewMultiNode[types.ID, multiNodeRPCClient]( - opts.logger, opts.selectionMode, opts.leaseDuration, opts.nodes, opts.sendonlys, opts.chainID, opts.chainFamily, opts.deathDeclarationDelay) - return testMultiNode{ - result, - } -} - -func newHealthyNode(t *testing.T, chainID types.ID) *mockNode[types.ID, multiNodeRPCClient] { - return newNodeWithState(t, chainID, nodeStateAlive) -} - -func newNodeWithState(t *testing.T, chainID types.ID, state nodeState) *mockNode[types.ID, multiNodeRPCClient] { - node := newMockNode[types.ID, multiNodeRPCClient](t) - node.On("ConfiguredChainID").Return(chainID).Once() - node.On("Start", mock.Anything).Return(nil).Once() - node.On("Close").Return(nil).Once() - node.On("String").Return(fmt.Sprintf("healthy_node_%d", rand.Int())).Maybe() - node.On("SetPoolChainInfoProvider", mock.Anything).Once() - node.On("State").Return(state).Maybe() - return node -} - -func TestMultiNode_Dial(t *testing.T) { - t.Parallel() - - newMockNode := newMockNode[types.ID, multiNodeRPCClient] - newMockSendOnlyNode := newMockSendOnlyNode[types.ID, multiNodeRPCClient] - - t.Run("Fails without nodes", func(t *testing.T) { - t.Parallel() - mn := newTestMultiNode(t, multiNodeOpts{ - selectionMode: NodeSelectionModeRoundRobin, - chainID: types.RandomID(), - }) - err := mn.Start(tests.Context(t)) - assert.ErrorContains(t, err, fmt.Sprintf("no available nodes for chain %s", mn.chainID)) - }) - t.Run("Fails with wrong node's chainID", func(t *testing.T) { - t.Parallel() - node := newMockNode(t) - multiNodeChainID := types.NewIDFromInt(10) - nodeChainID := types.NewIDFromInt(11) - node.On("ConfiguredChainID").Return(nodeChainID).Twice() - const nodeName = "nodeName" - node.On("String").Return(nodeName).Once() - mn := newTestMultiNode(t, multiNodeOpts{ - selectionMode: NodeSelectionModeRoundRobin, - chainID: multiNodeChainID, - nodes: []Node[types.ID, multiNodeRPCClient]{node}, - }) - err := mn.Start(tests.Context(t)) - assert.ErrorContains(t, err, fmt.Sprintf("node %s has configured chain ID %s which does not match multinode configured chain ID of %s", nodeName, nodeChainID, mn.chainID)) - }) - t.Run("Fails if node fails", func(t *testing.T) { - t.Parallel() - node := newMockNode(t) - chainID := types.RandomID() - node.On("ConfiguredChainID").Return(chainID).Once() - expectedError := errors.New("failed to start node") - node.On("Start", mock.Anything).Return(expectedError).Once() - node.On("SetPoolChainInfoProvider", mock.Anything).Once() - mn := newTestMultiNode(t, multiNodeOpts{ - selectionMode: NodeSelectionModeRoundRobin, - chainID: chainID, - nodes: []Node[types.ID, multiNodeRPCClient]{node}, - }) - err := mn.Start(tests.Context(t)) - assert.ErrorIs(t, err, expectedError) - }) - - t.Run("Closes started nodes on failure", func(t *testing.T) { - t.Parallel() - chainID := types.RandomID() - node1 := newHealthyNode(t, chainID) - node2 := newMockNode(t) - node2.On("ConfiguredChainID").Return(chainID).Once() - expectedError := errors.New("failed to start node") - node2.On("Start", mock.Anything).Return(expectedError).Once() - node2.On("SetPoolChainInfoProvider", mock.Anything).Once() - - mn := newTestMultiNode(t, multiNodeOpts{ - selectionMode: NodeSelectionModeRoundRobin, - chainID: chainID, - nodes: []Node[types.ID, multiNodeRPCClient]{node1, node2}, - }) - err := mn.Start(tests.Context(t)) - assert.ErrorIs(t, err, expectedError) - }) - t.Run("Fails with wrong send only node's chainID", func(t *testing.T) { - t.Parallel() - multiNodeChainID := types.NewIDFromInt(10) - node := newHealthyNode(t, multiNodeChainID) - sendOnly := newMockSendOnlyNode(t) - sendOnlyChainID := types.NewIDFromInt(11) - sendOnly.On("ConfiguredChainID").Return(sendOnlyChainID).Twice() - const sendOnlyName = "sendOnlyNodeName" - sendOnly.On("String").Return(sendOnlyName).Once() - - mn := newTestMultiNode(t, multiNodeOpts{ - selectionMode: NodeSelectionModeRoundRobin, - chainID: multiNodeChainID, - nodes: []Node[types.ID, multiNodeRPCClient]{node}, - sendonlys: []SendOnlyNode[types.ID, multiNodeRPCClient]{sendOnly}, - }) - err := mn.Start(tests.Context(t)) - assert.ErrorContains(t, err, fmt.Sprintf("sendonly node %s has configured chain ID %s which does not match multinode configured chain ID of %s", sendOnlyName, sendOnlyChainID, mn.chainID)) - }) - - newHealthySendOnly := func(t *testing.T, chainID types.ID) *mockSendOnlyNode[types.ID, multiNodeRPCClient] { - node := newMockSendOnlyNode(t) - node.On("ConfiguredChainID").Return(chainID).Once() - node.On("Start", mock.Anything).Return(nil).Once() - node.On("Close").Return(nil).Once() - return node - } - t.Run("Fails on send only node failure", func(t *testing.T) { - t.Parallel() - chainID := types.NewIDFromInt(10) - node := newHealthyNode(t, chainID) - sendOnly1 := newHealthySendOnly(t, chainID) - sendOnly2 := newMockSendOnlyNode(t) - sendOnly2.On("ConfiguredChainID").Return(chainID).Once() - expectedError := errors.New("failed to start send only node") - sendOnly2.On("Start", mock.Anything).Return(expectedError).Once() - - mn := newTestMultiNode(t, multiNodeOpts{ - selectionMode: NodeSelectionModeRoundRobin, - chainID: chainID, - nodes: []Node[types.ID, multiNodeRPCClient]{node}, - sendonlys: []SendOnlyNode[types.ID, multiNodeRPCClient]{sendOnly1, sendOnly2}, - }) - err := mn.Start(tests.Context(t)) - assert.ErrorIs(t, err, expectedError) - }) - t.Run("Starts successfully with healthy nodes", func(t *testing.T) { - t.Parallel() - chainID := types.NewIDFromInt(10) - node := newHealthyNode(t, chainID) - mn := newTestMultiNode(t, multiNodeOpts{ - selectionMode: NodeSelectionModeRoundRobin, - chainID: chainID, - nodes: []Node[types.ID, multiNodeRPCClient]{node}, - sendonlys: []SendOnlyNode[types.ID, multiNodeRPCClient]{newHealthySendOnly(t, chainID)}, - }) - servicetest.Run(t, mn) - selectedNode, err := mn.selectNode() - require.NoError(t, err) - assert.Equal(t, node, selectedNode) - }) -} - -func TestMultiNode_Report(t *testing.T) { - t.Parallel() - t.Run("Dial starts periodical reporting", func(t *testing.T) { - t.Parallel() - chainID := types.RandomID() - node1 := newHealthyNode(t, chainID) - node2 := newNodeWithState(t, chainID, nodeStateOutOfSync) - lggr, observedLogs := logger.TestObserved(t, zap.WarnLevel) - mn := newTestMultiNode(t, multiNodeOpts{ - selectionMode: NodeSelectionModeRoundRobin, - chainID: chainID, - nodes: []Node[types.ID, multiNodeRPCClient]{node1, node2}, - logger: lggr, - }) - mn.reportInterval = tests.TestInterval - mn.deathDeclarationDelay = tests.TestInterval - servicetest.Run(t, mn) - tests.AssertLogCountEventually(t, observedLogs, "At least one primary node is dead: 1/2 nodes are alive", 2) - }) - t.Run("Report critical error on all node failure", func(t *testing.T) { - t.Parallel() - chainID := types.RandomID() - node := newNodeWithState(t, chainID, nodeStateOutOfSync) - lggr, observedLogs := logger.TestObserved(t, zap.WarnLevel) - mn := newTestMultiNode(t, multiNodeOpts{ - selectionMode: NodeSelectionModeRoundRobin, - chainID: chainID, - nodes: []Node[types.ID, multiNodeRPCClient]{node}, - logger: lggr, - }) - mn.reportInterval = tests.TestInterval - mn.deathDeclarationDelay = tests.TestInterval - servicetest.Run(t, mn) - tests.AssertLogCountEventually(t, observedLogs, "no primary nodes available: 0/1 nodes are alive", 2) - err := mn.HealthReport()["MultiNode"] - require.Error(t, err) - assert.Contains(t, err.Error(), "no primary nodes available: 0/1 nodes are alive") - }) -} - -func TestMultiNode_CheckLease(t *testing.T) { - t.Parallel() - t.Run("Round robin disables lease check", func(t *testing.T) { - t.Parallel() - chainID := types.RandomID() - node := newHealthyNode(t, chainID) - lggr, observedLogs := logger.TestObserved(t, zap.InfoLevel) - mn := newTestMultiNode(t, multiNodeOpts{ - selectionMode: NodeSelectionModeRoundRobin, - chainID: chainID, - logger: lggr, - nodes: []Node[types.ID, multiNodeRPCClient]{node}, - }) - servicetest.Run(t, mn) - tests.RequireLogMessage(t, observedLogs, "Best node switching is disabled") - }) - t.Run("Misconfigured lease check period won't start", func(t *testing.T) { - t.Parallel() - chainID := types.RandomID() - node := newHealthyNode(t, chainID) - lggr, observedLogs := logger.TestObserved(t, zap.InfoLevel) - mn := newTestMultiNode(t, multiNodeOpts{ - selectionMode: NodeSelectionModeHighestHead, - chainID: chainID, - logger: lggr, - nodes: []Node[types.ID, multiNodeRPCClient]{node}, - leaseDuration: 0, - }) - servicetest.Run(t, mn) - tests.RequireLogMessage(t, observedLogs, "Best node switching is disabled") - }) - t.Run("Lease check updates active node", func(t *testing.T) { - t.Parallel() - chainID := types.RandomID() - node := newHealthyNode(t, chainID) - node.On("UnsubscribeAllExceptAliveLoop") - bestNode := newHealthyNode(t, chainID) - nodeSelector := newMockNodeSelector[types.ID, multiNodeRPCClient](t) - nodeSelector.On("Select").Return(bestNode) - lggr, observedLogs := logger.TestObserved(t, zap.InfoLevel) - mn := newTestMultiNode(t, multiNodeOpts{ - selectionMode: NodeSelectionModeHighestHead, - chainID: chainID, - logger: lggr, - nodes: []Node[types.ID, multiNodeRPCClient]{node, bestNode}, - leaseDuration: tests.TestInterval, - }) - mn.nodeSelector = nodeSelector - servicetest.Run(t, mn) - tests.AssertLogEventually(t, observedLogs, fmt.Sprintf("Switching to best node from %q to %q", node.String(), bestNode.String())) - tests.AssertEventually(t, func() bool { - mn.activeMu.RLock() - active := mn.activeNode - mn.activeMu.RUnlock() - return bestNode == active - }) - }) - t.Run("NodeStates returns proper states", func(t *testing.T) { - t.Parallel() - chainID := types.NewIDFromInt(10) - nodes := map[string]nodeState{ - "node_1": nodeStateAlive, - "node_2": nodeStateUnreachable, - "node_3": nodeStateDialed, - } - - opts := multiNodeOpts{ - selectionMode: NodeSelectionModeRoundRobin, - chainID: chainID, - } - - expectedResult := map[string]string{} - for name, state := range nodes { - node := newMockNode[types.ID, multiNodeRPCClient](t) - node.On("State").Return(state).Once() - node.On("Name").Return(name).Once() - opts.nodes = append(opts.nodes, node) - - sendOnly := newMockSendOnlyNode[types.ID, multiNodeRPCClient](t) - sendOnlyName := "send_only_" + name - sendOnly.On("State").Return(state).Once() - sendOnly.On("Name").Return(sendOnlyName).Once() - opts.sendonlys = append(opts.sendonlys, sendOnly) - - expectedResult[name] = state.String() - expectedResult[sendOnlyName] = state.String() - } - - mn := newTestMultiNode(t, opts) - states := mn.NodeStates() - assert.Equal(t, expectedResult, states) - }) -} - -func TestMultiNode_selectNode(t *testing.T) { - t.Parallel() - t.Run("Returns same node, if it's still healthy", func(t *testing.T) { - t.Parallel() - chainID := types.RandomID() - node1 := newMockNode[types.ID, multiNodeRPCClient](t) - node1.On("State").Return(nodeStateAlive).Once() - node1.On("String").Return("node1").Maybe() - node2 := newMockNode[types.ID, multiNodeRPCClient](t) - node2.On("String").Return("node2").Maybe() - mn := newTestMultiNode(t, multiNodeOpts{ - selectionMode: NodeSelectionModeRoundRobin, - chainID: chainID, - nodes: []Node[types.ID, multiNodeRPCClient]{node1, node2}, - }) - nodeSelector := newMockNodeSelector[types.ID, multiNodeRPCClient](t) - nodeSelector.On("Select").Return(node1).Once() - mn.nodeSelector = nodeSelector - prevActiveNode, err := mn.selectNode() - require.NoError(t, err) - require.Equal(t, node1.String(), prevActiveNode.String()) - 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() - chainID := types.RandomID() - oldBest := newMockNode[types.ID, multiNodeRPCClient](t) - oldBest.On("String").Return("oldBest").Maybe() - oldBest.On("UnsubscribeAllExceptAliveLoop") - newBest := newMockNode[types.ID, multiNodeRPCClient](t) - newBest.On("String").Return("newBest").Maybe() - mn := newTestMultiNode(t, multiNodeOpts{ - selectionMode: NodeSelectionModeRoundRobin, - chainID: chainID, - nodes: []Node[types.ID, multiNodeRPCClient]{oldBest, newBest}, - }) - nodeSelector := newMockNodeSelector[types.ID, multiNodeRPCClient](t) - nodeSelector.On("Select").Return(oldBest).Once() - mn.nodeSelector = nodeSelector - activeNode, err := mn.selectNode() - require.NoError(t, err) - require.Equal(t, oldBest.String(), activeNode.String()) - // old best died, so we should replace it - oldBest.On("State").Return(nodeStateOutOfSync).Twice() - nodeSelector.On("Select").Return(newBest).Once() - 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() - chainID := types.RandomID() - lggr, observedLogs := logger.TestObserved(t, zap.InfoLevel) - mn := newTestMultiNode(t, multiNodeOpts{ - selectionMode: NodeSelectionModeRoundRobin, - chainID: chainID, - logger: lggr, - }) - nodeSelector := newMockNodeSelector[types.ID, multiNodeRPCClient](t) - nodeSelector.On("Select").Return(nil).Once() - nodeSelector.On("Name").Return("MockedNodeSelector").Once() - mn.nodeSelector = nodeSelector - node, err := mn.selectNode() - require.EqualError(t, err, ErroringNodeError.Error()) - require.Nil(t, node) - tests.RequireLogMessage(t, observedLogs, "No live RPC nodes available") - }) -} - -func TestMultiNode_ChainInfo(t *testing.T) { - t.Parallel() - type nodeParams struct { - LatestChainInfo ChainInfo - HighestUserObservations ChainInfo - State nodeState - } - testCases := []struct { - Name string - ExpectedNLiveNodes int - ExpectedLatestChainInfo ChainInfo - ExpectedHighestUserObservations ChainInfo - NodeParams []nodeParams - }{ - { - Name: "no nodes", - ExpectedLatestChainInfo: ChainInfo{ - TotalDifficulty: big.NewInt(0), - }, - ExpectedHighestUserObservations: ChainInfo{ - TotalDifficulty: big.NewInt(0), - }, - }, - { - Name: "Best node is not healthy", - ExpectedNLiveNodes: 3, - ExpectedLatestChainInfo: ChainInfo{ - BlockNumber: 20, - FinalizedBlockNumber: 10, - TotalDifficulty: big.NewInt(10), - }, - ExpectedHighestUserObservations: ChainInfo{ - BlockNumber: 1005, - FinalizedBlockNumber: 995, - TotalDifficulty: big.NewInt(2005), - }, - NodeParams: []nodeParams{ - { - State: nodeStateOutOfSync, - LatestChainInfo: ChainInfo{ - BlockNumber: 1000, - FinalizedBlockNumber: 990, - TotalDifficulty: big.NewInt(2000), - }, - HighestUserObservations: ChainInfo{ - BlockNumber: 1005, - FinalizedBlockNumber: 995, - TotalDifficulty: big.NewInt(2005), - }, - }, - { - State: nodeStateAlive, - LatestChainInfo: ChainInfo{ - BlockNumber: 20, - FinalizedBlockNumber: 10, - TotalDifficulty: big.NewInt(9), - }, - HighestUserObservations: ChainInfo{ - BlockNumber: 25, - FinalizedBlockNumber: 15, - TotalDifficulty: big.NewInt(14), - }, - }, - { - State: nodeStateAlive, - LatestChainInfo: ChainInfo{ - BlockNumber: 19, - FinalizedBlockNumber: 9, - TotalDifficulty: big.NewInt(10), - }, - HighestUserObservations: ChainInfo{ - BlockNumber: 24, - FinalizedBlockNumber: 14, - TotalDifficulty: big.NewInt(15), - }, - }, - { - State: nodeStateAlive, - LatestChainInfo: ChainInfo{ - BlockNumber: 11, - FinalizedBlockNumber: 1, - TotalDifficulty: nil, - }, - HighestUserObservations: ChainInfo{ - BlockNumber: 16, - FinalizedBlockNumber: 6, - TotalDifficulty: nil, - }, - }, - }, - }, - } - - chainID := types.RandomID() - mn := newTestMultiNode(t, multiNodeOpts{ - selectionMode: NodeSelectionModeRoundRobin, - chainID: chainID, - }) - for i := range testCases { - tc := testCases[i] - t.Run(tc.Name, func(t *testing.T) { - for _, params := range tc.NodeParams { - node := newMockNode[types.ID, multiNodeRPCClient](t) - mn.primaryNodes = append(mn.primaryNodes, node) - node.On("StateAndLatest").Return(params.State, params.LatestChainInfo) - node.On("HighestUserObservations").Return(params.HighestUserObservations) - } - - nNodes, latestChainInfo := mn.LatestChainInfo() - assert.Equal(t, tc.ExpectedNLiveNodes, nNodes) - assert.Equal(t, tc.ExpectedLatestChainInfo, latestChainInfo) - - highestChainInfo := mn.HighestUserObservations() - assert.Equal(t, tc.ExpectedHighestUserObservations, highestChainInfo) - }) - } -} diff --git a/common/client/node.go b/common/client/node.go deleted file mode 100644 index 66161ac5d5f..00000000000 --- a/common/client/node.go +++ /dev/null @@ -1,336 +0,0 @@ -package client - -import ( - "context" - "errors" - "fmt" - "net/url" - "sync" - "time" - - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promauto" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/services" - - "github.com/smartcontractkit/chainlink/v2/common/types" -) - -const QueryTimeout = 10 * time.Second - -var errInvalidChainID = errors.New("invalid chain id") - -var ( - promPoolRPCNodeVerifies = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "pool_rpc_node_verifies", - Help: "The total number of chain ID verifications for the given RPC node", - }, []string{"network", "chainID", "nodeName"}) - promPoolRPCNodeVerifiesFailed = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "pool_rpc_node_verifies_failed", - Help: "The total number of failed chain ID verifications for the given RPC node", - }, []string{"network", "chainID", "nodeName"}) - promPoolRPCNodeVerifiesSuccess = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "pool_rpc_node_verifies_success", - Help: "The total number of successful chain ID verifications for the given RPC node", - }, []string{"network", "chainID", "nodeName"}) -) - -type NodeConfig interface { - PollFailureThreshold() uint32 - PollInterval() time.Duration - SelectionMode() string - SyncThreshold() uint32 - NodeIsSyncingEnabled() bool - FinalizedBlockPollInterval() time.Duration - EnforceRepeatableRead() bool - DeathDeclarationDelay() time.Duration - NewHeadsPollInterval() time.Duration -} - -type ChainConfig interface { - NodeNoNewHeadsThreshold() time.Duration - NoNewFinalizedHeadsThreshold() time.Duration - FinalityDepth() uint32 - FinalityTagEnabled() bool - FinalizedBlockOffset() uint32 -} - -type Node[ - CHAIN_ID types.ID, - RPC any, -] interface { - // State returns most accurate state of the Node on the moment of call. - // While some of the checks may be performed in the background and State may return cached value, critical, like - // `FinalizedBlockOutOfSync`, must be executed upon every call. - State() nodeState - // StateAndLatest returns nodeState with the latest ChainInfo observed by Node during current lifecycle. - StateAndLatest() (nodeState, ChainInfo) - // HighestUserObservations - returns highest ChainInfo ever observed by underlying RPC excluding results of health check requests - HighestUserObservations() ChainInfo - SetPoolChainInfoProvider(PoolChainInfoProvider) - // Name is a unique identifier for this node. - Name() string - // String - returns string representation of the node, useful for debugging (name + URLS used to connect to the RPC) - String() string - RPC() RPC - // UnsubscribeAllExceptAliveLoop - closes all subscriptions except the aliveLoop subscription - UnsubscribeAllExceptAliveLoop() - ConfiguredChainID() CHAIN_ID - // Order - returns priority order configured for the RPC - Order() int32 - // Start - starts health checks - Start(context.Context) error - Close() error -} - -type node[ - CHAIN_ID types.ID, - HEAD Head, - RPC RPCClient[CHAIN_ID, HEAD], -] struct { - services.StateMachine - lfcLog logger.Logger - name string - id int - chainID CHAIN_ID - nodePoolCfg NodeConfig - chainCfg ChainConfig - order int32 - chainFamily string - - ws *url.URL - http *url.URL - - rpc RPC - - stateMu sync.RWMutex // protects state* fields - state nodeState - - poolInfoProvider PoolChainInfoProvider - - stopCh services.StopChan - // wg waits for subsidiary goroutines - wg sync.WaitGroup - - healthCheckSubs []types.Subscription -} - -func NewNode[ - CHAIN_ID types.ID, - HEAD Head, - RPC RPCClient[CHAIN_ID, HEAD], -]( - nodeCfg NodeConfig, - chainCfg ChainConfig, - lggr logger.Logger, - wsuri *url.URL, - httpuri *url.URL, - name string, - id int, - chainID CHAIN_ID, - nodeOrder int32, - rpc RPC, - chainFamily string, -) Node[CHAIN_ID, RPC] { - n := new(node[CHAIN_ID, HEAD, RPC]) - n.name = name - n.id = id - n.chainID = chainID - n.nodePoolCfg = nodeCfg - n.chainCfg = chainCfg - n.order = nodeOrder - if wsuri != nil { - n.ws = wsuri - } - if httpuri != nil { - n.http = httpuri - } - n.stopCh = make(services.StopChan) - lggr = logger.Named(lggr, "Node") - lggr = logger.With(lggr, - "nodeTier", Primary.String(), - "nodeName", name, - "node", n.String(), - "chainID", chainID, - "nodeOrder", n.order, - ) - n.lfcLog = logger.Named(lggr, "Lifecycle") - n.rpc = rpc - n.chainFamily = chainFamily - return n -} - -func (n *node[CHAIN_ID, HEAD, RPC]) String() string { - s := fmt.Sprintf("(%s)%s", Primary.String(), n.name) - if n.ws != nil { - s = s + fmt.Sprintf(":%s", n.ws.String()) - } - if n.http != nil { - s = s + fmt.Sprintf(":%s", n.http.String()) - } - return s -} - -func (n *node[CHAIN_ID, HEAD, RPC]) ConfiguredChainID() (chainID CHAIN_ID) { - return n.chainID -} - -func (n *node[CHAIN_ID, HEAD, RPC]) Name() string { - return n.name -} - -func (n *node[CHAIN_ID, HEAD, RPC]) RPC() RPC { - return n.rpc -} - -// unsubscribeAllExceptAliveLoop is not thread-safe; it should only be called -// while holding the stateMu lock. -func (n *node[CHAIN_ID, HEAD, RPC]) unsubscribeAllExceptAliveLoop() { - n.rpc.UnsubscribeAllExcept(n.healthCheckSubs...) -} - -func (n *node[CHAIN_ID, HEAD, RPC]) UnsubscribeAllExceptAliveLoop() { - n.stateMu.Lock() - defer n.stateMu.Unlock() - n.unsubscribeAllExceptAliveLoop() -} - -func (n *node[CHAIN_ID, HEAD, RPC]) Close() error { - return n.StopOnce(n.name, n.close) -} - -func (n *node[CHAIN_ID, HEAD, RPC]) close() error { - defer func() { - n.wg.Wait() - n.rpc.Close() - }() - - n.stateMu.Lock() - defer n.stateMu.Unlock() - - close(n.stopCh) - n.state = nodeStateClosed - return nil -} - -// Start dials and verifies the node -// Should only be called once in a node's lifecycle -// Return value is necessary to conform to interface but this will never -// actually return an error. -func (n *node[CHAIN_ID, HEAD, RPC]) Start(startCtx context.Context) error { - return n.StartOnce(n.name, func() error { - n.start(startCtx) - return nil - }) -} - -// start initially dials the node and verifies chain ID -// This spins off lifecycle goroutines. -// Not thread-safe. -// Node lifecycle is synchronous: only one goroutine should be running at a -// time. -func (n *node[CHAIN_ID, HEAD, RPC]) start(startCtx context.Context) { - if n.state != nodeStateUndialed { - panic(fmt.Sprintf("cannot dial node with state %v", n.state)) - } - - if err := n.rpc.Dial(startCtx); err != nil { - n.lfcLog.Errorw("Dial failed: Node is unreachable", "err", err) - n.declareUnreachable() - return - } - n.setState(nodeStateDialed) - - state := n.verifyConn(startCtx, n.lfcLog) - n.declareState(state) -} - -// verifyChainID checks that connection to the node matches the given chain ID -// Not thread-safe -// Pure verifyChainID: does not mutate node "state" field. -func (n *node[CHAIN_ID, HEAD, RPC]) verifyChainID(callerCtx context.Context, lggr logger.Logger) nodeState { - promPoolRPCNodeVerifies.WithLabelValues(n.chainFamily, n.chainID.String(), n.name).Inc() - promFailed := func() { - promPoolRPCNodeVerifiesFailed.WithLabelValues(n.chainFamily, n.chainID.String(), n.name).Inc() - } - - st := n.getCachedState() - switch st { - case nodeStateClosed: - // The node is already closed, and any subsequent transition is invalid. - // To make spotting such transitions a bit easier, return the invalid node state. - return nodeStateLen - case nodeStateDialed, nodeStateOutOfSync, nodeStateInvalidChainID, nodeStateSyncing: - default: - panic(fmt.Sprintf("cannot verify node in state %v", st)) - } - - var chainID CHAIN_ID - var err error - if chainID, err = n.rpc.ChainID(callerCtx); err != nil { - promFailed() - lggr.Errorw("Failed to verify chain ID for node", "err", err, "nodeState", n.getCachedState()) - return nodeStateUnreachable - } else if chainID.String() != n.chainID.String() { - promFailed() - err = fmt.Errorf( - "rpc ChainID doesn't match local chain ID: RPC ID=%s, local ID=%s, node name=%s: %w", - chainID.String(), - n.chainID.String(), - n.name, - errInvalidChainID, - ) - lggr.Errorw("Failed to verify RPC node; remote endpoint returned the wrong chain ID", "err", err, "nodeState", n.getCachedState()) - return nodeStateInvalidChainID - } - - promPoolRPCNodeVerifiesSuccess.WithLabelValues(n.chainFamily, n.chainID.String(), n.name).Inc() - - return nodeStateAlive -} - -// createVerifiedConn - establishes new connection with the RPC and verifies that it's valid: chainID matches, and it's not syncing. -// Returns desired state if one of the verifications fails. Otherwise, returns nodeStateAlive. -func (n *node[CHAIN_ID, HEAD, RPC]) createVerifiedConn(ctx context.Context, lggr logger.Logger) nodeState { - if err := n.rpc.Dial(ctx); err != nil { - n.lfcLog.Errorw("Dial failed: Node is unreachable", "err", err, "nodeState", n.getCachedState()) - return nodeStateUnreachable - } - - return n.verifyConn(ctx, lggr) -} - -// verifyConn - verifies that current connection is valid: chainID matches, and it's not syncing. -// Returns desired state if one of the verifications fails. Otherwise, returns nodeStateAlive. -func (n *node[CHAIN_ID, HEAD, RPC]) verifyConn(ctx context.Context, lggr logger.Logger) nodeState { - state := n.verifyChainID(ctx, lggr) - if state != nodeStateAlive { - return state - } - - if n.nodePoolCfg.NodeIsSyncingEnabled() { - isSyncing, err := n.rpc.IsSyncing(ctx) - if err != nil { - lggr.Errorw("Unexpected error while verifying RPC node synchronization status", "err", err, "nodeState", n.getCachedState()) - return nodeStateUnreachable - } - - if isSyncing { - lggr.Errorw("Verification failed: Node is syncing", "nodeState", n.getCachedState()) - return nodeStateSyncing - } - } - - return nodeStateAlive -} - -func (n *node[CHAIN_ID, HEAD, RPC]) Order() int32 { - return n.order -} - -func (n *node[CHAIN_ID, HEAD, RPC]) newCtx() (context.Context, context.CancelFunc) { - ctx, cancel := n.stopCh.NewCtx() - ctx = CtxAddHealthCheckFlag(ctx) - return ctx, cancel -} diff --git a/common/client/node_fsm.go b/common/client/node_fsm.go deleted file mode 100644 index b707e9f4375..00000000000 --- a/common/client/node_fsm.go +++ /dev/null @@ -1,377 +0,0 @@ -package client - -import ( - "fmt" - - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promauto" -) - -var ( - promPoolRPCNodeTransitionsToAlive = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "pool_rpc_node_num_transitions_to_alive", - Help: transitionString(nodeStateAlive), - }, []string{"chainID", "nodeName"}) - promPoolRPCNodeTransitionsToInSync = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "pool_rpc_node_num_transitions_to_in_sync", - Help: fmt.Sprintf("%s to %s", transitionString(nodeStateOutOfSync), nodeStateAlive), - }, []string{"chainID", "nodeName"}) - promPoolRPCNodeTransitionsToOutOfSync = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "pool_rpc_node_num_transitions_to_out_of_sync", - Help: transitionString(nodeStateOutOfSync), - }, []string{"chainID", "nodeName"}) - promPoolRPCNodeTransitionsToUnreachable = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "pool_rpc_node_num_transitions_to_unreachable", - Help: transitionString(nodeStateUnreachable), - }, []string{"chainID", "nodeName"}) - promPoolRPCNodeTransitionsToInvalidChainID = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "pool_rpc_node_num_transitions_to_invalid_chain_id", - Help: transitionString(nodeStateInvalidChainID), - }, []string{"chainID", "nodeName"}) - promPoolRPCNodeTransitionsToUnusable = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "pool_rpc_node_num_transitions_to_unusable", - Help: transitionString(nodeStateUnusable), - }, []string{"chainID", "nodeName"}) - promPoolRPCNodeTransitionsToSyncing = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "pool_rpc_node_num_transitions_to_syncing", - Help: transitionString(nodeStateSyncing), - }, []string{"chainID", "nodeName"}) -) - -// nodeState represents the current state of the node -// Node is a FSM (finite state machine) -type nodeState int - -func (n nodeState) String() string { - switch n { - case nodeStateUndialed: - return "Undialed" - case nodeStateDialed: - return "Dialed" - case nodeStateInvalidChainID: - return "InvalidChainID" - case nodeStateAlive: - return "Alive" - case nodeStateUnreachable: - return "Unreachable" - case nodeStateUnusable: - return "Unusable" - case nodeStateOutOfSync: - return "OutOfSync" - case nodeStateClosed: - return "Closed" - case nodeStateSyncing: - return "Syncing" - case nodeStateFinalizedBlockOutOfSync: - return "FinalizedBlockOutOfSync" - default: - return fmt.Sprintf("nodeState(%d)", n) - } -} - -// GoString prints a prettier state -func (n nodeState) GoString() string { - return fmt.Sprintf("nodeState%s(%d)", n.String(), n) -} - -const ( - // nodeStateUndialed is the first state of a virgin node - nodeStateUndialed = nodeState(iota) - // nodeStateDialed is after a node has successfully dialed but before it has verified the correct chain ID - nodeStateDialed - // nodeStateInvalidChainID is after chain ID verification failed - nodeStateInvalidChainID - // nodeStateAlive is a healthy node after chain ID verification succeeded - nodeStateAlive - // nodeStateUnreachable is a node that cannot be dialed or has disconnected - nodeStateUnreachable - // nodeStateOutOfSync is a node that is accepting connections but exceeded - // the failure threshold without sending any new heads. It will be - // disconnected, then put into a revive loop and re-awakened after redial - // if a new head arrives - nodeStateOutOfSync - // nodeStateUnusable is a sendonly node that has an invalid URL that can never be reached - nodeStateUnusable - // nodeStateClosed is after the connection has been closed and the node is at the end of its lifecycle - nodeStateClosed - // nodeStateSyncing is a node that is actively back-filling blockchain. Usually, it's a newly set up node that is - // still syncing the chain. The main difference from `nodeStateOutOfSync` is that it represents state relative - // to other primary nodes configured in the MultiNode. In contrast, `nodeStateSyncing` represents the internal state of - // the node (RPC). - nodeStateSyncing - // nodeStateFinalizedBlockOutOfSync - node is lagging behind on latest finalized block - nodeStateFinalizedBlockOutOfSync - // nodeStateLen tracks the number of states - nodeStateLen -) - -// allNodeStates represents all possible states a node can be in -var allNodeStates []nodeState - -func init() { - for s := nodeState(0); s < nodeStateLen; s++ { - allNodeStates = append(allNodeStates, s) - } -} - -// FSM methods - -// State allows reading the current state of the node. -func (n *node[CHAIN_ID, HEAD, RPC]) State() nodeState { - n.stateMu.RLock() - defer n.stateMu.RUnlock() - return n.recalculateState() -} - -func (n *node[CHAIN_ID, HEAD, RPC]) getCachedState() nodeState { - n.stateMu.RLock() - defer n.stateMu.RUnlock() - return n.state -} - -func (n *node[CHAIN_ID, HEAD, RPC]) recalculateState() nodeState { - if n.state != nodeStateAlive { - return n.state - } - - // double check that node is not lagging on finalized block - if n.nodePoolCfg.EnforceRepeatableRead() && n.isFinalizedBlockOutOfSync() { - return nodeStateFinalizedBlockOutOfSync - } - - return nodeStateAlive -} - -func (n *node[CHAIN_ID, HEAD, RPC]) isFinalizedBlockOutOfSync() bool { - if n.poolInfoProvider == nil { - return false - } - - highestObservedByCaller := n.poolInfoProvider.HighestUserObservations() - latest, rpcHighest := n.rpc.GetInterceptedChainInfo() - isOutOfSync := false - if n.chainCfg.FinalityTagEnabled() { - isOutOfSync = latest.FinalizedBlockNumber < highestObservedByCaller.FinalizedBlockNumber-int64(n.chainCfg.FinalizedBlockOffset()) - } else { - isOutOfSync = latest.BlockNumber < highestObservedByCaller.BlockNumber-int64(n.chainCfg.FinalizedBlockOffset()) - } - - if isOutOfSync { - n.lfcLog.Debugw("finalized block is out of sync", "rpcLatestChainInfo", latest, "rpcHighest", rpcHighest, "highestObservedByCaller", highestObservedByCaller) - } - - return isOutOfSync -} - -// StateAndLatest returns nodeState with the latest ChainInfo observed by Node during current lifecycle. -func (n *node[CHAIN_ID, HEAD, RPC]) StateAndLatest() (nodeState, ChainInfo) { - n.stateMu.RLock() - defer n.stateMu.RUnlock() - latest, _ := n.rpc.GetInterceptedChainInfo() - return n.recalculateState(), latest -} - -// HighestUserObservations - returns highest ChainInfo ever observed by external user of the Node -func (n *node[CHAIN_ID, HEAD, RPC]) HighestUserObservations() ChainInfo { - _, highestUserObservations := n.rpc.GetInterceptedChainInfo() - return highestUserObservations -} -func (n *node[CHAIN_ID, HEAD, RPC]) SetPoolChainInfoProvider(poolInfoProvider PoolChainInfoProvider) { - n.poolInfoProvider = poolInfoProvider -} - -// setState is only used by internal state management methods. -// This is low-level; care should be taken by the caller to ensure the new state is a valid transition. -// State changes should always be synchronous: only one goroutine at a time should change state. -// n.stateMu should not be locked for long periods of time because external clients expect a timely response from n.State() -func (n *node[CHAIN_ID, HEAD, RPC]) setState(s nodeState) { - n.stateMu.Lock() - defer n.stateMu.Unlock() - n.state = s -} - -// declareXXX methods change the state and pass conrol off the new state -// management goroutine - -func (n *node[CHAIN_ID, HEAD, RPC]) declareAlive() { - n.transitionToAlive(func() { - n.lfcLog.Infow("RPC Node is online", "nodeState", n.state) - n.wg.Add(1) - go n.aliveLoop() - }) -} - -func (n *node[CHAIN_ID, HEAD, RPC]) transitionToAlive(fn func()) { - promPoolRPCNodeTransitionsToAlive.WithLabelValues(n.chainID.String(), n.name).Inc() - n.stateMu.Lock() - defer n.stateMu.Unlock() - if n.state == nodeStateClosed { - return - } - switch n.state { - case nodeStateDialed, nodeStateInvalidChainID, nodeStateSyncing: - n.state = nodeStateAlive - default: - panic(transitionFail(n.state, nodeStateAlive)) - } - fn() -} - -// declareInSync puts a node back into Alive state, allowing it to be used by -// pool consumers again -func (n *node[CHAIN_ID, HEAD, RPC]) declareInSync() { - n.transitionToInSync(func() { - n.lfcLog.Infow("RPC Node is back in sync", "nodeState", n.state) - n.wg.Add(1) - go n.aliveLoop() - }) -} - -func (n *node[CHAIN_ID, HEAD, RPC]) transitionToInSync(fn func()) { - promPoolRPCNodeTransitionsToAlive.WithLabelValues(n.chainID.String(), n.name).Inc() - promPoolRPCNodeTransitionsToInSync.WithLabelValues(n.chainID.String(), n.name).Inc() - n.stateMu.Lock() - defer n.stateMu.Unlock() - if n.state == nodeStateClosed { - return - } - switch n.state { - case nodeStateOutOfSync, nodeStateSyncing: - n.state = nodeStateAlive - default: - panic(transitionFail(n.state, nodeStateAlive)) - } - fn() -} - -// declareOutOfSync puts a node into OutOfSync state, disconnecting all current -// clients and making it unavailable for use until back in-sync. -func (n *node[CHAIN_ID, HEAD, RPC]) declareOutOfSync(syncIssues syncStatus) { - n.transitionToOutOfSync(func() { - n.lfcLog.Errorw("RPC Node is out of sync", "nodeState", n.state, "syncIssues", syncIssues) - n.wg.Add(1) - go n.outOfSyncLoop(syncIssues) - }) -} - -func (n *node[CHAIN_ID, HEAD, RPC]) transitionToOutOfSync(fn func()) { - promPoolRPCNodeTransitionsToOutOfSync.WithLabelValues(n.chainID.String(), n.name).Inc() - n.stateMu.Lock() - defer n.stateMu.Unlock() - if n.state == nodeStateClosed { - return - } - switch n.state { - case nodeStateAlive: - n.rpc.Close() - n.state = nodeStateOutOfSync - default: - panic(transitionFail(n.state, nodeStateOutOfSync)) - } - fn() -} - -func (n *node[CHAIN_ID, HEAD, RPC]) declareUnreachable() { - n.transitionToUnreachable(func() { - n.lfcLog.Errorw("RPC Node is unreachable", "nodeState", n.state) - n.wg.Add(1) - go n.unreachableLoop() - }) -} - -func (n *node[CHAIN_ID, HEAD, RPC]) transitionToUnreachable(fn func()) { - promPoolRPCNodeTransitionsToUnreachable.WithLabelValues(n.chainID.String(), n.name).Inc() - n.stateMu.Lock() - defer n.stateMu.Unlock() - if n.state == nodeStateClosed { - return - } - switch n.state { - case nodeStateUndialed, nodeStateDialed, nodeStateAlive, nodeStateOutOfSync, nodeStateInvalidChainID, nodeStateSyncing: - n.rpc.Close() - n.state = nodeStateUnreachable - default: - panic(transitionFail(n.state, nodeStateUnreachable)) - } - fn() -} - -func (n *node[CHAIN_ID, HEAD, RPC]) declareState(state nodeState) { - if n.getCachedState() == nodeStateClosed { - return - } - switch state { - case nodeStateInvalidChainID: - n.declareInvalidChainID() - case nodeStateUnreachable: - n.declareUnreachable() - case nodeStateSyncing: - n.declareSyncing() - case nodeStateAlive: - n.declareAlive() - default: - panic(fmt.Sprintf("%#v state declaration is not implemented", state)) - } -} - -func (n *node[CHAIN_ID, HEAD, RPC]) declareInvalidChainID() { - n.transitionToInvalidChainID(func() { - n.lfcLog.Errorw("RPC Node has the wrong chain ID", "nodeState", n.state) - n.wg.Add(1) - go n.invalidChainIDLoop() - }) -} - -func (n *node[CHAIN_ID, HEAD, RPC]) transitionToInvalidChainID(fn func()) { - promPoolRPCNodeTransitionsToInvalidChainID.WithLabelValues(n.chainID.String(), n.name).Inc() - n.stateMu.Lock() - defer n.stateMu.Unlock() - if n.state == nodeStateClosed { - return - } - switch n.state { - case nodeStateDialed, nodeStateOutOfSync, nodeStateSyncing: - n.rpc.Close() - n.state = nodeStateInvalidChainID - default: - panic(transitionFail(n.state, nodeStateInvalidChainID)) - } - fn() -} - -func (n *node[CHAIN_ID, HEAD, RPC]) declareSyncing() { - n.transitionToSyncing(func() { - n.lfcLog.Errorw("RPC Node is syncing", "nodeState", n.state) - n.wg.Add(1) - go n.syncingLoop() - }) -} - -func (n *node[CHAIN_ID, HEAD, RPC]) transitionToSyncing(fn func()) { - promPoolRPCNodeTransitionsToSyncing.WithLabelValues(n.chainID.String(), n.name).Inc() - n.stateMu.Lock() - defer n.stateMu.Unlock() - if n.state == nodeStateClosed { - return - } - switch n.state { - case nodeStateDialed, nodeStateOutOfSync, nodeStateInvalidChainID: - n.rpc.Close() - n.state = nodeStateSyncing - default: - panic(transitionFail(n.state, nodeStateSyncing)) - } - - if !n.nodePoolCfg.NodeIsSyncingEnabled() { - panic("unexpected transition to nodeStateSyncing, while it's disabled") - } - fn() -} - -func transitionString(state nodeState) string { - return fmt.Sprintf("Total number of times node has transitioned to %s", state) -} - -func transitionFail(from nodeState, to nodeState) string { - return fmt.Sprintf("cannot transition from %#v to %#v", from, to) -} diff --git a/common/client/node_fsm_test.go b/common/client/node_fsm_test.go deleted file mode 100644 index 93460d934a3..00000000000 --- a/common/client/node_fsm_test.go +++ /dev/null @@ -1,131 +0,0 @@ -package client - -import ( - "slices" - "strconv" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/smartcontractkit/chainlink/v2/common/types" -) - -type fnMock struct{ calls int } - -func (fm *fnMock) Fn() { - fm.calls++ -} - -func (fm *fnMock) AssertNotCalled(t *testing.T) { - assert.Equal(t, 0, fm.calls) -} - -func (fm *fnMock) AssertCalled(t *testing.T) { - assert.Greater(t, fm.calls, 0) -} - -func TestUnit_Node_StateTransitions(t *testing.T) { - t.Parallel() - - t.Run("setState", func(t *testing.T) { - n := newTestNode(t, testNodeOpts{rpc: nil, config: testNodeConfig{nodeIsSyncingEnabled: true}}) - assert.Equal(t, nodeStateUndialed, n.State()) - n.setState(nodeStateAlive) - assert.Equal(t, nodeStateAlive, n.State()) - n.setState(nodeStateUndialed) - assert.Equal(t, nodeStateUndialed, n.State()) - }) - - t.Run("transitionToAlive", func(t *testing.T) { - const destinationState = nodeStateAlive - allowedStates := []nodeState{nodeStateDialed, nodeStateInvalidChainID, nodeStateSyncing} - rpc := newMockRPCClient[types.ID, Head](t) - testTransition(t, rpc, testNode.transitionToAlive, destinationState, allowedStates...) - }) - - t.Run("transitionToInSync", func(t *testing.T) { - const destinationState = nodeStateAlive - allowedStates := []nodeState{nodeStateOutOfSync, nodeStateSyncing} - rpc := newMockRPCClient[types.ID, Head](t) - testTransition(t, rpc, testNode.transitionToInSync, destinationState, allowedStates...) - }) - t.Run("transitionToOutOfSync", func(t *testing.T) { - const destinationState = nodeStateOutOfSync - allowedStates := []nodeState{nodeStateAlive} - rpc := newMockRPCClient[types.ID, Head](t) - rpc.On("Close") - testTransition(t, rpc, testNode.transitionToOutOfSync, destinationState, allowedStates...) - }) - t.Run("transitionToUnreachable", func(t *testing.T) { - const destinationState = nodeStateUnreachable - allowedStates := []nodeState{nodeStateUndialed, nodeStateDialed, nodeStateAlive, nodeStateOutOfSync, nodeStateInvalidChainID, nodeStateSyncing} - rpc := newMockRPCClient[types.ID, Head](t) - rpc.On("Close") - testTransition(t, rpc, testNode.transitionToUnreachable, destinationState, allowedStates...) - }) - t.Run("transitionToInvalidChain", func(t *testing.T) { - const destinationState = nodeStateInvalidChainID - allowedStates := []nodeState{nodeStateDialed, nodeStateOutOfSync, nodeStateSyncing} - rpc := newMockRPCClient[types.ID, Head](t) - rpc.On("Close") - testTransition(t, rpc, testNode.transitionToInvalidChainID, destinationState, allowedStates...) - }) - t.Run("transitionToSyncing", func(t *testing.T) { - const destinationState = nodeStateSyncing - allowedStates := []nodeState{nodeStateDialed, nodeStateOutOfSync, nodeStateInvalidChainID} - rpc := newMockRPCClient[types.ID, Head](t) - rpc.On("Close") - testTransition(t, rpc, testNode.transitionToSyncing, destinationState, allowedStates...) - }) - t.Run("transitionToSyncing panics if nodeIsSyncing is disabled", func(t *testing.T) { - rpc := newMockRPCClient[types.ID, Head](t) - rpc.On("Close") - node := newTestNode(t, testNodeOpts{rpc: rpc}) - node.setState(nodeStateDialed) - fn := new(fnMock) - defer fn.AssertNotCalled(t) - assert.PanicsWithValue(t, "unexpected transition to nodeStateSyncing, while it's disabled", func() { - node.transitionToSyncing(fn.Fn) - }) - }) -} - -func testTransition(t *testing.T, rpc *mockRPCClient[types.ID, Head], transition func(node testNode, fn func()), destinationState nodeState, allowedStates ...nodeState) { - node := newTestNode(t, testNodeOpts{rpc: rpc, config: testNodeConfig{nodeIsSyncingEnabled: true}}) - for _, allowedState := range allowedStates { - m := new(fnMock) - node.setState(allowedState) - transition(node, m.Fn) - assert.Equal(t, destinationState, node.State(), "Expected node to successfully transition from %s to %s state", allowedState, destinationState) - m.AssertCalled(t) - } - // noop on attempt to transition from Closed state - m := new(fnMock) - node.setState(nodeStateClosed) - transition(node, m.Fn) - m.AssertNotCalled(t) - assert.Equal(t, nodeStateClosed, node.State(), "Expected node to remain in closed state on transition attempt") - - for _, nodeState := range allNodeStates { - if slices.Contains(allowedStates, nodeState) || nodeState == nodeStateClosed { - continue - } - - m := new(fnMock) - node.setState(nodeState) - assert.Panics(t, func() { - transition(node, m.Fn) - }, "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") - } -} - -func TestNodeState_String(t *testing.T) { - t.Run("Ensure all states are meaningful when converted to string", func(t *testing.T) { - for _, ns := range allNodeStates { - // ensure that string representation is not nodeState(%d) - assert.NotContains(t, ns.String(), strconv.FormatInt(int64(ns), 10), "Expected node state to have readable name") - } - }) -} diff --git a/common/client/node_lifecycle.go b/common/client/node_lifecycle.go deleted file mode 100644 index 6ec6a598eb2..00000000000 --- a/common/client/node_lifecycle.go +++ /dev/null @@ -1,700 +0,0 @@ -package client - -import ( - "context" - "fmt" - "math" - "math/big" - "time" - - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promauto" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/utils" - bigmath "github.com/smartcontractkit/chainlink-common/pkg/utils/big_math" - - iutils "github.com/smartcontractkit/chainlink/v2/common/internal/utils" - "github.com/smartcontractkit/chainlink/v2/common/types" -) - -var ( - promPoolRPCNodeHighestSeenBlock = promauto.NewGaugeVec(prometheus.GaugeOpts{ - Name: "pool_rpc_node_highest_seen_block", - Help: "The highest seen block for the given RPC node", - }, []string{"chainID", "nodeName"}) - promPoolRPCNodeHighestFinalizedBlock = promauto.NewGaugeVec(prometheus.GaugeOpts{ - Name: "pool_rpc_node_highest_finalized_block", - Help: "The highest seen finalized block for the given RPC node", - }, []string{"chainID", "nodeName"}) - promPoolRPCNodeNumSeenBlocks = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "pool_rpc_node_num_seen_blocks", - Help: "The total number of new blocks seen by the given RPC node", - }, []string{"chainID", "nodeName"}) - promPoolRPCNodePolls = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "pool_rpc_node_polls_total", - Help: "The total number of poll checks for the given RPC node", - }, []string{"chainID", "nodeName"}) - promPoolRPCNodePollsFailed = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "pool_rpc_node_polls_failed", - Help: "The total number of failed poll checks for the given RPC node", - }, []string{"chainID", "nodeName"}) - promPoolRPCNodePollsSuccess = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "pool_rpc_node_polls_success", - Help: "The total number of successful poll checks for the given RPC node", - }, []string{"chainID", "nodeName"}) -) - -// zombieNodeCheckInterval controls how often to re-check to see if we need to -// state change in case we have to force a state transition due to no available -// nodes. -// NOTE: This only applies to out-of-sync nodes if they are the last available node -func zombieNodeCheckInterval(noNewHeadsThreshold time.Duration) time.Duration { - interval := noNewHeadsThreshold - if interval <= 0 || interval > QueryTimeout { - interval = QueryTimeout - } - return utils.WithJitter(interval) -} - -const ( - msgCannotDisable = "but cannot disable this connection because there are no other RPC endpoints, or all other RPC endpoints are dead." - msgDegradedState = "Chainlink is now operating in a degraded state and urgent action is required to resolve the issue" -) - -// Node is a FSM -// Each state has a loop that goes with it, which monitors the node and moves it into another state as necessary. -// Only one loop must run at a time. -// Each loop passes control onto the next loop as it exits, except when the node is Closed which terminates the loop permanently. - -// This handles node lifecycle for the ALIVE state -// Should only be run ONCE per node, after a successful Dial -func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { - defer n.wg.Done() - ctx, cancel := n.newCtx() - defer cancel() - - { - // sanity check - state := n.getCachedState() - switch state { - case nodeStateAlive: - case nodeStateClosed: - return - default: - panic(fmt.Sprintf("aliveLoop can only run for node in Alive state, got: %s", state)) - } - } - - noNewHeadsTimeoutThreshold := n.chainCfg.NodeNoNewHeadsThreshold() - noNewFinalizedBlocksTimeoutThreshold := n.chainCfg.NoNewFinalizedHeadsThreshold() - pollFailureThreshold := n.nodePoolCfg.PollFailureThreshold() - pollInterval := n.nodePoolCfg.PollInterval() - - lggr := logger.Sugared(n.lfcLog).Named("Alive").With("noNewHeadsTimeoutThreshold", noNewHeadsTimeoutThreshold, "pollInterval", pollInterval, "pollFailureThreshold", pollFailureThreshold) - lggr.Tracew("Alive loop starting", "nodeState", n.getCachedState()) - - headsSub, err := n.registerNewSubscription(ctx, lggr.With("subscriptionType", "heads"), - n.chainCfg.NodeNoNewHeadsThreshold(), n.rpc.SubscribeToHeads) - if err != nil { - lggr.Errorw("Initial subscribe for heads failed", "nodeState", n.getCachedState(), "err", err) - n.declareUnreachable() - return - } - - defer n.unsubscribeHealthChecks() - - var pollCh <-chan time.Time - if pollInterval > 0 { - lggr.Debug("Polling enabled") - pollT := time.NewTicker(pollInterval) - defer pollT.Stop() - pollCh = pollT.C - if pollFailureThreshold > 0 { - // polling can be enabled with no threshold to enable polling but - // the node will not be marked offline regardless of the number of - // poll failures - lggr.Debug("Polling liveness checking enabled") - } - } else { - lggr.Debug("Polling disabled") - } - - var finalizedHeadsSub headSubscription[HEAD] - if n.chainCfg.FinalityTagEnabled() { - finalizedHeadsSub, err = n.registerNewSubscription(ctx, lggr.With("subscriptionType", "finalizedHeads"), - n.chainCfg.NoNewFinalizedHeadsThreshold(), n.rpc.SubscribeToFinalizedHeads) - if err != nil { - lggr.Errorw("Failed to subscribe to finalized heads", "err", err) - n.declareUnreachable() - return - } - } - - // Get the latest chain info to use as local highest - localHighestChainInfo, _ := n.rpc.GetInterceptedChainInfo() - var pollFailures uint32 - - for { - select { - case <-ctx.Done(): - return - case <-pollCh: - promPoolRPCNodePolls.WithLabelValues(n.chainID.String(), n.name).Inc() - lggr.Tracew("Pinging RPC", "nodeState", n.State(), "pollFailures", pollFailures) - pollCtx, cancel := context.WithTimeout(ctx, pollInterval) - err = n.RPC().Ping(pollCtx) - cancel() - if err != nil { - // prevent overflow - if pollFailures < math.MaxUint32 { - promPoolRPCNodePollsFailed.WithLabelValues(n.chainID.String(), n.name).Inc() - pollFailures++ - } - lggr.Warnw(fmt.Sprintf("Poll failure, RPC endpoint %s failed to respond properly", n.String()), "err", err, "pollFailures", pollFailures, "nodeState", n.getCachedState()) - } else { - lggr.Debugw("Ping successful", "nodeState", n.State()) - promPoolRPCNodePollsSuccess.WithLabelValues(n.chainID.String(), n.name).Inc() - pollFailures = 0 - } - if pollFailureThreshold > 0 && pollFailures >= pollFailureThreshold { - lggr.Errorw(fmt.Sprintf("RPC endpoint failed to respond to %d consecutive polls", pollFailures), "pollFailures", pollFailures, "nodeState", n.getCachedState()) - if n.poolInfoProvider != nil { - if l, _ := n.poolInfoProvider.LatestChainInfo(); l < 2 { - lggr.Criticalf("RPC endpoint failed to respond to polls; %s %s", msgCannotDisable, msgDegradedState) - continue - } - } - n.declareUnreachable() - return - } - if outOfSync, liveNodes := n.isOutOfSyncWithPool(); outOfSync { - // note: there must be another live node for us to be out of sync - if liveNodes < 2 { - lggr.Criticalf("RPC endpoint has fallen behind; %s %s", msgCannotDisable, msgDegradedState) - continue - } - n.declareOutOfSync(syncStatusNotInSyncWithPool) - return - } - case bh, open := <-headsSub.Heads: - if !open { - lggr.Errorw("Subscription channel unexpectedly closed", "nodeState", n.getCachedState()) - n.declareUnreachable() - return - } - receivedNewHead := n.onNewHead(lggr, &localHighestChainInfo, bh) - if receivedNewHead && noNewHeadsTimeoutThreshold > 0 { - headsSub.ResetTimer(noNewHeadsTimeoutThreshold) - } - case err = <-headsSub.Errors: - lggr.Errorw("Subscription was terminated", "err", err, "nodeState", n.getCachedState()) - n.declareUnreachable() - return - case <-headsSub.NoNewHeads: - // We haven't received a head on the channel for at least the - // threshold amount of time, mark it broken - lggr.Errorw(fmt.Sprintf("RPC endpoint detected out of sync; no new heads received for %s (last head received was %v)", noNewHeadsTimeoutThreshold, localHighestChainInfo.BlockNumber), "nodeState", n.getCachedState(), "latestReceivedBlockNumber", localHighestChainInfo.BlockNumber, "noNewHeadsTimeoutThreshold", noNewHeadsTimeoutThreshold) - if n.poolInfoProvider != nil { - if l, _ := n.poolInfoProvider.LatestChainInfo(); l < 2 { - lggr.Criticalf("RPC endpoint detected out of sync; %s %s", msgCannotDisable, msgDegradedState) - // We don't necessarily want to wait the full timeout to check again, we should - // check regularly and log noisily in this state - headsSub.ResetTimer(zombieNodeCheckInterval(noNewHeadsTimeoutThreshold)) - continue - } - } - n.declareOutOfSync(syncStatusNoNewHead) - return - case latestFinalized, open := <-finalizedHeadsSub.Heads: - if !open { - lggr.Errorw("Finalized heads subscription channel unexpectedly closed") - n.declareUnreachable() - return - } - - receivedNewHead := n.onNewFinalizedHead(lggr, &localHighestChainInfo, latestFinalized) - if receivedNewHead && noNewFinalizedBlocksTimeoutThreshold > 0 { - finalizedHeadsSub.ResetTimer(noNewFinalizedBlocksTimeoutThreshold) - } - case <-finalizedHeadsSub.NoNewHeads: - // We haven't received a finalized head on the channel for at least the - // threshold amount of time, mark it broken - lggr.Errorw(fmt.Sprintf("RPC's finalized state is out of sync; no new finalized heads received for %s (last finalized head received was %v)", noNewFinalizedBlocksTimeoutThreshold, localHighestChainInfo.FinalizedBlockNumber), "latestReceivedBlockNumber", localHighestChainInfo.BlockNumber) - if n.poolInfoProvider != nil { - if l, _ := n.poolInfoProvider.LatestChainInfo(); l < 2 { - lggr.Criticalf("RPC's finalized state is out of sync; %s %s", msgCannotDisable, msgDegradedState) - // We don't necessarily want to wait the full timeout to check again, we should - // check regularly and log noisily in this state - finalizedHeadsSub.ResetTimer(zombieNodeCheckInterval(noNewFinalizedBlocksTimeoutThreshold)) - continue - } - } - n.declareOutOfSync(syncStatusNoNewFinalizedHead) - return - case <-finalizedHeadsSub.Errors: - lggr.Errorw("Finalized heads subscription was terminated", "err", err) - n.declareUnreachable() - return - } - } -} - -func (n *node[CHAIN_ID, HEAD, RPC]) unsubscribeHealthChecks() { - n.stateMu.Lock() - for _, sub := range n.healthCheckSubs { - sub.Unsubscribe() - } - n.healthCheckSubs = []types.Subscription{} - n.stateMu.Unlock() -} - -type headSubscription[HEAD any] struct { - Heads <-chan HEAD - Errors <-chan error - NoNewHeads <-chan time.Time - - noNewHeadsTicker *time.Ticker - sub types.Subscription - cleanUpTasks []func() -} - -func (sub *headSubscription[HEAD]) ResetTimer(duration time.Duration) { - sub.noNewHeadsTicker.Reset(duration) -} - -func (sub *headSubscription[HEAD]) Unsubscribe() { - for _, doCleanUp := range sub.cleanUpTasks { - doCleanUp() - } -} - -func (n *node[CHAIN_ID, HEAD, PRC]) registerNewSubscription(ctx context.Context, lggr logger.SugaredLogger, - noNewDataThreshold time.Duration, newSub func(ctx context.Context) (<-chan HEAD, types.Subscription, error)) (headSubscription[HEAD], error) { - result := headSubscription[HEAD]{} - var err error - var sub types.Subscription - result.Heads, sub, err = newSub(ctx) - if err != nil { - return result, err - } - - result.Errors = sub.Err() - lggr.Debug("Successfully subscribed") - - result.sub = sub - n.stateMu.Lock() - n.healthCheckSubs = append(n.healthCheckSubs, sub) - n.stateMu.Unlock() - - result.cleanUpTasks = append(result.cleanUpTasks, sub.Unsubscribe) - - if noNewDataThreshold > 0 { - lggr.Debugw("Subscription liveness checking enabled") - result.noNewHeadsTicker = time.NewTicker(noNewDataThreshold) - result.NoNewHeads = result.noNewHeadsTicker.C - result.cleanUpTasks = append(result.cleanUpTasks, result.noNewHeadsTicker.Stop) - } else { - lggr.Debug("Subscription liveness checking disabled") - } - - return result, nil -} - -func (n *node[CHAIN_ID, HEAD, RPC]) onNewFinalizedHead(lggr logger.SugaredLogger, chainInfo *ChainInfo, latestFinalized HEAD) bool { - if !latestFinalized.IsValid() { - lggr.Warn("Latest finalized block is not valid") - return false - } - - latestFinalizedBN := latestFinalized.BlockNumber() - lggr.Debugw("Got latest finalized head", "latestFinalized", latestFinalized) - if latestFinalizedBN <= chainInfo.FinalizedBlockNumber { - lggr.Debugw("Ignoring previously seen finalized block number") - return false - } - - promPoolRPCNodeHighestFinalizedBlock.WithLabelValues(n.chainID.String(), n.name).Set(float64(latestFinalizedBN)) - chainInfo.FinalizedBlockNumber = latestFinalizedBN - return true -} - -func (n *node[CHAIN_ID, HEAD, RPC]) onNewHead(lggr logger.SugaredLogger, chainInfo *ChainInfo, head HEAD) bool { - if !head.IsValid() { - lggr.Warn("Latest head is not valid") - return false - } - - promPoolRPCNodeNumSeenBlocks.WithLabelValues(n.chainID.String(), n.name).Inc() - lggr.Debugw("Got head", "head", head) - lggr = lggr.With("latestReceivedBlockNumber", chainInfo.BlockNumber, "blockNumber", head.BlockNumber(), "nodeState", n.getCachedState()) - if head.BlockNumber() <= chainInfo.BlockNumber { - lggr.Debugw("Ignoring previously seen block number") - return false - } - - promPoolRPCNodeHighestSeenBlock.WithLabelValues(n.chainID.String(), n.name).Set(float64(head.BlockNumber())) - chainInfo.BlockNumber = head.BlockNumber() - - if !n.chainCfg.FinalityTagEnabled() { - latestFinalizedBN := max(head.BlockNumber()-int64(n.chainCfg.FinalityDepth()), 0) - if latestFinalizedBN > chainInfo.FinalizedBlockNumber { - promPoolRPCNodeHighestFinalizedBlock.WithLabelValues(n.chainID.String(), n.name).Set(float64(latestFinalizedBN)) - chainInfo.FinalizedBlockNumber = latestFinalizedBN - } - } - - return true -} - -const ( - msgReceivedBlock = "Received block for RPC node, waiting until back in-sync to mark as live again" - msgReceivedFinalizedBlock = "Received new finalized block for RPC node, waiting until back in-sync to mark as live again" - msgInSync = "RPC node back in sync" -) - -// isOutOfSyncWithPool returns outOfSync true if num or td is more than SyncThresold behind the best node. -// Always returns outOfSync false for SyncThreshold 0. -// liveNodes is only included when outOfSync is true. -func (n *node[CHAIN_ID, HEAD, RPC]) isOutOfSyncWithPool() (outOfSync bool, liveNodes int) { - if n.poolInfoProvider == nil { - n.lfcLog.Warn("skipping sync state against the pool - should only occur in tests") - return // skip for tests - } - threshold := n.nodePoolCfg.SyncThreshold() - if threshold == 0 { - return // disabled - } - // Check against best node - ln, ci := n.poolInfoProvider.LatestChainInfo() - localChainInfo, _ := n.rpc.GetInterceptedChainInfo() - mode := n.nodePoolCfg.SelectionMode() - switch mode { - case NodeSelectionModeHighestHead, NodeSelectionModeRoundRobin, NodeSelectionModePriorityLevel: - outOfSync = localChainInfo.BlockNumber < ci.BlockNumber-int64(threshold) - case NodeSelectionModeTotalDifficulty: - bigThreshold := big.NewInt(int64(threshold)) - outOfSync = localChainInfo.TotalDifficulty.Cmp(bigmath.Sub(ci.TotalDifficulty, bigThreshold)) < 0 - default: - panic("unrecognized NodeSelectionMode: " + mode) - } - - if outOfSync && n.getCachedState() == nodeStateAlive { - n.lfcLog.Errorw("RPC endpoint has fallen behind", "blockNumber", localChainInfo.BlockNumber, "bestLatestBlockNumber", ci.BlockNumber, "totalDifficulty", localChainInfo.TotalDifficulty) - } - return outOfSync, ln -} - -// outOfSyncLoop takes an OutOfSync node and waits until isOutOfSync returns false to go back to live status -func (n *node[CHAIN_ID, HEAD, RPC]) outOfSyncLoop(syncIssues syncStatus) { - defer n.wg.Done() - ctx, cancel := n.newCtx() - defer cancel() - - { - // sanity check - state := n.getCachedState() - switch state { - case nodeStateOutOfSync: - case nodeStateClosed: - return - default: - panic(fmt.Sprintf("outOfSyncLoop can only run for node in OutOfSync state, got: %s", state)) - } - } - - outOfSyncAt := time.Now() - - // set logger name to OutOfSync or FinalizedBlockOutOfSync - lggr := logger.Sugared(logger.Named(n.lfcLog, n.getCachedState().String())).With("nodeState", n.getCachedState()) - lggr.Debugw("Trying to revive out-of-sync RPC node") - - // Need to redial since out-of-sync nodes are automatically disconnected - state := n.createVerifiedConn(ctx, lggr) - if state != nodeStateAlive { - n.declareState(state) - return - } - - noNewHeadsTimeoutThreshold := n.chainCfg.NodeNoNewHeadsThreshold() - headsSub, err := n.registerNewSubscription(ctx, lggr.With("subscriptionType", "heads"), - noNewHeadsTimeoutThreshold, n.rpc.SubscribeToHeads) - if err != nil { - lggr.Errorw("Failed to subscribe heads on out-of-sync RPC node", "err", err) - n.declareUnreachable() - return - } - - defer n.unsubscribeHealthChecks() - - lggr.Tracew("Successfully subscribed to heads feed on out-of-sync RPC node") - - noNewFinalizedBlocksTimeoutThreshold := n.chainCfg.NoNewFinalizedHeadsThreshold() - var finalizedHeadsSub headSubscription[HEAD] - if n.chainCfg.FinalityTagEnabled() { - finalizedHeadsSub, err = n.registerNewSubscription(ctx, lggr.With("subscriptionType", "finalizedHeads"), - noNewFinalizedBlocksTimeoutThreshold, n.rpc.SubscribeToFinalizedHeads) - if err != nil { - lggr.Errorw("Subscribe to finalized heads failed on out-of-sync RPC node", "err", err) - n.declareUnreachable() - return - } - - lggr.Tracew("Successfully subscribed to finalized heads feed on out-of-sync RPC node") - } - - _, localHighestChainInfo := n.rpc.GetInterceptedChainInfo() - for { - if syncIssues == syncStatusSynced { - // back in-sync! flip back into alive loop - lggr.Infow(fmt.Sprintf("%s: %s. Node was out-of-sync for %s", msgInSync, n.String(), time.Since(outOfSyncAt))) - n.declareInSync() - return - } - - select { - case <-ctx.Done(): - return - case head, open := <-headsSub.Heads: - if !open { - lggr.Errorw("Subscription channel unexpectedly closed", "nodeState", n.getCachedState()) - n.declareUnreachable() - return - } - - if !n.onNewHead(lggr, &localHighestChainInfo, head) { - continue - } - - // received a new head - clear NoNewHead flag - syncIssues &= ^syncStatusNoNewHead - if outOfSync, _ := n.isOutOfSyncWithPool(); !outOfSync { - // we caught up with the pool - clear NotInSyncWithPool flag - syncIssues &= ^syncStatusNotInSyncWithPool - } else { - // we've received new head, but lagging behind the pool, add NotInSyncWithPool flag to prevent false transition to alive - syncIssues |= syncStatusNotInSyncWithPool - } - - if noNewHeadsTimeoutThreshold > 0 { - headsSub.ResetTimer(noNewHeadsTimeoutThreshold) - } - - lggr.Debugw(msgReceivedBlock, "blockNumber", head.BlockNumber(), "blockDifficulty", head.BlockDifficulty(), "syncIssues", syncIssues) - case <-time.After(zombieNodeCheckInterval(noNewHeadsTimeoutThreshold)): - if n.poolInfoProvider != nil { - if l, _ := n.poolInfoProvider.LatestChainInfo(); l < 1 { - lggr.Criticalw("RPC endpoint is still out of sync, but there are no other available nodes. This RPC node will be forcibly moved back into the live pool in a degraded state", "syncIssues", syncIssues) - n.declareInSync() - return - } - } - case err := <-headsSub.Errors: - lggr.Errorw("Subscription was terminated", "err", err) - n.declareUnreachable() - return - case <-headsSub.NoNewHeads: - // we are not resetting the timer, as there is no need to add syncStatusNoNewHead until it's removed on new head. - syncIssues |= syncStatusNoNewHead - lggr.Debugw(fmt.Sprintf("No new heads received for %s. Node stays out-of-sync due to sync issues: %s", noNewHeadsTimeoutThreshold, syncIssues)) - case latestFinalized, open := <-finalizedHeadsSub.Heads: - if !open { - lggr.Errorw("Finalized heads subscription channel unexpectedly closed") - n.declareUnreachable() - return - } - if !latestFinalized.IsValid() { - lggr.Warn("Latest finalized block is not valid") - continue - } - - receivedNewHead := n.onNewFinalizedHead(lggr, &localHighestChainInfo, latestFinalized) - if !receivedNewHead { - continue - } - - // on new finalized head remove NoNewFinalizedHead flag from the mask - syncIssues &= ^syncStatusNoNewFinalizedHead - if noNewFinalizedBlocksTimeoutThreshold > 0 { - finalizedHeadsSub.ResetTimer(noNewFinalizedBlocksTimeoutThreshold) - } - - var highestSeen ChainInfo - if n.poolInfoProvider != nil { - highestSeen = n.poolInfoProvider.HighestUserObservations() - } - - lggr.Debugw(msgReceivedFinalizedBlock, "blockNumber", latestFinalized.BlockNumber(), "poolHighestBlockNumber", highestSeen.FinalizedBlockNumber, "syncIssues", syncIssues) - case err := <-finalizedHeadsSub.Errors: - lggr.Errorw("Finalized head subscription was terminated", "err", err) - n.declareUnreachable() - return - case <-finalizedHeadsSub.NoNewHeads: - // we are not resetting the timer, as there is no need to add syncStatusNoNewFinalizedHead until it's removed on new finalized head. - syncIssues |= syncStatusNoNewFinalizedHead - lggr.Debugw(fmt.Sprintf("No new finalized heads received for %s. Node stays out-of-sync due to sync issues: %s", noNewFinalizedBlocksTimeoutThreshold, syncIssues)) - } - } -} - -func (n *node[CHAIN_ID, HEAD, RPC]) unreachableLoop() { - defer n.wg.Done() - ctx, cancel := n.newCtx() - defer cancel() - - { - // sanity check - state := n.getCachedState() - switch state { - case nodeStateUnreachable: - case nodeStateClosed: - return - default: - panic(fmt.Sprintf("unreachableLoop can only run for node in Unreachable state, got: %s", state)) - } - } - - unreachableAt := time.Now() - - lggr := logger.Sugared(logger.Named(n.lfcLog, "Unreachable")) - lggr.Debugw("Trying to revive unreachable RPC node", "nodeState", n.getCachedState()) - - dialRetryBackoff := iutils.NewRedialBackoff() - - for { - select { - case <-ctx.Done(): - return - case <-time.After(dialRetryBackoff.Duration()): - lggr.Tracew("Trying to re-dial RPC node", "nodeState", n.getCachedState()) - - err := n.rpc.Dial(ctx) - if err != nil { - lggr.Errorw(fmt.Sprintf("Failed to redial RPC node; still unreachable: %v", err), "err", err, "nodeState", n.getCachedState()) - continue - } - - n.setState(nodeStateDialed) - - state := n.verifyConn(ctx, lggr) - switch state { - case nodeStateUnreachable: - n.setState(nodeStateUnreachable) - continue - case nodeStateAlive: - lggr.Infow(fmt.Sprintf("Successfully redialled and verified RPC node %s. Node was offline for %s", n.String(), time.Since(unreachableAt)), "nodeState", n.getCachedState()) - fallthrough - default: - n.declareState(state) - return - } - } - } -} - -func (n *node[CHAIN_ID, HEAD, RPC]) invalidChainIDLoop() { - defer n.wg.Done() - ctx, cancel := n.newCtx() - defer cancel() - - { - // sanity check - state := n.getCachedState() - switch state { - case nodeStateInvalidChainID: - case nodeStateClosed: - return - default: - panic(fmt.Sprintf("invalidChainIDLoop can only run for node in InvalidChainID state, got: %s", state)) - } - } - - invalidAt := time.Now() - - lggr := logger.Named(n.lfcLog, "InvalidChainID") - - // Need to redial since invalid chain ID nodes are automatically disconnected - state := n.createVerifiedConn(ctx, lggr) - if state != nodeStateInvalidChainID { - n.declareState(state) - return - } - - lggr.Debugw(fmt.Sprintf("Periodically re-checking RPC node %s with invalid chain ID", n.String()), "nodeState", n.getCachedState()) - - chainIDRecheckBackoff := iutils.NewRedialBackoff() - - for { - select { - case <-ctx.Done(): - return - case <-time.After(chainIDRecheckBackoff.Duration()): - state := n.verifyConn(ctx, lggr) - switch state { - case nodeStateInvalidChainID: - continue - case nodeStateAlive: - lggr.Infow(fmt.Sprintf("Successfully verified RPC node. Node was offline for %s", time.Since(invalidAt)), "nodeState", n.getCachedState()) - fallthrough - default: - n.declareState(state) - return - } - } - } -} - -func (n *node[CHAIN_ID, HEAD, RPC]) syncingLoop() { - defer n.wg.Done() - ctx, cancel := n.newCtx() - defer cancel() - - { - // sanity check - state := n.getCachedState() - switch state { - case nodeStateSyncing: - case nodeStateClosed: - return - default: - panic(fmt.Sprintf("syncingLoop can only run for node in NodeStateSyncing state, got: %s", state)) - } - } - - syncingAt := time.Now() - - lggr := logger.Sugared(logger.Named(n.lfcLog, "Syncing")) - lggr.Debugw(fmt.Sprintf("Periodically re-checking RPC node %s with syncing status", n.String()), "nodeState", n.getCachedState()) - // Need to redial since syncing nodes are automatically disconnected - state := n.createVerifiedConn(ctx, lggr) - if state != nodeStateSyncing { - n.declareState(state) - return - } - - recheckBackoff := iutils.NewRedialBackoff() - - for { - select { - case <-ctx.Done(): - return - case <-time.After(recheckBackoff.Duration()): - lggr.Tracew("Trying to recheck if the node is still syncing", "nodeState", n.getCachedState()) - isSyncing, err := n.rpc.IsSyncing(ctx) - if err != nil { - lggr.Errorw("Unexpected error while verifying RPC node synchronization status", "err", err, "nodeState", n.getCachedState()) - n.declareUnreachable() - return - } - - if isSyncing { - lggr.Errorw("Verification failed: Node is syncing", "nodeState", n.getCachedState()) - continue - } - - lggr.Infow(fmt.Sprintf("Successfully verified RPC node. Node was syncing for %s", time.Since(syncingAt)), "nodeState", n.getCachedState()) - n.declareAlive() - return - } - } -} diff --git a/common/client/node_lifecycle_test.go b/common/client/node_lifecycle_test.go deleted file mode 100644 index 39c39e318ef..00000000000 --- a/common/client/node_lifecycle_test.go +++ /dev/null @@ -1,1983 +0,0 @@ -package client - -import ( - "errors" - "fmt" - "math/big" - "sync" - "sync/atomic" - "testing" - - "github.com/cometbft/cometbft/libs/rand" - prom "github.com/prometheus/client_model/go" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - "go.uber.org/zap" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - - clientMocks "github.com/smartcontractkit/chainlink/v2/common/client/mocks" - "github.com/smartcontractkit/chainlink/v2/common/types" - "github.com/smartcontractkit/chainlink/v2/common/types/mocks" -) - -func newSub(t *testing.T) *mocks.Subscription { - sub := mocks.NewSubscription(t) - sub.On("Err").Return((<-chan error)(nil)).Maybe() - sub.On("Unsubscribe") - return sub -} - -func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { - t.Parallel() - - newDialedNode := func(t *testing.T, opts testNodeOpts) testNode { - node := newTestNode(t, opts) - opts.rpc.On("Close").Return(nil) - - node.setState(nodeStateDialed) - return node - } - - t.Run("returns on closed", func(t *testing.T) { - node := newTestNode(t, testNodeOpts{}) - node.setState(nodeStateClosed) - node.wg.Add(1) - node.aliveLoop() - }) - t.Run("if initial subscribe fails, transitions to unreachable", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - node := newDialedNode(t, testNodeOpts{ - rpc: rpc, - }) - defer func() { assert.NoError(t, node.close()) }() - - expectedError := errors.New("failed to subscribe to rpc") - rpc.On("SubscribeToHeads", mock.Anything).Return(nil, nil, expectedError).Once() - // might be called in unreachable loop - rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Maybe() - node.declareAlive() - 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() - rpc := newMockRPCClient[types.ID, Head](t) - - lggr, observedLogs := logger.TestObserved(t, zap.WarnLevel) - node := newDialedNode(t, testNodeOpts{ - rpc: rpc, - lggr: lggr, - }) - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() - defer func() { assert.NoError(t, node.close()) }() - - sub := mocks.NewSubscription(t) - errChan := make(chan error) - close(errChan) - sub.On("Err").Return((<-chan error)(errChan)).Once() - sub.On("Unsubscribe").Once() - rpc.On("SubscribeToHeads", mock.Anything).Return(nil, sub, nil).Once() - // might be called in unreachable loop - rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Maybe() - node.declareAlive() - tests.AssertLogEventually(t, observedLogs, "Subscription was terminated") - assert.Equal(t, nodeStateUnreachable, node.State()) - }) - - newSubscribedNode := func(t *testing.T, opts testNodeOpts) testNode { - sub := newSub(t) - opts.rpc.On("SubscribeToHeads", mock.Anything).Return(make(<-chan Head), sub, nil).Once() - return newDialedNode(t, opts) - } - t.Run("Stays alive and waits for signal", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - node := newSubscribedNode(t, testNodeOpts{ - config: testNodeConfig{}, - rpc: rpc, - lggr: lggr, - }) - defer func() { assert.NoError(t, node.close()) }() - node.declareAlive() - tests.AssertLogEventually(t, observedLogs, "Subscription liveness checking disabled") - tests.AssertLogEventually(t, observedLogs, "Polling disabled") - assert.Equal(t, nodeStateAlive, node.State()) - }) - t.Run("stays alive while below pollFailureThreshold and resets counter on success", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}) - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - const pollFailureThreshold = 3 - node := newSubscribedNode(t, testNodeOpts{ - config: testNodeConfig{ - pollFailureThreshold: pollFailureThreshold, - pollInterval: tests.TestInterval, - }, - rpc: rpc, - lggr: lggr, - }) - defer func() { assert.NoError(t, node.close()) }() - - pollError := errors.New("failed to get ClientVersion") - // 1. Return error several times, but below threshold - rpc.On("Ping", mock.Anything).Return(pollError).Run(func(_ mock.Arguments) { - // stays healthy while below threshold - assert.Equal(t, nodeStateAlive, node.State()) - }).Times(pollFailureThreshold - 1) - // 2. Successful call that is expected to reset counter - rpc.On("Ping", mock.Anything).Return(nil).Once() - // 3. Return error. If we have not reset the timer, we'll transition to nonAliveState - rpc.On("Ping", mock.Anything).Return(pollError).Once() - // 4. Once during the call, check if node is alive - var ensuredAlive atomic.Bool - rpc.On("Ping", mock.Anything).Return(nil).Run(func(_ mock.Arguments) { - if ensuredAlive.Load() { - return - } - ensuredAlive.Store(true) - assert.Equal(t, nodeStateAlive, node.State()) - }).Once() - // redundant call to stay in alive state - rpc.On("Ping", mock.Anything).Return(nil) - node.declareAlive() - tests.AssertLogCountEventually(t, observedLogs, fmt.Sprintf("Poll failure, RPC endpoint %s failed to respond properly", node.String()), pollFailureThreshold) - tests.AssertLogCountEventually(t, observedLogs, "Ping 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() - rpc := newMockRPCClient[types.ID, Head](t) - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}) - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - const pollFailureThreshold = 3 - node := newSubscribedNode(t, testNodeOpts{ - config: testNodeConfig{ - pollFailureThreshold: pollFailureThreshold, - pollInterval: tests.TestInterval, - }, - rpc: rpc, - lggr: lggr, - }) - defer func() { assert.NoError(t, node.close()) }() - pollError := errors.New("failed to get ClientVersion") - rpc.On("Ping", mock.Anything).Return(pollError) - rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Maybe() - node.declareAlive() - tests.AssertLogCountEventually(t, observedLogs, fmt.Sprintf("Poll failure, RPC endpoint %s failed to respond properly", node.String()), pollFailureThreshold) - tests.AssertEventually(t, func() bool { - return nodeStateUnreachable == node.State() - }) - }) - t.Run("with threshold poll failures, but we are the last node alive, forcibly keeps it alive", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - const pollFailureThreshold = 3 - node := newSubscribedNode(t, testNodeOpts{ - config: testNodeConfig{ - pollFailureThreshold: pollFailureThreshold, - pollInterval: tests.TestInterval, - }, - rpc: rpc, - lggr: lggr, - }) - defer func() { assert.NoError(t, node.close()) }() - poolInfo := newMockPoolChainInfoProvider(t) - poolInfo.On("LatestChainInfo").Return(1, ChainInfo{ - BlockNumber: 20, - }).Once() - node.SetPoolChainInfoProvider(poolInfo) - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{BlockNumber: 20}, ChainInfo{BlockNumber: 20}) - pollError := errors.New("failed to get ClientVersion") - rpc.On("Ping", mock.Anything).Return(pollError) - node.declareAlive() - tests.AssertLogEventually(t, observedLogs, fmt.Sprintf("RPC endpoint failed to respond to %d consecutive polls", pollFailureThreshold)) - assert.Equal(t, nodeStateAlive, node.State()) - }) - t.Run("when behind more than SyncThreshold, transitions to out of sync", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - const syncThreshold = 10 - node := newSubscribedNode(t, testNodeOpts{ - config: testNodeConfig{ - pollInterval: tests.TestInterval, - syncThreshold: syncThreshold, - selectionMode: NodeSelectionModeRoundRobin, - }, - rpc: rpc, - lggr: lggr, - }) - defer func() { assert.NoError(t, node.close()) }() - rpc.On("Ping", mock.Anything).Return(nil) - const mostRecentBlock = 20 - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{BlockNumber: mostRecentBlock}, ChainInfo{BlockNumber: 30}) - poolInfo := newMockPoolChainInfoProvider(t) - poolInfo.On("LatestChainInfo").Return(10, ChainInfo{ - BlockNumber: syncThreshold + mostRecentBlock + 1, - TotalDifficulty: big.NewInt(10), - }) - node.SetPoolChainInfoProvider(poolInfo) - // tries to redial in outOfSync - rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Run(func(_ mock.Arguments) { - assert.Equal(t, nodeStateOutOfSync, node.State()) - }).Once() - rpc.On("Close").Maybe() - rpc.On("Dial", mock.Anything).Run(func(_ mock.Arguments) { - require.Equal(t, nodeStateOutOfSync, node.State()) - }).Return(errors.New("failed to dial")).Maybe() - node.declareAlive() - tests.AssertLogEventually(t, observedLogs, "Dial failed: Node is unreachable") - }) - t.Run("when behind more than SyncThreshold but we are the last live node, forcibly stays alive", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - const syncThreshold = 10 - node := newSubscribedNode(t, testNodeOpts{ - config: testNodeConfig{ - pollInterval: tests.TestInterval, - syncThreshold: syncThreshold, - selectionMode: NodeSelectionModeRoundRobin, - }, - rpc: rpc, - lggr: lggr, - }) - defer func() { assert.NoError(t, node.close()) }() - rpc.On("Ping", mock.Anything).Return(nil) - const mostRecentBlock = 20 - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{BlockNumber: mostRecentBlock}, ChainInfo{BlockNumber: 30}) - poolInfo := newMockPoolChainInfoProvider(t) - poolInfo.On("LatestChainInfo").Return(1, ChainInfo{ - BlockNumber: syncThreshold + mostRecentBlock + 1, - TotalDifficulty: big.NewInt(10), - }) - node.SetPoolChainInfoProvider(poolInfo) - node.declareAlive() - tests.AssertLogEventually(t, observedLogs, fmt.Sprintf("RPC endpoint has fallen behind; %s %s", msgCannotDisable, msgDegradedState)) - }) - t.Run("when behind but SyncThreshold=0, stay alive", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - node := newSubscribedNode(t, testNodeOpts{ - config: testNodeConfig{ - pollInterval: tests.TestInterval, - syncThreshold: 0, - selectionMode: NodeSelectionModeRoundRobin, - }, - rpc: rpc, - lggr: lggr, - }) - defer func() { assert.NoError(t, node.close()) }() - rpc.On("Ping", mock.Anything).Return(nil) - const mostRecentBlock = 20 - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{BlockNumber: mostRecentBlock}, ChainInfo{BlockNumber: 30}) - node.declareAlive() - tests.AssertLogCountEventually(t, observedLogs, "Ping successful", 2) - assert.Equal(t, nodeStateAlive, node.State()) - }) - t.Run("when no new heads received for threshold, transitions to out of sync", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}) - node := newSubscribedNode(t, testNodeOpts{ - config: testNodeConfig{}, - chainConfig: clientMocks.ChainConfig{ - NoNewHeadsThresholdVal: tests.TestInterval, - }, - rpc: rpc, - }) - defer func() { assert.NoError(t, node.close()) }() - // tries to redial in outOfSync - rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Run(func(_ mock.Arguments) { - assert.Equal(t, nodeStateOutOfSync, node.State()) - }).Once() - rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Maybe() - node.declareAlive() - tests.AssertEventually(t, func() bool { - // right after outOfSync we'll transfer to unreachable due to returned error on Dial - // we check that we were in out of sync state on first Dial call - return node.State() == nodeStateUnreachable - }) - }) - t.Run("when no new heads received for threshold but we are the last live node, forcibly stays alive", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}) - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - node := newSubscribedNode(t, testNodeOpts{ - config: testNodeConfig{}, - lggr: lggr, - chainConfig: clientMocks.ChainConfig{ - NoNewHeadsThresholdVal: tests.TestInterval, - }, - rpc: rpc, - }) - defer func() { assert.NoError(t, node.close()) }() - poolInfo := newMockPoolChainInfoProvider(t) - poolInfo.On("LatestChainInfo").Return(1, ChainInfo{ - BlockNumber: 20, - TotalDifficulty: big.NewInt(10), - }).Once() - node.SetPoolChainInfoProvider(poolInfo) - node.declareAlive() - tests.AssertLogEventually(t, observedLogs, fmt.Sprintf("RPC endpoint detected out of sync; %s %s", msgCannotDisable, msgDegradedState)) - assert.Equal(t, nodeStateAlive, node.State()) - }) - - t.Run("rpc closed head channel", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - sub := newSub(t) - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() - ch := make(chan Head) - rpc.On("SubscribeToHeads", mock.Anything).Run(func(args mock.Arguments) { - close(ch) - }).Return((<-chan Head)(ch), sub, nil).Once() - lggr, observedLogs := logger.TestObserved(t, zap.ErrorLevel) - node := newDialedNode(t, testNodeOpts{ - lggr: lggr, - config: testNodeConfig{}, - chainConfig: clientMocks.ChainConfig{ - NoNewHeadsThresholdVal: tests.TestInterval, - }, - rpc: rpc, - }) - defer func() { assert.NoError(t, node.close()) }() - rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Maybe() - node.declareAlive() - tests.AssertLogEventually(t, observedLogs, "Subscription channel unexpectedly closed") - assert.Equal(t, nodeStateUnreachable, node.State()) - }) - t.Run("If finality tag is not enabled updates finalized block metric using finality depth and latest head", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - sub := newSub(t) - const blockNumber = 1000 - const finalityDepth = 10 - const expectedBlock = 990 - ch := make(chan Head) - rpc.On("SubscribeToHeads", mock.Anything).Run(func(args mock.Arguments) { - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() - go writeHeads(t, ch, head{BlockNumber: blockNumber - 1}, head{BlockNumber: blockNumber}, head{BlockNumber: blockNumber - 1}) - }).Return((<-chan Head)(ch), sub, nil).Once() - name := "node-" + rand.Str(5) - node := newDialedNode(t, testNodeOpts{ - config: testNodeConfig{}, - chainConfig: clientMocks.ChainConfig{FinalityDepthVal: finalityDepth}, - rpc: rpc, - name: name, - chainID: big.NewInt(1), - }) - defer func() { assert.NoError(t, node.close()) }() - node.declareAlive() - tests.AssertEventually(t, func() bool { - metric, err := promPoolRPCNodeHighestFinalizedBlock.GetMetricWithLabelValues(big.NewInt(1).String(), name) - require.NoError(t, err) - var m = &prom.Metric{} - require.NoError(t, metric.Write(m)) - return float64(expectedBlock) == m.Gauge.GetValue() - }) - }) - t.Run("If fails to subscribe to latest finalized blocks, transitions to unreachable", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - sub := newSub(t) - rpc.On("SubscribeToHeads", mock.Anything).Return(make(<-chan Head), sub, nil).Once() - expectedError := errors.New("failed to subscribe to finalized heads") - rpc.On("SubscribeToFinalizedHeads", mock.Anything).Return(nil, sub, expectedError).Once() - lggr := logger.Test(t) - node := newDialedNode(t, testNodeOpts{ - config: testNodeConfig{ - finalizedBlockPollInterval: tests.TestInterval, - }, - chainConfig: clientMocks.ChainConfig{ - IsFinalityTagEnabled: true, - }, - rpc: rpc, - lggr: lggr, - }) - defer func() { assert.NoError(t, node.close()) }() - node.declareAlive() - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateUnreachable - }) - }) - t.Run("Logs warning if latest finalized block is not valid", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - sub := newSub(t) - rpc.On("SubscribeToHeads", mock.Anything).Return(make(<-chan Head), sub, nil).Once() - ch := make(chan Head, 1) - head := newMockHead(t) - head.On("IsValid").Return(false) - rpc.On("SubscribeToFinalizedHeads", mock.Anything).Run(func(args mock.Arguments) { - ch <- head - }).Return((<-chan Head)(ch), sub, nil).Once() - - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - node := newDialedNode(t, testNodeOpts{ - config: testNodeConfig{}, - chainConfig: clientMocks.ChainConfig{ - IsFinalityTagEnabled: true, - }, - rpc: rpc, - lggr: lggr, - }) - defer func() { assert.NoError(t, node.close()) }() - node.declareAlive() - tests.AssertLogEventually(t, observedLogs, "Latest finalized block is not valid") - }) - t.Run("On new finalized block updates corresponding metric", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - const expectedBlock = 1101 - const finalityDepth = 10 - ch := make(chan Head) - rpc.On("SubscribeToFinalizedHeads", mock.Anything).Return((<-chan Head)(ch), newSub(t), nil).Once() - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() - name := "node-" + rand.Str(5) - node := newSubscribedNode(t, testNodeOpts{ - config: testNodeConfig{}, - chainConfig: clientMocks.ChainConfig{ - FinalityDepthVal: finalityDepth, - IsFinalityTagEnabled: true, - }, - rpc: rpc, - name: name, - chainID: big.NewInt(1), - }) - defer func() { assert.NoError(t, node.close()) }() - node.declareAlive() - var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() - writeHeads(t, ch, head{BlockNumber: expectedBlock - 1}, head{BlockNumber: expectedBlock}, head{BlockNumber: expectedBlock - 1}) - }() - tests.AssertEventually(t, func() bool { - metric, err := promPoolRPCNodeHighestFinalizedBlock.GetMetricWithLabelValues(big.NewInt(1).String(), name) - require.NoError(t, err) - var m = &prom.Metric{} - require.NoError(t, metric.Write(m)) - return float64(expectedBlock) == m.Gauge.GetValue() - }) - }) - t.Run("If finalized heads channel is closed, transitions to unreachable", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() - ch := make(chan Head) - close(ch) - rpc.On("SubscribeToFinalizedHeads", mock.Anything).Return((<-chan Head)(ch), newSub(t), nil).Once() - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - node := newSubscribedNode(t, testNodeOpts{ - chainConfig: clientMocks.ChainConfig{ - IsFinalityTagEnabled: true, - }, - rpc: rpc, - lggr: lggr, - }) - defer func() { assert.NoError(t, node.close()) }() - rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Maybe() - node.declareAlive() - tests.AssertLogEventually(t, observedLogs, "Finalized heads subscription channel unexpectedly closed") - tests.AssertEventually(t, func() bool { - return nodeStateUnreachable == node.State() - }) - }) - t.Run("when no new finalized heads received for threshold, transitions to out of sync", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() - ch := make(chan Head, 1) - ch <- head{BlockNumber: 10}.ToMockHead(t) - rpc.On("SubscribeToFinalizedHeads", mock.Anything).Return((<-chan Head)(ch), newSub(t), nil).Once() - lggr, observed := logger.TestObserved(t, zap.DebugLevel) - noNewFinalizedHeadsThreshold := tests.TestInterval - node := newSubscribedNode(t, testNodeOpts{ - config: testNodeConfig{}, - chainConfig: clientMocks.ChainConfig{ - NoNewFinalizedHeadsThresholdVal: noNewFinalizedHeadsThreshold, - IsFinalityTagEnabled: true, - }, - rpc: rpc, - lggr: lggr, - }) - defer func() { assert.NoError(t, node.close()) }() - // tries to redial in outOfSync - rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Run(func(_ mock.Arguments) { - assert.Equal(t, nodeStateOutOfSync, node.State()) - }).Once() - rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Maybe() - node.declareAlive() - tests.AssertLogEventually(t, observed, fmt.Sprintf("RPC's finalized state is out of sync; no new finalized heads received for %s (last finalized head received was 10)", noNewFinalizedHeadsThreshold)) - tests.AssertEventually(t, func() bool { - // right after outOfSync we'll transfer to unreachable due to returned error on Dial - // we check that we were in out of sync state on first Dial call - return node.State() == nodeStateUnreachable - }) - }) - t.Run("when no new finalized heads received for threshold but we are the last live node, forcibly stays alive", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() - rpc.On("SubscribeToFinalizedHeads", mock.Anything).Return(make(<-chan Head), newSub(t), nil).Once() - lggr, observed := logger.TestObserved(t, zap.DebugLevel) - noNewFinalizedHeadsThreshold := tests.TestInterval - node := newSubscribedNode(t, testNodeOpts{ - config: testNodeConfig{}, - chainConfig: clientMocks.ChainConfig{ - NoNewFinalizedHeadsThresholdVal: noNewFinalizedHeadsThreshold, - IsFinalityTagEnabled: true, - }, - rpc: rpc, - lggr: lggr, - }) - defer func() { assert.NoError(t, node.close()) }() - poolInfo := newMockPoolChainInfoProvider(t) - poolInfo.On("LatestChainInfo").Return(1, ChainInfo{ - BlockNumber: 20, - TotalDifficulty: big.NewInt(10), - }).Once() - node.SetPoolChainInfoProvider(poolInfo) - node.declareAlive() - tests.AssertLogEventually(t, observed, fmt.Sprintf("RPC's finalized state is out of sync; %s %s", msgCannotDisable, msgDegradedState)) - assert.Equal(t, nodeStateAlive, node.State()) - }) - t.Run("If finalized subscription returns an error, transitions to unreachable", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() - sub := mocks.NewSubscription(t) - errCh := make(chan error, 1) - errCh <- errors.New("subscription failed") - sub.On("Err").Return((<-chan error)(errCh)) - sub.On("Unsubscribe").Once() - rpc.On("SubscribeToFinalizedHeads", mock.Anything).Return((<-chan Head)(nil), sub, nil).Once() - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - node := newSubscribedNode(t, testNodeOpts{ - chainConfig: clientMocks.ChainConfig{ - IsFinalityTagEnabled: true, - }, - rpc: rpc, - lggr: lggr, - }) - defer func() { assert.NoError(t, node.close()) }() - rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Maybe() - node.declareAlive() - tests.AssertLogEventually(t, observedLogs, "Finalized heads subscription was terminated") - tests.AssertEventually(t, func() bool { - return nodeStateUnreachable == node.State() - }) - }) -} - -type head struct { - BlockNumber int64 - BlockDifficulty *big.Int -} - -func (h head) ToMockHead(t *testing.T) *mockHead { - m := newMockHead(t) - m.On("BlockNumber").Return(h.BlockNumber).Maybe() - m.On("BlockDifficulty").Return(h.BlockDifficulty).Maybe() - m.On("IsValid").Return(true).Maybe() - return m -} - -func writeHeads(t *testing.T, ch chan<- Head, heads ...head) { - for _, head := range heads { - h := head.ToMockHead(t) - select { - case ch <- h: - case <-tests.Context(t).Done(): - return - } - } -} - -func setupRPCForAliveLoop(t *testing.T, rpc *mockRPCClient[types.ID, Head]) { - rpc.On("Dial", mock.Anything).Return(nil).Maybe() - aliveSubscription := mocks.NewSubscription(t) - aliveSubscription.On("Err").Return(nil).Maybe() - aliveSubscription.On("Unsubscribe").Maybe() - rpc.On("SubscribeToHeads", mock.Anything).Return(make(<-chan Head), aliveSubscription, nil).Maybe() - rpc.On("SubscribeToFinalizedHeads", mock.Anything).Return(make(<-chan Head), aliveSubscription, nil).Maybe() - rpc.On("SetAliveLoopSub", mock.Anything).Maybe() - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Maybe() -} - -func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { - t.Parallel() - - newAliveNode := func(t *testing.T, opts testNodeOpts) testNode { - node := newTestNode(t, opts) - opts.rpc.On("Close").Return(nil) - node.setState(nodeStateAlive) - return node - } - - t.Run("returns on closed", func(t *testing.T) { - t.Parallel() - node := newTestNode(t, testNodeOpts{}) - node.setState(nodeStateClosed) - node.wg.Add(1) - node.outOfSyncLoop(syncStatusNotInSyncWithPool) - }) - t.Run("on old blocks stays outOfSync and returns on close", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.RandomID() - lggr := logger.Test(t) - node := newAliveNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - lggr: lggr, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("Dial", mock.Anything).Return(nil).Once() - rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil).Once() - - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{BlockNumber: 0}, ChainInfo{BlockNumber: 13}).Once() - - outOfSyncSubscription := mocks.NewSubscription(t) - outOfSyncSubscription.On("Err").Return((<-chan error)(nil)) - outOfSyncSubscription.On("Unsubscribe").Once() - heads := []head{{BlockNumber: 7}, {BlockNumber: 11}, {BlockNumber: 13}} - ch := make(chan Head) - var wg sync.WaitGroup - wg.Add(1) - rpc.On("SubscribeToHeads", mock.Anything).Run(func(args mock.Arguments) { - go func() { - defer wg.Done() - writeHeads(t, ch, heads...) - }() - }).Return((<-chan Head)(ch), outOfSyncSubscription, nil).Once() - - rpc.On("Dial", mock.Anything).Return(errors.New("failed to redial")).Maybe() - - node.declareOutOfSync(syncStatusNoNewHead) - // wait until all heads are consumed - wg.Wait() - assert.Equal(t, nodeStateOutOfSync, node.State()) - }) - t.Run("if initial dial fails, transitions to unreachable", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - node := newAliveNode(t, testNodeOpts{ - rpc: rpc, - }) - defer func() { assert.NoError(t, node.close()) }() - - expectedError := errors.New("failed to dial rpc") - // might be called again in unreachable loop, so no need to set once - rpc.On("Dial", mock.Anything).Return(expectedError) - - node.declareOutOfSync(syncStatusNoNewHead) - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateUnreachable - }) - }) - t.Run("if fail to get chainID, transitions to unreachable", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - chainID := types.RandomID() - node := newAliveNode(t, testNodeOpts{ - rpc: rpc, - chainID: chainID, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("ChainID", mock.Anything).Return(chainID, nil) - // for out-of-sync - rpc.On("Dial", mock.Anything).Return(nil).Once() - // for unreachable - rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Maybe() - sub := mocks.NewSubscription(t) - errChan := make(chan error, 1) - errChan <- errors.New("subscription was terminate") - sub.On("Err").Return((<-chan error)(errChan)) - sub.On("Unsubscribe").Once() - rpc.On("SubscribeToHeads", mock.Anything).Return(make(<-chan Head), sub, nil) - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}) - - expectedError := errors.New("failed to get chain ID") - // might be called multiple times - rpc.On("ChainID", mock.Anything).Return(types.NewIDFromInt(0), expectedError) - node.declareOutOfSync(syncStatusNoNewHead) - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateUnreachable - }) - }) - t.Run("if chainID does not match, transitions to invalidChainID", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.NewIDFromInt(10) - rpcChainID := types.NewIDFromInt(11) - node := newAliveNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - }) - defer func() { assert.NoError(t, node.close()) }() - - // one for out-of-sync & one for invalid chainID - rpc.On("Dial", mock.Anything).Return(nil).Twice() - - // might be called multiple times - rpc.On("ChainID", mock.Anything).Return(rpcChainID, nil) - node.declareOutOfSync(syncStatusNoNewHead) - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateInvalidChainID - }) - }) - t.Run("if syncing, transitions to syncing", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.NewIDFromInt(10) - node := newAliveNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - config: testNodeConfig{nodeIsSyncingEnabled: true}, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("Dial", mock.Anything).Return(nil) - rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil) - - // might be called multiple times - rpc.On("IsSyncing", mock.Anything).Return(true, nil) - node.declareOutOfSync(syncStatusNoNewHead) - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateSyncing - }) - }) - t.Run("if fails to fetch syncing status, transitions to unreachable", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.NewIDFromInt(10) - node := newAliveNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - config: testNodeConfig{nodeIsSyncingEnabled: true}, - }) - defer func() { assert.NoError(t, node.close()) }() - - // one for out-of-sync - rpc.On("Dial", mock.Anything).Return(nil).Once() - - // for unreachable - rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Maybe() - rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil).Once() - // might be called multiple times - rpc.On("IsSyncing", mock.Anything).Return(false, errors.New("failed to check syncing")) - node.declareOutOfSync(syncStatusNoNewHead) - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateUnreachable - }) - }) - t.Run("if fails to subscribe, becomes unreachable", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.RandomID() - node := newAliveNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("Dial", mock.Anything).Return(nil).Once() - rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil).Once() - expectedError := errors.New("failed to subscribe") - rpc.On("SubscribeToHeads", mock.Anything).Return(nil, nil, expectedError).Once() - - rpc.On("Dial", mock.Anything).Return(errors.New("failed to redial")).Maybe() - node.declareOutOfSync(syncStatusNoNewHead) - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateUnreachable - }) - }) - t.Run("on subscription termination becomes unreachable", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.RandomID() - lggr, observedLogs := logger.TestObserved(t, zap.ErrorLevel) - node := newAliveNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - lggr: lggr, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("Dial", mock.Anything).Return(nil).Once() - rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil).Once() - - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() - sub := mocks.NewSubscription(t) - errChan := make(chan error, 1) - errChan <- errors.New("subscription was terminate") - sub.On("Err").Return((<-chan error)(errChan)) - sub.On("Unsubscribe").Once() - rpc.On("SubscribeToHeads", mock.Anything).Return(make(<-chan Head), sub, nil).Once() - rpc.On("Dial", mock.Anything).Return(errors.New("failed to redial")).Maybe() - node.declareOutOfSync(syncStatusNoNewHead) - tests.AssertLogEventually(t, observedLogs, "Subscription was terminated") - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateUnreachable - }) - }) - t.Run("becomes unreachable if head channel is closed", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.RandomID() - lggr, observedLogs := logger.TestObserved(t, zap.ErrorLevel) - node := newAliveNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - lggr: lggr, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("Dial", mock.Anything).Return(nil).Once() - rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil).Once() - - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() - - sub := newSub(t) - ch := make(chan Head) - rpc.On("SubscribeToHeads", mock.Anything).Run(func(args mock.Arguments) { - close(ch) - }).Return((<-chan Head)(ch), sub, nil).Once() - rpc.On("Dial", mock.Anything).Return(errors.New("failed to redial")).Maybe() - node.declareOutOfSync(syncStatusNoNewHead) - tests.AssertLogEventually(t, observedLogs, "Subscription channel unexpectedly closed") - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateUnreachable - }) - }) - t.Run("becomes alive if it receives a newer head", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.RandomID() - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - node := newAliveNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - lggr: lggr, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("Dial", mock.Anything).Return(nil).Once() - rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil).Once() - - outOfSyncSubscription := mocks.NewSubscription(t) - outOfSyncSubscription.On("Err").Return((<-chan error)(nil)) - outOfSyncSubscription.On("Unsubscribe").Once() - const highestBlock = 1000 - ch := make(chan Head) - rpc.On("SubscribeToHeads", mock.Anything).Run(func(args mock.Arguments) { - go writeHeads(t, ch, head{BlockNumber: highestBlock - 1}, head{BlockNumber: highestBlock}, head{BlockNumber: highestBlock + 1}) - }).Return((<-chan Head)(ch), outOfSyncSubscription, nil).Once() - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{BlockNumber: highestBlock}, ChainInfo{BlockNumber: highestBlock}) - setupRPCForAliveLoop(t, rpc) - - node.declareOutOfSync(syncStatusNoNewHead) - tests.AssertLogEventually(t, observedLogs, msgReceivedBlock) - tests.AssertLogEventually(t, observedLogs, msgInSync) - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateAlive - }) - }) - t.Run("becomes alive if there is no other nodes", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.RandomID() - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - node := newAliveNode(t, testNodeOpts{ - chainConfig: clientMocks.ChainConfig{ - NoNewHeadsThresholdVal: tests.TestInterval, - }, - rpc: rpc, - chainID: nodeChainID, - lggr: lggr, - }) - defer func() { assert.NoError(t, node.close()) }() - poolInfo := newMockPoolChainInfoProvider(t) - poolInfo.On("LatestChainInfo").Return(0, ChainInfo{ - BlockNumber: 100, - TotalDifficulty: big.NewInt(200), - }) - node.SetPoolChainInfoProvider(poolInfo) - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}) - - rpc.On("Dial", mock.Anything).Return(nil).Once() - rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil).Once() - - outOfSyncSubscription := mocks.NewSubscription(t) - outOfSyncSubscription.On("Err").Return((<-chan error)(nil)) - outOfSyncSubscription.On("Unsubscribe").Once() - rpc.On("SubscribeToHeads", mock.Anything).Return(make(<-chan Head), outOfSyncSubscription, nil).Once() - setupRPCForAliveLoop(t, rpc) - - node.declareOutOfSync(syncStatusNoNewHead) - tests.AssertLogEventually(t, observedLogs, "RPC endpoint is still out of sync, but there are no other available nodes. This RPC node will be forcibly moved back into the live pool in a degraded state") - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateAlive - }) - }) - t.Run("Stays out-of-sync if received new head, but lags behind pool", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.RandomID() - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - node := newAliveNode(t, testNodeOpts{ - chainConfig: clientMocks.ChainConfig{ - NoNewHeadsThresholdVal: tests.TestInterval, - }, - config: testNodeConfig{ - syncThreshold: 1, - selectionMode: NodeSelectionModeHighestHead, - }, - rpc: rpc, - chainID: nodeChainID, - lggr: lggr, - }) - defer func() { assert.NoError(t, node.close()) }() - poolInfo := newMockPoolChainInfoProvider(t) - const highestBlock = 20 - poolInfo.On("LatestChainInfo").Return(1, ChainInfo{ - BlockNumber: highestBlock * 2, - TotalDifficulty: big.NewInt(200), - }) - node.SetPoolChainInfoProvider(poolInfo) - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{BlockNumber: highestBlock}) - - rpc.On("Dial", mock.Anything).Return(nil).Once() - rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil).Once() - - outOfSyncSubscription := mocks.NewSubscription(t) - outOfSyncSubscription.On("Err").Return((<-chan error)(nil)) - outOfSyncSubscription.On("Unsubscribe").Once() - ch := make(chan Head) - rpc.On("SubscribeToHeads", mock.Anything).Run(func(args mock.Arguments) { - go writeHeads(t, ch, head{BlockNumber: highestBlock - 1}, head{BlockNumber: highestBlock}, head{BlockNumber: highestBlock + 1}) - }).Return((<-chan Head)(ch), outOfSyncSubscription, nil).Once() - - node.declareOutOfSync(syncStatusNoNewHead) - tests.AssertLogEventually(t, observedLogs, msgReceivedBlock) - tests.AssertLogEventually(t, observedLogs, "No new heads received for") - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateOutOfSync - }) - }) - - // creates RPC mock with all calls necessary to create heads subscription that won't produce any events - newRPCWithNoOpHeads := func(t *testing.T, chainID types.ID) *mockRPCClient[types.ID, Head] { - rpc := newMockRPCClient[types.ID, Head](t) - rpc.On("Dial", mock.Anything).Return(nil).Once() - rpc.On("ChainID", mock.Anything).Return(chainID, nil).Once() - sub := newSub(t) - rpc.On("SubscribeToHeads", mock.Anything).Return(make(<-chan Head), sub, nil).Once() - return rpc - } - - t.Run("if fails to subscribe to finalized, becomes unreachable", func(t *testing.T) { - t.Parallel() - nodeChainID := types.RandomID() - rpc := newRPCWithNoOpHeads(t, nodeChainID) - node := newAliveNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - chainConfig: clientMocks.ChainConfig{ - IsFinalityTagEnabled: true, - }, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("SubscribeToFinalizedHeads", mock.Anything).Return((<-chan Head)(nil), nil, errors.New("failed to subscribe")).Once() - // unreachable - rpc.On("Dial", mock.Anything).Return(errors.New("failed to redial")).Maybe() - - node.declareOutOfSync(syncStatusNoNewHead) - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateUnreachable - }) - }) - t.Run("on subscription termination becomes unreachable", func(t *testing.T) { - t.Parallel() - nodeChainID := types.RandomID() - rpc := newRPCWithNoOpHeads(t, nodeChainID) - lggr, observedLogs := logger.TestObserved(t, zap.ErrorLevel) - node := newAliveNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - lggr: lggr, - chainConfig: clientMocks.ChainConfig{ - IsFinalityTagEnabled: true, - }, - }) - defer func() { assert.NoError(t, node.close()) }() - - sub := mocks.NewSubscription(t) - errChan := make(chan error, 1) - errChan <- errors.New("subscription was terminate") - sub.On("Err").Return((<-chan error)(errChan)) - sub.On("Unsubscribe").Once() - rpc.On("SubscribeToFinalizedHeads", mock.Anything).Return(make(<-chan Head), sub, nil).Once() - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}) - - // unreachable - rpc.On("Dial", mock.Anything).Return(errors.New("failed to redial")).Maybe() - node.declareOutOfSync(syncStatusNoNewHead) - tests.AssertLogEventually(t, observedLogs, "Finalized head subscription was terminated") - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateUnreachable - }) - }) - t.Run("becomes unreachable if head channel is closed", func(t *testing.T) { - t.Parallel() - nodeChainID := types.RandomID() - rpc := newRPCWithNoOpHeads(t, nodeChainID) - lggr, observedLogs := logger.TestObserved(t, zap.ErrorLevel) - node := newAliveNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - lggr: lggr, - chainConfig: clientMocks.ChainConfig{ - IsFinalityTagEnabled: true, - }, - }) - defer func() { assert.NoError(t, node.close()) }() - - sub := newSub(t) - - ch := make(chan Head) - rpc.On("SubscribeToFinalizedHeads", mock.Anything).Run(func(args mock.Arguments) { - close(ch) - }).Return((<-chan Head)(ch), sub, nil).Once() - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}) - // unreachable - rpc.On("Dial", mock.Anything).Return(errors.New("failed to redial")).Maybe() - node.declareOutOfSync(syncStatusNoNewHead) - tests.AssertLogEventually(t, observedLogs, "Finalized heads subscription channel unexpectedly closed") - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateUnreachable - }) - }) - t.Run("becomes alive on new finalized block", func(t *testing.T) { - t.Parallel() - nodeChainID := types.RandomID() - rpc := newRPCWithNoOpHeads(t, nodeChainID) - lggr := logger.Test(t) - node := newAliveNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - lggr: lggr, - chainConfig: clientMocks.ChainConfig{ - IsFinalityTagEnabled: true, - NoNewFinalizedHeadsThresholdVal: tests.TestInterval, - }, - }) - defer func() { assert.NoError(t, node.close()) }() - - const highestBlock = 13 - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{FinalizedBlockNumber: highestBlock}, ChainInfo{FinalizedBlockNumber: highestBlock}) - - outOfSyncSubscription := mocks.NewSubscription(t) - outOfSyncSubscription.On("Err").Return((<-chan error)(nil)) - outOfSyncSubscription.On("Unsubscribe").Once() - ch := make(chan Head) - rpc.On("SubscribeToFinalizedHeads", mock.Anything).Return((<-chan Head)(ch), outOfSyncSubscription, nil).Once() - - setupRPCForAliveLoop(t, rpc) - - node.declareOutOfSync(syncStatusNoNewFinalizedHead) - heads := []head{{BlockNumber: highestBlock - 1}, {BlockNumber: highestBlock}} - writeHeads(t, ch, heads...) - assert.Equal(t, nodeStateOutOfSync, node.State()) - writeHeads(t, ch, head{BlockNumber: highestBlock + 1}) - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateAlive - }) - }) - t.Run("adds finalized block is not increasing flag, if there is no new finalized heads for too long", func(t *testing.T) { - t.Parallel() - nodeChainID := types.RandomID() - rpc := newRPCWithNoOpHeads(t, nodeChainID) - lggr, observed := logger.TestObserved(t, zap.DebugLevel) - const noNewFinalizedHeads = tests.TestInterval - node := newAliveNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - lggr: lggr, - chainConfig: clientMocks.ChainConfig{ - IsFinalityTagEnabled: true, - NoNewFinalizedHeadsThresholdVal: noNewFinalizedHeads, - }, - }) - defer func() { assert.NoError(t, node.close()) }() - - const highestBlock = 13 - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{FinalizedBlockNumber: highestBlock}) - - outOfSyncSubscription := mocks.NewSubscription(t) - outOfSyncSubscription.On("Err").Return((<-chan error)(nil)) - outOfSyncSubscription.On("Unsubscribe").Once() - ch := make(chan Head) - rpc.On("SubscribeToFinalizedHeads", mock.Anything).Return((<-chan Head)(ch), outOfSyncSubscription, nil).Once() - - node.declareOutOfSync(syncStatusNotInSyncWithPool) - heads := []head{{BlockNumber: highestBlock - 1}, {BlockNumber: highestBlock}} - writeHeads(t, ch, heads...) - assert.Equal(t, nodeStateOutOfSync, node.State()) - tests.AssertLogEventually(t, observed, fmt.Sprintf("No new finalized heads received for %s. Node stays "+ - "out-of-sync due to sync issues: NotInSyncWithRPCPool,NoNewFinalizedHead", noNewFinalizedHeads)) - }) -} - -func TestUnit_NodeLifecycle_unreachableLoop(t *testing.T) { - t.Parallel() - - newAliveNode := func(t *testing.T, opts testNodeOpts) testNode { - node := newTestNode(t, opts) - opts.rpc.On("Close").Return(nil) - - node.setState(nodeStateAlive) - return node - } - t.Run("returns on closed", func(t *testing.T) { - t.Parallel() - node := newTestNode(t, testNodeOpts{}) - node.setState(nodeStateClosed) - node.wg.Add(1) - node.unreachableLoop() - }) - t.Run("on failed redial, keeps trying", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.RandomID() - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - node := newAliveNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - lggr: lggr, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")) - node.declareUnreachable() - tests.AssertLogCountEventually(t, observedLogs, "Failed to redial RPC node; still unreachable", 2) - }) - t.Run("on failed chainID verification, keep trying", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.RandomID() - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - node := newAliveNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - lggr: lggr, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("Dial", mock.Anything).Return(nil) - rpc.On("ChainID", mock.Anything).Run(func(_ mock.Arguments) { - assert.Equal(t, nodeStateDialed, node.State()) - }).Return(nodeChainID, errors.New("failed to get chain id")) - node.declareUnreachable() - tests.AssertLogCountEventually(t, observedLogs, "Failed to verify chain ID for node", 2) - }) - t.Run("on chain ID mismatch transitions to invalidChainID", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.NewIDFromInt(10) - rpcChainID := types.NewIDFromInt(11) - node := newAliveNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("Dial", mock.Anything).Return(nil) - rpc.On("ChainID", mock.Anything).Return(rpcChainID, nil) - - node.declareUnreachable() - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateInvalidChainID - }) - }) - t.Run("on syncing status check failure, keeps trying", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.RandomID() - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - node := newAliveNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - lggr: lggr, - config: testNodeConfig{nodeIsSyncingEnabled: true}, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("Dial", mock.Anything).Return(nil) - rpc.On("ChainID", mock.Anything).Run(func(_ mock.Arguments) { - assert.Equal(t, nodeStateDialed, node.State()) - }).Return(nodeChainID, nil) - rpc.On("IsSyncing", mock.Anything).Return(false, errors.New("failed to check syncing status")) - node.declareUnreachable() - tests.AssertLogCountEventually(t, observedLogs, "Unexpected error while verifying RPC node synchronization status", 2) - }) - t.Run("on syncing, transitions to syncing state", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.RandomID() - node := newAliveNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - config: testNodeConfig{nodeIsSyncingEnabled: true}, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("Dial", mock.Anything).Return(nil) - rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil) - rpc.On("IsSyncing", mock.Anything).Return(true, nil) - - setupRPCForAliveLoop(t, rpc) - - node.declareUnreachable() - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateSyncing - }) - }) - t.Run("on successful verification becomes alive", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.RandomID() - node := newAliveNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - config: testNodeConfig{nodeIsSyncingEnabled: true}, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil) - rpc.On("IsSyncing", mock.Anything).Return(false, nil) - setupRPCForAliveLoop(t, rpc) - - node.declareUnreachable() - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateAlive - }) - }) - t.Run("on successful verification without isSyncing becomes alive", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.RandomID() - node := newAliveNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("Dial", mock.Anything).Return(nil) - rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil) - - setupRPCForAliveLoop(t, rpc) - - node.declareUnreachable() - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateAlive - }) - }) -} - -func TestUnit_NodeLifecycle_invalidChainIDLoop(t *testing.T) { - t.Parallel() - newDialedNode := func(t *testing.T, opts testNodeOpts) testNode { - node := newTestNode(t, opts) - opts.rpc.On("Close").Return(nil) - - node.setState(nodeStateDialed) - return node - } - t.Run("returns on closed", func(t *testing.T) { - t.Parallel() - node := newTestNode(t, testNodeOpts{}) - node.setState(nodeStateClosed) - node.wg.Add(1) - node.invalidChainIDLoop() - }) - t.Run("on invalid dial becomes unreachable", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.RandomID() - node := newDialedNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")) - rpc.On("Close") - - node.declareInvalidChainID() - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateUnreachable - }) - }) - t.Run("on failed chainID call becomes unreachable", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.RandomID() - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - node := newDialedNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - lggr: lggr, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("ChainID", mock.Anything).Return(nodeChainID, errors.New("failed to get chain id")) - // once for chainID and maybe another one for unreachable - rpc.On("Dial", mock.Anything).Return(nil).Once() - rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Maybe() - - node.declareInvalidChainID() - tests.AssertLogEventually(t, observedLogs, "Failed to verify chain ID for node") - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateUnreachable - }) - }) - t.Run("on chainID mismatch keeps trying", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.NewIDFromInt(10) - rpcChainID := types.NewIDFromInt(11) - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - node := newDialedNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - lggr: lggr, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("Dial", mock.Anything).Return(nil).Once() - rpc.On("ChainID", mock.Anything).Return(rpcChainID, nil) - - node.declareInvalidChainID() - tests.AssertLogCountEventually(t, observedLogs, "Failed to verify RPC node; remote endpoint returned the wrong chain ID", 2) - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateInvalidChainID - }) - }) - t.Run("on successful verification without isSyncing becomes alive", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.NewIDFromInt(10) - rpcChainID := types.NewIDFromInt(11) - node := newDialedNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - }) - defer func() { assert.NoError(t, node.close()) }() - - setupRPCForAliveLoop(t, rpc) - rpc.On("ChainID", mock.Anything).Return(rpcChainID, nil).Once() - rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil).Once() - - node.declareInvalidChainID() - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateAlive - }) - }) - t.Run("on successful verification becomes alive", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.NewIDFromInt(10) - rpcChainID := types.NewIDFromInt(11) - node := newDialedNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - config: testNodeConfig{nodeIsSyncingEnabled: true}, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("ChainID", mock.Anything).Return(rpcChainID, nil).Once() - rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil).Once() - rpc.On("IsSyncing", mock.Anything).Return(false, nil).Once() - - setupRPCForAliveLoop(t, rpc) - - node.declareInvalidChainID() - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateAlive - }) - }) -} - -func TestUnit_NodeLifecycle_start(t *testing.T) { - t.Parallel() - - newNode := func(t *testing.T, opts testNodeOpts) testNode { - node := newTestNode(t, opts) - opts.rpc.On("Close").Return(nil) - - return node - } - t.Run("if fails on initial dial, becomes unreachable", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.RandomID() - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - node := newNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - lggr: lggr, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")) - err := node.Start(tests.Context(t)) - assert.NoError(t, err) - tests.AssertLogEventually(t, observedLogs, "Dial failed: Node is unreachable") - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateUnreachable - }) - }) - t.Run("if chainID verification fails, becomes unreachable", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.RandomID() - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - node := newNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - lggr: lggr, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("Dial", mock.Anything).Return(nil) - rpc.On("ChainID", mock.Anything).Run(func(_ mock.Arguments) { - assert.Equal(t, nodeStateDialed, node.State()) - }).Return(nodeChainID, errors.New("failed to get chain id")) - err := node.Start(tests.Context(t)) - assert.NoError(t, err) - tests.AssertLogEventually(t, observedLogs, "Failed to verify chain ID for node") - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateUnreachable - }) - }) - t.Run("on chain ID mismatch transitions to invalidChainID", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.NewIDFromInt(10) - rpcChainID := types.NewIDFromInt(11) - node := newNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("Dial", mock.Anything).Return(nil) - - rpc.On("ChainID", mock.Anything).Return(rpcChainID, nil) - err := node.Start(tests.Context(t)) - assert.NoError(t, err) - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateInvalidChainID - }) - }) - t.Run("if syncing verification fails, becomes unreachable", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.RandomID() - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - node := newNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - lggr: lggr, - config: testNodeConfig{nodeIsSyncingEnabled: true}, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("Dial", mock.Anything).Return(nil).Once() - - rpc.On("ChainID", mock.Anything).Run(func(_ mock.Arguments) { - assert.Equal(t, nodeStateDialed, node.State()) - }).Return(nodeChainID, nil).Once() - rpc.On("IsSyncing", mock.Anything).Return(false, errors.New("failed to check syncing status")) - rpc.On("Dial", mock.Anything).Return(errors.New("failed to redial")) - err := node.Start(tests.Context(t)) - assert.NoError(t, err) - tests.AssertLogEventually(t, observedLogs, "Unexpected error while verifying RPC node synchronization status") - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateUnreachable - }) - }) - t.Run("on isSyncing transitions to syncing", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.NewIDFromInt(10) - node := newNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - config: testNodeConfig{nodeIsSyncingEnabled: true}, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("Dial", mock.Anything).Return(nil) - - rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil) - rpc.On("IsSyncing", mock.Anything).Return(true, nil) - err := node.Start(tests.Context(t)) - assert.NoError(t, err) - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateSyncing - }) - }) - t.Run("on successful verification becomes alive", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.RandomID() - node := newNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - config: testNodeConfig{nodeIsSyncingEnabled: true}, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil) - rpc.On("IsSyncing", mock.Anything).Return(false, nil) - setupRPCForAliveLoop(t, rpc) - - err := node.Start(tests.Context(t)) - assert.NoError(t, err) - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateAlive - }) - }) - t.Run("on successful verification without isSyncing becomes alive", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.RandomID() - node := newNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil) - setupRPCForAliveLoop(t, rpc) - - err := node.Start(tests.Context(t)) - assert.NoError(t, err) - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateAlive - }) - }) -} - -func TestUnit_NodeLifecycle_outOfSyncWithPool(t *testing.T) { - t.Parallel() - t.Run("skip if nLiveNodes is not configured", func(t *testing.T) { - node := newTestNode(t, testNodeOpts{}) - outOfSync, liveNodes := node.isOutOfSyncWithPool() - assert.Equal(t, false, outOfSync) - assert.Equal(t, 0, liveNodes) - }) - t.Run("skip if syncThreshold is not configured", func(t *testing.T) { - node := newTestNode(t, testNodeOpts{}) - poolInfo := newMockPoolChainInfoProvider(t) - node.SetPoolChainInfoProvider(poolInfo) - outOfSync, liveNodes := node.isOutOfSyncWithPool() - assert.Equal(t, false, outOfSync) - assert.Equal(t, 0, liveNodes) - }) - t.Run("panics on invalid selection mode", func(t *testing.T) { - node := newTestNode(t, testNodeOpts{ - config: testNodeConfig{syncThreshold: 1}, - }) - poolInfo := newMockPoolChainInfoProvider(t) - poolInfo.On("LatestChainInfo").Return(1, ChainInfo{}).Once() - node.SetPoolChainInfoProvider(poolInfo) - assert.Panics(t, func() { - _, _ = node.isOutOfSyncWithPool() - }) - }) - t.Run("block height selection mode", func(t *testing.T) { - const syncThreshold = 10 - const highestBlock = 1000 - const nodesNum = 20 - const totalDifficulty = 3000 - testCases := []struct { - name string - blockNumber int64 - outOfSync bool - }{ - { - name: "below threshold", - blockNumber: highestBlock - syncThreshold - 1, - outOfSync: true, - }, - { - name: "equal to threshold", - blockNumber: highestBlock - syncThreshold, - outOfSync: false, - }, - { - name: "equal to highest block", - blockNumber: highestBlock, - outOfSync: false, - }, - { - name: "higher than highest block", - blockNumber: highestBlock, - outOfSync: false, - }, - } - - for _, selectionMode := range []string{NodeSelectionModeHighestHead, NodeSelectionModeRoundRobin, NodeSelectionModePriorityLevel} { - node := newTestNode(t, testNodeOpts{ - config: testNodeConfig{ - syncThreshold: syncThreshold, - selectionMode: selectionMode, - }, - }) - poolInfo := newMockPoolChainInfoProvider(t) - poolInfo.On("LatestChainInfo").Return(nodesNum, ChainInfo{ - BlockNumber: highestBlock, - TotalDifficulty: big.NewInt(totalDifficulty), - }) - node.SetPoolChainInfoProvider(poolInfo) - for _, td := range []int64{totalDifficulty - syncThreshold - 1, totalDifficulty - syncThreshold, totalDifficulty, totalDifficulty + 1} { - for _, testCase := range testCases { - t.Run(fmt.Sprintf("%s: SelectionModeVal: %s: total difficulty: %d", testCase.name, selectionMode, td), func(t *testing.T) { - chainInfo := ChainInfo{BlockNumber: testCase.blockNumber, TotalDifficulty: big.NewInt(td)} - rpc := newMockRPCClient[types.ID, Head](t) - rpc.On("GetInterceptedChainInfo").Return(chainInfo, ChainInfo{}).Once() - node.rpc = rpc - outOfSync, liveNodes := node.isOutOfSyncWithPool() - assert.Equal(t, nodesNum, liveNodes) - assert.Equal(t, testCase.outOfSync, outOfSync) - }) - } - } - } - }) - t.Run("total difficulty selection mode", func(t *testing.T) { - const syncThreshold = 10 - const highestBlock = 1000 - const nodesNum = 20 - const totalDifficulty = 3000 - testCases := []struct { - name string - totalDifficulty int64 - outOfSync bool - }{ - { - name: "below threshold", - totalDifficulty: totalDifficulty - syncThreshold - 1, - outOfSync: true, - }, - { - name: "equal to threshold", - totalDifficulty: totalDifficulty - syncThreshold, - outOfSync: false, - }, - { - name: "equal to highest block", - totalDifficulty: totalDifficulty, - outOfSync: false, - }, - { - name: "higher than highest block", - totalDifficulty: totalDifficulty, - outOfSync: false, - }, - } - - node := newTestNode(t, testNodeOpts{ - config: testNodeConfig{ - syncThreshold: syncThreshold, - selectionMode: NodeSelectionModeTotalDifficulty, - }, - }) - - poolInfo := newMockPoolChainInfoProvider(t) - poolInfo.On("LatestChainInfo").Return(nodesNum, ChainInfo{ - BlockNumber: highestBlock, - TotalDifficulty: big.NewInt(totalDifficulty), - }) - node.SetPoolChainInfoProvider(poolInfo) - for _, hb := range []int64{highestBlock - syncThreshold - 1, highestBlock - syncThreshold, highestBlock, highestBlock + 1} { - for _, testCase := range testCases { - t.Run(fmt.Sprintf("%s: SelectionModeVal: %s: highest block: %d", testCase.name, NodeSelectionModeTotalDifficulty, hb), func(t *testing.T) { - chainInfo := ChainInfo{BlockNumber: hb, TotalDifficulty: big.NewInt(testCase.totalDifficulty)} - rpc := newMockRPCClient[types.ID, Head](t) - rpc.On("GetInterceptedChainInfo").Return(chainInfo, ChainInfo{}).Once() - node.rpc = rpc - outOfSync, liveNodes := node.isOutOfSyncWithPool() - assert.Equal(t, nodesNum, liveNodes) - assert.Equal(t, testCase.outOfSync, outOfSync) - }) - } - } - }) -} - -func TestUnit_NodeLifecycle_SyncingLoop(t *testing.T) { - t.Parallel() - newDialedNode := func(t *testing.T, opts testNodeOpts) testNode { - opts.config.nodeIsSyncingEnabled = true - node := newTestNode(t, opts) - opts.rpc.On("Close").Return(nil) - - node.setState(nodeStateDialed) - return node - } - t.Run("returns on closed", func(t *testing.T) { - t.Parallel() - node := newTestNode(t, testNodeOpts{}) - node.setState(nodeStateClosed) - node.wg.Add(1) - node.syncingLoop() - }) - t.Run("on invalid dial becomes unreachable", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.RandomID() - node := newDialedNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")) - - node.declareSyncing() - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateUnreachable - }) - }) - t.Run("on failed chainID call becomes unreachable", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.RandomID() - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - node := newDialedNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - lggr: lggr, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("ChainID", mock.Anything).Return(nodeChainID, errors.New("failed to get chain id")) - - // once for syncing and maybe another one for unreachable - rpc.On("Dial", mock.Anything).Return(nil).Once() - rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Maybe() - node.declareSyncing() - tests.AssertLogEventually(t, observedLogs, "Failed to verify chain ID for node") - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateUnreachable - }) - }) - t.Run("on chainID mismatch transitions to invalidChainID", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.NewIDFromInt(10) - rpcChainID := types.NewIDFromInt(11) - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - node := newDialedNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - lggr: lggr, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("Dial", mock.Anything).Return(nil).Twice() - - rpc.On("ChainID", mock.Anything).Return(rpcChainID, nil) - node.declareSyncing() - tests.AssertLogCountEventually(t, observedLogs, "Failed to verify RPC node; remote endpoint returned the wrong chain ID", 2) - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateInvalidChainID - }) - }) - t.Run("on failed Syncing check - becomes unreachable", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.RandomID() - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - node := newDialedNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - lggr: lggr, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil).Once() - // first one is needed to enter internal loop - rpc.On("IsSyncing", mock.Anything).Return(true, nil).Once() - rpc.On("IsSyncing", mock.Anything).Return(false, errors.New("failed to check if syncing")).Once() - rpc.On("Dial", mock.Anything).Return(nil).Once() - rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Maybe() - - node.declareSyncing() - tests.AssertLogEventually(t, observedLogs, "Unexpected error while verifying RPC node synchronization status") - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateUnreachable - }) - }) - t.Run("on IsSyncing - keeps trying", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.RandomID() - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - node := newDialedNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - lggr: lggr, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil).Once() - rpc.On("IsSyncing", mock.Anything).Return(true, nil) - rpc.On("Dial", mock.Anything).Return(nil).Once() - - node.declareSyncing() - tests.AssertLogCountEventually(t, observedLogs, "Verification failed: Node is syncing", 2) - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateSyncing - }) - }) - t.Run("on successful verification becomes alive", func(t *testing.T) { - t.Parallel() - rpc := newMockRPCClient[types.ID, Head](t) - nodeChainID := types.RandomID() - node := newDialedNode(t, testNodeOpts{ - rpc: rpc, - chainID: nodeChainID, - }) - defer func() { assert.NoError(t, node.close()) }() - - rpc.On("Dial", mock.Anything).Return(nil).Once() - - rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil).Once() - rpc.On("IsSyncing", mock.Anything).Return(true, nil).Once() - rpc.On("IsSyncing", mock.Anything).Return(false, nil).Once() - - setupRPCForAliveLoop(t, rpc) - - node.declareSyncing() - tests.AssertEventually(t, func() bool { - return node.State() == nodeStateAlive - }) - }) -} - -func TestNode_State(t *testing.T) { - t.Run("If not Alive, returns as is", func(t *testing.T) { - for state := nodeState(0); state < nodeStateLen; state++ { - if state == nodeStateAlive { - continue - } - - node := newTestNode(t, testNodeOpts{}) - node.setState(state) - assert.Equal(t, state, node.State()) - } - }) - t.Run("If repeatable read is not enforced, returns alive", func(t *testing.T) { - node := newTestNode(t, testNodeOpts{}) - node.setState(nodeStateAlive) - assert.Equal(t, nodeStateAlive, node.State()) - }) - testCases := []struct { - Name string - FinalizedBlockOffsetVal uint32 - IsFinalityTagEnabled bool - PoolChainInfo ChainInfo - NodeChainInfo ChainInfo - ExpectedState nodeState - }{ - { - Name: "If finality lag does not exceeds offset, returns alive (FinalityDepth)", - FinalizedBlockOffsetVal: 15, - PoolChainInfo: ChainInfo{ - BlockNumber: 20, - }, - NodeChainInfo: ChainInfo{ - BlockNumber: 5, - }, - ExpectedState: nodeStateAlive, - }, - { - Name: "If finality lag does not exceeds offset, returns alive (FinalityTag)", - FinalizedBlockOffsetVal: 15, - IsFinalityTagEnabled: true, - PoolChainInfo: ChainInfo{ - FinalizedBlockNumber: 20, - }, - NodeChainInfo: ChainInfo{ - FinalizedBlockNumber: 5, - }, - ExpectedState: nodeStateAlive, - }, - { - Name: "If finality lag exceeds offset, returns nodeStateFinalizedBlockOutOfSync (FinalityDepth)", - FinalizedBlockOffsetVal: 15, - PoolChainInfo: ChainInfo{ - BlockNumber: 20, - }, - NodeChainInfo: ChainInfo{ - BlockNumber: 4, - }, - ExpectedState: nodeStateFinalizedBlockOutOfSync, - }, - { - Name: "If finality lag exceeds offset, returns nodeStateFinalizedBlockOutOfSync (FinalityTag)", - FinalizedBlockOffsetVal: 15, - IsFinalityTagEnabled: true, - PoolChainInfo: ChainInfo{ - FinalizedBlockNumber: 20, - }, - NodeChainInfo: ChainInfo{ - FinalizedBlockNumber: 4, - }, - ExpectedState: nodeStateFinalizedBlockOutOfSync, - }, - } - for _, tc := range testCases { - t.Run(tc.Name, func(t *testing.T) { - rpc := newMockRPCClient[types.ID, Head](t) - rpc.On("GetInterceptedChainInfo").Return(tc.NodeChainInfo, tc.PoolChainInfo).Once() - node := newTestNode(t, testNodeOpts{ - config: testNodeConfig{ - enforceRepeatableRead: true, - }, - chainConfig: clientMocks.ChainConfig{ - FinalizedBlockOffsetVal: tc.FinalizedBlockOffsetVal, - IsFinalityTagEnabled: tc.IsFinalityTagEnabled, - }, - rpc: rpc, - }) - poolInfo := newMockPoolChainInfoProvider(t) - poolInfo.On("HighestUserObservations").Return(tc.PoolChainInfo).Once() - node.SetPoolChainInfoProvider(poolInfo) - node.setState(nodeStateAlive) - assert.Equal(t, tc.ExpectedState, node.State()) - }) - } -} diff --git a/common/client/node_selector.go b/common/client/node_selector.go deleted file mode 100644 index 372b521bb1c..00000000000 --- a/common/client/node_selector.go +++ /dev/null @@ -1,43 +0,0 @@ -package client - -import ( - "fmt" - - "github.com/smartcontractkit/chainlink/v2/common/types" -) - -const ( - NodeSelectionModeHighestHead = "HighestHead" - NodeSelectionModeRoundRobin = "RoundRobin" - NodeSelectionModeTotalDifficulty = "TotalDifficulty" - NodeSelectionModePriorityLevel = "PriorityLevel" -) - -type NodeSelector[ - CHAIN_ID types.ID, - RPC any, -] interface { - // Select returns a Node, or nil if none can be selected. - // Implementation must be thread-safe. - Select() Node[CHAIN_ID, RPC] - // Name returns the strategy name, e.g. "HighestHead" or "RoundRobin" - Name() string -} - -func newNodeSelector[ - CHAIN_ID types.ID, - RPC any, -](selectionMode string, nodes []Node[CHAIN_ID, RPC]) NodeSelector[CHAIN_ID, RPC] { - switch selectionMode { - case NodeSelectionModeHighestHead: - return NewHighestHeadNodeSelector[CHAIN_ID, RPC](nodes) - case NodeSelectionModeRoundRobin: - return NewRoundRobinSelector[CHAIN_ID, RPC](nodes) - case NodeSelectionModeTotalDifficulty: - return NewTotalDifficultyNodeSelector[CHAIN_ID, RPC](nodes) - case NodeSelectionModePriorityLevel: - return NewPriorityLevelNodeSelector[CHAIN_ID, RPC](nodes) - default: - panic(fmt.Sprintf("unsupported NodeSelectionMode: %s", selectionMode)) - } -} diff --git a/common/client/node_selector_highest_head.go b/common/client/node_selector_highest_head.go deleted file mode 100644 index 454584a77e1..00000000000 --- a/common/client/node_selector_highest_head.go +++ /dev/null @@ -1,40 +0,0 @@ -package client - -import ( - "math" - - "github.com/smartcontractkit/chainlink/v2/common/types" -) - -type highestHeadNodeSelector[ - CHAIN_ID types.ID, - RPC any, -] []Node[CHAIN_ID, RPC] - -func NewHighestHeadNodeSelector[ - CHAIN_ID types.ID, - RPC any, -](nodes []Node[CHAIN_ID, RPC]) NodeSelector[CHAIN_ID, RPC] { - return highestHeadNodeSelector[CHAIN_ID, RPC](nodes) -} - -func (s highestHeadNodeSelector[CHAIN_ID, RPC]) Select() Node[CHAIN_ID, RPC] { - var highestHeadNumber int64 = math.MinInt64 - var highestHeadNodes []Node[CHAIN_ID, RPC] - for _, n := range s { - state, currentChainInfo := n.StateAndLatest() - currentHeadNumber := currentChainInfo.BlockNumber - if state == nodeStateAlive && currentHeadNumber >= highestHeadNumber { - if highestHeadNumber < currentHeadNumber { - highestHeadNumber = currentHeadNumber - highestHeadNodes = nil - } - highestHeadNodes = append(highestHeadNodes, n) - } - } - return firstOrHighestPriority(highestHeadNodes) -} - -func (s highestHeadNodeSelector[CHAIN_ID, RPC]) Name() string { - return NodeSelectionModeHighestHead -} diff --git a/common/client/node_selector_highest_head_test.go b/common/client/node_selector_highest_head_test.go deleted file mode 100644 index 9d85c688e05..00000000000 --- a/common/client/node_selector_highest_head_test.go +++ /dev/null @@ -1,176 +0,0 @@ -package client - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/smartcontractkit/chainlink/v2/common/types" -) - -func TestHighestHeadNodeSelectorName(t *testing.T) { - selector := newNodeSelector[types.ID, RPCClient[types.ID, Head]](NodeSelectionModeHighestHead, nil) - assert.Equal(t, selector.Name(), NodeSelectionModeHighestHead) -} - -func TestHighestHeadNodeSelector(t *testing.T) { - t.Parallel() - - type nodeClient RPCClient[types.ID, Head] - - var nodes []Node[types.ID, nodeClient] - - for i := 0; i < 3; i++ { - node := newMockNode[types.ID, nodeClient](t) - if i == 0 { - // first node is out of sync - node.On("StateAndLatest").Return(nodeStateOutOfSync, ChainInfo{BlockNumber: int64(-1)}) - } else if i == 1 { - // second node is alive, LatestReceivedBlockNumber = 1 - node.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(1)}) - } else { - // third node is alive, LatestReceivedBlockNumber = 2 (best node) - node.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(2)}) - } - node.On("Order").Maybe().Return(int32(1)) - nodes = append(nodes, node) - } - - selector := newNodeSelector[types.ID, nodeClient](NodeSelectionModeHighestHead, nodes) - assert.Same(t, nodes[2], selector.Select()) - - t.Run("stick to the same node", func(t *testing.T) { - node := newMockNode[types.ID, nodeClient](t) - // fourth node is alive, LatestReceivedBlockNumber = 2 (same as 3rd) - node.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(2)}) - node.On("Order").Return(int32(1)) - nodes = append(nodes, node) - - selector := newNodeSelector(NodeSelectionModeHighestHead, nodes) - assert.Same(t, nodes[2], selector.Select()) - }) - - t.Run("another best node", func(t *testing.T) { - node := newMockNode[types.ID, nodeClient](t) - // fifth node is alive, LatestReceivedBlockNumber = 3 (better than 3rd and 4th) - node.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(3)}) - node.On("Order").Return(int32(1)) - nodes = append(nodes, node) - - selector := newNodeSelector(NodeSelectionModeHighestHead, nodes) - assert.Same(t, nodes[4], selector.Select()) - }) - - t.Run("nodes never update latest block number", func(t *testing.T) { - node1 := newMockNode[types.ID, nodeClient](t) - node1.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(-1)}) - node1.On("Order").Return(int32(1)) - node2 := newMockNode[types.ID, nodeClient](t) - node2.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(-1)}) - node2.On("Order").Return(int32(1)) - selector := newNodeSelector(NodeSelectionModeHighestHead, []Node[types.ID, nodeClient]{node1, node2}) - assert.Same(t, node1, selector.Select()) - }) -} - -func TestHighestHeadNodeSelector_None(t *testing.T) { - t.Parallel() - - type nodeClient RPCClient[types.ID, Head] - var nodes []Node[types.ID, nodeClient] - - for i := 0; i < 3; i++ { - node := newMockNode[types.ID, nodeClient](t) - if i == 0 { - // first node is out of sync - node.On("StateAndLatest").Return(nodeStateOutOfSync, ChainInfo{BlockNumber: int64(-1)}) - } else { - // others are unreachable - node.On("StateAndLatest").Return(nodeStateUnreachable, ChainInfo{BlockNumber: int64(-1)}) - } - nodes = append(nodes, node) - } - - selector := newNodeSelector(NodeSelectionModeHighestHead, nodes) - assert.Nil(t, selector.Select()) -} - -func TestHighestHeadNodeSelectorWithOrder(t *testing.T) { - t.Parallel() - - type nodeClient RPCClient[types.ID, Head] - var nodes []Node[types.ID, nodeClient] - - t.Run("same head and order", func(t *testing.T) { - for i := 0; i < 3; i++ { - node := newMockNode[types.ID, nodeClient](t) - node.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(1)}) - node.On("Order").Return(int32(2)) - nodes = append(nodes, node) - } - selector := newNodeSelector(NodeSelectionModeHighestHead, nodes) - // Should select the first node because all things are equal - assert.Same(t, nodes[0], selector.Select()) - }) - - t.Run("same head but different order", func(t *testing.T) { - node1 := newMockNode[types.ID, nodeClient](t) - node1.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(3)}) - node1.On("Order").Return(int32(3)) - - node2 := newMockNode[types.ID, nodeClient](t) - node2.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(3)}) - node2.On("Order").Return(int32(1)) - - node3 := newMockNode[types.ID, nodeClient](t) - node3.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(3)}) - node3.On("Order").Return(int32(2)) - - nodes := []Node[types.ID, nodeClient]{node1, node2, node3} - selector := newNodeSelector(NodeSelectionModeHighestHead, nodes) - // Should select the second node as it has the highest priority - assert.Same(t, nodes[1], selector.Select()) - }) - - t.Run("different head but same order", func(t *testing.T) { - node1 := newMockNode[types.ID, nodeClient](t) - node1.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(1)}) - node1.On("Order").Maybe().Return(int32(3)) - - node2 := newMockNode[types.ID, nodeClient](t) - node2.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(2)}) - node2.On("Order").Maybe().Return(int32(3)) - - node3 := newMockNode[types.ID, nodeClient](t) - node3.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(3)}) - node3.On("Order").Return(int32(3)) - - nodes := []Node[types.ID, nodeClient]{node1, node2, node3} - selector := newNodeSelector(NodeSelectionModeHighestHead, nodes) - // Should select the third node as it has the highest head - assert.Same(t, nodes[2], selector.Select()) - }) - - t.Run("different head and different order", func(t *testing.T) { - node1 := newMockNode[types.ID, nodeClient](t) - node1.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(10)}) - node1.On("Order").Maybe().Return(int32(3)) - - node2 := newMockNode[types.ID, nodeClient](t) - node2.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(11)}) - node2.On("Order").Maybe().Return(int32(4)) - - node3 := newMockNode[types.ID, nodeClient](t) - node3.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(11)}) - node3.On("Order").Maybe().Return(int32(3)) - - node4 := newMockNode[types.ID, nodeClient](t) - node4.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(10)}) - node4.On("Order").Maybe().Return(int32(1)) - - nodes := []Node[types.ID, nodeClient]{node1, node2, node3, node4} - selector := newNodeSelector(NodeSelectionModeHighestHead, nodes) - // Should select the third node as it has the highest head and will win the priority tie-breaker - assert.Same(t, nodes[2], selector.Select()) - }) -} diff --git a/common/client/node_selector_priority_level.go b/common/client/node_selector_priority_level.go deleted file mode 100644 index 6d6784fb216..00000000000 --- a/common/client/node_selector_priority_level.go +++ /dev/null @@ -1,123 +0,0 @@ -package client - -import ( - "math" - "sort" - "sync/atomic" - - "github.com/smartcontractkit/chainlink/v2/common/types" -) - -type priorityLevelNodeSelector[ - CHAIN_ID types.ID, - RPC any, -] struct { - nodes []Node[CHAIN_ID, RPC] - roundRobinCount []atomic.Uint32 -} - -type nodeWithPriority[ - CHAIN_ID types.ID, - RPC any, -] struct { - node Node[CHAIN_ID, RPC] - priority int32 -} - -func NewPriorityLevelNodeSelector[ - CHAIN_ID types.ID, - RPC any, -](nodes []Node[CHAIN_ID, RPC]) NodeSelector[CHAIN_ID, RPC] { - return &priorityLevelNodeSelector[CHAIN_ID, RPC]{ - nodes: nodes, - roundRobinCount: make([]atomic.Uint32, nrOfPriorityTiers(nodes)), - } -} - -func (s priorityLevelNodeSelector[CHAIN_ID, RPC]) Select() Node[CHAIN_ID, RPC] { - nodes := s.getHighestPriorityAliveTier() - - if len(nodes) == 0 { - return nil - } - priorityLevel := nodes[len(nodes)-1].priority - - // NOTE: Inc returns the number after addition, so we must -1 to get the "current" counter - count := s.roundRobinCount[priorityLevel].Add(1) - 1 - idx := int(count % uint32(len(nodes))) - - return nodes[idx].node -} - -func (s priorityLevelNodeSelector[CHAIN_ID, RPC]) Name() string { - return NodeSelectionModePriorityLevel -} - -// getHighestPriorityAliveTier filters nodes that are not in state nodeStateAlive and -// returns only the highest tier of alive nodes -func (s priorityLevelNodeSelector[CHAIN_ID, RPC]) getHighestPriorityAliveTier() []nodeWithPriority[CHAIN_ID, RPC] { - var nodes []nodeWithPriority[CHAIN_ID, RPC] - for _, n := range s.nodes { - if n.State() == nodeStateAlive { - nodes = append(nodes, nodeWithPriority[CHAIN_ID, RPC]{n, n.Order()}) - } - } - - if len(nodes) == 0 { - return nil - } - - return removeLowerTiers(nodes) -} - -// removeLowerTiers take a slice of nodeWithPriority[CHAIN_ID, BLOCK_HASH, HEAD, RPC] and keeps only the highest tier -func removeLowerTiers[ - CHAIN_ID types.ID, - RPC any, -](nodes []nodeWithPriority[CHAIN_ID, RPC]) []nodeWithPriority[CHAIN_ID, RPC] { - sort.SliceStable(nodes, func(i, j int) bool { - return nodes[i].priority > nodes[j].priority - }) - - var nodes2 []nodeWithPriority[CHAIN_ID, RPC] - currentPriority := nodes[len(nodes)-1].priority - - for _, n := range nodes { - if n.priority == currentPriority { - nodes2 = append(nodes2, n) - } - } - - return nodes2 -} - -// nrOfPriorityTiers calculates the total number of priority tiers -func nrOfPriorityTiers[ - CHAIN_ID types.ID, - RPC any, -](nodes []Node[CHAIN_ID, RPC]) int32 { - highestPriority := int32(0) - for _, n := range nodes { - priority := n.Order() - if highestPriority < priority { - highestPriority = priority - } - } - return highestPriority + 1 -} - -// firstOrHighestPriority takes a list of nodes and returns the first one with the highest priority -func firstOrHighestPriority[ - CHAIN_ID types.ID, - RPC any, -](nodes []Node[CHAIN_ID, RPC]) Node[CHAIN_ID, RPC] { - hp := int32(math.MaxInt32) - var node Node[CHAIN_ID, RPC] - for _, n := range nodes { - if n.Order() < hp { - hp = n.Order() - node = n - } - } - return node -} diff --git a/common/client/node_selector_priority_level_test.go b/common/client/node_selector_priority_level_test.go deleted file mode 100644 index 67aac97be1b..00000000000 --- a/common/client/node_selector_priority_level_test.go +++ /dev/null @@ -1,91 +0,0 @@ -package client - -import ( - "testing" - - "github.com/smartcontractkit/chainlink/v2/common/types" - - "github.com/stretchr/testify/assert" -) - -func TestPriorityLevelNodeSelectorName(t *testing.T) { - selector := newNodeSelector[types.ID, RPCClient[types.ID, Head]](NodeSelectionModePriorityLevel, nil) - assert.Equal(t, selector.Name(), NodeSelectionModePriorityLevel) -} - -func TestPriorityLevelNodeSelector(t *testing.T) { - t.Parallel() - - type nodeClient RPCClient[types.ID, Head] - type testNode struct { - order int32 - state nodeState - } - type testCase struct { - name string - nodes []testNode - expect []int // indexes of the nodes expected to be returned by Select - } - - testCases := []testCase{ - { - name: "TwoNodesSameOrder: Highest Allowed Order", - nodes: []testNode{ - {order: 1, state: nodeStateAlive}, - {order: 1, state: nodeStateAlive}, - }, - expect: []int{0, 1, 0, 1, 0, 1}, - }, - { - name: "TwoNodesSameOrder: Lowest Allowed Order", - nodes: []testNode{ - {order: 100, state: nodeStateAlive}, - {order: 100, state: nodeStateAlive}, - }, - expect: []int{0, 1, 0, 1, 0, 1}, - }, - { - name: "NoneAvailable", - nodes: []testNode{ - {order: 1, state: nodeStateOutOfSync}, - {order: 1, state: nodeStateUnreachable}, - {order: 1, state: nodeStateUnreachable}, - }, - expect: []int{}, // no nodes should be selected - }, - { - name: "DifferentOrder", - nodes: []testNode{ - {order: 1, state: nodeStateAlive}, - {order: 2, state: nodeStateAlive}, - {order: 3, state: nodeStateAlive}, - }, - expect: []int{0, 0}, // only the highest order node should be selected - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - var nodes []Node[types.ID, nodeClient] - for _, tn := range tc.nodes { - node := newMockNode[types.ID, nodeClient](t) - node.On("State").Return(tn.state) - node.On("Order").Return(tn.order) - nodes = append(nodes, node) - } - - selector := newNodeSelector(NodeSelectionModePriorityLevel, nodes) - for _, idx := range tc.expect { - if idx >= len(nodes) { - t.Fatalf("Invalid node index %d in test case '%s'", idx, tc.name) - } - assert.Same(t, nodes[idx], selector.Select()) - } - - // Check for nil selection if expected slice is empty - if len(tc.expect) == 0 { - assert.Nil(t, selector.Select()) - } - }) - } -} diff --git a/common/client/node_selector_round_robin.go b/common/client/node_selector_round_robin.go deleted file mode 100644 index 18cea03ebd5..00000000000 --- a/common/client/node_selector_round_robin.go +++ /dev/null @@ -1,48 +0,0 @@ -package client - -import ( - "sync/atomic" - - "github.com/smartcontractkit/chainlink/v2/common/types" -) - -type roundRobinSelector[ - CHAIN_ID types.ID, - RPC any, -] struct { - nodes []Node[CHAIN_ID, RPC] - roundRobinCount atomic.Uint32 -} - -func NewRoundRobinSelector[ - CHAIN_ID types.ID, - RPC any, -](nodes []Node[CHAIN_ID, RPC]) NodeSelector[CHAIN_ID, RPC] { - return &roundRobinSelector[CHAIN_ID, RPC]{ - nodes: nodes, - } -} - -func (s *roundRobinSelector[CHAIN_ID, RPC]) Select() Node[CHAIN_ID, RPC] { - var liveNodes []Node[CHAIN_ID, RPC] - for _, n := range s.nodes { - if n.State() == nodeStateAlive { - liveNodes = append(liveNodes, n) - } - } - - nNodes := len(liveNodes) - if nNodes == 0 { - return nil - } - - // NOTE: Inc returns the number after addition, so we must -1 to get the "current" counter - count := s.roundRobinCount.Add(1) - 1 - idx := int(count % uint32(nNodes)) - - return liveNodes[idx] -} - -func (s *roundRobinSelector[CHAIN_ID, RPC]) Name() string { - return NodeSelectionModeRoundRobin -} diff --git a/common/client/node_selector_round_robin_test.go b/common/client/node_selector_round_robin_test.go deleted file mode 100644 index 189b58da9ea..00000000000 --- a/common/client/node_selector_round_robin_test.go +++ /dev/null @@ -1,61 +0,0 @@ -package client - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/smartcontractkit/chainlink/v2/common/types" -) - -func TestRoundRobinNodeSelectorName(t *testing.T) { - selector := newNodeSelector[types.ID, RPCClient[types.ID, Head]](NodeSelectionModeRoundRobin, nil) - assert.Equal(t, selector.Name(), NodeSelectionModeRoundRobin) -} - -func TestRoundRobinNodeSelector(t *testing.T) { - t.Parallel() - - type nodeClient RPCClient[types.ID, Head] - var nodes []Node[types.ID, nodeClient] - - for i := 0; i < 3; i++ { - node := newMockNode[types.ID, nodeClient](t) - if i == 0 { - // first node is out of sync - node.On("State").Return(nodeStateOutOfSync) - } else { - // second & third nodes are alive - node.On("State").Return(nodeStateAlive) - } - nodes = append(nodes, node) - } - - selector := newNodeSelector(NodeSelectionModeRoundRobin, nodes) - assert.Same(t, nodes[1], selector.Select()) - assert.Same(t, nodes[2], selector.Select()) - assert.Same(t, nodes[1], selector.Select()) - assert.Same(t, nodes[2], selector.Select()) -} - -func TestRoundRobinNodeSelector_None(t *testing.T) { - t.Parallel() - - type nodeClient RPCClient[types.ID, Head] - var nodes []Node[types.ID, nodeClient] - - for i := 0; i < 3; i++ { - node := newMockNode[types.ID, nodeClient](t) - if i == 0 { - // first node is out of sync - node.On("State").Return(nodeStateOutOfSync) - } else { - // others are unreachable - node.On("State").Return(nodeStateUnreachable) - } - nodes = append(nodes, node) - } - - selector := newNodeSelector(NodeSelectionModeRoundRobin, nodes) - assert.Nil(t, selector.Select()) -} diff --git a/common/client/node_selector_test.go b/common/client/node_selector_test.go deleted file mode 100644 index f652bfc50ad..00000000000 --- a/common/client/node_selector_test.go +++ /dev/null @@ -1,18 +0,0 @@ -package client - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/smartcontractkit/chainlink/v2/common/types" -) - -func TestNodeSelector(t *testing.T) { - // rest of the tests are located in specific node selectors tests - t.Run("panics on unknown type", func(t *testing.T) { - assert.Panics(t, func() { - _ = newNodeSelector[types.ID, RPCClient[types.ID, Head]]("unknown", nil) - }) - }) -} diff --git a/common/client/node_selector_total_difficulty.go b/common/client/node_selector_total_difficulty.go deleted file mode 100644 index 3a4b9733f0d..00000000000 --- a/common/client/node_selector_total_difficulty.go +++ /dev/null @@ -1,53 +0,0 @@ -package client - -import ( - "math/big" - - "github.com/smartcontractkit/chainlink/v2/common/types" -) - -type totalDifficultyNodeSelector[ - CHAIN_ID types.ID, - RPC any, -] []Node[CHAIN_ID, RPC] - -func NewTotalDifficultyNodeSelector[ - CHAIN_ID types.ID, - RPC any, -](nodes []Node[CHAIN_ID, RPC]) NodeSelector[CHAIN_ID, RPC] { - return totalDifficultyNodeSelector[CHAIN_ID, RPC](nodes) -} - -func (s totalDifficultyNodeSelector[CHAIN_ID, RPC]) Select() Node[CHAIN_ID, RPC] { - // NodeNoNewHeadsThreshold may not be enabled, in this case all nodes have td == nil - var highestTD *big.Int - var nodes []Node[CHAIN_ID, RPC] - var aliveNodes []Node[CHAIN_ID, RPC] - - for _, n := range s { - state, currentChainInfo := n.StateAndLatest() - if state != nodeStateAlive { - continue - } - - currentTD := currentChainInfo.TotalDifficulty - aliveNodes = append(aliveNodes, n) - if currentTD != nil && (highestTD == nil || currentTD.Cmp(highestTD) >= 0) { - if highestTD == nil || currentTD.Cmp(highestTD) > 0 { - highestTD = currentTD - nodes = nil - } - nodes = append(nodes, n) - } - } - - // If all nodes have td == nil pick one from the nodes that are alive - if len(nodes) == 0 { - return firstOrHighestPriority(aliveNodes) - } - return firstOrHighestPriority(nodes) -} - -func (s totalDifficultyNodeSelector[CHAIN_ID, RPC]) Name() string { - return NodeSelectionModeTotalDifficulty -} diff --git a/common/client/node_selector_total_difficulty_test.go b/common/client/node_selector_total_difficulty_test.go deleted file mode 100644 index 7cd5867ddca..00000000000 --- a/common/client/node_selector_total_difficulty_test.go +++ /dev/null @@ -1,178 +0,0 @@ -package client - -import ( - "math/big" - "testing" - - "github.com/smartcontractkit/chainlink/v2/common/types" - - "github.com/stretchr/testify/assert" -) - -func TestTotalDifficultyNodeSelectorName(t *testing.T) { - selector := newNodeSelector[types.ID, RPCClient[types.ID, Head]](NodeSelectionModeTotalDifficulty, nil) - assert.Equal(t, selector.Name(), NodeSelectionModeTotalDifficulty) -} - -func TestTotalDifficultyNodeSelector(t *testing.T) { - t.Parallel() - - type nodeClient RPCClient[types.ID, Head] - var nodes []Node[types.ID, nodeClient] - - for i := 0; i < 3; i++ { - node := newMockNode[types.ID, nodeClient](t) - if i == 0 { - // first node is out of sync - node.On("StateAndLatest").Return(nodeStateOutOfSync, ChainInfo{BlockNumber: -1}) - } else if i == 1 { - // second node is alive - node.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: 1, TotalDifficulty: big.NewInt(7)}) - } else { - // third node is alive and best - node.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: 2, TotalDifficulty: big.NewInt(8)}) - } - node.On("Order").Maybe().Return(int32(1)) - nodes = append(nodes, node) - } - - selector := newNodeSelector(NodeSelectionModeTotalDifficulty, nodes) - assert.Same(t, nodes[2], selector.Select()) - - t.Run("stick to the same node", func(t *testing.T) { - node := newMockNode[types.ID, nodeClient](t) - // fourth node is alive (same as 3rd) - node.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: 2, TotalDifficulty: big.NewInt(8)}) - node.On("Order").Maybe().Return(int32(1)) - nodes = append(nodes, node) - - selector := newNodeSelector(NodeSelectionModeTotalDifficulty, nodes) - assert.Same(t, nodes[2], selector.Select()) - }) - - t.Run("another best node", func(t *testing.T) { - node := newMockNode[types.ID, nodeClient](t) - // fifth node is alive (better than 3rd and 4th) - node.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: 3, TotalDifficulty: big.NewInt(11)}) - node.On("Order").Maybe().Return(int32(1)) - nodes = append(nodes, node) - - selector := newNodeSelector(NodeSelectionModeTotalDifficulty, nodes) - assert.Same(t, nodes[4], selector.Select()) - }) - - t.Run("nodes never update latest block number", func(t *testing.T) { - node1 := newMockNode[types.ID, nodeClient](t) - node1.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: -1, TotalDifficulty: nil}) - node1.On("Order").Maybe().Return(int32(1)) - node2 := newMockNode[types.ID, nodeClient](t) - node2.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: -1, TotalDifficulty: nil}) - node2.On("Order").Maybe().Return(int32(1)) - nodes := []Node[types.ID, nodeClient]{node1, node2} - - selector := newNodeSelector(NodeSelectionModeTotalDifficulty, nodes) - assert.Same(t, node1, selector.Select()) - }) -} - -func TestTotalDifficultyNodeSelector_None(t *testing.T) { - t.Parallel() - - type nodeClient RPCClient[types.ID, Head] - var nodes []Node[types.ID, nodeClient] - - for i := 0; i < 3; i++ { - node := newMockNode[types.ID, nodeClient](t) - if i == 0 { - // first node is out of sync - node.On("StateAndLatest").Return(nodeStateOutOfSync, ChainInfo{BlockNumber: -1, TotalDifficulty: nil}) - } else { - // others are unreachable - node.On("StateAndLatest").Return(nodeStateUnreachable, ChainInfo{BlockNumber: 1, TotalDifficulty: big.NewInt(7)}) - } - nodes = append(nodes, node) - } - - selector := newNodeSelector(NodeSelectionModeTotalDifficulty, nodes) - assert.Nil(t, selector.Select()) -} - -func TestTotalDifficultyNodeSelectorWithOrder(t *testing.T) { - t.Parallel() - - type nodeClient RPCClient[types.ID, Head] - var nodes []Node[types.ID, nodeClient] - - t.Run("same td and order", func(t *testing.T) { - for i := 0; i < 3; i++ { - node := newMockNode[types.ID, nodeClient](t) - node.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: 1, TotalDifficulty: big.NewInt(10)}) - node.On("Order").Return(int32(2)) - nodes = append(nodes, node) - } - selector := newNodeSelector(NodeSelectionModeTotalDifficulty, nodes) - // Should select the first node because all things are equal - assert.Same(t, nodes[0], selector.Select()) - }) - - t.Run("same td but different order", func(t *testing.T) { - node1 := newMockNode[types.ID, nodeClient](t) - node1.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: 3, TotalDifficulty: big.NewInt(10)}) - node1.On("Order").Return(int32(3)) - - node2 := newMockNode[types.ID, nodeClient](t) - node2.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: 3, TotalDifficulty: big.NewInt(10)}) - node2.On("Order").Return(int32(1)) - - node3 := newMockNode[types.ID, nodeClient](t) - node3.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: 3, TotalDifficulty: big.NewInt(10)}) - node3.On("Order").Return(int32(2)) - - nodes := []Node[types.ID, nodeClient]{node1, node2, node3} - selector := newNodeSelector(NodeSelectionModeTotalDifficulty, nodes) - // Should select the second node as it has the highest priority - assert.Same(t, nodes[1], selector.Select()) - }) - - t.Run("different td but same order", func(t *testing.T) { - node1 := newMockNode[types.ID, nodeClient](t) - node1.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: 1, TotalDifficulty: big.NewInt(10)}) - node1.On("Order").Maybe().Return(int32(3)) - - node2 := newMockNode[types.ID, nodeClient](t) - node2.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: 1, TotalDifficulty: big.NewInt(11)}) - node2.On("Order").Maybe().Return(int32(3)) - - node3 := newMockNode[types.ID, nodeClient](t) - node3.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: 1, TotalDifficulty: big.NewInt(12)}) - node3.On("Order").Return(int32(3)) - - nodes := []Node[types.ID, nodeClient]{node1, node2, node3} - selector := newNodeSelector(NodeSelectionModeTotalDifficulty, nodes) - // Should select the third node as it has the highest td - assert.Same(t, nodes[2], selector.Select()) - }) - - t.Run("different head and different order", func(t *testing.T) { - node1 := newMockNode[types.ID, nodeClient](t) - node1.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: 1, TotalDifficulty: big.NewInt(100)}) - node1.On("Order").Maybe().Return(int32(4)) - - node2 := newMockNode[types.ID, nodeClient](t) - node2.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: 1, TotalDifficulty: big.NewInt(110)}) - node2.On("Order").Maybe().Return(int32(5)) - - node3 := newMockNode[types.ID, nodeClient](t) - node3.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: 1, TotalDifficulty: big.NewInt(110)}) - node3.On("Order").Maybe().Return(int32(1)) - - node4 := newMockNode[types.ID, nodeClient](t) - node4.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: 1, TotalDifficulty: big.NewInt(105)}) - node4.On("Order").Maybe().Return(int32(2)) - - nodes := []Node[types.ID, nodeClient]{node1, node2, node3, node4} - selector := newNodeSelector(NodeSelectionModeTotalDifficulty, nodes) - // Should select the third node as it has the highest td and will win the priority tie-breaker - assert.Same(t, nodes[2], selector.Select()) - }) -} diff --git a/common/client/node_test.go b/common/client/node_test.go deleted file mode 100644 index 6d98c2d9ea4..00000000000 --- a/common/client/node_test.go +++ /dev/null @@ -1,107 +0,0 @@ -package client - -import ( - "net/url" - "testing" - "time" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - - clientMocks "github.com/smartcontractkit/chainlink/v2/common/client/mocks" - "github.com/smartcontractkit/chainlink/v2/common/types" -) - -type testNodeConfig struct { - pollFailureThreshold uint32 - pollInterval time.Duration - selectionMode string - syncThreshold uint32 - nodeIsSyncingEnabled bool - enforceRepeatableRead bool - finalizedBlockPollInterval time.Duration - deathDeclarationDelay time.Duration - newHeadsPollInterval time.Duration -} - -func (n testNodeConfig) NewHeadsPollInterval() time.Duration { - return n.newHeadsPollInterval -} - -func (n testNodeConfig) PollFailureThreshold() uint32 { - return n.pollFailureThreshold -} - -func (n testNodeConfig) PollInterval() time.Duration { - return n.pollInterval -} - -func (n testNodeConfig) SelectionMode() string { - return n.selectionMode -} - -func (n testNodeConfig) SyncThreshold() uint32 { - return n.syncThreshold -} - -func (n testNodeConfig) NodeIsSyncingEnabled() bool { - return n.nodeIsSyncingEnabled -} - -func (n testNodeConfig) FinalizedBlockPollInterval() time.Duration { - return n.finalizedBlockPollInterval -} - -func (n testNodeConfig) EnforceRepeatableRead() bool { - return n.enforceRepeatableRead -} - -func (n testNodeConfig) DeathDeclarationDelay() time.Duration { - return n.deathDeclarationDelay -} - -type testNode struct { - *node[types.ID, Head, RPCClient[types.ID, Head]] -} - -type testNodeOpts struct { - config testNodeConfig - chainConfig clientMocks.ChainConfig - lggr logger.Logger - wsuri *url.URL - httpuri *url.URL - name string - id int - chainID types.ID - nodeOrder int32 - rpc *mockRPCClient[types.ID, Head] - chainFamily string -} - -func newTestNode(t *testing.T, opts testNodeOpts) testNode { - if opts.lggr == nil { - opts.lggr = logger.Test(t) - } - - if opts.name == "" { - opts.name = "tes node" - } - - if opts.chainFamily == "" { - opts.chainFamily = "test node chain family" - } - - if opts.chainID == nil { - opts.chainID = types.RandomID() - } - - if opts.id == 0 { - opts.id = 42 - } - - nodeI := NewNode[types.ID, Head, RPCClient[types.ID, Head]](opts.config, opts.chainConfig, opts.lggr, - opts.wsuri, opts.httpuri, opts.name, opts.id, opts.chainID, opts.nodeOrder, opts.rpc, opts.chainFamily) - - return testNode{ - nodeI.(*node[types.ID, Head, RPCClient[types.ID, Head]]), - } -} diff --git a/common/client/poller.go b/common/client/poller.go deleted file mode 100644 index bdd3d36f16f..00000000000 --- a/common/client/poller.go +++ /dev/null @@ -1,95 +0,0 @@ -package client - -import ( - "context" - "time" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/services" - - "github.com/smartcontractkit/chainlink/v2/common/types" -) - -// Poller is a component that polls a function at a given interval -// and delivers the result to a channel. It is used by multinode to poll -// for new heads and implements the Subscription interface. -type Poller[T any] struct { - services.Service - eng *services.Engine - - pollingInterval time.Duration - pollingFunc func(ctx context.Context) (T, error) - pollingTimeout time.Duration - channel chan<- T - errCh chan error -} - -// 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, lggr logger.Logger) (Poller[T], <-chan T) { - channel := make(chan T) - p := Poller[T]{ - pollingInterval: pollingInterval, - pollingFunc: pollingFunc, - pollingTimeout: pollingTimeout, - channel: channel, - errCh: make(chan error), - } - p.Service, p.eng = services.Config{ - Name: "Poller", - Start: p.start, - Close: p.close, - }.NewServiceEngine(lggr) - return p, channel -} - -var _ types.Subscription = &Poller[any]{} - -func (p *Poller[T]) start(ctx context.Context) error { - p.eng.Go(p.pollingLoop) - return nil -} - -// Unsubscribe cancels the sending of events to the data channel -func (p *Poller[T]) Unsubscribe() { - _ = p.Close() -} - -func (p *Poller[T]) close() error { - close(p.errCh) - close(p.channel) - return nil -} - -func (p *Poller[T]) Err() <-chan error { - return p.errCh -} - -func (p *Poller[T]) pollingLoop(ctx context.Context) { - ticker := services.NewTicker(p.pollingInterval) // reduce possibility of sending two exactly the same request at once - defer ticker.Stop() - - for { - select { - case <-ctx.Done(): - return - case <-ticker.C: - // Set polling timeout - pollingCtx, cancelPolling := context.WithTimeout(ctx, p.pollingTimeout) - // Execute polling function - result, err := p.pollingFunc(pollingCtx) - cancelPolling() - if err != nil { - p.eng.Warnf("polling error: %v", err) - continue - } - // Send result to channel or block if channel is full - select { - case p.channel <- result: - case <-ctx.Done(): - return - } - } - } -} diff --git a/common/client/poller_test.go b/common/client/poller_test.go deleted file mode 100644 index 930b101751c..00000000000 --- a/common/client/poller_test.go +++ /dev/null @@ -1,194 +0,0 @@ -package client - -import ( - "context" - "fmt" - "math/big" - "sync" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "go.uber.org/zap" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" -) - -func Test_Poller(t *testing.T) { - lggr := logger.Test(t) - - t.Run("Test multiple start", func(t *testing.T) { - ctx := tests.Context(t) - pollFunc := func(ctx context.Context) (Head, error) { - return nil, nil - } - - poller, _ := NewPoller[Head](time.Millisecond, pollFunc, time.Second, lggr) - err := poller.Start(ctx) - require.NoError(t, err) - - err = poller.Start(ctx) - require.Error(t, err) - poller.Unsubscribe() - }) - - t.Run("Test polling for heads", func(t *testing.T) { - ctx := tests.Context(t) - // Mock polling function that returns a new value every time it's called - var pollNumber int - pollLock := sync.Mutex{} - pollFunc := func(ctx context.Context) (Head, error) { - pollLock.Lock() - defer pollLock.Unlock() - pollNumber++ - h := head{ - BlockNumber: int64(pollNumber), - BlockDifficulty: big.NewInt(int64(pollNumber)), - } - return h.ToMockHead(t), nil - } - - // Create poller and start to receive data - poller, channel := NewPoller[Head](time.Millisecond, pollFunc, time.Second, lggr) - require.NoError(t, poller.Start(ctx)) - defer poller.Unsubscribe() - - // Receive updates from the poller - pollCount := 0 - pollMax := 50 - for ; pollCount < pollMax; pollCount++ { - h := <-channel - assert.Equal(t, int64(pollCount+1), h.BlockNumber()) - } - }) - - t.Run("Test polling errors", func(t *testing.T) { - ctx := tests.Context(t) - // Mock polling function that returns an error - var pollNumber int - pollLock := sync.Mutex{} - pollFunc := func(ctx context.Context) (Head, error) { - pollLock.Lock() - defer pollLock.Unlock() - pollNumber++ - return nil, fmt.Errorf("polling error %d", pollNumber) - } - - olggr, observedLogs := logger.TestObserved(t, zap.WarnLevel) - - // Create poller and subscribe to receive data - poller, _ := NewPoller[Head](time.Millisecond, pollFunc, time.Second, olggr) - require.NoError(t, poller.Start(ctx)) - defer poller.Unsubscribe() - - // Ensure that all errors were logged as expected - logsSeen := func() bool { - for pollCount := 0; pollCount < 50; pollCount++ { - numLogs := observedLogs.FilterMessage(fmt.Sprintf("polling error: polling error %d", pollCount+1)).Len() - if numLogs != 1 { - return false - } - } - return true - } - require.Eventually(t, logsSeen, tests.WaitTimeout(t), 100*time.Millisecond) - }) - - t.Run("Test polling timeout", func(t *testing.T) { - ctx := tests.Context(t) - pollFunc := func(ctx context.Context) (Head, error) { - if <-ctx.Done(); true { - return nil, ctx.Err() - } - return nil, nil - } - - // Set instant timeout - pollingTimeout := time.Duration(0) - - olggr, observedLogs := logger.TestObserved(t, zap.WarnLevel) - - // Create poller and subscribe to receive data - poller, _ := NewPoller[Head](time.Millisecond, pollFunc, pollingTimeout, olggr) - require.NoError(t, poller.Start(ctx)) - defer poller.Unsubscribe() - - // Ensure that timeout errors were logged as expected - logsSeen := func() bool { - return observedLogs.FilterMessage("polling error: context deadline exceeded").Len() >= 1 - } - require.Eventually(t, logsSeen, tests.WaitTimeout(t), 100*time.Millisecond) - }) - - t.Run("Test unsubscribe during polling", func(t *testing.T) { - ctx := tests.Context(t) - wait := make(chan struct{}) - closeOnce := sync.OnceFunc(func() { close(wait) }) - pollFunc := func(ctx context.Context) (Head, error) { - closeOnce() - // Block in polling function until context is cancelled - if <-ctx.Done(); true { - return nil, ctx.Err() - } - return nil, nil - } - - // Set long timeout - pollingTimeout := time.Minute - - olggr, observedLogs := logger.TestObserved(t, zap.WarnLevel) - - // Create poller and subscribe to receive data - poller, _ := NewPoller[Head](time.Millisecond, pollFunc, pollingTimeout, olggr) - require.NoError(t, poller.Start(ctx)) - - // Unsubscribe while blocked in polling function - <-wait - poller.Unsubscribe() - - // Ensure error was logged - logsSeen := func() bool { - return observedLogs.FilterMessage("polling error: context canceled").Len() >= 1 - } - require.Eventually(t, logsSeen, tests.WaitTimeout(t), 100*time.Millisecond) - }) -} - -func Test_Poller_Unsubscribe(t *testing.T) { - lggr := logger.Test(t) - pollFunc := func(ctx context.Context) (Head, error) { - select { - case <-ctx.Done(): - return nil, ctx.Err() - default: - h := head{ - BlockNumber: 0, - BlockDifficulty: big.NewInt(0), - } - return h.ToMockHead(t), nil - } - } - - t.Run("Test multiple unsubscribe", func(t *testing.T) { - ctx := tests.Context(t) - poller, channel := NewPoller[Head](time.Millisecond, pollFunc, time.Second, lggr) - err := poller.Start(ctx) - require.NoError(t, err) - - <-channel - poller.Unsubscribe() - poller.Unsubscribe() - }) - - t.Run("Read channel after unsubscribe", func(t *testing.T) { - ctx := tests.Context(t) - poller, channel := NewPoller[Head](time.Millisecond, pollFunc, time.Second, lggr) - err := poller.Start(ctx) - require.NoError(t, err) - - poller.Unsubscribe() - require.Equal(t, <-channel, nil) - }) -} diff --git a/common/client/send_only_node.go b/common/client/send_only_node.go deleted file mode 100644 index 0a1715fa191..00000000000 --- a/common/client/send_only_node.go +++ /dev/null @@ -1,183 +0,0 @@ -package client - -import ( - "context" - "fmt" - "net/url" - "sync" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/services" - - "github.com/smartcontractkit/chainlink/v2/common/types" -) - -type sendOnlyClient[ - CHAIN_ID types.ID, -] interface { - Close() - ChainID(context.Context) (CHAIN_ID, error) - Dial(ctx context.Context) error -} - -// SendOnlyNode represents one node used as a sendonly -type SendOnlyNode[ - CHAIN_ID types.ID, - RPC any, -] interface { - // Start may attempt to connect to the node, but should only return error for misconfiguration - never for temporary errors. - Start(context.Context) error - Close() error - - ConfiguredChainID() CHAIN_ID - RPC() RPC - - String() string - // State returns nodeState - State() nodeState - // Name is a unique identifier for this node. - Name() string -} - -// It only supports sending transactions -// It must use an http(s) url -type sendOnlyNode[ - CHAIN_ID types.ID, - RPC sendOnlyClient[CHAIN_ID], -] struct { - services.StateMachine - - stateMu sync.RWMutex // protects state* fields - state nodeState - - rpc RPC - uri url.URL - log logger.Logger - name string - chainID CHAIN_ID - chStop services.StopChan - wg sync.WaitGroup -} - -// NewSendOnlyNode returns a new sendonly node -func NewSendOnlyNode[ - CHAIN_ID types.ID, - RPC sendOnlyClient[CHAIN_ID], -]( - lggr logger.Logger, - httpuri url.URL, - name string, - chainID CHAIN_ID, - rpc RPC, -) SendOnlyNode[CHAIN_ID, RPC] { - s := new(sendOnlyNode[CHAIN_ID, RPC]) - s.name = name - s.log = logger.Named(logger.Named(lggr, "SendOnlyNode"), name) - s.log = logger.With(s.log, - "nodeTier", "sendonly", - ) - s.rpc = rpc - s.uri = httpuri - s.chainID = chainID - s.chStop = make(chan struct{}) - return s -} - -func (s *sendOnlyNode[CHAIN_ID, RPC]) Start(ctx context.Context) error { - return s.StartOnce(s.name, func() error { - s.start(ctx) - return nil - }) -} - -// Start setups up and verifies the sendonly node -// Should only be called once in a node's lifecycle -func (s *sendOnlyNode[CHAIN_ID, RPC]) start(startCtx context.Context) { - if s.State() != nodeStateUndialed { - panic(fmt.Sprintf("cannot dial node with state %v", s.state)) - } - - err := s.rpc.Dial(startCtx) - if err != nil { - promPoolRPCNodeTransitionsToUnusable.WithLabelValues(s.chainID.String(), s.name).Inc() - s.log.Errorw("Dial failed: SendOnly Node is unusable", "err", err) - s.setState(nodeStateUnusable) - return - } - s.setState(nodeStateDialed) - - if s.chainID.String() == "0" { - // Skip verification if chainID is zero - s.log.Warn("sendonly rpc ChainID verification skipped") - } else { - chainID, err := s.rpc.ChainID(startCtx) - if err != nil || chainID.String() != s.chainID.String() { - promPoolRPCNodeTransitionsToUnreachable.WithLabelValues(s.chainID.String(), s.name).Inc() - if err != nil { - promPoolRPCNodeTransitionsToUnreachable.WithLabelValues(s.chainID.String(), s.name).Inc() - s.log.Errorw(fmt.Sprintf("Verify failed: %v", err), "err", err) - s.setState(nodeStateUnreachable) - } else { - promPoolRPCNodeTransitionsToInvalidChainID.WithLabelValues(s.chainID.String(), s.name).Inc() - s.log.Errorf( - "sendonly rpc ChainID doesn't match local chain ID: RPC ID=%s, local ID=%s, node name=%s", - chainID.String(), - s.chainID.String(), - s.name, - ) - s.setState(nodeStateInvalidChainID) - } - // Since it has failed, spin up the verifyLoop that will keep - // retrying until success - s.wg.Add(1) - go s.verifyLoop() - return - } - } - - promPoolRPCNodeTransitionsToAlive.WithLabelValues(s.chainID.String(), s.name).Inc() - s.setState(nodeStateAlive) - s.log.Infow("Sendonly RPC Node is online", "nodeState", s.state) -} - -func (s *sendOnlyNode[CHAIN_ID, RPC]) Close() error { - return s.StopOnce(s.name, func() error { - s.rpc.Close() - close(s.chStop) - s.wg.Wait() - s.setState(nodeStateClosed) - return nil - }) -} - -func (s *sendOnlyNode[CHAIN_ID, RPC]) ConfiguredChainID() CHAIN_ID { - return s.chainID -} - -func (s *sendOnlyNode[CHAIN_ID, RPC]) RPC() RPC { - return s.rpc -} - -func (s *sendOnlyNode[CHAIN_ID, RPC]) String() string { - return fmt.Sprintf("(%s)%s:%s", Secondary.String(), s.name, s.uri.Redacted()) -} - -func (s *sendOnlyNode[CHAIN_ID, RPC]) setState(state nodeState) (changed bool) { - s.stateMu.Lock() - defer s.stateMu.Unlock() - if s.state == state { - return false - } - s.state = state - return true -} - -func (s *sendOnlyNode[CHAIN_ID, RPC]) State() nodeState { - s.stateMu.RLock() - defer s.stateMu.RUnlock() - return s.state -} - -func (s *sendOnlyNode[CHAIN_ID, RPC]) Name() string { - return s.name -} diff --git a/common/client/send_only_node_lifecycle.go b/common/client/send_only_node_lifecycle.go deleted file mode 100644 index c66d267ed42..00000000000 --- a/common/client/send_only_node_lifecycle.go +++ /dev/null @@ -1,67 +0,0 @@ -package client - -import ( - "fmt" - "time" - - "github.com/smartcontractkit/chainlink/v2/common/internal/utils" -) - -// verifyLoop may only be triggered once, on Start, if initial chain ID check -// fails. -// -// It will continue checking until success and then exit permanently. -func (s *sendOnlyNode[CHAIN_ID, RPC]) verifyLoop() { - defer s.wg.Done() - ctx, cancel := s.chStop.NewCtx() - defer cancel() - - backoff := utils.NewRedialBackoff() - for { - select { - case <-ctx.Done(): - return - case <-time.After(backoff.Duration()): - } - chainID, err := s.rpc.ChainID(ctx) - if err != nil { - ok := s.IfStarted(func() { - if changed := s.setState(nodeStateUnreachable); changed { - promPoolRPCNodeTransitionsToUnreachable.WithLabelValues(s.chainID.String(), s.name).Inc() - } - }) - if !ok { - return - } - s.log.Errorw(fmt.Sprintf("Verify failed: %v", err), "err", err) - continue - } else if chainID.String() != s.chainID.String() { - ok := s.IfStarted(func() { - if changed := s.setState(nodeStateInvalidChainID); changed { - promPoolRPCNodeTransitionsToInvalidChainID.WithLabelValues(s.chainID.String(), s.name).Inc() - } - }) - if !ok { - return - } - s.log.Errorf( - "sendonly rpc ChainID doesn't match local chain ID: RPC ID=%s, local ID=%s, node name=%s", - chainID.String(), - s.chainID.String(), - s.name, - ) - - continue - } - ok := s.IfStarted(func() { - if changed := s.setState(nodeStateAlive); changed { - promPoolRPCNodeTransitionsToAlive.WithLabelValues(s.chainID.String(), s.name).Inc() - } - }) - if !ok { - return - } - s.log.Infow("Sendonly RPC Node is online", "nodeState", s.state) - return - } -} diff --git a/common/client/send_only_node_test.go b/common/client/send_only_node_test.go deleted file mode 100644 index 532946da48f..00000000000 --- a/common/client/send_only_node_test.go +++ /dev/null @@ -1,139 +0,0 @@ -package client - -import ( - "errors" - "fmt" - "net/url" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - "go.uber.org/zap" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - - "github.com/smartcontractkit/chainlink/v2/common/types" -) - -func TestNewSendOnlyNode(t *testing.T) { - t.Parallel() - - urlFormat := "http://user:%s@testurl.com" - password := "pass" - u, err := url.Parse(fmt.Sprintf(urlFormat, password)) - require.NoError(t, err) - redacted := fmt.Sprintf(urlFormat, "xxxxx") - lggr := logger.Test(t) - name := "TestNewSendOnlyNode" - chainID := types.RandomID() - client := newMockSendOnlyClient[types.ID](t) - - node := NewSendOnlyNode(lggr, *u, name, chainID, client) - assert.NotNil(t, node) - - // Must contain name & url with redacted password - assert.Contains(t, node.String(), fmt.Sprintf("%s:%s", name, redacted)) - assert.Equal(t, node.ConfiguredChainID(), chainID) -} - -func TestStartSendOnlyNode(t *testing.T) { - t.Parallel() - t.Run("becomes unusable if initial dial fails", func(t *testing.T) { - t.Parallel() - lggr, observedLogs := logger.TestObserved(t, zap.WarnLevel) - client := newMockSendOnlyClient[types.ID](t) - client.On("Close").Once() - expectedError := errors.New("some http error") - client.On("Dial", mock.Anything).Return(expectedError).Once() - s := NewSendOnlyNode(lggr, url.URL{}, t.Name(), types.RandomID(), client) - - defer func() { assert.NoError(t, s.Close()) }() - err := s.Start(tests.Context(t)) - require.NoError(t, err) - - assert.Equal(t, nodeStateUnusable, s.State()) - tests.RequireLogMessage(t, observedLogs, "Dial failed: SendOnly Node is unusable") - }) - t.Run("Default ChainID(0) produces warn and skips checks", func(t *testing.T) { - t.Parallel() - lggr, observedLogs := logger.TestObserved(t, zap.WarnLevel) - client := newMockSendOnlyClient[types.ID](t) - client.On("Close").Once() - client.On("Dial", mock.Anything).Return(nil).Once() - s := NewSendOnlyNode(lggr, url.URL{}, t.Name(), types.NewIDFromInt(0), client) - - defer func() { assert.NoError(t, s.Close()) }() - err := s.Start(tests.Context(t)) - require.NoError(t, err) - - assert.Equal(t, nodeStateAlive, s.State()) - tests.RequireLogMessage(t, observedLogs, "sendonly rpc ChainID verification skipped") - }) - t.Run("Can recover from chainID verification failure", func(t *testing.T) { - t.Parallel() - lggr, observedLogs := logger.TestObserved(t, zap.WarnLevel) - client := newMockSendOnlyClient[types.ID](t) - client.On("Close").Once() - client.On("Dial", mock.Anything).Return(nil) - expectedError := errors.New("failed to get chain ID") - chainID := types.RandomID() - const failuresCount = 2 - client.On("ChainID", mock.Anything).Return(types.RandomID(), expectedError).Times(failuresCount) - client.On("ChainID", mock.Anything).Return(chainID, nil) - - s := NewSendOnlyNode(lggr, url.URL{}, t.Name(), chainID, client) - - defer func() { assert.NoError(t, s.Close()) }() - err := s.Start(tests.Context(t)) - require.NoError(t, err) - - assert.Equal(t, nodeStateUnreachable, s.State()) - tests.AssertLogCountEventually(t, observedLogs, fmt.Sprintf("Verify failed: %v", expectedError), failuresCount) - tests.AssertEventually(t, func() bool { - return s.State() == nodeStateAlive - }) - }) - t.Run("Can recover from chainID mismatch", func(t *testing.T) { - t.Parallel() - lggr, observedLogs := logger.TestObserved(t, zap.WarnLevel) - client := newMockSendOnlyClient[types.ID](t) - client.On("Close").Once() - client.On("Dial", mock.Anything).Return(nil).Once() - configuredChainID := types.NewIDFromInt(11) - rpcChainID := types.NewIDFromInt(20) - const failuresCount = 2 - client.On("ChainID", mock.Anything).Return(rpcChainID, nil).Times(failuresCount) - client.On("ChainID", mock.Anything).Return(configuredChainID, nil) - s := NewSendOnlyNode(lggr, url.URL{}, t.Name(), configuredChainID, client) - - defer func() { assert.NoError(t, s.Close()) }() - err := s.Start(tests.Context(t)) - require.NoError(t, err) - - assert.Equal(t, nodeStateInvalidChainID, s.State()) - tests.AssertLogCountEventually(t, observedLogs, "sendonly rpc ChainID doesn't match local chain ID", failuresCount) - tests.AssertEventually(t, func() bool { - return s.State() == nodeStateAlive - }) - }) - t.Run("Start with Random ChainID", func(t *testing.T) { - t.Parallel() - lggr, observedLogs := logger.TestObserved(t, zap.WarnLevel) - client := newMockSendOnlyClient[types.ID](t) - client.On("Close").Once() - client.On("Dial", mock.Anything).Return(nil).Once() - configuredChainID := types.RandomID() - client.On("ChainID", mock.Anything).Return(configuredChainID, nil) - s := NewSendOnlyNode(lggr, url.URL{}, t.Name(), configuredChainID, client) - - defer func() { assert.NoError(t, s.Close()) }() - err := s.Start(tests.Context(t)) - assert.NoError(t, err) - tests.AssertEventually(t, func() bool { - return s.State() == nodeStateAlive - }) - assert.Equal(t, 0, observedLogs.Len()) // No warnings expected - }) -} diff --git a/common/client/transaction_sender.go b/common/client/transaction_sender.go deleted file mode 100644 index 5f58682142f..00000000000 --- a/common/client/transaction_sender.go +++ /dev/null @@ -1,301 +0,0 @@ -package client - -import ( - "context" - "errors" - "math" - "slices" - "sync" - "time" - - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promauto" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/services" - - "github.com/smartcontractkit/chainlink/v2/common/types" -) - -var ( - // PromMultiNodeInvariantViolations reports violation of our assumptions - PromMultiNodeInvariantViolations = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "multi_node_invariant_violations", - Help: "The number of invariant violations", - }, []string{"network", "chainId", "invariant"}) -) - -type SendTxResult interface { - Code() SendTxReturnCode - Error() error -} - -const sendTxQuorum = 0.7 - -// SendTxRPCClient - defines interface of an RPC used by TransactionSender to broadcast transaction -type SendTxRPCClient[TX any, RESULT SendTxResult] interface { - // SendTransaction errors returned should include name or other unique identifier of the RPC - SendTransaction(ctx context.Context, tx TX) RESULT -} - -func NewTransactionSender[TX any, RESULT SendTxResult, CHAIN_ID types.ID, RPC SendTxRPCClient[TX, RESULT]]( - lggr logger.Logger, - chainID CHAIN_ID, - chainFamily string, - multiNode *MultiNode[CHAIN_ID, RPC], - newResult func(err error) RESULT, - sendTxSoftTimeout time.Duration, -) *TransactionSender[TX, RESULT, CHAIN_ID, RPC] { - if sendTxSoftTimeout == 0 { - sendTxSoftTimeout = QueryTimeout / 2 - } - return &TransactionSender[TX, RESULT, CHAIN_ID, RPC]{ - chainID: chainID, - chainFamily: chainFamily, - lggr: logger.Sugared(lggr).Named("TransactionSender").With("chainID", chainID.String()), - multiNode: multiNode, - newResult: newResult, - sendTxSoftTimeout: sendTxSoftTimeout, - chStop: make(services.StopChan), - } -} - -type TransactionSender[TX any, RESULT SendTxResult, CHAIN_ID types.ID, RPC SendTxRPCClient[TX, RESULT]] struct { - services.StateMachine - chainID CHAIN_ID - chainFamily string - lggr logger.SugaredLogger - multiNode *MultiNode[CHAIN_ID, RPC] - newResult func(err error) RESULT - sendTxSoftTimeout time.Duration // defines max waiting time from first response til responses evaluation - - wg sync.WaitGroup // waits for all reporting goroutines to finish - chStop services.StopChan -} - -// SendTransaction - broadcasts transaction to all the send-only and primary nodes in MultiNode. -// A returned nil or error does not guarantee that the transaction will or won't be included. Additional checks must be -// performed to determine the final state. -// -// Send-only nodes' results are ignored as they tend to return false-positive responses. Broadcast to them is necessary -// to speed up the propagation of TX in the network. -// -// Handling of primary nodes' results consists of collection and aggregation. -// In the collection step, we gather as many results as possible while minimizing waiting time. This operation succeeds -// on one of the following conditions: -// * Received at least one success -// * Received at least one result and `sendTxSoftTimeout` expired -// * Received results from the sufficient number of nodes defined by sendTxQuorum. -// The aggregation is based on the following conditions: -// * If there is at least one success - returns success -// * If there is at least one terminal error - returns terminal error -// * If there is both success and terminal error - returns success and reports invariant violation -// * Otherwise, returns any (effectively random) of the errors. -func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) SendTransaction(ctx context.Context, tx TX) RESULT { - var result RESULT - ctx, cancel := txSender.chStop.Ctx(ctx) - defer cancel() - if !txSender.IfStarted(func() { - txResults := make(chan RESULT) - txResultsToReport := make(chan RESULT) - primaryNodeWg := sync.WaitGroup{} - - healthyNodesNum := 0 - err := txSender.multiNode.DoAll(ctx, func(ctx context.Context, rpc RPC, isSendOnly bool) { - if isSendOnly { - txSender.wg.Add(1) - go func(ctx context.Context) { - defer txSender.wg.Done() - // Send-only nodes' results are ignored as they tend to return false-positive responses. - // Broadcast to them is necessary to speed up the propagation of TX in the network. - _ = txSender.broadcastTxAsync(ctx, rpc, tx) - }(ctx) - return - } - - // Primary Nodes - healthyNodesNum++ - primaryNodeWg.Add(1) - go func(ctx context.Context) { - // Broadcasting transaction and results reporting for invariant detection are background jobs that must be detached from - // callers cancellation. - // Results reporting to SendTransaction caller must respect caller's context to avoid goroutine leak. - defer primaryNodeWg.Done() - r := txSender.broadcastTxAsync(ctx, rpc, tx) - select { - case <-ctx.Done(): - txSender.lggr.Debugw("Failed to send tx results", "err", ctx.Err()) - return - case txResults <- r: - } - - ctx, cancel := txSender.chStop.Ctx(context.WithoutCancel(ctx)) - defer cancel() - select { - case <-ctx.Done(): - txSender.lggr.Debugw("Failed to send tx results to report", "err", ctx.Err()) - return - case txResultsToReport <- r: - } - }(ctx) - }) - - // This needs to be done in parallel so the reporting knows when it's done (when the channel is closed) - txSender.wg.Add(1) - go func() { - defer txSender.wg.Done() - primaryNodeWg.Wait() - close(txResultsToReport) - close(txResults) - }() - - if err != nil { - result = txSender.newResult(err) - return - } - - if healthyNodesNum == 0 { - result = txSender.newResult(ErroringNodeError) - return - } - - txSender.wg.Add(1) - go txSender.reportSendTxAnomalies(tx, txResultsToReport) - - result = txSender.collectTxResults(ctx, tx, healthyNodesNum, txResults) - }) { - result = txSender.newResult(errors.New("TransactionSender not started")) - } - - return result -} - -func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) broadcastTxAsync(ctx context.Context, rpc RPC, tx TX) RESULT { - // broadcast is a background job, so always detach from caller's cancellation - ctx, cancel := txSender.chStop.Ctx(context.WithoutCancel(ctx)) - defer cancel() - result := rpc.SendTransaction(ctx, tx) - txSender.lggr.Debugw("Node sent transaction", "tx", tx, "err", result.Error()) - if !slices.Contains(sendTxSuccessfulCodes, result.Code()) && ctx.Err() == nil { - txSender.lggr.Warnw("RPC returned error", "tx", tx, "err", result.Error()) - } - return result -} - -func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) reportSendTxAnomalies(tx TX, txResults <-chan RESULT) { - defer txSender.wg.Done() - resultsByCode := sendTxResults[RESULT]{} - // txResults eventually will be closed - for txResult := range txResults { - resultsByCode[txResult.Code()] = append(resultsByCode[txResult.Code()], txResult) - } - - select { - case <-txSender.chStop: - // it's ok to receive no results if txSender is closing. Return early to prevent false reporting of invariant violation. - if len(resultsByCode) == 0 { - return - } - default: - } - - _, criticalErr := aggregateTxResults[RESULT](resultsByCode) - if criticalErr != nil { - txSender.lggr.Criticalw("observed invariant violation on SendTransaction", "tx", tx, "resultsByCode", resultsByCode, "err", criticalErr) - PromMultiNodeInvariantViolations.WithLabelValues(txSender.chainFamily, txSender.chainID.String(), criticalErr.Error()).Inc() - } -} - -type sendTxResults[RESULT any] map[SendTxReturnCode][]RESULT - -func aggregateTxResults[RESULT any](resultsByCode sendTxResults[RESULT]) (result RESULT, criticalErr error) { - severeErrors, hasSevereErrors := findFirstIn(resultsByCode, sendTxSevereErrors) - successResults, hasSuccess := findFirstIn(resultsByCode, sendTxSuccessfulCodes) - if hasSuccess { - // We assume that primary node would never report false positive txResult for a transaction. - // Thus, if such case occurs it's probably due to misconfiguration or a bug and requires manual intervention. - if hasSevereErrors { - const errMsg = "found contradictions in nodes replies on SendTransaction: got success and severe error" - // return success, since at least 1 node has accepted our broadcasted Tx, and thus it can now be included onchain - return successResults[0], errors.New(errMsg) - } - - // other errors are temporary - we are safe to return success - return successResults[0], nil - } - - if hasSevereErrors { - return severeErrors[0], nil - } - - // return temporary error - for _, r := range resultsByCode { - return r[0], nil - } - - criticalErr = errors.New("expected at least one response on SendTransaction") - return result, criticalErr -} - -func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) collectTxResults(ctx context.Context, tx TX, healthyNodesNum int, txResults <-chan RESULT) RESULT { - requiredResults := int(math.Ceil(float64(healthyNodesNum) * sendTxQuorum)) - errorsByCode := sendTxResults[RESULT]{} - var softTimeoutChan <-chan time.Time - var resultsCount int -loop: - for { - select { - case <-ctx.Done(): - txSender.lggr.Debugw("Failed to collect of the results before context was done", "tx", tx, "errorsByCode", errorsByCode) - return txSender.newResult(ctx.Err()) - case r := <-txResults: - errorsByCode[r.Code()] = append(errorsByCode[r.Code()], r) - resultsCount++ - if slices.Contains(sendTxSuccessfulCodes, r.Code()) || resultsCount >= requiredResults { - break loop - } - case <-softTimeoutChan: - txSender.lggr.Debugw("Send Tx soft timeout expired - returning responses we've collected so far", "tx", tx, "resultsCount", resultsCount, "requiredResults", requiredResults) - break loop - } - - if softTimeoutChan == nil { - tm := time.NewTimer(txSender.sendTxSoftTimeout) - softTimeoutChan = tm.C - // we are fine with stopping timer at the end of function - //nolint - defer tm.Stop() - } - } - - // ignore critical error as it's reported in reportSendTxAnomalies - result, _ := aggregateTxResults(errorsByCode) - txSender.lggr.Debugw("Collected results", "errorsByCode", errorsByCode, "result", result) - return result -} - -func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) Start(ctx context.Context) error { - return txSender.StartOnce("TransactionSender", func() error { - return nil - }) -} - -func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) Close() error { - return txSender.StopOnce("TransactionSender", func() error { - txSender.lggr.Debug("Closing TransactionSender") - close(txSender.chStop) - txSender.wg.Wait() - return nil - }) -} - -// findFirstIn - returns the first existing key and value for the slice of keys -func findFirstIn[K comparable, V any](set map[K]V, keys []K) (V, bool) { - for _, k := range keys { - if v, ok := set[k]; ok { - return v, true - } - } - var zeroV V - return zeroV, false -} diff --git a/common/client/transaction_sender_test.go b/common/client/transaction_sender_test.go deleted file mode 100644 index 656791b7e86..00000000000 --- a/common/client/transaction_sender_test.go +++ /dev/null @@ -1,420 +0,0 @@ -package client - -import ( - "context" - "fmt" - "testing" - - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - "go.uber.org/zap" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - - "github.com/smartcontractkit/chainlink/v2/common/types" -) - -type TestSendTxRPCClient SendTxRPCClient[any, *sendTxResult] - -type sendTxMultiNode struct { - *MultiNode[types.ID, TestSendTxRPCClient] -} - -type sendTxRPC struct { - sendTxRun func(args mock.Arguments) - sendTxErr error -} - -type sendTxResult struct { - err error - code SendTxReturnCode -} - -var _ SendTxResult = (*sendTxResult)(nil) - -func NewSendTxResult(err error) *sendTxResult { - result := &sendTxResult{ - err: err, - } - return result -} - -func (r *sendTxResult) Error() error { - return r.err -} - -func (r *sendTxResult) Code() SendTxReturnCode { - return r.code -} - -var _ TestSendTxRPCClient = (*sendTxRPC)(nil) - -func newSendTxRPC(sendTxErr error, sendTxRun func(args mock.Arguments)) *sendTxRPC { - return &sendTxRPC{sendTxErr: sendTxErr, sendTxRun: sendTxRun} -} - -func (rpc *sendTxRPC) SendTransaction(ctx context.Context, _ any) *sendTxResult { - if rpc.sendTxRun != nil { - rpc.sendTxRun(mock.Arguments{ctx}) - } - return &sendTxResult{err: rpc.sendTxErr, code: classifySendTxError(nil, rpc.sendTxErr)} -} - -// newTestTransactionSender returns a sendTxMultiNode and TransactionSender. -// Only the TransactionSender is run via Start/Close. -func newTestTransactionSender(t *testing.T, chainID types.ID, lggr logger.Logger, - nodes []Node[types.ID, TestSendTxRPCClient], - sendOnlyNodes []SendOnlyNode[types.ID, TestSendTxRPCClient], -) (*sendTxMultiNode, *TransactionSender[any, *sendTxResult, types.ID, TestSendTxRPCClient]) { - mn := sendTxMultiNode{NewMultiNode[types.ID, TestSendTxRPCClient]( - lggr, NodeSelectionModeRoundRobin, 0, nodes, sendOnlyNodes, chainID, "chainFamily", 0)} - - txSender := NewTransactionSender[any, *sendTxResult, types.ID, TestSendTxRPCClient](lggr, chainID, mn.chainFamily, mn.MultiNode, NewSendTxResult, tests.TestInterval) - servicetest.Run(t, txSender) - return &mn, txSender -} - -func classifySendTxError(_ any, err error) SendTxReturnCode { - if err != nil { - return Fatal - } - return Successful -} - -func TestTransactionSender_SendTransaction(t *testing.T) { - t.Parallel() - - newNodeWithState := func(t *testing.T, state nodeState, txErr error, sendTxRun func(args mock.Arguments)) *mockNode[types.ID, TestSendTxRPCClient] { - rpc := newSendTxRPC(txErr, sendTxRun) - node := newMockNode[types.ID, TestSendTxRPCClient](t) - node.On("String").Return("node name").Maybe() - node.On("RPC").Return(rpc).Maybe() - node.On("State").Return(state).Maybe() - node.On("Start", mock.Anything).Return(nil).Maybe() - node.On("Close").Return(nil).Maybe() - node.On("SetPoolChainInfoProvider", mock.Anything).Return(nil).Maybe() - return node - } - - newNode := func(t *testing.T, txErr error, sendTxRun func(args mock.Arguments)) *mockNode[types.ID, TestSendTxRPCClient] { - return newNodeWithState(t, nodeStateAlive, txErr, sendTxRun) - } - - t.Run("Fails if there is no nodes available", func(t *testing.T) { - lggr := logger.Test(t) - _, txSender := newTestTransactionSender(t, types.RandomID(), lggr, nil, nil) - result := txSender.SendTransaction(tests.Context(t), nil) - assert.EqualError(t, result.Error(), ErroringNodeError.Error()) - }) - - t.Run("Transaction failure happy path", func(t *testing.T) { - expectedError := errors.New("transaction failed") - mainNode := newNode(t, expectedError, nil) - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - - _, txSender := newTestTransactionSender(t, types.RandomID(), lggr, - []Node[types.ID, TestSendTxRPCClient]{mainNode}, - []SendOnlyNode[types.ID, TestSendTxRPCClient]{newNode(t, errors.New("unexpected error"), nil)}) - - result := txSender.SendTransaction(tests.Context(t), nil) - require.ErrorIs(t, result.Error(), expectedError) - require.Equal(t, Fatal, result.Code()) - tests.AssertLogCountEventually(t, observedLogs, "Node sent transaction", 2) - tests.AssertLogCountEventually(t, observedLogs, "RPC returned error", 2) - }) - - t.Run("Transaction success happy path", func(t *testing.T) { - mainNode := newNode(t, nil, nil) - - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - _, txSender := newTestTransactionSender(t, types.RandomID(), lggr, - []Node[types.ID, TestSendTxRPCClient]{mainNode}, - []SendOnlyNode[types.ID, TestSendTxRPCClient]{newNode(t, errors.New("unexpected error"), nil)}) - - result := txSender.SendTransaction(tests.Context(t), nil) - require.NoError(t, result.Error()) - require.Equal(t, Successful, result.Code()) - tests.AssertLogCountEventually(t, observedLogs, "Node sent transaction", 2) - tests.AssertLogCountEventually(t, observedLogs, "RPC returned error", 1) - }) - - t.Run("Context expired before collecting sufficient results", func(t *testing.T) { - testContext, testCancel := context.WithCancel(tests.Context(t)) - defer testCancel() - - mainNode := newNode(t, nil, func(_ mock.Arguments) { - // block caller til end of the test - <-testContext.Done() - }) - - lggr := logger.Test(t) - - _, txSender := newTestTransactionSender(t, types.RandomID(), lggr, - []Node[types.ID, TestSendTxRPCClient]{mainNode}, nil) - - requestContext, cancel := context.WithCancel(tests.Context(t)) - cancel() - result := txSender.SendTransaction(requestContext, nil) - require.EqualError(t, result.Error(), "context canceled") - }) - - t.Run("Soft timeout stops results collection", func(t *testing.T) { - chainID := types.RandomID() - expectedError := errors.New("transaction failed") - fastNode := newNode(t, expectedError, nil) - - // hold reply from the node till end of the test - testContext, testCancel := context.WithCancel(tests.Context(t)) - defer testCancel() - slowNode := newNode(t, errors.New("transaction failed"), func(_ mock.Arguments) { - // block caller til end of the test - <-testContext.Done() - }) - - lggr := logger.Test(t) - - _, txSender := newTestTransactionSender(t, chainID, lggr, []Node[types.ID, TestSendTxRPCClient]{fastNode, slowNode}, nil) - result := txSender.SendTransaction(tests.Context(t), nil) - require.EqualError(t, result.Error(), expectedError.Error()) - }) - t.Run("Returns success without waiting for the rest of the nodes", func(t *testing.T) { - chainID := types.RandomID() - fastNode := newNode(t, nil, nil) - // hold reply from the node till end of the test - testContext, testCancel := context.WithCancel(tests.Context(t)) - defer testCancel() - slowNode := newNode(t, errors.New("transaction failed"), func(_ mock.Arguments) { - // block caller til end of the test - <-testContext.Done() - }) - slowSendOnly := newNode(t, errors.New("send only failed"), func(_ mock.Arguments) { - // block caller til end of the test - <-testContext.Done() - }) - lggr, _ := logger.TestObserved(t, zap.WarnLevel) - _, txSender := newTestTransactionSender(t, chainID, lggr, - []Node[types.ID, TestSendTxRPCClient]{fastNode, slowNode}, - []SendOnlyNode[types.ID, TestSendTxRPCClient]{slowSendOnly}) - - result := txSender.SendTransaction(tests.Context(t), nil) - require.NoError(t, result.Error()) - require.Equal(t, Successful, result.Code()) - }) - t.Run("Fails when multinode is closed", func(t *testing.T) { - chainID := types.RandomID() - fastNode := newNode(t, nil, nil) - fastNode.On("ConfiguredChainID").Return(chainID).Maybe() - // hold reply from the node till end of the test - testContext, testCancel := context.WithCancel(tests.Context(t)) - defer testCancel() - slowNode := newNode(t, errors.New("transaction failed"), func(_ mock.Arguments) { - // block caller til end of the test - <-testContext.Done() - }) - slowNode.On("ConfiguredChainID").Return(chainID).Maybe() - slowSendOnly := newNode(t, errors.New("send only failed"), func(_ mock.Arguments) { - // block caller til end of the test - <-testContext.Done() - }) - slowSendOnly.On("ConfiguredChainID").Return(chainID).Maybe() - - lggr, _ := logger.TestObserved(t, zap.DebugLevel) - - mn, txSender := newTestTransactionSender(t, chainID, lggr, - []Node[types.ID, TestSendTxRPCClient]{fastNode, slowNode}, - []SendOnlyNode[types.ID, TestSendTxRPCClient]{slowSendOnly}) - - require.NoError(t, mn.Start(tests.Context(t))) - require.NoError(t, mn.Close()) - result := txSender.SendTransaction(tests.Context(t), nil) - require.EqualError(t, result.Error(), "service is stopped") - }) - t.Run("Fails when closed", func(t *testing.T) { - chainID := types.RandomID() - fastNode := newNode(t, nil, nil) - // hold reply from the node till end of the test - testContext, testCancel := context.WithCancel(tests.Context(t)) - defer testCancel() - slowNode := newNode(t, errors.New("transaction failed"), func(_ mock.Arguments) { - // block caller til end of the test - <-testContext.Done() - }) - slowSendOnly := newNode(t, errors.New("send only failed"), func(_ mock.Arguments) { - // block caller til end of the test - <-testContext.Done() - }) - - var txSender *TransactionSender[any, *sendTxResult, types.ID, TestSendTxRPCClient] - - t.Cleanup(func() { // after txSender.Close() - result := txSender.SendTransaction(tests.Context(t), nil) - assert.EqualError(t, result.err, "TransactionSender not started") - }) - - _, txSender = newTestTransactionSender(t, chainID, logger.Test(t), - []Node[types.ID, TestSendTxRPCClient]{fastNode, slowNode}, - []SendOnlyNode[types.ID, TestSendTxRPCClient]{slowSendOnly}) - - }) - t.Run("Returns error if there is no healthy primary nodes", func(t *testing.T) { - chainID := types.RandomID() - primary := newNodeWithState(t, nodeStateUnreachable, nil, nil) - sendOnly := newNodeWithState(t, nodeStateUnreachable, nil, nil) - - lggr := logger.Test(t) - - _, txSender := newTestTransactionSender(t, chainID, lggr, - []Node[types.ID, TestSendTxRPCClient]{primary}, - []SendOnlyNode[types.ID, TestSendTxRPCClient]{sendOnly}) - - result := txSender.SendTransaction(tests.Context(t), nil) - assert.EqualError(t, result.Error(), ErroringNodeError.Error()) - }) - - t.Run("Transaction success even if one of the nodes is unhealthy", func(t *testing.T) { - chainID := types.RandomID() - mainNode := newNode(t, nil, nil) - unexpectedCall := func(args mock.Arguments) { - panic("SendTx must not be called for unhealthy node") - } - unhealthyNode := newNodeWithState(t, nodeStateUnreachable, nil, unexpectedCall) - unhealthySendOnlyNode := newNodeWithState(t, nodeStateUnreachable, nil, unexpectedCall) - - lggr := logger.Test(t) - - _, txSender := newTestTransactionSender(t, chainID, lggr, - []Node[types.ID, TestSendTxRPCClient]{mainNode, unhealthyNode}, - []SendOnlyNode[types.ID, TestSendTxRPCClient]{unhealthySendOnlyNode}) - - result := txSender.SendTransaction(tests.Context(t), nil) - require.NoError(t, result.Error()) - require.Equal(t, Successful, result.Code()) - }) - t.Run("All background jobs stop even if RPC returns result after soft timeout", func(t *testing.T) { - chainID := types.RandomID() - expectedError := errors.New("transaction failed") - fastNode := newNode(t, expectedError, nil) - - // hold reply from the node till SendTransaction returns result - sendTxContext, sendTxCancel := context.WithCancel(tests.Context(t)) - slowNode := newNode(t, errors.New("transaction failed"), func(_ mock.Arguments) { - <-sendTxContext.Done() - }) - - lggr := logger.Test(t) - - _, txSender := newTestTransactionSender(t, chainID, lggr, []Node[types.ID, TestSendTxRPCClient]{fastNode, slowNode}, nil) - result := txSender.SendTransaction(sendTxContext, nil) - sendTxCancel() - require.EqualError(t, result.Error(), expectedError.Error()) - // TxSender should stop all background go routines after SendTransaction is done and before test is done. - // Otherwise, it signals that we have a goroutine leak. - txSender.wg.Wait() - }) -} - -func TestTransactionSender_SendTransaction_aggregateTxResults(t *testing.T) { - t.Parallel() - // ensure failure on new SendTxReturnCode - codesToCover := map[SendTxReturnCode]struct{}{} - for code := Successful; code < sendTxReturnCodeLen; code++ { - codesToCover[code] = struct{}{} - } - - testCases := []struct { - Name string - ExpectedTxResult string - ExpectedCriticalErr string - ResultsByCode sendTxResults[*sendTxResult] - }{ - { - Name: "Returns success and logs critical error on success and Fatal", - ExpectedTxResult: "success", - ExpectedCriticalErr: "found contradictions in nodes replies on SendTransaction: got success and severe error", - ResultsByCode: sendTxResults[*sendTxResult]{ - Successful: {NewSendTxResult(errors.New("success"))}, - Fatal: {NewSendTxResult(errors.New("fatal"))}, - }, - }, - { - Name: "Returns TransactionAlreadyKnown and logs critical error on TransactionAlreadyKnown and Fatal", - ExpectedTxResult: "tx_already_known", - ExpectedCriticalErr: "found contradictions in nodes replies on SendTransaction: got success and severe error", - ResultsByCode: sendTxResults[*sendTxResult]{ - TransactionAlreadyKnown: {NewSendTxResult(errors.New("tx_already_known"))}, - Unsupported: {NewSendTxResult(errors.New("unsupported"))}, - }, - }, - { - Name: "Prefers sever error to temporary", - ExpectedTxResult: "underpriced", - ExpectedCriticalErr: "", - ResultsByCode: sendTxResults[*sendTxResult]{ - Retryable: {NewSendTxResult(errors.New("retryable"))}, - Underpriced: {NewSendTxResult(errors.New("underpriced"))}, - }, - }, - { - Name: "Returns temporary error", - ExpectedTxResult: "retryable", - ExpectedCriticalErr: "", - ResultsByCode: sendTxResults[*sendTxResult]{ - Retryable: {NewSendTxResult(errors.New("retryable"))}, - }, - }, - { - Name: "Insufficient funds is treated as error", - ExpectedTxResult: "insufficientFunds", - ExpectedCriticalErr: "", - ResultsByCode: sendTxResults[*sendTxResult]{ - InsufficientFunds: {NewSendTxResult(errors.New("insufficientFunds"))}, - }, - }, - { - Name: "Logs critical error on empty ResultsByCode", - ExpectedCriticalErr: "expected at least one response on SendTransaction", - ResultsByCode: sendTxResults[*sendTxResult]{}, - }, - { - Name: "Zk terminally stuck", - ExpectedTxResult: "not enough keccak counters to continue the execution", - ExpectedCriticalErr: "", - ResultsByCode: sendTxResults[*sendTxResult]{ - TerminallyStuck: {NewSendTxResult(errors.New("not enough keccak counters to continue the execution"))}, - }, - }, - } - - for _, testCase := range testCases { - for code := range testCase.ResultsByCode { - delete(codesToCover, code) - } - - t.Run(testCase.Name, func(t *testing.T) { - txResult, err := aggregateTxResults(testCase.ResultsByCode) - if testCase.ExpectedTxResult != "" { - require.EqualError(t, txResult.Error(), testCase.ExpectedTxResult) - } - - logger.Sugared(logger.Test(t)).Info("Map: " + fmt.Sprint(testCase.ResultsByCode)) - logger.Sugared(logger.Test(t)).Criticalw("observed invariant violation on SendTransaction", "resultsByCode", testCase.ResultsByCode, "err", err) - - if testCase.ExpectedCriticalErr == "" { - require.NoError(t, err) - } else { - require.EqualError(t, err, testCase.ExpectedCriticalErr) - } - }) - } - - // explicitly signal that following codes are properly handled in aggregateTxResults, - // but dedicated test cases won't be beneficial - for _, codeToIgnore := range []SendTxReturnCode{Unknown, ExceedsMaxFee, FeeOutOfValidRange} { - delete(codesToCover, codeToIgnore) - } - assert.Empty(t, codesToCover, "all of the SendTxReturnCode must be covered by this test") -} diff --git a/common/client/types.go b/common/client/types.go deleted file mode 100644 index 38880397442..00000000000 --- a/common/client/types.go +++ /dev/null @@ -1,83 +0,0 @@ -package client - -import ( - "context" - "math/big" - - "github.com/smartcontractkit/chainlink/v2/common/types" -) - -// RPCClient includes all the necessary generalized RPC methods used by Node to perform health checks -type RPCClient[ - CHAIN_ID types.ID, - HEAD Head, -] interface { - // ChainID - fetches ChainID from the RPC to verify that it matches config - ChainID(ctx context.Context) (CHAIN_ID, error) - // Dial - prepares the RPC for usage. Can be called on fresh or closed RPC - Dial(ctx context.Context) error - // SubscribeToHeads - returns channel and subscription for new heads. - SubscribeToHeads(ctx context.Context) (<-chan HEAD, types.Subscription, error) - // SubscribeToFinalizedHeads - returns channel and subscription for finalized heads. - SubscribeToFinalizedHeads(ctx context.Context) (<-chan HEAD, types.Subscription, error) - // Ping - returns error if RPC is not reachable - Ping(context.Context) error - // IsSyncing - returns true if the RPC is in Syncing state and can not process calls - IsSyncing(ctx context.Context) (bool, error) - // UnsubscribeAllExcept - close all subscriptions except `subs` - UnsubscribeAllExcept(subs ...types.Subscription) - // Close - closes all subscriptions and aborts all RPC calls - Close() - // GetInterceptedChainInfo - returns latest and highest observed by application layer ChainInfo. - // latest ChainInfo is the most recent value received within a NodeClient's current lifecycle between Dial and DisconnectAll. - // highestUserObservations ChainInfo is the highest ChainInfo observed excluding health checks calls. - // Its values must not be reset. - // The results of corresponding calls, to get the most recent head and the latest finalized head, must be - // intercepted and reflected in ChainInfo before being returned to a caller. Otherwise, MultiNode is not able to - // provide repeatable read guarantee. - // DisconnectAll must reset latest ChainInfo to default value. - // Ensure implementation does not have a race condition when values are reset before request completion and as - // a result latest ChainInfo contains information from the previous cycle. - GetInterceptedChainInfo() (latest, highestUserObservations ChainInfo) -} - -// Head is the interface required by the NodeClient -type Head interface { - BlockNumber() int64 - BlockDifficulty() *big.Int - IsValid() bool -} - -// PoolChainInfoProvider - provides aggregation of nodes pool ChainInfo -type PoolChainInfoProvider interface { - // LatestChainInfo - returns number of live nodes available in the pool, so we can prevent the last alive node in a pool from being - // moved to out-of-sync state. It is better to have one out-of-sync node than no nodes at all. - // Returns highest latest ChainInfo within the alive nodes. E.g. most recent block number and highest block number - // observed by Node A are 10 and 15; Node B - 12 and 14. This method will return 12. - LatestChainInfo() (int, ChainInfo) - // HighestUserObservations - returns highest ChainInfo ever observed by any user of MultiNode. - HighestUserObservations() ChainInfo -} - -// ChainInfo - defines RPC's or MultiNode's view on the chain -type ChainInfo struct { - BlockNumber int64 - FinalizedBlockNumber int64 - TotalDifficulty *big.Int -} - -func MaxTotalDifficulty(a, b *big.Int) *big.Int { - if a == nil { - if b == nil { - return nil - } - - return big.NewInt(0).Set(b) - } - - if b == nil || a.Cmp(b) >= 0 { - return big.NewInt(0).Set(a) - } - - return big.NewInt(0).Set(b) -} diff --git a/common/client/types_test.go b/common/client/types_test.go deleted file mode 100644 index 68d7a3fe78e..00000000000 --- a/common/client/types_test.go +++ /dev/null @@ -1,34 +0,0 @@ -package client - -import ( - "math/big" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestMaxDifficulty(t *testing.T) { - cases := []struct { - A, B, Result *big.Int - }{ - { - A: nil, B: nil, Result: nil, - }, - { - A: nil, B: big.NewInt(1), Result: big.NewInt(1), - }, - { - A: big.NewInt(1), B: big.NewInt(1), Result: big.NewInt(1), - }, - { - A: big.NewInt(1), B: big.NewInt(2), Result: big.NewInt(2), - }, - } - - for _, test := range cases { - actualResult := MaxTotalDifficulty(test.A, test.B) - assert.Equal(t, test.Result, actualResult, "expected max(%v, %v) to produce %v", test.A, test.B, test.Result) - inverted := MaxTotalDifficulty(test.B, test.A) - assert.Equal(t, actualResult, inverted, "expected max(%v, %v) == max(%v, %v)", test.A, test.B, test.B, test.A) - } -} diff --git a/common/fee/types/fee.go b/common/fee/types/fee.go deleted file mode 100644 index 2c03db5973f..00000000000 --- a/common/fee/types/fee.go +++ /dev/null @@ -1,15 +0,0 @@ -package types - -import ( - "fmt" -) - -// Opt is an option for a gas estimator -type Opt int - -const ( - // OptForceRefetch forces the estimator to bust a cache if necessary - OptForceRefetch Opt = iota -) - -type Fee fmt.Stringer diff --git a/common/fee/utils.go b/common/fee/utils.go deleted file mode 100644 index 3d4b001e839..00000000000 --- a/common/fee/utils.go +++ /dev/null @@ -1,29 +0,0 @@ -package fee - -import ( - "fmt" - "math" - "math/big" - - "github.com/shopspring/decimal" -) - -func ApplyMultiplier(feeLimit uint64, multiplier float32) (uint64, error) { - result := decimal.NewFromBigInt(big.NewInt(0).SetUint64(feeLimit), 0).Mul(decimal.NewFromFloat32(multiplier)) - - if result.GreaterThan(decimal.NewFromBigInt(big.NewInt(0).SetUint64(math.MaxUint64), 0)) { - return 0, fmt.Errorf("integer overflow when applying multiplier of %f to fee limit of %d", multiplier, feeLimit) - } - return result.BigInt().Uint64(), nil -} - -// Returns the input value increased by the given percentage. -func AddPercentage(value *big.Int, percentage uint16) *big.Int { - bumped := new(big.Int) - bumped.Mul(value, big.NewInt(int64(100+percentage))) - bumped.Div(bumped, big.NewInt(100)) - return bumped -} - -// Returns the fee in its chain specific unit. -type feeUnitToChainUnit func(fee *big.Int) string diff --git a/common/fee/models.go b/common/fees/fees.go similarity index 77% rename from common/fee/models.go rename to common/fees/fees.go index 0cc479d3560..84504eeee13 100644 --- a/common/fee/models.go +++ b/common/fees/fees.go @@ -1,15 +1,48 @@ -package fee +package fees import ( "errors" "fmt" + "math" "math/big" + "github.com/shopspring/decimal" + "github.com/smartcontractkit/chainlink-common/pkg/chains/label" "github.com/smartcontractkit/chainlink-common/pkg/logger" bigmath "github.com/smartcontractkit/chainlink-common/pkg/utils/big_math" ) +// Opt is an option for a gas estimator +type Opt int + +const ( + // OptForceRefetch forces the estimator to bust a cache if necessary + OptForceRefetch Opt = iota +) + +type Fee fmt.Stringer + +func ApplyMultiplier(feeLimit uint64, multiplier float32) (uint64, error) { + result := decimal.NewFromBigInt(big.NewInt(0).SetUint64(feeLimit), 0).Mul(decimal.NewFromFloat32(multiplier)) + + if result.GreaterThan(decimal.NewFromBigInt(big.NewInt(0).SetUint64(math.MaxUint64), 0)) { + return 0, fmt.Errorf("integer overflow when applying multiplier of %f to fee limit of %d", multiplier, feeLimit) + } + return result.BigInt().Uint64(), nil +} + +// AddPercentage returns the input value increased by the given percentage. +func AddPercentage(value *big.Int, percentage uint16) *big.Int { + bumped := new(big.Int) + bumped.Mul(value, big.NewInt(int64(100+percentage))) + bumped.Div(bumped, big.NewInt(100)) + return bumped +} + +// Returns the fee in its chain specific unit. +type feeUnitToChainUnit func(fee *big.Int) string + var ( ErrBumpFeeExceedsLimit = errors.New("fee bump exceeds limit") ErrBump = errors.New("fee bump failed") @@ -61,7 +94,7 @@ func CalculateBumpedFee( return bumpedFeePrice, nil } -// Returns highest bumped fee price of originalFeePrice bumped by fixed units or percentage. +// MaxBumpedFee returns highest bumped fee price of originalFeePrice bumped by fixed units or percentage. func MaxBumpedFee(originalFeePrice *big.Int, feeBumpPercent uint16, feeBumpUnits *big.Int) *big.Int { return bigmath.Max( AddPercentage(originalFeePrice, feeBumpPercent), diff --git a/common/headtracker/head_listener.go b/common/headtracker/head_listener.go index 5f967706e04..de7bad6f21b 100644 --- a/common/headtracker/head_listener.go +++ b/common/headtracker/head_listener.go @@ -7,6 +7,7 @@ import ( "sync/atomic" "time" + "github.com/jpillora/backoff" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" @@ -14,7 +15,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services" htrktypes "github.com/smartcontractkit/chainlink/v2/common/headtracker/types" - "github.com/smartcontractkit/chainlink/v2/common/internal/utils" "github.com/smartcontractkit/chainlink/v2/common/types" ) @@ -200,7 +200,11 @@ func (hl *headListener[HTH, S, ID, BLOCK_HASH]) receiveHeaders(ctx context.Conte } func (hl *headListener[HTH, S, ID, BLOCK_HASH]) subscribe(ctx context.Context) bool { - subscribeRetryBackoff := utils.NewRedialBackoff() + subscribeRetryBackoff := backoff.Backoff{ + Min: 1 * time.Second, + Max: 15 * time.Second, + Jitter: true, + } chainId := hl.client.ConfiguredChainID() diff --git a/common/headtracker/mocks/head_broadcaster.go b/common/headtracker/mocks/head_broadcaster.go index 87ac609e605..97ef4c4395d 100644 --- a/common/headtracker/mocks/head_broadcaster.go +++ b/common/headtracker/mocks/head_broadcaster.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -53,11 +53,11 @@ func (_c *HeadBroadcaster_BroadcastNewLongestChain_Call[H, BLOCK_HASH]) Return() } func (_c *HeadBroadcaster_BroadcastNewLongestChain_Call[H, BLOCK_HASH]) RunAndReturn(run func(H)) *HeadBroadcaster_BroadcastNewLongestChain_Call[H, BLOCK_HASH] { - _c.Call.Return(run) + _c.Run(run) return _c } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *HeadBroadcaster[H, BLOCK_HASH]) Close() error { ret := _m.Called() @@ -102,7 +102,7 @@ func (_c *HeadBroadcaster_Close_Call[H, BLOCK_HASH]) RunAndReturn(run func() err return _c } -// HealthReport provides a mock function with given fields: +// HealthReport provides a mock function with no fields func (_m *HeadBroadcaster[H, BLOCK_HASH]) HealthReport() map[string]error { ret := _m.Called() @@ -149,7 +149,7 @@ func (_c *HeadBroadcaster_HealthReport_Call[H, BLOCK_HASH]) RunAndReturn(run fun return _c } -// Name provides a mock function with given fields: +// Name provides a mock function with no fields func (_m *HeadBroadcaster[H, BLOCK_HASH]) Name() string { ret := _m.Called() @@ -194,7 +194,7 @@ func (_c *HeadBroadcaster_Name_Call[H, BLOCK_HASH]) RunAndReturn(run func() stri return _c } -// Ready provides a mock function with given fields: +// Ready provides a mock function with no fields func (_m *HeadBroadcaster[H, BLOCK_HASH]) Ready() error { ret := _m.Called() @@ -301,7 +301,9 @@ func (_m *HeadBroadcaster[H, BLOCK_HASH]) Subscribe(callback headtracker.HeadTra if rf, ok := ret.Get(0).(func(headtracker.HeadTrackable[H, BLOCK_HASH]) H); ok { r0 = rf(callback) } else { - r0 = ret.Get(0).(H) + if ret.Get(0) != nil { + r0 = ret.Get(0).(H) + } } if rf, ok := ret.Get(1).(func(headtracker.HeadTrackable[H, BLOCK_HASH]) func()); ok { diff --git a/common/headtracker/mocks/head_trackable.go b/common/headtracker/mocks/head_trackable.go index 50ea4665280..5475aeec254 100644 --- a/common/headtracker/mocks/head_trackable.go +++ b/common/headtracker/mocks/head_trackable.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -53,7 +53,7 @@ func (_c *HeadTrackable_OnNewLongestChain_Call[H, BLOCK_HASH]) Return() *HeadTra } func (_c *HeadTrackable_OnNewLongestChain_Call[H, BLOCK_HASH]) RunAndReturn(run func(context.Context, H)) *HeadTrackable_OnNewLongestChain_Call[H, BLOCK_HASH] { - _c.Call.Return(run) + _c.Run(run) return _c } diff --git a/common/headtracker/mocks/head_tracker.go b/common/headtracker/mocks/head_tracker.go index e0541bdd786..97e3233fbcb 100644 --- a/common/headtracker/mocks/head_tracker.go +++ b/common/headtracker/mocks/head_tracker.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -70,7 +70,7 @@ func (_c *HeadTracker_Backfill_Call[H, BLOCK_HASH]) RunAndReturn(run func(contex return _c } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *HeadTracker[H, BLOCK_HASH]) Close() error { ret := _m.Called() @@ -115,7 +115,7 @@ func (_c *HeadTracker_Close_Call[H, BLOCK_HASH]) RunAndReturn(run func() error) return _c } -// HealthReport provides a mock function with given fields: +// HealthReport provides a mock function with no fields func (_m *HeadTracker[H, BLOCK_HASH]) HealthReport() map[string]error { ret := _m.Called() @@ -179,13 +179,17 @@ func (_m *HeadTracker[H, BLOCK_HASH]) LatestAndFinalizedBlock(ctx context.Contex if rf, ok := ret.Get(0).(func(context.Context) H); ok { r0 = rf(ctx) } else { - r0 = ret.Get(0).(H) + if ret.Get(0) != nil { + r0 = ret.Get(0).(H) + } } if rf, ok := ret.Get(1).(func(context.Context) H); ok { r1 = rf(ctx) } else { - r1 = ret.Get(1).(H) + if ret.Get(1) != nil { + r1 = ret.Get(1).(H) + } } if rf, ok := ret.Get(2).(func(context.Context) error); ok { @@ -225,7 +229,7 @@ func (_c *HeadTracker_LatestAndFinalizedBlock_Call[H, BLOCK_HASH]) RunAndReturn( return _c } -// LatestChain provides a mock function with given fields: +// LatestChain provides a mock function with no fields func (_m *HeadTracker[H, BLOCK_HASH]) LatestChain() H { ret := _m.Called() @@ -237,7 +241,9 @@ func (_m *HeadTracker[H, BLOCK_HASH]) LatestChain() H { if rf, ok := ret.Get(0).(func() H); ok { r0 = rf() } else { - r0 = ret.Get(0).(H) + if ret.Get(0) != nil { + r0 = ret.Get(0).(H) + } } return r0 @@ -270,7 +276,7 @@ func (_c *HeadTracker_LatestChain_Call[H, BLOCK_HASH]) RunAndReturn(run func() H return _c } -// Name provides a mock function with given fields: +// Name provides a mock function with no fields func (_m *HeadTracker[H, BLOCK_HASH]) Name() string { ret := _m.Called() @@ -315,7 +321,7 @@ func (_c *HeadTracker_Name_Call[H, BLOCK_HASH]) RunAndReturn(run func() string) return _c } -// Ready provides a mock function with given fields: +// Ready provides a mock function with no fields func (_m *HeadTracker[H, BLOCK_HASH]) Ready() error { ret := _m.Called() diff --git a/common/internal/utils/utils.go b/common/internal/utils/utils.go deleted file mode 100644 index aeaad34a142..00000000000 --- a/common/internal/utils/utils.go +++ /dev/null @@ -1,35 +0,0 @@ -package utils - -import ( - "cmp" - "slices" - "time" - - "github.com/jpillora/backoff" - "golang.org/x/exp/constraints" -) - -// NewRedialBackoff is a standard backoff to use for redialling or reconnecting to -// unreachable network endpoints -func NewRedialBackoff() backoff.Backoff { - return backoff.Backoff{ - Min: 1 * time.Second, - Max: 15 * time.Second, - Jitter: true, - } -} - -// MinFunc returns the minimum value of the given element array with respect -// to the given key function. In the event U is not a compound type (e.g a -// struct) an identity function can be provided. -func MinFunc[U any, T constraints.Ordered](elems []U, f func(U) T) T { - var min T - if len(elems) == 0 { - return min - } - - e := slices.MinFunc(elems, func(a, b U) int { - return cmp.Compare(f(a), f(b)) - }) - return f(e) -} diff --git a/common/txmgr/broadcaster.go b/common/txmgr/broadcaster.go index 14e959c39ae..6174c1ed482 100644 --- a/common/txmgr/broadcaster.go +++ b/common/txmgr/broadcaster.go @@ -18,10 +18,9 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/utils" + "github.com/smartcontractkit/chainlink-framework/multinode" - "github.com/smartcontractkit/chainlink/v2/common/client" - commonfee "github.com/smartcontractkit/chainlink/v2/common/fee" - feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" + "github.com/smartcontractkit/chainlink/v2/common/fees" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/common/types" ) @@ -70,7 +69,7 @@ type TransmitCheckerFactory[ ADDR types.Hashable, TX_HASH, BLOCK_HASH types.Hashable, SEQ types.Sequence, - FEE feetypes.Fee, + FEE fees.Fee, ] interface { // BuildChecker builds a new TransmitChecker based on the given spec. BuildChecker(spec txmgrtypes.TransmitCheckerSpec[ADDR]) (TransmitChecker[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error) @@ -82,7 +81,7 @@ type TransmitChecker[ ADDR types.Hashable, TX_HASH, BLOCK_HASH types.Hashable, SEQ types.Sequence, - FEE feetypes.Fee, + FEE fees.Fee, ] interface { // Check the given transaction. If the transaction should not be sent, an error indicating why @@ -112,7 +111,7 @@ type Broadcaster[ TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, - FEE feetypes.Fee, + FEE fees.Fee, ] struct { services.StateMachine lggr logger.SugaredLogger @@ -158,7 +157,7 @@ func NewBroadcaster[ TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, - FEE feetypes.Fee, + FEE fees.Fee, ]( txStore txmgrtypes.TransactionStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, SEQ, FEE], client txmgrtypes.TransactionClient[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], @@ -436,8 +435,8 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) hand attempt, _, _, retryable, err := eb.NewTxAttempt(ctx, *etx, eb.lggr) // Mark transaction as fatal if provided gas limit is set too low - if errors.Is(err, commonfee.ErrFeeLimitTooLow) { - etx.Error = null.StringFrom(commonfee.ErrFeeLimitTooLow.Error()) + if errors.Is(err, fees.ErrFeeLimitTooLow) { + etx.Error = null.StringFrom(fees.ErrFeeLimitTooLow.Error()) return eb.saveFatallyErroredTransaction(eb.lggr, etx), false } else if err != nil { return fmt.Errorf("processUnstartedTxs failed on NewAttempt: %w", err), retryable @@ -498,7 +497,7 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) hand errType, err = eb.validateOnChainSequence(ctx, lgr, errType, err, etx, retryCount) } - if errType == client.Fatal || errType == client.TerminallyStuck { + if errType == multinode.Fatal || errType == multinode.TerminallyStuck { eb.SvcErrBuffer.Append(err) etx.Error = null.StringFrom(err.Error()) return eb.saveFatallyErroredTransaction(lgr, &etx), true @@ -508,9 +507,9 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) hand etx.BroadcastAt = &initialBroadcastAt switch errType { - case client.TransactionAlreadyKnown: + case multinode.TransactionAlreadyKnown: fallthrough - case client.Successful: + case multinode.Successful: // Either the transaction was successful or one of the following four scenarios happened: // // SCENARIO 1 @@ -557,14 +556,14 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) hand // Increment sequence if successfully broadcasted eb.sequenceTracker.GenerateNextSequence(etx.FromAddress, *etx.Sequence) return err, true - case client.Underpriced: + case multinode.Underpriced: bumpedAttempt, retryable, replaceErr := eb.replaceAttemptWithBumpedGas(ctx, lgr, err, etx, attempt) if replaceErr != nil { return replaceErr, retryable } return eb.handleInProgressTx(ctx, etx, bumpedAttempt, initialBroadcastAt, retryCount+1) - case client.InsufficientFunds: + case multinode.InsufficientFunds: // NOTE: This can occur due to either insufficient funds or a gas spike // combined with a high gas limit. Regardless of the cause, we need to obtain a new estimate, // replace the current attempt, and retry after the backoff duration. @@ -574,9 +573,9 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) hand return replaceErr, true } return err, true - case client.Retryable: + case multinode.Retryable: return err, true - case client.FeeOutOfValidRange: + case multinode.FeeOutOfValidRange: replacementAttempt, retryable, replaceErr := eb.replaceAttemptWithNewEstimation(ctx, lgr, etx, attempt) if replaceErr != nil { return replaceErr, retryable @@ -585,9 +584,9 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) hand lgr.Warnw("L2 rejected transaction due to incorrect fee, re-estimated and will try again", "etxID", etx.ID, "err", err, "newGasPrice", replacementAttempt.TxFee, "newGasLimit", replacementAttempt.ChainSpecificFeeLimit) return eb.handleInProgressTx(ctx, etx, *replacementAttempt, initialBroadcastAt, 0) - case client.Unsupported: + case multinode.Unsupported: return err, false - case client.ExceedsMaxFee: + case multinode.ExceedsMaxFee: // Broadcaster: Note that we may have broadcast to multiple nodes and had it // accepted by one of them! It is not guaranteed that all nodes share // the same tx fee cap. That is why we must treat this as an unknown @@ -600,7 +599,7 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) hand default: // Every error that doesn't fall under one of the above categories will be treated as Unknown. fallthrough - case client.Unknown: + case multinode.Unknown: eb.SvcErrBuffer.Append(err) lgr.Criticalw(`Unknown error occurred while handling tx queue in ProcessUnstartedTxs. This chain/RPC client may not be supported. `+ `Urgent resolution required, Chainlink is currently operating in a degraded state and may miss transactions`, "attempt", attempt, "err", err) @@ -632,9 +631,9 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) hand } } -func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) validateOnChainSequence(ctx context.Context, lgr logger.SugaredLogger, errType client.SendTxReturnCode, err error, etx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], retryCount int) (client.SendTxReturnCode, error) { +func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) validateOnChainSequence(ctx context.Context, lgr logger.SugaredLogger, errType multinode.SendTxReturnCode, err error, etx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], retryCount int) (multinode.SendTxReturnCode, error) { // Only check if sequence was incremented if broadcast was successful, otherwise return the existing err type - if errType != client.Successful { + if errType != multinode.Successful { return errType, err } // Transaction sequence cannot be nil here since a sequence is required to broadcast @@ -649,7 +648,7 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) vali // Insufficient transaction fee is a common scenario in which the sequence is not incremented by the chain even though we got a successful response // If the sequence failed to increment and hasn't reached the max retries, return the Underpriced error to try again with a bumped attempt if nextSeqOnChain.Int64() == txSeq.Int64() && retryCount < maxHederaBroadcastRetries { - return client.Underpriced, nil + return multinode.Underpriced, nil } // If the transaction reaches the retry limit and fails to get included, mark it as fatally errored @@ -657,17 +656,17 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) vali if nextSeqOnChain.Int64() == txSeq.Int64() && retryCount >= maxHederaBroadcastRetries { err := fmt.Errorf("failed to broadcast transaction on %s after %d retries", hederaChainType, retryCount) lgr.Error(err.Error()) - return client.Fatal, err + return multinode.Fatal, err } // Belts and braces approach to detect and handle sqeuence gaps if the broadcast is considered successful if nextSeqOnChain.Int64() < txSeq.Int64() { err := fmt.Errorf("next expected sequence on-chain (%s) is less than the broadcasted transaction's sequence (%s)", nextSeqOnChain.String(), txSeq.String()) lgr.Criticalw("Sequence gap has been detected and needs to be filled", "error", err) - return client.Fatal, err + return multinode.Fatal, err } - return client.Successful, nil + return multinode.Successful, nil } // Finds next transaction in the queue, assigns a sequence, and moves it to "in_progress" state ready for broadcast. @@ -722,7 +721,7 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) repl // replaceAttemptWithNewEstimation performs the replacement of the existing tx attempt with a new estimated fee attempt. func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) replaceAttemptWithNewEstimation(ctx context.Context, lgr logger.Logger, etx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], attempt txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) (updatedAttempt *txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], retryable bool, err error) { - newEstimatedAttempt, fee, feeLimit, retryable, err := eb.NewTxAttemptWithType(ctx, etx, lgr, attempt.TxType, feetypes.OptForceRefetch) + newEstimatedAttempt, fee, feeLimit, retryable, err := eb.NewTxAttemptWithType(ctx, etx, lgr, attempt.TxType, fees.OptForceRefetch) if err != nil { return &newEstimatedAttempt, retryable, err } diff --git a/common/txmgr/confirmer.go b/common/txmgr/confirmer.go index 7c5ba798cf2..7dd3be6b4ae 100644 --- a/common/txmgr/confirmer.go +++ b/common/txmgr/confirmer.go @@ -20,11 +20,9 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + "github.com/smartcontractkit/chainlink-framework/multinode" - "github.com/smartcontractkit/chainlink/v2/common/client" - commonfee "github.com/smartcontractkit/chainlink/v2/common/fee" - feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" - iutils "github.com/smartcontractkit/chainlink/v2/common/internal/utils" + "github.com/smartcontractkit/chainlink/v2/common/fees" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/common/types" ) @@ -91,7 +89,7 @@ type Confirmer[ BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, - FEE feetypes.Fee, + FEE fees.Fee, ] struct { services.StateMachine txStore txmgrtypes.TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] @@ -124,7 +122,7 @@ func NewConfirmer[ BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, - FEE feetypes.Fee, + FEE fees.Fee, ]( txStore txmgrtypes.TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE], client txmgrtypes.TxmClient[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE], @@ -635,7 +633,7 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) att } attempt, err = ec.bumpGas(ctx, etx, etx.TxAttempts) - if commonfee.IsBumpErr(err) { + if fees.IsBumpErr(err) { lggr.Errorw("Failed to bump gas", append(logFields, "err", err)...) // Do not create a new attempt if bumping gas would put us over the limit or cause some other problem // Instead try to resubmit the previous attempt, and keep resubmitting until its accepted @@ -679,7 +677,7 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) bum return bumpedAttempt, err } - if errors.Is(err, commonfee.ErrBumpFeeExceedsLimit) { + if errors.Is(err, fees.ErrBumpFeeExceedsLimit) { promGasBumpExceedsLimit.WithLabelValues(ec.chainID.String()).Inc() } @@ -696,7 +694,7 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) han errType, sendError := ec.client.SendTransactionReturnCode(ctx, etx, attempt, lggr) switch errType { - case client.Underpriced: + case multinode.Underpriced: // This should really not ever happen in normal operation since we // already bumped above the required minimum in broadcaster. ec.lggr.Warnw("Got terminally underpriced error for gas bump, this should never happen unless the remote RPC node changed its configuration on the fly, or you are using multiple RPC nodes with different minimum gas price requirements. This is not recommended", "attempt", attempt) @@ -731,7 +729,7 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) han return fmt.Errorf("saveReplacementInProgressAttempt failed: %w", err) } return ec.handleInProgressAttempt(ctx, lggr, etx, replacementAttempt, blockHeight) - case client.ExceedsMaxFee: + case multinode.ExceedsMaxFee: // Confirmer: Note it is not guaranteed that all nodes share the same tx fee cap. // So it is very likely that this attempt was successful on another node since // it was already successfully broadcasted. So we assume it is successful and @@ -745,7 +743,7 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) han lggr.Criticalw(`RPC node rejected this tx as outside Fee Cap but it may have been accepted by another Node`, "attempt", attempt) timeout := ec.dbConfig.DefaultQueryTimeout() return ec.txStore.SaveSentAttempt(ctx, timeout, &attempt, now) - case client.Fatal: + case multinode.Fatal: // WARNING: This should never happen! // Should NEVER be fatal this is an invariant violation. The // Broadcaster can never create a TxAttempt that will @@ -760,7 +758,7 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) han ec.SvcErrBuffer.Append(sendError) // This will loop continuously on every new head so it must be handled manually by the node operator! return ec.txStore.DeleteInProgressAttempt(ctx, attempt) - case client.TerminallyStuck: + case multinode.TerminallyStuck: // A transaction could broadcast successfully but then be considered terminally stuck on another attempt // Even though the transaction can succeed under different circumstances, we want to purge this transaction as soon as we get this error lggr.Warnw("terminally stuck transaction detected", "err", sendError.Error()) @@ -775,20 +773,20 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) han return fmt.Errorf("saveReplacementInProgressAttempt failed: %w", err) } return ec.handleInProgressAttempt(ctx, lggr, etx, purgeAttempt, blockHeight) - case client.TransactionAlreadyKnown: + case multinode.TransactionAlreadyKnown: // Sequence too low indicated that a transaction at this sequence was confirmed already. // Mark confirmed_missing_receipt and wait for the next cycle to try to get a receipt lggr.Debugw("Sequence already used", "txAttemptID", attempt.ID, "txHash", attempt.Hash.String()) timeout := ec.dbConfig.DefaultQueryTimeout() return ec.txStore.SaveConfirmedAttempt(ctx, timeout, &attempt, now) - case client.InsufficientFunds: + case multinode.InsufficientFunds: timeout := ec.dbConfig.DefaultQueryTimeout() return ec.txStore.SaveInsufficientFundsAttempt(ctx, timeout, &attempt, now) - case client.Successful: + case multinode.Successful: lggr.Debugw("Successfully broadcast transaction", "txAttemptID", attempt.ID, "txHash", attempt.Hash.String()) timeout := ec.dbConfig.DefaultQueryTimeout() return ec.txStore.SaveSentAttempt(ctx, timeout, &attempt, now) - case client.Unknown: + case multinode.Unknown: // Every error that doesn't fall under one of the above categories will be treated as Unknown. fallthrough default: @@ -838,7 +836,7 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) For } attempt.Tx = *etx // for logging ec.lggr.Debugw("Sending transaction", "txAttemptID", attempt.ID, "txHash", attempt.Hash, "err", err, "meta", etx.Meta, "feeLimit", attempt.ChainSpecificFeeLimit, "callerProvidedFeeLimit", etx.FeeLimit, "attempt", attempt) - if errCode, err := ec.client.SendTransactionReturnCode(ctx, *etx, attempt, ec.lggr); errCode != client.Successful && err != nil { + if errCode, err := ec.client.SendTransactionReturnCode(ctx, *etx, attempt, ec.lggr); errCode != multinode.Successful && err != nil { ec.lggr.Errorw(fmt.Sprintf("ForceRebroadcast: failed to rebroadcast tx %v with sequence %v, gas limit %v, and caller provided fee Limit %v : %s", etx.ID, *etx.Sequence, attempt.ChainSpecificFeeLimit, etx.FeeLimit, err.Error()), "err", err, "fee", attempt.TxFee) continue } @@ -867,7 +865,7 @@ func observeUntilTxConfirmed[ ADDR types.Hashable, TX_HASH, BLOCK_HASH types.Hashable, SEQ types.Sequence, - FEE feetypes.Fee, + FEE fees.Fee, ](chainID CHAIN_ID, attempts []txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], head types.Head[BLOCK_HASH]) { for _, attempt := range attempts { // We estimate the time until confirmation by subtracting from the time the tx (not the attempt) @@ -881,14 +879,14 @@ func observeUntilTxConfirmed[ // Since a tx can have many attempts, we take the number of blocks to confirm as the block number // of the receipt minus the block number of the first ever broadcast for this transaction. - broadcastBefore := iutils.MinFunc(attempt.Tx.TxAttempts, func(attempt txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) int64 { - if attempt.BroadcastBeforeBlockNum != nil { - return *attempt.BroadcastBeforeBlockNum + var minBroadcastBefore int64 + for _, a := range attempt.Tx.TxAttempts { + if b := a.BroadcastBeforeBlockNum; b != nil && *b < minBroadcastBefore { + minBroadcastBefore = *b } - return 0 - }) - if broadcastBefore > 0 { - blocksElapsed := head.BlockNumber() - broadcastBefore + } + if minBroadcastBefore > 0 { + blocksElapsed := head.BlockNumber() - minBroadcastBefore promBlocksUntilTxConfirmed. WithLabelValues(chainID.String()). Observe(float64(blocksElapsed)) diff --git a/common/txmgr/mocks/tx_manager.go b/common/txmgr/mocks/tx_manager.go index a296158a005..04a2c69d7c2 100644 --- a/common/txmgr/mocks/tx_manager.go +++ b/common/txmgr/mocks/tx_manager.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -6,7 +6,7 @@ import ( context "context" big "math/big" - feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" + fees "github.com/smartcontractkit/chainlink/v2/common/fees" mock "github.com/stretchr/testify/mock" null "gopkg.in/guregu/null.v4" @@ -21,11 +21,11 @@ import ( ) // TxManager is an autogenerated mock type for the TxManager type -type TxManager[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxManager[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { mock.Mock } -type TxManager_Expecter[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxManager_Expecter[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { mock *mock.Mock } @@ -33,7 +33,7 @@ func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) EXPECT return &TxManager_Expecter[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]{mock: &_m.Mock} } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) Close() error { ret := _m.Called() @@ -52,7 +52,7 @@ func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) Close( } // TxManager_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close' -type TxManager_Close_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxManager_Close_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -107,7 +107,7 @@ func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) CountT } // TxManager_CountTransactionsByState_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CountTransactionsByState' -type TxManager_CountTransactionsByState_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxManager_CountTransactionsByState_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -164,7 +164,7 @@ func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) Create } // TxManager_CreateTransaction_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateTransaction' -type TxManager_CreateTransaction_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxManager_CreateTransaction_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -221,7 +221,7 @@ func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) FindEa } // TxManager_FindEarliestUnconfirmedBroadcastTime_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindEarliestUnconfirmedBroadcastTime' -type TxManager_FindEarliestUnconfirmedBroadcastTime_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxManager_FindEarliestUnconfirmedBroadcastTime_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -277,7 +277,7 @@ func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) FindEa } // TxManager_FindEarliestUnconfirmedTxAttemptBlock_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindEarliestUnconfirmedTxAttemptBlock' -type TxManager_FindEarliestUnconfirmedTxAttemptBlock_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxManager_FindEarliestUnconfirmedTxAttemptBlock_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -335,7 +335,7 @@ func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) FindTx } // TxManager_FindTxesByMetaFieldAndStates_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindTxesByMetaFieldAndStates' -type TxManager_FindTxesByMetaFieldAndStates_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxManager_FindTxesByMetaFieldAndStates_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -397,7 +397,7 @@ func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) FindTx } // TxManager_FindTxesWithAttemptsAndReceiptsByIdsAndState_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindTxesWithAttemptsAndReceiptsByIdsAndState' -type TxManager_FindTxesWithAttemptsAndReceiptsByIdsAndState_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxManager_FindTxesWithAttemptsAndReceiptsByIdsAndState_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -458,7 +458,7 @@ func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) FindTx } // TxManager_FindTxesWithMetaFieldByReceiptBlockNum_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindTxesWithMetaFieldByReceiptBlockNum' -type TxManager_FindTxesWithMetaFieldByReceiptBlockNum_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxManager_FindTxesWithMetaFieldByReceiptBlockNum_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -519,7 +519,7 @@ func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) FindTx } // TxManager_FindTxesWithMetaFieldByStates_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindTxesWithMetaFieldByStates' -type TxManager_FindTxesWithMetaFieldByStates_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxManager_FindTxesWithMetaFieldByStates_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -565,7 +565,9 @@ func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) GetFor if rf, ok := ret.Get(0).(func(context.Context, ADDR) ADDR); ok { r0 = rf(ctx, eoa) } else { - r0 = ret.Get(0).(ADDR) + if ret.Get(0) != nil { + r0 = ret.Get(0).(ADDR) + } } if rf, ok := ret.Get(1).(func(context.Context, ADDR) error); ok { @@ -578,7 +580,7 @@ func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) GetFor } // TxManager_GetForwarderForEOA_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetForwarderForEOA' -type TxManager_GetForwarderForEOA_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxManager_GetForwarderForEOA_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -622,7 +624,9 @@ func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) GetFor if rf, ok := ret.Get(0).(func(context.Context, ADDR, ADDR) ADDR); ok { r0 = rf(ctx, eoa, ocr2AggregatorID) } else { - r0 = ret.Get(0).(ADDR) + if ret.Get(0) != nil { + r0 = ret.Get(0).(ADDR) + } } if rf, ok := ret.Get(1).(func(context.Context, ADDR, ADDR) error); ok { @@ -635,7 +639,7 @@ func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) GetFor } // TxManager_GetForwarderForEOAOCR2Feeds_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetForwarderForEOAOCR2Feeds' -type TxManager_GetForwarderForEOAOCR2Feeds_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxManager_GetForwarderForEOAOCR2Feeds_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -693,7 +697,7 @@ func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) GetTra } // TxManager_GetTransactionStatus_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTransactionStatus' -type TxManager_GetTransactionStatus_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxManager_GetTransactionStatus_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -721,7 +725,7 @@ func (_c *TxManager_GetTransactionStatus_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLO return _c } -// HealthReport provides a mock function with given fields: +// HealthReport provides a mock function with no fields func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) HealthReport() map[string]error { ret := _m.Called() @@ -742,7 +746,7 @@ func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) Health } // TxManager_HealthReport_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'HealthReport' -type TxManager_HealthReport_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxManager_HealthReport_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -768,7 +772,7 @@ func (_c *TxManager_HealthReport_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, return _c } -// Name provides a mock function with given fields: +// Name provides a mock function with no fields func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) Name() string { ret := _m.Called() @@ -787,7 +791,7 @@ func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) Name() } // TxManager_Name_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Name' -type TxManager_Name_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxManager_Name_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -819,7 +823,7 @@ func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) OnNewL } // TxManager_OnNewLongestChain_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'OnNewLongestChain' -type TxManager_OnNewLongestChain_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxManager_OnNewLongestChain_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -843,11 +847,11 @@ func (_c *TxManager_OnNewLongestChain_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_ } func (_c *TxManager_OnNewLongestChain_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) RunAndReturn(run func(context.Context, HEAD)) *TxManager_OnNewLongestChain_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] { - _c.Call.Return(run) + _c.Run(run) return _c } -// Ready provides a mock function with given fields: +// Ready provides a mock function with no fields func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) Ready() error { ret := _m.Called() @@ -866,7 +870,7 @@ func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) Ready( } // TxManager_Ready_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Ready' -type TxManager_Ready_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxManager_Ready_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -898,7 +902,7 @@ func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) Regist } // TxManager_RegisterResumeCallback_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RegisterResumeCallback' -type TxManager_RegisterResumeCallback_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxManager_RegisterResumeCallback_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -921,7 +925,7 @@ func (_c *TxManager_RegisterResumeCallback_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, B } func (_c *TxManager_RegisterResumeCallback_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) RunAndReturn(run func(txmgr.ResumeCallback)) *TxManager_RegisterResumeCallback_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -944,7 +948,7 @@ func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) Reset( } // TxManager_Reset_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Reset' -type TxManager_Reset_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxManager_Reset_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -1001,7 +1005,7 @@ func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) SendNa } // TxManager_SendNativeToken_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendNativeToken' -type TxManager_SendNativeToken_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxManager_SendNativeToken_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -1052,7 +1056,7 @@ func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) Start( } // TxManager_Start_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Start' -type TxManager_Start_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxManager_Start_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -1085,7 +1089,7 @@ func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) Trigge } // TxManager_Trigger_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Trigger' -type TxManager_Trigger_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxManager_Trigger_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -1108,13 +1112,13 @@ func (_c *TxManager_Trigger_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, } func (_c *TxManager_Trigger_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) RunAndReturn(run func(ADDR)) *TxManager_Trigger_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] { - _c.Call.Return(run) + _c.Run(run) return _c } // NewTxManager creates a new instance of TxManager. 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 NewTxManager[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee](t interface { +func NewTxManager[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee](t interface { mock.TestingT Cleanup(func()) }) *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] { diff --git a/common/txmgr/resender.go b/common/txmgr/resender.go index d4f1b4275a1..16d39763cd3 100644 --- a/common/txmgr/resender.go +++ b/common/txmgr/resender.go @@ -9,8 +9,9 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/chains/label" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" - "github.com/smartcontractkit/chainlink/v2/common/client" - feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" + "github.com/smartcontractkit/chainlink-framework/multinode" + + "github.com/smartcontractkit/chainlink/v2/common/fees" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/common/types" ) @@ -42,7 +43,7 @@ type Resender[ BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, - FEE feetypes.Fee, + FEE fees.Fee, ] struct { txStore txmgrtypes.TransactionStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, SEQ, FEE] client txmgrtypes.TransactionClient[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] @@ -66,7 +67,7 @@ func NewResender[ BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, - FEE feetypes.Fee, + FEE fees.Fee, ]( lggr logger.Logger, txStore txmgrtypes.TransactionStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, SEQ, FEE], @@ -184,13 +185,13 @@ func (er *Resender[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) resendUnco return nil } -func logResendResult(lggr logger.Logger, codes []client.SendTxReturnCode) { +func logResendResult(lggr logger.Logger, codes []multinode.SendTxReturnCode) { var nNew int var nFatal int for _, c := range codes { - if c == client.Successful { + if c == multinode.Successful { nNew++ - } else if c == client.Fatal { + } else if c == multinode.Fatal { nFatal++ } } @@ -217,7 +218,7 @@ func findOldestUnconfirmedAttempt[ ADDR types.Hashable, TX_HASH, BLOCK_HASH types.Hashable, SEQ types.Sequence, - FEE feetypes.Fee, + FEE fees.Fee, ](attempts []txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) (txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], bool) { var oldestAttempt txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] if len(attempts) < 1 { diff --git a/common/txmgr/tracker.go b/common/txmgr/tracker.go index 408ae62173a..6c2d586548f 100644 --- a/common/txmgr/tracker.go +++ b/common/txmgr/tracker.go @@ -11,7 +11,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" - feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" + "github.com/smartcontractkit/chainlink/v2/common/fees" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/common/types" ) @@ -39,7 +39,7 @@ type Tracker[ BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, - FEE feetypes.Fee, + FEE fees.Fee, ] struct { services.StateMachine txStore txmgrtypes.TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] @@ -67,7 +67,7 @@ func NewTracker[ BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, - FEE feetypes.Fee, + FEE fees.Fee, ]( txStore txmgrtypes.TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE], keyStore txmgrtypes.KeyStore[ADDR, CHAIN_ID, SEQ], diff --git a/common/txmgr/txmgr.go b/common/txmgr/txmgr.go index 3776f62254c..ec7841d470d 100644 --- a/common/txmgr/txmgr.go +++ b/common/txmgr/txmgr.go @@ -9,6 +9,7 @@ import ( "time" "github.com/google/uuid" + "github.com/jpillora/backoff" nullv4 "gopkg.in/guregu/null.v4" "github.com/smartcontractkit/chainlink-common/pkg/logger" @@ -16,9 +17,8 @@ import ( commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/utils" - feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" + "github.com/smartcontractkit/chainlink/v2/common/fees" "github.com/smartcontractkit/chainlink/v2/common/headtracker" - iutils "github.com/smartcontractkit/chainlink/v2/common/internal/utils" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/common/types" ) @@ -40,7 +40,7 @@ type TxManager[ TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, - FEE feetypes.Fee, + FEE fees.Fee, ] interface { headtracker.HeadTrackable[HEAD, BLOCK_HASH] services.Service @@ -65,6 +65,20 @@ type TxManager[ GetTransactionStatus(ctx context.Context, transactionID string) (state commontypes.TransactionStatus, err error) } +type TxmV2Wrapper[ + CHAIN_ID types.ID, + HEAD types.Head[BLOCK_HASH], + ADDR types.Hashable, + TX_HASH types.Hashable, + BLOCK_HASH types.Hashable, + SEQ types.Sequence, + FEE fees.Fee, +] interface { + services.Service + CreateTransaction(ctx context.Context, txRequest txmgrtypes.TxRequest[ADDR, TX_HASH]) (etx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) + Reset(addr ADDR, abandon bool) error +} + type reset struct { // f is the function to execute between stopping/starting the // Broadcaster and Confirmer @@ -82,7 +96,7 @@ type Txm[ BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, - FEE feetypes.Fee, + FEE fees.Fee, ] struct { services.StateMachine logger logger.SugaredLogger @@ -112,6 +126,7 @@ type Txm[ fwdMgr txmgrtypes.ForwarderManager[ADDR] txAttemptBuilder txmgrtypes.TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] newErrorClassifier NewErrorClassifier + txmv2wrapper TxmV2Wrapper[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] } func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) RegisterResumeCallback(fn ResumeCallback) { @@ -130,7 +145,7 @@ func NewTxm[ BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, - FEE feetypes.Fee, + FEE fees.Fee, ]( chainId CHAIN_ID, cfg txmgrtypes.TransactionManagerChainConfig, @@ -147,6 +162,7 @@ func NewTxm[ tracker *Tracker[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE], finalizer txmgrtypes.Finalizer[BLOCK_HASH, HEAD], newErrorClassifierFunc NewErrorClassifier, + txmv2wrapper TxmV2Wrapper[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], ) *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { b := Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]{ logger: logger.Sugared(lggr), @@ -169,6 +185,7 @@ func NewTxm[ tracker: tracker, newErrorClassifier: newErrorClassifierFunc, finalizer: finalizer, + txmv2wrapper: txmv2wrapper, } if txCfg.ResendAfterThreshold() <= 0 { @@ -207,6 +224,12 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Start(ctx return fmt.Errorf("Txm: Finalizer failed to start: %w", err) } + if b.txmv2wrapper != nil { + if err := ms.Start(ctx, b.txmv2wrapper); err != nil { + return fmt.Errorf("Txm: Txmv2 failed to start: %w", err) + } + } + b.logger.Info("Txm starting runLoop") b.wg.Add(1) go b.runLoop() @@ -237,6 +260,11 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Reset(addr f := func() { if abandon { err = b.abandon(addr) + if b.txmv2wrapper != nil { + if err2 := b.txmv2wrapper.Reset(addr, abandon); err2 != nil { + b.logger.Error("failed to abandon transactions for dual broadcast", "err", err2) + } + } } } @@ -359,7 +387,7 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) runLoop() go func() { defer wg.Done() // Retry indefinitely on failure - backoff := iutils.NewRedialBackoff() + backoff := newRedialBackoff() for { select { case <-time.After(backoff.Duration()): @@ -378,7 +406,7 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) runLoop() go func() { defer wg.Done() // Retry indefinitely on failure - backoff := iutils.NewRedialBackoff() + backoff := newRedialBackoff() for { select { case <-time.After(backoff.Duration()): @@ -397,7 +425,7 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) runLoop() go func() { defer wg.Done() // Retry indefinitely on failure - backoff := iutils.NewRedialBackoff() + backoff := newRedialBackoff() for { select { case <-time.After(backoff.Duration()): @@ -460,6 +488,12 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) runLoop() if err != nil && (!errors.Is(err, services.ErrAlreadyStopped) || !errors.Is(err, services.ErrCannotStopUnstarted)) { b.logger.Errorw(fmt.Sprintf("Failed to Close Finalizer: %v", err), "err", err) } + if b.txmv2wrapper != nil { + err = b.txmv2wrapper.Close() + if err != nil && (!errors.Is(err, services.ErrAlreadyStopped) || !errors.Is(err, services.ErrCannotStopUnstarted)) { + b.logger.Errorw(fmt.Sprintf("Failed to Close Finalizer: %v", err), "err", err) + } + } return case <-keysChanged: // This check prevents the weird edge-case where you can select @@ -513,11 +547,14 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Trigger(ad func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) CreateTransaction(ctx context.Context, txRequest txmgrtypes.TxRequest[ADDR, TX_HASH]) (tx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) { // Check for existing Tx with IdempotencyKey. If found, return the Tx and do nothing // Skipping CreateTransaction to avoid double send + if b.txmv2wrapper != nil && txRequest.Meta != nil && txRequest.Meta.DualBroadcast != nil && *txRequest.Meta.DualBroadcast { + return b.txmv2wrapper.CreateTransaction(ctx, txRequest) + } if txRequest.IdempotencyKey != nil { var existingTx *txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] existingTx, err = b.txStore.FindTxWithIdempotencyKey(ctx, *txRequest.IdempotencyKey, b.chainID) if err != nil { - return tx, fmt.Errorf("Failed to search for transaction with IdempotencyKey: %w", err) + return tx, fmt.Errorf("failed to search for transaction with IdempotencyKey: %w", err) } if existingTx != nil { b.logger.Infow("Found a Tx with IdempotencyKey. Returning existing Tx without creating a new one.", "IdempotencyKey", *txRequest.IdempotencyKey) @@ -682,7 +719,7 @@ type NullTxManager[ ADDR types.Hashable, TX_HASH, BLOCK_HASH types.Hashable, SEQ types.Sequence, - FEE feetypes.Fee, + FEE fees.Fee, ] struct { ErrMsg string } @@ -798,3 +835,13 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) pruneQueue return tx, nil } + +// newRedialBackoff is a standard backoff to use for redialling or reconnecting to +// unreachable network endpoints +func newRedialBackoff() backoff.Backoff { + return backoff.Backoff{ + Min: 1 * time.Second, + Max: 15 * time.Second, + Jitter: true, + } +} diff --git a/common/txmgr/types/client.go b/common/txmgr/types/client.go index 759b15d6162..610f503c5b5 100644 --- a/common/txmgr/types/client.go +++ b/common/txmgr/types/client.go @@ -7,8 +7,9 @@ import ( "time" "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink/v2/common/client" - feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" + "github.com/smartcontractkit/chainlink-framework/multinode" + + "github.com/smartcontractkit/chainlink/v2/common/fees" "github.com/smartcontractkit/chainlink/v2/common/types" ) @@ -20,7 +21,7 @@ type TxmClient[ BLOCK_HASH types.Hashable, R ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, - FEE feetypes.Fee, + FEE fees.Fee, ] interface { ChainClient[CHAIN_ID, ADDR, SEQ] TransactionClient[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] @@ -39,7 +40,7 @@ type TransactionClient[ TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, - FEE feetypes.Fee, + FEE fees.Fee, ] interface { ChainClient[CHAIN_ID, ADDR, SEQ] @@ -49,7 +50,7 @@ type TransactionClient[ bathSize int, lggr logger.SugaredLogger, ) ( - txCodes []client.SendTxReturnCode, + txCodes []multinode.SendTxReturnCode, txErrs []error, broadcastTime time.Time, successfulTxIDs []int64, @@ -59,7 +60,7 @@ type TransactionClient[ tx Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], attempt TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], lggr logger.SugaredLogger, - ) (client.SendTxReturnCode, error) + ) (multinode.SendTxReturnCode, error) SendEmptyTransaction( ctx context.Context, newTxAttempt func(ctx context.Context, seq SEQ, feeLimit uint64, fee FEE, fromAddress ADDR) (attempt TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error), diff --git a/common/txmgr/types/mocks/forwarder_manager.go b/common/txmgr/types/mocks/forwarder_manager.go index 4582e4bac07..8ee0be73822 100644 --- a/common/txmgr/types/mocks/forwarder_manager.go +++ b/common/txmgr/types/mocks/forwarder_manager.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -23,7 +23,7 @@ func (_m *ForwarderManager[ADDR]) EXPECT() *ForwarderManager_Expecter[ADDR] { return &ForwarderManager_Expecter[ADDR]{mock: &_m.Mock} } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *ForwarderManager[ADDR]) Close() error { ret := _m.Called() @@ -143,7 +143,9 @@ func (_m *ForwarderManager[ADDR]) ForwarderFor(ctx context.Context, addr ADDR) ( if rf, ok := ret.Get(0).(func(context.Context, ADDR) ADDR); ok { r0 = rf(ctx, addr) } else { - r0 = ret.Get(0).(ADDR) + if ret.Get(0) != nil { + r0 = ret.Get(0).(ADDR) + } } if rf, ok := ret.Get(1).(func(context.Context, ADDR) error); ok { @@ -200,7 +202,9 @@ func (_m *ForwarderManager[ADDR]) ForwarderForOCR2Feeds(ctx context.Context, eoa if rf, ok := ret.Get(0).(func(context.Context, ADDR, ADDR) ADDR); ok { r0 = rf(ctx, eoa, ocr2Aggregator) } else { - r0 = ret.Get(0).(ADDR) + if ret.Get(0) != nil { + r0 = ret.Get(0).(ADDR) + } } if rf, ok := ret.Get(1).(func(context.Context, ADDR, ADDR) error); ok { @@ -242,7 +246,7 @@ func (_c *ForwarderManager_ForwarderForOCR2Feeds_Call[ADDR]) RunAndReturn(run fu return _c } -// HealthReport provides a mock function with given fields: +// HealthReport provides a mock function with no fields func (_m *ForwarderManager[ADDR]) HealthReport() map[string]error { ret := _m.Called() @@ -289,7 +293,7 @@ func (_c *ForwarderManager_HealthReport_Call[ADDR]) RunAndReturn(run func() map[ return _c } -// Name provides a mock function with given fields: +// Name provides a mock function with no fields func (_m *ForwarderManager[ADDR]) Name() string { ret := _m.Called() @@ -334,7 +338,7 @@ func (_c *ForwarderManager_Name_Call[ADDR]) RunAndReturn(run func() string) *For return _c } -// Ready provides a mock function with given fields: +// Ready provides a mock function with no fields func (_m *ForwarderManager[ADDR]) Ready() error { ret := _m.Called() diff --git a/common/txmgr/types/mocks/key_store.go b/common/txmgr/types/mocks/key_store.go index 18161301b22..942d2773d9b 100644 --- a/common/txmgr/types/mocks/key_store.go +++ b/common/txmgr/types/mocks/key_store.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/common/txmgr/types/mocks/tx_attempt_builder.go b/common/txmgr/types/mocks/tx_attempt_builder.go index 746e580413c..ddc09f3b2dd 100644 --- a/common/txmgr/types/mocks/tx_attempt_builder.go +++ b/common/txmgr/types/mocks/tx_attempt_builder.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -6,7 +6,7 @@ import ( context "context" logger "github.com/smartcontractkit/chainlink-common/pkg/logger" - feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" + fees "github.com/smartcontractkit/chainlink/v2/common/fees" mock "github.com/stretchr/testify/mock" @@ -16,11 +16,11 @@ import ( ) // TxAttemptBuilder is an autogenerated mock type for the TxAttemptBuilder type -type TxAttemptBuilder[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxAttemptBuilder[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { mock.Mock } -type TxAttemptBuilder_Expecter[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxAttemptBuilder_Expecter[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { mock *mock.Mock } @@ -28,7 +28,7 @@ func (_m *TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) return &TxAttemptBuilder_Expecter[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]{mock: &_m.Mock} } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) Close() error { ret := _m.Called() @@ -47,7 +47,7 @@ func (_m *TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) } // TxAttemptBuilder_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close' -type TxAttemptBuilder_Close_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxAttemptBuilder_Close_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -73,7 +73,7 @@ func (_c *TxAttemptBuilder_Close_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, return _c } -// HealthReport provides a mock function with given fields: +// HealthReport provides a mock function with no fields func (_m *TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) HealthReport() map[string]error { ret := _m.Called() @@ -94,7 +94,7 @@ func (_m *TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) } // TxAttemptBuilder_HealthReport_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'HealthReport' -type TxAttemptBuilder_HealthReport_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxAttemptBuilder_HealthReport_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -120,7 +120,7 @@ func (_c *TxAttemptBuilder_HealthReport_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOC return _c } -// Name provides a mock function with given fields: +// Name provides a mock function with no fields func (_m *TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) Name() string { ret := _m.Called() @@ -139,7 +139,7 @@ func (_m *TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) } // TxAttemptBuilder_Name_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Name' -type TxAttemptBuilder_Name_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxAttemptBuilder_Name_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -190,7 +190,9 @@ func (_m *TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) if rf, ok := ret.Get(1).(func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], []txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], logger.Logger) FEE); ok { r1 = rf(ctx, tx, previousAttempt, priorAttempts, lggr) } else { - r1 = ret.Get(1).(FEE) + if ret.Get(1) != nil { + r1 = ret.Get(1).(FEE) + } } if rf, ok := ret.Get(2).(func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], []txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], logger.Logger) uint64); ok { @@ -215,7 +217,7 @@ func (_m *TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) } // TxAttemptBuilder_NewBumpTxAttempt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'NewBumpTxAttempt' -type TxAttemptBuilder_NewBumpTxAttempt_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxAttemptBuilder_NewBumpTxAttempt_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -282,7 +284,7 @@ func (_m *TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) } // TxAttemptBuilder_NewCustomTxAttempt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'NewCustomTxAttempt' -type TxAttemptBuilder_NewCustomTxAttempt_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxAttemptBuilder_NewCustomTxAttempt_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -343,7 +345,7 @@ func (_m *TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) } // TxAttemptBuilder_NewEmptyTxAttempt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'NewEmptyTxAttempt' -type TxAttemptBuilder_NewEmptyTxAttempt_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxAttemptBuilder_NewEmptyTxAttempt_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -403,7 +405,7 @@ func (_m *TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) } // TxAttemptBuilder_NewPurgeTxAttempt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'NewPurgeTxAttempt' -type TxAttemptBuilder_NewPurgeTxAttempt_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxAttemptBuilder_NewPurgeTxAttempt_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -433,7 +435,7 @@ func (_c *TxAttemptBuilder_NewPurgeTxAttempt_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, } // NewTxAttempt provides a mock function with given fields: ctx, tx, lggr, opts -func (_m *TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) NewTxAttempt(ctx context.Context, tx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], lggr logger.Logger, opts ...feetypes.Opt) (txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], FEE, uint64, bool, error) { +func (_m *TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) NewTxAttempt(ctx context.Context, tx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], lggr logger.Logger, opts ...fees.Opt) (txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], FEE, uint64, bool, error) { _va := make([]interface{}, len(opts)) for _i := range opts { _va[_i] = opts[_i] @@ -452,34 +454,36 @@ func (_m *TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) var r2 uint64 var r3 bool var r4 error - if rf, ok := ret.Get(0).(func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], logger.Logger, ...feetypes.Opt) (txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], FEE, uint64, bool, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], logger.Logger, ...fees.Opt) (txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], FEE, uint64, bool, error)); ok { return rf(ctx, tx, lggr, opts...) } - if rf, ok := ret.Get(0).(func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], logger.Logger, ...feetypes.Opt) txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]); ok { + if rf, ok := ret.Get(0).(func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], logger.Logger, ...fees.Opt) txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]); ok { r0 = rf(ctx, tx, lggr, opts...) } else { r0 = ret.Get(0).(txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) } - if rf, ok := ret.Get(1).(func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], logger.Logger, ...feetypes.Opt) FEE); ok { + if rf, ok := ret.Get(1).(func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], logger.Logger, ...fees.Opt) FEE); ok { r1 = rf(ctx, tx, lggr, opts...) } else { - r1 = ret.Get(1).(FEE) + if ret.Get(1) != nil { + r1 = ret.Get(1).(FEE) + } } - if rf, ok := ret.Get(2).(func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], logger.Logger, ...feetypes.Opt) uint64); ok { + if rf, ok := ret.Get(2).(func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], logger.Logger, ...fees.Opt) uint64); ok { r2 = rf(ctx, tx, lggr, opts...) } else { r2 = ret.Get(2).(uint64) } - if rf, ok := ret.Get(3).(func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], logger.Logger, ...feetypes.Opt) bool); ok { + if rf, ok := ret.Get(3).(func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], logger.Logger, ...fees.Opt) bool); ok { r3 = rf(ctx, tx, lggr, opts...) } else { r3 = ret.Get(3).(bool) } - if rf, ok := ret.Get(4).(func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], logger.Logger, ...feetypes.Opt) error); ok { + if rf, ok := ret.Get(4).(func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], logger.Logger, ...fees.Opt) error); ok { r4 = rf(ctx, tx, lggr, opts...) } else { r4 = ret.Error(4) @@ -489,7 +493,7 @@ func (_m *TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) } // TxAttemptBuilder_NewTxAttempt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'NewTxAttempt' -type TxAttemptBuilder_NewTxAttempt_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxAttemptBuilder_NewTxAttempt_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -497,18 +501,18 @@ type TxAttemptBuilder_NewTxAttempt_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK // - ctx context.Context // - tx txmgrtypes.Tx[CHAIN_ID,ADDR,TX_HASH,BLOCK_HASH,SEQ,FEE] // - lggr logger.Logger -// - opts ...feetypes.Opt +// - opts ...fees.Opt func (_e *TxAttemptBuilder_Expecter[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) NewTxAttempt(ctx interface{}, tx interface{}, lggr interface{}, opts ...interface{}) *TxAttemptBuilder_NewTxAttempt_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] { return &TxAttemptBuilder_NewTxAttempt_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]{Call: _e.mock.On("NewTxAttempt", append([]interface{}{ctx, tx, lggr}, opts...)...)} } -func (_c *TxAttemptBuilder_NewTxAttempt_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) Run(run func(ctx context.Context, tx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], lggr logger.Logger, opts ...feetypes.Opt)) *TxAttemptBuilder_NewTxAttempt_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] { +func (_c *TxAttemptBuilder_NewTxAttempt_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) Run(run func(ctx context.Context, tx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], lggr logger.Logger, opts ...fees.Opt)) *TxAttemptBuilder_NewTxAttempt_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]feetypes.Opt, len(args)-3) + variadicArgs := make([]fees.Opt, len(args)-3) for i, a := range args[3:] { if a != nil { - variadicArgs[i] = a.(feetypes.Opt) + variadicArgs[i] = a.(fees.Opt) } } run(args[0].(context.Context), args[1].(txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]), args[2].(logger.Logger), variadicArgs...) @@ -521,13 +525,13 @@ func (_c *TxAttemptBuilder_NewTxAttempt_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOC return _c } -func (_c *TxAttemptBuilder_NewTxAttempt_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) RunAndReturn(run func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], logger.Logger, ...feetypes.Opt) (txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], FEE, uint64, bool, error)) *TxAttemptBuilder_NewTxAttempt_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] { +func (_c *TxAttemptBuilder_NewTxAttempt_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) RunAndReturn(run func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], logger.Logger, ...fees.Opt) (txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], FEE, uint64, bool, error)) *TxAttemptBuilder_NewTxAttempt_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] { _c.Call.Return(run) return _c } // NewTxAttemptWithType provides a mock function with given fields: ctx, tx, lggr, txType, opts -func (_m *TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) NewTxAttemptWithType(ctx context.Context, tx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], lggr logger.Logger, txType int, opts ...feetypes.Opt) (txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], FEE, uint64, bool, error) { +func (_m *TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) NewTxAttemptWithType(ctx context.Context, tx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], lggr logger.Logger, txType int, opts ...fees.Opt) (txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], FEE, uint64, bool, error) { _va := make([]interface{}, len(opts)) for _i := range opts { _va[_i] = opts[_i] @@ -546,34 +550,36 @@ func (_m *TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) var r2 uint64 var r3 bool var r4 error - if rf, ok := ret.Get(0).(func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], logger.Logger, int, ...feetypes.Opt) (txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], FEE, uint64, bool, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], logger.Logger, int, ...fees.Opt) (txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], FEE, uint64, bool, error)); ok { return rf(ctx, tx, lggr, txType, opts...) } - if rf, ok := ret.Get(0).(func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], logger.Logger, int, ...feetypes.Opt) txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]); ok { + if rf, ok := ret.Get(0).(func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], logger.Logger, int, ...fees.Opt) txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]); ok { r0 = rf(ctx, tx, lggr, txType, opts...) } else { r0 = ret.Get(0).(txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) } - if rf, ok := ret.Get(1).(func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], logger.Logger, int, ...feetypes.Opt) FEE); ok { + if rf, ok := ret.Get(1).(func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], logger.Logger, int, ...fees.Opt) FEE); ok { r1 = rf(ctx, tx, lggr, txType, opts...) } else { - r1 = ret.Get(1).(FEE) + if ret.Get(1) != nil { + r1 = ret.Get(1).(FEE) + } } - if rf, ok := ret.Get(2).(func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], logger.Logger, int, ...feetypes.Opt) uint64); ok { + if rf, ok := ret.Get(2).(func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], logger.Logger, int, ...fees.Opt) uint64); ok { r2 = rf(ctx, tx, lggr, txType, opts...) } else { r2 = ret.Get(2).(uint64) } - if rf, ok := ret.Get(3).(func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], logger.Logger, int, ...feetypes.Opt) bool); ok { + if rf, ok := ret.Get(3).(func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], logger.Logger, int, ...fees.Opt) bool); ok { r3 = rf(ctx, tx, lggr, txType, opts...) } else { r3 = ret.Get(3).(bool) } - if rf, ok := ret.Get(4).(func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], logger.Logger, int, ...feetypes.Opt) error); ok { + if rf, ok := ret.Get(4).(func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], logger.Logger, int, ...fees.Opt) error); ok { r4 = rf(ctx, tx, lggr, txType, opts...) } else { r4 = ret.Error(4) @@ -583,7 +589,7 @@ func (_m *TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) } // TxAttemptBuilder_NewTxAttemptWithType_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'NewTxAttemptWithType' -type TxAttemptBuilder_NewTxAttemptWithType_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxAttemptBuilder_NewTxAttemptWithType_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -592,18 +598,18 @@ type TxAttemptBuilder_NewTxAttemptWithType_Call[CHAIN_ID types.ID, HEAD types.He // - tx txmgrtypes.Tx[CHAIN_ID,ADDR,TX_HASH,BLOCK_HASH,SEQ,FEE] // - lggr logger.Logger // - txType int -// - opts ...feetypes.Opt +// - opts ...fees.Opt func (_e *TxAttemptBuilder_Expecter[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) NewTxAttemptWithType(ctx interface{}, tx interface{}, lggr interface{}, txType interface{}, opts ...interface{}) *TxAttemptBuilder_NewTxAttemptWithType_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] { return &TxAttemptBuilder_NewTxAttemptWithType_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]{Call: _e.mock.On("NewTxAttemptWithType", append([]interface{}{ctx, tx, lggr, txType}, opts...)...)} } -func (_c *TxAttemptBuilder_NewTxAttemptWithType_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) Run(run func(ctx context.Context, tx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], lggr logger.Logger, txType int, opts ...feetypes.Opt)) *TxAttemptBuilder_NewTxAttemptWithType_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] { +func (_c *TxAttemptBuilder_NewTxAttemptWithType_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) Run(run func(ctx context.Context, tx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], lggr logger.Logger, txType int, opts ...fees.Opt)) *TxAttemptBuilder_NewTxAttemptWithType_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]feetypes.Opt, len(args)-4) + variadicArgs := make([]fees.Opt, len(args)-4) for i, a := range args[4:] { if a != nil { - variadicArgs[i] = a.(feetypes.Opt) + variadicArgs[i] = a.(fees.Opt) } } run(args[0].(context.Context), args[1].(txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]), args[2].(logger.Logger), args[3].(int), variadicArgs...) @@ -616,7 +622,7 @@ func (_c *TxAttemptBuilder_NewTxAttemptWithType_Call[CHAIN_ID, HEAD, ADDR, TX_HA return _c } -func (_c *TxAttemptBuilder_NewTxAttemptWithType_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) RunAndReturn(run func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], logger.Logger, int, ...feetypes.Opt) (txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], FEE, uint64, bool, error)) *TxAttemptBuilder_NewTxAttemptWithType_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] { +func (_c *TxAttemptBuilder_NewTxAttemptWithType_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) RunAndReturn(run func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], logger.Logger, int, ...fees.Opt) (txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], FEE, uint64, bool, error)) *TxAttemptBuilder_NewTxAttemptWithType_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] { _c.Call.Return(run) return _c } @@ -627,7 +633,7 @@ func (_m *TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) } // TxAttemptBuilder_OnNewLongestChain_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'OnNewLongestChain' -type TxAttemptBuilder_OnNewLongestChain_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxAttemptBuilder_OnNewLongestChain_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -651,11 +657,11 @@ func (_c *TxAttemptBuilder_OnNewLongestChain_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, } func (_c *TxAttemptBuilder_OnNewLongestChain_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) RunAndReturn(run func(context.Context, HEAD)) *TxAttemptBuilder_OnNewLongestChain_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] { - _c.Call.Return(run) + _c.Run(run) return _c } -// Ready provides a mock function with given fields: +// Ready provides a mock function with no fields func (_m *TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) Ready() error { ret := _m.Called() @@ -674,7 +680,7 @@ func (_m *TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) } // TxAttemptBuilder_Ready_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Ready' -type TxAttemptBuilder_Ready_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxAttemptBuilder_Ready_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -719,7 +725,7 @@ func (_m *TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) } // TxAttemptBuilder_Start_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Start' -type TxAttemptBuilder_Start_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxAttemptBuilder_Start_Call[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -748,7 +754,7 @@ func (_c *TxAttemptBuilder_Start_Call[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, // NewTxAttemptBuilder creates a new instance of TxAttemptBuilder. 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 NewTxAttemptBuilder[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE feetypes.Fee](t interface { +func NewTxAttemptBuilder[CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, FEE fees.Fee](t interface { mock.TestingT Cleanup(func()) }) *TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] { diff --git a/common/txmgr/types/mocks/tx_store.go b/common/txmgr/types/mocks/tx_store.go index b75ee69302a..29e67c6165f 100644 --- a/common/txmgr/types/mocks/tx_store.go +++ b/common/txmgr/types/mocks/tx_store.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -6,7 +6,7 @@ import ( context "context" big "math/big" - feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" + fees "github.com/smartcontractkit/chainlink/v2/common/fees" mock "github.com/stretchr/testify/mock" null "gopkg.in/guregu/null.v4" @@ -21,11 +21,11 @@ import ( ) // TxStore is an autogenerated mock type for the TxStore type -type TxStore[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { mock.Mock } -type TxStore_Expecter[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_Expecter[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { mock *mock.Mock } @@ -52,7 +52,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Abandon(ctx } // TxStore_Abandon_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Abandon' -type TxStore_Abandon_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_Abandon_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -100,7 +100,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) CheckTxQueu } // TxStore_CheckTxQueueCapacity_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CheckTxQueueCapacity' -type TxStore_CheckTxQueueCapacity_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_CheckTxQueueCapacity_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -130,13 +130,13 @@ func (_c *TxStore_CheckTxQueueCapacity_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, return _c } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Close() { _m.Called() } // TxStore_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close' -type TxStore_Close_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_Close_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -158,7 +158,7 @@ func (_c *TxStore_Close_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) } func (_c *TxStore_Close_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) RunAndReturn(run func()) *TxStore_Close_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -191,7 +191,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) CountTransa } // TxStore_CountTransactionsByState_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CountTransactionsByState' -type TxStore_CountTransactionsByState_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_CountTransactionsByState_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -249,7 +249,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) CountUnconf } // TxStore_CountUnconfirmedTransactions_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CountUnconfirmedTransactions' -type TxStore_CountUnconfirmedTransactions_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_CountUnconfirmedTransactions_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -307,7 +307,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) CountUnstar } // TxStore_CountUnstartedTransactions_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CountUnstartedTransactions' -type TxStore_CountUnstartedTransactions_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_CountUnstartedTransactions_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -365,7 +365,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) CreateTrans } // TxStore_CreateTransaction_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateTransaction' -type TxStore_CreateTransaction_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_CreateTransaction_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -413,7 +413,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) DeleteInPro } // TxStore_DeleteInProgressAttempt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteInProgressAttempt' -type TxStore_DeleteInProgressAttempt_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_DeleteInProgressAttempt_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -470,7 +470,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindEarlies } // TxStore_FindEarliestUnconfirmedBroadcastTime_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindEarliestUnconfirmedBroadcastTime' -type TxStore_FindEarliestUnconfirmedBroadcastTime_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_FindEarliestUnconfirmedBroadcastTime_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -527,7 +527,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindEarlies } // TxStore_FindEarliestUnconfirmedTxAttemptBlock_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindEarliestUnconfirmedTxAttemptBlock' -type TxStore_FindEarliestUnconfirmedTxAttemptBlock_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_FindEarliestUnconfirmedTxAttemptBlock_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -571,7 +571,9 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindLatestS if rf, ok := ret.Get(0).(func(context.Context, ADDR, CHAIN_ID) SEQ); ok { r0 = rf(ctx, fromAddress, chainID) } else { - r0 = ret.Get(0).(SEQ) + if ret.Get(0) != nil { + r0 = ret.Get(0).(SEQ) + } } if rf, ok := ret.Get(1).(func(context.Context, ADDR, CHAIN_ID) error); ok { @@ -584,7 +586,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindLatestS } // TxStore_FindLatestSequence_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindLatestSequence' -type TxStore_FindLatestSequence_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_FindLatestSequence_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -644,7 +646,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindNextUns } // TxStore_FindNextUnstartedTransactionFromAddress_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindNextUnstartedTransactionFromAddress' -type TxStore_FindNextUnstartedTransactionFromAddress_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_FindNextUnstartedTransactionFromAddress_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -713,7 +715,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindReorgOr } // TxStore_FindReorgOrIncludedTxs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindReorgOrIncludedTxs' -type TxStore_FindReorgOrIncludedTxs_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_FindReorgOrIncludedTxs_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -774,7 +776,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxAttem } // TxStore_FindTxAttemptsConfirmedMissingReceipt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindTxAttemptsConfirmedMissingReceipt' -type TxStore_FindTxAttemptsConfirmedMissingReceipt_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_FindTxAttemptsConfirmedMissingReceipt_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -833,7 +835,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxAttem } // TxStore_FindTxAttemptsRequiringResend_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindTxAttemptsRequiringResend' -type TxStore_FindTxAttemptsRequiringResend_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_FindTxAttemptsRequiringResend_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -895,7 +897,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxWithI } // TxStore_FindTxWithIdempotencyKey_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindTxWithIdempotencyKey' -type TxStore_FindTxWithIdempotencyKey_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_FindTxWithIdempotencyKey_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -955,7 +957,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxWithS } // TxStore_FindTxWithSequence_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindTxWithSequence' -type TxStore_FindTxWithSequence_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_FindTxWithSequence_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -1015,7 +1017,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxesByM } // TxStore_FindTxesByMetaFieldAndStates_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindTxesByMetaFieldAndStates' -type TxStore_FindTxesByMetaFieldAndStates_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_FindTxesByMetaFieldAndStates_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -1077,7 +1079,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxesPen } // TxStore_FindTxesPendingCallback_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindTxesPendingCallback' -type TxStore_FindTxesPendingCallback_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_FindTxesPendingCallback_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -1138,7 +1140,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxesWit } // TxStore_FindTxesWithAttemptsAndReceiptsByIdsAndState_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindTxesWithAttemptsAndReceiptsByIdsAndState' -type TxStore_FindTxesWithAttemptsAndReceiptsByIdsAndState_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_FindTxesWithAttemptsAndReceiptsByIdsAndState_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -1199,7 +1201,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxesWit } // TxStore_FindTxesWithMetaFieldByReceiptBlockNum_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindTxesWithMetaFieldByReceiptBlockNum' -type TxStore_FindTxesWithMetaFieldByReceiptBlockNum_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_FindTxesWithMetaFieldByReceiptBlockNum_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -1260,7 +1262,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxesWit } // TxStore_FindTxesWithMetaFieldByStates_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindTxesWithMetaFieldByStates' -type TxStore_FindTxesWithMetaFieldByStates_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_FindTxesWithMetaFieldByStates_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -1321,7 +1323,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxsRequ } // TxStore_FindTxsRequiringGasBump_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindTxsRequiringGasBump' -type TxStore_FindTxsRequiringGasBump_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_FindTxsRequiringGasBump_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -1384,7 +1386,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxsRequ } // TxStore_FindTxsRequiringResubmissionDueToInsufficientFunds_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindTxsRequiringResubmissionDueToInsufficientFunds' -type TxStore_FindTxsRequiringResubmissionDueToInsufficientFunds_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_FindTxsRequiringResubmissionDueToInsufficientFunds_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -1444,7 +1446,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) GetAbandone } // TxStore_GetAbandonedTransactionsByBatch_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetAbandonedTransactionsByBatch' -type TxStore_GetAbandonedTransactionsByBatch_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_GetAbandonedTransactionsByBatch_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -1506,7 +1508,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) GetInProgre } // TxStore_GetInProgressTxAttempts_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetInProgressTxAttempts' -type TxStore_GetInProgressTxAttempts_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_GetInProgressTxAttempts_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -1566,7 +1568,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) GetTxByID(c } // TxStore_GetTxByID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTxByID' -type TxStore_GetTxByID_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_GetTxByID_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -1625,7 +1627,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) GetTxInProg } // TxStore_GetTxInProgress_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTxInProgress' -type TxStore_GetTxInProgress_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_GetTxInProgress_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -1682,7 +1684,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) HasInProgre } // TxStore_HasInProgressTransaction_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'HasInProgressTransaction' -type TxStore_HasInProgressTransaction_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_HasInProgressTransaction_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -1730,7 +1732,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) LoadTxAttem } // TxStore_LoadTxAttempts_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'LoadTxAttempts' -type TxStore_LoadTxAttempts_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_LoadTxAttempts_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -1777,7 +1779,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) PreloadTxes } // TxStore_PreloadTxes_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'PreloadTxes' -type TxStore_PreloadTxes_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_PreloadTxes_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -1836,7 +1838,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) PruneUnstar } // TxStore_PruneUnstartedTxQueue_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'PruneUnstartedTxQueue' -type TxStore_PruneUnstartedTxQueue_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_PruneUnstartedTxQueue_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -1884,7 +1886,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) ReapTxHisto } // TxStore_ReapTxHistory_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ReapTxHistory' -type TxStore_ReapTxHistory_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_ReapTxHistory_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -1932,7 +1934,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) SaveConfirm } // TxStore_SaveConfirmedAttempt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SaveConfirmedAttempt' -type TxStore_SaveConfirmedAttempt_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_SaveConfirmedAttempt_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -1981,7 +1983,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) SaveFetched } // TxStore_SaveFetchedReceipts_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SaveFetchedReceipts' -type TxStore_SaveFetchedReceipts_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_SaveFetchedReceipts_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -2028,7 +2030,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) SaveInProgr } // TxStore_SaveInProgressAttempt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SaveInProgressAttempt' -type TxStore_SaveInProgressAttempt_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_SaveInProgressAttempt_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -2075,7 +2077,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) SaveInsuffi } // TxStore_SaveInsufficientFundsAttempt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SaveInsufficientFundsAttempt' -type TxStore_SaveInsufficientFundsAttempt_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_SaveInsufficientFundsAttempt_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -2124,7 +2126,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) SaveReplace } // TxStore_SaveReplacementInProgressAttempt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SaveReplacementInProgressAttempt' -type TxStore_SaveReplacementInProgressAttempt_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_SaveReplacementInProgressAttempt_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -2172,7 +2174,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) SaveSentAtt } // TxStore_SaveSentAttempt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SaveSentAttempt' -type TxStore_SaveSentAttempt_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_SaveSentAttempt_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -2221,7 +2223,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) SetBroadcas } // TxStore_SetBroadcastBeforeBlockNum_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetBroadcastBeforeBlockNum' -type TxStore_SetBroadcastBeforeBlockNum_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_SetBroadcastBeforeBlockNum_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -2269,7 +2271,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateBroad } // TxStore_UpdateBroadcastAts_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateBroadcastAts' -type TxStore_UpdateBroadcastAts_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_UpdateBroadcastAts_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -2317,7 +2319,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxAtt } // TxStore_UpdateTxAttemptInProgressToBroadcast_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateTxAttemptInProgressToBroadcast' -type TxStore_UpdateTxAttemptInProgressToBroadcast_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_UpdateTxAttemptInProgressToBroadcast_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -2366,7 +2368,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxCal } // TxStore_UpdateTxCallbackCompleted_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateTxCallbackCompleted' -type TxStore_UpdateTxCallbackCompleted_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_UpdateTxCallbackCompleted_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -2414,7 +2416,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxCon } // TxStore_UpdateTxConfirmed_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateTxConfirmed' -type TxStore_UpdateTxConfirmed_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_UpdateTxConfirmed_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -2461,7 +2463,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxFat } // TxStore_UpdateTxFatalError_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateTxFatalError' -type TxStore_UpdateTxFatalError_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_UpdateTxFatalError_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -2509,7 +2511,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxFat } // TxStore_UpdateTxFatalErrorAndDeleteAttempts_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateTxFatalErrorAndDeleteAttempts' -type TxStore_UpdateTxFatalErrorAndDeleteAttempts_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_UpdateTxFatalErrorAndDeleteAttempts_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -2556,7 +2558,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxUns } // TxStore_UpdateTxUnstartedToInProgress_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateTxUnstartedToInProgress' -type TxStore_UpdateTxUnstartedToInProgress_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_UpdateTxUnstartedToInProgress_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -2604,7 +2606,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxsFo } // TxStore_UpdateTxsForRebroadcast_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateTxsForRebroadcast' -type TxStore_UpdateTxsForRebroadcast_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_UpdateTxsForRebroadcast_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -2652,7 +2654,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxsUn } // TxStore_UpdateTxsUnconfirmed_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateTxsUnconfirmed' -type TxStore_UpdateTxsUnconfirmed_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +type TxStore_UpdateTxsUnconfirmed_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee] struct { *mock.Call } @@ -2682,7 +2684,7 @@ func (_c *TxStore_UpdateTxsUnconfirmed_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, // NewTxStore creates a new instance of TxStore. 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 NewTxStore[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee](t interface { +func NewTxStore[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE fees.Fee](t interface { mock.TestingT Cleanup(func()) }) *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { diff --git a/common/txmgr/types/mocks/tx_strategy.go b/common/txmgr/types/mocks/tx_strategy.go index b4f344d4424..98b6343ca9a 100644 --- a/common/txmgr/types/mocks/tx_strategy.go +++ b/common/txmgr/types/mocks/tx_strategy.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -83,7 +83,7 @@ func (_c *TxStrategy_PruneQueue_Call) RunAndReturn(run func(context.Context, typ return _c } -// Subject provides a mock function with given fields: +// Subject provides a mock function with no fields func (_m *TxStrategy) Subject() uuid.NullUUID { ret := _m.Called() diff --git a/common/txmgr/types/stuck_tx_detector.go b/common/txmgr/types/stuck_tx_detector.go index dc09eea9807..dcc7e7a027b 100644 --- a/common/txmgr/types/stuck_tx_detector.go +++ b/common/txmgr/types/stuck_tx_detector.go @@ -3,7 +3,7 @@ package types import ( "context" - feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" + "github.com/smartcontractkit/chainlink/v2/common/fees" "github.com/smartcontractkit/chainlink/v2/common/types" ) @@ -13,7 +13,7 @@ type StuckTxDetector[ ADDR types.Hashable, // ADDR - chain address type TX_HASH, BLOCK_HASH types.Hashable, // various chain hash types SEQ types.Sequence, // SEQ - chain sequence type (nonce, utxo, etc) - FEE feetypes.Fee, // FEE - chain fee type + FEE fees.Fee, // FEE - chain fee type ] interface { // Uses either a chain specific API or heuristic to determine if any unconfirmed transactions are terminally stuck. Returns only one transaction per enabled address. DetectStuckTransactions(ctx context.Context, enabledAddresses []ADDR, blockNum int64) ([]Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error) diff --git a/common/txmgr/types/tx.go b/common/txmgr/types/tx.go index b0bc2ca7025..b32e688fe50 100644 --- a/common/txmgr/types/tx.go +++ b/common/txmgr/types/tx.go @@ -17,7 +17,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" clnull "github.com/smartcontractkit/chainlink-common/pkg/utils/null" - feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" + "github.com/smartcontractkit/chainlink/v2/common/fees" "github.com/smartcontractkit/chainlink/v2/common/types" ) @@ -170,7 +170,7 @@ type TxAttempt[ ADDR types.Hashable, TX_HASH, BLOCK_HASH types.Hashable, SEQ types.Sequence, - FEE feetypes.Fee, + FEE fees.Fee, ] struct { ID int64 TxID int64 @@ -197,7 +197,7 @@ type Tx[ ADDR types.Hashable, TX_HASH, BLOCK_HASH types.Hashable, SEQ types.Sequence, - FEE feetypes.Fee, + FEE fees.Fee, ] struct { ID int64 IdempotencyKey *string diff --git a/common/txmgr/types/tx_attempt_builder.go b/common/txmgr/types/tx_attempt_builder.go index 44443e78211..acb93e9fc18 100644 --- a/common/txmgr/types/tx_attempt_builder.go +++ b/common/txmgr/types/tx_attempt_builder.go @@ -5,7 +5,8 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" - feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" + + "github.com/smartcontractkit/chainlink/v2/common/fees" "github.com/smartcontractkit/chainlink/v2/common/headtracker" "github.com/smartcontractkit/chainlink/v2/common/types" ) @@ -19,17 +20,17 @@ type TxAttemptBuilder[ ADDR types.Hashable, // ADDR - chain address type TX_HASH, BLOCK_HASH types.Hashable, // various chain hash types SEQ types.Sequence, // SEQ - chain sequence type (nonce, utxo, etc) - FEE feetypes.Fee, // FEE - chain fee type + FEE fees.Fee, // FEE - chain fee type ] interface { // interfaces for running the underlying estimator services.Service headtracker.HeadTrackable[HEAD, BLOCK_HASH] // NewTxAttempt builds a transaction using the configured transaction type and fee estimator (new estimation) - NewTxAttempt(ctx context.Context, tx Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], lggr logger.Logger, opts ...feetypes.Opt) (attempt TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], fee FEE, feeLimit uint64, retryable bool, err error) + NewTxAttempt(ctx context.Context, tx Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], lggr logger.Logger, opts ...fees.Opt) (attempt TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], fee FEE, feeLimit uint64, retryable bool, err error) // NewTxAttemptWithType builds a transaction using the configured fee estimator (new estimation) + passed in tx type - NewTxAttemptWithType(ctx context.Context, tx Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], lggr logger.Logger, txType int, opts ...feetypes.Opt) (attempt TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], fee FEE, feeLimit uint64, retryable bool, err error) + NewTxAttemptWithType(ctx context.Context, tx Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], lggr logger.Logger, txType int, opts ...fees.Opt) (attempt TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], fee FEE, feeLimit uint64, retryable bool, err error) // NewBumpTxAttempt builds a transaction using the configured fee estimator (bumping) + tx type from previous attempt // this should only be used after an initial attempt has been broadcast and the underlying gas estimator only needs to bump the fee diff --git a/common/txmgr/types/tx_store.go b/common/txmgr/types/tx_store.go index d685a6c5ce7..9a7e3736429 100644 --- a/common/txmgr/types/tx_store.go +++ b/common/txmgr/types/tx_store.go @@ -8,7 +8,7 @@ import ( "github.com/google/uuid" "gopkg.in/guregu/null.v4" - feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" + "github.com/smartcontractkit/chainlink/v2/common/fees" "github.com/smartcontractkit/chainlink/v2/common/types" ) @@ -27,7 +27,7 @@ type TxStore[ // Represents the sequence type for a chain. For example, nonce for EVM. SEQ types.Sequence, // Represents the chain specific fee type - FEE feetypes.Fee, + FEE fees.Fee, ] interface { UnstartedTxQueuePruner TxHistoryReaper[CHAIN_ID] @@ -61,7 +61,7 @@ type TransactionStore[ TX_HASH types.Hashable, BLOCK_HASH types.Hashable, SEQ types.Sequence, - FEE feetypes.Fee, + FEE fees.Fee, ] interface { CountUnconfirmedTransactions(ctx context.Context, fromAddress ADDR, chainID CHAIN_ID) (count uint32, err error) CountTransactionsByState(ctx context.Context, state TxState, chainID CHAIN_ID) (count uint32, err error) diff --git a/common/types/chain.go b/common/types/chain.go index bf4654142a8..35b3b0ca3f7 100644 --- a/common/types/chain.go +++ b/common/types/chain.go @@ -2,8 +2,6 @@ package types import ( "fmt" - - "github.com/smartcontractkit/chainlink-common/pkg/types" ) // Sequence represents the base type, for any chain's sequence object. @@ -16,10 +14,3 @@ type Sequence interface { // ID represents the base type, for any chain's ID. // It should be convertible to a string, that can uniquely identify this chain type ID fmt.Stringer - -// ChainStatusWithID compose of ChainStatus and RelayID. This is useful for -// storing the Network associated with the ChainStatus. -type ChainStatusWithID struct { - types.ChainStatus - types.RelayID -} diff --git a/common/types/mocks/head.go b/common/types/mocks/head.go deleted file mode 100644 index 85bef18a0be..00000000000 --- a/common/types/mocks/head.go +++ /dev/null @@ -1,601 +0,0 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. - -package mocks - -import ( - big "math/big" - time "time" - - mock "github.com/stretchr/testify/mock" - - types "github.com/smartcontractkit/chainlink/v2/common/types" -) - -// Head is an autogenerated mock type for the Head type -type Head[BLOCK_HASH types.Hashable] struct { - mock.Mock -} - -type Head_Expecter[BLOCK_HASH types.Hashable] struct { - mock *mock.Mock -} - -func (_m *Head[BLOCK_HASH]) EXPECT() *Head_Expecter[BLOCK_HASH] { - return &Head_Expecter[BLOCK_HASH]{mock: &_m.Mock} -} - -// BlockDifficulty provides a mock function with given fields: -func (_m *Head[BLOCK_HASH]) BlockDifficulty() *big.Int { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for BlockDifficulty") - } - - var r0 *big.Int - if rf, ok := ret.Get(0).(func() *big.Int); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*big.Int) - } - } - - return r0 -} - -// Head_BlockDifficulty_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BlockDifficulty' -type Head_BlockDifficulty_Call[BLOCK_HASH types.Hashable] struct { - *mock.Call -} - -// BlockDifficulty is a helper method to define mock.On call -func (_e *Head_Expecter[BLOCK_HASH]) BlockDifficulty() *Head_BlockDifficulty_Call[BLOCK_HASH] { - return &Head_BlockDifficulty_Call[BLOCK_HASH]{Call: _e.mock.On("BlockDifficulty")} -} - -func (_c *Head_BlockDifficulty_Call[BLOCK_HASH]) Run(run func()) *Head_BlockDifficulty_Call[BLOCK_HASH] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *Head_BlockDifficulty_Call[BLOCK_HASH]) Return(_a0 *big.Int) *Head_BlockDifficulty_Call[BLOCK_HASH] { - _c.Call.Return(_a0) - return _c -} - -func (_c *Head_BlockDifficulty_Call[BLOCK_HASH]) RunAndReturn(run func() *big.Int) *Head_BlockDifficulty_Call[BLOCK_HASH] { - _c.Call.Return(run) - return _c -} - -// BlockHash provides a mock function with given fields: -func (_m *Head[BLOCK_HASH]) BlockHash() BLOCK_HASH { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for BlockHash") - } - - var r0 BLOCK_HASH - if rf, ok := ret.Get(0).(func() BLOCK_HASH); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(BLOCK_HASH) - } - - return r0 -} - -// Head_BlockHash_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BlockHash' -type Head_BlockHash_Call[BLOCK_HASH types.Hashable] struct { - *mock.Call -} - -// BlockHash is a helper method to define mock.On call -func (_e *Head_Expecter[BLOCK_HASH]) BlockHash() *Head_BlockHash_Call[BLOCK_HASH] { - return &Head_BlockHash_Call[BLOCK_HASH]{Call: _e.mock.On("BlockHash")} -} - -func (_c *Head_BlockHash_Call[BLOCK_HASH]) Run(run func()) *Head_BlockHash_Call[BLOCK_HASH] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *Head_BlockHash_Call[BLOCK_HASH]) Return(_a0 BLOCK_HASH) *Head_BlockHash_Call[BLOCK_HASH] { - _c.Call.Return(_a0) - return _c -} - -func (_c *Head_BlockHash_Call[BLOCK_HASH]) RunAndReturn(run func() BLOCK_HASH) *Head_BlockHash_Call[BLOCK_HASH] { - _c.Call.Return(run) - return _c -} - -// BlockNumber provides a mock function with given fields: -func (_m *Head[BLOCK_HASH]) BlockNumber() int64 { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for BlockNumber") - } - - var r0 int64 - if rf, ok := ret.Get(0).(func() int64); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(int64) - } - - return r0 -} - -// Head_BlockNumber_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BlockNumber' -type Head_BlockNumber_Call[BLOCK_HASH types.Hashable] struct { - *mock.Call -} - -// BlockNumber is a helper method to define mock.On call -func (_e *Head_Expecter[BLOCK_HASH]) BlockNumber() *Head_BlockNumber_Call[BLOCK_HASH] { - return &Head_BlockNumber_Call[BLOCK_HASH]{Call: _e.mock.On("BlockNumber")} -} - -func (_c *Head_BlockNumber_Call[BLOCK_HASH]) Run(run func()) *Head_BlockNumber_Call[BLOCK_HASH] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *Head_BlockNumber_Call[BLOCK_HASH]) Return(_a0 int64) *Head_BlockNumber_Call[BLOCK_HASH] { - _c.Call.Return(_a0) - return _c -} - -func (_c *Head_BlockNumber_Call[BLOCK_HASH]) RunAndReturn(run func() int64) *Head_BlockNumber_Call[BLOCK_HASH] { - _c.Call.Return(run) - return _c -} - -// ChainLength provides a mock function with given fields: -func (_m *Head[BLOCK_HASH]) ChainLength() uint32 { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for ChainLength") - } - - var r0 uint32 - if rf, ok := ret.Get(0).(func() uint32); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(uint32) - } - - return r0 -} - -// Head_ChainLength_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ChainLength' -type Head_ChainLength_Call[BLOCK_HASH types.Hashable] struct { - *mock.Call -} - -// ChainLength is a helper method to define mock.On call -func (_e *Head_Expecter[BLOCK_HASH]) ChainLength() *Head_ChainLength_Call[BLOCK_HASH] { - return &Head_ChainLength_Call[BLOCK_HASH]{Call: _e.mock.On("ChainLength")} -} - -func (_c *Head_ChainLength_Call[BLOCK_HASH]) Run(run func()) *Head_ChainLength_Call[BLOCK_HASH] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *Head_ChainLength_Call[BLOCK_HASH]) Return(_a0 uint32) *Head_ChainLength_Call[BLOCK_HASH] { - _c.Call.Return(_a0) - return _c -} - -func (_c *Head_ChainLength_Call[BLOCK_HASH]) RunAndReturn(run func() uint32) *Head_ChainLength_Call[BLOCK_HASH] { - _c.Call.Return(run) - return _c -} - -// EarliestHeadInChain provides a mock function with given fields: -func (_m *Head[BLOCK_HASH]) EarliestHeadInChain() types.Head[BLOCK_HASH] { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for EarliestHeadInChain") - } - - var r0 types.Head[BLOCK_HASH] - if rf, ok := ret.Get(0).(func() types.Head[BLOCK_HASH]); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(types.Head[BLOCK_HASH]) - } - } - - return r0 -} - -// Head_EarliestHeadInChain_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EarliestHeadInChain' -type Head_EarliestHeadInChain_Call[BLOCK_HASH types.Hashable] struct { - *mock.Call -} - -// EarliestHeadInChain is a helper method to define mock.On call -func (_e *Head_Expecter[BLOCK_HASH]) EarliestHeadInChain() *Head_EarliestHeadInChain_Call[BLOCK_HASH] { - return &Head_EarliestHeadInChain_Call[BLOCK_HASH]{Call: _e.mock.On("EarliestHeadInChain")} -} - -func (_c *Head_EarliestHeadInChain_Call[BLOCK_HASH]) Run(run func()) *Head_EarliestHeadInChain_Call[BLOCK_HASH] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *Head_EarliestHeadInChain_Call[BLOCK_HASH]) Return(_a0 types.Head[BLOCK_HASH]) *Head_EarliestHeadInChain_Call[BLOCK_HASH] { - _c.Call.Return(_a0) - return _c -} - -func (_c *Head_EarliestHeadInChain_Call[BLOCK_HASH]) RunAndReturn(run func() types.Head[BLOCK_HASH]) *Head_EarliestHeadInChain_Call[BLOCK_HASH] { - _c.Call.Return(run) - return _c -} - -// GetParent provides a mock function with given fields: -func (_m *Head[BLOCK_HASH]) GetParent() types.Head[BLOCK_HASH] { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for GetParent") - } - - var r0 types.Head[BLOCK_HASH] - if rf, ok := ret.Get(0).(func() types.Head[BLOCK_HASH]); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(types.Head[BLOCK_HASH]) - } - } - - return r0 -} - -// Head_GetParent_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetParent' -type Head_GetParent_Call[BLOCK_HASH types.Hashable] struct { - *mock.Call -} - -// GetParent is a helper method to define mock.On call -func (_e *Head_Expecter[BLOCK_HASH]) GetParent() *Head_GetParent_Call[BLOCK_HASH] { - return &Head_GetParent_Call[BLOCK_HASH]{Call: _e.mock.On("GetParent")} -} - -func (_c *Head_GetParent_Call[BLOCK_HASH]) Run(run func()) *Head_GetParent_Call[BLOCK_HASH] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *Head_GetParent_Call[BLOCK_HASH]) Return(_a0 types.Head[BLOCK_HASH]) *Head_GetParent_Call[BLOCK_HASH] { - _c.Call.Return(_a0) - return _c -} - -func (_c *Head_GetParent_Call[BLOCK_HASH]) RunAndReturn(run func() types.Head[BLOCK_HASH]) *Head_GetParent_Call[BLOCK_HASH] { - _c.Call.Return(run) - return _c -} - -// GetParentHash provides a mock function with given fields: -func (_m *Head[BLOCK_HASH]) GetParentHash() BLOCK_HASH { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for GetParentHash") - } - - var r0 BLOCK_HASH - if rf, ok := ret.Get(0).(func() BLOCK_HASH); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(BLOCK_HASH) - } - - return r0 -} - -// Head_GetParentHash_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetParentHash' -type Head_GetParentHash_Call[BLOCK_HASH types.Hashable] struct { - *mock.Call -} - -// GetParentHash is a helper method to define mock.On call -func (_e *Head_Expecter[BLOCK_HASH]) GetParentHash() *Head_GetParentHash_Call[BLOCK_HASH] { - return &Head_GetParentHash_Call[BLOCK_HASH]{Call: _e.mock.On("GetParentHash")} -} - -func (_c *Head_GetParentHash_Call[BLOCK_HASH]) Run(run func()) *Head_GetParentHash_Call[BLOCK_HASH] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *Head_GetParentHash_Call[BLOCK_HASH]) Return(_a0 BLOCK_HASH) *Head_GetParentHash_Call[BLOCK_HASH] { - _c.Call.Return(_a0) - return _c -} - -func (_c *Head_GetParentHash_Call[BLOCK_HASH]) RunAndReturn(run func() BLOCK_HASH) *Head_GetParentHash_Call[BLOCK_HASH] { - _c.Call.Return(run) - return _c -} - -// GetTimestamp provides a mock function with given fields: -func (_m *Head[BLOCK_HASH]) GetTimestamp() time.Time { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for GetTimestamp") - } - - var r0 time.Time - if rf, ok := ret.Get(0).(func() time.Time); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(time.Time) - } - - return r0 -} - -// Head_GetTimestamp_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTimestamp' -type Head_GetTimestamp_Call[BLOCK_HASH types.Hashable] struct { - *mock.Call -} - -// GetTimestamp is a helper method to define mock.On call -func (_e *Head_Expecter[BLOCK_HASH]) GetTimestamp() *Head_GetTimestamp_Call[BLOCK_HASH] { - return &Head_GetTimestamp_Call[BLOCK_HASH]{Call: _e.mock.On("GetTimestamp")} -} - -func (_c *Head_GetTimestamp_Call[BLOCK_HASH]) Run(run func()) *Head_GetTimestamp_Call[BLOCK_HASH] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *Head_GetTimestamp_Call[BLOCK_HASH]) Return(_a0 time.Time) *Head_GetTimestamp_Call[BLOCK_HASH] { - _c.Call.Return(_a0) - return _c -} - -func (_c *Head_GetTimestamp_Call[BLOCK_HASH]) RunAndReturn(run func() time.Time) *Head_GetTimestamp_Call[BLOCK_HASH] { - _c.Call.Return(run) - return _c -} - -// HashAtHeight provides a mock function with given fields: blockNum -func (_m *Head[BLOCK_HASH]) HashAtHeight(blockNum int64) BLOCK_HASH { - ret := _m.Called(blockNum) - - if len(ret) == 0 { - panic("no return value specified for HashAtHeight") - } - - var r0 BLOCK_HASH - if rf, ok := ret.Get(0).(func(int64) BLOCK_HASH); ok { - r0 = rf(blockNum) - } else { - r0 = ret.Get(0).(BLOCK_HASH) - } - - return r0 -} - -// Head_HashAtHeight_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'HashAtHeight' -type Head_HashAtHeight_Call[BLOCK_HASH types.Hashable] struct { - *mock.Call -} - -// HashAtHeight is a helper method to define mock.On call -// - blockNum int64 -func (_e *Head_Expecter[BLOCK_HASH]) HashAtHeight(blockNum interface{}) *Head_HashAtHeight_Call[BLOCK_HASH] { - return &Head_HashAtHeight_Call[BLOCK_HASH]{Call: _e.mock.On("HashAtHeight", blockNum)} -} - -func (_c *Head_HashAtHeight_Call[BLOCK_HASH]) Run(run func(blockNum int64)) *Head_HashAtHeight_Call[BLOCK_HASH] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(int64)) - }) - return _c -} - -func (_c *Head_HashAtHeight_Call[BLOCK_HASH]) Return(_a0 BLOCK_HASH) *Head_HashAtHeight_Call[BLOCK_HASH] { - _c.Call.Return(_a0) - return _c -} - -func (_c *Head_HashAtHeight_Call[BLOCK_HASH]) RunAndReturn(run func(int64) BLOCK_HASH) *Head_HashAtHeight_Call[BLOCK_HASH] { - _c.Call.Return(run) - return _c -} - -// HeadAtHeight provides a mock function with given fields: blockNum -func (_m *Head[BLOCK_HASH]) HeadAtHeight(blockNum int64) (types.Head[BLOCK_HASH], error) { - ret := _m.Called(blockNum) - - if len(ret) == 0 { - panic("no return value specified for HeadAtHeight") - } - - var r0 types.Head[BLOCK_HASH] - var r1 error - if rf, ok := ret.Get(0).(func(int64) (types.Head[BLOCK_HASH], error)); ok { - return rf(blockNum) - } - if rf, ok := ret.Get(0).(func(int64) types.Head[BLOCK_HASH]); ok { - r0 = rf(blockNum) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(types.Head[BLOCK_HASH]) - } - } - - if rf, ok := ret.Get(1).(func(int64) error); ok { - r1 = rf(blockNum) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Head_HeadAtHeight_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'HeadAtHeight' -type Head_HeadAtHeight_Call[BLOCK_HASH types.Hashable] struct { - *mock.Call -} - -// HeadAtHeight is a helper method to define mock.On call -// - blockNum int64 -func (_e *Head_Expecter[BLOCK_HASH]) HeadAtHeight(blockNum interface{}) *Head_HeadAtHeight_Call[BLOCK_HASH] { - return &Head_HeadAtHeight_Call[BLOCK_HASH]{Call: _e.mock.On("HeadAtHeight", blockNum)} -} - -func (_c *Head_HeadAtHeight_Call[BLOCK_HASH]) Run(run func(blockNum int64)) *Head_HeadAtHeight_Call[BLOCK_HASH] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(int64)) - }) - return _c -} - -func (_c *Head_HeadAtHeight_Call[BLOCK_HASH]) Return(_a0 types.Head[BLOCK_HASH], _a1 error) *Head_HeadAtHeight_Call[BLOCK_HASH] { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *Head_HeadAtHeight_Call[BLOCK_HASH]) RunAndReturn(run func(int64) (types.Head[BLOCK_HASH], error)) *Head_HeadAtHeight_Call[BLOCK_HASH] { - _c.Call.Return(run) - return _c -} - -// IsValid provides a mock function with given fields: -func (_m *Head[BLOCK_HASH]) IsValid() bool { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for IsValid") - } - - var r0 bool - if rf, ok := ret.Get(0).(func() bool); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(bool) - } - - return r0 -} - -// Head_IsValid_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'IsValid' -type Head_IsValid_Call[BLOCK_HASH types.Hashable] struct { - *mock.Call -} - -// IsValid is a helper method to define mock.On call -func (_e *Head_Expecter[BLOCK_HASH]) IsValid() *Head_IsValid_Call[BLOCK_HASH] { - return &Head_IsValid_Call[BLOCK_HASH]{Call: _e.mock.On("IsValid")} -} - -func (_c *Head_IsValid_Call[BLOCK_HASH]) Run(run func()) *Head_IsValid_Call[BLOCK_HASH] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *Head_IsValid_Call[BLOCK_HASH]) Return(_a0 bool) *Head_IsValid_Call[BLOCK_HASH] { - _c.Call.Return(_a0) - return _c -} - -func (_c *Head_IsValid_Call[BLOCK_HASH]) RunAndReturn(run func() bool) *Head_IsValid_Call[BLOCK_HASH] { - _c.Call.Return(run) - return _c -} - -// LatestFinalizedHead provides a mock function with given fields: -func (_m *Head[BLOCK_HASH]) LatestFinalizedHead() types.Head[BLOCK_HASH] { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for LatestFinalizedHead") - } - - var r0 types.Head[BLOCK_HASH] - if rf, ok := ret.Get(0).(func() types.Head[BLOCK_HASH]); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(types.Head[BLOCK_HASH]) - } - } - - return r0 -} - -// Head_LatestFinalizedHead_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'LatestFinalizedHead' -type Head_LatestFinalizedHead_Call[BLOCK_HASH types.Hashable] struct { - *mock.Call -} - -// LatestFinalizedHead is a helper method to define mock.On call -func (_e *Head_Expecter[BLOCK_HASH]) LatestFinalizedHead() *Head_LatestFinalizedHead_Call[BLOCK_HASH] { - return &Head_LatestFinalizedHead_Call[BLOCK_HASH]{Call: _e.mock.On("LatestFinalizedHead")} -} - -func (_c *Head_LatestFinalizedHead_Call[BLOCK_HASH]) Run(run func()) *Head_LatestFinalizedHead_Call[BLOCK_HASH] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *Head_LatestFinalizedHead_Call[BLOCK_HASH]) Return(_a0 types.Head[BLOCK_HASH]) *Head_LatestFinalizedHead_Call[BLOCK_HASH] { - _c.Call.Return(_a0) - return _c -} - -func (_c *Head_LatestFinalizedHead_Call[BLOCK_HASH]) RunAndReturn(run func() types.Head[BLOCK_HASH]) *Head_LatestFinalizedHead_Call[BLOCK_HASH] { - _c.Call.Return(run) - return _c -} - -// NewHead creates a new instance of Head. 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 NewHead[BLOCK_HASH types.Hashable](t interface { - mock.TestingT - Cleanup(func()) -}) *Head[BLOCK_HASH] { - mock := &Head[BLOCK_HASH]{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/common/types/mocks/monitoring_endpoint.go b/common/types/mocks/monitoring_endpoint.go index d88be7cbf3f..892391d79a3 100644 --- a/common/types/mocks/monitoring_endpoint.go +++ b/common/types/mocks/monitoring_endpoint.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -46,7 +46,7 @@ func (_c *MonitoringEndpoint_SendLog_Call) Return() *MonitoringEndpoint_SendLog_ } func (_c *MonitoringEndpoint_SendLog_Call) RunAndReturn(run func([]byte)) *MonitoringEndpoint_SendLog_Call { - _c.Call.Return(run) + _c.Run(run) return _c } diff --git a/common/types/mocks/subscription.go b/common/types/mocks/subscription.go index b0b87c7287a..6c0764683b0 100644 --- a/common/types/mocks/subscription.go +++ b/common/types/mocks/subscription.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -17,7 +17,7 @@ func (_m *Subscription) EXPECT() *Subscription_Expecter { return &Subscription_Expecter{mock: &_m.Mock} } -// Err provides a mock function with given fields: +// Err provides a mock function with no fields func (_m *Subscription) Err() <-chan error { ret := _m.Called() @@ -64,7 +64,7 @@ func (_c *Subscription_Err_Call) RunAndReturn(run func() <-chan error) *Subscrip return _c } -// Unsubscribe provides a mock function with given fields: +// Unsubscribe provides a mock function with no fields func (_m *Subscription) Unsubscribe() { _m.Called() } @@ -92,7 +92,7 @@ func (_c *Subscription_Unsubscribe_Call) Return() *Subscription_Unsubscribe_Call } func (_c *Subscription_Unsubscribe_Call) RunAndReturn(run func()) *Subscription_Unsubscribe_Call { - _c.Call.Return(run) + _c.Run(run) return _c } diff --git a/common/types/receipt.go b/common/types/receipt.go deleted file mode 100644 index 01d5a72def5..00000000000 --- a/common/types/receipt.go +++ /dev/null @@ -1,14 +0,0 @@ -package types - -import "math/big" - -type Receipt[TX_HASH Hashable, BLOCK_HASH Hashable] interface { - GetStatus() uint64 - GetTxHash() TX_HASH - GetBlockNumber() *big.Int - IsZero() bool - IsUnmined() bool - GetFeeUsed() uint64 - GetTransactionIndex() uint - GetBlockHash() BLOCK_HASH -} diff --git a/common/types/test_utils.go b/common/types/test_utils.go deleted file mode 100644 index 40560f7866c..00000000000 --- a/common/types/test_utils.go +++ /dev/null @@ -1,16 +0,0 @@ -package types - -import ( - "math" - "math/big" - "math/rand" -) - -func RandomID() ID { - id := rand.Int63n(math.MaxInt32) + 10000 - return big.NewInt(id) -} - -func NewIDFromInt(id int64) ID { - return big.NewInt(id) -} diff --git a/contracts/.changeset/angry-needles-approve.md b/contracts/.changeset/angry-needles-approve.md new file mode 100644 index 00000000000..689f2ac6063 --- /dev/null +++ b/contracts/.changeset/angry-needles-approve.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': minor +--- + +#internal Removal and moving of various older Solidity contracts. Unused test helpers are removed, used files are now in their proper product folders diff --git a/contracts/.changeset/chilly-news-wink.md b/contracts/.changeset/chilly-news-wink.md new file mode 100644 index 00000000000..2ccdbb483ca --- /dev/null +++ b/contracts/.changeset/chilly-news-wink.md @@ -0,0 +1,10 @@ +--- +'@chainlink/contracts': minor +--- + +#feature Add two new pool types: Siloed-LockRelease and BurnToAddress and fix bug in HybridUSDCTokenPool for transferLiqudity #bugfix + + +PR issue: CCIP-4723 + +Solidity Review issue: CCIP-3966 \ No newline at end of file diff --git a/contracts/.changeset/clean-horses-cheat.md b/contracts/.changeset/clean-horses-cheat.md new file mode 100644 index 00000000000..09cce822451 --- /dev/null +++ b/contracts/.changeset/clean-horses-cheat.md @@ -0,0 +1,10 @@ +--- +'@chainlink/contracts': minor +--- + +Update FeeQuoter to support Solana chain families #feature + + +PR issue: CCIP-4687 + +Solidity Review issue: CCIP-3966 \ No newline at end of file diff --git a/contracts/.changeset/cold-geckos-yawn.md b/contracts/.changeset/cold-geckos-yawn.md new file mode 100644 index 00000000000..e7677f1282e --- /dev/null +++ b/contracts/.changeset/cold-geckos-yawn.md @@ -0,0 +1,10 @@ +--- +'@chainlink/contracts': minor +--- + +Remove dead transmission code + + +PR issue: CM-661 + +Solidity Review issue: CM-662 \ No newline at end of file diff --git a/contracts/.changeset/cuddly-roses-vanish.md b/contracts/.changeset/cuddly-roses-vanish.md new file mode 100644 index 00000000000..29282bab46b --- /dev/null +++ b/contracts/.changeset/cuddly-roses-vanish.md @@ -0,0 +1,10 @@ +--- +'@chainlink/contracts': patch +--- + +#internal Generate gethwrappers through Foundry instead of solc-select via python + + +PR issue: CCIP-4737 + +Solidity Review issue: CCIP-3966 \ No newline at end of file diff --git a/contracts/.changeset/early-cups-relax.md b/contracts/.changeset/early-cups-relax.md new file mode 100644 index 00000000000..1ec6aaba0b7 --- /dev/null +++ b/contracts/.changeset/early-cups-relax.md @@ -0,0 +1,9 @@ +--- +'@chainlink/contracts': minor +--- + +#internal Account for tokenTransferBytesOverhead in exec cost + +PR issue: CCIP-4646 + +Solidity Review issue: CCIP-3966 \ No newline at end of file diff --git a/contracts/.changeset/eighty-cycles-film.md b/contracts/.changeset/eighty-cycles-film.md new file mode 100644 index 00000000000..6cd56afa80a --- /dev/null +++ b/contracts/.changeset/eighty-cycles-film.md @@ -0,0 +1,10 @@ +--- +'@chainlink/contracts': patch +--- + +remove legacy curse check from RMNRemote isCursed() method #bugfix + + +PR issue: CCIP-4476 + +Solidity Review issue: CCIP-3966 \ No newline at end of file diff --git a/contracts/.changeset/little-frogs-roll.md b/contracts/.changeset/little-frogs-roll.md new file mode 100644 index 00000000000..f8883bf7f42 --- /dev/null +++ b/contracts/.changeset/little-frogs-roll.md @@ -0,0 +1,10 @@ +--- +'@chainlink/contracts': patch +--- + +#internal add EIP-7623 support + + +PR issue: CCIP-4761 + +Solidity Review issue: CCIP-3966 \ No newline at end of file diff --git a/contracts/.changeset/new-elephants-behave.md b/contracts/.changeset/new-elephants-behave.md new file mode 100644 index 00000000000..29f3c248afc --- /dev/null +++ b/contracts/.changeset/new-elephants-behave.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +fix test naming diff --git a/contracts/.changeset/ninety-pianos-approve.md b/contracts/.changeset/ninety-pianos-approve.md new file mode 100644 index 00000000000..d19823ceb6c --- /dev/null +++ b/contracts/.changeset/ninety-pianos-approve.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +Address misc fixes for workflow registry contract diff --git a/contracts/.changeset/poor-turtles-give.md b/contracts/.changeset/poor-turtles-give.md new file mode 100644 index 00000000000..7776bdd195e --- /dev/null +++ b/contracts/.changeset/poor-turtles-give.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +DEVSVCS-958: fix automation v2.3 batching bug #bugfix diff --git a/contracts/.changeset/purple-spies-draw.md b/contracts/.changeset/purple-spies-draw.md new file mode 100644 index 00000000000..ada0d279657 --- /dev/null +++ b/contracts/.changeset/purple-spies-draw.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': minor +--- + +Added new Data Streams contract version v0.5 diff --git a/contracts/.changeset/stale-dots-destroy.md b/contracts/.changeset/stale-dots-destroy.md new file mode 100644 index 00000000000..98cea8292e0 --- /dev/null +++ b/contracts/.changeset/stale-dots-destroy.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +replace f with fObserve in RMNHome and RMNRemote and update all tests CCIP-4058 diff --git a/contracts/.changeset/tame-cycles-ring.md b/contracts/.changeset/tame-cycles-ring.md new file mode 100644 index 00000000000..31fb56ce133 --- /dev/null +++ b/contracts/.changeset/tame-cycles-ring.md @@ -0,0 +1,10 @@ +--- +'@chainlink/contracts': patch +--- + +enable via-ir in CCIP compilation + + +PR issue: CCIP-4656 + +Solidity Review issue: CCIP-3966 \ No newline at end of file diff --git a/contracts/.changeset/twelve-pianos-chew.md b/contracts/.changeset/twelve-pianos-chew.md new file mode 100644 index 00000000000..9aa4fa8f2b2 --- /dev/null +++ b/contracts/.changeset/twelve-pianos-chew.md @@ -0,0 +1,10 @@ +--- +'@chainlink/contracts': minor +--- + +#internal Fix gas estimation by adding a reverting clause + +PR issue: CCIP-4223 + + +Solidity Review issue: CCIP-3966 \ No newline at end of file diff --git a/contracts/.changeset/violet-lamps-pump.md b/contracts/.changeset/violet-lamps-pump.md new file mode 100644 index 00000000000..4b180df24cd --- /dev/null +++ b/contracts/.changeset/violet-lamps-pump.md @@ -0,0 +1,10 @@ +--- +'@chainlink/contracts': patch +--- + +Create a new version of the ERC165Checker library which checks for sufficient gas before making an external call to prevent message delivery issues. #bugfix + + +PR issue: CCIP-4659 + +Solidity Review issue: CCIP-3966 \ No newline at end of file diff --git a/contracts/.solhintignore-test b/contracts/.solhintignore-test index acaca4fe1e4..137ba9998c7 100644 --- a/contracts/.solhintignore-test +++ b/contracts/.solhintignore-test @@ -4,7 +4,6 @@ ./src/v0.8/tests ./src/v0.8/llo-feeds/ ./src/v0.8/automation/ -./src/v0.8/transmission/ ./src/v0.8/l2ep/ ./src/v0.8/shared/ ./src/v0.8/operatorforwarder/ diff --git a/contracts/GNUmakefile b/contracts/GNUmakefile index 673198bb1e2..0844b6eb5bc 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 = ccip functions keystone l2ep liquiditymanager llo-feeds operatorforwarder shared transmission workflow +ALL_FOUNDRY_PRODUCTS = ccip functions keystone l2ep liquiditymanager llo-feeds operatorforwarder shared workflow # To make a snapshot for a specific product, either set the `FOUNDRY_PROFILE` env var # or call the target with `FOUNDRY_PROFILE=product` @@ -39,11 +39,11 @@ abigen: ## Build & install abigen. .PHONY: mockery mockery: $(mockery) ## Install mockery. - go install github.com/vektra/mockery/v2@v2.43.2 + go install github.com/vektra/mockery/v2@v2.50.0 .PHONY: foundry foundry: ## Install foundry. - foundryup --version nightly-aa69ed1e46dd61fbf9d73399396a4db4dd527431 + foundryup --install v0.3.0 .PHONY: foundry-refresh foundry-refresh: foundry diff --git a/contracts/STYLE_GUIDE.md b/contracts/STYLE_GUIDE.md index f1faab09644..1fbdc061f23 100644 --- a/contracts/STYLE_GUIDE.md +++ b/contracts/STYLE_GUIDE.md @@ -265,9 +265,6 @@ All contracts will expose a `typeAndVersion` constant. The string has the following format: `-` with the `-dev` part only being applicable to contracts that have not been fully released. Try to fit it into 32 bytes to keep the impact on contract sizes minimal. -Note that `ITypeAndVersion` should be used, not `TypeAndVersionInterface`. - - diff --git a/contracts/foundry.toml b/contracts/foundry.toml index 45272ad3f17..6c7c41a2d5b 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -22,12 +22,23 @@ multiline_func_header = "params_first" sort_imports = true single_line_statement_blocks = "preserve" +# This profile should be used for testing CCIP locally and in CI. [profile.ccip] -solc_version = '0.8.24' +solc_version = '0.8.26' src = 'src/v0.8/ccip' test = 'src/v0.8/ccip/test' +evm_version = 'paris' optimizer_runs = 500 + +# This profile should be used prior to any release to ensure the tests are passing with via-ir enabled. Enabling via-ir +# locally or in CI will slow down the compilation process, so it is not recommended to use it for everyday development. +[profile.ccip-compile] +solc_version = '0.8.26' +src = 'src/v0.8/ccip' +test = 'src/v0.8/ccip/test' evm_version = 'paris' +optimizer_runs = 80_000 +via_ir = true [profile.functions] solc_version = '0.8.19' @@ -85,12 +96,6 @@ solc_version = '0.8.19' src = 'src/v0.8/operatorforwarder' test = 'src/v0.8/operatorforwarder/test' -[profile.transmission] -optimizer_runs = 1_000_000 -solc_version = '0.8.19' -src = 'src/v0.8/transmission' -test = 'src/v0.8/transmission/test' - [profile.workflow] optimizer_runs = 1_000_000 solc_version = '0.8.24' @@ -104,5 +109,6 @@ optimizer_runs = 1_000_000 src = 'src/v0.8/shared' test = 'src/v0.8/shared/test' solc_version = '0.8.24' +evm_version = 'paris' # See more config options https://github.com/foundry-rs/foundry/tree/master/config diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index d655e886262..a6cb9fe68fc 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -1,757 +1,436 @@ -ARMProxy_constructor:test_Constructor() (gas: 302231) -ARMProxy_isCursed:test_IsCursed_Success() (gas: 47209) -ARMProxy_isCursed:test_call_ARMCallEmptyContract_Revert() (gas: 19412) -ARMProxy_isCursed:test_isCursed_RevertReasonForwarded_Revert() (gas: 45210) -ARMProxy_setARM:test_SetARM() (gas: 16599) -ARMProxy_setARM:test_SetARMzero() (gas: 11275) -BurnFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 27346) -BurnFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 54878) -BurnFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 244452) -BurnFromMintTokenPool_lockOrBurn:test_setup_Success() (gas: 24210) -BurnMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 27486) -BurnMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 54878) -BurnMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 242352) -BurnMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 17852) -BurnMintTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 27287) -BurnMintTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 54624) -BurnMintTokenPool_releaseOrMint:test_PoolMint_Success() (gas: 109426) -BurnMintWithLockReleaseFlagTokenPool_lockOrBurn:test_LockOrBurn_CorrectReturnData_Success() (gas: 242805) -BurnWithFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 27346) -BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 54878) -BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 244496) -BurnWithFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 24223) -CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2077779) -CCIPHome__validateConfig:test__validateConfigLessTransmittersThanSigners_Success() (gas: 332619) -CCIPHome__validateConfig:test__validateConfigSmallerFChain_Success() (gas: 458568) -CCIPHome__validateConfig:test__validateConfig_ABIEncodedAddress_OfframpAddressCannotBeZero_Reverts() (gas: 289191) -CCIPHome__validateConfig:test__validateConfig_ABIEncodedAddress_RMNHomeAddressCannotBeZero_Reverts() (gas: 289486) -CCIPHome__validateConfig:test__validateConfig_ChainSelectorNotFound_Reverts() (gas: 292216) -CCIPHome__validateConfig:test__validateConfig_ChainSelectorNotSet_Reverts() (gas: 288824) -CCIPHome__validateConfig:test__validateConfig_FChainTooHigh_Reverts() (gas: 336363) -CCIPHome__validateConfig:test__validateConfig_FMustBePositive_Reverts() (gas: 290590) -CCIPHome__validateConfig:test__validateConfig_FTooHigh_Reverts() (gas: 290055) -CCIPHome__validateConfig:test__validateConfig_NotEnoughTransmittersEmptyAddresses_Reverts() (gas: 308646) -CCIPHome__validateConfig:test__validateConfig_NotEnoughTransmitters_Reverts() (gas: 1191231) -CCIPHome__validateConfig:test__validateConfig_OfframpAddressCannotBeZero_Reverts() (gas: 288918) -CCIPHome__validateConfig:test__validateConfig_RMNHomeAddressCannotBeZero_Reverts() (gas: 289112) -CCIPHome__validateConfig:test__validateConfig_Success() (gas: 299797) -CCIPHome__validateConfig:test__validateConfig_TooManySigners_Reverts() (gas: 773105) -CCIPHome__validateConfig:test__validateConfig_ZeroP2PId_Reverts() (gas: 293455) -CCIPHome__validateConfig:test__validateConfig_ZeroSignerKey_Reverts() (gas: 293503) -CCIPHome_applyChainConfigUpdates:test__applyChainConfigUpdates_FChainNotPositive_Reverts() (gas: 187822) -CCIPHome_applyChainConfigUpdates:test_applyChainConfigUpdates_addChainConfigs_Success() (gas: 350051) -CCIPHome_applyChainConfigUpdates:test_applyChainConfigUpdates_nodeNotInRegistry_Reverts() (gas: 18089) -CCIPHome_applyChainConfigUpdates:test_applyChainConfigUpdates_removeChainConfigs_Success() (gas: 282212) -CCIPHome_applyChainConfigUpdates:test_applyChainConfigUpdates_selectorNotFound_Reverts() (gas: 14976) -CCIPHome_applyChainConfigUpdates:test_getPaginatedCCIPHomes_Success() (gas: 373475) -CCIPHome_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_DONIdMismatch_reverts() (gas: 38098) -CCIPHome_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_InnerCallReverts_reverts() (gas: 11783) -CCIPHome_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_InvalidSelector_reverts() (gas: 11015) -CCIPHome_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_OnlyCapabilitiesRegistryCanCall_reverts() (gas: 37072) -CCIPHome_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_success() (gas: 1455674) -CCIPHome_constructor:test_constructor_CapabilitiesRegistryAddressZero_reverts() (gas: 63865) -CCIPHome_constructor:test_constructor_success() (gas: 3531036) -CCIPHome_getAllConfigs:test_getAllConfigs_success() (gas: 2773023) -CCIPHome_getCapabilityConfiguration:test_getCapabilityConfiguration_success() (gas: 9116) -CCIPHome_getConfigDigests:test_getConfigDigests_success() (gas: 2547513) -CCIPHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive_CanOnlySelfCall_reverts() (gas: 9110) -CCIPHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive_ConfigDigestMismatch_reverts() (gas: 23074) -CCIPHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive_NoOpStateTransitionNotAllowed_reverts() (gas: 8840) -CCIPHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive_multiplePlugins_success() (gas: 5113754) -CCIPHome_revokeCandidate:test_revokeCandidate_CanOnlySelfCall_reverts() (gas: 9024) -CCIPHome_revokeCandidate:test_revokeCandidate_ConfigDigestMismatch_reverts() (gas: 19084) -CCIPHome_revokeCandidate:test_revokeCandidate_RevokingZeroDigestNotAllowed_reverts() (gas: 8773) -CCIPHome_revokeCandidate:test_revokeCandidate_success() (gas: 30676) -CCIPHome_setCandidate:test_setCandidate_CanOnlySelfCall_reverts() (gas: 29383) -CCIPHome_setCandidate:test_setCandidate_ConfigDigestMismatch_reverts() (gas: 1395154) -CCIPHome_setCandidate:test_setCandidate_success() (gas: 1365439) -CCIPHome_supportsInterface:test_supportsInterface_success() (gas: 9885) -DefensiveExampleTest:test_HappyPath_Success() (gas: 200540) -DefensiveExampleTest:test_Recovery() (gas: 425013) -E2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1512391) -EtherSenderReceiverTest_ccipReceive:test_ccipReceive_fallbackToWethTransfer() (gas: 96980) -EtherSenderReceiverTest_ccipReceive:test_ccipReceive_happyPath() (gas: 49812) -EtherSenderReceiverTest_ccipReceive:test_ccipReceive_wrongToken() (gas: 17479) -EtherSenderReceiverTest_ccipReceive:test_ccipReceive_wrongTokenAmount() (gas: 15753) -EtherSenderReceiverTest_ccipSend:test_ccipSend_reverts_insufficientFee_feeToken() (gas: 99953) -EtherSenderReceiverTest_ccipSend:test_ccipSend_reverts_insufficientFee_native() (gas: 76182) -EtherSenderReceiverTest_ccipSend:test_ccipSend_reverts_insufficientFee_weth() (gas: 99974) -EtherSenderReceiverTest_ccipSend:test_ccipSend_success_feeToken() (gas: 145007) -EtherSenderReceiverTest_ccipSend:test_ccipSend_success_native() (gas: 80439) -EtherSenderReceiverTest_ccipSend:test_ccipSend_success_nativeExcess() (gas: 80604) -EtherSenderReceiverTest_ccipSend:test_ccipSend_success_weth() (gas: 96107) -EtherSenderReceiverTest_constructor:test_constructor() (gas: 17575) -EtherSenderReceiverTest_getFee:test_getFee() (gas: 27456) -EtherSenderReceiverTest_validateFeeToken:test_validateFeeToken_reverts_feeToken_tokenAmountNotEqualToMsgValue() (gas: 20355) -EtherSenderReceiverTest_validateFeeToken:test_validateFeeToken_valid_feeToken() (gas: 16682) -EtherSenderReceiverTest_validateFeeToken:test_validateFeeToken_valid_native() (gas: 16615) -EtherSenderReceiverTest_validatedMessage:test_validatedMessage_dataOverwrittenToMsgSender() (gas: 25456) -EtherSenderReceiverTest_validatedMessage:test_validatedMessage_emptyDataOverwrittenToMsgSender() (gas: 25373) -EtherSenderReceiverTest_validatedMessage:test_validatedMessage_invalidTokenAmounts() (gas: 17969) -EtherSenderReceiverTest_validatedMessage:test_validatedMessage_tokenOverwrittenToWeth() (gas: 25328) -EtherSenderReceiverTest_validatedMessage:test_validatedMessage_validMessage_extraArgs() (gas: 26348) -FactoryBurnMintERC20_approve:test_Approve_Success() (gas: 55819) -FactoryBurnMintERC20_approve:test_InvalidAddress_Reverts() (gas: 10703) -FactoryBurnMintERC20_burn:test_BasicBurn_Success() (gas: 172464) -FactoryBurnMintERC20_burn:test_BurnFromZeroAddress_Reverts() (gas: 47338) -FactoryBurnMintERC20_burn:test_ExceedsBalance_Reverts() (gas: 22005) -FactoryBurnMintERC20_burn:test_SenderNotBurner_Reverts() (gas: 13520) -FactoryBurnMintERC20_burnFrom:test_BurnFrom_Success() (gas: 58274) -FactoryBurnMintERC20_burnFrom:test_ExceedsBalance_Reverts() (gas: 36191) -FactoryBurnMintERC20_burnFrom:test_InsufficientAllowance_Reverts() (gas: 22113) -FactoryBurnMintERC20_burnFrom:test_SenderNotBurner_Reverts() (gas: 13487) -FactoryBurnMintERC20_burnFromAlias:test_BurnFrom_Success() (gas: 58248) -FactoryBurnMintERC20_burnFromAlias:test_ExceedsBalance_Reverts() (gas: 36155) -FactoryBurnMintERC20_burnFromAlias:test_InsufficientAllowance_Reverts() (gas: 22068) -FactoryBurnMintERC20_burnFromAlias:test_SenderNotBurner_Reverts() (gas: 13442) -FactoryBurnMintERC20_constructor:test_Constructor_Success() (gas: 1450638) -FactoryBurnMintERC20_decreaseApproval:test_DecreaseApproval_Success() (gas: 31419) -FactoryBurnMintERC20_getCCIPAdmin:test_getCCIPAdmin_Success() (gas: 12717) -FactoryBurnMintERC20_getCCIPAdmin:test_setCCIPAdmin_Success() (gas: 23874) -FactoryBurnMintERC20_grantMintAndBurnRoles:test_GrantMintAndBurnRoles_Success() (gas: 121194) -FactoryBurnMintERC20_grantRole:test_GrantBurnAccess_Success() (gas: 53403) -FactoryBurnMintERC20_grantRole:test_GrantMany_Success() (gas: 961486) -FactoryBurnMintERC20_grantRole:test_GrantMintAccess_Success() (gas: 94165) -FactoryBurnMintERC20_increaseApproval:test_IncreaseApproval_Success() (gas: 44398) -FactoryBurnMintERC20_mint:test_BasicMint_Success() (gas: 149804) -FactoryBurnMintERC20_mint:test_MaxSupplyExceeded_Reverts() (gas: 50679) -FactoryBurnMintERC20_mint:test_SenderNotMinter_Reverts() (gas: 11405) -FactoryBurnMintERC20_supportsInterface:test_SupportsInterface_Success() (gas: 11538) -FactoryBurnMintERC20_transfer:test_InvalidAddress_Reverts() (gas: 10701) -FactoryBurnMintERC20_transfer:test_Transfer_Success() (gas: 42482) -FeeQuoter_applyDestChainConfigUpdates:test_InvalidChainFamilySelector_Revert() (gas: 16846) -FeeQuoter_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16759) -FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() (gas: 16813) -FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() (gas: 41239) -FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroInput_Success() (gas: 12563) -FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_Success() (gas: 140709) -FeeQuoter_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates_Success() (gas: 162719) -FeeQuoter_applyFeeTokensUpdates:test_OnlyCallableByOwner_Revert() (gas: 12263) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 11476) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() (gas: 54860) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() (gas: 45257) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12368) -FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Success() (gas: 89062) -FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13346) -FeeQuoter_applyTokenTransferFeeConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 17435) -FeeQuoter_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12349) -FeeQuoter_constructor:test_InvalidLinkTokenEqZeroAddress_Revert() (gas: 106632) -FeeQuoter_constructor:test_InvalidMaxFeeJuelsPerMsg_Revert() (gas: 110982) -FeeQuoter_constructor:test_InvalidStalenessThreshold_Revert() (gas: 111057) -FeeQuoter_constructor:test_Setup_Success() (gas: 5011219) -FeeQuoter_convertTokenAmount:test_ConvertTokenAmount_Success() (gas: 68416) -FeeQuoter_convertTokenAmount:test_LinkTokenNotSupported_Revert() (gas: 29300) -FeeQuoter_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 96433) -FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() (gas: 14857) -FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20988) -FeeQuoter_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices_Success() (gas: 73071) -FeeQuoter_getTokenAndGasPrices:test_StaleGasPrice_Revert() (gas: 26476) -FeeQuoter_getTokenAndGasPrices:test_StalenessCheckDisabled_Success() (gas: 112065) -FeeQuoter_getTokenAndGasPrices:test_UnsupportedChain_Revert() (gas: 16184) -FeeQuoter_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 109175) -FeeQuoter_getTokenPrice:test_GetTokenPriceFromFeed_Success() (gas: 68059) -FeeQuoter_getTokenPrice:test_GetTokenPrice_LocalMoreRecent_Success() (gas: 33529) -FeeQuoter_getTokenPrices:test_GetTokenPrices_Success() (gas: 78516) -FeeQuoter_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 37307) -FeeQuoter_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 35086) -FeeQuoter_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 28176) -FeeQuoter_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 96089) -FeeQuoter_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 20615) -FeeQuoter_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 27984) -FeeQuoter_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 28029) -FeeQuoter_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40822) -FeeQuoter_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29736) -FeeQuoter_getValidatedFee:test_DestinationChainNotEnabled_Revert() (gas: 18465) -FeeQuoter_getValidatedFee:test_EmptyMessage_Success() (gas: 83340) -FeeQuoter_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 53570) -FeeQuoter_getValidatedFee:test_HighGasMessage_Success() (gas: 239736) -FeeQuoter_getValidatedFee:test_InvalidEVMAddress_Revert() (gas: 22668) -FeeQuoter_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 29966) -FeeQuoter_getValidatedFee:test_MessageTooLarge_Revert() (gas: 100417) -FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 143246) -FeeQuoter_getValidatedFee:test_NotAFeeToken_Revert() (gas: 21280) -FeeQuoter_getValidatedFee:test_SingleTokenMessage_Success() (gas: 114510) -FeeQuoter_getValidatedFee:test_TooManyTokens_Revert() (gas: 23495) -FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 63909) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 1897852) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 1897810) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 1877929) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 1897584) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 1897788) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 1897600) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() (gas: 65232) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed_Success() (gas: 65112) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPrice_Success() (gas: 58894) -FeeQuoter_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 1897226) -FeeQuoter_getValidatedTokenPrice:test_StaleFeeToken_Success() (gas: 61843) -FeeQuoter_getValidatedTokenPrice:test_TokenNotSupportedFeed_Revert() (gas: 116970) -FeeQuoter_getValidatedTokenPrice:test_TokenNotSupported_Revert() (gas: 14182) -FeeQuoter_getValidatedTokenPrice:test_UnderflowFeedPrice_Revert() (gas: 1895903) -FeeQuoter_onReport:test_OnReport_SkipPriceUpdateWhenStaleUpdateReceived() (gas: 52614) -FeeQuoter_onReport:test_onReport() (gas: 89071) -FeeQuoter_onReport:test_onReport_withKeystoneForwarderContract() (gas: 122700) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsDefault_Success() (gas: 17381) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsEnforceOutOfOrder_Revert() (gas: 21553) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsGasLimitTooHigh_Revert() (gas: 18613) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsInvalidExtraArgsTag_Revert() (gas: 18153) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV1_Success() (gas: 18467) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV2_Success() (gas: 18590) -FeeQuoter_processMessageArgs:test_applyTokensTransferFeeConfigUpdates_InvalidFeeRange_Revert() (gas: 21476) -FeeQuoter_processMessageArgs:test_processMessageArgs_InvalidEVMAddressDestToken_Revert() (gas: 44974) -FeeQuoter_processMessageArgs:test_processMessageArgs_InvalidExtraArgs_Revert() (gas: 20008) -FeeQuoter_processMessageArgs:test_processMessageArgs_MalformedEVMExtraArgs_Revert() (gas: 20405) -FeeQuoter_processMessageArgs:test_processMessageArgs_MessageFeeTooHigh_Revert() (gas: 17976) -FeeQuoter_processMessageArgs:test_processMessageArgs_SourceTokenDataTooLarge_Revert() (gas: 123405) -FeeQuoter_processMessageArgs:test_processMessageArgs_TokenAmountArraysMismatching_Revert() (gas: 42236) -FeeQuoter_processMessageArgs:test_processMessageArgs_WitEVMExtraArgsV2_Success() (gas: 28702) -FeeQuoter_processMessageArgs:test_processMessageArgs_WithConvertedTokenAmount_Success() (gas: 30021) -FeeQuoter_processMessageArgs:test_processMessageArgs_WithCorrectPoolReturnData_Success() (gas: 76515) -FeeQuoter_processMessageArgs:test_processMessageArgs_WithEVMExtraArgsV1_Success() (gas: 28300) -FeeQuoter_processMessageArgs:test_processMessageArgs_WithEmptyEVMExtraArgs_Success() (gas: 26159) -FeeQuoter_processMessageArgs:test_processMessageArgs_WithLinkTokenAmount_Success() (gas: 19595) -FeeQuoter_supportsInterface:test_SupportsInterface_Success() (gas: 13263) -FeeQuoter_updatePrices:test_OnlyCallableByUpdater_Revert() (gas: 12198) -FeeQuoter_updatePrices:test_OnlyGasPrice_Success() (gas: 23872) -FeeQuoter_updatePrices:test_OnlyTokenPrice_Success() (gas: 28648) -FeeQuoter_updatePrices:test_UpdatableByAuthorizedCaller_Success() (gas: 74816) -FeeQuoter_updatePrices:test_UpdateMultiplePrices_Success() (gas: 145691) -FeeQuoter_updateTokenPriceFeeds:test_FeedNotUpdated() (gas: 52443) -FeeQuoter_updateTokenPriceFeeds:test_FeedUnset_Success() (gas: 66423) -FeeQuoter_updateTokenPriceFeeds:test_FeedUpdatedByNonOwner_Revert() (gas: 20124) -FeeQuoter_updateTokenPriceFeeds:test_MultipleFeedUpdate_Success() (gas: 93563) -FeeQuoter_updateTokenPriceFeeds:test_SingleFeedUpdate_Success() (gas: 53142) -FeeQuoter_updateTokenPriceFeeds:test_ZeroFeeds_Success() (gas: 12431) -FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressEncodePacked_Revert() (gas: 10710) -FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressPrecompiles_Revert() (gas: 4057945) -FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddress_Revert() (gas: 10906) -FeeQuoter_validateDestFamilyAddress:test_ValidEVMAddress_Success() (gas: 6841) -FeeQuoter_validateDestFamilyAddress:test_ValidNonEVMAddress_Success() (gas: 6567) -HybridLockReleaseUSDCTokenPool_TransferLiquidity:test_cannotTransferLiquidityDuringPendingMigration_Revert() (gas: 176859) -HybridLockReleaseUSDCTokenPool_TransferLiquidity:test_transferLiquidity_Success() (gas: 167004) -HybridLockReleaseUSDCTokenPool_lockOrBurn:test_PrimaryMechanism_Success() (gas: 135878) -HybridLockReleaseUSDCTokenPool_lockOrBurn:test_WhileMigrationPause_Revert() (gas: 109718) -HybridLockReleaseUSDCTokenPool_lockOrBurn:test_onLockReleaseMechanism_Success() (gas: 146937) -HybridLockReleaseUSDCTokenPool_lockOrBurn:test_onLockReleaseMechanism_thenSwitchToPrimary_Success() (gas: 209160) -HybridLockReleaseUSDCTokenPool_releaseOrMint:test_OnLockReleaseMechanism_Success() (gas: 213127) -HybridLockReleaseUSDCTokenPool_releaseOrMint:test_WhileMigrationPause_Revert() (gas: 109646) -HybridLockReleaseUSDCTokenPool_releaseOrMint:test_incomingMessageWithPrimaryMechanism() (gas: 265910) -LockReleaseTokenPool_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3209936) -LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 29734) -LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Success() (gas: 80625) -LockReleaseTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 59227) -LockReleaseTokenPool_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3206264) -LockReleaseTokenPool_provideLiquidity:test_Unauthorized_Revert() (gas: 11511) -LockReleaseTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 74100) -LockReleaseTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 54745) -LockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_Success() (gas: 223256) -LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Revert() (gas: 11003) -LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Success() (gas: 18182) -LockReleaseTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 10250) -LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_Success() (gas: 83328) -LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_transferTooMuch_Revert() (gas: 56101) -LockReleaseTokenPool_withdrawalLiquidity:test_InsufficientLiquidity_Revert() (gas: 60188) -LockReleaseTokenPool_withdrawalLiquidity:test_Unauthorized_Revert() (gas: 11464) +BurnFromMintTokenPool_lockOrBurn:test_PoolBurn() (gas: 238950) +BurnFromMintTokenPool_lockOrBurn:test_setup() (gas: 24178) +BurnMintTokenPool_lockOrBurn:test_PoolBurn() (gas: 236872) +BurnMintTokenPool_lockOrBurn:test_Setup() (gas: 17819) +BurnMintTokenPool_releaseOrMint:test_PoolMint() (gas: 102527) +BurnMintWithLockReleaseFlagTokenPool_lockOrBurn:test_LockOrBurn_CorrectReturnData() (gas: 237292) +BurnToAddressMintTokenPool_lockOrBurn:test_LockOrBurn() (gas: 257956) +BurnToAddressMintTokenPool_releaseOrMint:test_releaseOrMint() (gas: 126048) +BurnToAddressMintTokenPool_setOutstandingokens:test_setOutstandingTokens() (gas: 37793) +BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn() (gas: 239012) +BurnWithFromMintTokenPool_lockOrBurn:test_Setup() (gas: 24169) +CCIPClientExample_sanity:test_ImmutableExamples() (gas: 2078596) +CCIPHome__validateConfig:test__validateConfig() (gas: 300016) +CCIPHome__validateConfig:test__validateConfigLessTransmittersThanSigners() (gas: 332965) +CCIPHome__validateConfig:test__validateConfigSmallerFChain() (gas: 459322) +CCIPHome_applyChainConfigUpdates:test_applyChainConfigUpdates_addChainConfigs() (gas: 350127) +CCIPHome_applyChainConfigUpdates:test_applyChainConfigUpdates_removeChainConfigs() (gas: 282241) +CCIPHome_applyChainConfigUpdates:test_getPaginatedCCIPHomes() (gas: 373692) +CCIPHome_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet() (gas: 1455733) +CCIPHome_constructor:test_constructor() (gas: 3547489) +CCIPHome_getAllConfigs:test_getAllConfigs() (gas: 2772793) +CCIPHome_getCapabilityConfiguration:test_getCapabilityConfiguration() (gas: 9073) +CCIPHome_getConfigDigests:test_getConfigDigests() (gas: 2547587) +CCIPHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive_multiplePlugins() (gas: 5113791) +CCIPHome_revokeCandidate:test_revokeCandidate() (gas: 30647) +CCIPHome_setCandidate:test_setCandidate() (gas: 1365392) +CCIPHome_supportsInterface:test_supportsInterface() (gas: 9885) +DefensiveExampleTest:test_HappyPath() (gas: 200535) +DefensiveExampleTest:test_Recovery() (gas: 424996) +E2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1494287) +ERC165CheckerReverting_supportsInterfaceReverting:test__supportsInterfaceReverting() (gas: 10445) +EtherSenderReceiverTest_ccipReceive:test_ccipReceive_fallbackToWethTransfer() (gas: 96964) +EtherSenderReceiverTest_ccipReceive:test_ccipReceive_happyPath() (gas: 49797) +EtherSenderReceiverTest_ccipReceive:test_ccipReceive_wrongToken() (gas: 17460) +EtherSenderReceiverTest_ccipReceive:test_ccipReceive_wrongTokenAmount() (gas: 15748) +EtherSenderReceiverTest_ccipSend:test_ccipSend_feeToken() (gas: 145087) +EtherSenderReceiverTest_ccipSend:test_ccipSend_native() (gas: 80451) +EtherSenderReceiverTest_ccipSend:test_ccipSend_nativeExcess() (gas: 80616) +EtherSenderReceiverTest_ccipSend:test_ccipSend_weth() (gas: 96167) +EtherSenderReceiverTest_constructor:test_constructor() (gas: 17582) +EtherSenderReceiverTest_getFee:test_getFee() (gas: 27482) +EtherSenderReceiverTest_validateFeeToken:test_validateFeeToken_valid_feeToken() (gas: 16700) +EtherSenderReceiverTest_validateFeeToken:test_validateFeeToken_valid_native() (gas: 16611) +EtherSenderReceiverTest_validatedMessage:test_validatedMessage_dataOverwrittenToMsgSender() (gas: 25455) +EtherSenderReceiverTest_validatedMessage:test_validatedMessage_emptyDataOverwrittenToMsgSender() (gas: 25372) +EtherSenderReceiverTest_validatedMessage:test_validatedMessage_invalidTokenAmounts() (gas: 17955) +EtherSenderReceiverTest_validatedMessage:test_validatedMessage_tokenOverwrittenToWeth() (gas: 25327) +EtherSenderReceiverTest_validatedMessage:test_validatedMessage_validMessage_extraArgs() (gas: 26347) +FactoryBurnMintERC20_approve:test_Approve() (gas: 55786) +FactoryBurnMintERC20_burn:test_BasicBurn() (gas: 172448) +FactoryBurnMintERC20_burnFrom:test_BurnFrom() (gas: 58290) +FactoryBurnMintERC20_burnFromAlias:test_BurnFrom() (gas: 58264) +FactoryBurnMintERC20_constructor:test_Constructor() (gas: 1450297) +FactoryBurnMintERC20_decreaseApproval:test_DecreaseApproval() (gas: 31420) +FactoryBurnMintERC20_getCCIPAdmin:test_getCCIPAdmin() (gas: 12740) +FactoryBurnMintERC20_getCCIPAdmin:test_setCCIPAdmin() (gas: 23852) +FactoryBurnMintERC20_grantMintAndBurnRoles:test_GrantMintAndBurnRoles() (gas: 121216) +FactoryBurnMintERC20_grantRole:test_GrantBurnAccess() (gas: 53386) +FactoryBurnMintERC20_grantRole:test_GrantMany() (gas: 961708) +FactoryBurnMintERC20_grantRole:test_GrantMintAccess() (gas: 94181) +FactoryBurnMintERC20_increaseApproval:test_IncreaseApproval() (gas: 44421) +FactoryBurnMintERC20_mint:test_BasicMint() (gas: 149826) +FactoryBurnMintERC20_supportsInterface:test_SupportsInterface() (gas: 11539) +FactoryBurnMintERC20_transfer:test_Transfer() (gas: 42505) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates() (gas: 149063) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroInput() (gas: 12493) +FeeQuoter_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates() (gas: 162480) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens() (gas: 54881) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken() (gas: 45364) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12468) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig() (gas: 88604) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13196) +FeeQuoter_constructor:test_Setup() (gas: 5429233) +FeeQuoter_convertTokenAmount:test_ConvertTokenAmount() (gas: 68417) +FeeQuoter_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost() (gas: 98884) +FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost() (gas: 21505) +FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector() (gas: 14904) +FeeQuoter_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices() (gas: 73123) +FeeQuoter_getTokenAndGasPrices:test_StalenessCheckDisabled() (gas: 113576) +FeeQuoter_getTokenAndGasPrices:test_ZeroGasPrice() (gas: 110663) +FeeQuoter_getTokenPrice:test_GetTokenPriceFromFeed() (gas: 68158) +FeeQuoter_getTokenPrice:test_GetTokenPrice_LocalMoreRecent() (gas: 33546) +FeeQuoter_getTokenPrices:test_GetTokenPrices() (gas: 78534) +FeeQuoter_getTokenTransferCost:test_CustomTokenBpsFee() (gas: 34616) +FeeQuoter_getTokenTransferCost:test_FeeTokenBpsFee() (gas: 32395) +FeeQuoter_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas() (gas: 25465) +FeeQuoter_getTokenTransferCost:test_MixedTokenTransferFee() (gas: 91728) +FeeQuoter_getTokenTransferCost:test_NoTokenTransferChargesZeroFee() (gas: 17904) +FeeQuoter_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas() (gas: 25272) +FeeQuoter_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas() (gas: 25295) +FeeQuoter_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee() (gas: 37853) +FeeQuoter_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults() (gas: 26989) +FeeQuoter_getValidatedFee:test_EmptyMessage() (gas: 85158) +FeeQuoter_getValidatedFee:test_HighGasMessage() (gas: 243094) +FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer() (gas: 143736) +FeeQuoter_getValidatedFee:test_SingleTokenMessage() (gas: 115240) +FeeQuoter_getValidatedFee:test_SolChainFamilySelector() (gas: 60999) +FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier() (gas: 66233) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPrice() (gas: 58905) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed() (gas: 65115) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals() (gas: 1897724) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals() (gas: 1897766) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals() (gas: 1877822) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals() (gas: 1897564) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals() (gas: 1897700) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value() (gas: 1897534) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod() (gas: 65233) +FeeQuoter_getValidatedTokenPrice:test_StaleFeeToken() (gas: 61854) +FeeQuoter_onReport:test_OnReport_SkipPriceUpdateWhenStaleUpdateReceived() (gas: 52565) +FeeQuoter_onReport:test_onReport() (gas: 88942) +FeeQuoter_onReport:test_onReport_withKeystoneForwarderContract() (gas: 122570) +FeeQuoter_parseSVMExtraArgsFromBytes:test_SVMExtraArgsV1() (gas: 23233) +FeeQuoter_parseSVMExtraArgsFromBytes:test_SVMExtraArgsV1TagSelector() (gas: 3157) +FeeQuoter_processChainFamilySelector:test_processChainFamilySelectorEVM() (gas: 19457) +FeeQuoter_processChainFamilySelector:test_processChainFamilySelectorSVM_NoTokenTransfer() (gas: 22644) +FeeQuoter_processChainFamilySelector:test_processChainFamilySelectorSVM_WithTokenTransfer() (gas: 22633) +FeeQuoter_processMessageArgs:test_processMessageArgs_WitEVMExtraArgsV2() (gas: 29003) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithConvertedTokenAmount() (gas: 33038) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithCorrectPoolReturnData() (gas: 77567) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithEVMExtraArgsV1() (gas: 28634) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithEmptyEVMExtraArgs() (gas: 26494) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithLinkTokenAmount() (gas: 22700) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithSVMExtraArgsV1() (gas: 63415) +FeeQuoter_resolveGasLimitForDestination:test_EVMExtraArgsDefault() (gas: 17113) +FeeQuoter_resolveGasLimitForDestination:test_EVMExtraArgsV1() (gas: 16180) +FeeQuoter_resolveGasLimitForDestination:test_EVMExtraArgsV1TagSelector() (gas: 3169) +FeeQuoter_resolveGasLimitForDestination:test_EVMExtraArgsV2() (gas: 16306) +FeeQuoter_resolveGasLimitForDestination:test_EVMExtraArgsV2TagSelector() (gas: 3168) +FeeQuoter_supportsInterface:test_SupportsInterface() (gas: 13264) +FeeQuoter_updatePrices:test_OnlyGasPrice() (gas: 24001) +FeeQuoter_updatePrices:test_OnlyTokenPrice() (gas: 28739) +FeeQuoter_updatePrices:test_UpdatableByAuthorizedCaller() (gas: 74733) +FeeQuoter_updatePrices:test_UpdateMultiplePrices() (gas: 146225) +FeeQuoter_updateTokenPriceFeeds:test_FeedNotUpdated() (gas: 52495) +FeeQuoter_updateTokenPriceFeeds:test_FeedUnset() (gas: 66418) +FeeQuoter_updateTokenPriceFeeds:test_MultipleFeedUpdate() (gas: 93559) +FeeQuoter_updateTokenPriceFeeds:test_SingleFeedUpdate() (gas: 53171) +FeeQuoter_updateTokenPriceFeeds:test_ZeroFeeds() (gas: 12471) +FeeQuoter_validateDestFamilyAddress:test_ValidEVMAddress() (gas: 6796) +FeeQuoter_validateDestFamilyAddress:test_ValidSVMAddress() (gas: 6657) +HybridLockReleaseUSDCTokenPool_lockOrBurn:test_PrimaryMechanism() (gas: 130339) +HybridLockReleaseUSDCTokenPool_lockOrBurn:test_onLockReleaseMechanism() (gas: 140169) +HybridLockReleaseUSDCTokenPool_lockOrBurn:test_onLockReleaseMechanism_thenSwitchToPrimary() (gas: 202967) +HybridLockReleaseUSDCTokenPool_releaseOrMint:test_OnLockReleaseMechanism() (gas: 206350) +HybridLockReleaseUSDCTokenPool_releaseOrMint:test_incomingMessageWithPrimaryMechanism() (gas: 260423) +LockReleaseTokenPool_canAcceptLiquidity:test_CanAcceptLiquidity() (gas: 3222607) +LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList() (gas: 72828) +LockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint() (gas: 217898) +LockReleaseTokenPool_setRebalancer:test_SetRebalancer() (gas: 18183) +LockReleaseTokenPool_supportsInterface:test_SupportsInterface() (gas: 10251) +LockReleaseTokenPool_transferLiquidity:test_transferLiquidity() (gas: 83263) MerkleMultiProofTest:test_CVE_2023_34459() (gas: 5456) -MerkleMultiProofTest:test_EmptyLeaf_Revert() (gas: 3563) -MerkleMultiProofTest:test_MerkleRoot256() (gas: 394891) -MerkleMultiProofTest:test_MerkleRootSingleLeaf_Success() (gas: 3661) +MerkleMultiProofTest:test_MerkleRoot256() (gas: 396915) +MerkleMultiProofTest:test_MerkleRootSingleLeaf() (gas: 3684) MerkleMultiProofTest:test_SpecSync_gas() (gas: 34152) -MockRouterTest:test_ccipSendWithEVMExtraArgsV1_Success() (gas: 110095) -MockRouterTest:test_ccipSendWithEVMExtraArgsV2_Success() (gas: 132614) -MockRouterTest:test_ccipSendWithInsufficientNativeTokens_Revert() (gas: 34059) -MockRouterTest:test_ccipSendWithInvalidEVMExtraArgs_Revert() (gas: 106706) -MockRouterTest:test_ccipSendWithInvalidMsgValue_Revert() (gas: 60864) -MockRouterTest:test_ccipSendWithLinkFeeTokenAndValidMsgValue_Success() (gas: 126741) -MockRouterTest:test_ccipSendWithLinkFeeTokenbutInsufficientAllowance_Revert() (gas: 63499) -MockRouterTest:test_ccipSendWithSufficientNativeFeeTokens_Success() (gas: 44070) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ConfigRateMoreThanCapacity_Revert() (gas: 16554) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ConfigRateZero_Revert() (gas: 16634) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_DiableConfigCapacityNonZero_Revert() (gas: 16585) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_DisableConfigRateNonZero_Revert() (gas: 16571) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigsBothLanes_Success() (gas: 133973) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigs_Success() (gas: 316663) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_OnlyCallableByOwner_Revert() (gas: 17490) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfigOutbound_Success() (gas: 76620) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfig_Success() (gas: 76603) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfigWithNoDifference_Success() (gas: 38739) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfig_Success() (gas: 53937) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroChainSelector_Revert() (gas: 17154) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroConfigs_Success() (gas: 12481) -MultiAggregateRateLimiter_constructor:test_ConstructorNoAuthorizedCallers_Success() (gas: 1977286) -MultiAggregateRateLimiter_constructor:test_Constructor_Success() (gas: 2093583) -MultiAggregateRateLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 30794) -MultiAggregateRateLimiter_getTokenBucket:test_Refill_Success() (gas: 48169) -MultiAggregateRateLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15907) -MultiAggregateRateLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 17624) -MultiAggregateRateLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21652) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 14636) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 210637) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 58473) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 17791) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitDisabled_Success() (gas: 45202) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitExceeded_Revert() (gas: 46514) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitReset_Success() (gas: 76999) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 309039) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokens_Success() (gas: 50680) -MultiAggregateRateLimiter_onOutboundMessage:test_RateLimitValueDifferentLanes_Success() (gas: 51331) -MultiAggregateRateLimiter_onOutboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 19375) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 15914) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 210357) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 60266) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitDisabled_Success() (gas: 47025) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitExceeded_Revert() (gas: 48305) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() (gas: 78006) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 308985) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokens_Success() (gas: 52450) -MultiAggregateRateLimiter_setFeeQuoter:test_OnlyOwner_Revert() (gas: 10967) -MultiAggregateRateLimiter_setFeeQuoter:test_Owner_Success() (gas: 19190) -MultiAggregateRateLimiter_setFeeQuoter:test_ZeroAddress_Revert() (gas: 10642) -MultiAggregateRateLimiter_updateRateLimitTokens:test_NonOwner_Revert() (gas: 18518) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensMultipleChains_Success() (gas: 281000) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensSingleChain_Success() (gas: 255391) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_AddsAndRemoves_Success() (gas: 205169) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_RemoveNonExistentToken_Success() (gas: 29012) -MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroDestToken_AbiEncoded_Revert() (gas: 14001) -MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroDestToken_Revert() (gas: 18365) -MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroSourceToken_Revert() (gas: 18294) -MultiOCR3Base_setOCR3Configs:test_FMustBePositive_Revert() (gas: 59441) -MultiOCR3Base_setOCR3Configs:test_FTooHigh_Revert() (gas: 44190) -MultiOCR3Base_setOCR3Configs:test_MoreTransmittersThanSigners_Revert() (gas: 104844) -MultiOCR3Base_setOCR3Configs:test_NoTransmitters_Revert() (gas: 18908) -MultiOCR3Base_setOCR3Configs:test_RepeatSignerAddress_Revert() (gas: 283842) -MultiOCR3Base_setOCR3Configs:test_RepeatTransmitterAddress_Revert() (gas: 422489) -MultiOCR3Base_setOCR3Configs:test_SetConfigIgnoreSigners_Success() (gas: 512288) -MultiOCR3Base_setOCR3Configs:test_SetConfigWithSignersMismatchingTransmitters_Success() (gas: 680609) -MultiOCR3Base_setOCR3Configs:test_SetConfigWithSigners_Success() (gas: 829200) -MultiOCR3Base_setOCR3Configs:test_SetConfigWithoutSigners_Success() (gas: 457530) -MultiOCR3Base_setOCR3Configs:test_SetConfigsZeroInput_Success() (gas: 12436) -MultiOCR3Base_setOCR3Configs:test_SetMultipleConfigs_Success() (gas: 2142528) -MultiOCR3Base_setOCR3Configs:test_SignerCannotBeZeroAddress_Revert() (gas: 141905) -MultiOCR3Base_setOCR3Configs:test_StaticConfigChange_Revert() (gas: 807791) -MultiOCR3Base_setOCR3Configs:test_TooManySigners_Revert() (gas: 158911) -MultiOCR3Base_setOCR3Configs:test_TooManyTransmitters_Revert() (gas: 112357) -MultiOCR3Base_setOCR3Configs:test_TransmitterCannotBeZeroAddress_Revert() (gas: 254293) -MultiOCR3Base_setOCR3Configs:test_UpdateConfigSigners_Success() (gas: 861787) -MultiOCR3Base_setOCR3Configs:test_UpdateConfigTransmittersWithoutSigners_Success() (gas: 476186) -MultiOCR3Base_transmit:test_ConfigDigestMismatch_Revert() (gas: 42765) -MultiOCR3Base_transmit:test_ForkedChain_Revert() (gas: 48348) -MultiOCR3Base_transmit:test_InsufficientSignatures_Revert() (gas: 76893) -MultiOCR3Base_transmit:test_NonUniqueSignature_Revert() (gas: 65621) -MultiOCR3Base_transmit:test_SignatureOutOfRegistration_Revert() (gas: 33387) -MultiOCR3Base_transmit:test_TooManySignatures_Revert() (gas: 79597) -MultiOCR3Base_transmit:test_TransmitSigners_gas_Success() (gas: 33589) -MultiOCR3Base_transmit:test_TransmitWithExtraCalldataArgs_Revert() (gas: 47082) -MultiOCR3Base_transmit:test_TransmitWithLessCalldataArgs_Revert() (gas: 25583) -MultiOCR3Base_transmit:test_TransmitWithoutSignatureVerification_gas_Success() (gas: 18615) -MultiOCR3Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 24193) -MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 60994) -MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39824) -MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 32920) -NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates() (gas: 123604) -NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySet_overrideAllowed() (gas: 45986) -NonceManager_applyPreviousRampsUpdates:test_SingleRampUpdate_success() (gas: 66889) -NonceManager_applyPreviousRampsUpdates:test_ZeroInput() (gas: 12169) -NonceManager_getInboundNonce:test_getInboundNonce_NoPrevOffRampForChain() (gas: 185821) -NonceManager_getInboundNonce:test_getInboundNonce_Upgraded() (gas: 152976) -NonceManager_getInboundNonce:test_getInboundNonce_UpgradedNonceNewSenderStartsAtZero() (gas: 189296) -NonceManager_getInboundNonce:test_getInboundNonce_UpgradedNonceStartsAtV1Nonce() (gas: 252384) -NonceManager_getInboundNonce:test_getInboundNonce_UpgradedOffRampNonceSkipsIfMsgInFlight() (gas: 220672) -NonceManager_getInboundNonce:test_getInboundNonce_UpgradedSenderNoncesReadsPreviousRamp() (gas: 60520) -NonceManager_getIncrementedOutboundNonce:test_getIncrementedOutboundNonce() (gas: 37979) -NonceManager_getIncrementedOutboundNonce:test_incrementInboundNonce() (gas: 38756) -NonceManager_getIncrementedOutboundNonce:test_incrementInboundNonce_SkippedIncorrectNonce() (gas: 23759) -NonceManager_getIncrementedOutboundNonce:test_incrementNoncesInboundAndOutbound() (gas: 71901) -NonceManager_getOutboundNonce:test_getOutboundNonce_Upgrade() (gas: 105300) -NonceManager_getOutboundNonce:test_getOutboundNonce_UpgradeNonceNewSenderStartsAtZero() (gas: 166146) -NonceManager_getOutboundNonce:test_getOutboundNonce_UpgradeNonceStartsAtV1Nonce() (gas: 195937) -NonceManager_getOutboundNonce:test_getOutboundNonce_UpgradeSenderNoncesReadsPreviousRamp() (gas: 140158) -OffRamp_afterOC3ConfigSet:test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() (gas: 5903354) -OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 626094) -OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 166505) -OffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 16719) -OffRamp_applySourceChainConfigUpdates:test_InvalidOnRampUpdate_Revert() (gas: 274389) -OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Success() (gas: 168604) -OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 181037) -OffRamp_applySourceChainConfigUpdates:test_RouterAddress_Revert() (gas: 13441) -OffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 72724) -OffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 15519) -OffRamp_applySourceChainConfigUpdates:test_allowNonOnRampUpdateAfterLaneIsUsed_success() (gas: 284695) -OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain_Success() (gas: 177591) -OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 333573) -OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 276839) -OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 168529) -OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 188173) -OffRamp_batchExecute:test_SingleReport_Success() (gas: 156527) -OffRamp_batchExecute:test_Unhealthy_Success() (gas: 545431) -OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10643) -OffRamp_commit:test_CommitOnRampMismatch_Revert() (gas: 92450) -OffRamp_commit:test_FailedRMNVerification_Reverts() (gas: 63117) -OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 69655) -OffRamp_commit:test_InvalidInterval_Revert() (gas: 65803) -OffRamp_commit:test_InvalidRootRevert() (gas: 64898) -OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6664144) -OffRamp_commit:test_NoConfig_Revert() (gas: 6247562) -OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 112728) -OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 120561) -OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 112660) -OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 354785) -OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 163983) -OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 140923) -OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 147631) -OffRamp_commit:test_RootWithRMNDisabled_success() (gas: 153596) -OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 61365) -OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 231709) -OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 125027) -OffRamp_commit:test_Unhealthy_Revert() (gas: 60177) -OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 206221) -OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 53305) -OffRamp_constructor:test_Constructor_Success() (gas: 6210339) -OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 137118) -OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103828) -OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101677) -OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 162599) -OffRamp_constructor:test_ZeroRMNRemote_Revert() (gas: 101597) -OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101598) -OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17532) -OffRamp_execute:test_LargeBatch_Success() (gas: 3378447) -OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 371209) -OffRamp_execute:test_MultipleReports_Success() (gas: 298806) -OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 7072622) -OffRamp_execute:test_NoConfig_Revert() (gas: 6297092) -OffRamp_execute:test_NonArray_Revert() (gas: 27572) -OffRamp_execute:test_SingleReport_Success() (gas: 175631) -OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 147790) -OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6964290) -OffRamp_execute:test_ZeroReports_Revert() (gas: 17248) -OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens() (gas: 56213) -OffRamp_executeSingleMessage:test_executeSingleMessage_NonContract() (gas: 20508) -OffRamp_executeSingleMessage:test_executeSingleMessage_NonContractWithTokens() (gas: 238130) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithMessageInterceptor() (gas: 91994) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens() (gas: 268223) -OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 28659) -OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 15530) -OffRamp_executeSingleReport:test_InvalidSourcePoolAddress() (gas: 474738) -OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 48296) -OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 34101) -OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 28824) -OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 187677) -OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 197809) -OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 40687) -OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 405023) -OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 248786) -OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 192430) -OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 212456) -OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 243699) -OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 141510) -OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 402622) -OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 58242) -OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 73812) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 574336) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 522887) -OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 26795) -OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 540963) -OffRamp_executeSingleReport:test_Unhealthy_Success() (gas: 540910) -OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 452000) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 135231) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 164892) -OffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3905742) -OffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 121048) -OffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 89737) -OffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 81694) -OffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 74284) -OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 172639) -OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 213251) -OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 27248) -OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 165935) -OffRamp_manuallyExecute:test_manuallyExecute_InvalidReceiverExecutionGasLimit_Revert() (gas: 27774) -OffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 55362) -OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 489669) -OffRamp_manuallyExecute:test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() (gas: 314861) -OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2224794) -OffRamp_manuallyExecute:test_manuallyExecute_SourceChainSelectorMismatch_Revert() (gas: 165330) -OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 226161) -OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 226701) -OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 774719) -OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 344726) -OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 37632) -OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 101465) -OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 36790) -OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 91430) -OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 83518) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens() (gas: 168872) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_RevertWhenInvalidDataLengthReturnData() (gas: 62822) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_RevertWhenPoolDoesNotSupportDest() (gas: 78426) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_WithGasOverride() (gas: 170742) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals() (gas: 181981) -OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11465) -OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 13975) -OffRamp_setDynamicConfig:test_SetDynamicConfigWithInterceptor_Success() (gas: 47491) -OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 25464) -OffRamp_trialExecute:test_trialExecute() (gas: 271859) -OffRamp_trialExecute:test_trialExecute_RateLimitError() (gas: 127545) -OffRamp_trialExecute:test_trialExecute_TokenHandlingErrorIsCaught() (gas: 138855) -OffRamp_trialExecute:test_trialExecute_TokenPoolIsNotAContract() (gas: 289500) -OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 251641) -OnRamp_applyAllowlistUpdates:test_applyAllowlistUpdates_InvalidAllowListRequestDisabledAllowListWithAdds() (gas: 17227) -OnRamp_applyAllowlistUpdates:test_applyAllowlistUpdates_Revert() (gas: 67101) -OnRamp_applyAllowlistUpdates:test_applyAllowlistUpdates_Success() (gas: 325983) -OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_Success() (gas: 65892) -OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_WithInvalidChainSelector_Revert() (gas: 12902) -OnRamp_constructor:test_Constructor_EnableAllowList_ForwardFromRouter_Reverts() (gas: 2569362) -OnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (gas: 95148) -OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 93090) -OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 98066) -OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 93146) -OnRamp_constructor:test_Constructor_Success() (gas: 2647459) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 115432) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 146300) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145875) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 144080) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 146072) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 145470) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 140731) -OnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 38526) -OnRamp_forwardFromRouter:test_MessageInterceptionError_Revert() (gas: 143112) -OnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 36611) -OnRamp_forwardFromRouter:test_MultiCannotSendZeroTokens_Revert() (gas: 36493) -OnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 18290) -OnRamp_forwardFromRouter:test_Paused_Revert() (gas: 38412) -OnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 23629) -OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 186715) -OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 213144) -OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 147070) -OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 161303) -OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 4073863) -OnRamp_forwardFromRouter:test_UnAllowedOriginalSender_Revert() (gas: 24015) -OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 75854) -OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 38588) -OnRamp_forwardFromRouter:test_forwardFromRouter_WithInterception_Success() (gas: 281529) -OnRamp_getFee:test_EmptyMessage_Success() (gas: 98692) -OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 65475) -OnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 87119) -OnRamp_getFee:test_NotAFeeTokenButPricedToken_Revert() (gas: 35166) -OnRamp_getFee:test_SingleTokenMessage_Success() (gas: 113865) -OnRamp_getFee:test_Unhealthy_Revert() (gas: 17040) -OnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10565) -OnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35405) -OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigFeeAggregatorEqAddressZero_Revert() (gas: 11535) -OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigFeeQuoterEqAddressZero_Revert() (gas: 13194) -OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigInvalidConfig_Revert() (gas: 11499) -OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigOnlyOwner_Revert() (gas: 11938) -OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigReentrancyGuardEnteredEqTrue_Revert() (gas: 13264) -OnRamp_setDynamicConfig:test_setDynamicConfig_Success() (gas: 56440) -OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 125901) -PingPong_ccipReceive:test_CcipReceive_Success() (gas: 172880) -PingPong_setOutOfOrderExecution:test_OutOfOrderExecution_Success() (gas: 20283) -PingPong_setPaused:test_Pausing_Success() (gas: 17738) -PingPong_startPingPong:test_StartPingPong_With_OOO_Success() (gas: 151993) -PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered_Success() (gas: 177608) -RMNHome_getConfigDigests:test_getConfigDigests_success() (gas: 1079685) -RMNHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive_ConfigDigestMismatch_reverts() (gas: 23879) -RMNHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive_NoOpStateTransitionNotAllowed_reverts() (gas: 10597) -RMNHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive_OnlyOwner_reverts() (gas: 10843) -RMNHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive_success() (gas: 1085033) -RMNHome_revokeCandidate:test_revokeCandidate_ConfigDigestMismatch_reverts() (gas: 19041) -RMNHome_revokeCandidate:test_revokeCandidate_OnlyOwner_reverts() (gas: 10889) -RMNHome_revokeCandidate:test_revokeCandidate_RevokingZeroDigestNotAllowed_reverts() (gas: 10628) -RMNHome_revokeCandidate:test_revokeCandidate_success() (gas: 28147) -RMNHome_setCandidate:test_setCandidate_ConfigDigestMismatch_reverts() (gas: 597564) -RMNHome_setCandidate:test_setCandidate_OnlyOwner_reverts() (gas: 15071) -RMNHome_setCandidate:test_setCandidate_success() (gas: 589330) -RMNHome_setDynamicConfig:test_setDynamicConfig_DigestNotFound_reverts() (gas: 30186) -RMNHome_setDynamicConfig:test_setDynamicConfig_MinObserversTooHigh_reverts() (gas: 18854) -RMNHome_setDynamicConfig:test_setDynamicConfig_OnlyOwner_reverts() (gas: 14009) -RMNHome_setDynamicConfig:test_setDynamicConfig_success() (gas: 104862) -RMNHome_validateStaticAndDynamicConfig:test_validateStaticAndDynamicConfig_DuplicateOffchainPublicKey_reverts() (gas: 18850) -RMNHome_validateStaticAndDynamicConfig:test_validateStaticAndDynamicConfig_DuplicatePeerId_reverts() (gas: 18710) -RMNHome_validateStaticAndDynamicConfig:test_validateStaticAndDynamicConfig_DuplicateSourceChain_reverts() (gas: 20387) -RMNHome_validateStaticAndDynamicConfig:test_validateStaticAndDynamicConfig_NotEnoughObservers_reverts() (gas: 21405) -RMNHome_validateStaticAndDynamicConfig:test_validateStaticAndDynamicConfig_OutOfBoundsNodesLength_reverts() (gas: 137318) -RMNHome_validateStaticAndDynamicConfig:test_validateStaticAndDynamicConfig_OutOfBoundsObserverNodeIndex_reverts() (gas: 20522) -RMNRemote_constructor:test_constructor() (gas: 8398) -RMNRemote_curse:test_curse_AlreadyCursed_duplicateSubject_reverts() (gas: 154501) -RMNRemote_curse:test_curse_calledByNonOwner_reverts() (gas: 18734) -RMNRemote_curse:test_curse_success() (gas: 149475) -RMNRemote_global_and_legacy_curses:test_global_and_legacy_curses_success() (gas: 133441) +MockRouterTest:test_ccipSendWithEVMExtraArgsV1() (gas: 110081) +MockRouterTest:test_ccipSendWithEVMExtraArgsV2() (gas: 132594) +MockRouterTest:test_ccipSendWithLinkFeeTokenAndValidMsgValue() (gas: 126679) +MockRouterTest:test_ccipSendWithSufficientNativeFeeTokens() (gas: 44038) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigs() (gas: 317373) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigsBothLanes() (gas: 134278) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfig() (gas: 76755) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfigOutbound() (gas: 76797) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfig() (gas: 54084) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfigWithNoDifference() (gas: 38924) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroConfigs() (gas: 12505) +MultiAggregateRateLimiter_constructor:test_Constructor() (gas: 2102740) +MultiAggregateRateLimiter_constructor:test_ConstructorNoAuthorizedCallers() (gas: 1986594) +MultiAggregateRateLimiter_getTokenBucket:test_GetTokenBucket() (gas: 30888) +MultiAggregateRateLimiter_getTokenBucket:test_Refill() (gas: 48378) +MultiAggregateRateLimiter_getTokenValue:test_GetTokenValue() (gas: 17594) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDifferentTokensOnDifferentChains() (gas: 211396) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDisabledRateLimitToken() (gas: 58810) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithNoTokens() (gas: 17918) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitDisabled() (gas: 45460) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitReset() (gas: 77677) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokens() (gas: 50923) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokensOnDifferentChains() (gas: 309989) +MultiAggregateRateLimiter_onOutboundMessage:test_RateLimitValueDifferentLanes() (gas: 51567) +MultiAggregateRateLimiter_onOutboundMessage:test_ValidateMessageWithNoTokens() (gas: 19379) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains() (gas: 210948) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken() (gas: 60522) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitDisabled() (gas: 47112) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitReset() (gas: 78418) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokens() (gas: 52633) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains() (gas: 309747) +MultiAggregateRateLimiter_setFeeQuoter:test_Owner() (gas: 19146) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensMultipleChains() (gas: 281364) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensSingleChain() (gas: 255770) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_AddsAndRemoves() (gas: 205543) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_RemoveNonExistentToken() (gas: 29151) +MultiOCR3Base_setOCR3Configs:test_SetConfigIgnoreSigners() (gas: 512335) +MultiOCR3Base_setOCR3Configs:test_SetConfigWithSigners() (gas: 829238) +MultiOCR3Base_setOCR3Configs:test_SetConfigWithSignersMismatchingTransmitters() (gas: 680660) +MultiOCR3Base_setOCR3Configs:test_SetConfigWithoutSigners() (gas: 457485) +MultiOCR3Base_setOCR3Configs:test_SetConfigsZeroInput() (gas: 12437) +MultiOCR3Base_setOCR3Configs:test_SetMultipleConfigs() (gas: 2142785) +MultiOCR3Base_setOCR3Configs:test_UpdateConfigSigners() (gas: 861909) +MultiOCR3Base_setOCR3Configs:test_UpdateConfigTransmittersWithoutSigners() (gas: 476109) +MultiOCR3Base_transmit:test_TransmitSigners_gas() (gas: 33559) +MultiOCR3Base_transmit:test_TransmitWithoutSignatureVerification_gas() (gas: 18638) +NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates() (gas: 123617) +NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySet_overrideAllowed() (gas: 45935) +NonceManager_applyPreviousRampsUpdates:test_SingleRampUpdate() (gas: 66937) +NonceManager_applyPreviousRampsUpdates:test_ZeroInput() (gas: 12123) +NonceManager_getInboundNonce:test_getInboundNonce_NoPrevOffRampForChain() (gas: 178906) +NonceManager_getInboundNonce:test_getInboundNonce_Upgraded() (gas: 146095) +NonceManager_getInboundNonce:test_getInboundNonce_UpgradedNonceNewSenderStartsAtZero() (gas: 182376) +NonceManager_getInboundNonce:test_getInboundNonce_UpgradedNonceStartsAtV1Nonce() (gas: 245089) +NonceManager_getInboundNonce:test_getInboundNonce_UpgradedOffRampNonceSkipsIfMsgInFlight() (gas: 213735) +NonceManager_getInboundNonce:test_getInboundNonce_UpgradedSenderNoncesReadsPreviousRamp() (gas: 60418) +NonceManager_getIncrementedOutboundNonce:test_getIncrementedOutboundNonce() (gas: 37974) +NonceManager_getIncrementedOutboundNonce:test_incrementInboundNonce() (gas: 38746) +NonceManager_getIncrementedOutboundNonce:test_incrementInboundNonce_SkippedIncorrectNonce() (gas: 23739) +NonceManager_getIncrementedOutboundNonce:test_incrementNoncesInboundAndOutbound() (gas: 71886) +NonceManager_getOutboundNonce:test_getOutboundNonce_Upgrade() (gas: 105588) +NonceManager_getOutboundNonce:test_getOutboundNonce_UpgradeNonceNewSenderStartsAtZero() (gas: 167456) +NonceManager_getOutboundNonce:test_getOutboundNonce_UpgradeNonceStartsAtV1Nonce() (gas: 197510) +NonceManager_getOutboundNonce:test_getOutboundNonce_UpgradeSenderNoncesReadsPreviousRamp() (gas: 145209) +OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains() (gas: 626140) +OffRamp_applySourceChainConfigUpdates:test_AddNewChain() (gas: 166441) +OffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates() (gas: 16671) +OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain() (gas: 180998) +OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp() (gas: 168513) +OffRamp_applySourceChainConfigUpdates:test_allowNonOnRampUpdateAfterLaneIsUsed() (gas: 284861) +OffRamp_batchExecute:test_MultipleReportsDifferentChains() (gas: 326028) +OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain() (gas: 170852) +OffRamp_batchExecute:test_MultipleReportsSameChain() (gas: 269327) +OffRamp_batchExecute:test_MultipleReportsSkipDuplicate() (gas: 161811) +OffRamp_batchExecute:test_SingleReport() (gas: 149617) +OffRamp_batchExecute:test_Unhealthy() (gas: 533326) +OffRamp_commit:test_OnlyGasPriceUpdates() (gas: 112973) +OffRamp_commit:test_OnlyTokenPriceUpdates() (gas: 112927) +OffRamp_commit:test_PriceSequenceNumberCleared() (gas: 355397) +OffRamp_commit:test_ReportAndPriceUpdate() (gas: 164209) +OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 141051) +OffRamp_commit:test_RootWithRMNDisabled() (gas: 153873) +OffRamp_commit:test_StaleReportWithRoot() (gas: 232057) +OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot() (gas: 206700) +OffRamp_constructor:test_Constructor() (gas: 6311247) +OffRamp_execute:test_LargeBatch() (gas: 3373860) +OffRamp_execute:test_MultipleReports() (gas: 291458) +OffRamp_execute:test_MultipleReportsWithPartialValidationFailures() (gas: 364826) +OffRamp_execute:test_SingleReport() (gas: 168850) +OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens() (gas: 51610) +OffRamp_executeSingleMessage:test_executeSingleMessage_NonContract() (gas: 20514) +OffRamp_executeSingleMessage:test_executeSingleMessage_NonContractWithTokens() (gas: 230418) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithMessageInterceptor() (gas: 87465) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens() (gas: 259935) +OffRamp_executeSingleReport:test_InvalidSourcePoolAddress() (gas: 455383) +OffRamp_executeSingleReport:test_ReceiverError() (gas: 180822) +OffRamp_executeSingleReport:test_SingleMessageNoTokens() (gas: 205270) +OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain() (gas: 241357) +OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered() (gas: 185263) +OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver() (gas: 243920) +OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 134656) +OffRamp_executeSingleReport:test_SkippedIncorrectNonce() (gas: 58298) +OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes() (gas: 392394) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE() (gas: 562427) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 510808) +OffRamp_executeSingleReport:test_Unhealthy() (gas: 528949) +OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain() (gas: 439299) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage() (gas: 158038) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered() (gas: 128422) +OffRamp_getExecutionState:test_FillExecutionState() (gas: 3955662) +OffRamp_getExecutionState:test_GetDifferentChainExecutionState() (gas: 121311) +OffRamp_getExecutionState:test_GetExecutionState() (gas: 90102) +OffRamp_manuallyExecute:test_manuallyExecute() (gas: 212393) +OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched() (gas: 165767) +OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit() (gas: 479170) +OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails() (gas: 2229662) +OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride() (gas: 212943) +OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride() (gas: 732343) +OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages() (gas: 337040) +OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken() (gas: 94629) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens() (gas: 161157) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_WithGasOverride() (gas: 163023) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals() (gas: 174276) +OffRamp_setDynamicConfig:test_SetDynamicConfig() (gas: 25442) +OffRamp_setDynamicConfig:test_SetDynamicConfigWithInterceptor() (gas: 47493) +OffRamp_trialExecute:test_trialExecute() (gas: 263614) +OffRamp_trialExecute:test_trialExecute_CallWithExactGasRevertsAndSenderIsNotGasEstimator() (gas: 24490) +OffRamp_trialExecute:test_trialExecute_RateLimitError() (gas: 120710) +OffRamp_trialExecute:test_trialExecute_RevertsWhen_NoEnoughGasForCallSigAndSenderIsGasEstimator() (gas: 29391) +OffRamp_trialExecute:test_trialExecute_RevertsWhen_NoGasForCallExactCheckAndSenderIsGasEstimator() (gas: 29539) +OffRamp_trialExecute:test_trialExecute_TokenHandlingErrorIsCaught() (gas: 131932) +OffRamp_trialExecute:test_trialExecute_TokenPoolIsNotAContract() (gas: 281327) +OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy() (gas: 245406) +OnRamp_applyAllowlistUpdates:test_applyAllowlistUpdates() (gas: 325996) +OnRamp_applyAllowlistUpdates:test_applyAllowlistUpdates_InvalidAllowListRequestDisabledAllowListWithAdds() (gas: 17190) +OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates() (gas: 65874) +OnRamp_constructor:test_Constructor() (gas: 2672063) +OnRamp_forwardFromRouter:test_ForwardFromRouter() (gas: 145718) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2() (gas: 146530) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue() (gas: 115709) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 146116) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 144372) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 146357) +OnRamp_forwardFromRouter:test_ForwardFromRouter_ConfigurableSourceRouter() (gas: 143697) +OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered() (gas: 187475) +OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce() (gas: 213852) +OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 147363) +OnRamp_forwardFromRouter:test_forwardFromRouter_WithInterception() (gas: 275037) +OnRamp_getFee:test_EmptyMessage() (gas: 100389) +OnRamp_getFee:test_GetFeeOfZeroForTokenMessage() (gas: 89392) +OnRamp_getFee:test_SingleTokenMessage() (gas: 115707) +OnRamp_getTokenPool:test_GetTokenPool() (gas: 35404) +OnRamp_setDynamicConfig:test_setDynamicConfig() (gas: 56650) +OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens() (gas: 125835) +PingPong_ccipReceive:test_CcipReceive() (gas: 167206) +PingPong_setOutOfOrderExecution:test_OutOfOrderExecution() (gas: 20284) +PingPong_setPaused:test_Pausing() (gas: 17760) +PingPong_startPingPong:test_StartPingPong_With_OOO() (gas: 146357) +PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered() (gas: 171988) +RMNHome_getConfigDigests:test_getConfigDigests() (gas: 1081176) +RMNHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive() (gas: 1086556) +RMNHome_revokeCandidate:test_revokeCandidate() (gas: 28085) +RMNHome_setCandidate:test_setCandidate() (gas: 590250) +RMNHome_setDynamicConfig:test_setDynamicConfig() (gas: 105498) +RMNProxy_constructor:test_Constructor() (gas: 302031) +RMNProxy_isCursed:test_IsCursed_GlobalCurseSubject() (gas: 89809) +RMNProxy_setARM:test_SetARM() (gas: 16599) +RMNProxy_setARM:test_SetARMzero() (gas: 11275) +RMNRemote_constructor:test_constructor() (gas: 8410) +RMNRemote_curse:test_curse() (gas: 149422) +RMNRemote_global_curses:test_isCursed_globalCurseSubject() (gas: 71707) RMNRemote_isBlessed:test_isBlessed() (gas: 17588) -RMNRemote_setConfig:test_setConfig_ZeroValueNotAllowed_revert() (gas: 37971) -RMNRemote_setConfig:test_setConfig_addSigner_removeSigner_success() (gas: 993448) -RMNRemote_setConfig:test_setConfig_duplicateOnChainPublicKey_reverts() (gas: 323540) -RMNRemote_setConfig:test_setConfig_invalidSignerOrder_reverts() (gas: 80201) -RMNRemote_setConfig:test_setConfig_notEnoughSigners_reverts() (gas: 54232) -RMNRemote_uncurse:test_uncurse_NotCursed_duplicatedUncurseSubject_reverts() (gas: 51940) -RMNRemote_uncurse:test_uncurse_calledByNonOwner_reverts() (gas: 18615) -RMNRemote_uncurse:test_uncurse_success() (gas: 40135) -RMNRemote_verify_withConfigNotSet:test_verify_reverts() (gas: 13600) -RMNRemote_verify_withConfigSet:test_verify_InvalidSignature_reverts() (gas: 96471) -RMNRemote_verify_withConfigSet:test_verify_OutOfOrderSignatures_duplicateSignature_reverts() (gas: 94289) -RMNRemote_verify_withConfigSet:test_verify_OutOfOrderSignatures_not_sorted_reverts() (gas: 101352) -RMNRemote_verify_withConfigSet:test_verify_ThresholdNotMet_reverts() (gas: 304744) -RMNRemote_verify_withConfigSet:test_verify_UnexpectedSigner_reverts() (gas: 428284) -RMNRemote_verify_withConfigSet:test_verify_success() (gas: 86181) -RateLimiter_constructor:test_Constructor_Success() (gas: 19806) -RateLimiter_consume:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 16042) -RateLimiter_consume:test_AggregateValueRateLimitReached_Revert() (gas: 22435) -RateLimiter_consume:test_ConsumeAggregateValue_Success() (gas: 31495) -RateLimiter_consume:test_ConsumeTokens_Success() (gas: 20403) -RateLimiter_consume:test_ConsumeUnlimited_Success() (gas: 40693) -RateLimiter_consume:test_ConsumingMoreThanUint128_Revert() (gas: 15800) -RateLimiter_consume:test_RateLimitReachedOverConsecutiveBlocks_Revert() (gas: 25781) -RateLimiter_consume:test_Refill_Success() (gas: 37447) -RateLimiter_consume:test_TokenMaxCapacityExceeded_Revert() (gas: 18388) -RateLimiter_consume:test_TokenRateLimitReached_Revert() (gas: 24930) -RateLimiter_currentTokenBucketState:test_CurrentTokenBucketState_Success() (gas: 38947) -RateLimiter_currentTokenBucketState:test_Refill_Success() (gas: 46852) -RateLimiter_setTokenBucketConfig:test_SetRateLimiterConfig_Success() (gas: 38509) -RegistryModuleOwnerCustom_constructor:test_constructor_Revert() (gas: 36107) -RegistryModuleOwnerCustom_registerAccessControlDefaultAdmin:test_registerAccessControlDefaultAdmin_Revert() (gas: 20200) -RegistryModuleOwnerCustom_registerAccessControlDefaultAdmin:test_registerAccessControlDefaultAdmin_Success() (gas: 130631) -RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin:test_registerAdminViaGetCCIPAdmin_Revert() (gas: 19797) -RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin:test_registerAdminViaGetCCIPAdmin_Success() (gas: 130126) -RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner_Revert() (gas: 19602) -RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner_Success() (gas: 129930) -Router_applyRampUpdates:test_applyRampUpdates_OffRampUpdatesWithRouting() (gas: 10749731) -Router_applyRampUpdates:test_applyRampUpdates_OnRampDisable() (gas: 56422) -Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 131447) -Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 221710) -Router_ccipSend:test_FeeTokenAmountTooLow_Revert() (gas: 71858) -Router_ccipSend:test_InvalidMsgValue() (gas: 32411) -Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 69524) -Router_ccipSend:test_NativeFeeTokenOverpay_Success() (gas: 193318) -Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 61550) -Router_ccipSend:test_NativeFeeToken_Success() (gas: 191922) -Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 226583) -Router_ccipSend:test_UnsupportedDestinationChain_Revert() (gas: 25056) -Router_ccipSend:test_WhenNotHealthy_Revert() (gas: 45056) -Router_ccipSend:test_WrappedNativeFeeToken_Success() (gas: 194231) -Router_ccipSend:test_ccipSend_nativeFeeNoTokenSuccess_gas() (gas: 140696) -Router_ccipSend:test_ccipSend_nativeFeeOneTokenSuccess_gas() (gas: 230894) -Router_constructor:test_Constructor_Success() (gas: 13222) +RMNRemote_setConfig:test_setConfig_addSigner_removeSigner() (gas: 994169) +RMNRemote_uncurse:test_uncurse() (gas: 40136) +RMNRemote_verify_withConfigSet:test_verify() (gas: 86470) +RateLimiter_constructor:test_Constructor() (gas: 19820) +RateLimiter_consume:test_ConsumeAggregateValue() (gas: 31633) +RateLimiter_consume:test_ConsumeTokens() (gas: 20369) +RateLimiter_consume:test_ConsumeUnlimited() (gas: 40923) +RateLimiter_consume:test_Refill() (gas: 37562) +RateLimiter_currentTokenBucketState:test_CurrentTokenBucketState() (gas: 39126) +RateLimiter_currentTokenBucketState:test_Refill() (gas: 47182) +RateLimiter_setTokenBucketConfig:test_SetRateLimiterConfig() (gas: 38645) +RegistryModuleOwnerCustom_registerAccessControlDefaultAdmin:test_registerAccessControlDefaultAdmin() (gas: 130641) +RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin:test_registerAdminViaGetCCIPAdmin() (gas: 130136) +RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner() (gas: 129941) +Router_applyRampUpdates:test_applyRampUpdates_OffRampUpdatesWithRouting() (gas: 10413055) +Router_applyRampUpdates:test_applyRampUpdates_OnRampDisable() (gas: 56445) +Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 125820) +Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 213241) +Router_ccipSend:test_InvalidMsgValue() (gas: 27856) +Router_ccipSend:test_NativeFeeToken() (gas: 186661) +Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 62761) +Router_ccipSend:test_NativeFeeTokenOverpay() (gas: 188056) +Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 54853) +Router_ccipSend:test_NonLinkFeeToken() (gas: 220901) +Router_ccipSend:test_WrappedNativeFeeToken() (gas: 188878) +Router_ccipSend:test_ccipSend_nativeFeeNoTokenSuccess_gas() (gas: 134978) +Router_ccipSend:test_ccipSend_nativeFeeOneTokenSuccess_gas() (gas: 222442) +Router_constructor:test_Constructor() (gas: 13170) Router_getArmProxy:test_getArmProxy() (gas: 10573) -Router_getFee:test_GetFeeSupportedChain_Success() (gas: 51934) -Router_getFee:test_UnsupportedDestinationChain_Revert() (gas: 17385) -Router_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10565) -Router_recoverTokens:test_RecoverTokensInvalidRecipient_Revert() (gas: 11410) -Router_recoverTokens:test_RecoverTokensNoFunds_Revert() (gas: 20199) -Router_recoverTokens:test_RecoverTokensNonOwner_Revert() (gas: 11236) -Router_recoverTokens:test_RecoverTokensValueReceiver_Revert() (gas: 349502) -Router_recoverTokens:test_RecoverTokens_Success() (gas: 52667) -Router_routeMessage:test_routeMessage_AutoExec_Success() (gas: 43213) -Router_routeMessage:test_routeMessage_ExecutionEvent_Success() (gas: 159418) -Router_routeMessage:test_routeMessage_ManualExec_Success() (gas: 35723) -Router_routeMessage:test_routeMessage_OnlyOffRamp_Revert() (gas: 25376) -Router_routeMessage:test_routeMessage_WhenNotHealthy_Revert() (gas: 44812) -Router_setWrappedNative:test_OnlyOwner_Revert() (gas: 11030) -TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_OnlyPendingAdministrator_Revert() (gas: 51433) -TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_Success() (gas: 44189) -TokenAdminRegistry_addRegistryModule:test_addRegistryModule_OnlyOwner_Revert() (gas: 12662) -TokenAdminRegistry_addRegistryModule:test_addRegistryModule_Success() (gas: 67155) -TokenAdminRegistry_getAllConfiguredTokens:test_getAllConfiguredTokens_outOfBounds_Success() (gas: 11395) -TokenAdminRegistry_getPool:test_getPool_Success() (gas: 17701) -TokenAdminRegistry_getPools:test_getPools_Success() (gas: 40331) -TokenAdminRegistry_isAdministrator:test_isAdministrator_Success() (gas: 106315) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_AlreadyRegistered_Revert() (gas: 104412) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_OnlyRegistryModule_Revert() (gas: 15643) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_ZeroAddress_Revert() (gas: 15177) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_module_Success() (gas: 113094) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_owner_Success() (gas: 108031) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_reRegisterWhileUnclaimed_Success() (gas: 116216) -TokenAdminRegistry_removeRegistryModule:test_removeRegistryModule_OnlyOwner_Revert() (gas: 12651) -TokenAdminRegistry_removeRegistryModule:test_removeRegistryModule_Success() (gas: 54735) -TokenAdminRegistry_setPool:test_setPool_InvalidTokenPoolToken_Revert() (gas: 19316) -TokenAdminRegistry_setPool:test_setPool_OnlyAdministrator_Revert() (gas: 18170) -TokenAdminRegistry_setPool:test_setPool_Success() (gas: 36267) -TokenAdminRegistry_setPool:test_setPool_ZeroAddressRemovesPool_Success() (gas: 30875) -TokenAdminRegistry_transferAdminRole:test_transferAdminRole_OnlyAdministrator_Revert() (gas: 18202) -TokenAdminRegistry_transferAdminRole:test_transferAdminRole_Success() (gas: 49592) -TokenPoolFactory_constructor:test_constructor_Revert() (gas: 1121653) -TokenPoolFactory_createTokenPool:test_createTokenPoolLockRelease_ExistingToken_predict_Success() (gas: 12612969) -TokenPoolFactory_createTokenPool:test_createTokenPool_BurnFromMintTokenPool_Success() (gas: 6513874) -TokenPoolFactory_createTokenPool:test_createTokenPool_ExistingRemoteToken_AndPredictPool_Success() (gas: 13434268) -TokenPoolFactory_createTokenPool:test_createTokenPool_RemoteTokenHasDifferentDecimals_Success() (gas: 13441570) -TokenPoolFactory_createTokenPool:test_createTokenPool_WithNoExistingRemoteContracts_predict_Success() (gas: 13771048) -TokenPoolFactory_createTokenPool:test_createTokenPool_WithNoExistingTokenOnRemoteChain_Success() (gas: 6301066) -TokenPoolFactory_createTokenPool:test_createTokenPool_WithRemoteTokenAndRemotePool_Success() (gas: 6510314) -TokenPoolWithAllowList_applyAllowListUpdates:test_AllowListNotEnabled_Revert() (gas: 2827849) -TokenPoolWithAllowList_applyAllowListUpdates:test_OnlyOwner_Revert() (gas: 12119) -TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowListSkipsZero_Success() (gas: 23567) -TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowList_Success() (gas: 178398) -TokenPoolWithAllowList_getAllowList:test_GetAllowList_Success() (gas: 23929) -TokenPoolWithAllowList_getAllowListEnabled:test_GetAllowListEnabled_Success() (gas: 8408) -TokenPoolWithAllowList_setRouter:test_SetRouter_Success() (gas: 25005) -TokenPoolWithAllowList_setRouter:test_ZeroAddressNotAllowed_Revert() (gas: 10729) -TokenPool_addRemotePool:test_NonExistentChain_Revert() (gas: 14222) -TokenPool_addRemotePool:test_PoolAlreadyAdded_Revert() (gas: 117205) -TokenPool_addRemotePool:test_ZeroLengthAddressNotAllowed_Revert() (gas: 14014) -TokenPool_addRemotePool:test_addRemotePool_MultipleActive() (gas: 472820) -TokenPool_addRemotePool:test_addRemotePool_Success() (gas: 157095) -TokenPool_applyChainUpdates:test_applyChainUpdates_InvalidRateLimitRate_Revert() (gas: 455575) -TokenPool_applyChainUpdates:test_applyChainUpdates_NonExistentChain_Revert() (gas: 15032) -TokenPool_applyChainUpdates:test_applyChainUpdates_OnlyCallableByOwner_Revert() (gas: 11863) -TokenPool_applyChainUpdates:test_applyChainUpdates_Success() (gas: 592089) -TokenPool_applyChainUpdates:test_applyChainUpdates_UpdatesRemotePoolHashes() (gas: 1077776) -TokenPool_applyChainUpdates:test_applyChainUpdates_ZeroAddressNotAllowed_Revert() (gas: 226472) +Router_getFee:test_GetFeeSupportedChain() (gas: 52432) +Router_recoverTokens:test_RecoverTokens() (gas: 52686) +Router_routeMessage:test_routeMessage_AutoExec() (gas: 38071) +Router_routeMessage:test_routeMessage_ExecutionEvent() (gas: 153593) +Router_routeMessage:test_routeMessage_ManualExec() (gas: 31120) +SiloedLockReleaseTokenPool_lockOrBurn:test_lockOrBurn_SiloedFunds() (gas: 76874) +SiloedLockReleaseTokenPool_lockOrBurn:test_lockOrBurn_UnsiloedFunds() (gas: 76104) +SiloedLockReleaseTokenPool_provideLiqudity:test_ProvideLiquidity_LegacyProvideLiquiditySelector() (gas: 91873) +SiloedLockReleaseTokenPool_provideLiqudity:test_ProvideLiquidity_SiloedChain() (gas: 82416) +SiloedLockReleaseTokenPool_provideLiqudity:test_ProvideLiquidity_UnsiloedChain() (gas: 84036) +SiloedLockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_RevertsWhen_InsufficientLiquidity_SiloedChain() (gas: 110002) +SiloedLockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_RevertsWhen_InsufficientLiquidity_UnsiloedChain() (gas: 115718) +SiloedLockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_SiloedChain() (gas: 262340) +SiloedLockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_UnsiloedChain() (gas: 263392) +SiloedLockReleaseTokenPool_setRebalancer:test_setRebalancer_UnsiloedChains() (gas: 24429) +SiloedLockReleaseTokenPool_setRebalancer:test_setSiloRebalancer() (gas: 32165) +SiloedLockReleaseTokenPool_updateSiloDesignations:test_updateSiloDesignations() (gas: 105825) +SiloedLockReleaseTokenPool_withdrawLiqudity:test_withdrawLiquidity_RevertsWhen_LegacyFunctionSelectorUnauthorized() (gas: 18244) +SiloedLockReleaseTokenPool_withdrawLiqudity:test_withdrawLiquidity_SiloedFunds() (gas: 70948) +SiloedLockReleaseTokenPool_withdrawLiqudity:test_withdrawLiquidity_UnsiloedFunds_LegacyFunctionSelector() (gas: 76391) +SiloedLockReleaseTokenPool_withdrawLiqudity:test_withdrawSiloedLiquidity_UnsiloedFunds() (gas: 71945) +TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole() (gas: 44236) +TokenAdminRegistry_addRegistryModule:test_addRegistryModule() (gas: 67093) +TokenAdminRegistry_getAllConfiguredTokens:test_getAllConfiguredTokens_outOfBounds() (gas: 11363) +TokenAdminRegistry_getPool:test_getPool() (gas: 17679) +TokenAdminRegistry_getPools:test_getPools() (gas: 40271) +TokenAdminRegistry_isAdministrator:test_isAdministrator() (gas: 106335) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_module() (gas: 113043) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_owner() (gas: 107992) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_reRegisterWhileUnclaimed() (gas: 116200) +TokenAdminRegistry_removeRegistryModule:test_removeRegistryModule() (gas: 54757) +TokenAdminRegistry_setPool:test_setPool() (gas: 36207) +TokenAdminRegistry_setPool:test_setPool_ZeroAddressRemovesPool() (gas: 30852) +TokenAdminRegistry_transferAdminRole:test_transferAdminRole() (gas: 49558) +TokenPoolFactory_createTokenPool:test_createTokenPoolLockRelease_ExistingToken_predict() (gas: 12646379) +TokenPoolFactory_createTokenPool:test_createTokenPool_BurnFromMintTokenPool() (gas: 6526762) +TokenPoolFactory_createTokenPool:test_createTokenPool_ExistingRemoteToken_AndPredictPool() (gas: 13480657) +TokenPoolFactory_createTokenPool:test_createTokenPool_RemoteTokenHasDifferentDecimals() (gas: 13488141) +TokenPoolFactory_createTokenPool:test_createTokenPool_WithNoExistingRemoteContracts_predict() (gas: 13819502) +TokenPoolFactory_createTokenPool:test_createTokenPool_WithNoExistingTokenOnRemoteChain() (gas: 6315855) +TokenPoolFactory_createTokenPool:test_createTokenPool_WithRemoteTokenAndRemotePool() (gas: 6523352) +TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowList() (gas: 178482) +TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowListSkipsZero() (gas: 23580) +TokenPoolWithAllowList_getAllowList:test_GetAllowList() (gas: 23908) +TokenPoolWithAllowList_getAllowListEnabled:test_GetAllowListEnabled() (gas: 8386) +TokenPoolWithAllowList_setRouter:test_SetRouter() (gas: 24994) +TokenPool_addRemotePool:test_addRemotePool() (gas: 157121) +TokenPool_addRemotePool:test_addRemotePool_MultipleActive() (gas: 453937) +TokenPool_applyChainUpdates:test_applyChainUpdates() (gas: 592354) +TokenPool_applyChainUpdates:test_applyChainUpdates_UpdatesRemotePoolHashes() (gas: 1077690) TokenPool_calculateLocalAmount:test_calculateLocalAmount() (gas: 93680) TokenPool_constructor:test_constructor() (gas: 21930) -TokenPool_constructor:test_constructor_DecimalCallFails() (gas: 2824157) -TokenPool_getRemotePool:test_getRemotePools() (gas: 330500) -TokenPool_onlyOffRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 21504) -TokenPool_onlyOffRamp:test_ChainNotAllowed_Revert() (gas: 240435) -TokenPool_onlyOffRamp:test_onlyOffRamp_Success() (gas: 94291) -TokenPool_onlyOnRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 21156) -TokenPool_onlyOnRamp:test_ChainNotAllowed_Revert() (gas: 204376) -TokenPool_onlyOnRamp:test_onlyOnRamp_Success() (gas: 49238) -TokenPool_parseRemoteDecimals:test_parseRemoteDecimals() (gas: 14020) -TokenPool_parseRemoteDecimals:test_parseRemoteDecimals_NoDecimalsDefaultsToLocalDecimals() (gas: 9727) -TokenPool_removeRemotePool:test_InvalidRemotePoolForChain_Revert() (gas: 17499) -TokenPool_removeRemotePool:test_NonExistentChain_Revert() (gas: 14344) -TokenPool_removeRemotePool:test_removeRemotePool_Success() (gas: 188387) -TokenPool_setChainRateLimiterConfig:test_NonExistentChain_Revert() (gas: 17214) -TokenPool_setChainRateLimiterConfig:test_OnlyOwnerOrRateLimitAdmin_Revert() (gas: 15307) -TokenPool_setChainRateLimiterConfigs:test_MismatchedArrayLengths_Revert() (gas: 23960) -TokenPool_setChainRateLimiterConfigs:test_NonExistentChain_Revert() (gas: 19424) -TokenPool_setChainRateLimiterConfigs:test_OnlyOwnerOrRateLimitAdmin_Revert() (gas: 16511) -TokenPool_setRateLimitAdmin:test_SetRateLimitAdmin_Revert() (gas: 11002) -TokenPool_setRateLimitAdmin:test_SetRateLimitAdmin_Success() (gas: 37606) -USDCBridgeMigrator_BurnLockedUSDC:test_PrimaryMechanism_Success() (gas: 135887) -USDCBridgeMigrator_BurnLockedUSDC:test_WhileMigrationPause_Revert() (gas: 109751) -USDCBridgeMigrator_BurnLockedUSDC:test_invalidPermissions_Revert() (gas: 39493) -USDCBridgeMigrator_BurnLockedUSDC:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 309833) -USDCBridgeMigrator_BurnLockedUSDC:test_onLockReleaseMechanism_Success() (gas: 146961) -USDCBridgeMigrator_BurnLockedUSDC:test_onLockReleaseMechanism_thenSwitchToPrimary_Success() (gas: 209124) -USDCBridgeMigrator_cancelMigrationProposal:test_cancelExistingCCTPMigrationProposal_Success() (gas: 56155) -USDCBridgeMigrator_cancelMigrationProposal:test_cannotCancelANonExistentMigrationProposal_Revert() (gas: 12669) -USDCBridgeMigrator_excludeTokensFromBurn:test_excludeTokensWhenNoMigrationProposalPending_Revert() (gas: 13579) -USDCBridgeMigrator_proposeMigration:test_ChainNotUsingLockRelease_Revert() (gas: 15765) -USDCBridgeMigrator_provideLiquidity:test_PrimaryMechanism_Success() (gas: 136004) -USDCBridgeMigrator_provideLiquidity:test_WhileMigrationPause_Revert() (gas: 109893) -USDCBridgeMigrator_provideLiquidity:test_cannotModifyLiquidityWithoutPermissions_Revert() (gas: 13390) -USDCBridgeMigrator_provideLiquidity:test_cannotProvideLiquidityWhenMigrationProposalPending_Revert() (gas: 67428) -USDCBridgeMigrator_provideLiquidity:test_cannotProvideLiquidity_AfterMigration_Revert() (gas: 313933) -USDCBridgeMigrator_provideLiquidity:test_invalidPermissions_Revert() (gas: 39493) -USDCBridgeMigrator_provideLiquidity:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 310092) -USDCBridgeMigrator_provideLiquidity:test_onLockReleaseMechanism_Success() (gas: 147102) -USDCBridgeMigrator_provideLiquidity:test_onLockReleaseMechanism_thenSwitchToPrimary_Success() (gas: 209430) -USDCBridgeMigrator_releaseOrMint:test_OnLockReleaseMechanism_Success() (gas: 213160) -USDCBridgeMigrator_releaseOrMint:test_WhileMigrationPause_Revert() (gas: 109679) -USDCBridgeMigrator_releaseOrMint:test_incomingMessageWithPrimaryMechanism() (gas: 265963) -USDCBridgeMigrator_releaseOrMint:test_unstickManualTxAfterMigration_destChain_Success() (gas: 150538) -USDCBridgeMigrator_releaseOrMint:test_unstickManualTxAfterMigration_homeChain_Success() (gas: 511783) -USDCBridgeMigrator_updateChainSelectorMechanism:test_PrimaryMechanism_Success() (gas: 136021) -USDCBridgeMigrator_updateChainSelectorMechanism:test_WhileMigrationPause_Revert() (gas: 109871) -USDCBridgeMigrator_updateChainSelectorMechanism:test_cannotRevertChainMechanism_afterMigration_Revert() (gas: 313532) -USDCBridgeMigrator_updateChainSelectorMechanism:test_invalidPermissions_Revert() (gas: 39471) -USDCBridgeMigrator_updateChainSelectorMechanism:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 310092) -USDCBridgeMigrator_updateChainSelectorMechanism:test_onLockReleaseMechanism_Success() (gas: 147057) -USDCBridgeMigrator_updateChainSelectorMechanism:test_onLockReleaseMechanism_thenSwitchToPrimary_Success() (gas: 209483) -USDCTokenPool__validateMessage:test_ValidateInvalidMessage_Revert() (gas: 26049) -USDCTokenPool_lockOrBurn:test_CallerIsNotARampOnRouter_Revert() (gas: 35319) -USDCTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 29897) -USDCTokenPool_lockOrBurn:test_LockOrBurn_Success() (gas: 133426) -USDCTokenPool_lockOrBurn:test_UnknownDomain_Revert() (gas: 433430) -USDCTokenPool_releaseOrMint:test_ReleaseOrMintRealTx_Success() (gas: 265695) -USDCTokenPool_releaseOrMint:test_TokenMaxCapacityExceeded_Revert() (gas: 47231) -USDCTokenPool_releaseOrMint:test_UnlockingUSDCFailed_Revert() (gas: 95262) -USDCTokenPool_setDomains:test_InvalidDomain_Revert() (gas: 66437) -USDCTokenPool_setDomains:test_OnlyOwner_Revert() (gas: 11314) -USDCTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 10107) \ No newline at end of file +TokenPool_constructor:test_constructor_DecimalCallFails() (gas: 2836717) +TokenPool_getRemotePool:test_getRemotePools() (gas: 330476) +TokenPool_onlyOffRamp:test_onlyOffRamp() (gas: 94348) +TokenPool_onlyOnRamp:test_onlyOnRamp() (gas: 49257) +TokenPool_parseRemoteDecimals:test_parseRemoteDecimals() (gas: 14030) +TokenPool_parseRemoteDecimals:test_parseRemoteDecimals_NoDecimalsDefaultsToLocalDecimals() (gas: 9705) +TokenPool_removeRemotePool:test_removeRemotePool() (gas: 188402) +TokenPool_setRateLimitAdmin:test_SetRateLimitAdmin() (gas: 37630) +USDCBridgeMigrator_BurnLockedUSDC:test_PrimaryMechanism() (gas: 130502) +USDCBridgeMigrator_BurnLockedUSDC:test_lockOrBurn_then_BurnInCCTPMigration() (gas: 303967) +USDCBridgeMigrator_BurnLockedUSDC:test_onLockReleaseMechanism() (gas: 140236) +USDCBridgeMigrator_BurnLockedUSDC:test_onLockReleaseMechanism_thenSwitchToPrimary() (gas: 203330) +USDCBridgeMigrator_cancelMigrationProposal:test_cancelExistingCCTPMigrationProposal() (gas: 56100) +USDCBridgeMigrator_provideLiquidity:test_PrimaryMechanism() (gas: 130520) +USDCBridgeMigrator_provideLiquidity:test_lockOrBurn_then_BurnInCCTPMigration() (gas: 303967) +USDCBridgeMigrator_provideLiquidity:test_onLockReleaseMechanism() (gas: 140325) +USDCBridgeMigrator_provideLiquidity:test_onLockReleaseMechanism_thenSwitchToPrimary() (gas: 203331) +USDCBridgeMigrator_releaseOrMint:test_OnLockReleaseMechanism() (gas: 206383) +USDCBridgeMigrator_releaseOrMint:test_incomingMessageWithPrimaryMechanism() (gas: 260476) +USDCBridgeMigrator_releaseOrMint:test_unstickManualTxAfterMigration_destChain() (gas: 142853) +USDCBridgeMigrator_releaseOrMint:test_unstickManualTxAfterMigration_homeChain() (gas: 505540) +USDCBridgeMigrator_updateChainSelectorMechanism:test_PrimaryMechanism() (gas: 130502) +USDCBridgeMigrator_updateChainSelectorMechanism:test_lockOrBurn_then_BurnInCCTPMigration() (gas: 303949) +USDCBridgeMigrator_updateChainSelectorMechanism:test_onLockReleaseMechanism() (gas: 140325) +USDCBridgeMigrator_updateChainSelectorMechanism:test_onLockReleaseMechanism_thenSwitchToPrimary() (gas: 203312) +USDCTokenPool_lockOrBurn:test_LockOrBurn() (gas: 128094) +USDCTokenPool_releaseOrMint:test_ReleaseOrMintRealTx() (gas: 260189) +USDCTokenPool_supportsInterface:test_SupportsInterface() (gas: 10108) \ No newline at end of file diff --git a/contracts/gas-snapshots/llo-feeds.gas-snapshot b/contracts/gas-snapshots/llo-feeds.gas-snapshot index 44d08f26645..1dc426f9c1d 100644 --- a/contracts/gas-snapshots/llo-feeds.gas-snapshot +++ b/contracts/gas-snapshots/llo-feeds.gas-snapshot @@ -357,95 +357,279 @@ FeeManagerProcessFeeTest:test_surchargeIsNoLongerAppliedAfterRemoving() (gas: 47 FeeManagerProcessFeeTest:test_surchargeIsNotAppliedForLinkFee() (gas: 49938) FeeManagerProcessFeeTest:test_surchargeIsNotAppliedWith100PercentDiscount() (gas: 78261) FeeManagerProcessFeeTest:test_testRevertIfReportHasExpired() (gas: 14941) +FeeManagerProcessFeeTestV05:test_DiscountIsAppliedForNative() (gas: 52650) +FeeManagerProcessFeeTestV05:test_DiscountIsReturnedForNative() (gas: 52643) +FeeManagerProcessFeeTestV05:test_DiscountIsReturnedForNativeWithSurcharge() (gas: 78900) +FeeManagerProcessFeeTestV05:test_GlobalDiscountCantBeSetToMoreThanMaximum() (gas: 19501) +FeeManagerProcessFeeTestV05:test_GlobalDiscountIsOverridenByIndividualDiscountLink() (gas: 79464) +FeeManagerProcessFeeTestV05:test_GlobalDiscountIsOverridenByIndividualDiscountNative() (gas: 82478) +FeeManagerProcessFeeTestV05:test_GlobalDiscountIsUpdatedAfterBeingSetToZeroLink() (gas: 48284) +FeeManagerProcessFeeTestV05:test_GlobalDiscountIsUpdatedAfterBeingSetToZeroNative() (gas: 51464) +FeeManagerProcessFeeTestV05:test_GlobalDiscountWithLink() (gas: 51813) +FeeManagerProcessFeeTestV05:test_GlobalDiscountWithNative() (gas: 54759) +FeeManagerProcessFeeTestV05:test_GlobalDiscountWithNativeAndLink() (gas: 83629) +FeeManagerProcessFeeTestV05:test_V1PayloadVerifies() (gas: 26980) +FeeManagerProcessFeeTestV05:test_V1PayloadVerifiesAndReturnsChange() (gas: 58936) +FeeManagerProcessFeeTestV05:test_V2PayloadVerifies() (gas: 119040) +FeeManagerProcessFeeTestV05:test_V2PayloadWithoutQuoteFails() (gas: 27395) +FeeManagerProcessFeeTestV05:test_V2PayloadWithoutZeroFee() (gas: 72654) +FeeManagerProcessFeeTestV05:test_WithdrawERC20() (gas: 72726) +FeeManagerProcessFeeTestV05:test_WithdrawNonAdminAddr() (gas: 56309) +FeeManagerProcessFeeTestV05:test_WithdrawUnwrappedNative() (gas: 26463) +FeeManagerProcessFeeTestV05:test_baseFeeIsAppliedForLink() (gas: 19451) +FeeManagerProcessFeeTestV05:test_baseFeeIsAppliedForNative() (gas: 22456) +FeeManagerProcessFeeTestV05:test_correctDiscountIsAppliedWhenBothTokensAreDiscounted() (gas: 91085) +FeeManagerProcessFeeTestV05:test_discountAIsNotAppliedWhenSetForOtherUsers() (gas: 58840) +FeeManagerProcessFeeTestV05:test_discountFeeRoundsDownWhenUneven() (gas: 52850) +FeeManagerProcessFeeTestV05:test_discountIsAppliedForLink() (gas: 49706) +FeeManagerProcessFeeTestV05:test_discountIsAppliedWith100PercentSurcharge() (gas: 78951) +FeeManagerProcessFeeTestV05:test_discountIsNoLongerAppliedAfterRemoving() (gas: 48341) +FeeManagerProcessFeeTestV05:test_discountIsNotAppliedForInvalidTokenAddress() (gas: 17538) +FeeManagerProcessFeeTestV05:test_discountIsNotAppliedToOtherFeeds() (gas: 56844) +FeeManagerProcessFeeTestV05:test_discountIsReturnedForLink() (gas: 49678) +FeeManagerProcessFeeTestV05:test_emptyQuoteRevertsWithError() (gas: 12162) +FeeManagerProcessFeeTestV05:test_eventIsEmittedAfterSurchargeIsSet() (gas: 41378) +FeeManagerProcessFeeTestV05:test_eventIsEmittedIfNotEnoughLink() (gas: 177182) +FeeManagerProcessFeeTestV05:test_eventIsEmittedUponWithdraw() (gas: 69031) +FeeManagerProcessFeeTestV05:test_feeIsUpdatedAfterDiscountIsRemoved() (gas: 51588) +FeeManagerProcessFeeTestV05:test_feeIsUpdatedAfterNewDiscountIsApplied() (gas: 67751) +FeeManagerProcessFeeTestV05:test_feeIsUpdatedAfterNewSurchargeIsApplied() (gas: 66958) +FeeManagerProcessFeeTestV05:test_feeIsZeroWith100PercentDiscount() (gas: 52049) +FeeManagerProcessFeeTestV05:test_getBaseRewardWithLinkQuote() (gas: 19449) +FeeManagerProcessFeeTestV05:test_getLinkFeeIsRoundedUp() (gas: 49855) +FeeManagerProcessFeeTestV05:test_getLinkRewardIsSameAsFee() (gas: 55692) +FeeManagerProcessFeeTestV05:test_getLinkRewardWithNativeQuoteAndSurchargeWithLinkDiscount() (gas: 85071) +FeeManagerProcessFeeTestV05:test_getRewardWithLinkDiscount() (gas: 49702) +FeeManagerProcessFeeTestV05:test_getRewardWithLinkQuoteAndLinkDiscount() (gas: 49683) +FeeManagerProcessFeeTestV05:test_getRewardWithNativeQuote() (gas: 22432) +FeeManagerProcessFeeTestV05:test_getRewardWithNativeQuoteAndSurcharge() (gas: 53166) +FeeManagerProcessFeeTestV05:test_linkAvailableForPaymentReturnsLinkBalance() (gas: 53192) +FeeManagerProcessFeeTestV05:test_nativeSurcharge0Percent() (gas: 33154) +FeeManagerProcessFeeTestV05:test_nativeSurcharge100Percent() (gas: 53191) +FeeManagerProcessFeeTestV05:test_nativeSurchargeCannotExceed100Percent() (gas: 17219) +FeeManagerProcessFeeTestV05:test_nativeSurchargeEventIsEmittedOnUpdate() (gas: 41424) +FeeManagerProcessFeeTestV05:test_noFeeIsAppliedWhenReportHasZeroFee() (gas: 51894) +FeeManagerProcessFeeTestV05:test_noFeeIsAppliedWhenReportHasZeroFeeAndDiscountAndSurchargeIsSet() (gas: 78129) +FeeManagerProcessFeeTestV05:test_nonAdminProxyUserCannotProcessFee() (gas: 21895) +FeeManagerProcessFeeTestV05:test_nonAdminUserCanNotSetDiscount() (gas: 19806) +FeeManagerProcessFeeTestV05:test_onlyOwnerCanSetGlobalDiscount() (gas: 19842) +FeeManagerProcessFeeTestV05:test_payLinkDeficit() (gas: 196279) +FeeManagerProcessFeeTestV05:test_payLinkDeficitOnlyCallableByAdmin() (gas: 17413) +FeeManagerProcessFeeTestV05:test_payLinkDeficitPaysAllFeesProcessed() (gas: 216836) +FeeManagerProcessFeeTestV05:test_payLinkDeficitTwice() (gas: 200635) +FeeManagerProcessFeeTestV05:test_processFeeAsProxy() (gas: 119378) +FeeManagerProcessFeeTestV05:test_processFeeDefaultReportsStillVerifiesWithEmptyQuote() (gas: 27468) +FeeManagerProcessFeeTestV05:test_processFeeEmitsEventIfNotEnoughLink() (gas: 165495) +FeeManagerProcessFeeTestV05:test_processFeeIfSubscriberIsSelf() (gas: 30333) +FeeManagerProcessFeeTestV05:test_processFeeNative() (gas: 176116) +FeeManagerProcessFeeTestV05:test_processFeeUsesCorrectDigest() (gas: 120669) +FeeManagerProcessFeeTestV05:test_processFeeWithDefaultReportPayloadAndQuoteStillVerifies() (gas: 29542) +FeeManagerProcessFeeTestV05:test_processFeeWithDiscountEmitsEvent() (gas: 241463) +FeeManagerProcessFeeTestV05:test_processFeeWithInvalidReportVersionFailsToDecode() (gas: 28517) +FeeManagerProcessFeeTestV05:test_processFeeWithNoDiscountDoesNotEmitEvent() (gas: 169043) +FeeManagerProcessFeeTestV05:test_processFeeWithUnwrappedNative() (gas: 183981) +FeeManagerProcessFeeTestV05:test_processFeeWithUnwrappedNativeLinkAddress() (gas: 133756) +FeeManagerProcessFeeTestV05:test_processFeeWithUnwrappedNativeLinkAddressExcessiveFee() (gas: 159388) +FeeManagerProcessFeeTestV05:test_processFeeWithUnwrappedNativeShortFunds() (gas: 94925) +FeeManagerProcessFeeTestV05:test_processFeeWithUnwrappedNativeWithExcessiveFee() (gas: 190970) +FeeManagerProcessFeeTestV05:test_processFeeWithWithCorruptQuotePayload() (gas: 72965) +FeeManagerProcessFeeTestV05:test_processFeeWithWithEmptyQuotePayload() (gas: 27733) +FeeManagerProcessFeeTestV05:test_processFeeWithWithZeroQuotePayload() (gas: 27783) +FeeManagerProcessFeeTestV05:test_processFeeWithZeroLinkNonZeroNativeWithLinkQuote() (gas: 35257) +FeeManagerProcessFeeTestV05:test_processFeeWithZeroLinkNonZeroNativeWithNativeQuote() (gas: 156015) +FeeManagerProcessFeeTestV05:test_processFeeWithZeroNativeNonZeroLinkReturnsChange() (gas: 56111) +FeeManagerProcessFeeTestV05:test_processFeeWithZeroNativeNonZeroLinkWithLinkQuote() (gas: 119289) +FeeManagerProcessFeeTestV05:test_processFeeWithZeroNativeNonZeroLinkWithNativeQuote() (gas: 38028) +FeeManagerProcessFeeTestV05:test_processMultipleLinkReports() (gas: 226585) +FeeManagerProcessFeeTestV05:test_processMultipleUnwrappedNativeReports() (gas: 260448) +FeeManagerProcessFeeTestV05:test_processMultipleV1Reports() (gas: 74825) +FeeManagerProcessFeeTestV05:test_processMultipleWrappedNativeReports() (gas: 243227) +FeeManagerProcessFeeTestV05:test_processV1V2V3Reports() (gas: 211066) +FeeManagerProcessFeeTestV05:test_processV1V2V3ReportsWithUnwrapped() (gas: 252722) +FeeManagerProcessFeeTestV05:test_reportWithNoExpiryOrFeeReturnsZero() (gas: 13591) +FeeManagerProcessFeeTestV05:test_setDiscountOver100Percent() (gas: 19584) +FeeManagerProcessFeeTestV05:test_subscriberDiscountEventIsEmittedOnUpdate() (gas: 46261) +FeeManagerProcessFeeTestV05:test_surchargeFeeRoundsUpWhenUneven() (gas: 53500) +FeeManagerProcessFeeTestV05:test_surchargeIsApplied() (gas: 53447) +FeeManagerProcessFeeTestV05:test_surchargeIsAppliedForNativeFeeWithDiscount() (gas: 79313) +FeeManagerProcessFeeTestV05:test_surchargeIsNoLongerAppliedAfterRemoving() (gas: 49165) +FeeManagerProcessFeeTestV05:test_surchargeIsNotAppliedForLinkFee() (gas: 52244) +FeeManagerProcessFeeTestV05:test_surchargeIsNotAppliedWith100PercentDiscount() (gas: 78309) +FeeManagerProcessFeeTestV05:test_testRevertIfReportHasExpired() (gas: 14941) MultiVerifierBillingTests:test_multipleFeeManagersAndVerifiers() (gas: 4598496) RewardManagerClaimTest:test_claimAllRecipients() (gas: 277131) +RewardManagerClaimTest:test_claimAllRecipients() (gas: 277131) +RewardManagerClaimTest:test_claimMultipleRecipients() (gas: 154341) RewardManagerClaimTest:test_claimMultipleRecipients() (gas: 154341) RewardManagerClaimTest:test_claimRewardsWithDuplicatePoolIdsDoesNotPayoutTwice() (gas: 330086) +RewardManagerClaimTest:test_claimRewardsWithDuplicatePoolIdsDoesNotPayoutTwice() (gas: 330086) RewardManagerClaimTest:test_claimSingleRecipient() (gas: 89024) +RewardManagerClaimTest:test_claimSingleRecipient() (gas: 89024) +RewardManagerClaimTest:test_claimUnevenAmountRoundsDown() (gas: 315289) RewardManagerClaimTest:test_claimUnevenAmountRoundsDown() (gas: 315289) RewardManagerClaimTest:test_claimUnregisteredPoolId() (gas: 35123) +RewardManagerClaimTest:test_claimUnregisteredPoolId() (gas: 35123) RewardManagerClaimTest:test_claimUnregisteredRecipient() (gas: 41182) +RewardManagerClaimTest:test_claimUnregisteredRecipient() (gas: 41182) +RewardManagerClaimTest:test_eventIsEmittedUponClaim() (gas: 86069) RewardManagerClaimTest:test_eventIsEmittedUponClaim() (gas: 86069) RewardManagerClaimTest:test_eventIsNotEmittedUponUnsuccessfulClaim() (gas: 25031) +RewardManagerClaimTest:test_eventIsNotEmittedUponUnsuccessfulClaim() (gas: 25031) RewardManagerClaimTest:test_recipientsClaimMultipleDeposits() (gas: 386675) +RewardManagerClaimTest:test_recipientsClaimMultipleDeposits() (gas: 386675) +RewardManagerClaimTest:test_singleRecipientClaimMultipleDeposits() (gas: 137663) RewardManagerClaimTest:test_singleRecipientClaimMultipleDeposits() (gas: 137663) RewardManagerNoRecipientSet:test_claimAllRecipientsAfterRecipientsSet() (gas: 492113) +RewardManagerNoRecipientSet:test_claimAllRecipientsAfterRecipientsSet() (gas: 492113) RewardManagerPayRecipientsTest:test_addFundsToPoolAsNonOwnerOrFeeManager() (gas: 11451) +RewardManagerPayRecipientsTest:test_addFundsToPoolAsNonOwnerOrFeeManager() (gas: 11451) +RewardManagerPayRecipientsTest:test_addFundsToPoolAsOwner() (gas: 53912) RewardManagerPayRecipientsTest:test_addFundsToPoolAsOwner() (gas: 53912) RewardManagerPayRecipientsTest:test_payAllRecipients() (gas: 250840) +RewardManagerPayRecipientsTest:test_payAllRecipients() (gas: 250840) RewardManagerPayRecipientsTest:test_payAllRecipientsFromNonAdminUser() (gas: 20475) +RewardManagerPayRecipientsTest:test_payAllRecipientsFromNonAdminUser() (gas: 20475) +RewardManagerPayRecipientsTest:test_payAllRecipientsFromRecipientInPool() (gas: 251064) RewardManagerPayRecipientsTest:test_payAllRecipientsFromRecipientInPool() (gas: 251064) RewardManagerPayRecipientsTest:test_payAllRecipientsWithAdditionalInvalidRecipient() (gas: 262268) +RewardManagerPayRecipientsTest:test_payAllRecipientsWithAdditionalInvalidRecipient() (gas: 262268) RewardManagerPayRecipientsTest:test_payAllRecipientsWithAdditionalUnregisteredRecipient() (gas: 265753) +RewardManagerPayRecipientsTest:test_payAllRecipientsWithAdditionalUnregisteredRecipient() (gas: 265753) +RewardManagerPayRecipientsTest:test_payRecipientWithInvalidPool() (gas: 28869) RewardManagerPayRecipientsTest:test_payRecipientWithInvalidPool() (gas: 28869) RewardManagerPayRecipientsTest:test_payRecipientsEmptyRecipientList() (gas: 25335) +RewardManagerPayRecipientsTest:test_payRecipientsEmptyRecipientList() (gas: 25335) RewardManagerPayRecipientsTest:test_payRecipientsWithInvalidPoolId() (gas: 31397) +RewardManagerPayRecipientsTest:test_payRecipientsWithInvalidPoolId() (gas: 31397) +RewardManagerPayRecipientsTest:test_paySingleRecipient() (gas: 84740) RewardManagerPayRecipientsTest:test_paySingleRecipient() (gas: 84740) RewardManagerPayRecipientsTest:test_paySubsetOfRecipientsInPool() (gas: 198455) +RewardManagerPayRecipientsTest:test_paySubsetOfRecipientsInPool() (gas: 198455) +RewardManagerRecipientClaimDifferentWeightsTest:test_allRecipientsClaimingReceiveExpectedAmount() (gas: 280727) RewardManagerRecipientClaimDifferentWeightsTest:test_allRecipientsClaimingReceiveExpectedAmount() (gas: 280727) RewardManagerRecipientClaimMultiplePoolsTest:test_claimAllRecipientsMultiplePools() (gas: 512369) +RewardManagerRecipientClaimMultiplePoolsTest:test_claimAllRecipientsMultiplePools() (gas: 512369) RewardManagerRecipientClaimMultiplePoolsTest:test_claimAllRecipientsSinglePool() (gas: 283634) +RewardManagerRecipientClaimMultiplePoolsTest:test_claimAllRecipientsSinglePool() (gas: 283634) +RewardManagerRecipientClaimMultiplePoolsTest:test_claimEmptyPoolWhenSecondPoolContainsFunds() (gas: 293418) RewardManagerRecipientClaimMultiplePoolsTest:test_claimEmptyPoolWhenSecondPoolContainsFunds() (gas: 293418) RewardManagerRecipientClaimMultiplePoolsTest:test_claimMultipleRecipientsMultiplePools() (gas: 263015) +RewardManagerRecipientClaimMultiplePoolsTest:test_claimMultipleRecipientsMultiplePools() (gas: 263015) RewardManagerRecipientClaimMultiplePoolsTest:test_claimMultipleRecipientsSinglePool() (gas: 154485) +RewardManagerRecipientClaimMultiplePoolsTest:test_claimMultipleRecipientsSinglePool() (gas: 154485) +RewardManagerRecipientClaimMultiplePoolsTest:test_claimSingleRecipientMultiplePools() (gas: 132623) RewardManagerRecipientClaimMultiplePoolsTest:test_claimSingleRecipientMultiplePools() (gas: 132623) RewardManagerRecipientClaimMultiplePoolsTest:test_claimSingleUniqueRecipient() (gas: 106022) +RewardManagerRecipientClaimMultiplePoolsTest:test_claimSingleUniqueRecipient() (gas: 106022) RewardManagerRecipientClaimMultiplePoolsTest:test_claimUnevenAmountRoundsDown() (gas: 579532) +RewardManagerRecipientClaimMultiplePoolsTest:test_claimUnevenAmountRoundsDown() (gas: 579532) +RewardManagerRecipientClaimMultiplePoolsTest:test_claimUnregisteredRecipient() (gas: 64626) RewardManagerRecipientClaimMultiplePoolsTest:test_claimUnregisteredRecipient() (gas: 64626) RewardManagerRecipientClaimMultiplePoolsTest:test_getAvailableRewardsCursorAndTotalPoolsEqual() (gas: 13029) +RewardManagerRecipientClaimMultiplePoolsTest:test_getAvailableRewardsCursorAndTotalPoolsEqual() (gas: 13029) RewardManagerRecipientClaimMultiplePoolsTest:test_getAvailableRewardsCursorCannotBeGreaterThanTotalPools() (gas: 12724) +RewardManagerRecipientClaimMultiplePoolsTest:test_getAvailableRewardsCursorCannotBeGreaterThanTotalPools() (gas: 12724) +RewardManagerRecipientClaimMultiplePoolsTest:test_getAvailableRewardsCursorSingleResult() (gas: 22426) RewardManagerRecipientClaimMultiplePoolsTest:test_getAvailableRewardsCursorSingleResult() (gas: 22426) RewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInBothPools() (gas: 32225) +RewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInBothPools() (gas: 32225) RewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInBothPoolsWhereAlreadyClaimed() (gas: 148553) +RewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInBothPoolsWhereAlreadyClaimed() (gas: 148553) +RewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInNoPools() (gas: 21683) RewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInNoPools() (gas: 21683) RewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInSinglePool() (gas: 27742) +RewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInSinglePool() (gas: 27742) RewardManagerRecipientClaimMultiplePoolsTest:test_recipientsClaimMultipleDeposits() (gas: 391245) +RewardManagerRecipientClaimMultiplePoolsTest:test_recipientsClaimMultipleDeposits() (gas: 391245) +RewardManagerRecipientClaimMultiplePoolsTest:test_singleRecipientClaimMultipleDeposits() (gas: 137748) RewardManagerRecipientClaimMultiplePoolsTest:test_singleRecipientClaimMultipleDeposits() (gas: 137748) RewardManagerRecipientClaimUnevenWeightTest:test_allRecipientsClaimingReceiveExpectedAmount() (gas: 199454) +RewardManagerRecipientClaimUnevenWeightTest:test_allRecipientsClaimingReceiveExpectedAmount() (gas: 199454) RewardManagerRecipientClaimUnevenWeightTest:test_allRecipientsClaimingReceiveExpectedAmountWithSmallDeposit() (gas: 219327) +RewardManagerRecipientClaimUnevenWeightTest:test_allRecipientsClaimingReceiveExpectedAmountWithSmallDeposit() (gas: 219327) +RewardManagerSetRecipientsTest:test_eventIsEmittedUponSetRecipients() (gas: 191707) RewardManagerSetRecipientsTest:test_eventIsEmittedUponSetRecipients() (gas: 191707) RewardManagerSetRecipientsTest:test_setRecipientContainsDuplicateRecipients() (gas: 126082) +RewardManagerSetRecipientsTest:test_setRecipientContainsDuplicateRecipients() (gas: 126082) +RewardManagerSetRecipientsTest:test_setRewardRecipientFromManagerAddress() (gas: 193880) RewardManagerSetRecipientsTest:test_setRewardRecipientFromManagerAddress() (gas: 193880) RewardManagerSetRecipientsTest:test_setRewardRecipientFromNonOwnerOrFeeManagerAddress() (gas: 21452) +RewardManagerSetRecipientsTest:test_setRewardRecipientFromNonOwnerOrFeeManagerAddress() (gas: 21452) RewardManagerSetRecipientsTest:test_setRewardRecipientTwice() (gas: 193368) +RewardManagerSetRecipientsTest:test_setRewardRecipientTwice() (gas: 193368) +RewardManagerSetRecipientsTest:test_setRewardRecipientWeights() (gas: 180630) RewardManagerSetRecipientsTest:test_setRewardRecipientWeights() (gas: 180630) RewardManagerSetRecipientsTest:test_setRewardRecipientWithZeroAddress() (gas: 90224) +RewardManagerSetRecipientsTest:test_setRewardRecipientWithZeroAddress() (gas: 90224) RewardManagerSetRecipientsTest:test_setRewardRecipientWithZeroWeight() (gas: 191334) +RewardManagerSetRecipientsTest:test_setRewardRecipientWithZeroWeight() (gas: 191334) +RewardManagerSetRecipientsTest:test_setRewardRecipients() (gas: 185589) RewardManagerSetRecipientsTest:test_setRewardRecipients() (gas: 185589) RewardManagerSetRecipientsTest:test_setRewardRecipientsIsEmpty() (gas: 87136) +RewardManagerSetRecipientsTest:test_setRewardRecipientsIsEmpty() (gas: 87136) RewardManagerSetRecipientsTest:test_setSingleRewardRecipient() (gas: 110371) +RewardManagerSetRecipientsTest:test_setSingleRewardRecipient() (gas: 110371) +RewardManagerSetupTest:test_eventEmittedUponFeeManagerUpdate() (gas: 21366) RewardManagerSetupTest:test_eventEmittedUponFeeManagerUpdate() (gas: 21366) RewardManagerSetupTest:test_eventEmittedUponFeePaid() (gas: 259132) +RewardManagerSetupTest:test_eventEmittedUponFeePaid() (gas: 259132) RewardManagerSetupTest:test_rejectsZeroLinkAddressOnConstruction() (gas: 59411) +RewardManagerSetupTest:test_rejectsZeroLinkAddressOnConstruction() (gas: 59411) +RewardManagerSetupTest:test_setFeeManagerZeroAddress() (gas: 17105) RewardManagerSetupTest:test_setFeeManagerZeroAddress() (gas: 17105) RewardManagerUpdateRewardRecipientsMultiplePoolsTest:test_updatePrimaryRecipientWeights() (gas: 376628) +RewardManagerUpdateRewardRecipientsMultiplePoolsTest:test_updatePrimaryRecipientWeights() (gas: 376628) RewardManagerUpdateRewardRecipientsTest:test_eventIsEmittedUponUpdateRecipients() (gas: 280509) +RewardManagerUpdateRewardRecipientsTest:test_eventIsEmittedUponUpdateRecipients() (gas: 280509) +RewardManagerUpdateRewardRecipientsTest:test_onlyAdminCanUpdateRecipients() (gas: 19749) RewardManagerUpdateRewardRecipientsTest:test_onlyAdminCanUpdateRecipients() (gas: 19749) RewardManagerUpdateRewardRecipientsTest:test_partialUpdateRecipientWeights() (gas: 220972) +RewardManagerUpdateRewardRecipientsTest:test_partialUpdateRecipientWeights() (gas: 220972) RewardManagerUpdateRewardRecipientsTest:test_updateAllRecipientsWithSameAddressAndWeight() (gas: 274309) +RewardManagerUpdateRewardRecipientsTest:test_updateAllRecipientsWithSameAddressAndWeight() (gas: 274309) +RewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsToSubset() (gas: 254232) RewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsToSubset() (gas: 254232) RewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsWithExcessiveWeight() (gas: 259219) +RewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsWithExcessiveWeight() (gas: 259219) RewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsWithSameAddressAndWeight() (gas: 149916) +RewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsWithSameAddressAndWeight() (gas: 149916) +RewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsWithUnderWeightSet() (gas: 259293) RewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsWithUnderWeightSet() (gas: 259293) RewardManagerUpdateRewardRecipientsTest:test_updateRecipientWeights() (gas: 372109) +RewardManagerUpdateRewardRecipientsTest:test_updateRecipientWeights() (gas: 372109) +RewardManagerUpdateRewardRecipientsTest:test_updateRecipientWithNewZeroAddress() (gas: 270802) RewardManagerUpdateRewardRecipientsTest:test_updateRecipientWithNewZeroAddress() (gas: 270802) RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsContainsDuplicateRecipients() (gas: 288575) +RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsContainsDuplicateRecipients() (gas: 288575) RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentLargerSet() (gas: 407876) +RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentLargerSet() (gas: 407876) +RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentPartialSet() (gas: 318029) RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentPartialSet() (gas: 318029) RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentSet() (gas: 377784) +RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentSet() (gas: 377784) RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentSetWithInvalidWeights() (gas: 312122) +RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentSetWithInvalidWeights() (gas: 312122) +RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsUpdateAndRemoveExistingForLargerSet() (gas: 399699) RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsUpdateAndRemoveExistingForLargerSet() (gas: 399699) RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsUpdateAndRemoveExistingForSmallerSet() (gas: 289513) +RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsUpdateAndRemoveExistingForSmallerSet() (gas: 289513) VerificationdeactivateConfigWhenThereAreMultipleDigestsTest:test_correctlyRemovesAMiddleDigest() (gas: 27017) VerificationdeactivateConfigWhenThereAreMultipleDigestsTest:test_correctlyRemovesTheFirstDigest() (gas: 27007) VerificationdeactivateConfigWhenThereAreMultipleDigestsTest:test_correctlyUnsetsDigestsInSequence() (gas: 45102) VerificationdeactivateConfigWhenThereAreMultipleDigestsTest:test_revertsIfCalledByNonOwner() (gas: 15016) VerificationdeactivateConfigWhenThereAreMultipleDigestsTest:test_revertsIfRemovingAnEmptyDigest() (gas: 10907) VerificationdeactivateConfigWhenThereAreMultipleDigestsTest:test_revertsIfRemovingAnNonExistentDigest() (gas: 13381) +VerificationdeactivateConfigWhenThereAreMultipleDigestsTestV05:test_revertsIfCalledByNonOwner() (gas: 14977) +VerificationdeactivateConfigWhenThereAreMultipleDigestsTestV05:test_revertsIfRemovingAnEmptyDigest() (gas: 10891) +VerificationdeactivateConfigWhenThereAreMultipleDigestsTestV05:test_revertsIfRemovingAnNonExistentDigest() (gas: 13195) VerifierActivateConfigTest:test_revertsIfDigestIsEmpty() (gas: 10962) VerifierActivateConfigTest:test_revertsIfDigestNotSet() (gas: 13394) VerifierActivateConfigTest:test_revertsIfNotOwner() (gas: 17182) +VerifierActivateConfigTestV05:test_revertsIfDigestIsEmpty() (gas: 10903) +VerifierActivateConfigTestV05:test_revertsIfDigestNotSet() (gas: 13154) +VerifierActivateConfigTestV05:test_revertsIfNotOwner() (gas: 17123) VerifierActivateConfigWithDeactivatedConfigTest:test_allowsVerification() (gas: 97175) +VerifierActivateConfigWithDeactivatedConfigTestV05:test_allowsVerification() (gas: 94200) VerifierActivateFeedTest:test_revertsIfNoFeedExistsActivate() (gas: 13179) VerifierActivateFeedTest:test_revertsIfNoFeedExistsDeactivate() (gas: 13202) VerifierActivateFeedTest:test_revertsIfNotOwnerActivateFeed() (gas: 17109) @@ -463,8 +647,16 @@ VerifierBulkVerifyBillingReport:test_verifyWithBulkLink() (gas: 557541) VerifierBulkVerifyBillingReport:test_verifyWithBulkNative() (gas: 560806) VerifierBulkVerifyBillingReport:test_verifyWithBulkNativeUnwrapped() (gas: 568629) VerifierBulkVerifyBillingReport:test_verifyWithBulkNativeUnwrappedReturnsChange() (gas: 575635) +VerifierBulkVerifyBillingReportV05:test_verifyMultiVersions() (gas: 473747) +VerifierBulkVerifyBillingReportV05:test_verifyMultiVersionsReturnsVerifiedReports() (gas: 472005) +VerifierBulkVerifyBillingReportV05:test_verifyWithBulkLink() (gas: 556573) +VerifierBulkVerifyBillingReportV05:test_verifyWithBulkNative() (gas: 559838) +VerifierBulkVerifyBillingReportV05:test_verifyWithBulkNativeUnwrapped() (gas: 567661) +VerifierBulkVerifyBillingReportV05:test_verifyWithBulkNativeUnwrappedReturnsChange() (gas: 574763) VerifierConstructorTest:test_revertsIfInitializedWithEmptyVerifierProxy() (gas: 59960) VerifierConstructorTest:test_setsTheCorrectProperties() (gas: 1813269) +VerifierConstructorTestV05:test_revertsIfInitializedWithEmptyVerifierProxy() (gas: 59657) +VerifierConstructorTestV05:test_setsTheCorrectProperties() (gas: 1530840) VerifierDeactivateFeedWithVerifyTest:test_currentReportAllowsVerification() (gas: 192073) VerifierDeactivateFeedWithVerifyTest:test_currentReportFailsVerification() (gas: 113388) VerifierDeactivateFeedWithVerifyTest:test_previousReportAllowsVerification() (gas: 99669) @@ -472,9 +664,14 @@ VerifierDeactivateFeedWithVerifyTest:test_previousReportFailsVerification() (gas VerifierInterfacesTest:test_DestinationContractInterfaces() (gas: 628150) VerifierProxyAccessControlledVerificationTest:test_proxiesToTheVerifierIfHasAccess() (gas: 208507) VerifierProxyAccessControlledVerificationTest:test_revertsIfNoAccess() (gas: 112323) +VerifierProxyAccessControlledVerificationTestV05:test_proxiesToTheVerifierIfHasAccess() (gas: 206027) +VerifierProxyAccessControlledVerificationTestV05:test_revertsIfNoAccess() (gas: 112323) VerifierProxyConstructorTest:test_correctlySetsTheCorrectAccessControllerInterface() (gas: 1485337) +VerifierProxyConstructorTest:test_correctlySetsTheCorrectAccessControllerInterface() (gas: 1485337) +VerifierProxyConstructorTest:test_correctlySetsTheOwner() (gas: 1465483) VerifierProxyConstructorTest:test_correctlySetsTheOwner() (gas: 1465483) VerifierProxyConstructorTest:test_correctlySetsVersion() (gas: 9767) +VerifierProxyConstructorTest:test_correctlySetsVersion() (gas: 9767) VerifierProxyInitializeVerifierTest:test_revertsIfDigestAlreadySet() (gas: 54117) VerifierProxyInitializeVerifierTest:test_revertsIfNotCorrectVerifier() (gas: 13613) VerifierProxyInitializeVerifierTest:test_revertsIfNotOwner() (gas: 17168) @@ -484,16 +681,35 @@ VerifierProxyInitializeVerifierTest:test_setFeeManagerWhichDoesntHonourIERC165In VerifierProxyInitializeVerifierTest:test_setFeeManagerWhichDoesntHonourInterface() (gas: 16290) VerifierProxyInitializeVerifierTest:test_setFeeManagerZeroAddress() (gas: 10911) VerifierProxyInitializeVerifierTest:test_updatesVerifierIfVerifier() (gas: 54086) +VerifierProxyInitializeVerifierTestV05:test_revertsIfDigestAlreadySet() (gas: 48384) +VerifierProxyInitializeVerifierTestV05:test_revertsIfNotCorrectVerifier() (gas: 13613) +VerifierProxyInitializeVerifierTestV05:test_revertsIfNotOwner() (gas: 17168) +VerifierProxyInitializeVerifierTestV05:test_revertsIfVerifierAlreadyInitialized() (gas: 42053) +VerifierProxyInitializeVerifierTestV05:test_revertsIfZeroAddress() (gas: 10956) +VerifierProxyInitializeVerifierTestV05:test_setFeeManagerWhichDoesntHonourIERC165Interface() (gas: 13890) +VerifierProxyInitializeVerifierTestV05:test_setFeeManagerWhichDoesntHonourInterface() (gas: 16290) +VerifierProxyInitializeVerifierTestV05:test_setFeeManagerZeroAddress() (gas: 10911) +VerifierProxyInitializeVerifierTestV05:test_updatesVerifierIfVerifier() (gas: 48356) +VerifierProxySetAccessControllerTest:test_emitsTheCorrectEvent() (gas: 35348) VerifierProxySetAccessControllerTest:test_emitsTheCorrectEvent() (gas: 35348) VerifierProxySetAccessControllerTest:test_revertsIfCalledByNonOwner() (gas: 15025) +VerifierProxySetAccessControllerTest:test_revertsIfCalledByNonOwner() (gas: 15025) VerifierProxySetAccessControllerTest:test_successfullySetsNewAccessController() (gas: 34921) +VerifierProxySetAccessControllerTest:test_successfullySetsNewAccessController() (gas: 34921) +VerifierProxySetAccessControllerTest:test_successfullySetsNewAccessControllerIsEmpty() (gas: 15065) VerifierProxySetAccessControllerTest:test_successfullySetsNewAccessControllerIsEmpty() (gas: 15065) VerifierProxyUnsetVerifierTest:test_revertsIfDigestDoesNotExist() (gas: 13149) +VerifierProxyUnsetVerifierTest:test_revertsIfDigestDoesNotExist() (gas: 13149) VerifierProxyUnsetVerifierTest:test_revertsIfNotAdmin() (gas: 14973) +VerifierProxyUnsetVerifierTest:test_revertsIfNotAdmin() (gas: 14973) +VerifierProxyUnsetVerifierWithPreviouslySetVerifierTest:test_correctlyUnsetsVerifier() (gas: 15555) VerifierProxyUnsetVerifierWithPreviouslySetVerifierTest:test_correctlyUnsetsVerifier() (gas: 15555) VerifierProxyUnsetVerifierWithPreviouslySetVerifierTest:test_emitsAnEventAfterUnsettingVerifier() (gas: 17985) +VerifierProxyUnsetVerifierWithPreviouslySetVerifierTest:test_emitsAnEventAfterUnsettingVerifier() (gas: 17985) VerifierProxyVerifyTest:test_proxiesToTheCorrectVerifier() (gas: 204342) VerifierProxyVerifyTest:test_revertsIfNoVerifierConfigured() (gas: 117331) +VerifierProxyVerifyTestV05:test_proxiesToTheCorrectVerifier() (gas: 201862) +VerifierProxyVerifyTestV05:test_revertsIfNoVerifierConfigured() (gas: 117331) VerifierSetAccessControllerTest:test_revertsIfCalledByNonOwner() (gas: 17152) VerifierSetAccessControllerTest:test_setFeeManagerWhichDoesntHonourInterface() (gas: 16272) VerifierSetAccessControllerTest:test_successfullySetsNewFeeManager() (gas: 42214) @@ -508,15 +724,41 @@ VerifierSetConfigTest:test_revertsIfFaultToleranceIsZero() (gas: 176543) VerifierSetConfigTest:test_revertsIfNotEnoughSigners() (gas: 15842) VerifierSetConfigTest:test_revertsIfSetWithTooManySigners() (gas: 22182) VerifierSetConfigTest:test_revertsIfSignerContainsZeroAddress() (gas: 228025) +VerifierSetConfigTestV05:test_correctlyUpdatesTheConfig() (gas: 1022171) +VerifierSetConfigTestV05:test_revertsIfCalledByNonOwner() (gas: 213898) +VerifierSetConfigTestV05:test_revertsIfDuplicateSigners() (gas: 243789) +VerifierSetConfigTestV05:test_revertsIfFaultToleranceIsZero() (gas: 207455) +VerifierSetConfigTestV05:test_revertsIfNotEnoughSigners() (gas: 16407) +VerifierSetConfigTestV05:test_revertsIfSetWithTooManySigners() (gas: 41461) +VerifierSetConfigTestV05:test_revertsIfSignerContainsZeroAddress() (gas: 220308) +VerifierSetConfigWhenThereAreMultipleDigestsTest05:test_configDigestMatchesConfiguratorDigest() (gas: 584372) +VerifierSetConfigWhenThereAreMultipleDigestsTest05:test_correctlySetsConfigWhenDigestsAreRemoved() (gas: 527267) +VerifierSetConfigWhenThereAreMultipleDigestsTest05:test_correctlyUpdatesDigestsOnMultipleVerifiersInTheProxy() (gas: 961409) +VerifierSetConfigWhenThereAreMultipleDigestsTest05:test_correctlyUpdatesTheDigestInTheProxy() (gas: 519967) +VerifierSetConfigWhenThereAreMultipleDigestsTest05:test_incrementalConfigUpdates() (gas: 1424440) +VerifierSetConfigWhenThereAreMultipleDigestsTest05:test_revertsIfDuplicateConfigIsSet() (gas: 545708) VerifierSetConfigWhenThereAreMultipleDigestsTest:test_correctlySetsConfigWhenDigestsAreRemoved() (gas: 542029) VerifierSetConfigWhenThereAreMultipleDigestsTest:test_correctlyUpdatesDigestsOnMultipleVerifiersInTheProxy() (gas: 967324) VerifierSetConfigWhenThereAreMultipleDigestsTest:test_correctlyUpdatesTheDigestInTheProxy() (gas: 522969) VerifierSupportsInterfaceTest:test_falseIfIsNotCorrectInterface() (gas: 8421) +VerifierSupportsInterfaceTest:test_falseIfIsNotCorrectInterface() (gas: 8421) +VerifierSupportsInterfaceTest:test_trueIfIsCorrectInterface() (gas: 8464) VerifierSupportsInterfaceTest:test_trueIfIsCorrectInterface() (gas: 8464) VerifierTestBillingReport:test_verifyWithLink() (gas: 275293) VerifierTestBillingReport:test_verifyWithNative() (gas: 316326) VerifierTestBillingReport:test_verifyWithNativeUnwrapped() (gas: 318619) VerifierTestBillingReport:test_verifyWithNativeUnwrappedReturnsChange() (gas: 325642) +VerifierTestBillingReportV05:test_verifyWithLink() (gas: 275097) +VerifierTestBillingReportV05:test_verifyWithNative() (gas: 316130) +VerifierTestBillingReportV05:test_verifyWithNativeUnwrapped() (gas: 318423) +VerifierTestBillingReportV05:test_verifyWithNativeUnwrappedReturnsChange() (gas: 325542) +VerifierUpdateConfigTest:test_updateConfig() (gas: 673580) +VerifierUpdateConfigTest:test_updateConfigRevertsIfCalledByNonOwner() (gas: 505312) +VerifierUpdateConfigTest:test_updateConfigRevertsIfDigestNotSet() (gas: 92340) +VerifierUpdateConfigTest:test_updateConfigRevertsIfFIsZero() (gas: 500500) +VerifierUpdateConfigTest:test_updateConfigRevertsIfFTooHigh() (gas: 501433) +VerifierUpdateConfigTest:test_updateConfigRevertsIfPrevSignersLengthMismatch() (gas: 526466) +VerifierUpdateConfigTest:test_updateConfigWithDifferentSigners() (gas: 803519) VerifierVerifyBulkTest:test_revertsVerifyBulkIfNoAccess() (gas: 112855) VerifierVerifyBulkTest:test_verifyBulkSingleCaseWithSingleConfig() (gas: 745006) VerifierVerifyBulkTest:test_verifyBulkWithSingleConfigOneVerifyFails() (gas: 698163) @@ -524,16 +766,31 @@ VerifierVerifyMultipleConfigDigestTest:test_canVerifyNewerReportsWithNewerConfig VerifierVerifyMultipleConfigDigestTest:test_canVerifyOlderReportsWithOlderConfigs() (gas: 189843) VerifierVerifyMultipleConfigDigestTest:test_revertsIfAReportIsVerifiedWithAnExistingButIncorrectDigest() (gas: 88216) VerifierVerifyMultipleConfigDigestTest:test_revertsIfVerifyingWithAnUnsetDigest() (gas: 128073) +VerifierVerifyMultipleConfigDigestTestV05:test_canVerifyNewerReportsWithNewerConfigs() (gas: 131504) +VerifierVerifyMultipleConfigDigestTestV05:test_canVerifyOlderReportsWithOlderConfigs() (gas: 187363) +VerifierVerifyMultipleConfigDigestTestV05:test_revertsIfAReportIsVerifiedWithAnExistingButIncorrectDigest() (gas: 85898) +VerifierVerifyMultipleConfigDigestTestV05:test_revertsIfVerifyingWithAnUnsetDigest() (gas: 123076) +VerifierVerifyMultipleConfigDigestTestV05:test_verifyAfterConfigUpdate() (gas: 906142) +VerifierVerifyMultipleConfigDigestTestV05:test_verifyAfterConfigUpdateWithExistingSigners() (gas: 745636) VerifierVerifySingleConfigDigestTest:test_emitsAnEventIfReportVerified() (gas: 186934) -VerifierVerifySingleConfigDigestTest:test_returnsThePriceAndBlockNumIfReportVerified() (gas: 189847) -VerifierVerifySingleConfigDigestTest:test_revertsIfConfigDigestNotSet() (gas: 116184) +VerifierVerifySingleConfigDigestTest:test_returnsThePriceAndBlockNumIfReportVerified() (gas: 189825) +VerifierVerifySingleConfigDigestTest:test_revertsIfConfigDigestNotSet() (gas: 116162) VerifierVerifySingleConfigDigestTest:test_revertsIfDuplicateSignersHaveSigned() (gas: 182371) -VerifierVerifySingleConfigDigestTest:test_revertsIfMismatchedSignatureLength() (gas: 53086) +VerifierVerifySingleConfigDigestTest:test_revertsIfMismatchedSignatureLengthV03() (gas: 53108) VerifierVerifySingleConfigDigestTest:test_revertsIfReportHasUnconfiguredFeedID() (gas: 103987) VerifierVerifySingleConfigDigestTest:test_revertsIfVerifiedByNonProxy() (gas: 100992) -VerifierVerifySingleConfigDigestTest:test_revertsIfVerifiedWithIncorrectAddresses() (gas: 184055) +VerifierVerifySingleConfigDigestTest:test_revertsIfVerifiedWithIncorrectAddresses() (gas: 184100) VerifierVerifySingleConfigDigestTest:test_revertsIfWrongNumberOfSigners() (gas: 110042) -VerifierVerifySingleConfigDigestTest:test_setsTheCorrectEpoch() (gas: 194637) +VerifierVerifySingleConfigDigestTest:test_setsTheCorrectEpoch() (gas: 194615) +VerifierVerifySingleConfigDigestTestV05:test_emitsAnEventIfReportVerified() (gas: 184487) +VerifierVerifySingleConfigDigestTestV05:test_returnsThePriceAndBlockNumIfReportVerified() (gas: 187378) +VerifierVerifySingleConfigDigestTestV05:test_revertsIfConfigDigestNotSet() (gas: 113700) +VerifierVerifySingleConfigDigestTestV05:test_revertsIfDuplicateSignersHaveSigned() (gas: 179780) +VerifierVerifySingleConfigDigestTestV05:test_revertsIfMismatchedSignatureLength() (gas: 50778) +VerifierVerifySingleConfigDigestTestV05:test_revertsIfReportHasUnconfiguredConfigDigest() (gas: 104583) +VerifierVerifySingleConfigDigestTestV05:test_revertsIfVerifiedByNonProxy() (gas: 100947) +VerifierVerifySingleConfigDigestTestV05:test_revertsIfVerifiedWithIncorrectAddresses() (gas: 181509) +VerifierVerifySingleConfigDigestTestV05:test_revertsIfWrongNumberOfSigners() (gas: 107712) VerifierVerifyTest:test_canVerifyNewerReportsWithNewerConfigs() (gas: 862947) VerifierVerifyTest:test_canVerifyOlderV3ReportsWithOlderConfigs() (gas: 815914) VerifierVerifyTest:test_failToVerifyReportIfDupSigners() (gas: 450740) @@ -547,10 +804,18 @@ VerifierVerifyTest:test_verifyFailsWhenReportIsOlderThanConfig() (gas: 2303309) VerifierVerifyTest:test_verifyReport() (gas: 1434779) VerifierVerifyTest:test_verifyTooglingActiveFlagsDonConfigs() (gas: 1918758) Verifier_accessControlledVerify:testVerifyWithAccessControl_gas() (gas: 212077) +Verifier_accessControlledVerifyV05:testVerifyWithAccessControl_gas() (gas: 209597) Verifier_bulkVerifyWithFee:testBulkVerifyProxyWithLinkFeeSuccess_gas() (gas: 519389) Verifier_bulkVerifyWithFee:testBulkVerifyProxyWithNativeFeeSuccess_gas() (gas: 542808) +Verifier_bulkVerifyWithFeeV05:testBulkVerifyProxyWithLinkFeeSuccess_gas() (gas: 518413) +Verifier_bulkVerifyWithFeeV05:testBulkVerifyProxyWithNativeFeeSuccess_gas() (gas: 541832) Verifier_setConfig:testSetConfigSuccess_gas() (gas: 922625) +Verifier_setConfigV05:testSetConfigSuccess_gas() (gas: 895165) Verifier_verify:testVerifyProxySuccess_gas() (gas: 198742) Verifier_verify:testVerifySuccess_gas() (gas: 186736) +Verifier_verifyV05:testVerifyProxySuccess_gas() (gas: 196262) +Verifier_verifyV05:testVerifySuccess_gas() (gas: 184256) Verifier_verifyWithFee:testVerifyProxyWithLinkFeeSuccess_gas() (gas: 238899) -Verifier_verifyWithFee:testVerifyProxyWithNativeFeeSuccess_gas() (gas: 257399) \ No newline at end of file +Verifier_verifyWithFee:testVerifyProxyWithNativeFeeSuccess_gas() (gas: 257399) +Verifier_verifyWithFeeV05:testVerifyProxyWithLinkFeeSuccess_gas() (gas: 238703) +Verifier_verifyWithFeeV05:testVerifyProxyWithNativeFeeSuccess_gas() (gas: 257203) \ No newline at end of file diff --git a/contracts/gas-snapshots/shared.gas-snapshot b/contracts/gas-snapshots/shared.gas-snapshot index 54475701734..fc8096cbb5d 100644 --- a/contracts/gas-snapshots/shared.gas-snapshot +++ b/contracts/gas-snapshots/shared.gas-snapshot @@ -1,111 +1,111 @@ -AuthorizedCallers_applyAuthorizedCallerUpdates:test_AddAndRemove_Success() (gas: 124848) -AuthorizedCallers_applyAuthorizedCallerUpdates:test_OnlyAdd_Success() (gas: 132793) -AuthorizedCallers_applyAuthorizedCallerUpdates:test_OnlyCallableByOwner_Revert() (gas: 12218) -AuthorizedCallers_applyAuthorizedCallerUpdates:test_OnlyRemove_Success() (gas: 44833) -AuthorizedCallers_applyAuthorizedCallerUpdates:test_RemoveThenAdd_Success() (gas: 56901) -AuthorizedCallers_applyAuthorizedCallerUpdates:test_SkipRemove_Success() (gas: 31911) -AuthorizedCallers_applyAuthorizedCallerUpdates:test_ZeroAddressNotAllowed_Revert() (gas: 64612) -AuthorizedCallers_constructor:test_ZeroAddressNotAllowed_Revert() (gas: 64589) -AuthorizedCallers_constructor:test_constructor_Success() (gas: 663486) -BurnMintERC20_approve:test_approve() (gas: 57609) -BurnMintERC20_burn:test_BasicBurn() (gas: 153528) -BurnMintERC20_burnFrom:test_BurnFrom() (gas: 57965) -BurnMintERC20_burnFromAlias:test_burn() (gas: 58009) -BurnMintERC20_constructor:test_Constructor() (gas: 1680059) -BurnMintERC20_getCCIPAdmin:test_getCCIPAdmin() (gas: 10544) -BurnMintERC20_getCCIPAdmin:test_setCCIPAdmin() (gas: 21562) -BurnMintERC20_grantMintAndBurnRoles:test_GrantMintAndBurnRoles() (gas: 79089) -BurnMintERC20_mint:test_mint() (gas: 101815) -BurnMintERC20_supportsInterface:test_SupportsInterface() (gas: 11202) -BurnMintERC20_transfer:test_transfer() (gas: 42318) -BurnMintERC677_approve:testApproveSuccess() (gas: 55477) -BurnMintERC677_approve:testInvalidAddressReverts() (gas: 10653) -BurnMintERC677_burn:testBasicBurnSuccess() (gas: 172022) -BurnMintERC677_burn:testBurnFromZeroAddressReverts() (gas: 47166) -BurnMintERC677_burn:testExceedsBalanceReverts() (gas: 21816) -BurnMintERC677_burn:testSenderNotBurnerReverts() (gas: 13346) -BurnMintERC677_burnFrom:testBurnFromSuccess() (gas: 57928) -BurnMintERC677_burnFrom:testExceedsBalanceReverts() (gas: 35838) -BurnMintERC677_burnFrom:testInsufficientAllowanceReverts() (gas: 21824) -BurnMintERC677_burnFrom:testSenderNotBurnerReverts() (gas: 13346) -BurnMintERC677_burnFromAlias:testBurnFromSuccess() (gas: 57955) -BurnMintERC677_burnFromAlias:testExceedsBalanceReverts() (gas: 35854) -BurnMintERC677_burnFromAlias:testInsufficientAllowanceReverts() (gas: 21844) -BurnMintERC677_burnFromAlias:testSenderNotBurnerReverts() (gas: 13366) -BurnMintERC677_constructor:testConstructorSuccess() (gas: 1651040) -BurnMintERC677_decreaseApproval:testDecreaseApprovalSuccess() (gas: 31049) -BurnMintERC677_grantMintAndBurnRoles:testGrantMintAndBurnRolesSuccess() (gas: 121279) -BurnMintERC677_grantRole:testGrantBurnAccessSuccess() (gas: 53402) -BurnMintERC677_grantRole:testGrantManySuccess() (gas: 937593) -BurnMintERC677_grantRole:testGrantMintAccessSuccess() (gas: 94280) -BurnMintERC677_increaseApproval:testIncreaseApprovalSuccess() (gas: 44052) -BurnMintERC677_mint:testBasicMintSuccess() (gas: 149664) -BurnMintERC677_mint:testMaxSupplyExceededReverts() (gas: 50323) -BurnMintERC677_mint:testSenderNotMinterReverts() (gas: 11182) -BurnMintERC677_supportsInterface:testConstructorSuccess() (gas: 12455) -BurnMintERC677_transfer:testInvalidAddressReverts() (gas: 10629) -BurnMintERC677_transfer:testTransferSuccess() (gas: 42279) -CallWithExactGas__callWithExactGas:test_CallWithExactGasReceiverErrorSuccess() (gas: 65883) -CallWithExactGas__callWithExactGas:test_CallWithExactGasSafeReturnDataExactGas() (gas: 18293) -CallWithExactGas__callWithExactGas:test_NoContractReverts() (gas: 11544) -CallWithExactGas__callWithExactGas:test_NoGasForCallExactCheckReverts() (gas: 15760) -CallWithExactGas__callWithExactGas:test_NotEnoughGasForCallReverts() (gas: 16210) -CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_CallWithExactGasEvenIfTargetIsNoContractExactGasSuccess() (gas: 20033) -CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_CallWithExactGasEvenIfTargetIsNoContractReceiverErrorSuccess() (gas: 66394) -CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_NoContractSuccess() (gas: 12942) -CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_NoGasForCallExactCheckReturnFalseSuccess() (gas: 12984) -CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_NotEnoughGasForCallReturnsFalseSuccess() (gas: 13293) -CallWithExactGas__callWithExactGasSafeReturnData:test_CallWithExactGasSafeReturnDataExactGas() (gas: 20287) -CallWithExactGas__callWithExactGasSafeReturnData:test_NoContractReverts() (gas: 13915) -CallWithExactGas__callWithExactGasSafeReturnData:test_NoGasForCallExactCheckReverts() (gas: 16108) -CallWithExactGas__callWithExactGasSafeReturnData:test_NotEnoughGasForCallReverts() (gas: 16513) -CallWithExactGas__callWithExactGasSafeReturnData:test_callWithExactGasSafeReturnData_ThrowOOGError_Revert() (gas: 36713) -EnumerableMapAddresses_at:testAtSuccess() (gas: 95055) -EnumerableMapAddresses_at:testBytes32AtSuccess() (gas: 94828) -EnumerableMapAddresses_at:testBytesAtSuccess() (gas: 96507) -EnumerableMapAddresses_contains:testBytes32ContainsSuccess() (gas: 93503) -EnumerableMapAddresses_contains:testBytesContainsSuccess() (gas: 93974) -EnumerableMapAddresses_contains:testContainsSuccess() (gas: 93678) -EnumerableMapAddresses_get:testBytes32GetSuccess() (gas: 94238) -EnumerableMapAddresses_get:testBytesGetSuccess() (gas: 95919) -EnumerableMapAddresses_get:testGetSuccess() (gas: 94409) -EnumerableMapAddresses_get_errorMessage:testBytesGetErrorMessageSuccess() (gas: 95852) -EnumerableMapAddresses_get_errorMessage:testGetErrorMessageSuccess() (gas: 94467) -EnumerableMapAddresses_length:testBytes32LengthSuccess() (gas: 72418) -EnumerableMapAddresses_length:testBytesLengthSuccess() (gas: 73035) -EnumerableMapAddresses_length:testLengthSuccess() (gas: 72592) -EnumerableMapAddresses_remove:testBytes32RemoveSuccess() (gas: 73432) -EnumerableMapAddresses_remove:testBytesRemoveSuccess() (gas: 74216) -EnumerableMapAddresses_remove:testRemoveSuccess() (gas: 73651) -EnumerableMapAddresses_set:testBytes32SetSuccess() (gas: 94475) -EnumerableMapAddresses_set:testBytesSetSuccess() (gas: 95405) -EnumerableMapAddresses_set:testSetSuccess() (gas: 94638) -EnumerableMapAddresses_tryGet:testBytes32TryGetSuccess() (gas: 94602) -EnumerableMapAddresses_tryGet:testBytesTryGetSuccess() (gas: 96316) -EnumerableMapAddresses_tryGet:testTryGetSuccess() (gas: 94869) -OpStackBurnMintERC677_constructor:testConstructorSuccess() (gas: 1721342) -OpStackBurnMintERC677_interfaceCompatibility:testBurnCompatibility() (gas: 291244) -OpStackBurnMintERC677_interfaceCompatibility:testMintCompatibility() (gas: 137917) -OpStackBurnMintERC677_interfaceCompatibility:testStaticFunctionsCompatibility() (gas: 13773) -OpStackBurnMintERC677_supportsInterface:testConstructorSuccess() (gas: 12728) -Ownable2Step_acceptOwnership:test_acceptOwnership_MustBeProposedOwner_reverts() (gas: 10353) -Ownable2Step_acceptOwnership:test_acceptOwnership_success() (gas: 31070) -Ownable2Step_constructor:test_constructor_OwnerCannotBeZero_reverts() (gas: 35924) -Ownable2Step_constructor:test_constructor_success() (gas: 10424) -Ownable2Step_onlyOwner:test_onlyOwner_OnlyCallableByOwner_reverts() (gas: 10746) -Ownable2Step_onlyOwner:test_onlyOwner_success() (gas: 7503) -Ownable2Step_transferOwnership:test_transferOwnership_CannotTransferToSelf_reverts() (gas: 10494) -Ownable2Step_transferOwnership:test_transferOwnership_success() (gas: 30124) -SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_EmptySubset_Reverts() (gas: 5191) -SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_EmptySuperset_Reverts() (gas: 4522) -SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_HasDuplicates_Reverts() (gas: 7738) -SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_NotASubset_Reverts() (gas: 11700) -SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_SingleElementSubset() (gas: 3908) -SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_SingleElementSubsetAndSuperset_Equal() (gas: 1459) -SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_SingleElementSubsetAndSuperset_NotEqual_Reverts() (gas: 6149) -SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_SubsetEqualsSuperset_NoRevert() (gas: 7830) -SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_SubsetLargerThanSuperset_Reverts() (gas: 15363) -SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_SupersetHasDuplicates_Reverts() (gas: 8767) -SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_UnsortedSubset_Reverts() (gas: 7106) -SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_UnsortedSuperset_Reverts() (gas: 8947) -SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_ValidSubset_Success() (gas: 5653) \ No newline at end of file +AuthorizedCallers_applyAuthorizedCallerUpdates:test_AddAndRemove_Success() (gas: 124942) +AuthorizedCallers_applyAuthorizedCallerUpdates:test_OnlyAdd_Success() (gas: 132869) +AuthorizedCallers_applyAuthorizedCallerUpdates:test_OnlyCallableByOwner_Revert() (gas: 12238) +AuthorizedCallers_applyAuthorizedCallerUpdates:test_OnlyRemove_Success() (gas: 44907) +AuthorizedCallers_applyAuthorizedCallerUpdates:test_RemoveThenAdd_Success() (gas: 56991) +AuthorizedCallers_applyAuthorizedCallerUpdates:test_SkipRemove_Success() (gas: 31961) +AuthorizedCallers_applyAuthorizedCallerUpdates:test_ZeroAddressNotAllowed_Revert() (gas: 64413) +AuthorizedCallers_constructor:test_ZeroAddressNotAllowed_Revert() (gas: 64390) +AuthorizedCallers_constructor:test_constructor_Success() (gas: 674931) +BurnMintERC20_approve:test_approve() (gas: 57652) +BurnMintERC20_burn:test_BasicBurn() (gas: 153607) +BurnMintERC20_burnFrom:test_BurnFrom() (gas: 57995) +BurnMintERC20_burnFromAlias:test_burn() (gas: 58039) +BurnMintERC20_constructor:test_Constructor() (gas: 1694831) +BurnMintERC20_getCCIPAdmin:test_getCCIPAdmin() (gas: 10548) +BurnMintERC20_getCCIPAdmin:test_setCCIPAdmin() (gas: 21590) +BurnMintERC20_grantMintAndBurnRoles:test_GrantMintAndBurnRoles() (gas: 79142) +BurnMintERC20_mint:test_mint() (gas: 101849) +BurnMintERC20_supportsInterface:test_SupportsInterface() (gas: 11218) +BurnMintERC20_transfer:test_transfer() (gas: 42338) +BurnMintERC677_approve:testApproveSuccess() (gas: 55512) +BurnMintERC677_approve:testInvalidAddressReverts() (gas: 10663) +BurnMintERC677_burn:testBasicBurnSuccess() (gas: 172100) +BurnMintERC677_burn:testBurnFromZeroAddressReverts() (gas: 47201) +BurnMintERC677_burn:testExceedsBalanceReverts() (gas: 21841) +BurnMintERC677_burn:testSenderNotBurnerReverts() (gas: 13359) +BurnMintERC677_burnFrom:testBurnFromSuccess() (gas: 57959) +BurnMintERC677_burnFrom:testExceedsBalanceReverts() (gas: 35864) +BurnMintERC677_burnFrom:testInsufficientAllowanceReverts() (gas: 21849) +BurnMintERC677_burnFrom:testSenderNotBurnerReverts() (gas: 13359) +BurnMintERC677_burnFromAlias:testBurnFromSuccess() (gas: 57985) +BurnMintERC677_burnFromAlias:testExceedsBalanceReverts() (gas: 35880) +BurnMintERC677_burnFromAlias:testInsufficientAllowanceReverts() (gas: 21869) +BurnMintERC677_burnFromAlias:testSenderNotBurnerReverts() (gas: 13379) +BurnMintERC677_constructor:testConstructorSuccess() (gas: 1672812) +BurnMintERC677_decreaseApproval:testDecreaseApprovalSuccess() (gas: 31069) +BurnMintERC677_grantMintAndBurnRoles:testGrantMintAndBurnRolesSuccess() (gas: 121324) +BurnMintERC677_grantRole:testGrantBurnAccessSuccess() (gas: 53442) +BurnMintERC677_grantRole:testGrantManySuccess() (gas: 937759) +BurnMintERC677_grantRole:testGrantMintAccessSuccess() (gas: 94323) +BurnMintERC677_increaseApproval:testIncreaseApprovalSuccess() (gas: 44076) +BurnMintERC677_mint:testBasicMintSuccess() (gas: 149699) +BurnMintERC677_mint:testMaxSupplyExceededReverts() (gas: 50363) +BurnMintERC677_mint:testSenderNotMinterReverts() (gas: 11195) +BurnMintERC677_supportsInterface:testConstructorSuccess() (gas: 12476) +BurnMintERC677_transfer:testInvalidAddressReverts() (gas: 10639) +BurnMintERC677_transfer:testTransferSuccess() (gas: 42299) +CallWithExactGas__callWithExactGas:test_CallWithExactGasReceiverErrorSuccess() (gas: 65949) +CallWithExactGas__callWithExactGas:test_CallWithExactGasSafeReturnDataExactGas() (gas: 18324) +CallWithExactGas__callWithExactGas:test_NoContractReverts() (gas: 11559) +CallWithExactGas__callWithExactGas:test_NoGasForCallExactCheckReverts() (gas: 15788) +CallWithExactGas__callWithExactGas:test_NotEnoughGasForCallReverts() (gas: 16241) +CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_CallWithExactGasEvenIfTargetIsNoContractExactGasSuccess() (gas: 20073) +CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_CallWithExactGasEvenIfTargetIsNoContractReceiverErrorSuccess() (gas: 66461) +CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_NoContractSuccess() (gas: 12962) +CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_NoGasForCallExactCheckReturnFalseSuccess() (gas: 13005) +CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_NotEnoughGasForCallReturnsFalseSuccess() (gas: 13317) +CallWithExactGas__callWithExactGasSafeReturnData:test_CallWithExactGasSafeReturnDataExactGas() (gas: 20331) +CallWithExactGas__callWithExactGasSafeReturnData:test_NoContractReverts() (gas: 13939) +CallWithExactGas__callWithExactGasSafeReturnData:test_NoGasForCallExactCheckReverts() (gas: 16139) +CallWithExactGas__callWithExactGasSafeReturnData:test_NotEnoughGasForCallReverts() (gas: 16547) +CallWithExactGas__callWithExactGasSafeReturnData:test_callWithExactGasSafeReturnData_ThrowOOGError_Revert() (gas: 36755) +EnumerableMapAddresses_at:testAtSuccess() (gas: 95086) +EnumerableMapAddresses_at:testBytes32AtSuccess() (gas: 94855) +EnumerableMapAddresses_at:testBytesAtSuccess() (gas: 96542) +EnumerableMapAddresses_contains:testBytes32ContainsSuccess() (gas: 93518) +EnumerableMapAddresses_contains:testBytesContainsSuccess() (gas: 93990) +EnumerableMapAddresses_contains:testContainsSuccess() (gas: 93696) +EnumerableMapAddresses_get:testBytes32GetSuccess() (gas: 94256) +EnumerableMapAddresses_get:testBytesGetSuccess() (gas: 95945) +EnumerableMapAddresses_get:testGetSuccess() (gas: 94431) +EnumerableMapAddresses_get_errorMessage:testBytesGetErrorMessageSuccess() (gas: 95878) +EnumerableMapAddresses_get_errorMessage:testGetErrorMessageSuccess() (gas: 94489) +EnumerableMapAddresses_length:testBytes32LengthSuccess() (gas: 72445) +EnumerableMapAddresses_length:testBytesLengthSuccess() (gas: 73064) +EnumerableMapAddresses_length:testLengthSuccess() (gas: 72623) +EnumerableMapAddresses_remove:testBytes32RemoveSuccess() (gas: 73462) +EnumerableMapAddresses_remove:testBytesRemoveSuccess() (gas: 74249) +EnumerableMapAddresses_remove:testRemoveSuccess() (gas: 73686) +EnumerableMapAddresses_set:testBytes32SetSuccess() (gas: 94496) +EnumerableMapAddresses_set:testBytesSetSuccess() (gas: 95428) +EnumerableMapAddresses_set:testSetSuccess() (gas: 94663) +EnumerableMapAddresses_tryGet:testBytes32TryGetSuccess() (gas: 94622) +EnumerableMapAddresses_tryGet:testBytesTryGetSuccess() (gas: 96345) +EnumerableMapAddresses_tryGet:testTryGetSuccess() (gas: 94893) +OpStackBurnMintERC677_constructor:testConstructorSuccess() (gas: 1743682) +OpStackBurnMintERC677_interfaceCompatibility:testBurnCompatibility() (gas: 291483) +OpStackBurnMintERC677_interfaceCompatibility:testMintCompatibility() (gas: 137957) +OpStackBurnMintERC677_interfaceCompatibility:testStaticFunctionsCompatibility() (gas: 13781) +OpStackBurnMintERC677_supportsInterface:testConstructorSuccess() (gas: 12752) +Ownable2Step_acceptOwnership:test_acceptOwnership_MustBeProposedOwner_reverts() (gas: 10360) +Ownable2Step_acceptOwnership:test_acceptOwnership_success() (gas: 31088) +Ownable2Step_constructor:test_constructor_OwnerCannotBeZero_reverts() (gas: 35858) +Ownable2Step_constructor:test_constructor_success() (gas: 10428) +Ownable2Step_onlyOwner:test_onlyOwner_OnlyCallableByOwner_reverts() (gas: 10754) +Ownable2Step_onlyOwner:test_onlyOwner_success() (gas: 7506) +Ownable2Step_transferOwnership:test_transferOwnership_CannotTransferToSelf_reverts() (gas: 10501) +Ownable2Step_transferOwnership:test_transferOwnership_success() (gas: 30140) +SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_EmptySubset_Reverts() (gas: 5208) +SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_EmptySuperset_Reverts() (gas: 4535) +SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_HasDuplicates_Reverts() (gas: 7761) +SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_NotASubset_Reverts() (gas: 11733) +SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_SingleElementSubset() (gas: 3922) +SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_SingleElementSubsetAndSuperset_Equal() (gas: 1464) +SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_SingleElementSubsetAndSuperset_NotEqual_Reverts() (gas: 6172) +SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_SubsetEqualsSuperset_NoRevert() (gas: 7859) +SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_SubsetLargerThanSuperset_Reverts() (gas: 15410) +SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_SupersetHasDuplicates_Reverts() (gas: 8790) +SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_UnsortedSubset_Reverts() (gas: 7128) +SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_UnsortedSuperset_Reverts() (gas: 8970) +SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_ValidSubset_Success() (gas: 5671) \ No newline at end of file diff --git a/contracts/gas-snapshots/workflow.gas-snapshot b/contracts/gas-snapshots/workflow.gas-snapshot index bdfd2b24aec..48f92cbabbe 100644 --- a/contracts/gas-snapshots/workflow.gas-snapshot +++ b/contracts/gas-snapshots/workflow.gas-snapshot @@ -1,25 +1,25 @@ -WorkflowRegistryManager_activateVersion:test_WhenTheVersionNumberIsNotActive_AndWhenThereAreNoActiveVersions() (gas: 528769) -WorkflowRegistryManager_addVersion:test_WhenAutoActivateIsFalse() (gas: 265551) -WorkflowRegistryManager_addVersion:test_WhenAutoActivateIsTrue() (gas: 270596) -WorkflowRegistryManager_getActiveVersion:test_WhenAnActiveVersionExists() (gas: 287760) +WorkflowRegistryManager_activateVersion:test_WhenTheVersionNumberIsNotActive_AndWhenThereAreNoActiveVersions() (gas: 529151) +WorkflowRegistryManager_addVersion:test_WhenAutoActivateIsFalse() (gas: 265730) +WorkflowRegistryManager_addVersion:test_WhenAutoActivateIsTrue() (gas: 270806) +WorkflowRegistryManager_getActiveVersion:test_WhenAnActiveVersionExists() (gas: 287951) WorkflowRegistryManager_getActiveVersion:test_WhenNoActiveVersionIsAvailable() (gas: 13258) -WorkflowRegistryManager_getActiveVersionNumber:test_WhenAnActiveVersionExists() (gas: 283885) +WorkflowRegistryManager_getActiveVersionNumber:test_WhenAnActiveVersionExists() (gas: 284076) WorkflowRegistryManager_getActiveVersionNumber:test_WhenNoActiveVersionIsAvailable() (gas: 10698) WorkflowRegistryManager_getAllVersions:test_WhenLimitExceedsMaximumPaginationLimit() (gas: 54503) WorkflowRegistryManager_getAllVersions:test_WhenRequestingWithInvalidStartIndex() (gas: 11338) WorkflowRegistryManager_getAllVersions:test_WhenRequestingWithValidStartIndexAndLimitWithinBounds() (gas: 40398) WorkflowRegistryManager_getLatestVersion:test_WhenNoVersionsHaveBeenRegistered() (gas: 12984) -WorkflowRegistryManager_getLatestVersion:test_WhenVersionsHaveBeenRegistered() (gas: 287791) +WorkflowRegistryManager_getLatestVersion:test_WhenVersionsHaveBeenRegistered() (gas: 287982) WorkflowRegistryManager_getLatestVersionNumber:test_WhenNoVersionsHaveBeenRegistered() (gas: 10637) -WorkflowRegistryManager_getLatestVersionNumber:test_WhenVersionsHaveBeenRegistered() (gas: 284134) +WorkflowRegistryManager_getLatestVersionNumber:test_WhenVersionsHaveBeenRegistered() (gas: 284325) WorkflowRegistryManager_getVersion:test_WhenVersionNumberIsNotRegistered() (gas: 13785) -WorkflowRegistryManager_getVersion:test_WhenVersionNumberIsRegistered() (gas: 288169) -WorkflowRegistryManager_getVersionNumberByContractAddressAndChainID:test_WhenAVersionIsRegisteredForTheContractAddressAndChainIDCombination() (gas: 285022) -WorkflowRegistryManager_getVersionNumberByContractAddressAndChainID:test_WhenNoVersionIsRegisteredForTheContractAddressAndChainIDCombination() (gas: 286634) -WorkflowRegistryManager_getVersionNumberByContractAddressAndChainID:test_WhenTheContractAddressIsInvalid() (gas: 284604) -WorkflowRegistry_activateWorkflow:test_WhenTheCallerIsAnAuthorizedAddress() (gas: 517416) -WorkflowRegistry_deleteWorkflow:test_WhenTheCallerIsAnAuthorizedAddress_AndTheDonIDIsAllowed() (gas: 422157) -WorkflowRegistry_deleteWorkflow:test_WhenTheCallerIsAnAuthorizedAddress_AndTheDonIDIsNotAllowed() (gas: 439960) +WorkflowRegistryManager_getVersion:test_WhenVersionNumberIsRegistered() (gas: 288360) +WorkflowRegistryManager_getVersionNumberByContractAddressAndChainID:test_WhenAVersionIsRegisteredForTheContractAddressAndChainIDCombination() (gas: 285213) +WorkflowRegistryManager_getVersionNumberByContractAddressAndChainID:test_WhenNoVersionIsRegisteredForTheContractAddressAndChainIDCombination() (gas: 286825) +WorkflowRegistryManager_getVersionNumberByContractAddressAndChainID:test_WhenTheContractAddressIsInvalid() (gas: 284795) +WorkflowRegistry_activateWorkflow:test_WhenTheCallerIsAnAuthorizedAddress() (gas: 517448) +WorkflowRegistry_deleteWorkflow:test_WhenTheCallerIsAnAuthorizedAddress_AndTheDonIDIsAllowed() (gas: 422188) +WorkflowRegistry_deleteWorkflow:test_WhenTheCallerIsAnAuthorizedAddress_AndTheDonIDIsNotAllowed() (gas: 439990) WorkflowRegistry_getAllAllowedDONs:test_WhenTheRegistryIsLocked() (gas: 47473) WorkflowRegistry_getAllAllowedDONs:test_WhenTheSetOfAllowedDONsIsEmpty() (gas: 25780) WorkflowRegistry_getAllAllowedDONs:test_WhenThereAreMultipleAllowedDONs() (gas: 75437) @@ -28,9 +28,9 @@ WorkflowRegistry_getAllAuthorizedAddresses:test_WhenTheRegistryIsLocked() (gas: WorkflowRegistry_getAllAuthorizedAddresses:test_WhenTheSetOfAuthorizedAddressesIsEmpty() (gas: 26152) WorkflowRegistry_getAllAuthorizedAddresses:test_WhenThereAreMultipleAuthorizedAddresses() (gas: 78270) WorkflowRegistry_getAllAuthorizedAddresses:test_WhenThereIsASingleAuthorizedAddress() (gas: 16832) -WorkflowRegistry_getWorkflowMetadata:test_WhenTheRegistryIsLocked() (gas: 541532) +WorkflowRegistry_getWorkflowMetadata:test_WhenTheRegistryIsLocked() (gas: 541570) WorkflowRegistry_getWorkflowMetadata:test_WhenTheWorkflowDoesNotExist() (gas: 17543) -WorkflowRegistry_getWorkflowMetadata:test_WhenTheWorkflowExistsWithTheOwnerAndName() (gas: 512388) +WorkflowRegistry_getWorkflowMetadata:test_WhenTheWorkflowExistsWithTheOwnerAndName() (gas: 512426) WorkflowRegistry_getWorkflowMetadataListByDON:test_WhenLimitExceedsTotalWorkflows() (gas: 128146) WorkflowRegistry_getWorkflowMetadataListByDON:test_WhenLimitIsEqualToTotalWorkflows() (gas: 128035) WorkflowRegistry_getWorkflowMetadataListByDON:test_WhenLimitIsLessThanTotalWorkflows() (gas: 90141) @@ -48,17 +48,17 @@ WorkflowRegistry_getWorkflowMetadataListByOwner:test_WhenStartIsGreaterThanOrEqu WorkflowRegistry_getWorkflowMetadataListByOwner:test_WhenTheOwnerHasNoWorkflows() (gas: 14006) WorkflowRegistry_getWorkflowMetadataListByOwner:test_WhenTheRegistryIsLocked() (gas: 165968) WorkflowRegistry_lockRegistry:test_WhenTheCallerIsTheContractOwner() (gas: 38758) -WorkflowRegistry_pauseWorkflow:test_WhenTheDonIDIsAllowed_AndTheCallerIsAnAuthorizedAddress() (gas: 517380) -WorkflowRegistry_pauseWorkflow:test_WhenTheDonIDIsAllowed_AndTheCallerIsAnUnauthorizedAddress() (gas: 525183) -WorkflowRegistry_pauseWorkflow:test_WhenTheDonIDIsNotAllowed_AndTheCallerIsAnAuthorizedAddress() (gas: 524942) -WorkflowRegistry_pauseWorkflow:test_WhenTheDonIDIsNotAllowed_AndTheCallerIsAnUnauthorizedAddress() (gas: 529353) -WorkflowRegistry_registerWorkflow:test_WhenTheWorkflowInputsAreAllValid() (gas: 572178) -WorkflowRegistry_requestForceUpdateSecrets:test_WhenTheCallerIsAnAuthorizedAddress_AndTheWorkflowIsInAnAllowedDON() (gas: 936016) -WorkflowRegistry_requestForceUpdateSecrets:test_WhenTheCallerIsAnAuthorizedAddress_AndTheWorkflowIsNotInAnAllowedDON() (gas: 510784) -WorkflowRegistry_requestForceUpdateSecrets:test_WhenTheCallerIsNotAnAuthorizedAddress() (gas: 509138) +WorkflowRegistry_pauseWorkflow:test_WhenTheDonIDIsAllowed_AndTheCallerIsAnAuthorizedAddress() (gas: 517427) +WorkflowRegistry_pauseWorkflow:test_WhenTheDonIDIsAllowed_AndTheCallerIsAnUnauthorizedAddress() (gas: 525230) +WorkflowRegistry_pauseWorkflow:test_WhenTheDonIDIsNotAllowed_AndTheCallerIsAnAuthorizedAddress() (gas: 524989) +WorkflowRegistry_pauseWorkflow:test_WhenTheDonIDIsNotAllowed_AndTheCallerIsAnUnauthorizedAddress() (gas: 529400) +WorkflowRegistry_registerWorkflow:test_WhenTheWorkflowInputsAreAllValid() (gas: 572239) +WorkflowRegistry_requestForceUpdateSecrets:test_WhenTheCallerIsAnAuthorizedAddress_AndTheWorkflowIsInAnAllowedDON() (gas: 936092) +WorkflowRegistry_requestForceUpdateSecrets:test_WhenTheCallerIsAnAuthorizedAddress_AndTheWorkflowIsNotInAnAllowedDON() (gas: 510822) +WorkflowRegistry_requestForceUpdateSecrets:test_WhenTheCallerIsNotAnAuthorizedAddress() (gas: 509176) WorkflowRegistry_unlockRegistry:test_WhenTheCallerIsTheContractOwner() (gas: 30325) WorkflowRegistry_updateAllowedDONs:test_WhenTheBoolInputIsFalse() (gas: 29739) -WorkflowRegistry_updateAllowedDONs:test_WhenTheBoolInputIsTrue() (gas: 170296) +WorkflowRegistry_updateAllowedDONs:test_WhenTheBoolInputIsTrue() (gas: 170256) WorkflowRegistry_updateAuthorizedAddresses:test_WhenTheBoolInputIsFalse() (gas: 30278) -WorkflowRegistry_updateAuthorizedAddresses:test_WhenTheBoolInputIsTrue() (gas: 175515) -WorkflowRegistry_updateWorkflow:test_WhenTheWorkflowInputsAreAllValid() (gas: 515666) +WorkflowRegistry_updateAuthorizedAddresses:test_WhenTheBoolInputIsTrue() (gas: 175475) +WorkflowRegistry_updateWorkflow:test_WhenTheWorkflowInputsAreAllValid() (gas: 515414) \ No newline at end of file diff --git a/contracts/scripts/lcov_prune b/contracts/scripts/lcov_prune index 9d5d592c646..9dbd6781d96 100755 --- a/contracts/scripts/lcov_prune +++ b/contracts/scripts/lcov_prune @@ -27,8 +27,6 @@ exclusion_list_ccip=( "src/v0.8/ccip/libraries/USDPriceWith18Decimals.sol" "src/v0.8/ccip/libraries/MerkleMultiProof.sol" "src/v0.8/ccip/libraries/Pool.sol" - "src/v0.8/ConfirmedOwnerWithProposal.sol" - "src/v0.8/tests/MockV3Aggregator.sol" "src/v0.8/ccip/applications/CCIPClientExample.sol" "src/v0.8/keystone/*" ) diff --git a/contracts/scripts/native_solc_compile_all b/contracts/scripts/native_solc_compile_all index 090d8c8a07b..a66456bb6d5 100755 --- a/contracts/scripts/native_solc_compile_all +++ b/contracts/scripts/native_solc_compile_all @@ -12,7 +12,7 @@ python3 -m pip install --require-hashes -r $SCRIPTPATH/requirements.txt # 6 and 7 are legacy contracts, for each other product we have a native_solc_compile_all_$product script # These scripts can be run individually, or all together with this script. # To add new CL products, simply write a native_solc_compile_all_$product script and add it to the list below. -for product in automation events_mock feeds functions keystone llo-feeds logpoller operatorforwarder shared transmission vrf ccip liquiditymanager workflow +for product in automation events_mock feeds functions keystone llo-feeds operatorforwarder shared vrf ccip liquiditymanager workflow do $SCRIPTPATH/native_solc_compile_all_$product done diff --git a/contracts/scripts/native_solc_compile_all_automation b/contracts/scripts/native_solc_compile_all_automation index e189e78cb0f..eb4b39201ba 100755 --- a/contracts/scripts/native_solc_compile_all_automation +++ b/contracts/scripts/native_solc_compile_all_automation @@ -73,11 +73,11 @@ compileContract automation/testhelpers/UpkeepCounter.sol compileContract automation/interfaces/StreamsLookupCompatibleInterface.sol -compileContract tests/VerifiableLoadUpkeep.sol -compileContract tests/VerifiableLoadStreamsLookupUpkeep.sol -compileContract tests/VerifiableLoadLogTriggerUpkeep.sol -compileContract tests/AutomationConsumerBenchmark.sol -compileContract tests/StreamsLookupUpkeep.sol +compileContract automation/testhelpers/VerifiableLoadUpkeep.sol +compileContract automation/testhelpers/VerifiableLoadStreamsLookupUpkeep.sol +compileContract automation/testhelpers/VerifiableLoadLogTriggerUpkeep.sol +compileContract automation/testhelpers/AutomationConsumerBenchmark.sol +compileContract automation/testhelpers/StreamsLookupUpkeep.sol SOLC_VERSION="0.8.19" diff --git a/contracts/scripts/native_solc_compile_all_ccip b/contracts/scripts/native_solc_compile_all_ccip index 4b894c1e2f1..a62a25ddbb0 100755 --- a/contracts/scripts/native_solc_compile_all_ccip +++ b/contracts/scripts/native_solc_compile_all_ccip @@ -6,85 +6,83 @@ echo " ┌─────────────────────── echo " │ Compiling CCIP contracts... │" echo " └──────────────────────────────────────────────┘" -SOLC_VERSION="0.8.24" -OPTIMIZE_RUNS=26000 -OPTIMIZE_RUNS_OFFRAMP=500 +# The offRamp uses a specific lower optimization runs value. All other contracts use the default value +# as specified in the foundry.toml. +OPTIMIZE_RUNS_OFFRAMP=800 +OPTIMIZE_RUNS_FEE_QUOTER=10000 +PROJECT="ccip" +FOUNDRY_PROJECT_SUFFIX="-compile" +CONTRACTS_DIR="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; cd ../ && pwd -P )" +export FOUNDRY_PROFILE="$PROJECT"$FOUNDRY_PROJECT_SUFFIX -SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" -python3 -m pip install --require-hashes -r "$SCRIPTPATH"/requirements.txt -solc-select install $SOLC_VERSION -solc-select use $SOLC_VERSION -export SOLC_VERSION=$SOLC_VERSION - -ROOT="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; cd ../../ && pwd -P )" - -compileContract () { +compileContract() { local contract - contract=$(basename "$1" ".sol") + contract=$(basename "$1") + echo "Compiling" "$contract" - local optimize_runs=$OPTIMIZE_RUNS + local command + command="forge build $CONTRACTS_DIR/src/v0.8/$PROJECT/"$1.sol" \ + --root $CONTRACTS_DIR \ + $(getOptimizations "$contract") \ + --extra-output-files bin abi \ + -o $CONTRACTS_DIR/solc/$PROJECT/$contract" - case $1 in - "ccip/offRamp/OffRamp.sol") - echo "OffRamp uses $OPTIMIZE_RUNS_OFFRAMP optimizer runs." - optimize_runs=$OPTIMIZE_RUNS_OFFRAMP - ;; - esac - - solc --overwrite --optimize --optimize-runs $optimize_runs --metadata-hash none \ - -o "$ROOT"/contracts/solc/v$SOLC_VERSION/"$contract" \ - --abi --bin --allow-paths "$ROOT"/contracts/src/v0.8 \ - --bin-runtime --hashes --metadata --metadata-literal --combined-json abi,hashes,metadata,srcmap,srcmap-runtime \ - --evm-version paris \ - "$ROOT"/contracts/src/v0.8/"$1" + $command } +# Define optimization overrides in this function. Anything that is not an override will use the default value +# as specified in the foundry.toml. +function getOptimizations() { + local optimize_runs_override="" + + case $1 in + "OffRamp") + optimize_runs_override="--optimizer-runs $OPTIMIZE_RUNS_OFFRAMP" + ;; + "FeeQuoter") + optimize_runs_override="--optimizer-runs $OPTIMIZE_RUNS_FEE_QUOTER" + ;; + esac + + echo "$optimize_runs_override" +} -# Solc produces and overwrites intermediary contracts. -# Contracts should be ordered in reverse-import-complexity-order to minimize overwrite risks. -compileContract ccip/offRamp/OffRamp.sol -compileContract ccip/FeeQuoter.sol -compileContract ccip/onRamp/OnRamp.sol -compileContract ccip/applications/PingPongDemo.sol -compileContract ccip/applications/EtherSenderReceiver.sol -compileContract ccip/rmn/RMNRemote.sol -compileContract ccip/rmn/RMNHome.sol -compileContract ccip/rmn/ARMProxy.sol -compileContract ccip/MultiAggregateRateLimiter.sol -compileContract ccip/Router.sol -compileContract ccip/tokenAdminRegistry/TokenAdminRegistry.sol -compileContract ccip/tokenAdminRegistry/RegistryModuleOwnerCustom.sol -compileContract ccip/capability/CCIPHome.sol -compileContract ccip/NonceManager.sol -compileContract shared/token/ERC677/BurnMintERC677.sol -compileContract shared/token/ERC20/BurnMintERC20.sol - +compileContract offRamp/OffRamp +compileContract FeeQuoter +compileContract onRamp/OnRamp +compileContract applications/PingPongDemo +compileContract applications/EtherSenderReceiver +compileContract MultiAggregateRateLimiter +compileContract Router +compileContract tokenAdminRegistry/TokenAdminRegistry +compileContract tokenAdminRegistry/RegistryModuleOwnerCustom +compileContract capability/CCIPHome +compileContract NonceManager +compileContract rmn/RMNRemote +compileContract rmn/RMNHome +compileContract rmn/RMNProxy # Pools -compileContract ccip/pools/LockReleaseTokenPool.sol -compileContract ccip/pools/BurnMintTokenPool.sol -compileContract ccip/pools/BurnFromMintTokenPool.sol -compileContract ccip/pools/BurnWithFromMintTokenPool.sol -compileContract ccip/pools/TokenPool.sol - +compileContract pools/LockReleaseTokenPool +compileContract pools/BurnMintTokenPool +compileContract pools/BurnFromMintTokenPool +compileContract pools/BurnWithFromMintTokenPool +compileContract pools/TokenPool +compileContract pools/USDC/USDCTokenPool # Test helpers -compileContract ccip/test/helpers/BurnMintERC677Helper.sol -compileContract ccip/test/helpers/MessageHasher.sol -compileContract ccip/test/helpers/USDCReaderTester.sol -compileContract ccip/test/helpers/ReportCodec.sol -compileContract ccip/test/helpers/receivers/MaybeRevertMessageReceiver.sol -compileContract ccip/test/helpers/MultiOCR3Helper.sol -compileContract ccip/test/mocks/MockE2EUSDCTokenMessenger.sol -compileContract ccip/test/mocks/MockE2EUSDCTransmitter.sol -compileContract ccip/test/WETH9.sol -compileContract ccip/test/helpers/CCIPReaderTester.sol - -# Encoding Utils -compileContract ccip/interfaces/encodingutils/ICCIPEncodingUtils.sol +compileContract test/helpers/BurnMintERC677Helper +compileContract test/helpers/MessageHasher +compileContract test/helpers/USDCReaderTester +compileContract test/helpers/ReportCodec +compileContract test/helpers/receivers/MaybeRevertMessageReceiver +compileContract test/helpers/MultiOCR3Helper +compileContract test/mocks/MockE2EUSDCTokenMessenger +compileContract test/mocks/MockE2EUSDCTransmitter +compileContract test/WETH9 +compileContract test/helpers/CCIPReaderTester +# Offchain test encoding utils +compileContract test/helpers/EncodingUtils -# Customer contracts -compileContract ccip/pools/USDC/USDCTokenPool.sol -compileContract tests/MockV3Aggregator.sol diff --git a/contracts/scripts/native_solc_compile_all_feeds b/contracts/scripts/native_solc_compile_all_feeds index 2c5808d4663..9e0a58b4364 100755 --- a/contracts/scripts/native_solc_compile_all_feeds +++ b/contracts/scripts/native_solc_compile_all_feeds @@ -31,5 +31,5 @@ compileContract () { # Aggregators compileContract shared/interfaces/AggregatorV2V3Interface.sol -compileContract Chainlink.sol -compileContract ChainlinkClient.sol +compileContract operatorforwarder/Chainlink.sol +compileContract operatorforwarder/ChainlinkClient.sol diff --git a/contracts/scripts/native_solc_compile_all_llo-feeds b/contracts/scripts/native_solc_compile_all_llo-feeds index bbcd53df900..8cafea5cb4c 100755 --- a/contracts/scripts/native_solc_compile_all_llo-feeds +++ b/contracts/scripts/native_solc_compile_all_llo-feeds @@ -9,7 +9,6 @@ echo " └─────────────────────── SOLC_VERSION="0.8.19" OPTIMIZE_RUNS=1000000 - SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" python3 -m pip install --require-hashes -r "$SCRIPTPATH"/requirements.txt solc-select install $SOLC_VERSION @@ -19,15 +18,15 @@ export SOLC_VERSION=$SOLC_VERSION ROOT="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; cd ../../ && pwd -P )" compileContract () { - local contract - contract=$(basename "$1" ".sol") - - solc --overwrite --optimize --optimize-runs $OPTIMIZE_RUNS --metadata-hash none \ - -o "$ROOT"/contracts/solc/v$SOLC_VERSION/"$contract" \ - --abi --bin --allow-paths "$ROOT"/contracts/src/v0.8\ - "$ROOT"/contracts/src/v0.8/"$1" + local contract dir + contract=$(basename "$1" ".sol") + dir=$(dirname "$1") + + solc --overwrite --optimize --optimize-runs $OPTIMIZE_RUNS --metadata-hash none \ + -o "$ROOT"/contracts/solc/v$SOLC_VERSION/"$dir"/"$contract" \ + --abi --bin --allow-paths "$ROOT"/contracts/src/v0.8\ + "$ROOT"/contracts/src/v0.8/"$1" } - compileContract llo-feeds/v0.3.0/Verifier.sol compileContract llo-feeds/v0.3.0/VerifierProxy.sol compileContract llo-feeds/v0.3.0/FeeManager.sol @@ -38,6 +37,10 @@ compileContract llo-feeds/v0.4.0/DestinationFeeManager.sol compileContract llo-feeds/v0.4.0/DestinationRewardManager.sol compileContract llo-feeds/v0.5.0/configuration/ChannelConfigStore.sol compileContract llo-feeds/v0.5.0/configuration/Configurator.sol +compileContract llo-feeds/v0.5.0/Verifier.sol +compileContract llo-feeds/v0.5.0/VerifierProxy.sol +compileContract llo-feeds/v0.5.0/FeeManager.sol +compileContract llo-feeds/v0.5.0/RewardManager.sol # Test | Mocks compileContract llo-feeds/v0.3.0/test/mocks/ErroredVerifier.sol diff --git a/contracts/scripts/native_solc_compile_all_logpoller b/contracts/scripts/native_solc_compile_all_logpoller deleted file mode 100755 index e8ea2a2be80..00000000000 --- a/contracts/scripts/native_solc_compile_all_logpoller +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env bash - -set -e - -echo " ┌──────────────────────────────────────────────┐" -echo " │ Compiling LogPoller contracts... │" -echo " └──────────────────────────────────────────────┘" - -SOLC_VERSION="0.8.19" -OPTIMIZE_RUNS=1000000 - - -SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" -python3 -m pip install --require-hashes -r "$SCRIPTPATH"/requirements.txt -solc-select install $SOLC_VERSION -solc-select use $SOLC_VERSION -export SOLC_VERSION=$SOLC_VERSION - -ROOT="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; cd ../../ && pwd -P )" - -compileContract () { - local contract - contract=$(basename "$1" ".sol") - - solc --overwrite --optimize --optimize-runs $OPTIMIZE_RUNS --metadata-hash none \ - -o "$ROOT"/contracts/solc/v$SOLC_VERSION/"$contract" \ - --abi --bin --allow-paths "$ROOT"/contracts/src/v0.8\ - "$ROOT"/contracts/src/v0.8/"$1" -} - - -compileContract tests/LogEmitter.sol -compileContract tests/VRFLogEmitter.sol \ No newline at end of file diff --git a/contracts/scripts/native_solc_compile_all_shared b/contracts/scripts/native_solc_compile_all_shared index 841f94354e3..1b251db7d9b 100755 --- a/contracts/scripts/native_solc_compile_all_shared +++ b/contracts/scripts/native_solc_compile_all_shared @@ -6,32 +6,44 @@ echo " ┌─────────────────────── echo " │ Compiling shared contracts... │" echo " └──────────────────────────────────────────────┘" -SOLC_VERSION="0.8.19" -OPTIMIZE_RUNS=1000000 +PROJECT="shared" +FOUNDRY_PROJECT_SUFFIX="" +CONTRACTS_DIR="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; cd ../ && pwd -P )" +export FOUNDRY_PROFILE="$PROJECT"$FOUNDRY_PROJECT_SUFFIX -SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" -python3 -m pip install --require-hashes -r "$SCRIPTPATH"/requirements.txt -solc-select install $SOLC_VERSION -solc-select use $SOLC_VERSION -export SOLC_VERSION=$SOLC_VERSION - -ROOT="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; cd ../../ && pwd -P )" - -compileContract () { +compileContract() { local contract - contract=$(basename "$1" ".sol") - - solc --overwrite --optimize --optimize-runs $OPTIMIZE_RUNS --metadata-hash none \ - -o "$ROOT"/contracts/solc/v$SOLC_VERSION/"$contract" \ - --abi --bin --allow-paths "$ROOT"/contracts/src/v0.8\ - "$ROOT"/contracts/src/v0.8/"$1" + contract=$(basename "$1") + echo "Compiling" "$contract" + + if [ -n "$2" ]; then + echo "Compiling from another project: ""$2" + PROJECT=$2 + fi + + # We override the foundry.toml Solidity version to not change the bytecode. + local command + command="forge build $CONTRACTS_DIR/src/v0.8/$PROJECT/"$1.sol" \ + --root $CONTRACTS_DIR \ + --extra-output-files bin abi \ + --use 0.8.19 \ + -o $CONTRACTS_DIR/solc/$PROJECT/$contract" + + $command } -compileContract shared/token/ERC677/BurnMintERC677.sol -compileContract shared/token/ERC677/LinkToken.sol -compileContract shared/token/ERC20/BurnMintERC20.sol -compileContract shared/mocks/WERC20Mock.sol -compileContract vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol -compileContract shared/test/helpers/ChainReaderTester.sol -compileContract vendor/multicall/ebd8b64/src/Multicall3.sol +compileContract interfaces/AggregatorV3Interface +compileContract interfaces/ITypeAndVersion +compileContract token/ERC677/ERC677 +compileContract token/ERC677/BurnMintERC677 +compileContract token/ERC677/LinkToken +compileContract token/ERC20/BurnMintERC20 +compileContract test/helpers/ChainReaderTester +compileContract test/helpers/LogEmitter +compileContract test/helpers/VRFLogEmitter +compileContract mocks/MockV3Aggregator +compileContract mocks/WERC20Mock + +compileContract openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20 vendor +compileContract multicall/ebd8b64/src/Multicall3 vendor diff --git a/contracts/scripts/native_solc_compile_all_transmission b/contracts/scripts/native_solc_compile_all_transmission deleted file mode 100755 index 9650a2b27d3..00000000000 --- a/contracts/scripts/native_solc_compile_all_transmission +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env bash - -set -e - -echo " ┌──────────────────────────────────────────────┐" -echo " │ Compiling Transmission contracts... │" -echo " └──────────────────────────────────────────────┘" - -SOLC_VERSION="0.8.19" -OPTIMIZE_RUNS=1000000 - -SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" -ROOT="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; cd ../../ && pwd -P )" -python3 -m pip install --require-hashes -r "$SCRIPTPATH"/requirements.txt - -solc-select install $SOLC_VERSION -solc-select use $SOLC_VERSION -export SOLC_VERSION=$SOLC_VERSION - -compileContract () { - local contract - contract=$(basename "$1" ".sol") - - solc --overwrite --optimize --optimize-runs $OPTIMIZE_RUNS --metadata-hash none \ - -o "$ROOT"/contracts/solc/v$SOLC_VERSION/"$contract" \ - --abi --bin --allow-paths "$ROOT"/contracts/src/v0.8\ - "$ROOT"/contracts/src/v0.8/"$1" -} - -# Contracts -compileContract transmission/dev/ERC-4337/SCA.sol -compileContract transmission/dev/ERC-4337/Paymaster.sol -compileContract transmission/dev/ERC-4337/SmartContractAccountFactory.sol - -# Testhelpers -compileContract transmission/dev/testhelpers/SmartContractAccountHelper.sol -compileContract transmission/dev/testhelpers/Greeter.sol - -# Vendor -compileContract vendor/entrypoint/core/EntryPoint.sol diff --git a/contracts/src/v0.8/Denominations.sol b/contracts/src/v0.8/Denominations.sol deleted file mode 100644 index 6e9aa778ec7..00000000000 --- a/contracts/src/v0.8/Denominations.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.0; - -library Denominations { - address public constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; - address public constant BTC = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB; - - // Fiat currencies follow https://en.wikipedia.org/wiki/ISO_4217 - address public constant USD = address(840); - address public constant GBP = address(826); - address public constant EUR = address(978); - address public constant JPY = address(392); - address public constant KRW = address(410); - address public constant CNY = address(156); - address public constant AUD = address(36); - address public constant CAD = address(124); - address public constant CHF = address(756); - address public constant ARS = address(32); - address public constant PHP = address(608); - address public constant NZD = address(554); - address public constant SGD = address(702); - address public constant NGN = address(566); - address public constant ZAR = address(710); - address public constant RUB = address(643); - address public constant INR = address(356); - address public constant BRL = address(986); -} diff --git a/contracts/src/v0.8/Flags.sol b/contracts/src/v0.8/Flags.sol deleted file mode 100644 index de14583bcb4..00000000000 --- a/contracts/src/v0.8/Flags.sol +++ /dev/null @@ -1,124 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {SimpleReadAccessController} from "./shared/access/SimpleReadAccessController.sol"; -import {AccessControllerInterface} from "./shared/interfaces/AccessControllerInterface.sol"; -import {FlagsInterface} from "./interfaces/FlagsInterface.sol"; - -/** - * @title The Flags contract - * @notice Allows flags to signal to any reader on the access control list. - * The owner can set flags, or designate other addresses to set flags. The - * owner must turn the flags off, other setters cannot. An expected pattern is - * to allow addresses to raise flags on themselves, so if you are subscribing to - * FlagOn events you should filter for addresses you care about. - */ -// solhint-disable gas-custom-errors -contract Flags is FlagsInterface, SimpleReadAccessController { - AccessControllerInterface public raisingAccessController; - - mapping(address => bool) private s_flags; - - event FlagRaised(address indexed subject); - event FlagLowered(address indexed subject); - event RaisingAccessControllerUpdated(address indexed previous, address indexed current); - - /** - * @param racAddress address for the raising access controller. - */ - constructor(address racAddress) { - setRaisingAccessController(racAddress); - } - - /** - * @notice read the warning flag status of a contract address. - * @param subject The contract address being checked for a flag. - * @return A true value indicates that a flag was raised and a - * false value indicates that no flag was raised. - */ - function getFlag(address subject) external view override checkAccess returns (bool) { - return s_flags[subject]; - } - - /** - * @notice read the warning flag status of a contract address. - * @param subjects An array of addresses being checked for a flag. - * @return An array of bools where a true value for any flag indicates that - * a flag was raised and a false value indicates that no flag was raised. - */ - function getFlags(address[] calldata subjects) external view override checkAccess returns (bool[] memory) { - bool[] memory responses = new bool[](subjects.length); - for (uint256 i = 0; i < subjects.length; i++) { - responses[i] = s_flags[subjects[i]]; - } - return responses; - } - - /** - * @notice enable the warning flag for an address. - * Access is controlled by raisingAccessController, except for owner - * who always has access. - * @param subject The contract address whose flag is being raised - */ - function raiseFlag(address subject) external override { - require(_allowedToRaiseFlags(), "Not allowed to raise flags"); - - _tryToRaiseFlag(subject); - } - - /** - * @notice enable the warning flags for multiple addresses. - * Access is controlled by raisingAccessController, except for owner - * who always has access. - * @param subjects List of the contract addresses whose flag is being raised - */ - function raiseFlags(address[] calldata subjects) external override { - require(_allowedToRaiseFlags(), "Not allowed to raise flags"); - - for (uint256 i = 0; i < subjects.length; i++) { - _tryToRaiseFlag(subjects[i]); - } - } - - /** - * @notice allows owner to disable the warning flags for multiple addresses. - * @param subjects List of the contract addresses whose flag is being lowered - */ - function lowerFlags(address[] calldata subjects) external override onlyOwner { - for (uint256 i = 0; i < subjects.length; i++) { - address subject = subjects[i]; - - if (s_flags[subject]) { - s_flags[subject] = false; - emit FlagLowered(subject); - } - } - } - - /** - * @notice allows owner to change the access controller for raising flags. - * @param racAddress new address for the raising access controller. - */ - function setRaisingAccessController(address racAddress) public override onlyOwner { - address previous = address(raisingAccessController); - - if (previous != racAddress) { - raisingAccessController = AccessControllerInterface(racAddress); - - emit RaisingAccessControllerUpdated(previous, racAddress); - } - } - - // PRIVATE - - function _allowedToRaiseFlags() private view returns (bool) { - return msg.sender == owner() || raisingAccessController.hasAccess(msg.sender, msg.data); - } - - function _tryToRaiseFlag(address subject) private { - if (!s_flags[subject]) { - s_flags[subject] = true; - emit FlagRaised(subject); - } - } -} diff --git a/contracts/src/v0.8/PermissionedForwardProxy.sol b/contracts/src/v0.8/PermissionedForwardProxy.sol deleted file mode 100644 index 544f89065c0..00000000000 --- a/contracts/src/v0.8/PermissionedForwardProxy.sol +++ /dev/null @@ -1,65 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.6; - -import {Address} from "@openzeppelin/contracts/utils/Address.sol"; -import {ConfirmedOwner} from "./shared/access/ConfirmedOwner.sol"; - -/** - * @title PermissionedForwardProxy - * @notice This proxy is used to forward calls from sender to target. It maintains - * a permission list to check which sender is allowed to call which target - */ -contract PermissionedForwardProxy is ConfirmedOwner { - using Address for address; - - error PermissionNotSet(); - - event PermissionSet(address indexed sender, address target); - event PermissionRemoved(address indexed sender); - - mapping(address => address) private s_forwardPermissionList; - - constructor() ConfirmedOwner(msg.sender) {} - - /** - * @notice Verifies if msg.sender has permission to forward to target address and then forwards the handler - * @param target address of the contract to forward the handler to - * @param handler bytes to be passed to target in call data - */ - function forward(address target, bytes calldata handler) external { - if (s_forwardPermissionList[msg.sender] != target) { - revert PermissionNotSet(); - } - target.functionCall(handler); - } - - /** - * @notice Adds permission for sender to forward calls to target via this proxy. - * Note that it allows to overwrite an existing permission - * @param sender The address who will use this proxy to forward calls - * @param target The address where sender will be allowed to forward calls - */ - function setPermission(address sender, address target) external onlyOwner { - s_forwardPermissionList[sender] = target; - - emit PermissionSet(sender, target); - } - - /** - * @notice Removes permission for sender to forward calls via this proxy - * @param sender The address who will use this proxy to forward calls - */ - function removePermission(address sender) external onlyOwner { - delete s_forwardPermissionList[sender]; - - emit PermissionRemoved(sender); - } - - /** - * @notice Returns the target address that the sender can use this proxy for - * @param sender The address to fetch the permissioned target for - */ - function getPermission(address sender) external view returns (address) { - return s_forwardPermissionList[sender]; - } -} diff --git a/contracts/src/v0.8/ValidatorProxy.sol b/contracts/src/v0.8/ValidatorProxy.sol deleted file mode 100644 index 58e0e28a899..00000000000 --- a/contracts/src/v0.8/ValidatorProxy.sol +++ /dev/null @@ -1,230 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {ConfirmedOwner} from "./shared/access/ConfirmedOwner.sol"; -import {AggregatorValidatorInterface} from "./shared/interfaces/AggregatorValidatorInterface.sol"; -import {TypeAndVersionInterface} from "./interfaces/TypeAndVersionInterface.sol"; - -// solhint-disable gas-custom-errors -contract ValidatorProxy is AggregatorValidatorInterface, TypeAndVersionInterface, ConfirmedOwner { - /// @notice Uses a single storage slot to store the current address - struct AggregatorConfiguration { - address target; - bool hasNewProposal; - } - - struct ValidatorConfiguration { - AggregatorValidatorInterface target; - bool hasNewProposal; - } - - // Configuration for the current aggregator - AggregatorConfiguration private s_currentAggregator; - // Proposed aggregator address - address private s_proposedAggregator; - - // Configuration for the current validator - ValidatorConfiguration private s_currentValidator; - // Proposed validator address - AggregatorValidatorInterface private s_proposedValidator; - - event AggregatorProposed(address indexed aggregator); - event AggregatorUpgraded(address indexed previous, address indexed current); - event ValidatorProposed(AggregatorValidatorInterface indexed validator); - event ValidatorUpgraded(AggregatorValidatorInterface indexed previous, AggregatorValidatorInterface indexed current); - /// @notice The proposed aggregator called validate, but the call was not passed on to any validators - event ProposedAggregatorValidateCall( - address indexed proposed, - uint256 previousRoundId, - int256 previousAnswer, - uint256 currentRoundId, - int256 currentAnswer - ); - - /** - * @notice Construct the ValidatorProxy with an aggregator and a validator - * @param aggregator address - * @param validator address - */ - constructor(address aggregator, AggregatorValidatorInterface validator) ConfirmedOwner(msg.sender) { - s_currentAggregator = AggregatorConfiguration({target: aggregator, hasNewProposal: false}); - s_currentValidator = ValidatorConfiguration({target: validator, hasNewProposal: false}); - } - - /** - * @notice Validate a transmission - * @dev Must be called by either the `s_currentAggregator.target`, or the `s_proposedAggregator`. - * If called by the `s_currentAggregator.target` this function passes the call on to the `s_currentValidator.target` - * and the `s_proposedValidator`, if it is set. - * If called by the `s_proposedAggregator` this function emits a `ProposedAggregatorValidateCall` to signal that - * the call was received. - * @dev To guard against external `validate` calls reverting, we use raw calls here. - * We favour `call` over try-catch to ensure that failures are avoided even if the validator address is incorrectly - * set as a non-contract address. - * @dev If the `aggregator` and `validator` are the same contract or collude, this could exhibit reentrancy behavior. - * However, since that contract would have to be explicitly written for reentrancy and that the `owner` would have - * to configure this contract to use that malicious contract, we refrain from using mutex or check here. - * @dev This does not perform any checks on any roundId, so it is possible that a validator receive different reports - * for the same roundId at different points in time. Validator implementations should be aware of this. - * @param previousRoundId uint256 - * @param previousAnswer int256 - * @param currentRoundId uint256 - * @param currentAnswer int256 - * @return bool - */ - function validate( - uint256 previousRoundId, - int256 previousAnswer, - uint256 currentRoundId, - int256 currentAnswer - ) external override returns (bool) { - address currentAggregator = s_currentAggregator.target; - if (msg.sender != currentAggregator) { - address proposedAggregator = s_proposedAggregator; - require(msg.sender == proposedAggregator, "Not a configured aggregator"); - // If the aggregator is still in proposed state, emit an event and don't push to any validator. - // This is to confirm that `validate` is being called prior to upgrade. - emit ProposedAggregatorValidateCall( - proposedAggregator, - previousRoundId, - previousAnswer, - currentRoundId, - currentAnswer - ); - return true; - } - - // Send the validate call to the current validator - ValidatorConfiguration memory currentValidator = s_currentValidator; - address currentValidatorAddress = address(currentValidator.target); - require(currentValidatorAddress != address(0), "No validator set"); - // solhint-disable-next-line avoid-low-level-calls - currentValidatorAddress.call( - abi.encodeWithSelector( - AggregatorValidatorInterface.validate.selector, - previousRoundId, - previousAnswer, - currentRoundId, - currentAnswer - ) - ); - // If there is a new proposed validator, send the validate call to that validator also - if (currentValidator.hasNewProposal) { - // solhint-disable-next-line avoid-low-level-calls - address(s_proposedValidator).call( - abi.encodeWithSelector( - AggregatorValidatorInterface.validate.selector, - previousRoundId, - previousAnswer, - currentRoundId, - currentAnswer - ) - ); - } - return true; - } - - /** AGGREGATOR CONFIGURATION FUNCTIONS **/ - - /** - * @notice Propose an aggregator - * @dev A zero address can be used to unset the proposed aggregator. Only owner can call. - * @param proposed address - */ - function proposeNewAggregator(address proposed) external onlyOwner { - require(s_proposedAggregator != proposed && s_currentAggregator.target != proposed, "Invalid proposal"); - s_proposedAggregator = proposed; - // If proposed is zero address, hasNewProposal = false - s_currentAggregator.hasNewProposal = (proposed != address(0)); - emit AggregatorProposed(proposed); - } - - /** - * @notice Upgrade the aggregator by setting the current aggregator as the proposed aggregator. - * @dev Must have a proposed aggregator. Only owner can call. - */ - function upgradeAggregator() external onlyOwner { - // Get configuration in memory - AggregatorConfiguration memory current = s_currentAggregator; - address previous = current.target; - address proposed = s_proposedAggregator; - - // Perform the upgrade - require(current.hasNewProposal, "No proposal"); - s_currentAggregator = AggregatorConfiguration({target: proposed, hasNewProposal: false}); - delete s_proposedAggregator; - - emit AggregatorUpgraded(previous, proposed); - } - - /** - * @notice Get aggregator details - * @return current address - * @return hasProposal bool - * @return proposed address - */ - function getAggregators() external view returns (address current, bool hasProposal, address proposed) { - current = s_currentAggregator.target; - hasProposal = s_currentAggregator.hasNewProposal; - proposed = s_proposedAggregator; - return (current, hasProposal, proposed); - } - - /** VALIDATOR CONFIGURATION FUNCTIONS **/ - - /** - * @notice Propose an validator - * @dev A zero address can be used to unset the proposed validator. Only owner can call. - * @param proposed address - */ - function proposeNewValidator(AggregatorValidatorInterface proposed) external onlyOwner { - require(s_proposedValidator != proposed && s_currentValidator.target != proposed, "Invalid proposal"); - s_proposedValidator = proposed; - // If proposed is zero address, hasNewProposal = false - s_currentValidator.hasNewProposal = (address(proposed) != address(0)); - emit ValidatorProposed(proposed); - } - - /** - * @notice Upgrade the validator by setting the current validator as the proposed validator. - * @dev Must have a proposed validator. Only owner can call. - */ - function upgradeValidator() external onlyOwner { - // Get configuration in memory - ValidatorConfiguration memory current = s_currentValidator; - AggregatorValidatorInterface previous = current.target; - AggregatorValidatorInterface proposed = s_proposedValidator; - - // Perform the upgrade - require(current.hasNewProposal, "No proposal"); - s_currentValidator = ValidatorConfiguration({target: proposed, hasNewProposal: false}); - delete s_proposedValidator; - - emit ValidatorUpgraded(previous, proposed); - } - - /** - * @notice Get validator details - * @return current address - * @return hasProposal bool - * @return proposed address - */ - function getValidators() - external - view - returns (AggregatorValidatorInterface current, bool hasProposal, AggregatorValidatorInterface proposed) - { - current = s_currentValidator.target; - hasProposal = s_currentValidator.hasNewProposal; - proposed = s_proposedValidator; - return (current, hasProposal, proposed); - } - - /** - * @notice The type and version of this contract - * @return Type and version string - */ - function typeAndVersion() external pure virtual override returns (string memory) { - return "ValidatorProxy 1.0.0"; - } -} diff --git a/contracts/src/v0.8/automation/HeartbeatRequester.sol b/contracts/src/v0.8/automation/HeartbeatRequester.sol index 8ef7fa44422..077bb93d18f 100644 --- a/contracts/src/v0.8/automation/HeartbeatRequester.sol +++ b/contracts/src/v0.8/automation/HeartbeatRequester.sol @@ -2,7 +2,7 @@ // solhint-disable-next-line one-contract-per-file pragma solidity 0.8.6; -import {TypeAndVersionInterface} from "./../interfaces/TypeAndVersionInterface.sol"; +import {ITypeAndVersion} from "./../shared/interfaces/ITypeAndVersion.sol"; import {ConfirmedOwner} from "../shared/access/ConfirmedOwner.sol"; // defines some interfaces for type safety and reduces encoding/decoding @@ -20,7 +20,7 @@ interface IOffchainAggregator { * by eligible caller, it will call a proxy for an aggregator address and request a new round. The aggregator * is gated by permissions and this requester address needs to be whitelisted. */ -contract HeartbeatRequester is TypeAndVersionInterface, ConfirmedOwner { +contract HeartbeatRequester is ITypeAndVersion, ConfirmedOwner { event HeartbeatPermitted(address indexed permittedCaller, address newProxy, address oldProxy); event HeartbeatRemoved(address indexed permittedCaller, address removedProxy); diff --git a/contracts/src/v0.8/automation/UpkeepTranscoder.sol b/contracts/src/v0.8/automation/UpkeepTranscoder.sol index 03f40d890b8..5e60270d355 100644 --- a/contracts/src/v0.8/automation/UpkeepTranscoder.sol +++ b/contracts/src/v0.8/automation/UpkeepTranscoder.sol @@ -3,14 +3,14 @@ pragma solidity ^0.8.0; import {UpkeepTranscoderInterface} from "./interfaces/UpkeepTranscoderInterface.sol"; -import {TypeAndVersionInterface} from "../interfaces/TypeAndVersionInterface.sol"; +import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; import {UpkeepFormat} from "./UpkeepFormat.sol"; /** * @notice Transcoder for converting upkeep data from one keeper * registry version to another */ -contract UpkeepTranscoder is UpkeepTranscoderInterface, TypeAndVersionInterface { +contract UpkeepTranscoder is UpkeepTranscoderInterface, ITypeAndVersion { error InvalidTranscoding(); /** diff --git a/contracts/src/v0.8/automation/dev/MercuryRegistry.sol b/contracts/src/v0.8/automation/dev/MercuryRegistry.sol index 247301a7438..9035f0af927 100644 --- a/contracts/src/v0.8/automation/dev/MercuryRegistry.sol +++ b/contracts/src/v0.8/automation/dev/MercuryRegistry.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.19; import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; import {AutomationCompatibleInterface} from "../interfaces/AutomationCompatibleInterface.sol"; import {StreamsLookupCompatibleInterface} from "../interfaces/StreamsLookupCompatibleInterface.sol"; -import {ChainSpecificUtil} from "../../ChainSpecificUtil.sol"; +import {ChainSpecificUtil} from "../../shared/util/ChainSpecificUtil.sol"; /*--------------------------------------------------------------------------------------------------------------------+ | Mercury + Automation | diff --git a/contracts/src/v0.8/tests/MockArbGasInfo.sol b/contracts/src/v0.8/automation/mocks/MockArbGasInfo.sol similarity index 100% rename from contracts/src/v0.8/tests/MockArbGasInfo.sol rename to contracts/src/v0.8/automation/mocks/MockArbGasInfo.sol diff --git a/contracts/src/v0.8/mocks/MockArbSys.sol b/contracts/src/v0.8/automation/mocks/MockArbSys.sol similarity index 100% rename from contracts/src/v0.8/mocks/MockArbSys.sol rename to contracts/src/v0.8/automation/mocks/MockArbSys.sol diff --git a/contracts/src/v0.8/tests/MockGasBoundCaller.sol b/contracts/src/v0.8/automation/mocks/MockGasBoundCaller.sol similarity index 100% rename from contracts/src/v0.8/tests/MockGasBoundCaller.sol rename to contracts/src/v0.8/automation/mocks/MockGasBoundCaller.sol diff --git a/contracts/src/v0.8/tests/MockZKSyncSystemContext.sol b/contracts/src/v0.8/automation/mocks/MockZKSyncSystemContext.sol similarity index 100% rename from contracts/src/v0.8/tests/MockZKSyncSystemContext.sol rename to contracts/src/v0.8/automation/mocks/MockZKSyncSystemContext.sol diff --git a/contracts/src/v0.8/automation/test/v2_3/AutomationRegistry2_3.t.sol b/contracts/src/v0.8/automation/test/v2_3/AutomationRegistry2_3.t.sol index 41aabf1bbe2..e461060e27d 100644 --- a/contracts/src/v0.8/automation/test/v2_3/AutomationRegistry2_3.t.sol +++ b/contracts/src/v0.8/automation/test/v2_3/AutomationRegistry2_3.t.sol @@ -1653,6 +1653,140 @@ contract Transmit is SetUp { vm.stopPrank(); } + struct PaymentReceipt { + uint96 gasChargeInBillingToken; + uint96 premiumInBillingToken; + uint96 gasReimbursementInJuels; + uint96 premiumInJuels; + IERC20 billingToken; + uint96 linkUSD; + uint96 nativeUSD; + uint96 billingUSD; + } + event ReorgedUpkeepReport(uint256 indexed id, bytes trigger); + event UpkeepCharged(uint256 indexed id, PaymentReceipt receipt); + event UpkeepPerformed( + uint256 indexed id, + bool indexed success, + uint96 totalPayment, + uint256 gasUsed, + uint256 gasOverhead, + bytes trigger + ); + function test_whenFirstUpkeepFails_subsequentUpkeepsPerform() external { + // the first and second upkeeps use LINK as billing token and the third uses WETH + // the first upkeep fails the pre perform check due to incorrect block number in its trigger + // the second and third upkeep perform + // the first upkeep should not be charged and the second and third upkeep should be charged + uint256[] memory prevUpkeepBalances = new uint256[](3); + prevUpkeepBalances[0] = registry.getBalance(linkUpkeepID); + prevUpkeepBalances[1] = registry.getBalance(linkUpkeepID2); + prevUpkeepBalances[2] = registry.getBalance(nativeUpkeepID); + uint256[] memory prevTokenBalances = new uint256[](2); + prevTokenBalances[0] = linkToken.balanceOf(address(registry)); + prevTokenBalances[1] = weth.balanceOf(address(registry)); + uint256[] memory prevReserveBalances = new uint256[](2); + prevReserveBalances[0] = registry.getReserveAmount(address(linkToken)); + prevReserveBalances[1] = registry.getReserveAmount(address(weth)); + uint256[] memory upkeepIDs = new uint256[](3); + upkeepIDs[0] = linkUpkeepID; + upkeepIDs[1] = linkUpkeepID2; + upkeepIDs[2] = nativeUpkeepID; + + // do the transmit + vm.expectEmit(); + emit ReorgedUpkeepReport(linkUpkeepID, abi.encode(block.number, blockhash(block.number))); + vm.expectEmit(true, false, false, false); + emit UpkeepCharged(linkUpkeepID2, PaymentReceipt(0, 0, 0, 0, linkToken, 0, 0, 0)); + vm.expectEmit(true, true, false, false); + emit UpkeepPerformed(linkUpkeepID2, true, 0, 0, 0, bytes("")); + vm.expectEmit(true, false, false, false); + emit UpkeepCharged(nativeUpkeepID, PaymentReceipt(0, 0, 0, 0, linkToken, 0, 0, 0)); + vm.expectEmit(true, true, false, false); + emit UpkeepPerformed(nativeUpkeepID, true, 0, 0, 0, bytes("")); + bool[] memory goodTriggers = new bool[](3); + goodTriggers[0] = false; + goodTriggers[1] = true; + goodTriggers[2] = true; + _batchTransmitWithBadTriggers(upkeepIDs, goodTriggers, registry); + + // assert upkeep balances + // the first upkeep fails and the second and third upkeep succeeds + require(prevUpkeepBalances[0] == registry.getBalance(linkUpkeepID), "link upkeep balance should remain the same"); + require(prevUpkeepBalances[1] > registry.getBalance(linkUpkeepID2), "link upkeep 2 balance should have decreased"); + require(prevUpkeepBalances[2] > registry.getBalance(nativeUpkeepID), "native upkeep balance should have decreased"); + // assert token balances have not changed + assertEq(prevTokenBalances[0], linkToken.balanceOf(address(registry))); + assertEq(prevTokenBalances[1], weth.balanceOf(address(registry))); + // assert reserve amounts have adjusted accordingly + require( + prevReserveBalances[0] < registry.getReserveAmount(address(linkToken)), + "link reserve amount should have increased" + ); // link reserve amount increases in value equal to the decrease of the other reserve amounts + require( + prevReserveBalances[1] > registry.getReserveAmount(address(weth)), + "native reserve amount should have decreased" + ); + } + + function test_whenSecondUpkeepFails_FirstAndThirdUpkeepsPerform() external { + // the first upkeep uses WETH as billing token and the second and third use LINK + // the first upkeep succeeds + // the second upkeep fails pre perform check due to incorrect block number in its trigger + // the third upkeep succeeds + // the second upkeep should not be charged and the first and third upkeep should be charged + uint256[] memory prevUpkeepBalances = new uint256[](3); + prevUpkeepBalances[0] = registry.getBalance(nativeUpkeepID); + prevUpkeepBalances[1] = registry.getBalance(linkUpkeepID); + prevUpkeepBalances[2] = registry.getBalance(linkUpkeepID2); + uint256[] memory prevTokenBalances = new uint256[](2); + prevTokenBalances[0] = weth.balanceOf(address(registry)); + prevTokenBalances[1] = linkToken.balanceOf(address(registry)); + uint256[] memory prevReserveBalances = new uint256[](2); + prevReserveBalances[0] = registry.getReserveAmount(address(weth)); + prevReserveBalances[1] = registry.getReserveAmount(address(linkToken)); + uint256[] memory upkeepIDs = new uint256[](3); + upkeepIDs[0] = nativeUpkeepID; + upkeepIDs[1] = linkUpkeepID; + upkeepIDs[2] = linkUpkeepID2; + + // do the transmit + // expect this event first because all the upkeeps will be checked first before they are performed and charged + vm.expectEmit(); + emit ReorgedUpkeepReport(linkUpkeepID, abi.encode(block.number, blockhash(block.number))); + vm.expectEmit(true, false, false, false); + emit UpkeepCharged(nativeUpkeepID, PaymentReceipt(0, 0, 0, 0, linkToken, 0, 0, 0)); + vm.expectEmit(true, true, false, false); + emit UpkeepPerformed(nativeUpkeepID, true, 0, 0, 0, bytes("")); + vm.expectEmit(true, false, false, false); + emit UpkeepCharged(linkUpkeepID2, PaymentReceipt(0, 0, 0, 0, linkToken, 0, 0, 0)); + vm.expectEmit(true, true, false, false); + emit UpkeepPerformed(linkUpkeepID2, true, 0, 0, 0, bytes("")); + bool[] memory goodTriggers = new bool[](3); + goodTriggers[0] = true; + goodTriggers[1] = false; + goodTriggers[2] = true; + _batchTransmitWithBadTriggers(upkeepIDs, goodTriggers, registry); + + // assert upkeep balances + // the first upkeep fails and the second and third upkeep succeeds + require(prevUpkeepBalances[0] > registry.getBalance(nativeUpkeepID), "native upkeep balance should have decreased"); + require(prevUpkeepBalances[1] == registry.getBalance(linkUpkeepID), "link upkeep balance should remain the same"); + require(prevUpkeepBalances[2] > registry.getBalance(linkUpkeepID2), "link upkeep 2 balance should have decreased"); + // assert token balances have not changed + assertEq(prevTokenBalances[0], weth.balanceOf(address(registry))); + assertEq(prevTokenBalances[1], linkToken.balanceOf(address(registry))); + // assert reserve amounts have adjusted accordingly + require( + prevReserveBalances[0] > registry.getReserveAmount(address(weth)), + "native reserve amount should have decreased" + ); // link reserve amount increases in value equal to the decrease of the other reserve amounts + require( + prevReserveBalances[1] < registry.getReserveAmount(address(linkToken)), + "link reserve amount should have increased" + ); + } + function test_handlesMixedBatchOfBillingTokens() external { uint256[] memory prevUpkeepBalances = new uint256[](3); prevUpkeepBalances[0] = registry.getBalance(linkUpkeepID); @@ -1696,7 +1830,7 @@ contract Transmit is SetUp { // assert reserve amounts have adjusted accordingly require( prevReserveBalances[0] < registry.getReserveAmount(address(linkToken)), - "usd reserve amount should have increased" + "link reserve amount should have increased" ); // link reserve amount increases in value equal to the decrease of the other reserve amounts require( prevReserveBalances[1] > registry.getReserveAmount(address(usdToken18)), diff --git a/contracts/src/v0.8/automation/test/v2_3/BaseTest.t.sol b/contracts/src/v0.8/automation/test/v2_3/BaseTest.t.sol index e0d15daab6c..44bb0f0ae60 100644 --- a/contracts/src/v0.8/automation/test/v2_3/BaseTest.t.sol +++ b/contracts/src/v0.8/automation/test/v2_3/BaseTest.t.sol @@ -6,7 +6,7 @@ import "forge-std/Test.sol"; import {LinkToken} from "../../../shared/token/ERC677/LinkToken.sol"; import {ERC20Mock} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol"; import {ERC20Mock6Decimals} from "../../mocks/ERC20Mock6Decimals.sol"; -import {MockV3Aggregator} from "../../../tests/MockV3Aggregator.sol"; +import {MockV3Aggregator} from "../../../shared/mocks/MockV3Aggregator.sol"; import {AutomationForwarderLogic} from "../../AutomationForwarderLogic.sol"; import {UpkeepTranscoder5_0 as Transcoder} from "../../v2_3/UpkeepTranscoder5_0.sol"; import {AutomationRegistry2_3} from "../../v2_3/AutomationRegistry2_3.sol"; @@ -367,6 +367,54 @@ contract BaseTest is Test { _handleTransmit(ids, registry, bytes4(0)); } + function _batchTransmitWithBadTriggers(uint256[] memory ids, bool[] memory goodTriggers, Registry registry) internal { + bytes memory reportBytes; + { + uint256[] memory upkeepIds = new uint256[](ids.length); + uint256[] memory gasLimits = new uint256[](ids.length); + bytes[] memory performDatas = new bytes[](ids.length); + bytes[] memory triggers = new bytes[](ids.length); + for (uint256 i = 0; i < ids.length; i++) { + upkeepIds[i] = ids[i]; + gasLimits[i] = registry.getUpkeep(ids[i]).performGas; + performDatas[i] = new bytes(0); + uint8 triggerType = registry.getTriggerType(ids[i]); + if (triggerType == 0) { + uint256 j = 0; + if (goodTriggers[i]) { + j = 1; + } + triggers[i] = _encodeConditionalTrigger( + AutoBase.ConditionalTrigger(uint32(block.number - j), blockhash(block.number - j)) + ); + } else { + revert("not implemented"); + } + } + + AutoBase.Report memory report = AutoBase.Report( + uint256(1000000000), + uint256(2000000000), + upkeepIds, + gasLimits, + triggers, + performDatas + ); + + reportBytes = _encodeReport(report); + } + (, , bytes32 configDigest) = registry.latestConfigDetails(); + bytes32[3] memory reportContext = [configDigest, configDigest, configDigest]; + uint256[] memory signerPKs = new uint256[](2); + signerPKs[0] = SIGNING_KEY0; + signerPKs[1] = SIGNING_KEY1; + (bytes32[] memory rs, bytes32[] memory ss, bytes32 vs) = _signReport(reportBytes, reportContext, signerPKs); + + vm.startPrank(TRANSMITTERS[0]); + registry.transmit(reportContext, reportBytes, rs, ss, vs); + vm.stopPrank(); + } + // tests single upkeep, expects revert function _transmitAndExpectRevert(uint256 id, Registry registry, bytes4 selector) internal { uint256[] memory ids = new uint256[](1); diff --git a/contracts/src/v0.8/automation/test/v2_3_zksync/BaseTest.t.sol b/contracts/src/v0.8/automation/test/v2_3_zksync/BaseTest.t.sol index cde05ab3a22..f33360aa9f6 100644 --- a/contracts/src/v0.8/automation/test/v2_3_zksync/BaseTest.t.sol +++ b/contracts/src/v0.8/automation/test/v2_3_zksync/BaseTest.t.sol @@ -6,7 +6,7 @@ import "forge-std/Test.sol"; import {LinkToken} from "../../../shared/token/ERC677/LinkToken.sol"; import {ERC20Mock} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol"; import {ERC20Mock6Decimals} from "../../mocks/ERC20Mock6Decimals.sol"; -import {MockV3Aggregator} from "../../../tests/MockV3Aggregator.sol"; +import {MockV3Aggregator} from "../../../shared/mocks/MockV3Aggregator.sol"; import {AutomationForwarderLogic} from "../../AutomationForwarderLogic.sol"; import {UpkeepTranscoder5_0 as Transcoder} from "../../v2_3/UpkeepTranscoder5_0.sol"; import {ZKSyncAutomationRegistry2_3} from "../../v2_3_zksync/ZKSyncAutomationRegistry2_3.sol"; @@ -21,8 +21,8 @@ import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4 import {MockUpkeep} from "../../mocks/MockUpkeep.sol"; import {IWrappedNative} from "../../interfaces/v2_3/IWrappedNative.sol"; import {WETH9} from "../WETH9.sol"; -import {MockGasBoundCaller} from "../../../tests/MockGasBoundCaller.sol"; -import {MockZKSyncSystemContext} from "../../../tests/MockZKSyncSystemContext.sol"; +import {MockGasBoundCaller} from "../../mocks/MockGasBoundCaller.sol"; +import {MockZKSyncSystemContext} from "../../mocks/MockZKSyncSystemContext.sol"; /** * @title BaseTest provides basic test setup procedures and dependencies for use by other @@ -419,6 +419,54 @@ contract BaseTest is Test { vm.stopPrank(); } + function _batchTransmitWithBadTriggers(uint256[] memory ids, bool[] memory goodTriggers, Registry registry) internal { + bytes memory reportBytes; + { + uint256[] memory upkeepIds = new uint256[](ids.length); + uint256[] memory gasLimits = new uint256[](ids.length); + bytes[] memory performDatas = new bytes[](ids.length); + bytes[] memory triggers = new bytes[](ids.length); + for (uint256 i = 0; i < ids.length; i++) { + upkeepIds[i] = ids[i]; + gasLimits[i] = registry.getUpkeep(ids[i]).performGas; + performDatas[i] = new bytes(0); + uint8 triggerType = registry.getTriggerType(ids[i]); + if (triggerType == 0) { + uint256 j = 0; + if (goodTriggers[i]) { + j = 1; + } + triggers[i] = _encodeConditionalTrigger( + ZKSyncAutoBase.ConditionalTrigger(uint32(block.number - j), blockhash(block.number - j)) + ); + } else { + revert("not implemented"); + } + } + + ZKSyncAutoBase.Report memory report = ZKSyncAutoBase.Report( + uint256(1000000000), + uint256(2000000000), + upkeepIds, + gasLimits, + triggers, + performDatas + ); + + reportBytes = _encodeReport(report); + } + (, , bytes32 configDigest) = registry.latestConfigDetails(); + bytes32[3] memory reportContext = [configDigest, configDigest, configDigest]; + uint256[] memory signerPKs = new uint256[](2); + signerPKs[0] = SIGNING_KEY0; + signerPKs[1] = SIGNING_KEY1; + (bytes32[] memory rs, bytes32[] memory ss, bytes32 vs) = _signReport(reportBytes, reportContext, signerPKs); + + vm.startPrank(TRANSMITTERS[0]); + registry.transmit(reportContext, reportBytes, rs, ss, vs); + vm.stopPrank(); + } + /// @notice Gather signatures on report data /// @param report - Report bytes generated from `_buildReport` /// @param reportContext - Report context bytes32 generated from `_buildReport` diff --git a/contracts/src/v0.8/automation/test/v2_3_zksync/ZKSyncAutomationRegistry2_3.t.sol b/contracts/src/v0.8/automation/test/v2_3_zksync/ZKSyncAutomationRegistry2_3.t.sol index 7098d9f38fa..2e3ca5b1584 100644 --- a/contracts/src/v0.8/automation/test/v2_3_zksync/ZKSyncAutomationRegistry2_3.t.sol +++ b/contracts/src/v0.8/automation/test/v2_3_zksync/ZKSyncAutomationRegistry2_3.t.sol @@ -1655,6 +1655,140 @@ contract Transmit is SetUp { vm.stopPrank(); } + struct PaymentReceipt { + uint96 gasChargeInBillingToken; + uint96 premiumInBillingToken; + uint96 gasReimbursementInJuels; + uint96 premiumInJuels; + IERC20 billingToken; + uint96 linkUSD; + uint96 nativeUSD; + uint96 billingUSD; + } + event ReorgedUpkeepReport(uint256 indexed id, bytes trigger); + event UpkeepCharged(uint256 indexed id, PaymentReceipt receipt); + event UpkeepPerformed( + uint256 indexed id, + bool indexed success, + uint96 totalPayment, + uint256 gasUsed, + uint256 gasOverhead, + bytes trigger + ); + function test_whenFirstUpkeepFails_subsequentUpkeepsPerformZK() external { + // the first and second upkeeps use LINK as billing token and the third uses WETH + // the first upkeep fails the pre perform check due to incorrect block number in its trigger + // the second and third upkeep perform + // the first upkeep should not be charged and the second and third upkeep should be charged + uint256[] memory prevUpkeepBalances = new uint256[](3); + prevUpkeepBalances[0] = registry.getBalance(linkUpkeepID); + prevUpkeepBalances[1] = registry.getBalance(linkUpkeepID2); + prevUpkeepBalances[2] = registry.getBalance(nativeUpkeepID); + uint256[] memory prevTokenBalances = new uint256[](2); + prevTokenBalances[0] = linkToken.balanceOf(address(registry)); + prevTokenBalances[1] = weth.balanceOf(address(registry)); + uint256[] memory prevReserveBalances = new uint256[](2); + prevReserveBalances[0] = registry.getReserveAmount(address(linkToken)); + prevReserveBalances[1] = registry.getReserveAmount(address(weth)); + uint256[] memory upkeepIDs = new uint256[](3); + upkeepIDs[0] = linkUpkeepID; + upkeepIDs[1] = linkUpkeepID2; + upkeepIDs[2] = nativeUpkeepID; + + // do the transmit + vm.expectEmit(); + emit ReorgedUpkeepReport(linkUpkeepID, abi.encode(block.number, blockhash(block.number))); + vm.expectEmit(true, false, false, false); + emit UpkeepCharged(linkUpkeepID2, PaymentReceipt(0, 0, 0, 0, linkToken, 0, 0, 0)); + vm.expectEmit(true, true, false, false); + emit UpkeepPerformed(linkUpkeepID2, true, 0, 0, 0, bytes("")); + vm.expectEmit(true, false, false, false); + emit UpkeepCharged(nativeUpkeepID, PaymentReceipt(0, 0, 0, 0, linkToken, 0, 0, 0)); + vm.expectEmit(true, true, false, false); + emit UpkeepPerformed(nativeUpkeepID, true, 0, 0, 0, bytes("")); + bool[] memory goodTriggers = new bool[](3); + goodTriggers[0] = false; + goodTriggers[1] = true; + goodTriggers[2] = true; + _batchTransmitWithBadTriggers(upkeepIDs, goodTriggers, registry); + + // assert upkeep balances + // the first upkeep fails and the second and third upkeep succeeds + require(prevUpkeepBalances[0] == registry.getBalance(linkUpkeepID), "link upkeep balance should remain the same"); + require(prevUpkeepBalances[1] > registry.getBalance(linkUpkeepID2), "link upkeep 2 balance should have decreased"); + require(prevUpkeepBalances[2] > registry.getBalance(nativeUpkeepID), "native upkeep balance should have decreased"); + // assert token balances have not changed + assertEq(prevTokenBalances[0], linkToken.balanceOf(address(registry))); + assertEq(prevTokenBalances[1], weth.balanceOf(address(registry))); + // assert reserve amounts have adjusted accordingly + require( + prevReserveBalances[0] < registry.getReserveAmount(address(linkToken)), + "link reserve amount should have increased" + ); // link reserve amount increases in value equal to the decrease of the other reserve amounts + require( + prevReserveBalances[1] > registry.getReserveAmount(address(weth)), + "native reserve amount should have decreased" + ); + } + + function test_whenSecondUpkeepFails_FirstAndThirdUpkeepsPerform() external { + // the first upkeep uses WETH as billing token and the second and third use LINK + // the first upkeep succeeds + // the second upkeep fails pre perform check due to incorrect block number in its trigger + // the third upkeep succeeds + // the second upkeep should not be charged and the first and third upkeep should be charged + uint256[] memory prevUpkeepBalances = new uint256[](3); + prevUpkeepBalances[0] = registry.getBalance(nativeUpkeepID); + prevUpkeepBalances[1] = registry.getBalance(linkUpkeepID); + prevUpkeepBalances[2] = registry.getBalance(linkUpkeepID2); + uint256[] memory prevTokenBalances = new uint256[](2); + prevTokenBalances[0] = weth.balanceOf(address(registry)); + prevTokenBalances[1] = linkToken.balanceOf(address(registry)); + uint256[] memory prevReserveBalances = new uint256[](2); + prevReserveBalances[0] = registry.getReserveAmount(address(weth)); + prevReserveBalances[1] = registry.getReserveAmount(address(linkToken)); + uint256[] memory upkeepIDs = new uint256[](3); + upkeepIDs[0] = nativeUpkeepID; + upkeepIDs[1] = linkUpkeepID; + upkeepIDs[2] = linkUpkeepID2; + + // do the transmit + // expect this event first because all the upkeeps will be checked first before they are performed and charged + vm.expectEmit(); + emit ReorgedUpkeepReport(linkUpkeepID, abi.encode(block.number, blockhash(block.number))); + vm.expectEmit(true, false, false, false); + emit UpkeepCharged(nativeUpkeepID, PaymentReceipt(0, 0, 0, 0, linkToken, 0, 0, 0)); + vm.expectEmit(true, true, false, false); + emit UpkeepPerformed(nativeUpkeepID, true, 0, 0, 0, bytes("")); + vm.expectEmit(true, false, false, false); + emit UpkeepCharged(linkUpkeepID2, PaymentReceipt(0, 0, 0, 0, linkToken, 0, 0, 0)); + vm.expectEmit(true, true, false, false); + emit UpkeepPerformed(linkUpkeepID2, true, 0, 0, 0, bytes("")); + bool[] memory goodTriggers = new bool[](3); + goodTriggers[0] = true; + goodTriggers[1] = false; + goodTriggers[2] = true; + _batchTransmitWithBadTriggers(upkeepIDs, goodTriggers, registry); + + // assert upkeep balances + // the first upkeep fails and the second and third upkeep succeeds + require(prevUpkeepBalances[0] > registry.getBalance(nativeUpkeepID), "native upkeep balance should have decreased"); + require(prevUpkeepBalances[1] == registry.getBalance(linkUpkeepID), "link upkeep balance should remain the same"); + require(prevUpkeepBalances[2] > registry.getBalance(linkUpkeepID2), "link upkeep 2 balance should have decreased"); + // assert token balances have not changed + assertEq(prevTokenBalances[0], weth.balanceOf(address(registry))); + assertEq(prevTokenBalances[1], linkToken.balanceOf(address(registry))); + // assert reserve amounts have adjusted accordingly + require( + prevReserveBalances[0] > registry.getReserveAmount(address(weth)), + "native reserve amount should have decreased" + ); // link reserve amount increases in value equal to the decrease of the other reserve amounts + require( + prevReserveBalances[1] < registry.getReserveAmount(address(linkToken)), + "link reserve amount should have increased" + ); + } + function test_handlesMixedBatchOfBillingTokens() external { uint256[] memory prevUpkeepBalances = new uint256[](3); prevUpkeepBalances[0] = registry.getBalance(linkUpkeepID); @@ -1698,7 +1832,7 @@ contract Transmit is SetUp { // assert reserve amounts have adjusted accordingly require( prevReserveBalances[0] < registry.getReserveAmount(address(linkToken)), - "usd reserve amount should have increased" + "link reserve amount should have increased" ); // link reserve amount increases in value equal to the decrease of the other reserve amounts require( prevReserveBalances[1] > registry.getReserveAmount(address(usdToken18)), diff --git a/contracts/src/v0.8/tests/AutomationConsumerBenchmark.sol b/contracts/src/v0.8/automation/testhelpers/AutomationConsumerBenchmark.sol similarity index 100% rename from contracts/src/v0.8/tests/AutomationConsumerBenchmark.sol rename to contracts/src/v0.8/automation/testhelpers/AutomationConsumerBenchmark.sol diff --git a/contracts/src/v0.8/tests/CronReceiver.sol b/contracts/src/v0.8/automation/testhelpers/CronReceiver.sol similarity index 100% rename from contracts/src/v0.8/tests/CronReceiver.sol rename to contracts/src/v0.8/automation/testhelpers/CronReceiver.sol diff --git a/contracts/src/v0.8/tests/ERC20BalanceMonitorExposed.sol b/contracts/src/v0.8/automation/testhelpers/ERC20BalanceMonitorExposed.sol similarity index 89% rename from contracts/src/v0.8/tests/ERC20BalanceMonitorExposed.sol rename to contracts/src/v0.8/automation/testhelpers/ERC20BalanceMonitorExposed.sol index a29ba36eeb4..748cf1cb727 100644 --- a/contracts/src/v0.8/tests/ERC20BalanceMonitorExposed.sol +++ b/contracts/src/v0.8/automation/testhelpers/ERC20BalanceMonitorExposed.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.6; -import "../automation/upkeeps/ERC20BalanceMonitor.sol"; +import "../upkeeps/ERC20BalanceMonitor.sol"; contract ERC20BalanceMonitorExposed is ERC20BalanceMonitor { constructor( diff --git a/contracts/src/v0.8/tests/EthBalanceMonitorExposed.sol b/contracts/src/v0.8/automation/testhelpers/EthBalanceMonitorExposed.sol similarity index 88% rename from contracts/src/v0.8/tests/EthBalanceMonitorExposed.sol rename to contracts/src/v0.8/automation/testhelpers/EthBalanceMonitorExposed.sol index 74cc682df23..f27c9621c39 100644 --- a/contracts/src/v0.8/tests/EthBalanceMonitorExposed.sol +++ b/contracts/src/v0.8/automation/testhelpers/EthBalanceMonitorExposed.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.6; -import "../automation/upkeeps/EthBalanceMonitor.sol"; +import "../upkeeps/EthBalanceMonitor.sol"; contract EthBalanceMonitorExposed is EthBalanceMonitor { constructor( diff --git a/contracts/src/v0.8/tests/KeeperCompatibleTestHelper.sol b/contracts/src/v0.8/automation/testhelpers/KeeperCompatibleTestHelper.sol similarity index 88% rename from contracts/src/v0.8/tests/KeeperCompatibleTestHelper.sol rename to contracts/src/v0.8/automation/testhelpers/KeeperCompatibleTestHelper.sol index 2e931c4fb4d..3c71dc2f848 100644 --- a/contracts/src/v0.8/tests/KeeperCompatibleTestHelper.sol +++ b/contracts/src/v0.8/automation/testhelpers/KeeperCompatibleTestHelper.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import "../automation/KeeperCompatible.sol"; +import "../KeeperCompatible.sol"; contract KeeperCompatibleTestHelper is KeeperCompatible { function checkUpkeep(bytes calldata) external override returns (bool, bytes memory) {} diff --git a/contracts/src/v0.8/tests/MockOVMGasPriceOracle.sol b/contracts/src/v0.8/automation/testhelpers/MockOVMGasPriceOracle.sol similarity index 100% rename from contracts/src/v0.8/tests/MockOVMGasPriceOracle.sol rename to contracts/src/v0.8/automation/testhelpers/MockOVMGasPriceOracle.sol diff --git a/contracts/src/v0.8/tests/ReceiveEmitter.sol b/contracts/src/v0.8/automation/testhelpers/ReceiveEmitter.sol similarity index 100% rename from contracts/src/v0.8/tests/ReceiveEmitter.sol rename to contracts/src/v0.8/automation/testhelpers/ReceiveEmitter.sol diff --git a/contracts/src/v0.8/tests/ReceiveFallbackEmitter.sol b/contracts/src/v0.8/automation/testhelpers/ReceiveFallbackEmitter.sol similarity index 100% rename from contracts/src/v0.8/tests/ReceiveFallbackEmitter.sol rename to contracts/src/v0.8/automation/testhelpers/ReceiveFallbackEmitter.sol diff --git a/contracts/src/v0.8/tests/ReceiveReverter.sol b/contracts/src/v0.8/automation/testhelpers/ReceiveReverter.sol similarity index 100% rename from contracts/src/v0.8/tests/ReceiveReverter.sol rename to contracts/src/v0.8/automation/testhelpers/ReceiveReverter.sol diff --git a/contracts/src/v0.8/tests/StreamsLookupUpkeep.sol b/contracts/src/v0.8/automation/testhelpers/StreamsLookupUpkeep.sol similarity index 95% rename from contracts/src/v0.8/tests/StreamsLookupUpkeep.sol rename to contracts/src/v0.8/automation/testhelpers/StreamsLookupUpkeep.sol index dec93d5b1f7..aaf35b5c595 100644 --- a/contracts/src/v0.8/tests/StreamsLookupUpkeep.sol +++ b/contracts/src/v0.8/automation/testhelpers/StreamsLookupUpkeep.sol @@ -1,8 +1,8 @@ pragma solidity 0.8.16; -import "../automation/interfaces/AutomationCompatibleInterface.sol"; -import "../automation/interfaces/StreamsLookupCompatibleInterface.sol"; -import {ArbSys} from "../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; +import "../interfaces/AutomationCompatibleInterface.sol"; +import "../interfaces/StreamsLookupCompatibleInterface.sol"; +import {ArbSys} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; interface IVerifierProxy { /** diff --git a/contracts/src/v0.8/tests/VerifiableLoadBase.sol b/contracts/src/v0.8/automation/testhelpers/VerifiableLoadBase.sol similarity index 98% rename from contracts/src/v0.8/tests/VerifiableLoadBase.sol rename to contracts/src/v0.8/automation/testhelpers/VerifiableLoadBase.sol index 86ebf8b8c7c..1aa181dd1d3 100644 --- a/contracts/src/v0.8/tests/VerifiableLoadBase.sol +++ b/contracts/src/v0.8/automation/testhelpers/VerifiableLoadBase.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.16; -import "../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; -import {IKeeperRegistryMaster, IAutomationV21PlusCommon} from "../automation/interfaces/v2_1/IKeeperRegistryMaster.sol"; -import {ArbSys} from "../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; -import "../automation/v2_1/AutomationRegistrar2_1.sol"; -import {LogTriggerConfig} from "../automation/v2_1/AutomationUtils2_1.sol"; +import "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; +import {IKeeperRegistryMaster, IAutomationV21PlusCommon} from "../interfaces/v2_1/IKeeperRegistryMaster.sol"; +import {ArbSys} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; +import "../v2_1/AutomationRegistrar2_1.sol"; +import {LogTriggerConfig} from "../v2_1/AutomationUtils2_1.sol"; abstract contract VerifiableLoadBase is ConfirmedOwner { error IndexOutOfRange(); diff --git a/contracts/src/v0.8/tests/VerifiableLoadLogTriggerUpkeep.sol b/contracts/src/v0.8/automation/testhelpers/VerifiableLoadLogTriggerUpkeep.sol similarity index 97% rename from contracts/src/v0.8/tests/VerifiableLoadLogTriggerUpkeep.sol rename to contracts/src/v0.8/automation/testhelpers/VerifiableLoadLogTriggerUpkeep.sol index 39b95bb0ae5..400ddd0c966 100644 --- a/contracts/src/v0.8/tests/VerifiableLoadLogTriggerUpkeep.sol +++ b/contracts/src/v0.8/automation/testhelpers/VerifiableLoadLogTriggerUpkeep.sol @@ -2,8 +2,8 @@ pragma solidity 0.8.16; import "./VerifiableLoadBase.sol"; -import "../automation/interfaces/ILogAutomation.sol"; -import "../automation/interfaces/StreamsLookupCompatibleInterface.sol"; +import "../interfaces/ILogAutomation.sol"; +import "../interfaces/StreamsLookupCompatibleInterface.sol"; contract VerifiableLoadLogTriggerUpkeep is VerifiableLoadBase, StreamsLookupCompatibleInterface, ILogAutomation { bool public useMercury; diff --git a/contracts/src/v0.8/tests/VerifiableLoadStreamsLookupUpkeep.sol b/contracts/src/v0.8/automation/testhelpers/VerifiableLoadStreamsLookupUpkeep.sol similarity index 97% rename from contracts/src/v0.8/tests/VerifiableLoadStreamsLookupUpkeep.sol rename to contracts/src/v0.8/automation/testhelpers/VerifiableLoadStreamsLookupUpkeep.sol index c74aec1a790..97be9ebc81a 100644 --- a/contracts/src/v0.8/tests/VerifiableLoadStreamsLookupUpkeep.sol +++ b/contracts/src/v0.8/automation/testhelpers/VerifiableLoadStreamsLookupUpkeep.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.16; import "./VerifiableLoadBase.sol"; -import "../automation/interfaces/StreamsLookupCompatibleInterface.sol"; +import "../interfaces/StreamsLookupCompatibleInterface.sol"; contract VerifiableLoadStreamsLookupUpkeep is VerifiableLoadBase, StreamsLookupCompatibleInterface { constructor(AutomationRegistrar2_1 _registrar, bool _useArb) VerifiableLoadBase(_registrar, _useArb) {} diff --git a/contracts/src/v0.8/tests/VerifiableLoadUpkeep.sol b/contracts/src/v0.8/automation/testhelpers/VerifiableLoadUpkeep.sol similarity index 100% rename from contracts/src/v0.8/tests/VerifiableLoadUpkeep.sol rename to contracts/src/v0.8/automation/testhelpers/VerifiableLoadUpkeep.sol diff --git a/contracts/src/v0.8/automation/v1_2/KeeperRegistrar1_2.sol b/contracts/src/v0.8/automation/v1_2/KeeperRegistrar1_2.sol index f455d56f17a..d2b6e560487 100644 --- a/contracts/src/v0.8/automation/v1_2/KeeperRegistrar1_2.sol +++ b/contracts/src/v0.8/automation/v1_2/KeeperRegistrar1_2.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.6; import "../interfaces/v1_2/KeeperRegistryInterface1_2.sol"; -import "../../interfaces/TypeAndVersionInterface.sol"; +import "../../shared/interfaces/ITypeAndVersion.sol"; import "../../shared/interfaces/LinkTokenInterface.sol"; import "../../shared/access/ConfirmedOwner.sol"; import "../../shared/interfaces/IERC677Receiver.sol"; @@ -17,7 +17,7 @@ import "../../shared/interfaces/IERC677Receiver.sol"; * The idea is to have same interface(functions,events) for UI or anyone using this contract irrespective of auto approve being enabled or not. * they can just listen to `RegistrationRequested` & `RegistrationApproved` events and know the status on registrations. */ -contract KeeperRegistrar is TypeAndVersionInterface, ConfirmedOwner, IERC677Receiver { +contract KeeperRegistrar is ITypeAndVersion, ConfirmedOwner, IERC677Receiver { /** * DISABLED: No auto approvals, all new upkeeps should be approved manually. * ENABLED_SENDER_ALLOWLIST: Auto approvals for allowed senders subject to max allowed. Manual for rest. diff --git a/contracts/src/v0.8/automation/v1_2/KeeperRegistry1_2.sol b/contracts/src/v0.8/automation/v1_2/KeeperRegistry1_2.sol index 2fa1ee6188b..5e1c8dacd48 100644 --- a/contracts/src/v0.8/automation/v1_2/KeeperRegistry1_2.sol +++ b/contracts/src/v0.8/automation/v1_2/KeeperRegistry1_2.sol @@ -6,7 +6,7 @@ import "@openzeppelin/contracts/utils/Address.sol"; import "@openzeppelin/contracts/security/Pausable.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "../KeeperBase.sol"; -import "../../interfaces/TypeAndVersionInterface.sol"; +import "../../shared/interfaces/ITypeAndVersion.sol"; import "../../shared/interfaces/AggregatorV3Interface.sol"; import "../interfaces/KeeperCompatibleInterface.sol"; import "../interfaces/v1_2/KeeperRegistryInterface1_2.sol"; @@ -31,7 +31,7 @@ struct Upkeep { * contracts. Clients must support the Upkeep interface. */ contract KeeperRegistry1_2 is - TypeAndVersionInterface, + ITypeAndVersion, ConfirmedOwner, KeeperBase, ReentrancyGuard, diff --git a/contracts/src/v0.8/automation/v1_3/KeeperRegistry1_3.sol b/contracts/src/v0.8/automation/v1_3/KeeperRegistry1_3.sol index dbef8d77d19..2d56443822b 100644 --- a/contracts/src/v0.8/automation/v1_3/KeeperRegistry1_3.sol +++ b/contracts/src/v0.8/automation/v1_3/KeeperRegistry1_3.sol @@ -8,7 +8,7 @@ import "./KeeperRegistryBase1_3.sol"; import "./KeeperRegistryLogic1_3.sol"; import {AutomationRegistryExecutableInterface, State} from "../interfaces/v1_3/AutomationRegistryInterface1_3.sol"; import "../interfaces/MigratableKeeperRegistryInterface.sol"; -import "../../interfaces/TypeAndVersionInterface.sol"; +import "../../shared/interfaces/ITypeAndVersion.sol"; import "../../shared/interfaces/IERC677Receiver.sol"; /** @@ -18,7 +18,7 @@ import "../../shared/interfaces/IERC677Receiver.sol"; contract KeeperRegistry1_3 is KeeperRegistryBase1_3, Proxy, - TypeAndVersionInterface, + ITypeAndVersion, AutomationRegistryExecutableInterface, MigratableKeeperRegistryInterface, IERC677Receiver diff --git a/contracts/src/v0.8/automation/v2_0/KeeperRegistrar2_0.sol b/contracts/src/v0.8/automation/v2_0/KeeperRegistrar2_0.sol index c1b7e45b859..78cc06a8b20 100644 --- a/contracts/src/v0.8/automation/v2_0/KeeperRegistrar2_0.sol +++ b/contracts/src/v0.8/automation/v2_0/KeeperRegistrar2_0.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.6; import "../../shared/interfaces/LinkTokenInterface.sol"; import "../interfaces/v2_0/AutomationRegistryInterface2_0.sol"; -import "../../interfaces/TypeAndVersionInterface.sol"; +import "../../shared/interfaces/ITypeAndVersion.sol"; import "../../shared/access/ConfirmedOwner.sol"; import "../../shared/interfaces/IERC677Receiver.sol"; @@ -17,7 +17,7 @@ import "../../shared/interfaces/IERC677Receiver.sol"; * The idea is to have same interface(functions,events) for UI or anyone using this contract irrespective of auto approve being enabled or not. * they can just listen to `RegistrationRequested` & `RegistrationApproved` events and know the status on registrations. */ -contract KeeperRegistrar2_0 is TypeAndVersionInterface, ConfirmedOwner, IERC677Receiver { +contract KeeperRegistrar2_0 is ITypeAndVersion, ConfirmedOwner, IERC677Receiver { /** * DISABLED: No auto approvals, all new upkeeps should be approved manually. * ENABLED_SENDER_ALLOWLIST: Auto approvals for allowed senders subject to max allowed. Manual for rest. diff --git a/contracts/src/v0.8/automation/v2_0/UpkeepTranscoder3_0.sol b/contracts/src/v0.8/automation/v2_0/UpkeepTranscoder3_0.sol index 0a56f209cc8..df8368de691 100644 --- a/contracts/src/v0.8/automation/v2_0/UpkeepTranscoder3_0.sol +++ b/contracts/src/v0.8/automation/v2_0/UpkeepTranscoder3_0.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.6; import "../../automation/interfaces/UpkeepTranscoderInterface.sol"; -import "../../interfaces/TypeAndVersionInterface.sol"; +import "../../shared/interfaces/ITypeAndVersion.sol"; import {Upkeep as UpkeepV1} from "../../automation/v1_2/KeeperRegistry1_2.sol"; import {Upkeep as UpkeepV2} from "../../automation/v1_3/KeeperRegistryBase1_3.sol"; import {Upkeep as UpkeepV3} from "../../automation/v2_0/KeeperRegistryBase2_0.sol"; @@ -13,7 +13,7 @@ import "../../automation/UpkeepFormat.sol"; * @notice UpkeepTranscoder 3_0 allows converting upkeep data from previous keeper registry versions 1.2 and 1.3 to * registry 2.0 */ -contract UpkeepTranscoder3_0 is UpkeepTranscoderInterface, TypeAndVersionInterface { +contract UpkeepTranscoder3_0 is UpkeepTranscoderInterface, ITypeAndVersion { error InvalidTranscoding(); /** diff --git a/contracts/src/v0.8/automation/v2_1/AutomationRegistrar2_1.sol b/contracts/src/v0.8/automation/v2_1/AutomationRegistrar2_1.sol index 407dda2414e..503f16bbe4c 100644 --- a/contracts/src/v0.8/automation/v2_1/AutomationRegistrar2_1.sol +++ b/contracts/src/v0.8/automation/v2_1/AutomationRegistrar2_1.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.16; import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; import {IKeeperRegistryMaster} from "../interfaces/v2_1/IKeeperRegistryMaster.sol"; -import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; import {IERC677Receiver} from "../../shared/interfaces/IERC677Receiver.sol"; @@ -17,7 +17,7 @@ import {IERC677Receiver} from "../../shared/interfaces/IERC677Receiver.sol"; * The idea is to have same interface(functions,events) for UI or anyone using this contract irrespective of auto approve being enabled or not. * they can just listen to `RegistrationRequested` & `RegistrationApproved` events and know the status on registrations. */ -contract AutomationRegistrar2_1 is TypeAndVersionInterface, ConfirmedOwner, IERC677Receiver { +contract AutomationRegistrar2_1 is ITypeAndVersion, ConfirmedOwner, IERC677Receiver { /** * DISABLED: No auto approvals, all new upkeeps should be approved manually. * ENABLED_SENDER_ALLOWLIST: Auto approvals for allowed senders subject to max allowed. Manual for rest. diff --git a/contracts/src/v0.8/automation/v2_1/UpkeepTranscoder4_0.sol b/contracts/src/v0.8/automation/v2_1/UpkeepTranscoder4_0.sol index 53b681d4cc1..41f50de0932 100644 --- a/contracts/src/v0.8/automation/v2_1/UpkeepTranscoder4_0.sol +++ b/contracts/src/v0.8/automation/v2_1/UpkeepTranscoder4_0.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.16; import {UpkeepTranscoderInterfaceV2} from "../interfaces/UpkeepTranscoderInterfaceV2.sol"; -import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {KeeperRegistryBase2_1 as R21} from "./KeeperRegistryBase2_1.sol"; import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; @@ -52,7 +52,7 @@ struct UpkeepV20 { * @notice UpkeepTranscoder allows converting upkeep data from previous keeper registry versions 1.2, 1.3, and * 2.0 to registry 2.1 */ -contract UpkeepTranscoder4_0 is UpkeepTranscoderInterfaceV2, TypeAndVersionInterface { +contract UpkeepTranscoder4_0 is UpkeepTranscoderInterfaceV2, ITypeAndVersion { error InvalidTranscoding(); /** diff --git a/contracts/src/v0.8/automation/v2_3/AutomationRegistrar2_3.sol b/contracts/src/v0.8/automation/v2_3/AutomationRegistrar2_3.sol index 2effb8d4d2f..251611cfb04 100644 --- a/contracts/src/v0.8/automation/v2_3/AutomationRegistrar2_3.sol +++ b/contracts/src/v0.8/automation/v2_3/AutomationRegistrar2_3.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.19; import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; import {IAutomationRegistryMaster2_3} from "../interfaces/v2_3/IAutomationRegistryMaster2_3.sol"; -import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; import {IERC677Receiver} from "../../shared/interfaces/IERC677Receiver.sol"; import {IERC20Metadata as IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; @@ -21,7 +21,7 @@ import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/tok * The idea is to have same interface(functions,events) for UI or anyone using this contract irrespective of auto approve being enabled or not. * they can just listen to `RegistrationRequested` & `RegistrationApproved` events and know the status on registrations. */ -contract AutomationRegistrar2_3 is TypeAndVersionInterface, ConfirmedOwner, IERC677Receiver { +contract AutomationRegistrar2_3 is ITypeAndVersion, ConfirmedOwner, IERC677Receiver { using SafeERC20 for IERC20; /** diff --git a/contracts/src/v0.8/automation/v2_3/AutomationRegistry2_3.sol b/contracts/src/v0.8/automation/v2_3/AutomationRegistry2_3.sol index 031d7b5dfb8..fbf509772f0 100644 --- a/contracts/src/v0.8/automation/v2_3/AutomationRegistry2_3.sol +++ b/contracts/src/v0.8/automation/v2_3/AutomationRegistry2_3.sol @@ -192,9 +192,7 @@ contract AutomationRegistry2_3 is AutomationRegistryBase2_3, OCR2Abstract, Chain uint256 nativeUSD = _getNativeUSD(hotVars); for (uint256 i = 0; i < report.upkeepIds.length; i++) { if (upkeepTransmitInfo[i].earlyChecksPassed) { - if (i == 0 || upkeepTransmitInfo[i].upkeep.billingToken != upkeepTransmitInfo[i - 1].upkeep.billingToken) { - billingTokenParams = _getBillingTokenPaymentParams(hotVars, upkeepTransmitInfo[i].upkeep.billingToken); - } + billingTokenParams = _getBillingTokenPaymentParams(hotVars, upkeepTransmitInfo[i].upkeep.billingToken); PaymentReceipt memory receipt = _handlePayment( hotVars, PaymentParams({ diff --git a/contracts/src/v0.8/automation/v2_3/AutomationRegistryBase2_3.sol b/contracts/src/v0.8/automation/v2_3/AutomationRegistryBase2_3.sol index 354a6a9b475..bc9cc144424 100644 --- a/contracts/src/v0.8/automation/v2_3/AutomationRegistryBase2_3.sol +++ b/contracts/src/v0.8/automation/v2_3/AutomationRegistryBase2_3.sol @@ -59,8 +59,8 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { // tx itself, but since payment processing itself takes gas, and it needs the overhead as input, we use fixed constants // to account for gas used in payment processing. These values are calibrated using hardhat tests which simulates various cases and verifies that // the variables result in accurate estimation - uint256 internal constant ACCOUNTING_FIXED_GAS_OVERHEAD = 51_200; // Fixed overhead per tx - uint256 internal constant ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD = 14_200; // Overhead per upkeep performed in batch + uint256 internal constant ACCOUNTING_FIXED_GAS_OVERHEAD = 51_000; // Fixed overhead per tx + uint256 internal constant ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD = 14_900; // Overhead per upkeep performed in batch LinkTokenInterface internal immutable i_link; AggregatorV3Interface internal immutable i_linkUSDFeed; diff --git a/contracts/src/v0.8/automation/v2_3/UpkeepTranscoder5_0.sol b/contracts/src/v0.8/automation/v2_3/UpkeepTranscoder5_0.sol index 32530c71257..e0312588ed9 100644 --- a/contracts/src/v0.8/automation/v2_3/UpkeepTranscoder5_0.sol +++ b/contracts/src/v0.8/automation/v2_3/UpkeepTranscoder5_0.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.19; import {UpkeepTranscoderInterfaceV2} from "../interfaces/UpkeepTranscoderInterfaceV2.sol"; -import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; enum RegistryVersion { V12, @@ -17,7 +17,7 @@ enum RegistryVersion { * @notice UpkeepTranscoder is a contract that allows converting upkeep data from previous registry versions to newer versions * @dev it currently only supports 2.3 -> 2.3 migrations */ -contract UpkeepTranscoder5_0 is UpkeepTranscoderInterfaceV2, TypeAndVersionInterface { +contract UpkeepTranscoder5_0 is UpkeepTranscoderInterfaceV2, ITypeAndVersion { error InvalidTranscoding(); string public constant override typeAndVersion = "UpkeepTranscoder 5.0.0"; diff --git a/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistry2_3.sol b/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistry2_3.sol index 5d5bf23aa26..b1b2feff83f 100644 --- a/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistry2_3.sol +++ b/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistry2_3.sol @@ -187,9 +187,7 @@ contract ZKSyncAutomationRegistry2_3 is ZKSyncAutomationRegistryBase2_3, OCR2Abs uint256 nativeUSD = _getNativeUSD(hotVars); for (uint256 i = 0; i < report.upkeepIds.length; i++) { if (upkeepTransmitInfo[i].earlyChecksPassed) { - if (i == 0 || upkeepTransmitInfo[i].upkeep.billingToken != upkeepTransmitInfo[i - 1].upkeep.billingToken) { - billingTokenParams = _getBillingTokenPaymentParams(hotVars, upkeepTransmitInfo[i].upkeep.billingToken); - } + billingTokenParams = _getBillingTokenPaymentParams(hotVars, upkeepTransmitInfo[i].upkeep.billingToken); PaymentReceipt memory receipt = _handlePayment( hotVars, PaymentParams({ diff --git a/contracts/src/v0.8/ccip/FeeQuoter.sol b/contracts/src/v0.8/ccip/FeeQuoter.sol index b312e732e61..590233c6230 100644 --- a/contracts/src/v0.8/ccip/FeeQuoter.sol +++ b/contracts/src/v0.8/ccip/FeeQuoter.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IReceiver} from "../keystone/interfaces/IReceiver.sol"; import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; @@ -34,9 +34,11 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, error DataFeedValueOutOfUint224Range(); error InvalidDestBytesOverhead(address token, uint32 destBytesOverhead); error MessageGasLimitTooHigh(); + error MessageComputeUnitLimitTooHigh(); error DestinationChainNotEnabled(uint64 destChainSelector); error ExtraArgOutOfOrderExecutionMustBeTrue(); error InvalidExtraArgsTag(); + error InvalidExtraArgsData(); error SourceTokenDataTooLarge(address token); error InvalidDestChainConfig(uint64 destChainSelector); error MessageFeeTooHigh(uint256 msgFeeJuels, uint256 maxFeeJuelsPerMsg); @@ -44,6 +46,8 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, error MessageTooLarge(uint256 maxSize, uint256 actualSize); error UnsupportedNumberOfTokens(uint256 numberOfTokens, uint256 maxNumberOfTokensPerMsg); error InvalidFeeRange(uint256 minFeeUSDCents, uint256 maxFeeUSDCents); + error InvalidChainFamilySelector(bytes4 chainFamilySelector); + error InvalidTokenReceiver(); event FeeTokenAdded(address indexed feeToken); event FeeTokenRemoved(address indexed feeToken); @@ -91,24 +95,26 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, /// @dev Struct to hold the fee & validation configs for a destination chain. struct DestChainConfig { - bool isEnabled; // ──────────────────────────╮ Whether this destination chain is enabled. - uint16 maxNumberOfTokensPerMsg; // │ Maximum number of distinct ERC20 tokens transferred per message. - uint32 maxDataBytes; // │ Maximum data payload size in bytes. - uint32 maxPerMsgGasLimit; // │ Maximum gas limit for messages targeting EVMs. - uint32 destGasOverhead; // │ Gas charged on top of the gasLimit to cover destination chain costs. - uint16 destGasPerPayloadByte; // │ Destination chain gas charged each byte of `data` payload. - uint32 destDataAvailabilityOverheadGas; // │ Data availability gas charged for overhead costs e.g. for OCR. - uint16 destGasPerDataAvailabilityByte; // │ Gas units charged per byte of message data that needs availability. - uint16 destDataAvailabilityMultiplierBps; // │ Multiplier for data availability gas, multiples of bps, or 0.0001. + bool isEnabled; // ─────────────────────────╮ Whether this destination chain is enabled. + uint16 maxNumberOfTokensPerMsg; // │ Maximum number of distinct ERC20 tokens transferred per message. + uint32 maxDataBytes; // │ Maximum data payload size in bytes. + uint32 maxPerMsgGasLimit; // │ Maximum gas limit for messages targeting EVMs. + uint32 destGasOverhead; // │ Gas charged on top of the gasLimit to cover destination chain costs. + uint8 destGasPerPayloadByteBase; // │ Default dest-chain gas charged each byte of `data` payload. + uint8 destGasPerPayloadByteHigh; // │ High dest-chain gas charged each byte of `data` payload, used to account for eip-7623. + uint16 destGasPerPayloadByteThreshold; // │ The value at which the billing switches from destGasPerPayloadByteBase to destGasPerPayloadByteHigh. + uint32 destDataAvailabilityOverheadGas; // │ Data availability gas charged for overhead costs e.g. for OCR. + uint16 destGasPerDataAvailabilityByte; // │ Gas units charged per byte of message data that needs availability. + uint16 destDataAvailabilityMultiplierBps; //│ Multiplier for data availability gas, multiples of bps, or 0.0001. + bytes4 chainFamilySelector; // │ Selector that identifies the destination chain's family. Used to determine the correct validations to perform for the dest chain. + bool enforceOutOfOrder; // ─────────────────╯ Whether to enforce the allowOutOfOrderExecution extraArg value to be true. // The following three properties are defaults, they can be overridden by setting the TokenTransferFeeConfig for a token. - uint16 defaultTokenFeeUSDCents; // │ Default token fee charged per token transfer. - uint32 defaultTokenDestGasOverhead; // ──────╯ Default gas charged to execute a token transfer on the destination chain. - uint32 defaultTxGasLimit; //──────────╮ Default gas limit for a tx. - uint64 gasMultiplierWeiPerEth; // │ Multiplier for gas costs, 1e18 based so 11e17 = 10% extra cost. - uint32 networkFeeUSDCents; // │ Flat network fee to charge for messages, multiples of 0.01 USD. - uint32 gasPriceStalenessThreshold; // │ The amount of time a gas price can be stale before it is considered invalid (0 means disabled). - bool enforceOutOfOrder; // │ Whether to enforce the allowOutOfOrderExecution extraArg value to be true. - bytes4 chainFamilySelector; // ───────╯ Selector that identifies the destination chain's family. Used to determine the correct validations to perform for the dest chain. + uint16 defaultTokenFeeUSDCents; // ────╮ Default token fee charged per token transfer. + uint32 defaultTokenDestGasOverhead; // │ Default gas charged to execute a token transfer on the destination chain. + uint32 defaultTxGasLimit; // │ Default gas limit for a tx. + uint64 gasMultiplierWeiPerEth; // │ Multiplier for gas costs, 1e18 based so 11e17 = 10% extra cost. + uint32 gasPriceStalenessThreshold; // │ The amount of time a gas price can be stale before it is considered invalid (0 means disabled). + uint32 networkFeeUSDCents; // ─────────╯ Flat network fee to charge for messages, multiples of 0.01 USD. } /// @dev Struct to hold the configs and its destination chain selector. Same as DestChainConfig but with the @@ -549,11 +555,12 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, Client.EVM2AnyMessage calldata message ) external view returns (uint256 feeTokenAmount) { DestChainConfig memory destChainConfig = s_destChainConfigs[destChainSelector]; - if (!destChainConfig.isEnabled) revert DestinationChainNotEnabled(destChainSelector); if (!s_feeTokens.contains(message.feeToken)) revert FeeTokenNotSupported(message.feeToken); uint256 numberOfTokens = message.tokenAmounts.length; - _validateMessage(destChainConfig, message.data.length, numberOfTokens, message.receiver); + uint256 gasLimit = _resolveGasLimitForDestination(message.extraArgs, destChainConfig); + + _validateMessage(destChainConfig, message.data.length, numberOfTokens, gasLimit, message.receiver); // The below call asserts that feeToken is a supported token. uint224 feeTokenPrice = _getValidatedTokenPrice(message.feeToken); @@ -563,25 +570,33 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, // If message-only and no token transfers, a flat network fee is charged. // If there are token transfers, premiumFee is calculated from token transfer fee. // If there are both token transfers and message, premiumFee is only calculated from token transfer fee. - uint256 premiumFee = 0; + uint256 premiumFeeUSDWei = 0; uint32 tokenTransferGas = 0; uint32 tokenTransferBytesOverhead = 0; if (numberOfTokens > 0) { - (premiumFee, tokenTransferGas, tokenTransferBytesOverhead) = - _getTokenTransferCost(destChainConfig, destChainSelector, message.feeToken, feeTokenPrice, message.tokenAmounts); + (premiumFeeUSDWei, tokenTransferGas, tokenTransferBytesOverhead) = _getTokenTransferCost( + destChainConfig.defaultTokenFeeUSDCents, + destChainConfig.defaultTokenDestGasOverhead, + destChainSelector, + message.feeToken, + feeTokenPrice, + message.tokenAmounts + ); } else { // Convert USD cents with 2 decimals to 18 decimals. - premiumFee = uint256(destChainConfig.networkFeeUSDCents) * 1e16; + premiumFeeUSDWei = uint256(destChainConfig.networkFeeUSDCents) * 1e16; } + // Apply the premium multiplier for the fee token, making it 36 decimals + premiumFeeUSDWei *= s_premiumMultiplierWeiPerEth[message.feeToken]; // Calculate data availability cost in USD with 36 decimals. Data availability cost exists on rollups that need to // post transaction calldata onto another storage layer, e.g. Eth mainnet, incurring additional storage gas costs. - uint256 dataAvailabilityCost = 0; + uint256 dataAvailabilityCostUSD36Decimals = 0; // Only calculate data availability cost if data availability multiplier is non-zero. // The multiplier should be set to 0 if destination chain does not charge data availability cost. if (destChainConfig.destDataAvailabilityMultiplierBps > 0) { - dataAvailabilityCost = _getDataAvailabilityCost( + dataAvailabilityCostUSD36Decimals = _getDataAvailabilityCost( destChainConfig, // Parse the data availability gas price stored in the higher-order 112 bits of the encoded gas price. uint112(packedGasPrice >> Internal.GAS_PRICE_BITS), @@ -591,24 +606,36 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, ); } - // Calculate execution gas fee on destination chain in USD with 36 decimals. - // We add the message gas limit, the overhead gas, the gas of passing message data to receiver, and token transfer - // gas together. We then multiply this gas total with the gas multiplier and gas price, converting it into USD with - // 36 decimals. uint112(packedGasPrice) = executionGasPrice + // Calculate the calldata, taking into account EIP-7623. We charge destGasPerPayloadByteBase for the calldata cost + // up to destGasPerPayloadByteThreshold, even when the total calldata length exceeds the threshold. This is safe + // because we also charge for execution gas on top of this. When correct values are chosen, the execution gas we + // charge is always higher than the difference between the base and high calldata costs for the first + // destGasPerPayloadByteThreshold bytes. Since we don't pay for execution gas in EIP-7623, this execution gas is + // effectively used to cover the higher calldata costs for the first destGasPerPayloadByteThreshold bytes. + // The threshold should be adjusted based on expected execution cost and, potentially, to discourage large payloads. + // Example: 16 base, 40 high, 100k execution cost. 100k/(40-16) = max 4.16kb as the threshold. Take 4kb threshold. + // Calldata length = 5000 + // Our calculations: 1000 * 40 + 4000 * 16 = 104k calldata cost + 100k execution cost = 204k calculated cost. + // Actual cost: 5000 * 40 = 200k + // The difference is 4k in favour of CCIP. The lower the threshold, the more premium is charged for large payloads. + uint256 calldataLength = message.data.length + tokenTransferBytesOverhead; + uint256 destCallDataCost = calldataLength * destChainConfig.destGasPerPayloadByteBase; + if (calldataLength > destChainConfig.destGasPerPayloadByteThreshold) { + destCallDataCost = destChainConfig.destGasPerPayloadByteBase * destChainConfig.destGasPerPayloadByteThreshold + + (calldataLength - destChainConfig.destGasPerPayloadByteThreshold) * destChainConfig.destGasPerPayloadByteHigh; + } - // NOTE: Fee logic is currently only supported for EVM-Chains, and the gas price is assumed to be in wei. - // fee logic for other chains should be implemented in the future. - uint256 executionCost = uint112(packedGasPrice) - * ( - destChainConfig.destGasOverhead + (message.data.length * destChainConfig.destGasPerPayloadByte) + tokenTransferGas - + _parseEVMExtraArgsFromBytes(message.extraArgs, destChainConfig).gasLimit - ) * destChainConfig.gasMultiplierWeiPerEth; + // We add the destination chain CCIP overhead (commit, exec), the token transfer gas, the calldata cost and the msg + // gas limit to get the total gas the tx costs to execute on the destination chain. + uint256 totalDestChainGas = destChainConfig.destGasOverhead + tokenTransferGas + destCallDataCost + gasLimit; - // Calculate number of fee tokens to charge. // Total USD fee is in 36 decimals, feeTokenPrice is in 18 decimals USD for 1e18 smallest token denominations. - // Result of the division is the number of smallest token denominations. - return ((premiumFee * s_premiumMultiplierWeiPerEth[message.feeToken]) + executionCost + dataAvailabilityCost) - / feeTokenPrice; + // The result is the fee in the feeTokens smallest denominations (e.g. wei for ETH). + // uint112(packedGasPrice) = executionGasPrice + return ( + totalDestChainGas * uint112(packedGasPrice) * destChainConfig.gasMultiplierWeiPerEth + premiumFeeUSDWei + + dataAvailabilityCostUSD36Decimals + ) / feeTokenPrice; } /// @notice Sets the fee configuration for a token. @@ -649,7 +676,8 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, /// @dev Assumes that tokenAmounts are validated to be listed tokens elsewhere. /// @dev Splitting one token transfer into multiple transfers is discouraged, as it will result in a transferFee /// equal or greater than the same amount aggregated/de-duped. - /// @param destChainConfig the config configured for the destination chain selector. + /// @param defaultTokenFeeUSDCents the default token fee in USD cents. + /// @param defaultTokenDestGasOverhead the default token destination gas overhead. /// @param destChainSelector the destination chain selector. /// @param feeToken address of the feeToken. /// @param feeTokenPrice price of feeToken in USD with 18 decimals. @@ -658,7 +686,8 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, /// @return tokenTransferGas total execution gas of the token transfers. /// @return tokenTransferBytesOverhead additional token transfer data passed to destination, e.g. USDC attestation. function _getTokenTransferCost( - DestChainConfig memory destChainConfig, + uint256 defaultTokenFeeUSDCents, + uint32 defaultTokenDestGasOverhead, uint64 destChainSelector, address feeToken, uint224 feeTokenPrice, @@ -672,8 +701,8 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, // If the token has no specific overrides configured, we use the global defaults. if (!transferFeeConfig.isEnabled) { - tokenTransferFeeUSDWei += uint256(destChainConfig.defaultTokenFeeUSDCents) * 1e16; - tokenTransferGas += destChainConfig.defaultTokenDestGasOverhead; + tokenTransferFeeUSDWei += defaultTokenFeeUSDCents * 1e16; + tokenTransferGas += defaultTokenDestGasOverhead; tokenTransferBytesOverhead += Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES; continue; } @@ -847,29 +876,85 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, /// @param chainFamilySelector Tag to identify the target family. /// @param destAddress Dest address to validate. /// @dev precondition - assumes the family tag is correct and validated. - function _validateDestFamilyAddress(bytes4 chainFamilySelector, bytes memory destAddress) internal pure { + function _validateDestFamilyAddress( + bytes4 chainFamilySelector, + bytes memory destAddress, + uint256 gasLimit + ) internal pure { if (chainFamilySelector == Internal.CHAIN_FAMILY_SELECTOR_EVM) { - Internal._validateEVMAddress(destAddress); + return Internal._validateEVMAddress(destAddress); + } + if (chainFamilySelector == Internal.CHAIN_FAMILY_SELECTOR_SVM) { + return Internal._validateSVMAddress(destAddress, gasLimit > 0); + } + revert InvalidChainFamilySelector(chainFamilySelector); + } + + function _resolveGasLimitForDestination( + bytes calldata extraArgs, + DestChainConfig memory destChainConfig + ) internal pure returns (uint256) { + if (destChainConfig.chainFamilySelector == Internal.CHAIN_FAMILY_SELECTOR_EVM) { + return _parseEVMExtraArgsFromBytes( + extraArgs, + destChainConfig.defaultTxGasLimit, + destChainConfig.maxPerMsgGasLimit, + destChainConfig.enforceOutOfOrder + ).gasLimit; } + if (destChainConfig.chainFamilySelector == Internal.CHAIN_FAMILY_SELECTOR_SVM) { + return _parseSVMExtraArgsFromBytes( + extraArgs, destChainConfig.maxPerMsgGasLimit, destChainConfig.enforceOutOfOrder + ).computeUnits; + } + revert InvalidChainFamilySelector(destChainConfig.chainFamilySelector); + } + + /// @notice Parse and validate the SVM specific Extra Args Bytes. + function _parseSVMExtraArgsFromBytes( + bytes calldata extraArgs, + uint256 maxPerMsgGasLimit, + bool enforcedOutOfOrder + ) internal pure returns (Client.SVMExtraArgsV1 memory svmExtraArgs) { + if (extraArgs.length == 0) { + revert InvalidExtraArgsData(); + } + + bytes4 tag = bytes4(extraArgs[:4]); + if (tag != Client.SVM_EXTRA_EXTRA_ARGS_V1_TAG) { + revert InvalidExtraArgsTag(); + } + + svmExtraArgs = abi.decode(extraArgs[4:], (Client.SVMExtraArgsV1)); + + if (enforcedOutOfOrder && !svmExtraArgs.allowOutOfOrderExecution) { + revert ExtraArgOutOfOrderExecutionMustBeTrue(); + } + + if (svmExtraArgs.computeUnits > maxPerMsgGasLimit) { + revert MessageComputeUnitLimitTooHigh(); + } + + return svmExtraArgs; } /// @dev Convert the extra args bytes into a struct with validations against the dest chain config. /// @param extraArgs The extra args bytes. - /// @param destChainConfig Dest chain config to validate against. /// @return evmExtraArgs The EVMExtraArgs struct (latest version). function _parseEVMExtraArgsFromBytes( bytes calldata extraArgs, - DestChainConfig memory destChainConfig + uint32 defaultTxGasLimit, + uint256 maxPerMsgGasLimit, + bool enforceOutOfOrder ) internal pure returns (Client.EVMExtraArgsV2 memory) { - Client.EVMExtraArgsV2 memory evmExtraArgs = - _parseUnvalidatedEVMExtraArgsFromBytes(extraArgs, destChainConfig.defaultTxGasLimit); + Client.EVMExtraArgsV2 memory evmExtraArgs = _parseUnvalidatedEVMExtraArgsFromBytes(extraArgs, defaultTxGasLimit); - if (evmExtraArgs.gasLimit > uint256(destChainConfig.maxPerMsgGasLimit)) revert MessageGasLimitTooHigh(); + if (evmExtraArgs.gasLimit > maxPerMsgGasLimit) revert MessageGasLimitTooHigh(); // If the chain enforces out of order execution, the extra args must allow it, otherwise revert. We cannot assume // the user intended to use OOO on any chain that requires it as it may lead to unexpected behavior. Therefore we // revert instead of assuming the user intended to use OOO. - if (destChainConfig.enforceOutOfOrder && !evmExtraArgs.allowOutOfOrderExecution) { + if (enforceOutOfOrder && !evmExtraArgs.allowOutOfOrderExecution) { revert ExtraArgOutOfOrderExecutionMustBeTrue(); } @@ -899,7 +984,6 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, // Clients may still include it but it will be ignored. return Client.EVMExtraArgsV2({gasLimit: abi.decode(argsData, (uint256)), allowOutOfOrderExecution: false}); } - revert InvalidExtraArgsTag(); } @@ -913,6 +997,7 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, DestChainConfig memory destChainConfig, uint256 dataLength, uint256 numberOfTokens, + uint256 gasLimit, bytes memory receiver ) internal pure { // Check that payload is formed correctly. @@ -922,7 +1007,7 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, if (numberOfTokens > uint256(destChainConfig.maxNumberOfTokensPerMsg)) { revert UnsupportedNumberOfTokens(numberOfTokens, destChainConfig.maxNumberOfTokensPerMsg); } - _validateDestFamilyAddress(destChainConfig.chainFamilySelector, receiver); + _validateDestFamilyAddress(destChainConfig.chainFamilySelector, receiver, gasLimit); } /// @inheritdoc IFeeQuoter @@ -953,16 +1038,42 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, if (msgFeeJuels > i_maxFeeJuelsPerMsg) revert MessageFeeTooHigh(msgFeeJuels, i_maxFeeJuelsPerMsg); - uint64 defaultTxGasLimit = s_destChainConfigs[destChainSelector].defaultTxGasLimit; + (convertedExtraArgs, isOutOfOrderExecution) = + _processChainFamilySelector(destChainSelector, sourceTokenAmounts.length > 0, extraArgs); - // NOTE: Only EVM chains are supported for now, additional validation logic will be added when supporting other - // chain families to parse non-EVM args. - // Since the message is called after getFee, which will already validate the params, no validation is necessary. - Client.EVMExtraArgsV2 memory parsedExtraArgs = _parseUnvalidatedEVMExtraArgsFromBytes(extraArgs, defaultTxGasLimit); - isOutOfOrderExecution = parsedExtraArgs.allowOutOfOrderExecution; destExecDataPerToken = _processPoolReturnData(destChainSelector, onRampTokenTransfers, sourceTokenAmounts); - return (msgFeeJuels, isOutOfOrderExecution, Client._argsToBytes(parsedExtraArgs), destExecDataPerToken); + return (msgFeeJuels, isOutOfOrderExecution, convertedExtraArgs, destExecDataPerToken); + } + + /// @notice Parses the extra Args based on the chain family selector. Isolated into a separate function + /// as it was the only way to prevent a stack too deep error, and makes future chain family additions easier. + function _processChainFamilySelector( + uint64 destChainSelector, + bool isMessageWithTokenTransfer, + bytes calldata extraArgs + ) internal view returns (bytes memory, bool) { + DestChainConfig memory destChainConfig = s_destChainConfigs[destChainSelector]; + if (destChainConfig.chainFamilySelector == Internal.CHAIN_FAMILY_SELECTOR_EVM) { + // Since the message is called after getFee, which already validates the params, no validation is necessary. + Client.EVMExtraArgsV2 memory parsedExtraArgs = + _parseUnvalidatedEVMExtraArgsFromBytes(extraArgs, destChainConfig.defaultTxGasLimit); + + return (Client._argsToBytes(parsedExtraArgs), parsedExtraArgs.allowOutOfOrderExecution); + } + if (destChainConfig.chainFamilySelector == Internal.CHAIN_FAMILY_SELECTOR_SVM) { + bytes32 tokenReceiver = _parseSVMExtraArgsFromBytes( + extraArgs, destChainConfig.maxPerMsgGasLimit, destChainConfig.enforceOutOfOrder + ).tokenReceiver; + if (isMessageWithTokenTransfer && tokenReceiver == bytes32(0)) { + revert InvalidTokenReceiver(); + } + + // ExtraArgs are required on SVM, meaning the supplied extraArgs are either invalid and we would have reverted + // or we have valid extraArgs and we can return them without having to re-encode them. + return (extraArgs, true); + } + revert InvalidChainFamilySelector(destChainConfig.chainFamilySelector); } /// @notice Validates pool return data. @@ -990,12 +1101,13 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, } } - _validateDestFamilyAddress(chainFamilySelector, onRampTokenTransfers[i].destTokenAddress); + // We pass '1' here so that SVM validation requires a non-zero token address. + // The 'gasLimit' parameter isn't actually used for gas in this context; it simply + // signals that the address must not be zero on SVM. + _validateDestFamilyAddress(chainFamilySelector, onRampTokenTransfers[i].destTokenAddress, 1); FeeQuoter.TokenTransferFeeConfig memory tokenTransferFeeConfig = s_tokenTransferFeeConfig[destChainSelector][sourceToken]; - // NOTE: Only EVM chains' gas model is supported for now, additional fee logic for non-EVM chains will - // be required in the future with parsing based on chain family selector. uint32 destGasAmount = tokenTransferFeeConfig.isEnabled ? tokenTransferFeeConfig.destGasOverhead : s_destChainConfigs[destChainSelector].defaultTokenDestGasOverhead; @@ -1037,12 +1149,9 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, uint64 destChainSelector = destChainConfigArgs[i].destChainSelector; DestChainConfig memory destChainConfig = destChainConfigArg.destChainConfig; - // destChainSelector must be non-zero, defaultTxGasLimit must be set, and must be less than maxPerMsgGasLimit. - // Only EVM chains are supported for now, additional validation logic will be added when supporting other chain - // families + // destChainSelector must be non-zero, defaultTxGasLimit must be set, must be less than maxPerMsgGasLimit if ( destChainSelector == 0 || destChainConfig.defaultTxGasLimit == 0 - || destChainConfig.chainFamilySelector != Internal.CHAIN_FAMILY_SELECTOR_EVM || destChainConfig.defaultTxGasLimit > destChainConfig.maxPerMsgGasLimit ) { revert InvalidDestChainConfig(destChainSelector); diff --git a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol index 4ec67b409d6..fc553e4939c 100644 --- a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol +++ b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; import {IFeeQuoter} from "./interfaces/IFeeQuoter.sol"; diff --git a/contracts/src/v0.8/ccip/NonceManager.sol b/contracts/src/v0.8/ccip/NonceManager.sol index 382844c27d9..d8569658fcc 100644 --- a/contracts/src/v0.8/ccip/NonceManager.sol +++ b/contracts/src/v0.8/ccip/NonceManager.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; import {IEVM2AnyOnRamp} from "./interfaces/IEVM2AnyOnRamp.sol"; diff --git a/contracts/src/v0.8/ccip/Router.sol b/contracts/src/v0.8/ccip/Router.sol index 150ba00f39d..a3f9e409f72 100644 --- a/contracts/src/v0.8/ccip/Router.sol +++ b/contracts/src/v0.8/ccip/Router.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; import {IAny2EVMMessageReceiver} from "./interfaces/IAny2EVMMessageReceiver.sol"; diff --git a/contracts/src/v0.8/ccip/applications/EtherSenderReceiver.sol b/contracts/src/v0.8/ccip/applications/EtherSenderReceiver.sol index 8a07792782b..ca72079ec4e 100644 --- a/contracts/src/v0.8/ccip/applications/EtherSenderReceiver.sol +++ b/contracts/src/v0.8/ccip/applications/EtherSenderReceiver.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; diff --git a/contracts/src/v0.8/ccip/capability/CCIPHome.sol b/contracts/src/v0.8/ccip/capability/CCIPHome.sol index 829c54c5b62..174b2e3d83b 100644 --- a/contracts/src/v0.8/ccip/capability/CCIPHome.sol +++ b/contracts/src/v0.8/ccip/capability/CCIPHome.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {ICapabilityConfiguration} from "../../keystone/interfaces/ICapabilityConfiguration.sol"; import {INodeInfoProvider} from "../../keystone/interfaces/INodeInfoProvider.sol"; diff --git a/contracts/src/v0.8/ccip/interfaces/IRMNRemote.sol b/contracts/src/v0.8/ccip/interfaces/IRMNRemote.sol index 74dd8e83fac..37573f2d980 100644 --- a/contracts/src/v0.8/ccip/interfaces/IRMNRemote.sol +++ b/contracts/src/v0.8/ccip/interfaces/IRMNRemote.sol @@ -12,7 +12,7 @@ interface IRMNRemote { } /// @notice Verifies signatures of RMN nodes, on dest lane updates as provided in the CommitReport. - /// @param offRampAddress is not inferred by msg.sender, in case the call is made through ARMProxy. + /// @param offRampAddress is not inferred by msg.sender, in case the call is made through RMNProxy. /// @param merkleRoots must be well formed, and is a representation of the CommitReport received from the oracles. /// @param signatures rmnNodes ECDSA sigs, only r & s, must be sorted in ascending order by signer address. /// @dev Will revert if verification fails. diff --git a/contracts/src/v0.8/ccip/libraries/Client.sol b/contracts/src/v0.8/ccip/libraries/Client.sol index b1e1ca4a7c5..cde66e46cc0 100644 --- a/contracts/src/v0.8/ccip/libraries/Client.sol +++ b/contracts/src/v0.8/ccip/libraries/Client.sol @@ -42,6 +42,9 @@ library Client { // bytes4(keccak256("CCIP EVMExtraArgsV2")); bytes4 public constant EVM_EXTRA_ARGS_V2_TAG = 0x181dcf10; + // bytes4(keccak256("CCIP SVMExtraArgsV1")); + bytes4 public constant SVM_EXTRA_EXTRA_ARGS_V1_TAG = 0x1f3b3aba; + /// @param gasLimit: gas limit for the callback on the destination chain. /// @param allowOutOfOrderExecution: if true, it indicates that the message can be executed in any order relative to /// other messages from the same sender. This value's default varies by chain. On some chains, a particular value is @@ -51,9 +54,23 @@ library Client { bool allowOutOfOrderExecution; } + struct SVMExtraArgsV1 { + uint32 computeUnits; + uint64 accountIsWritableBitmap; + bool allowOutOfOrderExecution; + bytes32 tokenReceiver; + bytes32[] accounts; + } + function _argsToBytes( EVMExtraArgsV2 memory extraArgs ) internal pure returns (bytes memory bts) { return abi.encodeWithSelector(EVM_EXTRA_ARGS_V2_TAG, extraArgs); } + + function _svmArgsToBytes( + SVMExtraArgsV1 memory extraArgs + ) internal pure returns (bytes memory bts) { + return abi.encodeWithSelector(SVM_EXTRA_EXTRA_ARGS_V1_TAG, extraArgs); + } } diff --git a/contracts/src/v0.8/ccip/libraries/ERC165CheckerReverting.sol b/contracts/src/v0.8/ccip/libraries/ERC165CheckerReverting.sol new file mode 100644 index 00000000000..574b6d1501a --- /dev/null +++ b/contracts/src/v0.8/ccip/libraries/ERC165CheckerReverting.sol @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; + +/// @notice Library used to query support of an interface declared via {IERC165}. +/// @dev These functions return the actual result of the query: they do not `revert` if an interface is not supported. +library ERC165CheckerReverting { + error InsufficientGasForStaticCall(); + + // As per the EIP-165 spec, no interface should ever match 0xffffffff. + bytes4 private constant INTERFACE_ID_INVALID = 0xffffffff; + + /// @dev 30k gas is required to make the staticcall. Under the 63/64 rule this means that 30,477 gas must be available + /// to ensure that at least 30k is forwarded. Checking for at least 31,000 ensures that after additional + /// operations are performed there is still >= 30,477 gas remaining. + /// 30,000 = ((30,477 * 63) / 64) + uint256 private constant MINIMUM_GAS_REQUIREMENT = 31_000; + + /// @notice Returns true if `account` supports a defined interface. + /// @dev The function must support both the interfaceId and interfaces specified by ERC165 generally as per the standard. + /// @param account the contract to be queried for support. + /// @param interfaceId the interface being checked for support. + /// @return true if the contract at account indicates support of the interface with, false otherwise. + function _supportsInterfaceReverting(address account, bytes4 interfaceId) internal view returns (bool) { + // As a gas optimization, short circuit return false if interfaceId is not supported, as it is most likely interfaceId + // to be unsupported by the target. + return _supportsERC165InterfaceUncheckedReverting(account, interfaceId) + && !_supportsERC165InterfaceUncheckedReverting(account, INTERFACE_ID_INVALID) + && _supportsERC165InterfaceUncheckedReverting(account, type(IERC165).interfaceId); + } + + /// @notice Query if a contract implements an interface, does not check ERC165 support + /// @param account The address of the contract to query for support of an interface + /// @param interfaceId The interface identifier, as specified in ERC-165 + /// @return true if the contract at account indicates support of the interface with + /// identifier interfaceId, false otherwise + /// @dev Assumes that account contains a contract that supports ERC165, otherwise + /// the behavior of this method is undefined. This precondition can be checked. + /// @dev Function will only revert if the minimum gas requirement is not met before the staticcall is performed. + function _supportsERC165InterfaceUncheckedReverting(address account, bytes4 interfaceId) internal view returns (bool) { + bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId); + + bool success; + uint256 returnSize; + uint256 returnValue; + + bytes4 notEnoughGasSelector = InsufficientGasForStaticCall.selector; + + assembly { + // The EVM does not return a specific error code if a revert is due to OOG. This check ensures that + // the message will not throw an OOG error by requiring that the amount of gas for the following + // staticcall exists before invoking it. + if lt(gas(), MINIMUM_GAS_REQUIREMENT) { + mstore(0x0, notEnoughGasSelector) + revert(0x0, 0x4) + } + + success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20) + returnSize := returndatasize() + returnValue := mload(0x00) + } + return success && returnSize >= 0x20 && returnValue > 0; + } +} diff --git a/contracts/src/v0.8/ccip/libraries/Internal.sol b/contracts/src/v0.8/ccip/libraries/Internal.sol index 25d923ee1ed..435e26733a9 100644 --- a/contracts/src/v0.8/ccip/libraries/Internal.sol +++ b/contracts/src/v0.8/ccip/libraries/Internal.sol @@ -10,6 +10,7 @@ import {MerkleMultiProof} from "../libraries/MerkleMultiProof.sol"; /// expect to have migrated to a new version by then. library Internal { error InvalidEVMAddress(bytes encodedAddress); + error InvalidSVMAddress(bytes SVMAddress); /// @dev We limit return data to a selector plus 4 words. This is to avoid malicious contracts from returning /// large amounts of data and causing repeated out-of-gas scenarios. @@ -17,6 +18,11 @@ library Internal { /// @dev The expected number of bytes returned by the balanceOf function. uint256 internal constant MAX_BALANCE_OF_RET_BYTES = 32; + /// @dev The address used to send calls for gas estimation. + /// You only need to use this address if the minimum gas limit specified by the user is not actually enough to execute the + /// given message and you're attempting to estimate the actual necessary gas limit + address public constant GAS_ESTIMATION_SENDER = address(0xC11C11C11C11C11C11C11C11C11C11C11C11C1); + /// @notice A collection of token price and gas price updates. /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. struct PriceUpdates { @@ -161,16 +167,23 @@ library Internal { /// @notice This methods provides validation for parsing abi encoded addresses by ensuring the address is within the /// EVM address space. If it isn't it will revert with an InvalidEVMAddress error, which we can catch and handle /// more gracefully than a revert from abi.decode. - /// @return The address if it is valid, the function will revert otherwise. function _validateEVMAddress( bytes memory encodedAddress - ) internal pure returns (address) { + ) internal pure { if (encodedAddress.length != 32) revert InvalidEVMAddress(encodedAddress); uint256 encodedAddressUint = abi.decode(encodedAddress, (uint256)); if (encodedAddressUint > type(uint160).max || encodedAddressUint < PRECOMPILE_SPACE) { revert InvalidEVMAddress(encodedAddress); } - return address(uint160(encodedAddressUint)); + } + + function _validateSVMAddress(bytes memory encodedAddress, bool mustBeNonZero) internal pure { + if (encodedAddress.length != 32) revert InvalidSVMAddress(encodedAddress); + if (mustBeNonZero) { + if (abi.decode(encodedAddress, (bytes32)) == bytes32(0)) { + revert InvalidSVMAddress(encodedAddress); + } + } } /// @notice Enum listing the possible message execution states within the offRamp contract. @@ -262,6 +275,9 @@ library Internal { // bytes4(keccak256("CCIP ChainFamilySelector EVM")); bytes4 public constant CHAIN_FAMILY_SELECTOR_EVM = 0x2812d52c; + // bytes4(keccak256("CCIP ChainFamilySelector SVM")); + bytes4 public constant CHAIN_FAMILY_SELECTOR_SVM = 0x1e10bdc4; + /// @dev Holds a merkle root and interval for a source chain so that an array of these can be passed in the CommitReport. /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. /// @dev inefficient struct packing intentionally chosen to maintain order of specificity. Not a storage struct so impact is minimal. diff --git a/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol b/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol index b6741f78fbe..a6feb0b069c 100644 --- a/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol +++ b/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.4; import {Ownable2StepMsgSender} from "../../shared/access/Ownable2StepMsgSender.sol"; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {Internal} from "../libraries/Internal.sol"; /// @notice Onchain verification of reports from the offchain reporting protocol with multiple OCR plugin support. abstract contract MultiOCR3Base is ITypeAndVersion, Ownable2StepMsgSender { @@ -42,6 +43,7 @@ abstract contract MultiOCR3Base is ITypeAndVersion, Ownable2StepMsgSender { error NonUniqueSignatures(); error OracleCannotBeZeroAddress(); error StaticConfigCannotBeChanged(uint8 ocrPluginType); + error InsufficientGasForCallWithExact(); /// @dev Packing these fields used on the hot path in a ConfigInfo variable reduces the retrieval of all /// of them to a minimum number of SLOADs. @@ -274,7 +276,9 @@ abstract contract MultiOCR3Base is ITypeAndVersion, Ownable2StepMsgSender { && msg.sender == s_ocrConfigs[ocrPluginType].transmitters[transmitter.index] ) ) { - revert UnauthorizedTransmitter(); + if (msg.sender != Internal.GAS_ESTIMATION_SENDER) { + revert UnauthorizedTransmitter(); + } } } diff --git a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol index 76424b4e2a7..9ecf41272ab 100644 --- a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IAny2EVMMessageReceiver} from "../interfaces/IAny2EVMMessageReceiver.sol"; @@ -13,13 +13,13 @@ import {ITokenAdminRegistry} from "../interfaces/ITokenAdminRegistry.sol"; import {CallWithExactGas} from "../../shared/call/CallWithExactGas.sol"; import {Client} from "../libraries/Client.sol"; +import {ERC165CheckerReverting} from "../libraries/ERC165CheckerReverting.sol"; import {Internal} from "../libraries/Internal.sol"; import {MerkleMultiProof} from "../libraries/MerkleMultiProof.sol"; import {Pool} from "../libraries/Pool.sol"; import {MultiOCR3Base} from "../ocr/MultiOCR3Base.sol"; import {IERC20} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/IERC20.sol"; -import {ERC165Checker} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/ERC165Checker.sol"; import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; /// @notice OffRamp enables OCR networks to execute multiple messages in an OffRamp in a single transaction. @@ -28,7 +28,7 @@ import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts /// @dev MultiOCR3Base is used to store multiple OCR configs for the OffRamp. The execution plugin type has to be /// configured without signature verification, and the commit plugin type with verification. contract OffRamp is ITypeAndVersion, MultiOCR3Base { - using ERC165Checker for address; + using ERC165CheckerReverting for address; using EnumerableSet for EnumerableSet.UintSet; error ZeroChainSelectorNotAllowed(); @@ -544,6 +544,14 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { ) internal returns (Internal.MessageExecutionState executionState, bytes memory) { try this.executeSingleMessage(message, offchainTokenData, tokenGasOverrides) {} catch (bytes memory err) { + if (msg.sender == Internal.GAS_ESTIMATION_SENDER) { + if ( + CallWithExactGas.NOT_ENOUGH_GAS_FOR_CALL_SIG == bytes4(err) + || CallWithExactGas.NO_GAS_FOR_CALL_EXACT_CHECK_SIG == bytes4(err) + ) { + revert InsufficientGasForCallWithExact(); + } + } // return the message execution state as FAILURE and the revert data. // Max length of revert data is Router.MAX_RET_BYTES, max length of err is 4 + Router.MAX_RET_BYTES. return (Internal.MessageExecutionState.FAILURE, err); @@ -604,9 +612,12 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { // 3. If the receiver is a contract but it does not support the IAny2EVMMessageReceiver interface. // // The ordering of these checks is important, as the first check is the cheapest to execute. + // + // To prevent message delivery bypass issues, a modified version of the ERC165Checker is used + // which checks for sufficient gas before making the external call. if ( (message.data.length == 0 && message.gasLimit == 0) || message.receiver.code.length == 0 - || !message.receiver.supportsInterface(type(IAny2EVMMessageReceiver).interfaceId) + || !message.receiver._supportsInterfaceReverting(type(IAny2EVMMessageReceiver).interfaceId) ) return; (bool success, bytes memory returnData,) = s_sourceChainConfigs[message.header.sourceChainSelector] @@ -647,7 +658,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { // This is done to prevent a pool from reverting the entire transaction if it doesn't support the interface. // The call gets a max or 30k gas per instance, of which there are three. This means offchain gas estimations should // account for 90k gas overhead due to the interface check. - if (localPoolAddress == address(0) || !localPoolAddress.supportsInterface(Pool.CCIP_POOL_V1)) { + if (localPoolAddress == address(0) || !localPoolAddress._supportsInterfaceReverting(Pool.CCIP_POOL_V1)) { revert NotACompatiblePool(localPoolAddress); } diff --git a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol index e988b17ad82..fb0cbedd5e7 100644 --- a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol +++ b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IEVM2AnyOnRampClient} from "../interfaces/IEVM2AnyOnRampClient.sol"; diff --git a/contracts/src/v0.8/ccip/pools/BurnFromMintTokenPool.sol b/contracts/src/v0.8/ccip/pools/BurnFromMintTokenPool.sol index 8ce63a12bb5..c42ca75f66d 100644 --- a/contracts/src/v0.8/ccip/pools/BurnFromMintTokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/BurnFromMintTokenPool.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IBurnMintERC20} from "../../shared/token/ERC20/IBurnMintERC20.sol"; diff --git a/contracts/src/v0.8/ccip/pools/BurnMintTokenPool.sol b/contracts/src/v0.8/ccip/pools/BurnMintTokenPool.sol index 30203a4ced7..d1d6577b105 100644 --- a/contracts/src/v0.8/ccip/pools/BurnMintTokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/BurnMintTokenPool.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IBurnMintERC20} from "../../shared/token/ERC20/IBurnMintERC20.sol"; diff --git a/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAbstract.sol b/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAbstract.sol index b3bbf4ff5e1..aba9852d639 100644 --- a/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAbstract.sol +++ b/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAbstract.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IBurnMintERC20} from "../../shared/token/ERC20/IBurnMintERC20.sol"; @@ -35,7 +35,7 @@ abstract contract BurnMintTokenPoolAbstract is TokenPool { /// @dev The _validateReleaseOrMint check is an essential security check function releaseOrMint( Pool.ReleaseOrMintInV1 calldata releaseOrMintIn - ) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) { + ) public virtual override returns (Pool.ReleaseOrMintOutV1 memory) { _validateReleaseOrMint(releaseOrMintIn); // Calculate the local amount diff --git a/contracts/src/v0.8/ccip/pools/BurnToAddressMintTokenPool.sol b/contracts/src/v0.8/ccip/pools/BurnToAddressMintTokenPool.sol new file mode 100644 index 00000000000..563375f099a --- /dev/null +++ b/contracts/src/v0.8/ccip/pools/BurnToAddressMintTokenPool.sol @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {IBurnMintERC20} from "../../shared/token/ERC20/IBurnMintERC20.sol"; + +import {Pool} from "../libraries/Pool.sol"; +import {BurnMintTokenPoolAbstract} from "./BurnMintTokenPoolAbstract.sol"; +import {TokenPool} from "./TokenPool.sol"; + +import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; + +/// @notice This pool mints and burns a 3rd-party token by sending tokens to an address which is unrecoverable. +/// @dev The pool is designed to have an immutable burn address. If the tokens at the burn address become recoverable, +/// for example, a quantum computer calculating a private key for the zero address, the pool will need to be replaced +/// with a new pool with a different burn address. +contract BurnToAddressMintTokenPool is BurnMintTokenPoolAbstract, ITypeAndVersion { + using SafeERC20 for IERC20; + + event OutstandingTokensSet(uint256 newMintedTokenAmount, uint256 oldMintedTokenAmount); + + error InsufficientOutstandingTokens(); + + string public constant override typeAndVersion = "BurnToAddressTokenPool 1.5.1"; + + /// @notice The address where tokens are sent during a call to lockOrBurn, functionally burning but without decreasing + /// total supply. This address is expected to have no ability to recover the tokens sent to it, and will thus be locked forever. + /// This can be either an EOA without a corresponding private key, or a contract which does not have the ability to transfer the tokens. + address public immutable i_burnAddress; + + /// @notice Minted Tokens is a safety mechanism to ensure that more tokens cannot be sent out of the bridge + /// than were originally sent in via CCIP. On incoming messages the value is increased, and on outgoing messages, + /// the value is decreased. For pools with existing tokens in circulation, the value may not be known at deployment + /// time, and thus should be set later using the setoutstandingTokens() function. + uint256 internal s_outstandingTokens; + + /// @dev Since burnAddress is expected to make the tokens unrecoverable, no check for the zero address needs to be + /// performed, as it is a valid input. + constructor( + IBurnMintERC20 token, + uint8 localTokenDecimals, + address[] memory allowlist, + address rmnProxy, + address router, + address burnAddress + ) TokenPool(token, localTokenDecimals, allowlist, rmnProxy, router) { + i_burnAddress = burnAddress; + } + + /// @notice Mint tokens from the pool to the recipient, updating the internal accounting for an outflow of tokens. + /// @dev If the amount of tokens to be + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) public virtual override returns (Pool.ReleaseOrMintOutV1 memory) { + // When minting tokens, the local outstanding supply increases. These tokens will be burned + // when they are sent back to the pool on an outgoing message. + s_outstandingTokens += releaseOrMintIn.amount; + + return super.releaseOrMint(releaseOrMintIn); + } + + /// @inheritdoc BurnMintTokenPoolAbstract + /// @notice Tokens are burned by sending to an address which can never transfer them, + /// making the tokens unrecoverable without reducing the total supply. + function _burn( + uint256 amount + ) internal virtual override { + if (amount > s_outstandingTokens) { + revert InsufficientOutstandingTokens(); + } + + // When tokens are burned, the amount outstanding decreases. This ensures that more tokens cannot be sent out + // of the bridge than were originally sent in via CCIP. + s_outstandingTokens -= amount; + + getToken().safeTransfer(i_burnAddress, amount); + } + + /// @notice Returns the address where tokens are sent during a call to lockOrBurn + /// @return burnAddress the address which receives the tokens. + function getBurnAddress() public view returns (address burnAddress) { + return i_burnAddress; + } + + /// @notice Return the amount of tokens which were minted by this contract and not yet burned. + /// @return outstandingTokens The amount of tokens which were minted by this token pool and not yet burned. + function getOutstandingTokens() public view returns (uint256 outstandingTokens) { + return s_outstandingTokens; + } + + /// @notice Set the amount of tokens which were minted by this contract and not yet burned. + /// @param amount The new amount of tokens which were minted by this token pool and not yet burned. + function setOutstandingTokens( + uint256 amount + ) external onlyOwner { + uint256 currentOutstandingTokens = s_outstandingTokens; + + s_outstandingTokens = amount; + + emit OutstandingTokensSet(amount, currentOutstandingTokens); + } +} diff --git a/contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol b/contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol index fb8538141ca..3659c638dd5 100644 --- a/contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IBurnMintERC20} from "../../shared/token/ERC20/IBurnMintERC20.sol"; diff --git a/contracts/src/v0.8/ccip/pools/LockReleaseTokenPool.sol b/contracts/src/v0.8/ccip/pools/LockReleaseTokenPool.sol index ecc28a14dd1..54977a95758 100644 --- a/contracts/src/v0.8/ccip/pools/LockReleaseTokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/LockReleaseTokenPool.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {ILiquidityContainer} from "../../liquiditymanager/interfaces/ILiquidityContainer.sol"; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; diff --git a/contracts/src/v0.8/ccip/pools/SiloedLockReleaseTokenPool.sol b/contracts/src/v0.8/ccip/pools/SiloedLockReleaseTokenPool.sol new file mode 100644 index 00000000000..adb3a452957 --- /dev/null +++ b/contracts/src/v0.8/ccip/pools/SiloedLockReleaseTokenPool.sol @@ -0,0 +1,299 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; + +import {Pool} from "../libraries/Pool.sol"; +import {TokenPool} from "./TokenPool.sol"; + +import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; + +/// @notice A variation on Lock Release token pools where liquidity is shared among some chains, and stored independently +/// for others. Chains which do not share liquidity are known as siloed chains. +contract SiloedLockReleaseTokenPool is TokenPool, ITypeAndVersion { + using SafeERC20 for IERC20; + + error InsufficientLiquidity(uint256 availableLiquidity, uint256 requestedAmount); + error ChainNotSiloed(uint64 remoteChainSelector); + error InvalidChainSelector(uint64 remoteChainSelector); + + event LiquidityAdded(uint64 remoteChainSelector, address indexed provider, uint256 amount); + event LiquidityRemoved(uint64 remoteChainSelector, address indexed provider, uint256 amount); + event ChainUnsiloed(uint64 remoteChainSelector, uint256 amountUnsiloed); + event ChainSiloed(uint64 remoteChainSelector, address rebalancer); + event SiloRebalancerSet(uint64 indexed remoteChainSelector, address oldRebalancer, address newRebalancer); + event UnsiloedRebalancerSet(address oldRebalancer, address newRebalancer); + + string public constant override typeAndVersion = "SiloedLockReleaseTokenPool 1.6.0-dev"; + + /// @notice The amount of tokens available for remote chains which are not siloed as an additional security precaution. + uint256 internal s_unsiloedTokenBalance; + + /// @notice The rebalancer for unsiloed chains, which can add liquidity to the shared pool. + address internal s_rebalancer; + + struct SiloConfigUpdate { + uint64 remoteChainSelector; + address rebalancer; + } + + struct SiloConfig { + uint256 tokenBalance; // The amount of tokens available for incoming messages, either locked or as liquidity. + address rebalancer; // ─╮ The address allowed to add liquidity for the given siloed chain. + bool isSiloed; // ──────╯ Whether funds should be isolated from all other chains or shared amongst all non-siloed chains. + } + + /// @notice The configuration for each chain that is siloed, or not. By default chains are not siloed. + mapping(uint64 remoteChainSelector => SiloConfig) internal s_chainConfigs; + + constructor( + IERC20 token, + uint8 localTokenDecimals, + address[] memory allowlist, + address rmnProxy, + address router + ) TokenPool(token, localTokenDecimals, allowlist, rmnProxy, router) {} + + /// @notice Locks the token in the pool + /// @dev The _validateLockOrBurn check is an essential security check + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) external virtual override returns (Pool.LockOrBurnOutV1 memory) { + _validateLockOrBurn(lockOrBurnIn); + + // If funds need to be siloed, update internal accounting; + if (s_chainConfigs[lockOrBurnIn.remoteChainSelector].isSiloed) { + s_chainConfigs[lockOrBurnIn.remoteChainSelector].tokenBalance += lockOrBurnIn.amount; + } + // If the messages is going to a chain without siloed funds, update state accounting accordingly. + else { + s_unsiloedTokenBalance += lockOrBurnIn.amount; + } + + emit Locked(msg.sender, lockOrBurnIn.amount); + + return Pool.LockOrBurnOutV1({ + destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), + destPoolData: _encodeLocalDecimals() + }); + } + + /// @notice Release tokens from the pool to the recipient + /// @dev The _validateReleaseOrMint check is an essential security check + /// @dev If the releaseOrMintIn amount is greater than available liquidity, the function will revert as a security + /// measure to prevent funds from a Silo being released by another chain. + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) { + _validateReleaseOrMint(releaseOrMintIn); + + // Calculate the local amount + uint256 localAmount = + _calculateLocalAmount(releaseOrMintIn.amount, _parseRemoteDecimals(releaseOrMintIn.sourcePoolData)); + + // Save gas by using storage instead of memory as a value may need to be updated. + SiloConfig storage remoteConfig = s_chainConfigs[releaseOrMintIn.remoteChainSelector]; + + // Prevent A silent underflow by explicitly ensuring that enough funds are available to release + uint256 availableLiquidity = remoteConfig.isSiloed ? remoteConfig.tokenBalance : s_unsiloedTokenBalance; + if (localAmount > availableLiquidity) revert InsufficientLiquidity(availableLiquidity, localAmount); + + // Tracking balances independently by chain is a security measure to prevent liquidity for one chain from being + // released by another chain. + if (remoteConfig.isSiloed) { + remoteConfig.tokenBalance -= localAmount; + } else { + s_unsiloedTokenBalance -= localAmount; + } + + // Release to the recipient + getToken().safeTransfer(releaseOrMintIn.receiver, localAmount); + + emit Released(msg.sender, releaseOrMintIn.receiver, localAmount); + + return Pool.ReleaseOrMintOutV1({destinationAmount: localAmount}); + } + + /// @notice Returns whether the tokens locked for a given remote chain should be siloed independently + /// from all other remote chains. + /// @param remoteChainSelector the CCIP specific selector for the remote chain being interacted with. + /// @return isSiloed Whether the funds should be isolated from all the others. + function isSiloed( + uint64 remoteChainSelector + ) external view returns (bool) { + return s_chainConfigs[remoteChainSelector].isSiloed; + } + + /// @notice Returns the amount of tokens in the token pool that were siloed for a specific remote chain selector. + /// @param remoteChainSelector the CCIP specific selector for the remote chain being interacted with. + /// @return lockedTokens The tokens locked into this token pool for the given selector. If the chain is not siloed, + /// the amount will be the amount of liquidity shared among all unsiloed chains. + function getAvailableTokens( + uint64 remoteChainSelector + ) external view returns (uint256 lockedTokens) { + if (s_chainConfigs[remoteChainSelector].isSiloed) { + return s_chainConfigs[remoteChainSelector].tokenBalance; + } + + return s_unsiloedTokenBalance; + } + + /// @notice Returns the amount of tokens in the token pool that are shared among all unsiloed chains. + /// @return unsiloedTokens amount of tokens available to all unsiloed chains. + function getUnsiloedLiquidity() external view returns (uint256) { + return s_unsiloedTokenBalance; + } + + /// @notice Updates designations for chains on whether to mark funds as Siloed or not + /// @param removes A list of chain selectors to disable Siloing. Their funds will be moved into the unsiloed pool. + /// If a chain is not siloed, and attempted to be removed, the function will revert. + /// @param adds A list of chain selectors to enable Siloing. Adding a chain to siloing will not set the rebalancer. + /// The rebalancer will need to be set separately. + function updateSiloDesignations(uint64[] calldata removes, SiloConfigUpdate[] calldata adds) external onlyOwner { + for (uint256 i = 0; i < removes.length; ++i) { + if (!s_chainConfigs[removes[i]].isSiloed) revert ChainNotSiloed(removes[i]); + + // When a chain is removed from siloing, the funds are moved to the accounting pool shared by all unsiloed chain. + uint256 amountUnsiloed = s_chainConfigs[removes[i]].tokenBalance; + + s_unsiloedTokenBalance += amountUnsiloed; + + delete s_chainConfigs[removes[i]]; + + // Emit a removal event which includes the amount of funds moved to the general silo. + emit ChainUnsiloed(removes[i], amountUnsiloed); + } + + for (uint256 i = 0; i < adds.length; ++i) { + // Since the zero chain selector is used to designate unsiloed chains, it should never be used for siloed chains. + if (adds[i].remoteChainSelector == 0) { + revert InvalidChainSelector(0); + } + + SiloConfig memory newConfig = SiloConfig({tokenBalance: 0, rebalancer: adds[i].rebalancer, isSiloed: true}); + + s_chainConfigs[adds[i].remoteChainSelector] = newConfig; + + emit ChainSiloed(adds[i].remoteChainSelector, adds[i].rebalancer); + } + } + + /// @notice Gets the rebalancer able to provide liquidity for a remote chain selector + /// @param remoteChainSelector The CCIP specific selector for the remote chain being interacted with. + /// @return The current liquidity manager, contract owner if the chain's funds are not siloed. + function getSiloRebalancer( + uint64 remoteChainSelector + ) public view returns (address) { + SiloConfig memory remoteConfig = s_chainConfigs[remoteChainSelector]; + if (remoteConfig.isSiloed) { + return remoteConfig.rebalancer; + } + + return s_rebalancer; + } + + /// @notice Sets the Rebalancer address for a given remoteChainSelector. + /// @dev Only callable by the owner. + /// @param remoteChainSelector the remote chain to set. + /// @param newRebalancer the address allowed to add liquidity for the given siloed chain. + function setSiloRebalancer(uint64 remoteChainSelector, address newRebalancer) external onlyOwner { + SiloConfig memory remoteConfig = s_chainConfigs[remoteChainSelector]; + + if (!remoteConfig.isSiloed) revert ChainNotSiloed(remoteChainSelector); + + address oldRebalancer = remoteConfig.rebalancer; + + s_chainConfigs[remoteChainSelector].rebalancer = newRebalancer; + + emit SiloRebalancerSet(remoteChainSelector, newRebalancer, oldRebalancer); + } + + /// @notice Sets the Rebalancer address for unsiloed chains. + /// @dev Only callable by the owner. + /// @param newRebalancer the address allowed to add liquidity for the given siloed chain. + function setRebalancer( + address newRebalancer + ) external onlyOwner { + address oldRebalancer = s_rebalancer; + + s_rebalancer = newRebalancer; + + emit UnsiloedRebalancerSet(newRebalancer, oldRebalancer); + } + + /// @notice Adds liquidity to the pool. The tokens should be approved first. + /// @param remoteChainSelector the remote chain to set. If the chain is not siloed, the liquidity will be shared among all + /// non-siloed chains. + /// @param amount The amount of liquidity to provide. + /// @dev Only the rebalancer for the chain can add liquidity + function provideSiloedLiquidity(uint64 remoteChainSelector, uint256 amount) external { + _provideLiquidity(remoteChainSelector, amount); + } + + /// @notice Adds liquidity to the pool for unsiloed chains. Function is used to support legacy liquidity operations + /// by using a function selector available to previous L/R pools. + /// @dev Since the remoteChainSelector 0 should never be applied to a real chain, it is used to designate unsiloed chains. + /// @param amount The amount of liquidity to provide. + function provideLiquidity( + uint256 amount + ) external { + _provideLiquidity(0, amount); + } + + function _provideLiquidity(uint64 remoteChainSelector, uint256 amount) internal { + if (msg.sender != getSiloRebalancer(remoteChainSelector)) revert Unauthorized(msg.sender); + + // Storage is used instead of memory to save gas, as the state may need to be updated if the chain is siloed. + SiloConfig storage remoteConfig = s_chainConfigs[remoteChainSelector]; + + if (remoteConfig.isSiloed) { + remoteConfig.tokenBalance += amount; + } else { + s_unsiloedTokenBalance += amount; + } + + i_token.safeTransferFrom(msg.sender, address(this), amount); + emit LiquidityAdded(remoteChainSelector, msg.sender, amount); + } + + /// @notice Removes liquidity from the pool for unsiloed chains. Function is used to support legacy liquidity operations + /// by using a function selector available to previous L/R pools. + /// @dev Since the remoteChainSelector 0 should never be applied to a real chain, it is used to designate unsiloed chains. + /// @param amount The amount of liquidity to remove. + function withdrawLiquidity( + uint256 amount + ) external { + _withdrawLiquidity(0, amount); + } + + /// @notice Removed liquidity to the pool. The tokens will be sent to msg.sender. + /// @dev Only the rebalancer can remove liquidity from the contract, for both siloed and unsiloed chains. + /// @param remoteChainSelector the remote chain to set. If the chain is not siloed, then no accounting will be updated, + /// which can be considered the liquidity for all non-siloed chains sharing liquidity. + /// @param amount The amount of liquidity to remove. + function withdrawSiloedLiquidity(uint64 remoteChainSelector, uint256 amount) external { + _withdrawLiquidity(remoteChainSelector, amount); + } + + function _withdrawLiquidity(uint64 remoteChainSelector, uint256 amount) internal { + if (msg.sender != getSiloRebalancer(remoteChainSelector)) revert Unauthorized(msg.sender); + + // Save gas by using storage as multiple values may need to be read/written. + SiloConfig storage remoteConfig = s_chainConfigs[remoteChainSelector]; + + // Prevent A silent underflow by explicitly ensuring that enough funds are available to withdraw + uint256 availableLiquidity = remoteConfig.isSiloed ? remoteConfig.tokenBalance : s_unsiloedTokenBalance; + if (amount > availableLiquidity) revert InsufficientLiquidity(availableLiquidity, amount); + + // If funds are siloed by chain, prevent more than has been locked from being removed from the token pool. + if (remoteConfig.isSiloed) { + remoteConfig.tokenBalance -= amount; + } else { + s_unsiloedTokenBalance -= amount; + } + + i_token.safeTransfer(msg.sender, amount); + emit LiquidityRemoved(remoteChainSelector, msg.sender, amount); + } +} diff --git a/contracts/src/v0.8/ccip/pools/TokenPool.sol b/contracts/src/v0.8/ccip/pools/TokenPool.sol index 9d8e77a7928..47a2ebad238 100644 --- a/contracts/src/v0.8/ccip/pools/TokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/TokenPool.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IPoolV1} from "../interfaces/IPool.sol"; import {IRMN} from "../interfaces/IRMN.sol"; diff --git a/contracts/src/v0.8/ccip/pools/USDC/BurnMintWithLockReleaseFlagTokenPool.sol b/contracts/src/v0.8/ccip/pools/USDC/BurnMintWithLockReleaseFlagTokenPool.sol index 746df9b4e11..6b46dfacca6 100644 --- a/contracts/src/v0.8/ccip/pools/USDC/BurnMintWithLockReleaseFlagTokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/USDC/BurnMintWithLockReleaseFlagTokenPool.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; diff --git a/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol b/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol index 264b1230c7c..3f94a1b719a 100644 --- a/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol @@ -1,10 +1,9 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {ILiquidityContainer} from "../../../liquiditymanager/interfaces/ILiquidityContainer.sol"; import {ITokenMessenger} from "../USDC/ITokenMessenger.sol"; -import {Ownable2StepMsgSender} from "../../../shared/access/Ownable2StepMsgSender.sol"; import {Pool} from "../../libraries/Pool.sol"; import {TokenPool} from "../TokenPool.sol"; import {USDCTokenPool} from "../USDC/USDCTokenPool.sol"; @@ -209,31 +208,6 @@ contract HybridLockReleaseUSDCTokenPool is USDCTokenPool, USDCBridgeMigrator { emit ILiquidityContainer.LiquidityRemoved(msg.sender, amount); } - /// @notice This function can be used to transfer liquidity from an older version of the pool to this pool. To do so - /// this pool must be the owner of the old pool. Since the pool uses two-step ownership transfer, the old pool must - /// first propose the ownership transfer, and then this pool must accept it. This function can only be called after - /// the ownership transfer has been proposed, as it will accept it and then make the call to withdrawLiquidity - /// @dev When upgrading a LockRelease pool, this function can be called at the same time as the pool is changed in the - /// TokenAdminRegistry. This allows for a smooth transition of both liquidity and transactions to the new pool. - /// Alternatively, when no multicall is available, a portion of the funds can be transferred to the new pool before - /// changing which pool CCIP uses, to ensure both pools can operate. Then the pool should be changed in the - /// TokenAdminRegistry, which will activate the new pool. All new transactions will use the new pool and its - /// liquidity. - /// @param from The address of the old pool. - /// @param remoteChainSelector The chain for which liquidity is being transferred. - function transferLiquidity(address from, uint64 remoteChainSelector) external onlyOwner { - Ownable2StepMsgSender(from).acceptOwnership(); - - // Withdraw all available liquidity from the old pool. No check is needed for pending migrations, as the old pool - // will revert if the migration has begun. - uint256 withdrawAmount = HybridLockReleaseUSDCTokenPool(from).getLockedTokensForChain(remoteChainSelector); - HybridLockReleaseUSDCTokenPool(from).withdrawLiquidity(remoteChainSelector, withdrawAmount); - - s_lockedTokensByChainSelector[remoteChainSelector] += withdrawAmount; - - emit LiquidityTransferred(from, remoteChainSelector, withdrawAmount); - } - // ================================================================ // │ Alt Mechanism Logic | // ================================================================ diff --git a/contracts/src/v0.8/ccip/pools/USDC/USDCBridgeMigrator.sol b/contracts/src/v0.8/ccip/pools/USDC/USDCBridgeMigrator.sol index 1dcecac8b2f..a8ad7052110 100644 --- a/contracts/src/v0.8/ccip/pools/USDC/USDCBridgeMigrator.sol +++ b/contracts/src/v0.8/ccip/pools/USDC/USDCBridgeMigrator.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Ownable2StepMsgSender} from "../../../shared/access/Ownable2StepMsgSender.sol"; import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; diff --git a/contracts/src/v0.8/ccip/pools/USDC/USDCTokenPool.sol b/contracts/src/v0.8/ccip/pools/USDC/USDCTokenPool.sol index 5998e52f156..524f8f47f70 100644 --- a/contracts/src/v0.8/ccip/pools/USDC/USDCTokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/USDC/USDCTokenPool.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; import {IMessageTransmitter} from "./IMessageTransmitter.sol"; diff --git a/contracts/src/v0.8/ccip/rmn/RMNHome.sol b/contracts/src/v0.8/ccip/rmn/RMNHome.sol index 92aab25ae8e..b1eb56679f4 100644 --- a/contracts/src/v0.8/ccip/rmn/RMNHome.sol +++ b/contracts/src/v0.8/ccip/rmn/RMNHome.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; @@ -81,7 +81,7 @@ contract RMNHome is Ownable2StepMsgSender, ITypeAndVersion { struct SourceChain { uint64 chainSelector; // ─╮ The Source chain selector. - uint64 f; // ─────────────╯ Maximum number of faulty observers; f+1 observers required to agree on an observation for this source chain. + uint64 fObserve; // ──────╯ Maximum number of faulty observers; f+1 observers required to agree on an observation for this source chain. uint256 observerNodesBitmap; // ObserverNodesBitmap & (1<. -pragma solidity 0.8.24; +pragma solidity ^0.8.24; // solhint-disable contract WETH9 { diff --git a/contracts/src/v0.8/ccip/test/applications/DefensiveExample/DefensiveExample.t.sol b/contracts/src/v0.8/ccip/test/applications/DefensiveExample/DefensiveExample.t.sol index ddaadbac801..1817476c134 100644 --- a/contracts/src/v0.8/ccip/test/applications/DefensiveExample/DefensiveExample.t.sol +++ b/contracts/src/v0.8/ccip/test/applications/DefensiveExample/DefensiveExample.t.sol @@ -68,7 +68,7 @@ contract DefensiveExampleTest is OnRampSetup { assertEq(IERC20(token).balanceOf(address(s_receiver)), receiverBalancePre - amount); } - function test_HappyPath_Success() public { + function test_HappyPath() public { bytes32 messageId = keccak256("messageId"); address token = address(s_destFeeToken); uint256 amount = 111333333777; diff --git a/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver/EtherSenderReceiverTest.ccipSend.t.sol b/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver/EtherSenderReceiverTest.ccipSend.t.sol index dea42f36098..5f91841ab6e 100644 --- a/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver/EtherSenderReceiverTest.ccipSend.t.sol +++ b/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver/EtherSenderReceiverTest.ccipSend.t.sol @@ -99,7 +99,7 @@ contract EtherSenderReceiverTest_ccipSend is EtherSenderReceiverTestSetup { } } - function test_ccipSend_reverts_insufficientFee_weth() public { + function test_RevertWhen_ccipSends_insufficientFee_weth() public { Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); tokenAmounts[0] = Client.EVMTokenAmount({ token: address(0), // callers may not specify this. @@ -127,7 +127,7 @@ contract EtherSenderReceiverTest_ccipSend is EtherSenderReceiverTestSetup { s_etherSenderReceiver.ccipSend{value: AMOUNT}(DESTINATION_CHAIN_SELECTOR, message); } - function test_ccipSend_reverts_insufficientFee_feeToken() public { + function test_RevertWhen_ccipSends_insufficientFee_feeToken() public { Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); tokenAmounts[0] = Client.EVMTokenAmount({ token: address(0), // callers may not specify this. @@ -155,7 +155,7 @@ contract EtherSenderReceiverTest_ccipSend is EtherSenderReceiverTestSetup { s_etherSenderReceiver.ccipSend{value: AMOUNT}(DESTINATION_CHAIN_SELECTOR, message); } - function test_ccipSend_reverts_insufficientFee_native() public { + function test_RevertWhen_ccipSends_insufficientFee_native() public { Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); tokenAmounts[0] = Client.EVMTokenAmount({ token: address(0), // callers may not specify this. @@ -181,7 +181,7 @@ contract EtherSenderReceiverTest_ccipSend is EtherSenderReceiverTestSetup { s_etherSenderReceiver.ccipSend{value: AMOUNT + FEE_WEI - 1}(DESTINATION_CHAIN_SELECTOR, message); } - function test_ccipSend_success_nativeExcess() public { + function test_ccipSend_nativeExcess() public { Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); tokenAmounts[0] = Client.EVMTokenAmount({ token: address(0), // callers may not specify this. @@ -218,7 +218,7 @@ contract EtherSenderReceiverTest_ccipSend is EtherSenderReceiverTestSetup { assertEq(actualMsgId, expectedMsgId, "message id must be correct"); } - function test_ccipSend_success_native() public { + function test_ccipSend_native() public { Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); tokenAmounts[0] = Client.EVMTokenAmount({ token: address(0), // callers may not specify this. @@ -251,7 +251,7 @@ contract EtherSenderReceiverTest_ccipSend is EtherSenderReceiverTestSetup { assertEq(actualMsgId, expectedMsgId, "message id must be correct"); } - function test_ccipSend_success_feeToken() public { + function test_ccipSend_feeToken() public { Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); tokenAmounts[0] = Client.EVMTokenAmount({ token: address(0), // callers may not specify this. @@ -287,7 +287,7 @@ contract EtherSenderReceiverTest_ccipSend is EtherSenderReceiverTestSetup { assertEq(routerAllowance, FEE_JUELS, "router allowance must be feeJuels"); } - function test_ccipSend_success_weth() public { + function test_ccipSend_weth() public { Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); tokenAmounts[0] = Client.EVMTokenAmount({ token: address(0), // callers may not specify this. diff --git a/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver/EtherSenderReceiverTest.validateFeeToken.t.sol b/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver/EtherSenderReceiverTest.validateFeeToken.t.sol index ae24ca3deae..29da1a1e068 100644 --- a/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver/EtherSenderReceiverTest.validateFeeToken.t.sol +++ b/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver/EtherSenderReceiverTest.validateFeeToken.t.sol @@ -36,7 +36,7 @@ contract EtherSenderReceiverTest_validateFeeToken is EtherSenderReceiverTestSetu s_etherSenderReceiver.validateFeeToken{value: AMOUNT}(message); } - function test_validateFeeToken_reverts_feeToken_tokenAmountNotEqualToMsgValue() public { + function test_RevertWhen_validateFeeTokens_feeToken_tokenAmountNotEqualToMsgValue() public { Client.EVMTokenAmount[] memory tokenAmount = new Client.EVMTokenAmount[](1); tokenAmount[0] = Client.EVMTokenAmount({token: address(s_weth), amount: AMOUNT}); Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ diff --git a/contracts/src/v0.8/ccip/test/applications/ImmutableExample/ImmutableExample.t.sol b/contracts/src/v0.8/ccip/test/applications/ImmutableExample/ImmutableExample.t.sol index 2eb9b736ad4..8cb2cdd97d9 100644 --- a/contracts/src/v0.8/ccip/test/applications/ImmutableExample/ImmutableExample.t.sol +++ b/contracts/src/v0.8/ccip/test/applications/ImmutableExample/ImmutableExample.t.sol @@ -11,7 +11,7 @@ import {ERC165Checker} from "../../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/ERC165Checker.sol"; contract CCIPClientExample_sanity is OnRampSetup { - function test_ImmutableExamples_Success() public { + function test_ImmutableExamples() public { CCIPClientExample exampleContract = new CCIPClientExample(s_sourceRouter, IERC20(s_sourceFeeToken)); deal(address(exampleContract), 100 ether); deal(s_sourceFeeToken, address(exampleContract), 100 ether); diff --git a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.ccipReceive.t.sol b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.ccipReceive.t.sol index a7559b6dea2..75d642defac 100644 --- a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.ccipReceive.t.sol +++ b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.ccipReceive.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {PingPongDemo} from "../../../applications/PingPongDemo.sol"; import {Client} from "../../../libraries/Client.sol"; @@ -7,7 +7,7 @@ import {Client} from "../../../libraries/Client.sol"; import {PingPongDappSetup} from "./PingPongDappSetup.t.sol"; contract PingPong_ccipReceive is PingPongDappSetup { - function test_CcipReceive_Success() public { + function test_CcipReceive() public { Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](0); uint256 pingPongNumber = 5; diff --git a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setCounterpart.t.sol b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setCounterpart.t.sol index 8db2e75c5d7..e9c4135dead 100644 --- a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setCounterpart.t.sol +++ b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setCounterpart.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {PingPongDappSetup} from "./PingPongDappSetup.t.sol"; diff --git a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setCounterpartAddress.t.sol b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setCounterpartAddress.t.sol index 0e5587dac5f..43f123bbf6c 100644 --- a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setCounterpartAddress.t.sol +++ b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setCounterpartAddress.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {PingPongDappSetup} from "./PingPongDappSetup.t.sol"; diff --git a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setCounterpartChainSelector.t.sol b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setCounterpartChainSelector.t.sol index a7d148089bc..3702c002e73 100644 --- a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setCounterpartChainSelector.t.sol +++ b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setCounterpartChainSelector.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {PingPongDappSetup} from "./PingPongDappSetup.t.sol"; diff --git a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setOutOfOrderExecution.t.sol b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setOutOfOrderExecution.t.sol index 0e09e67f7cb..2929153db8e 100644 --- a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setOutOfOrderExecution.t.sol +++ b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setOutOfOrderExecution.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {PingPongDemo} from "../../../applications/PingPongDemo.sol"; import {PingPongDappSetup} from "./PingPongDappSetup.t.sol"; contract PingPong_setOutOfOrderExecution is PingPongDappSetup { - function test_OutOfOrderExecution_Success() public { + function test_OutOfOrderExecution() public { assertFalse(s_pingPong.getOutOfOrderExecution()); vm.expectEmit(); diff --git a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setPaused.t.sol b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setPaused.t.sol index 82cd22199ec..645cbe6b81d 100644 --- a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setPaused.t.sol +++ b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setPaused.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {PingPongDappSetup} from "./PingPongDappSetup.t.sol"; contract PingPong_setPaused is PingPongDappSetup { - function test_Pausing_Success() public { + function test_Pausing() public { assertFalse(s_pingPong.isPaused()); s_pingPong.setPaused(true); diff --git a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.startPingPong.t.sol b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.startPingPong.t.sol index d9dfc980154..6dccdca6b38 100644 --- a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.startPingPong.t.sol +++ b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.startPingPong.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {PingPongDemo} from "../../../applications/PingPongDemo.sol"; import {Internal} from "../../../libraries/Internal.sol"; @@ -10,11 +10,11 @@ import {PingPongDappSetup} from "./PingPongDappSetup.t.sol"; contract PingPong_startPingPong is PingPongDappSetup { uint256 internal s_pingPongNumber = 1; - function test_StartPingPong_With_Sequenced_Ordered_Success() public { + function test_StartPingPong_With_Sequenced_Ordered() public { _assertPingPongSuccess(); } - function test_StartPingPong_With_OOO_Success() public { + function test_StartPingPong_With_OOO() public { s_pingPong.setOutOfOrderExecution(true); _assertPingPongSuccess(); diff --git a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPongDappSetup.t.sol b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPongDappSetup.t.sol index 8c009a0660d..64f52f16b1c 100644 --- a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPongDappSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPongDappSetup.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {PingPongDemo} from "../../../applications/PingPongDemo.sol"; import {OnRampSetup} from "../../onRamp/OnRamp/OnRampSetup.t.sol"; diff --git a/contracts/src/v0.8/ccip/test/attacks/OnRamp/FacadeClient.sol b/contracts/src/v0.8/ccip/test/attacks/OnRamp/FacadeClient.sol index 8947a27df1d..e8623c74e8a 100644 --- a/contracts/src/v0.8/ccip/test/attacks/OnRamp/FacadeClient.sol +++ b/contracts/src/v0.8/ccip/test/attacks/OnRamp/FacadeClient.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IRouterClient} from "../../../interfaces/IRouterClient.sol"; diff --git a/contracts/src/v0.8/ccip/test/attacks/OnRamp/OnRampTokenPoolReentrancy.t.sol b/contracts/src/v0.8/ccip/test/attacks/OnRamp/OnRampTokenPoolReentrancy.t.sol index 54e08a2a5ef..271e10e7561 100644 --- a/contracts/src/v0.8/ccip/test/attacks/OnRamp/OnRampTokenPoolReentrancy.t.sol +++ b/contracts/src/v0.8/ccip/test/attacks/OnRamp/OnRampTokenPoolReentrancy.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Client} from "../../../libraries/Client.sol"; import {OnRamp} from "../../../onRamp/OnRamp.sol"; @@ -29,7 +29,7 @@ contract OnRampTokenPoolReentrancy is OnRampSetup { new FacadeClient(address(s_sourceRouter), DEST_CHAIN_SELECTOR, s_sourceToken, s_feeToken, i_receiver); s_maliciousTokenPool = new ReentrantMaliciousTokenPool( - address(s_facadeClient), s_sourceToken, address(s_mockRMN), address(s_sourceRouter) + address(s_facadeClient), s_sourceToken, address(s_mockRMNRemote), address(s_sourceRouter) ); bytes[] memory remotePoolAddresses = new bytes[](1); @@ -59,7 +59,7 @@ contract OnRampTokenPoolReentrancy is OnRampSetup { /// (reenter)-> Facade -> 2nd call to ccipSend /// In this case, Facade's second call would produce an EVM2Any msg with a lower sequence number. /// The issue was fixed by implementing a reentrancy guard in OnRamp. - function test_OnRampTokenPoolReentrancy_Success() public { + function test_OnRampTokenPoolReentrancy() public { uint256 amount = 1; Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); diff --git a/contracts/src/v0.8/ccip/test/attacks/OnRamp/ReentrantMaliciousTokenPool.sol b/contracts/src/v0.8/ccip/test/attacks/OnRamp/ReentrantMaliciousTokenPool.sol index 39ab239e22f..3a7af8af506 100644 --- a/contracts/src/v0.8/ccip/test/attacks/OnRamp/ReentrantMaliciousTokenPool.sol +++ b/contracts/src/v0.8/ccip/test/attacks/OnRamp/ReentrantMaliciousTokenPool.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Pool} from "../../../libraries/Pool.sol"; import {TokenPool} from "../../../pools/TokenPool.sol"; diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.applyChainConfigUpdates.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.applyChainConfigUpdates.t.sol index 9bf096b9551..2547ac3010d 100644 --- a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.applyChainConfigUpdates.t.sol +++ b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.applyChainConfigUpdates.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {INodeInfoProvider} from "../../../../keystone/interfaces/INodeInfoProvider.sol"; @@ -13,7 +13,7 @@ contract CCIPHome_applyChainConfigUpdates is CCIPHomeTestSetup { s_ccipHome = new CCIPHomeHelper(CAPABILITIES_REGISTRY); } - function test_applyChainConfigUpdates_addChainConfigs_Success() public { + function test_applyChainConfigUpdates_addChainConfigs() public { bytes32[] memory chainReaders = new bytes32[](1); chainReaders[0] = keccak256(abi.encode(1)); CCIPHome.ChainConfigArgs[] memory adds = new CCIPHome.ChainConfigArgs[](2); @@ -54,7 +54,7 @@ contract CCIPHome_applyChainConfigUpdates is CCIPHomeTestSetup { assertEq(s_ccipHome.getNumChainConfigurations(), 2, "total chain configs must be 2"); } - function test_getPaginatedCCIPHomes_Success() public { + function test_getPaginatedCCIPHomes() public { bytes32[] memory chainReaders = new bytes32[](1); chainReaders[0] = keccak256(abi.encode(1)); CCIPHome.ChainConfigArgs[] memory adds = new CCIPHome.ChainConfigArgs[](2); @@ -106,7 +106,7 @@ contract CCIPHome_applyChainConfigUpdates is CCIPHomeTestSetup { assertEq(configs.length, 0, "chain configs length must be 0"); } - function test_applyChainConfigUpdates_removeChainConfigs_Success() public { + function test_applyChainConfigUpdates_removeChainConfigs() public { bytes32[] memory chainReaders = new bytes32[](1); chainReaders[0] = keccak256(abi.encode(1)); @@ -162,7 +162,7 @@ contract CCIPHome_applyChainConfigUpdates is CCIPHomeTestSetup { // Reverts. - function test_applyChainConfigUpdates_selectorNotFound_Reverts() public { + function test_RevertWhen_applyChainConfigUpdates_selectorNotFound() public { uint64[] memory removes = new uint64[](1); removes[0] = uint64(1); @@ -170,7 +170,7 @@ contract CCIPHome_applyChainConfigUpdates is CCIPHomeTestSetup { s_ccipHome.applyChainConfigUpdates(removes, new CCIPHome.ChainConfigArgs[](0)); } - function test_applyChainConfigUpdates_nodeNotInRegistry_Reverts() public { + function test_RevertWhen_applyChainConfigUpdates_nodeNotInRegistry() public { bytes32[] memory chainReaders = new bytes32[](1); chainReaders[0] = keccak256(abi.encode(1)); CCIPHome.ChainConfigArgs[] memory adds = new CCIPHome.ChainConfigArgs[](1); @@ -189,7 +189,7 @@ contract CCIPHome_applyChainConfigUpdates is CCIPHomeTestSetup { s_ccipHome.applyChainConfigUpdates(new uint64[](0), adds); } - function test__applyChainConfigUpdates_FChainNotPositive_Reverts() public { + function test_RevertWhen__applyChainConfigUpdates_FChainNotPositive() public { bytes32[] memory chainReaders = new bytes32[](1); chainReaders[0] = keccak256(abi.encode(1)); CCIPHome.ChainConfigArgs[] memory adds = new CCIPHome.ChainConfigArgs[](2); diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.beforeCapabilityConfigSet.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.beforeCapabilityConfigSet.t.sol index 090c8336c48..540c9d71e04 100644 --- a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.beforeCapabilityConfigSet.t.sol +++ b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.beforeCapabilityConfigSet.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {CCIPHome} from "../../../capability/CCIPHome.sol"; import {Internal} from "../../../libraries/Internal.sol"; @@ -13,7 +13,7 @@ contract CCIPHome_beforeCapabilityConfigSet is CCIPHomeTestSetup { vm.startPrank(address(CAPABILITIES_REGISTRY)); } - function test_beforeCapabilityConfigSet_success() public { + function test_beforeCapabilityConfigSet() public { // first set a config bytes memory callData = abi.encodeCall( CCIPHome.setCandidate, @@ -61,7 +61,7 @@ contract CCIPHome_beforeCapabilityConfigSet is CCIPHomeTestSetup { assertEq(activeDigest, newCandidateDigest); } - function test_beforeCapabilityConfigSet_OnlyCapabilitiesRegistryCanCall_reverts() public { + function test_RevertWhen_beforeCapabilityConfigSet_OnlyCapabilitiesRegistryCanCall() public { bytes memory callData = abi.encodeCall( CCIPHome.setCandidate, (DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, _getBaseConfig(Internal.OCRPluginType.Commit), ZERO_DIGEST) @@ -74,14 +74,14 @@ contract CCIPHome_beforeCapabilityConfigSet is CCIPHomeTestSetup { s_ccipHome.beforeCapabilityConfigSet(new bytes32[](0), callData, 0, DEFAULT_DON_ID); } - function test_beforeCapabilityConfigSet_InvalidSelector_reverts() public { + function test_RevertWhen_beforeCapabilityConfigSet_InvalidSelector() public { bytes memory callData = abi.encodeCall(CCIPHome.getConfigDigests, (DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE)); vm.expectRevert(abi.encodeWithSelector(CCIPHome.InvalidSelector.selector, CCIPHome.getConfigDigests.selector)); s_ccipHome.beforeCapabilityConfigSet(new bytes32[](0), callData, 0, DEFAULT_DON_ID); } - function test_beforeCapabilityConfigSet_DONIdMismatch_reverts() public { + function test_RevertWhen_beforeCapabilityConfigSet_DONIdMismatch() public { uint32 wrongDonId = DEFAULT_DON_ID + 1; bytes memory callData = abi.encodeCall( @@ -93,7 +93,7 @@ contract CCIPHome_beforeCapabilityConfigSet is CCIPHomeTestSetup { s_ccipHome.beforeCapabilityConfigSet(new bytes32[](0), callData, 0, wrongDonId); } - function test_beforeCapabilityConfigSet_InnerCallReverts_reverts() public { + function test_RevertWhen_beforeCapabilityConfigSet_InnerCallReverts() public { bytes memory callData = abi.encodeCall(CCIPHome.revokeCandidate, (DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, ZERO_DIGEST)); vm.expectRevert(CCIPHome.RevokingZeroDigestNotAllowed.selector); diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.constructor.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.constructor.t.sol index f4c1a777f3d..18e8c700992 100644 --- a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.constructor.t.sol +++ b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.constructor.t.sol @@ -1,17 +1,17 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {CCIPHome} from "../../../capability/CCIPHome.sol"; import {CCIPHomeTestSetup} from "./CCIPHomeTestSetup.t.sol"; contract CCIPHome_constructor is CCIPHomeTestSetup { - function test_constructor_success() public { + function test_constructor() public { CCIPHome ccipHome = new CCIPHome(CAPABILITIES_REGISTRY); assertEq(address(ccipHome.getCapabilityRegistry()), CAPABILITIES_REGISTRY); } - function test_constructor_CapabilitiesRegistryAddressZero_reverts() public { + function test_RevertWhen_constructor_CapabilitiesRegistryAddressZero() public { vm.expectRevert(CCIPHome.ZeroAddressNotAllowed.selector); new CCIPHome(address(0)); } diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.getAllConfigs.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.getAllConfigs.t.sol index 277819e1179..c14b54d294e 100644 --- a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.getAllConfigs.t.sol +++ b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.getAllConfigs.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {CCIPHome} from "../../../capability/CCIPHome.sol"; import {Internal} from "../../../libraries/Internal.sol"; import {CCIPHomeTestSetup} from "./CCIPHomeTestSetup.t.sol"; contract CCIPHome_getAllConfigs is CCIPHomeTestSetup { - function test_getAllConfigs_success() public { + function test_getAllConfigs() public { CCIPHome.OCR3Config memory config = _getBaseConfig(Internal.OCRPluginType.Commit); bytes32 firstDigest = s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, ZERO_DIGEST); diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.getCapabilityConfiguration.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.getCapabilityConfiguration.t.sol index ea65e111f0d..d4a6e150bae 100644 --- a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.getCapabilityConfiguration.t.sol +++ b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.getCapabilityConfiguration.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {CCIPHomeTestSetup} from "./CCIPHomeTestSetup.t.sol"; contract CCIPHome_getCapabilityConfiguration is CCIPHomeTestSetup { - function test_getCapabilityConfiguration_success() public view { + function test_getCapabilityConfiguration() public view { bytes memory config = s_ccipHome.getCapabilityConfiguration(DEFAULT_DON_ID); assertEq(config.length, 0); } diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.getConfigDigests.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.getConfigDigests.t.sol index 8cca6b12589..e239d04d341 100644 --- a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.getConfigDigests.t.sol +++ b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.getConfigDigests.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {CCIPHome} from "../../../capability/CCIPHome.sol"; import {Internal} from "../../../libraries/Internal.sol"; @@ -7,7 +7,7 @@ import {Internal} from "../../../libraries/Internal.sol"; import {CCIPHomeTestSetup} from "./CCIPHomeTestSetup.t.sol"; contract CCIPHome_getConfigDigests is CCIPHomeTestSetup { - function test_getConfigDigests_success() public { + function test_getConfigDigests() public { (bytes32 activeDigest, bytes32 candidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); assertEq(activeDigest, ZERO_DIGEST); assertEq(candidateDigest, ZERO_DIGEST); diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.promoteCandidateAndRevokeActive.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.promoteCandidateAndRevokeActive.t.sol index 09f25750ac3..cfa653754b0 100644 --- a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.promoteCandidateAndRevokeActive.t.sol +++ b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.promoteCandidateAndRevokeActive.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {CCIPHome} from "../../../capability/CCIPHome.sol"; import {Internal} from "../../../libraries/Internal.sol"; @@ -7,7 +7,7 @@ import {Internal} from "../../../libraries/Internal.sol"; import {CCIPHomeTestSetup} from "./CCIPHomeTestSetup.t.sol"; contract CCIPHome_promoteCandidateAndRevokeActive is CCIPHomeTestSetup { - function test_promoteCandidateAndRevokeActive_multiplePlugins_success() public { + function test_promoteCandidateAndRevokeActive_multiplePlugins() public { promoteCandidateAndRevokeActive(Internal.OCRPluginType.Commit); promoteCandidateAndRevokeActive(Internal.OCRPluginType.Execution); @@ -57,12 +57,12 @@ contract CCIPHome_promoteCandidateAndRevokeActive is CCIPHomeTestSetup { assertEq(keccak256(abi.encode(activeConfig.config)), keccak256(abi.encode(config))); } - function test_promoteCandidateAndRevokeActive_NoOpStateTransitionNotAllowed_reverts() public { + function test_RevertWhen_promoteCandidateAndRevokeActive_NoOpStateTransitionNotAllowed() public { vm.expectRevert(CCIPHome.NoOpStateTransitionNotAllowed.selector); s_ccipHome.promoteCandidateAndRevokeActive(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, ZERO_DIGEST, ZERO_DIGEST); } - function test_promoteCandidateAndRevokeActive_ConfigDigestMismatch_reverts() public { + function test_RevertWhen_promoteCandidateAndRevokeActive_ConfigDigestMismatch() public { (bytes32 priorActiveDigest, bytes32 priorCandidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); bytes32 wrongActiveDigest = keccak256("wrongActiveDigest"); @@ -84,7 +84,7 @@ contract CCIPHome_promoteCandidateAndRevokeActive is CCIPHomeTestSetup { ); } - function test_promoteCandidateAndRevokeActive_CanOnlySelfCall_reverts() public { + function test_RevertWhen_promoteCandidateAndRevokeActive_CanOnlySelfCall() public { vm.stopPrank(); vm.expectRevert(CCIPHome.CanOnlySelfCall.selector); diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.revokeCandidate.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.revokeCandidate.t.sol index b2793727d59..719b8989b1c 100644 --- a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.revokeCandidate.t.sol +++ b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.revokeCandidate.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {CCIPHome} from "../../../capability/CCIPHome.sol"; import {Internal} from "../../../libraries/Internal.sol"; @@ -18,7 +18,7 @@ contract CCIPHome_revokeCandidate is CCIPHomeTestSetup { s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, ZERO_DIGEST); } - function test_revokeCandidate_success() public { + function test_revokeCandidate() public { (bytes32 priorActiveDigest, bytes32 priorCandidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); @@ -42,7 +42,7 @@ contract CCIPHome_revokeCandidate is CCIPHomeTestSetup { assertTrue(candidateDigest != priorCandidateDigest); } - function test_revokeCandidate_ConfigDigestMismatch_reverts() public { + function test_RevertWhen_revokeCandidate_ConfigDigestMismatch() public { (, bytes32 priorCandidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); bytes32 wrongDigest = keccak256("wrong_digest"); @@ -50,12 +50,12 @@ contract CCIPHome_revokeCandidate is CCIPHomeTestSetup { s_ccipHome.revokeCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, wrongDigest); } - function test_revokeCandidate_RevokingZeroDigestNotAllowed_reverts() public { + function test_RevertWhen_revokeCandidate_RevokingZeroDigestNotAllowed() public { vm.expectRevert(CCIPHome.RevokingZeroDigestNotAllowed.selector); s_ccipHome.revokeCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, ZERO_DIGEST); } - function test_revokeCandidate_CanOnlySelfCall_reverts() public { + function test_RevertWhen_revokeCandidate_CanOnlySelfCall() public { vm.startPrank(address(0)); vm.expectRevert(CCIPHome.CanOnlySelfCall.selector); diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.setCandidate.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.setCandidate.t.sol index 49f365b22cd..be0ae1df243 100644 --- a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.setCandidate.t.sol +++ b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.setCandidate.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {CCIPHome} from "../../../capability/CCIPHome.sol"; import {Internal} from "../../../libraries/Internal.sol"; @@ -7,7 +7,7 @@ import {Internal} from "../../../libraries/Internal.sol"; import {CCIPHomeTestSetup} from "./CCIPHomeTestSetup.t.sol"; contract CCIPHome_setCandidate is CCIPHomeTestSetup { - function test_setCandidate_success() public { + function test_setCandidate() public { CCIPHome.OCR3Config memory config = _getBaseConfig(Internal.OCRPluginType.Commit); CCIPHome.VersionedConfig memory versionedConfig = CCIPHome.VersionedConfig({version: 1, config: config, configDigest: ZERO_DIGEST}); @@ -28,7 +28,7 @@ contract CCIPHome_setCandidate is CCIPHomeTestSetup { assertEq(keccak256(abi.encode(storedVersionedConfig.config)), keccak256(abi.encode(versionedConfig.config))); } - function test_setCandidate_ConfigDigestMismatch_reverts() public { + function test_RevertWhen_setCandidate_ConfigDigestMismatch() public { CCIPHome.OCR3Config memory config = _getBaseConfig(Internal.OCRPluginType.Commit); bytes32 digest = s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, ZERO_DIGEST); @@ -42,7 +42,7 @@ contract CCIPHome_setCandidate is CCIPHomeTestSetup { s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, digest); } - function test_setCandidate_CanOnlySelfCall_reverts() public { + function test_RevertWhen_setCandidate_CanOnlySelfCall() public { vm.stopPrank(); vm.expectRevert(CCIPHome.CanOnlySelfCall.selector); diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.supportsInterface.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.supportsInterface.t.sol index c67f007f735..88cefdadb66 100644 --- a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.supportsInterface.t.sol +++ b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.supportsInterface.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {ICapabilityConfiguration} from "../../../../keystone/interfaces/ICapabilityConfiguration.sol"; @@ -7,7 +7,7 @@ import {IERC165} from "../../../../vendor/openzeppelin-solidity/v5.0.2/contracts import {CCIPHomeTestSetup} from "./CCIPHomeTestSetup.t.sol"; contract CCIPHome_supportsInterface is CCIPHomeTestSetup { - function test_supportsInterface_success() public view { + function test_supportsInterface() public view { assertTrue(s_ccipHome.supportsInterface(type(IERC165).interfaceId)); assertTrue(s_ccipHome.supportsInterface(type(ICapabilityConfiguration).interfaceId)); } diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.validateConfig.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.validateConfig.t.sol index 13c1a0610d7..4591e9b37bc 100644 --- a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.validateConfig.t.sol +++ b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.validateConfig.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {INodeInfoProvider} from "../../../../keystone/interfaces/INodeInfoProvider.sol"; @@ -96,11 +96,11 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { // Successes. - function test__validateConfig_Success() public { + function test__validateConfig() public { s_ccipHome.validateConfig(_getCorrectOCR3Config()); } - function test__validateConfigLessTransmittersThanSigners_Success() public { + function test__validateConfigLessTransmittersThanSigners() public { // fChain is 1, so there should be at least 4 transmitters. CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(5, 1); config.nodes[1].transmitterKey = bytes(""); @@ -108,7 +108,7 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { s_ccipHome.validateConfig(config); } - function test__validateConfigSmallerFChain_Success() public { + function test__validateConfigSmallerFChain() public { CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(11, 3); // Set fChain to 2 @@ -119,7 +119,7 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { // Reverts - function test__validateConfig_ChainSelectorNotSet_Reverts() public { + function test_RevertWhen__validateConfig_ChainSelectorNotSet() public { CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); config.chainSelector = 0; // invalid @@ -127,7 +127,7 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { s_ccipHome.validateConfig(config); } - function test__validateConfig_OfframpAddressCannotBeZero_Reverts() public { + function test_RevertWhen__validateConfig_OfframpAddressCannotBeZero() public { CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); config.offrampAddress = ""; // invalid @@ -135,7 +135,7 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { s_ccipHome.validateConfig(config); } - function test__validateConfig_ABIEncodedAddress_OfframpAddressCannotBeZero_Reverts() public { + function test_RevertWhen__validateConfig_ABIEncodedAddress_OfframpAddressCannotBeZero() public { CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); config.offrampAddress = abi.encode(address(0)); // invalid @@ -143,7 +143,7 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { s_ccipHome.validateConfig(config); } - function test__validateConfig_RMNHomeAddressCannotBeZero_Reverts() public { + function test_RevertWhen__validateConfig_RMNHomeAddressCannotBeZero() public { CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); config.rmnHomeAddress = ""; // invalid @@ -151,7 +151,7 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { s_ccipHome.validateConfig(config); } - function test__validateConfig_ABIEncodedAddress_RMNHomeAddressCannotBeZero_Reverts() public { + function test_RevertWhen__validateConfig_ABIEncodedAddress_RMNHomeAddressCannotBeZero() public { CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); config.rmnHomeAddress = abi.encode(address(0)); // invalid @@ -159,7 +159,7 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { s_ccipHome.validateConfig(config); } - function test__validateConfig_ChainSelectorNotFound_Reverts() public { + function test_RevertWhen__validateConfig_ChainSelectorNotFound() public { CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); config.chainSelector = 2; // not set @@ -167,7 +167,7 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { s_ccipHome.validateConfig(config); } - function test__validateConfig_NotEnoughTransmitters_Reverts() public { + function test_RevertWhen__validateConfig_NotEnoughTransmitters() public { CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); uint256 numberOfTransmitters = 3; @@ -185,7 +185,7 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { s_ccipHome.validateConfig(config); } - function test__validateConfig_NotEnoughTransmittersEmptyAddresses_Reverts() public { + function test_RevertWhen__validateConfig_NotEnoughTransmittersEmptyAddresses() public { CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); config.nodes[0].transmitterKey = bytes(""); @@ -201,7 +201,7 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { s_ccipHome.validateConfig(config); } - function test__validateConfig_TooManySigners_Reverts() public { + function test_RevertWhen__validateConfig_TooManySigners() public { CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); config.nodes = new CCIPHome.OCR3Node[](257); @@ -209,7 +209,7 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { s_ccipHome.validateConfig(config); } - function test__validateConfig_FChainTooHigh_Reverts() public { + function test_RevertWhen__validateConfig_FChainTooHigh() public { CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); config.FRoleDON = 2; // too low @@ -220,7 +220,7 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { s_ccipHome.validateConfig(config); } - function test__validateConfig_FMustBePositive_Reverts() public { + function test_RevertWhen__validateConfig_FMustBePositive() public { CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); config.FRoleDON = 0; // not positive @@ -228,7 +228,7 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { s_ccipHome.validateConfig(config); } - function test__validateConfig_FTooHigh_Reverts() public { + function test_RevertWhen__validateConfig_FTooHigh() public { CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); config.FRoleDON = 2; // too high @@ -236,7 +236,7 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { s_ccipHome.validateConfig(config); } - function test__validateConfig_ZeroP2PId_Reverts() public { + function test_RevertWhen__validateConfig_ZeroP2PId() public { CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); config.nodes[1].p2pId = bytes32(0); @@ -244,7 +244,7 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { s_ccipHome.validateConfig(config); } - function test__validateConfig_ZeroSignerKey_Reverts() public { + function test_RevertWhen__validateConfig_ZeroSignerKey() public { CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); config.nodes[2].signerKey = bytes(""); diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHomeTestSetup.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHomeTestSetup.t.sol index a06f50a01cf..33012aa71eb 100644 --- a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHomeTestSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHomeTestSetup.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {INodeInfoProvider} from "../../../../keystone/interfaces/INodeInfoProvider.sol"; diff --git a/contracts/src/v0.8/ccip/test/e2e/End2End.t.sol b/contracts/src/v0.8/ccip/test/e2e/End2End.t.sol index 282784755dd..9851f09e9a5 100644 --- a/contracts/src/v0.8/ccip/test/e2e/End2End.t.sol +++ b/contracts/src/v0.8/ccip/test/e2e/End2End.t.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; -import {IRMN} from "../../interfaces/IRMN.sol"; import {IRMNRemote} from "../../interfaces/IRMNRemote.sol"; import {AuthorizedCallers} from "../../../shared/access/AuthorizedCallers.sol"; @@ -45,7 +44,7 @@ contract E2E is OnRampSetup, OffRampSetup { OffRampSetup.setUp(); // Deploy new source router for the new source chain - s_sourceRouter2 = new Router(s_sourceRouter.getWrappedNative(), address(s_mockRMN)); + s_sourceRouter2 = new Router(s_sourceRouter.getWrappedNative(), address(s_mockRMNRemote)); // Deploy new TokenAdminRegistry for the new source chain s_tokenAdminRegistry2 = new TokenAdminRegistry(); @@ -55,7 +54,12 @@ contract E2E is OnRampSetup, OffRampSetup { address token = s_sourceTokens[i]; address pool = address( new LockReleaseTokenPool( - IERC20(token), DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), true, address(s_sourceRouter2) + IERC20(token), + DEFAULT_TOKEN_DECIMALS, + new address[](0), + address(s_mockRMNRemote), + true, + address(s_sourceRouter2) ) ); @@ -78,7 +82,7 @@ contract E2E is OnRampSetup, OffRampSetup { s_nonceManager2 = new NonceManager(new address[](0)); ( - // Deploy the new source chain onramp + // Deploy the new source chain onRamp // Outsource to shared helper function with OnRampSetup s_onRamp2, s_metadataHash2 @@ -97,10 +101,10 @@ contract E2E is OnRampSetup, OffRampSetup { onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: address(s_onRamp2)}); s_sourceRouter2.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), new Router.OffRamp[](0)); - // Deploy offramp + // Deploy offRamp _deployOffRamp(s_mockRMNRemote, s_inboundNonceManager); - // Enable source chains on offramp + // Enable source chains on offRamp OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](2); sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ router: s_destRouter, @@ -162,7 +166,7 @@ contract E2E is OnRampSetup, OffRampSetup { merkleRoots[0] = MerkleHelper.getMerkleRoot(hashedMessages1); merkleRoots[1] = MerkleHelper.getMerkleRoot(hashedMessages2); - // TODO make these real sigs :) + // TODO make these real sigs IRMNRemote.Signature[] memory rmnSignatures = new IRMNRemote.Signature[](0); Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](2); @@ -191,9 +195,6 @@ contract E2E is OnRampSetup, OffRampSetup { // Scoped to RMN and verify to reduce stack pressure { - s_mockRMN.setTaggedRootBlessed(IRMN.TaggedRoot({commitStore: address(s_offRamp), root: merkleRoots[0]}), true); - s_mockRMN.setTaggedRootBlessed(IRMN.TaggedRoot({commitStore: address(s_offRamp), root: merkleRoots[1]}), true); - bytes32[] memory proofs = new bytes32[](0); bytes32[] memory hashedLeaves = new bytes32[](1); hashedLeaves[0] = merkleRoots[0]; @@ -264,16 +265,7 @@ contract E2E is OnRampSetup, OffRampSetup { message.receiver = abi.encode(address(s_receiver)); Internal.EVM2AnyRampMessage memory msgEvent = _messageToEvent( - message, - sourceChainSelector, - DEST_CHAIN_SELECTOR, - expectedSeqNum, - nonce, - feeAmount, - feeAmount, - OWNER, - metadataHash, - tokenAdminRegistry + message, sourceChainSelector, expectedSeqNum, nonce, feeAmount, feeAmount, OWNER, metadataHash, tokenAdminRegistry ); vm.expectEmit(); diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyDestChainConfigUpdates.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyDestChainConfigUpdates.t.sol index b663151a96c..242b513cf5a 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyDestChainConfigUpdates.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyDestChainConfigUpdates.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {FeeQuoter} from "../../FeeQuoter.sol"; import {Internal} from "../../libraries/Internal.sol"; @@ -38,7 +38,7 @@ contract FeeQuoter_applyDestChainConfigUpdates is FeeQuoterSetup { ); } - function test_applyDestChainConfigUpdates_Success() public { + function test_applyDestChainConfigUpdates() public { FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = new FeeQuoter.DestChainConfigArgs[](2); destChainConfigArgs[0] = _generateFeeQuoterDestChainConfigArgs()[0]; destChainConfigArgs[0].destChainConfig.isEnabled = false; @@ -61,7 +61,7 @@ contract FeeQuoter_applyDestChainConfigUpdates is FeeQuoterSetup { _assertFeeQuoterDestChainConfigsEqual(destChainConfigArgs[1].destChainConfig, gotDestChainConfig1); } - function test_applyDestChainConfigUpdatesZeroInput_Success() public { + function test_applyDestChainConfigUpdatesZeroInput() public { FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = new FeeQuoter.DestChainConfigArgs[](0); vm.recordLogs(); @@ -72,7 +72,7 @@ contract FeeQuoter_applyDestChainConfigUpdates is FeeQuoterSetup { // Reverts - function test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() public { + function test_RevertWhen_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero() public { FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); FeeQuoter.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; @@ -83,7 +83,7 @@ contract FeeQuoter_applyDestChainConfigUpdates is FeeQuoterSetup { s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); } - function test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() public { + function test_RevertWhen_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit() public { FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); FeeQuoter.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; @@ -99,7 +99,7 @@ contract FeeQuoter_applyDestChainConfigUpdates is FeeQuoterSetup { s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); } - function test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() public { + function test_RevertWhen_InvalidDestChainConfigDestChainSelectorEqZero() public { FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); FeeQuoter.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; @@ -109,16 +109,4 @@ contract FeeQuoter_applyDestChainConfigUpdates is FeeQuoterSetup { ); s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); } - - function test_InvalidChainFamilySelector_Revert() public { - FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); - FeeQuoter.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; - - destChainConfigArg.destChainConfig.chainFamilySelector = bytes4(uint32(1)); - - vm.expectRevert( - abi.encodeWithSelector(FeeQuoter.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) - ); - s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); - } } diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyFeeTokensUpdates.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyFeeTokensUpdates.t.sol index a32e50bb3e4..b2412df3d6b 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyFeeTokensUpdates.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyFeeTokensUpdates.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Ownable2Step} from "../../../shared/access/Ownable2Step.sol"; import {FeeQuoter} from "../../FeeQuoter.sol"; import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; contract FeeQuoter_applyFeeTokensUpdates is FeeQuoterSetup { - function test_ApplyFeeTokensUpdates_Success() public { + function test_ApplyFeeTokensUpdates() public { address[] memory feeTokens = new address[](1); feeTokens[0] = s_sourceTokens[1]; @@ -48,7 +48,7 @@ contract FeeQuoter_applyFeeTokensUpdates is FeeQuoterSetup { s_feeQuoter.applyFeeTokensUpdates(feeTokens, feeTokens); } - function test_OnlyCallableByOwner_Revert() public { + function test_RevertWhen_OnlyCallableByOwner() public { vm.startPrank(STRANGER); vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyPremiumMultiplierWeiPerEthUpdates.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyPremiumMultiplierWeiPerEthUpdates.t.sol index 67b1ed9ae92..3eaa8436932 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyPremiumMultiplierWeiPerEthUpdates.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyPremiumMultiplierWeiPerEthUpdates.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Ownable2Step} from "../../../shared/access/Ownable2Step.sol"; import {FeeQuoter} from "../../FeeQuoter.sol"; @@ -26,7 +26,7 @@ contract FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates is FeeQuoterSetup { ); } - function test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() public { + function test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken() public { FeeQuoter.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs = new FeeQuoter.PremiumMultiplierWeiPerEthArgs[](1); premiumMultiplierWeiPerEthArgs[0] = s_feeQuoterPremiumMultiplierWeiPerEthArgs[0]; @@ -45,7 +45,7 @@ contract FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates is FeeQuoterSetup { ); } - function test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() public { + function test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens() public { FeeQuoter.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs = new FeeQuoter.PremiumMultiplierWeiPerEthArgs[](2); premiumMultiplierWeiPerEthArgs[0] = s_feeQuoterPremiumMultiplierWeiPerEthArgs[0]; @@ -82,7 +82,7 @@ contract FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates is FeeQuoterSetup { // Reverts - function test_OnlyCallableByOwnerOrAdmin_Revert() public { + function test_RevertWhen_OnlyCallableByOwnerOrAdmin() public { FeeQuoter.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs; vm.startPrank(STRANGER); diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyTokenTransferFeeConfigUpdates.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyTokenTransferFeeConfigUpdates.t.sol index 711374a2441..2acdd1ed0d0 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyTokenTransferFeeConfigUpdates.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyTokenTransferFeeConfigUpdates.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Ownable2Step} from "../../../shared/access/Ownable2Step.sol"; import {FeeQuoter} from "../../FeeQuoter.sol"; @@ -59,7 +59,7 @@ contract FeeQuoter_applyTokenTransferFeeConfigUpdates is FeeQuoterSetup { } } - function test_ApplyTokenTransferFeeConfig_Success() public { + function test_ApplyTokenTransferFeeConfig() public { FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(1, 2); tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = address(5); @@ -152,7 +152,7 @@ contract FeeQuoter_applyTokenTransferFeeConfigUpdates is FeeQuoterSetup { // Reverts - function test_OnlyCallableByOwnerOrAdmin_Revert() public { + function test_RevertWhen_OnlyCallableByOwnerOrAdmin() public { vm.startPrank(STRANGER); FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs; @@ -163,7 +163,7 @@ contract FeeQuoter_applyTokenTransferFeeConfigUpdates is FeeQuoterSetup { ); } - function test_InvalidDestBytesOverhead_Revert() public { + function test_RevertWhen_InvalidDestBytesOverhead() public { FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(1, 1); tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = address(5); diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.constructor.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.constructor.t.sol index c2d36bee96d..e77e52dd25e 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.constructor.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.constructor.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {FeeQuoter} from "../../FeeQuoter.sol"; import {FeeQuoterHelper} from "../helpers/FeeQuoterHelper.sol"; import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; contract FeeQuoter_constructor is FeeQuoterSetup { - function test_Setup_Success() public virtual { + function test_Setup() public virtual { address[] memory priceUpdaters = new address[](2); priceUpdaters[0] = STRANGER; priceUpdaters[1] = OWNER; @@ -78,7 +78,7 @@ contract FeeQuoter_constructor is FeeQuoterSetup { } } - function test_InvalidStalenessThreshold_Revert() public { + function test_RevertWhen_InvalidStalenessThreshold() public { FeeQuoter.StaticConfig memory staticConfig = FeeQuoter.StaticConfig({ linkToken: s_sourceTokens[0], maxFeeJuelsPerMsg: MAX_MSG_FEES_JUELS, @@ -98,7 +98,7 @@ contract FeeQuoter_constructor is FeeQuoterSetup { ); } - function test_InvalidLinkTokenEqZeroAddress_Revert() public { + function test_RevertWhen_InvalidLinkTokenEqZeroAddress() public { FeeQuoter.StaticConfig memory staticConfig = FeeQuoter.StaticConfig({ linkToken: address(0), maxFeeJuelsPerMsg: MAX_MSG_FEES_JUELS, @@ -118,7 +118,7 @@ contract FeeQuoter_constructor is FeeQuoterSetup { ); } - function test_InvalidMaxFeeJuelsPerMsg_Revert() public { + function test_RevertWhen_InvalidMaxFeeJuelsPerMsg() public { FeeQuoter.StaticConfig memory staticConfig = FeeQuoter.StaticConfig({ linkToken: s_sourceTokens[0], maxFeeJuelsPerMsg: 0, diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.convertTokenAmount.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.convertTokenAmount.t.sol index 33e941cfbe3..2d6864b4957 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.convertTokenAmount.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.convertTokenAmount.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {FeeQuoter} from "../../FeeQuoter.sol"; import {Internal} from "../../libraries/Internal.sol"; import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; contract FeeQuoter_convertTokenAmount is FeeQuoterSetup { - function test_ConvertTokenAmount_Success() public view { + function test_ConvertTokenAmount() public view { Internal.PriceUpdates memory initialPriceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); uint256 amount = 3e16; uint256 conversionRate = (uint256(initialPriceUpdates.tokenPriceUpdates[2].usdPerToken) * 1e18) @@ -50,7 +50,7 @@ contract FeeQuoter_convertTokenAmount is FeeQuoterSetup { // Reverts - function test_LinkTokenNotSupported_Revert() public { + function test_RevertWhen_LinkTokenNotSupported() public { vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, DUMMY_CONTRACT_ADDRESS)); s_feeQuoter.convertTokenAmount(DUMMY_CONTRACT_ADDRESS, 3e16, s_sourceTokens[0]); diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getDataAvailabilityCost.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getDataAvailabilityCost.t.sol index 6f2566ac754..1d28e8ed756 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getDataAvailabilityCost.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getDataAvailabilityCost.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {FeeQuoter} from "../../FeeQuoter.sol"; import {Internal} from "../../libraries/Internal.sol"; import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; contract FeeQuoter_getDataAvailabilityCost is FeeQuoterSetup { - function test_EmptyMessageCalculatesDataAvailabilityCost_Success() public { + function test_EmptyMessageCalculatesDataAvailabilityCost() public { uint256 dataAvailabilityCostUSD = s_feeQuoter.getDataAvailabilityCost(DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, 0, 0, 0); @@ -42,7 +42,7 @@ contract FeeQuoter_getDataAvailabilityCost is FeeQuoterSetup { assertFalse(dataAvailabilityCostUSD == dataAvailabilityCostUSD2); } - function test_SimpleMessageCalculatesDataAvailabilityCost_Success() public view { + function test_SimpleMessageCalculatesDataAvailabilityCost() public view { uint256 dataAvailabilityCostUSD = s_feeQuoter.getDataAvailabilityCost(DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, 100, 5, 50); @@ -58,7 +58,7 @@ contract FeeQuoter_getDataAvailabilityCost is FeeQuoterSetup { assertEq(expectedDataAvailabilityCostUSD, dataAvailabilityCostUSD); } - function test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() public view { + function test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector() public view { uint256 dataAvailabilityCostUSD = s_feeQuoter.getDataAvailabilityCost(0, USD_PER_DATA_AVAILABILITY_GAS, 100, 5, 50); assertEq(dataAvailabilityCostUSD, 0); diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenAndGasPrices.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenAndGasPrices.t.sol index 18ccf5efa79..d7919293759 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenAndGasPrices.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenAndGasPrices.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {FeeQuoter} from "../../FeeQuoter.sol"; import {Internal} from "../../libraries/Internal.sol"; import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; contract FeeQuoter_getTokenAndGasPrices is FeeQuoterSetup { - function test_GetFeeTokenAndGasPrices_Success() public view { + function test_GetFeeTokenAndGasPrices() public view { (uint224 feeTokenPrice, uint224 gasPrice) = s_feeQuoter.getTokenAndGasPrices(s_sourceFeeToken, DEST_CHAIN_SELECTOR); Internal.PriceUpdates memory priceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); @@ -15,7 +15,7 @@ contract FeeQuoter_getTokenAndGasPrices is FeeQuoterSetup { assertEq(gasPrice, priceUpdates.gasPriceUpdates[0].usdPerUnitGas); } - function test_StalenessCheckDisabled_Success() public { + function test_StalenessCheckDisabled() public { uint64 neverStaleChainSelector = 345678; FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); destChainConfigArgs[0].destChainSelector = neverStaleChainSelector; @@ -38,7 +38,7 @@ contract FeeQuoter_getTokenAndGasPrices is FeeQuoterSetup { assertEq(gasPrice, 999); } - function test_ZeroGasPrice_Success() public { + function test_ZeroGasPrice() public { uint64 zeroGasDestChainSelector = 345678; FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); destChainConfigArgs[0].destChainSelector = zeroGasDestChainSelector; @@ -56,12 +56,12 @@ contract FeeQuoter_getTokenAndGasPrices is FeeQuoterSetup { assertEq(gasPrice, 0); } - function test_UnsupportedChain_Revert() public { + function test_RevertWhen_UnsupportedChain() public { vm.expectRevert(abi.encodeWithSelector(FeeQuoter.DestinationChainNotEnabled.selector, DEST_CHAIN_SELECTOR + 1)); s_feeQuoter.getTokenAndGasPrices(s_sourceTokens[0], DEST_CHAIN_SELECTOR + 1); } - function test_StaleGasPrice_Revert() public { + function test_RevertWhen_StaleGasPrice() public { uint256 diff = TWELVE_HOURS + 1; vm.warp(block.timestamp + diff); vm.expectRevert(abi.encodeWithSelector(FeeQuoter.StaleGasPrice.selector, DEST_CHAIN_SELECTOR, TWELVE_HOURS, diff)); diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenPrice.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenPrice.t.sol index c00e750d27f..a0f0a1076d8 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenPrice.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenPrice.t.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; -import {MockV3Aggregator} from "../../../tests/MockV3Aggregator.sol"; +import {MockV3Aggregator} from "../../../shared/mocks/MockV3Aggregator.sol"; import {FeeQuoter} from "../../FeeQuoter.sol"; import {Internal} from "../../libraries/Internal.sol"; import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; contract FeeQuoter_getTokenPrice is FeeQuoterSetup { - function test_GetTokenPriceFromFeed_Success() public { - uint256 originalTimestampValue = block.timestamp; + function test_GetTokenPriceFromFeed() public { + uint32 originalTimestampValue = uint32(block.timestamp); // Above staleness threshold vm.warp(originalTimestampValue + s_feeQuoter.getStaticConfig().tokenPriceStalenessThreshold + 1); @@ -24,16 +24,16 @@ contract FeeQuoter_getTokenPrice is FeeQuoterSetup { assertEq(tokenPriceAnswer.timestamp, uint32(originalTimestampValue)); } - function test_GetTokenPrice_LocalMoreRecent_Success() public { - uint256 originalTimestampValue = block.timestamp; + function test_GetTokenPrice_LocalMoreRecent() public { + uint32 originalTimestampValue = uint32(block.timestamp); + uint224 usdPerToken = 1e18; Internal.PriceUpdates memory update = Internal.PriceUpdates({ tokenPriceUpdates: new Internal.TokenPriceUpdate[](1), gasPriceUpdates: new Internal.GasPriceUpdate[](0) }); - update.tokenPriceUpdates[0] = - Internal.TokenPriceUpdate({sourceToken: s_sourceTokens[0], usdPerToken: uint32(originalTimestampValue + 5)}); + update.tokenPriceUpdates[0] = Internal.TokenPriceUpdate({sourceToken: s_sourceTokens[0], usdPerToken: usdPerToken}); vm.expectEmit(); emit FeeQuoter.UsdPerTokenUpdated( @@ -48,6 +48,6 @@ contract FeeQuoter_getTokenPrice is FeeQuoterSetup { //Assert that the returned price is the local price, not the oracle price assertEq(tokenPriceAnswer.value, update.tokenPriceUpdates[0].usdPerToken); - assertEq(tokenPriceAnswer.timestamp, uint32(originalTimestampValue)); + assertEq(tokenPriceAnswer.timestamp, originalTimestampValue); } } diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenPrices.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenPrices.t.sol index 63f936332fd..89edbddee38 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenPrices.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenPrices.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Internal} from "../../libraries/Internal.sol"; import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; contract FeeQuoter_getTokenPrices is FeeQuoterSetup { - function test_GetTokenPrices_Success() public view { + function test_GetTokenPrices() public view { Internal.PriceUpdates memory priceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); address[] memory tokens = new address[](3); diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenTransferCost.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenTransferCost.t.sol index 9f0aa9440b8..76298b7c838 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenTransferCost.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenTransferCost.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {FeeQuoter} from "../../FeeQuoter.sol"; import {Client} from "../../libraries/Client.sol"; @@ -12,7 +12,7 @@ contract FeeQuoter_getTokenTransferCost is FeeQuoterFeeSetup { address internal s_selfServeTokenDefaultPricing = makeAddr("self-serve-token-default-pricing"); - function test_NoTokenTransferChargesZeroFee_Success() public view { + function test_NoTokenTransferChargesZeroFee() public view { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); @@ -22,7 +22,7 @@ contract FeeQuoter_getTokenTransferCost is FeeQuoterFeeSetup { assertEq(0, destBytesOverhead); } - function test_getTokenTransferCost_selfServeUsesDefaults_Success() public view { + function test_getTokenTransferCost_selfServeUsesDefaults() public view { Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_selfServeTokenDefaultPricing, 1000); // Get config to assert it isn't set @@ -40,7 +40,7 @@ contract FeeQuoter_getTokenTransferCost is FeeQuoterFeeSetup { assertEq(DEFAULT_TOKEN_BYTES_OVERHEAD, destBytesOverhead); } - function test_SmallTokenTransferChargesMinFeeAndGas_Success() public view { + function test_SmallTokenTransferChargesMinFeeAndGas() public view { Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 1000); FeeQuoter.TokenTransferFeeConfig memory transferFeeConfig = s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); @@ -53,7 +53,7 @@ contract FeeQuoter_getTokenTransferCost is FeeQuoterFeeSetup { assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); } - function test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() public view { + function test_ZeroAmountTokenTransferChargesMinFeeAndGas() public view { Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 0); FeeQuoter.TokenTransferFeeConfig memory transferFeeConfig = s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); @@ -66,7 +66,7 @@ contract FeeQuoter_getTokenTransferCost is FeeQuoterFeeSetup { assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); } - function test_LargeTokenTransferChargesMaxFeeAndGas_Success() public view { + function test_LargeTokenTransferChargesMaxFeeAndGas() public view { Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 1e36); FeeQuoter.TokenTransferFeeConfig memory transferFeeConfig = s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); @@ -79,7 +79,7 @@ contract FeeQuoter_getTokenTransferCost is FeeQuoterFeeSetup { assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); } - function test_FeeTokenBpsFee_Success() public view { + function test_FeeTokenBpsFee() public view { uint256 tokenAmount = 10000e18; Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, tokenAmount); @@ -99,7 +99,7 @@ contract FeeQuoter_getTokenTransferCost is FeeQuoterFeeSetup { assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); } - function test_CustomTokenBpsFee_Success() public view { + function test_CustomTokenBpsFee() public view { uint256 tokenAmount = 200000e18; Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ @@ -127,7 +127,7 @@ contract FeeQuoter_getTokenTransferCost is FeeQuoterFeeSetup { assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); } - function test_ZeroFeeConfigChargesMinFee_Success() public { + function test_ZeroFeeConfigChargesMinFee() public { FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(1, 1); tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = s_sourceFeeToken; @@ -185,7 +185,7 @@ contract FeeQuoter_getTokenTransferCost is FeeQuoterFeeSetup { assertEq(bytesOverheadMultiple, bytesOverheadSingle * transfers); } - function test_MixedTokenTransferFee_Success() public view { + function test_MixedTokenTransferFee() public view { address[3] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative(), CUSTOM_TOKEN]; uint224[3] memory tokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice, CUSTOM_TOKEN_PRICE]; FeeQuoter.TokenTransferFeeConfig[3] memory tokenTransferFeeConfigs = [ diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getValidatedFee.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getValidatedFee.t.sol index 1f76f3120ae..67ff5ae4ede 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getValidatedFee.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getValidatedFee.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {FeeQuoter} from "../../FeeQuoter.sol"; import {Client} from "../../libraries/Client.sol"; @@ -11,7 +11,7 @@ import {FeeQuoterFeeSetup} from "./FeeQuoterSetup.t.sol"; contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { using USDPriceWith18Decimals for uint224; - function test_EmptyMessage_Success() public view { + function test_EmptyMessage() public view { address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; @@ -24,8 +24,8 @@ contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { uint256 feeAmount = s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); uint256 gasUsed = GAS_LIMIT + DEST_GAS_OVERHEAD; - uint256 gasFeeUSD = (gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS); - uint256 messageFeeUSD = (_configUSDCentToWei(destChainConfig.networkFeeUSDCents) * premiumMultiplierWeiPerEth); + uint256 gasFeeUSD = gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS; + uint256 messageFeeUSD = _configUSDCentToWei(destChainConfig.networkFeeUSDCents) * premiumMultiplierWeiPerEth; uint256 dataAvailabilityFeeUSD = s_feeQuoter.getDataAvailabilityCost( DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, message.data.length, message.tokenAmounts.length, 0 ); @@ -35,7 +35,7 @@ contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { } } - function test_ZeroDataAvailabilityMultiplier_Success() public { + function test_ZeroDataAvailabilityMultiplier() public { FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = new FeeQuoter.DestChainConfigArgs[](1); FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); destChainConfigArgs[0] = @@ -49,14 +49,14 @@ contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { uint256 feeAmount = s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); uint256 gasUsed = GAS_LIMIT + DEST_GAS_OVERHEAD; - uint256 gasFeeUSD = (gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS); - uint256 messageFeeUSD = (_configUSDCentToWei(destChainConfig.networkFeeUSDCents) * premiumMultiplierWeiPerEth); + uint256 gasFeeUSD = gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS; + uint256 messageFeeUSD = _configUSDCentToWei(destChainConfig.networkFeeUSDCents) * premiumMultiplierWeiPerEth; uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD) / s_feeTokenPrice; assertEq(totalPriceInFeeToken, feeAmount); } - function test_HighGasMessage_Success() public view { + function test_HighGasMessage() public view { address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; @@ -75,9 +75,13 @@ contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); uint256 feeAmount = s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); - uint256 gasUsed = customGasLimit + DEST_GAS_OVERHEAD + customDataSize * DEST_GAS_PER_PAYLOAD_BYTE; - uint256 gasFeeUSD = (gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS); - uint256 messageFeeUSD = (_configUSDCentToWei(destChainConfig.networkFeeUSDCents) * premiumMultiplierWeiPerEth); + + uint256 callDataCostHigh = (customDataSize - DEST_GAS_PER_PAYLOAD_BYTE_THRESHOLD) * DEST_GAS_PER_PAYLOAD_BYTE_HIGH + + DEST_GAS_PER_PAYLOAD_BYTE_THRESHOLD * DEST_GAS_PER_PAYLOAD_BYTE_BASE; + + uint256 gasUsed = customGasLimit + DEST_GAS_OVERHEAD + callDataCostHigh; + uint256 gasFeeUSD = gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS; + uint256 messageFeeUSD = _configUSDCentToWei(destChainConfig.networkFeeUSDCents) * premiumMultiplierWeiPerEth; uint256 dataAvailabilityFeeUSD = s_feeQuoter.getDataAvailabilityCost( DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, message.data.length, message.tokenAmounts.length, 0 ); @@ -87,7 +91,7 @@ contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { } } - function test_SingleTokenMessage_Success() public view { + function test_SingleTokenMessage() public view { address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; @@ -103,12 +107,12 @@ contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { uint256 feeAmount = s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); - uint256 gasUsed = GAS_LIMIT + DEST_GAS_OVERHEAD + uint256 gasUsed = GAS_LIMIT + DEST_GAS_OVERHEAD + tokenBytesOverhead * DEST_GAS_PER_PAYLOAD_BYTE_BASE + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token).destGasOverhead; - uint256 gasFeeUSD = (gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS); + uint256 gasFeeUSD = gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS; (uint256 transferFeeUSD,,) = s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, feeTokenPrices[i], message.tokenAmounts); - uint256 messageFeeUSD = (transferFeeUSD * s_feeQuoter.getPremiumMultiplierWeiPerEth(message.feeToken)); + uint256 messageFeeUSD = transferFeeUSD * s_feeQuoter.getPremiumMultiplierWeiPerEth(message.feeToken); uint256 dataAvailabilityFeeUSD = s_feeQuoter.getDataAvailabilityCost( DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, @@ -122,7 +126,7 @@ contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { } } - function test_MessageWithDataAndTokenTransfer_Success() public view { + function test_MessageWithDataAndTokenTransfer() public view { address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; @@ -152,12 +156,20 @@ contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { tokenBytesOverhead += destBytesOverhead == 0 ? uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) : destBytesOverhead; } - uint256 gasUsed = - customGasLimit + DEST_GAS_OVERHEAD + message.data.length * DEST_GAS_PER_PAYLOAD_BYTE + tokenGasOverhead; - uint256 gasFeeUSD = (gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS); - (uint256 transferFeeUSD,,) = + (uint256 transferFeeUSD,, uint256 tokenTransferBytesOverhead) = s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, feeTokenPrices[i], message.tokenAmounts); - uint256 messageFeeUSD = (transferFeeUSD * premiumMultiplierWeiPerEth); + + uint256 gasFeeUSD; + + { + uint256 gasUsed = customGasLimit + DEST_GAS_OVERHEAD + + (message.data.length + tokenTransferBytesOverhead) * DEST_GAS_PER_PAYLOAD_BYTE_BASE + tokenGasOverhead; + + gasFeeUSD = gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS; + } + + uint256 messageFeeUSD = transferFeeUSD * premiumMultiplierWeiPerEth; + uint256 dataAvailabilityFeeUSD = s_feeQuoter.getDataAvailabilityCost( DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, @@ -193,14 +205,25 @@ contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); } - // Reverts + function test_SolChainFamilySelector() public { + // Update config to enforce allowOutOfOrderExecution = true. + vm.stopPrank(); + vm.startPrank(OWNER); + + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); + destChainConfigArgs[0].destChainConfig.chainFamilySelector = Internal.CHAIN_FAMILY_SELECTOR_SVM; - function test_DestinationChainNotEnabled_Revert() public { - vm.expectRevert(abi.encodeWithSelector(FeeQuoter.DestinationChainNotEnabled.selector, DEST_CHAIN_SELECTOR + 1)); - s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR + 1, _generateEmptyMessage()); + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + vm.stopPrank(); + + Client.EVM2AnyMessage memory message = _generateEmptyMessage2SVM(); + + s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); } - function test_EnforceOutOfOrder_Revert() public { + // Reverts + + function test_RevertWhen_EnforceOutOfOrder() public { // Update config to enforce allowOutOfOrderExecution = true. vm.stopPrank(); vm.startPrank(OWNER); @@ -218,7 +241,7 @@ contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); } - function test_MessageTooLarge_Revert() public { + function test_RevertWhen_MessageTooLarge() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.data = new bytes(MAX_DATA_SIZE + 1); vm.expectRevert(abi.encodeWithSelector(FeeQuoter.MessageTooLarge.selector, MAX_DATA_SIZE, message.data.length)); @@ -226,7 +249,7 @@ contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); } - function test_TooManyTokens_Revert() public { + function test_RevertWhen_TooManyTokens() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); uint256 tooMany = MAX_TOKENS_LENGTH + 1; message.tokenAmounts = new Client.EVMTokenAmount[](tooMany); @@ -235,14 +258,14 @@ contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { } // Asserts gasLimit must be <=maxGasLimit - function test_MessageGasLimitTooHigh_Revert() public { + function test_RevertWhen_MessageGasLimitTooHigh() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: MAX_GAS_LIMIT + 1})); vm.expectRevert(abi.encodeWithSelector(FeeQuoter.MessageGasLimitTooHigh.selector)); s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); } - function test_NotAFeeToken_Revert() public { + function test_RevertWhen_NotAFeeToken() public { address notAFeeToken = address(0x111111); Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(notAFeeToken, 1); message.feeToken = notAFeeToken; @@ -252,7 +275,7 @@ contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); } - function test_InvalidEVMAddress_Revert() public { + function test_RevertWhen_InvalidEVMAddress() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.receiver = abi.encode(type(uint208).max); diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getValidatedTokenPrice.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getValidatedTokenPrice.t.sol index 6d508bc9116..b5603a61306 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getValidatedTokenPrice.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getValidatedTokenPrice.t.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; -import {MockV3Aggregator} from "../../../tests/MockV3Aggregator.sol"; +import {MockV3Aggregator} from "../../../shared/mocks/MockV3Aggregator.sol"; import {FeeQuoter} from "../../FeeQuoter.sol"; import {Internal} from "../../libraries/Internal.sol"; import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; contract FeeQuoter_getValidatedTokenPrice is FeeQuoterSetup { - function test_GetValidatedTokenPrice_Success() public view { + function test_GetValidatedTokenPrice() public view { Internal.PriceUpdates memory priceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); address token = priceUpdates.tokenPriceUpdates[0].sourceToken; @@ -16,7 +16,7 @@ contract FeeQuoter_getValidatedTokenPrice is FeeQuoterSetup { assertEq(priceUpdates.tokenPriceUpdates[0].usdPerToken, tokenPrice); } - function test_GetValidatedTokenPriceFromFeed_Success() public { + function test_GetValidatedTokenPriceFromFeed() public { uint256 originalTimestampValue = block.timestamp; // Right below staleness threshold @@ -29,7 +29,7 @@ contract FeeQuoter_getValidatedTokenPrice is FeeQuoterSetup { assertEq(tokenPriceAnswer, uint224(1e18)); } - function test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() public { + function test_GetValidatedTokenPriceFromFeedOverStalenessPeriod() public { uint256 originalTimestampValue = block.timestamp; // Right above staleness threshold @@ -42,7 +42,7 @@ contract FeeQuoter_getValidatedTokenPrice is FeeQuoterSetup { assertEq(tokenPriceAnswer, uint224(1e18)); } - function test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() public { + function test_GetValidatedTokenPriceFromFeedMaxInt224Value() public { address tokenAddress = _deploySourceToken("testToken", 0, 18); address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 18, int256(uint256(type(uint224).max))); @@ -56,7 +56,7 @@ contract FeeQuoter_getValidatedTokenPrice is FeeQuoterSetup { assertEq(tokenPriceAnswer, uint224(type(uint224).max)); } - function test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() public { + function test_GetValidatedTokenPriceFromFeedErc20Below18Decimals() public { address tokenAddress = _deploySourceToken("testToken", 0, 6); address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 8, 1e8); @@ -70,7 +70,7 @@ contract FeeQuoter_getValidatedTokenPrice is FeeQuoterSetup { assertEq(tokenPriceAnswer, uint224(1e30)); } - function test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() public { + function test_GetValidatedTokenPriceFromFeedErc20Above18Decimals() public { address tokenAddress = _deploySourceToken("testToken", 0, 24); address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 8, 1e8); @@ -84,7 +84,7 @@ contract FeeQuoter_getValidatedTokenPrice is FeeQuoterSetup { assertEq(tokenPriceAnswer, uint224(1e12)); } - function test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() public { + function test_GetValidatedTokenPriceFromFeedFeedAt18Decimals() public { address tokenAddress = _deploySourceToken("testToken", 0, 18); address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 18, 1e18); @@ -98,7 +98,7 @@ contract FeeQuoter_getValidatedTokenPrice is FeeQuoterSetup { assertEq(tokenPriceAnswer, uint224(1e18)); } - function test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() public { + function test_GetValidatedTokenPriceFromFeedFeedAt0Decimals() public { address tokenAddress = _deploySourceToken("testToken", 0, 0); address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 0, 1e31); @@ -112,7 +112,7 @@ contract FeeQuoter_getValidatedTokenPrice is FeeQuoterSetup { assertEq(tokenPriceAnswer, uint224(1e67)); } - function test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() public { + function test_GetValidatedTokenPriceFromFeedFlippedDecimals() public { address tokenAddress = _deploySourceToken("testToken", 0, 20); address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 20, 1e18); @@ -126,7 +126,7 @@ contract FeeQuoter_getValidatedTokenPrice is FeeQuoterSetup { assertEq(tokenPriceAnswer, uint224(1e14)); } - function test_StaleFeeToken_Success() public { + function test_StaleFeeToken() public { vm.warp(block.timestamp + TWELVE_HOURS + 1); Internal.PriceUpdates memory priceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); @@ -139,7 +139,7 @@ contract FeeQuoter_getValidatedTokenPrice is FeeQuoterSetup { // Reverts - function test_OverflowFeedPrice_Revert() public { + function test_RevertWhen_OverflowFeedPrice() public { address tokenAddress = _deploySourceToken("testToken", 0, 18); address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 18, int256(uint256(type(uint224).max) + 1)); @@ -151,7 +151,7 @@ contract FeeQuoter_getValidatedTokenPrice is FeeQuoterSetup { s_feeQuoter.getValidatedTokenPrice(tokenAddress); } - function test_UnderflowFeedPrice_Revert() public { + function test_RevertWhen_UnderflowFeedPrice() public { address tokenAddress = _deploySourceToken("testToken", 0, 18); address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 18, -1); @@ -163,12 +163,12 @@ contract FeeQuoter_getValidatedTokenPrice is FeeQuoterSetup { s_feeQuoter.getValidatedTokenPrice(tokenAddress); } - function test_TokenNotSupported_Revert() public { + function test_RevertWhen_TokenNotSupported() public { vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, DUMMY_CONTRACT_ADDRESS)); s_feeQuoter.getValidatedTokenPrice(DUMMY_CONTRACT_ADDRESS); } - function test_TokenNotSupportedFeed_Revert() public { + function test_RevertWhen_TokenNotSupportedFeed() public { address sourceToken = _initialiseSingleTokenPriceFeed(); MockV3Aggregator(s_dataFeedByToken[sourceToken]).updateAnswer(0); Internal.PriceUpdates memory priceUpdates = Internal.PriceUpdates({ diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.onReport.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.onReport.t.sol index ebd800b7d48..dd132e43b22 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.onReport.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.onReport.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {KeystoneFeedsPermissionHandler} from "../../../keystone/KeystoneFeedsPermissionHandler.sol"; @@ -132,7 +132,7 @@ contract FeeQuoter_onReport is FeeQuoterSetup { assertEq(vm.getRecordedLogs().length, 0); } - function test_onReport_RevertWhen_TokenNotSupported() public { + function test_RevertWhen_onReportWhen_TokenNotSupported() public { FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](1); report[0] = FeeQuoter.ReceivedCCIPFeedReport({token: s_sourceTokens[1], price: 4e18, timestamp: uint32(block.timestamp)}); @@ -143,7 +143,7 @@ contract FeeQuoter_onReport is FeeQuoterSetup { s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); } - function test_onReport_RevertWhen_InvalidForwarder() public { + function test_RevertWhen_onReportWhen_InvalidForwarder() public { FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](1); report[0] = FeeQuoter.ReceivedCCIPFeedReport({token: s_sourceTokens[0], price: 4e18, timestamp: uint32(block.timestamp)}); diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.parseEVMExtraArgsFromBytes.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.parseEVMExtraArgsFromBytes.t.sol index 8f4e3f954ca..ba2bde126c8 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.parseEVMExtraArgsFromBytes.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.parseEVMExtraArgsFromBytes.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {FeeQuoter} from "../../FeeQuoter.sol"; import {Client} from "../../libraries/Client.sol"; import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; -contract FeeQuoter_parseEVMExtraArgsFromBytes is FeeQuoterSetup { +contract FeeQuoter_resolveGasLimitForDestination is FeeQuoterSetup { FeeQuoter.DestChainConfig private s_destChainConfig; function setUp() public virtual override { @@ -13,40 +13,48 @@ contract FeeQuoter_parseEVMExtraArgsFromBytes is FeeQuoterSetup { s_destChainConfig = _generateFeeQuoterDestChainConfigArgs()[0].destChainConfig; } - function test_EVMExtraArgsV1_Success() public view { + function test_EVMExtraArgsV1TagSelector() public view { + assertEq(Client.EVM_EXTRA_ARGS_V1_TAG, bytes4(keccak256("CCIP EVMExtraArgsV1"))); + } + + function test_EVMExtraArgsV2TagSelector() public view { + assertEq(Client.EVM_EXTRA_ARGS_V2_TAG, bytes4(keccak256("CCIP EVMExtraArgsV2"))); + } + + function test_EVMExtraArgsV1() public view { Client.EVMExtraArgsV1 memory inputArgs = Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT}); bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); Client.EVMExtraArgsV2 memory expectedOutputArgs = Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: false}); vm.assertEq( - abi.encode(s_feeQuoter.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig)), + abi.encode(s_feeQuoter.parseEVMExtraArgsFromBytes(inputExtraArgs, DEST_CHAIN_SELECTOR)), abi.encode(expectedOutputArgs) ); } - function test_EVMExtraArgsV2_Success() public view { + function test_EVMExtraArgsV2() public view { Client.EVMExtraArgsV2 memory inputArgs = Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: true}); bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); vm.assertEq( - abi.encode(s_feeQuoter.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig)), abi.encode(inputArgs) + abi.encode(s_feeQuoter.parseEVMExtraArgsFromBytes(inputExtraArgs, DEST_CHAIN_SELECTOR)), abi.encode(inputArgs) ); } - function test_EVMExtraArgsDefault_Success() public view { + function test_EVMExtraArgsDefault() public view { Client.EVMExtraArgsV2 memory expectedOutputArgs = Client.EVMExtraArgsV2({gasLimit: s_destChainConfig.defaultTxGasLimit, allowOutOfOrderExecution: false}); vm.assertEq( - abi.encode(s_feeQuoter.parseEVMExtraArgsFromBytes("", s_destChainConfig)), abi.encode(expectedOutputArgs) + abi.encode(s_feeQuoter.parseEVMExtraArgsFromBytes("", DEST_CHAIN_SELECTOR)), abi.encode(expectedOutputArgs) ); } // Reverts - function test_EVMExtraArgsInvalidExtraArgsTag_Revert() public { + function test_RevertWhen_EVMExtraArgsInvalidExtraArgsTag() public { Client.EVMExtraArgsV2 memory inputArgs = Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: true}); bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); @@ -54,25 +62,25 @@ contract FeeQuoter_parseEVMExtraArgsFromBytes is FeeQuoterSetup { inputExtraArgs[0] = bytes1(uint8(0)); vm.expectRevert(FeeQuoter.InvalidExtraArgsTag.selector); - s_feeQuoter.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig); + s_feeQuoter.parseEVMExtraArgsFromBytes(inputExtraArgs, DEST_CHAIN_SELECTOR); } - function test_EVMExtraArgsEnforceOutOfOrder_Revert() public { + function test_RevertWhen_EVMExtraArgsEnforceOutOfOrder() public { Client.EVMExtraArgsV2 memory inputArgs = Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: false}); bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); s_destChainConfig.enforceOutOfOrder = true; vm.expectRevert(FeeQuoter.ExtraArgOutOfOrderExecutionMustBeTrue.selector); - s_feeQuoter.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig); + s_feeQuoter.parseEVMExtraArgsFromBytes(inputExtraArgs, DEST_CHAIN_SELECTOR, true); } - function test_EVMExtraArgsGasLimitTooHigh_Revert() public { + function test_RevertWhen_EVMExtraArgsGasLimitTooHigh() public { Client.EVMExtraArgsV2 memory inputArgs = Client.EVMExtraArgsV2({gasLimit: s_destChainConfig.maxPerMsgGasLimit + 1, allowOutOfOrderExecution: true}); bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); vm.expectRevert(FeeQuoter.MessageGasLimitTooHigh.selector); - s_feeQuoter.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig); + s_feeQuoter.parseEVMExtraArgsFromBytes(inputExtraArgs, DEST_CHAIN_SELECTOR); } } diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.parseSVMExtraArgsFromBytes.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.parseSVMExtraArgsFromBytes.t.sol new file mode 100644 index 00000000000..882fc17fe8f --- /dev/null +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.parseSVMExtraArgsFromBytes.t.sol @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import {FeeQuoter} from "../../FeeQuoter.sol"; +import {Client} from "../../libraries/Client.sol"; + +import {Internal} from "../../libraries/Internal.sol"; +import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; + +contract FeeQuoter_parseSVMExtraArgsFromBytes is FeeQuoterSetup { + FeeQuoter.DestChainConfig private s_destChainConfig; + + /// @dev a Valid pubkey is one that is 32 bytes long, and that's it since no other validation can be performed + /// within the constraints of the EVM. + bytes32 internal constant VALID_SOL_PUBKEY = keccak256("SOL_PUBKEY"); + + function setUp() public virtual override { + super.setUp(); + s_destChainConfig = _generateFeeQuoterDestChainConfigArgs()[0].destChainConfig; + s_destChainConfig.enforceOutOfOrder = true; // Enforcing out of order execution for messages to SVM + s_destChainConfig.chainFamilySelector = Internal.CHAIN_FAMILY_SELECTOR_SVM; + + FeeQuoter.DestChainConfigArgs[] memory destChainConfigs = new FeeQuoter.DestChainConfigArgs[](1); + destChainConfigs[0] = + FeeQuoter.DestChainConfigArgs({destChainSelector: DEST_CHAIN_SELECTOR, destChainConfig: s_destChainConfig}); + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigs); + } + + function test_SVMExtraArgsV1TagSelector() public view { + assertEq(Client.SVM_EXTRA_EXTRA_ARGS_V1_TAG, bytes4(keccak256("CCIP SVMExtraArgsV1"))); + } + + function test_SVMExtraArgsV1() public view { + bytes32[] memory solAccounts = new bytes32[](1); + solAccounts[0] = VALID_SOL_PUBKEY; + + Client.SVMExtraArgsV1 memory inputArgs = Client.SVMExtraArgsV1({ + computeUnits: GAS_LIMIT, + accountIsWritableBitmap: 0, + tokenReceiver: bytes32(0), + allowOutOfOrderExecution: true, + accounts: solAccounts + }); + + bytes memory inputExtraArgs = Client._svmArgsToBytes(inputArgs); + + Client.SVMExtraArgsV1 memory expectedOutputArgs = Client.SVMExtraArgsV1({ + computeUnits: GAS_LIMIT, + accountIsWritableBitmap: 0, + tokenReceiver: bytes32(0), + allowOutOfOrderExecution: true, + accounts: solAccounts + }); + + vm.assertEq( + abi.encode(s_feeQuoter.parseSVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig)), + abi.encode(expectedOutputArgs) + ); + } + + // Reverts + function test_RevertWhen_ExtraArgsAreEmpty() public { + bytes memory inputExtraArgs = new bytes(0); + vm.expectRevert(FeeQuoter.InvalidExtraArgsData.selector); + s_feeQuoter.parseSVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig); + } + + function test_RevertWhen_InvalidExtraArgsTag() public { + bytes memory inputExtraArgs = abi.encodeWithSelector(bytes4(0)); + + vm.expectRevert(FeeQuoter.InvalidExtraArgsTag.selector); + s_feeQuoter.parseSVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig); + } + + function test_RevertWhen_SVMMessageGasLimitTooHigh() public { + Client.SVMExtraArgsV1 memory inputArgs = Client.SVMExtraArgsV1({ + computeUnits: s_destChainConfig.maxPerMsgGasLimit + 1, + accountIsWritableBitmap: 0, + tokenReceiver: bytes32(0), + allowOutOfOrderExecution: true, + accounts: new bytes32[](0) + }); + + bytes memory inputExtraArgs = Client._svmArgsToBytes(inputArgs); + + vm.expectRevert(FeeQuoter.MessageComputeUnitLimitTooHigh.selector); + s_feeQuoter.parseSVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig); + } + + function test_RevertWhen_ExtraArgOutOfOrderExecutionIsFalse() public { + bytes memory inputExtraArgs = abi.encodeWithSelector( + Client.SVM_EXTRA_EXTRA_ARGS_V1_TAG, + Client.SVMExtraArgsV1({ + computeUnits: 1_000_000, + accountIsWritableBitmap: 0, + tokenReceiver: bytes32(0), + allowOutOfOrderExecution: false, // mismatch with enforcedOutOfOrder = true + accounts: new bytes32[](0) + }) + ); + + vm.expectRevert(FeeQuoter.ExtraArgOutOfOrderExecutionMustBeTrue.selector); + s_feeQuoter.parseSVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig); + } +} diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.processChainFamilySelector.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.processChainFamilySelector.t.sol new file mode 100644 index 00000000000..e90034d3a9e --- /dev/null +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.processChainFamilySelector.t.sol @@ -0,0 +1,131 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import {FeeQuoter} from "../../FeeQuoter.sol"; +import {Client} from "../../libraries/Client.sol"; +import {Internal} from "../../libraries/Internal.sol"; +import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; + +contract FeeQuoter_processChainFamilySelector is FeeQuoterSetup { + uint64 internal constant SVM_SELECTOR = SOURCE_CHAIN_SELECTOR; + uint64 internal constant EVM_SELECTOR = DEST_CHAIN_SELECTOR; + uint64 internal constant INVALID_SELECTOR = 99; + + function setUp() public virtual override { + super.setUp(); + + // 1. Configure an EVM chain + FeeQuoter.DestChainConfig memory evmConfig; + evmConfig.chainFamilySelector = Internal.CHAIN_FAMILY_SELECTOR_EVM; + evmConfig.defaultTxGasLimit = 500_000; + evmConfig.maxPerMsgGasLimit = 1_000_000; // Example + evmConfig.enforceOutOfOrder = false; // Example + + // 2. Configure an SVM chain + FeeQuoter.DestChainConfig memory svmConfig; + svmConfig.chainFamilySelector = Internal.CHAIN_FAMILY_SELECTOR_SVM; + svmConfig.defaultTxGasLimit = 2_000_000; + svmConfig.maxPerMsgGasLimit = 3_000_000; // Example + svmConfig.enforceOutOfOrder = true; + + // Apply both configs + FeeQuoter.DestChainConfigArgs[] memory configs = new FeeQuoter.DestChainConfigArgs[](2); + configs[0] = FeeQuoter.DestChainConfigArgs({destChainSelector: EVM_SELECTOR, destChainConfig: evmConfig}); + configs[1] = FeeQuoter.DestChainConfigArgs({destChainSelector: SVM_SELECTOR, destChainConfig: svmConfig}); + s_feeQuoter.applyDestChainConfigUpdates(configs); + } + + // ---------------------------------------------------------------- + // TEST: EVM path + // ---------------------------------------------------------------- + function test_processChainFamilySelectorEVM() public { + Client.EVMExtraArgsV2 memory evmArgs = Client.EVMExtraArgsV2({gasLimit: 400_000, allowOutOfOrderExecution: true}); + bytes memory encodedEvmArgs = Client._argsToBytes(evmArgs); + + (bytes memory resultBytes, bool outOfOrder) = s_feeQuoter.processChainFamilySelector( + EVM_SELECTOR, + false, // isMessageWithTokenTransfer + encodedEvmArgs + ); + + assertEq(resultBytes, encodedEvmArgs, "Should return the same EVM-encoded bytes"); + assertEq(outOfOrder, evmArgs.allowOutOfOrderExecution, "Out-of-order mismatch"); + } + + // ---------------------------------------------------------------- + // TEST: SVM path + // ---------------------------------------------------------------- + function test_processChainFamilySelectorSVM_WithTokenTransfer() public { + // Construct an SVMExtraArgsV1 with a non-zero tokenReceiver + Client.SVMExtraArgsV1 memory svmArgs = Client.SVMExtraArgsV1({ + computeUnits: 1_500_000, // within the limit + accountIsWritableBitmap: 0, + tokenReceiver: bytes32("someReceiver"), + allowOutOfOrderExecution: true, + accounts: new bytes32[](0) + }); + bytes memory encodedSvmArgs = Client._svmArgsToBytes(svmArgs); + + (bytes memory resultBytes, bool outOfOrder) = s_feeQuoter.processChainFamilySelector( + SVM_SELECTOR, + true, // isMessageWithTokenTransfer + encodedSvmArgs + ); + + // The function should NOT revert since tokenReceiver != 0 + // Check that it returned the SVM-encoded bytes + assertEq(resultBytes, encodedSvmArgs, "Should return the same SVM-encoded bytes"); + // The function always returns `true` for outOfOrder on SVM + assertTrue(outOfOrder, "Out-of-order for SVM must be true"); + } + + function test_processChainFamilySelectorSVM_NoTokenTransfer() public { + Client.SVMExtraArgsV1 memory svmArgs = Client.SVMExtraArgsV1({ + computeUnits: 2_000_000, + accountIsWritableBitmap: 0, + tokenReceiver: bytes32(0), // zero is fine if not transferring tokens + allowOutOfOrderExecution: true, + accounts: new bytes32[](0) + }); + bytes memory encodedSvmArgs = Client._svmArgsToBytes(svmArgs); + + (bytes memory resultBytes, bool outOfOrder) = s_feeQuoter.processChainFamilySelector( + SVM_SELECTOR, + false, // no token transfer + encodedSvmArgs + ); + + // Should succeed with outOfOrder = true + assertEq(resultBytes, encodedSvmArgs, "Should return the SVM-encoded bytes"); + assertTrue(outOfOrder, "Out-of-order should be true for SVM"); + } + + // TEST: SVM path → reverts + + function test_processChainFamilySelector_RevertWhen_TokenTransferNoTokenReceiver() public { + // Construct an SVMExtraArgsV1 with tokenReceiver == 0 + Client.SVMExtraArgsV1 memory svmArgs = Client.SVMExtraArgsV1({ + computeUnits: 1_500_000, + accountIsWritableBitmap: 0, + tokenReceiver: bytes32(0), // <-- zero + allowOutOfOrderExecution: true, + accounts: new bytes32[](0) + }); + bytes memory encodedSvmArgs = Client._svmArgsToBytes(svmArgs); + + vm.expectRevert(FeeQuoter.InvalidTokenReceiver.selector); + + s_feeQuoter.processChainFamilySelector( + SVM_SELECTOR, + true, // token transfer + encodedSvmArgs + ); + } + + function test_processChainFamilySelector_RevertWhen_InvalidChainFamilySelector() public { + // Provide random extraArgs + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.InvalidChainFamilySelector.selector, bytes4(0))); + + s_feeQuoter.processChainFamilySelector(INVALID_SELECTOR, false, "0x1234"); + } +} diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.processMessageArgs.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.processMessageArgs.t.sol index 65baa576ead..92b59a7e592 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.processMessageArgs.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.processMessageArgs.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {FeeQuoter} from "../../FeeQuoter.sol"; import {Client} from "../../libraries/Client.sol"; @@ -15,7 +15,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { super.setUp(); } - function test_processMessageArgs_WithLinkTokenAmount_Success() public view { + function test_processMessageArgs_WithLinkTokenAmount() public view { ( uint256 msgFeeJuels, /* bool isOutOfOrderExecution */ @@ -36,7 +36,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { assertEq(msgFeeJuels, MAX_MSG_FEES_JUELS); } - function test_processMessageArgs_WithConvertedTokenAmount_Success() public view { + function test_processMessageArgs_WithConvertedTokenAmount() public view { address feeToken = s_sourceTokens[1]; uint256 feeTokenAmount = 10_000 gwei; uint256 expectedConvertedAmount = s_feeQuoter.convertTokenAmount(feeToken, feeTokenAmount, s_sourceTokens[0]); @@ -60,7 +60,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { assertEq(msgFeeJuels, expectedConvertedAmount); } - function test_processMessageArgs_WithEmptyEVMExtraArgs_Success() public view { + function test_processMessageArgs_WithEmptyEVMExtraArgs() public view { ( /* uint256 msgFeeJuels */ , @@ -80,7 +80,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { assertEq(convertedExtraArgs, Client._argsToBytes(s_feeQuoter.parseEVMExtraArgsFromBytes("", DEST_CHAIN_SELECTOR))); } - function test_processMessageArgs_WithEVMExtraArgsV1_Success() public view { + function test_processMessageArgs_WithEVMExtraArgsV1() public view { bytes memory extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 1000})); ( @@ -104,7 +104,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { ); } - function test_processMessageArgs_WitEVMExtraArgsV2_Success() public view { + function test_processMessageArgs_WitEVMExtraArgsV2() public view { bytes memory extraArgs = Client._argsToBytes(Client.EVMExtraArgsV2({gasLimit: 0, allowOutOfOrderExecution: true})); ( @@ -128,9 +128,50 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { ); } + function test_processMessageArgs_WithSVMExtraArgsV1() public { + // Apply the chain update to set the chain family selector to SOL + FeeQuoter.DestChainConfig memory s_destChainConfig = _generateFeeQuoterDestChainConfigArgs()[0].destChainConfig; + s_destChainConfig.chainFamilySelector = Internal.CHAIN_FAMILY_SELECTOR_SVM; + + FeeQuoter.DestChainConfigArgs[] memory destChainConfigs = new FeeQuoter.DestChainConfigArgs[](1); + destChainConfigs[0] = + FeeQuoter.DestChainConfigArgs({destChainSelector: DEST_CHAIN_SELECTOR, destChainConfig: s_destChainConfig}); + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigs); + + bytes memory extraArgs = Client._svmArgsToBytes( + Client.SVMExtraArgsV1({ + computeUnits: 0, + accountIsWritableBitmap: 0, + tokenReceiver: bytes32(0), + allowOutOfOrderExecution: true, + accounts: new bytes32[](0) + }) + ); + + ( + /* uint256 msgFeeJuels */ + , + bool isOutOfOrderExecution, + bytes memory convertedExtraArgs, + /* destExecDataPerToken */ + ) = s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, + s_sourceTokens[0], + 0, + extraArgs, + new Internal.EVM2AnyTokenTransfer[](0), + new Client.EVMTokenAmount[](0) + ); + + assertTrue(isOutOfOrderExecution); + assertEq( + convertedExtraArgs, Client._svmArgsToBytes(s_feeQuoter.parseSVMExtraArgsFromBytes(extraArgs, s_destChainConfig)) + ); + } + // Reverts - function test_processMessageArgs_MessageFeeTooHigh_Revert() public { + function test_RevertWhen_processMessageArgs_MessageFeeTooHigh() public { vm.expectRevert( abi.encodeWithSelector(FeeQuoter.MessageFeeTooHigh.selector, MAX_MSG_FEES_JUELS + 1, MAX_MSG_FEES_JUELS) ); @@ -145,7 +186,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { ); } - function test_processMessageArgs_InvalidExtraArgs_Revert() public { + function test_RevertWhen_processMessageArgs_InvalidExtraArgs() public { vm.expectRevert(FeeQuoter.InvalidExtraArgsTag.selector); s_feeQuoter.processMessageArgs( @@ -158,7 +199,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { ); } - function test_processMessageArgs_MalformedEVMExtraArgs_Revert() public { + function test_RevertWhen_processMessageArgs_MalformedEVMExtraArgs() public { // abi.decode error vm.expectRevert(); @@ -172,7 +213,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { ); } - function test_processMessageArgs_WithCorrectPoolReturnData_Success() public view { + function test_processMessageArgs_WithCorrectPoolReturnData() public view { Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](2); sourceTokenAmounts[0].amount = 1e18; sourceTokenAmounts[0].token = s_sourceTokens[0]; @@ -199,7 +240,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { } } - function test_processMessageArgs_TokenAmountArraysMismatching_Revert() public { + function test_RevertWhen_processMessageArgs_TokenAmountArraysMismatching() public { Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](2); sourceTokenAmounts[0].amount = 1e18; sourceTokenAmounts[0].token = s_sourceTokens[0]; @@ -220,7 +261,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { ); } - function test_applyTokensTransferFeeConfigUpdates_InvalidFeeRange_Revert() public { + function test_RevertWhen_applyTokensTransferFeeConfigUpdates_InvalidFeeRange() public { address sourceETH = s_sourceTokens[1]; // Set token config to allow larger data @@ -243,7 +284,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { ); } - function test_processMessageArgs_SourceTokenDataTooLarge_Revert() public { + function test_RevertWhen_processMessageArgs_SourceTokenDataTooLarge() public { address sourceETH = s_sourceTokens[1]; Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](1); @@ -300,7 +341,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { ); } - function test_processMessageArgs_InvalidEVMAddressDestToken_Revert() public { + function test_RevertWhen_processMessageArgs_InvalidEVMAddressDestToken() public { bytes memory nonEvmAddress = abi.encode(type(uint208).max); Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](1); diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.supportsInterface.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.supportsInterface.t.sol index a9352392301..35712d9bfcf 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.supportsInterface.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.supportsInterface.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IReceiver} from "../../../keystone/interfaces/IReceiver.sol"; import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; @@ -9,7 +9,7 @@ import {IFeeQuoter} from "../../interfaces/IFeeQuoter.sol"; import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; contract FeeQuoter_supportsInterface is FeeQuoterSetup { - function test_SupportsInterface_Success() public view { + function test_SupportsInterface() public view { assertTrue(s_feeQuoter.supportsInterface(type(IReceiver).interfaceId)); assertTrue(s_feeQuoter.supportsInterface(type(ITypeAndVersion).interfaceId)); assertTrue(s_feeQuoter.supportsInterface(type(IFeeQuoter).interfaceId)); diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.updatePrices.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.updatePrices.t.sol index d40ac7d33ad..6f463af248b 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.updatePrices.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.updatePrices.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {AuthorizedCallers} from "../../../shared/access/AuthorizedCallers.sol"; import {FeeQuoter} from "../../FeeQuoter.sol"; @@ -7,7 +7,7 @@ import {Internal} from "../../libraries/Internal.sol"; import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; contract FeeQuoter_updatePrices is FeeQuoterSetup { - function test_OnlyTokenPrice_Success() public { + function test_OnlyTokenPrice() public { Internal.PriceUpdates memory update = Internal.PriceUpdates({ tokenPriceUpdates: new Internal.TokenPriceUpdate[](1), gasPriceUpdates: new Internal.GasPriceUpdate[](0) @@ -24,7 +24,7 @@ contract FeeQuoter_updatePrices is FeeQuoterSetup { assertEq(s_feeQuoter.getTokenPrice(s_sourceTokens[0]).value, update.tokenPriceUpdates[0].usdPerToken); } - function test_OnlyGasPrice_Success() public { + function test_OnlyGasPrice() public { Internal.PriceUpdates memory update = Internal.PriceUpdates({ tokenPriceUpdates: new Internal.TokenPriceUpdate[](0), gasPriceUpdates: new Internal.GasPriceUpdate[](1) @@ -44,7 +44,7 @@ contract FeeQuoter_updatePrices is FeeQuoterSetup { ); } - function test_UpdateMultiplePrices_Success() public { + function test_UpdateMultiplePrices() public { Internal.TokenPriceUpdate[] memory tokenPriceUpdates = new Internal.TokenPriceUpdate[](3); tokenPriceUpdates[0] = Internal.TokenPriceUpdate({sourceToken: s_sourceTokens[0], usdPerToken: 4e18}); tokenPriceUpdates[1] = Internal.TokenPriceUpdate({sourceToken: s_sourceTokens[1], usdPerToken: 1800e18}); @@ -86,7 +86,7 @@ contract FeeQuoter_updatePrices is FeeQuoterSetup { } } - function test_UpdatableByAuthorizedCaller_Success() public { + function test_UpdatableByAuthorizedCaller() public { Internal.PriceUpdates memory priceUpdates = Internal.PriceUpdates({ tokenPriceUpdates: new Internal.TokenPriceUpdate[](1), gasPriceUpdates: new Internal.GasPriceUpdate[](0) @@ -127,7 +127,7 @@ contract FeeQuoter_updatePrices is FeeQuoterSetup { // Reverts - function test_OnlyCallableByUpdater_Revert() public { + function test_RevertWhen_OnlyCallableByUpdater() public { Internal.PriceUpdates memory priceUpdates = Internal.PriceUpdates({ tokenPriceUpdates: new Internal.TokenPriceUpdate[](0), gasPriceUpdates: new Internal.GasPriceUpdate[](0) diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.updateTokenPriceFeeds.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.updateTokenPriceFeeds.t.sol index 9341fab121b..2ee95e4f513 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.updateTokenPriceFeeds.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.updateTokenPriceFeeds.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Ownable2Step} from "../../../shared/access/Ownable2Step.sol"; import {FeeQuoter} from "../../FeeQuoter.sol"; @@ -9,7 +9,7 @@ import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; import {Vm} from "forge-std/Vm.sol"; contract FeeQuoter_updateTokenPriceFeeds is FeeQuoterSetup { - function test_ZeroFeeds_Success() public { + function test_ZeroFeeds() public { Vm.Log[] memory logEntries = vm.getRecordedLogs(); FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](0); @@ -20,7 +20,7 @@ contract FeeQuoter_updateTokenPriceFeeds is FeeQuoterSetup { assertEq(logEntries.length, 0); } - function test_SingleFeedUpdate_Success() public { + function test_SingleFeedUpdate() public { FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); @@ -37,7 +37,7 @@ contract FeeQuoter_updateTokenPriceFeeds is FeeQuoterSetup { ); } - function test_MultipleFeedUpdate_Success() public { + function test_MultipleFeedUpdate() public { FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](2); for (uint256 i = 0; i < 2; ++i) { @@ -62,7 +62,7 @@ contract FeeQuoter_updateTokenPriceFeeds is FeeQuoterSetup { ); } - function test_FeedUnset_Success() public { + function test_FeedUnset() public { Internal.TimestampedPackedUint224 memory priceQueryInitial = s_feeQuoter.getTokenPrice(s_sourceTokens[0]); assertFalse(priceQueryInitial.value == 0); assertFalse(priceQueryInitial.timestamp == 0); @@ -106,7 +106,7 @@ contract FeeQuoter_updateTokenPriceFeeds is FeeQuoterSetup { // Reverts - function test_FeedUpdatedByNonOwner_Revert() public { + function test_RevertWhen_FeedUpdatedByNonOwner() public { FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.validateDestFamilyAddress.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.validateDestFamilyAddress.t.sol index 761cb7546a9..ae4e4766bd9 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.validateDestFamilyAddress.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.validateDestFamilyAddress.t.sol @@ -1,42 +1,49 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; +import {FeeQuoter} from "../../FeeQuoter.sol"; import {Internal} from "../../libraries/Internal.sol"; import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; contract FeeQuoter_validateDestFamilyAddress is FeeQuoterSetup { - function test_ValidEVMAddress_Success() public view { + function test_ValidEVMAddress() public view { bytes memory encodedAddress = abi.encode(address(10000)); - s_feeQuoter.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, encodedAddress); + s_feeQuoter.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, encodedAddress, 0); } - function test_ValidNonEVMAddress_Success() public view { - s_feeQuoter.validateDestFamilyAddress(bytes4(uint32(1)), abi.encode(type(uint208).max)); + function test_ValidSVMAddress() public view { + s_feeQuoter.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_SVM, abi.encode(type(uint208).max), 0); } // Reverts + function test_RevertWhen_InvalidChainFamilySelector() public { + bytes4 selector = bytes4(0xdeadbeef); + bytes memory encodedAddress = abi.encode(address(10000)); + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.InvalidChainFamilySelector.selector, selector)); + s_feeQuoter.validateDestFamilyAddress(selector, encodedAddress, 0); + } - function test_InvalidEVMAddress_Revert() public { + function test_RevertWhen_InvalidEVMAddress() public { bytes memory invalidAddress = abi.encode(type(uint208).max); vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, invalidAddress)); - s_feeQuoter.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, invalidAddress); + s_feeQuoter.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, invalidAddress, 0); } - function test_InvalidEVMAddressEncodePacked_Revert() public { + function test_RevertWhen_InvalidEVMAddressEncodePacked() public { bytes memory invalidAddress = abi.encodePacked(address(234)); vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, invalidAddress)); - s_feeQuoter.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, invalidAddress); + s_feeQuoter.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, invalidAddress, 0); } - function test_InvalidEVMAddressPrecompiles_Revert() public { + function test_RevertWhen_InvalidEVMAddressPrecompiles() public { for (uint160 i = 0; i < Internal.PRECOMPILE_SPACE; ++i) { bytes memory invalidAddress = abi.encode(address(i)); vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, invalidAddress)); - s_feeQuoter.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, invalidAddress); + s_feeQuoter.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, invalidAddress, 0); } s_feeQuoter.validateDestFamilyAddress( - Internal.CHAIN_FAMILY_SELECTOR_EVM, abi.encode(address(uint160(Internal.PRECOMPILE_SPACE))) + Internal.CHAIN_FAMILY_SELECTOR_EVM, abi.encode(address(uint160(Internal.PRECOMPILE_SPACE))), 0 ); } } diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol index 92c2b3fe309..5bf9b845eae 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; -import {MockV3Aggregator} from "../../../tests/MockV3Aggregator.sol"; +import {MockV3Aggregator} from "../../../shared/mocks/MockV3Aggregator.sol"; import {FeeQuoter} from "../../FeeQuoter.sol"; import {Client} from "../../libraries/Client.sol"; import {Internal} from "../../libraries/Internal.sol"; @@ -17,6 +17,20 @@ contract FeeQuoterSetup is TokenSetup { address internal constant CUSTOM_TOKEN = address(12345); address internal constant CUSTOM_TOKEN_2 = address(bytes20(keccak256("CUSTOM_TOKEN_2"))); + uint32 internal constant MAX_DATA_SIZE = 30_000; + uint16 internal constant MAX_TOKENS_LENGTH = 5; + uint32 internal constant MAX_GAS_LIMIT = 4_000_000; + + // OnRamp + uint96 internal constant MAX_MSG_FEES_JUELS = 1_000e18; + uint32 internal constant DEST_GAS_OVERHEAD = 300_000; + uint8 internal constant DEST_GAS_PER_PAYLOAD_BYTE_BASE = 16; + uint8 internal constant DEST_GAS_PER_PAYLOAD_BYTE_HIGH = 40; + uint16 internal constant DEST_GAS_PER_PAYLOAD_BYTE_THRESHOLD = 3000; + + uint16 internal constant DEFAULT_TOKEN_FEE_USD_CENTS = 50; + uint32 internal constant DEFAULT_TOKEN_BYTES_OVERHEAD = 32; + // Use 16 gas per data availability byte in our tests. // This is an overestimation in OP stack, it ignores 4 gas per 0 byte rule. // Arbitrum on the other hand, does always use 16 gas per data availability byte. @@ -248,7 +262,9 @@ contract FeeQuoterSetup is TokenSetup { isEnabled: true, maxNumberOfTokensPerMsg: MAX_TOKENS_LENGTH, destGasOverhead: DEST_GAS_OVERHEAD, - destGasPerPayloadByte: DEST_GAS_PER_PAYLOAD_BYTE, + destGasPerPayloadByteBase: DEST_GAS_PER_PAYLOAD_BYTE_BASE, + destGasPerPayloadByteHigh: DEST_GAS_PER_PAYLOAD_BYTE_HIGH, + destGasPerPayloadByteThreshold: DEST_GAS_PER_PAYLOAD_BYTE_THRESHOLD, destDataAvailabilityOverheadGas: DEST_DATA_AVAILABILITY_OVERHEAD_GAS, destGasPerDataAvailabilityByte: DEST_GAS_PER_DATA_AVAILABILITY_BYTE, destDataAvailabilityMultiplierBps: DEST_GAS_DATA_AVAILABILITY_MULTIPLIER_BPS, @@ -297,7 +313,9 @@ contract FeeQuoterSetup is TokenSetup { assertEq(a.maxDataBytes, b.maxDataBytes); assertEq(a.maxPerMsgGasLimit, b.maxPerMsgGasLimit); assertEq(a.destGasOverhead, b.destGasOverhead); - assertEq(a.destGasPerPayloadByte, b.destGasPerPayloadByte); + assertEq(a.destGasPerPayloadByteBase, b.destGasPerPayloadByteBase); + assertEq(a.destGasPerPayloadByteHigh, b.destGasPerPayloadByteHigh); + assertEq(a.destGasPerPayloadByteThreshold, b.destGasPerPayloadByteThreshold); assertEq(a.destDataAvailabilityOverheadGas, b.destDataAvailabilityOverheadGas); assertEq(a.destGasPerDataAvailabilityByte, b.destGasPerDataAvailabilityByte); assertEq(a.destDataAvailabilityMultiplierBps, b.destDataAvailabilityMultiplierBps); @@ -330,6 +348,25 @@ contract FeeQuoterFeeSetup is FeeQuoterSetup { }); } + // Used to generate a message with a specific extraArgs tag for SVM + function _generateEmptyMessage2SVM() public view returns (Client.EVM2AnyMessage memory) { + return Client.EVM2AnyMessage({ + receiver: abi.encode(OWNER), + data: "", + tokenAmounts: new Client.EVMTokenAmount[](0), + feeToken: s_sourceFeeToken, + extraArgs: Client._svmArgsToBytes( + Client.SVMExtraArgsV1({ + computeUnits: GAS_LIMIT, + accountIsWritableBitmap: 0, + allowOutOfOrderExecution: true, + tokenReceiver: bytes32(0), + accounts: new bytes32[](0) + }) + ) + }); + } + function _generateSingleTokenMessage( address token, uint256 amount diff --git a/contracts/src/v0.8/ccip/test/helpers/BurnMintERC677Helper.sol b/contracts/src/v0.8/ccip/test/helpers/BurnMintERC677Helper.sol index c3f95a7e067..7775b777cf5 100644 --- a/contracts/src/v0.8/ccip/test/helpers/BurnMintERC677Helper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/BurnMintERC677Helper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; import {IGetCCIPAdmin} from "../../interfaces/IGetCCIPAdmin.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/BurnMintMultiTokenPool.sol b/contracts/src/v0.8/ccip/test/helpers/BurnMintMultiTokenPool.sol index bb1d4c9af36..6b842ede7f2 100644 --- a/contracts/src/v0.8/ccip/test/helpers/BurnMintMultiTokenPool.sol +++ b/contracts/src/v0.8/ccip/test/helpers/BurnMintMultiTokenPool.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/CCIPHomeHelper.sol b/contracts/src/v0.8/ccip/test/helpers/CCIPHomeHelper.sol index 0bc97c7aa5b..3f8dc595f4d 100644 --- a/contracts/src/v0.8/ccip/test/helpers/CCIPHomeHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/CCIPHomeHelper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {CCIPHome} from "../../capability/CCIPHome.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/CCIPReaderTester.sol b/contracts/src/v0.8/ccip/test/helpers/CCIPReaderTester.sol index d3567c6027d..236797f87f0 100644 --- a/contracts/src/v0.8/ccip/test/helpers/CCIPReaderTester.sol +++ b/contracts/src/v0.8/ccip/test/helpers/CCIPReaderTester.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Internal} from "../../libraries/Internal.sol"; import {OffRamp} from "../../offRamp/OffRamp.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/ERC20RebasingHelper.sol b/contracts/src/v0.8/ccip/test/helpers/ERC20RebasingHelper.sol index 617d39af5c4..874a84ad127 100644 --- a/contracts/src/v0.8/ccip/test/helpers/ERC20RebasingHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/ERC20RebasingHelper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {ERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/EVM2EVMOffRampHelper.sol b/contracts/src/v0.8/ccip/test/helpers/EVM2EVMOffRampHelper.sol index 9f4ca68d84a..079cf36c4a3 100644 --- a/contracts/src/v0.8/ccip/test/helpers/EVM2EVMOffRampHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/EVM2EVMOffRampHelper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; contract EVM2EVMOffRampHelper { uint64 public s_nonce; diff --git a/contracts/src/v0.8/ccip/interfaces/encodingutils/ICCIPEncodingUtils.sol b/contracts/src/v0.8/ccip/test/helpers/EncodingUtils.sol similarity index 94% rename from contracts/src/v0.8/ccip/interfaces/encodingutils/ICCIPEncodingUtils.sol rename to contracts/src/v0.8/ccip/test/helpers/EncodingUtils.sol index c8a976eda87..b44672335ce 100644 --- a/contracts/src/v0.8/ccip/interfaces/encodingutils/ICCIPEncodingUtils.sol +++ b/contracts/src/v0.8/ccip/test/helpers/EncodingUtils.sol @@ -2,14 +2,14 @@ pragma solidity ^0.8.0; import {CCIPHome} from "../../capability/CCIPHome.sol"; - import {OffRamp} from "../../offRamp/OffRamp.sol"; import {RMNRemote} from "../../rmn/RMNRemote.sol"; /// @dev this file exposes structs that are otherwise internal to the CCIP codebase. /// doing this allows those structs to be encoded and decoded with type safety in offchain code. /// and tests because generated wrappers are available. -interface ICCIPEncodingUtils { +// solhint-disable-next-line +interface EncodingUtils { /// @dev the RMN Report struct is used in integration / E2E tests. function exposeRmnReport(bytes32 rmnReportVersion, RMNRemote.Report memory rmnReport) external; diff --git a/contracts/src/v0.8/ccip/test/helpers/EtherSenderReceiverHelper.sol b/contracts/src/v0.8/ccip/test/helpers/EtherSenderReceiverHelper.sol index e357645bcb2..197b262671f 100644 --- a/contracts/src/v0.8/ccip/test/helpers/EtherSenderReceiverHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/EtherSenderReceiverHelper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {EtherSenderReceiver} from "../../applications/EtherSenderReceiver.sol"; import {Client} from "../../libraries/Client.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/FeeQuoterHelper.sol b/contracts/src/v0.8/ccip/test/helpers/FeeQuoterHelper.sol index e392ba05589..6e4233b7d1f 100644 --- a/contracts/src/v0.8/ccip/test/helpers/FeeQuoterHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/FeeQuoterHelper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {FeeQuoter} from "../../FeeQuoter.sol"; import {Client} from "../../libraries/Client.sol"; @@ -48,7 +48,12 @@ contract FeeQuoterHelper is FeeQuoter { Client.EVMTokenAmount[] calldata tokenAmounts ) external view returns (uint256, uint32, uint32) { return _getTokenTransferCost( - s_destChainConfigs[destChainSelector], destChainSelector, feeToken, feeTokenPrice, tokenAmounts + s_destChainConfigs[destChainSelector].defaultTokenFeeUSDCents, + s_destChainConfigs[destChainSelector].defaultTokenDestGasOverhead, + destChainSelector, + feeToken, + feeTokenPrice, + tokenAmounts ); } @@ -56,18 +61,48 @@ contract FeeQuoterHelper is FeeQuoter { bytes calldata extraArgs, uint64 destChainSelector ) external view returns (Client.EVMExtraArgsV2 memory) { - return _parseEVMExtraArgsFromBytes(extraArgs, s_destChainConfigs[destChainSelector]); + return _parseEVMExtraArgsFromBytes( + extraArgs, + s_destChainConfigs[destChainSelector].defaultTxGasLimit, + s_destChainConfigs[destChainSelector].maxPerMsgGasLimit, + s_destChainConfigs[destChainSelector].enforceOutOfOrder + ); } function parseEVMExtraArgsFromBytes( + bytes calldata extraArgs, + uint64 destChainSelector, + bool enforceOutOfOrder + ) external view returns (Client.EVMExtraArgsV2 memory) { + return _parseEVMExtraArgsFromBytes( + extraArgs, + s_destChainConfigs[destChainSelector].defaultTxGasLimit, + s_destChainConfigs[destChainSelector].maxPerMsgGasLimit, + enforceOutOfOrder + ); + } + + function parseSVMExtraArgsFromBytes( bytes calldata extraArgs, DestChainConfig memory destChainConfig - ) external pure returns (Client.EVMExtraArgsV2 memory) { - return _parseEVMExtraArgsFromBytes(extraArgs, destChainConfig); + ) external pure returns (Client.SVMExtraArgsV1 memory) { + return _parseSVMExtraArgsFromBytes(extraArgs, destChainConfig.maxPerMsgGasLimit, destChainConfig.enforceOutOfOrder); } - function validateDestFamilyAddress(bytes4 chainFamilySelector, bytes memory destAddress) external pure { - _validateDestFamilyAddress(chainFamilySelector, destAddress); + function processChainFamilySelector( + uint64 chainFamilySelector, + bool isMessageWithTokenTransfer, + bytes calldata extraArgs + ) external view returns (bytes memory, bool) { + return _processChainFamilySelector(chainFamilySelector, isMessageWithTokenTransfer, extraArgs); + } + + function validateDestFamilyAddress( + bytes4 chainFamilySelector, + bytes memory destAddress, + uint256 gasLimit + ) external pure { + _validateDestFamilyAddress(chainFamilySelector, destAddress, gasLimit); } function calculateRebasedValue( @@ -77,4 +112,11 @@ contract FeeQuoterHelper is FeeQuoter { ) external pure returns (uint224) { return _calculateRebasedValue(dataFeedDecimal, tokenDecimal, feedValue); } + + function resolveGasLimitForDestination( + bytes calldata extraArgs, + DestChainConfig memory destChainConfig + ) external pure returns (uint256 gasLimit) { + return _resolveGasLimitForDestination(extraArgs, destChainConfig); + } } diff --git a/contracts/src/v0.8/ccip/test/helpers/IgnoreContractSize.sol b/contracts/src/v0.8/ccip/test/helpers/IgnoreContractSize.sol index b30124069f2..d9fca95b696 100644 --- a/contracts/src/v0.8/ccip/test/helpers/IgnoreContractSize.sol +++ b/contracts/src/v0.8/ccip/test/helpers/IgnoreContractSize.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; contract IgnoreContractSize { // test contracts are excluded from forge build --sizes by default diff --git a/contracts/src/v0.8/ccip/test/helpers/MaybeRevertingBurnMintTokenPool.sol b/contracts/src/v0.8/ccip/test/helpers/MaybeRevertingBurnMintTokenPool.sol index 9def7688147..2ec5219b36c 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MaybeRevertingBurnMintTokenPool.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MaybeRevertingBurnMintTokenPool.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; @@ -60,7 +60,7 @@ contract MaybeRevertingBurnMintTokenPool is BurnMintTokenPool { /// @notice Reverts depending on the value of `s_revertReason` function releaseOrMint( Pool.ReleaseOrMintInV1 calldata releaseOrMintIn - ) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) { + ) public virtual override returns (Pool.ReleaseOrMintOutV1 memory) { _validateReleaseOrMint(releaseOrMintIn); bytes memory revertReason = s_revertReason; diff --git a/contracts/src/v0.8/ccip/test/helpers/MerkleHelper.sol b/contracts/src/v0.8/ccip/test/helpers/MerkleHelper.sol index 3893d082b6a..e6854e42187 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MerkleHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MerkleHelper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {MerkleMultiProof} from "../../libraries/MerkleMultiProof.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/MessageInterceptorHelper.sol b/contracts/src/v0.8/ccip/test/helpers/MessageInterceptorHelper.sol index 80cdf61602b..049e1fdb676 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MessageInterceptorHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MessageInterceptorHelper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IMessageInterceptor} from "../../interfaces/IMessageInterceptor.sol"; import {Client} from "../../libraries/Client.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol b/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol index 7c2e6cc8c24..fc7040fbe1e 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {MultiAggregateRateLimiter} from "../../MultiAggregateRateLimiter.sol"; import {Client} from "../../libraries/Client.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/MultiOCR3Helper.sol b/contracts/src/v0.8/ccip/test/helpers/MultiOCR3Helper.sol index 68347d153fa..6fbd5295c39 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MultiOCR3Helper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MultiOCR3Helper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {MultiOCR3Base} from "../../ocr/MultiOCR3Base.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/MultiTokenPool.sol b/contracts/src/v0.8/ccip/test/helpers/MultiTokenPool.sol index c8243d50bd7..697d490b288 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MultiTokenPool.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MultiTokenPool.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IPoolV1} from "../../interfaces/IPool.sol"; import {IRMN} from "../../interfaces/IRMN.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/OffRampHelper.sol b/contracts/src/v0.8/ccip/test/helpers/OffRampHelper.sol index 40f7ccb5914..c315c2e53d4 100644 --- a/contracts/src/v0.8/ccip/test/helpers/OffRampHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/OffRampHelper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; import {Client} from "../../libraries/Client.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/OnRampHelper.sol b/contracts/src/v0.8/ccip/test/helpers/OnRampHelper.sol index d315a58fc5d..d9f049718df 100644 --- a/contracts/src/v0.8/ccip/test/helpers/OnRampHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/OnRampHelper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {OnRamp} from "../../onRamp/OnRamp.sol"; import {IgnoreContractSize} from "./IgnoreContractSize.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/RateLimiterHelper.sol b/contracts/src/v0.8/ccip/test/helpers/RateLimiterHelper.sol index 6cd1c18705a..9cf4d467416 100644 --- a/contracts/src/v0.8/ccip/test/helpers/RateLimiterHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/RateLimiterHelper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {RateLimiter} from "../../libraries/RateLimiter.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/ReportCodec.sol b/contracts/src/v0.8/ccip/test/helpers/ReportCodec.sol index 41e4a95b060..b29cd28b1d5 100644 --- a/contracts/src/v0.8/ccip/test/helpers/ReportCodec.sol +++ b/contracts/src/v0.8/ccip/test/helpers/ReportCodec.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Internal} from "../../libraries/Internal.sol"; import {OffRamp} from "../../offRamp/OffRamp.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol b/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol index c067b220fc0..d6a34608136 100644 --- a/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Pool} from "../../libraries/Pool.sol"; import {TokenPool} from "../../pools/TokenPool.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/USDCReaderTester.sol b/contracts/src/v0.8/ccip/test/helpers/USDCReaderTester.sol index d1baa22de1b..f958f1fbf8b 100644 --- a/contracts/src/v0.8/ccip/test/helpers/USDCReaderTester.sol +++ b/contracts/src/v0.8/ccip/test/helpers/USDCReaderTester.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; contract USDCReaderTester { event MessageSent(bytes); diff --git a/contracts/src/v0.8/ccip/test/helpers/USDCTokenPoolHelper.sol b/contracts/src/v0.8/ccip/test/helpers/USDCTokenPoolHelper.sol index 7a3400588a8..0996fb5bd7b 100644 --- a/contracts/src/v0.8/ccip/test/helpers/USDCTokenPoolHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/USDCTokenPoolHelper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/receivers/ConformingReceiver.sol b/contracts/src/v0.8/ccip/test/helpers/receivers/ConformingReceiver.sol index d4102da0752..3fee88c6b5e 100644 --- a/contracts/src/v0.8/ccip/test/helpers/receivers/ConformingReceiver.sol +++ b/contracts/src/v0.8/ccip/test/helpers/receivers/ConformingReceiver.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {CCIPReceiver} from "../../../applications/CCIPReceiver.sol"; import {Client} from "../../../libraries/Client.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiver.sol b/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiver.sol index b40b2c34431..91a697ac318 100644 --- a/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiver.sol +++ b/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiver.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IAny2EVMMessageReceiver} from "../../../interfaces/IAny2EVMMessageReceiver.sol"; import {Client} from "../../../libraries/Client.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiverNo165.sol b/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiverNo165.sol index 07e5ac8544f..9f5030666af 100644 --- a/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiverNo165.sol +++ b/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiverNo165.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IAny2EVMMessageReceiver} from "../../../interfaces/IAny2EVMMessageReceiver.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuser.sol b/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuser.sol index b8aeeb027ae..64f14632c26 100644 --- a/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuser.sol +++ b/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuser.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {CCIPReceiver} from "../../../applications/CCIPReceiver.sol"; import {Client} from "../../../libraries/Client.sol"; diff --git a/contracts/src/v0.8/ccip/test/libraries/ERC165CheckerReverting.supportsInterfaceReverting.t.sol b/contracts/src/v0.8/ccip/test/libraries/ERC165CheckerReverting.supportsInterfaceReverting.t.sol new file mode 100644 index 00000000000..9a63e37ef86 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/libraries/ERC165CheckerReverting.supportsInterfaceReverting.t.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import {IAny2EVMMessageReceiver} from "../../interfaces/IAny2EVMMessageReceiver.sol"; + +import {ERC165CheckerReverting} from "../../libraries/ERC165CheckerReverting.sol"; +import {MaybeRevertMessageReceiver} from "../helpers/receivers/MaybeRevertMessageReceiver.sol"; + +import {Test} from "forge-std/Test.sol"; + +contract ERC165CheckerReverting_supportsInterfaceReverting is Test { + using ERC165CheckerReverting for address; + + address internal s_receiver; + + bytes4 internal constant EXAMPLE_INTERFACE_ID = 0xdeadbeef; + + error InsufficientGasForStaticCall(); + + constructor() { + s_receiver = address(new MaybeRevertMessageReceiver(false)); + } + + function test__supportsInterfaceReverting() public view { + assertTrue(s_receiver._supportsInterfaceReverting(type(IAny2EVMMessageReceiver).interfaceId)); + } + + // Reverts + + function test__supportsInterfaceReverting_RevertWhen_NotEnoughGasForSupportsInterface() public { + vm.expectRevert(InsufficientGasForStaticCall.selector); + + // Library calls cannot be called with gas limit overrides, so a public function must be exposed + // instead which can proxy the call to the library. + + // The gas limit was chosen so that after overhead, <31k would remain to trigger the error. + this.invokeERC165Checker{gas: 33_000}(); + } + + // Meant to test the call with a manual gas limit override + function invokeERC165Checker() external view { + s_receiver._supportsInterfaceReverting(EXAMPLE_INTERFACE_ID); + } +} diff --git a/contracts/src/v0.8/ccip/test/libraries/MerkleMultiProof.t.sol b/contracts/src/v0.8/ccip/test/libraries/MerkleMultiProof.t.sol index 4f03f3e6f55..6a287ce7369 100644 --- a/contracts/src/v0.8/ccip/test/libraries/MerkleMultiProof.t.sol +++ b/contracts/src/v0.8/ccip/test/libraries/MerkleMultiProof.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {MerkleMultiProof} from "../../libraries/MerkleMultiProof.sol"; import {MerkleHelper} from "../helpers/MerkleHelper.sol"; @@ -160,14 +160,14 @@ contract MerkleMultiProofTest is Test { assertEq(MerkleMultiProof._merkleRoot(leaves, proofs, 7), finalResult); } - function test_MerkleRootSingleLeaf_Success() public pure { + function test_MerkleRootSingleLeaf() public pure { bytes32[] memory leaves = new bytes32[](1); leaves[0] = "root"; bytes32[] memory proofs = new bytes32[](0); assertEq(MerkleMultiProof._merkleRoot(leaves, proofs, 0), leaves[0]); } - function test_EmptyLeaf_Revert() public { + function test_RevertWhen_EmptyLeaf() public { bytes32[] memory leaves = new bytes32[](0); bytes32[] memory proofs = new bytes32[](0); diff --git a/contracts/src/v0.8/ccip/test/libraries/RateLimiter.t.sol b/contracts/src/v0.8/ccip/test/libraries/RateLimiter.t.sol index da6a6f9ada7..24ffaa72b26 100644 --- a/contracts/src/v0.8/ccip/test/libraries/RateLimiter.t.sol +++ b/contracts/src/v0.8/ccip/test/libraries/RateLimiter.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {RateLimiter} from "../../libraries/RateLimiter.sol"; import {RateLimiterHelper} from "../helpers/RateLimiterHelper.sol"; @@ -18,7 +18,7 @@ contract RateLimiterSetup is Test { } contract RateLimiter_constructor is RateLimiterSetup { - function test_Constructor_Success() public view { + function test_Constructor() public view { RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); assertEq(s_config.rate, rateLimiter.rate); assertEq(s_config.capacity, rateLimiter.capacity); @@ -29,7 +29,7 @@ contract RateLimiter_constructor is RateLimiterSetup { } contract RateLimiter_setTokenBucketConfig is RateLimiterSetup { - function test_SetRateLimiterConfig_Success() public { + function test_SetRateLimiterConfig() public { RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); assertEq(s_config.rate, rateLimiter.rate); assertEq(s_config.capacity, rateLimiter.capacity); @@ -52,7 +52,7 @@ contract RateLimiter_setTokenBucketConfig is RateLimiterSetup { } contract RateLimiter_currentTokenBucketState is RateLimiterSetup { - function test_CurrentTokenBucketState_Success() public { + function test_CurrentTokenBucketState() public { RateLimiter.TokenBucket memory bucket = s_helper.currentTokenBucketState(); assertEq(s_config.rate, bucket.rate); assertEq(s_config.capacity, bucket.capacity); @@ -72,7 +72,7 @@ contract RateLimiter_currentTokenBucketState is RateLimiterSetup { assertEq(BLOCK_TIME, bucket.lastUpdated); } - function test_Refill_Success() public { + function test_Refill() public { RateLimiter.TokenBucket memory bucket = s_helper.currentTokenBucketState(); assertEq(s_config.rate, bucket.rate); assertEq(s_config.capacity, bucket.capacity); @@ -109,7 +109,7 @@ contract RateLimiter_currentTokenBucketState is RateLimiterSetup { contract RateLimiter_consume is RateLimiterSetup { address internal s_token = address(100); - function test_ConsumeAggregateValue_Success() public { + function test_ConsumeAggregateValue() public { RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); assertEq(s_config.rate, rateLimiter.rate); assertEq(s_config.capacity, rateLimiter.capacity); @@ -132,7 +132,7 @@ contract RateLimiter_consume is RateLimiterSetup { assertEq(BLOCK_TIME, rateLimiter.lastUpdated); } - function test_ConsumeTokens_Success() public { + function test_ConsumeTokens() public { uint256 requestTokens = 50; vm.expectEmit(); @@ -141,7 +141,7 @@ contract RateLimiter_consume is RateLimiterSetup { s_helper.consume(requestTokens, s_token); } - function test_Refill_Success() public { + function test_Refill() public { uint256 requestTokens = 50; vm.expectEmit(); @@ -172,7 +172,7 @@ contract RateLimiter_consume is RateLimiterSetup { assertEq(BLOCK_TIME + warpTime, rateLimiter.lastUpdated); } - function test_ConsumeUnlimited_Success() public { + function test_ConsumeUnlimited() public { s_helper.consume(0, address(0)); RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); @@ -204,7 +204,7 @@ contract RateLimiter_consume is RateLimiterSetup { // Reverts - function test_AggregateValueMaxCapacityExceeded_Revert() public { + function test_RevertWhen_AggregateValueMaxCapacityExceeded() public { RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); vm.expectRevert( @@ -215,7 +215,7 @@ contract RateLimiter_consume is RateLimiterSetup { s_helper.consume(rateLimiter.capacity + 1, address(0)); } - function test_TokenMaxCapacityExceeded_Revert() public { + function test_RevertWhen_TokenMaxCapacityExceeded() public { RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); vm.expectRevert( @@ -226,7 +226,7 @@ contract RateLimiter_consume is RateLimiterSetup { s_helper.consume(rateLimiter.capacity + 1, s_token); } - function test_ConsumingMoreThanUint128_Revert() public { + function test_RevertWhen_ConsumingMoreThanUint128() public { RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); uint256 request = uint256(type(uint128).max) + 1; @@ -237,7 +237,7 @@ contract RateLimiter_consume is RateLimiterSetup { s_helper.consume(request, address(0)); } - function test_AggregateValueRateLimitReached_Revert() public { + function test_RevertWhen_AggregateValueRateLimitReached() public { RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); uint256 overLimit = 20; @@ -256,7 +256,7 @@ contract RateLimiter_consume is RateLimiterSetup { s_helper.consume(requestTokens2, address(0)); } - function test_TokenRateLimitReached_Revert() public { + function test_RevertWhen_TokenRateLimitReached() public { RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); uint256 overLimit = 20; @@ -275,7 +275,7 @@ contract RateLimiter_consume is RateLimiterSetup { s_helper.consume(requestTokens2, s_token); } - function test_RateLimitReachedOverConsecutiveBlocks_Revert() public { + function test_RevertWhen_RateLimitReachedOverConsecutiveBlocks() public { uint256 initBlockTime = BLOCK_TIME + 10000; vm.warp(initBlockTime); diff --git a/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTokenMessenger.sol b/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTokenMessenger.sol index c142cb89477..dc814a3578e 100644 --- a/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTokenMessenger.sol +++ b/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTokenMessenger.sol @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; import {ITokenMessenger} from "../../pools/USDC/ITokenMessenger.sol"; diff --git a/contracts/src/v0.8/ccip/test/mocks/MockRMN.sol b/contracts/src/v0.8/ccip/test/mocks/MockRMN.sol deleted file mode 100644 index 435c6697632..00000000000 --- a/contracts/src/v0.8/ccip/test/mocks/MockRMN.sol +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IRMN} from "../../interfaces/IRMN.sol"; - -/// @notice WARNING: This contract is to be only used for testing, all methods are unprotected. -contract MockRMN is IRMN { - error CustomError(bytes err); - - bytes private s_isCursedRevert; - - bool private s_globalCursed; - mapping(bytes16 subject => bool cursed) private s_cursedBySubject; - mapping(address commitStore => mapping(bytes32 root => bool blessed)) private s_blessedByRoot; - - function setTaggedRootBlessed(IRMN.TaggedRoot calldata taggedRoot, bool blessed) external { - s_blessedByRoot[taggedRoot.commitStore][taggedRoot.root] = blessed; - } - - function setGlobalCursed( - bool cursed - ) external { - s_globalCursed = cursed; - } - - function setChainCursed(uint64 chainSelector, bool cursed) external { - s_cursedBySubject[bytes16(uint128(chainSelector))] = cursed; - } - - /// @notice Setting a revert error with length of 0 will disable reverts - /// @dev Useful to test revert handling of ARMProxy - function setIsCursedRevert( - bytes calldata revertErr - ) external { - s_isCursedRevert = revertErr; - } - - // IRMN implementation follows - - function isCursed() external view returns (bool) { - if (s_isCursedRevert.length > 0) { - revert CustomError(s_isCursedRevert); - } - return s_globalCursed; - } - - function isCursed( - bytes16 subject - ) external view returns (bool) { - if (s_isCursedRevert.length > 0) { - revert CustomError(s_isCursedRevert); - } - return s_globalCursed || s_cursedBySubject[subject]; - } - - function isBlessed( - IRMN.TaggedRoot calldata taggedRoot - ) external view returns (bool) { - return s_blessedByRoot[taggedRoot.commitStore][taggedRoot.root]; - } -} diff --git a/contracts/src/v0.8/ccip/test/mocks/MockUSDCTokenMessenger.sol b/contracts/src/v0.8/ccip/test/mocks/MockUSDCTokenMessenger.sol index 562a9f467ff..f198835c236 100644 --- a/contracts/src/v0.8/ccip/test/mocks/MockUSDCTokenMessenger.sol +++ b/contracts/src/v0.8/ccip/test/mocks/MockUSDCTokenMessenger.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; import {ITokenMessenger} from "../../pools/USDC/ITokenMessenger.sol"; diff --git a/contracts/src/v0.8/ccip/test/mocks/test/MockRouterTest.t.sol b/contracts/src/v0.8/ccip/test/mocks/test/MockRouterTest.t.sol index 549d6b8f843..11371d71f95 100644 --- a/contracts/src/v0.8/ccip/test/mocks/test/MockRouterTest.t.sol +++ b/contracts/src/v0.8/ccip/test/mocks/test/MockRouterTest.t.sol @@ -1,7 +1,6 @@ pragma solidity ^0.8.0; import {Client} from "../../../libraries/Client.sol"; - import {TokenSetup} from "../../TokenSetup.t.sol"; import {IRouterClient, MockCCIPRouter} from "../MockRouter.sol"; @@ -31,32 +30,32 @@ contract MockRouterTest is TokenSetup { s_sourceFeeToken = _deploySourceToken("sLINK", type(uint256).max, 18); } - function test_ccipSendWithInsufficientNativeTokens_Revert() public { + function test_RevertWhen_ccipSendWithInsufficientNativeTokens() public { //Should revert because did not include sufficient eth to pay for fees vm.expectRevert(IRouterClient.InsufficientFeeTokenAmount.selector); mockRouter.ccipSend(MOCK_CHAIN_SELECTOR, message); } - function test_ccipSendWithSufficientNativeFeeTokens_Success() public { + function test_ccipSendWithSufficientNativeFeeTokens() public { //ccipSend with sufficient native tokens for fees mockRouter.ccipSend{value: 0.1 ether}(MOCK_CHAIN_SELECTOR, message); } - function test_ccipSendWithInvalidMsgValue_Revert() public { + function test_RevertWhen_ccipSendWithInvalidMsgValue() public { message.feeToken = address(1); //Set to non native-token fees vm.expectRevert(IRouterClient.InvalidMsgValue.selector); mockRouter.ccipSend{value: 0.1 ether}(MOCK_CHAIN_SELECTOR, message); } - function test_ccipSendWithLinkFeeTokenbutInsufficientAllowance_Revert() public { + function test_RevertWhen_ccipSendWithLinkFeeTokenbutInsufficientAllowance() public { message.feeToken = s_sourceFeeToken; vm.expectRevert(bytes("ERC20: insufficient allowance")); mockRouter.ccipSend(MOCK_CHAIN_SELECTOR, message); } - function test_ccipSendWithLinkFeeTokenAndValidMsgValue_Success() public { + function test_ccipSendWithLinkFeeTokenAndValidMsgValue() public { message.feeToken = s_sourceFeeToken; vm.startPrank(OWNER, OWNER); @@ -66,19 +65,19 @@ contract MockRouterTest is TokenSetup { mockRouter.ccipSend(MOCK_CHAIN_SELECTOR, message); } - function test_ccipSendWithEVMExtraArgsV1_Success() public { + function test_ccipSendWithEVMExtraArgsV1() public { Client.EVMExtraArgsV1 memory extraArgs = Client.EVMExtraArgsV1({gasLimit: 500_000}); message.extraArgs = Client._argsToBytes(extraArgs); mockRouter.ccipSend{value: 0.1 ether}(MOCK_CHAIN_SELECTOR, message); } - function test_ccipSendWithEVMExtraArgsV2_Success() public { + function test_ccipSendWithEVMExtraArgsV2() public { Client.EVMExtraArgsV2 memory extraArgs = Client.EVMExtraArgsV2({gasLimit: 500_000, allowOutOfOrderExecution: true}); message.extraArgs = Client._argsToBytes(extraArgs); mockRouter.ccipSend{value: 0.1 ether}(MOCK_CHAIN_SELECTOR, message); } - function test_ccipSendWithInvalidEVMExtraArgs_Revert() public { + function test_RevertWhen_ccipSendWithInvalidEVMExtraArgs() public { uint256 gasLimit = 500_000; bytes4 invalidExtraArgsTag = bytes4(keccak256("CCIP EVMExtraArgsInvalid")); message.extraArgs = abi.encodeWithSelector(invalidExtraArgsTag, gasLimit); diff --git a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3Base.setOCR3Configs.t.sol b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3Base.setOCR3Configs.t.sol index c70a8666654..36593790409 100644 --- a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3Base.setOCR3Configs.t.sol +++ b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3Base.setOCR3Configs.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {MultiOCR3Base} from "../../../ocr/MultiOCR3Base.sol"; import {MultiOCR3Helper} from "../../helpers/MultiOCR3Helper.sol"; @@ -8,7 +8,7 @@ import {MultiOCR3BaseSetup} from "./MultiOCR3BaseSetup.t.sol"; import {Vm} from "forge-std/Vm.sol"; contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { - function test_SetConfigsZeroInput_Success() public { + function test_SetConfigsZeroInput() public { vm.recordLogs(); s_multiOCR3.setOCR3Configs(new MultiOCR3Base.OCRConfigArgs[](0)); @@ -17,7 +17,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { assertEq(logEntries.length, 0); } - function test_SetConfigWithSigners_Success() public { + function test_SetConfigWithSigners() public { uint8 F = 2; _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); @@ -59,7 +59,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { _assertOCRConfigEquality(s_multiOCR3.latestConfigDetails(0), expectedConfig); } - function test_SetConfigWithSignersMismatchingTransmitters_Success() public { + function test_SetConfigWithSignersMismatchingTransmitters() public { uint8 F = 2; _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); @@ -101,7 +101,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { _assertOCRConfigEquality(s_multiOCR3.latestConfigDetails(0), expectedConfig); } - function test_SetConfigWithoutSigners_Success() public { + function test_SetConfigWithoutSigners() public { uint8 F = 1; address[] memory signers = new address[](0); @@ -144,7 +144,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { _assertOCRConfigEquality(s_multiOCR3.latestConfigDetails(0), expectedConfig); } - function test_SetConfigIgnoreSigners_Success() public { + function test_SetConfigIgnoreSigners() public { uint8 F = 1; _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); @@ -192,7 +192,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { } } - function test_SetMultipleConfigs_Success() public { + function test_SetMultipleConfigs() public { _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(1)); _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(2)); @@ -321,7 +321,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { _assertOCRConfigEquality(s_multiOCR3.latestConfigDetails(ocrConfig.ocrPluginType), expectedConfig); } - function test_UpdateConfigTransmittersWithoutSigners_Success() public { + function test_UpdateConfigTransmittersWithoutSigners() public { _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); @@ -380,7 +380,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { } } - function test_UpdateConfigSigners_Success() public { + function test_UpdateConfigSigners() public { _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); @@ -450,7 +450,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { // Reverts - function test_RepeatTransmitterAddress_Revert() public { + function test_RevertWhen_RepeatTransmitterAddress() public { address[] memory signers = s_validSigners; address[] memory transmitters = s_validTransmitters; transmitters[0] = signers[0]; @@ -473,7 +473,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { s_multiOCR3.setOCR3Configs(ocrConfigs); } - function test_RepeatSignerAddress_Revert() public { + function test_RevertWhen_RepeatSignerAddress() public { address[] memory signers = s_validSigners; address[] memory transmitters = s_validTransmitters; signers[1] = signers[0]; @@ -496,7 +496,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { s_multiOCR3.setOCR3Configs(ocrConfigs); } - function test_SignerCannotBeZeroAddress_Revert() public { + function test_RevertWhen_SignerCannotBeZeroAddress() public { uint8 F = 1; address[] memory signers = new address[](3 * F + 1); address[] memory transmitters = new address[](3 * F + 1); @@ -521,7 +521,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { s_multiOCR3.setOCR3Configs(ocrConfigs); } - function test_TransmitterCannotBeZeroAddress_Revert() public { + function test_RevertWhen_TransmitterCannotBeZeroAddress() public { uint8 F = 1; address[] memory signers = new address[](3 * F + 1); address[] memory transmitters = new address[](3 * F + 1); @@ -546,7 +546,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { s_multiOCR3.setOCR3Configs(ocrConfigs); } - function test_StaticConfigChange_Revert() public { + function test_RevertWhen_StaticConfigChange() public { uint8 F = 1; _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); @@ -569,7 +569,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { s_multiOCR3.setOCR3Configs(ocrConfigs); } - function test_FTooHigh_Revert() public { + function test_RevertWhen_FTooHigh() public { address[] memory signers = new address[](0); address[] memory transmitters = new address[](1); @@ -589,7 +589,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { s_multiOCR3.setOCR3Configs(ocrConfigs); } - function test_FMustBePositive_Revert() public { + function test_RevertWhen_FMustBePositive() public { MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ ocrPluginType: 0, @@ -608,7 +608,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { s_multiOCR3.setOCR3Configs(ocrConfigs); } - function test_NoTransmitters_Revert() public { + function test_RevertWhen_NoTransmitters() public { address[] memory signers = new address[](0); address[] memory transmitters = new address[](0); @@ -628,7 +628,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { s_multiOCR3.setOCR3Configs(ocrConfigs); } - function test_TooManyTransmitters_Revert() public { + function test_RevertWhen_TooManyTransmitters() public { address[] memory signers = new address[](0); address[] memory transmitters = new address[](257); @@ -650,7 +650,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { s_multiOCR3.setOCR3Configs(ocrConfigs); } - function test_TooManySigners_Revert() public { + function test_RevertWhen_TooManySigners() public { address[] memory signers = new address[](257); MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); @@ -671,7 +671,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { s_multiOCR3.setOCR3Configs(ocrConfigs); } - function test_MoreTransmittersThanSigners_Revert() public { + function test_RevertWhen_MoreTransmittersThanSigners() public { MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ ocrPluginType: 0, diff --git a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3Base.transmit.t.sol b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3Base.transmit.t.sol index 2855b47eeea..ef75fdaf807 100644 --- a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3Base.transmit.t.sol +++ b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3Base.transmit.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {MultiOCR3Base} from "../../../ocr/MultiOCR3Base.sol"; import {MultiOCR3BaseSetup} from "./MultiOCR3BaseSetup.t.sol"; @@ -45,7 +45,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { s_multiOCR3.setOCR3Configs(ocrConfigs); } - function test_TransmitSigners_gas_Success() public { + function test_TransmitSigners_gas() public { vm.pauseGasMetering(); bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; @@ -63,7 +63,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, rawVs); } - function test_TransmitWithoutSignatureVerification_gas_Success() public { + function test_TransmitWithoutSignatureVerification_gas() public { vm.pauseGasMetering(); bytes32[2] memory reportContext = [s_configDigest3, s_configDigest3]; @@ -137,7 +137,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { } // Reverts - function test_ForkedChain_Revert() public { + function test_RevertWhen_ForkedChain() public { bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = @@ -145,7 +145,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { s_multiOCR3.setTransmitOcrPluginType(0); - uint256 chain1 = block.chainid; + uint256 chain1 = uint200(block.chainid); uint256 chain2 = chain1 + 1; vm.chainId(chain2); vm.expectRevert(abi.encodeWithSelector(MultiOCR3Base.ForkedChain.selector, chain1, chain2)); @@ -154,7 +154,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, rawVs); } - function test_ZeroSignatures_Revert() public { + function test_RevertWhen_ZeroSignatures() public { bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; s_multiOCR3.setTransmitOcrPluginType(0); @@ -164,7 +164,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { s_multiOCR3.transmitWithSignatures(reportContext, REPORT, new bytes32[](0), new bytes32[](0), bytes32("")); } - function test_TooManySignatures_Revert() public { + function test_RevertWhen_TooManySignatures() public { bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; // 1 signature too many @@ -178,7 +178,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, rawVs); } - function test_InsufficientSignatures_Revert() public { + function test_RevertWhen_InsufficientSignatures() public { bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; // Missing 1 signature for unique report @@ -192,7 +192,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, rawVs); } - function test_ConfigDigestMismatch_Revert() public { + function test_RevertWhen_ConfigDigestMismatch() public { bytes32 configDigest; bytes32[2] memory reportContext = [configDigest, configDigest]; @@ -204,7 +204,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { s_multiOCR3.transmitWithSignatures(reportContext, REPORT, new bytes32[](0), new bytes32[](0), rawVs); } - function test_SignatureOutOfRegistration_Revert() public { + function test_RevertWhen_SignatureOutOfRegistration() public { bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; bytes32[] memory rs = new bytes32[](2); @@ -217,7 +217,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, bytes32("")); } - function test_UnAuthorizedTransmitter_Revert() public { + function test_RevertWhen_UnAuthorizedTransmitter() public { bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; bytes32[] memory rs = new bytes32[](2); bytes32[] memory ss = new bytes32[](2); @@ -228,7 +228,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, bytes32("")); } - function test_NonUniqueSignature_Revert() public { + function test_RevertWhen_NonUniqueSignature() public { bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; (bytes32[] memory rs, bytes32[] memory ss, uint8[] memory vs, bytes32 rawVs) = @@ -246,7 +246,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, rawVs); } - function test_UnauthorizedSigner_Revert() public { + function test_RevertWhen_UnauthorizedSigner() public { bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = @@ -262,7 +262,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, rawVs); } - function test_UnconfiguredPlugin_Revert() public { + function test_RevertWhen_UnconfiguredPlugin() public { bytes32 configDigest; bytes32[2] memory reportContext = [configDigest, configDigest]; @@ -272,7 +272,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { s_multiOCR3.transmitWithoutSignatures(reportContext, REPORT); } - function test_TransmitWithLessCalldataArgs_Revert() public { + function test_RevertWhen_TransmitWithLessCalldataArgs() public { bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; s_multiOCR3.setTransmitOcrPluginType(0); @@ -293,7 +293,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { s_multiOCR3.transmitWithoutSignatures(reportContext, REPORT); } - function test_TransmitWithExtraCalldataArgs_Revert() public { + function test_RevertWhen_TransmitWithExtraCalldataArgs() public { bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; bytes32[] memory rs = new bytes32[](2); bytes32[] memory ss = new bytes32[](2); diff --git a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3BaseSetup.t.sol b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3BaseSetup.t.sol index 8418aa54cf1..d6325e27806 100644 --- a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3BaseSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3BaseSetup.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {MultiOCR3Base} from "../../../ocr/MultiOCR3Base.sol"; import {BaseTest} from "../../BaseTest.t.sol"; diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.afterOC3ConfigSet.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.afterOC3ConfigSet.t.sol index d2edb7a261a..9d610473277 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.afterOC3ConfigSet.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.afterOC3ConfigSet.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Internal} from "../../../libraries/Internal.sol"; import {MultiOCR3Base} from "../../../ocr/MultiOCR3Base.sol"; @@ -8,7 +8,7 @@ import {OffRampHelper} from "../../helpers/OffRampHelper.sol"; import {OffRampSetup} from "./OffRampSetup.t.sol"; contract OffRamp_afterOC3ConfigSet is OffRampSetup { - function test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() public { + function test_RevertWhen_afterOCR3ConfigSet_SignatureVerificationDisabled() public { s_offRamp = new OffRampHelper( OffRamp.StaticConfig({ chainSelector: DEST_CHAIN_SELECTOR, diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.applySourceChainConfigUpdates.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.applySourceChainConfigUpdates.t.sol index 84c522108ae..c2e1ddbce3f 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.applySourceChainConfigUpdates.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.applySourceChainConfigUpdates.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IRouter} from "../../../interfaces/IRouter.sol"; @@ -10,7 +10,7 @@ import {OffRampSetup} from "./OffRampSetup.t.sol"; import {Vm} from "forge-std/Vm.sol"; contract OffRamp_applySourceChainConfigUpdates is OffRampSetup { - function test_ApplyZeroUpdates_Success() public { + function test_ApplyZeroUpdates() public { OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](0); vm.recordLogs(); @@ -23,7 +23,7 @@ contract OffRamp_applySourceChainConfigUpdates is OffRampSetup { assertEq(s_offRamp.getSourceChainSelectors().length, 0); } - function test_AddNewChain_Success() public { + function test_AddNewChain() public { OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ router: s_destRouter, @@ -46,7 +46,7 @@ contract OffRamp_applySourceChainConfigUpdates is OffRampSetup { _assertSourceChainConfigEquality(s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR_1), expectedSourceChainConfig); } - function test_ReplaceExistingChain_Success() public { + function test_ReplaceExistingChain() public { OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ router: s_destRouter, @@ -77,7 +77,7 @@ contract OffRamp_applySourceChainConfigUpdates is OffRampSetup { assertEq(resultSourceChainSelectors.length, 1); } - function test_AddMultipleChains_Success() public { + function test_AddMultipleChains() public { OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](3); sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ router: s_destRouter, @@ -171,7 +171,7 @@ contract OffRamp_applySourceChainConfigUpdates is OffRampSetup { ); } - function test_ReplaceExistingChainOnRamp_Success() public { + function test_ReplaceExistingChainOnRamp() public { OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ router: s_destRouter, @@ -192,7 +192,7 @@ contract OffRamp_applySourceChainConfigUpdates is OffRampSetup { s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); } - function test_allowNonOnRampUpdateAfterLaneIsUsed_success() public { + function test_allowNonOnRampUpdateAfterLaneIsUsed() public { OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ router: s_destRouter, @@ -233,7 +233,7 @@ contract OffRamp_applySourceChainConfigUpdates is OffRampSetup { // Reverts - function test_ZeroOnRampAddress_Revert() public { + function test_RevertWhen_ZeroOnRampAddress() public { OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ router: s_destRouter, @@ -250,7 +250,7 @@ contract OffRamp_applySourceChainConfigUpdates is OffRampSetup { s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); } - function test_RouterAddress_Revert() public { + function test_RevertWhen_RouterAddress() public { OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ router: IRouter(address(0)), @@ -263,7 +263,7 @@ contract OffRamp_applySourceChainConfigUpdates is OffRampSetup { s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); } - function test_ZeroSourceChainSelector_Revert() public { + function test_RevertWhen_ZeroSourceChainSelector() public { OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ router: s_destRouter, @@ -276,7 +276,7 @@ contract OffRamp_applySourceChainConfigUpdates is OffRampSetup { s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); } - function test_InvalidOnRampUpdate_Revert() public { + function test_RevertWhen_InvalidOnRampUpdate() public { OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ router: s_destRouter, diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.batchExecute.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.batchExecute.t.sol index aef54612945..a170b21623c 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.batchExecute.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.batchExecute.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Internal} from "../../../libraries/Internal.sol"; import {OffRamp} from "../../../offRamp/OffRamp.sol"; @@ -15,7 +15,7 @@ contract OffRamp_batchExecute is OffRampSetup { s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_3, 1); } - function test_SingleReport_Success() public { + function test_SingleReport() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); @@ -37,7 +37,7 @@ contract OffRamp_batchExecute is OffRampSetup { assertGt(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender), nonceBefore); } - function test_MultipleReportsSameChain_Success() public { + function test_MultipleReportsSameChain() public { Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); @@ -87,7 +87,7 @@ contract OffRamp_batchExecute is OffRampSetup { assertGt(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages1[0].sender), nonceBefore); } - function test_MultipleReportsDifferentChains_Success() public { + function test_MultipleReportsDifferentChains() public { Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); @@ -143,7 +143,7 @@ contract OffRamp_batchExecute is OffRampSetup { assertGt(nonceChain3, 0); } - function test_MultipleReportsDifferentChainsSkipCursedChain_Success() public { + function test_MultipleReportsDifferentChainsSkipCursedChain() public { _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, true); Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); @@ -182,7 +182,7 @@ contract OffRamp_batchExecute is OffRampSetup { } } - function test_MultipleReportsSkipDuplicate_Success() public { + function test_MultipleReportsSkipDuplicate() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); @@ -205,7 +205,7 @@ contract OffRamp_batchExecute is OffRampSetup { ); } - function test_Unhealthy_Success() public { + function test_Unhealthy() public { _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, true); vm.expectEmit(); emit OffRamp.SkippedReportExecution(SOURCE_CHAIN_SELECTOR_1); @@ -230,12 +230,12 @@ contract OffRamp_batchExecute is OffRampSetup { } // Reverts - function test_ZeroReports_Revert() public { + function test_RevertWhen_ZeroReports() public { vm.expectRevert(OffRamp.EmptyBatch.selector); s_offRamp.batchExecute(new Internal.ExecutionReport[](0), new OffRamp.GasLimitOverride[][](1)); } - function test_OutOfBoundsGasLimitsAccess_Revert() public { + function test_RevertWhen_OutOfBoundsGasLimitsAccess() public { Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.ccipReceive.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.ccipReceive.t.sol index c05d8ec476a..320193f78a2 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.ccipReceive.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.ccipReceive.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Client} from "../../../libraries/Client.sol"; import {OffRampSetup} from "./OffRampSetup.t.sol"; diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.commit.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.commit.t.sol index 7cfb9cd36b7..f0611f8c5fc 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.commit.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.commit.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IFeeQuoter} from "../../../interfaces/IFeeQuoter.sol"; import {IRMNRemote} from "../../../interfaces/IRMNRemote.sol"; @@ -20,7 +20,7 @@ contract OffRamp_commit is OffRampSetup { s_latestSequenceNumber = uint64(uint256(s_configDigestCommit)); } - function test_ReportAndPriceUpdate_Success() public { + function test_ReportAndPriceUpdate() public { OffRamp.CommitReport memory commitReport = _constructCommitReport(); vm.expectEmit(); @@ -64,7 +64,7 @@ contract OffRamp_commit is OffRampSetup { assertEq(block.timestamp, s_offRamp.getMerkleRoot(SOURCE_CHAIN_SELECTOR_1, root)); } - function test_RootWithRMNDisabled_success() public { + function test_RootWithRMNDisabled() public { // force RMN verification to fail vm.mockCallRevert(address(s_mockRMNRemote), abi.encodeWithSelector(IRMNRemote.verify.selector), bytes("")); @@ -101,7 +101,7 @@ contract OffRamp_commit is OffRampSetup { assertEq(block.timestamp, s_offRamp.getMerkleRoot(SOURCE_CHAIN_SELECTOR_1, root)); } - function test_StaleReportWithRoot_Success() public { + function test_StaleReportWithRoot() public { uint64 maxSeq = 12; uint224 tokenStartPrice = IFeeQuoter(s_offRamp.getDynamicConfig().feeQuoter).getTokenPrice(s_sourceFeeToken).value; @@ -144,7 +144,7 @@ contract OffRamp_commit is OffRampSetup { assertEq(tokenStartPrice, IFeeQuoter(s_offRamp.getDynamicConfig().feeQuoter).getTokenPrice(s_sourceFeeToken).value); } - function test_OnlyTokenPriceUpdates_Success() public { + function test_OnlyTokenPriceUpdates() public { // force RMN verification to fail vm.mockCallRevert(address(s_mockRMNRemote), abi.encodeWithSelector(IRMNRemote.verify.selector), bytes("")); @@ -166,7 +166,7 @@ contract OffRamp_commit is OffRampSetup { assertEq(s_latestSequenceNumber, s_offRamp.getLatestPriceSequenceNumber()); } - function test_OnlyGasPriceUpdates_Success() public { + function test_OnlyGasPriceUpdates() public { // force RMN verification to fail vm.mockCallRevert(address(s_mockRMNRemote), abi.encodeWithSelector(IRMNRemote.verify.selector), bytes("")); @@ -187,7 +187,7 @@ contract OffRamp_commit is OffRampSetup { assertEq(s_latestSequenceNumber, s_offRamp.getLatestPriceSequenceNumber()); } - function test_PriceSequenceNumberCleared_Success() public { + function test_PriceSequenceNumberCleared() public { Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](0); OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), @@ -236,7 +236,7 @@ contract OffRamp_commit is OffRampSetup { _commit(commitReport, s_latestSequenceNumber); } - function test_ValidPriceUpdateThenStaleReportWithRoot_Success() public { + function test_ValidPriceUpdateThenStaleReportWithRoot() public { uint64 maxSeq = 12; uint224 tokenPrice1 = 4e18; uint224 tokenPrice2 = 5e18; @@ -282,7 +282,7 @@ contract OffRamp_commit is OffRampSetup { // Reverts - function test_UnauthorizedTransmitter_Revert() public { + function test_RevertWhen_UnauthorizedTransmitter() public { OffRamp.CommitReport memory commitReport = _constructCommitReport(); bytes32[2] memory reportContext = [s_configDigestCommit, bytes32(uint256(s_latestSequenceNumber))]; @@ -294,7 +294,7 @@ contract OffRamp_commit is OffRampSetup { s_offRamp.commit(reportContext, abi.encode(commitReport), rs, ss, rawVs); } - function test_NoConfig_Revert() public { + function test_RevertWhen_NoConfig() public { _redeployOffRampWithNoOCRConfigs(); OffRamp.CommitReport memory commitReport = _constructCommitReport(); @@ -308,7 +308,7 @@ contract OffRamp_commit is OffRampSetup { s_offRamp.commit(reportContext, abi.encode(commitReport), rs, ss, rawVs); } - function test_NoConfigWithOtherConfigPresent_Revert() public { + function test_RevertWhen_NoConfigWithOtherConfigPresent() public { _redeployOffRampWithNoOCRConfigs(); MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); @@ -333,7 +333,7 @@ contract OffRamp_commit is OffRampSetup { s_offRamp.commit(reportContext, abi.encode(commitReport), rs, ss, rawVs); } - function test_FailedRMNVerification_Reverts() public { + function test_RevertWhen_FailedRMNVerifications() public { // force RMN verification to fail vm.mockCallRevert(address(s_mockRMNRemote), abi.encodeWithSelector(IRMNRemote.verify.selector), bytes("")); @@ -342,7 +342,7 @@ contract OffRamp_commit is OffRampSetup { _commit(commitReport, s_latestSequenceNumber); } - function test_Unhealthy_Revert() public { + function test_RevertWhen_Unhealthy() public { _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, true); Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); roots[0] = Internal.MerkleRoot({ @@ -360,7 +360,7 @@ contract OffRamp_commit is OffRampSetup { _commit(commitReport, s_latestSequenceNumber); } - function test_InvalidRootRevert() public { + function test_RevertWhen_InvalidRoot() public { Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, @@ -376,7 +376,7 @@ contract OffRamp_commit is OffRampSetup { _commit(commitReport, s_latestSequenceNumber); } - function test_InvalidInterval_Revert() public { + function test_RevertWhen_InvalidInterval() public { Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, @@ -396,7 +396,7 @@ contract OffRamp_commit is OffRampSetup { _commit(commitReport, s_latestSequenceNumber); } - function test_InvalidIntervalMinLargerThanMax_Revert() public { + function test_RevertWhen_InvalidIntervalMinLargerThanMax() public { s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR); Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); roots[0] = Internal.MerkleRoot({ @@ -417,7 +417,7 @@ contract OffRamp_commit is OffRampSetup { _commit(commitReport, s_latestSequenceNumber); } - function test_ZeroEpochAndRound_Revert() public { + function test_RevertWhen_ZeroEpochAndRound() public { Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](0); OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), @@ -429,7 +429,7 @@ contract OffRamp_commit is OffRampSetup { _commit(commitReport, 0); } - function test_OnlyPriceUpdateStaleReport_Revert() public { + function test_RevertWhen_OnlyPriceUpdateStaleReport() public { Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](0); OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), @@ -445,7 +445,7 @@ contract OffRamp_commit is OffRampSetup { _commit(commitReport, s_latestSequenceNumber); } - function test_SourceChainNotEnabled_Revert() public { + function test_RevertWhen_SourceChainNotEnabled() public { Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); roots[0] = Internal.MerkleRoot({ sourceChainSelector: 0, @@ -462,7 +462,7 @@ contract OffRamp_commit is OffRampSetup { _commit(commitReport, s_latestSequenceNumber); } - function test_RootAlreadyCommitted_Revert() public { + function test_RevertWhen_RootAlreadyCommitted() public { Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, @@ -484,7 +484,7 @@ contract OffRamp_commit is OffRampSetup { _commit(commitReport, ++s_latestSequenceNumber); } - function test_CommitOnRampMismatch_Revert() public { + function test_RevertWhen_CommitOnRampMismatch() public { OffRamp.CommitReport memory commitReport = _constructCommitReport(); commitReport.merkleRoots[0].onRampAddress = ON_RAMP_ADDRESS_2; diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.constructor.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.constructor.t.sol index d31b7939d9c..49ba54dab7e 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.constructor.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.constructor.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IRMNRemote} from "../../../interfaces/IRMNRemote.sol"; @@ -10,7 +10,7 @@ import {OffRampHelper} from "../../helpers/OffRampHelper.sol"; import {OffRampSetup} from "./OffRampSetup.t.sol"; contract OffRamp_constructor is OffRampSetup { - function test_Constructor_Success() public { + function test_Constructor() public { OffRamp.StaticConfig memory staticConfig = OffRamp.StaticConfig({ chainSelector: DEST_CHAIN_SELECTOR, gasForCallExactCheck: GAS_FOR_CALL_EXACT_CHECK, @@ -126,7 +126,7 @@ contract OffRamp_constructor is OffRampSetup { } // Revert - function test_ZeroOnRampAddress_Revert() public { + function test_RevertWhen_ZeroOnRampAddress() public { uint64[] memory sourceChainSelectors = new uint64[](1); sourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; @@ -153,7 +153,7 @@ contract OffRamp_constructor is OffRampSetup { ); } - function test_SourceChainSelector_Revert() public { + function test_RevertWhen_SourceChainSelector() public { uint64[] memory sourceChainSelectors = new uint64[](1); sourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; @@ -180,7 +180,7 @@ contract OffRamp_constructor is OffRampSetup { ); } - function test_ZeroRMNRemote_Revert() public { + function test_RevertWhen_ZeroRMNRemote() public { uint64[] memory sourceChainSelectors = new uint64[](1); sourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; @@ -201,7 +201,7 @@ contract OffRamp_constructor is OffRampSetup { ); } - function test_ZeroChainSelector_Revert() public { + function test_RevertWhen_ZeroChainSelector() public { uint64[] memory sourceChainSelectors = new uint64[](1); sourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; @@ -222,7 +222,7 @@ contract OffRamp_constructor is OffRampSetup { ); } - function test_ZeroTokenAdminRegistry_Revert() public { + function test_RevertWhen_ZeroTokenAdminRegistry() public { uint64[] memory sourceChainSelectors = new uint64[](1); sourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; @@ -243,7 +243,7 @@ contract OffRamp_constructor is OffRampSetup { ); } - function test_ZeroNonceManager_Revert() public { + function test_RevertWhen_ZeroNonceManager() public { uint64[] memory sourceChainSelectors = new uint64[](1); sourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.execute.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.execute.t.sol index f12ca7b4609..8d9b91143bb 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.execute.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.execute.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IMessageInterceptor} from "../../../interfaces/IMessageInterceptor.sol"; @@ -18,7 +18,7 @@ contract OffRamp_execute is OffRampSetup { } // Asserts that execute completes - function test_SingleReport_Success() public { + function test_SingleReport() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); Internal.ExecutionReport[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); @@ -42,7 +42,7 @@ contract OffRamp_execute is OffRampSetup { ); } - function test_MultipleReports_Success() public { + function test_MultipleReports() public { Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); @@ -95,7 +95,7 @@ contract OffRamp_execute is OffRampSetup { ); } - function test_LargeBatch_Success() public { + function test_LargeBatch() public { Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](10); for (uint64 i = 0; i < reports.length; ++i) { Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](3); @@ -131,7 +131,7 @@ contract OffRamp_execute is OffRampSetup { } } - function test_MultipleReportsWithPartialValidationFailures_Success() public { + function test_MultipleReportsWithPartialValidationFailures() public { _enableInboundMessageInterceptor(); Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); @@ -197,7 +197,7 @@ contract OffRamp_execute is OffRampSetup { // Reverts - function test_UnauthorizedTransmitter_Revert() public { + function test_RevertWhen_UnauthorizedTransmitter() public { bytes32[2] memory reportContext = [s_configDigestExec, s_configDigestExec]; Internal.Any2EVMRampMessage[] memory messages = @@ -208,7 +208,7 @@ contract OffRamp_execute is OffRampSetup { s_offRamp.execute(reportContext, abi.encode(reports)); } - function test_NoConfig_Revert() public { + function test_RevertWhen_NoConfig() public { _redeployOffRampWithNoOCRConfigs(); s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 1); @@ -223,7 +223,7 @@ contract OffRamp_execute is OffRampSetup { s_offRamp.execute(reportContext, abi.encode(reports)); } - function test_NoConfigWithOtherConfigPresent_Revert() public { + function test_RevertWhen_NoConfigWithOtherConfigPresent() public { _redeployOffRampWithNoOCRConfigs(); s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 1); @@ -249,7 +249,7 @@ contract OffRamp_execute is OffRampSetup { s_offRamp.execute(reportContext, abi.encode(reports)); } - function test_WrongConfigWithSigners_Revert() public { + function test_RevertWhen_WrongConfigWithSigners() public { _redeployOffRampWithNoOCRConfigs(); s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 1); @@ -269,14 +269,14 @@ contract OffRamp_execute is OffRampSetup { s_offRamp.setOCR3Configs(ocrConfigs); } - function test_ZeroReports_Revert() public { + function test_RevertWhen_ZeroReports() public { Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](0); vm.expectRevert(OffRamp.EmptyBatch.selector); _execute(reports); } - function test_IncorrectArrayType_Revert() public { + function test_RevertWhen_IncorrectArrayType() public { bytes32[2] memory reportContext = [s_configDigestExec, s_configDigestExec]; uint256[] memory wrongData = new uint256[](2); @@ -287,7 +287,7 @@ contract OffRamp_execute is OffRampSetup { s_offRamp.execute(reportContext, abi.encode(wrongData)); } - function test_NonArray_Revert() public { + function test_RevertWhen_NonArray() public { bytes32[2] memory reportContext = [s_configDigestExec, s_configDigestExec]; Internal.Any2EVMRampMessage[] memory messages = diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.executeSingleMessage.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.executeSingleMessage.t.sol index 20b711f529e..40535ad4f7f 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.executeSingleMessage.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.executeSingleMessage.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IMessageInterceptor} from "../../../interfaces/IMessageInterceptor.sol"; import {IRouter} from "../../../interfaces/IRouter.sol"; @@ -106,7 +106,7 @@ contract OffRamp_executeSingleMessage is OffRampSetup { // Reverts - function test_executeSingleMessage_RevertWhen_TokenHandlingError() public { + function test_RevertWhen_executeSingleMessageWhen_TokenHandlingError() public { Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageWithMaybeRevertingSingleToken(1, 50); address destPool = s_destPoolByToken[message.tokenAmounts[0].destTokenAddress]; @@ -119,7 +119,7 @@ contract OffRamp_executeSingleMessage is OffRampSetup { s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } - function test_executeSingleMessage_RevertWhen_ZeroGasDONExecution() public { + function test_RevertWhen_executeSingleMessageWhen_ZeroGasDONExecution() public { Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); message.gasLimit = 0; @@ -129,7 +129,7 @@ contract OffRamp_executeSingleMessage is OffRampSetup { s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } - function test_executeSingleMessage_RevertWhen_MessageSender() public { + function test_RevertWhen_executeSingleMessageWhen_MessageSender() public { vm.stopPrank(); Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); @@ -137,7 +137,7 @@ contract OffRamp_executeSingleMessage is OffRampSetup { s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } - function test_executeSingleMessage_RevertWhen_MessageValidationError() public { + function test_RevertWhen_executeSingleMessageWhen_MessageValidationError() public { vm.stopPrank(); vm.startPrank(OWNER); _enableInboundMessageInterceptor(); @@ -154,7 +154,7 @@ contract OffRamp_executeSingleMessage is OffRampSetup { s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } - function test_executeSingleMessage_RevertWhen_WithFailingValidationNoRouterCall() public { + function test_RevertWhen_executeSingleMessageWhen_WithFailingValidationNoRouterCall() public { vm.stopPrank(); vm.startPrank(OWNER); _enableInboundMessageInterceptor(); diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.executeSingleReport.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.executeSingleReport.t.sol index 7facff30cc4..d5bb32a8a12 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.executeSingleReport.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.executeSingleReport.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {CallWithExactGas} from "../../../../shared/call/CallWithExactGas.sol"; import {NonceManager} from "../../../NonceManager.sol"; @@ -22,7 +22,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_3, 1); } - function test_SingleMessageNoTokens_Success() public { + function test_SingleMessageNoTokens() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); @@ -59,7 +59,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { assertGt(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender), nonceBefore); } - function test_SingleMessageNoTokensUnordered_Success() public { + function test_SingleMessageNoTokensUnordered() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].header.nonce = 0; @@ -110,7 +110,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); } - function test_SingleMessageNoTokensOtherChain_Success() public { + function test_SingleMessageNoTokensOtherChain() public { Internal.Any2EVMRampMessage[] memory messagesChain1 = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); s_offRamp.executeSingleReport( @@ -133,7 +133,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { assertEq(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messagesChain1[0].sender), nonceChain1); } - function test_ReceiverError_Success() public { + function test_ReceiverError() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); @@ -165,7 +165,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { assertEq(uint64(1), s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(OWNER))); } - function test_SkippedIncorrectNonce_Success() public { + function test_SkippedIncorrectNonce() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); @@ -182,7 +182,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); } - function test_SkippedIncorrectNonceStillExecutes_Success() public { + function test_SkippedIncorrectNonceStillExecutes() public { Internal.Any2EVMRampMessage[] memory messages = _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); @@ -206,7 +206,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); } - function test__execute_SkippedAlreadyExecutedMessage_Success() public { + function test__execute_SkippedAlreadyExecutedMessage() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); @@ -231,7 +231,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); } - function test__execute_SkippedAlreadyExecutedMessageUnordered_Success() public { + function test__execute_SkippedAlreadyExecutedMessageUnordered() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].header.nonce = 0; @@ -260,7 +260,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { // Send a message to a contract that does not implement the CCIPReceiver interface // This should execute successfully. - function test_SingleMessageToNonCCIPReceiver_Success() public { + function test_SingleMessageToNonCCIPReceiver() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); MaybeRevertMessageReceiverNo165 newReceiver = new MaybeRevertMessageReceiverNo165(true); @@ -337,7 +337,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); } - function test_TwoMessagesWithTokensAndGE_Success() public { + function test_TwoMessagesWithTokensAndGE() public { Internal.Any2EVMRampMessage[] memory messages = _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); // Set message 1 to use another receiver to simulate more fair gas costs @@ -456,7 +456,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); } - function test_WithCurseOnAnotherSourceChain_Success() public { + function test_WithCurseOnAnotherSourceChain() public { _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_2, true); s_offRamp.executeSingleReport( _generateReportFromMessages( @@ -466,7 +466,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); } - function test_Unhealthy_Success() public { + function test_Unhealthy() public { _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, true); vm.expectEmit(); @@ -492,7 +492,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { // Reverts - function test_MismatchingDestChainSelector_Revert() public { + function test_RevertWhen_MismatchingDestChainSelector() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3); messages[0].header.destChainSelector = DEST_CHAIN_SELECTOR + 1; @@ -505,7 +505,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { s_offRamp.executeSingleReport(executionReport, new OffRamp.GasLimitOverride[](0)); } - function test_UnhealthySingleChainCurse_Revert() public { + function test_RevertWhen_UnhealthySingleChainCurse() public { _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, true); vm.expectEmit(); emit OffRamp.SkippedReportExecution(SOURCE_CHAIN_SELECTOR_1); @@ -527,7 +527,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { _assertNoEmit(OffRamp.SkippedReportExecution.selector); } - function test_UnexpectedTokenData_Revert() public { + function test_RevertWhen_UnexpectedTokenData() public { Internal.ExecutionReport memory report = _generateReportFromMessages( SOURCE_CHAIN_SELECTOR_1, _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) ); @@ -538,7 +538,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { s_offRamp.executeSingleReport(report, new OffRamp.GasLimitOverride[](0)); } - function test_EmptyReport_Revert() public { + function test_RevertWhen_EmptyReport() public { vm.expectRevert(abi.encodeWithSelector(OffRamp.EmptyReport.selector, SOURCE_CHAIN_SELECTOR_1)); s_offRamp.executeSingleReport( @@ -553,7 +553,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); } - function test_RootNotCommitted_Revert() public { + function test_RevertWhen_RootNotCommitted() public { s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 0); vm.expectRevert(abi.encodeWithSelector(OffRamp.RootNotCommitted.selector, SOURCE_CHAIN_SELECTOR_1)); @@ -564,7 +564,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); } - function test_ManualExecutionNotYetEnabled_Revert() public { + function test_RevertWhen_ManualExecutionNotYetEnabled() public { s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, BLOCK_TIME); vm.expectRevert(abi.encodeWithSelector(OffRamp.ManualExecutionNotYetEnabled.selector, SOURCE_CHAIN_SELECTOR_1)); @@ -576,7 +576,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); } - function test_NonExistingSourceChain_Revert() public { + function test_RevertWhen_NonExistingSourceChain() public { uint64 newSourceChainSelector = SOURCE_CHAIN_SELECTOR_1 + 1; bytes memory newOnRamp = abi.encode(ON_RAMP_ADDRESS, 1); @@ -588,7 +588,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); } - function test_DisabledSourceChain_Revert() public { + function test_RevertWhen_DisabledSourceChain() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_2, ON_RAMP_ADDRESS_2); @@ -598,7 +598,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); } - function test_TokenDataMismatch_Revert() public { + function test_RevertWhen_TokenDataMismatch() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); Internal.ExecutionReport memory report = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); @@ -613,7 +613,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { s_offRamp.executeSingleReport(report, new OffRamp.GasLimitOverride[](0)); } - function test_RouterYULCall_Revert() public { + function test_RevertWhen_RouterYULCall() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); @@ -636,7 +636,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); } - function test_RetryFailedMessageWithoutManualExecution_Revert() public { + function test_RevertWhen_RetryFailedMessageWithoutManualExecution() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.getExecutionState.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.getExecutionState.t.sol index ac9cfe86cd9..96261f5f0b3 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.getExecutionState.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.getExecutionState.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Internal} from "../../../libraries/Internal.sol"; import {OffRampSetup} from "./OffRampSetup.t.sol"; @@ -32,7 +32,7 @@ contract OffRamp_getExecutionState is OffRampSetup { } } - function test_GetExecutionState_Success() public { + function test_GetExecutionState() public { s_offRamp.setExecutionStateHelper(SOURCE_CHAIN_SELECTOR_1, 0, Internal.MessageExecutionState.FAILURE); assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, 0), 3); @@ -72,7 +72,7 @@ contract OffRamp_getExecutionState is OffRampSetup { ); } - function test_GetDifferentChainExecutionState_Success() public { + function test_GetDifferentChainExecutionState() public { s_offRamp.setExecutionStateHelper(SOURCE_CHAIN_SELECTOR_1, 0, Internal.MessageExecutionState.FAILURE); assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, 0), 3); assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1 + 1, 0), 0); @@ -119,7 +119,7 @@ contract OffRamp_getExecutionState is OffRampSetup { ); } - function test_FillExecutionState_Success() public { + function test_FillExecutionState() public { for (uint64 i = 0; i < 384; ++i) { s_offRamp.setExecutionStateHelper(SOURCE_CHAIN_SELECTOR_1, i, Internal.MessageExecutionState.FAILURE); } diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.manuallyExecute.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.manuallyExecute.t.sol index 0422053bdd7..d2406a0e40b 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.manuallyExecute.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.manuallyExecute.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Internal} from "../../../libraries/Internal.sol"; import {MultiOCR3Base} from "../../../ocr/MultiOCR3Base.sol"; @@ -23,7 +23,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_3, 1); } - function test_manuallyExecute_Success() public { + function test_manuallyExecute() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].receiver = address(s_reverting_receiver); @@ -49,7 +49,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { ); } - function test_manuallyExecute_WithGasOverride_Success() public { + function test_manuallyExecute_WithGasOverride() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].receiver = address(s_reverting_receiver); @@ -75,7 +75,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { ); } - function test_manuallyExecute_DoesNotRevertIfUntouched_Success() public { + function test_manuallyExecute_DoesNotRevertIfUntouched() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].receiver = address(s_reverting_receiver); @@ -108,7 +108,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { ); } - function test_manuallyExecute_WithMultiReportGasOverride_Success() public { + function test_manuallyExecute_WithMultiReportGasOverride() public { Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](3); Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](2); @@ -174,7 +174,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { } } - function test_manuallyExecute_WithPartialMessages_Success() public { + function test_manuallyExecute_WithPartialMessages() public { Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](3); for (uint64 i = 0; i < 3; ++i) { @@ -246,7 +246,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { ); } - function test_manuallyExecute_LowGasLimit_Success() public { + function test_manuallyExecute_LowGasLimit() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].gasLimit = 1; @@ -287,12 +287,12 @@ contract OffRamp_manuallyExecute is OffRampSetup { // Reverts - function test_manuallyExecute_ForkedChain_Revert() public { + function test_RevertWhen_manuallyExecute_ForkedChain() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); Internal.ExecutionReport[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - uint256 chain1 = block.chainid; + uint256 chain1 = uint200(block.chainid); uint256 chain2 = chain1 + 1; vm.chainId(chain2); vm.expectRevert(abi.encodeWithSelector(MultiOCR3Base.ForkedChain.selector, chain1, chain2)); @@ -303,7 +303,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { s_offRamp.manuallyExecute(reports, gasLimitOverrides); } - function test_ManualExecGasLimitMismatchSingleReport_Revert() public { + function test_RevertWhen_ManualExecGasLimitMismatchSingleReport() public { Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](2); messages[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); messages[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2); @@ -333,7 +333,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { s_offRamp.manuallyExecute(reports, gasLimitOverrides); } - function test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() public { + function test_RevertWhen_manuallyExecute_GasLimitMismatchMultipleReports() public { Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); @@ -376,7 +376,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { s_offRamp.manuallyExecute(reports, gasLimitOverrides); } - function test_manuallyExecute_InvalidReceiverExecutionGasLimit_Revert() public { + function test_RevertWhen_manuallyExecute_InvalidReceiverExecutionGasLimit() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); @@ -395,7 +395,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); } - function test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() public { + function test_RevertWhen_manuallyExecute_DestinationGasAmountCountMismatch() public { uint256[] memory amounts = new uint256[](2); amounts[0] = 1000; amounts[1] = 1000; @@ -418,7 +418,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); } - function test_manuallyExecute_InvalidTokenGasOverride_Revert() public { + function test_RevertWhen_manuallyExecute_InvalidTokenGasOverride() public { uint256[] memory amounts = new uint256[](2); amounts[0] = 1000; amounts[1] = 1000; @@ -444,7 +444,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); } - function test_manuallyExecute_FailedTx_Revert() public { + function test_RevertWhen_manuallyExecute_FailedTx() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); @@ -473,7 +473,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); } - function test_manuallyExecute_ReentrancyFails_Success() public { + function test_manuallyExecute_ReentrancyFails() public { uint256 tokenAmount = 1e9; IERC20 tokenToAbuse = IERC20(s_destFeeToken); @@ -531,7 +531,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { assertEq(tokenToAbuse.balanceOf(address(receiver)), balancePre + tokenAmount); } - function test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() public { + function test_RevertWhen_manuallyExecute_MultipleReportsWithSingleCursedLane() public { Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](3); Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](2); @@ -562,7 +562,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { s_offRamp.manuallyExecute(reports, gasLimitOverrides); } - function test_manuallyExecute_SourceChainSelectorMismatch_Revert() public { + function test_RevertWhen_manuallyExecute_SourceChainSelectorMismatch() public { Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](1); Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); messages1[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.releaseOrMintSingleToken.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.releaseOrMintSingleToken.t.sol index f35db67abf6..c30cdeb4d93 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.releaseOrMintSingleToken.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.releaseOrMintSingleToken.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {ITokenAdminRegistry} from "../../../interfaces/ITokenAdminRegistry.sol"; @@ -17,7 +17,7 @@ contract OffRamp_releaseOrMintSingleToken is OffRampSetup { _setupMultipleOffRamps(); } - function test__releaseOrMintSingleToken_Success() public { + function test__releaseOrMintSingleToken() public { uint256 amount = 123123; address token = s_sourceTokens[0]; bytes memory originalSender = abi.encode(OWNER); @@ -56,7 +56,7 @@ contract OffRamp_releaseOrMintSingleToken is OffRampSetup { assertEq(startingBalance + amount, dstToken1.balanceOf(OWNER)); } - function test_releaseOrMintToken_InvalidDataLength_Revert() public { + function test_RevertWhen_releaseOrMintToken_InvalidDataLength() public { uint256 amount = 123123; address token = s_sourceTokens[0]; @@ -78,7 +78,7 @@ contract OffRamp_releaseOrMintSingleToken is OffRampSetup { s_offRamp.releaseOrMintSingleToken(tokenAmount, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR, ""); } - function test_releaseOrMintToken_RevertWhen_TokenHandlingError_BalanceOf() public { + function test_RevertWhen_releaseOrMintTokenWhen_TokenHandlingError_BalanceOf() public { uint256 amount = 123123; address token = s_sourceTokens[0]; address destTokenAddress = s_destTokenBySourceToken[token]; @@ -101,7 +101,7 @@ contract OffRamp_releaseOrMintSingleToken is OffRampSetup { s_offRamp.releaseOrMintSingleToken(tokenAmount, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR, ""); } - function test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() public { + function test_RevertWhen_releaseOrMintToken_ReleaseOrMintBalanceMismatch() public { uint256 amount = 123123; address token = s_sourceTokens[0]; uint256 mockedStaticBalance = 50000; @@ -129,7 +129,7 @@ contract OffRamp_releaseOrMintSingleToken is OffRampSetup { s_offRamp.releaseOrMintSingleToken(tokenAmount, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR, ""); } - function test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() public { + function test_RevertWhen_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool() public { uint256 amount = 123123; address token = s_sourceTokens[0]; uint256 mockedStaticBalance = 50000; @@ -154,7 +154,7 @@ contract OffRamp_releaseOrMintSingleToken is OffRampSetup { ); } - function test__releaseOrMintSingleToken_NotACompatiblePool_Revert() public { + function test_RevertWhen__releaseOrMintSingleToken_NotACompatiblePool() public { uint256 amount = 123123; address token = s_sourceTokens[0]; address destToken = s_destTokenBySourceToken[token]; @@ -197,7 +197,7 @@ contract OffRamp_releaseOrMintSingleToken is OffRampSetup { s_offRamp.releaseOrMintSingleToken(tokenAmount, originalSender, OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData); } - function test_releaseOrMintSingleToken_RevertWhen_TokenHandlingError_transfer() public { + function test_RevertWhen_releaseOrMintSingleTokenWhen_TokenHandlingError_transfer() public { address receiver = makeAddr("receiver"); uint256 amount = 123123; address token = s_sourceTokens[0]; diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.releaseOrMintTokens.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.releaseOrMintTokens.t.sol index d2636ee08c8..07cf730c9d6 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.releaseOrMintTokens.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.releaseOrMintTokens.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {CallWithExactGas} from "../../../../shared/call/CallWithExactGas.sol"; import {Client} from "../../../libraries/Client.sol"; @@ -118,7 +118,7 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { // Revert - function test_releaseOrMintTokens_RevertWhen_TokenHandlingError() public { + function test_RevertWhen_releaseOrMintTokensWhen_TokenHandlingError() public { Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); bytes memory unknownError = bytes("unknown error"); @@ -138,7 +138,7 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { ); } - function test_releaseOrMintTokens_RevertWhenInvalidDataLengthReturnData() public { + function test_RevertWhen_releaseOrMintTokensWhenInvalidDataLengthReturnData() public { uint256 amount = 100; Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); srcTokenAmounts[0].amount = amount; @@ -172,7 +172,7 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { ); } - function test_releaseOrMintTokens_RevertWhen_PoolIsNotAPool() public { + function test_RevertWhen_releaseOrMintTokensWhen_PoolIsNotAPool() public { // The offRamp is a contract, but not a pool address fakePoolAddress = address(s_offRamp); @@ -191,7 +191,7 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { ); } - function test_releaseOrMintTokens_RevertWhenPoolDoesNotSupportDest() public { + function test_RevertWhen_releaseOrMintTokensWhenPoolDoesNotSupportDest() public { Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); uint256 amount1 = 100; srcTokenAmounts[0].amount = amount1; diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.setDynamicConfig.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.setDynamicConfig.t.sol index 384d9b446aa..93857ecfc07 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.setDynamicConfig.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.setDynamicConfig.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; import {OffRamp} from "../../../offRamp/OffRamp.sol"; import {OffRampSetup} from "./OffRampSetup.t.sol"; contract OffRamp_setDynamicConfig is OffRampSetup { - function test_SetDynamicConfig_Success() public { + function test_SetDynamicConfig() public { OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(address(s_feeQuoter)); vm.expectEmit(); @@ -18,7 +18,7 @@ contract OffRamp_setDynamicConfig is OffRampSetup { _assertSameConfig(dynamicConfig, newConfig); } - function test_SetDynamicConfigWithInterceptor_Success() public { + function test_SetDynamicConfigWithInterceptor() public { OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(address(s_feeQuoter)); dynamicConfig.messageInterceptor = address(s_inboundMessageInterceptor); @@ -33,7 +33,7 @@ contract OffRamp_setDynamicConfig is OffRampSetup { // Reverts - function test_NonOwner_Revert() public { + function test_RevertWhen_NonOwner() public { vm.startPrank(STRANGER); OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(address(s_feeQuoter)); @@ -42,7 +42,7 @@ contract OffRamp_setDynamicConfig is OffRampSetup { s_offRamp.setDynamicConfig(dynamicConfig); } - function test_FeeQuoterZeroAddress_Revert() public { + function test_RevertWhen_FeeQuoterZeroAddress() public { OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(address(0)); vm.expectRevert(OffRamp.ZeroAddressNotAllowed.selector); diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.trialExecute.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.trialExecute.t.sol index 807cea5e268..6b72b25bb61 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.trialExecute.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.trialExecute.t.sol @@ -1,8 +1,10 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; +import {CallWithExactGas} from "../../../../shared/call/CallWithExactGas.sol"; import {Internal} from "../../../libraries/Internal.sol"; import {RateLimiter} from "../../../libraries/RateLimiter.sol"; +import {MultiOCR3Base} from "../../../ocr/MultiOCR3Base.sol"; import {OffRamp} from "../../../offRamp/OffRamp.sol"; import {OffRampSetup} from "./OffRampSetup.t.sol"; @@ -117,4 +119,59 @@ contract OffRamp_trialExecute is OffRampSetup { assertEq(uint256(Internal.MessageExecutionState.FAILURE), uint256(newState)); assertEq(abi.encodeWithSelector(OffRamp.NotACompatiblePool.selector, address(0)), err); } + + function test_trialExecute_CallWithExactGasRevertsAndSenderIsNotGasEstimator() public { + Internal.Any2EVMRampMessage memory message = + _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); + + bytes[] memory offchainTokenData = new bytes[](message.tokenAmounts.length); + uint32[] memory tokenGasOverrides = new uint32[](0); + + vm.mockCallRevert( + address(s_offRamp), + abi.encodeCall(s_offRamp.executeSingleMessage, (message, offchainTokenData, tokenGasOverrides)), + abi.encodeWithSelector(CallWithExactGas.NOT_ENOUGH_GAS_FOR_CALL_SIG, "") + ); + + (Internal.MessageExecutionState newState, bytes memory err) = + s_offRamp.trialExecute(message, offchainTokenData, tokenGasOverrides); + assertEq(uint256(Internal.MessageExecutionState.FAILURE), uint256(newState)); + assertEq(CallWithExactGas.NotEnoughGasForCall.selector, bytes4(err)); + } + + function test_trialExecute_RevertsWhen_NoGasForCallExactCheckAndSenderIsGasEstimator() public { + Internal.Any2EVMRampMessage memory message = + _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); + + bytes[] memory offchainTokenData = new bytes[](message.tokenAmounts.length); + uint32[] memory tokenGasOverrides = new uint32[](0); + + vm.mockCallRevert( + address(s_offRamp), + abi.encodeCall(s_offRamp.executeSingleMessage, (message, offchainTokenData, tokenGasOverrides)), + abi.encodeWithSelector(CallWithExactGas.NO_GAS_FOR_CALL_EXACT_CHECK_SIG, "") + ); + + changePrank(Internal.GAS_ESTIMATION_SENDER); + vm.expectRevert(MultiOCR3Base.InsufficientGasForCallWithExact.selector); + s_offRamp.trialExecute(message, offchainTokenData, tokenGasOverrides); + } + + function test_trialExecute_RevertsWhen_NoEnoughGasForCallSigAndSenderIsGasEstimator() public { + Internal.Any2EVMRampMessage memory message = + _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); + + bytes[] memory offchainTokenData = new bytes[](message.tokenAmounts.length); + uint32[] memory tokenGasOverrides = new uint32[](0); + + vm.mockCallRevert( + address(s_offRamp), + abi.encodeCall(s_offRamp.executeSingleMessage, (message, offchainTokenData, tokenGasOverrides)), + abi.encodeWithSelector(CallWithExactGas.NOT_ENOUGH_GAS_FOR_CALL_SIG, "") + ); + + changePrank(Internal.GAS_ESTIMATION_SENDER); + vm.expectRevert(MultiOCR3Base.InsufficientGasForCallWithExact.selector); + s_offRamp.trialExecute(message, offchainTokenData, tokenGasOverrides); + } } diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRampSetup.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRampSetup.t.sol index f8b70ebf283..daf496c9d75 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRampSetup.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IAny2EVMMessageReceiver} from "../../../interfaces/IAny2EVMMessageReceiver.sol"; import {IRMNRemote} from "../../../interfaces/IRMNRemote.sol"; diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.applyDestChainConfigUpdates.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.applyDestChainConfigUpdates.t.sol index 2b99fd423be..ff385104f9b 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.applyDestChainConfigUpdates.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.applyDestChainConfigUpdates.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IRouter} from "../../../interfaces/IRouter.sol"; @@ -7,7 +7,7 @@ import {OnRamp} from "../../../onRamp/OnRamp.sol"; import {OnRampSetup} from "./OnRampSetup.t.sol"; contract OnRamp_applyDestChainConfigUpdates is OnRampSetup { - function test_ApplyDestChainConfigUpdates_Success() external { + function test_ApplyDestChainConfigUpdates() external { OnRamp.DestChainConfigArgs[] memory configArgs = new OnRamp.DestChainConfigArgs[](1); configArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; @@ -53,7 +53,7 @@ contract OnRamp_applyDestChainConfigUpdates is OnRampSetup { assertEq(numLogs, vm.getRecordedLogs().length); // indicates no changes made } - function test_ApplyDestChainConfigUpdates_WithInvalidChainSelector_Revert() external { + function test_RevertWhen_ApplyDestChainConfigUpdates_WithInvalidChainSelector() external { OnRamp.DestChainConfigArgs[] memory configArgs = new OnRamp.DestChainConfigArgs[](1); configArgs[0].destChainSelector = 0; // invalid vm.expectRevert(abi.encodeWithSelector(OnRamp.InvalidDestChainConfig.selector, 0)); @@ -62,7 +62,7 @@ contract OnRamp_applyDestChainConfigUpdates is OnRampSetup { } contract OnRamp_applyAllowlistUpdates is OnRampSetup { - function test_applyAllowlistUpdates_Success() public { + function test_applyAllowlistUpdates() public { OnRamp.DestChainConfigArgs[] memory configArgs = new OnRamp.DestChainConfigArgs[](2); configArgs[0] = OnRamp.DestChainConfigArgs({ destChainSelector: DEST_CHAIN_SELECTOR, @@ -162,7 +162,7 @@ contract OnRamp_applyAllowlistUpdates is OnRampSetup { assertTrue(isActive); } - function test_applyAllowlistUpdates_Revert() public { + function test_RevertWhen_applyAllowlistUpdates() public { OnRamp.DestChainConfigArgs[] memory configArgs = new OnRamp.DestChainConfigArgs[](2); configArgs[0] = OnRamp.DestChainConfigArgs({ destChainSelector: DEST_CHAIN_SELECTOR, diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.constructor.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.constructor.t.sol index 1e31a2a1377..70153562e54 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.constructor.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.constructor.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IRMNRemote} from "../../../interfaces/IRMNRemote.sol"; import {IRouter} from "../../../interfaces/IRouter.sol"; @@ -10,7 +10,7 @@ import {OnRampHelper} from "../../helpers/OnRampHelper.sol"; import {OnRampSetup} from "./OnRampSetup.t.sol"; contract OnRamp_constructor is OnRampSetup { - function test_Constructor_Success() public { + function test_Constructor() public { OnRamp.StaticConfig memory staticConfig = OnRamp.StaticConfig({ chainSelector: SOURCE_CHAIN_SELECTOR, rmnRemote: s_mockRMNRemote, @@ -41,7 +41,7 @@ contract OnRamp_constructor is OnRampSetup { assertEq(1, s_onRamp.getExpectedNextSequenceNumber(DEST_CHAIN_SELECTOR)); } - function test_Constructor_EnableAllowList_ForwardFromRouter_Reverts() public { + function test_RevertWhen_Constructor_EnableAllowList_ForwardFromRouter() public { OnRamp.StaticConfig memory staticConfig = OnRamp.StaticConfig({ chainSelector: SOURCE_CHAIN_SELECTOR, rmnRemote: s_mockRMNRemote, @@ -74,7 +74,7 @@ contract OnRamp_constructor is OnRampSetup { tempOnRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); } - function test_Constructor_InvalidConfigChainSelectorEqZero_Revert() public { + function test_RevertWhen_Constructor_InvalidConfigChainSelectorEqZero() public { vm.expectRevert(OnRamp.InvalidConfig.selector); new OnRampHelper( OnRamp.StaticConfig({ @@ -88,7 +88,7 @@ contract OnRamp_constructor is OnRampSetup { ); } - function test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() public { + function test_RevertWhen_Constructor_InvalidConfigRMNProxyEqAddressZero() public { vm.expectRevert(OnRamp.InvalidConfig.selector); s_onRamp = new OnRampHelper( OnRamp.StaticConfig({ @@ -102,7 +102,7 @@ contract OnRamp_constructor is OnRampSetup { ); } - function test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() public { + function test_RevertWhen_Constructor_InvalidConfigNonceManagerEqAddressZero() public { vm.expectRevert(OnRamp.InvalidConfig.selector); new OnRampHelper( OnRamp.StaticConfig({ @@ -116,7 +116,7 @@ contract OnRamp_constructor is OnRampSetup { ); } - function test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() public { + function test_RevertWhen_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero() public { vm.expectRevert(OnRamp.InvalidConfig.selector); new OnRampHelper( OnRamp.StaticConfig({ diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.forwardFromRouter.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.forwardFromRouter.t.sol index 7f53f9c5b3c..8168cff7e1c 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.forwardFromRouter.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.forwardFromRouter.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IMessageInterceptor} from "../../../interfaces/IMessageInterceptor.sol"; import {IRouter} from "../../../interfaces/IRouter.sol"; @@ -68,7 +68,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); } - function test_ForwardFromRouter_Success_ConfigurableSourceRouter() public { + function test_ForwardFromRouter_ConfigurableSourceRouter() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT * 2})); uint256 feeAmount = 1234567890; @@ -117,7 +117,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); } - function test_ForwardFromRouter_Success() public { + function test_ForwardFromRouter() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); uint256 feeAmount = 1234567890; @@ -129,7 +129,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); } - function test_ForwardFromRouterExtraArgsV2_Success() public { + function test_ForwardFromRouterExtraArgsV2() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.extraArgs = abi.encodeWithSelector( Client.EVM_EXTRA_ARGS_V2_TAG, Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT * 2, allowOutOfOrderExecution: false}) @@ -143,7 +143,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); } - function test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() public { + function test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.extraArgs = abi.encodeWithSelector( Client.EVM_EXTRA_ARGS_V2_TAG, Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT * 2, allowOutOfOrderExecution: true}) @@ -157,7 +157,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); } - function test_ShouldIncrementSeqNumAndNonce_Success() public { + function test_ShouldIncrementSeqNumAndNonce() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); for (uint64 i = 1; i < 4; ++i) { @@ -176,7 +176,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { } } - function test_ShouldIncrementNonceOnlyOnOrdered_Success() public { + function test_ShouldIncrementNonceOnlyOnOrdered() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.extraArgs = abi.encodeWithSelector( Client.EVM_EXTRA_ARGS_V2_TAG, Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT * 2, allowOutOfOrderExecution: true}) @@ -212,32 +212,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { assertEq(IERC20(s_sourceFeeToken).balanceOf(address(s_onRamp)), feeAmount); } - function test_ShouldStoreNonLinkFees() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.feeToken = s_sourceTokens[1]; - - uint256 feeAmount = 1234567890; - IERC20(s_sourceTokens[1]).transferFrom(OWNER, address(s_onRamp), feeAmount); - - // Calculate conversion done by prices contract - uint256 feeTokenPrice = s_feeQuoter.getTokenPrice(s_sourceTokens[1]).value; - uint256 linkTokenPrice = s_feeQuoter.getTokenPrice(s_sourceFeeToken).value; - uint256 conversionRate = (feeTokenPrice * 1e18) / linkTokenPrice; - uint256 expectedJuels = (feeAmount * conversionRate) / 1e18; - - vm.expectEmit(); - emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, feeAmount, expectedJuels, OWNER)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - - assertEq(IERC20(s_sourceTokens[1]).balanceOf(address(s_onRamp)), feeAmount); - } - // Make sure any valid sender, receiver and feeAmount can be handled. - // @TODO Temporarily setting lower fuzz run as 256 triggers snapshot gas off by 1 error. - // https://github.com/foundry-rs/foundry/issues/5689 - /// forge-dynamicConfig: default.fuzz.runs = 32 - /// forge-dynamicConfig: ccip.fuzz.runs = 32 function testFuzz_ForwardFromRouter_Success(address originalSender, address receiver, uint96 feeTokenAmount) public { // To avoid RouterMustSetOriginalSender vm.assume(originalSender != address(0)); @@ -250,14 +225,13 @@ contract OnRamp_forwardFromRouter is OnRampSetup { destinationChainSelectors[0] = uint64(DEST_CHAIN_SELECTOR); address[] memory addAllowedList = new address[](1); addAllowedList[0] = originalSender; - OnRamp.AllowlistConfigArgs memory allowlistConfigArgs = OnRamp.AllowlistConfigArgs({ + OnRamp.AllowlistConfigArgs[] memory applyAllowlistConfigArgsItems = new OnRamp.AllowlistConfigArgs[](1); + applyAllowlistConfigArgsItems[0] = OnRamp.AllowlistConfigArgs({ allowlistEnabled: true, destChainSelector: DEST_CHAIN_SELECTOR, addedAllowlistedSenders: addAllowedList, removedAllowlistedSenders: new address[](0) }); - OnRamp.AllowlistConfigArgs[] memory applyAllowlistConfigArgsItems = new OnRamp.AllowlistConfigArgs[](1); - applyAllowlistConfigArgsItems[0] = allowlistConfigArgs; s_onRamp.applyAllowlistUpdates(applyAllowlistConfigArgsItems); vm.stopPrank(); @@ -271,9 +245,6 @@ contract OnRamp_forwardFromRouter is OnRampSetup { Internal.EVM2AnyRampMessage memory expectedEvent = _messageToEvent(message, 1, 1, feeTokenAmount, originalSender); - vm.expectEmit(); - emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, expectedEvent.header.sequenceNumber, expectedEvent); - // Assert the message Id is correct assertEq( expectedEvent.header.messageId, @@ -281,7 +252,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { ); } - function test_forwardFromRouter_WithInterception_Success() public { + function test_forwardFromRouter_WithInterception() public { _enableOutboundMessageInterceptor(); Client.EVM2AnyMessage memory message = _generateEmptyMessage(); @@ -301,7 +272,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { // Reverts - function test_Paused_Revert() public { + function test_RevertWhen_Paused() public { // We pause by disabling the whitelist vm.stopPrank(); vm.startPrank(OWNER); @@ -310,7 +281,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), 0, OWNER); } - function test_InvalidExtraArgsTag_Revert() public { + function test_RevertWhen_InvalidExtraArgsTag() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.extraArgs = bytes("bad args"); @@ -319,26 +290,26 @@ contract OnRamp_forwardFromRouter is OnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); } - function test_Permissions_Revert() public { + function test_RevertWhen_Permissions() public { vm.stopPrank(); vm.startPrank(OWNER); vm.expectRevert(OnRamp.MustBeCalledByRouter.selector); s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), 0, OWNER); } - function test_OriginalSender_Revert() public { + function test_RevertWhen_OriginalSender() public { vm.expectRevert(OnRamp.RouterMustSetOriginalSender.selector); s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), 0, address(0)); } - function test_UnAllowedOriginalSender_Revert() public { + function test_RevertWhen_UnAllowedOriginalSender() public { vm.stopPrank(); vm.startPrank(STRANGER); vm.expectRevert(abi.encodeWithSelector(OnRamp.SenderNotAllowed.selector, STRANGER)); s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), 0, STRANGER); } - function test_MessageInterceptionError_Revert() public { + function test_RevertWhen_MessageInterceptionError() public { _enableOutboundMessageInterceptor(); Client.EVM2AnyMessage memory message = _generateEmptyMessage(); @@ -357,7 +328,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); } - function test_MultiCannotSendZeroTokens_Revert() public { + function test_RevertWhen_MultiCannotSendZeroTokens() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.tokenAmounts = new Client.EVMTokenAmount[](1); message.tokenAmounts[0].amount = 0; @@ -366,7 +337,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); } - function test_UnsupportedToken_Revert() public { + function test_RevertWhen_UnsupportedToken() public { address wrongToken = address(1); Client.EVM2AnyMessage memory message = _generateEmptyMessage(); @@ -389,7 +360,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); } - function test_forwardFromRouter_UnsupportedToken_Revert() public { + function test_RevertWhen_forwardFromRouter_UnsupportedToken() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.tokenAmounts = new Client.EVMTokenAmount[](1); message.tokenAmounts[0].amount = 1; @@ -400,7 +371,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); } - function test_MesssageFeeTooHigh_Revert() public { + function test_RevertWhen_MessageFeeTooHigh() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); vm.expectRevert( @@ -410,7 +381,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, MAX_MSG_FEES_JUELS + 1, OWNER); } - function test_SourceTokenDataTooLarge_Revert() public { + function test_RevertWhen_SourceTokenDataTooLarge() public { address sourceETH = s_sourceTokens[1]; vm.stopPrank(); vm.startPrank(OWNER); diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.getFee.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.getFee.t.sol index 63a4c0c322e..33e4a90cd5d 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.getFee.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.getFee.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {FeeQuoter} from "../../../FeeQuoter.sol"; import {Client} from "../../../libraries/Client.sol"; @@ -10,7 +10,7 @@ import {OnRampSetup} from "./OnRampSetup.t.sol"; contract OnRamp_getFee is OnRampSetup { using USDPriceWith18Decimals for uint224; - function test_EmptyMessage_Success() public view { + function test_EmptyMessage() public view { address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; @@ -25,7 +25,7 @@ contract OnRamp_getFee is OnRampSetup { } } - function test_SingleTokenMessage_Success() public view { + function test_SingleTokenMessage() public view { address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; @@ -41,7 +41,7 @@ contract OnRamp_getFee is OnRampSetup { } } - function test_GetFeeOfZeroForTokenMessage_Success() public { + function test_GetFeeOfZeroForTokenMessage() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); uint256 feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); @@ -63,13 +63,13 @@ contract OnRamp_getFee is OnRampSetup { // Reverts - function test_Unhealthy_Revert() public { + function test_RevertWhen_Unhealthy() public { _setMockRMNChainCurse(DEST_CHAIN_SELECTOR, true); vm.expectRevert(abi.encodeWithSelector(OnRamp.CursedByRMN.selector, DEST_CHAIN_SELECTOR)); s_onRamp.getFee(DEST_CHAIN_SELECTOR, _generateEmptyMessage()); } - function test_EnforceOutOfOrder_Revert() public { + function test_RevertWhen_EnforceOutOfOrder() public { // Update dynamic config to enforce allowOutOfOrderExecution = true. vm.stopPrank(); vm.startPrank(OWNER); @@ -87,7 +87,7 @@ contract OnRamp_getFee is OnRampSetup { s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); } - function test_NotAFeeTokenButPricedToken_Revert() public { + function test_RevertWhen_NotAFeeTokenButPricedToken() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.feeToken = s_sourceTokens[1]; diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.getSupportedTokens.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.getSupportedTokens.t.sol index c04f3cf3d51..551b36a67f7 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.getSupportedTokens.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.getSupportedTokens.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {OnRamp} from "../../../onRamp/OnRamp.sol"; import {OnRampSetup} from "./OnRampSetup.t.sol"; contract OnRamp_getSupportedTokens is OnRampSetup { - function test_GetSupportedTokens_Revert() public { + function test_RevertWhen_GetSupportedTokens() public { vm.expectRevert(OnRamp.GetSupportedTokensFunctionalityRemovedCheckAdminRegistry.selector); s_onRamp.getSupportedTokens(DEST_CHAIN_SELECTOR); } diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.getTokenPool.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.getTokenPool.t.sol index 8612ce86e36..2b3856eea5f 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.getTokenPool.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.getTokenPool.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {OnRampSetup} from "./OnRampSetup.t.sol"; import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; contract OnRamp_getTokenPool is OnRampSetup { - function test_GetTokenPool_Success() public view { + function test_GetTokenPool() public view { assertEq( s_sourcePoolByToken[s_sourceTokens[0]], address(s_onRamp.getPoolBySourceToken(DEST_CHAIN_SELECTOR, IERC20(s_sourceTokens[0]))) diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.setDynamicConfig.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.setDynamicConfig.t.sol index 057ed0a79dd..10839968dbe 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.setDynamicConfig.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.setDynamicConfig.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; import {OnRamp} from "../../../onRamp/OnRamp.sol"; import {OnRampSetup} from "./OnRampSetup.t.sol"; contract OnRamp_setDynamicConfig is OnRampSetup { - function test_setDynamicConfig_Success() public { + function test_setDynamicConfig() public { OnRamp.StaticConfig memory staticConfig = s_onRamp.getStaticConfig(); OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ feeQuoter: address(23423), @@ -27,7 +27,7 @@ contract OnRamp_setDynamicConfig is OnRampSetup { // Reverts - function test_setDynamicConfig_InvalidConfigFeeQuoterEqAddressZero_Revert() public { + function test_RevertWhen_setDynamicConfig_InvalidConfigFeeQuoterEqAddressZero() public { OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ feeQuoter: address(0), reentrancyGuardEntered: false, @@ -40,7 +40,7 @@ contract OnRamp_setDynamicConfig is OnRampSetup { s_onRamp.setDynamicConfig(newConfig); } - function test_setDynamicConfig_InvalidConfigInvalidConfig_Revert() public { + function test_RevertWhen_setDynamicConfig_InvalidConfigInvalidConfig() public { OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ feeQuoter: address(23423), reentrancyGuardEntered: false, @@ -55,7 +55,7 @@ contract OnRamp_setDynamicConfig is OnRampSetup { s_onRamp.setDynamicConfig(newConfig); } - function test_setDynamicConfig_InvalidConfigFeeAggregatorEqAddressZero_Revert() public { + function test_RevertWhen_setDynamicConfig_InvalidConfigFeeAggregatorEqAddressZero() public { OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ feeQuoter: address(23423), reentrancyGuardEntered: false, @@ -68,13 +68,13 @@ contract OnRamp_setDynamicConfig is OnRampSetup { s_onRamp.setDynamicConfig(newConfig); } - function test_setDynamicConfig_InvalidConfigOnlyOwner_Revert() public { + function test_RevertWhen_setDynamicConfig_InvalidConfigOnlyOwner() public { vm.startPrank(STRANGER); vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); s_onRamp.setDynamicConfig(_generateDynamicOnRampConfig(address(2))); } - function test_setDynamicConfig_InvalidConfigReentrancyGuardEnteredEqTrue_Revert() public { + function test_RevertWhen_setDynamicConfig_InvalidConfigReentrancyGuardEnteredEqTrue() public { OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ feeQuoter: address(23423), reentrancyGuardEntered: true, diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.withdrawFeeTokens.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.withdrawFeeTokens.t.sol index 2af7242150a..16b1246e90c 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.withdrawFeeTokens.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.withdrawFeeTokens.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Client} from "../../../libraries/Client.sol"; import {OnRamp} from "../../../onRamp/OnRamp.sol"; @@ -57,7 +57,7 @@ contract OnRamp_withdrawFeeTokens is OnRampSetup { } } - function test_WithdrawFeeTokens_Success() public { + function test_WithdrawFeeTokens() public { vm.expectEmit(); emit OnRamp.FeeTokenWithdrawn(FEE_AGGREGATOR, s_sourceFeeToken, s_nopFees[s_sourceFeeToken]); diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRampSetup.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRampSetup.t.sol index ead9e7088ce..e310a733bc6 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRampSetup.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IRouter} from "../../../interfaces/IRouter.sol"; @@ -75,7 +75,6 @@ contract OnRampSetup is FeeQuoterFeeSetup { return _messageToEvent( message, SOURCE_CHAIN_SELECTOR, - DEST_CHAIN_SELECTOR, seqNum, nonce, feeTokenAmount, @@ -89,7 +88,6 @@ contract OnRampSetup is FeeQuoterFeeSetup { function _messageToEvent( Client.EVM2AnyMessage memory message, uint64 sourceChainSelector, - uint64 destChainSelector, uint64 seqNum, uint64 nonce, uint256 feeTokenAmount, @@ -99,13 +97,13 @@ contract OnRampSetup is FeeQuoterFeeSetup { TokenAdminRegistry tokenAdminRegistry ) internal view returns (Internal.EVM2AnyRampMessage memory) { Client.EVMExtraArgsV2 memory extraArgs = - s_feeQuoter.parseEVMExtraArgsFromBytes(message.extraArgs, destChainSelector); + s_feeQuoter.parseEVMExtraArgsFromBytes(message.extraArgs, DEST_CHAIN_SELECTOR); Internal.EVM2AnyRampMessage memory messageEvent = Internal.EVM2AnyRampMessage({ header: Internal.RampMessageHeader({ messageId: "", sourceChainSelector: sourceChainSelector, - destChainSelector: destChainSelector, + destChainSelector: DEST_CHAIN_SELECTOR, sequenceNumber: seqNum, nonce: extraArgs.allowOutOfOrderExecution ? 0 : nonce }), diff --git a/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool/BurnFromMintTokenPool.lockOrBurn.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool/BurnFromMintTokenPool.lockOrBurn.t.sol index 44a8f2299af..bbdbd6c83ba 100644 --- a/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool/BurnFromMintTokenPool.lockOrBurn.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool/BurnFromMintTokenPool.lockOrBurn.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Pool} from "../../../libraries/Pool.sol"; import {RateLimiter} from "../../../libraries/RateLimiter.sol"; @@ -9,15 +9,15 @@ import {BurnFromMintTokenPoolSetup} from "./BurnFromMintTokenPoolSetup.t.sol"; import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; contract BurnFromMintTokenPool_lockOrBurn is BurnFromMintTokenPoolSetup { - function test_setup_Success() public view { + function test_setup() public view { assertEq(address(s_burnMintERC20), address(s_pool.getToken())); - assertEq(address(s_mockRMN), s_pool.getRmnProxy()); + assertEq(address(s_mockRMNRemote), s_pool.getRmnProxy()); assertEq(false, s_pool.getAllowListEnabled()); assertEq(type(uint256).max, s_burnMintERC20.allowance(address(s_pool), address(s_pool))); assertEq("BurnFromMintTokenPool 1.5.1", s_pool.typeAndVersion()); } - function test_PoolBurn_Success() public { + function test_PoolBurn() public { uint256 burnAmount = 20_000e18; deal(address(s_burnMintERC20), address(s_pool), burnAmount); @@ -51,8 +51,9 @@ contract BurnFromMintTokenPool_lockOrBurn is BurnFromMintTokenPoolSetup { } // Should not burn tokens if cursed. - function test_PoolBurnRevertNotHealthy_Revert() public { - s_mockRMN.setGlobalCursed(true); + function test_RevertWhen_PoolBurnRevertNotHealthy() public { + vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSignature("isCursed(bytes16)"), abi.encode(true)); + uint256 before = s_burnMintERC20.balanceOf(address(s_pool)); vm.startPrank(s_burnMintOnRamp); @@ -70,7 +71,7 @@ contract BurnFromMintTokenPool_lockOrBurn is BurnFromMintTokenPoolSetup { assertEq(s_burnMintERC20.balanceOf(address(s_pool)), before); } - function test_ChainNotAllowed_Revert() public { + function test_RevertWhen_ChainNotAllowed() public { uint64 wrongChainSelector = 8838833; vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, wrongChainSelector)); s_pool.releaseOrMint( diff --git a/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool/BurnFromMintTokenPoolSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool/BurnFromMintTokenPoolSetup.t.sol index 98de04ea3fa..cf11f467579 100644 --- a/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool/BurnFromMintTokenPoolSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool/BurnFromMintTokenPoolSetup.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {BurnFromMintTokenPool} from "../../../pools/BurnFromMintTokenPool.sol"; import {BurnMintSetup} from "../BurnMintTokenPool/BurnMintSetup.t.sol"; @@ -11,7 +11,7 @@ contract BurnFromMintTokenPoolSetup is BurnMintSetup { BurnMintSetup.setUp(); s_pool = new BurnFromMintTokenPool( - s_burnMintERC20, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), address(s_sourceRouter) + s_burnMintERC20, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMNRemote), address(s_sourceRouter) ); s_burnMintERC20.grantMintAndBurnRoles(address(s_pool)); diff --git a/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintSetup.t.sol index 6c5d4dd6369..175f5aaece4 100644 --- a/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintSetup.t.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {BurnMintERC20} from "../../../../shared/token/ERC20/BurnMintERC20.sol"; import {Router} from "../../../Router.sol"; import {BurnMintTokenPool} from "../../../pools/BurnMintTokenPool.sol"; import {TokenPool} from "../../../pools/TokenPool.sol"; -import {RouterSetup} from "../../router/Router/RouterSetup.t.sol"; +import {BaseTest} from "../../BaseTest.t.sol"; -contract BurnMintSetup is RouterSetup { +contract BurnMintSetup is BaseTest { BurnMintERC20 internal s_burnMintERC20; address internal s_burnMintOffRamp = makeAddr("burn_mint_offRamp"); address internal s_burnMintOnRamp = makeAddr("burn_mint_onRamp"); @@ -16,7 +16,7 @@ contract BurnMintSetup is RouterSetup { address internal s_remoteToken = makeAddr("remote_token"); function setUp() public virtual override { - RouterSetup.setUp(); + super.setUp(); s_burnMintERC20 = new BurnMintERC20("Chainlink Token", "LINK", 18, 0, 0); } diff --git a/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintTokenPool.lockOrBurn.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintTokenPool.lockOrBurn.t.sol index e0bbffa9919..7b19f2881d6 100644 --- a/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintTokenPool.lockOrBurn.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintTokenPool.lockOrBurn.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Pool} from "../../../libraries/Pool.sol"; import {RateLimiter} from "../../../libraries/RateLimiter.sol"; @@ -16,7 +16,7 @@ contract BurnMintTokenPoolSetup is BurnMintSetup { BurnMintSetup.setUp(); s_pool = new BurnMintTokenPool( - s_burnMintERC20, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), address(s_sourceRouter) + s_burnMintERC20, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMNRemote), address(s_sourceRouter) ); s_burnMintERC20.grantMintAndBurnRoles(address(s_pool)); @@ -25,14 +25,14 @@ contract BurnMintTokenPoolSetup is BurnMintSetup { } contract BurnMintTokenPool_lockOrBurn is BurnMintTokenPoolSetup { - function test_Setup_Success() public view { + function test_Setup() public view { assertEq(address(s_burnMintERC20), address(s_pool.getToken())); - assertEq(address(s_mockRMN), s_pool.getRmnProxy()); + assertEq(address(s_mockRMNRemote), s_pool.getRmnProxy()); assertEq(false, s_pool.getAllowListEnabled()); assertEq("BurnMintTokenPool 1.5.1", s_pool.typeAndVersion()); } - function test_PoolBurn_Success() public { + function test_PoolBurn() public { uint256 burnAmount = 20_000e18; deal(address(s_burnMintERC20), address(s_pool), burnAmount); @@ -66,8 +66,8 @@ contract BurnMintTokenPool_lockOrBurn is BurnMintTokenPoolSetup { } // Should not burn tokens if cursed. - function test_PoolBurnRevertNotHealthy_Revert() public { - s_mockRMN.setGlobalCursed(true); + function test_RevertWhen_PoolBurnRevertNotHealthy() public { + vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSignature("isCursed(bytes16)"), abi.encode(true)); uint256 before = s_burnMintERC20.balanceOf(address(s_pool)); vm.startPrank(s_burnMintOnRamp); @@ -85,7 +85,7 @@ contract BurnMintTokenPool_lockOrBurn is BurnMintTokenPoolSetup { assertEq(s_burnMintERC20.balanceOf(address(s_pool)), before); } - function test_ChainNotAllowed_Revert() public { + function test_RevertWhen_ChainNotAllowed() public { uint64 wrongChainSelector = 8838833; vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, wrongChainSelector)); diff --git a/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintTokenPool.releaseOrMint.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintTokenPool.releaseOrMint.t.sol index e950b079889..88b96b1fef7 100644 --- a/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintTokenPool.releaseOrMint.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintTokenPool.releaseOrMint.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Pool} from "../../../libraries/Pool.sol"; import {BurnMintTokenPool} from "../../../pools/BurnMintTokenPool.sol"; @@ -15,7 +15,7 @@ contract BurnMintTokenPoolSetup is BurnMintSetup { BurnMintSetup.setUp(); s_pool = new BurnMintTokenPool( - s_burnMintERC20, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), address(s_sourceRouter) + s_burnMintERC20, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMNRemote), address(s_sourceRouter) ); s_burnMintERC20.grantMintAndBurnRoles(address(s_pool)); @@ -24,7 +24,7 @@ contract BurnMintTokenPoolSetup is BurnMintSetup { } contract BurnMintTokenPool_releaseOrMint is BurnMintTokenPoolSetup { - function test_PoolMint_Success() public { + function test_PoolMint() public { uint256 amount = 1e19; address receiver = makeAddr("receiver_address"); @@ -49,9 +49,9 @@ contract BurnMintTokenPool_releaseOrMint is BurnMintTokenPoolSetup { assertEq(s_burnMintERC20.balanceOf(receiver), amount); } - function test_PoolMintNotHealthy_Revert() public { + function test_RevertWhen_PoolMintNotHealthy() public { // Should not mint tokens if cursed. - s_mockRMN.setGlobalCursed(true); + vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSignature("isCursed(bytes16)"), abi.encode(true)); uint256 before = s_burnMintERC20.balanceOf(OWNER); vm.startPrank(s_burnMintOffRamp); @@ -72,7 +72,7 @@ contract BurnMintTokenPool_releaseOrMint is BurnMintTokenPoolSetup { assertEq(s_burnMintERC20.balanceOf(OWNER), before); } - function test_ChainNotAllowed_Revert() public { + function test_RevertWhen_ChainNotAllowed() public { uint64 wrongChainSelector = 8838833; vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, wrongChainSelector)); diff --git a/contracts/src/v0.8/ccip/test/pools/BurnMintWithLockReleaseFlagTokenPool/BurnMintWithLockReleaseFlagTokenPool.lockOrBurn.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnMintWithLockReleaseFlagTokenPool/BurnMintWithLockReleaseFlagTokenPool.lockOrBurn.t.sol index bb58afd254a..bc8de71d209 100644 --- a/contracts/src/v0.8/ccip/test/pools/BurnMintWithLockReleaseFlagTokenPool/BurnMintWithLockReleaseFlagTokenPool.lockOrBurn.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/BurnMintWithLockReleaseFlagTokenPool/BurnMintWithLockReleaseFlagTokenPool.lockOrBurn.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Pool} from "../../../libraries/Pool.sol"; import {RateLimiter} from "../../../libraries/RateLimiter.sol"; @@ -18,7 +18,7 @@ contract BurnMintWithLockReleaseFlagTokenPoolSetup is BurnMintSetup { BurnMintSetup.setUp(); s_pool = new BurnMintWithLockReleaseFlagTokenPool( - s_burnMintERC20, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), address(s_sourceRouter) + s_burnMintERC20, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMNRemote), address(s_sourceRouter) ); s_burnMintERC20.grantMintAndBurnRoles(address(s_pool)); @@ -27,7 +27,7 @@ contract BurnMintWithLockReleaseFlagTokenPoolSetup is BurnMintSetup { } contract BurnMintWithLockReleaseFlagTokenPool_lockOrBurn is BurnMintWithLockReleaseFlagTokenPoolSetup { - function test_LockOrBurn_CorrectReturnData_Success() public { + function test_LockOrBurn_CorrectReturnData() public { uint256 burnAmount = 20_000e18; deal(address(s_burnMintERC20), address(s_pool), burnAmount); diff --git a/contracts/src/v0.8/ccip/test/pools/BurnToAddressMintTokenPool/BurnToAddressMintTokenPool.lockOrBurn.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnToAddressMintTokenPool/BurnToAddressMintTokenPool.lockOrBurn.t.sol new file mode 100644 index 00000000000..c5e559b2d9e --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/BurnToAddressMintTokenPool/BurnToAddressMintTokenPool.lockOrBurn.t.sol @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import {Pool} from "../../../libraries/Pool.sol"; +import {BurnToAddressMintTokenPool} from "../../../pools/BurnToAddressMintTokenPool.sol"; +import {BurnToAddressMintTokenPoolSetup} from "./BurnToAddressMintTokenPoolSetup.t.sol"; + +import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol"; + +contract BurnToAddressMintTokenPool_lockOrBurn is BurnToAddressMintTokenPoolSetup { + uint256 public constant AMOUNT = 1e24; + + function test_LockOrBurn() public { + s_pool.setOutstandingTokens(AMOUNT); + + deal(address(s_burnMintERC20), address(s_pool), AMOUNT); + assertEq(s_burnMintERC20.balanceOf(address(s_pool)), AMOUNT); + + vm.startPrank(s_burnMintOnRamp); + + vm.expectEmit(); + emit IERC20.Transfer(address(s_pool), BURN_ADDRESS, AMOUNT); + + vm.expectCall(address(s_burnMintERC20), abi.encodeWithSelector(IERC20.transfer.selector, BURN_ADDRESS, AMOUNT)); + + s_pool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: bytes(""), + amount: AMOUNT, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_burnMintERC20) + }) + ); + + assertEq(s_burnMintERC20.balanceOf(s_pool.getBurnAddress()), AMOUNT); + assertEq(s_burnMintERC20.balanceOf(address(s_pool)), 0); + assertEq(s_pool.getOutstandingTokens(), 0); + } + + // Reverts + + function test_LockOrBurn_RevertWhen_InsufficientOutstandingTokens() public { + s_pool.setOutstandingTokens(AMOUNT - 1); + + deal(address(s_burnMintERC20), address(s_pool), AMOUNT); + assertEq(s_burnMintERC20.balanceOf(address(s_pool)), AMOUNT); + + vm.startPrank(s_burnMintOnRamp); + + vm.expectRevert(BurnToAddressMintTokenPool.InsufficientOutstandingTokens.selector); + + s_pool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: bytes(""), + amount: AMOUNT, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_burnMintERC20) + }) + ); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/BurnToAddressMintTokenPool/BurnToAddressMintTokenPool.releaseOrMint.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnToAddressMintTokenPool/BurnToAddressMintTokenPool.releaseOrMint.t.sol new file mode 100644 index 00000000000..508ed6bb787 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/BurnToAddressMintTokenPool/BurnToAddressMintTokenPool.releaseOrMint.t.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import {Pool} from "../../../libraries/Pool.sol"; +import {BurnToAddressMintTokenPoolSetup} from "./BurnToAddressMintTokenPoolSetup.t.sol"; + +import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol"; + +contract BurnToAddressMintTokenPool_releaseOrMint is BurnToAddressMintTokenPoolSetup { + function test_releaseOrMint() public { + uint256 amount = 1e24; + address receiver = makeAddr("RECEIVER_ADDRESS"); + + vm.startPrank(s_burnMintOffRamp); + + vm.expectEmit(); + emit IERC20.Transfer(address(0), receiver, amount); + + s_pool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: bytes(""), + receiver: receiver, + amount: amount, + localToken: address(s_burnMintERC20), + remoteChainSelector: DEST_CHAIN_SELECTOR, + sourcePoolAddress: abi.encode(s_remoteBurnMintPool), + sourcePoolData: "", + offchainTokenData: "" + }) + ); + + assertEq(s_burnMintERC20.balanceOf(receiver), amount); + assertEq(s_pool.getOutstandingTokens(), amount); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/BurnToAddressMintTokenPool/BurnToAddressMintTokenPool.setMintedTokens.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnToAddressMintTokenPool/BurnToAddressMintTokenPool.setMintedTokens.t.sol new file mode 100644 index 00000000000..11c615d8b2b --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/BurnToAddressMintTokenPool/BurnToAddressMintTokenPool.setMintedTokens.t.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import {BurnToAddressMintTokenPool} from "../../../pools/BurnToAddressMintTokenPool.sol"; +import {BurnToAddressMintTokenPoolSetup} from "./BurnToAddressMintTokenPoolSetup.t.sol"; + +contract BurnToAddressMintTokenPool_setOutstandingokens is BurnToAddressMintTokenPoolSetup { + function test_setOutstandingTokens() public { + uint256 amount = 1e18; + + assertEq(s_pool.getOutstandingTokens(), 0); + + vm.expectEmit(); + emit BurnToAddressMintTokenPool.OutstandingTokensSet(amount, 0); + + s_pool.setOutstandingTokens(amount); + + assertEq(s_pool.getOutstandingTokens(), amount); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/BurnToAddressMintTokenPool/BurnToAddressMintTokenPoolSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnToAddressMintTokenPool/BurnToAddressMintTokenPoolSetup.t.sol new file mode 100644 index 00000000000..a27c0a0f8c4 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/BurnToAddressMintTokenPool/BurnToAddressMintTokenPoolSetup.t.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import {BurnToAddressMintTokenPool} from "../../../pools/BurnToAddressMintTokenPool.sol"; +import {BurnMintSetup} from "../BurnMintTokenPool/BurnMintSetup.t.sol"; + +contract BurnToAddressMintTokenPoolSetup is BurnMintSetup { + BurnToAddressMintTokenPool internal s_pool; + + address public constant BURN_ADDRESS = address(0xdead); + + function setUp() public virtual override { + BurnMintSetup.setUp(); + + s_pool = new BurnToAddressMintTokenPool( + s_burnMintERC20, + DEFAULT_TOKEN_DECIMALS, + new address[](0), + address(s_mockRMNRemote), + address(s_sourceRouter), + BURN_ADDRESS + ); + + s_burnMintERC20.grantMintAndBurnRoles(address(s_pool)); + + _applyChainUpdates(address(s_pool)); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.lockOrBurn.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.lockOrBurn.t.sol index b96dcd78b5d..477f9e86430 100644 --- a/contracts/src/v0.8/ccip/test/pools/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.lockOrBurn.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.lockOrBurn.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Pool} from "../../../libraries/Pool.sol"; import {RateLimiter} from "../../../libraries/RateLimiter.sol"; @@ -16,7 +16,7 @@ contract BurnWithFromMintTokenPoolSetup is BurnMintSetup { BurnMintSetup.setUp(); s_pool = new BurnWithFromMintTokenPool( - s_burnMintERC20, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), address(s_sourceRouter) + s_burnMintERC20, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMNRemote), address(s_sourceRouter) ); s_burnMintERC20.grantMintAndBurnRoles(address(s_pool)); @@ -25,15 +25,15 @@ contract BurnWithFromMintTokenPoolSetup is BurnMintSetup { } contract BurnWithFromMintTokenPool_lockOrBurn is BurnWithFromMintTokenPoolSetup { - function test_Setup_Success() public view { + function test_Setup() public view { assertEq(address(s_burnMintERC20), address(s_pool.getToken())); - assertEq(address(s_mockRMN), s_pool.getRmnProxy()); + assertEq(address(s_mockRMNRemote), s_pool.getRmnProxy()); assertEq(false, s_pool.getAllowListEnabled()); assertEq(type(uint256).max, s_burnMintERC20.allowance(address(s_pool), address(s_pool))); assertEq("BurnWithFromMintTokenPool 1.5.1", s_pool.typeAndVersion()); } - function test_PoolBurn_Success() public { + function test_PoolBurn() public { uint256 burnAmount = 20_000e18; deal(address(s_burnMintERC20), address(s_pool), burnAmount); @@ -67,8 +67,8 @@ contract BurnWithFromMintTokenPool_lockOrBurn is BurnWithFromMintTokenPoolSetup } // Should not burn tokens if cursed. - function test_PoolBurnRevertNotHealthy_Revert() public { - s_mockRMN.setGlobalCursed(true); + function test_RevertWhen_PoolBurnRevertNotHealthy() public { + vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSignature("isCursed(bytes16)"), abi.encode(true)); uint256 before = s_burnMintERC20.balanceOf(address(s_pool)); vm.startPrank(s_burnMintOnRamp); @@ -86,7 +86,7 @@ contract BurnWithFromMintTokenPool_lockOrBurn is BurnWithFromMintTokenPoolSetup assertEq(s_burnMintERC20.balanceOf(address(s_pool)), before); } - function test_ChainNotAllowed_Revert() public { + function test_RevertWhen_ChainNotAllowed() public { uint64 wrongChainSelector = 8838833; vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, wrongChainSelector)); s_pool.releaseOrMint( diff --git a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.canAcceptLiquidity.t.sol b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.canAcceptLiquidity.t.sol index 63b6e0bc351..e4bebbf1820 100644 --- a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.canAcceptLiquidity.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.canAcceptLiquidity.t.sol @@ -1,15 +1,15 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {LockReleaseTokenPool} from "../../../pools/LockReleaseTokenPool.sol"; import {LockReleaseTokenPoolSetup} from "./LockReleaseTokenPoolSetup.t.sol"; contract LockReleaseTokenPool_canAcceptLiquidity is LockReleaseTokenPoolSetup { - function test_CanAcceptLiquidity_Success() public { + function test_CanAcceptLiquidity() public { assertEq(true, s_lockReleaseTokenPool.canAcceptLiquidity()); s_lockReleaseTokenPool = new LockReleaseTokenPool( - s_token, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), false, address(s_sourceRouter) + s_token, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMNRemote), false, address(s_sourceRouter) ); assertEq(false, s_lockReleaseTokenPool.canAcceptLiquidity()); } diff --git a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.lockOrBurn.t.sol b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.lockOrBurn.t.sol index 7c87fbcc95d..490f848f7af 100644 --- a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.lockOrBurn.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.lockOrBurn.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Pool} from "../../../libraries/Pool.sol"; import {RateLimiter} from "../../../libraries/RateLimiter.sol"; @@ -30,7 +30,7 @@ contract LockReleaseTokenPool_lockOrBurn is LockReleaseTokenPoolSetup { ); } - function test_LockOrBurnWithAllowList_Success() public { + function test_LockOrBurnWithAllowList() public { uint256 amount = 100; vm.startPrank(s_allowedOnRamp); @@ -63,7 +63,7 @@ contract LockReleaseTokenPool_lockOrBurn is LockReleaseTokenPoolSetup { ); } - function test_LockOrBurnWithAllowList_Revert() public { + function test_RevertWhen_LockOrBurnWithAllowList() public { vm.startPrank(s_allowedOnRamp); vm.expectRevert(abi.encodeWithSelector(TokenPool.SenderNotAllowed.selector, STRANGER)); @@ -79,9 +79,9 @@ contract LockReleaseTokenPool_lockOrBurn is LockReleaseTokenPoolSetup { ); } - function test_PoolBurnRevertNotHealthy_Revert() public { + function test_RevertWhen_PoolBurnRevertNotHealthy() public { // Should not burn tokens if cursed. - s_mockRMN.setGlobalCursed(true); + vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSignature("isCursed(bytes16)"), abi.encode(true)); uint256 before = s_token.balanceOf(address(s_lockReleaseTokenPoolWithAllowList)); vm.startPrank(s_allowedOnRamp); diff --git a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.provideLiquidity.t.sol b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.provideLiquidity.t.sol index 6ef52e88467..88724f89abb 100644 --- a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.provideLiquidity.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.provideLiquidity.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {LockReleaseTokenPool} from "../../../pools/LockReleaseTokenPool.sol"; @@ -21,7 +21,7 @@ contract LockReleaseTokenPool_provideLiquidity is LockReleaseTokenPoolSetup { // Reverts - function test_Unauthorized_Revert() public { + function test_RevertWhen_Unauthorized() public { vm.startPrank(STRANGER); vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, STRANGER)); @@ -36,9 +36,9 @@ contract LockReleaseTokenPool_provideLiquidity is LockReleaseTokenPoolSetup { s_lockReleaseTokenPool.provideLiquidity(amount); } - function test_LiquidityNotAccepted_Revert() public { + function test_RevertWhen_LiquidityNotAccepted() public { s_lockReleaseTokenPool = new LockReleaseTokenPool( - s_token, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), false, address(s_sourceRouter) + s_token, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMNRemote), false, address(s_sourceRouter) ); vm.expectRevert(LockReleaseTokenPool.LiquidityNotAccepted.selector); diff --git a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.releaseOrMint.t.sol b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.releaseOrMint.t.sol index 9a67f766448..9ef5130370a 100644 --- a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.releaseOrMint.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.releaseOrMint.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Pool} from "../../../libraries/Pool.sol"; import {RateLimiter} from "../../../libraries/RateLimiter.sol"; @@ -27,7 +27,7 @@ contract LockReleaseTokenPool_releaseOrMint is LockReleaseTokenPoolSetup { s_lockReleaseTokenPoolWithAllowList.applyChainUpdates(new uint64[](0), chainUpdate); } - function test_ReleaseOrMint_Success() public { + function test_ReleaseOrMint() public { vm.startPrank(s_allowedOffRamp); uint256 amount = 100; @@ -93,7 +93,7 @@ contract LockReleaseTokenPool_releaseOrMint is LockReleaseTokenPoolSetup { ); } - function test_ChainNotAllowed_Revert() public { + function test_RevertWhen_ChainNotAllowed() public { uint64[] memory chainsToRemove = new uint64[](1); chainsToRemove[0] = SOURCE_CHAIN_SELECTOR; @@ -116,9 +116,9 @@ contract LockReleaseTokenPool_releaseOrMint is LockReleaseTokenPoolSetup { ); } - function test_PoolMintNotHealthy_Revert() public { + function test_RevertWhen_PoolMintNotHealthy() public { // Should not mint tokens if cursed. - s_mockRMN.setGlobalCursed(true); + vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSignature("isCursed(bytes16)"), abi.encode(true)); uint256 before = s_token.balanceOf(OWNER); vm.startPrank(s_allowedOffRamp); vm.expectRevert(TokenPool.CursedByRMN.selector); diff --git a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.setRebalancer.t.sol b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.setRebalancer.t.sol index 25286c1a376..055bbf3c55d 100644 --- a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.setRebalancer.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.setRebalancer.t.sol @@ -1,17 +1,17 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; import {LockReleaseTokenPoolSetup} from "./LockReleaseTokenPoolSetup.t.sol"; contract LockReleaseTokenPool_setRebalancer is LockReleaseTokenPoolSetup { - function test_SetRebalancer_Success() public { + function test_SetRebalancer() public { assertEq(address(s_lockReleaseTokenPool.getRebalancer()), OWNER); s_lockReleaseTokenPool.setRebalancer(STRANGER); assertEq(address(s_lockReleaseTokenPool.getRebalancer()), STRANGER); } - function test_SetRebalancer_Revert() public { + function test_RevertWhen_SetRebalancer() public { vm.startPrank(STRANGER); vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); diff --git a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.supportsInterface.t.sol b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.supportsInterface.t.sol index 9a08fc38c96..000ece21f35 100644 --- a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.supportsInterface.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.supportsInterface.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IPoolV1} from "../../../interfaces/IPool.sol"; @@ -8,7 +8,7 @@ import {LockReleaseTokenPoolSetup} from "./LockReleaseTokenPoolSetup.t.sol"; import {IERC165} from "../../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; contract LockReleaseTokenPool_supportsInterface is LockReleaseTokenPoolSetup { - function test_SupportsInterface_Success() public view { + function test_SupportsInterface() public view { assertTrue(s_lockReleaseTokenPool.supportsInterface(type(IPoolV1).interfaceId)); assertTrue(s_lockReleaseTokenPool.supportsInterface(type(IERC165).interfaceId)); } diff --git a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.transferLiquidity.t.sol b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.transferLiquidity.t.sol index 60b9c935bd3..7eca1f95067 100644 --- a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.transferLiquidity.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.transferLiquidity.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {LockReleaseTokenPool} from "../../../pools/LockReleaseTokenPool.sol"; import {LockReleaseTokenPoolSetup} from "./LockReleaseTokenPoolSetup.t.sol"; @@ -12,13 +12,13 @@ contract LockReleaseTokenPool_transferLiquidity is LockReleaseTokenPoolSetup { super.setUp(); s_oldLockReleaseTokenPool = new LockReleaseTokenPool( - s_token, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), true, address(s_sourceRouter) + s_token, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMNRemote), true, address(s_sourceRouter) ); deal(address(s_token), address(s_oldLockReleaseTokenPool), s_amount); } - function test_transferLiquidity_Success() public { + function test_transferLiquidity() public { uint256 balancePre = s_token.balanceOf(address(s_lockReleaseTokenPool)); s_oldLockReleaseTokenPool.setRebalancer(address(s_lockReleaseTokenPool)); @@ -31,7 +31,7 @@ contract LockReleaseTokenPool_transferLiquidity is LockReleaseTokenPoolSetup { assertEq(s_token.balanceOf(address(s_lockReleaseTokenPool)), balancePre + s_amount); } - function test_transferLiquidity_transferTooMuch_Revert() public { + function test_RevertWhen_transferLiquidity_transferTooMuch() public { uint256 balancePre = s_token.balanceOf(address(s_lockReleaseTokenPool)); s_oldLockReleaseTokenPool.setRebalancer(address(s_lockReleaseTokenPool)); diff --git a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.withdrawalLiquidity.t.sol b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.withdrawalLiquidity.t.sol index 29b6ef6c7f8..df21bc36fab 100644 --- a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.withdrawalLiquidity.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.withdrawalLiquidity.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {LockReleaseTokenPool} from "../../../pools/LockReleaseTokenPool.sol"; @@ -20,14 +20,14 @@ contract LockReleaseTokenPool_withdrawalLiquidity is LockReleaseTokenPoolSetup { } // Reverts - function test_Unauthorized_Revert() public { + function test_RevertWhen_Unauthorized() public { vm.startPrank(STRANGER); vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, STRANGER)); s_lockReleaseTokenPool.withdrawLiquidity(1); } - function test_InsufficientLiquidity_Revert() public { + function test_RevertWhen_InsufficientLiquidity() public { uint256 maxUint256 = 2 ** 256 - 1; s_token.approve(address(s_lockReleaseTokenPool), maxUint256); s_lockReleaseTokenPool.provideLiquidity(maxUint256); diff --git a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPoolSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPoolSetup.t.sol index 13bcb8cfdee..8fc7a84ecbb 100644 --- a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPoolSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPoolSetup.t.sol @@ -1,15 +1,15 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {BurnMintERC20} from "../../../../shared/token/ERC20/BurnMintERC20.sol"; import {Router} from "../../../Router.sol"; import {LockReleaseTokenPool} from "../../../pools/LockReleaseTokenPool.sol"; import {TokenPool} from "../../../pools/TokenPool.sol"; +import {BaseTest} from "../../BaseTest.t.sol"; import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {RouterSetup} from "../../router/Router/RouterSetup.t.sol"; -contract LockReleaseTokenPoolSetup is RouterSetup { +contract LockReleaseTokenPoolSetup is BaseTest { IERC20 internal s_token; LockReleaseTokenPool internal s_lockReleaseTokenPool; LockReleaseTokenPool internal s_lockReleaseTokenPoolWithAllowList; @@ -22,17 +22,17 @@ contract LockReleaseTokenPoolSetup is RouterSetup { address internal s_sourcePoolAddress = address(53852352095); function setUp() public virtual override { - RouterSetup.setUp(); + super.setUp(); s_token = new BurnMintERC20("LINK", "LNK", 18, 0, 0); deal(address(s_token), OWNER, type(uint256).max); s_lockReleaseTokenPool = new LockReleaseTokenPool( - s_token, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), true, address(s_sourceRouter) + s_token, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMNRemote), true, address(s_sourceRouter) ); - s_allowedList.push(USER_1); + s_allowedList.push(vm.randomAddress()); s_allowedList.push(OWNER); s_lockReleaseTokenPoolWithAllowList = new LockReleaseTokenPool( - s_token, DEFAULT_TOKEN_DECIMALS, s_allowedList, address(s_mockRMN), true, address(s_sourceRouter) + s_token, DEFAULT_TOKEN_DECIMALS, s_allowedList, address(s_mockRMNRemote), true, address(s_sourceRouter) ); bytes[] memory remotePoolAddresses = new bytes[](1); diff --git a/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.lockOrBurn.t.sol b/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.lockOrBurn.t.sol new file mode 100644 index 00000000000..2cf51a045e9 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.lockOrBurn.t.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import {Pool} from "../../../libraries/Pool.sol"; +import {RateLimiter} from "../../../libraries/RateLimiter.sol"; +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {SiloedLockReleaseTokenPoolSetup} from "./SiloedLockReleaseTokenPoolSetup.t.sol"; + +contract SiloedLockReleaseTokenPool_lockOrBurn is SiloedLockReleaseTokenPoolSetup { + uint256 public constant AMOUNT = 10e18; + + function test_lockOrBurn_SiloedFunds() public { + assertTrue(s_siloedLockReleaseTokenPool.isSiloed(SILOED_CHAIN_SELECTOR)); + + vm.startPrank(s_allowedOnRamp); + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(AMOUNT); + vm.expectEmit(); + emit TokenPool.Locked(s_allowedOnRamp, AMOUNT); + + s_siloedLockReleaseTokenPool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: STRANGER, + receiver: bytes(""), + amount: AMOUNT, + remoteChainSelector: SILOED_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + + assertEq(s_siloedLockReleaseTokenPool.getAvailableTokens(SILOED_CHAIN_SELECTOR), AMOUNT); + } + + function test_lockOrBurn_UnsiloedFunds() public { + vm.startPrank(s_allowedOnRamp); + + assertFalse(s_siloedLockReleaseTokenPool.isSiloed(DEST_CHAIN_SELECTOR)); + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(AMOUNT); + vm.expectEmit(); + emit TokenPool.Locked(s_allowedOnRamp, AMOUNT); + + s_siloedLockReleaseTokenPool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: STRANGER, + receiver: bytes(""), + amount: AMOUNT, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + + assertEq(s_siloedLockReleaseTokenPool.getAvailableTokens(DEST_CHAIN_SELECTOR), AMOUNT); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.provideLiquidity.t.sol b/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.provideLiquidity.t.sol new file mode 100644 index 00000000000..6af10971018 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.provideLiquidity.t.sol @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import {SiloedLockReleaseTokenPool} from "../../../pools/SiloedLockReleaseTokenPool.sol"; +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {SiloedLockReleaseTokenPoolSetup} from "./SiloedLockReleaseTokenPoolSetup.t.sol"; + +contract SiloedLockReleaseTokenPool_provideLiqudity is SiloedLockReleaseTokenPoolSetup { + address public UNAUTHORIZED_ADDRESS = address(0xdeadbeef); + + function setUp() public override { + super.setUp(); + + s_siloedLockReleaseTokenPool.setSiloRebalancer(SILOED_CHAIN_SELECTOR, OWNER); + } + + function test_ProvideLiquidity_UnsiloedChain() public { + uint256 amount = 1e24; + + vm.expectEmit(); + emit SiloedLockReleaseTokenPool.LiquidityAdded(DEST_CHAIN_SELECTOR, OWNER, amount); + + s_siloedLockReleaseTokenPool.provideSiloedLiquidity(DEST_CHAIN_SELECTOR, amount); + + assertEq(s_token.balanceOf(address(s_siloedLockReleaseTokenPool)), amount); + + // Since the funds for the destination chain are not siloed, + // the locked token amount should not be increased + assertEq(s_siloedLockReleaseTokenPool.getAvailableTokens(DEST_CHAIN_SELECTOR), amount); + assertEq(s_siloedLockReleaseTokenPool.getUnsiloedLiquidity(), amount); + } + + function test_ProvideLiquidity_SiloedChain() public { + uint256 amount = 1e24; + + vm.expectEmit(); + emit SiloedLockReleaseTokenPool.LiquidityAdded(SILOED_CHAIN_SELECTOR, OWNER, amount); + + s_siloedLockReleaseTokenPool.provideSiloedLiquidity(SILOED_CHAIN_SELECTOR, amount); + + assertEq(s_token.balanceOf(address(s_siloedLockReleaseTokenPool)), amount); + + assertEq(s_siloedLockReleaseTokenPool.getAvailableTokens(SILOED_CHAIN_SELECTOR), amount); + + // Since the funds for the destination chain are not siloed, the locked token amount should not be increased + assertEq(s_siloedLockReleaseTokenPool.getUnsiloedLiquidity(), 0); + } + + function test_ProvideLiquidity_LegacyProvideLiquiditySelector() public { + uint256 amount = 1e24; + + vm.expectEmit(); + emit SiloedLockReleaseTokenPool.LiquidityAdded(0, OWNER, amount); + + s_siloedLockReleaseTokenPool.provideLiquidity(amount); + + assertEq(s_token.balanceOf(address(s_siloedLockReleaseTokenPool)), amount); + + // Since the funds for the destination chain are not siloed, + // the locked token amount should not be increased + assertEq(s_siloedLockReleaseTokenPool.getAvailableTokens(DEST_CHAIN_SELECTOR), amount); + assertEq(s_siloedLockReleaseTokenPool.getUnsiloedLiquidity(), amount); + assertEq(s_siloedLockReleaseTokenPool.getAvailableTokens(SILOED_CHAIN_SELECTOR), 0); + } + + // Reverts + + function test_ProvideLiquidity_RevertWhen_UnauthorizedForSiloedChain() public { + vm.startPrank(UNAUTHORIZED_ADDRESS); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, UNAUTHORIZED_ADDRESS)); + + s_siloedLockReleaseTokenPool.provideSiloedLiquidity(SILOED_CHAIN_SELECTOR, 1); + } + + function test_ProvideLiquidity_RevertWhen_UnauthorizedForUnsiloedChain() public { + vm.startPrank(UNAUTHORIZED_ADDRESS); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, UNAUTHORIZED_ADDRESS)); + + s_siloedLockReleaseTokenPool.provideSiloedLiquidity(DEST_CHAIN_SELECTOR, 1); + } + + function test_ProvideLiquidity_RevertWhen_LegacyFunctionSelector_Unauthorized() public { + vm.startPrank(UNAUTHORIZED_ADDRESS); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, UNAUTHORIZED_ADDRESS)); + + s_siloedLockReleaseTokenPool.provideLiquidity(1); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.releaseOrMint.t.sol b/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.releaseOrMint.t.sol new file mode 100644 index 00000000000..eec0503b716 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.releaseOrMint.t.sol @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import {Pool} from "../../../libraries/Pool.sol"; +import {SiloedLockReleaseTokenPool} from "../../../pools/SiloedLockReleaseTokenPool.sol"; +import {SiloedLockReleaseTokenPoolSetup} from "./SiloedLockReleaseTokenPoolSetup.t.sol"; + +import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol"; + +contract SiloedLockReleaseTokenPool_releaseOrMint is SiloedLockReleaseTokenPoolSetup { + function test_ReleaseOrMint_SiloedChain() public { + uint256 amount = 10e18; + + deal(address(s_token), address(s_siloedLockReleaseTokenPool), amount); + vm.startPrank(s_allowedOnRamp); + + // Lock funds so that they can be released without underflowing the internal accounting + s_siloedLockReleaseTokenPool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: STRANGER, + receiver: bytes(""), + amount: amount, + remoteChainSelector: SILOED_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + + assertEq(s_siloedLockReleaseTokenPool.getAvailableTokens(SILOED_CHAIN_SELECTOR), amount); + + vm.startPrank(s_allowedOffRamp); + + vm.expectEmit(); + emit IERC20.Transfer(address(s_siloedLockReleaseTokenPool), OWNER, amount); + + s_siloedLockReleaseTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: bytes(""), + receiver: OWNER, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SILOED_CHAIN_SELECTOR, + sourcePoolAddress: abi.encode(s_siloedDestPoolAddress), + sourcePoolData: "", + offchainTokenData: "" + }) + ); + + assertEq(s_siloedLockReleaseTokenPool.getAvailableTokens(SILOED_CHAIN_SELECTOR), 0); + } + + function test_ReleaseOrMint_UnsiloedChain() public { + uint256 amount = 10e18; + + deal(address(s_token), address(s_siloedLockReleaseTokenPool), amount); + vm.startPrank(s_allowedOnRamp); + + // Lock funds for unsiloed chain so they can be released later + s_siloedLockReleaseTokenPool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: STRANGER, + receiver: bytes(""), + amount: amount, + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + + assertEq(s_siloedLockReleaseTokenPool.getAvailableTokens(SOURCE_CHAIN_SELECTOR), amount); + assertEq(s_siloedLockReleaseTokenPool.getUnsiloedLiquidity(), amount); + + vm.startPrank(s_allowedOffRamp); + + vm.expectEmit(); + emit IERC20.Transfer(address(s_siloedLockReleaseTokenPool), OWNER, amount); + + s_siloedLockReleaseTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: bytes(""), + receiver: OWNER, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: abi.encode(s_siloedDestPoolAddress), + sourcePoolData: "", + offchainTokenData: "" + }) + ); + + assertEq(s_siloedLockReleaseTokenPool.getAvailableTokens(SOURCE_CHAIN_SELECTOR), 0); + assertEq(s_siloedLockReleaseTokenPool.getUnsiloedLiquidity(), 0); + } + + // Reverts + + function test_ReleaseOrMint_RevertsWhen_InsufficientLiquidity_SiloedChain() public { + uint256 releaseAmount = 10e18; + uint256 liquidityAmount = releaseAmount - 1; + + s_siloedLockReleaseTokenPool.provideSiloedLiquidity(SILOED_CHAIN_SELECTOR, liquidityAmount); + + // Since amount to release is greater than provided liquidity, the function should revert + vm.expectRevert( + abi.encodeWithSelector(SiloedLockReleaseTokenPool.InsufficientLiquidity.selector, liquidityAmount, releaseAmount) + ); + + vm.startPrank(s_allowedOffRamp); + + s_siloedLockReleaseTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: bytes(""), + receiver: OWNER, + amount: releaseAmount, + localToken: address(s_token), + remoteChainSelector: SILOED_CHAIN_SELECTOR, + sourcePoolAddress: abi.encode(s_siloedDestPoolAddress), + sourcePoolData: "", + offchainTokenData: "" + }) + ); + } + + function test_ReleaseOrMint_RevertsWhen_InsufficientLiquidity_UnsiloedChain() public { + uint256 releaseAmount = 10e18; + uint256 liquidityAmount = releaseAmount - 1; + + // Call the provide liquidity function which provides to unsiloed chains. + s_siloedLockReleaseTokenPool.provideLiquidity(liquidityAmount); + + // Since amount to release is greater than provided liquidity, the function should revert + vm.expectRevert( + abi.encodeWithSelector(SiloedLockReleaseTokenPool.InsufficientLiquidity.selector, liquidityAmount, releaseAmount) + ); + + vm.startPrank(s_allowedOffRamp); + + s_siloedLockReleaseTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: bytes(""), + receiver: OWNER, + amount: releaseAmount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: abi.encode(s_siloedDestPoolAddress), + sourcePoolData: "", + offchainTokenData: "" + }) + ); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.setRebalancer.t.sol b/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.setRebalancer.t.sol new file mode 100644 index 00000000000..ea676d53015 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.setRebalancer.t.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import {SiloedLockReleaseTokenPool} from "../../../pools/SiloedLockReleaseTokenPool.sol"; +import {SiloedLockReleaseTokenPoolSetup} from "./SiloedLockReleaseTokenPoolSetup.t.sol"; + +contract SiloedLockReleaseTokenPool_setRebalancer is SiloedLockReleaseTokenPoolSetup { + address public constant REBALANCER_ADDRESS = address(0xdeadbeef); + + function test_setSiloRebalancer() public { + vm.expectEmit(); + emit SiloedLockReleaseTokenPool.SiloRebalancerSet(SILOED_CHAIN_SELECTOR, REBALANCER_ADDRESS, OWNER); + + s_siloedLockReleaseTokenPool.setSiloRebalancer(SILOED_CHAIN_SELECTOR, REBALANCER_ADDRESS); + + assertEq(s_siloedLockReleaseTokenPool.getSiloRebalancer(SILOED_CHAIN_SELECTOR), REBALANCER_ADDRESS); + assertEq(s_siloedLockReleaseTokenPool.getSiloRebalancer(DEST_CHAIN_SELECTOR), OWNER); + } + + function test_setRebalancer_UnsiloedChains() public { + vm.expectEmit(); + emit SiloedLockReleaseTokenPool.UnsiloedRebalancerSet(REBALANCER_ADDRESS, OWNER); + + s_siloedLockReleaseTokenPool.setRebalancer(REBALANCER_ADDRESS); + + assertEq(s_siloedLockReleaseTokenPool.getSiloRebalancer(DEST_CHAIN_SELECTOR), REBALANCER_ADDRESS); + } + + // Reverts + + function test_setSiloRebalancer_RevertWhen_ChainNotSiloed() public { + vm.expectRevert(abi.encodeWithSelector(SiloedLockReleaseTokenPool.ChainNotSiloed.selector, DEST_CHAIN_SELECTOR)); + + s_siloedLockReleaseTokenPool.setSiloRebalancer(DEST_CHAIN_SELECTOR, REBALANCER_ADDRESS); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.updateSiloDesignations.t.sol b/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.updateSiloDesignations.t.sol new file mode 100644 index 00000000000..506b1373ceb --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.updateSiloDesignations.t.sol @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import {SiloedLockReleaseTokenPool} from "../../../pools/SiloedLockReleaseTokenPool.sol"; +import {SiloedLockReleaseTokenPoolSetup} from "./SiloedLockReleaseTokenPoolSetup.t.sol"; + +contract SiloedLockReleaseTokenPool_updateSiloDesignations is SiloedLockReleaseTokenPoolSetup { + function test_updateSiloDesignations() public { + uint256 amount = 1e18; + + SiloedLockReleaseTokenPool.SiloConfigUpdate[] memory chainSelectors = + new SiloedLockReleaseTokenPool.SiloConfigUpdate[](1); + + chainSelectors[0] = + SiloedLockReleaseTokenPool.SiloConfigUpdate({remoteChainSelector: SILOED_CHAIN_SELECTOR, rebalancer: OWNER}); + + vm.expectEmit(); + emit SiloedLockReleaseTokenPool.ChainSiloed(SILOED_CHAIN_SELECTOR, OWNER); + + s_siloedLockReleaseTokenPool.updateSiloDesignations(new uint64[](0), chainSelectors); + + // Assert that the funds are siloed correctly + assertTrue(s_siloedLockReleaseTokenPool.isSiloed(SILOED_CHAIN_SELECTOR)); + assertEq(s_siloedLockReleaseTokenPool.getAvailableTokens(SILOED_CHAIN_SELECTOR), 0); + assertEq(s_siloedLockReleaseTokenPool.getSiloRebalancer(SILOED_CHAIN_SELECTOR), OWNER); + + // Provide some Liquidity so that we can then check that it gets removed. + s_siloedLockReleaseTokenPool.setSiloRebalancer(SILOED_CHAIN_SELECTOR, OWNER); + s_siloedLockReleaseTokenPool.provideSiloedLiquidity(SILOED_CHAIN_SELECTOR, amount); + assertEq(s_siloedLockReleaseTokenPool.getAvailableTokens(SILOED_CHAIN_SELECTOR), amount); + + vm.expectEmit(); + emit SiloedLockReleaseTokenPool.ChainUnsiloed(SILOED_CHAIN_SELECTOR, amount); + + assertEq(s_siloedLockReleaseTokenPool.getUnsiloedLiquidity(), 0); + + uint64[] memory removableChainSelectors = new uint64[](1); + removableChainSelectors[0] = SILOED_CHAIN_SELECTOR; + + s_siloedLockReleaseTokenPool.updateSiloDesignations( + removableChainSelectors, new SiloedLockReleaseTokenPool.SiloConfigUpdate[](0) + ); + + // Check that the locked funds accounting was cleared when the funds were un-siloed. + assertFalse(s_siloedLockReleaseTokenPool.isSiloed(SILOED_CHAIN_SELECTOR)); + assertEq(s_siloedLockReleaseTokenPool.getAvailableTokens(SILOED_CHAIN_SELECTOR), amount); + + // Assert that the available liquidity moved from being siloed to unsiloed. + assertEq(s_siloedLockReleaseTokenPool.getUnsiloedLiquidity(), amount); + } + + // Reverts + + function test_updateSiloDesignations_RevertWhen_ChainNotSiloed() public { + uint64[] memory removableChainSelectors = new uint64[](1); + removableChainSelectors[0] = DEST_CHAIN_SELECTOR; + + vm.expectRevert(abi.encodeWithSelector(SiloedLockReleaseTokenPool.ChainNotSiloed.selector, DEST_CHAIN_SELECTOR)); + + s_siloedLockReleaseTokenPool.updateSiloDesignations( + removableChainSelectors, new SiloedLockReleaseTokenPool.SiloConfigUpdate[](0) + ); + } + + function test_updateSiloDesignations_RevertWhen_InvalidChainSelector() public { + SiloedLockReleaseTokenPool.SiloConfigUpdate[] memory adds = new SiloedLockReleaseTokenPool.SiloConfigUpdate[](1); + adds[0] = SiloedLockReleaseTokenPool.SiloConfigUpdate({remoteChainSelector: 0, rebalancer: OWNER}); + + vm.expectRevert(abi.encodeWithSelector(SiloedLockReleaseTokenPool.InvalidChainSelector.selector, 0)); + + s_siloedLockReleaseTokenPool.updateSiloDesignations(new uint64[](0), adds); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.withdrawLiquidity.t.sol b/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.withdrawLiquidity.t.sol new file mode 100644 index 00000000000..7a82f0954a0 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.withdrawLiquidity.t.sol @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import {SiloedLockReleaseTokenPool} from "../../../pools/SiloedLockReleaseTokenPool.sol"; +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {SiloedLockReleaseTokenPoolSetup} from "./SiloedLockReleaseTokenPoolSetup.t.sol"; + +contract SiloedLockReleaseTokenPool_withdrawLiqudity is SiloedLockReleaseTokenPoolSetup { + address public UNAUTHORIZED_ADDRESS = address(0xdeadbeef); + + function setUp() public override { + super.setUp(); + + s_siloedLockReleaseTokenPool.setSiloRebalancer(SILOED_CHAIN_SELECTOR, OWNER); + } + + function test_withdrawLiquidity_SiloedFunds() public { + uint256 amount = 1e24; + + uint256 balanceBefore = s_token.balanceOf(OWNER); + + // Provide the Liquidity first + s_siloedLockReleaseTokenPool.provideSiloedLiquidity(SILOED_CHAIN_SELECTOR, amount); + + vm.expectEmit(); + emit SiloedLockReleaseTokenPool.LiquidityRemoved(SILOED_CHAIN_SELECTOR, OWNER, amount); + + // Remove the Liquidity + s_siloedLockReleaseTokenPool.withdrawSiloedLiquidity(SILOED_CHAIN_SELECTOR, amount); + + assertEq(s_token.balanceOf(OWNER), balanceBefore); + assertEq(s_token.balanceOf(address(s_siloedLockReleaseTokenPool)), 0); + assertEq(s_siloedLockReleaseTokenPool.getAvailableTokens(SILOED_CHAIN_SELECTOR), 0); + assertEq(s_siloedLockReleaseTokenPool.getUnsiloedLiquidity(), 0); + } + + function test_withdrawSiloedLiquidity_UnsiloedFunds() public { + uint256 amount = 1e24; + + uint256 balanceBefore = s_token.balanceOf(OWNER); + + // Provide the Liquidity first + s_siloedLockReleaseTokenPool.provideSiloedLiquidity(DEST_CHAIN_SELECTOR, amount); + + assertEq(s_siloedLockReleaseTokenPool.getUnsiloedLiquidity(), amount); + + vm.expectEmit(); + emit SiloedLockReleaseTokenPool.LiquidityRemoved(DEST_CHAIN_SELECTOR, OWNER, amount); + + // Remove the Liquidity + s_siloedLockReleaseTokenPool.withdrawSiloedLiquidity(DEST_CHAIN_SELECTOR, amount); + + assertEq(s_token.balanceOf(OWNER), balanceBefore); + assertEq(s_token.balanceOf(address(s_siloedLockReleaseTokenPool)), 0); + assertEq(s_siloedLockReleaseTokenPool.getUnsiloedLiquidity(), 0); + } + + function test_withdrawLiquidity_UnsiloedFunds_LegacyFunctionSelector() public { + uint256 amount = 1e24; + + uint256 balanceBefore = s_token.balanceOf(OWNER); + + // Provide the Liquidity first + s_siloedLockReleaseTokenPool.provideSiloedLiquidity(DEST_CHAIN_SELECTOR, amount); + + assertEq(s_siloedLockReleaseTokenPool.getUnsiloedLiquidity(), amount); + + vm.expectEmit(); + emit SiloedLockReleaseTokenPool.LiquidityRemoved(0, OWNER, amount); + + // Remove the Liquidity + s_siloedLockReleaseTokenPool.withdrawLiquidity(amount); + + assertEq(s_token.balanceOf(OWNER), balanceBefore); + assertEq(s_token.balanceOf(address(s_siloedLockReleaseTokenPool)), 0); + assertEq(s_siloedLockReleaseTokenPool.getUnsiloedLiquidity(), 0); + assertEq(s_siloedLockReleaseTokenPool.getAvailableTokens(DEST_CHAIN_SELECTOR), 0); + } + + // Reverts + + function test_withdrawLiquidity_RevertWhen_SiloedFunds_NotEnoughLiquidity() public { + uint256 liquidityAmount = 1e24; + uint256 withdrawAmount = liquidityAmount + 1; + + s_siloedLockReleaseTokenPool.provideSiloedLiquidity(SILOED_CHAIN_SELECTOR, liquidityAmount); + + // Call should revert due to underflow error due to trying to burn more tokens than are locked via CCIP. + vm.expectRevert( + abi.encodeWithSelector(SiloedLockReleaseTokenPool.InsufficientLiquidity.selector, liquidityAmount, withdrawAmount) + ); + + s_siloedLockReleaseTokenPool.withdrawSiloedLiquidity(SILOED_CHAIN_SELECTOR, withdrawAmount); + } + + function test_withdrawSiloedLiquidity_RevertWhen_UnsiloedFunds_NotEnoughLiquidity() public { + uint256 liquidityAmount = 1e24; + uint256 withdrawAmount = liquidityAmount + 1; + + s_siloedLockReleaseTokenPool.provideSiloedLiquidity(DEST_CHAIN_SELECTOR, liquidityAmount); + + // Call should revert due to underflow error due to trying to burn more tokens than are locked via CCIP. + vm.expectRevert( + abi.encodeWithSelector(SiloedLockReleaseTokenPool.InsufficientLiquidity.selector, liquidityAmount, withdrawAmount) + ); + + // Test withdrawing funds from unsiloed liquidity pool but underflow + s_siloedLockReleaseTokenPool.withdrawSiloedLiquidity(DEST_CHAIN_SELECTOR, withdrawAmount); + } + + function test_withdrawSiloedLiqudity_RevertWhen_UnauthorizedOnlyUnsiloedRebalancer() public { + vm.startPrank(UNAUTHORIZED_ADDRESS); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, UNAUTHORIZED_ADDRESS)); + + s_siloedLockReleaseTokenPool.withdrawSiloedLiquidity(DEST_CHAIN_SELECTOR, 1); + } + + function test_withdrawLiquidity_RevertsWhen_LegacyFunctionSelectorUnauthorized() public { + vm.startPrank(UNAUTHORIZED_ADDRESS); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, UNAUTHORIZED_ADDRESS)); + + s_siloedLockReleaseTokenPool.withdrawLiquidity(1); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPoolSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPoolSetup.t.sol new file mode 100644 index 00000000000..e7724663e05 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPoolSetup.t.sol @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import {BurnMintERC20} from "../../../../shared/token/ERC20/BurnMintERC20.sol"; +import {Router} from "../../../Router.sol"; +import {SiloedLockReleaseTokenPool} from "../../../pools/SiloedLockReleaseTokenPool.sol"; +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {BaseTest} from "../../BaseTest.t.sol"; + +import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +contract SiloedLockReleaseTokenPoolSetup is BaseTest { + IERC20 internal s_token; + SiloedLockReleaseTokenPool internal s_siloedLockReleaseTokenPool; + address[] internal s_allowedList; + + address internal s_allowedOnRamp = address(123); + address internal s_allowedOffRamp = address(234); + + address internal s_destPoolAddress = address(2736782345); + address internal s_sourcePoolAddress = address(53852352095); + + address internal s_siloedDestPoolAddress = address(4245234524); + uint64 internal constant SILOED_CHAIN_SELECTOR = DEST_CHAIN_SELECTOR + 1; + + function setUp() public virtual override { + super.setUp(); + s_token = new BurnMintERC20("LINK", "LNK", 18, 0, 0); + deal(address(s_token), OWNER, type(uint256).max); + + s_siloedLockReleaseTokenPool = new SiloedLockReleaseTokenPool( + s_token, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMNRemote), address(s_sourceRouter) + ); + + s_siloedLockReleaseTokenPool.setRebalancer(OWNER); + + s_token.approve(address(s_siloedLockReleaseTokenPool), type(uint256).max); + + bytes[] memory remotePoolAddresses = new bytes[](2); + remotePoolAddresses[0] = abi.encode(s_destPoolAddress); + remotePoolAddresses[1] = abi.encode(s_siloedDestPoolAddress); + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](3); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + remotePoolAddresses: remotePoolAddresses, + remoteTokenAddress: abi.encode(address(2)), + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + + chainUpdates[1] = TokenPool.ChainUpdate({ + remoteChainSelector: SILOED_CHAIN_SELECTOR, + remotePoolAddresses: remotePoolAddresses, + remoteTokenAddress: abi.encode(address(2)), + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + + chainUpdates[2] = TokenPool.ChainUpdate({ + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + remotePoolAddresses: remotePoolAddresses, + remoteTokenAddress: abi.encode(address(2)), + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + + s_siloedLockReleaseTokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](3); + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](2); + + onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_allowedOnRamp}); + offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: s_allowedOffRamp}); + + onRampUpdates[1] = Router.OnRamp({destChainSelector: SILOED_CHAIN_SELECTOR, onRamp: s_allowedOnRamp}); + offRampUpdates[1] = Router.OffRamp({sourceChainSelector: SILOED_CHAIN_SELECTOR, offRamp: s_allowedOffRamp}); + + onRampUpdates[2] = Router.OnRamp({destChainSelector: SOURCE_CHAIN_SELECTOR, onRamp: s_allowedOnRamp}); + + s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); + + // Apply Siloeing Rules + SiloedLockReleaseTokenPool.SiloConfigUpdate[] memory adds = new SiloedLockReleaseTokenPool.SiloConfigUpdate[](1); + + adds[0] = + SiloedLockReleaseTokenPool.SiloConfigUpdate({remoteChainSelector: SILOED_CHAIN_SELECTOR, rebalancer: OWNER}); + + s_siloedLockReleaseTokenPool.updateSiloDesignations(new uint64[](0), adds); + + assertTrue(s_siloedLockReleaseTokenPool.isSiloed(SILOED_CHAIN_SELECTOR)); + assertFalse(s_siloedLockReleaseTokenPool.isSiloed(DEST_CHAIN_SELECTOR)); + + s_siloedLockReleaseTokenPool.setSiloRebalancer(SILOED_CHAIN_SELECTOR, OWNER); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.addRemotePool.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.addRemotePool.t.sol index 287ee796f67..5a2e84f5c98 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.addRemotePool.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.addRemotePool.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Router} from "../../../Router.sol"; import {Pool} from "../../../libraries/Pool.sol"; @@ -7,7 +7,7 @@ import {TokenPool} from "../../../pools/TokenPool.sol"; import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; contract TokenPool_addRemotePool is TokenPoolSetup { - function test_addRemotePool_Success() public { + function test_addRemotePool() public { // Use a longer data type to ensure it also works for non-evm bytes memory remotePool = abi.encode(makeAddr("non-evm-1"), makeAddr("non-evm-2")); @@ -130,7 +130,7 @@ contract TokenPool_addRemotePool is TokenPoolSetup { // Reverts - function test_NonExistentChain_Revert() public { + function test_RevertWhen_NonExistentChain() public { uint64 chainSelector = DEST_CHAIN_SELECTOR + 1; bytes memory remotePool = abi.encode(type(uint256).max); @@ -139,7 +139,7 @@ contract TokenPool_addRemotePool is TokenPoolSetup { s_tokenPool.addRemotePool(chainSelector, remotePool); } - function test_ZeroLengthAddressNotAllowed_Revert() public { + function test_RevertWhen_ZeroLengthAddressNotAllowed() public { bytes memory remotePool = ""; vm.expectRevert(abi.encodeWithSelector(TokenPool.ZeroAddressNotAllowed.selector)); @@ -147,7 +147,7 @@ contract TokenPool_addRemotePool is TokenPoolSetup { s_tokenPool.addRemotePool(DEST_CHAIN_SELECTOR, remotePool); } - function test_PoolAlreadyAdded_Revert() public { + function test_RevertWhen_PoolAlreadyAdded() public { uint64 chainSelector = DEST_CHAIN_SELECTOR; bytes memory remotePool = abi.encode(type(uint256).max); diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.applyAllowListUpdates.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.applyAllowListUpdates.t.sol index 96629445810..95d498430dc 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.applyAllowListUpdates.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.applyAllowListUpdates.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; import {TokenPool} from "../../../pools/TokenPool.sol"; @@ -8,7 +8,7 @@ import {TokenPoolHelper} from "../../helpers/TokenPoolHelper.sol"; import {TokenPoolWithAllowListSetup} from "./TokenPoolWithAllowListSetup.t.sol"; contract TokenPoolWithAllowList_applyAllowListUpdates is TokenPoolWithAllowListSetup { - function test_SetAllowList_Success() public { + function test_SetAllowList() public { address[] memory newAddresses = new address[](2); newAddresses[0] = address(1); newAddresses[1] = address(2); @@ -60,7 +60,7 @@ contract TokenPoolWithAllowList_applyAllowListUpdates is TokenPoolWithAllowListS assertEq(0, setAddresses.length); } - function test_SetAllowListSkipsZero_Success() public { + function test_SetAllowListSkipsZero() public { uint256 setAddressesLength = s_tokenPool.getAllowList().length; address[] memory newAddresses = new address[](1); @@ -74,16 +74,16 @@ contract TokenPoolWithAllowList_applyAllowListUpdates is TokenPoolWithAllowListS // Reverts - function test_OnlyOwner_Revert() public { + function test_RevertWhen_OnlyOwner() public { vm.stopPrank(); vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); address[] memory newAddresses = new address[](2); s_tokenPool.applyAllowListUpdates(new address[](0), newAddresses); } - function test_AllowListNotEnabled_Revert() public { + function test_RevertWhen_AllowListNotEnabled() public { s_tokenPool = new TokenPoolHelper( - s_token, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), address(s_sourceRouter) + s_token, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMNRemote), address(s_sourceRouter) ); vm.expectRevert(TokenPool.AllowListNotEnabled.selector); diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.applyChainUpdates.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.applyChainUpdates.t.sol index 1ecfc83c5ce..e26cf766362 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.applyChainUpdates.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.applyChainUpdates.t.sol @@ -1,27 +1,26 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; import {BurnMintERC677} from "../../../../shared/token/ERC677/BurnMintERC677.sol"; import {RateLimiter} from "../../../libraries/RateLimiter.sol"; import {TokenPool} from "../../../pools/TokenPool.sol"; - +import {BaseTest} from "../../BaseTest.t.sol"; import {TokenPoolHelper} from "../../helpers/TokenPoolHelper.sol"; -import {RouterSetup} from "../../router/Router/RouterSetup.t.sol"; import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -contract TokenPool_applyChainUpdates is RouterSetup { +contract TokenPool_applyChainUpdates is BaseTest { IERC20 internal s_token; TokenPoolHelper internal s_tokenPool; function setUp() public virtual override { - RouterSetup.setUp(); + super.setUp(); s_token = new BurnMintERC677("LINK", "LNK", 18, 0); deal(address(s_token), OWNER, type(uint256).max); s_tokenPool = new TokenPoolHelper( - s_token, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), address(s_sourceRouter) + s_token, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMNRemote), address(s_sourceRouter) ); } @@ -48,7 +47,7 @@ contract TokenPool_applyChainUpdates is RouterSetup { } } - function test_applyChainUpdates_Success() public { + function test_applyChainUpdates() public { RateLimiter.Config memory outboundRateLimit1 = RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e18}); RateLimiter.Config memory inboundRateLimit1 = RateLimiter.Config({isEnabled: true, capacity: 100e29, rate: 1e19}); RateLimiter.Config memory outboundRateLimit2 = RateLimiter.Config({isEnabled: true, capacity: 100e26, rate: 1e16}); @@ -200,13 +199,13 @@ contract TokenPool_applyChainUpdates is RouterSetup { // Reverts - function test_applyChainUpdates_OnlyCallableByOwner_Revert() public { + function test_RevertWhen_applyChainUpdates_OnlyCallableByOwner() public { vm.startPrank(STRANGER); vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); s_tokenPool.applyChainUpdates(new uint64[](0), new TokenPool.ChainUpdate[](0)); } - function test_applyChainUpdates_ZeroAddressNotAllowed_Revert() public { + function test_RevertWhen_applyChainUpdates_ZeroAddressNotAllowed() public { bytes[] memory remotePoolAddresses = new bytes[](1); remotePoolAddresses[0] = ""; @@ -235,7 +234,7 @@ contract TokenPool_applyChainUpdates is RouterSetup { s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdates); } - function test_applyChainUpdates_NonExistentChain_Revert() public { + function test_RevertWhen_applyChainUpdates_NonExistentChain() public { uint64[] memory chainRemoves = new uint64[](1); chainRemoves[0] = 1; @@ -243,7 +242,7 @@ contract TokenPool_applyChainUpdates is RouterSetup { s_tokenPool.applyChainUpdates(chainRemoves, new TokenPool.ChainUpdate[](0)); } - function test_applyChainUpdates_InvalidRateLimitRate_Revert() public { + function test_RevertWhen_applyChainUpdates_InvalidRateLimitRate() public { uint64 unusedChainSelector = 2 ** 64 - 1; TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.calculateLocalAmount.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.calculateLocalAmount.t.sol index 4262fac2218..8faf2303524 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.calculateLocalAmount.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.calculateLocalAmount.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {TokenPool} from "../../../pools/TokenPool.sol"; import {TokenPoolHelper} from "../../helpers/TokenPoolHelper.sol"; @@ -36,7 +36,7 @@ contract TokenPool_calculateLocalAmount is TokenPoolSetup { // Reverts - function test_calculateLocalAmount_RevertWhen_LowRemoteDecimalsOverflows() public { + function test_RevertWhen_calculateLocalAmountWhen_LowRemoteDecimalsOverflows() public { uint8 remoteDecimals = 0; uint8 localDecimals = 78; uint256 remoteAmount = 1; @@ -44,7 +44,7 @@ contract TokenPool_calculateLocalAmount is TokenPoolSetup { vm.mockCall(address(s_token), abi.encodeWithSelector(IERC20Metadata.decimals.selector), abi.encode(localDecimals)); s_tokenPool = - new TokenPoolHelper(s_token, localDecimals, new address[](0), address(s_mockRMN), address(s_sourceRouter)); + new TokenPoolHelper(s_token, localDecimals, new address[](0), address(s_mockRMNRemote), address(s_sourceRouter)); vm.expectRevert( abi.encodeWithSelector(TokenPool.OverflowDetected.selector, remoteDecimals, localDecimals, remoteAmount) @@ -53,7 +53,7 @@ contract TokenPool_calculateLocalAmount is TokenPoolSetup { s_tokenPool.calculateLocalAmount(remoteAmount, remoteDecimals); } - function test_calculateLocalAmount_RevertWhen_HighLocalDecimalsOverflows() public { + function test_RevertWhen_calculateLocalAmountWhen_HighLocalDecimalsOverflows() public { uint8 remoteDecimals = 18; uint8 localDecimals = 18 + 78; uint256 remoteAmount = 1; @@ -61,7 +61,7 @@ contract TokenPool_calculateLocalAmount is TokenPoolSetup { vm.mockCall(address(s_token), abi.encodeWithSelector(IERC20Metadata.decimals.selector), abi.encode(localDecimals)); s_tokenPool = - new TokenPoolHelper(s_token, localDecimals, new address[](0), address(s_mockRMN), address(s_sourceRouter)); + new TokenPoolHelper(s_token, localDecimals, new address[](0), address(s_mockRMNRemote), address(s_sourceRouter)); vm.expectRevert( abi.encodeWithSelector(TokenPool.OverflowDetected.selector, remoteDecimals, localDecimals, remoteAmount) @@ -70,7 +70,7 @@ contract TokenPool_calculateLocalAmount is TokenPoolSetup { s_tokenPool.calculateLocalAmount(remoteAmount, remoteDecimals); } - function test_calculateLocalAmount_RevertWhen_HighRemoteDecimalsOverflows() public { + function test_RevertWhen_calculateLocalAmountWhen_HighRemoteDecimalsOverflows() public { uint8 remoteDecimals = 18 + 78; uint8 localDecimals = 18; uint256 remoteAmount = 1; @@ -82,7 +82,7 @@ contract TokenPool_calculateLocalAmount is TokenPoolSetup { s_tokenPool.calculateLocalAmount(remoteAmount, remoteDecimals); } - function test_calculateLocalAmount_RevertWhen_HighAmountOverflows() public { + function test_RevertWhen_calculateLocalAmountWhen_HighAmountOverflows() public { uint8 remoteDecimals = 18; uint8 localDecimals = 18 + 28; uint256 remoteAmount = 1e50; @@ -90,7 +90,7 @@ contract TokenPool_calculateLocalAmount is TokenPoolSetup { vm.mockCall(address(s_token), abi.encodeWithSelector(IERC20Metadata.decimals.selector), abi.encode(localDecimals)); s_tokenPool = - new TokenPoolHelper(s_token, localDecimals, new address[](0), address(s_mockRMN), address(s_sourceRouter)); + new TokenPoolHelper(s_token, localDecimals, new address[](0), address(s_mockRMNRemote), address(s_sourceRouter)); vm.expectRevert( abi.encodeWithSelector(TokenPool.OverflowDetected.selector, remoteDecimals, localDecimals, remoteAmount) diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.constructor.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.constructor.t.sol index 4b643d66b9e..28c13582c6f 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.constructor.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.constructor.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {TokenPool} from "../../../pools/TokenPool.sol"; import {TokenPoolHelper} from "../../helpers/TokenPoolHelper.sol"; @@ -12,7 +12,7 @@ import {IERC20Metadata} from contract TokenPool_constructor is TokenPoolSetup { function test_constructor() public view { assertEq(address(s_token), address(s_tokenPool.getToken())); - assertEq(address(s_mockRMN), s_tokenPool.getRmnProxy()); + assertEq(address(s_mockRMNRemote), s_tokenPool.getRmnProxy()); assertFalse(s_tokenPool.getAllowListEnabled()); assertEq(address(s_sourceRouter), s_tokenPool.getRouter()); assertEq(DEFAULT_TOKEN_DECIMALS, s_tokenPool.getTokenDecimals()); @@ -23,22 +23,23 @@ contract TokenPool_constructor is TokenPoolSetup { vm.mockCallRevert(address(s_token), abi.encodeWithSelector(IERC20Metadata.decimals.selector), "decimals fails"); - s_tokenPool = new TokenPoolHelper(s_token, decimals, new address[](0), address(s_mockRMN), address(s_sourceRouter)); + s_tokenPool = + new TokenPoolHelper(s_token, decimals, new address[](0), address(s_mockRMNRemote), address(s_sourceRouter)); assertEq(s_tokenPool.getTokenDecimals(), decimals); } // Reverts - function test_constructor_RevertWhen_ZeroAddressNotAllowed() public { + function test_RevertWhen_constructorWhen_ZeroAddressNotAllowed() public { vm.expectRevert(TokenPool.ZeroAddressNotAllowed.selector); s_tokenPool = new TokenPoolHelper( - IERC20(address(0)), DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), address(s_sourceRouter) + IERC20(address(0)), DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMNRemote), address(s_sourceRouter) ); } - function test_constructor_RevertWhen_InvalidDecimalArgs() public { + function test_RevertWhen_constructorWhen_InvalidDecimalArgs() public { uint8 invalidDecimals = DEFAULT_TOKEN_DECIMALS + 1; vm.expectRevert( @@ -46,6 +47,6 @@ contract TokenPool_constructor is TokenPoolSetup { ); s_tokenPool = - new TokenPoolHelper(s_token, invalidDecimals, new address[](0), address(s_mockRMN), address(s_sourceRouter)); + new TokenPoolHelper(s_token, invalidDecimals, new address[](0), address(s_mockRMNRemote), address(s_sourceRouter)); } } diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getAllowList.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getAllowList.t.sol index 8d4256d3479..ea9bbf5d068 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getAllowList.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getAllowList.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {TokenPoolWithAllowListSetup} from "./TokenPoolWithAllowListSetup.t.sol"; contract TokenPoolWithAllowList_getAllowList is TokenPoolWithAllowListSetup { - function test_GetAllowList_Success() public view { + function test_GetAllowList() public view { address[] memory setAddresses = s_tokenPool.getAllowList(); assertEq(2, setAddresses.length); assertEq(s_allowedSenders[0], setAddresses[0]); diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getAllowListEnabled.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getAllowListEnabled.t.sol index 2a36a846999..b710433f785 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getAllowListEnabled.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getAllowListEnabled.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {TokenPoolWithAllowListSetup} from "./TokenPoolWithAllowListSetup.t.sol"; contract TokenPoolWithAllowList_getAllowListEnabled is TokenPoolWithAllowListSetup { - function test_GetAllowListEnabled_Success() public view { + function test_GetAllowListEnabled() public view { assertTrue(s_tokenPool.getAllowListEnabled()); } } diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getRemotePool.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getRemotePool.t.sol index 5e619aede4c..dc570781d81 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getRemotePool.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getRemotePool.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {TokenPool} from "../../../pools/TokenPool.sol"; import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.onlyOffRamp.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.onlyOffRamp.t.sol index 8df07a285f3..7f972010754 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.onlyOffRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.onlyOffRamp.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Router} from "../../../Router.sol"; import {TokenPool} from "../../../pools/TokenPool.sol"; import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; contract TokenPool_onlyOffRamp is TokenPoolSetup { - function test_onlyOffRamp_Success() public { + function test_onlyOffRamp() public { uint64 chainSelector = DEST_CHAIN_SELECTOR; address offRamp = makeAddr("onRamp"); @@ -19,7 +19,7 @@ contract TokenPool_onlyOffRamp is TokenPoolSetup { s_tokenPool.onlyOffRampModifier(chainSelector); } - function test_ChainNotAllowed_Revert() public { + function test_RevertWhen_ChainNotAllowed() public { uint64 chainSelector = DEST_CHAIN_SELECTOR + 1; address offRamp = makeAddr("onRamp"); @@ -60,7 +60,7 @@ contract TokenPool_onlyOffRamp is TokenPoolSetup { s_tokenPool.onlyOffRampModifier(chainSelector); } - function test_CallerIsNotARampOnRouter_Revert() public { + function test_RevertWhen_CallerIsNotARampOnRouter() public { uint64 chainSelector = DEST_CHAIN_SELECTOR; address offRamp = makeAddr("offRamp"); diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.onlyOnRamp.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.onlyOnRamp.t.sol index be0c21e4c1e..970228c424f 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.onlyOnRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.onlyOnRamp.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Router} from "../../../Router.sol"; import {TokenPool} from "../../../pools/TokenPool.sol"; import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; contract TokenPool_onlyOnRamp is TokenPoolSetup { - function test_onlyOnRamp_Success() public { + function test_onlyOnRamp() public { uint64 chainSelector = DEST_CHAIN_SELECTOR; address onRamp = makeAddr("onRamp"); @@ -19,7 +19,7 @@ contract TokenPool_onlyOnRamp is TokenPoolSetup { s_tokenPool.onlyOnRampModifier(chainSelector); } - function test_ChainNotAllowed_Revert() public { + function test_RevertWhen_ChainNotAllowed() public { uint64 chainSelector = DEST_CHAIN_SELECTOR + 1; address onRamp = makeAddr("onRamp"); @@ -60,7 +60,7 @@ contract TokenPool_onlyOnRamp is TokenPoolSetup { s_tokenPool.onlyOffRampModifier(chainSelector); } - function test_CallerIsNotARampOnRouter_Revert() public { + function test_RevertWhen_CallerIsNotARampOnRouter() public { uint64 chainSelector = DEST_CHAIN_SELECTOR; address onRamp = makeAddr("onRamp"); diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.parseRemoteDecimals.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.parseRemoteDecimals.t.sol index 9817fe227e4..49b40fc5c60 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.parseRemoteDecimals.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.parseRemoteDecimals.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {TokenPool} from "../../../pools/TokenPool.sol"; import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; @@ -18,7 +18,7 @@ contract TokenPool_parseRemoteDecimals is TokenPoolSetup { assertEq(s_tokenPool.parseRemoteDecimals(""), s_tokenPool.getTokenDecimals()); } - function test_parseRemoteDecimals_RevertWhen_InvalidRemoteChainDecimals_DigitTooLarge() public { + function test_RevertWhen_parseRemoteDecimalsWhen_InvalidRemoteChainDecimals_DigitTooLarge() public { bytes memory encodedDecimals = abi.encode(uint256(256)); vm.expectRevert(abi.encodeWithSelector(TokenPool.InvalidRemoteChainDecimals.selector, encodedDecimals)); @@ -26,7 +26,7 @@ contract TokenPool_parseRemoteDecimals is TokenPoolSetup { s_tokenPool.parseRemoteDecimals(encodedDecimals); } - function test_parseRemoteDecimals_RevertWhen_InvalidRemoteChainDecimals_WrongType() public { + function test_RevertWhen_parseRemoteDecimalsWhen_InvalidRemoteChainDecimals_WrongType() public { bytes memory encodedDecimals = abi.encode(uint256(256), "wrong type"); vm.expectRevert(abi.encodeWithSelector(TokenPool.InvalidRemoteChainDecimals.selector, encodedDecimals)); diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.removeRemotePool.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.removeRemotePool.t.sol index 2fa9ef16624..ac50a34b8ca 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.removeRemotePool.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.removeRemotePool.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {TokenPool} from "../../../pools/TokenPool.sol"; import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; contract TokenPool_removeRemotePool is TokenPoolSetup { - function test_removeRemotePool_Success() public { + function test_removeRemotePool() public { uint64 chainSelector = DEST_CHAIN_SELECTOR; // Use a longer data type to ensure it also works for non-evm bytes memory remotePool = abi.encode(makeAddr("non-evm-1"), makeAddr("non-evm-2")); @@ -41,7 +41,7 @@ contract TokenPool_removeRemotePool is TokenPoolSetup { // Reverts - function test_NonExistentChain_Revert() public { + function test_RevertWhen_NonExistentChain() public { uint64 chainSelector = DEST_CHAIN_SELECTOR + 1; bytes memory remotePool = abi.encode(type(uint256).max); @@ -50,7 +50,7 @@ contract TokenPool_removeRemotePool is TokenPoolSetup { s_tokenPool.removeRemotePool(chainSelector, remotePool); } - function test_InvalidRemotePoolForChain_Revert() public { + function test_RevertWhen_InvalidRemotePoolForChain() public { uint64 chainSelector = DEST_CHAIN_SELECTOR; bytes memory remotePool = abi.encode(type(uint256).max); diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setChainRateLimiterConfig.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setChainRateLimiterConfig.t.sol index 4dea9bf4032..afb8a649a07 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setChainRateLimiterConfig.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setChainRateLimiterConfig.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {RateLimiter} from "../../../libraries/RateLimiter.sol"; import {TokenPool} from "../../../pools/TokenPool.sol"; @@ -50,7 +50,7 @@ contract TokenPool_setChainRateLimiterConfig is TokenPoolSetup { // Reverts - function test_OnlyOwnerOrRateLimitAdmin_Revert() public { + function test_RevertWhen_OnlyOwnerOrRateLimitAdmin() public { vm.startPrank(STRANGER); vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, STRANGER)); @@ -59,7 +59,7 @@ contract TokenPool_setChainRateLimiterConfig is TokenPoolSetup { ); } - function test_NonExistentChain_Revert() public { + function test_RevertWhen_NonExistentChain() public { uint64 wrongChainSelector = 9084102894; vm.expectRevert(abi.encodeWithSelector(TokenPool.NonExistentChain.selector, wrongChainSelector)); diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setChainRateLimiterConfigs.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setChainRateLimiterConfigs.t.sol index 716e06734ee..27e01fd5921 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setChainRateLimiterConfigs.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setChainRateLimiterConfigs.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {RateLimiter} from "../../../libraries/RateLimiter.sol"; import {TokenPool} from "../../../pools/TokenPool.sol"; @@ -79,7 +79,7 @@ contract TokenPool_setChainRateLimiterConfigs is TokenPoolSetup { // Reverts - function test_OnlyOwnerOrRateLimitAdmin_Revert() public { + function test_RevertWhen_OnlyOwnerOrRateLimitAdmin() public { uint64[] memory chainSelectors = new uint64[](1); chainSelectors[0] = DEST_CHAIN_SELECTOR; @@ -95,7 +95,7 @@ contract TokenPool_setChainRateLimiterConfigs is TokenPoolSetup { s_tokenPool.setChainRateLimiterConfigs(chainSelectors, newOutboundConfigs, newInboundConfigs); } - function test_NonExistentChain_Revert() public { + function test_RevertWhen_NonExistentChain() public { uint64 wrongChainSelector = 9084102894; uint64[] memory chainSelectors = new uint64[](1); @@ -108,7 +108,7 @@ contract TokenPool_setChainRateLimiterConfigs is TokenPoolSetup { s_tokenPool.setChainRateLimiterConfigs(chainSelectors, newOutboundConfigs, newInboundConfigs); } - function test_MismatchedArrayLengths_Revert() public { + function test_RevertWhen_MismatchedArrayLengths() public { uint64[] memory chainSelectors = new uint64[](1); RateLimiter.Config[] memory newOutboundConfigs = new RateLimiter.Config[](1); diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setRateLimitAdmin.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setRateLimitAdmin.t.sol index 7c57741cf42..0d6622f859a 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setRateLimitAdmin.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setRateLimitAdmin.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; @@ -7,7 +7,7 @@ import {TokenPool} from "../../../pools/TokenPool.sol"; import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; contract TokenPool_setRateLimitAdmin is TokenPoolSetup { - function test_SetRateLimitAdmin_Success() public { + function test_SetRateLimitAdmin() public { assertEq(address(0), s_tokenPool.getRateLimitAdmin()); vm.expectEmit(); emit TokenPool.RateLimitAdminSet(OWNER); @@ -17,7 +17,7 @@ contract TokenPool_setRateLimitAdmin is TokenPoolSetup { // Reverts - function test_SetRateLimitAdmin_Revert() public { + function test_RevertWhen_SetRateLimitAdmin() public { vm.startPrank(STRANGER); vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setRouter.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setRouter.t.sol index 4bf85f3af9f..37108e3899b 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setRouter.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setRouter.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {TokenPool} from "../../../pools/TokenPool.sol"; import {TokenPoolWithAllowListSetup} from "./TokenPoolWithAllowListSetup.t.sol"; contract TokenPoolWithAllowList_setRouter is TokenPoolWithAllowListSetup { - function test_SetRouter_Success() public { + function test_SetRouter() public { assertEq(address(s_sourceRouter), s_tokenPool.getRouter()); address newRouter = makeAddr("newRouter"); @@ -20,7 +20,7 @@ contract TokenPoolWithAllowList_setRouter is TokenPoolWithAllowListSetup { // Reverts - function test_ZeroAddressNotAllowed_Revert() public { + function test_RevertWhen_ZeroAddressNotAllowed() public { address newRouter = address(0); vm.expectRevert(TokenPool.ZeroAddressNotAllowed.selector); diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPoolSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPoolSetup.t.sol index b2bdeefee12..0fb44fba024 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPoolSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPoolSetup.t.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {BurnMintERC20} from "../../../../shared/token/ERC20/BurnMintERC20.sol"; import {TokenPool} from "../../../pools/TokenPool.sol"; +import {BaseTest} from "../../BaseTest.t.sol"; import {TokenPoolHelper} from "../../helpers/TokenPoolHelper.sol"; -import {RouterSetup} from "../../router/Router/RouterSetup.t.sol"; import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -contract TokenPoolSetup is RouterSetup { +contract TokenPoolSetup is BaseTest { IERC20 internal s_token; TokenPoolHelper internal s_tokenPool; @@ -16,12 +16,12 @@ contract TokenPoolSetup is RouterSetup { address internal s_initialRemoteToken = makeAddr("initialRemoteToken"); function setUp() public virtual override { - RouterSetup.setUp(); + super.setUp(); s_token = new BurnMintERC20("LINK", "LNK", 18, 0, 0); deal(address(s_token), OWNER, type(uint256).max); s_tokenPool = new TokenPoolHelper( - s_token, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), address(s_sourceRouter) + s_token, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMNRemote), address(s_sourceRouter) ); bytes[] memory remotePoolAddresses = new bytes[](1); diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPoolWithAllowListSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPoolWithAllowListSetup.t.sol index 478e8996376..f69b004d548 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPoolWithAllowListSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPoolWithAllowListSetup.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {TokenPoolHelper} from "../../helpers/TokenPoolHelper.sol"; import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; @@ -14,7 +14,7 @@ contract TokenPoolWithAllowListSetup is TokenPoolSetup { s_allowedSenders.push(OWNER); s_tokenPool = new TokenPoolHelper( - s_token, DEFAULT_TOKEN_DECIMALS, s_allowedSenders, address(s_mockRMN), address(s_sourceRouter) + s_token, DEFAULT_TOKEN_DECIMALS, s_allowedSenders, address(s_mockRMNRemote), address(s_sourceRouter) ); } } diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.lockOrBurn.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.lockOrBurn.t.sol index 394357f213f..51556b63d17 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.lockOrBurn.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.lockOrBurn.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {ITokenMessenger} from "../../../../pools/USDC/ITokenMessenger.sol"; @@ -11,7 +11,7 @@ import {USDCTokenPool} from "../../../../pools/USDC/USDCTokenPool.sol"; import {HybridLockReleaseUSDCTokenPoolSetup} from "./HybridLockReleaseUSDCTokenPoolSetup.t.sol"; contract HybridLockReleaseUSDCTokenPool_lockOrBurn is HybridLockReleaseUSDCTokenPoolSetup { - function test_onLockReleaseMechanism_Success() public { + function test_onLockReleaseMechanism() public { bytes32 receiver = bytes32(uint256(uint160(STRANGER))); // Mark the destination chain as supporting CCTP, so use L/R instead. @@ -47,7 +47,7 @@ contract HybridLockReleaseUSDCTokenPool_lockOrBurn is HybridLockReleaseUSDCToken assertEq(s_token.balanceOf(address(s_usdcTokenPool)), amount, "Incorrect token amount in the tokenPool"); } - function test_PrimaryMechanism_Success() public { + function test_PrimaryMechanism() public { bytes32 receiver = bytes32(uint256(uint160(STRANGER))); uint256 amount = 1; @@ -91,9 +91,9 @@ contract HybridLockReleaseUSDCTokenPool_lockOrBurn is HybridLockReleaseUSDCToken assertEq(s_mockUSDC.s_nonce() - 1, nonce); } - function test_onLockReleaseMechanism_thenSwitchToPrimary_Success() public { + function test_onLockReleaseMechanism_thenSwitchToPrimary() public { // Test Enabling the LR mechanism and sending an outgoing message - test_PrimaryMechanism_Success(); + test_PrimaryMechanism(); // Disable the LR mechanism so that primary CCTP is used and then attempt to send a message uint64[] memory destChainRemoves = new uint64[](1); @@ -107,10 +107,10 @@ contract HybridLockReleaseUSDCTokenPool_lockOrBurn is HybridLockReleaseUSDCToken s_usdcTokenPool.updateChainSelectorMechanisms(destChainRemoves, new uint64[](0)); // Send an outgoing message - test_PrimaryMechanism_Success(); + test_PrimaryMechanism(); } - function test_WhileMigrationPause_Revert() public { + function test_RevertWhen_WhileMigrationPause() public { // Mark the destination chain as supporting CCTP, so use L/R instead. uint64[] memory destChainAdds = new uint64[](1); destChainAdds[0] = DEST_CHAIN_SELECTOR; diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.releaseOrMint.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.releaseOrMint.t.sol index ea3c581ea52..f528ea2586a 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.releaseOrMint.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.releaseOrMint.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Internal} from "../../../../libraries/Internal.sol"; import {Pool} from "../../../../libraries/Pool.sol"; @@ -12,7 +12,7 @@ import {MockE2EUSDCTransmitter} from "../../../mocks/MockE2EUSDCTransmitter.sol" import {HybridLockReleaseUSDCTokenPoolSetup} from "./HybridLockReleaseUSDCTokenPoolSetup.t.sol"; contract HybridLockReleaseUSDCTokenPool_releaseOrMint is HybridLockReleaseUSDCTokenPoolSetup { - function test_OnLockReleaseMechanism_Success() public { + function test_OnLockReleaseMechanism() public { address recipient = address(1234); // Designate the SOURCE_CHAIN as not using native-USDC, and so the L/R mechanism must be used instead @@ -120,7 +120,7 @@ contract HybridLockReleaseUSDCTokenPool_releaseOrMint is HybridLockReleaseUSDCTo ); } - function test_WhileMigrationPause_Revert() public { + function test_RevertWhen_WhileMigrationPause() public { address recipient = address(1234); // Designate the SOURCE_CHAIN as not using native-USDC, and so the L/R mechanism must be used instead diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.transferLiquidity.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.transferLiquidity.t.sol deleted file mode 100644 index 4e5a45a1438..00000000000 --- a/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.transferLiquidity.t.sol +++ /dev/null @@ -1,95 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ILiquidityContainer} from "../../../../../liquiditymanager/interfaces/ILiquidityContainer.sol"; - -import {HybridLockReleaseUSDCTokenPool} from "../../../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; -import {HybridLockReleaseUSDCTokenPoolSetup} from "./HybridLockReleaseUSDCTokenPoolSetup.t.sol"; - -contract HybridLockReleaseUSDCTokenPool_TransferLiquidity is HybridLockReleaseUSDCTokenPoolSetup { - function test_transferLiquidity_Success() public { - // Set as the OWNER so we can provide liquidity - vm.startPrank(OWNER); - - s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); - s_token.approve(address(s_usdcTokenPool), type(uint256).max); - - uint256 liquidityAmount = 1e9; - - // Provide some liquidity to the pool - s_usdcTokenPool.provideLiquidity(DEST_CHAIN_SELECTOR, liquidityAmount); - - // Set the new token pool as the rebalancer - s_usdcTokenPool.transferOwnership(address(s_usdcTokenPoolTransferLiquidity)); - - vm.expectEmit(); - emit ILiquidityContainer.LiquidityRemoved(address(s_usdcTokenPoolTransferLiquidity), liquidityAmount); - - vm.expectEmit(); - emit HybridLockReleaseUSDCTokenPool.LiquidityTransferred( - address(s_usdcTokenPool), DEST_CHAIN_SELECTOR, liquidityAmount - ); - - s_usdcTokenPoolTransferLiquidity.transferLiquidity(address(s_usdcTokenPool), DEST_CHAIN_SELECTOR); - - assertEq( - s_usdcTokenPool.owner(), - address(s_usdcTokenPoolTransferLiquidity), - "Ownership of the old pool should be transferred to the new pool" - ); - - assertEq( - s_usdcTokenPoolTransferLiquidity.getLockedTokensForChain(DEST_CHAIN_SELECTOR), - liquidityAmount, - "Tokens locked for dest chain doesn't match expected amount in storage" - ); - - assertEq( - s_usdcTokenPool.getLockedTokensForChain(DEST_CHAIN_SELECTOR), - 0, - "Tokens locked for dest chain in old token pool doesn't match expected amount in storage" - ); - - assertEq( - s_token.balanceOf(address(s_usdcTokenPoolTransferLiquidity)), - liquidityAmount, - "Liquidity amount of tokens should be new in new pool, but aren't" - ); - - assertEq( - s_token.balanceOf(address(s_usdcTokenPool)), - 0, - "Liquidity amount of tokens should be zero in old pool, but aren't" - ); - } - - function test_cannotTransferLiquidityDuringPendingMigration_Revert() public { - // Set as the OWNER so we can provide liquidity - vm.startPrank(OWNER); - - // Mark the destination chain as supporting CCTP, so use L/R instead. - uint64[] memory destChainAdds = new uint64[](1); - destChainAdds[0] = DEST_CHAIN_SELECTOR; - - s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); - - s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); - s_token.approve(address(s_usdcTokenPool), type(uint256).max); - - uint256 liquidityAmount = 1e9; - - // Provide some liquidity to the pool - s_usdcTokenPool.provideLiquidity(DEST_CHAIN_SELECTOR, liquidityAmount); - - // Set the new token pool as the rebalancer - s_usdcTokenPool.transferOwnership(address(s_usdcTokenPoolTransferLiquidity)); - - s_usdcTokenPool.proposeCCTPMigration(DEST_CHAIN_SELECTOR); - - vm.expectRevert( - abi.encodeWithSelector(HybridLockReleaseUSDCTokenPool.LanePausedForCCTPMigration.selector, DEST_CHAIN_SELECTOR) - ); - - s_usdcTokenPoolTransferLiquidity.transferLiquidity(address(s_usdcTokenPool), DEST_CHAIN_SELECTOR); - } -} diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPoolSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPoolSetup.t.sol index 9b318b782ce..13262fa6472 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPoolSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPoolSetup.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {BurnMintERC677} from "../../../../../shared/token/ERC677/BurnMintERC677.sol"; @@ -15,11 +15,13 @@ contract HybridLockReleaseUSDCTokenPoolSetup is USDCSetup { function setUp() public virtual override { super.setUp(); - s_usdcTokenPool = - new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + s_usdcTokenPool = new HybridLockReleaseUSDCTokenPool( + s_mockUSDC, s_token, new address[](0), address(s_mockRMNRemote), address(s_router) + ); - s_usdcTokenPoolTransferLiquidity = - new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + s_usdcTokenPoolTransferLiquidity = new HybridLockReleaseUSDCTokenPool( + s_mockUSDC, s_token, new address[](0), address(s_mockRMNRemote), address(s_router) + ); BurnMintERC677(address(s_token)).grantMintAndBurnRoles(address(s_usdcTokenPool)); diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.burnLockedUSDC.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.burnLockedUSDC.t.sol index 52ddb9dad4c..59055fe4978 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.burnLockedUSDC.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.burnLockedUSDC.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Pool} from "../../../../libraries/Pool.sol"; import {TokenPool} from "../../../../pools/TokenPool.sol"; @@ -8,7 +8,7 @@ import {HybridLockReleaseUSDCTokenPool_lockOrBurn} from "../HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.lockOrBurn.t.sol"; contract USDCBridgeMigrator_BurnLockedUSDC is HybridLockReleaseUSDCTokenPool_lockOrBurn { - function test_lockOrBurn_then_BurnInCCTPMigration_Success() public { + function test_lockOrBurn_then_BurnInCCTPMigration() public { bytes32 receiver = bytes32(uint256(uint160(STRANGER))); address CIRCLE = makeAddr("CIRCLE CCTP Migrator"); @@ -96,10 +96,10 @@ contract USDCBridgeMigrator_BurnLockedUSDC is HybridLockReleaseUSDCTokenPool_loc s_usdcTokenPool.shouldUseLockRelease(DEST_CHAIN_SELECTOR), "Lock/Release mech should be disabled after a burn" ); - test_PrimaryMechanism_Success(); + test_PrimaryMechanism(); } - function test_invalidPermissions_Revert() public { + function test_RevertWhen_invalidPermissions() public { address CIRCLE = makeAddr("CIRCLE"); vm.startPrank(OWNER); diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.cancelMigrationProposal.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.cancelMigrationProposal.t.sol index f4f56cba3e6..40df069d80e 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.cancelMigrationProposal.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.cancelMigrationProposal.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {USDCBridgeMigrator} from "../../../../pools/USDC/USDCBridgeMigrator.sol"; import {HybridLockReleaseUSDCTokenPoolSetup} from "./USDCBridgeMigratorSetup.t.sol"; contract USDCBridgeMigrator_cancelMigrationProposal is HybridLockReleaseUSDCTokenPoolSetup { - function test_cancelExistingCCTPMigrationProposal_Success() public { + function test_cancelExistingCCTPMigrationProposal() public { vm.startPrank(OWNER); // Mark the destination chain as supporting CCTP, so use L/R instead. @@ -40,7 +40,7 @@ contract USDCBridgeMigrator_cancelMigrationProposal is HybridLockReleaseUSDCToke s_usdcTokenPool.cancelExistingCCTPMigrationProposal(); } - function test_cannotCancelANonExistentMigrationProposal_Revert() public { + function test_RevertWhen_cannotCancelANonExistentMigrationProposal() public { vm.expectRevert(USDCBridgeMigrator.NoMigrationProposalPending.selector); // Proposal to migrate doesn't exist, and so the chain selector is zero, and therefore should revert diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.excludeTokensFromBurn.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.excludeTokensFromBurn.t.sol index 855db7c5c64..441de21d0a2 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.excludeTokensFromBurn.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.excludeTokensFromBurn.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {USDCBridgeMigrator} from "../../../../pools/USDC/USDCBridgeMigrator.sol"; import {HybridLockReleaseUSDCTokenPoolSetup} from "./USDCBridgeMigratorSetup.t.sol"; contract USDCBridgeMigrator_excludeTokensFromBurn is HybridLockReleaseUSDCTokenPoolSetup { - function test_excludeTokensWhenNoMigrationProposalPending_Revert() public { + function test_RevertWhen_excludeTokensWhenNoMigrationProposalPending() public { vm.expectRevert(abi.encodeWithSelector(USDCBridgeMigrator.NoMigrationProposalPending.selector)); vm.startPrank(OWNER); diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.proposeMigration.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.proposeMigration.t.sol index b2668bde801..b7c2b46820f 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.proposeMigration.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.proposeMigration.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {USDCBridgeMigrator} from "../../../../pools/USDC/USDCBridgeMigrator.sol"; import {HybridLockReleaseUSDCTokenPoolSetup} from "./USDCBridgeMigratorSetup.t.sol"; contract USDCBridgeMigrator_proposeMigration is HybridLockReleaseUSDCTokenPoolSetup { - function test_ChainNotUsingLockRelease_Revert() public { + function test_RevertWhen_ChainNotUsingLockRelease() public { vm.expectRevert(abi.encodeWithSelector(USDCBridgeMigrator.InvalidChainSelector.selector)); vm.startPrank(OWNER); diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.provideLiquidity.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.provideLiquidity.t.sol index 88196d87795..5163f23f97f 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.provideLiquidity.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.provideLiquidity.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {TokenPool} from "../../../../pools/TokenPool.sol"; import {HybridLockReleaseUSDCTokenPool} from "../../../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; import {USDCBridgeMigrator_BurnLockedUSDC} from "./USDCBridgeMigrator.burnLockedUSDC.t.sol"; contract USDCBridgeMigrator_provideLiquidity is USDCBridgeMigrator_BurnLockedUSDC { - function test_cannotModifyLiquidityWithoutPermissions_Revert() public { + function test_RevertWhen_cannotModifyLiquidityWithoutPermissions() public { address randomAddr = makeAddr("RANDOM"); vm.startPrank(randomAddr); @@ -17,8 +17,8 @@ contract USDCBridgeMigrator_provideLiquidity is USDCBridgeMigrator_BurnLockedUSD s_usdcTokenPool.provideLiquidity(DEST_CHAIN_SELECTOR, 1e6); } - function test_cannotProvideLiquidity_AfterMigration_Revert() public { - test_lockOrBurn_then_BurnInCCTPMigration_Success(); + function test_RevertWhen_cannotProvideLiquidity_AfterMigration() public { + test_lockOrBurn_then_BurnInCCTPMigration(); vm.startPrank(OWNER); @@ -31,7 +31,7 @@ contract USDCBridgeMigrator_provideLiquidity is USDCBridgeMigrator_BurnLockedUSD s_usdcTokenPool.provideLiquidity(DEST_CHAIN_SELECTOR, 1e6); } - function test_cannotProvideLiquidityWhenMigrationProposalPending_Revert() public { + function test_RevertWhen_cannotProvideLiquidityWhenMigrationProposalPending() public { vm.startPrank(OWNER); // Mark the destination chain as supporting CCTP, so use L/R instead. diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.releaseOrMint.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.releaseOrMint.t.sol index 40569603e96..46861d614b6 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.releaseOrMint.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.releaseOrMint.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Internal} from "../../../../libraries/Internal.sol"; import {Pool} from "../../../../libraries/Pool.sol"; @@ -11,7 +11,7 @@ import {HybridLockReleaseUSDCTokenPool_releaseOrMint} from "../HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.releaseOrMint.t.sol"; contract USDCBridgeMigrator_releaseOrMint is HybridLockReleaseUSDCTokenPool_releaseOrMint { - function test_unstickManualTxAfterMigration_destChain_Success() public { + function test_unstickManualTxAfterMigration_destChain() public { address recipient = address(1234); // Test the edge case where a tx is stuck in the manual tx queue and the destination chain is the one that // should process is after a migration. I.E the message will have the Lock-Release flag set in the OffChainData, @@ -83,7 +83,7 @@ contract USDCBridgeMigrator_releaseOrMint is HybridLockReleaseUSDCTokenPool_rele ); } - function test_unstickManualTxAfterMigration_homeChain_Success() public { + function test_unstickManualTxAfterMigration_homeChain() public { address CIRCLE = makeAddr("CIRCLE"); address recipient = address(1234); diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.updateChainSelectorMechanism.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.updateChainSelectorMechanism.t.sol index 9db74061a31..160c09f7431 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.updateChainSelectorMechanism.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.updateChainSelectorMechanism.t.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {HybridLockReleaseUSDCTokenPool} from "../../../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; import {USDCBridgeMigrator_BurnLockedUSDC} from "./USDCBridgeMigrator.burnLockedUSDC.t.sol"; contract USDCBridgeMigrator_updateChainSelectorMechanism is USDCBridgeMigrator_BurnLockedUSDC { - function test_cannotRevertChainMechanism_afterMigration_Revert() public { - test_lockOrBurn_then_BurnInCCTPMigration_Success(); + function test_RevertWhen_cannotRevertChainMechanism_afterMigration() public { + test_lockOrBurn_then_BurnInCCTPMigration(); vm.startPrank(OWNER); diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigratorSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigratorSetup.t.sol index 5a250fd16a8..bf9af4c66ad 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigratorSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigratorSetup.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {HybridLockReleaseUSDCTokenPool} from "../../../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; import {USDCSetup} from "../USDCSetup.t.sol"; @@ -11,10 +11,12 @@ contract HybridLockReleaseUSDCTokenPoolSetup is USDCSetup { function setUp() public virtual override { super.setUp(); - s_usdcTokenPool = - new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + s_usdcTokenPool = new HybridLockReleaseUSDCTokenPool( + s_mockUSDC, s_token, new address[](0), address(s_mockRMNRemote), address(s_router) + ); - s_usdcTokenPoolTransferLiquidity = - new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + s_usdcTokenPoolTransferLiquidity = new HybridLockReleaseUSDCTokenPool( + s_mockUSDC, s_token, new address[](0), address(s_mockRMNRemote), address(s_router) + ); } } diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCSetup.t.sol index 9ec89b52582..e000999cb30 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCSetup.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IBurnMintERC20} from "../../../../shared/token/ERC20/IBurnMintERC20.sol"; @@ -85,7 +85,7 @@ contract USDCSetup is BaseTest { } function _setUpRamps() internal { - s_router = new Router(address(s_token), address(s_mockRMN)); + s_router = new Router(address(s_token), address(s_mockRMNRemote)); Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_routerAllowedOnRamp}); diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.lockOrBurn.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.lockOrBurn.t.sol index 03d328b8e8c..484c795b375 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.lockOrBurn.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.lockOrBurn.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {ITokenMessenger} from "../../../../pools/USDC/ITokenMessenger.sol"; @@ -12,7 +12,7 @@ import {USDCTokenPoolSetup} from "./USDCTokenPoolSetup.t.sol"; contract USDCTokenPool_lockOrBurn is USDCTokenPoolSetup { // Base test case, included for PR gas comparisons as fuzz tests are excluded from forge snapshot due to being flaky. - function test_LockOrBurn_Success() public { + function test_LockOrBurn() public { bytes32 receiver = bytes32(uint256(uint160(STRANGER))); uint256 amount = 1; s_token.transfer(address(s_usdcTokenPool), amount); @@ -132,7 +132,7 @@ contract USDCTokenPool_lockOrBurn is USDCTokenPoolSetup { } // Reverts - function test_UnknownDomain_Revert() public { + function test_RevertWhen_UnknownDomain() public { uint64 wrongDomain = DEST_CHAIN_SELECTOR + 1; // We need to setup the wrong chainSelector so it reaches the domain check Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); @@ -168,7 +168,7 @@ contract USDCTokenPool_lockOrBurn is USDCTokenPoolSetup { ); } - function test_CallerIsNotARampOnRouter_Revert() public { + function test_RevertWhen_CallerIsNotARampOnRouter() public { vm.expectRevert(abi.encodeWithSelector(TokenPool.CallerIsNotARampOnRouter.selector, OWNER)); s_usdcTokenPool.lockOrBurn( @@ -182,7 +182,7 @@ contract USDCTokenPool_lockOrBurn is USDCTokenPoolSetup { ); } - function test_LockOrBurnWithAllowList_Revert() public { + function test_RevertWhen_LockOrBurnWithAllowList() public { vm.startPrank(s_routerAllowedOnRamp); vm.expectRevert(abi.encodeWithSelector(TokenPool.SenderNotAllowed.selector, STRANGER)); diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.releaseOrMint.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.releaseOrMint.t.sol index 4499c748a6b..0dfe1dc4925 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.releaseOrMint.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.releaseOrMint.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Internal} from "../../../../libraries/Internal.sol"; import {Pool} from "../../../../libraries/Pool.sol"; @@ -84,7 +84,7 @@ contract USDCTokenPool_releaseOrMint is USDCTokenPoolSetup { } // https://etherscan.io/tx/0xac9f501fe0b76df1f07a22e1db30929fd12524bc7068d74012dff948632f0883 - function test_ReleaseOrMintRealTx_Success() public { + function test_ReleaseOrMintRealTx() public { bytes memory encodedUsdcMessage = hex"000000000000000300000000000000000000127a00000000000000000000000019330d10d9cc8751218eaf51e8885d058642e08a000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af3155000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000004af08f56978be7dce2d1be3c65c005b41e79401c000000000000000000000000000000000000000000000000000000002057ff7a0000000000000000000000003a23f943181408eac424116af7b7790c94cb97a50000000000000000000000000000000000000000000000000000000000000000000000000000008274119237535fd659626b090f87e365ff89ebc7096bb32e8b0e85f155626b73ae7c4bb2485c184b7cc3cf7909045487890b104efb62ae74a73e32901bdcec91df1bb9ee08ccb014fcbcfe77b74d1263fd4e0b0e8de05d6c9a5913554364abfd5ea768b222f50c715908183905d74044bb2b97527c7e70ae7983c443a603557cac3b1c000000000000000000000000000000000000000000000000000000000000"; bytes memory attestation = bytes("attestation bytes"); @@ -127,7 +127,7 @@ contract USDCTokenPool_releaseOrMint is USDCTokenPoolSetup { } // Reverts - function test_UnlockingUSDCFailed_Revert() public { + function test_RevertWhen_UnlockingUSDCFailed() public { vm.startPrank(s_routerAllowedOffRamp); s_mockUSDCTransmitter.setShouldSucceed(false); @@ -179,7 +179,7 @@ contract USDCTokenPool_releaseOrMint is USDCTokenPoolSetup { ); } - function test_TokenMaxCapacityExceeded_Revert() public { + function test_RevertWhen_TokenMaxCapacityExceeded() public { uint256 capacity = _getInboundRateLimiterConfig().capacity; uint256 amount = 10 * capacity; address recipient = address(1); diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.setDomains.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.setDomains.t.sol index 7fcb75fdf3f..0d4ff379dd7 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.setDomains.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.setDomains.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Ownable2Step} from "../../../../../shared/access/Ownable2Step.sol"; import {USDCTokenPool} from "../../../../pools/USDC/USDCTokenPool.sol"; @@ -47,7 +47,7 @@ contract USDCTokenPool_setDomains is USDCTokenPoolSetup { // Reverts - function test_OnlyOwner_Revert() public { + function test_RevertWhen_OnlyOwner() public { USDCTokenPool.DomainUpdate[] memory domainUpdates = new USDCTokenPool.DomainUpdate[](0); vm.startPrank(STRANGER); @@ -56,7 +56,7 @@ contract USDCTokenPool_setDomains is USDCTokenPoolSetup { s_usdcTokenPool.setDomains(domainUpdates); } - function test_InvalidDomain_Revert() public { + function test_RevertWhen_InvalidDomain() public { bytes32 validCaller = bytes32(uint256(25)); // Ensure valid domain works USDCTokenPool.DomainUpdate[] memory domainUpdates = new USDCTokenPool.DomainUpdate[](1); diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.supportsInterface.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.supportsInterface.t.sol index 05ac5f08136..304791ae2e6 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.supportsInterface.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.supportsInterface.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IPoolV1} from "../../../../interfaces/IPool.sol"; import {USDCTokenPoolSetup} from "./USDCTokenPoolSetup.t.sol"; @@ -7,7 +7,7 @@ import {USDCTokenPoolSetup} from "./USDCTokenPoolSetup.t.sol"; import {IERC165} from "../../../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; contract USDCTokenPool_supportsInterface is USDCTokenPoolSetup { - function test_SupportsInterface_Success() public view { + function test_SupportsInterface() public view { assertTrue(s_usdcTokenPool.supportsInterface(type(IPoolV1).interfaceId)); assertTrue(s_usdcTokenPool.supportsInterface(type(IERC165).interfaceId)); } diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.validateMessage.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.validateMessage.t.sol index 975368c38b9..deaee56c7c7 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.validateMessage.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.validateMessage.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {USDCTokenPool} from "../../../../pools/USDC/USDCTokenPool.sol"; import {USDCTokenPoolSetup} from "./USDCTokenPoolSetup.t.sol"; @@ -28,7 +28,7 @@ contract USDCTokenPool__validateMessage is USDCTokenPoolSetup { // Reverts - function test_ValidateInvalidMessage_Revert() public { + function test_RevertWhen_ValidateInvalidMessage() public { USDCMessage memory usdcMessage = USDCMessage({ version: 0, sourceDomain: 1553252, diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPoolSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPoolSetup.t.sol index bc6108926b3..0166fe4b645 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPoolSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPoolSetup.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {USDCTokenPool} from "../../../../pools/USDC/USDCTokenPool.sol"; import {USDCTokenPoolHelper} from "../../../helpers/USDCTokenPoolHelper.sol"; @@ -14,11 +14,11 @@ contract USDCTokenPoolSetup is USDCSetup { super.setUp(); s_usdcTokenPool = - new USDCTokenPoolHelper(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + new USDCTokenPoolHelper(s_mockUSDC, s_token, new address[](0), address(s_mockRMNRemote), address(s_router)); - s_allowedList.push(USER_1); + s_allowedList.push(vm.randomAddress()); s_usdcTokenPoolWithAllowList = - new USDCTokenPoolHelper(s_mockUSDC, s_token, s_allowedList, address(s_mockRMN), address(s_router)); + new USDCTokenPoolHelper(s_mockUSDC, s_token, s_allowedList, address(s_mockRMNRemote), address(s_router)); _poolApplyChainUpdates(address(s_usdcTokenPool)); _poolApplyChainUpdates(address(s_usdcTokenPoolWithAllowList)); diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiterSetup.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiterSetup.t.sol index d3e87f5faa4..73dbeff1bf4 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiterSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiterSetup.t.sol @@ -1,16 +1,14 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {MultiAggregateRateLimiter} from "../../../MultiAggregateRateLimiter.sol"; import {Client} from "../../../libraries/Client.sol"; import {Internal} from "../../../libraries/Internal.sol"; import {RateLimiter} from "../../../libraries/RateLimiter.sol"; -import {BaseTest} from "../../BaseTest.t.sol"; - import {FeeQuoterSetup} from "../../feeQuoter/FeeQuoterSetup.t.sol"; import {MultiAggregateRateLimiterHelper} from "../../helpers/MultiAggregateRateLimiterHelper.sol"; -contract MultiAggregateRateLimiterSetup is BaseTest, FeeQuoterSetup { +contract MultiAggregateRateLimiterSetup is FeeQuoterSetup { MultiAggregateRateLimiterHelper internal s_rateLimiter; address internal constant TOKEN = 0x21118E64E1fB0c487F25Dd6d3601FF6af8D32E4e; @@ -27,8 +25,7 @@ contract MultiAggregateRateLimiterSetup is BaseTest, FeeQuoterSetup { address[] internal s_authorizedCallers; - function setUp() public virtual override(BaseTest, FeeQuoterSetup) { - BaseTest.setUp(); + function setUp() public virtual override { FeeQuoterSetup.setUp(); Internal.PriceUpdates memory priceUpdates = _getSingleTokenPriceUpdateStruct(TOKEN, TOKEN_PRICE); diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_applyRateLimiterConfigUpdates.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_applyRateLimiterConfigUpdates.t.sol index 306be6b5956..78f2101b852 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_applyRateLimiterConfigUpdates.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_applyRateLimiterConfigUpdates.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; import {MultiAggregateRateLimiter} from "../../../MultiAggregateRateLimiter.sol"; @@ -9,7 +9,7 @@ import {MultiAggregateRateLimiterSetup} from "./MultiAggregateRateLimiterSetup.t import {Vm} from "forge-std/Vm.sol"; contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggregateRateLimiterSetup { - function test_ZeroConfigs_Success() public { + function test_ZeroConfigs() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](0); @@ -20,7 +20,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega assertEq(logEntries.length, 0); } - function test_SingleConfig_Success() public { + function test_SingleConfig() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ @@ -46,7 +46,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega assertEq(BLOCK_TIME, bucket1.lastUpdated); } - function test_SingleConfigOutbound_Success() public { + function test_SingleConfigOutbound() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ @@ -72,7 +72,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega assertEq(BLOCK_TIME, bucket1.lastUpdated); } - function test_MultipleConfigs_Success() public { + function test_MultipleConfigs() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](5); @@ -103,7 +103,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega } } - function test_MultipleConfigsBothLanes_Success() public { + function test_MultipleConfigsBothLanes() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](2); @@ -134,7 +134,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega } } - function test_UpdateExistingConfig_Success() public { + function test_UpdateExistingConfig() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ @@ -170,7 +170,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega ); } - function test_UpdateExistingConfigWithNoDifference_Success() public { + function test_UpdateExistingConfigWithNoDifference() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ @@ -198,7 +198,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega } // Reverts - function test_ZeroChainSelector_Revert() public { + function test_RevertWhen_ZeroChainSelector() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ @@ -211,7 +211,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); } - function test_OnlyCallableByOwner_Revert() public { + function test_RevertWhen_OnlyCallableByOwner() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ @@ -225,7 +225,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); } - function test_ConfigRateMoreThanCapacity_Revert() public { + function test_RevertWhen_ConfigRateMoreThanCapacity() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ @@ -240,7 +240,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); } - function test_ConfigRateZero_Revert() public { + function test_RevertWhen_ConfigRateZero() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ @@ -255,7 +255,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); } - function test_DisableConfigRateNonZero_Revert() public { + function test_RevertWhen_DisableConfigRateNonZero() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ @@ -270,7 +270,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); } - function test_DiableConfigCapacityNonZero_Revert() public { + function test_RevertWhen_DiableConfigCapacityNonZero() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_constructor.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_constructor.t.sol index 0f858a79a56..c9ea2bce69a 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_constructor.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_constructor.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {MultiAggregateRateLimiter} from "../../../MultiAggregateRateLimiter.sol"; import {MultiAggregateRateLimiterHelper} from "../../helpers/MultiAggregateRateLimiterHelper.sol"; @@ -7,7 +7,7 @@ import {MultiAggregateRateLimiterSetup} from "./MultiAggregateRateLimiterSetup.t import {Vm} from "forge-std/Vm.sol"; contract MultiAggregateRateLimiter_constructor is MultiAggregateRateLimiterSetup { - function test_ConstructorNoAuthorizedCallers_Success() public { + function test_ConstructorNoAuthorizedCallers() public { address[] memory authorizedCallers = new address[](0); vm.recordLogs(); @@ -21,7 +21,7 @@ contract MultiAggregateRateLimiter_constructor is MultiAggregateRateLimiterSetup assertEq(address(s_feeQuoter), s_rateLimiter.getFeeQuoter()); } - function test_Constructor_Success() public { + function test_Constructor() public { address[] memory authorizedCallers = new address[](2); authorizedCallers[0] = MOCK_OFFRAMP; authorizedCallers[1] = MOCK_ONRAMP; diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_getTokenBucket.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_getTokenBucket.t.sol index bfb5da07da3..dabf1b60c9a 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_getTokenBucket.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_getTokenBucket.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {MultiAggregateRateLimiter} from "../../../MultiAggregateRateLimiter.sol"; import {RateLimiter} from "../../../libraries/RateLimiter.sol"; @@ -8,7 +8,7 @@ import {MultiAggregateRateLimiterSetup} from "./MultiAggregateRateLimiterSetup.t import {stdError} from "forge-std/Test.sol"; contract MultiAggregateRateLimiter_getTokenBucket is MultiAggregateRateLimiterSetup { - function test_GetTokenBucket_Success() public view { + function test_GetTokenBucket() public view { RateLimiter.TokenBucket memory bucketInbound = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); _assertConfigWithTokenBucketEquality(s_rateLimiterConfig1, bucketInbound); assertEq(BLOCK_TIME, bucketInbound.lastUpdated); @@ -18,7 +18,7 @@ contract MultiAggregateRateLimiter_getTokenBucket is MultiAggregateRateLimiterSe assertEq(BLOCK_TIME, bucketOutbound.lastUpdated); } - function test_Refill_Success() public { + function test_Refill() public { s_rateLimiterConfig1.capacity = s_rateLimiterConfig1.capacity * 2; MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = @@ -57,7 +57,7 @@ contract MultiAggregateRateLimiter_getTokenBucket is MultiAggregateRateLimiterSe // Reverts - function test_TimeUnderflow_Revert() public { + function test_RevertWhen_TimeUnderflow() public { vm.warp(BLOCK_TIME - 1); vm.expectRevert(stdError.arithmeticError); diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_getTokenValue.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_getTokenValue.t.sol index 9b4448339e8..a70c28ec875 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_getTokenValue.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_getTokenValue.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {MultiAggregateRateLimiter} from "../../../MultiAggregateRateLimiter.sol"; import {Client} from "../../../libraries/Client.sol"; import {MultiAggregateRateLimiterSetup} from "./MultiAggregateRateLimiterSetup.t.sol"; contract MultiAggregateRateLimiter_getTokenValue is MultiAggregateRateLimiterSetup { - function test_GetTokenValue_Success() public view { + function test_GetTokenValue() public view { uint256 numberOfTokens = 10; Client.EVMTokenAmount memory tokenAmount = Client.EVMTokenAmount({token: TOKEN, amount: 10}); uint256 value = s_rateLimiter.getTokenValue(tokenAmount); @@ -14,7 +14,7 @@ contract MultiAggregateRateLimiter_getTokenValue is MultiAggregateRateLimiterSet } // Reverts - function test_NoTokenPrice_Reverts() public { + function test_RevertWhen_NoTokenPrices() public { address tokenWithNoPrice = makeAddr("Token with no price"); Client.EVMTokenAmount memory tokenAmount = Client.EVMTokenAmount({token: tokenWithNoPrice, amount: 10}); diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_onInboundMessage.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_onInboundMessage.t.sol index 8697dae871e..48f7ec88a42 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_onInboundMessage.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_onInboundMessage.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {AuthorizedCallers} from "../../../../shared/access/AuthorizedCallers.sol"; import {MultiAggregateRateLimiter} from "../../../MultiAggregateRateLimiter.sol"; @@ -34,7 +34,7 @@ contract MultiAggregateRateLimiter_onInboundMessage is MultiAggregateRateLimiter s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), tokensToAdd); } - function test_ValidateMessageWithNoTokens_Success() public { + function test_ValidateMessageWithNoTokens() public { vm.startPrank(MOCK_OFFRAMP); vm.recordLogs(); @@ -45,7 +45,7 @@ contract MultiAggregateRateLimiter_onInboundMessage is MultiAggregateRateLimiter assertEq(logEntries.length, 0); } - function test_ValidateMessageWithTokens_Success() public { + function test_ValidateMessageWithTokens() public { vm.startPrank(MOCK_OFFRAMP); Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); @@ -59,7 +59,7 @@ contract MultiAggregateRateLimiter_onInboundMessage is MultiAggregateRateLimiter s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); } - function test_ValidateMessageWithDisabledRateLimitToken_Success() public { + function test_ValidateMessageWithDisabledRateLimitToken() public { MultiAggregateRateLimiter.LocalRateLimitToken[] memory removes = new MultiAggregateRateLimiter.LocalRateLimitToken[](1); removes[0] = MultiAggregateRateLimiter.LocalRateLimitToken({ @@ -80,7 +80,7 @@ contract MultiAggregateRateLimiter_onInboundMessage is MultiAggregateRateLimiter s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); } - function test_ValidateMessageWithRateLimitDisabled_Success() public { + function test_ValidateMessageWithRateLimitDisabled() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ @@ -104,7 +104,7 @@ contract MultiAggregateRateLimiter_onInboundMessage is MultiAggregateRateLimiter assertEq(logEntries.length, 0); } - function test_ValidateMessageWithTokensOnDifferentChains_Success() public { + function test_ValidateMessageWithTokensOnDifferentChains() public { MultiAggregateRateLimiter.RateLimitTokenArgs[] memory tokensToAdd = new MultiAggregateRateLimiter.RateLimitTokenArgs[](s_sourceTokens.length); for (uint224 i = 0; i < s_sourceTokens.length; ++i) { @@ -152,7 +152,7 @@ contract MultiAggregateRateLimiter_onInboundMessage is MultiAggregateRateLimiter assertEq(bucketChain2.capacity - totalValue, bucketChain2.tokens); } - function test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() public { + function test_ValidateMessageWithDifferentTokensOnDifferentChains() public { MultiAggregateRateLimiter.RateLimitTokenArgs[] memory tokensToAdd = new MultiAggregateRateLimiter.RateLimitTokenArgs[](1); @@ -203,7 +203,7 @@ contract MultiAggregateRateLimiter_onInboundMessage is MultiAggregateRateLimiter assertEq(bucketChain2.capacity - totalValue2, bucketChain2.tokens); } - function test_ValidateMessageWithRateLimitReset_Success() public { + function test_ValidateMessageWithRateLimitReset() public { vm.startPrank(MOCK_OFFRAMP); Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); @@ -228,7 +228,7 @@ contract MultiAggregateRateLimiter_onInboundMessage is MultiAggregateRateLimiter // Reverts - function test_ValidateMessageWithRateLimitExceeded_Revert() public { + function test_RevertWhen_ValidateMessageWithRateLimitExceeded() public { vm.startPrank(MOCK_OFFRAMP); Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); @@ -240,7 +240,7 @@ contract MultiAggregateRateLimiter_onInboundMessage is MultiAggregateRateLimiter s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); } - function test_ValidateMessageFromUnauthorizedCaller_Revert() public { + function test_RevertWhen_ValidateMessageFromUnauthorizedCaller() public { vm.startPrank(STRANGER); vm.expectRevert(abi.encodeWithSelector(AuthorizedCallers.UnauthorizedCaller.selector, STRANGER)); diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_onOutboundMessage.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_onOutboundMessage.t.sol index 9d20e203619..7886a77f5b6 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_onOutboundMessage.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_onOutboundMessage.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {AuthorizedCallers} from "../../../../shared/access/AuthorizedCallers.sol"; import {MultiAggregateRateLimiter} from "../../../MultiAggregateRateLimiter.sol"; @@ -31,7 +31,7 @@ contract MultiAggregateRateLimiter_onOutboundMessage is MultiAggregateRateLimite s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), tokensToAdd); } - function test_ValidateMessageWithNoTokens_Success() public { + function test_ValidateMessageWithNoTokens() public { vm.startPrank(MOCK_ONRAMP); vm.recordLogs(); @@ -41,7 +41,7 @@ contract MultiAggregateRateLimiter_onOutboundMessage is MultiAggregateRateLimite assertEq(vm.getRecordedLogs().length, 0); } - function test_onOutboundMessage_ValidateMessageWithTokens_Success() public { + function test_onOutboundMessage_ValidateMessageWithTokens() public { vm.startPrank(MOCK_ONRAMP); Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); @@ -55,7 +55,7 @@ contract MultiAggregateRateLimiter_onOutboundMessage is MultiAggregateRateLimite s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessage(tokenAmounts)); } - function test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken_Success() public { + function test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken() public { MultiAggregateRateLimiter.LocalRateLimitToken[] memory removes = new MultiAggregateRateLimiter.LocalRateLimitToken[](1); removes[0] = MultiAggregateRateLimiter.LocalRateLimitToken({ @@ -76,7 +76,7 @@ contract MultiAggregateRateLimiter_onOutboundMessage is MultiAggregateRateLimite s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessage(tokenAmounts)); } - function test_onOutboundMessage_ValidateMessageWithRateLimitDisabled_Success() public { + function test_onOutboundMessage_ValidateMessageWithRateLimitDisabled() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ @@ -99,7 +99,7 @@ contract MultiAggregateRateLimiter_onOutboundMessage is MultiAggregateRateLimite assertEq(vm.getRecordedLogs().length, 0); } - function test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains_Success() public { + function test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains() public { MultiAggregateRateLimiter.RateLimitTokenArgs[] memory tokensToAdd = new MultiAggregateRateLimiter.RateLimitTokenArgs[](s_sourceTokens.length); for (uint224 i = 0; i < s_sourceTokens.length; ++i) { @@ -147,7 +147,7 @@ contract MultiAggregateRateLimiter_onOutboundMessage is MultiAggregateRateLimite assertEq(bucketChain2.capacity - totalValue, bucketChain2.tokens); } - function test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains_Success() public { + function test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains() public { MultiAggregateRateLimiter.RateLimitTokenArgs[] memory tokensToAdd = new MultiAggregateRateLimiter.RateLimitTokenArgs[](1); @@ -198,7 +198,7 @@ contract MultiAggregateRateLimiter_onOutboundMessage is MultiAggregateRateLimite assertEq(bucketChain2.capacity - totalValue2, bucketChain2.tokens); } - function test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() public { + function test_onOutboundMessage_ValidateMessageWithRateLimitReset() public { vm.startPrank(MOCK_ONRAMP); Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); @@ -221,7 +221,7 @@ contract MultiAggregateRateLimiter_onOutboundMessage is MultiAggregateRateLimite s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessage(tokenAmounts)); } - function test_RateLimitValueDifferentLanes_Success() public { + function test_RateLimitValueDifferentLanes() public { vm.pauseGasMetering(); // start from blocktime that does not equal rate limiter init timestamp vm.warp(BLOCK_TIME + 1); @@ -266,7 +266,7 @@ contract MultiAggregateRateLimiter_onOutboundMessage is MultiAggregateRateLimite // Reverts - function test_onOutboundMessage_ValidateMessageWithRateLimitExceeded_Revert() public { + function test_RevertWhen_onOutboundMessage_ValidateMessageWithRateLimitExceeded() public { vm.startPrank(MOCK_OFFRAMP); Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); @@ -278,7 +278,7 @@ contract MultiAggregateRateLimiter_onOutboundMessage is MultiAggregateRateLimite s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessage(tokenAmounts)); } - function test_onOutboundMessage_ValidateMessageFromUnauthorizedCaller_Revert() public { + function test_RevertWhen_onOutboundMessage_ValidateMessageFromUnauthorizedCaller() public { vm.startPrank(STRANGER); vm.expectRevert(abi.encodeWithSelector(AuthorizedCallers.UnauthorizedCaller.selector, STRANGER)); diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_setFeeQuoter.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_setFeeQuoter.t.sol index 39412a65045..77968339685 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_setFeeQuoter.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_setFeeQuoter.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {AuthorizedCallers} from "../../../../shared/access/AuthorizedCallers.sol"; import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; @@ -7,7 +7,7 @@ import {MultiAggregateRateLimiter} from "../../../MultiAggregateRateLimiter.sol" import {MultiAggregateRateLimiterSetup} from "./MultiAggregateRateLimiterSetup.t.sol"; contract MultiAggregateRateLimiter_setFeeQuoter is MultiAggregateRateLimiterSetup { - function test_Owner_Success() public { + function test_Owner() public { address newAddress = address(42); vm.expectEmit(); @@ -19,14 +19,14 @@ contract MultiAggregateRateLimiter_setFeeQuoter is MultiAggregateRateLimiterSetu // Reverts - function test_OnlyOwner_Revert() public { + function test_RevertWhen_OnlyOwner() public { vm.startPrank(STRANGER); vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); s_rateLimiter.setFeeQuoter(STRANGER); } - function test_ZeroAddress_Revert() public { + function test_RevertWhen_ZeroAddress() public { vm.expectRevert(AuthorizedCallers.ZeroAddressNotAllowed.selector); s_rateLimiter.setFeeQuoter(address(0)); } diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_updateRateLimitTokens.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_updateRateLimitTokens.t.sol index 2125983ed70..85c9495c05e 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_updateRateLimitTokens.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_updateRateLimitTokens.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {AuthorizedCallers} from "../../../../shared/access/AuthorizedCallers.sol"; import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; @@ -24,7 +24,7 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi s_rateLimiter.updateRateLimitTokens(removes, new MultiAggregateRateLimiter.RateLimitTokenArgs[](0)); } - function test_UpdateRateLimitTokensSingleChain_Success() public { + function test_UpdateRateLimitTokensSingleChain() public { MultiAggregateRateLimiter.RateLimitTokenArgs[] memory adds = new MultiAggregateRateLimiter.RateLimitTokenArgs[](2); adds[0] = MultiAggregateRateLimiter.RateLimitTokenArgs({ localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ @@ -61,7 +61,7 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi } } - function test_UpdateRateLimitTokensMultipleChains_Success() public { + function test_UpdateRateLimitTokensMultipleChains() public { MultiAggregateRateLimiter.RateLimitTokenArgs[] memory adds = new MultiAggregateRateLimiter.RateLimitTokenArgs[](2); adds[0] = MultiAggregateRateLimiter.RateLimitTokenArgs({ localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ @@ -104,7 +104,7 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi assertEq(remoteTokensChain2[0], adds[1].remoteToken); } - function test_UpdateRateLimitTokens_AddsAndRemoves_Success() public { + function test_UpdateRateLimitTokens_AddsAndRemoves() public { MultiAggregateRateLimiter.RateLimitTokenArgs[] memory adds = new MultiAggregateRateLimiter.RateLimitTokenArgs[](2); adds[0] = MultiAggregateRateLimiter.RateLimitTokenArgs({ localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ @@ -150,7 +150,7 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi assertEq(adds[1].localTokenArgs.localToken, localTokens[0]); } - function test_UpdateRateLimitTokens_RemoveNonExistentToken_Success() public { + function test_UpdateRateLimitTokens_RemoveNonExistentToken() public { MultiAggregateRateLimiter.RateLimitTokenArgs[] memory adds = new MultiAggregateRateLimiter.RateLimitTokenArgs[](0); MultiAggregateRateLimiter.LocalRateLimitToken[] memory removes = @@ -175,7 +175,7 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi // Reverts - function test_ZeroSourceToken_Revert() public { + function test_RevertWhen_ZeroSourceToken() public { MultiAggregateRateLimiter.RateLimitTokenArgs[] memory adds = new MultiAggregateRateLimiter.RateLimitTokenArgs[](1); adds[0] = MultiAggregateRateLimiter.RateLimitTokenArgs({ localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ @@ -189,7 +189,7 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), adds); } - function test_ZeroDestToken_Revert() public { + function test_RevertWhen_ZeroDestToken() public { MultiAggregateRateLimiter.RateLimitTokenArgs[] memory adds = new MultiAggregateRateLimiter.RateLimitTokenArgs[](1); adds[0] = MultiAggregateRateLimiter.RateLimitTokenArgs({ localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ @@ -203,7 +203,7 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), adds); } - function test_ZeroDestToken_AbiEncoded_Revert() public { + function test_RevertWhen_ZeroDestToken_AbiEncoded() public { MultiAggregateRateLimiter.RateLimitTokenArgs[] memory adds = new MultiAggregateRateLimiter.RateLimitTokenArgs[](1); adds[0] = MultiAggregateRateLimiter.RateLimitTokenArgs({ localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ @@ -217,7 +217,7 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), adds); } - function test_NonOwner_Revert() public { + function test_RevertWhen_NonOwner() public { MultiAggregateRateLimiter.RateLimitTokenArgs[] memory adds = new MultiAggregateRateLimiter.RateLimitTokenArgs[](4); vm.startPrank(STRANGER); diff --git a/contracts/src/v0.8/ccip/test/rmn/ArmProxy/ArmPorxy.setARM.t.sol b/contracts/src/v0.8/ccip/test/rmn/ArmProxy/ArmPorxy.setARM.t.sol deleted file mode 100644 index 88e613c06da..00000000000 --- a/contracts/src/v0.8/ccip/test/rmn/ArmProxy/ArmPorxy.setARM.t.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ARMProxy} from "../../../rmn/ARMProxy.sol"; - -import {ARMProxyTestSetup} from "./ARMProxyTestSetup.t.sol"; - -contract ARMProxy_setARM is ARMProxyTestSetup { - function test_SetARM() public { - vm.expectEmit(); - emit ARMProxy.ARMSet(MOCK_RMN_ADDRESS); - vm.prank(OWNER_ADDRESS); - s_armProxy.setARM(MOCK_RMN_ADDRESS); - assertEq(s_armProxy.getARM(), MOCK_RMN_ADDRESS); - } - - function test_SetARMzero() public { - vm.expectRevert(abi.encodeWithSelector(ARMProxy.ZeroAddressNotAllowed.selector)); - vm.prank(OWNER_ADDRESS); - s_armProxy.setARM(address(0x0)); - } -} diff --git a/contracts/src/v0.8/ccip/test/rmn/ArmProxy/ArmProxy.constructor.t.sol b/contracts/src/v0.8/ccip/test/rmn/ArmProxy/ArmProxy.constructor.t.sol deleted file mode 100644 index 778a9d4086c..00000000000 --- a/contracts/src/v0.8/ccip/test/rmn/ArmProxy/ArmProxy.constructor.t.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ARMProxy} from "../../../rmn/ARMProxy.sol"; -import {ARMProxyTestSetup} from "./ARMProxyTestSetup.t.sol"; - -contract ARMProxy_constructor is ARMProxyTestSetup { - function test_Constructor() public { - vm.expectEmit(); - emit ARMProxy.ARMSet(MOCK_RMN_ADDRESS); - ARMProxy proxy = new ARMProxy(MOCK_RMN_ADDRESS); - assertEq(proxy.getARM(), MOCK_RMN_ADDRESS); - } -} diff --git a/contracts/src/v0.8/ccip/test/rmn/ArmProxy/ArmProxy.isCursed.t.sol b/contracts/src/v0.8/ccip/test/rmn/ArmProxy/ArmProxy.isCursed.t.sol deleted file mode 100644 index fdc6fce0cf4..00000000000 --- a/contracts/src/v0.8/ccip/test/rmn/ArmProxy/ArmProxy.isCursed.t.sol +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IRMN} from "../../../interfaces/IRMN.sol"; - -import {ARMProxy} from "../../../rmn/ARMProxy.sol"; -import {MockRMN} from "../../mocks/MockRMN.sol"; - -import {ARMProxyTestSetup} from "./ARMProxyTestSetup.t.sol"; - -contract ARMProxy_isCursed is ARMProxyTestSetup { - MockRMN internal s_mockRMN; - - function setUp() public virtual override { - super.setUp(); - s_mockRMN = new MockRMN(); - s_armProxy = new ARMProxy(address(s_mockRMN)); - } - - function test_IsCursed_Success() public { - s_armProxy.setARM(address(s_mockRMN)); - assertFalse(IRMN(address(s_armProxy)).isCursed()); - s_mockRMN.setGlobalCursed(true); - assertTrue(IRMN(address(s_armProxy)).isCursed()); - } - - function test_isCursed_RevertReasonForwarded_Revert() public { - bytes memory err = bytes("revert"); - s_mockRMN.setIsCursedRevert(err); - s_armProxy.setARM(address(s_mockRMN)); - vm.expectRevert(abi.encodeWithSelector(MockRMN.CustomError.selector, err)); - IRMN(address(s_armProxy)).isCursed(); - } - - function test_call_ARMCallEmptyContract_Revert() public { - s_armProxy.setARM(EMPTY_ADDRESS); // No code at address 1, should revert. - vm.expectRevert(); - bytes memory b = new bytes(0); - (bool success,) = address(s_armProxy).call(b); - success; - } -} diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.getConfigDigests.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.getConfigDigests.t.sol index b339bb183e7..f17a7d27311 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.getConfigDigests.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.getConfigDigests.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {RMNHomeTestSetup} from "./RMNHomeTestSetup.t.sol"; contract RMNHome_getConfigDigests is RMNHomeTestSetup { - function test_getConfigDigests_success() public { + function test_getConfigDigests() public { (bytes32 activeDigest, bytes32 candidateDigest) = s_rmnHome.getConfigDigests(); assertEq(activeDigest, ZERO_DIGEST); assertEq(candidateDigest, ZERO_DIGEST); diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.promoteCandidateAndRevokeActive.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.promoteCandidateAndRevokeActive.t.sol index 6d99ed1cfaa..f45d63ffeb0 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.promoteCandidateAndRevokeActive.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.promoteCandidateAndRevokeActive.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; import {RMNHome} from "../../../rmn/RMNHome.sol"; @@ -7,7 +7,7 @@ import {RMNHome} from "../../../rmn/RMNHome.sol"; import {RMNHomeTestSetup} from "./RMNHomeTestSetup.t.sol"; contract RMNHome_promoteCandidateAndRevokeActive is RMNHomeTestSetup { - function test_promoteCandidateAndRevokeActive_success() public { + function test_promoteCandidateAndRevokeActive() public { Config memory config = _getBaseConfig(); bytes32 firstConfigToPromote = s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); @@ -43,12 +43,12 @@ contract RMNHome_promoteCandidateAndRevokeActive is RMNHomeTestSetup { assertEq(candidateConfig.configDigest, ZERO_DIGEST); } - function test_promoteCandidateAndRevokeActive_NoOpStateTransitionNotAllowed_reverts() public { + function test_RevertWhen_promoteCandidateAndRevokeActive_NoOpStateTransitionNotAllowed() public { vm.expectRevert(RMNHome.NoOpStateTransitionNotAllowed.selector); s_rmnHome.promoteCandidateAndRevokeActive(ZERO_DIGEST, ZERO_DIGEST); } - function test_promoteCandidateAndRevokeActive_ConfigDigestMismatch_reverts() public { + function test_RevertWhen_promoteCandidateAndRevokeActive_ConfigDigestMismatch() public { (bytes32 priorActiveDigest, bytes32 priorCandidateDigest) = s_rmnHome.getConfigDigests(); bytes32 wrongActiveDigest = keccak256("wrongActiveDigest"); bytes32 wrongCandidateDigest = keccak256("wrongCandidateDigest"); @@ -63,7 +63,7 @@ contract RMNHome_promoteCandidateAndRevokeActive is RMNHomeTestSetup { s_rmnHome.promoteCandidateAndRevokeActive(priorCandidateDigest, wrongActiveDigest); } - function test_promoteCandidateAndRevokeActive_OnlyOwner_reverts() public { + function test_RevertWhen_promoteCandidateAndRevokeActive_OnlyOwner() public { vm.startPrank(address(0)); vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.revokeCandidate.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.revokeCandidate.t.sol index a486bd193ff..9c8034d2d2d 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.revokeCandidate.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.revokeCandidate.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; import {RMNHome} from "../../../rmn/RMNHome.sol"; @@ -13,11 +13,11 @@ contract RMNHome_revokeCandidate is RMNHomeTestSetup { bytes32 digest = s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); s_rmnHome.promoteCandidateAndRevokeActive(digest, ZERO_DIGEST); - config.dynamicConfig.sourceChains[1].f--; + config.dynamicConfig.sourceChains[1].fObserve--; s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); } - function test_revokeCandidate_success() public { + function test_revokeCandidate() public { (bytes32 priorActiveDigest, bytes32 priorCandidateDigest) = s_rmnHome.getConfigDigests(); vm.expectEmit(); @@ -39,7 +39,7 @@ contract RMNHome_revokeCandidate is RMNHomeTestSetup { assertTrue(candidateDigest != priorCandidateDigest); } - function test_revokeCandidate_ConfigDigestMismatch_reverts() public { + function test_RevertWhen_revokeCandidate_ConfigDigestMismatch() public { (, bytes32 priorCandidateDigest) = s_rmnHome.getConfigDigests(); bytes32 wrongDigest = keccak256("wrong_digest"); @@ -47,12 +47,12 @@ contract RMNHome_revokeCandidate is RMNHomeTestSetup { s_rmnHome.revokeCandidate(wrongDigest); } - function test_revokeCandidate_RevokingZeroDigestNotAllowed_reverts() public { + function test_RevertWhen_revokeCandidate_RevokingZeroDigestNotAllowed() public { vm.expectRevert(RMNHome.RevokingZeroDigestNotAllowed.selector); s_rmnHome.revokeCandidate(ZERO_DIGEST); } - function test_revokeCandidate_OnlyOwner_reverts() public { + function test_RevertWhen_revokeCandidate_OnlyOwner() public { vm.startPrank(address(0)); vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.setCandidate.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.setCandidate.t.sol index 6fae7a90552..fb32ae4a9d0 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.setCandidate.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.setCandidate.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; import {RMNHome} from "../../../rmn/RMNHome.sol"; @@ -7,7 +7,7 @@ import {RMNHome} from "../../../rmn/RMNHome.sol"; import {RMNHomeTestSetup} from "./RMNHomeTestSetup.t.sol"; contract RMNHome_setCandidate is RMNHomeTestSetup { - function test_setCandidate_success() public { + function test_setCandidate() public { Config memory config = _getBaseConfig(); RMNHome.VersionedConfig memory versionedConfig = RMNHome.VersionedConfig({ version: 1, @@ -42,14 +42,14 @@ contract RMNHome_setCandidate is RMNHomeTestSetup { for (uint256 i = 0; i < storedDynamicConfig.sourceChains.length; i++) { RMNHome.SourceChain memory storedSourceChain = storedDynamicConfig.sourceChains[i]; assertEq(storedSourceChain.chainSelector, versionedConfig.dynamicConfig.sourceChains[i].chainSelector); - assertEq(storedSourceChain.f, versionedConfig.dynamicConfig.sourceChains[i].f); + assertEq(storedSourceChain.fObserve, versionedConfig.dynamicConfig.sourceChains[i].fObserve); assertEq(storedSourceChain.observerNodesBitmap, versionedConfig.dynamicConfig.sourceChains[i].observerNodesBitmap); } assertEq(storedDynamicConfig.offchainConfig, versionedConfig.dynamicConfig.offchainConfig); assertEq(storedStaticConfig.offchainConfig, versionedConfig.staticConfig.offchainConfig); } - function test_setCandidate_ConfigDigestMismatch_reverts() public { + function test_RevertWhen_setCandidate_ConfigDigestMismatch() public { Config memory config = _getBaseConfig(); bytes32 digest = s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); @@ -63,7 +63,7 @@ contract RMNHome_setCandidate is RMNHomeTestSetup { s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, digest); } - function test_setCandidate_OnlyOwner_reverts() public { + function test_RevertWhen_setCandidate_OnlyOwner() public { Config memory config = _getBaseConfig(); vm.startPrank(address(0)); diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.setDynamicConfig.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.setDynamicConfig.t.sol index 048a6ef226e..da200238dbb 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.setDynamicConfig.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.setDynamicConfig.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; import {RMNHome} from "../../../rmn/RMNHome.sol"; @@ -12,11 +12,11 @@ contract RMNHome_setDynamicConfig is RMNHomeTestSetup { s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); } - function test_setDynamicConfig_success() public { + function test_setDynamicConfig() public { (bytes32 priorActiveDigest,) = s_rmnHome.getConfigDigests(); Config memory config = _getBaseConfig(); - config.dynamicConfig.sourceChains[1].f--; + config.dynamicConfig.sourceChains[1].fObserve--; (, bytes32 candidateConfigDigest) = s_rmnHome.getConfigDigests(); @@ -27,7 +27,9 @@ contract RMNHome_setDynamicConfig is RMNHomeTestSetup { (RMNHome.VersionedConfig memory storedVersionedConfig, bool ok) = s_rmnHome.getConfig(candidateConfigDigest); assertTrue(ok); - assertEq(storedVersionedConfig.dynamicConfig.sourceChains[0].f, config.dynamicConfig.sourceChains[0].f); + assertEq( + storedVersionedConfig.dynamicConfig.sourceChains[0].fObserve, config.dynamicConfig.sourceChains[0].fObserve + ); // Asser the digests don't change when updating the dynamic config (bytes32 activeDigest, bytes32 candidateDigest) = s_rmnHome.getConfigDigests(); @@ -36,15 +38,15 @@ contract RMNHome_setDynamicConfig is RMNHomeTestSetup { } // Asserts the validation function is being called - function test_setDynamicConfig_MinObserversTooHigh_reverts() public { + function test_RevertWhen_setDynamicConfig_MinObserversTooHigh() public { Config memory config = _getBaseConfig(); - config.dynamicConfig.sourceChains[0].f++; + config.dynamicConfig.sourceChains[0].fObserve++; vm.expectRevert(abi.encodeWithSelector(RMNHome.DigestNotFound.selector, ZERO_DIGEST)); s_rmnHome.setDynamicConfig(config.dynamicConfig, ZERO_DIGEST); } - function test_setDynamicConfig_DigestNotFound_reverts() public { + function test_RevertWhen_setDynamicConfig_DigestNotFound() public { // Zero always reverts vm.expectRevert(abi.encodeWithSelector(RMNHome.DigestNotFound.selector, ZERO_DIGEST)); s_rmnHome.setDynamicConfig(_getBaseConfig().dynamicConfig, ZERO_DIGEST); @@ -55,7 +57,7 @@ contract RMNHome_setDynamicConfig is RMNHomeTestSetup { s_rmnHome.setDynamicConfig(_getBaseConfig().dynamicConfig, nonExistentDigest); } - function test_setDynamicConfig_OnlyOwner_reverts() public { + function test_RevertWhen_setDynamicConfig_OnlyOwner() public { Config memory config = _getBaseConfig(); vm.startPrank(address(0)); diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.validateStaticAndDynamicConfig.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.validateStaticAndDynamicConfig.t.sol index 2aa7b1a5100..31eb3c5aa0c 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.validateStaticAndDynamicConfig.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.validateStaticAndDynamicConfig.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {RMNHome} from "../../../rmn/RMNHome.sol"; import {RMNHomeTestSetup} from "./RMNHomeTestSetup.t.sol"; contract RMNHome_validateStaticAndDynamicConfig is RMNHomeTestSetup { - function test_validateStaticAndDynamicConfig_OutOfBoundsNodesLength_reverts() public { + function test_RevertWhen_validateStaticAndDynamicConfig_OutOfBoundsNodesLength() public { Config memory config = _getBaseConfig(); config.staticConfig.nodes = new RMNHome.Node[](257); @@ -14,7 +14,7 @@ contract RMNHome_validateStaticAndDynamicConfig is RMNHomeTestSetup { s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); } - function test_validateStaticAndDynamicConfig_DuplicatePeerId_reverts() public { + function test_RevertWhen_validateStaticAndDynamicConfig_DuplicatePeerId() public { Config memory config = _getBaseConfig(); config.staticConfig.nodes[1].peerId = config.staticConfig.nodes[0].peerId; @@ -22,7 +22,7 @@ contract RMNHome_validateStaticAndDynamicConfig is RMNHomeTestSetup { s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); } - function test_validateStaticAndDynamicConfig_DuplicateOffchainPublicKey_reverts() public { + function test_RevertWhen_validateStaticAndDynamicConfig_DuplicateOffchainPublicKey() public { Config memory config = _getBaseConfig(); config.staticConfig.nodes[1].offchainPublicKey = config.staticConfig.nodes[0].offchainPublicKey; @@ -30,7 +30,7 @@ contract RMNHome_validateStaticAndDynamicConfig is RMNHomeTestSetup { s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); } - function test_validateStaticAndDynamicConfig_DuplicateSourceChain_reverts() public { + function test_RevertWhen_validateStaticAndDynamicConfig_DuplicateSourceChain() public { Config memory config = _getBaseConfig(); config.dynamicConfig.sourceChains[1].chainSelector = config.dynamicConfig.sourceChains[0].chainSelector; @@ -38,7 +38,7 @@ contract RMNHome_validateStaticAndDynamicConfig is RMNHomeTestSetup { s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); } - function test_validateStaticAndDynamicConfig_OutOfBoundsObserverNodeIndex_reverts() public { + function test_RevertWhen_validateStaticAndDynamicConfig_OutOfBoundsObserverNodeIndex() public { Config memory config = _getBaseConfig(); config.dynamicConfig.sourceChains[0].observerNodesBitmap = 1 << config.staticConfig.nodes.length; @@ -46,9 +46,9 @@ contract RMNHome_validateStaticAndDynamicConfig is RMNHomeTestSetup { s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); } - function test_validateStaticAndDynamicConfig_NotEnoughObservers_reverts() public { + function test_RevertWhen_validateStaticAndDynamicConfig_NotEnoughObservers() public { Config memory config = _getBaseConfig(); - config.dynamicConfig.sourceChains[0].f++; + config.dynamicConfig.sourceChains[0].fObserve++; vm.expectRevert(RMNHome.NotEnoughObservers.selector); s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHomeTestSetup.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHomeTestSetup.t.sol index 6bb76c29ba7..2dc6eaa5682 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHomeTestSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHomeTestSetup.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {RMNHome} from "../../../rmn/RMNHome.sol"; import {Test} from "forge-std/Test.sol"; @@ -21,9 +21,11 @@ contract RMNHomeTestSetup is Test { RMNHome.SourceChain[] memory sourceChains = new RMNHome.SourceChain[](2); // Observer 0 for source chain 9000 - sourceChains[0] = RMNHome.SourceChain({chainSelector: 9000, f: 1, observerNodesBitmap: 1 << 0 | 1 << 1 | 1 << 2}); + sourceChains[0] = + RMNHome.SourceChain({chainSelector: 9000, fObserve: 1, observerNodesBitmap: 1 << 0 | 1 << 1 | 1 << 2}); // Observers 0, 1 and 2 for source chain 9001 - sourceChains[1] = RMNHome.SourceChain({chainSelector: 9001, f: 1, observerNodesBitmap: 1 << 0 | 1 << 1 | 1 << 2}); + sourceChains[1] = + RMNHome.SourceChain({chainSelector: 9001, fObserve: 1, observerNodesBitmap: 1 << 0 | 1 << 1 | 1 << 2}); return Config({ staticConfig: RMNHome.StaticConfig({nodes: nodes, offchainConfig: abi.encode("static_config")}), diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNProxy/RMNProxy.constructor.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNProxy/RMNProxy.constructor.t.sol new file mode 100644 index 00000000000..7efa4059436 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/rmn/RMNProxy/RMNProxy.constructor.t.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import {RMNProxy} from "../../../rmn/RMNProxy.sol"; +import {RMNProxyTestSetup} from "./RMNProxyTestSetup.t.sol"; + +contract RMNProxy_constructor is RMNProxyTestSetup { + function test_Constructor() public { + vm.expectEmit(); + emit RMNProxy.ARMSet(MOCK_RMN_ADDRESS); + RMNProxy proxy = new RMNProxy(MOCK_RMN_ADDRESS); + assertEq(proxy.getARM(), MOCK_RMN_ADDRESS); + } +} diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNProxy/RMNProxy.isCursed.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNProxy/RMNProxy.isCursed.t.sol new file mode 100644 index 00000000000..add370a3d67 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/rmn/RMNProxy/RMNProxy.isCursed.t.sol @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import {IRMN} from "../../../interfaces/IRMN.sol"; + +import {RMNProxy} from "../../../rmn/RMNProxy.sol"; +import {GLOBAL_CURSE_SUBJECT, RMNRemote} from "../../../rmn/RMNRemote.sol"; +import {RMNProxyTestSetup} from "./RMNProxyTestSetup.t.sol"; + +contract RMNProxy_isCursed is RMNProxyTestSetup { + RMNRemote internal s_mockRMNRemote; + + function setUp() public virtual override { + super.setUp(); + s_mockRMNRemote = new RMNRemote(1, IRMN(address(0))); + s_rmnProxy = new RMNProxy(address(s_mockRMNRemote)); + } + + function test_IsCursed_GlobalCurseSubject() public { + assertFalse(IRMN(address(s_rmnProxy)).isCursed()); + + s_mockRMNRemote.curse(GLOBAL_CURSE_SUBJECT); + vm.assertTrue(IRMN(address(s_rmnProxy)).isCursed()); + } + + error CustomError(bytes err); + + function test_isCursed_RevertWhen_isCursedReasonForwarded() public { + bytes memory err = bytes("revert"); + vm.mockCallRevert( + address(s_mockRMNRemote), abi.encodeWithSignature("isCursed()"), abi.encodeWithSelector(CustomError.selector, err) + ); + + s_rmnProxy.setARM(address(s_mockRMNRemote)); + vm.expectRevert(abi.encodeWithSelector(CustomError.selector, err)); + IRMN(address(s_rmnProxy)).isCursed(); + } + + function test_RevertWhen_call_ARMCallEmptyContract() public { + s_rmnProxy.setARM(EMPTY_ADDRESS); // No code at address 1, should revert. + vm.expectRevert(); + (bool success,) = address(s_rmnProxy).call(new bytes(0)); + success; + } +} diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNProxy/RMNProxy.setARM.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNProxy/RMNProxy.setARM.t.sol new file mode 100644 index 00000000000..ef0f8518955 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/rmn/RMNProxy/RMNProxy.setARM.t.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import {RMNProxy} from "../../../rmn/RMNProxy.sol"; + +import {RMNProxyTestSetup} from "./RMNProxyTestSetup.t.sol"; + +contract RMNProxy_setARM is RMNProxyTestSetup { + function test_SetARM() public { + vm.expectEmit(); + emit RMNProxy.ARMSet(MOCK_RMN_ADDRESS); + vm.prank(OWNER_ADDRESS); + s_rmnProxy.setARM(MOCK_RMN_ADDRESS); + assertEq(s_rmnProxy.getARM(), MOCK_RMN_ADDRESS); + } + + function test_SetARMzero() public { + vm.expectRevert(abi.encodeWithSelector(RMNProxy.ZeroAddressNotAllowed.selector)); + vm.prank(OWNER_ADDRESS); + s_rmnProxy.setARM(address(0x0)); + } +} diff --git a/contracts/src/v0.8/ccip/test/rmn/ArmProxy/ARMProxyTestSetup.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNProxy/RMNProxyTestSetup.t.sol similarity index 64% rename from contracts/src/v0.8/ccip/test/rmn/ArmProxy/ARMProxyTestSetup.t.sol rename to contracts/src/v0.8/ccip/test/rmn/RMNProxy/RMNProxyTestSetup.t.sol index 6a98d726d63..9c8a372dfb9 100644 --- a/contracts/src/v0.8/ccip/test/rmn/ArmProxy/ARMProxyTestSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNProxy/RMNProxyTestSetup.t.sol @@ -1,20 +1,20 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; -import {ARMProxy} from "../../../rmn/ARMProxy.sol"; +import {RMNProxy} from "../../../rmn/RMNProxy.sol"; import {Test} from "forge-std/Test.sol"; -contract ARMProxyTestSetup is Test { +contract RMNProxyTestSetup is Test { address internal constant EMPTY_ADDRESS = address(0x1); address internal constant OWNER_ADDRESS = 0xC0ffeeEeC0fFeeeEc0ffeEeEc0ffEEEEC0FfEEee; address internal constant MOCK_RMN_ADDRESS = 0x1337133713371337133713371337133713371337; - ARMProxy internal s_armProxy; + RMNProxy internal s_rmnProxy; function setUp() public virtual { - // needed so that the extcodesize check in ARMProxy.fallback doesn't revert + // needed so that the extcodesize check in RMNProxy.fallback doesn't revert vm.etch(MOCK_RMN_ADDRESS, bytes("fake bytecode")); vm.prank(OWNER_ADDRESS); - s_armProxy = new ARMProxy(MOCK_RMN_ADDRESS); + s_rmnProxy = new RMNProxy(MOCK_RMN_ADDRESS); } } diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.constructor.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.constructor.t.sol index 413ef4a6797..8c2b0157800 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.constructor.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.constructor.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {RMNRemoteSetup} from "./RMNRemoteSetup.t.sol"; diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.curse.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.curse.t.sol index e1af2ab4e6b..4c3d6bd3fb1 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.curse.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.curse.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; import {RMNRemote} from "../../../rmn/RMNRemote.sol"; import {RMNRemoteSetup} from "./RMNRemoteSetup.t.sol"; contract RMNRemote_curse is RMNRemoteSetup { - function test_curse_success() public { + function test_curse() public { vm.expectEmit(); emit RMNRemote.Cursed(s_curseSubjects); @@ -19,14 +19,14 @@ contract RMNRemote_curse is RMNRemoteSetup { assertFalse(s_rmnRemote.isCursed(bytes16(keccak256("subject 3")))); } - function test_curse_AlreadyCursed_duplicateSubject_reverts() public { + function test_RevertWhen_curse_AlreadyCursed_duplicateSubject() public { s_curseSubjects.push(CURSE_SUBJ_1); vm.expectRevert(abi.encodeWithSelector(RMNRemote.AlreadyCursed.selector, CURSE_SUBJ_1)); s_rmnRemote.curse(s_curseSubjects); } - function test_curse_calledByNonOwner_reverts() public { + function test_RevertWhen_curse_calledByNonOwner() public { vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); vm.stopPrank(); vm.prank(STRANGER); diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.globalAndLegacyCurses.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.globalAndLegacyCurses.t.sol deleted file mode 100644 index da6677678fe..00000000000 --- a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.globalAndLegacyCurses.t.sol +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {GLOBAL_CURSE_SUBJECT, LEGACY_CURSE_SUBJECT} from "../../../rmn/RMNRemote.sol"; -import {RMNRemoteSetup} from "./RMNRemoteSetup.t.sol"; - -contract RMNRemote_global_and_legacy_curses is RMNRemoteSetup { - function test_global_and_legacy_curses_success() public { - bytes16 randSubject = bytes16(keccak256("random subject")); - assertFalse(s_rmnRemote.isCursed()); - assertFalse(s_rmnRemote.isCursed(randSubject)); - - s_rmnRemote.curse(GLOBAL_CURSE_SUBJECT); - assertTrue(s_rmnRemote.isCursed()); - assertTrue(s_rmnRemote.isCursed(randSubject)); - - s_rmnRemote.uncurse(GLOBAL_CURSE_SUBJECT); - assertFalse(s_rmnRemote.isCursed()); - assertFalse(s_rmnRemote.isCursed(randSubject)); - - s_rmnRemote.curse(LEGACY_CURSE_SUBJECT); - assertTrue(s_rmnRemote.isCursed()); - assertFalse(s_rmnRemote.isCursed(randSubject)); // legacy curse doesn't affect specific subjects - - s_rmnRemote.uncurse(LEGACY_CURSE_SUBJECT); - assertFalse(s_rmnRemote.isCursed()); - assertFalse(s_rmnRemote.isCursed(randSubject)); - } -} diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.globalCurses.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.globalCurses.t.sol new file mode 100644 index 00000000000..3732095ea9d --- /dev/null +++ b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.globalCurses.t.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import {GLOBAL_CURSE_SUBJECT} from "../../../rmn/RMNRemote.sol"; +import {RMNRemoteSetup} from "./RMNRemoteSetup.t.sol"; + +contract RMNRemote_global_curses is RMNRemoteSetup { + function test_isCursed_globalCurseSubject() public { + bytes16 randSubject = bytes16(keccak256("random subject")); + assertFalse(s_rmnRemote.isCursed()); + assertFalse(s_rmnRemote.isCursed(randSubject)); + + s_rmnRemote.curse(GLOBAL_CURSE_SUBJECT); + assertTrue(s_rmnRemote.isCursed()); + assertTrue(s_rmnRemote.isCursed(randSubject)); + + s_rmnRemote.uncurse(GLOBAL_CURSE_SUBJECT); + assertFalse(s_rmnRemote.isCursed()); + assertFalse(s_rmnRemote.isCursed(randSubject)); + } +} diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.isBlessed.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.isBlessed.t.sol index aabfe74bf4d..d013f9edf0b 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.isBlessed.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.isBlessed.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IRMN} from "../../../interfaces/IRMN.sol"; @@ -23,7 +23,7 @@ contract RMNRemote_isBlessed is RMNRemoteSetup { assertFalse(s_rmnRemote.isBlessed(taggedRoot)); } - function test_isBlessed_RevertWhen_IsBlessedNotAvailable() public { + function test_RevertWhen_isBlessedWhen_IsBlessedNotAvailable() public { IRMN.TaggedRoot memory taggedRoot = IRMN.TaggedRoot({root: keccak256("root"), commitStore: makeAddr("commitStore")}); s_rmnRemote = new RMNRemote(100, IRMN(address(0))); diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.setConfig.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.setConfig.t.sol index 0805871955d..f6312fea8b0 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.setConfig.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.setConfig.t.sol @@ -1,24 +1,24 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {RMNRemote} from "../../../rmn/RMNRemote.sol"; import {RMNRemoteSetup} from "./RMNRemoteSetup.t.sol"; contract RMNRemote_setConfig is RMNRemoteSetup { - function test_setConfig_ZeroValueNotAllowed_revert() public { + function test_RevertWhen_setConfig_ZeroValueNotAllowed() public { RMNRemote.Config memory config = - RMNRemote.Config({rmnHomeContractConfigDigest: bytes32(0), signers: s_signers, f: 1}); + RMNRemote.Config({rmnHomeContractConfigDigest: bytes32(0), signers: s_signers, fSign: 1}); vm.expectRevert(RMNRemote.ZeroValueNotAllowed.selector); s_rmnRemote.setConfig(config); } - function test_setConfig_addSigner_removeSigner_success() public { + function test_setConfig_addSigner_removeSigner() public { uint32 currentConfigVersion = 0; uint256 numSigners = s_signers.length; RMNRemote.Config memory config = - RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, f: 1}); + RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, fSign: 1}); vm.expectEmit(); emit RMNRemote.ConfigSet(++currentConfigVersion, config); @@ -28,7 +28,7 @@ contract RMNRemote_setConfig is RMNRemoteSetup { // add a signer address newSigner = makeAddr("new signer"); s_signers.push(RMNRemote.Signer({onchainPublicKey: newSigner, nodeIndex: uint64(numSigners)})); - config = RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, f: 1}); + config = RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, fSign: 1}); vm.expectEmit(); emit RMNRemote.ConfigSet(++currentConfigVersion, config); @@ -44,7 +44,7 @@ contract RMNRemote_setConfig is RMNRemoteSetup { // remove two signers s_signers.pop(); s_signers.pop(); - config = RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, f: 1}); + config = RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, fSign: 1}); vm.expectEmit(); emit RMNRemote.ConfigSet(++currentConfigVersion, config); @@ -56,30 +56,30 @@ contract RMNRemote_setConfig is RMNRemoteSetup { assertEq(version, currentConfigVersion); } - function test_setConfig_invalidSignerOrder_reverts() public { + function test_RevertWhen_setConfig_invalidSignerOrder() public { s_signers.push(RMNRemote.Signer({onchainPublicKey: address(4), nodeIndex: 0})); RMNRemote.Config memory config = - RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, f: 1}); + RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, fSign: 1}); vm.expectRevert(RMNRemote.InvalidSignerOrder.selector); s_rmnRemote.setConfig(config); } - function test_setConfig_notEnoughSigners_reverts() public { + function test_RevertWhen_setConfig_notEnoughSigners() public { RMNRemote.Config memory config = RMNRemote.Config({ rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, - f: uint64(s_signers.length / 2) // at least 2f+1 is required + fSign: uint64(s_signers.length / 2) // at least 2f+1 is required }); vm.expectRevert(RMNRemote.NotEnoughSigners.selector); s_rmnRemote.setConfig(config); } - function test_setConfig_duplicateOnChainPublicKey_reverts() public { + function test_RevertWhen_setConfig_duplicateOnChainPublicKey() public { s_signers.push(RMNRemote.Signer({onchainPublicKey: s_signerWallets[0].addr, nodeIndex: uint64(s_signers.length)})); RMNRemote.Config memory config = - RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, f: 1}); + RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, fSign: 1}); vm.expectRevert(RMNRemote.DuplicateOnchainPublicKey.selector); s_rmnRemote.setConfig(config); diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.uncurse.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.uncurse.t.sol index ad784a8cb30..5f537f3d7fc 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.uncurse.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.uncurse.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; import {RMNRemote} from "../../../rmn/RMNRemote.sol"; @@ -11,7 +11,7 @@ contract RMNRemote_uncurse is RMNRemoteSetup { s_rmnRemote.curse(s_curseSubjects); } - function test_uncurse_success() public { + function test_uncurse() public { vm.expectEmit(); emit RMNRemote.Uncursed(s_curseSubjects); @@ -22,14 +22,14 @@ contract RMNRemote_uncurse is RMNRemoteSetup { assertFalse(s_rmnRemote.isCursed(CURSE_SUBJ_2)); } - function test_uncurse_NotCursed_duplicatedUncurseSubject_reverts() public { + function test_RevertWhen_uncurse_NotCursed_duplicatedUncurseSubject() public { s_curseSubjects.push(CURSE_SUBJ_1); vm.expectRevert(abi.encodeWithSelector(RMNRemote.NotCursed.selector, CURSE_SUBJ_1)); s_rmnRemote.uncurse(s_curseSubjects); } - function test_uncurse_calledByNonOwner_reverts() public { + function test_RevertWhen_uncurse_calledByNonOwner() public { vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); vm.stopPrank(); vm.prank(STRANGER); diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.verifywithConfigNotSet.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.verifywithConfigNotSet.t.sol index bba4e8e6a0d..f48d87ef620 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.verifywithConfigNotSet.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.verifywithConfigNotSet.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IRMNRemote} from "../../../interfaces/IRMNRemote.sol"; @@ -8,7 +8,7 @@ import {RMNRemote} from "../../../rmn/RMNRemote.sol"; import {RMNRemoteSetup} from "./RMNRemoteSetup.t.sol"; contract RMNRemote_verify_withConfigNotSet is RMNRemoteSetup { - function test_verify_reverts() public { + function test_RevertWhen_verifys() public { Internal.MerkleRoot[] memory merkleRoots = new Internal.MerkleRoot[](0); IRMNRemote.Signature[] memory signatures = new IRMNRemote.Signature[](0); diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.verifywithConfigSet.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.verifywithConfigSet.t.sol index 1ba9de9d039..6a68a14cead 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.verifywithConfigSet.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.verifywithConfigSet.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IRMNRemote} from "../../../interfaces/IRMNRemote.sol"; import {RMNRemote} from "../../../rmn/RMNRemote.sol"; @@ -8,48 +8,44 @@ import {RMNRemoteSetup} from "./RMNRemoteSetup.t.sol"; contract RMNRemote_verify_withConfigSet is RMNRemoteSetup { function setUp() public override { super.setUp(); + RMNRemote.Config memory config = - RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, f: 3}); + RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, fSign: 3}); s_rmnRemote.setConfig(config); _generatePayloadAndSigs(2, 4); } - function test_verify_success() public view { + function test_verify() public view { s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures); } - function test_verify_InvalidSignature_reverts() public { - IRMNRemote.Signature memory sig = s_signatures[s_signatures.length - 1]; - sig.r = _randomBytes32(); - s_signatures.pop(); - s_signatures.push(sig); + function test_verify_RevertWhen_InvalidSignature() public { + s_signatures[s_signatures.length - 1].r = 0x0; vm.expectRevert(RMNRemote.InvalidSignature.selector); + s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures); } - function test_verify_OutOfOrderSignatures_not_sorted_reverts() public { + function test_verify_RevertWhen_OutOfOrderSignatures_not_sorted() public { IRMNRemote.Signature memory sig1 = s_signatures[s_signatures.length - 1]; - s_signatures.pop(); - IRMNRemote.Signature memory sig2 = s_signatures[s_signatures.length - 1]; - s_signatures.pop(); - s_signatures.push(sig1); - s_signatures.push(sig2); + IRMNRemote.Signature memory sig2 = s_signatures[s_signatures.length - 2]; + + s_signatures[s_signatures.length - 1] = sig2; + s_signatures[s_signatures.length - 2] = sig1; vm.expectRevert(RMNRemote.OutOfOrderSignatures.selector); s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures); } - function test_verify_OutOfOrderSignatures_duplicateSignature_reverts() public { - IRMNRemote.Signature memory sig = s_signatures[s_signatures.length - 2]; - s_signatures.pop(); - s_signatures.push(sig); + function test_verify_RevertWhen_OutOfOrderSignatures_duplicateSignature() public { + s_signatures[s_signatures.length - 1] = s_signatures[s_signatures.length - 2]; vm.expectRevert(RMNRemote.OutOfOrderSignatures.selector); s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures); } - function test_verify_UnexpectedSigner_reverts() public { + function test_verify_RevertWhen_UnexpectedSigner() public { _setupSigners(4); // create new signers that aren't configured on RMNRemote _generatePayloadAndSigs(2, 4); @@ -57,9 +53,9 @@ contract RMNRemote_verify_withConfigSet is RMNRemoteSetup { s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures); } - function test_verify_ThresholdNotMet_reverts() public { + function test_verify_RevertWhen_ThresholdNotMet() public { RMNRemote.Config memory config = - RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, f: 2}); // 3 = f+1 sigs required + RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, fSign: 2}); // 3 = f+1 sigs required s_rmnRemote.setConfig(config); _generatePayloadAndSigs(2, 2); // 2 sigs generated, but 3 required diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemoteSetup.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemoteSetup.t.sol index afb65eeab11..3c3ecd7a62b 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemoteSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemoteSetup.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IRMN} from "../../../interfaces/IRMN.sol"; import {IRMNRemote} from "../../../interfaces/IRMNRemote.sol"; @@ -49,7 +49,7 @@ contract RMNRemoteSetup is BaseTest { } for (uint256 i = 0; i < numSigners; ++i) { - s_signerWallets.push(vm.createWallet(_randomNum())); + s_signerWallets.push(vm.createWallet(vm.randomUint())); } _sort(s_signerWallets); @@ -84,11 +84,11 @@ contract RMNRemoteSetup is BaseTest { /// @notice generates a random dest lane update function _generateRandomDestLaneUpdate() private returns (Internal.MerkleRoot memory) { - uint64 minSeqNum = uint32(_randomNum()); + uint64 minSeqNum = uint32(vm.randomUint()); uint64 maxSeqNum = minSeqNum + 100; return Internal.MerkleRoot({ - sourceChainSelector: uint64(_randomNum()), - onRampAddress: abi.encode(_randomAddress()), + sourceChainSelector: uint64(vm.randomUint()), + onRampAddress: abi.encode(vm.randomAddress()), minSeqNr: minSeqNum, maxSeqNr: maxSeqNum, merkleRoot: _randomBytes32() @@ -147,4 +147,9 @@ contract RMNRemoteSetup is BaseTest { } } } + + /// @dev returns a pseudo-random bytes32 + function _randomBytes32() internal returns (bytes32) { + return bytes32(vm.randomUint()); + } } diff --git a/contracts/src/v0.8/ccip/test/router/Router/Router.applyRampUpdates.t.sol b/contracts/src/v0.8/ccip/test/router/Router/Router.applyRampUpdates.t.sol index be0999542ea..4284c854466 100644 --- a/contracts/src/v0.8/ccip/test/router/Router/Router.applyRampUpdates.t.sol +++ b/contracts/src/v0.8/ccip/test/router/Router/Router.applyRampUpdates.t.sol @@ -1,18 +1,18 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; -import {Router} from "../../../Router.sol"; import {IAny2EVMMessageReceiver} from "../../../interfaces/IAny2EVMMessageReceiver.sol"; import {IRouter} from "../../../interfaces/IRouter.sol"; -import {Client} from "../../../libraries/Client.sol"; +import {Router} from "../../../Router.sol"; +import {Client} from "../../../libraries/Client.sol"; +import {BaseTest} from "../../BaseTest.t.sol"; import {MaybeRevertMessageReceiver} from "../../helpers/receivers/MaybeRevertMessageReceiver.sol"; -import {RouterSetup} from "./RouterSetup.t.sol"; -contract Router_applyRampUpdates is RouterSetup { +contract Router_applyRampUpdates is BaseTest { MaybeRevertMessageReceiver internal s_receiver; - function setUp() public virtual override(RouterSetup) { + function setUp() public virtual override { super.setUp(); s_receiver = new MaybeRevertMessageReceiver(false); } @@ -22,7 +22,14 @@ contract Router_applyRampUpdates is RouterSetup { ) internal { vm.startPrank(offRamp.offRamp); - Client.Any2EVMMessage memory message = _generateReceiverMessage(offRamp.sourceChainSelector); + Client.Any2EVMMessage memory message = Client.Any2EVMMessage({ + messageId: bytes32("a"), + sourceChainSelector: offRamp.sourceChainSelector, + sender: bytes("a"), + data: bytes("a"), + destTokenAmounts: new Client.EVMTokenAmount[](0) + }); + vm.expectCall(address(s_receiver), abi.encodeWithSelector(IAny2EVMMessageReceiver.ccipReceive.selector, message)); s_sourceRouter.routeMessage(message, GAS_FOR_CALL_EXACT_CHECK, 100_000, address(s_receiver)); } @@ -34,7 +41,16 @@ contract Router_applyRampUpdates is RouterSetup { vm.expectRevert(IRouter.OnlyOffRamp.selector); s_sourceRouter.routeMessage( - _generateReceiverMessage(offRamp.sourceChainSelector), GAS_FOR_CALL_EXACT_CHECK, 100_000, address(s_receiver) + Client.Any2EVMMessage({ + messageId: bytes32("a"), + sourceChainSelector: offRamp.sourceChainSelector, + sender: bytes("a"), + data: bytes("a"), + destTokenAmounts: new Client.EVMTokenAmount[](0) + }), + GAS_FOR_CALL_EXACT_CHECK, + 100_000, + address(s_receiver) ); } @@ -267,7 +283,7 @@ contract Router_applyRampUpdates is RouterSetup { assertTrue(s_sourceRouter.isChainSupported(DEST_CHAIN_SELECTOR)); } - function test_applyRampUpdates_RevertWhen_OnlyOwner() public { + function test_RevertWhen_applyRampUpdatesWhen_OnlyOwner() public { vm.stopPrank(); vm.expectRevert("Only callable by owner"); Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](0); @@ -275,7 +291,7 @@ contract Router_applyRampUpdates is RouterSetup { s_sourceRouter.applyRampUpdates(onRampUpdates, offRampUpdates, offRampUpdates); } - function test_applyRampUpdates_RevertWhen_OffRampMismatch() public { + function test_RevertWhen_applyRampUpdatesWhen_OffRampMismatch() public { address offRamp = address(uint160(2)); Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](0); diff --git a/contracts/src/v0.8/ccip/test/router/Router/Router.ccipSend.t.sol b/contracts/src/v0.8/ccip/test/router/Router/Router.ccipSend.t.sol index c44a94d8d3d..bf7b8f59353 100644 --- a/contracts/src/v0.8/ccip/test/router/Router/Router.ccipSend.t.sol +++ b/contracts/src/v0.8/ccip/test/router/Router/Router.ccipSend.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; @@ -138,7 +138,7 @@ contract Router_ccipSend is OnRampSetup { vm.resumeGasMetering(); } - function test_NonLinkFeeToken_Success() public { + function test_NonLinkFeeToken() public { address[] memory feeTokens = new address[](1); feeTokens[0] = s_sourceTokens[1]; s_feeQuoter.applyFeeTokensUpdates(new address[](0), feeTokens); @@ -149,7 +149,7 @@ contract Router_ccipSend is OnRampSetup { s_sourceRouter.ccipSend(DEST_CHAIN_SELECTOR, message); } - function test_NativeFeeToken_Success() public { + function test_NativeFeeToken() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.feeToken = address(0); // Raw native uint256 nativeQuote = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); @@ -158,7 +158,7 @@ contract Router_ccipSend is OnRampSetup { s_sourceRouter.ccipSend{value: nativeQuote}(DEST_CHAIN_SELECTOR, message); } - function test_NativeFeeTokenOverpay_Success() public { + function test_NativeFeeTokenOverpay() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.feeToken = address(0); // Raw native uint256 nativeQuote = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); @@ -170,7 +170,7 @@ contract Router_ccipSend is OnRampSetup { assertEq(address(s_sourceRouter).balance, 0); } - function test_WrappedNativeFeeToken_Success() public { + function test_WrappedNativeFeeToken() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.feeToken = s_sourceRouter.getWrappedNative(); uint256 nativeQuote = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); @@ -184,14 +184,15 @@ contract Router_ccipSend is OnRampSetup { // Reverts - function test_WhenNotHealthy_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - s_mockRMN.setGlobalCursed(true); + function test_RevertWhen_WhenNotHealthy() public { + vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSignature("isCursed()"), abi.encode(true)); + vm.expectRevert(Router.BadARMSignal.selector); - s_sourceRouter.ccipSend(DEST_CHAIN_SELECTOR, message); + + s_sourceRouter.ccipSend(DEST_CHAIN_SELECTOR, _generateEmptyMessage()); } - function test_UnsupportedDestinationChain_Revert() public { + function test_RevertWhen_UnsupportedDestinationChain() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); uint64 wrongChain = DEST_CHAIN_SELECTOR + 1; @@ -200,7 +201,7 @@ contract Router_ccipSend is OnRampSetup { s_sourceRouter.ccipSend(wrongChain, message); } - function test_FeeTokenAmountTooLow_Revert() public { + function test_RevertWhen_FeeTokenAmountTooLow() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); IERC20(s_sourceTokens[0]).approve(address(s_sourceRouter), 0); diff --git a/contracts/src/v0.8/ccip/test/router/Router/Router.constructor.t.sol b/contracts/src/v0.8/ccip/test/router/Router/Router.constructor.t.sol index a7dd90fc5e5..6ac1d483729 100644 --- a/contracts/src/v0.8/ccip/test/router/Router/Router.constructor.t.sol +++ b/contracts/src/v0.8/ccip/test/router/Router/Router.constructor.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {OnRampSetup} from "../../onRamp/OnRamp/OnRampSetup.t.sol"; contract Router_constructor is OnRampSetup { - function test_Constructor_Success() public view { + function test_Constructor() public view { assertEq("Router 1.2.0", s_sourceRouter.typeAndVersion()); assertEq(OWNER, s_sourceRouter.owner()); } diff --git a/contracts/src/v0.8/ccip/test/router/Router/Router.getArmProxy.t.sol b/contracts/src/v0.8/ccip/test/router/Router/Router.getArmProxy.t.sol index a88e4c6b543..3bc57e56291 100644 --- a/contracts/src/v0.8/ccip/test/router/Router/Router.getArmProxy.t.sol +++ b/contracts/src/v0.8/ccip/test/router/Router/Router.getArmProxy.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; -import {RouterSetup} from "./RouterSetup.t.sol"; +import {BaseTest} from "../../BaseTest.t.sol"; -contract Router_getArmProxy is RouterSetup { +contract Router_getArmProxy is BaseTest { function test_getArmProxy() public view { - assertEq(s_sourceRouter.getArmProxy(), address(s_mockRMN)); + assertEq(s_sourceRouter.getArmProxy(), address(s_mockRMNRemote)); } } diff --git a/contracts/src/v0.8/ccip/test/router/Router/Router.getFee.t.sol b/contracts/src/v0.8/ccip/test/router/Router/Router.getFee.t.sol index 9cb2249bf6b..f800b6a269c 100644 --- a/contracts/src/v0.8/ccip/test/router/Router/Router.getFee.t.sol +++ b/contracts/src/v0.8/ccip/test/router/Router/Router.getFee.t.sol @@ -1,19 +1,19 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IRouterClient} from "../../../interfaces/IRouterClient.sol"; import {Client} from "../../../libraries/Client.sol"; import {OnRampSetup} from "../../onRamp/OnRamp/OnRampSetup.t.sol"; contract Router_getFee is OnRampSetup { - function test_GetFeeSupportedChain_Success() public view { + function test_GetFeeSupportedChain() public view { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); assertGt(expectedFee, 10e9); } // Reverts - function test_UnsupportedDestinationChain_Revert() public { + function test_RevertWhen_UnsupportedDestinationChain() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); vm.expectRevert(abi.encodeWithSelector(IRouterClient.UnsupportedDestinationChain.selector, 999)); diff --git a/contracts/src/v0.8/ccip/test/router/Router/Router.getSupportedTokens.t.sol b/contracts/src/v0.8/ccip/test/router/Router/Router.getSupportedTokens.t.sol index 734f1f35ca5..d13acceff3c 100644 --- a/contracts/src/v0.8/ccip/test/router/Router/Router.getSupportedTokens.t.sol +++ b/contracts/src/v0.8/ccip/test/router/Router/Router.getSupportedTokens.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {OnRamp} from "../../../onRamp/OnRamp.sol"; import {OnRampSetup} from "../../onRamp/OnRamp/OnRampSetup.t.sol"; contract Router_getSupportedTokens is OnRampSetup { - function test_GetSupportedTokens_Revert() public { + function test_RevertWhen_GetSupportedTokens() public { vm.expectRevert(OnRamp.GetSupportedTokensFunctionalityRemovedCheckAdminRegistry.selector); s_onRamp.getSupportedTokens(DEST_CHAIN_SELECTOR); } diff --git a/contracts/src/v0.8/ccip/test/router/Router/Router.recoverTokens.t.sol b/contracts/src/v0.8/ccip/test/router/Router/Router.recoverTokens.t.sol index 3eb76b52d1b..4d9c7928fc9 100644 --- a/contracts/src/v0.8/ccip/test/router/Router/Router.recoverTokens.t.sol +++ b/contracts/src/v0.8/ccip/test/router/Router/Router.recoverTokens.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; @@ -9,7 +9,7 @@ import {MaybeRevertMessageReceiver} from "../../helpers/receivers/MaybeRevertMes import {OnRampSetup} from "../../onRamp/OnRamp/OnRampSetup.t.sol"; contract Router_recoverTokens is OnRampSetup { - function test_RecoverTokens_Success() public { + function test_RecoverTokens() public { // Assert we can recover sourceToken IERC20 token = IERC20(s_sourceTokens[0]); uint256 balanceBefore = token.balanceOf(OWNER); @@ -28,25 +28,25 @@ contract Router_recoverTokens is OnRampSetup { assertEq(address(s_sourceRouter).balance, 0); } - function test_RecoverTokensNonOwner_Revert() public { + function test_RevertWhen_RecoverTokensNonOwner() public { // Reverts if not owner vm.startPrank(STRANGER); vm.expectRevert("Only callable by owner"); s_sourceRouter.recoverTokens(address(0), STRANGER, 1); } - function test_RecoverTokensInvalidRecipient_Revert() public { + function test_RevertWhen_RecoverTokensInvalidRecipient() public { vm.expectRevert(abi.encodeWithSelector(Router.InvalidRecipientAddress.selector, address(0))); s_sourceRouter.recoverTokens(address(0), address(0), 1); } - function test_RecoverTokensNoFunds_Revert() public { + function test_RevertWhen_RecoverTokensNoFunds() public { // Reverts if no funds present vm.expectRevert(); s_sourceRouter.recoverTokens(address(0), OWNER, 10); } - function test_RecoverTokensValueReceiver_Revert() public { + function test_RevertWhen_RecoverTokensValueReceiver() public { MaybeRevertMessageReceiver revertingValueReceiver = new MaybeRevertMessageReceiver(true); deal(address(s_sourceRouter), 10); diff --git a/contracts/src/v0.8/ccip/test/router/Router/Router.routeMessage.t.sol b/contracts/src/v0.8/ccip/test/router/Router/Router.routeMessage.t.sol index 8fca851fa4a..26b629dd30e 100644 --- a/contracts/src/v0.8/ccip/test/router/Router/Router.routeMessage.t.sol +++ b/contracts/src/v0.8/ccip/test/router/Router/Router.routeMessage.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; -import {Router} from "../../../Router.sol"; import {IAny2EVMMessageReceiver} from "../../../interfaces/IAny2EVMMessageReceiver.sol"; import {IRouter} from "../../../interfaces/IRouter.sol"; -import {Client} from "../../../libraries/Client.sol"; +import {Router} from "../../../Router.sol"; +import {Client} from "../../../libraries/Client.sol"; import {MaybeRevertMessageReceiver} from "../../helpers/receivers/MaybeRevertMessageReceiver.sol"; import {OffRampSetup} from "../../offRamp/OffRamp/OffRampSetup.t.sol"; @@ -21,7 +21,20 @@ contract Router_routeMessage is OffRampSetup { return ((gasleft() - 2 * (16 * callDataLength + GAS_FOR_CALL_EXACT_CHECK)) * 62) / 64; } - function test_routeMessage_ManualExec_Success() public { + function _generateReceiverMessage( + uint64 chainSelector + ) internal pure returns (Client.Any2EVMMessage memory) { + Client.EVMTokenAmount[] memory ta = new Client.EVMTokenAmount[](0); + return Client.Any2EVMMessage({ + messageId: bytes32("a"), + sourceChainSelector: chainSelector, + sender: bytes("a"), + data: bytes("a"), + destTokenAmounts: ta + }); + } + + function test_routeMessage_ManualExec() public { Client.Any2EVMMessage memory message = _generateReceiverMessage(SOURCE_CHAIN_SELECTOR); // Manuel execution cannot run out of gas @@ -36,7 +49,7 @@ contract Router_routeMessage is OffRampSetup { assertGt(gasUsed, 3_000); } - function test_routeMessage_ExecutionEvent_Success() public { + function test_routeMessage_ExecutionEvent() public { Client.Any2EVMMessage memory message = _generateReceiverMessage(SOURCE_CHAIN_SELECTOR); // Should revert with reason bytes memory realError1 = new bytes(2); @@ -61,7 +74,7 @@ contract Router_routeMessage is OffRampSetup { assertFalse(success); assertEq(abi.encodeWithSelector(MaybeRevertMessageReceiver.CustomError.selector, realError1), retData); - assertGt(gasUsed, 3_000); + assertGt(gasUsed, 2850); // Reason is truncated // Over the MAX_RET_BYTES limit (including offset and length word since we have a dynamic values), should be ignored @@ -165,7 +178,7 @@ contract Router_routeMessage is OffRampSetup { assertEq(expectedRetData, retData); } - function test_routeMessage_AutoExec_Success() public { + function test_routeMessage_AutoExec() public { (bool success,,) = s_destRouter.routeMessage( _generateReceiverMessage(SOURCE_CHAIN_SELECTOR), GAS_FOR_CALL_EXACT_CHECK, 100_000, address(s_receiver) ); @@ -181,7 +194,7 @@ contract Router_routeMessage is OffRampSetup { } // Reverts - function test_routeMessage_OnlyOffRamp_Revert() public { + function test_RevertWhen_routeMessage_OnlyOffRamp() public { vm.stopPrank(); vm.startPrank(STRANGER); @@ -191,8 +204,8 @@ contract Router_routeMessage is OffRampSetup { ); } - function test_routeMessage_WhenNotHealthy_Revert() public { - s_mockRMN.setGlobalCursed(true); + function test_RevertWhen_routeMessage_WhenNotHealthy() public { + vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSignature("isCursed()"), abi.encode(true)); vm.expectRevert(Router.BadARMSignal.selector); s_destRouter.routeMessage( _generateReceiverMessage(SOURCE_CHAIN_SELECTOR), GAS_FOR_CALL_EXACT_CHECK, 100_000, address(s_receiver) diff --git a/contracts/src/v0.8/ccip/test/router/Router/Router.setWrappedNative.t.sol b/contracts/src/v0.8/ccip/test/router/Router/Router.setWrappedNative.t.sol index a23d98e4eaa..62cab30b5d0 100644 --- a/contracts/src/v0.8/ccip/test/router/Router/Router.setWrappedNative.t.sol +++ b/contracts/src/v0.8/ccip/test/router/Router/Router.setWrappedNative.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {OnRampSetup} from "../../onRamp/OnRamp/OnRampSetup.t.sol"; @@ -12,7 +12,7 @@ contract Router_setWrappedNative is OnRampSetup { } // Reverts - function test_OnlyOwner_Revert() public { + function test_RevertWhen_OnlyOwner() public { vm.stopPrank(); vm.expectRevert("Only callable by owner"); s_sourceRouter.setWrappedNative(address(1)); diff --git a/contracts/src/v0.8/ccip/test/router/Router/RouterSetup.t.sol b/contracts/src/v0.8/ccip/test/router/Router/RouterSetup.t.sol deleted file mode 100644 index 4a977db6c23..00000000000 --- a/contracts/src/v0.8/ccip/test/router/Router/RouterSetup.t.sol +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {Router} from "../../../Router.sol"; -import {Client} from "../../../libraries/Client.sol"; -import {Internal} from "../../../libraries/Internal.sol"; -import {BaseTest} from "../../BaseTest.t.sol"; -import {WETH9} from "../../WETH9.sol"; - -contract RouterSetup is BaseTest { - Router internal s_sourceRouter; - Router internal s_destRouter; - - function setUp() public virtual override { - BaseTest.setUp(); - - if (address(s_sourceRouter) == address(0)) { - WETH9 weth = new WETH9(); - s_sourceRouter = new Router(address(weth), address(s_mockRMN)); - vm.label(address(s_sourceRouter), "sourceRouter"); - } - if (address(s_destRouter) == address(0)) { - WETH9 weth = new WETH9(); - s_destRouter = new Router(address(weth), address(s_mockRMN)); - vm.label(address(s_destRouter), "destRouter"); - } - } - - function _generateReceiverMessage( - uint64 chainSelector - ) internal pure returns (Client.Any2EVMMessage memory) { - Client.EVMTokenAmount[] memory ta = new Client.EVMTokenAmount[](0); - return Client.Any2EVMMessage({ - messageId: bytes32("a"), - sourceChainSelector: chainSelector, - sender: bytes("a"), - data: bytes("a"), - destTokenAmounts: ta - }); - } - - function _generateSourceTokenData() internal pure returns (Internal.SourceTokenData memory) { - return Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(address(12312412312)), - destTokenAddress: abi.encode(address(9809808909)), - extraData: "", - destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD - }); - } -} diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/BurnMintERC20Setup.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/BurnMintERC20Setup.t.sol index 098d5e4601e..f5ad827db45 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/BurnMintERC20Setup.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/BurnMintERC20Setup.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {FactoryBurnMintERC20} from "../../../tokenAdminRegistry/TokenPoolFactory/FactoryBurnMintERC20.sol"; import {BaseTest} from "../../BaseTest.t.sol"; diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.approve.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.approve.t.sol index 9ba6da0186d..4117bba4f6e 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.approve.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.approve.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; contract FactoryBurnMintERC20_approve is BurnMintERC20Setup { - function test_Approve_Success() public { + function test_Approve() public { uint256 balancePre = s_burnMintERC20.balanceOf(STRANGER); uint256 sendingAmount = s_amount / 2; @@ -19,7 +19,7 @@ contract FactoryBurnMintERC20_approve is BurnMintERC20Setup { // Reverts - function test_InvalidAddress_Reverts() public { + function test_RevertWhen_InvalidAddresss() public { vm.expectRevert(); s_burnMintERC20.approve(address(s_burnMintERC20), s_amount); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.burn.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.burn.t.sol index 5f6e7ee4d04..8ca692a4069 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.burn.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.burn.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; import {FactoryBurnMintERC20} from "../../../tokenAdminRegistry/TokenPoolFactory/FactoryBurnMintERC20.sol"; import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; contract FactoryBurnMintERC20_burn is BurnMintERC20Setup { - function test_BasicBurn_Success() public { + function test_BasicBurn() public { s_burnMintERC20.grantBurnRole(OWNER); deal(address(s_burnMintERC20), OWNER, s_amount); @@ -20,13 +20,13 @@ contract FactoryBurnMintERC20_burn is BurnMintERC20Setup { // Revert - function test_SenderNotBurner_Reverts() public { + function test_RevertWhen_SenderNotBurners() public { vm.expectRevert(abi.encodeWithSelector(FactoryBurnMintERC20.SenderNotBurner.selector, OWNER)); s_burnMintERC20.burnFrom(STRANGER, s_amount); } - function test_ExceedsBalance_Reverts() public { + function test_RevertWhen_ExceedsBalances() public { changePrank(s_mockPool); vm.expectRevert("ERC20: burn amount exceeds balance"); @@ -34,7 +34,7 @@ contract FactoryBurnMintERC20_burn is BurnMintERC20Setup { s_burnMintERC20.burn(s_amount * 2); } - function test_BurnFromZeroAddress_Reverts() public { + function test_RevertWhen_BurnFromZeroAddresss() public { s_burnMintERC20.grantBurnRole(address(0)); changePrank(address(0)); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.burnFrom.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.burnFrom.t.sol index e2dcaf28563..4549ca01dbe 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.burnFrom.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.burnFrom.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {FactoryBurnMintERC20} from "../../../tokenAdminRegistry/TokenPoolFactory/FactoryBurnMintERC20.sol"; import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; @@ -9,7 +9,7 @@ contract FactoryBurnMintERC20_burnFrom is BurnMintERC20Setup { BurnMintERC20Setup.setUp(); } - function test_BurnFrom_Success() public { + function test_BurnFrom() public { s_burnMintERC20.approve(s_mockPool, s_amount); changePrank(s_mockPool); @@ -21,13 +21,13 @@ contract FactoryBurnMintERC20_burnFrom is BurnMintERC20Setup { // Reverts - function test_SenderNotBurner_Reverts() public { + function test_RevertWhen_SenderNotBurners() public { vm.expectRevert(abi.encodeWithSelector(FactoryBurnMintERC20.SenderNotBurner.selector, OWNER)); s_burnMintERC20.burnFrom(OWNER, s_amount); } - function test_InsufficientAllowance_Reverts() public { + function test_RevertWhen_InsufficientAllowances() public { changePrank(s_mockPool); vm.expectRevert("ERC20: insufficient allowance"); @@ -35,7 +35,7 @@ contract FactoryBurnMintERC20_burnFrom is BurnMintERC20Setup { s_burnMintERC20.burnFrom(OWNER, s_amount); } - function test_ExceedsBalance_Reverts() public { + function test_RevertWhen_ExceedsBalances() public { s_burnMintERC20.approve(s_mockPool, s_amount * 2); changePrank(s_mockPool); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.burnFromAlias.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.burnFromAlias.t.sol index 0d46f1d54a5..c71f6142b2d 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.burnFromAlias.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.burnFromAlias.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {FactoryBurnMintERC20} from "../../../tokenAdminRegistry/TokenPoolFactory/FactoryBurnMintERC20.sol"; import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; @@ -9,7 +9,7 @@ contract FactoryBurnMintERC20_burnFromAlias is BurnMintERC20Setup { BurnMintERC20Setup.setUp(); } - function test_BurnFrom_Success() public { + function test_BurnFrom() public { s_burnMintERC20.approve(s_mockPool, s_amount); changePrank(s_mockPool); @@ -21,13 +21,13 @@ contract FactoryBurnMintERC20_burnFromAlias is BurnMintERC20Setup { // Reverts - function test_SenderNotBurner_Reverts() public { + function test_RevertWhen_SenderNotBurners() public { vm.expectRevert(abi.encodeWithSelector(FactoryBurnMintERC20.SenderNotBurner.selector, OWNER)); s_burnMintERC20.burn(OWNER, s_amount); } - function test_InsufficientAllowance_Reverts() public { + function test_RevertWhen_InsufficientAllowances() public { changePrank(s_mockPool); vm.expectRevert("ERC20: insufficient allowance"); @@ -35,7 +35,7 @@ contract FactoryBurnMintERC20_burnFromAlias is BurnMintERC20Setup { s_burnMintERC20.burn(OWNER, s_amount); } - function test_ExceedsBalance_Reverts() public { + function test_RevertWhen_ExceedsBalances() public { s_burnMintERC20.approve(s_mockPool, s_amount * 2); changePrank(s_mockPool); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.constructor.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.constructor.t.sol index f1ee0866abe..a5f65a903c0 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.constructor.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.constructor.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {FactoryBurnMintERC20} from "../../../tokenAdminRegistry/TokenPoolFactory/FactoryBurnMintERC20.sol"; import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; contract FactoryBurnMintERC20_constructor is BurnMintERC20Setup { - function test_Constructor_Success() public { + function test_Constructor() public { string memory name = "Chainlink token v2"; string memory symbol = "LINK2"; uint8 decimals = 19; diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.decreaseApproval.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.decreaseApproval.t.sol index aa621a998ed..fbd64b5858e 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.decreaseApproval.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.decreaseApproval.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; contract FactoryBurnMintERC20_decreaseApproval is BurnMintERC20Setup { - function test_DecreaseApproval_Success() public { + function test_DecreaseApproval() public { s_burnMintERC20.approve(s_mockPool, s_amount); uint256 allowance = s_burnMintERC20.allowance(OWNER, s_mockPool); assertEq(allowance, s_amount); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.getCCIPAdmin.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.getCCIPAdmin.t.sol index fc6a81a712b..2e30bc2a557 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.getCCIPAdmin.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.getCCIPAdmin.t.sol @@ -1,15 +1,15 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {FactoryBurnMintERC20} from "../../../tokenAdminRegistry/TokenPoolFactory/FactoryBurnMintERC20.sol"; import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; contract FactoryBurnMintERC20_getCCIPAdmin is BurnMintERC20Setup { - function test_getCCIPAdmin_Success() public view { + function test_getCCIPAdmin() public view { assertEq(s_alice, s_burnMintERC20.getCCIPAdmin()); } - function test_setCCIPAdmin_Success() public { + function test_setCCIPAdmin() public { address newAdmin = makeAddr("newAdmin"); vm.expectEmit(); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.grantMintAndBurnRoles.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.grantMintAndBurnRoles.t.sol index aaa967edc15..0e55271cab3 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.grantMintAndBurnRoles.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.grantMintAndBurnRoles.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {FactoryBurnMintERC20} from "../../../tokenAdminRegistry/TokenPoolFactory/FactoryBurnMintERC20.sol"; import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; contract FactoryBurnMintERC20_grantMintAndBurnRoles is BurnMintERC20Setup { - function test_GrantMintAndBurnRoles_Success() public { + function test_GrantMintAndBurnRoles() public { assertFalse(s_burnMintERC20.isMinter(STRANGER)); assertFalse(s_burnMintERC20.isBurner(STRANGER)); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.grantRole.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.grantRole.t.sol index a06b52ac338..473c143cbd5 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.grantRole.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.grantRole.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {FactoryBurnMintERC20} from "../../../tokenAdminRegistry/TokenPoolFactory/FactoryBurnMintERC20.sol"; import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; contract FactoryBurnMintERC20_grantRole is BurnMintERC20Setup { - function test_GrantMintAccess_Success() public { + function test_GrantMintAccess() public { assertFalse(s_burnMintERC20.isMinter(STRANGER)); vm.expectEmit(); @@ -23,7 +23,7 @@ contract FactoryBurnMintERC20_grantRole is BurnMintERC20Setup { assertFalse(s_burnMintERC20.isMinter(STRANGER)); } - function test_GrantBurnAccess_Success() public { + function test_GrantBurnAccess() public { assertFalse(s_burnMintERC20.isBurner(STRANGER)); vm.expectEmit(); @@ -41,7 +41,7 @@ contract FactoryBurnMintERC20_grantRole is BurnMintERC20Setup { assertFalse(s_burnMintERC20.isBurner(STRANGER)); } - function test_GrantMany_Success() public { + function test_GrantMany() public { // Since alice was already granted mint and burn roles in the setup, we will revoke them // and then grant them again for the purposes of the test s_burnMintERC20.revokeMintRole(s_alice); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.increaseApproval.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.increaseApproval.t.sol index e93cc2a71e6..b0782470691 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.increaseApproval.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.increaseApproval.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; contract FactoryBurnMintERC20_increaseApproval is BurnMintERC20Setup { - function test_IncreaseApproval_Success() public { + function test_IncreaseApproval() public { s_burnMintERC20.approve(s_mockPool, s_amount); uint256 allowance = s_burnMintERC20.allowance(OWNER, s_mockPool); assertEq(allowance, s_amount); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.mint.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.mint.t.sol index b22783a3c75..59c4145f27b 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.mint.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.mint.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {FactoryBurnMintERC20} from "../../../tokenAdminRegistry/TokenPoolFactory/FactoryBurnMintERC20.sol"; @@ -7,7 +7,7 @@ import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/ import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; contract FactoryBurnMintERC20_mint is BurnMintERC20Setup { - function test_BasicMint_Success() public { + function test_BasicMint() public { uint256 balancePre = s_burnMintERC20.balanceOf(OWNER); s_burnMintERC20.grantMintAndBurnRoles(OWNER); @@ -22,12 +22,12 @@ contract FactoryBurnMintERC20_mint is BurnMintERC20Setup { // Revert - function test_SenderNotMinter_Reverts() public { + function test_RevertWhen_SenderNotMinters() public { vm.expectRevert(abi.encodeWithSelector(FactoryBurnMintERC20.SenderNotMinter.selector, OWNER)); s_burnMintERC20.mint(STRANGER, 1e18); } - function test_MaxSupplyExceeded_Reverts() public { + function test_RevertWhen_MaxSupplyExceededs() public { changePrank(s_mockPool); // Mint max supply diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.supportsInterface.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.supportsInterface.t.sol index bdf3c3e7ae3..0070a943cec 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.supportsInterface.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.supportsInterface.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IBurnMintERC20} from "../../../../shared/token/ERC20/IBurnMintERC20.sol"; import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; @@ -7,7 +7,7 @@ import {IERC165} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; contract FactoryBurnMintERC20_supportsInterface is BurnMintERC20Setup { - function test_SupportsInterface_Success() public view { + function test_SupportsInterface() public view { assertTrue(s_burnMintERC20.supportsInterface(type(IERC20).interfaceId)); assertTrue(s_burnMintERC20.supportsInterface(type(IBurnMintERC20).interfaceId)); assertTrue(s_burnMintERC20.supportsInterface(type(IERC165).interfaceId)); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.transfer.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.transfer.t.sol index 333d50d333e..cf93e9f0b95 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.transfer.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.transfer.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; contract FactoryBurnMintERC20_transfer is BurnMintERC20Setup { - function test_Transfer_Success() public { + function test_Transfer() public { uint256 balancePre = s_burnMintERC20.balanceOf(STRANGER); uint256 sendingAmount = s_amount / 2; @@ -15,7 +15,7 @@ contract FactoryBurnMintERC20_transfer is BurnMintERC20Setup { // Reverts - function test_InvalidAddress_Reverts() public { + function test_RevertWhen_InvalidAddresss() public { vm.expectRevert(); s_burnMintERC20.transfer(address(s_burnMintERC20), s_amount); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.constructor.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.constructor.t.sol index 22bf54e633b..64b58b2d4dd 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.constructor.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.constructor.t.sol @@ -5,7 +5,7 @@ import {RegistryModuleOwnerCustom} from "../../../tokenAdminRegistry/RegistryMod import {RegistryModuleOwnerCustomSetup} from "./RegistryModuleOwnerCustomSetup.t.sol"; contract RegistryModuleOwnerCustom_constructor is RegistryModuleOwnerCustomSetup { - function test_constructor_Revert() public { + function test_RevertWhen_constructor() public { vm.expectRevert(abi.encodeWithSelector(RegistryModuleOwnerCustom.AddressZero.selector)); new RegistryModuleOwnerCustom(address(0)); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.registerAccessControlDefaultAdmin.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.registerAccessControlDefaultAdmin.t.sol index 5bf1c0aee34..6660962b0cf 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.registerAccessControlDefaultAdmin.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.registerAccessControlDefaultAdmin.t.sol @@ -23,7 +23,7 @@ contract RegistryModuleOwnerCustom_registerAccessControlDefaultAdmin is Registry s_token = address(new AccessController(OWNER)); } - function test_registerAccessControlDefaultAdmin_Success() public { + function test_registerAccessControlDefaultAdmin() public { assertEq(s_tokenAdminRegistry.getTokenConfig(s_token).administrator, address(0)); bytes32 defaultAdminRole = AccessController(s_token).DEFAULT_ADMIN_ROLE(); @@ -43,7 +43,7 @@ contract RegistryModuleOwnerCustom_registerAccessControlDefaultAdmin is Registry assertEq(s_tokenAdminRegistry.getTokenConfig(s_token).pendingAdministrator, OWNER); } - function test_registerAccessControlDefaultAdmin_Revert() public { + function test_RevertWhen_registerAccessControlDefaultAdmin() public { bytes32 defaultAdminRole = AccessController(s_token).DEFAULT_ADMIN_ROLE(); address wrongSender = makeAddr("Not_expected_owner"); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.registerAdminViaGetCCIPAdmin.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.registerAdminViaGetCCIPAdmin.t.sol index 5e3c6545417..8646d918afe 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.registerAdminViaGetCCIPAdmin.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.registerAdminViaGetCCIPAdmin.t.sol @@ -9,7 +9,7 @@ import {TokenAdminRegistry} from "../../../tokenAdminRegistry/TokenAdminRegistry import {RegistryModuleOwnerCustomSetup} from "./RegistryModuleOwnerCustomSetup.t.sol"; contract RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin is RegistryModuleOwnerCustomSetup { - function test_registerAdminViaGetCCIPAdmin_Success() public { + function test_registerAdminViaGetCCIPAdmin() public { assertEq(s_tokenAdminRegistry.getTokenConfig(s_token).administrator, address(0)); address expectedOwner = IGetCCIPAdmin(s_token).getCCIPAdmin(); @@ -29,7 +29,7 @@ contract RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin is RegistryModul assertEq(s_tokenAdminRegistry.getTokenConfig(s_token).pendingAdministrator, OWNER); } - function test_registerAdminViaGetCCIPAdmin_Revert() public { + function test_RevertWhen_registerAdminViaGetCCIPAdmin() public { address expectedOwner = IGetCCIPAdmin(s_token).getCCIPAdmin(); vm.startPrank(makeAddr("Not_expected_owner")); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.registerAdminViaOwner.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.registerAdminViaOwner.t.sol index b4e1a5e4577..6fcee1b039e 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.registerAdminViaOwner.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.registerAdminViaOwner.t.sol @@ -9,7 +9,7 @@ import {TokenAdminRegistry} from "../../../tokenAdminRegistry/TokenAdminRegistry import {RegistryModuleOwnerCustomSetup} from "./RegistryModuleOwnerCustomSetup.t.sol"; contract RegistryModuleOwnerCustom_registerAdminViaOwner is RegistryModuleOwnerCustomSetup { - function test_registerAdminViaOwner_Success() public { + function test_registerAdminViaOwner() public { assertEq(s_tokenAdminRegistry.getTokenConfig(s_token).administrator, address(0)); address expectedOwner = IOwner(s_token).owner(); @@ -29,7 +29,7 @@ contract RegistryModuleOwnerCustom_registerAdminViaOwner is RegistryModuleOwnerC assertEq(s_tokenAdminRegistry.getTokenConfig(s_token).pendingAdministrator, OWNER); } - function test_registerAdminViaOwner_Revert() public { + function test_RevertWhen_registerAdminViaOwner() public { address expectedOwner = IOwner(s_token).owner(); vm.startPrank(makeAddr("Not_expected_owner")); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.acceptAdminRole.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.acceptAdminRole.t.sol index 069159b8938..05c3ac77893 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.acceptAdminRole.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.acceptAdminRole.t.sol @@ -5,7 +5,7 @@ import {TokenAdminRegistry} from "../../../tokenAdminRegistry/TokenAdminRegistry import {TokenAdminRegistrySetup} from "./TokenAdminRegistrySetup.t.sol"; contract TokenAdminRegistry_acceptAdminRole is TokenAdminRegistrySetup { - function test_acceptAdminRole_Success() public { + function test_acceptAdminRole() public { address token = s_sourceTokens[0]; address currentAdmin = s_tokenAdminRegistry.getTokenConfig(token).administrator; @@ -36,7 +36,7 @@ contract TokenAdminRegistry_acceptAdminRole is TokenAdminRegistrySetup { assertEq(config.administrator, newAdmin); } - function test_acceptAdminRole_OnlyPendingAdministrator_Revert() public { + function test_RevertWhen_acceptAdminRole_OnlyPendingAdministrator() public { address token = s_sourceTokens[0]; address currentAdmin = s_tokenAdminRegistry.getTokenConfig(token).administrator; address newAdmin = makeAddr("newAdmin"); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.addRegistryModule.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.addRegistryModule.t.sol index 9874ceb72bc..9e21cd3e193 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.addRegistryModule.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.addRegistryModule.t.sol @@ -5,7 +5,7 @@ import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; import {TokenAdminRegistrySetup} from "./TokenAdminRegistrySetup.t.sol"; contract TokenAdminRegistry_addRegistryModule is TokenAdminRegistrySetup { - function test_addRegistryModule_Success() public { + function test_addRegistryModule() public { address newModule = makeAddr("newModule"); s_tokenAdminRegistry.addRegistryModule(newModule); @@ -19,7 +19,7 @@ contract TokenAdminRegistry_addRegistryModule is TokenAdminRegistrySetup { vm.assertEq(vm.getRecordedLogs().length, 0); } - function test_addRegistryModule_OnlyOwner_Revert() public { + function test_RevertWhen_addRegistryModule_OnlyOwner() public { address newModule = makeAddr("newModule"); vm.stopPrank(); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.getAllConfiguredTokens.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.getAllConfiguredTokens.t.sol index 6e16f27eca7..9d42bcc8b2f 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.getAllConfiguredTokens.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.getAllConfiguredTokens.t.sol @@ -28,7 +28,7 @@ contract TokenAdminRegistry_getAllConfiguredTokens is TokenAdminRegistrySetup { } } - function test_getAllConfiguredTokens_outOfBounds_Success() public view { + function test_getAllConfiguredTokens_outOfBounds() public view { address[] memory tokens = s_tokenAdminRegistry.getAllConfiguredTokens(type(uint64).max, 10); assertEq(tokens.length, 0); } diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.getPool.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.getPool.t.sol index 297e3c3143a..12288ae365c 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.getPool.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.getPool.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; import {TokenAdminRegistrySetup} from "./TokenAdminRegistrySetup.t.sol"; contract TokenAdminRegistry_getPool is TokenAdminRegistrySetup { - function test_getPool_Success() public view { + function test_getPool() public view { address got = s_tokenAdminRegistry.getPool(s_sourceTokens[0]); assertEq(got, s_sourcePoolByToken[s_sourceTokens[0]]); } diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.getPools.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.getPools.t.sol index 7c673ee5be6..194adc447b9 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.getPools.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.getPools.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; import {TokenAdminRegistrySetup} from "./TokenAdminRegistrySetup.t.sol"; contract TokenAdminRegistry_getPools is TokenAdminRegistrySetup { - function test_getPools_Success() public { + function test_getPools() public { address[] memory tokens = new address[](1); tokens[0] = s_sourceTokens[0]; diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.isAdministrator.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.isAdministrator.t.sol index 00555ba3ff2..e94a0654a7e 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.isAdministrator.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.isAdministrator.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; import {TokenAdminRegistrySetup} from "./TokenAdminRegistrySetup.t.sol"; contract TokenAdminRegistry_isAdministrator is TokenAdminRegistrySetup { - function test_isAdministrator_Success() public { + function test_isAdministrator() public { address newAdmin = makeAddr("newAdmin"); address newToken = makeAddr("newToken"); assertFalse(s_tokenAdminRegistry.isAdministrator(newToken, newAdmin)); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.proposeAdministrator.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.proposeAdministrator.t.sol index 6f3ac4449c6..3d2fc0dafee 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.proposeAdministrator.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.proposeAdministrator.t.sol @@ -5,7 +5,7 @@ import {TokenAdminRegistry} from "../../../tokenAdminRegistry/TokenAdminRegistry import {TokenAdminRegistrySetup} from "./TokenAdminRegistrySetup.t.sol"; contract TokenAdminRegistry_proposeAdministrator is TokenAdminRegistrySetup { - function test_proposeAdministrator_module_Success() public { + function test_proposeAdministrator_module() public { vm.startPrank(s_registryModule); address newAdmin = makeAddr("newAdmin"); address newToken = makeAddr("newToken"); @@ -25,7 +25,7 @@ contract TokenAdminRegistry_proposeAdministrator is TokenAdminRegistrySetup { assertTrue(s_tokenAdminRegistry.isAdministrator(newToken, newAdmin)); } - function test_proposeAdministrator_owner_Success() public { + function test_proposeAdministrator_owner() public { address newAdmin = makeAddr("newAdmin"); address newToken = makeAddr("newToken"); @@ -42,7 +42,7 @@ contract TokenAdminRegistry_proposeAdministrator is TokenAdminRegistrySetup { assertTrue(s_tokenAdminRegistry.isAdministrator(newToken, newAdmin)); } - function test_proposeAdministrator_reRegisterWhileUnclaimed_Success() public { + function test_proposeAdministrator_reRegisterWhileUnclaimed() public { address newAdmin = makeAddr("wrongAddress"); address newToken = makeAddr("newToken"); @@ -87,7 +87,7 @@ contract TokenAdminRegistry_proposeAdministrator is TokenAdminRegistrySetup { } } - function test_proposeAdministrator_OnlyRegistryModule_Revert() public { + function test_RevertWhen_proposeAdministrator_OnlyRegistryModule() public { address newToken = makeAddr("newToken"); vm.stopPrank(); @@ -95,14 +95,14 @@ contract TokenAdminRegistry_proposeAdministrator is TokenAdminRegistrySetup { s_tokenAdminRegistry.proposeAdministrator(newToken, OWNER); } - function test_proposeAdministrator_ZeroAddress_Revert() public { + function test_RevertWhen_proposeAdministrator_ZeroAddress() public { address newToken = makeAddr("newToken"); vm.expectRevert(abi.encodeWithSelector(TokenAdminRegistry.ZeroAddress.selector)); s_tokenAdminRegistry.proposeAdministrator(newToken, address(0)); } - function test_proposeAdministrator_AlreadyRegistered_Revert() public { + function test_RevertWhen_proposeAdministrator_AlreadyRegistered() public { address newAdmin = makeAddr("newAdmin"); address newToken = makeAddr("newToken"); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.removeRegistryModule.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.removeRegistryModule.t.sol index d5fde7ad5d5..5f5141eb3f3 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.removeRegistryModule.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.removeRegistryModule.t.sol @@ -6,7 +6,7 @@ import {TokenAdminRegistry} from "../../../tokenAdminRegistry/TokenAdminRegistry import {TokenAdminRegistrySetup} from "./TokenAdminRegistrySetup.t.sol"; contract TokenAdminRegistry_removeRegistryModule is TokenAdminRegistrySetup { - function test_removeRegistryModule_Success() public { + function test_removeRegistryModule() public { address newModule = makeAddr("newModule"); s_tokenAdminRegistry.addRegistryModule(newModule); @@ -27,7 +27,7 @@ contract TokenAdminRegistry_removeRegistryModule is TokenAdminRegistrySetup { vm.assertEq(vm.getRecordedLogs().length, 0); } - function test_removeRegistryModule_OnlyOwner_Revert() public { + function test_RevertWhen_removeRegistryModule_OnlyOwner() public { address newModule = makeAddr("newModule"); vm.stopPrank(); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.setPool.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.setPool.t.sol index 51119ce30bb..589b882dc21 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.setPool.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.setPool.t.sol @@ -6,7 +6,7 @@ import {TokenAdminRegistry} from "../../../tokenAdminRegistry/TokenAdminRegistry import {TokenAdminRegistrySetup} from "./TokenAdminRegistrySetup.t.sol"; contract TokenAdminRegistry_setPool is TokenAdminRegistrySetup { - function test_setPool_Success() public { + function test_setPool() public { address pool = makeAddr("pool"); vm.mockCall(pool, abi.encodeWithSelector(IPoolV1.isSupportedToken.selector), abi.encode(true)); @@ -24,7 +24,7 @@ contract TokenAdminRegistry_setPool is TokenAdminRegistrySetup { vm.assertEq(vm.getRecordedLogs().length, 0); } - function test_setPool_ZeroAddressRemovesPool_Success() public { + function test_setPool_ZeroAddressRemovesPool() public { address pool = makeAddr("pool"); vm.mockCall(pool, abi.encodeWithSelector(IPoolV1.isSupportedToken.selector), abi.encode(true)); s_tokenAdminRegistry.setPool(s_sourceTokens[0], pool); @@ -39,7 +39,7 @@ contract TokenAdminRegistry_setPool is TokenAdminRegistrySetup { assertEq(s_tokenAdminRegistry.getPool(s_sourceTokens[0]), address(0)); } - function test_setPool_InvalidTokenPoolToken_Revert() public { + function test_RevertWhen_setPool_InvalidTokenPoolToken() public { address pool = makeAddr("pool"); vm.mockCall(pool, abi.encodeWithSelector(IPoolV1.isSupportedToken.selector), abi.encode(false)); @@ -47,7 +47,7 @@ contract TokenAdminRegistry_setPool is TokenAdminRegistrySetup { s_tokenAdminRegistry.setPool(s_sourceTokens[0], pool); } - function test_setPool_OnlyAdministrator_Revert() public { + function test_RevertWhen_setPool_OnlyAdministrator() public { vm.stopPrank(); vm.expectRevert( diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.transferAdminRole.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.transferAdminRole.t.sol index 07a10b083af..7d0916c8093 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.transferAdminRole.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.transferAdminRole.t.sol @@ -5,7 +5,7 @@ import {TokenAdminRegistry} from "../../../tokenAdminRegistry/TokenAdminRegistry import {TokenAdminRegistrySetup} from "./TokenAdminRegistrySetup.t.sol"; contract TokenAdminRegistry_transferAdminRole is TokenAdminRegistrySetup { - function test_transferAdminRole_Success() public { + function test_transferAdminRole() public { address token = s_sourceTokens[0]; address currentAdmin = s_tokenAdminRegistry.getTokenConfig(token).administrator; @@ -23,7 +23,7 @@ contract TokenAdminRegistry_transferAdminRole is TokenAdminRegistrySetup { assertEq(config.administrator, currentAdmin); } - function test_transferAdminRole_OnlyAdministrator_Revert() public { + function test_RevertWhen_transferAdminRole_OnlyAdministrator() public { vm.stopPrank(); vm.expectRevert( diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactory.constructor.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactory.constructor.t.sol index fbba0ccbb06..5aa79d3d164 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactory.constructor.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactory.constructor.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {ITokenAdminRegistry} from "../../../interfaces/ITokenAdminRegistry.sol"; @@ -12,7 +12,7 @@ import {TokenPoolFactorySetup} from "./TokenPoolFactorySetup.t.sol"; contract TokenPoolFactory_constructor is TokenPoolFactorySetup { using Create2 for bytes32; - function test_constructor_Revert() public { + function test_RevertWhen_constructor() public { // Revert cause the tokenAdminRegistry is address(0) vm.expectRevert(TokenPoolFactory.InvalidZeroAddress.selector); new TokenPoolFactory(ITokenAdminRegistry(address(0)), RegistryModuleOwnerCustom(address(0)), address(0), address(0)); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactory.createTokenPool.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactory.createTokenPool.t.sol index 301e26173bf..260f5322659 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactory.createTokenPool.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactory.createTokenPool.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IBurnMintERC20} from "../../../../shared/token/ERC20/IBurnMintERC20.sol"; import {IOwner} from "../../../interfaces/IOwner.sol"; @@ -38,7 +38,7 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { s_sourceRouter.applyRampUpdates(new Router.OnRamp[](0), new Router.OffRamp[](0), offRampUpdates); } - function test_createTokenPool_WithNoExistingTokenOnRemoteChain_Success() public { + function test_createTokenPool_WithNoExistingTokenOnRemoteChain() public { vm.startPrank(OWNER); bytes32 dynamicSalt = keccak256(abi.encodePacked(FAKE_SALT, OWNER)); @@ -75,7 +75,7 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { assertEq(IOwner(poolAddress).owner(), OWNER, "Token should be owned by the owner"); } - function test_createTokenPool_WithNoExistingRemoteContracts_predict_Success() public { + function test_createTokenPool_WithNoExistingRemoteContracts_predict() public { vm.startPrank(OWNER); bytes32 dynamicSalt = keccak256(abi.encodePacked(FAKE_SALT, OWNER)); @@ -204,7 +204,7 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { assertEq(IOwner(poolAddress).owner(), OWNER, "Pool should be controlled by the OWNER"); } - function test_createTokenPool_ExistingRemoteToken_AndPredictPool_Success() public { + function test_createTokenPool_ExistingRemoteToken_AndPredictPool() public { vm.startPrank(OWNER); bytes32 dynamicSalt = keccak256(abi.encodePacked(FAKE_SALT, OWNER)); @@ -301,7 +301,7 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { ); } - function test_createTokenPool_WithRemoteTokenAndRemotePool_Success() public { + function test_createTokenPool_WithRemoteTokenAndRemotePool() public { vm.startPrank(OWNER); bytes memory RANDOM_TOKEN_ADDRESS = abi.encode(makeAddr("RANDOM_TOKEN")); @@ -351,7 +351,7 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { assertEq(IOwner(poolAddress).owner(), OWNER, "Token should be owned by the owner"); } - function test_createTokenPoolLockRelease_ExistingToken_predict_Success() public { + function test_createTokenPoolLockRelease_ExistingToken_predict() public { vm.startPrank(OWNER); // We have to create a new factory, registry module, and token admin registry to simulate the other chain @@ -446,7 +446,7 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { ); } - function test_createTokenPool_BurnFromMintTokenPool_Success() public { + function test_createTokenPool_BurnFromMintTokenPool() public { vm.startPrank(OWNER); bytes memory RANDOM_TOKEN_ADDRESS = abi.encode(makeAddr("RANDOM_TOKEN")); @@ -496,7 +496,7 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { assertEq(IOwner(poolAddress).owner(), OWNER, "Token should be owned by the owner"); } - function test_createTokenPool_RemoteTokenHasDifferentDecimals_Success() public { + function test_createTokenPool_RemoteTokenHasDifferentDecimals() public { vm.startPrank(OWNER); bytes32 dynamicSalt = keccak256(abi.encodePacked(FAKE_SALT, OWNER)); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactorySetup.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactorySetup.t.sol index 9f78ceb9439..ee280dbdf76 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactorySetup.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactorySetup.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {Create2} from "../../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Create2.sol"; import {BurnMintTokenPool} from "../../../pools/BurnMintTokenPool.sol"; diff --git a/contracts/src/v0.8/ccip/tokenAdminRegistry/RegistryModuleOwnerCustom.sol b/contracts/src/v0.8/ccip/tokenAdminRegistry/RegistryModuleOwnerCustom.sol index 4392fa8c56f..23014ccfc73 100644 --- a/contracts/src/v0.8/ccip/tokenAdminRegistry/RegistryModuleOwnerCustom.sol +++ b/contracts/src/v0.8/ccip/tokenAdminRegistry/RegistryModuleOwnerCustom.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IGetCCIPAdmin} from "../interfaces/IGetCCIPAdmin.sol"; diff --git a/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenAdminRegistry.sol b/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenAdminRegistry.sol index 725bde0fbdf..6aa3950ec6b 100644 --- a/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenAdminRegistry.sol +++ b/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenAdminRegistry.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IPoolV1} from "../interfaces/IPool.sol"; diff --git a/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenPoolFactory/FactoryBurnMintERC20.sol b/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenPoolFactory/FactoryBurnMintERC20.sol index 6fdba0f9b1f..97cbdb32e83 100644 --- a/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenPoolFactory/FactoryBurnMintERC20.sol +++ b/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenPoolFactory/FactoryBurnMintERC20.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IGetCCIPAdmin} from "../../../ccip/interfaces/IGetCCIPAdmin.sol"; import {IOwnable} from "../../../shared/interfaces/IOwnable.sol"; diff --git a/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactory.sol b/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactory.sol index 94beff704a4..8e036076b15 100644 --- a/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactory.sol +++ b/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactory.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; +pragma solidity ^0.8.24; import {IOwnable} from "../../../shared/interfaces/IOwnable.sol"; import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; diff --git a/contracts/src/v0.8/functions/tests/v1_X/Setup.t.sol b/contracts/src/v0.8/functions/tests/v1_X/Setup.t.sol index 444fc18fe81..f0069231e87 100644 --- a/contracts/src/v0.8/functions/tests/v1_X/Setup.t.sol +++ b/contracts/src/v0.8/functions/tests/v1_X/Setup.t.sol @@ -7,10 +7,10 @@ import {FunctionsRouterHarness, FunctionsRouter} from "./testhelpers/FunctionsRo import {FunctionsCoordinatorHarness} from "./testhelpers/FunctionsCoordinatorHarness.sol"; import {FunctionsBilling} from "../../dev/v1_X/FunctionsBilling.sol"; import {FunctionsResponse} from "../../dev/v1_X/libraries/FunctionsResponse.sol"; -import {MockV3Aggregator} from "../../../tests/MockV3Aggregator.sol"; +import {MockV3Aggregator} from "../../../shared/mocks/MockV3Aggregator.sol"; import {TermsOfServiceAllowList} from "../../dev/v1_X/accessControl/TermsOfServiceAllowList.sol"; import {TermsOfServiceAllowListConfig} from "../../dev/v1_X/accessControl/interfaces/ITermsOfServiceAllowList.sol"; -import {MockLinkToken} from "../../../mocks/MockLinkToken.sol"; +import {MockLinkToken} from "./testhelpers/MockLinkToken.sol"; import {FunctionsBillingConfig} from "../../dev/v1_X/interfaces/IFunctionsBilling.sol"; import "forge-std/Vm.sol"; diff --git a/contracts/src/v0.8/mocks/MockLinkToken.sol b/contracts/src/v0.8/functions/tests/v1_X/testhelpers/MockLinkToken.sol similarity index 94% rename from contracts/src/v0.8/mocks/MockLinkToken.sol rename to contracts/src/v0.8/functions/tests/v1_X/testhelpers/MockLinkToken.sol index a68f1b1d341..37ab5f50d56 100644 --- a/contracts/src/v0.8/mocks/MockLinkToken.sol +++ b/contracts/src/v0.8/functions/tests/v1_X/testhelpers/MockLinkToken.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {IERC677Receiver} from "../shared/interfaces/IERC677Receiver.sol"; +import {IERC677Receiver} from "../../../../shared/interfaces/IERC677Receiver.sol"; contract MockLinkToken { uint256 private constant TOTAL_SUPPLY = 1_000_000_000 * 1e18; diff --git a/contracts/src/v0.8/interfaces/FeedRegistryInterface.sol b/contracts/src/v0.8/interfaces/FeedRegistryInterface.sol deleted file mode 100644 index 6e353a79263..00000000000 --- a/contracts/src/v0.8/interfaces/FeedRegistryInterface.sol +++ /dev/null @@ -1,124 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; -pragma abicoder v2; - -import {AggregatorV2V3Interface} from "../shared/interfaces/AggregatorV2V3Interface.sol"; - -// solhint-disable-next-line interface-starts-with-i -interface FeedRegistryInterface { - struct Phase { - uint16 phaseId; - uint80 startingAggregatorRoundId; - uint80 endingAggregatorRoundId; - } - - event FeedProposed( - address indexed asset, - address indexed denomination, - address indexed proposedAggregator, - address currentAggregator, - address sender - ); - event FeedConfirmed( - address indexed asset, - address indexed denomination, - address indexed latestAggregator, - address previousAggregator, - uint16 nextPhaseId, - address sender - ); - - // V3 AggregatorV3Interface - - function decimals(address base, address quote) external view returns (uint8); - - function description(address base, address quote) external view returns (string memory); - - function version(address base, address quote) external view returns (uint256); - - function latestRoundData( - address base, - address quote - ) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); - - function getRoundData( - address base, - address quote, - uint80 _roundId - ) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); - - // V2 AggregatorInterface - - function latestAnswer(address base, address quote) external view returns (int256 answer); - - function latestTimestamp(address base, address quote) external view returns (uint256 timestamp); - - function latestRound(address base, address quote) external view returns (uint256 roundId); - - function getAnswer(address base, address quote, uint256 roundId) external view returns (int256 answer); - - function getTimestamp(address base, address quote, uint256 roundId) external view returns (uint256 timestamp); - - // Registry getters - - function getFeed(address base, address quote) external view returns (AggregatorV2V3Interface aggregator); - - function getPhaseFeed( - address base, - address quote, - uint16 phaseId - ) external view returns (AggregatorV2V3Interface aggregator); - - function isFeedEnabled(address aggregator) external view returns (bool); - - function getPhase(address base, address quote, uint16 phaseId) external view returns (Phase memory phase); - - // Round helpers - - function getRoundFeed( - address base, - address quote, - uint80 roundId - ) external view returns (AggregatorV2V3Interface aggregator); - - function getPhaseRange( - address base, - address quote, - uint16 phaseId - ) external view returns (uint80 startingRoundId, uint80 endingRoundId); - - function getPreviousRoundId( - address base, - address quote, - uint80 roundId - ) external view returns (uint80 previousRoundId); - - function getNextRoundId(address base, address quote, uint80 roundId) external view returns (uint80 nextRoundId); - - // Feed management - - function proposeFeed(address base, address quote, address aggregator) external; - - function confirmFeed(address base, address quote, address aggregator) external; - - // Proposed aggregator - - function getProposedFeed( - address base, - address quote - ) external view returns (AggregatorV2V3Interface proposedAggregator); - - function proposedGetRoundData( - address base, - address quote, - uint80 roundId - ) external view returns (uint80 id, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); - - function proposedLatestRoundData( - address base, - address quote - ) external view returns (uint80 id, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); - - // Phases - function getCurrentPhaseId(address base, address quote) external view returns (uint16 currentPhaseId); -} diff --git a/contracts/src/v0.8/interfaces/FlagsInterface.sol b/contracts/src/v0.8/interfaces/FlagsInterface.sol deleted file mode 100644 index beb2b581e3f..00000000000 --- a/contracts/src/v0.8/interfaces/FlagsInterface.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -// solhint-disable-next-line interface-starts-with-i -interface FlagsInterface { - function getFlag(address) external view returns (bool); - - function getFlags(address[] calldata) external view returns (bool[] memory); - - function raiseFlag(address) external; - - function raiseFlags(address[] calldata) external; - - function lowerFlags(address[] calldata) external; - - function setRaisingAccessController(address) external; -} diff --git a/contracts/src/v0.8/interfaces/PoRAddressList.sol b/contracts/src/v0.8/interfaces/PoRAddressList.sol deleted file mode 100644 index af06e29a456..00000000000 --- a/contracts/src/v0.8/interfaces/PoRAddressList.sol +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/** - * @title Chainlink Proof-of-Reserve address list interface. - * @notice This interface enables Chainlink nodes to get the list addresses to be used in a PoR feed. A single - * contract that implements this interface can only store an address list for a single PoR feed. - * @dev All functions in this interface are expected to be called off-chain, so gas usage is not a big concern. - * This makes it possible to store addresses in optimized data types and convert them to human-readable strings - * in `getPoRAddressList()`. - */ -// solhint-disable-next-line interface-starts-with-i -interface PoRAddressList { - /// @notice Get total number of addresses in the list. - function getPoRAddressListLength() external view returns (uint256); - - /** - * @notice Get a batch of human-readable addresses from the address list. The requested batch size can be greater - * than the actual address list size, in which the full address list will be returned. - * @dev Due to limitations of gas usage in off-chain calls, we need to support fetching the addresses in batches. - * EVM addresses need to be converted to human-readable strings. The address strings need to be in the same format - * that would be used when querying the balance of that address. - * @param startIndex The index of the first address in the batch. - * @param endIndex The index of the last address in the batch. If `endIndex > getPoRAddressListLength()-1`, - * endIndex need to default to `getPoRAddressListLength()-1`. - * @return Array of addresses as strings. - */ - function getPoRAddressList(uint256 startIndex, uint256 endIndex) external view returns (string[] memory); -} diff --git a/contracts/src/v0.8/interfaces/TypeAndVersionInterface.sol b/contracts/src/v0.8/interfaces/TypeAndVersionInterface.sol deleted file mode 100644 index 786f2750acf..00000000000 --- a/contracts/src/v0.8/interfaces/TypeAndVersionInterface.sol +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -abstract contract TypeAndVersionInterface { - function typeAndVersion() external pure virtual returns (string memory); -} diff --git a/contracts/src/v0.8/keystone/KeystoneFeedsPermissionHandler.sol b/contracts/src/v0.8/keystone/KeystoneFeedsPermissionHandler.sol index 809081b92e0..36b520bb3d1 100644 --- a/contracts/src/v0.8/keystone/KeystoneFeedsPermissionHandler.sol +++ b/contracts/src/v0.8/keystone/KeystoneFeedsPermissionHandler.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity ^0.8.19; import {Ownable2StepMsgSender} from "../shared/access/Ownable2StepMsgSender.sol"; diff --git a/contracts/src/v0.8/keystone/KeystoneForwarder.sol b/contracts/src/v0.8/keystone/KeystoneForwarder.sol index 4a8660c4c32..5807f042593 100644 --- a/contracts/src/v0.8/keystone/KeystoneForwarder.sol +++ b/contracts/src/v0.8/keystone/KeystoneForwarder.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity ^0.8.19; import {IReceiver} from "./interfaces/IReceiver.sol"; import {IRouter} from "./interfaces/IRouter.sol"; @@ -316,15 +316,15 @@ contract KeystoneForwarder is OwnerIsCreator, ITypeAndVersion, IRouter { bytes memory rawReport ) internal pure returns (bytes32 workflowExecutionId, uint64 configId, bytes2 reportId) { // (first 32 bytes of memory contain length of the report) - // version // offset 32, size 1 - // workflow_execution_id // offset 33, size 32 - // timestamp // offset 65, size 4 - // don_id // offset 69, size 4 - // don_config_version, // offset 73, size 4 - // workflow_cid // offset 77, size 32 - // workflow_name // offset 109, size 10 - // workflow_owner // offset 119, size 20 - // report_id // offset 139, size 2 + // version offset 32, size 1 + // workflow_execution_id offset 33, size 32 + // timestamp offset 65, size 4 + // don_id offset 69, size 4 + // don_config_version, offset 73, size 4 + // workflow_cid offset 77, size 32 + // workflow_name offset 109, size 10 + // workflow_owner offset 119, size 20 + // report_id offset 139, size 2 assembly { workflowExecutionId := mload(add(rawReport, 33)) // shift right by 24 bytes to get the combined don_id and don_config_version diff --git a/contracts/src/v0.8/tests/FeedConsumer.sol b/contracts/src/v0.8/l2ep/test/FeedConsumer.sol similarity index 92% rename from contracts/src/v0.8/tests/FeedConsumer.sol rename to contracts/src/v0.8/l2ep/test/FeedConsumer.sol index c9fc62357a6..f83781b5ac1 100644 --- a/contracts/src/v0.8/tests/FeedConsumer.sol +++ b/contracts/src/v0.8/l2ep/test/FeedConsumer.sol @@ -1,9 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {AggregatorV2V3Interface} from "../shared/interfaces/AggregatorV2V3Interface.sol"; +import {AggregatorV2V3Interface} from "../../shared/interfaces/AggregatorV2V3Interface.sol"; contract FeedConsumer { + // solhint-disable-next-line AggregatorV2V3Interface public immutable AGGREGATOR; constructor(address feedAddress) { diff --git a/contracts/src/v0.8/tests/Greeter.sol b/contracts/src/v0.8/l2ep/test/Greeter.sol similarity index 82% rename from contracts/src/v0.8/tests/Greeter.sol rename to contracts/src/v0.8/l2ep/test/Greeter.sol index 88ccca560de..313c7c5e3b0 100644 --- a/contracts/src/v0.8/tests/Greeter.sol +++ b/contracts/src/v0.8/l2ep/test/Greeter.sol @@ -1,7 +1,8 @@ pragma solidity ^0.8.0; -import "../shared/access/ConfirmedOwner.sol"; +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +// solhint-disable contract Greeter is ConfirmedOwner { string public greeting; diff --git a/contracts/src/v0.8/tests/MockArbitrumInbox.sol b/contracts/src/v0.8/l2ep/test/mocks/MockArbitrumInbox.sol similarity index 94% rename from contracts/src/v0.8/tests/MockArbitrumInbox.sol rename to contracts/src/v0.8/l2ep/test/mocks/MockArbitrumInbox.sol index 445a361b309..3ec76338b8c 100644 --- a/contracts/src/v0.8/tests/MockArbitrumInbox.sol +++ b/contracts/src/v0.8/l2ep/test/mocks/MockArbitrumInbox.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.9; -import {IInbox} from "../vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IInbox.sol"; -import {IBridge} from "../vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IBridge.sol"; +import {IInbox} from "../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IInbox.sol"; +import {IBridge} from "../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IBridge.sol"; contract MockArbitrumInbox is IInbox { event RetryableTicketNoRefundAliasRewriteCreated( diff --git a/contracts/src/v0.8/tests/MockOptimismL1CrossDomainMessenger.sol b/contracts/src/v0.8/l2ep/test/mocks/MockOptimismL1CrossDomainMessenger.sol similarity index 100% rename from contracts/src/v0.8/tests/MockOptimismL1CrossDomainMessenger.sol rename to contracts/src/v0.8/l2ep/test/mocks/MockOptimismL1CrossDomainMessenger.sol diff --git a/contracts/src/v0.8/tests/MockOptimismL2CrossDomainMessenger.sol b/contracts/src/v0.8/l2ep/test/mocks/MockOptimismL2CrossDomainMessenger.sol similarity index 100% rename from contracts/src/v0.8/tests/MockOptimismL2CrossDomainMessenger.sol rename to contracts/src/v0.8/l2ep/test/mocks/MockOptimismL2CrossDomainMessenger.sol diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/L2EPTest.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/L2EPTest.t.sol index 93640f4bcb4..0bd377a7cbf 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/L2EPTest.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/L2EPTest.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.24; -import {Greeter} from "../../../tests/Greeter.sol"; +import {Greeter} from "../Greeter.sol"; import {MultiSend} from "../../../vendor/MultiSend.sol"; import {Test} from "forge-std/Test.sol"; diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainForwarder.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainForwarder.t.sol index e0a76a2b37a..62f7cd5651e 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainForwarder.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainForwarder.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.24; import {ArbitrumCrossDomainForwarder} from "../../../arbitrum/ArbitrumCrossDomainForwarder.sol"; -import {Greeter} from "../../../../tests/Greeter.sol"; +import {Greeter} from "../../Greeter.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; contract ArbitrumCrossDomainForwarderTest is L2EPTest { diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainGovernor.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainGovernor.t.sol index 746da3d1cef..45f67d52ccd 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainGovernor.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainGovernor.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.24; import {ArbitrumCrossDomainGovernor} from "../../../arbitrum/ArbitrumCrossDomainGovernor.sol"; -import {Greeter} from "../../../../tests/Greeter.sol"; +import {Greeter} from "../../Greeter.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; import {MultiSend} from "../../../../vendor/MultiSend.sol"; diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumSequencerUptimeFeed.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumSequencerUptimeFeed.t.sol index deaa81977b7..1474b680ec2 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumSequencerUptimeFeed.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumSequencerUptimeFeed.t.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.24; import {SimpleWriteAccessController} from "../../../../shared/access/SimpleWriteAccessController.sol"; import {ArbitrumSequencerUptimeFeed} from "../../../arbitrum/ArbitrumSequencerUptimeFeed.sol"; import {MockAggregatorV2V3} from "../../mocks/MockAggregatorV2V3.sol"; -import {FeedConsumer} from "../../../../tests/FeedConsumer.sol"; +import {FeedConsumer} from "../../FeedConsumer.sol"; import {Flags} from "../../../Flags.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumValidator.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumValidator.t.sol index 95278e644b1..7497ae198e2 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumValidator.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumValidator.t.sol @@ -6,7 +6,7 @@ import {AccessControllerInterface} from "../../../../shared/interfaces/AccessCon import {SimpleWriteAccessController} from "../../../../shared/access/SimpleWriteAccessController.sol"; import {ArbitrumSequencerUptimeFeed} from "../../../arbitrum/ArbitrumSequencerUptimeFeed.sol"; import {ArbitrumValidator} from "../../../arbitrum/ArbitrumValidator.sol"; -import {MockArbitrumInbox} from "../../../../tests/MockArbitrumInbox.sol"; +import {MockArbitrumInbox} from "../../mocks/MockArbitrumInbox.sol"; import {MockAggregatorV2V3} from "../../mocks/MockAggregatorV2V3.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainForwarder.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainForwarder.t.sol index 28d70fa35a5..5562b413e3b 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainForwarder.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainForwarder.t.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.24; import {OptimismCrossDomainForwarder} from "../../../optimism/OptimismCrossDomainForwarder.sol"; import {MockOVMCrossDomainMessenger} from "../../mocks/optimism/MockOVMCrossDomainMessenger.sol"; -import {Greeter} from "../../../../tests/Greeter.sol"; +import {Greeter} from "../../Greeter.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; contract OptimismCrossDomainForwarderTest is L2EPTest { diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainGovernor.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainGovernor.t.sol index 57f79124512..3328a89b89d 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainGovernor.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainGovernor.t.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.24; import {OptimismCrossDomainGovernor} from "../../../optimism/OptimismCrossDomainGovernor.sol"; import {MockOVMCrossDomainMessenger} from "../../mocks/optimism/MockOVMCrossDomainMessenger.sol"; -import {Greeter} from "../../../../tests/Greeter.sol"; +import {Greeter} from "../../Greeter.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; import {MultiSend} from "../../../../vendor/MultiSend.sol"; diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismSequencerUptimeFeed.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismSequencerUptimeFeed.t.sol index 34010c313e8..393da70d79a 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismSequencerUptimeFeed.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismSequencerUptimeFeed.t.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {MockOptimismL1CrossDomainMessenger} from "../../../../tests/MockOptimismL1CrossDomainMessenger.sol"; -import {MockOptimismL2CrossDomainMessenger} from "../../../../tests/MockOptimismL2CrossDomainMessenger.sol"; +import {MockOptimismL1CrossDomainMessenger} from "../../mocks/MockOptimismL1CrossDomainMessenger.sol"; +import {MockOptimismL2CrossDomainMessenger} from "../../mocks/MockOptimismL2CrossDomainMessenger.sol"; import {OptimismSequencerUptimeFeed} from "../../../optimism/OptimismSequencerUptimeFeed.sol"; import {BaseSequencerUptimeFeed} from "../../../base/BaseSequencerUptimeFeed.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismValidator.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismValidator.t.sol index 48ff1f7778d..6fb00e708c5 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismValidator.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismValidator.t.sol @@ -3,8 +3,8 @@ pragma solidity 0.8.24; import {ISequencerUptimeFeed} from "../../../interfaces/ISequencerUptimeFeed.sol"; -import {MockOptimismL1CrossDomainMessenger} from "../../../../tests/MockOptimismL1CrossDomainMessenger.sol"; -import {MockOptimismL2CrossDomainMessenger} from "../../../../tests/MockOptimismL2CrossDomainMessenger.sol"; +import {MockOptimismL1CrossDomainMessenger} from "../../mocks/MockOptimismL1CrossDomainMessenger.sol"; +import {MockOptimismL2CrossDomainMessenger} from "../../mocks/MockOptimismL2CrossDomainMessenger.sol"; import {OptimismSequencerUptimeFeed} from "../../../optimism/OptimismSequencerUptimeFeed.sol"; import {OptimismValidator} from "../../../optimism/OptimismValidator.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainForwarder.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainForwarder.t.sol index 0025c6b9937..d28df02e975 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainForwarder.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainForwarder.t.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.24; import {MockScrollCrossDomainMessenger} from "../../mocks/scroll/MockScrollCrossDomainMessenger.sol"; import {ScrollCrossDomainForwarder} from "../../../scroll/ScrollCrossDomainForwarder.sol"; -import {Greeter} from "../../../../tests/Greeter.sol"; +import {Greeter} from "../../Greeter.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; contract ScrollCrossDomainForwarderTest is L2EPTest { diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainGovernor.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainGovernor.t.sol index a2523e5feb6..544923f49f5 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainGovernor.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainGovernor.t.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.24; import {MockScrollCrossDomainMessenger} from "../../mocks/scroll/MockScrollCrossDomainMessenger.sol"; import {ScrollCrossDomainGovernor} from "../../../scroll/ScrollCrossDomainGovernor.sol"; -import {Greeter} from "../../../../tests/Greeter.sol"; +import {Greeter} from "../../Greeter.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; import {MultiSend} from "../../../../vendor/MultiSend.sol"; diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/shared/BaseSequencerUptimeFeed.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/shared/BaseSequencerUptimeFeed.t.sol index 20553e33bab..367aa00a620 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/shared/BaseSequencerUptimeFeed.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/shared/BaseSequencerUptimeFeed.t.sol @@ -5,7 +5,7 @@ import {Vm} from "forge-std/Test.sol"; import {AddressAliasHelper} from "../../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; import {BaseSequencerUptimeFeed} from "../../../base/BaseSequencerUptimeFeed.sol"; import {MockBaseSequencerUptimeFeed} from "../../../test/mocks/MockBaseSequencerUptimeFeed.sol"; -import {FeedConsumer} from "../../../../tests/FeedConsumer.sol"; +import {FeedConsumer} from "../../FeedConsumer.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; contract BaseSequencerUptimeFeed_Setup is L2EPTest { diff --git a/contracts/src/v0.8/llo-feeds/v0.3.0/FeeManager.sol b/contracts/src/v0.8/llo-feeds/v0.3.0/FeeManager.sol index 44f550e3253..71f2f50fcb8 100644 --- a/contracts/src/v0.8/llo-feeds/v0.3.0/FeeManager.sol +++ b/contracts/src/v0.8/llo-feeds/v0.3.0/FeeManager.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.19; import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; import {IFeeManager} from "./interfaces/IFeeManager.sol"; -import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; import {Common} from "../libraries/Common.sol"; import {IRewardManager} from "./interfaces/IRewardManager.sol"; @@ -19,7 +19,7 @@ import {IVerifierFeeManager} from "./interfaces/IVerifierFeeManager.sol"; * @author Austin Born * @notice This contract is used for the handling of fees required for users verifying reports. */ -contract FeeManager is IFeeManager, ConfirmedOwner, TypeAndVersionInterface { +contract FeeManager is IFeeManager, ConfirmedOwner, ITypeAndVersion { using SafeERC20 for IERC20; /// @notice list of subscribers and their discounts subscriberDiscounts[subscriber][feedId][token] @@ -158,7 +158,7 @@ contract FeeManager is IFeeManager, ConfirmedOwner, TypeAndVersionInterface { _; } - /// @inheritdoc TypeAndVersionInterface + /// @inheritdoc ITypeAndVersion function typeAndVersion() external pure override returns (string memory) { return "FeeManager 2.0.0"; } diff --git a/contracts/src/v0.8/llo-feeds/v0.3.0/RewardManager.sol b/contracts/src/v0.8/llo-feeds/v0.3.0/RewardManager.sol index 49fef51c569..9e9a58857c7 100644 --- a/contracts/src/v0.8/llo-feeds/v0.3.0/RewardManager.sol +++ b/contracts/src/v0.8/llo-feeds/v0.3.0/RewardManager.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.19; import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; import {IRewardManager} from "./interfaces/IRewardManager.sol"; import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol"; -import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {Common} from "../libraries/Common.sol"; import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; @@ -14,7 +14,7 @@ import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/tok * @author Austin Born * @notice This contract will be used to reward any configured recipients within a pool. Recipients will receive a share of their pool relative to their configured weight. */ -contract RewardManager is IRewardManager, ConfirmedOwner, TypeAndVersionInterface { +contract RewardManager is IRewardManager, ConfirmedOwner, ITypeAndVersion { using SafeERC20 for IERC20; // @dev The mapping of total fees collected for a particular pot: s_totalRewardRecipientFees[poolId] @@ -73,7 +73,7 @@ contract RewardManager is IRewardManager, ConfirmedOwner, TypeAndVersionInterfac i_linkAddress = linkAddress; } - // @inheritdoc TypeAndVersionInterface + // @inheritdoc ITypeAndVersion function typeAndVersion() external pure override returns (string memory) { return "RewardManager 1.1.0"; } diff --git a/contracts/src/v0.8/llo-feeds/v0.3.0/Verifier.sol b/contracts/src/v0.8/llo-feeds/v0.3.0/Verifier.sol index fe5742108a5..ce4fe974bd9 100644 --- a/contracts/src/v0.8/llo-feeds/v0.3.0/Verifier.sol +++ b/contracts/src/v0.8/llo-feeds/v0.3.0/Verifier.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.19; import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; import {IVerifier} from "./interfaces/IVerifier.sol"; import {IVerifierProxy} from "./interfaces/IVerifierProxy.sol"; -import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; import {Common} from "../libraries/Common.sol"; @@ -18,7 +18,7 @@ uint256 constant MAX_NUM_ORACLES = 31; * a feed. The verifier contract is used to verify that such reports have * been signed by the correct signers. **/ -contract Verifier is IVerifier, ConfirmedOwner, TypeAndVersionInterface { +contract Verifier is IVerifier, ConfirmedOwner, ITypeAndVersion { // The first byte of the mask can be 0, because we only ever have 31 oracles uint256 internal constant ORACLE_MASK = 0x0001010101010101010101010101010101010101010101010101010101010101; @@ -193,7 +193,7 @@ contract Verifier is IVerifier, ConfirmedOwner, TypeAndVersionInterface { return interfaceId == this.verify.selector; } - /// @inheritdoc TypeAndVersionInterface + /// @inheritdoc ITypeAndVersion function typeAndVersion() external pure override returns (string memory) { return "Verifier 1.2.0"; } diff --git a/contracts/src/v0.8/llo-feeds/v0.3.0/VerifierProxy.sol b/contracts/src/v0.8/llo-feeds/v0.3.0/VerifierProxy.sol index c06312dd7be..e66b937f153 100644 --- a/contracts/src/v0.8/llo-feeds/v0.3.0/VerifierProxy.sol +++ b/contracts/src/v0.8/llo-feeds/v0.3.0/VerifierProxy.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.19; import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; import {IVerifierProxy} from "./interfaces/IVerifierProxy.sol"; import {IVerifier} from "./interfaces/IVerifier.sol"; -import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {AccessControllerInterface} from "../../shared/interfaces/AccessControllerInterface.sol"; import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; import {IVerifierFeeManager} from "./interfaces/IVerifierFeeManager.sol"; @@ -15,7 +15,7 @@ import {Common} from "../libraries/Common.sol"; * on a chain. It is responsible for taking in a verification request and routing * it to the correct verifier contract. */ -contract VerifierProxy is IVerifierProxy, ConfirmedOwner, TypeAndVersionInterface { +contract VerifierProxy is IVerifierProxy, ConfirmedOwner, ITypeAndVersion { /// @notice This event is emitted whenever a new verifier contract is set /// @param oldConfigDigest The config digest that was previously the latest config /// digest of the verifier contract at the verifier address. @@ -115,7 +115,7 @@ contract VerifierProxy is IVerifierProxy, ConfirmedOwner, TypeAndVersionInterfac _; } - /// @inheritdoc TypeAndVersionInterface + /// @inheritdoc ITypeAndVersion function typeAndVersion() external pure override returns (string memory) { return "VerifierProxy 2.0.0"; } diff --git a/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierVerifyTest.t.sol b/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierVerifyTest.t.sol index 1c14ba974c0..ab1094b3adf 100644 --- a/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierVerifyTest.t.sol +++ b/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierVerifyTest.t.sol @@ -142,7 +142,7 @@ contract VerifierVerifySingleConfigDigestTest is VerifierVerifyTest { s_verifier.verify(signedReport, msg.sender); } - function test_revertsIfMismatchedSignatureLength() public { + function test_revertsIfMismatchedSignatureLengthV03() public { bytes32[] memory rs = new bytes32[](FAULT_TOLERANCE + 1); bytes32[] memory ss = new bytes32[](FAULT_TOLERANCE + 3); bytes32 rawVs = bytes32(""); diff --git a/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationFeeManager.sol b/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationFeeManager.sol index 08ac1d45f58..eb35cdc7956 100644 --- a/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationFeeManager.sol +++ b/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationFeeManager.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.19; import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; import {Common} from "../libraries/Common.sol"; import {IWERC20} from "../../shared/interfaces/IWERC20.sol"; @@ -23,7 +23,7 @@ contract DestinationFeeManager is IDestinationFeeManager, IDestinationVerifierFeeManager, ConfirmedOwner, - TypeAndVersionInterface + ITypeAndVersion { using SafeERC20 for IERC20; @@ -164,7 +164,7 @@ contract DestinationFeeManager is _; } - /// @inheritdoc TypeAndVersionInterface + /// @inheritdoc ITypeAndVersion function typeAndVersion() external pure override returns (string memory) { return "DestinationFeeManager 0.4.0"; } diff --git a/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationRewardManager.sol b/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationRewardManager.sol index 4b4c1f50efd..9f66a423cb6 100644 --- a/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationRewardManager.sol +++ b/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationRewardManager.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.19; import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; import {IDestinationRewardManager} from "./interfaces/IDestinationRewardManager.sol"; import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol"; -import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {Common} from "../libraries/Common.sol"; import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; @@ -14,7 +14,7 @@ import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/tok * @author Austin Born * @notice This contract will be used to reward any configured recipients within a pool. Recipients will receive a share of their pool relative to their configured weight. */ -contract DestinationRewardManager is IDestinationRewardManager, ConfirmedOwner, TypeAndVersionInterface { +contract DestinationRewardManager is IDestinationRewardManager, ConfirmedOwner, ITypeAndVersion { using SafeERC20 for IERC20; // @dev The mapping of total fees collected for a particular pot: s_totalRewardRecipientFees[poolId] @@ -73,7 +73,7 @@ contract DestinationRewardManager is IDestinationRewardManager, ConfirmedOwner, i_linkAddress = linkAddress; } - // @inheritdoc TypeAndVersionInterface + // @inheritdoc ITypeAndVersion function typeAndVersion() external pure override returns (string memory) { return "DestinationRewardManager 0.4.0"; } diff --git a/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationVerifier.sol b/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationVerifier.sol index 8ab0f6acc23..545a0d60727 100644 --- a/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationVerifier.sol +++ b/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationVerifier.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.19; import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; import {IDestinationVerifier} from "./interfaces/IDestinationVerifier.sol"; -import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; import {Common} from "../libraries/Common.sol"; import {IAccessController} from "../../shared/interfaces/IAccessController.sol"; @@ -23,7 +23,7 @@ contract DestinationVerifier is IDestinationVerifier, IDestinationVerifierProxyVerifier, ConfirmedOwner, - TypeAndVersionInterface + ITypeAndVersion { /// @notice The list of DON configurations by hash(address|donConfigId) - set to true if the signer is part of the config mapping(bytes32 => bool) private s_signerByAddressAndDonConfigId; @@ -436,7 +436,7 @@ contract DestinationVerifier is interfaceId == type(IDestinationVerifierProxyVerifier).interfaceId; } - /// @inheritdoc TypeAndVersionInterface + /// @inheritdoc ITypeAndVersion function typeAndVersion() external pure override returns (string memory) { return "DestinationVerifier 0.4.0"; } diff --git a/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationVerifierProxy.sol b/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationVerifierProxy.sol index 6790883ba31..6a16dc20cb3 100644 --- a/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationVerifierProxy.sol +++ b/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationVerifierProxy.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.19; import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; import {IDestinationVerifierProxy} from "./interfaces/IDestinationVerifierProxy.sol"; import {IDestinationVerifierProxyVerifier} from "./interfaces/IDestinationVerifierProxyVerifier.sol"; @@ -12,7 +12,7 @@ import {IDestinationVerifierProxyVerifier} from "./interfaces/IDestinationVerifi * @author Michael Fletcher * @notice This contract will be used to route all requests through to the assigned verifier contract. This contract does not support individual feed configurations and is aimed at being a simple proxy for the verifier contract on any destination chain. */ -contract DestinationVerifierProxy is IDestinationVerifierProxy, ConfirmedOwner, TypeAndVersionInterface { +contract DestinationVerifierProxy is IDestinationVerifierProxy, ConfirmedOwner, ITypeAndVersion { /// @notice The active verifier for this proxy IDestinationVerifierProxyVerifier private s_verifier; @@ -24,7 +24,7 @@ contract DestinationVerifierProxy is IDestinationVerifierProxy, ConfirmedOwner, constructor() ConfirmedOwner(msg.sender) {} - /// @inheritdoc TypeAndVersionInterface + /// @inheritdoc ITypeAndVersion function typeAndVersion() external pure override returns (string memory) { return "DestinationVerifierProxy 0.4.0"; } diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/FeeManager.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/FeeManager.sol new file mode 100644 index 00000000000..30bd055c4ea --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/FeeManager.sol @@ -0,0 +1,525 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {IFeeManager} from "./interfaces/IFeeManager.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {Common} from "../libraries/Common.sol"; +import {IRewardManager} from "./interfaces/IRewardManager.sol"; +import {IWERC20} from "../../shared/interfaces/IWERC20.sol"; +import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol"; +import {Math} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/Math.sol"; +import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; +import {IVerifierFeeManager} from "./interfaces/IVerifierFeeManager.sol"; + +/** + * @title FeeManager + * @author Michael Fletcher + * @author Austin Born + * @notice This contract is used for the handling of fees required for users verifying reports. + */ +contract FeeManager is IFeeManager, ConfirmedOwner, ITypeAndVersion { + using SafeERC20 for IERC20; + + /// @notice list of subscribers and their discounts subscriberDiscounts[subscriber][feedId][token] + mapping(address => mapping(bytes32 => mapping(address => uint256))) public s_subscriberDiscounts; + + /// @notice map of global discounts + mapping(address => mapping(address => uint256)) public s_globalDiscounts; + + /// @notice keep track of any subsidised link that is owed to the reward manager. + mapping(bytes32 => uint256) public s_linkDeficit; + + /// @notice the total discount that can be applied to a fee, 1e18 = 100% discount + uint64 private constant PERCENTAGE_SCALAR = 1e18; + + /// @notice the LINK token address + address public immutable i_linkAddress; + + /// @notice the native token address + address public immutable i_nativeAddress; + + /// @notice the proxy address + address public immutable i_proxyAddress; + + /// @notice the reward manager address + IRewardManager public immutable i_rewardManager; + + // @notice the mask to apply to get the report version + bytes32 private constant REPORT_VERSION_MASK = 0xffff000000000000000000000000000000000000000000000000000000000000; + + // @notice the different report versions + bytes32 private constant REPORT_V1 = 0x0001000000000000000000000000000000000000000000000000000000000000; + + /// @notice the surcharge fee to be paid if paying in native + uint256 public s_nativeSurcharge; + + /// @notice the error thrown if the discount or surcharge is invalid + error InvalidSurcharge(); + + /// @notice the error thrown if the discount is invalid + error InvalidDiscount(); + + /// @notice the error thrown if the address is invalid + error InvalidAddress(); + + /// @notice thrown if msg.value is supplied with a bad quote + error InvalidDeposit(); + + /// @notice thrown if a report has expired + error ExpiredReport(); + + /// @notice thrown if a report has no quote + error InvalidQuote(); + + // @notice thrown when the caller is not authorized + error Unauthorized(); + + // @notice thrown when trying to clear a zero deficit + error ZeroDeficit(); + + /// @notice thrown when trying to pay an address that cannot except funds + error InvalidReceivingAddress(); + + /// @notice Emitted whenever a subscriber's discount is updated + /// @param subscriber address of the subscriber to update discounts for + /// @param feedId Feed ID for the discount + /// @param token Token address for the discount + /// @param discount Discount to apply, in relation to the PERCENTAGE_SCALAR + event SubscriberDiscountUpdated(address indexed subscriber, bytes32 indexed feedId, address token, uint64 discount); + + /// @notice Emitted when updating the native surcharge + /// @param newSurcharge Surcharge amount to apply relative to PERCENTAGE_SCALAR + event NativeSurchargeUpdated(uint64 newSurcharge); + + /// @notice Emits when this contract does not have enough LINK to send to the reward manager when paying in native + /// @param rewards Config digest and link fees which could not be subsidised + event InsufficientLink(IRewardManager.FeePayment[] rewards); + + /// @notice Emitted when funds are withdrawn + /// @param adminAddress Address of the admin + /// @param recipient Address of the recipient + /// @param assetAddress Address of the asset withdrawn + /// @param quantity Amount of the asset withdrawn + event Withdraw(address adminAddress, address recipient, address assetAddress, uint192 quantity); + + /// @notice Emits when a deficit has been cleared for a particular config digest + /// @param configDigest Config digest of the deficit cleared + /// @param linkQuantity Amount of LINK required to pay the deficit + event LinkDeficitCleared(bytes32 indexed configDigest, uint256 linkQuantity); + + /// @notice Emits when a fee has been processed + /// @param configDigest Config digest of the fee processed + /// @param subscriber Address of the subscriber who paid the fee + /// @param fee Fee paid + /// @param reward Reward paid + /// @param appliedDiscount Discount applied to the fee + event DiscountApplied( + bytes32 indexed configDigest, + address indexed subscriber, + Common.Asset fee, + Common.Asset reward, + uint256 appliedDiscount + ); + + /** + * @notice Construct the FeeManager contract + * @param _linkAddress The address of the LINK token + * @param _nativeAddress The address of the wrapped ERC-20 version of the native token (represents fee in native or wrapped) + * @param _proxyAddress The address of the proxy contract + * @param _rewardManagerAddress The address of the reward manager contract + */ + constructor( + address _linkAddress, + address _nativeAddress, + address _proxyAddress, + address _rewardManagerAddress + ) ConfirmedOwner(msg.sender) { + if ( + _linkAddress == address(0) || + _nativeAddress == address(0) || + _proxyAddress == address(0) || + _rewardManagerAddress == address(0) + ) revert InvalidAddress(); + + i_linkAddress = _linkAddress; + i_nativeAddress = _nativeAddress; + i_proxyAddress = _proxyAddress; + i_rewardManager = IRewardManager(_rewardManagerAddress); + + IERC20(i_linkAddress).approve(address(i_rewardManager), type(uint256).max); + } + + modifier onlyOwnerOrProxy() { + if (msg.sender != i_proxyAddress && msg.sender != owner()) revert Unauthorized(); + _; + } + + modifier onlyProxy() { + if (msg.sender != i_proxyAddress) revert Unauthorized(); + _; + } + + /// @inheritdoc ITypeAndVersion + function typeAndVersion() external pure override returns (string memory) { + return "FeeManager 2.1.0"; + } + + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) external pure override returns (bool) { + return interfaceId == this.processFee.selector || interfaceId == this.processFeeBulk.selector; + } + + /// @inheritdoc IVerifierFeeManager + function processFee( + bytes calldata payload, + bytes calldata parameterPayload, + address subscriber + ) external payable override onlyProxy { + (Common.Asset memory fee, Common.Asset memory reward, uint256 appliedDiscount) = _processFee( + payload, + parameterPayload, + subscriber + ); + + if (fee.amount == 0) { + _transfer(subscriber, msg.value); + return; + } + + IFeeManager.FeeAndReward[] memory feeAndReward = new IFeeManager.FeeAndReward[](1); + feeAndReward[0] = IFeeManager.FeeAndReward(bytes32(payload), fee, reward, appliedDiscount); + + if (fee.assetAddress == i_linkAddress) { + _handleFeesAndRewards(subscriber, feeAndReward, 1, 0); + } else { + _handleFeesAndRewards(subscriber, feeAndReward, 0, 1); + } + } + + /// @inheritdoc IVerifierFeeManager + function processFeeBulk( + bytes[] calldata payloads, + bytes calldata parameterPayload, + address subscriber + ) external payable override onlyProxy { + FeeAndReward[] memory feesAndRewards = new IFeeManager.FeeAndReward[](payloads.length); + + //keep track of the number of fees to prevent over initialising the FeePayment array within _convertToLinkAndNativeFees + uint256 numberOfLinkFees; + uint256 numberOfNativeFees; + + uint256 feesAndRewardsIndex; + for (uint256 i; i < payloads.length; ++i) { + (Common.Asset memory fee, Common.Asset memory reward, uint256 appliedDiscount) = _processFee( + payloads[i], + parameterPayload, + subscriber + ); + + if (fee.amount != 0) { + feesAndRewards[feesAndRewardsIndex++] = IFeeManager.FeeAndReward( + bytes32(payloads[i]), + fee, + reward, + appliedDiscount + ); + + unchecked { + //keep track of some tallys to make downstream calculations more efficient + if (fee.assetAddress == i_linkAddress) { + ++numberOfLinkFees; + } else { + ++numberOfNativeFees; + } + } + } + } + + if (numberOfLinkFees != 0 || numberOfNativeFees != 0) { + _handleFeesAndRewards(subscriber, feesAndRewards, numberOfLinkFees, numberOfNativeFees); + } else { + _transfer(subscriber, msg.value); + } + } + + /// @inheritdoc IFeeManager + function getFeeAndReward( + address subscriber, + bytes memory report, + address quoteAddress + ) public view returns (Common.Asset memory, Common.Asset memory, uint256) { + Common.Asset memory fee; + Common.Asset memory reward; + + //get the feedId from the report + bytes32 feedId = bytes32(report); + + //the report needs to be a support version + bytes32 reportVersion = _getReportVersion(feedId); + + //version 1 of the reports don't require quotes, so the fee will be 0 + if (reportVersion == REPORT_V1) { + fee.assetAddress = i_nativeAddress; + reward.assetAddress = i_linkAddress; + return (fee, reward, 0); + } + + //verify the quote payload is a supported token + if (quoteAddress != i_nativeAddress && quoteAddress != i_linkAddress) { + revert InvalidQuote(); + } + + //decode the report depending on the version + uint256 linkQuantity; + uint256 nativeQuantity; + uint256 expiresAt; + (, , , nativeQuantity, linkQuantity, expiresAt) = abi.decode( + report, + (bytes32, uint32, uint32, uint192, uint192, uint32) + ); + + //read the timestamp bytes from the report data and verify it has not expired + if (expiresAt < block.timestamp) { + revert ExpiredReport(); + } + + //get the discount being applied + uint256 discount = s_subscriberDiscounts[subscriber][feedId][quoteAddress]; + + if (discount == 0) { + //check if a global discount has been applied + discount = s_globalDiscounts[subscriber][quoteAddress]; + } + + //the reward is always set in LINK + reward.assetAddress = i_linkAddress; + reward.amount = Math.ceilDiv(linkQuantity * (PERCENTAGE_SCALAR - discount), PERCENTAGE_SCALAR); + + //calculate either the LINK fee or native fee if it's within the report + if (quoteAddress == i_linkAddress) { + fee.assetAddress = i_linkAddress; + fee.amount = reward.amount; + } else { + uint256 surchargedFee = Math.ceilDiv(nativeQuantity * (PERCENTAGE_SCALAR + s_nativeSurcharge), PERCENTAGE_SCALAR); + + fee.assetAddress = i_nativeAddress; + fee.amount = Math.ceilDiv(surchargedFee * (PERCENTAGE_SCALAR - discount), PERCENTAGE_SCALAR); + } + + //return the fee + return (fee, reward, discount); + } + + /// @inheritdoc IVerifierFeeManager + function setFeeRecipients( + bytes32 configDigest, + Common.AddressAndWeight[] calldata rewardRecipientAndWeights + ) external onlyOwnerOrProxy { + i_rewardManager.setRewardRecipients(configDigest, rewardRecipientAndWeights); + } + + /// @inheritdoc IFeeManager + function setNativeSurcharge(uint64 surcharge) external onlyOwner { + if (surcharge > PERCENTAGE_SCALAR) revert InvalidSurcharge(); + + s_nativeSurcharge = surcharge; + + emit NativeSurchargeUpdated(surcharge); + } + + /// @inheritdoc IFeeManager + function updateSubscriberDiscount( + address subscriber, + bytes32 feedId, + address token, + uint64 discount + ) external onlyOwner { + //make sure the discount is not greater than the total discount that can be applied + if (discount > PERCENTAGE_SCALAR) revert InvalidDiscount(); + //make sure the token is either LINK or native + if (token != i_linkAddress && token != i_nativeAddress) revert InvalidAddress(); + + s_subscriberDiscounts[subscriber][feedId][token] = discount; + + emit SubscriberDiscountUpdated(subscriber, feedId, token, discount); + } + + function updateSubscriberGlobalDiscount(address subscriber, address token, uint64 discount) external onlyOwner { + //make sure the discount is not greater than the total discount that can be applied + if (discount > PERCENTAGE_SCALAR) revert InvalidDiscount(); + //make sure the token is either LINK or native + if (token != i_linkAddress && token != i_nativeAddress) revert InvalidAddress(); + + s_globalDiscounts[subscriber][token] = discount; + + emit SubscriberDiscountUpdated(subscriber, bytes32(0), token, discount); + } + + /// @inheritdoc IFeeManager + function withdraw(address assetAddress, address recipient, uint192 quantity) external onlyOwner { + //address 0 is used to withdraw native in the context of withdrawing + if (assetAddress == address(0)) { + _transfer(recipient, quantity); + return; + } + + //withdraw the requested asset + IERC20(assetAddress).safeTransfer(recipient, quantity); + + //emit event when funds are withdrawn + emit Withdraw(msg.sender, recipient, assetAddress, uint192(quantity)); + } + + /// @inheritdoc IFeeManager + function linkAvailableForPayment() external view returns (uint256) { + //return the amount of LINK this contact has available to pay rewards + return IERC20(i_linkAddress).balanceOf(address(this)); + } + + /** + * @notice Gets the current version of the report that is encoded as the last two bytes of the feed + * @param feedId feed id to get the report version for + */ + function _getReportVersion(bytes32 feedId) internal pure returns (bytes32) { + return REPORT_VERSION_MASK & feedId; + } + + function _processFee( + bytes calldata payload, + bytes calldata parameterPayload, + address subscriber + ) internal view returns (Common.Asset memory, Common.Asset memory, uint256) { + if (subscriber == address(this)) revert InvalidAddress(); + + //decode the report from the payload + (, bytes memory report) = abi.decode(payload, (bytes32[3], bytes)); + + //get the feedId from the report + bytes32 feedId = bytes32(report); + + //v1 doesn't need a quote payload, so skip the decoding + address quote; + if (_getReportVersion(feedId) != REPORT_V1) { + //decode the quote from the bytes + (quote) = abi.decode(parameterPayload, (address)); + } + + //decode the fee, it will always be native or LINK + return getFeeAndReward(subscriber, report, quote); + } + + function _handleFeesAndRewards( + address subscriber, + FeeAndReward[] memory feesAndRewards, + uint256 numberOfLinkFees, + uint256 numberOfNativeFees + ) internal { + IRewardManager.FeePayment[] memory linkRewards = new IRewardManager.FeePayment[](numberOfLinkFees); + IRewardManager.FeePayment[] memory nativeFeeLinkRewards = new IRewardManager.FeePayment[](numberOfNativeFees); + + uint256 totalNativeFee; + uint256 totalNativeFeeLinkValue; + + uint256 linkRewardsIndex; + uint256 nativeFeeLinkRewardsIndex; + + uint256 totalNumberOfFees = numberOfLinkFees + numberOfNativeFees; + for (uint256 i; i < totalNumberOfFees; ++i) { + if (feesAndRewards[i].fee.assetAddress == i_linkAddress) { + linkRewards[linkRewardsIndex++] = IRewardManager.FeePayment( + feesAndRewards[i].configDigest, + uint192(feesAndRewards[i].reward.amount) + ); + } else { + nativeFeeLinkRewards[nativeFeeLinkRewardsIndex++] = IRewardManager.FeePayment( + feesAndRewards[i].configDigest, + uint192(feesAndRewards[i].reward.amount) + ); + totalNativeFee += feesAndRewards[i].fee.amount; + totalNativeFeeLinkValue += feesAndRewards[i].reward.amount; + } + + if (feesAndRewards[i].appliedDiscount != 0) { + emit DiscountApplied( + feesAndRewards[i].configDigest, + subscriber, + feesAndRewards[i].fee, + feesAndRewards[i].reward, + feesAndRewards[i].appliedDiscount + ); + } + } + + //keep track of change in case of any over payment + uint256 change; + + if (msg.value != 0) { + //there must be enough to cover the fee + if (totalNativeFee > msg.value) revert InvalidDeposit(); + + //wrap the amount required to pay the fee & approve as the subscriber paid in wrapped native + IWERC20(i_nativeAddress).deposit{value: totalNativeFee}(); + + unchecked { + //msg.value is always >= to fee.amount + change = msg.value - totalNativeFee; + } + } else { + if (totalNativeFee != 0) { + //subscriber has paid in wrapped native, so transfer the native to this contract + IERC20(i_nativeAddress).safeTransferFrom(subscriber, address(this), totalNativeFee); + } + } + + if (linkRewards.length != 0) { + i_rewardManager.onFeePaid(linkRewards, subscriber); + } + + if (nativeFeeLinkRewards.length != 0) { + //distribute subsidised fees paid in Native + if (totalNativeFeeLinkValue > IERC20(i_linkAddress).balanceOf(address(this))) { + // If not enough LINK on this contract to forward for rewards, tally the deficit to be paid by out-of-band LINK + for (uint256 i; i < nativeFeeLinkRewards.length; ++i) { + unchecked { + //we have previously tallied the fees, any overflows would have already reverted + s_linkDeficit[nativeFeeLinkRewards[i].poolId] += nativeFeeLinkRewards[i].amount; + } + } + + emit InsufficientLink(nativeFeeLinkRewards); + } else { + //distribute the fees + i_rewardManager.onFeePaid(nativeFeeLinkRewards, address(this)); + } + } + + // a refund may be needed if the payee has paid in excess of the fee + _transfer(subscriber, change); + } + + function _transfer(address to, uint256 quantity) internal { + if (quantity != 0) { + (bool success, ) = payable(to).call{value: quantity}(""); + if (!success) revert InvalidReceivingAddress(); + } + } + + /// @inheritdoc IFeeManager + function payLinkDeficit(bytes32 configDigest) external onlyOwner { + uint256 deficit = s_linkDeficit[configDigest]; + + if (deficit == 0) revert ZeroDeficit(); + + delete s_linkDeficit[configDigest]; + + IRewardManager.FeePayment[] memory deficitFeePayment = new IRewardManager.FeePayment[](1); + + deficitFeePayment[0] = IRewardManager.FeePayment(configDigest, uint192(deficit)); + + i_rewardManager.onFeePaid(deficitFeePayment, address(this)); + + emit LinkDeficitCleared(configDigest, deficit); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/RewardManager.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/RewardManager.sol new file mode 100644 index 00000000000..9e9a58857c7 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/RewardManager.sol @@ -0,0 +1,321 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {IRewardManager} from "./interfaces/IRewardManager.sol"; +import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {Common} from "../libraries/Common.sol"; +import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; + +/** + * @title RewardManager + * @author Michael Fletcher + * @author Austin Born + * @notice This contract will be used to reward any configured recipients within a pool. Recipients will receive a share of their pool relative to their configured weight. + */ +contract RewardManager is IRewardManager, ConfirmedOwner, ITypeAndVersion { + using SafeERC20 for IERC20; + + // @dev The mapping of total fees collected for a particular pot: s_totalRewardRecipientFees[poolId] + mapping(bytes32 => uint256) public s_totalRewardRecipientFees; + + // @dev The mapping of fee balances for each pot last time the recipient claimed: s_totalRewardRecipientFeesLastClaimedAmounts[poolId][recipient] + mapping(bytes32 => mapping(address => uint256)) public s_totalRewardRecipientFeesLastClaimedAmounts; + + // @dev The mapping of RewardRecipient weights for a particular poolId: s_rewardRecipientWeights[poolId][rewardRecipient]. + mapping(bytes32 => mapping(address => uint256)) public s_rewardRecipientWeights; + + // @dev Keep track of the reward recipient weights that have been set to prevent duplicates + mapping(bytes32 => bool) public s_rewardRecipientWeightsSet; + + // @dev Store a list of pool ids that have been registered, to make off chain lookups easier + bytes32[] public s_registeredPoolIds; + + // @dev The address for the LINK contract + address public immutable i_linkAddress; + + // The total weight of all RewardRecipients. 1e18 = 100% of the pool fees + uint64 private constant PERCENTAGE_SCALAR = 1e18; + + // The fee manager address + address public s_feeManagerAddress; + + // @notice Thrown whenever the RewardRecipient weights are invalid + error InvalidWeights(); + + // @notice Thrown when any given address is invalid + error InvalidAddress(); + + // @notice Thrown when the pool id is invalid + error InvalidPoolId(); + + // @notice Thrown when the calling contract is not within the authorized contracts + error Unauthorized(); + + // @notice Thrown when getAvailableRewardPoolIds parameters are incorrectly set + error InvalidPoolLength(); + + // Events emitted upon state change + event RewardRecipientsUpdated(bytes32 indexed poolId, Common.AddressAndWeight[] newRewardRecipients); + event RewardsClaimed(bytes32 indexed poolId, address indexed recipient, uint192 quantity); + event FeeManagerUpdated(address newFeeManagerAddress); + event FeePaid(FeePayment[] payments, address payer); + + /** + * @notice Constructor + * @param linkAddress address of the wrapped LINK token + */ + constructor(address linkAddress) ConfirmedOwner(msg.sender) { + //ensure that the address ia not zero + if (linkAddress == address(0)) revert InvalidAddress(); + + i_linkAddress = linkAddress; + } + + // @inheritdoc ITypeAndVersion + function typeAndVersion() external pure override returns (string memory) { + return "RewardManager 1.1.0"; + } + + // @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) external pure override returns (bool) { + return interfaceId == this.onFeePaid.selector; + } + + modifier onlyOwnerOrFeeManager() { + if (msg.sender != owner() && msg.sender != s_feeManagerAddress) revert Unauthorized(); + _; + } + + modifier onlyOwnerOrRecipientInPool(bytes32 poolId) { + if (msg.sender != owner() && s_rewardRecipientWeights[poolId][msg.sender] == 0) revert Unauthorized(); + _; + } + + modifier onlyFeeManager() { + if (msg.sender != s_feeManagerAddress) revert Unauthorized(); + _; + } + + /// @inheritdoc IRewardManager + function onFeePaid(FeePayment[] calldata payments, address payer) external override onlyFeeManager { + uint256 totalFeeAmount; + for (uint256 i; i < payments.length; ++i) { + unchecked { + //the total amount for any ERC-20 asset cannot exceed 2^256 - 1 + //see https://github.com/OpenZeppelin/openzeppelin-contracts/blob/36bf1e46fa811f0f07d38eb9cfbc69a955f300ce/contracts/token/ERC20/ERC20.sol#L266 + //for example implementation. + s_totalRewardRecipientFees[payments[i].poolId] += payments[i].amount; + + //tally the total payable fees + totalFeeAmount += payments[i].amount; + } + } + + //transfer the fees to this contract + IERC20(i_linkAddress).safeTransferFrom(payer, address(this), totalFeeAmount); + + emit FeePaid(payments, payer); + } + + /// @inheritdoc IRewardManager + function claimRewards(bytes32[] memory poolIds) external override { + _claimRewards(msg.sender, poolIds); + } + + // wrapper impl for claimRewards + function _claimRewards(address recipient, bytes32[] memory poolIds) internal returns (uint256) { + //get the total amount claimable for this recipient + uint256 claimAmount; + + //loop and claim all the rewards in the poolId pot + for (uint256 i; i < poolIds.length; ++i) { + //get the poolId to be claimed + bytes32 poolId = poolIds[i]; + + //get the total fees for the pot + uint256 totalFeesInPot = s_totalRewardRecipientFees[poolId]; + + unchecked { + //avoid unnecessary storage reads if there's no fees in the pot + if (totalFeesInPot == 0) continue; + + //get the claimable amount for this recipient, this calculation will never exceed the amount in the pot + uint256 claimableAmount = totalFeesInPot - s_totalRewardRecipientFeesLastClaimedAmounts[poolId][recipient]; + + //calculate the recipients share of the fees, which is their weighted share of the difference between the last amount they claimed and the current amount in the pot. This can never be more than the total amount in existence + uint256 recipientShare = (claimableAmount * s_rewardRecipientWeights[poolId][recipient]) / PERCENTAGE_SCALAR; + + //if there's no fees to claim, continue as there's nothing to update + if (recipientShare == 0) continue; + + //keep track of the total amount claimable, this can never be more than the total amount in existence + claimAmount += recipientShare; + + //set the current total amount of fees in the pot as it's used to calculate future claims + s_totalRewardRecipientFeesLastClaimedAmounts[poolId][recipient] = totalFeesInPot; + + //emit event if the recipient has rewards to claim + emit RewardsClaimed(poolIds[i], recipient, uint192(recipientShare)); + } + } + + //check if there's any rewards to claim in the given poolId + if (claimAmount != 0) { + //transfer the reward to the recipient + IERC20(i_linkAddress).safeTransfer(recipient, claimAmount); + } + + return claimAmount; + } + + /// @inheritdoc IRewardManager + function setRewardRecipients( + bytes32 poolId, + Common.AddressAndWeight[] calldata rewardRecipientAndWeights + ) external override onlyOwnerOrFeeManager { + //revert if there are no recipients to set + if (rewardRecipientAndWeights.length == 0) revert InvalidAddress(); + + //check that the weights have not been previously set + if (s_rewardRecipientWeightsSet[poolId]) revert InvalidPoolId(); + + //keep track of the registered poolIds to make off chain lookups easier + s_registeredPoolIds.push(poolId); + + //keep track of which pools have had their reward recipients set + s_rewardRecipientWeightsSet[poolId] = true; + + //set the reward recipients, this will only be called once and contain the full set of RewardRecipients with a total weight of 100% + _setRewardRecipientWeights(poolId, rewardRecipientAndWeights, PERCENTAGE_SCALAR); + + emit RewardRecipientsUpdated(poolId, rewardRecipientAndWeights); + } + + function _setRewardRecipientWeights( + bytes32 poolId, + Common.AddressAndWeight[] calldata rewardRecipientAndWeights, + uint256 expectedWeight + ) internal { + //we can't update the weights if it contains duplicates + if (Common._hasDuplicateAddresses(rewardRecipientAndWeights)) revert InvalidAddress(); + + //loop all the reward recipients and validate the weight and address + uint256 totalWeight; + for (uint256 i; i < rewardRecipientAndWeights.length; ++i) { + //get the weight + uint256 recipientWeight = rewardRecipientAndWeights[i].weight; + //get the address + address recipientAddress = rewardRecipientAndWeights[i].addr; + + //ensure the reward recipient address is not zero + if (recipientAddress == address(0)) revert InvalidAddress(); + + //save/overwrite the weight for the reward recipient + s_rewardRecipientWeights[poolId][recipientAddress] = recipientWeight; + + unchecked { + //keep track of the cumulative weight, this cannot overflow as the total weight is restricted at 1e18 + totalWeight += recipientWeight; + } + } + + //if total weight is not met, the fees will either be under or over distributed + if (totalWeight != expectedWeight) revert InvalidWeights(); + } + + /// @inheritdoc IRewardManager + function updateRewardRecipients( + bytes32 poolId, + Common.AddressAndWeight[] calldata newRewardRecipients + ) external override onlyOwner { + //create an array of poolIds to pass to _claimRewards if required + bytes32[] memory poolIds = new bytes32[](1); + poolIds[0] = poolId; + + //loop all the reward recipients and claim their rewards before updating their weights + uint256 existingTotalWeight; + for (uint256 i; i < newRewardRecipients.length; ++i) { + //get the address + address recipientAddress = newRewardRecipients[i].addr; + //get the existing weight + uint256 existingWeight = s_rewardRecipientWeights[poolId][recipientAddress]; + + //if a recipient is updated, the rewards must be claimed first as they can't claim previous fees at the new weight + _claimRewards(newRewardRecipients[i].addr, poolIds); + + unchecked { + //keep tally of the weights so that the expected collective weight is known + existingTotalWeight += existingWeight; + } + } + + //update the reward recipients, if the new collective weight isn't equal to the previous collective weight, the fees will either be under or over distributed + _setRewardRecipientWeights(poolId, newRewardRecipients, existingTotalWeight); + + //emit event + emit RewardRecipientsUpdated(poolId, newRewardRecipients); + } + + /// @inheritdoc IRewardManager + function payRecipients(bytes32 poolId, address[] calldata recipients) external onlyOwnerOrRecipientInPool(poolId) { + //convert poolIds to an array to match the interface of _claimRewards + bytes32[] memory poolIdsArray = new bytes32[](1); + poolIdsArray[0] = poolId; + + //loop each recipient and claim the rewards for each of the pools and assets + for (uint256 i; i < recipients.length; ++i) { + _claimRewards(recipients[i], poolIdsArray); + } + } + + /// @inheritdoc IRewardManager + function setFeeManager(address newFeeManagerAddress) external onlyOwner { + if (newFeeManagerAddress == address(0)) revert InvalidAddress(); + + s_feeManagerAddress = newFeeManagerAddress; + + emit FeeManagerUpdated(newFeeManagerAddress); + } + + /// @inheritdoc IRewardManager + function getAvailableRewardPoolIds( + address recipient, + uint256 startIndex, + uint256 endIndex + ) external view returns (bytes32[] memory) { + //get the length of the pool ids which we will loop through and potentially return + uint256 registeredPoolIdsLength = s_registeredPoolIds.length; + + uint256 lastIndex = endIndex > registeredPoolIdsLength ? registeredPoolIdsLength : endIndex; + + if (startIndex > lastIndex) revert InvalidPoolLength(); + + //create a new array with the maximum amount of potential pool ids + bytes32[] memory claimablePoolIds = new bytes32[](lastIndex - startIndex); + //we want the pools which a recipient has funds for to be sequential, so we need to keep track of the index + uint256 poolIdArrayIndex; + + //loop all the pool ids, and check if the recipient has a registered weight and a claimable amount + for (uint256 i = startIndex; i < lastIndex; ++i) { + //get the poolId + bytes32 poolId = s_registeredPoolIds[i]; + + //if the recipient has a weight, they are a recipient of this poolId + if (s_rewardRecipientWeights[poolId][recipient] != 0) { + //get the total in this pool + uint256 totalPoolAmount = s_totalRewardRecipientFees[poolId]; + //if the recipient has any LINK, then add the poolId to the array + unchecked { + //s_totalRewardRecipientFeesLastClaimedAmounts can never exceed total pool amount, and the number of pools can't exceed the max array length + if (totalPoolAmount - s_totalRewardRecipientFeesLastClaimedAmounts[poolId][recipient] != 0) { + claimablePoolIds[poolIdArrayIndex++] = poolId; + } + } + } + } + + return claimablePoolIds; + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/Verifier.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/Verifier.sol new file mode 100644 index 00000000000..d6b975166f4 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/Verifier.sol @@ -0,0 +1,346 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {IVerifier} from "./interfaces/IVerifier.sol"; +import {IVerifierProxy} from "./interfaces/IVerifierProxy.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {Common} from "../libraries/Common.sol"; + +// OCR2 standard +uint256 constant MAX_NUM_ORACLES = 31; + +/* + * The verifier contract is used to verify offchain reports signed + * by DONs. A report consists of a price, block number and feed Id. It + * represents the observed price of an asset at a specified block number for + * a feed. The verifier contract is used to verify that such reports have + * been signed by the correct signers. + **/ +contract Verifier is IVerifier, ConfirmedOwner, ITypeAndVersion { + // The first byte of the mask can be 0, because we only ever have 31 oracles + uint256 internal constant ORACLE_MASK = 0x0001010101010101010101010101010101010101010101010101010101010101; + + enum Role { + // Default role for an oracle address. This means that the oracle address + // is not a signer + Unset, + // Role given to an oracle address that is allowed to sign a report + Signer + } + + struct Signer { + // Index of oracle in a configuration + uint8 index; + // The oracle's role + Role role; + } + + struct VerifierState { + // The block number of the block the last time the configuration was updated. + uint32 latestConfigBlockNumber; + // Whether the config is deactivated + bool isActive; + // Fault tolerance + uint8 f; + // Number of signers + uint8 oracleCount; + // Map of signer addresses to oracles + mapping(address => Signer) oracles; + } + + /// @notice This event is emitted when a new report is verified. + /// It is used to keep a historical record of verified reports. + event ReportVerified(bytes32 indexed feedId, address requester); + + /// @notice This event is emitted whenever a new DON configuration is set. + event ConfigSet(bytes32 indexed configDigest, address[] signers, uint8 f); + + /// @notice This event is + event ConfigUpdated(bytes32 indexed configDigest, address[] prevSigners, address[] newSigners); + + /// @notice This event is emitted whenever a configuration is deactivated + event ConfigDeactivated(bytes32 indexed configDigest); + + /// @notice This event is emitted whenever a configuration is activated + event ConfigActivated(bytes32 indexed configDigest); + + /// @notice This error is thrown whenever an address tries + /// to exeecute a transaction that it is not authorized to do so + error AccessForbidden(); + + /// @notice This error is thrown whenever a zero address is passed + error ZeroAddress(); + + /// @notice This error is thrown whenever the config digest + /// is empty + error DigestEmpty(); + + /// @notice This error is thrown whenever the config digest + /// passed in has not been set in this verifier + /// @param configDigest The config digest that has not been set + error DigestNotSet(bytes32 configDigest); + + /// @notice This error is thrown whenever the config digest + /// has been deactivated + /// @param configDigest The config digest that is inactive + error DigestInactive(bytes32 configDigest); + + /// @notice This error is thrown whenever trying to set a config + /// with a fault tolerance of 0 + error FaultToleranceMustBePositive(); + + /// @notice This error is thrown whenever a report is signed + /// with more than the max number of signers + /// @param numSigners The number of signers who have signed the report + /// @param maxSigners The maximum number of signers that can sign a report + error ExcessSigners(uint256 numSigners, uint256 maxSigners); + + /// @notice This error is thrown whenever a report is signed + /// with less than the minimum number of signers + /// @param numSigners The number of signers who have signed the report + /// @param minSigners The minimum number of signers that need to sign a report + error InsufficientSigners(uint256 numSigners, uint256 minSigners); + + /// @notice This error is thrown whenever a report is signed + /// with an incorrect number of signers + /// @param numSigners The number of signers who have signed the report + /// @param expectedNumSigners The expected number of signers that need to sign + /// a report + error IncorrectSignatureCount(uint256 numSigners, uint256 expectedNumSigners); + + /// @notice This error is thrown whenever the R and S signer components + /// have different lengths + /// @param rsLength The number of r signature components + /// @param ssLength The number of s signature components + error MismatchedSignatures(uint256 rsLength, uint256 ssLength); + + /// @notice This error is thrown whenever setting a config with duplicate signatures + error NonUniqueSignatures(); + + /// @notice This error is thrown whenever a report fails to verify due to bad or duplicate signatures + error BadVerification(); + + /// @notice This error is thrown whenever a config digest is already set when setting the configuration + error ConfigDigestAlreadySet(); + + /// @notice The address of the verifier proxy + address private immutable i_verifierProxyAddr; + + /// @notice Verifier states keyed on config digest + mapping(bytes32 => VerifierState) internal s_verifierStates; + + /// @param verifierProxyAddr The address of the VerifierProxy contract + constructor(address verifierProxyAddr) ConfirmedOwner(msg.sender) { + if (verifierProxyAddr == address(0)) revert ZeroAddress(); + i_verifierProxyAddr = verifierProxyAddr; + } + + modifier checkConfigValid(uint256 numSigners, uint256 f) { + if (f == 0) revert FaultToleranceMustBePositive(); + if (numSigners > MAX_NUM_ORACLES) revert ExcessSigners(numSigners, MAX_NUM_ORACLES); + if (numSigners <= 3 * f) revert InsufficientSigners(numSigners, 3 * f + 1); + _; + } + + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) external pure override returns (bool isVerifier) { + return interfaceId == this.verify.selector; + } + + /// @inheritdoc ITypeAndVersion + function typeAndVersion() external pure override returns (string memory) { + return "Verifier 2.0.0"; + } + + /// @inheritdoc IVerifier + function verify( + bytes calldata signedReport, + address sender + ) external override returns (bytes memory verifierResponse) { + if (msg.sender != i_verifierProxyAddr) revert AccessForbidden(); + ( + bytes32[3] memory reportContext, + bytes memory reportData, + bytes32[] memory rs, + bytes32[] memory ss, + bytes32 rawVs + ) = abi.decode(signedReport, (bytes32[3], bytes, bytes32[], bytes32[], bytes32)); + + // reportContext consists of: + // reportContext[0]: ConfigDigest + // reportContext[1]: 27 byte padding, 4-byte epoch and 1-byte round + // reportContext[2]: ExtraHash + bytes32 configDigest = reportContext[0]; + + VerifierState storage verifierState = s_verifierStates[configDigest]; + + _validateReport(configDigest, rs, ss, verifierState); + + bytes32 hashedReport = keccak256(reportData); + + _verifySignatures(hashedReport, reportContext, rs, ss, rawVs, verifierState); + emit ReportVerified(bytes32(reportData), sender); + + return reportData; + } + + /// @notice Validates parameters of the report + /// @param configDigest Config digest from the report + /// @param rs R components from the report + /// @param ss S components from the report + /// @param config Config for the given digest + function _validateReport( + bytes32 configDigest, + bytes32[] memory rs, + bytes32[] memory ss, + VerifierState storage config + ) private view { + uint8 expectedNumSignatures = config.f + 1; + + if (!config.isActive) revert DigestInactive(configDigest); + if (rs.length != expectedNumSignatures) revert IncorrectSignatureCount(rs.length, expectedNumSignatures); + if (rs.length != ss.length) revert MismatchedSignatures(rs.length, ss.length); + } + + /// @notice Verifies that a report has been signed by the correct + /// signers and that enough signers have signed the reports. + /// @param hashedReport The keccak256 hash of the raw report's bytes + /// @param reportContext The context the report was signed in + /// @param rs ith element is the R components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries + /// @param ss ith element is the S components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries + /// @param rawVs ith element is the the V component of the ith signature + /// @param config The config digest the report was signed for + function _verifySignatures( + bytes32 hashedReport, + bytes32[3] memory reportContext, + bytes32[] memory rs, + bytes32[] memory ss, + bytes32 rawVs, + VerifierState storage config + ) private view { + bytes32 h = keccak256(abi.encodePacked(hashedReport, reportContext)); + // i-th byte counts number of sigs made by i-th signer + uint256 signedCount; + + Signer memory o; + address signerAddress; + uint256 numSigners = rs.length; + for (uint256 i; i < numSigners; ++i) { + signerAddress = ecrecover(h, uint8(rawVs[i]) + 27, rs[i], ss[i]); + o = config.oracles[signerAddress]; + if (o.role != Role.Signer) revert BadVerification(); + unchecked { + signedCount += 1 << (8 * o.index); + } + } + + if (signedCount & ORACLE_MASK != signedCount) revert BadVerification(); + } + + /// @inheritdoc IVerifier + function updateConfig( + bytes32 configDigest, + address[] calldata prevSigners, + address[] calldata newSigners, + uint8 f + ) external override checkConfigValid(newSigners.length, f) onlyOwner { + VerifierState storage config = s_verifierStates[configDigest]; + + if (config.f == 0) revert DigestNotSet(configDigest); + + // We must be removing the number of signers that were originally set + if (config.oracleCount != prevSigners.length) { + revert NonUniqueSignatures(); + } + + for (uint256 i; i < prevSigners.length; ++i) { + // Check the signers being removed are not zero address or duplicates + if (config.oracles[prevSigners[i]].role == Role.Unset) { + revert NonUniqueSignatures(); + } + + delete config.oracles[prevSigners[i]]; + } + + // Once signers have been cleared we can set the new signers + _setConfig(configDigest, newSigners, f, new Common.AddressAndWeight[](0), true); + + emit ConfigUpdated(configDigest, prevSigners, newSigners); + } + + /// @inheritdoc IVerifier + function setConfig( + bytes32 configDigest, + address[] calldata signers, + uint8 f, + Common.AddressAndWeight[] memory recipientAddressesAndWeights + ) external override checkConfigValid(signers.length, f) onlyOwner { + _setConfig(configDigest, signers, f, recipientAddressesAndWeights, false); + } + + function _setConfig( + bytes32 configDigest, + address[] calldata signers, + uint8 f, + Common.AddressAndWeight[] memory recipientAddressesAndWeights, + bool _updateConfig + ) internal { + VerifierState storage verifierState = s_verifierStates[configDigest]; + + if (verifierState.f > 0 && !_updateConfig) { + revert ConfigDigestAlreadySet(); + } + + verifierState.latestConfigBlockNumber = uint32(block.number); + verifierState.f = f; + verifierState.isActive = true; + verifierState.oracleCount = uint8(signers.length); + + for (uint8 i; i < signers.length; ++i) { + address signerAddr = signers[i]; + if (signerAddr == address(0)) revert ZeroAddress(); + + // All signer roles are unset by default for a new config digest. + // Here the contract checks to see if a signer's address has already + // been set to ensure that the group of signer addresses that will + // sign reports with the config digest are unique. + bool isSignerAlreadySet = verifierState.oracles[signerAddr].role != Role.Unset; + if (isSignerAlreadySet) revert NonUniqueSignatures(); + verifierState.oracles[signerAddr] = Signer({role: Role.Signer, index: i}); + } + + if (!_updateConfig) { + IVerifierProxy(i_verifierProxyAddr).setVerifier(bytes32(0), configDigest, recipientAddressesAndWeights); + + emit ConfigSet(configDigest, signers, f); + } + } + + /// @inheritdoc IVerifier + function activateConfig(bytes32 configDigest) external onlyOwner { + VerifierState storage verifierState = s_verifierStates[configDigest]; + + if (configDigest == bytes32("")) revert DigestEmpty(); + if (verifierState.f == 0) revert DigestNotSet(configDigest); + verifierState.isActive = true; + emit ConfigActivated(configDigest); + } + + /// @inheritdoc IVerifier + function deactivateConfig(bytes32 configDigest) external onlyOwner { + VerifierState storage verifierState = s_verifierStates[configDigest]; + + if (configDigest == bytes32("")) revert DigestEmpty(); + if (verifierState.f == 0) revert DigestNotSet(configDigest); + verifierState.isActive = false; + emit ConfigDeactivated(configDigest); + } + + /// @inheritdoc IVerifier + function latestConfigDetails(bytes32 configDigest) external view override returns (uint32 blockNumber) { + VerifierState storage verifierState = s_verifierStates[configDigest]; + return (verifierState.latestConfigBlockNumber); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/VerifierProxy.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/VerifierProxy.sol new file mode 100644 index 00000000000..e66b937f153 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/VerifierProxy.sol @@ -0,0 +1,229 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {IVerifierProxy} from "./interfaces/IVerifierProxy.sol"; +import {IVerifier} from "./interfaces/IVerifier.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {AccessControllerInterface} from "../../shared/interfaces/AccessControllerInterface.sol"; +import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {IVerifierFeeManager} from "./interfaces/IVerifierFeeManager.sol"; +import {Common} from "../libraries/Common.sol"; + +/** + * The verifier proxy contract is the gateway for all report verification requests + * on a chain. It is responsible for taking in a verification request and routing + * it to the correct verifier contract. + */ +contract VerifierProxy is IVerifierProxy, ConfirmedOwner, ITypeAndVersion { + /// @notice This event is emitted whenever a new verifier contract is set + /// @param oldConfigDigest The config digest that was previously the latest config + /// digest of the verifier contract at the verifier address. + /// @param oldConfigDigest The latest config digest of the verifier contract + /// at the verifier address. + /// @param verifierAddress The address of the verifier contract that verifies reports for + /// a given digest + event VerifierSet(bytes32 oldConfigDigest, bytes32 newConfigDigest, address verifierAddress); + + /// @notice This event is emitted whenever a new verifier contract is initialized + /// @param verifierAddress The address of the verifier contract that verifies reports + event VerifierInitialized(address verifierAddress); + + /// @notice This event is emitted whenever a verifier is unset + /// @param configDigest The config digest that was unset + /// @param verifierAddress The Verifier contract address unset + event VerifierUnset(bytes32 configDigest, address verifierAddress); + + /// @notice This event is emitted when a new access controller is set + /// @param oldAccessController The old access controller address + /// @param newAccessController The new access controller address + event AccessControllerSet(address oldAccessController, address newAccessController); + + /// @notice This event is emitted when a new fee manager is set + /// @param oldFeeManager The old fee manager address + /// @param newFeeManager The new fee manager address + event FeeManagerSet(address oldFeeManager, address newFeeManager); + + /// @notice This error is thrown whenever an address tries + /// to exeecute a transaction that it is not authorized to do so + error AccessForbidden(); + + /// @notice This error is thrown whenever a zero address is passed + error ZeroAddress(); + + /// @notice This error is thrown when trying to set a verifier address + /// for a digest that has already been initialized + /// @param configDigest The digest for the verifier that has + /// already been set + /// @param verifier The address of the verifier the digest was set for + error ConfigDigestAlreadySet(bytes32 configDigest, address verifier); + + /// @notice This error is thrown when trying to set a verifier address that has already been initialized + error VerifierAlreadyInitialized(address verifier); + + /// @notice This error is thrown when the verifier at an address does + /// not conform to the verifier interface + error VerifierInvalid(); + + /// @notice This error is thrown when the fee manager at an address does + /// not conform to the fee manager interface + error FeeManagerInvalid(); + + /// @notice This error is thrown whenever a verifier is not found + /// @param configDigest The digest for which a verifier is not found + error VerifierNotFound(bytes32 configDigest); + + /// @notice This error is thrown whenever billing fails. + error BadVerification(); + + /// @notice Mapping of authorized verifiers + mapping(address => bool) private s_initializedVerifiers; + + /// @notice Mapping between config digests and verifiers + mapping(bytes32 => address) private s_verifiersByConfig; + + /// @notice The contract to control addresses that are allowed to verify reports + AccessControllerInterface public s_accessController; + + /// @notice The contract to control fees for report verification + IVerifierFeeManager public s_feeManager; + + constructor(AccessControllerInterface accessController) ConfirmedOwner(msg.sender) { + s_accessController = accessController; + } + + modifier checkAccess() { + AccessControllerInterface ac = s_accessController; + if (address(ac) != address(0) && !ac.hasAccess(msg.sender, msg.data)) revert AccessForbidden(); + _; + } + + modifier onlyInitializedVerifier() { + if (!s_initializedVerifiers[msg.sender]) revert AccessForbidden(); + _; + } + + modifier onlyValidVerifier(address verifierAddress) { + if (verifierAddress == address(0)) revert ZeroAddress(); + if (!IERC165(verifierAddress).supportsInterface(IVerifier.verify.selector)) revert VerifierInvalid(); + _; + } + + modifier onlyUnsetConfigDigest(bytes32 configDigest) { + address configDigestVerifier = s_verifiersByConfig[configDigest]; + if (configDigestVerifier != address(0)) revert ConfigDigestAlreadySet(configDigest, configDigestVerifier); + _; + } + + /// @inheritdoc ITypeAndVersion + function typeAndVersion() external pure override returns (string memory) { + return "VerifierProxy 2.0.0"; + } + + /// @inheritdoc IVerifierProxy + function verify( + bytes calldata payload, + bytes calldata parameterPayload + ) external payable checkAccess returns (bytes memory) { + IVerifierFeeManager feeManager = s_feeManager; + + // Bill the verifier + if (address(feeManager) != address(0)) { + feeManager.processFee{value: msg.value}(payload, parameterPayload, msg.sender); + } + + return _verify(payload); + } + + /// @inheritdoc IVerifierProxy + function verifyBulk( + bytes[] calldata payloads, + bytes calldata parameterPayload + ) external payable checkAccess returns (bytes[] memory verifiedReports) { + IVerifierFeeManager feeManager = s_feeManager; + + // Bill the verifier + if (address(feeManager) != address(0)) { + feeManager.processFeeBulk{value: msg.value}(payloads, parameterPayload, msg.sender); + } + + //verify the reports + verifiedReports = new bytes[](payloads.length); + for (uint256 i; i < payloads.length; ++i) { + verifiedReports[i] = _verify(payloads[i]); + } + + return verifiedReports; + } + + function _verify(bytes calldata payload) internal returns (bytes memory verifiedReport) { + // First 32 bytes of the signed report is the config digest + bytes32 configDigest = bytes32(payload); + address verifierAddress = s_verifiersByConfig[configDigest]; + if (verifierAddress == address(0)) revert VerifierNotFound(configDigest); + + return IVerifier(verifierAddress).verify(payload, msg.sender); + } + + /// @inheritdoc IVerifierProxy + function initializeVerifier(address verifierAddress) external override onlyOwner onlyValidVerifier(verifierAddress) { + if (s_initializedVerifiers[verifierAddress]) revert VerifierAlreadyInitialized(verifierAddress); + + s_initializedVerifiers[verifierAddress] = true; + emit VerifierInitialized(verifierAddress); + } + + /// @inheritdoc IVerifierProxy + function setVerifier( + bytes32 currentConfigDigest, + bytes32 newConfigDigest, + Common.AddressAndWeight[] calldata addressesAndWeights + ) external override onlyUnsetConfigDigest(newConfigDigest) onlyInitializedVerifier { + s_verifiersByConfig[newConfigDigest] = msg.sender; + + // Empty recipients array will be ignored and must be set off chain + if (addressesAndWeights.length > 0) { + if (address(s_feeManager) == address(0)) { + revert ZeroAddress(); + } + + s_feeManager.setFeeRecipients(newConfigDigest, addressesAndWeights); + } + + emit VerifierSet(currentConfigDigest, newConfigDigest, msg.sender); + } + + /// @inheritdoc IVerifierProxy + function unsetVerifier(bytes32 configDigest) external override onlyOwner { + address verifierAddress = s_verifiersByConfig[configDigest]; + if (verifierAddress == address(0)) revert VerifierNotFound(configDigest); + delete s_verifiersByConfig[configDigest]; + emit VerifierUnset(configDigest, verifierAddress); + } + + /// @inheritdoc IVerifierProxy + function getVerifier(bytes32 configDigest) external view override returns (address) { + return s_verifiersByConfig[configDigest]; + } + + /// @inheritdoc IVerifierProxy + function setAccessController(AccessControllerInterface accessController) external onlyOwner { + address oldAccessController = address(s_accessController); + s_accessController = accessController; + emit AccessControllerSet(oldAccessController, address(accessController)); + } + + /// @inheritdoc IVerifierProxy + function setFeeManager(IVerifierFeeManager feeManager) external onlyOwner { + if (address(feeManager) == address(0)) revert ZeroAddress(); + + if ( + !IERC165(feeManager).supportsInterface(IVerifierFeeManager.processFee.selector) || + !IERC165(feeManager).supportsInterface(IVerifierFeeManager.processFeeBulk.selector) + ) revert FeeManagerInvalid(); + + address oldFeeManager = address(s_feeManager); + s_feeManager = IVerifierFeeManager(feeManager); + emit FeeManagerSet(oldFeeManager, address(feeManager)); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/ChannelConfigStore.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/ChannelConfigStore.sol index f5e5040bb8f..465292d9e0c 100644 --- a/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/ChannelConfigStore.sol +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/ChannelConfigStore.sol @@ -3,9 +3,9 @@ pragma solidity ^0.8.19; import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; import {IChannelConfigStore} from "./interfaces/IChannelConfigStore.sol"; -import {TypeAndVersionInterface} from "../../../interfaces/TypeAndVersionInterface.sol"; +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; -contract ChannelConfigStore is ConfirmedOwner, IChannelConfigStore, TypeAndVersionInterface { +contract ChannelConfigStore is ConfirmedOwner, IChannelConfigStore, ITypeAndVersion { event NewChannelDefinition(uint256 indexed donId, uint32 version, string url, bytes32 sha); constructor() ConfirmedOwner(msg.sender) {} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/Configurator.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/Configurator.sol index c946b3e2508..9b72f3d4fec 100644 --- a/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/Configurator.sol +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/Configurator.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.19; import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; -import {TypeAndVersionInterface} from "../../../interfaces/TypeAndVersionInterface.sol"; +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; import {IConfigurator} from "./interfaces/IConfigurator.sol"; @@ -18,7 +18,7 @@ uint256 constant MIN_SUPPORTED_ONCHAIN_CONFIG_VERSION = 1; * @notice This contract is intended to be deployed on the source chain and acts as a OCR3 configurator for LLO/Mercury **/ -contract Configurator is IConfigurator, ConfirmedOwner, TypeAndVersionInterface, IERC165 { +contract Configurator is IConfigurator, ConfirmedOwner, ITypeAndVersion, IERC165 { /// @notice This error is thrown whenever trying to set a config /// with a fault tolerance of 0 error FaultToleranceMustBePositive(); @@ -334,7 +334,7 @@ contract Configurator is IConfigurator, ConfirmedOwner, TypeAndVersionInterface, return interfaceId == type(IConfigurator).interfaceId; } - /// @inheritdoc TypeAndVersionInterface + /// @inheritdoc ITypeAndVersion function typeAndVersion() external pure override returns (string memory) { return "Configurator 0.5.0"; } diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/interfaces/IFeeManager.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/interfaces/IFeeManager.sol new file mode 100644 index 00000000000..5ea331ea8fd --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/interfaces/IFeeManager.sol @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {Common} from "../../libraries/Common.sol"; +import {IVerifierFeeManager} from "./IVerifierFeeManager.sol"; + +interface IFeeManager is IERC165, IVerifierFeeManager { + /** + * @notice Calculate the applied fee and the reward from a report. If the sender is a subscriber, they will receive a discount. + * @param subscriber address trying to verify + * @param report report to calculate the fee for + * @param quoteAddress address of the quote payment token + * @return (fee, reward, totalDiscount) fee and the reward data with the discount applied + */ + function getFeeAndReward( + address subscriber, + bytes memory report, + address quoteAddress + ) external returns (Common.Asset memory, Common.Asset memory, uint256); + + /** + * @notice Sets the native surcharge + * @param surcharge surcharge to be paid if paying in native + */ + function setNativeSurcharge(uint64 surcharge) external; + + /** + * @notice Adds a subscriber to the fee manager + * @param subscriber address of the subscriber + * @param feedId feed id to apply the discount to + * @param token token to apply the discount to + * @param discount discount to be applied to the fee + */ + function updateSubscriberDiscount(address subscriber, bytes32 feedId, address token, uint64 discount) external; + + /** + * @notice Withdraws any native or LINK rewards to the owner address + * @param assetAddress address of the asset to withdraw + * @param recipientAddress address to withdraw to + * @param quantity quantity to withdraw + */ + function withdraw(address assetAddress, address recipientAddress, uint192 quantity) external; + + /** + * @notice Returns the link balance of the fee manager + * @return link balance of the fee manager + */ + function linkAvailableForPayment() external returns (uint256); + + /** + * @notice Admin function to pay the LINK deficit for a given config digest + * @param configDigest the config digest to pay the deficit for + */ + function payLinkDeficit(bytes32 configDigest) external; + + /** + * @notice Adds a subscriber to the fee manager + * @param subscriber address of the subscriber + * @param token token to apply the discount to + * @param discount discount to be applied to the fee + */ + function updateSubscriberGlobalDiscount(address subscriber, address token, uint64 discount) external; + + /** + * @notice The structure to hold a fee and reward to verify a report + * @param digest the digest linked to the fee and reward + * @param fee the fee paid to verify the report + * @param reward the reward paid upon verification + & @param appliedDiscount the discount applied to the reward + */ + struct FeeAndReward { + bytes32 configDigest; + Common.Asset fee; + Common.Asset reward; + uint256 appliedDiscount; + } + + /** + * @notice The structure to hold quote metadata + * @param quoteAddress the address of the quote + */ + struct Quote { + address quoteAddress; + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/interfaces/IRewardManager.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/interfaces/IRewardManager.sol new file mode 100644 index 00000000000..f08ce34db29 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/interfaces/IRewardManager.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {Common} from "../../libraries/Common.sol"; + +interface IRewardManager is IERC165 { + /** + * @notice Record the fee received for a particular pool + * @param payments array of structs containing pool id and amount + * @param payee the user the funds should be retrieved from + */ + function onFeePaid(FeePayment[] calldata payments, address payee) external; + + /** + * @notice Claims the rewards in a specific pool + * @param poolIds array of poolIds to claim rewards for + */ + function claimRewards(bytes32[] calldata poolIds) external; + + /** + * @notice Set the RewardRecipients and weights for a specific pool. This should only be called once per pool Id. Else updateRewardRecipients should be used. + * @param poolId poolId to set RewardRecipients and weights for + * @param rewardRecipientAndWeights array of each RewardRecipient and associated weight + */ + function setRewardRecipients(bytes32 poolId, Common.AddressAndWeight[] calldata rewardRecipientAndWeights) external; + + /** + * @notice Updates a subset the reward recipients for a specific poolId. The collective weight of the recipients should add up to the recipients existing weights. Any recipients with a weight of 0 will be removed. + * @param poolId the poolId to update + * @param newRewardRecipients array of new reward recipients + */ + function updateRewardRecipients(bytes32 poolId, Common.AddressAndWeight[] calldata newRewardRecipients) external; + + /** + * @notice Pays all the recipients for each of the pool ids + * @param poolId the pool id to pay recipients for + * @param recipients array of recipients to pay within the pool + */ + function payRecipients(bytes32 poolId, address[] calldata recipients) external; + + /** + * @notice Sets the fee manager. This needs to be done post construction to prevent a circular dependency. + * @param newFeeManager address of the new verifier proxy + */ + function setFeeManager(address newFeeManager) external; + + /** + * @notice Gets a list of pool ids which have reward for a specific recipient. + * @param recipient address of the recipient to get pool ids for + * @param startIndex the index to start from + * @param endIndex the index to stop at + */ + function getAvailableRewardPoolIds( + address recipient, + uint256 startIndex, + uint256 endIndex + ) external view returns (bytes32[] memory); + + /** + * @notice The structure to hold a fee payment notice + * @param poolId the poolId receiving the payment + * @param amount the amount being paid + */ + struct FeePayment { + bytes32 poolId; + uint192 amount; + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/interfaces/IVerifier.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/interfaces/IVerifier.sol new file mode 100644 index 00000000000..a99f53a3f8c --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/interfaces/IVerifier.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {Common} from "../../libraries/Common.sol"; + +interface IVerifier is IERC165 { + /** + * @notice Verifies that the data encoded has been signed + * correctly by routing to the correct verifier. + * @param signedReport The encoded data to be verified. + * @param sender The address that requested to verify the contract. + * This is only used for logging purposes. + * @dev Verification is typically only done through the proxy contract so + * we can't just use msg.sender to log the requester as the msg.sender + * contract will always be the proxy. + * @return verifierResponse The encoded verified response. + */ + function verify(bytes calldata signedReport, address sender) external returns (bytes memory verifierResponse); + + /** + * @notice sets a configuration and its associated keys and f + * @param configDigest The digest of the configuration we're setting + * @param signers addresses with which oracles sign the reports + * @param f number of faulty oracles the system can tolerate + * @param recipientAddressesAndWeights the addresses and weights of all the recipients to receive rewards + */ + function setConfig( + bytes32 configDigest, + address[] calldata signers, + uint8 f, + Common.AddressAndWeight[] memory recipientAddressesAndWeights + ) external; + + /** + * @notice updates a configuration that has been set + * @param configDigest The digest of the configuration we're updating + * @param prevSigners the existing signers that need to be removed + * @param newSigners the signers to be added + * @param f the newnumber of faulty oracles the system can tolerate + */ + function updateConfig( + bytes32 configDigest, + address[] calldata prevSigners, + address[] calldata newSigners, + uint8 f + ) external; + + /** + * @notice Activates the configuration for a config digest + * @param configDigest The config digest to activate + * @dev This function can be called by the contract admin to activate a configuration. + */ + function activateConfig(bytes32 configDigest) external; + + /** + * @notice Deactivates the configuration for a config digest + * @param configDigest The config digest to deactivate + * @dev This function can be called by the contract admin to deactivate an incorrect configuration. + */ + function deactivateConfig(bytes32 configDigest) external; + + /** + * @notice information about current offchain reporting protocol configuration + * @param configDigest Config Digest to fetch data for + * @return blockNumber block at which this config was set + */ + function latestConfigDetails(bytes32 configDigest) external view returns (uint32 blockNumber); +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/interfaces/IVerifierFeeManager.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/interfaces/IVerifierFeeManager.sol new file mode 100644 index 00000000000..da3fdfac153 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/interfaces/IVerifierFeeManager.sol @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {Common} from "../../libraries/Common.sol"; + +interface IVerifierFeeManager is IERC165 { + /** + * @notice Handles fees for a report from the subscriber and manages rewards + * @param payload report to process the fee for + * @param parameterPayload fee payload + * @param subscriber address of the fee will be applied + */ + function processFee(bytes calldata payload, bytes calldata parameterPayload, address subscriber) external payable; + + /** + * @notice Processes the fees for each report in the payload, billing the subscriber and paying the reward manager + * @param payloads reports to process + * @param parameterPayload fee payload + * @param subscriber address of the user to process fee for + */ + function processFeeBulk( + bytes[] calldata payloads, + bytes calldata parameterPayload, + address subscriber + ) external payable; + + /** + * @notice Sets the fee recipients according to the fee manager + * @param configDigest digest of the configuration + * @param rewardRecipientAndWeights the address and weights of all the recipients to receive rewards + */ + function setFeeRecipients( + bytes32 configDigest, + Common.AddressAndWeight[] calldata rewardRecipientAndWeights + ) external; +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/interfaces/IVerifierProxy.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/interfaces/IVerifierProxy.sol new file mode 100644 index 00000000000..6609e4869ae --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/interfaces/IVerifierProxy.sol @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {Common} from "../../libraries/Common.sol"; +import {AccessControllerInterface} from "../../../shared/interfaces/AccessControllerInterface.sol"; +import {IVerifierFeeManager} from "./IVerifierFeeManager.sol"; + +interface IVerifierProxy { + /** + * @notice Verifies that the data encoded has been signed + * correctly by routing to the correct verifier, and bills the user if applicable. + * @param payload The encoded data to be verified, including the signed + * report. + * @param parameterPayload fee metadata for billing + * @return verifierResponse The encoded report from the verifier. + */ + function verify( + bytes calldata payload, + bytes calldata parameterPayload + ) external payable returns (bytes memory verifierResponse); + + /** + * @notice Bulk verifies that the data encoded has been signed + * correctly by routing to the correct verifier, and bills the user if applicable. + * @param payloads The encoded payloads to be verified, including the signed + * report. + * @param parameterPayload fee metadata for billing + * @return verifiedReports The encoded reports from the verifier. + */ + function verifyBulk( + bytes[] calldata payloads, + bytes calldata parameterPayload + ) external payable returns (bytes[] memory verifiedReports); + + /** + * @notice Sets the verifier address initially, allowing `setVerifier` to be set by this Verifier in the future + * @param verifierAddress The address of the verifier contract to initialize + */ + function initializeVerifier(address verifierAddress) external; + + /** + * @notice Sets a new verifier for a config digest + * @param currentConfigDigest The current config digest + * @param newConfigDigest The config digest to set + * @param addressesAndWeights The addresses and weights of reward recipients + * reports for a given config digest. + */ + function setVerifier( + bytes32 currentConfigDigest, + bytes32 newConfigDigest, + Common.AddressAndWeight[] memory addressesAndWeights + ) external; + + /** + * @notice Removes a verifier for a given config digest + * @param configDigest The config digest of the verifier to remove + */ + function unsetVerifier(bytes32 configDigest) external; + + /** + * @notice Retrieves the verifier address that verifies reports + * for a config digest. + * @param configDigest The config digest to query for + * @return verifierAddress The address of the verifier contract that verifies + * reports for a given config digest. + */ + function getVerifier(bytes32 configDigest) external view returns (address verifierAddress); + + /** + * @notice Called by the admin to set an access controller contract + * @param accessController The new access controller to set + */ + function setAccessController(AccessControllerInterface accessController) external; + + /** + * @notice Updates the fee manager + * @param feeManager The new fee manager + */ + function setFeeManager(IVerifierFeeManager feeManager) external; +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/test/fee-manager/BaseFeeManager.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/test/fee-manager/BaseFeeManager.t.sol new file mode 100644 index 00000000000..764bf4f088f --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/test/fee-manager/BaseFeeManager.t.sol @@ -0,0 +1,391 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {Test} from "forge-std/Test.sol"; +import {FeeManager} from "../../FeeManager.sol"; +import {RewardManager} from "../../RewardManager.sol"; +import {Common} from "../../../libraries/Common.sol"; +import {ERC20Mock} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol"; +import {WERC20Mock} from "../../../../shared/mocks/WERC20Mock.sol"; +import {IRewardManager} from "../../interfaces/IRewardManager.sol"; +import {FeeManagerProxy} from "../mocks/FeeManagerProxy.sol"; + +/** + * @title BaseFeeManagerTest + * @author Michael Fletcher + * @notice Base class for all feeManager tests + * @dev This contract is intended to be inherited from and not used directly. It contains functionality to setup the feeManager + */ +contract BaseFeeManagerTest is Test { + //contracts + FeeManager internal feeManager; + RewardManager internal rewardManager; + FeeManagerProxy internal feeManagerProxy; + + ERC20Mock internal link; + WERC20Mock internal native; + + //erc20 config + uint256 internal constant DEFAULT_LINK_MINT_QUANTITY = 100 ether; + uint256 internal constant DEFAULT_NATIVE_MINT_QUANTITY = 100 ether; + + //contract owner + address internal constant INVALID_ADDRESS = address(0); + address internal constant ADMIN = address(uint160(uint256(keccak256("ADMIN")))); + address internal constant USER = address(uint160(uint256(keccak256("USER")))); + address internal constant PROXY = address(uint160(uint256(keccak256("PROXY")))); + + //version masks + bytes32 internal constant V_MASK = 0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; + bytes32 internal constant V1_BITMASK = 0x0001000000000000000000000000000000000000000000000000000000000000; + bytes32 internal constant V2_BITMASK = 0x0002000000000000000000000000000000000000000000000000000000000000; + bytes32 internal constant V3_BITMASK = 0x0003000000000000000000000000000000000000000000000000000000000000; + + //feed ids & config digests + bytes32 internal constant DEFAULT_FEED_1_V1 = (keccak256("ETH-USD") & V_MASK) | V1_BITMASK; + bytes32 internal constant DEFAULT_FEED_1_V2 = (keccak256("ETH-USD") & V_MASK) | V2_BITMASK; + bytes32 internal constant DEFAULT_FEED_1_V3 = (keccak256("ETH-USD") & V_MASK) | V3_BITMASK; + + bytes32 internal constant DEFAULT_FEED_2_V3 = (keccak256("LINK-USD") & V_MASK) | V3_BITMASK; + bytes32 internal constant DEFAULT_CONFIG_DIGEST = keccak256("DEFAULT_CONFIG_DIGEST"); + + //report + uint256 internal constant DEFAULT_REPORT_LINK_FEE = 1e10; + uint256 internal constant DEFAULT_REPORT_NATIVE_FEE = 1e12; + + //rewards + uint64 internal constant FEE_SCALAR = 1e18; + + address internal constant NATIVE_WITHDRAW_ADDRESS = address(0); + + //the selector for each error + bytes4 internal immutable INVALID_DISCOUNT_ERROR = FeeManager.InvalidDiscount.selector; + bytes4 internal immutable INVALID_ADDRESS_ERROR = FeeManager.InvalidAddress.selector; + bytes4 internal immutable INVALID_SURCHARGE_ERROR = FeeManager.InvalidSurcharge.selector; + bytes4 internal immutable EXPIRED_REPORT_ERROR = FeeManager.ExpiredReport.selector; + bytes4 internal immutable INVALID_DEPOSIT_ERROR = FeeManager.InvalidDeposit.selector; + bytes4 internal immutable INVALID_QUOTE_ERROR = FeeManager.InvalidQuote.selector; + bytes4 internal immutable UNAUTHORIZED_ERROR = FeeManager.Unauthorized.selector; + bytes internal constant ONLY_CALLABLE_BY_OWNER_ERROR = "Only callable by owner"; + bytes internal constant INSUFFICIENT_ALLOWANCE_ERROR = "ERC20: insufficient allowance"; + bytes4 internal immutable ZERO_DEFICIT = FeeManager.ZeroDeficit.selector; + + //events emitted + event SubscriberDiscountUpdated(address indexed subscriber, bytes32 indexed feedId, address token, uint64 discount); + event NativeSurchargeUpdated(uint64 newSurcharge); + event InsufficientLink(IRewardManager.FeePayment[] feesAndRewards); + event Withdraw(address adminAddress, address recipient, address assetAddress, uint192 quantity); + event LinkDeficitCleared(bytes32 indexed configDigest, uint256 linkQuantity); + event DiscountApplied( + bytes32 indexed configDigest, + address indexed subscriber, + Common.Asset fee, + Common.Asset reward, + uint256 appliedDiscountQuantity + ); + + function setUp() public virtual { + //change to admin user + vm.startPrank(ADMIN); + + //init required contracts + _initializeContracts(); + } + + function _initializeContracts() internal { + link = new ERC20Mock("LINK", "LINK", ADMIN, 0); + native = new WERC20Mock(); + + feeManagerProxy = new FeeManagerProxy(); + rewardManager = new RewardManager(address(link)); + feeManager = new FeeManager(address(link), address(native), address(feeManagerProxy), address(rewardManager)); + + //link the feeManager to the proxy + feeManagerProxy.setFeeManager(feeManager); + + //link the feeManager to the reward manager + rewardManager.setFeeManager(address(feeManager)); + + //mint some tokens to the admin + link.mint(ADMIN, DEFAULT_LINK_MINT_QUANTITY); + native.mint(ADMIN, DEFAULT_NATIVE_MINT_QUANTITY); + vm.deal(ADMIN, DEFAULT_NATIVE_MINT_QUANTITY); + + //mint some tokens to the user + link.mint(USER, DEFAULT_LINK_MINT_QUANTITY); + native.mint(USER, DEFAULT_NATIVE_MINT_QUANTITY); + vm.deal(USER, DEFAULT_NATIVE_MINT_QUANTITY); + + //mint some tokens to the proxy + link.mint(PROXY, DEFAULT_LINK_MINT_QUANTITY); + native.mint(PROXY, DEFAULT_NATIVE_MINT_QUANTITY); + vm.deal(PROXY, DEFAULT_NATIVE_MINT_QUANTITY); + } + + function setSubscriberDiscount( + address subscriber, + bytes32 feedId, + address token, + uint256 discount, + address sender + ) internal { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //set the discount + feeManager.updateSubscriberDiscount(subscriber, feedId, token, uint64(discount)); + + //change back to the original address + changePrank(originalAddr); + } + + function setSubscriberGlobalDiscount(address subscriber, address token, uint256 discount, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //set the discount + feeManager.updateSubscriberGlobalDiscount(subscriber, token, uint64(discount)); + + //change back to the original address + changePrank(originalAddr); + } + + function setNativeSurcharge(uint256 surcharge, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //set the surcharge + feeManager.setNativeSurcharge(uint64(surcharge)); + + //change back to the original address + changePrank(originalAddr); + } + + // solium-disable-next-line no-unused-vars + function getFee(bytes memory report, address quote, address subscriber) public view returns (Common.Asset memory) { + //get the fee + (Common.Asset memory fee, , ) = feeManager.getFeeAndReward(subscriber, report, quote); + + return fee; + } + + function getReward(bytes memory report, address quote, address subscriber) public view returns (Common.Asset memory) { + //get the reward + (, Common.Asset memory reward, ) = feeManager.getFeeAndReward(subscriber, report, quote); + + return reward; + } + + function getAppliedDiscount(bytes memory report, address quote, address subscriber) public view returns (uint256) { + //get the reward + (, , uint256 appliedDiscount) = feeManager.getFeeAndReward(subscriber, report, quote); + + return appliedDiscount; + } + + function getV1Report(bytes32 feedId) public pure returns (bytes memory) { + return abi.encode(feedId, uint32(0), int192(0), int192(0), int192(0), uint64(0), bytes32(0), uint64(0), uint64(0)); + } + + function getV2Report(bytes32 feedId) public view returns (bytes memory) { + return + abi.encode( + feedId, + uint32(0), + uint32(0), + uint192(DEFAULT_REPORT_NATIVE_FEE), + uint192(DEFAULT_REPORT_LINK_FEE), + uint32(block.timestamp), + int192(0) + ); + } + + function getV3Report(bytes32 feedId) public view returns (bytes memory) { + return + abi.encode( + feedId, + uint32(0), + uint32(0), + uint192(DEFAULT_REPORT_NATIVE_FEE), + uint192(DEFAULT_REPORT_LINK_FEE), + uint32(block.timestamp), + int192(0), + int192(0), + int192(0) + ); + } + + function getV3ReportWithCustomExpiryAndFee( + bytes32 feedId, + uint256 expiry, + uint256 linkFee, + uint256 nativeFee + ) public pure returns (bytes memory) { + return + abi.encode( + feedId, + uint32(0), + uint32(0), + uint192(nativeFee), + uint192(linkFee), + uint32(expiry), + int192(0), + int192(0), + int192(0) + ); + } + + function getLinkQuote() public view returns (address) { + return address(link); + } + + function getNativeQuote() public view returns (address) { + return address(native); + } + + function withdraw(address assetAddress, address recipient, uint256 amount, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //set the surcharge + feeManager.withdraw(assetAddress, recipient, uint192(amount)); + + //change back to the original address + changePrank(originalAddr); + } + + function getLinkBalance(address balanceAddress) public view returns (uint256) { + return link.balanceOf(balanceAddress); + } + + function getNativeBalance(address balanceAddress) public view returns (uint256) { + return native.balanceOf(balanceAddress); + } + + function getNativeUnwrappedBalance(address balanceAddress) public view returns (uint256) { + return balanceAddress.balance; + } + + function mintLink(address recipient, uint256 amount) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(ADMIN); + + //mint the link to the recipient + link.mint(recipient, amount); + + //change back to the original address + changePrank(originalAddr); + } + + function mintNative(address recipient, uint256 amount, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //mint the native to the recipient + native.mint(recipient, amount); + + //change back to the original address + changePrank(originalAddr); + } + + function issueUnwrappedNative(address recipient, uint256 quantity) public { + vm.deal(recipient, quantity); + } + + function ProcessFeeAsUser( + bytes memory payload, + address subscriber, + address tokenAddress, + uint256 wrappedNativeValue, + address sender + ) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //process the fee + feeManager.processFee{value: wrappedNativeValue}(payload, abi.encode(tokenAddress), subscriber); + + //change ProcessFeeAsUserback to the original address + changePrank(originalAddr); + } + + function processFee(bytes memory payload, address subscriber, address feeAddress, uint256 wrappedNativeValue) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(subscriber); + + //process the fee + feeManagerProxy.processFee{value: wrappedNativeValue}(payload, abi.encode(feeAddress)); + + //change back to the original address + changePrank(originalAddr); + } + + function processFee( + bytes[] memory payloads, + address subscriber, + address feeAddress, + uint256 wrappedNativeValue + ) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(subscriber); + + //process the fee + feeManagerProxy.processFeeBulk{value: wrappedNativeValue}(payloads, abi.encode(feeAddress)); + + //change back to the original address + changePrank(originalAddr); + } + + function getPayload(bytes memory reportPayload) public pure returns (bytes memory) { + return abi.encode([DEFAULT_CONFIG_DIGEST, 0, 0], reportPayload, new bytes32[](1), new bytes32[](1), bytes32("")); + } + + function approveLink(address spender, uint256 quantity, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //approve the link to be transferred + link.approve(spender, quantity); + + //change back to the original address + changePrank(originalAddr); + } + + function approveNative(address spender, uint256 quantity, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //approve the link to be transferred + native.approve(spender, quantity); + + //change back to the original address + changePrank(originalAddr); + } + + function payLinkDeficit(bytes32 configDigest, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //approve the link to be transferred + feeManager.payLinkDeficit(configDigest); + + //change back to the original address + changePrank(originalAddr); + } + + function getLinkDeficit(bytes32 configDigest) public view returns (uint256) { + return feeManager.s_linkDeficit(configDigest); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/test/fee-manager/FeeManager.general.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/test/fee-manager/FeeManager.general.t.sol new file mode 100644 index 00000000000..5abd496edd7 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/test/fee-manager/FeeManager.general.t.sol @@ -0,0 +1,242 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import "./BaseFeeManager.t.sol"; + +/** + * @title BaseFeeManagerTest + * @author Michael Fletcher + * @notice This contract will test the setup functionality of the feemanager + */ +contract FeeManagerProcessFeeTestV05 is BaseFeeManagerTest { + function setUp() public override { + super.setUp(); + } + + function test_WithdrawERC20() public { + //simulate a fee + mintLink(address(feeManager), DEFAULT_LINK_MINT_QUANTITY); + + //get the balances to ne used for comparison + uint256 contractBalance = getLinkBalance(address(feeManager)); + uint256 adminBalance = getLinkBalance(ADMIN); + + //the amount to withdraw + uint256 withdrawAmount = contractBalance / 2; + + //withdraw some balance + withdraw(address(link), ADMIN, withdrawAmount, ADMIN); + + //check the balance has been reduced + uint256 newContractBalance = getLinkBalance(address(feeManager)); + uint256 newAdminBalance = getLinkBalance(ADMIN); + + //check the balance is greater than zero + assertGt(newContractBalance, 0); + //check the balance has been reduced by the correct amount + assertEq(newContractBalance, contractBalance - withdrawAmount); + //check the admin balance has increased by the correct amount + assertEq(newAdminBalance, adminBalance + withdrawAmount); + } + + function test_WithdrawUnwrappedNative() public { + //issue funds straight to the contract to bypass the lack of fallback function + issueUnwrappedNative(address(feeManager), DEFAULT_NATIVE_MINT_QUANTITY); + + //get the balances to be used for comparison + uint256 contractBalance = getNativeUnwrappedBalance(address(feeManager)); + uint256 adminBalance = getNativeUnwrappedBalance(ADMIN); + + //the amount to withdraw + uint256 withdrawAmount = contractBalance / 2; + + //withdraw some balance + withdraw(NATIVE_WITHDRAW_ADDRESS, ADMIN, withdrawAmount, ADMIN); + + //check the balance has been reduced + uint256 newContractBalance = getNativeUnwrappedBalance(address(feeManager)); + uint256 newAdminBalance = getNativeUnwrappedBalance(ADMIN); + + //check the balance is greater than zero + assertGt(newContractBalance, 0); + //check the balance has been reduced by the correct amount + assertEq(newContractBalance, contractBalance - withdrawAmount); + //check the admin balance has increased by the correct amount + assertEq(newAdminBalance, adminBalance + withdrawAmount); + } + + function test_WithdrawNonAdminAddr() public { + //simulate a fee + mintLink(address(feeManager), DEFAULT_LINK_MINT_QUANTITY); + + //should revert if not admin + vm.expectRevert(ONLY_CALLABLE_BY_OWNER_ERROR); + + //withdraw some balance + withdraw(address(link), ADMIN, DEFAULT_LINK_MINT_QUANTITY, USER); + } + + function test_eventIsEmittedAfterSurchargeIsSet() public { + //native surcharge + uint64 nativeSurcharge = FEE_SCALAR / 5; + + //expect an emit + vm.expectEmit(); + + //emit the event that is expected to be emitted + emit NativeSurchargeUpdated(nativeSurcharge); + + //set the surcharge + setNativeSurcharge(nativeSurcharge, ADMIN); + } + + function test_subscriberDiscountEventIsEmittedOnUpdate() public { + //native surcharge + uint64 discount = FEE_SCALAR / 3; + + //an event should be emitted + vm.expectEmit(); + + //emit the event that is expected to be emitted + emit SubscriberDiscountUpdated(USER, DEFAULT_FEED_1_V3, address(native), discount); + + //set the surcharge + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), discount, ADMIN); + } + + function test_eventIsEmittedUponWithdraw() public { + //simulate a fee + mintLink(address(feeManager), DEFAULT_LINK_MINT_QUANTITY); + + //the amount to withdraw + uint192 withdrawAmount = 1; + + //expect an emit + vm.expectEmit(); + + //the event to be emitted + emit Withdraw(ADMIN, ADMIN, address(link), withdrawAmount); + + //withdraw some balance + withdraw(address(link), ADMIN, withdrawAmount, ADMIN); + } + + function test_linkAvailableForPaymentReturnsLinkBalance() public { + //simulate a deposit of link for the conversion pool + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + //check there's a balance + assertGt(getLinkBalance(address(feeManager)), 0); + + //check the link available for payment is the link balance + assertEq(feeManager.linkAvailableForPayment(), getLinkBalance(address(feeManager))); + } + + function test_payLinkDeficit() public { + //get the default payload + bytes memory payload = getPayload(getV2Report(DEFAULT_FEED_1_V3)); + + approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); + + //not enough funds in the reward pool should trigger an insufficient link event + vm.expectEmit(); + + IRewardManager.FeePayment[] memory contractFees = new IRewardManager.FeePayment[](1); + contractFees[0] = IRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); + + emit InsufficientLink(contractFees); + + //process the fee + processFee(payload, USER, address(native), 0); + + //double check the rewardManager balance is 0 + assertEq(getLinkBalance(address(rewardManager)), 0); + + //simulate a deposit of link to cover the deficit + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + vm.expectEmit(); + emit LinkDeficitCleared(DEFAULT_CONFIG_DIGEST, DEFAULT_REPORT_LINK_FEE); + + //pay the deficit which will transfer link from the rewardManager to the rewardManager + payLinkDeficit(DEFAULT_CONFIG_DIGEST, ADMIN); + + //check the rewardManager received the link + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + } + + function test_payLinkDeficitTwice() public { + //get the default payload + bytes memory payload = getPayload(getV2Report(DEFAULT_FEED_1_V3)); + + approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); + + //not enough funds in the reward pool should trigger an insufficient link event + vm.expectEmit(); + + IRewardManager.FeePayment[] memory contractFees = new IRewardManager.FeePayment[](1); + contractFees[0] = IRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); + + //emit the event that is expected to be emitted + emit InsufficientLink(contractFees); + + //process the fee + processFee(payload, USER, address(native), 0); + + //double check the rewardManager balance is 0 + assertEq(getLinkBalance(address(rewardManager)), 0); + + //simulate a deposit of link to cover the deficit + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + vm.expectEmit(); + emit LinkDeficitCleared(DEFAULT_CONFIG_DIGEST, DEFAULT_REPORT_LINK_FEE); + + //pay the deficit which will transfer link from the rewardManager to the rewardManager + payLinkDeficit(DEFAULT_CONFIG_DIGEST, ADMIN); + + //check the rewardManager received the link + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + + //paying again should revert with 0 + vm.expectRevert(ZERO_DEFICIT); + + payLinkDeficit(DEFAULT_CONFIG_DIGEST, ADMIN); + } + + function test_payLinkDeficitPaysAllFeesProcessed() public { + //get the default payload + bytes memory payload = getPayload(getV2Report(DEFAULT_FEED_1_V3)); + + //approve the native to be transferred from the user + approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE * 2, USER); + + //processing the fee will transfer the native from the user to the feeManager + processFee(payload, USER, address(native), 0); + processFee(payload, USER, address(native), 0); + + //check the deficit has been increased twice + assertEq(getLinkDeficit(DEFAULT_CONFIG_DIGEST), DEFAULT_REPORT_LINK_FEE * 2); + + //double check the rewardManager balance is 0 + assertEq(getLinkBalance(address(rewardManager)), 0); + + //simulate a deposit of link to cover the deficit + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE * 2); + + vm.expectEmit(); + emit LinkDeficitCleared(DEFAULT_CONFIG_DIGEST, DEFAULT_REPORT_LINK_FEE * 2); + + //pay the deficit which will transfer link from the rewardManager to the rewardManager + payLinkDeficit(DEFAULT_CONFIG_DIGEST, ADMIN); + + //check the rewardManager received the link + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * 2); + } + + function test_payLinkDeficitOnlyCallableByAdmin() public { + vm.expectRevert(ONLY_CALLABLE_BY_OWNER_ERROR); + + payLinkDeficit(DEFAULT_CONFIG_DIGEST, USER); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/test/fee-manager/FeeManager.getFeeAndReward.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/test/fee-manager/FeeManager.getFeeAndReward.t.sol new file mode 100644 index 00000000000..c953b7f59db --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/test/fee-manager/FeeManager.getFeeAndReward.t.sol @@ -0,0 +1,720 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {Common} from "../../../libraries/Common.sol"; +import "./BaseFeeManager.t.sol"; + +/** + * @title BaseFeeManagerTest + * @author Michael Fletcher + * @notice This contract will test the functionality of the feeManager's getFeeAndReward + */ +contract FeeManagerProcessFeeTestV05 is BaseFeeManagerTest { + function test_baseFeeIsAppliedForNative() public view { + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be the default + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE); + } + + function test_baseFeeIsAppliedForLink() public view { + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //fee should be the default + assertEq(fee.amount, DEFAULT_REPORT_LINK_FEE); + } + + function test_discountAIsNotAppliedWhenSetForOtherUsers() public { + //set the subscriber discount for another user + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), INVALID_ADDRESS); + + //fee should be the default + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE); + } + + function test_discountIsNotAppliedForInvalidTokenAddress() public { + //should revert with invalid address as it's not a configured token + vm.expectRevert(INVALID_ADDRESS_ERROR); + + //set the subscriber discount for another user + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, INVALID_ADDRESS, FEE_SCALAR / 2, ADMIN); + } + + function test_discountIsAppliedForLink() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //fee should be half the default + assertEq(fee.amount, DEFAULT_REPORT_LINK_FEE / 2); + } + + function test_DiscountIsAppliedForNative() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be half the default + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE / 2); + } + + function test_discountIsNoLongerAppliedAfterRemoving() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //fee should be half the default + assertEq(fee.amount, DEFAULT_REPORT_LINK_FEE / 2); + + //remove the discount + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), 0, ADMIN); + + //get the fee required by the feeManager + fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //fee should be the default + assertEq(fee.amount, DEFAULT_REPORT_LINK_FEE); + } + + function test_surchargeIsApplied() public { + //native surcharge + uint256 nativeSurcharge = FEE_SCALAR / 5; + + //set the surcharge + setNativeSurcharge(nativeSurcharge, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected surcharge + uint256 expectedSurcharge = ((DEFAULT_REPORT_NATIVE_FEE * nativeSurcharge) / FEE_SCALAR); + + //expected fee should the base fee offset by the surcharge and discount + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge); + } + + function test_surchargeIsNotAppliedForLinkFee() public { + //native surcharge + uint256 nativeSurcharge = FEE_SCALAR / 5; + + //set the surcharge + setNativeSurcharge(nativeSurcharge, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //fee should be the default + assertEq(fee.amount, DEFAULT_REPORT_LINK_FEE); + } + + function test_surchargeIsNoLongerAppliedAfterRemoving() public { + //native surcharge + uint256 nativeSurcharge = FEE_SCALAR / 5; + + //set the surcharge + setNativeSurcharge(nativeSurcharge, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected surcharge + uint256 expectedSurcharge = ((DEFAULT_REPORT_NATIVE_FEE * nativeSurcharge) / FEE_SCALAR); + + //expected fee should be the base fee offset by the surcharge and discount + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge); + + //remove the surcharge + setNativeSurcharge(0, ADMIN); + + //get the fee required by the feeManager + fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be the default + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE); + } + + function test_feeIsUpdatedAfterNewSurchargeIsApplied() public { + //native surcharge + uint256 nativeSurcharge = FEE_SCALAR / 5; + + //set the surcharge + setNativeSurcharge(nativeSurcharge, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected surcharge + uint256 expectedSurcharge = ((DEFAULT_REPORT_NATIVE_FEE * nativeSurcharge) / FEE_SCALAR); + + //expected fee should the base fee offset by the surcharge and discount + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge); + + //change the surcharge + setNativeSurcharge(nativeSurcharge, ADMIN); + + //get the fee required by the feeManager + fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected surcharge + expectedSurcharge = ((DEFAULT_REPORT_NATIVE_FEE * nativeSurcharge) / FEE_SCALAR); + + //expected fee should the base fee offset by the surcharge and discount + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge); + } + + function test_surchargeIsAppliedForNativeFeeWithDiscount() public { + //native surcharge + uint256 nativeSurcharge = FEE_SCALAR / 5; + + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //set the surcharge + setNativeSurcharge(nativeSurcharge, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected surcharge quantity + uint256 expectedSurcharge = ((DEFAULT_REPORT_NATIVE_FEE * nativeSurcharge) / FEE_SCALAR); + + //calculate the expected discount quantity + uint256 expectedDiscount = ((DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge) / 2); + + //expected fee should the base fee offset by the surcharge and discount + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge - expectedDiscount); + } + + function test_emptyQuoteRevertsWithError() public { + //expect a revert + vm.expectRevert(INVALID_QUOTE_ERROR); + + //get the fee required by the feeManager + getFee(getV3Report(DEFAULT_FEED_1_V3), address(0), USER); + } + + function test_nativeSurcharge100Percent() public { + //set the surcharge + setNativeSurcharge(FEE_SCALAR, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be twice the base fee + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE * 2); + } + + function test_nativeSurcharge0Percent() public { + //set the surcharge + setNativeSurcharge(0, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should base fee + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE); + } + + function test_nativeSurchargeCannotExceed100Percent() public { + //should revert if surcharge is greater than 100% + vm.expectRevert(INVALID_SURCHARGE_ERROR); + + //set the surcharge above the max + setNativeSurcharge(FEE_SCALAR + 1, ADMIN); + } + + function test_discountIsAppliedWith100PercentSurcharge() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //set the surcharge + setNativeSurcharge(FEE_SCALAR, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected discount quantity + uint256 expectedDiscount = DEFAULT_REPORT_NATIVE_FEE; + + //fee should be twice the surcharge minus the discount + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE * 2 - expectedDiscount); + } + + function test_feeIsZeroWith100PercentDiscount() public { + //set the subscriber discount to 100% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be zero + assertEq(fee.amount, 0); + } + + function test_feeIsUpdatedAfterDiscountIsRemoved() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected discount quantity + uint256 expectedDiscount = DEFAULT_REPORT_NATIVE_FEE / 2; + + //fee should be 50% of the base fee + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE - expectedDiscount); + + //remove the discount + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), 0, ADMIN); + + //get the fee required by the feeManager + fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be the base fee + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE); + } + + function test_feeIsUpdatedAfterNewDiscountIsApplied() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected discount quantity + uint256 expectedDiscount = DEFAULT_REPORT_NATIVE_FEE / 2; + + //fee should be 50% of the base fee + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE - expectedDiscount); + + //change the discount to 25% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 4, ADMIN); + + //get the fee required by the feeManager + fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //expected discount is now 25% + expectedDiscount = DEFAULT_REPORT_NATIVE_FEE / 4; + + //fee should be the base fee minus the expected discount + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE - expectedDiscount); + } + + function test_setDiscountOver100Percent() public { + //should revert with invalid discount + vm.expectRevert(INVALID_DISCOUNT_ERROR); + + //set the subscriber discount to over 100% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR + 1, ADMIN); + } + + function test_surchargeIsNotAppliedWith100PercentDiscount() public { + //native surcharge + uint256 nativeSurcharge = FEE_SCALAR / 5; + + //set the subscriber discount to 100% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR, ADMIN); + + //set the surcharge + setNativeSurcharge(nativeSurcharge, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be zero + assertEq(fee.amount, 0); + } + + function test_nonAdminUserCanNotSetDiscount() public { + //should revert with unauthorized + vm.expectRevert(ONLY_CALLABLE_BY_OWNER_ERROR); + + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR, USER); + } + + function test_surchargeFeeRoundsUpWhenUneven() public { + //native surcharge + uint256 nativeSurcharge = FEE_SCALAR / 3; + + //set the surcharge + setNativeSurcharge(nativeSurcharge, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected surcharge quantity + uint256 expectedSurcharge = (DEFAULT_REPORT_NATIVE_FEE * nativeSurcharge) / FEE_SCALAR; + + //expected fee should the base fee offset by the expected surcharge + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge + 1); + } + + function test_discountFeeRoundsDownWhenUneven() public { + //native surcharge + uint256 discount = FEE_SCALAR / 3; + + //set the subscriber discount to 33.333% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), discount, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected quantity + uint256 expectedDiscount = ((DEFAULT_REPORT_NATIVE_FEE * discount) / FEE_SCALAR); + + //expected fee should the base fee offset by the expected surcharge + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE - expectedDiscount); + } + + function test_reportWithNoExpiryOrFeeReturnsZero() public view { + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV1Report(DEFAULT_FEED_1_V1), getNativeQuote(), USER); + + //fee should be zero + assertEq(fee.amount, 0); + } + + function test_correctDiscountIsAppliedWhenBothTokensAreDiscounted() public { + //set the subscriber and native discounts + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 4, ADMIN); + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager for both tokens + Common.Asset memory linkFee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + Common.Asset memory nativeFee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected discount quantity for each token + uint256 expectedDiscountLink = (DEFAULT_REPORT_LINK_FEE * FEE_SCALAR) / 4 / FEE_SCALAR; + uint256 expectedDiscountNative = (DEFAULT_REPORT_NATIVE_FEE * FEE_SCALAR) / 2 / FEE_SCALAR; + + //check the fee calculation for each token + assertEq(linkFee.amount, DEFAULT_REPORT_LINK_FEE - expectedDiscountLink); + assertEq(nativeFee.amount, DEFAULT_REPORT_NATIVE_FEE - expectedDiscountNative); + } + + function test_discountIsNotAppliedToOtherFeeds() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_2_V3), getNativeQuote(), USER); + + //fee should be the base fee + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE); + } + + function test_noFeeIsAppliedWhenReportHasZeroFee() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee( + getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, uint32(block.timestamp), 0, 0), + getNativeQuote(), + USER + ); + + //fee should be zero + assertEq(fee.amount, 0); + } + + function test_noFeeIsAppliedWhenReportHasZeroFeeAndDiscountAndSurchargeIsSet() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //set the surcharge + setNativeSurcharge(FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee( + getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, uint32(block.timestamp), 0, 0), + getNativeQuote(), + USER + ); + + //fee should be zero + assertEq(fee.amount, 0); + } + + function test_nativeSurchargeEventIsEmittedOnUpdate() public { + //native surcharge + uint64 nativeSurcharge = FEE_SCALAR / 3; + + //an event should be emitted + vm.expectEmit(); + + //emit the event that is expected to be emitted + emit NativeSurchargeUpdated(nativeSurcharge); + + //set the surcharge + setNativeSurcharge(nativeSurcharge, ADMIN); + } + + function test_getBaseRewardWithLinkQuote() public view { + //get the fee required by the feeManager + Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //the reward should equal the base fee + assertEq(reward.amount, DEFAULT_REPORT_LINK_FEE); + } + + function test_getRewardWithLinkQuoteAndLinkDiscount() public { + //set the link discount + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //the reward should equal the discounted base fee + assertEq(reward.amount, DEFAULT_REPORT_LINK_FEE / 2); + } + + function test_getRewardWithNativeQuote() public view { + //get the fee required by the feeManager + Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //the reward should equal the base fee in link + assertEq(reward.amount, DEFAULT_REPORT_LINK_FEE); + } + + function test_getRewardWithNativeQuoteAndSurcharge() public { + //set the native surcharge + setNativeSurcharge(FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //the reward should equal the base fee in link regardless of the surcharge + assertEq(reward.amount, DEFAULT_REPORT_LINK_FEE); + } + + function test_getRewardWithLinkDiscount() public { + //set the link discount + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //the reward should equal the discounted base fee + assertEq(reward.amount, DEFAULT_REPORT_LINK_FEE / 2); + } + + function test_getLinkFeeIsRoundedUp() public { + //set the link discount + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 3, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //the reward should equal .66% + 1 of the base fee due to a 33% discount rounded up + assertEq(fee.amount, (DEFAULT_REPORT_LINK_FEE * 2) / 3 + 1); + } + + function test_getLinkRewardIsSameAsFee() public { + //set the link discount + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 3, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //check the reward is in link + assertEq(fee.assetAddress, address(link)); + + //the reward should equal .66% of the base fee due to a 33% discount rounded down + assertEq(reward.amount, fee.amount); + } + + function test_getLinkRewardWithNativeQuoteAndSurchargeWithLinkDiscount() public { + //set the native surcharge + setNativeSurcharge(FEE_SCALAR / 2, ADMIN); + + //set the link discount + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 3, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //the reward should equal the base fee in link regardless of the surcharge + assertEq(reward.amount, DEFAULT_REPORT_LINK_FEE); + } + + function test_testRevertIfReportHasExpired() public { + //expect a revert + vm.expectRevert(EXPIRED_REPORT_ERROR); + + //get the fee required by the feeManager + getFee( + getV3ReportWithCustomExpiryAndFee( + DEFAULT_FEED_1_V3, + block.timestamp - 1, + DEFAULT_REPORT_LINK_FEE, + DEFAULT_REPORT_NATIVE_FEE + ), + getNativeQuote(), + USER + ); + } + + function test_discountIsReturnedForLink() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 2, ADMIN); + + //get the fee applied + uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //fee should be half the default + assertEq(discount, FEE_SCALAR / 2); + } + + function test_DiscountIsReturnedForNative() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //get the discount applied + uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be half the default + assertEq(discount, FEE_SCALAR / 2); + } + + function test_DiscountIsReturnedForNativeWithSurcharge() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //set the surcharge + setNativeSurcharge(FEE_SCALAR / 5, ADMIN); + + //get the discount applied + uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be half the default + assertEq(discount, FEE_SCALAR / 2); + } + + function test_GlobalDiscountWithNative() public { + //set the global discount to 50% + setSubscriberGlobalDiscount(USER, address(native), FEE_SCALAR / 2, ADMIN); + + //get the discount applied + uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be half the default + assertEq(discount, FEE_SCALAR / 2); + } + + function test_GlobalDiscountWithLink() public { + //set the global discount to 50% + setSubscriberGlobalDiscount(USER, address(link), FEE_SCALAR / 2, ADMIN); + + //get the discount applied + uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //fee should be half the default + assertEq(discount, FEE_SCALAR / 2); + } + + function test_GlobalDiscountWithNativeAndLink() public { + //set the global discount to 50% + setSubscriberGlobalDiscount(USER, address(native), FEE_SCALAR / 2, ADMIN); + setSubscriberGlobalDiscount(USER, address(link), FEE_SCALAR / 2, ADMIN); + + //get the discount applied + uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //fee should be half the default + assertEq(discount, FEE_SCALAR / 2); + } + + function test_GlobalDiscountIsOverridenByIndividualDiscountNative() public { + //set the global discount to 50% + setSubscriberGlobalDiscount(USER, address(native), FEE_SCALAR / 2, ADMIN); + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 4, ADMIN); + + //get the discount applied + uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be half the default + assertEq(discount, FEE_SCALAR / 4); + } + + function test_GlobalDiscountIsOverridenByIndividualDiscountLink() public { + //set the global discount to 50% + setSubscriberGlobalDiscount(USER, address(link), FEE_SCALAR / 2, ADMIN); + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 4, ADMIN); + + //get the discount applied + uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //fee should be half the default + assertEq(discount, FEE_SCALAR / 4); + } + + function test_GlobalDiscountIsUpdatedAfterBeingSetToZeroLink() public { + //set the global discount to 50% + setSubscriberGlobalDiscount(USER, address(link), FEE_SCALAR / 2, ADMIN); + + //get the discount applied + uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //fee should be half the default + assertEq(discount, FEE_SCALAR / 2); + + //set the global discount to zero + setSubscriberGlobalDiscount(USER, address(link), 0, ADMIN); + + //get the discount applied + discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //fee should be zero + assertEq(discount, 0); + } + + function test_GlobalDiscountIsUpdatedAfterBeingSetToZeroNative() public { + //set the global discount to 50% + setSubscriberGlobalDiscount(USER, address(native), FEE_SCALAR / 2, ADMIN); + + //get the discount applied + uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be half the default + assertEq(discount, FEE_SCALAR / 2); + + //set the global discount to zero + setSubscriberGlobalDiscount(USER, address(native), 0, ADMIN); + + //get the discount applied + discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be zero + assertEq(discount, 0); + } + + function test_GlobalDiscountCantBeSetToMoreThanMaximum() public { + //should revert with invalid discount + vm.expectRevert(INVALID_DISCOUNT_ERROR); + + //set the global discount to 101% + setSubscriberGlobalDiscount(USER, address(native), FEE_SCALAR + 1, ADMIN); + } + + function test_onlyOwnerCanSetGlobalDiscount() public { + //should revert with unauthorized + vm.expectRevert(ONLY_CALLABLE_BY_OWNER_ERROR); + + //set the global discount to 50% + setSubscriberGlobalDiscount(USER, address(native), FEE_SCALAR / 2, USER); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/test/fee-manager/FeeManager.processFee.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/test/fee-manager/FeeManager.processFee.t.sol new file mode 100644 index 00000000000..62571946e47 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/test/fee-manager/FeeManager.processFee.t.sol @@ -0,0 +1,492 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {Common} from "../../../libraries/Common.sol"; +import "./BaseFeeManager.t.sol"; +import {IRewardManager} from "../../interfaces/IRewardManager.sol"; + +/** + * @title BaseFeeManagerTest + * @author Michael Fletcher + * @notice This contract will test the functionality of the feeManager processFee + */ +contract FeeManagerProcessFeeTestV05 is BaseFeeManagerTest { + function setUp() public override { + super.setUp(); + } + + function test_nonAdminProxyUserCannotProcessFee() public { + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //should revert as the user is not the owner + vm.expectRevert(UNAUTHORIZED_ERROR); + + //process the fee + ProcessFeeAsUser(payload, USER, address(link), 0, USER); + } + + function test_processFeeAsProxy() public { + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //approve the link to be transferred from the from the subscriber to the rewardManager + approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); + + //processing the fee will transfer the link from the user to the rewardManager + processFee(payload, USER, address(link), 0); + + //check the link has been transferred + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + + //check the user has had the link fee deducted + assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE); + } + + function test_processFeeIfSubscriberIsSelf() public { + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //expect a revert due to the feeManager being the subscriber + vm.expectRevert(INVALID_ADDRESS_ERROR); + + //process the fee will fail due to assertion + processFee(payload, address(feeManager), address(native), 0); + } + + function test_processFeeWithWithEmptyQuotePayload() public { + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //expect a revert as the quote is invalid + vm.expectRevert(); + + //processing the fee will transfer the link by default + processFee(payload, USER, address(0), 0); + } + + function test_processFeeWithWithZeroQuotePayload() public { + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //expect a revert as the quote is invalid + vm.expectRevert(INVALID_QUOTE_ERROR); + + //processing the fee will transfer the link by default + processFee(payload, USER, INVALID_ADDRESS, 0); + } + + function test_processFeeWithWithCorruptQuotePayload() public { + //get the default payload + bytes memory payload = abi.encode( + [DEFAULT_CONFIG_DIGEST, 0, 0], + getV3Report(DEFAULT_FEED_1_V3), + new bytes32[](1), + new bytes32[](1), + bytes32("") + ); + + //expect an evm revert as the quote is corrupt + vm.expectRevert(); + + //processing the fee will not withdraw anything as there is no fee to collect + processFee(payload, USER, address(link), 0); + } + + function test_processFeeDefaultReportsStillVerifiesWithEmptyQuote() public { + //get the default payload + bytes memory payload = getPayload(getV1Report(DEFAULT_FEED_1_V1)); + + //processing the fee will transfer the link from the user to the rewardManager + processFee(payload, USER, address(0), 0); + } + + function test_processFeeWithDefaultReportPayloadAndQuoteStillVerifies() public { + //get the default payload + bytes memory payload = getPayload(getV1Report(DEFAULT_FEED_1_V1)); + + //processing the fee will not withdraw anything as there is no fee to collect + processFee(payload, USER, address(link), 0); + } + + function test_processFeeNative() public { + //simulate a deposit of link for the conversion pool + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //approve the native to be transferred from the user + approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); + + //processing the fee will transfer the native from the user to the feeManager + processFee(payload, USER, address(native), 0); + + //check the native has been transferred + assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE); + + //check the link has been transferred to the rewardManager + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + + //check the feeManager has had the link deducted, the remaining balance should be 0 + assertEq(getLinkBalance(address(feeManager)), 0); + + //check the subscriber has had the native deducted + assertEq(getNativeBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); + } + + function test_processFeeEmitsEventIfNotEnoughLink() public { + //simulate a deposit of half the link required for the fee + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE / 2); + + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //approve the native to be transferred from the user + approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); + + //expect an emit as there's not enough link + vm.expectEmit(); + + IRewardManager.FeePayment[] memory contractFees = new IRewardManager.FeePayment[](1); + contractFees[0] = IRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); + + //emit the event that is expected to be emitted + emit InsufficientLink(contractFees); + + //processing the fee will transfer the native from the user to the feeManager + processFee(payload, USER, address(native), 0); + + //check the native has been transferred + assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE); + + //check no link has been transferred to the rewardManager + assertEq(getLinkBalance(address(rewardManager)), 0); + assertEq(getLinkBalance(address(feeManager)), DEFAULT_REPORT_LINK_FEE / 2); + + //check the subscriber has had the native deducted + assertEq(getNativeBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); + } + + function test_processFeeWithUnwrappedNative() public { + //simulate a deposit of link for the conversion pool + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //only the proxy or admin can call processFee, they will pass in the native value on the users behalf + processFee(payload, USER, address(native), DEFAULT_REPORT_NATIVE_FEE); + + //check the native has been transferred and converted to wrapped native + assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE); + assertEq(getNativeUnwrappedBalance(address(feeManager)), 0); + + //check the link has been transferred to the rewardManager + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + + //check the feeManager has had the link deducted, the remaining balance should be 0 + assertEq(getLinkBalance(address(feeManager)), 0); + + //check the subscriber has had the native deducted + assertEq(getNativeUnwrappedBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); + } + + function test_processFeeWithUnwrappedNativeShortFunds() public { + //simulate a deposit of link for the conversion pool + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //expect a revert as not enough funds + vm.expectRevert(INVALID_DEPOSIT_ERROR); + + //only the proxy or admin can call processFee, they will pass in the native value on the users behalf + processFee(payload, USER, address(native), DEFAULT_REPORT_NATIVE_FEE - 1); + } + + function test_processFeeWithUnwrappedNativeLinkAddress() public { + //simulate a deposit of link for the conversion pool + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //expect a revert as not enough funds + vm.expectRevert(INSUFFICIENT_ALLOWANCE_ERROR); + + //the change will be returned and the user will attempted to be billed in LINK + processFee(payload, USER, address(link), DEFAULT_REPORT_NATIVE_FEE - 1); + } + + function test_processFeeWithUnwrappedNativeLinkAddressExcessiveFee() public { + //approve the link to be transferred from the from the subscriber to the rewardManager + approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, PROXY); + + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //call processFee from the proxy to test whether the funds are returned to the subscriber. In reality, the funds would be returned to the caller of the proxy. + processFee(payload, PROXY, address(link), DEFAULT_REPORT_NATIVE_FEE); + + //check the native unwrapped is no longer in the account + assertEq(getNativeBalance(address(feeManager)), 0); + assertEq(getNativeUnwrappedBalance(address(feeManager)), 0); + + //check the link has been transferred to the rewardManager + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + + //check the feeManager has had the link deducted, the remaining balance should be 0 + assertEq(getLinkBalance(address(feeManager)), 0); + + //native should not be deducted + assertEq(getNativeUnwrappedBalance(PROXY), DEFAULT_NATIVE_MINT_QUANTITY); + } + + function test_processFeeWithUnwrappedNativeWithExcessiveFee() public { + //simulate a deposit of link for the conversion pool + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //call processFee from the proxy to test whether the funds are returned to the subscriber. In reality, the funds would be returned to the caller of the proxy. + processFee(payload, PROXY, address(native), DEFAULT_REPORT_NATIVE_FEE * 2); + + //check the native has been transferred and converted to wrapped native + assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE); + assertEq(getNativeUnwrappedBalance(address(feeManager)), 0); + + //check the link has been transferred to the rewardManager + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + + //check the feeManager has had the link deducted, the remaining balance should be 0 + assertEq(getLinkBalance(address(feeManager)), 0); + + //check the subscriber has had the native deducted + assertEq(getNativeUnwrappedBalance(PROXY), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); + } + + function test_processFeeUsesCorrectDigest() public { + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //approve the link to be transferred from the from the subscriber to the rewardManager + approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); + + //processing the fee will transfer the link from the user to the rewardManager + processFee(payload, USER, address(link), 0); + + //check the link has been transferred + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + + //check the user has had the link fee deducted + assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE); + + //check funds have been paid to the reward manager + assertEq(rewardManager.s_totalRewardRecipientFees(DEFAULT_CONFIG_DIGEST), DEFAULT_REPORT_LINK_FEE); + } + + function test_V1PayloadVerifies() public { + //replicate a default payload + bytes memory payload = abi.encode( + [DEFAULT_CONFIG_DIGEST, 0, 0], + getV2Report(DEFAULT_FEED_1_V1), + new bytes32[](1), + new bytes32[](1), + bytes32("") + ); + + //processing the fee will transfer the link from the user to the rewardManager + processFee(payload, USER, address(0), 0); + } + + function test_V2PayloadVerifies() public { + //get the default payload + bytes memory payload = getPayload(getV2Report(DEFAULT_FEED_1_V2)); + + //approve the link to be transferred from the from the subscriber to the rewardManager + approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); + + //processing the fee will transfer the link from the user to the rewardManager + processFee(payload, USER, address(link), 0); + + //check the link has been transferred + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + + //check the user has had the link fee deducted + assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE); + } + + function test_V2PayloadWithoutQuoteFails() public { + //get the default payload + bytes memory payload = getPayload(getV2Report(DEFAULT_FEED_1_V2)); + + //expect a revert as the quote is invalid + vm.expectRevert(); + + //processing the fee will transfer the link from the user to the rewardManager + processFee(payload, USER, address(0), 0); + } + + function test_V2PayloadWithoutZeroFee() public { + //get the default payload + bytes memory payload = getPayload(getV2Report(DEFAULT_FEED_1_V2)); + + //expect a revert as the quote is invalid + vm.expectRevert(); + + //processing the fee will transfer the link from the user to the rewardManager + processFee(payload, USER, address(link), 0); + } + + function test_processFeeWithInvalidReportVersionFailsToDecode() public { + bytes memory data = abi.encode(0x0000100000000000000000000000000000000000000000000000000000000000); + + //get the default payload + bytes memory payload = getPayload(data); + + //serialization will fail as there is no report to decode + vm.expectRevert(); + + //processing the fee will not withdraw anything as there is no fee to collect + processFee(payload, USER, address(link), 0); + } + + function test_processFeeWithZeroNativeNonZeroLinkWithNativeQuote() public { + //get the default payload + bytes memory payload = getPayload( + getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, block.timestamp, DEFAULT_REPORT_LINK_FEE, 0) + ); + + //call processFee should not revert as the fee is 0 + processFee(payload, PROXY, address(native), 0); + } + + function test_processFeeWithZeroNativeNonZeroLinkWithLinkQuote() public { + //get the default payload + bytes memory payload = getPayload( + getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, block.timestamp, DEFAULT_REPORT_LINK_FEE, 0) + ); + + //approve the link to be transferred from the from the subscriber to the rewardManager + approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); + + //processing the fee will transfer the link to the rewardManager from the user + processFee(payload, USER, address(link), 0); + + //check the link has been transferred + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + + //check the user has had the link fee deducted + assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE); + } + + function test_processFeeWithZeroLinkNonZeroNativeWithNativeQuote() public { + //simulate a deposit of link for the conversion pool + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + //get the default payload + bytes memory payload = getPayload( + getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, block.timestamp, 0, DEFAULT_REPORT_NATIVE_FEE) + ); + + //approve the native to be transferred from the user + approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); + + //processing the fee will transfer the native from the user to the feeManager + processFee(payload, USER, address(native), 0); + + //check the native has been transferred + assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE); + + //check no link has been transferred to the rewardManager + assertEq(getLinkBalance(address(rewardManager)), 0); + + //check the feeManager has had no link deducted + assertEq(getLinkBalance(address(feeManager)), DEFAULT_REPORT_LINK_FEE); + + //check the subscriber has had the native deducted + assertEq(getNativeBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); + } + + function test_processFeeWithZeroLinkNonZeroNativeWithLinkQuote() public { + //get the default payload + bytes memory payload = getPayload( + getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, block.timestamp, 0, DEFAULT_REPORT_NATIVE_FEE) + ); + + //call processFee should not revert as the fee is 0 + processFee(payload, USER, address(link), 0); + } + + function test_processFeeWithZeroNativeNonZeroLinkReturnsChange() public { + //get the default payload + bytes memory payload = getPayload( + getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, block.timestamp, 0, DEFAULT_REPORT_NATIVE_FEE) + ); + + //call processFee should not revert as the fee is 0 + processFee(payload, USER, address(link), DEFAULT_REPORT_NATIVE_FEE); + + //check the change has been returned + assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY); + } + + function test_V1PayloadVerifiesAndReturnsChange() public { + //emulate a V1 payload with no quote + bytes memory payload = getPayload(getV1Report(DEFAULT_FEED_1_V1)); + + processFee(payload, USER, address(0), DEFAULT_REPORT_NATIVE_FEE); + + //Fee manager should not contain any native + assertEq(address(feeManager).balance, 0); + assertEq(getNativeBalance(address(feeManager)), 0); + + //check the unused native passed in is returned + assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY); + } + + function test_processFeeWithDiscountEmitsEvent() public { + //simulate a deposit of link for the conversion pool + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //approve the native to be transferred from the user + approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE / 2, USER); + + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + uint256 appliedDiscount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + vm.expectEmit(); + + emit DiscountApplied(DEFAULT_CONFIG_DIGEST, USER, fee, reward, appliedDiscount); + + //call processFee should not revert as the fee is 0 + processFee(payload, USER, address(native), 0); + } + + function test_processFeeWithNoDiscountDoesNotEmitEvent() public { + //simulate a deposit of link for the conversion pool + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + //approve the native to be transferred from the user + approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); + + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //call processFee should not revert as the fee is 0 + processFee(payload, USER, address(native), 0); + + //no logs should have been emitted + assertEq(vm.getRecordedLogs().length, 0); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/test/fee-manager/FeeManager.processFeeBulk.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/test/fee-manager/FeeManager.processFeeBulk.t.sol new file mode 100644 index 00000000000..ce048481485 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/test/fee-manager/FeeManager.processFeeBulk.t.sol @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import "./BaseFeeManager.t.sol"; +import {IRewardManager} from "../../interfaces/IRewardManager.sol"; + +/** + * @title BaseFeeManagerTest + * @author Michael Fletcher + * @notice This contract will test the functionality of the feeManager processFee + */ +contract FeeManagerProcessFeeTestV05 is BaseFeeManagerTest { + uint256 internal constant NUMBER_OF_REPORTS = 5; + + function setUp() public override { + super.setUp(); + } + + function test_processMultipleLinkReports() public { + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + bytes[] memory payloads = new bytes[](NUMBER_OF_REPORTS); + for (uint256 i = 0; i < NUMBER_OF_REPORTS; ++i) { + payloads[i] = payload; + } + + approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS, USER); + + processFee(payloads, USER, address(link), DEFAULT_NATIVE_MINT_QUANTITY); + + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS); + assertEq(getLinkBalance(address(feeManager)), 0); + assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS); + + //the subscriber (user) should receive funds back and not the proxy, although when live the proxy will forward the funds sent and not cover it seen here + assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY); + assertEq(PROXY.balance, DEFAULT_NATIVE_MINT_QUANTITY); + } + + function test_processMultipleWrappedNativeReports() public { + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS + 1); + + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + bytes[] memory payloads = new bytes[](NUMBER_OF_REPORTS); + for (uint256 i; i < NUMBER_OF_REPORTS; ++i) { + payloads[i] = payload; + } + + approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS, USER); + + processFee(payloads, USER, address(native), 0); + + assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS); + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS); + assertEq(getLinkBalance(address(feeManager)), 1); + assertEq(getNativeBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS); + } + + function test_processMultipleUnwrappedNativeReports() public { + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS + 1); + + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + bytes[] memory payloads = new bytes[](NUMBER_OF_REPORTS); + for (uint256 i; i < NUMBER_OF_REPORTS; ++i) { + payloads[i] = payload; + } + + processFee(payloads, USER, address(native), DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS * 2); + + assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS); + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS); + assertEq(getLinkBalance(address(feeManager)), 1); + + assertEq(PROXY.balance, DEFAULT_NATIVE_MINT_QUANTITY); + assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS); + } + + function test_processV1V2V3Reports() public { + mintLink(address(feeManager), 1); + + bytes memory payloadV1 = abi.encode( + [DEFAULT_CONFIG_DIGEST, 0, 0], + getV1Report(DEFAULT_FEED_1_V1), + new bytes32[](1), + new bytes32[](1), + bytes32("") + ); + + bytes memory linkPayloadV2 = getPayload(getV2Report(DEFAULT_FEED_1_V2)); + bytes memory linkPayloadV3 = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + bytes[] memory payloads = new bytes[](5); + payloads[0] = payloadV1; + payloads[1] = linkPayloadV2; + payloads[2] = linkPayloadV2; + payloads[3] = linkPayloadV3; + payloads[4] = linkPayloadV3; + + approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE * 4, USER); + + processFee(payloads, USER, address(link), 0); + + assertEq(getNativeBalance(address(feeManager)), 0); + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * 4); + assertEq(getLinkBalance(address(feeManager)), 1); + + assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE * 4); + assertEq(getNativeBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - 0); + } + + function test_processV1V2V3ReportsWithUnwrapped() public { + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE * 4 + 1); + + bytes memory payloadV1 = abi.encode( + [DEFAULT_CONFIG_DIGEST, 0, 0], + getV1Report(DEFAULT_FEED_1_V1), + new bytes32[](1), + new bytes32[](1), + bytes32("") + ); + + bytes memory nativePayloadV2 = getPayload(getV2Report(DEFAULT_FEED_1_V2)); + bytes memory nativePayloadV3 = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + bytes[] memory payloads = new bytes[](5); + payloads[0] = payloadV1; + payloads[1] = nativePayloadV2; + payloads[2] = nativePayloadV2; + payloads[3] = nativePayloadV3; + payloads[4] = nativePayloadV3; + + processFee(payloads, USER, address(native), DEFAULT_REPORT_NATIVE_FEE * 4); + + assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE * 4); + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * 4); + assertEq(getLinkBalance(address(feeManager)), 1); + + assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * 4); + assertEq(PROXY.balance, DEFAULT_NATIVE_MINT_QUANTITY); + } + + function test_processMultipleV1Reports() public { + bytes memory payload = abi.encode( + [DEFAULT_CONFIG_DIGEST, 0, 0], + getV1Report(DEFAULT_FEED_1_V1), + new bytes32[](1), + new bytes32[](1), + bytes32("") + ); + + bytes[] memory payloads = new bytes[](NUMBER_OF_REPORTS); + for (uint256 i = 0; i < NUMBER_OF_REPORTS; ++i) { + payloads[i] = payload; + } + + processFee(payloads, USER, address(native), DEFAULT_REPORT_NATIVE_FEE * 5); + + assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY); + assertEq(PROXY.balance, DEFAULT_NATIVE_MINT_QUANTITY); + } + + function test_eventIsEmittedIfNotEnoughLink() public { + bytes memory nativePayload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + bytes[] memory payloads = new bytes[](5); + payloads[0] = nativePayload; + payloads[1] = nativePayload; + payloads[2] = nativePayload; + payloads[3] = nativePayload; + payloads[4] = nativePayload; + + approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE * 5, USER); + + IRewardManager.FeePayment[] memory payments = new IRewardManager.FeePayment[](5); + payments[0] = IRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); + payments[1] = IRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); + payments[2] = IRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); + payments[3] = IRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); + payments[4] = IRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); + + vm.expectEmit(); + + emit InsufficientLink(payments); + + processFee(payloads, USER, address(native), 0); + + assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE * 5); + assertEq(getNativeBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * 5); + assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/test/gas/Gas_VerifierTest.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/test/gas/Gas_VerifierTest.t.sol new file mode 100644 index 00000000000..c56c2dca284 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/test/gas/Gas_VerifierTest.t.sol @@ -0,0 +1,234 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTest, BaseTestWithConfiguredVerifierAndFeeManager} from "../verifier/BaseVerifierTest.t.sol"; +import {SimpleWriteAccessController} from "../../../../shared/access/SimpleWriteAccessController.sol"; +import {Common} from "../../../libraries/Common.sol"; +import {IRewardManager} from "../../interfaces/IRewardManager.sol"; + +contract Verifier_setConfigV05 is BaseTest { + address[] internal s_signerAddrs; + + function setUp() public override { + BaseTest.setUp(); + Signer[] memory signers = _getSigners(MAX_ORACLES); + s_signerAddrs = _getSignerAddresses(signers); + s_verifierProxy.initializeVerifier(address(s_verifier)); + } + + function testSetConfigSuccess_gas() public { + bytes32 configDigest = _configDigestFromConfigData( + FEED_ID, + SOURCE_CHAIN_ID, + SOURCE_ADDRESS, + 1, + s_signerAddrs, + s_offchaintransmitters, + FAULT_TOLERANCE, + bytes(""), + 1, + bytes("") + ); + + s_verifier.setConfig(configDigest, s_signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + } +} + +contract Verifier_verifyWithFeeV05 is BaseTestWithConfiguredVerifierAndFeeManager { + uint256 internal constant DEFAULT_LINK_MINT_QUANTITY = 100 ether; + uint256 internal constant DEFAULT_NATIVE_MINT_QUANTITY = 100 ether; + + function setUp() public virtual override { + super.setUp(); + + //mint some link and eth to warm the storage + link.mint(address(rewardManager), DEFAULT_LINK_MINT_QUANTITY); + native.mint(address(feeManager), DEFAULT_NATIVE_MINT_QUANTITY); + + //warm the rewardManager + link.mint(address(this), DEFAULT_NATIVE_MINT_QUANTITY); + _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, address(this)); + bytes32 latestConfigDigest = v1ConfigDigest; + + //mint some tokens to the user + link.mint(USER, DEFAULT_LINK_MINT_QUANTITY); + native.mint(USER, DEFAULT_NATIVE_MINT_QUANTITY); + vm.deal(USER, DEFAULT_NATIVE_MINT_QUANTITY); + + //mint some link tokens to the feeManager pool + link.mint(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + //approve funds prior to test + _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); + _approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); + + IRewardManager.FeePayment[] memory payments = new IRewardManager.FeePayment[](1); + payments[0] = IRewardManager.FeePayment(latestConfigDigest, uint192(DEFAULT_REPORT_LINK_FEE)); + + changePrank(address(feeManager)); + rewardManager.onFeePaid(payments, address(this)); + + changePrank(USER); + } + + function testVerifyProxyWithLinkFeeSuccess_gas() public { + bytes memory signedLinkPayload = _generateV3EncodedBlob( + _generateV3Report(), + _generateReportContext(v3ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + s_verifierProxy.verify(signedLinkPayload, abi.encode(link)); + } + + function testVerifyProxyWithNativeFeeSuccess_gas() public { + bytes memory signedNativePayload = _generateV3EncodedBlob( + _generateV3Report(), + _generateReportContext(v3ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + s_verifierProxy.verify(signedNativePayload, abi.encode(native)); + } +} + +contract Verifier_bulkVerifyWithFeeV05 is BaseTestWithConfiguredVerifierAndFeeManager { + uint256 internal constant DEFAULT_LINK_MINT_QUANTITY = 100 ether; + uint256 internal constant DEFAULT_NATIVE_MINT_QUANTITY = 100 ether; + uint256 internal constant NUMBER_OF_REPORTS_TO_VERIFY = 5; + + function setUp() public virtual override { + super.setUp(); + + //mint some link and eth to warm the storage + link.mint(address(rewardManager), DEFAULT_LINK_MINT_QUANTITY); + native.mint(address(feeManager), DEFAULT_NATIVE_MINT_QUANTITY); + + //warm the rewardManager + link.mint(address(this), DEFAULT_NATIVE_MINT_QUANTITY); + _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, address(this)); + bytes32 latestConfigDigest = v1ConfigDigest; + + //mint some tokens to the user + link.mint(USER, DEFAULT_LINK_MINT_QUANTITY); + native.mint(USER, DEFAULT_NATIVE_MINT_QUANTITY); + vm.deal(USER, DEFAULT_NATIVE_MINT_QUANTITY); + + //mint some link tokens to the feeManager pool + link.mint(address(feeManager), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS_TO_VERIFY); + + //approve funds prior to test + _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS_TO_VERIFY, USER); + _approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS_TO_VERIFY, USER); + + IRewardManager.FeePayment[] memory payments = new IRewardManager.FeePayment[](1); + payments[0] = IRewardManager.FeePayment(latestConfigDigest, uint192(DEFAULT_REPORT_LINK_FEE)); + + changePrank(address(feeManager)); + rewardManager.onFeePaid(payments, address(this)); + + changePrank(USER); + } + + function testBulkVerifyProxyWithLinkFeeSuccess_gas() public { + bytes memory signedLinkPayload = _generateV3EncodedBlob( + _generateV3Report(), + _generateReportContext(v3ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + bytes[] memory signedLinkPayloads = new bytes[](NUMBER_OF_REPORTS_TO_VERIFY); + for (uint256 i = 0; i < NUMBER_OF_REPORTS_TO_VERIFY; i++) { + signedLinkPayloads[i] = signedLinkPayload; + } + + s_verifierProxy.verifyBulk(signedLinkPayloads, abi.encode(link)); + } + + function testBulkVerifyProxyWithNativeFeeSuccess_gas() public { + bytes memory signedNativePayload = _generateV3EncodedBlob( + _generateV3Report(), + _generateReportContext(v3ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + bytes[] memory signedNativePayloads = new bytes[](NUMBER_OF_REPORTS_TO_VERIFY); + for (uint256 i = 0; i < NUMBER_OF_REPORTS_TO_VERIFY; i++) { + signedNativePayloads[i] = signedNativePayload; + } + + s_verifierProxy.verifyBulk(signedNativePayloads, abi.encode(native)); + } +} + +contract Verifier_verifyV05 is BaseTestWithConfiguredVerifierAndFeeManager { + bytes internal s_signedReport; + bytes32 internal s_configDigest; + + function setUp() public override { + BaseTestWithConfiguredVerifierAndFeeManager.setUp(); + BaseTest.V1Report memory s_testReportOne = _createV1Report( + FEED_ID, + OBSERVATIONS_TIMESTAMP, + MEDIAN, + BID, + ASK, + BLOCKNUMBER_UPPER_BOUND, + blockhash(BLOCKNUMBER_UPPER_BOUND), + BLOCKNUMBER_LOWER_BOUND, + uint32(block.timestamp) + ); + s_configDigest = v1ConfigDigest; + bytes32[3] memory reportContext; + reportContext[0] = s_configDigest; + reportContext[1] = bytes32(abi.encode(uint32(5), uint8(1))); + s_signedReport = _generateV1EncodedBlob(s_testReportOne, reportContext, _getSigners(FAULT_TOLERANCE + 1)); + } + + function testVerifySuccess_gas() public { + changePrank(address(s_verifierProxy)); + + s_verifier.verify(s_signedReport, msg.sender); + } + + function testVerifyProxySuccess_gas() public { + s_verifierProxy.verify(s_signedReport, abi.encode(native)); + } +} + +contract Verifier_accessControlledVerifyV05 is BaseTestWithConfiguredVerifierAndFeeManager { + bytes internal s_signedReport; + bytes32 internal s_configDigest; + SimpleWriteAccessController s_accessController; + + address internal constant CLIENT = address(9000); + address internal constant ACCESS_CONTROLLER_ADDR = address(10000); + + function setUp() public override { + BaseTestWithConfiguredVerifierAndFeeManager.setUp(); + BaseTest.V1Report memory s_testReportOne = _createV1Report( + FEED_ID, + OBSERVATIONS_TIMESTAMP, + MEDIAN, + BID, + ASK, + BLOCKNUMBER_UPPER_BOUND, + blockhash(BLOCKNUMBER_UPPER_BOUND), + BLOCKNUMBER_LOWER_BOUND, + uint32(block.timestamp) + ); + s_configDigest = v1ConfigDigest; + bytes32[3] memory reportContext; + reportContext[0] = s_configDigest; + reportContext[1] = bytes32(abi.encode(uint32(5), uint8(1))); + s_signedReport = _generateV1EncodedBlob(s_testReportOne, reportContext, _getSigners(FAULT_TOLERANCE + 1)); + s_accessController = new SimpleWriteAccessController(); + s_verifierProxy.setAccessController(s_accessController); + s_accessController.addAccess(CLIENT); + } + + function testVerifyWithAccessControl_gas() public { + changePrank(CLIENT); + s_verifierProxy.verify(s_signedReport, abi.encode(native)); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/test/mocks/ErroredVerifier.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/test/mocks/ErroredVerifier.sol new file mode 100644 index 00000000000..2313ac6dd72 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/test/mocks/ErroredVerifier.sol @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {IVerifier} from "../../interfaces/IVerifier.sol"; +import {Common} from "../../../libraries/Common.sol"; + +contract ErroredVerifier is IVerifier { + function supportsInterface(bytes4 interfaceId) public pure override returns (bool) { + return interfaceId == this.verify.selector; + } + + //define each of the errors thrown in the revert below + + error FailedToVerify(); + error FailedToSetConfig(); + error FailedToUnsetConfig(); + error FailedToActivateConfig(); + error FailedToDeactivateConfig(); + error FailedToActivateFeed(); + error FailedToDeactivateFeed(); + error FailedToGetLatestConfigDigestAndEpoch(); + error FailedToGetLatestConfigDetails(); + + function verify( + bytes memory, + /** + * signedReport* + */ + address + ) + external + pure + override + returns ( + /** + * sender* + */ + bytes memory + ) + { + revert FailedToVerify(); + } + + function updateConfig(bytes32, address[] calldata, address[] calldata, uint8) external pure { + revert FailedToUnsetConfig(); + } + + function setConfig(bytes32, address[] calldata, uint8, Common.AddressAndWeight[] calldata) external pure override { + revert FailedToSetConfig(); + } + + function activateConfig(bytes32) external pure { + revert FailedToActivateConfig(); + } + + function deactivateConfig(bytes32) external pure { + revert FailedToDeactivateConfig(); + } + + function latestConfigDetails(bytes32) external pure override returns (uint32) { + revert FailedToGetLatestConfigDetails(); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/test/mocks/ExposedVerifier.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/test/mocks/ExposedVerifier.sol new file mode 100644 index 00000000000..1c004bf3846 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/test/mocks/ExposedVerifier.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +// ExposedVerifier exposes certain internal Verifier +// methods/structures so that golang code can access them, and we get +// reliable type checking on their usage +contract ExposedVerifier { + constructor() {} + + function _configDigestFromConfigData( + bytes32 feedId, + uint256 chainId, + address contractAddress, + uint64 configCount, + address[] memory signers, + bytes32[] memory offchainTransmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) internal pure returns (bytes32) { + uint256 h = uint256( + keccak256( + abi.encode( + feedId, + chainId, + contractAddress, + configCount, + signers, + offchainTransmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig + ) + ) + ); + uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 + uint256 prefix = 0x0006 << (256 - 16); // 0x000600..00 + return bytes32((prefix & prefixMask) | (h & ~prefixMask)); + } + + function exposedConfigDigestFromConfigData( + bytes32 _feedId, + uint256 _chainId, + address _contractAddress, + uint64 _configCount, + address[] memory _signers, + bytes32[] memory _offchainTransmitters, + uint8 _f, + bytes calldata _onchainConfig, + uint64 _encodedConfigVersion, + bytes memory _encodedConfig + ) public pure returns (bytes32) { + return + _configDigestFromConfigData( + _feedId, + _chainId, + _contractAddress, + _configCount, + _signers, + _offchainTransmitters, + _f, + _onchainConfig, + _encodedConfigVersion, + _encodedConfig + ); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/test/mocks/FeeManagerProxy.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/test/mocks/FeeManagerProxy.sol new file mode 100644 index 00000000000..9abb4c50c29 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/test/mocks/FeeManagerProxy.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IFeeManager} from "../../interfaces/IFeeManager.sol"; + +contract FeeManagerProxy { + IFeeManager internal s_feeManager; + + function processFee(bytes calldata payload, bytes calldata parameterPayload) public payable { + s_feeManager.processFee{value: msg.value}(payload, parameterPayload, msg.sender); + } + + function processFeeBulk(bytes[] calldata payloads, bytes calldata parameterPayload) public payable { + s_feeManager.processFeeBulk{value: msg.value}(payloads, parameterPayload, msg.sender); + } + + function setFeeManager(IFeeManager feeManager) public { + s_feeManager = feeManager; + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/test/mocks/MockConfigurator.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/test/mocks/MockConfigurator.sol new file mode 100644 index 00000000000..85c41194db0 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/test/mocks/MockConfigurator.sol @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +// Derived from v0.5/Configurator.sol +contract MockConfigurator { + struct ConfigurationState { + uint64 configCount; + uint32 latestConfigBlockNumber; + bytes32 configDigest; + } + + mapping(bytes32 => ConfigurationState) public s_configurationStates; + + function setStagingConfig( + bytes32 configId, + bytes[] memory signers, + bytes32[] memory offchainTransmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) external { + ConfigurationState storage configurationState = s_configurationStates[configId]; + + uint64 newConfigCount = ++configurationState.configCount; + + bytes32 configDigest = _configDigestFromConfigData( + configId, + block.chainid, + address(this), + newConfigCount, + signers, + offchainTransmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig + ); + + s_configurationStates[configId].configDigest = configDigest; + configurationState.latestConfigBlockNumber = uint32(block.number); + } + + function _configDigestFromConfigData( + bytes32 configId, + uint256 sourceChainId, + address sourceAddress, + uint64 configCount, + bytes[] memory signers, + bytes32[] memory offchainTransmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) internal pure returns (bytes32) { + uint256 h = uint256( + keccak256( + abi.encode( + configId, + sourceChainId, + sourceAddress, + configCount, + signers, + offchainTransmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig + ) + ) + ); + uint256 prefixMask = type(uint256).max << (256 - 16); + uint256 prefix = 0x0009 << (256 - 16); + return bytes32((prefix & prefixMask) | (h & ~prefixMask)); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/test/reward-manager/BaseRewardManager.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/test/reward-manager/BaseRewardManager.t.sol new file mode 100644 index 00000000000..b002342b411 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/test/reward-manager/BaseRewardManager.t.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {Test} from "forge-std/Test.sol"; +import {ERC20Mock} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol"; +import {RewardManager} from "../../RewardManager.sol"; +import {Common} from "../../../libraries/Common.sol"; +import {IRewardManager} from "../../interfaces/IRewardManager.sol"; + +/** + * @title BaseRewardManagerTest + * @author Michael Fletcher + * @notice Base class for all reward manager tests + * @dev This contract is intended to be inherited from and not used directly. It contains functionality to setup a primary and secondary pool + */ +contract BaseRewardManagerTest is Test { + //contracts + ERC20Mock internal asset; + ERC20Mock internal unsupported; + RewardManager internal rewardManager; + + //default address for unregistered recipient + address internal constant INVALID_ADDRESS = address(0); + //contract owner + address internal constant ADMIN = address(uint160(uint256(keccak256("ADMIN")))); + //address to represent verifier contract + address internal constant FEE_MANAGER = address(uint160(uint256(keccak256("FEE_MANAGER")))); + //a general user + address internal constant USER = address(uint160(uint256(keccak256("USER")))); + + //default recipients configured in reward manager + address internal constant DEFAULT_RECIPIENT_1 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_1")))); + address internal constant DEFAULT_RECIPIENT_2 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_2")))); + address internal constant DEFAULT_RECIPIENT_3 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_3")))); + address internal constant DEFAULT_RECIPIENT_4 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_4")))); + address internal constant DEFAULT_RECIPIENT_5 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_5")))); + address internal constant DEFAULT_RECIPIENT_6 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_6")))); + address internal constant DEFAULT_RECIPIENT_7 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_7")))); + + //additional recipients not in the reward manager + address internal constant DEFAULT_RECIPIENT_8 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_8")))); + address internal constant DEFAULT_RECIPIENT_9 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_9")))); + + //two pools should be enough to test all edge cases + bytes32 internal constant PRIMARY_POOL_ID = keccak256("primary_pool"); + bytes32 internal constant SECONDARY_POOL_ID = keccak256("secondary_pool"); + bytes32 internal constant INVALID_POOL_ID = keccak256("invalid_pool"); + bytes32 internal constant ZERO_POOL_ID = bytes32(0); + + //convenience arrays of all pool combinations used for testing + bytes32[] internal PRIMARY_POOL_ARRAY = [PRIMARY_POOL_ID]; + bytes32[] internal SECONDARY_POOL_ARRAY = [SECONDARY_POOL_ID]; + bytes32[] internal ALL_POOLS = [PRIMARY_POOL_ID, SECONDARY_POOL_ID]; + + //erc20 config + uint256 internal constant DEFAULT_MINT_QUANTITY = 100 ether; + + //reward scalar (this should match the const in the contract) + uint64 internal constant POOL_SCALAR = 1e18; + uint64 internal constant ONE_PERCENT = POOL_SCALAR / 100; + uint64 internal constant FIFTY_PERCENT = POOL_SCALAR / 2; + uint64 internal constant TEN_PERCENT = POOL_SCALAR / 10; + + //the selector for each error + bytes4 internal immutable UNAUTHORIZED_ERROR_SELECTOR = RewardManager.Unauthorized.selector; + bytes4 internal immutable INVALID_ADDRESS_ERROR_SELECTOR = RewardManager.InvalidAddress.selector; + bytes4 internal immutable INVALID_WEIGHT_ERROR_SELECTOR = RewardManager.InvalidWeights.selector; + bytes4 internal immutable INVALID_POOL_ID_ERROR_SELECTOR = RewardManager.InvalidPoolId.selector; + bytes internal constant ONLY_CALLABLE_BY_OWNER_ERROR = "Only callable by owner"; + bytes4 internal immutable INVALID_POOL_LENGTH_SELECTOR = RewardManager.InvalidPoolLength.selector; + + // Events emitted within the reward manager + event RewardRecipientsUpdated(bytes32 indexed poolId, Common.AddressAndWeight[] newRewardRecipients); + event RewardsClaimed(bytes32 indexed poolId, address indexed recipient, uint192 quantity); + event FeeManagerUpdated(address newProxyAddress); + event FeePaid(IRewardManager.FeePayment[] payments, address payee); + + function setUp() public virtual { + //change to admin user + vm.startPrank(ADMIN); + + //init required contracts + _initializeERC20Contracts(); + _initializeRewardManager(); + } + + function _initializeERC20Contracts() internal { + //create the contracts + asset = new ERC20Mock("ASSET", "AST", ADMIN, 0); + unsupported = new ERC20Mock("UNSUPPORTED", "UNS", ADMIN, 0); + + //mint some tokens to the admin + asset.mint(ADMIN, DEFAULT_MINT_QUANTITY); + unsupported.mint(ADMIN, DEFAULT_MINT_QUANTITY); + + //mint some tokens to the user + asset.mint(FEE_MANAGER, DEFAULT_MINT_QUANTITY); + unsupported.mint(FEE_MANAGER, DEFAULT_MINT_QUANTITY); + } + + function _initializeRewardManager() internal { + //create the contract + rewardManager = new RewardManager(address(asset)); + + rewardManager.setFeeManager(FEE_MANAGER); + } + + function createPrimaryPool() public { + rewardManager.setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients()); + } + + function createSecondaryPool() public { + rewardManager.setRewardRecipients(SECONDARY_POOL_ID, getSecondaryRecipients()); + } + + //override this to test variations of different recipients. changing this function will require existing tests to be updated as constants are hardcoded to be explicit + function getPrimaryRecipients() public virtual returns (Common.AddressAndWeight[] memory) { + //array of recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); + + //init each recipient with even weights. 2500 = 25% of pool + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, POOL_SCALAR / 4); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, POOL_SCALAR / 4); + recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, POOL_SCALAR / 4); + recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, POOL_SCALAR / 4); + + return recipients; + } + + function getPrimaryRecipientAddresses() public pure returns (address[] memory) { + //array of recipients + address[] memory recipients = new address[](4); + + recipients[0] = DEFAULT_RECIPIENT_1; + recipients[1] = DEFAULT_RECIPIENT_2; + recipients[2] = DEFAULT_RECIPIENT_3; + recipients[3] = DEFAULT_RECIPIENT_4; + + return recipients; + } + + //override this to test variations of different recipients. + function getSecondaryRecipients() public virtual returns (Common.AddressAndWeight[] memory) { + //array of recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); + + //init each recipient with even weights. 2500 = 25% of pool + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, POOL_SCALAR / 4); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, POOL_SCALAR / 4); + recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, POOL_SCALAR / 4); + recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_7, POOL_SCALAR / 4); + + return recipients; + } + + function getSecondaryRecipientAddresses() public pure returns (address[] memory) { + //array of recipients + address[] memory recipients = new address[](4); + + recipients[0] = DEFAULT_RECIPIENT_1; + recipients[1] = DEFAULT_RECIPIENT_5; + recipients[2] = DEFAULT_RECIPIENT_6; + recipients[3] = DEFAULT_RECIPIENT_7; + + return recipients; + } + + function addFundsToPool(bytes32 poolId, Common.Asset memory amount, address sender) public { + IRewardManager.FeePayment[] memory payments = new IRewardManager.FeePayment[](1); + payments[0] = IRewardManager.FeePayment(poolId, uint192(amount.amount)); + + addFundsToPool(payments, sender); + } + + function addFundsToPool(IRewardManager.FeePayment[] memory payments, address sender) public { + //record the current address and switch to the sender + address originalAddr = msg.sender; + changePrank(sender); + + uint256 totalPayment; + for (uint256 i; i < payments.length; ++i) { + totalPayment += payments[i].amount; + } + + //approve the amount being paid into the pool + ERC20Mock(address(asset)).approve(address(rewardManager), totalPayment); + + //this represents the verifier adding some funds to the pool + rewardManager.onFeePaid(payments, sender); + + //change back to the original address + changePrank(originalAddr); + } + + function getAsset(uint256 quantity) public view returns (Common.Asset memory) { + return Common.Asset(address(asset), quantity); + } + + function getAssetBalance(address addr) public view returns (uint256) { + return asset.balanceOf(addr); + } + + function claimRewards(bytes32[] memory poolIds, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //claim the rewards + rewardManager.claimRewards(poolIds); + + //change back to the original address + changePrank(originalAddr); + } + + function payRecipients(bytes32 poolId, address[] memory recipients, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //pay the recipients + rewardManager.payRecipients(poolId, recipients); + + //change back to the original address + changePrank(originalAddr); + } + + function setRewardRecipients(bytes32 poolId, Common.AddressAndWeight[] memory recipients, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //pay the recipients + rewardManager.setRewardRecipients(poolId, recipients); + + //change back to the original address + changePrank(originalAddr); + } + + function setFeeManager(address feeManager, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //update the proxy + rewardManager.setFeeManager(feeManager); + + //change back to the original address + changePrank(originalAddr); + } + + function updateRewardRecipients(bytes32 poolId, Common.AddressAndWeight[] memory recipients, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //pay the recipients + rewardManager.updateRewardRecipients(poolId, recipients); + + //change back to the original address + changePrank(originalAddr); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/test/reward-manager/RewardManager.claim.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/test/reward-manager/RewardManager.claim.t.sol new file mode 100644 index 00000000000..efbe9fd6b36 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/test/reward-manager/RewardManager.claim.t.sol @@ -0,0 +1,790 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseRewardManagerTest} from "./BaseRewardManager.t.sol"; +import {Common} from "../../../libraries/Common.sol"; + +/** + * @title BaseRewardManagerTest + * @author Michael Fletcher + * @notice This contract will test the claim functionality of the RewardManager contract. + */ +contract RewardManagerClaimTest is BaseRewardManagerTest { + uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; + + function setUp() public override { + //setup contracts + super.setUp(); + + //create a single pool for these tests + createPrimaryPool(); + + //add funds to the pool to be split among the recipients + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + } + + function test_claimAllRecipients() public { + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //claim funds for each recipient within the pool + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + } + + function test_claimRewardsWithDuplicatePoolIdsDoesNotPayoutTwice() public { + //add funds to a different pool to ensure they're not claimed + addFundsToPool(SECONDARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //create an array containing duplicate poolIds + bytes32[] memory poolIds = new bytes32[](2); + poolIds[0] = PRIMARY_POOL_ID; + poolIds[1] = PRIMARY_POOL_ID; + + //claim funds for each recipient within the pool + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(poolIds, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + + //the pool should still have the remaining + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + } + + function test_claimSingleRecipient() public { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[0]; + + //claim the individual rewards for this recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check the recipients balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + + //check the rewardManager has the remaining quantity + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT - expectedRecipientAmount); + } + + function test_claimMultipleRecipients() public { + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, getPrimaryRecipients()[0].addr); + claimRewards(PRIMARY_POOL_ARRAY, getPrimaryRecipients()[1].addr); + + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check the recipients balance matches the ratio the recipient should have received + assertEq(getAssetBalance(getPrimaryRecipients()[0].addr), expectedRecipientAmount); + assertEq(getAssetBalance(getPrimaryRecipients()[1].addr), expectedRecipientAmount); + + //check the rewardManager has the remaining quantity + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT - (expectedRecipientAmount * 2)); + } + + function test_claimUnregisteredRecipient() public { + //claim the rewards for a recipient who isn't in this pool + claimRewards(PRIMARY_POOL_ARRAY, getSecondaryRecipients()[1].addr); + + //check the recipients didn't receive any fees from this pool + assertEq(getAssetBalance(getSecondaryRecipients()[1].addr), 0); + + //check the rewardManager has the remaining quantity + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + } + + function test_claimUnevenAmountRoundsDown() public { + //adding 1 to the pool should leave 1 wei worth of dust, which the contract doesn't handle due to it being economically infeasible + addFundsToPool(PRIMARY_POOL_ID, getAsset(1), FEE_MANAGER); + + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //claim funds for each recipient within the pool + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + + //check the rewardManager has the remaining quantity equals 1 wei + assertEq(getAssetBalance(address(rewardManager)), 1); + } + + function test_claimUnregisteredPoolId() public { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[0]; + + //claim the individual rewards for this recipient + claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); + + //check the recipients balance is still 0 as there's no pool to receive fees from + assertEq(getAssetBalance(recipient.addr), 0); + + //check the rewardManager has the full amount + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + } + + function test_singleRecipientClaimMultipleDeposits() public { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[0]; + + //claim the individual rewards for this recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check the recipients balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + + //check the rewardManager has the remaining quantity, which is 3/4 of the initial deposit + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT - expectedRecipientAmount); + + //add funds to the pool to be split among the recipients + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + + //claim the individual rewards for this recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //check the recipients balance matches the ratio the recipient should have received, which is 1/4 of each deposit + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount * 2); + + //check the rewardManager has the remaining quantity, which is now 3/4 of both deposits + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 2 - (expectedRecipientAmount * 2)); + } + + function test_recipientsClaimMultipleDeposits() public { + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //claim funds for each recipient within the pool + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + + //the reward manager balance should be 0 as all of the funds have been claimed + assertEq(getAssetBalance(address(rewardManager)), 0); + + //add funds to the pool to be split among the recipients + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + + //claim funds for each recipient within the pool + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //expected recipient amount is 1/4 of the pool deposit + expectedRecipientAmount = (POOL_DEPOSIT_AMOUNT / 4) * 2; + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + + //the reward manager balance should again be 0 as all of the funds have been claimed + assertEq(getAssetBalance(address(rewardManager)), 0); + } + + function test_eventIsEmittedUponClaim() public { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[0]; + + //expect an emit + vm.expectEmit(); + + //emit the event that is expected to be emitted + emit RewardsClaimed(PRIMARY_POOL_ID, recipient.addr, uint192(POOL_DEPOSIT_AMOUNT / 4)); + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + } + + function test_eventIsNotEmittedUponUnsuccessfulClaim() public { + //record logs to check no events were emitted + vm.recordLogs(); + + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[0]; + + //claim the individual rewards for each recipient + claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); + + //no logs should have been emitted + assertEq(vm.getRecordedLogs().length, 0); + } +} + +contract RewardManagerRecipientClaimMultiplePoolsTest is BaseRewardManagerTest { + uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; + + function setUp() public override { + //setup contracts + super.setUp(); + + //create a two pools + createPrimaryPool(); + createSecondaryPool(); + + //add funds to each of the pools to be split among the recipients + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + addFundsToPool(SECONDARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + } + + function test_claimAllRecipientsSinglePool() public { + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //claim funds for each recipient within the pool + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + + //check the pool balance is still equal to DEPOSIT_AMOUNT as the test only claims for one of the pools + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + } + + function test_claimMultipleRecipientsSinglePool() public { + //claim the individual rewards for each recipient + claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[0].addr); + claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[1].addr); + + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check the recipients balance matches the ratio the recipient should have received + assertEq(getAssetBalance(getSecondaryRecipients()[0].addr), expectedRecipientAmount); + assertEq(getAssetBalance(getSecondaryRecipients()[1].addr), expectedRecipientAmount); + + //check the rewardManager has the remaining quantity + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 2 - (expectedRecipientAmount * 2)); + } + + function test_claimMultipleRecipientsMultiplePools() public { + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, getPrimaryRecipients()[0].addr); + claimRewards(PRIMARY_POOL_ARRAY, getPrimaryRecipients()[1].addr); + claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[0].addr); + claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[1].addr); + + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check the recipients balance matches the ratio the recipient should have received. The first recipient is shared across both pools so should receive 1/4 of each pool + assertEq(getAssetBalance(getPrimaryRecipients()[0].addr), expectedRecipientAmount * 2); + assertEq(getAssetBalance(getPrimaryRecipients()[1].addr), expectedRecipientAmount); + assertEq(getAssetBalance(getSecondaryRecipients()[1].addr), expectedRecipientAmount); + + //check the rewardManager has the remaining quantity + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + } + + function test_claimAllRecipientsMultiplePools() public { + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //claim funds for each recipient within the pool + for (uint256 i = 1; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + + //claim funds for each recipient within the pool + for (uint256 i = 1; i < getSecondaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory secondaryRecipient = getSecondaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(SECONDARY_POOL_ARRAY, secondaryRecipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(secondaryRecipient.addr), expectedRecipientAmount); + } + + //special case to handle the first recipient of each pool as they're the same address + Common.AddressAndWeight memory commonRecipient = getPrimaryRecipients()[0]; + + //claim the individual rewards for each pool + claimRewards(PRIMARY_POOL_ARRAY, commonRecipient.addr); + claimRewards(SECONDARY_POOL_ARRAY, commonRecipient.addr); + + //check the balance matches the ratio the recipient should have received, which is 1/4 of each deposit for each pool + assertEq(getAssetBalance(commonRecipient.addr), expectedRecipientAmount * 2); + } + + function test_claimSingleUniqueRecipient() public { + //the first recipient of the secondary pool is in both pools, so take the second recipient which is unique + Common.AddressAndWeight memory recipient = getSecondaryRecipients()[1]; + + //claim the individual rewards for this recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); + + //the recipient should have received 1/4 of the deposit amount + uint256 recipientExpectedAmount = POOL_DEPOSIT_AMOUNT / 4; + + //the recipient should have received 1/4 of the deposit amount + assertEq(getAssetBalance(recipient.addr), recipientExpectedAmount); + + //check the rewardManager has the remaining quantity + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 2 - recipientExpectedAmount); + } + + function test_claimSingleRecipientMultiplePools() public { + //the first recipient of the secondary pool is in both pools + Common.AddressAndWeight memory recipient = getSecondaryRecipients()[0]; + + //claim the individual rewards for this recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); + + //the recipient should have received 1/4 of the deposit amount for each pool + uint256 recipientExpectedAmount = (POOL_DEPOSIT_AMOUNT / 4) * 2; + + //this recipient belongs in both pools so should have received 1/4 of each + assertEq(getAssetBalance(recipient.addr), recipientExpectedAmount); + + //check the rewardManager has the remaining quantity + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 2 - recipientExpectedAmount); + } + + function test_claimUnregisteredRecipient() public { + //claim the individual rewards for this recipient + claimRewards(PRIMARY_POOL_ARRAY, getSecondaryRecipients()[1].addr); + claimRewards(SECONDARY_POOL_ARRAY, getPrimaryRecipients()[1].addr); + + //check the recipients didn't receive any fees from this pool + assertEq(getAssetBalance(getSecondaryRecipients()[1].addr), 0); + assertEq(getAssetBalance(getPrimaryRecipients()[1].addr), 0); + + //check the rewardManager has the remaining quantity + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 2); + } + + function test_claimUnevenAmountRoundsDown() public { + //adding an uneven amount of dust to each pool, this should round down to the nearest whole number with 4 remaining in the contract + addFundsToPool(PRIMARY_POOL_ID, getAsset(3), FEE_MANAGER); + addFundsToPool(SECONDARY_POOL_ID, getAsset(1), FEE_MANAGER); + + //the recipient should have received 1/4 of the deposit amount for each pool + uint256 recipientExpectedAmount = POOL_DEPOSIT_AMOUNT / 4; + + //claim funds for each recipient within the pool + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), recipientExpectedAmount); + } + + //special case to handle the first recipient of each pool as they're the same address + claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[0].addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(getSecondaryRecipients()[0].addr), recipientExpectedAmount * 2); + + //claim funds for each recipient of the secondary pool except the first + for (uint256 i = 1; i < getSecondaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getSecondaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), recipientExpectedAmount); + } + + //contract should have 4 remaining + assertEq(getAssetBalance(address(rewardManager)), 4); + } + + function test_singleRecipientClaimMultipleDeposits() public { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getSecondaryRecipients()[0]; + + //claim the individual rewards for this recipient + claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); + + //the recipient should have received 1/4 of the deposit amount + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check the recipients balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + + //check the rewardManager has the remaining quantity, which is 3/4 of the initial deposit plus the deposit from the second pool + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 2 - expectedRecipientAmount); + + //add funds to the pool to be split among the recipients + addFundsToPool(SECONDARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + + //claim the individual rewards for this recipient + claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); + + //the recipient should have received 1/4 of the next deposit amount + expectedRecipientAmount += POOL_DEPOSIT_AMOUNT / 4; + + //check the recipients balance matches the ratio the recipient should have received, which is 1/4 of each deposit + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + + //check the rewardManager has the remaining quantity, which is now 3/4 of both deposits + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 3 - expectedRecipientAmount); + } + + function test_recipientsClaimMultipleDeposits() public { + //the recipient should have received 1/4 of the deposit amount + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //claim funds for each recipient within the pool + for (uint256 i; i < getSecondaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getSecondaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + + //the reward manager balance should contain only the funds of the secondary pool + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + + //add funds to the pool to be split among the recipients + addFundsToPool(SECONDARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + + //special case to handle the first recipient of each pool as they're the same address + claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[0].addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(getSecondaryRecipients()[0].addr), expectedRecipientAmount * 2); + + //claim funds for each recipient within the pool except the first + for (uint256 i = 1; i < getSecondaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getSecondaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount * 2); + } + + //the reward manager balance should again be the balance of the secondary pool as the primary pool has been emptied twice + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + } + + function test_claimEmptyPoolWhenSecondPoolContainsFunds() public { + //the recipient should have received 1/4 of the deposit amount + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //claim all rewards for each recipient in the primary pool + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + + //claim all the rewards again for the first recipient as that address is a member of both pools + claimRewards(PRIMARY_POOL_ARRAY, getSecondaryRecipients()[0].addr); + + //check the balance + assertEq(getAssetBalance(getSecondaryRecipients()[0].addr), expectedRecipientAmount); + } + + function test_getRewardsAvailableToRecipientInBothPools() public { + //get index 0 as this recipient is in both default pools + bytes32[] memory poolIds = rewardManager.getAvailableRewardPoolIds( + getPrimaryRecipients()[0].addr, + 0, + type(uint256).max + ); + + //check the recipient is in both pools + assertEq(poolIds[0], PRIMARY_POOL_ID); + assertEq(poolIds[1], SECONDARY_POOL_ID); + } + + function test_getRewardsAvailableToRecipientInSinglePool() public { + //get index 0 as this recipient is in both default pools + bytes32[] memory poolIds = rewardManager.getAvailableRewardPoolIds( + getPrimaryRecipients()[1].addr, + 0, + type(uint256).max + ); + + //check the recipient is in both pools + assertEq(poolIds[0], PRIMARY_POOL_ID); + assertEq(poolIds[1], ZERO_POOL_ID); + } + + function test_getRewardsAvailableToRecipientInNoPools() public view { + //get index 0 as this recipient is in both default pools + bytes32[] memory poolIds = rewardManager.getAvailableRewardPoolIds(FEE_MANAGER, 0, type(uint256).max); + + //check the recipient is in neither pool + assertEq(poolIds[0], ZERO_POOL_ID); + assertEq(poolIds[1], ZERO_POOL_ID); + } + + function test_getRewardsAvailableToRecipientInBothPoolsWhereAlreadyClaimed() public { + //get index 0 as this recipient is in both default pools + bytes32[] memory poolIds = rewardManager.getAvailableRewardPoolIds( + getPrimaryRecipients()[0].addr, + 0, + type(uint256).max + ); + + //check the recipient is in both pools + assertEq(poolIds[0], PRIMARY_POOL_ID); + assertEq(poolIds[1], SECONDARY_POOL_ID); + + //claim the rewards for each pool + claimRewards(PRIMARY_POOL_ARRAY, getPrimaryRecipients()[0].addr); + claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[0].addr); + + //get the available pools again + poolIds = rewardManager.getAvailableRewardPoolIds(getPrimaryRecipients()[0].addr, 0, type(uint256).max); + + //user should not be in any pool + assertEq(poolIds[0], ZERO_POOL_ID); + assertEq(poolIds[1], ZERO_POOL_ID); + } + + function test_getAvailableRewardsCursorCannotBeGreaterThanTotalPools() public { + vm.expectRevert(INVALID_POOL_LENGTH_SELECTOR); + + rewardManager.getAvailableRewardPoolIds(FEE_MANAGER, type(uint256).max, 0); + } + + function test_getAvailableRewardsCursorAndTotalPoolsEqual() public { + bytes32[] memory poolIds = rewardManager.getAvailableRewardPoolIds(getPrimaryRecipients()[0].addr, 2, 2); + + assertEq(poolIds.length, 0); + } + + function test_getAvailableRewardsCursorSingleResult() public { + bytes32[] memory poolIds = rewardManager.getAvailableRewardPoolIds(getPrimaryRecipients()[0].addr, 0, 1); + + assertEq(poolIds[0], PRIMARY_POOL_ID); + } +} + +contract RewardManagerRecipientClaimDifferentWeightsTest is BaseRewardManagerTest { + uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; + + function setUp() public override { + //setup contracts + super.setUp(); + + //create a single pool for these tests + createPrimaryPool(); + + //add funds to the pool to be split among the recipients + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + } + + function getPrimaryRecipients() public virtual override returns (Common.AddressAndWeight[] memory) { + //array of recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); + + //init each recipient with uneven weights + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, TEN_PERCENT); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, TEN_PERCENT * 8); + recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, ONE_PERCENT * 6); + recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, ONE_PERCENT * 4); + + return recipients; + } + + function test_allRecipientsClaimingReceiveExpectedAmount() public { + //loop all the recipients and claim their expected amount + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //the recipient should have received a share proportional to their weight + uint256 expectedRecipientAmount = (POOL_DEPOSIT_AMOUNT * recipient.weight) / POOL_SCALAR; + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + } +} + +contract RewardManagerRecipientClaimUnevenWeightTest is BaseRewardManagerTest { + uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; + + function setUp() public override { + //setup contracts + super.setUp(); + + //create a single pool for these tests + createPrimaryPool(); + } + + function getPrimaryRecipients() public virtual override returns (Common.AddressAndWeight[] memory) { + //array of recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](2); + + uint64 oneThird = POOL_SCALAR / 3; + + //init each recipient with even weights. + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, oneThird); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, 2 * oneThird + 1); + + return recipients; + } + + function test_allRecipientsClaimingReceiveExpectedAmountWithSmallDeposit() public { + //add a smaller amount of funds to the pool + uint256 smallDeposit = 1e8; + + //add a smaller amount of funds to the pool + addFundsToPool(PRIMARY_POOL_ID, getAsset(smallDeposit), FEE_MANAGER); + + //loop all the recipients and claim their expected amount + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //the recipient should have received a share proportional to their weight + uint256 expectedRecipientAmount = (smallDeposit * recipient.weight) / POOL_SCALAR; + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + + //smaller deposits will consequently have less precision and will not be able to be split as evenly, the remaining 1 will be lost due to 333...|... being paid out instead of 333...4| + assertEq(getAssetBalance(address(rewardManager)), 1); + } + + function test_allRecipientsClaimingReceiveExpectedAmount() public { + //add funds to the pool to be split among the recipients + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + + //loop all the recipients and claim their expected amount + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //the recipient should have received a share proportional to their weight + uint256 expectedRecipientAmount = (POOL_DEPOSIT_AMOUNT * recipient.weight) / POOL_SCALAR; + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + + //their should be 0 wei left over indicating a successful split + assertEq(getAssetBalance(address(rewardManager)), 0); + } +} + +contract RewardManagerNoRecipientSet is BaseRewardManagerTest { + uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; + + function setUp() public override { + //setup contracts + super.setUp(); + + //add funds to the pool to be split among the recipients once registered + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + } + + function test_claimAllRecipientsAfterRecipientsSet() public { + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //try and claim funds for each recipient within the pool + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //there should be no rewards claimed as the recipient is not registered + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //check the recipient received nothing + assertEq(getAssetBalance(recipient.addr), 0); + } + + //Set the recipients after the rewards have been paid into the pool + setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); + + //claim funds for each recipient within the pool + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //there should be no rewards claimed as the recipient is registered + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/test/reward-manager/RewardManager.general.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/test/reward-manager/RewardManager.general.t.sol new file mode 100644 index 00000000000..b2e0cf99bb9 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/test/reward-manager/RewardManager.general.t.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseRewardManagerTest} from "./BaseRewardManager.t.sol"; +import {RewardManager} from "../../RewardManager.sol"; +import {ERC20Mock} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol"; +import {IRewardManager} from "../../interfaces/IRewardManager.sol"; + +/** + * @title BaseRewardManagerTest + * @author Michael Fletcher + * @notice This contract will test the core functionality of the RewardManager contract + */ +contract RewardManagerSetupTest is BaseRewardManagerTest { + uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; + + function setUp() public override { + //setup contracts + super.setUp(); + } + + function test_rejectsZeroLinkAddressOnConstruction() public { + //should revert if the contract is a zero address + vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); + + //create a rewardManager with a zero link address + new RewardManager(address(0)); + } + + function test_eventEmittedUponFeeManagerUpdate() public { + //expect the event to be emitted + vm.expectEmit(); + + //emit the event that is expected to be emitted + emit FeeManagerUpdated(FEE_MANAGER); + + //set the verifier proxy + setFeeManager(FEE_MANAGER, ADMIN); + } + + function test_eventEmittedUponFeePaid() public { + //create pool and add funds + createPrimaryPool(); + + //change to the feeManager who is the one who will be paying the fees + changePrank(FEE_MANAGER); + + //approve the amount being paid into the pool + ERC20Mock(getAsset(POOL_DEPOSIT_AMOUNT).assetAddress).approve(address(rewardManager), POOL_DEPOSIT_AMOUNT); + + IRewardManager.FeePayment[] memory payments = new IRewardManager.FeePayment[](1); + payments[0] = IRewardManager.FeePayment(PRIMARY_POOL_ID, uint192(POOL_DEPOSIT_AMOUNT)); + + //event is emitted when funds are added + vm.expectEmit(); + emit FeePaid(payments, FEE_MANAGER); + + //this represents the verifier adding some funds to the pool + rewardManager.onFeePaid(payments, FEE_MANAGER); + } + + function test_setFeeManagerZeroAddress() public { + //should revert if the contract is a zero address + vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); + + //set the verifier proxy + setFeeManager(address(0), ADMIN); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/test/reward-manager/RewardManager.payRecipients.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/test/reward-manager/RewardManager.payRecipients.t.sol new file mode 100644 index 00000000000..89fac663ba3 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/test/reward-manager/RewardManager.payRecipients.t.sol @@ -0,0 +1,194 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseRewardManagerTest} from "./BaseRewardManager.t.sol"; +import {IRewardManager} from "../../interfaces/IRewardManager.sol"; + +/** + * @title BaseRewardManagerTest + * @author Michael Fletcher + * @notice This contract will test the payRecipients functionality of the RewardManager contract + */ +contract RewardManagerPayRecipientsTest is BaseRewardManagerTest { + uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; + + function setUp() public override { + //setup contracts + super.setUp(); + + //create a single pool for these tests + createPrimaryPool(); + + //add funds to the pool to be split among the recipients + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + } + + function test_payAllRecipients() public { + //pay all the recipients in the pool + payRecipients(PRIMARY_POOL_ID, getPrimaryRecipientAddresses(), ADMIN); + + //each recipient should receive 1/4 of the pool + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check each recipient received the correct amount + for (uint256 i = 0; i < getPrimaryRecipientAddresses().length; i++) { + assertEq(getAssetBalance(getPrimaryRecipientAddresses()[i]), expectedRecipientAmount); + } + } + + function test_paySingleRecipient() public { + //get the first individual recipient + address recipient = getPrimaryRecipientAddresses()[0]; + + //get a single recipient as an array + address[] memory recipients = new address[](1); + recipients[0] = recipient; + + //pay a single recipient + payRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + + //the recipient should have received 1/4 of the deposit amount + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + assertEq(getAssetBalance(recipient), expectedRecipientAmount); + } + + function test_payRecipientWithInvalidPool() public { + //get the first individual recipient + address recipient = getPrimaryRecipientAddresses()[0]; + + //get a single recipient as an array + address[] memory recipients = new address[](1); + recipients[0] = recipient; + + //pay a single recipient + payRecipients(SECONDARY_POOL_ID, recipients, ADMIN); + + //the recipient should have received nothing + assertEq(getAssetBalance(recipient), 0); + } + + function test_payRecipientsEmptyRecipientList() public { + //get a single recipient + address[] memory recipients = new address[](0); + + //pay a single recipient + payRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + + //rewardManager should have the full balance + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + } + + function test_payAllRecipientsWithAdditionalUnregisteredRecipient() public { + //load all the recipients and add an additional one who is not in the pool + address[] memory recipients = new address[](getPrimaryRecipientAddresses().length + 1); + for (uint256 i = 0; i < getPrimaryRecipientAddresses().length; i++) { + recipients[i] = getPrimaryRecipientAddresses()[i]; + } + recipients[recipients.length - 1] = DEFAULT_RECIPIENT_5; + + //pay the recipients + payRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + + //each recipient should receive 1/4 of the pool except the last + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check each recipient received the correct amount + for (uint256 i = 0; i < getPrimaryRecipientAddresses().length; i++) { + assertEq(getAssetBalance(getPrimaryRecipientAddresses()[i]), expectedRecipientAmount); + } + + //the unregistered recipient should receive nothing + assertEq(getAssetBalance(DEFAULT_RECIPIENT_5), 0); + } + + function test_payAllRecipientsWithAdditionalInvalidRecipient() public { + //load all the recipients and add an additional one which is invalid, that should receive nothing + address[] memory recipients = new address[](getPrimaryRecipientAddresses().length + 1); + for (uint256 i = 0; i < getPrimaryRecipientAddresses().length; i++) { + recipients[i] = getPrimaryRecipientAddresses()[i]; + } + recipients[recipients.length - 1] = INVALID_ADDRESS; + + //pay the recipients + payRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + + //each recipient should receive 1/4 of the pool except the last + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check each recipient received the correct amount + for (uint256 i = 0; i < getPrimaryRecipientAddresses().length; i++) { + assertEq(getAssetBalance(getPrimaryRecipientAddresses()[i]), expectedRecipientAmount); + } + } + + function test_paySubsetOfRecipientsInPool() public { + //load a subset of the recipients into an array + address[] memory recipients = new address[](getPrimaryRecipientAddresses().length - 1); + for (uint256 i = 0; i < recipients.length; i++) { + recipients[i] = getPrimaryRecipientAddresses()[i]; + } + + //pay the subset of recipients + payRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + + //each recipient should receive 1/4 of the pool except the last + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check each subset of recipients received the correct amount + for (uint256 i = 0; i < recipients.length - 1; i++) { + assertEq(getAssetBalance(recipients[i]), expectedRecipientAmount); + } + + //check the pool has the remaining balance + assertEq( + getAssetBalance(address(rewardManager)), + POOL_DEPOSIT_AMOUNT - expectedRecipientAmount * recipients.length + ); + } + + function test_payAllRecipientsFromNonAdminUser() public { + //should revert if the caller isn't an admin or recipient within the pool + vm.expectRevert(UNAUTHORIZED_ERROR_SELECTOR); + + //pay all the recipients in the pool + payRecipients(PRIMARY_POOL_ID, getPrimaryRecipientAddresses(), FEE_MANAGER); + } + + function test_payAllRecipientsFromRecipientInPool() public { + //pay all the recipients in the pool + payRecipients(PRIMARY_POOL_ID, getPrimaryRecipientAddresses(), DEFAULT_RECIPIENT_1); + + //each recipient should receive 1/4 of the pool + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check each recipient received the correct amount + for (uint256 i = 0; i < getPrimaryRecipientAddresses().length; i++) { + assertEq(getAssetBalance(getPrimaryRecipientAddresses()[i]), expectedRecipientAmount); + } + } + + function test_payRecipientsWithInvalidPoolId() public { + //pay all the recipients in the pool + payRecipients(INVALID_POOL_ID, getPrimaryRecipientAddresses(), ADMIN); + + //pool should still contain the full balance + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + } + + function test_addFundsToPoolAsOwner() public { + //add funds to the pool + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + } + + function test_addFundsToPoolAsNonOwnerOrFeeManager() public { + //should revert if the caller isn't an admin or recipient within the pool + vm.expectRevert(UNAUTHORIZED_ERROR_SELECTOR); + + IRewardManager.FeePayment[] memory payments = new IRewardManager.FeePayment[](1); + payments[0] = IRewardManager.FeePayment(PRIMARY_POOL_ID, uint192(POOL_DEPOSIT_AMOUNT)); + + //add funds to the pool + rewardManager.onFeePaid(payments, USER); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/test/reward-manager/RewardManager.setRecipients.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/test/reward-manager/RewardManager.setRecipients.t.sol new file mode 100644 index 00000000000..d3e6990bd9f --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/test/reward-manager/RewardManager.setRecipients.t.sol @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseRewardManagerTest} from "./BaseRewardManager.t.sol"; +import {Common} from "../../../libraries/Common.sol"; + +/** + * @title BaseRewardManagerTest + * @author Michael Fletcher + * @notice This contract will test the setRecipient functionality of the RewardManager contract + */ +contract RewardManagerSetRecipientsTest is BaseRewardManagerTest { + function setUp() public override { + //setup contracts + super.setUp(); + } + + function test_setRewardRecipients() public { + //set the recipients + setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); + } + + function test_setRewardRecipientsIsEmpty() public { + //array of recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); + + //should revert if the recipients array is empty + vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); + + //set the recipients + setRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_setRewardRecipientWithZeroWeight() public { + //array of recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](5); + + //init each recipient with even weights + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, ONE_PERCENT * 25); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, ONE_PERCENT * 25); + recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, ONE_PERCENT * 25); + recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, ONE_PERCENT * 25); + recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, 0); + + //set the recipients + setRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_setRewardRecipientWithZeroAddress() public { + //array of recipients + Common.AddressAndWeight[] memory recipients = getPrimaryRecipients(); + + //override the first recipient with a zero address + recipients[0].addr = address(0); + + //should revert if the recipients array is empty + vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); + + //set the recipients + setRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_setRewardRecipientWeights() public { + //array of recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); + + //init each recipient with even weights + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, 25); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, 25); + recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, 25); + recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, 25); + + //should revert if the recipients array is empty + vm.expectRevert(INVALID_WEIGHT_ERROR_SELECTOR); + + //set the recipients with a recipient with a weight of 100% + setRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_setSingleRewardRecipient() public { + //array of recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](1); + + //init each recipient with even weights + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, POOL_SCALAR); + + //set the recipients with a recipient with a weight of 100% + setRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_setRewardRecipientTwice() public { + //set the recipients + setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); + + //should revert if recipients for this pool have already been set + vm.expectRevert(INVALID_POOL_ID_ERROR_SELECTOR); + + //set the recipients again + setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); + } + + function test_setRewardRecipientFromNonOwnerOrFeeManagerAddress() public { + //should revert if the sender is not the owner or proxy + vm.expectRevert(UNAUTHORIZED_ERROR_SELECTOR); + + //set the recipients + setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), USER); + } + + function test_setRewardRecipientFromManagerAddress() public { + //update the proxy address + setFeeManager(FEE_MANAGER, ADMIN); + + //set the recipients + setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), FEE_MANAGER); + } + + function test_eventIsEmittedUponSetRecipients() public { + //expect an emit + vm.expectEmit(); + + //emit the event that is expected to be emitted + emit RewardRecipientsUpdated(PRIMARY_POOL_ID, getPrimaryRecipients()); + + //set the recipients + setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); + } + + function test_setRecipientContainsDuplicateRecipients() public { + //create a new array to hold the existing recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length * 2); + + //add all the existing recipients + for (uint256 i; i < getPrimaryRecipients().length; i++) { + recipients[i] = getPrimaryRecipients()[i]; + } + //add all the existing recipients again + for (uint256 i; i < getPrimaryRecipients().length; i++) { + recipients[i + getPrimaryRecipients().length] = getPrimaryRecipients()[i]; + } + + //should revert as the list contains a duplicate + vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); + + //set the recipients + setRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/test/reward-manager/RewardManager.updateRewardRecipients.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/test/reward-manager/RewardManager.updateRewardRecipients.t.sol new file mode 100644 index 00000000000..0d3a2b69b39 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/test/reward-manager/RewardManager.updateRewardRecipients.t.sol @@ -0,0 +1,450 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseRewardManagerTest} from "./BaseRewardManager.t.sol"; +import {Common} from "../../../libraries/Common.sol"; + +/** + * @title BaseRewardManagerTest + * @author Michael Fletcher + * @notice This contract will test the updateRecipient functionality of the RewardManager contract + */ +contract RewardManagerUpdateRewardRecipientsTest is BaseRewardManagerTest { + uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; + + function setUp() public override { + //setup contracts + super.setUp(); + + //create a single pool for these tests + createPrimaryPool(); + + //add funds to the pool to be split among the recipients + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + } + + function test_onlyAdminCanUpdateRecipients() public { + //should revert if the caller is not the admin + vm.expectRevert(ONLY_CALLABLE_BY_OWNER_ERROR); + + //updating a recipient should force the funds to be paid out + updateRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), FEE_MANAGER); + } + + function test_updateAllRecipientsWithSameAddressAndWeight() public { + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //updating a recipient should force the funds to be paid out + updateRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); + + //check each recipient received the correct amount + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(getPrimaryRecipients()[i].addr), expectedRecipientAmount); + } + } + + function test_updatePartialRecipientsWithSameAddressAndWeight() public { + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //get a subset of the recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](2); + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, ONE_PERCENT * 25); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, ONE_PERCENT * 25); + + //updating a recipient should force the funds to be paid out + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + + //check each recipient received the correct amount + for (uint256 i; i < recipients.length; i++) { + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipients[i].addr), expectedRecipientAmount); + } + + //the reward manager should still have half remaining funds + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT / 2); + } + + function test_updateRecipientWithNewZeroAddress() public { + //create a new array to hold the existing recipients plus a new zero address + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length + 1); + + //add all the existing recipients + for (uint256 i; i < getPrimaryRecipients().length; i++) { + recipients[i] = getPrimaryRecipients()[i]; + } + //add a new address to the primary recipients + recipients[recipients.length - 1] = Common.AddressAndWeight(address(0), 0); + + //should revert if the recipient is a zero address + vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); + + //update the recipients with invalid address + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updateRecipientsContainsDuplicateRecipients() public { + //create a new array to hold the existing recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length * 2); + + //add all the existing recipients + for (uint256 i; i < getPrimaryRecipients().length; i++) { + recipients[i] = getPrimaryRecipients()[i]; + } + //add all the existing recipients again + for (uint256 i; i < getPrimaryRecipients().length; i++) { + recipients[i + getPrimaryRecipients().length] = getPrimaryRecipients()[i]; + } + + //should revert as the list contains a duplicate + vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); + + //update the recipients with the duplicate addresses + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updateRecipientsToDifferentSet() public { + //create a list of containing recipients from the primary configured set, and new recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length + 4); + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //copy the recipient and set the weight to 0 which implies the recipient is being replaced + recipients[i] = Common.AddressAndWeight(getPrimaryRecipients()[i].addr, 0); + } + + //add the new recipients individually + recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, ONE_PERCENT * 25); + recipients[5] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, ONE_PERCENT * 25); + recipients[6] = Common.AddressAndWeight(DEFAULT_RECIPIENT_7, ONE_PERCENT * 25); + recipients[7] = Common.AddressAndWeight(DEFAULT_RECIPIENT_8, ONE_PERCENT * 25); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updateRecipientsToDifferentPartialSet() public { + //create a list of containing recipients from the primary configured set, and new recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length + 2); + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //copy the recipient and set the weight to 0 which implies the recipient is being replaced + recipients[i] = Common.AddressAndWeight(getPrimaryRecipients()[i].addr, 0); + } + + //add the new recipients individually + recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, FIFTY_PERCENT); + recipients[5] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, FIFTY_PERCENT); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updateRecipientsToDifferentLargerSet() public { + //create a list of containing recipients from the primary configured set, and new recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length + 5); + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //copy the recipient and set the weight to 0 which implies the recipient is being replaced + recipients[i] = Common.AddressAndWeight(getPrimaryRecipients()[i].addr, 0); + } + + //add the new recipients individually + recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, TEN_PERCENT * 2); + recipients[5] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, TEN_PERCENT * 2); + recipients[6] = Common.AddressAndWeight(DEFAULT_RECIPIENT_7, TEN_PERCENT * 2); + recipients[7] = Common.AddressAndWeight(DEFAULT_RECIPIENT_8, TEN_PERCENT * 2); + recipients[8] = Common.AddressAndWeight(DEFAULT_RECIPIENT_9, TEN_PERCENT * 2); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updateRecipientsUpdateAndRemoveExistingForLargerSet() public { + //create a list of containing recipients from the primary configured set, and new recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](9); + + //update the existing recipients + recipients[0] = Common.AddressAndWeight(getPrimaryRecipients()[0].addr, 0); + recipients[1] = Common.AddressAndWeight(getPrimaryRecipients()[1].addr, 0); + recipients[2] = Common.AddressAndWeight(getPrimaryRecipients()[2].addr, TEN_PERCENT * 3); + recipients[3] = Common.AddressAndWeight(getPrimaryRecipients()[3].addr, TEN_PERCENT * 3); + + //add the new recipients individually + recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, TEN_PERCENT); + recipients[5] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, TEN_PERCENT); + recipients[6] = Common.AddressAndWeight(DEFAULT_RECIPIENT_7, TEN_PERCENT); + recipients[7] = Common.AddressAndWeight(DEFAULT_RECIPIENT_8, TEN_PERCENT); + recipients[8] = Common.AddressAndWeight(DEFAULT_RECIPIENT_9, TEN_PERCENT); + + //should revert as the weight does not equal 100% + vm.expectRevert(INVALID_WEIGHT_ERROR_SELECTOR); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updateRecipientsUpdateAndRemoveExistingForSmallerSet() public { + //create a list of containing recipients from the primary configured set, and new recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](5); + + //update the existing recipients + recipients[0] = Common.AddressAndWeight(getPrimaryRecipients()[0].addr, 0); + recipients[1] = Common.AddressAndWeight(getPrimaryRecipients()[1].addr, 0); + recipients[2] = Common.AddressAndWeight(getPrimaryRecipients()[2].addr, TEN_PERCENT * 3); + recipients[3] = Common.AddressAndWeight(getPrimaryRecipients()[3].addr, TEN_PERCENT * 2); + + //add the new recipients individually + recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, TEN_PERCENT * 5); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updateRecipientsToDifferentSetWithInvalidWeights() public { + //create a list of containing recipients from the primary configured set, and new recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length + 2); + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //copy the recipient and set the weight to 0 which implies the recipient is being replaced + recipients[i] = Common.AddressAndWeight(getPrimaryRecipients()[i].addr, 0); + } + + //add the new recipients individually + recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, TEN_PERCENT * 5); + recipients[5] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, TEN_PERCENT); + + //should revert as the weight will not equal 100% + vm.expectRevert(INVALID_WEIGHT_ERROR_SELECTOR); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updatePartialRecipientsToSubset() public { + //create a list of containing recipients from the primary configured set, and new recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, 0); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, 0); + recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, TEN_PERCENT * 5); + recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, TEN_PERCENT * 5); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updatePartialRecipientsWithUnderWeightSet() public { + //create a list of containing recipients from the primary configured set, and new recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, TEN_PERCENT); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, TEN_PERCENT); + recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, TEN_PERCENT); + recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, TEN_PERCENT); + + //should revert as the new weights exceed the previous weights being replaced + vm.expectRevert(INVALID_WEIGHT_ERROR_SELECTOR); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updatePartialRecipientsWithExcessiveWeight() public { + //create a list of containing recipients from the primary configured set, and new recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, TEN_PERCENT); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, TEN_PERCENT); + recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, TEN_PERCENT); + recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, POOL_SCALAR); + + //should revert as the new weights exceed the previous weights being replaced + vm.expectRevert(INVALID_WEIGHT_ERROR_SELECTOR); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updateRecipientWeights() public { + //expected recipient amount is 1/4 of the pool deposit for original recipients + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //create a list of containing recipients from the primary configured set with their new weights + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, TEN_PERCENT); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, TEN_PERCENT); + recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, TEN_PERCENT * 3); + recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, TEN_PERCENT * 5); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + + //check each recipient received the correct amount + for (uint256 i; i < recipients.length; i++) { + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipients[i].addr), expectedRecipientAmount); + } + + //the reward manager should have no funds remaining + assertEq(getAssetBalance(address(rewardManager)), 0); + + //add more funds to the pool to check new distribution + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + + //loop each user and claim the rewards + for (uint256 i; i < recipients.length; i++) { + //claim the rewards for this recipient + claimRewards(PRIMARY_POOL_ARRAY, recipients[i].addr); + } + + //manually check the balance of each recipient + assertEq( + getAssetBalance(DEFAULT_RECIPIENT_1), + (POOL_DEPOSIT_AMOUNT * TEN_PERCENT) / POOL_SCALAR + expectedRecipientAmount + ); + assertEq( + getAssetBalance(DEFAULT_RECIPIENT_2), + (POOL_DEPOSIT_AMOUNT * TEN_PERCENT) / POOL_SCALAR + expectedRecipientAmount + ); + assertEq( + getAssetBalance(DEFAULT_RECIPIENT_3), + (POOL_DEPOSIT_AMOUNT * TEN_PERCENT * 3) / POOL_SCALAR + expectedRecipientAmount + ); + assertEq( + getAssetBalance(DEFAULT_RECIPIENT_4), + (POOL_DEPOSIT_AMOUNT * TEN_PERCENT * 5) / POOL_SCALAR + expectedRecipientAmount + ); + } + + function test_partialUpdateRecipientWeights() public { + //expected recipient amount is 1/4 of the pool deposit for original recipients + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //create a list of containing recipients from the primary configured set with their new weights + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](2); + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, TEN_PERCENT); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, TEN_PERCENT * 4); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + + //check each recipient received the correct amount + for (uint256 i; i < recipients.length; i++) { + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipients[i].addr), expectedRecipientAmount); + } + + //the reward manager should have half the funds remaining + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT / 2); + + //add more funds to the pool to check new distribution + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + + //loop each user and claim the rewards + for (uint256 i; i < recipients.length; i++) { + //claim the rewards for this recipient + claimRewards(PRIMARY_POOL_ARRAY, recipients[i].addr); + } + + //manually check the balance of each recipient + assertEq( + getAssetBalance(DEFAULT_RECIPIENT_1), + (POOL_DEPOSIT_AMOUNT * TEN_PERCENT) / POOL_SCALAR + expectedRecipientAmount + ); + assertEq( + getAssetBalance(DEFAULT_RECIPIENT_2), + (POOL_DEPOSIT_AMOUNT * TEN_PERCENT * 4) / POOL_SCALAR + expectedRecipientAmount + ); + + //the reward manager should have half the funds remaining + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + } + + function test_eventIsEmittedUponUpdateRecipients() public { + //expect an emit + vm.expectEmit(); + + //emit the event that is expected to be emitted + emit RewardRecipientsUpdated(PRIMARY_POOL_ID, getPrimaryRecipients()); + + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //updating a recipient should force the funds to be paid out + updateRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); + + //check each recipient received the correct amount + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(getPrimaryRecipients()[i].addr), expectedRecipientAmount); + } + } +} + +contract RewardManagerUpdateRewardRecipientsMultiplePoolsTest is BaseRewardManagerTest { + uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; + + function setUp() public override { + //setup contracts + super.setUp(); + + //create a single pool for these tests + createPrimaryPool(); + createSecondaryPool(); + + //add funds to the pool to be split among the recipients + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + addFundsToPool(SECONDARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + } + + function getSecondaryRecipients() public override returns (Common.AddressAndWeight[] memory) { + //for testing purposes, the primary and secondary pool to contain the same recipients + return getPrimaryRecipients(); + } + + function test_updatePrimaryRecipientWeights() public { + //expected recipient amount is 1/4 of the pool deposit for original recipients + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //create a list of containing recipients from the primary configured set, and new recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, TEN_PERCENT * 4); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, TEN_PERCENT * 4); + recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, TEN_PERCENT); + recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, TEN_PERCENT); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + + //check each recipient received the correct amount + for (uint256 i; i < recipients.length; i++) { + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipients[i].addr), expectedRecipientAmount); + } + + //the reward manager should still have the funds for the secondary pool + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + + //add more funds to the pool to check new distribution + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + + //claim the rewards for the updated recipients manually + claimRewards(PRIMARY_POOL_ARRAY, recipients[0].addr); + claimRewards(PRIMARY_POOL_ARRAY, recipients[1].addr); + claimRewards(PRIMARY_POOL_ARRAY, recipients[2].addr); + claimRewards(PRIMARY_POOL_ARRAY, recipients[3].addr); + + //check the balance matches the ratio the recipient who were updated should have received + assertEq( + getAssetBalance(recipients[0].addr), + (POOL_DEPOSIT_AMOUNT * TEN_PERCENT * 4) / POOL_SCALAR + expectedRecipientAmount + ); + assertEq( + getAssetBalance(recipients[1].addr), + (POOL_DEPOSIT_AMOUNT * TEN_PERCENT * 4) / POOL_SCALAR + expectedRecipientAmount + ); + assertEq( + getAssetBalance(recipients[2].addr), + (POOL_DEPOSIT_AMOUNT * TEN_PERCENT) / POOL_SCALAR + expectedRecipientAmount + ); + assertEq( + getAssetBalance(recipients[3].addr), + (POOL_DEPOSIT_AMOUNT * TEN_PERCENT) / POOL_SCALAR + expectedRecipientAmount + ); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/BaseVerifierTest.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/BaseVerifierTest.t.sol new file mode 100644 index 00000000000..bfa9d05d71e --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/BaseVerifierTest.t.sol @@ -0,0 +1,556 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {Test} from "forge-std/Test.sol"; +import {VerifierProxy} from "../../VerifierProxy.sol"; +import {IERC165} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {IVerifier} from "../../interfaces/IVerifier.sol"; +import {ErroredVerifier} from "../mocks/ErroredVerifier.sol"; +import {Verifier} from "../../Verifier.sol"; +import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; +import {AccessControllerInterface} from "../../../../shared/interfaces/AccessControllerInterface.sol"; +import {FeeManager} from "../../FeeManager.sol"; +import {Common} from "../../../libraries/Common.sol"; +import {ERC20Mock} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol"; +import {WERC20Mock} from "../../../../shared/mocks/WERC20Mock.sol"; +import {RewardManager} from "../../RewardManager.sol"; + +contract BaseTest is Test { + uint256 internal constant MAX_ORACLES = 31; + address internal constant ADMIN = address(1); + address internal constant USER = address(2); + address internal constant MOCK_VERIFIER_ADDRESS = address(100); + address internal constant MOCK_VERIFIER_ADDRESS_TWO = address(200); + address internal constant ACCESS_CONTROLLER_ADDRESS = address(300); + + bytes32 internal constant V_MASK = 0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; + bytes32 internal constant V1_BITMASK = 0x0001000000000000000000000000000000000000000000000000000000000000; + bytes32 internal constant V2_BITMASK = 0x0002000000000000000000000000000000000000000000000000000000000000; + bytes32 internal constant V3_BITMASK = 0x0003000000000000000000000000000000000000000000000000000000000000; + + uint256 internal constant SOURCE_CHAIN_ID = 0x1234; + address internal constant SOURCE_ADDRESS = address(0x1234); + + //version 0 feeds + bytes32 internal constant FEED_ID = (keccak256("ETH-USD") & V_MASK) | V1_BITMASK; + bytes32 internal constant FEED_ID_2 = (keccak256("LINK-USD") & V_MASK) | V1_BITMASK; + bytes32 internal constant FEED_ID_3 = (keccak256("BTC-USD") & V_MASK) | V1_BITMASK; + + //version 3 feeds + bytes32 internal constant FEED_ID_V3 = (keccak256("ETH-USD") & V_MASK) | V3_BITMASK; + + bytes32 internal constant INVALID_FEED = keccak256("INVALID"); + uint32 internal constant OBSERVATIONS_TIMESTAMP = 1000; + uint64 internal constant BLOCKNUMBER_LOWER_BOUND = 1000; + uint64 internal constant BLOCKNUMBER_UPPER_BOUND = BLOCKNUMBER_LOWER_BOUND + 5; + int192 internal constant MEDIAN = 1 ether; + int192 internal constant BID = 500000000 gwei; + int192 internal constant ASK = 2 ether; + + bytes32 internal constant EMPTY_BYTES = bytes32(""); + + uint8 internal constant FAULT_TOLERANCE = 10; + uint64 internal constant VERIFIER_VERSION = 1; + + string internal constant SERVER_URL = "https://mercury.server/client/"; + uint8 internal constant MAX_COMMITMENT_DELAY = 5; + + VerifierProxy internal s_verifierProxy; + Verifier internal s_verifier; + Verifier internal s_verifier_2; + ErroredVerifier internal s_erroredVerifier; + + struct Signer { + uint256 mockPrivateKey; + address signerAddress; + } + + struct V1Report { + // The feed ID the report has data for + bytes32 feedId; + // The time the median value was observed on + uint32 observationsTimestamp; + // The median value agreed in an OCR round + int192 median; + // The best bid value agreed in an OCR round + int192 bid; + // The best ask value agreed in an OCR round + int192 ask; + // The upper bound of the block range the median value was observed within + uint64 blocknumberUpperBound; + // The blockhash for the upper bound of block range (ensures correct blockchain) + bytes32 upperBlockhash; + // The lower bound of the block range the median value was observed within + uint64 blocknumberLowerBound; + // The current block timestamp + uint64 currentBlockTimestamp; + } + + Signer[MAX_ORACLES] internal s_signers; + bytes32[] internal s_offchaintransmitters; + bool private s_baseTestInitialized; + + function setUp() public virtual { + // BaseTest.setUp is often called multiple times from tests' setUp due to inheritance. + if (s_baseTestInitialized) return; + s_baseTestInitialized = true; + + vm.startPrank(ADMIN); + vm.mockCall( + MOCK_VERIFIER_ADDRESS, + abi.encodeWithSelector(IERC165.supportsInterface.selector, IVerifier.verify.selector), + abi.encode(true) + ); + s_verifierProxy = new VerifierProxy(AccessControllerInterface(address(0))); + + s_verifier = new Verifier(address(s_verifierProxy)); + s_verifier_2 = new Verifier(address(s_verifierProxy)); + s_erroredVerifier = new ErroredVerifier(); + + for (uint256 i; i < MAX_ORACLES; i++) { + uint256 mockPK = i + 1; + s_signers[i].mockPrivateKey = mockPK; + s_signers[i].signerAddress = vm.addr(mockPK); + } + } + + function _getSigners(uint256 numSigners) internal view returns (Signer[] memory) { + Signer[] memory signers = new Signer[](numSigners); + for (uint256 i; i < numSigners; i++) { + signers[i] = s_signers[i]; + } + return signers; + } + + function _getSignerAddresses(Signer[] memory signers) internal view returns (address[] memory) { + address[] memory signerAddrs = new address[](signers.length); + for (uint256 i = 0; i < signerAddrs.length; i++) { + signerAddrs[i] = s_signers[i].signerAddress; + } + return signerAddrs; + } + + function _generateSignerSignatures( + bytes memory report, + bytes32[3] memory reportContext, + Signer[] memory signers + ) internal pure returns (bytes32[] memory rawRs, bytes32[] memory rawSs, bytes32 rawVs) { + bytes32[] memory rs = new bytes32[](signers.length); + bytes32[] memory ss = new bytes32[](signers.length); + bytes memory vs = new bytes(signers.length); + + bytes32 hash = keccak256(abi.encodePacked(keccak256(report), reportContext)); + + for (uint256 i = 0; i < signers.length; i++) { + (uint8 v, bytes32 r, bytes32 s) = vm.sign(signers[i].mockPrivateKey, hash); + rs[i] = r; + ss[i] = s; + vs[i] = bytes1(v - 27); + } + return (rs, ss, bytes32(vs)); + } + + function _encodeReport(V1Report memory report) internal pure returns (bytes memory) { + return + abi.encode( + report.feedId, + report.observationsTimestamp, + report.median, + report.bid, + report.ask, + report.blocknumberUpperBound, + report.upperBlockhash, + report.blocknumberLowerBound, + report.currentBlockTimestamp + ); + } + + function _generateV1EncodedBlob( + V1Report memory report, + bytes32[3] memory reportContext, + Signer[] memory signers + ) internal pure returns (bytes memory) { + bytes memory reportBytes = _encodeReport(report); + (bytes32[] memory rs, bytes32[] memory ss, bytes32 rawVs) = _generateSignerSignatures( + reportBytes, + reportContext, + signers + ); + return abi.encode(reportContext, reportBytes, rs, ss, rawVs); + } + + function _configDigestFromConfigData( + bytes32 feedId, + uint256 chainId, + address verifierAddr, + uint64 configCount, + address[] memory signers, + bytes32[] memory offchainTransmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) internal pure returns (bytes32) { + // Convert addresses to bytes array to match configurator + bytes[] memory signersAsBytes = new bytes[](signers.length); + for (uint i; i < signers.length; ++i) { + signersAsBytes[i] = abi.encodePacked(signers[i]); + } + + uint256 h = uint256( + keccak256( + abi.encode( + feedId, + chainId, + verifierAddr, + configCount, + signersAsBytes, + offchainTransmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig + ) + ) + ); + uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 + uint256 prefix = 0x0009 << (256 - 16); // 0x000900..00 + return bytes32((prefix & prefixMask) | (h & ~prefixMask)); + } + + function _createV1Report( + bytes32 feedId, + uint32 observationsTimestamp, + int192 median, + int192 bid, + int192 ask, + uint64 blocknumberUpperBound, + bytes32 upperBlockhash, + uint64 blocknumberLowerBound, + uint32 currentBlockTimestamp + ) internal pure returns (V1Report memory) { + return + V1Report({ + feedId: feedId, + observationsTimestamp: observationsTimestamp, + median: median, + bid: bid, + ask: ask, + blocknumberUpperBound: blocknumberUpperBound, + upperBlockhash: upperBlockhash, + blocknumberLowerBound: blocknumberLowerBound, + currentBlockTimestamp: currentBlockTimestamp + }); + } + + function _ccipReadURL(bytes32 feedId, uint256 commitmentBlock) internal pure returns (string memory url) { + return + string( + abi.encodePacked( + SERVER_URL, + "?feedIDHex=", + Strings.toHexString(uint256(feedId)), + "&L2Blocknumber=", + Strings.toString(commitmentBlock) + ) + ); + } +} + +contract BaseTestWithConfiguredVerifierAndFeeManager is BaseTest { + FeeManager internal feeManager; + RewardManager internal rewardManager; + ERC20Mock internal link; + WERC20Mock internal native; + + uint256 internal constant DEFAULT_REPORT_LINK_FEE = 1e10; + uint256 internal constant DEFAULT_REPORT_NATIVE_FEE = 1e12; + + bytes32 internal v1ConfigDigest; + bytes32 internal v3ConfigDigest; + + struct V3Report { + // The feed ID the report has data for + bytes32 feedId; + // The time the median value was observed on + uint32 observationsTimestamp; + // The timestamp the report is valid from + uint32 validFromTimestamp; + // The link fee + uint192 linkFee; + // The native fee + uint192 nativeFee; + // The expiry of the report + uint32 expiresAt; + // The median value agreed in an OCR round + int192 benchmarkPrice; + // The best bid value agreed in an OCR round + int192 bid; + // The best ask value agreed in an OCR round + int192 ask; + } + + function setUp() public virtual override { + BaseTest.setUp(); + Signer[] memory signers = _getSigners(MAX_ORACLES); + + s_verifierProxy.initializeVerifier(address(s_verifier)); + + v1ConfigDigest = _configDigestFromConfigData( + FEED_ID, + SOURCE_CHAIN_ID, + SOURCE_ADDRESS, + 1, + _getSignerAddresses(signers), + s_offchaintransmitters, + FAULT_TOLERANCE, + bytes(""), + VERIFIER_VERSION, + bytes("") + ); + + s_verifier.setConfig( + v1ConfigDigest, + _getSignerAddresses(signers), + FAULT_TOLERANCE, + new Common.AddressAndWeight[](0) + ); + + v3ConfigDigest = _configDigestFromConfigData( + FEED_ID_V3, + SOURCE_CHAIN_ID, + SOURCE_ADDRESS, + 1, + _getSignerAddresses(signers), + s_offchaintransmitters, + FAULT_TOLERANCE, + bytes(""), + VERIFIER_VERSION, + bytes("") + ); + + s_verifier.setConfig( + v3ConfigDigest, + _getSignerAddresses(signers), + FAULT_TOLERANCE, + new Common.AddressAndWeight[](0) + ); + + link = new ERC20Mock("LINK", "LINK", ADMIN, 0); + native = new WERC20Mock(); + + rewardManager = new RewardManager(address(link)); + feeManager = new FeeManager(address(link), address(native), address(s_verifierProxy), address(rewardManager)); + + s_verifierProxy.setFeeManager(feeManager); + rewardManager.setFeeManager(address(feeManager)); + } + + function _encodeReport(V3Report memory report) internal pure returns (bytes memory) { + return + abi.encode( + report.feedId, + report.observationsTimestamp, + report.validFromTimestamp, + report.nativeFee, + report.linkFee, + report.expiresAt, + report.benchmarkPrice, + report.bid, + report.ask + ); + } + + function _generateV3EncodedBlob( + V3Report memory report, + bytes32[3] memory reportContext, + Signer[] memory signers + ) internal pure returns (bytes memory) { + bytes memory reportBytes = _encodeReport(report); + (bytes32[] memory rs, bytes32[] memory ss, bytes32 rawVs) = _generateSignerSignatures( + reportBytes, + reportContext, + signers + ); + return abi.encode(reportContext, reportBytes, rs, ss, rawVs); + } + + function _generateV1Report() internal view returns (V1Report memory) { + return + _createV1Report( + FEED_ID, + OBSERVATIONS_TIMESTAMP, + MEDIAN, + BID, + ASK, + BLOCKNUMBER_UPPER_BOUND, + bytes32(blockhash(BLOCKNUMBER_UPPER_BOUND)), + BLOCKNUMBER_LOWER_BOUND, + uint32(block.timestamp) + ); + } + + function _generateV3Report() internal view returns (V3Report memory) { + return + V3Report({ + feedId: FEED_ID_V3, + observationsTimestamp: OBSERVATIONS_TIMESTAMP, + validFromTimestamp: uint32(block.timestamp), + nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), + linkFee: uint192(DEFAULT_REPORT_LINK_FEE), + expiresAt: uint32(block.timestamp), + benchmarkPrice: MEDIAN, + bid: BID, + ask: ASK + }); + } + + function _generateReportContext(bytes32 configDigest) internal pure returns (bytes32[3] memory) { + bytes32[3] memory reportContext; + reportContext[0] = configDigest; + reportContext[1] = bytes32(abi.encode(uint32(5), uint8(1))); + return reportContext; + } + + function _approveLink(address spender, uint256 quantity, address sender) internal { + address originalAddr = msg.sender; + changePrank(sender); + + link.approve(spender, quantity); + changePrank(originalAddr); + } + + function _approveNative(address spender, uint256 quantity, address sender) internal { + address originalAddr = msg.sender; + changePrank(sender); + + native.approve(spender, quantity); + changePrank(originalAddr); + } + + function _verify(bytes memory payload, address feeAddress, uint256 wrappedNativeValue, address sender) internal { + address originalAddr = msg.sender; + changePrank(sender); + + s_verifierProxy.verify{value: wrappedNativeValue}(payload, abi.encode(feeAddress)); + + changePrank(originalAddr); + } + + function _verifyBulk( + bytes[] memory payload, + address feeAddress, + uint256 wrappedNativeValue, + address sender + ) internal { + address originalAddr = msg.sender; + changePrank(sender); + + s_verifierProxy.verifyBulk{value: wrappedNativeValue}(payload, abi.encode(feeAddress)); + + changePrank(originalAddr); + } +} + +contract BaseTestWithMultipleConfiguredDigests is BaseTestWithConfiguredVerifierAndFeeManager { + bytes32 internal s_configDigestOne; + bytes32 internal s_configDigestTwo; + bytes32 internal s_configDigestThree; + bytes32 internal s_configDigestFour; + bytes32 internal s_configDigestFive; + + uint32 internal s_numConfigsSet; + + uint8 internal constant FAULT_TOLERANCE_TWO = 2; + uint8 internal constant FAULT_TOLERANCE_THREE = 1; + + function setUp() public virtual override { + BaseTestWithConfiguredVerifierAndFeeManager.setUp(); + Signer[] memory signers = _getSigners(MAX_ORACLES); + + s_configDigestOne = v1ConfigDigest; + + // Verifier 1, Feed 1, Config 2 + Signer[] memory secondSetOfSigners = _getSigners(8); + s_configDigestTwo = _configDigestFromConfigData( + FEED_ID, + SOURCE_CHAIN_ID, + SOURCE_ADDRESS, + 2, + _getSignerAddresses(secondSetOfSigners), + s_offchaintransmitters, + FAULT_TOLERANCE_TWO, + bytes(""), + 2, + bytes("") + ); + s_verifier.setConfig( + s_configDigestTwo, + _getSignerAddresses(secondSetOfSigners), + FAULT_TOLERANCE_TWO, + new Common.AddressAndWeight[](0) + ); + + // Verifier 1, Feed 1, Config 3 + Signer[] memory thirdSetOfSigners = _getSigners(5); + s_configDigestThree = _configDigestFromConfigData( + FEED_ID, + SOURCE_CHAIN_ID, + SOURCE_ADDRESS, + 3, + _getSignerAddresses(thirdSetOfSigners), + s_offchaintransmitters, + FAULT_TOLERANCE_THREE, + bytes(""), + 3, + bytes("") + ); + s_verifier.setConfig( + s_configDigestThree, + _getSignerAddresses(thirdSetOfSigners), + FAULT_TOLERANCE_THREE, + new Common.AddressAndWeight[](0) + ); + + // Verifier 1, Feed 2, Config 1 + s_configDigestFour = _configDigestFromConfigData( + FEED_ID_2, + SOURCE_CHAIN_ID, + SOURCE_ADDRESS, + 1, + _getSignerAddresses(signers), + s_offchaintransmitters, + FAULT_TOLERANCE, + bytes(""), + 4, + bytes("") + ); + s_verifier.setConfig( + s_configDigestFour, + _getSignerAddresses(signers), + FAULT_TOLERANCE, + new Common.AddressAndWeight[](0) + ); + + // Verifier 2, Feed 3, Config 1 + s_verifierProxy.initializeVerifier(address(s_verifier_2)); + s_configDigestFive = _configDigestFromConfigData( + FEED_ID_3, + SOURCE_CHAIN_ID, + SOURCE_ADDRESS, + 1, + _getSignerAddresses(signers), + s_offchaintransmitters, + FAULT_TOLERANCE, + bytes(""), + 5, + bytes("") + ); + s_verifier_2.setConfig( + s_configDigestFive, + _getSignerAddresses(signers), + FAULT_TOLERANCE, + new Common.AddressAndWeight[](0) + ); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierActivateConfigTest.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierActivateConfigTest.t.sol new file mode 100644 index 00000000000..f5f3598210c --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierActivateConfigTest.t.sol @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTestWithConfiguredVerifierAndFeeManager, BaseTestWithMultipleConfiguredDigests} from "./BaseVerifierTest.t.sol"; +import {Verifier} from "../../Verifier.sol"; + +contract VerifierActivateConfigTestV05 is BaseTestWithConfiguredVerifierAndFeeManager { + function test_revertsIfNotOwner() public { + vm.expectRevert("Only callable by owner"); + + changePrank(address(s_verifierProxy)); + s_verifier.activateConfig(bytes32("mock")); + } + + function test_revertsIfDigestIsEmpty() public { + vm.expectRevert(abi.encodeWithSelector(Verifier.DigestEmpty.selector)); + s_verifier.activateConfig(bytes32("")); + } + + function test_revertsIfDigestNotSet() public { + vm.expectRevert(abi.encodeWithSelector(Verifier.DigestNotSet.selector, bytes32("non-existent-digest"))); + s_verifier.activateConfig(bytes32("non-existent-digest")); + } +} + +contract VerifierActivateConfigWithDeactivatedConfigTestV05 is BaseTestWithMultipleConfiguredDigests { + bytes32[3] internal s_reportContext; + + event ConfigActivated(bytes32 configDigest); + + V1Report internal s_testReportOne; + + function setUp() public override { + BaseTestWithMultipleConfiguredDigests.setUp(); + s_reportContext[0] = s_configDigestTwo; + s_reportContext[1] = bytes32(abi.encode(uint32(5), uint8(1))); + s_testReportOne = _createV1Report( + FEED_ID, + uint32(block.timestamp), + MEDIAN, + BID, + ASK, + uint64(block.number), + blockhash(block.number + 3), + uint64(block.number + 3), + uint32(block.timestamp) + ); + + s_verifier.deactivateConfig(s_configDigestTwo); + } + + function test_allowsVerification() public { + s_verifier.activateConfig(s_configDigestTwo); + changePrank(address(s_verifierProxy)); + + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(FAULT_TOLERANCE_TWO + 1) + ); + s_verifier.verify(signedReport, msg.sender); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierProxyConstructorTest.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierProxyConstructorTest.t.sol new file mode 100644 index 00000000000..811a9b440ee --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierProxyConstructorTest.t.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTest} from "./BaseVerifierTest.t.sol"; +import {VerifierProxy} from "../../VerifierProxy.sol"; +import {AccessControllerInterface} from "../../../../shared/interfaces/AccessControllerInterface.sol"; + +contract VerifierProxyConstructorTest is BaseTest { + function test_correctlySetsTheOwner() public { + VerifierProxy proxy = new VerifierProxy(AccessControllerInterface(address(0))); + assertEq(proxy.owner(), ADMIN); + } + + function test_correctlySetsTheCorrectAccessControllerInterface() public { + address accessControllerAddr = address(1234); + VerifierProxy proxy = new VerifierProxy(AccessControllerInterface(accessControllerAddr)); + assertEq(address(proxy.s_accessController()), accessControllerAddr); + } + + function test_correctlySetsVersion() public view { + string memory version = s_verifierProxy.typeAndVersion(); + assertEq(version, "VerifierProxy 2.0.0"); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierProxyInitializeVerifierTest.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierProxyInitializeVerifierTest.t.sol new file mode 100644 index 00000000000..d3c372797fd --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierProxyInitializeVerifierTest.t.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTest} from "./BaseVerifierTest.t.sol"; +import {VerifierProxy} from "../../VerifierProxy.sol"; + +contract VerifierProxyInitializeVerifierTestV05 is BaseTest { + bytes32 latestDigest; + + function setUp() public override { + BaseTest.setUp(); + } + + function test_revertsIfNotOwner() public { + changePrank(USER); + vm.expectRevert("Only callable by owner"); + s_verifierProxy.initializeVerifier(address(s_verifier)); + } + + function test_revertsIfZeroAddress() public { + vm.expectRevert(abi.encodeWithSelector(VerifierProxy.ZeroAddress.selector)); + s_verifierProxy.initializeVerifier(address(0)); + } + + function test_revertsIfVerifierAlreadyInitialized() public { + s_verifierProxy.initializeVerifier(address(s_verifier)); + vm.expectRevert(abi.encodeWithSelector(VerifierProxy.VerifierAlreadyInitialized.selector, address(s_verifier))); + s_verifierProxy.initializeVerifier(address(s_verifier)); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierProxySetAccessControllerTest.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierProxySetAccessControllerTest.t.sol new file mode 100644 index 00000000000..03bd6d97ee5 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierProxySetAccessControllerTest.t.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTest} from "./BaseVerifierTest.t.sol"; +import {AccessControllerInterface} from "../../../../shared/interfaces/AccessControllerInterface.sol"; + +contract VerifierProxySetAccessControllerTest is BaseTest { + event AccessControllerSet(address oldAccessController, address newAccessController); + + function test_revertsIfCalledByNonOwner() public { + vm.expectRevert("Only callable by owner"); + + changePrank(USER); + s_verifierProxy.setAccessController(AccessControllerInterface(ACCESS_CONTROLLER_ADDRESS)); + } + + function test_successfullySetsNewAccessController() public { + s_verifierProxy.setAccessController(AccessControllerInterface(ACCESS_CONTROLLER_ADDRESS)); + AccessControllerInterface ac = s_verifierProxy.s_accessController(); + assertEq(address(ac), ACCESS_CONTROLLER_ADDRESS); + } + + function test_successfullySetsNewAccessControllerIsEmpty() public { + s_verifierProxy.setAccessController(AccessControllerInterface(address(0))); + AccessControllerInterface ac = s_verifierProxy.s_accessController(); + assertEq(address(ac), address(0)); + } + + function test_emitsTheCorrectEvent() public { + vm.expectEmit(true, false, false, false); + emit AccessControllerSet(address(0), ACCESS_CONTROLLER_ADDRESS); + s_verifierProxy.setAccessController(AccessControllerInterface(ACCESS_CONTROLLER_ADDRESS)); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierProxySetVerifierTest.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierProxySetVerifierTest.t.sol new file mode 100644 index 00000000000..c81df675d68 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierProxySetVerifierTest.t.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTestWithConfiguredVerifierAndFeeManager} from "./BaseVerifierTest.t.sol"; +import {IVerifier} from "../../interfaces/IVerifier.sol"; +import {VerifierProxy} from "../../VerifierProxy.sol"; +import {IERC165} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {Common} from "../../../libraries/Common.sol"; + +contract VerifierProxyInitializeVerifierTestV05 is BaseTestWithConfiguredVerifierAndFeeManager { + function test_revertsIfNotCorrectVerifier() public { + vm.expectRevert(abi.encodeWithSelector(VerifierProxy.AccessForbidden.selector)); + s_verifierProxy.setVerifier(bytes32("prev-config"), bytes32("new-config"), new Common.AddressAndWeight[](0)); + } + + function test_revertsIfDigestAlreadySet() public { + bytes32 takenDigest = v1ConfigDigest; + + address maliciousVerifier = address(666); + bytes32 maliciousDigest = bytes32("malicious-digest"); + vm.mockCall( + maliciousVerifier, + abi.encodeWithSelector(IERC165.supportsInterface.selector, IVerifier.verify.selector), + abi.encode(true) + ); + s_verifierProxy.initializeVerifier(maliciousVerifier); + vm.expectRevert( + abi.encodeWithSelector(VerifierProxy.ConfigDigestAlreadySet.selector, takenDigest, address(s_verifier)) + ); + changePrank(address(maliciousVerifier)); + s_verifierProxy.setVerifier(maliciousDigest, takenDigest, new Common.AddressAndWeight[](0)); + } + + function test_updatesVerifierIfVerifier() public { + bytes32 prevDigest = v1ConfigDigest; + changePrank(address(s_verifier)); + s_verifierProxy.setVerifier(prevDigest, bytes32("new-config"), new Common.AddressAndWeight[](0)); + assertEq(s_verifierProxy.getVerifier(bytes32("new-config")), address(s_verifier)); + assertEq(s_verifierProxy.getVerifier(prevDigest), address(s_verifier)); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierProxyTest.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierProxyTest.t.sol new file mode 100644 index 00000000000..1b44dda438e --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierProxyTest.t.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTestWithConfiguredVerifierAndFeeManager} from "./BaseVerifierTest.t.sol"; +import {VerifierProxy} from "../../VerifierProxy.sol"; +import {FeeManager} from "../../FeeManager.sol"; + +contract VerifierProxyInitializeVerifierTestV05 is BaseTestWithConfiguredVerifierAndFeeManager { + function test_setFeeManagerZeroAddress() public { + vm.expectRevert(abi.encodeWithSelector(VerifierProxy.ZeroAddress.selector)); + s_verifierProxy.setFeeManager(FeeManager(address(0))); + } + + function test_setFeeManagerWhichDoesntHonourInterface() public { + vm.expectRevert(abi.encodeWithSelector(VerifierProxy.FeeManagerInvalid.selector)); + s_verifierProxy.setFeeManager(FeeManager(address(s_verifier))); + } + + function test_setFeeManagerWhichDoesntHonourIERC165Interface() public { + vm.expectRevert(); + s_verifierProxy.setFeeManager(FeeManager(address(1))); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierProxyUnsetVerifierTest.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierProxyUnsetVerifierTest.t.sol new file mode 100644 index 00000000000..74da281a3cd --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierProxyUnsetVerifierTest.t.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTest, BaseTestWithConfiguredVerifierAndFeeManager} from "./BaseVerifierTest.t.sol"; +import {VerifierProxy} from "../../VerifierProxy.sol"; + +contract VerifierProxyUnsetVerifierTest is BaseTest { + function test_revertsIfNotAdmin() public { + vm.expectRevert("Only callable by owner"); + + changePrank(USER); + s_verifierProxy.unsetVerifier(bytes32("")); + } + + function test_revertsIfDigestDoesNotExist() public { + vm.expectRevert(abi.encodeWithSelector(VerifierProxy.VerifierNotFound.selector, bytes32(""))); + s_verifierProxy.unsetVerifier(bytes32("")); + } +} + +contract VerifierProxyUnsetVerifierWithPreviouslySetVerifierTest is BaseTestWithConfiguredVerifierAndFeeManager { + bytes32 internal s_configDigest; + + event VerifierUnset(bytes32 configDigest, address verifierAddr); + + function setUp() public override { + BaseTestWithConfiguredVerifierAndFeeManager.setUp(); + s_configDigest = v3ConfigDigest; + } + + function test_correctlyUnsetsVerifier() public { + s_verifierProxy.unsetVerifier(s_configDigest); + address verifierAddr = s_verifierProxy.getVerifier(s_configDigest); + assertEq(verifierAddr, address(0)); + } + + function test_emitsAnEventAfterUnsettingVerifier() public { + vm.expectEmit(true, false, false, false); + emit VerifierUnset(s_configDigest, address(s_verifier)); + s_verifierProxy.unsetVerifier(s_configDigest); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierSetConfigTest.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierSetConfigTest.t.sol new file mode 100644 index 00000000000..7c082a98bd6 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierSetConfigTest.t.sol @@ -0,0 +1,467 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTest, BaseTestWithMultipleConfiguredDigests} from "./BaseVerifierTest.t.sol"; +import {Verifier} from "../../Verifier.sol"; +import {Common} from "../../../libraries/Common.sol"; +import {MockConfigurator} from "../mocks/MockConfigurator.sol"; + +contract VerifierSetConfigTestV05 is BaseTest { + function setUp() public virtual override { + BaseTest.setUp(); + } + + function test_revertsIfCalledByNonOwner() public { + vm.expectRevert("Only callable by owner"); + Signer[] memory signers = _getSigners(MAX_ORACLES); + + bytes32 configDigest = _configDigestFromConfigData( + FEED_ID, + SOURCE_CHAIN_ID, + SOURCE_ADDRESS, + 1, + _getSignerAddresses(signers), + s_offchaintransmitters, + FAULT_TOLERANCE, + bytes(""), + VERIFIER_VERSION, + bytes("") + ); + + changePrank(USER); + s_verifier.setConfig(configDigest, _getSignerAddresses(signers), FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + } + + function test_revertsIfSetWithTooManySigners() public { + address[] memory signers = new address[](MAX_ORACLES + 1); + + bytes32 configDigest = _configDigestFromConfigData( + FEED_ID, + SOURCE_CHAIN_ID, + SOURCE_ADDRESS, + 1, + signers, + s_offchaintransmitters, + FAULT_TOLERANCE, + bytes(""), + VERIFIER_VERSION, + bytes("") + ); + + vm.expectRevert(abi.encodeWithSelector(Verifier.ExcessSigners.selector, signers.length, MAX_ORACLES)); + s_verifier.setConfig(configDigest, signers, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + } + + function test_revertsIfFaultToleranceIsZero() public { + Signer[] memory signers = _getSigners(MAX_ORACLES); + + bytes32 configDigest = _configDigestFromConfigData( + FEED_ID, + SOURCE_CHAIN_ID, + SOURCE_ADDRESS, + 1, + _getSignerAddresses(signers), + s_offchaintransmitters, + 0, + bytes(""), + VERIFIER_VERSION, + bytes("") + ); + + vm.expectRevert(abi.encodeWithSelector(Verifier.FaultToleranceMustBePositive.selector)); + s_verifier.setConfig(configDigest, _getSignerAddresses(signers), 0, new Common.AddressAndWeight[](0)); + } + + function test_revertsIfNotEnoughSigners() public { + address[] memory signers = new address[](2); + signers[0] = address(1000); + signers[1] = address(1001); + + bytes32 configDigest = _configDigestFromConfigData( + FEED_ID, + SOURCE_CHAIN_ID, + SOURCE_ADDRESS, + 1, + signers, + s_offchaintransmitters, + FAULT_TOLERANCE, + bytes(""), + VERIFIER_VERSION, + bytes("") + ); + + vm.expectRevert( + abi.encodeWithSelector(Verifier.InsufficientSigners.selector, signers.length, FAULT_TOLERANCE * 3 + 1) + ); + s_verifier.setConfig(configDigest, signers, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + } + + function test_revertsIfDuplicateSigners() public { + Signer[] memory signers = _getSigners(MAX_ORACLES); + address[] memory signerAddrs = _getSignerAddresses(signers); + signerAddrs[0] = signerAddrs[1]; + + bytes32 configDigest = _configDigestFromConfigData( + FEED_ID, + SOURCE_CHAIN_ID, + SOURCE_ADDRESS, + 1, + signerAddrs, + s_offchaintransmitters, + FAULT_TOLERANCE, + bytes(""), + VERIFIER_VERSION, + bytes("") + ); + + vm.expectRevert(abi.encodeWithSelector(Verifier.NonUniqueSignatures.selector)); + s_verifier.setConfig(configDigest, signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + } + + function test_revertsIfSignerContainsZeroAddress() public { + Signer[] memory signers = _getSigners(MAX_ORACLES); + address[] memory signerAddrs = _getSignerAddresses(signers); + signerAddrs[0] = address(0); + + bytes32 configDigest = _configDigestFromConfigData( + FEED_ID, + SOURCE_CHAIN_ID, + SOURCE_ADDRESS, + 1, + signerAddrs, + s_offchaintransmitters, + FAULT_TOLERANCE, + bytes(""), + VERIFIER_VERSION, + bytes("") + ); + + vm.expectRevert(abi.encodeWithSelector(Verifier.ZeroAddress.selector)); + s_verifier.setConfig(configDigest, signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + } + + function test_correctlyUpdatesTheConfig() public { + Signer[] memory signers = _getSigners(MAX_ORACLES); + + s_verifierProxy.initializeVerifier(address(s_verifier)); + + bytes32 configDigest = _configDigestFromConfigData( + FEED_ID, + SOURCE_CHAIN_ID, + SOURCE_ADDRESS, + 1, + _getSignerAddresses(signers), + s_offchaintransmitters, + FAULT_TOLERANCE, + bytes(""), + VERIFIER_VERSION, + bytes("") + ); + + s_verifier.setConfig(configDigest, _getSignerAddresses(signers), FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + + uint32 blockNumber = s_verifier.latestConfigDetails(configDigest); + assertEq(blockNumber, block.number); + } +} + +contract VerifierUpdateConfigTest is BaseTest { + function setUp() public virtual override { + BaseTest.setUp(); + + s_verifierProxy.initializeVerifier(address(s_verifier)); + } + + function test_updateConfig() public { + // Get initial signers and config digest + address[] memory signerAddresses = _getSignerAddresses(_getSigners(15)); + bytes32 configDigest = keccak256("test222"); + + // Set initial config + s_verifier.setConfig(configDigest, signerAddresses, 4, new Common.AddressAndWeight[](0)); + + // Unset the config + s_verifier.updateConfig(configDigest, signerAddresses, signerAddresses, 4); + } + + function test_updateConfigRevertsIfFIsZero() public { + // Get initial signers and config digest + address[] memory signerAddresses = _getSignerAddresses(_getSigners(15)); + bytes32 configDigest = keccak256("test"); + + // Set initial config + s_verifier.setConfig(configDigest, signerAddresses, 4, new Common.AddressAndWeight[](0)); + + // Try to update with f=0 + vm.expectRevert(Verifier.FaultToleranceMustBePositive.selector); + s_verifier.updateConfig(configDigest, signerAddresses, signerAddresses, 0); + } + + function test_updateConfigRevertsIfFTooHigh() public { + // Get initial signers and config digest + address[] memory signerAddresses = _getSignerAddresses(_getSigners(15)); + bytes32 configDigest = keccak256("test"); + + // Set initial config + s_verifier.setConfig(configDigest, signerAddresses, 4, new Common.AddressAndWeight[](0)); + + // Try to update with f too high + vm.expectRevert(abi.encodeWithSelector(Verifier.InsufficientSigners.selector, signerAddresses.length, 46)); + s_verifier.updateConfig(configDigest, signerAddresses, signerAddresses, 15); + } + + function test_updateConfigWithDifferentSigners() public { + // Get initial signers and config digest + address[] memory initialSigners = _getSignerAddresses(_getSigners(15)); + bytes32 configDigest = keccak256("test"); + + // Set initial config + s_verifier.setConfig(configDigest, initialSigners, 4, new Common.AddressAndWeight[](0)); + + // Get new signers + address[] memory newSigners = _getSignerAddresses(_getSigners(20)); + + // Update config with new signers + s_verifier.updateConfig(configDigest, initialSigners, newSigners, 6); + + // Verify config was updated + uint32 blockNumber = s_verifier.latestConfigDetails(configDigest); + assertEq(blockNumber, block.number); + } + + function test_updateConfigRevertsIfDigestNotSet() public { + address[] memory signerAddresses = _getSignerAddresses(_getSigners(15)); + bytes32 nonExistentDigest = keccak256("nonexistent"); + + vm.expectRevert(abi.encodeWithSelector(Verifier.DigestNotSet.selector, nonExistentDigest)); + s_verifier.updateConfig(nonExistentDigest, signerAddresses, signerAddresses, 4); + } + + function test_updateConfigRevertsIfPrevSignersLengthMismatch() public { + // Get initial signers and config digest + address[] memory initialSigners = _getSignerAddresses(_getSigners(15)); + bytes32 configDigest = keccak256("test"); + + // Set initial config + s_verifier.setConfig(configDigest, initialSigners, 4, new Common.AddressAndWeight[](0)); + + // Try to update with wrong number of previous signers + address[] memory wrongPrevSigners = _getSignerAddresses(_getSigners(10)); + address[] memory newSigners = _getSignerAddresses(_getSigners(15)); + + vm.expectRevert(Verifier.NonUniqueSignatures.selector); + s_verifier.updateConfig(configDigest, wrongPrevSigners, newSigners, 4); + } + + function test_updateConfigRevertsIfCalledByNonOwner() public { + address[] memory signerAddresses = _getSignerAddresses(_getSigners(15)); + bytes32 configDigest = keccak256("test"); + + // Set initial config + s_verifier.setConfig(configDigest, signerAddresses, 4, new Common.AddressAndWeight[](0)); + + // Try to update as non-owner + changePrank(USER); + vm.expectRevert("Only callable by owner"); + s_verifier.updateConfig(configDigest, signerAddresses, signerAddresses, 4); + } +} + +contract VerifierSetConfigWhenThereAreMultipleDigestsTest05 is BaseTestWithMultipleConfiguredDigests { + function test_correctlyUpdatesTheDigestInTheProxy() public { + Signer[] memory newSigners = _getSigners(15); + + bytes32 configDigest = _configDigestFromConfigData( + FEED_ID, + SOURCE_CHAIN_ID, + SOURCE_ADDRESS, + 1, + _getSignerAddresses(newSigners), + s_offchaintransmitters, + 4, + bytes(""), + VERIFIER_VERSION, + bytes("") + ); + + s_verifier.setConfig(configDigest, _getSignerAddresses(newSigners), 4, new Common.AddressAndWeight[](0)); + + address verifierAddr = s_verifierProxy.getVerifier(configDigest); + assertEq(verifierAddr, address(s_verifier)); + } + + function test_correctlyUpdatesDigestsOnMultipleVerifiersInTheProxy() public { + Signer[] memory newSigners = _getSigners(15); + + bytes32 configDigest = _configDigestFromConfigData( + FEED_ID_2, + SOURCE_CHAIN_ID, + SOURCE_ADDRESS, + 1, + _getSignerAddresses(newSigners), + s_offchaintransmitters, + 4, + bytes(""), + VERIFIER_VERSION, + bytes("") + ); + + s_verifier.setConfig(configDigest, _getSignerAddresses(newSigners), 4, new Common.AddressAndWeight[](0)); + + address verifierAddr = s_verifierProxy.getVerifier(configDigest); + assertEq(verifierAddr, address(s_verifier)); + + bytes32 configDigest2 = _configDigestFromConfigData( + FEED_ID_3, + SOURCE_CHAIN_ID, + SOURCE_ADDRESS, + 1, + _getSignerAddresses(newSigners), + s_offchaintransmitters, + 4, + bytes(""), + VERIFIER_VERSION, + bytes("") + ); + + s_verifier_2.setConfig(configDigest2, _getSignerAddresses(newSigners), 4, new Common.AddressAndWeight[](0)); + + address verifierAddr2 = s_verifierProxy.getVerifier(configDigest2); + assertEq(verifierAddr2, address(s_verifier_2)); + } + + function test_correctlySetsConfigWhenDigestsAreRemoved() public { + s_verifier.deactivateConfig(s_configDigestTwo); + + Signer[] memory newSigners = _getSigners(15); + + bytes32 configDigest = _configDigestFromConfigData( + FEED_ID, + SOURCE_CHAIN_ID, + SOURCE_ADDRESS, + 1, + _getSignerAddresses(newSigners), + s_offchaintransmitters, + 4, + bytes(""), + VERIFIER_VERSION, + bytes("") + ); + + s_verifier.setConfig(configDigest, _getSignerAddresses(newSigners), 4, new Common.AddressAndWeight[](0)); + + uint32 blockNumber = s_verifier.latestConfigDetails(configDigest); + + assertEq(blockNumber, block.number); + } + + function test_revertsIfDuplicateConfigIsSet() public { + // Set initial config + bytes32 configDigest = _configDigestFromConfigData( + FEED_ID, + SOURCE_CHAIN_ID, + SOURCE_ADDRESS, + 1, + _getSignerAddresses(_getSigners(15)), + s_offchaintransmitters, + 4, + bytes(""), + VERIFIER_VERSION, + bytes("") + ); + + s_verifier.setConfig(configDigest, _getSignerAddresses(_getSigners(15)), 4, new Common.AddressAndWeight[](0)); + + // Try to set same config again + vm.expectRevert(abi.encodeWithSelector(Verifier.ConfigDigestAlreadySet.selector)); + s_verifier.setConfig(configDigest, _getSignerAddresses(_getSigners(15)), 4, new Common.AddressAndWeight[](0)); + } + + function test_incrementalConfigUpdates() public { + // Set initial config + bytes32 configDigest1 = _configDigestFromConfigData( + FEED_ID, + SOURCE_CHAIN_ID, + SOURCE_ADDRESS, + 1, + _getSignerAddresses(_getSigners(15)), + s_offchaintransmitters, + 4, + bytes(""), + VERIFIER_VERSION, + bytes("") + ); + + s_verifier.setConfig(configDigest1, _getSignerAddresses(_getSigners(15)), 4, new Common.AddressAndWeight[](0)); + + // Set second config + bytes32 configDigest2 = _configDigestFromConfigData( + FEED_ID, + SOURCE_CHAIN_ID, + SOURCE_ADDRESS, + 2, + _getSignerAddresses(_getSigners(15)), + s_offchaintransmitters, + 4, + bytes(""), + VERIFIER_VERSION, + bytes("") + ); + + s_verifier.setConfig(configDigest2, _getSignerAddresses(_getSigners(15)), 4, new Common.AddressAndWeight[](0)); + + // Set third config + bytes32 configDigest3 = _configDigestFromConfigData( + FEED_ID, + SOURCE_CHAIN_ID, + SOURCE_ADDRESS, + 3, + _getSignerAddresses(_getSigners(15)), + s_offchaintransmitters, + 4, + bytes(""), + VERIFIER_VERSION, + bytes("") + ); + + s_verifier.setConfig(configDigest3, _getSignerAddresses(_getSigners(15)), 4, new Common.AddressAndWeight[](0)); + } + + function test_configDigestMatchesConfiguratorDigest() public { + MockConfigurator configurator = new MockConfigurator(); + + // Convert addresses to bytes array + Signer[] memory signers = _getSigners(15); + bytes[] memory signersAsBytes = new bytes[](signers.length); + for (uint i; i < signers.length; ++i) { + signersAsBytes[i] = abi.encodePacked(signers[i].signerAddress); + } + + configurator.setStagingConfig( + FEED_ID, + signersAsBytes, + s_offchaintransmitters, + 4, + bytes(""), + VERIFIER_VERSION, + bytes("") + ); + + bytes32 expectedConfigDigest = _configDigestFromConfigData( + FEED_ID, + block.chainid, + address(configurator), + 1, + _getSignerAddresses(signers), + s_offchaintransmitters, + 4, + bytes(""), + VERIFIER_VERSION, + bytes("") + ); + + (, , bytes32 configDigest) = configurator.s_configurationStates(FEED_ID); + + assertEq(configDigest, expectedConfigDigest); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierTest.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierTest.t.sol new file mode 100644 index 00000000000..36933d18b46 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierTest.t.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTest} from "./BaseVerifierTest.t.sol"; +import {Verifier} from "../../Verifier.sol"; + +contract VerifierConstructorTestV05 is BaseTest { + function test_revertsIfInitializedWithEmptyVerifierProxy() public { + vm.expectRevert(abi.encodeWithSelector(Verifier.ZeroAddress.selector)); + new Verifier(address(0)); + } + + function test_setsTheCorrectProperties() public { + Verifier v = new Verifier(address(s_verifierProxy)); + assertEq(v.owner(), ADMIN); + + uint32 blockNumber = v.latestConfigDetails(FEED_ID); + assertEq(blockNumber, 0); + + string memory typeAndVersion = s_verifier.typeAndVersion(); + assertEq(typeAndVersion, "Verifier 2.0.0"); + } +} + +contract VerifierSupportsInterfaceTest is BaseTest { + function test_falseIfIsNotCorrectInterface() public view { + bool isInterface = s_verifier.supportsInterface(bytes4("abcd")); + assertEq(isInterface, false); + } + + function test_trueIfIsCorrectInterface() public view { + bool isInterface = s_verifier.supportsInterface(Verifier.verify.selector); + assertEq(isInterface, true); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierTestBillingReport.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierTestBillingReport.t.sol new file mode 100644 index 00000000000..deb1d1fb4c1 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierTestBillingReport.t.sol @@ -0,0 +1,218 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTestWithConfiguredVerifierAndFeeManager} from "./BaseVerifierTest.t.sol"; + +contract VerifierTestWithConfiguredVerifierAndFeeManager is BaseTestWithConfiguredVerifierAndFeeManager { + uint256 internal constant DEFAULT_LINK_MINT_QUANTITY = 100 ether; + uint256 internal constant DEFAULT_NATIVE_MINT_QUANTITY = 100 ether; + + function setUp() public virtual override { + super.setUp(); + + //mint some tokens to the user + link.mint(USER, DEFAULT_LINK_MINT_QUANTITY); + native.mint(USER, DEFAULT_NATIVE_MINT_QUANTITY); + vm.deal(USER, DEFAULT_NATIVE_MINT_QUANTITY); + + //mint some link tokens to the feeManager pool + link.mint(address(feeManager), DEFAULT_REPORT_LINK_FEE); + } +} + +contract VerifierTestBillingReportV05 is VerifierTestWithConfiguredVerifierAndFeeManager { + function test_verifyWithLink() public { + bytes memory signedReport = _generateV3EncodedBlob( + _generateV3Report(), + _generateReportContext(v3ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); + + _verify(signedReport, address(link), 0, USER); + + assertEq(link.balanceOf(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE); + } + + function test_verifyWithNative() public { + bytes memory signedReport = _generateV3EncodedBlob( + _generateV3Report(), + _generateReportContext(v3ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + _approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); + + _verify(signedReport, address(native), 0, USER); + + assertEq(native.balanceOf(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); + assertEq(link.balanceOf(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + } + + function test_verifyWithNativeUnwrapped() public { + bytes memory signedReport = _generateV3EncodedBlob( + _generateV3Report(), + _generateReportContext(v3ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + _verify(signedReport, address(native), DEFAULT_REPORT_NATIVE_FEE, USER); + + assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); + assertEq(address(feeManager).balance, 0); + } + + function test_verifyWithNativeUnwrappedReturnsChange() public { + bytes memory signedReport = _generateV3EncodedBlob( + _generateV3Report(), + _generateReportContext(v3ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + _verify(signedReport, address(native), DEFAULT_REPORT_NATIVE_FEE * 2, USER); + + assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); + assertEq(address(feeManager).balance, 0); + } +} + +contract VerifierBulkVerifyBillingReportV05 is VerifierTestWithConfiguredVerifierAndFeeManager { + uint256 internal constant NUMBERS_OF_REPORTS = 5; + + function test_verifyWithBulkLink() public { + bytes memory signedReport = _generateV3EncodedBlob( + _generateV3Report(), + _generateReportContext(v3ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + bytes[] memory signedReports = new bytes[](NUMBERS_OF_REPORTS); + for (uint256 i = 0; i < NUMBERS_OF_REPORTS; i++) { + signedReports[i] = signedReport; + } + + _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE * NUMBERS_OF_REPORTS, USER); + + _verifyBulk(signedReports, address(link), 0, USER); + + assertEq(link.balanceOf(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE * NUMBERS_OF_REPORTS); + assertEq(link.balanceOf(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * NUMBERS_OF_REPORTS); + } + + function test_verifyWithBulkNative() public { + bytes memory signedReport = _generateV3EncodedBlob( + _generateV3Report(), + _generateReportContext(v3ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + bytes[] memory signedReports = new bytes[](NUMBERS_OF_REPORTS); + for (uint256 i = 0; i < NUMBERS_OF_REPORTS; i++) { + signedReports[i] = signedReport; + } + + _approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE * NUMBERS_OF_REPORTS, USER); + + _verifyBulk(signedReports, address(native), 0, USER); + + assertEq(native.balanceOf(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * NUMBERS_OF_REPORTS); + } + + function test_verifyWithBulkNativeUnwrapped() public { + bytes memory signedReport = _generateV3EncodedBlob( + _generateV3Report(), + _generateReportContext(v3ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + bytes[] memory signedReports = new bytes[](NUMBERS_OF_REPORTS); + for (uint256 i; i < NUMBERS_OF_REPORTS; i++) { + signedReports[i] = signedReport; + } + + _verifyBulk(signedReports, address(native), DEFAULT_REPORT_NATIVE_FEE * NUMBERS_OF_REPORTS, USER); + + assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * 5); + assertEq(address(feeManager).balance, 0); + } + + function test_verifyWithBulkNativeUnwrappedReturnsChange() public { + bytes memory signedReport = _generateV3EncodedBlob( + _generateV3Report(), + _generateReportContext(v3ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + bytes[] memory signedReports = new bytes[](NUMBERS_OF_REPORTS); + for (uint256 i = 0; i < NUMBERS_OF_REPORTS; i++) { + signedReports[i] = signedReport; + } + + _verifyBulk(signedReports, address(native), DEFAULT_REPORT_NATIVE_FEE * (NUMBERS_OF_REPORTS * 2), USER); + + assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * NUMBERS_OF_REPORTS); + assertEq(address(feeManager).balance, 0); + } + + function test_verifyMultiVersions() public { + bytes memory signedReportV1 = _generateV1EncodedBlob( + _generateV1Report(), + _generateReportContext(v1ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + bytes memory signedReportV3 = _generateV3EncodedBlob( + _generateV3Report(), + _generateReportContext(v3ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + bytes[] memory signedReports = new bytes[](3); + + signedReports[0] = signedReportV1; + signedReports[1] = signedReportV3; + signedReports[2] = signedReportV3; + + _approveLink(address(rewardManager), 2 * DEFAULT_REPORT_LINK_FEE, USER); + + _verifyBulk(signedReports, address(link), 0, USER); + + assertEq(link.balanceOf(USER), DEFAULT_LINK_MINT_QUANTITY - 2 * DEFAULT_REPORT_LINK_FEE); + assertEq(native.balanceOf(USER), DEFAULT_NATIVE_MINT_QUANTITY); + assertEq(link.balanceOf(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * 2); + } + + function test_verifyMultiVersionsReturnsVerifiedReports() public { + bytes memory signedReportV1 = _generateV1EncodedBlob( + _generateV1Report(), + _generateReportContext(v1ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + bytes memory signedReportV3 = _generateV3EncodedBlob( + _generateV3Report(), + _generateReportContext(v3ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + bytes[] memory signedReports = new bytes[](3); + + signedReports[0] = signedReportV1; + signedReports[1] = signedReportV3; + signedReports[2] = signedReportV3; + + _approveLink(address(rewardManager), 2 * DEFAULT_REPORT_LINK_FEE, USER); + + address originalAddr = msg.sender; + changePrank(USER); + + bytes[] memory verifierReports = s_verifierProxy.verifyBulk{value: 0}(signedReports, abi.encode(link)); + + changePrank(originalAddr); + + assertEq(verifierReports[0], _encodeReport(_generateV1Report())); + assertEq(verifierReports[1], _encodeReport(_generateV3Report())); + assertEq(verifierReports[2], _encodeReport(_generateV3Report())); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierUnsetConfigTest.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierUnsetConfigTest.t.sol new file mode 100644 index 00000000000..942ef3db3f8 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierUnsetConfigTest.t.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTestWithMultipleConfiguredDigests} from "./BaseVerifierTest.t.sol"; +import {Verifier} from "../../Verifier.sol"; + +contract VerificationdeactivateConfigWhenThereAreMultipleDigestsTestV05 is BaseTestWithMultipleConfiguredDigests { + function test_revertsIfCalledByNonOwner() public { + vm.expectRevert("Only callable by owner"); + + changePrank(USER); + s_verifier.deactivateConfig(bytes32("")); + } + + function test_revertsIfRemovingAnEmptyDigest() public { + vm.expectRevert(abi.encodeWithSelector(Verifier.DigestEmpty.selector)); + s_verifier.deactivateConfig(bytes32("")); + } + + function test_revertsIfRemovingAnNonExistentDigest() public { + vm.expectRevert(abi.encodeWithSelector(Verifier.DigestNotSet.selector, bytes32("mock-digest"))); + s_verifier.deactivateConfig(bytes32("mock-digest")); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierVerifyTest.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierVerifyTest.t.sol new file mode 100644 index 00000000000..02ddb8c5aee --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/test/verifier/VerifierVerifyTest.t.sol @@ -0,0 +1,364 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTestWithConfiguredVerifierAndFeeManager} from "./BaseVerifierTest.t.sol"; +import {Verifier} from "../../Verifier.sol"; +import {VerifierProxy} from "../../VerifierProxy.sol"; +import {AccessControllerInterface} from "../../../../shared/interfaces/AccessControllerInterface.sol"; +import {Common} from "../../../libraries/Common.sol"; + +contract VerifierVerifyTest is BaseTestWithConfiguredVerifierAndFeeManager { + bytes32[3] internal s_reportContext; + + event ReportVerified(bytes32 indexed feedId, address requester); + + V1Report internal s_testReportOne; + + function setUp() public virtual override { + BaseTestWithConfiguredVerifierAndFeeManager.setUp(); + s_reportContext[0] = v1ConfigDigest; + s_reportContext[1] = bytes32(abi.encode(uint32(5), uint8(1))); + s_testReportOne = _createV1Report( + FEED_ID, + OBSERVATIONS_TIMESTAMP, + MEDIAN, + BID, + ASK, + BLOCKNUMBER_UPPER_BOUND, + blockhash(BLOCKNUMBER_UPPER_BOUND), + BLOCKNUMBER_LOWER_BOUND, + uint32(block.timestamp) + ); + } + + function assertReportsEqual(bytes memory response, V1Report memory testReport) public pure { + ( + bytes32 feedId, + uint32 timestamp, + int192 median, + int192 bid, + int192 ask, + uint64 blockNumUB, + bytes32 upperBlockhash, + uint64 blockNumLB + ) = abi.decode(response, (bytes32, uint32, int192, int192, int192, uint64, bytes32, uint64)); + assertEq(feedId, testReport.feedId); + assertEq(timestamp, testReport.observationsTimestamp); + assertEq(median, testReport.median); + assertEq(bid, testReport.bid); + assertEq(ask, testReport.ask); + assertEq(blockNumLB, testReport.blocknumberLowerBound); + assertEq(blockNumUB, testReport.blocknumberUpperBound); + assertEq(upperBlockhash, testReport.upperBlockhash); + } +} + +contract VerifierProxyVerifyTestV05 is VerifierVerifyTest { + function test_revertsIfNoVerifierConfigured() public { + s_reportContext[0] = bytes32("corrupt-digest"); + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + vm.expectRevert(abi.encodeWithSelector(VerifierProxy.VerifierNotFound.selector, bytes32("corrupt-digest"))); + s_verifierProxy.verify(signedReport, bytes("")); + } + + function test_proxiesToTheCorrectVerifier() public { + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + + bytes memory response = s_verifierProxy.verify(signedReport, abi.encode(native)); + assertReportsEqual(response, s_testReportOne); + } +} + +contract VerifierProxyAccessControlledVerificationTestV05 is VerifierVerifyTest { + function setUp() public override { + VerifierVerifyTest.setUp(); + AccessControllerInterface accessController = AccessControllerInterface(ACCESS_CONTROLLER_ADDRESS); + + s_verifierProxy.setAccessController(accessController); + } + + function test_revertsIfNoAccess() public { + vm.mockCall( + ACCESS_CONTROLLER_ADDRESS, + abi.encodeWithSelector(AccessControllerInterface.hasAccess.selector, USER), + abi.encode(false) + ); + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + vm.expectRevert(abi.encodeWithSelector(VerifierProxy.AccessForbidden.selector)); + + changePrank(USER); + s_verifierProxy.verify(signedReport, abi.encode(native)); + } + + function test_proxiesToTheVerifierIfHasAccess() public { + vm.mockCall( + ACCESS_CONTROLLER_ADDRESS, + abi.encodeWithSelector(AccessControllerInterface.hasAccess.selector, USER), + abi.encode(true) + ); + + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + + changePrank(USER); + bytes memory response = s_verifierProxy.verify(signedReport, bytes("")); + assertReportsEqual(response, s_testReportOne); + } +} + +contract VerifierVerifySingleConfigDigestTestV05 is VerifierVerifyTest { + function test_revertsIfVerifiedByNonProxy() public { + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + vm.expectRevert(abi.encodeWithSelector(Verifier.AccessForbidden.selector)); + s_verifier.verify(signedReport, msg.sender); + } + + function test_revertsIfVerifiedWithIncorrectAddresses() public { + Signer[] memory signers = _getSigners(FAULT_TOLERANCE + 1); + signers[10].mockPrivateKey = 1234; + bytes memory signedReport = _generateV1EncodedBlob(s_testReportOne, s_reportContext, signers); + changePrank(address(s_verifierProxy)); + vm.expectRevert(abi.encodeWithSelector(Verifier.BadVerification.selector)); + s_verifier.verify(signedReport, msg.sender); + } + + function test_revertsIfMismatchedSignatureLength() public { + bytes32[] memory rs = new bytes32[](FAULT_TOLERANCE + 1); + bytes32[] memory ss = new bytes32[](FAULT_TOLERANCE + 3); + bytes32 rawVs = bytes32(""); + bytes memory signedReport = abi.encode(s_reportContext, abi.encode(s_testReportOne), rs, ss, rawVs); + changePrank(address(s_verifierProxy)); + vm.expectRevert(abi.encodeWithSelector(Verifier.MismatchedSignatures.selector, rs.length, ss.length)); + s_verifier.verify(signedReport, msg.sender); + } + + function test_revertsIfConfigDigestNotSet() public { + bytes32[3] memory reportContext = s_reportContext; + reportContext[0] = bytes32("wrong-context-digest"); + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + vm.expectRevert(abi.encodeWithSelector(Verifier.DigestInactive.selector, reportContext[0])); + changePrank(address(s_verifierProxy)); + s_verifier.verify(signedReport, msg.sender); + } + + function test_revertsIfReportHasUnconfiguredConfigDigest() public { + V1Report memory report = _createV1Report( + FEED_ID_2, + OBSERVATIONS_TIMESTAMP, + MEDIAN, + BID, + ASK, + BLOCKNUMBER_UPPER_BOUND, + blockhash(BLOCKNUMBER_UPPER_BOUND), + BLOCKNUMBER_LOWER_BOUND, + uint32(block.timestamp) + ); + s_reportContext[0] = keccak256("unconfigured-digesty"); + bytes memory signedReport = _generateV1EncodedBlob(report, s_reportContext, _getSigners(FAULT_TOLERANCE + 1)); + vm.expectRevert(abi.encodeWithSelector(Verifier.DigestInactive.selector, s_reportContext[0])); + changePrank(address(s_verifierProxy)); + s_verifier.verify(signedReport, msg.sender); + } + + function test_revertsIfWrongNumberOfSigners() public { + bytes memory signedReport = _generateV1EncodedBlob(s_testReportOne, s_reportContext, _getSigners(10)); + vm.expectRevert(abi.encodeWithSelector(Verifier.IncorrectSignatureCount.selector, 10, FAULT_TOLERANCE + 1)); + changePrank(address(s_verifierProxy)); + s_verifier.verify(signedReport, msg.sender); + } + + function test_revertsIfDuplicateSignersHaveSigned() public { + Signer[] memory signers = _getSigners(FAULT_TOLERANCE + 1); + // Duplicate signer at index 1 + signers[0] = signers[1]; + bytes memory signedReport = _generateV1EncodedBlob(s_testReportOne, s_reportContext, signers); + vm.expectRevert(abi.encodeWithSelector(Verifier.BadVerification.selector)); + changePrank(address(s_verifierProxy)); + s_verifier.verify(signedReport, msg.sender); + } + + function test_returnsThePriceAndBlockNumIfReportVerified() public { + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + changePrank(address(s_verifierProxy)); + bytes memory response = s_verifier.verify(signedReport, msg.sender); + + assertReportsEqual(response, s_testReportOne); + } + + function test_emitsAnEventIfReportVerified() public { + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + vm.expectEmit(true, true, true, true, address(s_verifier)); + emit ReportVerified(s_testReportOne.feedId, msg.sender); + changePrank(address(s_verifierProxy)); + s_verifier.verify(signedReport, msg.sender); + } +} + +contract VerifierVerifyMultipleConfigDigestTestV05 is VerifierVerifyTest { + bytes32 internal s_oldConfigDigest; + bytes32 internal s_newConfigDigest; + + uint8 internal constant FAULT_TOLERANCE_TWO = 5; + + function setUp() public override { + VerifierVerifyTest.setUp(); + s_oldConfigDigest = v1ConfigDigest; + + s_newConfigDigest = _configDigestFromConfigData( + FEED_ID, + SOURCE_CHAIN_ID, + SOURCE_ADDRESS, + 2, + _getSignerAddresses(_getSigners(20)), + s_offchaintransmitters, + FAULT_TOLERANCE_TWO, + bytes(""), + VERIFIER_VERSION, + bytes("") + ); + + s_verifier.setConfig( + s_newConfigDigest, + _getSignerAddresses(_getSigners(20)), + FAULT_TOLERANCE_TWO, + new Common.AddressAndWeight[](0) + ); + } + + function test_revertsIfVerifyingWithAnUnsetDigest() public { + s_verifier.deactivateConfig(s_oldConfigDigest); + + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + changePrank(address(s_verifierProxy)); + vm.expectRevert(abi.encodeWithSelector(Verifier.DigestInactive.selector, s_reportContext[0])); + s_verifier.verify(signedReport, msg.sender); + } + + function test_canVerifyOlderReportsWithOlderConfigs() public { + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + changePrank(address(s_verifierProxy)); + bytes memory response = s_verifier.verify(signedReport, msg.sender); + assertReportsEqual(response, s_testReportOne); + } + + function test_canVerifyNewerReportsWithNewerConfigs() public { + s_reportContext[0] = s_newConfigDigest; + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(FAULT_TOLERANCE_TWO + 1) + ); + changePrank(address(s_verifierProxy)); + bytes memory response = s_verifier.verify(signedReport, msg.sender); + assertReportsEqual(response, s_testReportOne); + } + + function test_revertsIfAReportIsVerifiedWithAnExistingButIncorrectDigest() public { + // Try sending the older digest signed with the new set of signers + s_reportContext[0] = s_oldConfigDigest; + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(FAULT_TOLERANCE_TWO + 1) + ); + vm.expectRevert( + abi.encodeWithSelector(Verifier.IncorrectSignatureCount.selector, FAULT_TOLERANCE_TWO + 1, FAULT_TOLERANCE + 1) + ); + changePrank(address(s_verifierProxy)); + s_verifier.verify(signedReport, msg.sender); + } + + function test_verifyAfterConfigUpdate() public { + // Get initial signers and set initial config + address[] memory initialSigners = _getSignerAddresses(_getSigners(15)); + bytes32 configDigest = keccak256("test"); + + s_verifier.setConfig(configDigest, initialSigners, 4, new Common.AddressAndWeight[](0)); + + // Get new signers and update config + address[] memory newSigners = _getSignerAddresses(_getSigners(20)); + s_verifier.updateConfig(configDigest, initialSigners, newSigners, 6); + + // Verify report with new signers should pass + s_reportContext[0] = configDigest; + bytes memory signedReportNewSigners = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(7) // More than f=6 signers + ); + + bytes memory response = s_verifierProxy.verify(signedReportNewSigners, bytes("")); + assertReportsEqual(response, s_testReportOne); + + // Verify report with old signers should fail + bytes memory signedReportOldSigners = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(5) // Old number of signers + ); + vm.expectRevert(abi.encodeWithSelector(Verifier.IncorrectSignatureCount.selector, 5, 7)); + + s_verifierProxy.verify(signedReportOldSigners, bytes("")); + } + + function test_verifyAfterConfigUpdateWithExistingSigners() public { + // Get initial signers and set initial config + address[] memory signers = _getSignerAddresses(_getSigners(15)); + bytes32 configDigest = keccak256("test"); + + s_verifier.setConfig(configDigest, signers, 4, new Common.AddressAndWeight[](0)); + + // Update config with same signers and f + s_verifier.updateConfig(configDigest, signers, signers, 4); + + // Verify report should pass + s_reportContext[0] = configDigest; + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(5) // More than f=4 signers + ); + + bytes memory response = s_verifierProxy.verify(signedReport, bytes("")); + assertReportsEqual(response, s_testReportOne); + } +} diff --git a/contracts/src/v0.8/mocks/MockAggregatorValidator.sol b/contracts/src/v0.8/mocks/MockAggregatorValidator.sol deleted file mode 100644 index bdc935cd231..00000000000 --- a/contracts/src/v0.8/mocks/MockAggregatorValidator.sol +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import "../shared/interfaces/AggregatorValidatorInterface.sol"; - -contract MockAggregatorValidator is AggregatorValidatorInterface { - uint8 immutable id; - - constructor(uint8 id_) { - id = id_; - } - - event ValidateCalled( - uint8 id, - uint256 previousRoundId, - int256 previousAnswer, - uint256 currentRoundId, - int256 currentAnswer - ); - - function validate( - uint256 previousRoundId, - int256 previousAnswer, - uint256 currentRoundId, - int256 currentAnswer - ) external override returns (bool) { - emit ValidateCalled(id, previousRoundId, previousAnswer, currentRoundId, currentAnswer); - return true; - } -} diff --git a/contracts/src/v0.8/mocks/MockOffchainAggregator.sol b/contracts/src/v0.8/mocks/MockOffchainAggregator.sol deleted file mode 100644 index 5366bbee0b0..00000000000 --- a/contracts/src/v0.8/mocks/MockOffchainAggregator.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.6; - -contract MockOffchainAggregator { - event RoundIdUpdated(uint80 roundId); - - uint80 public roundId; - - function requestNewRound() external returns (uint80) { - roundId++; - emit RoundIdUpdated(roundId); - return roundId; - } -} diff --git a/contracts/src/v0.8/Chainlink.sol b/contracts/src/v0.8/operatorforwarder/Chainlink.sol similarity index 96% rename from contracts/src/v0.8/Chainlink.sol rename to contracts/src/v0.8/operatorforwarder/Chainlink.sol index e511cfc8085..f3ee84cb11e 100644 --- a/contracts/src/v0.8/Chainlink.sol +++ b/contracts/src/v0.8/operatorforwarder/Chainlink.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {CBORChainlink} from "./vendor/CBORChainlink.sol"; -import {BufferChainlink} from "./vendor/BufferChainlink.sol"; +import {CBORChainlink} from "../vendor/CBORChainlink.sol"; +import {BufferChainlink} from "../vendor/BufferChainlink.sol"; /** * @title Library for common Chainlink functions diff --git a/contracts/src/v0.8/ChainlinkClient.sol b/contracts/src/v0.8/operatorforwarder/ChainlinkClient.sol similarity index 98% rename from contracts/src/v0.8/ChainlinkClient.sol rename to contracts/src/v0.8/operatorforwarder/ChainlinkClient.sol index 1d8640a27b2..c619683cbb1 100644 --- a/contracts/src/v0.8/ChainlinkClient.sol +++ b/contracts/src/v0.8/operatorforwarder/ChainlinkClient.sol @@ -3,11 +3,11 @@ pragma solidity ^0.8.0; import {Chainlink} from "./Chainlink.sol"; import {ENSInterface} from "./interfaces/ENSInterface.sol"; -import {LinkTokenInterface} from "./shared/interfaces/LinkTokenInterface.sol"; +import {LinkTokenInterface} from "../shared/interfaces/LinkTokenInterface.sol"; import {ChainlinkRequestInterface} from "./interfaces/ChainlinkRequestInterface.sol"; import {OperatorInterface} from "./interfaces/OperatorInterface.sol"; import {PointerInterface} from "./interfaces/PointerInterface.sol"; -import {ENSResolver as ENSResolver_Chainlink} from "./vendor/ENSResolver.sol"; +import {ENSResolver as ENSResolver_Chainlink} from "../vendor/ENSResolver.sol"; /** * @title The ChainlinkClient contract diff --git a/contracts/src/v0.8/operatorforwarder/Operator.sol b/contracts/src/v0.8/operatorforwarder/Operator.sol index 64882e43cda..ff22558a098 100644 --- a/contracts/src/v0.8/operatorforwarder/Operator.sol +++ b/contracts/src/v0.8/operatorforwarder/Operator.sol @@ -6,10 +6,10 @@ import {LinkTokenReceiver} from "./LinkTokenReceiver.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 {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 {OracleInterface} from "./interfaces/OracleInterface.sol"; import {SafeCast} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; // @title The Chainlink Operator contract diff --git a/contracts/src/v0.8/interfaces/ChainlinkRequestInterface.sol b/contracts/src/v0.8/operatorforwarder/interfaces/ChainlinkRequestInterface.sol similarity index 100% rename from contracts/src/v0.8/interfaces/ChainlinkRequestInterface.sol rename to contracts/src/v0.8/operatorforwarder/interfaces/ChainlinkRequestInterface.sol diff --git a/contracts/src/v0.8/interfaces/ENSInterface.sol b/contracts/src/v0.8/operatorforwarder/interfaces/ENSInterface.sol similarity index 100% rename from contracts/src/v0.8/interfaces/ENSInterface.sol rename to contracts/src/v0.8/operatorforwarder/interfaces/ENSInterface.sol diff --git a/contracts/src/v0.8/interfaces/OperatorInterface.sol b/contracts/src/v0.8/operatorforwarder/interfaces/OperatorInterface.sol similarity index 100% rename from contracts/src/v0.8/interfaces/OperatorInterface.sol rename to contracts/src/v0.8/operatorforwarder/interfaces/OperatorInterface.sol diff --git a/contracts/src/v0.8/interfaces/OracleInterface.sol b/contracts/src/v0.8/operatorforwarder/interfaces/OracleInterface.sol similarity index 100% rename from contracts/src/v0.8/interfaces/OracleInterface.sol rename to contracts/src/v0.8/operatorforwarder/interfaces/OracleInterface.sol diff --git a/contracts/src/v0.8/interfaces/PointerInterface.sol b/contracts/src/v0.8/operatorforwarder/interfaces/PointerInterface.sol similarity index 100% rename from contracts/src/v0.8/interfaces/PointerInterface.sol rename to contracts/src/v0.8/operatorforwarder/interfaces/PointerInterface.sol diff --git a/contracts/src/v0.8/tests/Broken.sol b/contracts/src/v0.8/operatorforwarder/test/Broken.sol similarity index 95% rename from contracts/src/v0.8/tests/Broken.sol rename to contracts/src/v0.8/operatorforwarder/test/Broken.sol index 21fa9b014e9..6edfbd88d51 100644 --- a/contracts/src/v0.8/tests/Broken.sol +++ b/contracts/src/v0.8/operatorforwarder/test/Broken.sol @@ -1,6 +1,7 @@ pragma solidity ^0.8.0; // Broken is a contract to aid debugging and testing reverting calls during development. +// solhint-disable contract Broken { error Unauthorized(string reason, int256 reason2); diff --git a/contracts/src/v0.8/operatorforwarder/test/testhelpers/ChainlinkClientHelper.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/ChainlinkClientHelper.sol index 9b6ba6bb432..1efd93114d9 100644 --- a/contracts/src/v0.8/operatorforwarder/test/testhelpers/ChainlinkClientHelper.sol +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/ChainlinkClientHelper.sol @@ -1,7 +1,7 @@ // 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 FULFILL_SELECTOR = this.fulfill.selector; diff --git a/contracts/src/v0.8/operatorforwarder/test/testhelpers/Chainlinked.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/Chainlinked.sol index dba5d407623..67fda6452cd 100644 --- a/contracts/src/v0.8/operatorforwarder/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/test/testhelpers/Consumer.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/Consumer.sol index 3ec32dd6a29..b422081084e 100644 --- a/contracts/src/v0.8/operatorforwarder/test/testhelpers/Consumer.sol +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/Consumer.sol @@ -1,8 +1,8 @@ // 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; diff --git a/contracts/src/v0.8/operatorforwarder/test/testhelpers/EmptyOracle.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/EmptyOracle.sol index f278791d2bb..6a4c281995a 100644 --- a/contracts/src/v0.8/operatorforwarder/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/test/testhelpers/GasGuzzlingConsumer.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/GasGuzzlingConsumer.sol index 029102018b0..040eeec394e 100644 --- a/contracts/src/v0.8/operatorforwarder/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/test/testhelpers/MaliciousMultiWordConsumer.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousMultiWordConsumer.sol index 93af16f64fd..ad65927b40b 100644 --- a/contracts/src/v0.8/operatorforwarder/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/test/testhelpers/MaliciousRequester.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousRequester.sol index c01c8a60bb7..8864d8fdffb 100644 --- a/contracts/src/v0.8/operatorforwarder/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/MultiWordConsumer.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MultiWordConsumer.sol index b3fdfcb813a..50420807cf9 100644 --- a/contracts/src/v0.8/operatorforwarder/test/testhelpers/MultiWordConsumer.sol +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MultiWordConsumer.sol @@ -1,7 +1,7 @@ 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; diff --git a/contracts/src/v0.8/tests/MockV3Aggregator.sol b/contracts/src/v0.8/shared/mocks/MockV3Aggregator.sol similarity index 95% rename from contracts/src/v0.8/tests/MockV3Aggregator.sol rename to contracts/src/v0.8/shared/mocks/MockV3Aggregator.sol index 9822d23e853..a405b7f6bef 100644 --- a/contracts/src/v0.8/tests/MockV3Aggregator.sol +++ b/contracts/src/v0.8/shared/mocks/MockV3Aggregator.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import "../shared/interfaces/AggregatorV2V3Interface.sol"; +import {AggregatorV2V3Interface} from "../interfaces/AggregatorV2V3Interface.sol"; /** * @title MockV3Aggregator @@ -11,6 +11,7 @@ import "../shared/interfaces/AggregatorV2V3Interface.sol"; * aggregator contract, but how the aggregator got * its answer is unimportant */ +// solhint-disable contract MockV3Aggregator is AggregatorV2V3Interface { uint256 public constant override version = 0; diff --git a/contracts/src/v0.8/tests/LogEmitter.sol b/contracts/src/v0.8/shared/test/helpers/LogEmitter.sol similarity index 97% rename from contracts/src/v0.8/tests/LogEmitter.sol rename to contracts/src/v0.8/shared/test/helpers/LogEmitter.sol index 37306cc2bc5..4bf9e9e5674 100644 --- a/contracts/src/v0.8/tests/LogEmitter.sol +++ b/contracts/src/v0.8/shared/test/helpers/LogEmitter.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +// solhint-disable contract LogEmitter { event Log1(uint256); event Log2(uint256 indexed); diff --git a/contracts/src/v0.8/tests/VRFLogEmitter.sol b/contracts/src/v0.8/shared/test/helpers/VRFLogEmitter.sol similarity index 100% rename from contracts/src/v0.8/tests/VRFLogEmitter.sol rename to contracts/src/v0.8/shared/test/helpers/VRFLogEmitter.sol diff --git a/contracts/src/v0.8/ChainSpecificUtil.sol b/contracts/src/v0.8/shared/util/ChainSpecificUtil.sol similarity index 95% rename from contracts/src/v0.8/ChainSpecificUtil.sol rename to contracts/src/v0.8/shared/util/ChainSpecificUtil.sol index c5052cd9b25..d541f5f8486 100644 --- a/contracts/src/v0.8/ChainSpecificUtil.sol +++ b/contracts/src/v0.8/shared/util/ChainSpecificUtil.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.9; -import {ArbSys} from "./vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; -import {ArbGasInfo} from "./vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; -import {OVM_GasPriceOracle} from "./vendor/@eth-optimism/contracts/v0.8.9/contracts/L2/predeploys/OVM_GasPriceOracle.sol"; +import {ArbSys} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; +import {ArbGasInfo} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; +import {OVM_GasPriceOracle} from "../../vendor/@eth-optimism/contracts/v0.8.9/contracts/L2/predeploys/OVM_GasPriceOracle.sol"; /// @dev A library that abstracts out opcodes that behave differently across chains. /// @dev The methods below return values that are pertinent to the given chain. diff --git a/contracts/src/v0.8/tests/ChainlinkClientTestHelper.sol b/contracts/src/v0.8/tests/ChainlinkClientTestHelper.sol deleted file mode 100644 index a344138a17d..00000000000 --- a/contracts/src/v0.8/tests/ChainlinkClientTestHelper.sol +++ /dev/null @@ -1,83 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import "../ChainlinkClient.sol"; - -contract ChainlinkClientTestHelper is ChainlinkClient { - constructor(address _link, address _oracle) { - _setChainlinkToken(_link); - _setChainlinkOracle(_oracle); - } - - event Request(bytes32 id, address callbackAddress, bytes4 callbackfunctionSelector, bytes data); - event LinkAmount(uint256 amount); - - function publicNewRequest(bytes32 _id, address _address, bytes memory _fulfillmentSignature) public { - Chainlink.Request memory req = _buildChainlinkRequest(_id, _address, bytes4(keccak256(_fulfillmentSignature))); - emit Request(req.id, req.callbackAddress, req.callbackFunctionId, req.buf.buf); - } - - function publicRequest(bytes32 _id, address _address, bytes memory _fulfillmentSignature, uint256 _wei) public { - Chainlink.Request memory req = _buildChainlinkRequest(_id, _address, bytes4(keccak256(_fulfillmentSignature))); - _sendChainlinkRequest(req, _wei); - } - - function publicRequestRunTo( - address _oracle, - bytes32 _id, - address _address, - bytes memory _fulfillmentSignature, - uint256 _wei - ) public { - Chainlink.Request memory run = _buildChainlinkRequest(_id, _address, bytes4(keccak256(_fulfillmentSignature))); - _sendChainlinkRequestTo(_oracle, run, _wei); - } - - function publicRequestOracleData(bytes32 _id, bytes memory _fulfillmentSignature, uint256 _wei) public { - Chainlink.Request memory req = _buildOperatorRequest(_id, bytes4(keccak256(_fulfillmentSignature))); - _sendOperatorRequest(req, _wei); - } - - function publicRequestOracleDataFrom( - address _oracle, - bytes32 _id, - bytes memory _fulfillmentSignature, - uint256 _wei - ) public { - Chainlink.Request memory run = _buildOperatorRequest(_id, bytes4(keccak256(_fulfillmentSignature))); - _sendOperatorRequestTo(_oracle, run, _wei); - } - - function publicCancelRequest( - bytes32 _requestId, - uint256 _payment, - bytes4 _callbackFunctionId, - uint256 _expiration - ) public { - _cancelChainlinkRequest(_requestId, _payment, _callbackFunctionId, _expiration); - } - - function publicChainlinkToken() public view returns (address) { - return _chainlinkTokenAddress(); - } - - function publicFulfillChainlinkRequest(bytes32 _requestId, bytes32) public { - fulfillRequest(_requestId, bytes32(0)); - } - - function fulfillRequest(bytes32 _requestId, bytes32) public { - _validateChainlinkCallback(_requestId); - } - - function publicLINK(uint256 _amount) public { - emit LinkAmount(LINK_DIVISIBILITY * _amount); - } - - function publicOracleAddress() public view returns (address) { - return _chainlinkOracleAddress(); - } - - function publicAddExternalRequest(address _oracle, bytes32 _requestId) public { - _addChainlinkExternalRequest(_oracle, _requestId); - } -} diff --git a/contracts/src/v0.8/tests/ChainlinkTestHelper.sol b/contracts/src/v0.8/tests/ChainlinkTestHelper.sol deleted file mode 100644 index d42f30c374d..00000000000 --- a/contracts/src/v0.8/tests/ChainlinkTestHelper.sol +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import "../Chainlink.sol"; -import "../vendor/CBORChainlink.sol"; -import "../vendor/BufferChainlink.sol"; - -contract ChainlinkTestHelper { - using Chainlink for Chainlink.Request; - using CBORChainlink for BufferChainlink.buffer; - - Chainlink.Request private req; - - event RequestData(bytes payload); - - function closeEvent() public { - emit RequestData(req.buf.buf); - } - - function setBuffer(bytes memory data) public { - Chainlink.Request memory r2 = req; - r2._setBuffer(data); - req = r2; - } - - function add(string memory _key, string memory _value) public { - Chainlink.Request memory r2 = req; - r2._add(_key, _value); - req = r2; - } - - function addBytes(string memory _key, bytes memory _value) public { - Chainlink.Request memory r2 = req; - r2._addBytes(_key, _value); - req = r2; - } - - function addInt(string memory _key, int256 _value) public { - Chainlink.Request memory r2 = req; - r2._addInt(_key, _value); - req = r2; - } - - function addUint(string memory _key, uint256 _value) public { - Chainlink.Request memory r2 = req; - r2._addUint(_key, _value); - req = r2; - } - - // Temporarily have method receive bytes32[] memory until experimental - // string[] memory can be invoked from truffle tests. - function addStringArray(string memory _key, string[] memory _values) public { - Chainlink.Request memory r2 = req; - r2._addStringArray(_key, _values); - req = r2; - } -} diff --git a/contracts/src/v0.8/tests/Counter.sol b/contracts/src/v0.8/tests/Counter.sol deleted file mode 100644 index 1ceb7891490..00000000000 --- a/contracts/src/v0.8/tests/Counter.sol +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.0; - -contract Counter { - error AlwaysRevert(); - - uint256 public count = 0; - - function increment() public returns (uint256) { - count += 1; - return count; - } - - function reset() public { - count = 0; - } - - function alwaysRevert() public pure { - revert AlwaysRevert(); - } - - function alwaysRevertWithString() public pure { - revert("always revert"); - } -} diff --git a/contracts/src/v0.8/tests/FlagsTestHelper.sol b/contracts/src/v0.8/tests/FlagsTestHelper.sol deleted file mode 100644 index 3e35cae8911..00000000000 --- a/contracts/src/v0.8/tests/FlagsTestHelper.sol +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import "../Flags.sol"; - -contract FlagsTestHelper { - Flags public flags; - - constructor(address flagsContract) { - flags = Flags(flagsContract); - } - - function getFlag(address subject) external view returns (bool) { - return flags.getFlag(subject); - } - - function getFlags(address[] calldata subjects) external view returns (bool[] memory) { - return flags.getFlags(subjects); - } -} diff --git a/contracts/src/v0.8/tests/MockETHLINKAggregator.sol b/contracts/src/v0.8/tests/MockETHLINKAggregator.sol deleted file mode 100644 index d685aac7314..00000000000 --- a/contracts/src/v0.8/tests/MockETHLINKAggregator.sol +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import "../shared/interfaces/AggregatorV3Interface.sol"; - -contract MockETHLINKAggregator is AggregatorV3Interface { - int256 public answer; - - constructor(int256 _answer) public { - answer = _answer; - } - - function decimals() external view override returns (uint8) { - return 18; - } - - function description() external view override returns (string memory) { - return "MockETHLINKAggregator"; - } - - function version() external view override returns (uint256) { - return 1; - } - - function getRoundData( - uint80 _roundId - ) - external - view - override - returns (uint80 roundId, int256 ans, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) - { - return (1, answer, block.timestamp, block.timestamp, 1); - } - - function latestRoundData() - external - view - override - returns (uint80 roundId, int256 ans, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) - { - return (1, answer, block.timestamp, block.timestamp, 1); - } -} diff --git a/contracts/src/v0.8/transmission/dev/ERC-4337/Paymaster.sol b/contracts/src/v0.8/transmission/dev/ERC-4337/Paymaster.sol deleted file mode 100644 index 932d35006c4..00000000000 --- a/contracts/src/v0.8/transmission/dev/ERC-4337/Paymaster.sol +++ /dev/null @@ -1,134 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {IPaymaster} from "../../../vendor/entrypoint/interfaces/IPaymaster.sol"; -import {SCALibrary} from "./SCALibrary.sol"; -import {LinkTokenInterface} from "../../../shared/interfaces/LinkTokenInterface.sol"; -import {AggregatorV3Interface} from "../../../shared/interfaces/AggregatorV3Interface.sol"; -import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; -import {UserOperation} from "../../../vendor/entrypoint/interfaces/UserOperation.sol"; -import {_packValidationData} from "../../../vendor/entrypoint/core/Helpers.sol"; - -/// @dev LINK token paymaster implementation. -/// TODO: more documentation. -contract Paymaster is IPaymaster, ConfirmedOwner { - error OnlyCallableFromLink(); - error InvalidCalldata(); - error Unauthorized(address sender, address validator); - error UserOperationAlreadyTried(bytes32 userOpHash); - error InsufficientFunds(uint256 juelsNeeded, uint256 subscriptionBalance); - - LinkTokenInterface public immutable i_linkToken; - AggregatorV3Interface public immutable i_linkEthFeed; - address public immutable i_entryPoint; - - struct Config { - uint32 stalenessSeconds; - int256 fallbackWeiPerUnitLink; - } - Config public s_config; - - mapping(bytes32 => bool) internal s_userOpHashMapping; - mapping(address => uint256) internal s_subscriptions; - - constructor( - LinkTokenInterface linkToken, - AggregatorV3Interface linkEthFeed, - address entryPoint - ) ConfirmedOwner(msg.sender) { - i_linkToken = linkToken; - i_linkEthFeed = linkEthFeed; - i_entryPoint = entryPoint; - } - - function setConfig(uint32 stalenessSeconds, int256 fallbackWeiPerUnitLink) external onlyOwner { - s_config = Config({stalenessSeconds: stalenessSeconds, fallbackWeiPerUnitLink: fallbackWeiPerUnitLink}); - } - - function onTokenTransfer(address /* _sender */, uint256 _amount, bytes calldata _data) external { - if (msg.sender != address(i_linkToken)) { - revert OnlyCallableFromLink(); - } - if (_data.length != 32) { - revert InvalidCalldata(); - } - - address subscription = abi.decode(_data, (address)); - s_subscriptions[subscription] += _amount; - } - - function validatePaymasterUserOp( - UserOperation calldata userOp, - bytes32 userOpHash, - uint256 maxCost - ) external returns (bytes memory context, uint256 validationData) { - if (msg.sender != i_entryPoint) { - revert Unauthorized(msg.sender, i_entryPoint); - } - if (s_userOpHashMapping[userOpHash]) { - revert UserOperationAlreadyTried(userOpHash); - } - - uint256 extraCostJuels = _handleExtraCostJuels(userOp); - uint256 costJuels = _getCostJuels(maxCost) + extraCostJuels; - if (s_subscriptions[userOp.sender] < costJuels) { - revert InsufficientFunds(costJuels, s_subscriptions[userOp.sender]); - } - - s_userOpHashMapping[userOpHash] = true; - return (abi.encode(userOp.sender, extraCostJuels), _packValidationData(false, 0, 0)); // success - } - - /// @dev Calculates any extra LINK cost for the user operation, based on the funding type passed to the - /// @dev paymaster. Handles funding the LINK token funding described in the user operation. - /// TODO: add logic for subscription top-up. - function _handleExtraCostJuels(UserOperation calldata userOp) internal returns (uint256 extraCost) { - if (userOp.paymasterAndData.length == 20) { - return 0; // no extra data, stop here - } - - uint8 paymentType = uint8(userOp.paymasterAndData[20]); - - // For direct funding, use top-up logic. - if (paymentType == uint8(SCALibrary.LinkPaymentType.DIRECT_FUNDING)) { - SCALibrary.DirectFundingData memory directFundingData = abi.decode( - userOp.paymasterAndData[21:], - (SCALibrary.DirectFundingData) - ); - if ( - directFundingData.topupThreshold != 0 && - i_linkToken.balanceOf(directFundingData.recipient) < directFundingData.topupThreshold - ) { - i_linkToken.transfer(directFundingData.recipient, directFundingData.topupAmount); - extraCost = directFundingData.topupAmount; - } - } - return extraCost; - } - - /// @dev Deducts user subscription balance after execution. - function postOp(PostOpMode /* mode */, bytes calldata context, uint256 actualGasCost) external { - if (msg.sender != i_entryPoint) { - revert Unauthorized(msg.sender, i_entryPoint); - } - (address sender, uint256 extraCostJuels) = abi.decode(context, (address, uint256)); - s_subscriptions[sender] -= (_getCostJuels(actualGasCost) + extraCostJuels); - } - - function _getCostJuels(uint256 costWei) internal view returns (uint256 costJuels) { - costJuels = (1e18 * costWei) / uint256(_getFeedData()); - return costJuels; - } - - function _getFeedData() internal view returns (int256) { - uint32 stalenessSeconds = s_config.stalenessSeconds; - bool staleFallback = stalenessSeconds > 0; - uint256 timestamp; - int256 weiPerUnitLink; - (, weiPerUnitLink, , timestamp, ) = i_linkEthFeed.latestRoundData(); - if (staleFallback && stalenessSeconds < block.timestamp - timestamp) { - weiPerUnitLink = s_config.fallbackWeiPerUnitLink; - } - return weiPerUnitLink; - } -} diff --git a/contracts/src/v0.8/transmission/dev/ERC-4337/SCA.sol b/contracts/src/v0.8/transmission/dev/ERC-4337/SCA.sol deleted file mode 100644 index 589c55f5b3b..00000000000 --- a/contracts/src/v0.8/transmission/dev/ERC-4337/SCA.sol +++ /dev/null @@ -1,73 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {IAccount} from "../../../vendor/entrypoint/interfaces/IAccount.sol"; -import {SCALibrary} from "./SCALibrary.sol"; -import {UserOperation} from "../../../vendor/entrypoint/interfaces/UserOperation.sol"; -import {_packValidationData} from "../../../vendor/entrypoint/core/Helpers.sol"; - -/// @dev Smart Contract Account, a contract deployed for a single user and that allows -/// @dev them to invoke meta-transactions. -/// TODO: Consider making the Smart Contract Account upgradeable. -contract SCA is IAccount { - uint256 public s_nonce; - address public immutable i_owner; - address public immutable i_entryPoint; - - error IncorrectNonce(uint256 currentNonce, uint256 nonceGiven); - error NotAuthorized(address sender); - error BadFormatOrOOG(); - error TransactionExpired(uint256 deadline, uint256 currentTimestamp); - error InvalidSignature(bytes32 operationHash, address owner); - - // Assign the owner of this contract upon deployment. - constructor(address owner, address entryPoint) { - i_owner = owner; - i_entryPoint = entryPoint; - } - - /// @dev Validates the user operation via a signature check. - /// TODO: Utilize a "validAfter" for a tx to be only valid _after_ a certain time. - function validateUserOp( - UserOperation calldata userOp, - bytes32 userOpHash, - uint256 /* missingAccountFunds - unused in favor of paymaster */ - ) external returns (uint256 validationData) { - if (userOp.nonce != s_nonce) { - // Revert for non-signature errors. - revert IncorrectNonce(s_nonce, userOp.nonce); - } - - // Verify signature on hash. - bytes32 fullHash = SCALibrary._getUserOpFullHash(userOpHash, address(this)); - bytes memory signature = userOp.signature; - if (SCALibrary._recoverSignature(signature, fullHash) != i_owner) { - return _packValidationData(true, 0, 0); // signature error - } - s_nonce++; - - // Unpack deadline, return successful signature. - (, , uint48 deadline, ) = abi.decode(userOp.callData[4:], (address, uint256, uint48, bytes)); - return _packValidationData(false, deadline, 0); - } - - /// @dev Execute a transaction on behalf of the owner. This function can only - /// @dev be called by the EntryPoint contract, and assumes that `validateUserOp` has succeeded. - function executeTransactionFromEntryPoint(address to, uint256 value, uint48 deadline, bytes calldata data) external { - if (msg.sender != i_entryPoint) { - revert NotAuthorized(msg.sender); - } - if (deadline != 0 && block.timestamp > deadline) { - revert TransactionExpired(deadline, block.timestamp); - } - - // Execute transaction. Bubble up an error if found. - (bool success, bytes memory returnData) = to.call{value: value}(data); - if (!success) { - if (returnData.length == 0) revert BadFormatOrOOG(); - assembly { - revert(add(32, returnData), mload(returnData)) - } - } - } -} diff --git a/contracts/src/v0.8/transmission/dev/ERC-4337/SCALibrary.sol b/contracts/src/v0.8/transmission/dev/ERC-4337/SCALibrary.sol deleted file mode 100644 index 095a3428ef4..00000000000 --- a/contracts/src/v0.8/transmission/dev/ERC-4337/SCALibrary.sol +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -library SCALibrary { - // keccak256("EIP712Domain(uint256 chainId, address verifyingContract)"); - bytes32 internal constant DOMAIN_SEPARATOR = hex"1c7d3b72b37a35523e273aaadd7b4cd66f618bb81429ab053412d51f50ccea61"; - - // keccak256("executeTransactionFromEntryPoint(address to, uint256 value, bytes calldata data)"); - bytes32 internal constant TYPEHASH = hex"4750045d47fce615521b32cee713ff8db50147e98aec5ca94926b52651ca3fa0"; - - enum LinkPaymentType { - DIRECT_FUNDING, - SUBSCRIPTION // TODO: implement - } - - struct DirectFundingData { - address recipient; // recipient of the top-up - uint256 topupThreshold; // set to zero to disable auto-topup - uint256 topupAmount; - } - - function _getUserOpFullHash(bytes32 userOpHash, address scaAddress) internal view returns (bytes32 fullHash) { - bytes32 hashOfEncoding = keccak256(abi.encode(SCALibrary.TYPEHASH, userOpHash)); - fullHash = keccak256( - abi.encodePacked( - bytes1(0x19), - bytes1(0x01), - SCALibrary.DOMAIN_SEPARATOR, - block.chainid, - scaAddress, - hashOfEncoding - ) - ); - return fullHash; - } - - function _recoverSignature(bytes memory signature, bytes32 fullHash) internal pure returns (address) { - bytes32 r; - bytes32 s; - assembly { - r := mload(add(signature, 0x20)) - s := mload(add(signature, 0x40)) - } - uint8 v = uint8(signature[64]); - - return ecrecover(fullHash, v + 27, r, s); - } -} diff --git a/contracts/src/v0.8/transmission/dev/ERC-4337/SmartContractAccountFactory.sol b/contracts/src/v0.8/transmission/dev/ERC-4337/SmartContractAccountFactory.sol deleted file mode 100644 index f27c8e15cf6..00000000000 --- a/contracts/src/v0.8/transmission/dev/ERC-4337/SmartContractAccountFactory.sol +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -contract SmartContractAccountFactory { - event ContractCreated(address scaAddress); - - error DeploymentFailed(); - - /// @dev Use create2 to deploy a new Smart Contract Account. - /// @dev See EIP-1014 for more on CREATE2. - /// TODO: Return the address of the Smart Contract Account even if it is already - /// deployed. - function deploySmartContractAccount( - bytes32 abiEncodedOwnerAddress, - bytes memory initCode - ) external payable returns (address scaAddress) { - assembly { - scaAddress := create2( - 0, // value - left at zero here - add(0x20, initCode), // initialization bytecode - mload(initCode), // length of initialization bytecode - abiEncodedOwnerAddress // user-defined nonce to ensure unique SCA addresses - ) - } - if (scaAddress == address(0)) { - revert DeploymentFailed(); - } - - emit ContractCreated(scaAddress); - - return scaAddress; - } -} diff --git a/contracts/src/v0.8/transmission/dev/testhelpers/Greeter.sol b/contracts/src/v0.8/transmission/dev/testhelpers/Greeter.sol deleted file mode 100644 index 5851c86581e..00000000000 --- a/contracts/src/v0.8/transmission/dev/testhelpers/Greeter.sol +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -/// @dev Ownerless greeter contract. -contract Greeter { - string private s_greeting; - - function setGreeting(string memory greeting) external { - s_greeting = greeting; - } - - function getGreeting() external view returns (string memory) { - return s_greeting; - } -} diff --git a/contracts/src/v0.8/transmission/dev/testhelpers/SmartContractAccountHelper.sol b/contracts/src/v0.8/transmission/dev/testhelpers/SmartContractAccountHelper.sol deleted file mode 100644 index b080484d8cc..00000000000 --- a/contracts/src/v0.8/transmission/dev/testhelpers/SmartContractAccountHelper.sol +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {SCA} from "../ERC-4337/SCA.sol"; -import {SmartContractAccountFactory} from "../ERC-4337/SmartContractAccountFactory.sol"; -import {SCALibrary} from "../ERC-4337/SCALibrary.sol"; - -library SmartContractAccountHelper { - bytes internal constant INITIALIZE_CODE = type(SCA).creationCode; - - function getFullEndTxEncoding( - address endContract, - uint256 value, - uint256 deadline, - bytes memory data - ) public view returns (bytes memory encoding) { - encoding = bytes.concat( - SCA.executeTransactionFromEntryPoint.selector, - abi.encode(endContract, value, block.timestamp + deadline, data) - ); - return encoding; - } - - function getFullHashForSigning(bytes32 userOpHash, address scaAddress) public view returns (bytes32) { - return SCALibrary._getUserOpFullHash(userOpHash, scaAddress); - } - - function getSCAInitCodeWithConstructor( - address owner, - address entryPoint - ) public pure returns (bytes memory initCode) { - initCode = bytes.concat(INITIALIZE_CODE, abi.encode(owner, entryPoint)); - return initCode; - } - - function getInitCode( - address factory, - address owner, - address entryPoint - ) external pure returns (bytes memory initCode) { - bytes32 salt = bytes32(uint256(uint160(owner)) << 96); - bytes memory initializeCodeWithConstructor = bytes.concat(INITIALIZE_CODE, abi.encode(owner, entryPoint)); - initCode = bytes.concat( - bytes20(address(factory)), - abi.encodeWithSelector( - SmartContractAccountFactory.deploySmartContractAccount.selector, - salt, - initializeCodeWithConstructor - ) - ); - return initCode; - } - - /// @dev Computes the smart contract address that results from a CREATE2 operation, per EIP-1014. - function calculateSmartContractAccountAddress( - address owner, - address entryPoint, - address factory - ) external pure returns (address) { - bytes32 salt = bytes32(uint256(uint160(owner)) << 96); - bytes memory initializeCodeWithConstructor = bytes.concat(INITIALIZE_CODE, abi.encode(owner, entryPoint)); - bytes32 initializeCodeHash = keccak256(initializeCodeWithConstructor); - return address(uint160(uint256(keccak256(abi.encodePacked(hex"ff", address(factory), salt, initializeCodeHash))))); - } - - function getAbiEncodedDirectRequestData( - address recipient, - uint256 topupThreshold, - uint256 topupAmount - ) external pure returns (bytes memory) { - SCALibrary.DirectFundingData memory data = SCALibrary.DirectFundingData({ - recipient: recipient, - topupThreshold: topupThreshold, - topupAmount: topupAmount - }); - return abi.encode(data); - } -} diff --git a/contracts/src/v0.8/transmission/test/BaseTest.t.sol b/contracts/src/v0.8/transmission/test/BaseTest.t.sol deleted file mode 100644 index 4da698d1740..00000000000 --- a/contracts/src/v0.8/transmission/test/BaseTest.t.sol +++ /dev/null @@ -1,17 +0,0 @@ -pragma solidity ^0.8.0; - -import {Test} from "forge-std/Test.sol"; - -contract BaseTest is Test { - bool private s_baseTestInitialized; - address internal constant OWNER = 0x00007e64E1fB0C487F25dd6D3601ff6aF8d32e4e; - - function setUp() public virtual { - // BaseTest.setUp is often called multiple times from tests' setUp due to inheritance. - if (s_baseTestInitialized) return; - s_baseTestInitialized = true; - - // Set msg.sender to OWNER until changePrank or stopPrank is called - vm.startPrank(OWNER); - } -} diff --git a/contracts/src/v0.8/transmission/test/EIP_712_1014_4337.t.sol b/contracts/src/v0.8/transmission/test/EIP_712_1014_4337.t.sol deleted file mode 100644 index fdfe190de26..00000000000 --- a/contracts/src/v0.8/transmission/test/EIP_712_1014_4337.t.sol +++ /dev/null @@ -1,365 +0,0 @@ -pragma solidity 0.8.19; - -import "../../shared/interfaces/LinkTokenInterface.sol"; - -import "./BaseTest.t.sol"; -import "../dev/ERC-4337/SmartContractAccountFactory.sol"; -import "../dev/testhelpers/SmartContractAccountHelper.sol"; -import "../dev/ERC-4337/SCA.sol"; -import "../dev/testhelpers/Greeter.sol"; -import "../dev/ERC-4337/Paymaster.sol"; -import "../../transmission/dev/ERC-4337/SCALibrary.sol"; -import "../../mocks/MockLinkToken.sol"; -import "../../tests/MockV3Aggregator.sol"; -import "../../vrf/mocks/VRFCoordinatorMock.sol"; -import "../../vrf/testhelpers/VRFConsumer.sol"; - -import "../../vendor/entrypoint/interfaces/UserOperation.sol"; -import "../../vendor/entrypoint/core/EntryPoint.sol"; -import "../../vendor/entrypoint/interfaces/IEntryPoint.sol"; - -/*--------------------------------------------------------------------------------------------------------------------+ -| EIP 712 + 1014 + 4337 | -| ________________ | -| This implementation allows for meta-transactions to be signed by end-users and posted on-chain by executors. It | -| utilizes the following components: | -| - EIP-712: The method by which meta-transactions are authorized. | -| - EIP-1014: The method by which the Smart Contract Account is generated. | -| - EIP-4337: The method by which meta-transactions are executed. | -| | -| The below tests illustrate end-user flows for interacting with this meta-transaction system. For users with | -| existing Smart Contract Accounts (SCAs), they simply sign off on the operation, after which the executor | -| invokes the EntryPoint that authorizes the operation on the end-user's SCA, and then execute the transaction | -| as the SCA. For users without existing SCAs, EIP-1014 ensures that the address of an SCA can be known in advance, | -| so users can sign-off on transactions that will be executed by a not-yet-deployed SCA. The EntryPoint contract | -| takes advantage of this functionality and allows for the SCA to be created in the same user operation that invokes | -| it, and the end-user signs off on this creation-and-execution flow. After the initial creation-and-execution, the | -| SCA is reused for future transactions. | -| | -| End-Dapps/protocols do not need to be EIP-2771-compliant or accommodate any other kind of transaction standard. | -| They can be interacted with out-of-the-box through the SCA, which acts in place of the user's EOA as their | -| immutable identity. | -| | --+---------------------------------------------------------------------------------------------------------------------*/ - -contract EIP_712_1014_4337 is BaseTest { - event RandomnessRequest(address indexed sender, bytes32 indexed keyHash, uint256 indexed seed, uint256 fee); - - address internal constant LINK_WHALE = 0xD883a6A1C22fC4AbFE938a5aDF9B2Cc31b1BF18B; - address internal ENTRY_POINT; - - Greeter greeter; - EntryPoint entryPoint; - MockV3Aggregator linkEthFeed; - - // Randomly generated private/public key pair. - uint256 END_USER_PKEY = uint256(bytes32(hex"99d518dbfea4b4ec301390f7e26d53d711fa1ca0c1a6e4cbed89617d4c578a8e")); - address END_USER = 0xB6708257D4E1bf0b8C144793fc2Ff3193C737ed1; - - function setUp() public override { - BaseTest.setUp(); - // Fund user accounts; - vm.deal(END_USER, 10_000 ether); - vm.deal(LINK_WHALE, 10_000 ether); - - // Impersonate a LINK whale. - changePrank(LINK_WHALE); - - // Create simple greeter contract. - greeter = new Greeter(); - assertEq("", greeter.getGreeting()); - - // Create entry point contract. - entryPoint = new EntryPoint(); - ENTRY_POINT = address(entryPoint); - - // Deploy link/eth feed. - linkEthFeed = new MockV3Aggregator(18, 5000000000000000); // .005 ETH - } - - /// @dev Test case for user that already has a Smart Contract Account. - /// @dev EntryPoint.sol should use the existing SCA to execute the meta transaction. - function testEIP712EIP4337WithExistingSmartContractAccount() public { - // Pre-calculate user smart contract account address. - SmartContractAccountFactory factory = new SmartContractAccountFactory(); - address toDeployAddress = SmartContractAccountHelper.calculateSmartContractAccountAddress( - END_USER, - ENTRY_POINT, - address(factory) - ); - - // Deploy the end-contract. - bytes32 salt = bytes32(uint256(uint160(END_USER)) << 96); - bytes memory fullInitializeCode = SmartContractAccountHelper.getSCAInitCodeWithConstructor(END_USER, ENTRY_POINT); - factory.deploySmartContractAccount(salt, fullInitializeCode); - changePrank(END_USER); - - // Ensure a correct deployment and a functioning end-contract. - uint256 contractCodeSize; - assembly { - contractCodeSize := extcodesize(toDeployAddress) - } - assertTrue(contractCodeSize > 0); - assertEq(END_USER, SCA(toDeployAddress).i_owner()); - - // Create the calldata for a setGreeting call. - string memory greeting = "hi"; - bytes memory encodedGreetingCall = bytes.concat(Greeter.setGreeting.selector, abi.encode(greeting)); // abi.encodeWithSelector equivalent - - // Produce the final full end-tx encoding, to be used as calldata in the user operation. - bytes memory fullEncoding = SmartContractAccountHelper.getFullEndTxEncoding( - address(greeter), - uint256(0), - 0, - encodedGreetingCall - ); - - // Construct the user operation. - UserOperation memory op = UserOperation({ - sender: toDeployAddress, - nonce: 0, - initCode: "", - callData: fullEncoding, - callGasLimit: 1_000_000, - verificationGasLimit: 1_000_000, - preVerificationGas: 10_000, - maxFeePerGas: 100, - maxPriorityFeePerGas: 200, - paymasterAndData: "", - signature: "" - }); - - // Sign user operation. - bytes32 userOpHash = entryPoint.getUserOpHash(op); - bytes32 fullHash = SCALibrary._getUserOpFullHash(userOpHash, toDeployAddress); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(END_USER_PKEY, fullHash); - op.signature = abi.encodePacked(r, s, v - 27); - - // Deposit funds for the transaction. - entryPoint.depositTo{value: 10 ether}(toDeployAddress); - - // Execute the user operation. - UserOperation[] memory operations = new UserOperation[](1); - operations[0] = op; - entryPoint.handleOps(operations, payable(END_USER)); - - // Assert that the greeting was set. - assertEq("hi", Greeter(greeter).getGreeting()); - assertEq(SCA(toDeployAddress).s_nonce(), uint256(1)); - } - - /// @dev Test case for fresh user, EntryPoint.sol should generate a - /// @dev Smart Contract Account for them and execute the meta transaction. - function testEIP712EIP4337AndCreateSmartContractAccount() public { - // Pre-calculate user smart contract account address. - SmartContractAccountFactory factory = new SmartContractAccountFactory(); - address toDeployAddress = SmartContractAccountHelper.calculateSmartContractAccountAddress( - END_USER, - ENTRY_POINT, - address(factory) - ); - - // Construct initCode byte array. - bytes memory fullInitializeCode = SmartContractAccountHelper.getInitCode(address(factory), END_USER, ENTRY_POINT); - - // Create the calldata for a setGreeting call. - string memory greeting = "bye"; - bytes memory encodedGreetingCall = bytes.concat(Greeter.setGreeting.selector, abi.encode(greeting)); - - // Produce the final full end-tx encoding, to be used as calldata in the user operation. - bytes memory fullEncoding = SmartContractAccountHelper.getFullEndTxEncoding( - address(greeter), - uint256(0), - 0, - encodedGreetingCall - ); - - // Construct the user operation. - UserOperation memory op = UserOperation({ - sender: toDeployAddress, - nonce: 0, - initCode: fullInitializeCode, - callData: fullEncoding, - callGasLimit: 1_000_000, - verificationGasLimit: 1_000_000, - preVerificationGas: 10_000, - maxFeePerGas: 100, - maxPriorityFeePerGas: 200, - paymasterAndData: "", - signature: "" - }); - - // Sign user operation. - bytes32 userOpHash = entryPoint.getUserOpHash(op); - bytes32 fullHash = SCALibrary._getUserOpFullHash(userOpHash, toDeployAddress); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(END_USER_PKEY, fullHash); - op.signature = abi.encodePacked(r, s, v - 27); - - // Deposit funds for the transaction. - entryPoint.depositTo{value: 10 ether}(toDeployAddress); - - // Execute the user operation. - UserOperation[] memory operations = new UserOperation[](1); - operations[0] = op; - entryPoint.handleOps(operations, payable(END_USER)); - - // Assert that the greeting was set. - assertEq("bye", Greeter(greeter).getGreeting()); - assertEq(SCA(toDeployAddress).s_nonce(), uint256(1)); - assertEq(SCA(toDeployAddress).i_owner(), END_USER); - } - - /// @dev Test case for a user executing a setGreeting with a LINK token paymaster. - function testEIP712EIP4337AndCreateSmartContractAccountWithPaymaster() public { - // Pre-calculate user smart contract account address. - SmartContractAccountFactory factory = new SmartContractAccountFactory(); - address toDeployAddress = SmartContractAccountHelper.calculateSmartContractAccountAddress( - END_USER, - ENTRY_POINT, - address(factory) - ); - - // Construct initCode byte array. - bytes memory fullInitializeCode = SmartContractAccountHelper.getInitCode(address(factory), END_USER, ENTRY_POINT); - - // Create the calldata for a setGreeting call. - string memory greeting = "good day"; - bytes memory encodedGreetingCall = bytes.concat(Greeter.setGreeting.selector, abi.encode(greeting)); - - // Produce the final full end-tx encoding, to be used as calldata in the user operation. - bytes memory fullEncoding = SmartContractAccountHelper.getFullEndTxEncoding( - address(greeter), - uint256(0), - 0, - encodedGreetingCall - ); - - // Create Link token, and deposit into paymaster. - MockLinkToken linkToken = new MockLinkToken(); - Paymaster paymaster = new Paymaster(LinkTokenInterface(address(linkToken)), linkEthFeed, ENTRY_POINT); - linkToken.transferAndCall(address(paymaster), 1000 ether, abi.encode(address(toDeployAddress))); - - // Construct the user opeartion. - UserOperation memory op = UserOperation({ - sender: toDeployAddress, - nonce: 0, - initCode: fullInitializeCode, - callData: fullEncoding, - callGasLimit: 1_000_000, - verificationGasLimit: 1_500_000, - preVerificationGas: 10_000, - maxFeePerGas: 100, - maxPriorityFeePerGas: 200, - paymasterAndData: abi.encodePacked(address(paymaster)), - signature: "" - }); - - // Sign user operation. - bytes32 userOpHash = entryPoint.getUserOpHash(op); - bytes32 fullHash = SCALibrary._getUserOpFullHash(userOpHash, toDeployAddress); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(END_USER_PKEY, fullHash); - op.signature = abi.encodePacked(r, s, v - 27); - - // Deposit funds for the transaction. - entryPoint.depositTo{value: 10 ether}(address(paymaster)); - - // Execute the user operation. - UserOperation[] memory operations = new UserOperation[](1); - operations[0] = op; - entryPoint.handleOps(operations, payable(END_USER)); - - // Assert that the greeting was set. - assertEq("good day", Greeter(greeter).getGreeting()); - assertEq(SCA(toDeployAddress).s_nonce(), uint256(1)); - } - - /// @dev Test case for a VRF Request via LINK token paymaster and an SCA. - function testEIP712EIP4337AndCreateSmartContractAccountWithPaymasterForVRFRequest() public { - // Pre-calculate user smart contract account address. - SmartContractAccountFactory factory = new SmartContractAccountFactory(); - address toDeployAddress = SmartContractAccountHelper.calculateSmartContractAccountAddress( - END_USER, - ENTRY_POINT, - address(factory) - ); - - // Construct initCode byte array. - bytes memory fullInitializeCode = SmartContractAccountHelper.getInitCode(address(factory), END_USER, ENTRY_POINT); - - // Create the calldata for a VRF request. - bytes32 keyhash = bytes32(uint256(123)); - uint256 fee = 1 ether; - bytes memory encodedVRFRequestCallData = bytes.concat( - VRFConsumer.doRequestRandomness.selector, - abi.encode(keyhash, fee) - ); - - // Create the VRF Contracts - MockLinkToken linkToken = new MockLinkToken(); - VRFCoordinatorMock vrfCoordinator = new VRFCoordinatorMock(address(linkToken)); - VRFConsumer vrfConsumer = new VRFConsumer(address(vrfCoordinator), address(linkToken)); - - // Produce the final full end-tx encoding, to be used as calldata in the user operation. - bytes memory fullEncoding = SmartContractAccountHelper.getFullEndTxEncoding( - address(vrfConsumer), // end-contract - uint256(0), // value - 0, // timeout (seconds) - encodedVRFRequestCallData - ); - - // Create Link token, and deposit into paymaster. - Paymaster paymaster = new Paymaster(LinkTokenInterface(address(linkToken)), linkEthFeed, ENTRY_POINT); - linkToken.transferAndCall(address(paymaster), 1000 ether, abi.encode(address(toDeployAddress))); - - // Construct direct funding data. - SCALibrary.DirectFundingData memory directFundingData = SCALibrary.DirectFundingData({ - recipient: address(vrfConsumer), - topupThreshold: 1, - topupAmount: 10 ether - }); - - // Construct the user operation. - UserOperation memory op = UserOperation({ - sender: toDeployAddress, - nonce: 0, - initCode: fullInitializeCode, - callData: fullEncoding, - callGasLimit: 200_000, - verificationGasLimit: 1_000_000, - preVerificationGas: 10_000, - maxFeePerGas: 10, - maxPriorityFeePerGas: 10, - paymasterAndData: abi.encodePacked(address(paymaster), uint8(0), abi.encode(directFundingData)), - signature: "" - }); - - // Sign user operation. - bytes32 fullHash = SCALibrary._getUserOpFullHash(entryPoint.getUserOpHash(op), toDeployAddress); - op.signature = getSignature(fullHash); - - // Deposit funds for the transaction. - entryPoint.depositTo{value: 10 ether}(address(paymaster)); - - // Assert correct log is emitted for the end-contract vrf request. - vm.expectEmit(true, true, true, true); - emit RandomnessRequest( - address(vrfConsumer), - keyhash, - 0, // seed - we use a zero seed - fee - ); - - // Execute the user operation. - UserOperation[] memory operations = new UserOperation[](1); - operations[0] = op; - - // Execute user operation and ensure correct outcome. - entryPoint.handleOps(operations, payable(END_USER)); - assertEq(SCA(toDeployAddress).s_nonce(), uint256(1)); - } - - function getSignature(bytes32 h) internal view returns (bytes memory) { - (uint8 v, bytes32 r, bytes32 s) = vm.sign(END_USER_PKEY, h); - return abi.encodePacked(r, s, v - 27); - } -} diff --git a/contracts/src/v0.8/vendor/entrypoint/core/EntryPoint.sol b/contracts/src/v0.8/vendor/entrypoint/core/EntryPoint.sol deleted file mode 100644 index 86a34b07bf7..00000000000 --- a/contracts/src/v0.8/vendor/entrypoint/core/EntryPoint.sol +++ /dev/null @@ -1,861 +0,0 @@ -/** - ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation. - ** Only one instance required on each chain. - **/ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity ^0.8.12; - -/* solhint-disable avoid-low-level-calls */ -/* solhint-disable no-inline-assembly */ - -import "../interfaces/IAccount.sol"; -import "../interfaces/IPaymaster.sol"; -import "../interfaces/IEntryPoint.sol"; - -import "../utils/Exec.sol"; -import "./StakeManager.sol"; -import "./SenderCreator.sol"; -import "./Helpers.sol"; - -contract EntryPoint is IEntryPoint, StakeManager { - using UserOperationLib for UserOperation; - - SenderCreator private immutable senderCreator = new SenderCreator(); - - // internal value used during simulation: need to query aggregator. - address private constant SIMULATE_FIND_AGGREGATOR = address(1); - - // marker for inner call revert on out of gas - bytes32 private constant INNER_OUT_OF_GAS = hex"deaddead"; - - uint256 private constant REVERT_REASON_MAX_LEN = 2048; - - /** - * for simulation purposes, validateUserOp (and validatePaymasterUserOp) must return this value - * in case of signature failure, instead of revert. - */ - uint256 public constant SIG_VALIDATION_FAILED = 1; - - /** - * compensate the caller's beneficiary address with the collected fees of all UserOperations. - * @param beneficiary the address to receive the fees - * @param amount amount to transfer. - */ - function _compensate(address payable beneficiary, uint256 amount) internal { - require(beneficiary != address(0), "AA90 invalid beneficiary"); - (bool success, ) = beneficiary.call{value: amount}(""); - require(success, "AA91 failed send to beneficiary"); - } - - /** - * execute a user op - * @param opIndex index into the opInfo array - * @param userOp the userOp to execute - * @param opInfo the opInfo filled by validatePrepayment for this userOp. - * @return collected the total amount this userOp paid. - */ - function _executeUserOp( - uint256 opIndex, - UserOperation calldata userOp, - UserOpInfo memory opInfo - ) private returns (uint256 collected) { - uint256 preGas = gasleft(); - bytes memory context = getMemoryBytesFromOffset(opInfo.contextOffset); - - try this.innerHandleOp(userOp.callData, opInfo, context) returns ( - uint256 _actualGasCost - ) { - collected = _actualGasCost; - } catch { - bytes32 innerRevertCode; - assembly { - returndatacopy(0, 0, 32) - innerRevertCode := mload(0) - } - // handleOps was called with gas limit too low. abort entire bundle. - if (innerRevertCode == INNER_OUT_OF_GAS) { - //report paymaster, since if it is not deliberately caused by the bundler, - // it must be a revert caused by paymaster. - revert FailedOp(opIndex, "AA95 out of gas"); - } - - uint256 actualGas = preGas - gasleft() + opInfo.preOpGas; - collected = _handlePostOp( - opIndex, - IPaymaster.PostOpMode.postOpReverted, - opInfo, - context, - actualGas - ); - } - } - - /** - * Execute a batch of UserOperations. - * no signature aggregator is used. - * if any account requires an aggregator (that is, it returned an aggregator when - * performing simulateValidation), then handleAggregatedOps() must be used instead. - * @param ops the operations to execute - * @param beneficiary the address to receive the fees - */ - function handleOps( - UserOperation[] calldata ops, - address payable beneficiary - ) public { - uint256 opslen = ops.length; - UserOpInfo[] memory opInfos = new UserOpInfo[](opslen); - - unchecked { - for (uint256 i = 0; i < opslen; i++) { - UserOpInfo memory opInfo = opInfos[i]; - ( - uint256 validationData, - uint256 pmValidationData - ) = _validatePrepayment(i, ops[i], opInfo); - _validateAccountAndPaymasterValidationData( - i, - validationData, - pmValidationData, - address(0) - ); - } - - uint256 collected = 0; - - for (uint256 i = 0; i < opslen; i++) { - collected += _executeUserOp(i, ops[i], opInfos[i]); - } - - _compensate(beneficiary, collected); - } //unchecked - } - - /** - * Execute a batch of UserOperation with Aggregators - * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts) - * @param beneficiary the address to receive the fees - */ - function handleAggregatedOps( - UserOpsPerAggregator[] calldata opsPerAggregator, - address payable beneficiary - ) public { - uint256 opasLen = opsPerAggregator.length; - uint256 totalOps = 0; - for (uint256 i = 0; i < opasLen; i++) { - UserOpsPerAggregator calldata opa = opsPerAggregator[i]; - UserOperation[] calldata ops = opa.userOps; - IAggregator aggregator = opa.aggregator; - - //address(1) is special marker of "signature error" - require( - address(aggregator) != address(1), - "AA96 invalid aggregator" - ); - - if (address(aggregator) != address(0)) { - // solhint-disable-next-line no-empty-blocks - try aggregator.validateSignatures(ops, opa.signature) {} catch { - revert SignatureValidationFailed(address(aggregator)); - } - } - - totalOps += ops.length; - } - - UserOpInfo[] memory opInfos = new UserOpInfo[](totalOps); - - uint256 opIndex = 0; - for (uint256 a = 0; a < opasLen; a++) { - UserOpsPerAggregator calldata opa = opsPerAggregator[a]; - UserOperation[] calldata ops = opa.userOps; - IAggregator aggregator = opa.aggregator; - - uint256 opslen = ops.length; - for (uint256 i = 0; i < opslen; i++) { - UserOpInfo memory opInfo = opInfos[opIndex]; - ( - uint256 validationData, - uint256 paymasterValidationData - ) = _validatePrepayment(opIndex, ops[i], opInfo); - _validateAccountAndPaymasterValidationData( - i, - validationData, - paymasterValidationData, - address(aggregator) - ); - opIndex++; - } - } - - uint256 collected = 0; - opIndex = 0; - for (uint256 a = 0; a < opasLen; a++) { - UserOpsPerAggregator calldata opa = opsPerAggregator[a]; - emit SignatureAggregatorChanged(address(opa.aggregator)); - UserOperation[] calldata ops = opa.userOps; - uint256 opslen = ops.length; - - for (uint256 i = 0; i < opslen; i++) { - collected += _executeUserOp(opIndex, ops[i], opInfos[opIndex]); - opIndex++; - } - } - emit SignatureAggregatorChanged(address(0)); - - _compensate(beneficiary, collected); - } - - /// @inheritdoc IEntryPoint - function simulateHandleOp( - UserOperation calldata op, - address target, - bytes calldata targetCallData - ) external override { - UserOpInfo memory opInfo; - _simulationOnlyValidations(op); - ( - uint256 validationData, - uint256 paymasterValidationData - ) = _validatePrepayment(0, op, opInfo); - ValidationData memory data = _intersectTimeRange( - validationData, - paymasterValidationData - ); - - numberMarker(); - uint256 paid = _executeUserOp(0, op, opInfo); - numberMarker(); - bool targetSuccess; - bytes memory targetResult; - if (target != address(0)) { - (targetSuccess, targetResult) = target.call(targetCallData); - } - revert ExecutionResult( - opInfo.preOpGas, - paid, - data.validAfter, - data.validUntil, - targetSuccess, - targetResult - ); - } - - // A memory copy of UserOp static fields only. - // Excluding: callData, initCode and signature. Replacing paymasterAndData with paymaster. - struct MemoryUserOp { - address sender; - uint256 nonce; - uint256 callGasLimit; - uint256 verificationGasLimit; - uint256 preVerificationGas; - address paymaster; - uint256 maxFeePerGas; - uint256 maxPriorityFeePerGas; - } - - struct UserOpInfo { - MemoryUserOp mUserOp; - bytes32 userOpHash; - uint256 prefund; - uint256 contextOffset; - uint256 preOpGas; - } - - /** - * inner function to handle a UserOperation. - * Must be declared "external" to open a call context, but it can only be called by handleOps. - */ - function innerHandleOp( - bytes memory callData, - UserOpInfo memory opInfo, - bytes calldata context - ) external returns (uint256 actualGasCost) { - uint256 preGas = gasleft(); - require(msg.sender == address(this), "AA92 internal call only"); - MemoryUserOp memory mUserOp = opInfo.mUserOp; - - uint256 callGasLimit = mUserOp.callGasLimit; - unchecked { - // handleOps was called with gas limit too low. abort entire bundle. - if ( - gasleft() < callGasLimit + mUserOp.verificationGasLimit + 5000 - ) { - assembly { - mstore(0, INNER_OUT_OF_GAS) - revert(0, 32) - } - } - } - - IPaymaster.PostOpMode mode = IPaymaster.PostOpMode.opSucceeded; - if (callData.length > 0) { - bool success = Exec.call(mUserOp.sender, 0, callData, callGasLimit); - if (!success) { - bytes memory result = Exec.getReturnData(REVERT_REASON_MAX_LEN); - if (result.length > 0) { - emit UserOperationRevertReason( - opInfo.userOpHash, - mUserOp.sender, - mUserOp.nonce, - result - ); - } - mode = IPaymaster.PostOpMode.opReverted; - } - } - - unchecked { - uint256 actualGas = preGas - gasleft() + opInfo.preOpGas; - //note: opIndex is ignored (relevant only if mode==postOpReverted, which is only possible outside of innerHandleOp) - return _handlePostOp(0, mode, opInfo, context, actualGas); - } - } - - /** - * generate a request Id - unique identifier for this request. - * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid. - */ - function getUserOpHash(UserOperation calldata userOp) - public - view - returns (bytes32) - { - return - keccak256(abi.encode(userOp.hash(), address(this), block.chainid)); - } - - /** - * copy general fields from userOp into the memory opInfo structure. - */ - function _copyUserOpToMemory( - UserOperation calldata userOp, - MemoryUserOp memory mUserOp - ) internal pure { - mUserOp.sender = userOp.sender; - mUserOp.nonce = userOp.nonce; - mUserOp.callGasLimit = userOp.callGasLimit; - mUserOp.verificationGasLimit = userOp.verificationGasLimit; - mUserOp.preVerificationGas = userOp.preVerificationGas; - mUserOp.maxFeePerGas = userOp.maxFeePerGas; - mUserOp.maxPriorityFeePerGas = userOp.maxPriorityFeePerGas; - bytes calldata paymasterAndData = userOp.paymasterAndData; - if (paymasterAndData.length > 0) { - require( - paymasterAndData.length >= 20, - "AA93 invalid paymasterAndData" - ); - mUserOp.paymaster = address(bytes20(paymasterAndData[:20])); - } else { - mUserOp.paymaster = address(0); - } - } - - /** - * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp. - * @dev this method always revert. Successful result is ValidationResult error. other errors are failures. - * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data. - * @param userOp the user operation to validate. - */ - function simulateValidation(UserOperation calldata userOp) external { - UserOpInfo memory outOpInfo; - - _simulationOnlyValidations(userOp); - ( - uint256 validationData, - uint256 paymasterValidationData - ) = _validatePrepayment(0, userOp, outOpInfo); - StakeInfo memory paymasterInfo = _getStakeInfo( - outOpInfo.mUserOp.paymaster - ); - StakeInfo memory senderInfo = _getStakeInfo(outOpInfo.mUserOp.sender); - StakeInfo memory factoryInfo; - { - bytes calldata initCode = userOp.initCode; - address factory = initCode.length >= 20 - ? address(bytes20(initCode[0:20])) - : address(0); - factoryInfo = _getStakeInfo(factory); - } - - ValidationData memory data = _intersectTimeRange( - validationData, - paymasterValidationData - ); - address aggregator = data.aggregator; - bool sigFailed = aggregator == address(1); - ReturnInfo memory returnInfo = ReturnInfo( - outOpInfo.preOpGas, - outOpInfo.prefund, - sigFailed, - data.validAfter, - data.validUntil, - getMemoryBytesFromOffset(outOpInfo.contextOffset) - ); - - if (aggregator != address(0) && aggregator != address(1)) { - AggregatorStakeInfo memory aggregatorInfo = AggregatorStakeInfo( - aggregator, - _getStakeInfo(aggregator) - ); - revert ValidationResultWithAggregation( - returnInfo, - senderInfo, - factoryInfo, - paymasterInfo, - aggregatorInfo - ); - } - revert ValidationResult( - returnInfo, - senderInfo, - factoryInfo, - paymasterInfo - ); - } - - function _getRequiredPrefund(MemoryUserOp memory mUserOp) - internal - pure - returns (uint256 requiredPrefund) - { - unchecked { - //when using a Paymaster, the verificationGasLimit is used also to as a limit for the postOp call. - // our security model might call postOp eventually twice - uint256 mul = mUserOp.paymaster != address(0) ? 3 : 1; - uint256 requiredGas = mUserOp.callGasLimit + - mUserOp.verificationGasLimit * - mul + - mUserOp.preVerificationGas; - - requiredPrefund = requiredGas * mUserOp.maxFeePerGas; - } - } - - // create the sender's contract if needed. - function _createSenderIfNeeded( - uint256 opIndex, - UserOpInfo memory opInfo, - bytes calldata initCode - ) internal { - if (initCode.length != 0) { - address sender = opInfo.mUserOp.sender; - if (sender.code.length != 0) - revert FailedOp(opIndex, "AA10 sender already constructed"); - address sender1 = senderCreator.createSender{ - gas: opInfo.mUserOp.verificationGasLimit - }(initCode); - if (sender1 == address(0)) - revert FailedOp(opIndex, "AA13 initCode failed or OOG"); - if (sender1 != sender) - revert FailedOp(opIndex, "AA14 initCode must return sender"); - if (sender1.code.length == 0) - revert FailedOp(opIndex, "AA15 initCode must create sender"); - address factory = address(bytes20(initCode[0:20])); - emit AccountDeployed( - opInfo.userOpHash, - sender, - factory, - opInfo.mUserOp.paymaster - ); - } - } - - /** - * Get counterfactual sender address. - * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation. - * this method always revert, and returns the address in SenderAddressResult error - * @param initCode the constructor code to be passed into the UserOperation. - */ - function getSenderAddress(bytes calldata initCode) public { - revert SenderAddressResult(senderCreator.createSender(initCode)); - } - - function _simulationOnlyValidations(UserOperation calldata userOp) - internal - view - { - // solhint-disable-next-line no-empty-blocks - try - this._validateSenderAndPaymaster( - userOp.initCode, - userOp.sender, - userOp.paymasterAndData - ) - {} catch Error(string memory revertReason) { - if (bytes(revertReason).length != 0) { - revert FailedOp(0, revertReason); - } - } - } - - /** - * Called only during simulation. - * This function always reverts to prevent warm/cold storage differentiation in simulation vs execution. - */ - function _validateSenderAndPaymaster( - bytes calldata initCode, - address sender, - bytes calldata paymasterAndData - ) external view { - if (initCode.length == 0 && sender.code.length == 0) { - // it would revert anyway. but give a meaningful message - revert("AA20 account not deployed"); - } - if (paymasterAndData.length >= 20) { - address paymaster = address(bytes20(paymasterAndData[0:20])); - if (paymaster.code.length == 0) { - // it would revert anyway. but give a meaningful message - revert("AA30 paymaster not deployed"); - } - } - // always revert - revert(""); - } - - /** - * call account.validateUserOp. - * revert (with FailedOp) in case validateUserOp reverts, or account didn't send required prefund. - * decrement account's deposit if needed - */ - function _validateAccountPrepayment( - uint256 opIndex, - UserOperation calldata op, - UserOpInfo memory opInfo, - uint256 requiredPrefund - ) - internal - returns ( - uint256 gasUsedByValidateAccountPrepayment, - uint256 validationData - ) - { - unchecked { - uint256 preGas = gasleft(); - MemoryUserOp memory mUserOp = opInfo.mUserOp; - address sender = mUserOp.sender; - _createSenderIfNeeded(opIndex, opInfo, op.initCode); - address paymaster = mUserOp.paymaster; - numberMarker(); - uint256 missingAccountFunds = 0; - if (paymaster == address(0)) { - uint256 bal = balanceOf(sender); - missingAccountFunds = bal > requiredPrefund - ? 0 - : requiredPrefund - bal; - } - try - IAccount(sender).validateUserOp{ - gas: mUserOp.verificationGasLimit - }(op, opInfo.userOpHash, missingAccountFunds) - returns (uint256 _validationData) { - validationData = _validationData; - } catch Error(string memory revertReason) { - revert FailedOp( - opIndex, - string.concat("AA23 reverted: ", revertReason) - ); - } catch { - revert FailedOp(opIndex, "AA23 reverted (or OOG)"); - } - if (paymaster == address(0)) { - DepositInfo storage senderInfo = deposits[sender]; - uint256 deposit = senderInfo.deposit; - if (requiredPrefund > deposit) { - revert FailedOp(opIndex, "AA21 didn't pay prefund"); - } - senderInfo.deposit = uint112(deposit - requiredPrefund); - } - gasUsedByValidateAccountPrepayment = preGas - gasleft(); - } - } - - /** - * In case the request has a paymaster: - * Validate paymaster has enough deposit. - * Call paymaster.validatePaymasterUserOp. - * Revert with proper FailedOp in case paymaster reverts. - * Decrement paymaster's deposit - */ - function _validatePaymasterPrepayment( - uint256 opIndex, - UserOperation calldata op, - UserOpInfo memory opInfo, - uint256 requiredPreFund, - uint256 gasUsedByValidateAccountPrepayment - ) internal returns (bytes memory context, uint256 validationData) { - unchecked { - MemoryUserOp memory mUserOp = opInfo.mUserOp; - uint256 verificationGasLimit = mUserOp.verificationGasLimit; - require( - verificationGasLimit > gasUsedByValidateAccountPrepayment, - "AA41 too little verificationGas" - ); - uint256 gas = verificationGasLimit - - gasUsedByValidateAccountPrepayment; - - address paymaster = mUserOp.paymaster; - DepositInfo storage paymasterInfo = deposits[paymaster]; - uint256 deposit = paymasterInfo.deposit; - if (deposit < requiredPreFund) { - revert FailedOp(opIndex, "AA31 paymaster deposit too low"); - } - paymasterInfo.deposit = uint112(deposit - requiredPreFund); - try - IPaymaster(paymaster).validatePaymasterUserOp{gas: gas}( - op, - opInfo.userOpHash, - requiredPreFund - ) - returns (bytes memory _context, uint256 _validationData) { - context = _context; - validationData = _validationData; - } catch Error(string memory revertReason) { - revert FailedOp( - opIndex, - string.concat("AA33 reverted: ", revertReason) - ); - } catch { - revert FailedOp(opIndex, "AA33 reverted (or OOG)"); - } - } - } - - /** - * revert if either account validationData or paymaster validationData is expired - */ - function _validateAccountAndPaymasterValidationData( - uint256 opIndex, - uint256 validationData, - uint256 paymasterValidationData, - address expectedAggregator - ) internal view { - (address aggregator, bool outOfTimeRange) = _getValidationData( - validationData - ); - if (expectedAggregator != aggregator) { - revert FailedOp(opIndex, "AA24 signature error"); - } - if (outOfTimeRange) { - revert FailedOp(opIndex, "AA22 expired or not due"); - } - //pmAggregator is not a real signature aggregator: we don't have logic to handle it as address. - // non-zero address means that the paymaster fails due to some signature check (which is ok only during estimation) - address pmAggregator; - (pmAggregator, outOfTimeRange) = _getValidationData( - paymasterValidationData - ); - if (pmAggregator != address(0)) { - revert FailedOp(opIndex, "AA34 signature error"); - } - if (outOfTimeRange) { - revert FailedOp(opIndex, "AA32 paymaster expired or not due"); - } - } - - function _getValidationData(uint256 validationData) - internal - view - returns (address aggregator, bool outOfTimeRange) - { - if (validationData == 0) { - return (address(0), false); - } - ValidationData memory data = _parseValidationData(validationData); - // solhint-disable-next-line not-rely-on-time - outOfTimeRange = - block.timestamp > data.validUntil || - block.timestamp < data.validAfter; - aggregator = data.aggregator; - } - - /** - * validate account and paymaster (if defined). - * also make sure total validation doesn't exceed verificationGasLimit - * this method is called off-chain (simulateValidation()) and on-chain (from handleOps) - * @param opIndex the index of this userOp into the "opInfos" array - * @param userOp the userOp to validate - */ - function _validatePrepayment( - uint256 opIndex, - UserOperation calldata userOp, - UserOpInfo memory outOpInfo - ) - private - returns (uint256 validationData, uint256 paymasterValidationData) - { - uint256 preGas = gasleft(); - MemoryUserOp memory mUserOp = outOpInfo.mUserOp; - _copyUserOpToMemory(userOp, mUserOp); - outOpInfo.userOpHash = getUserOpHash(userOp); - - // validate all numeric values in userOp are well below 128 bit, so they can safely be added - // and multiplied without causing overflow - uint256 maxGasValues = mUserOp.preVerificationGas | - mUserOp.verificationGasLimit | - mUserOp.callGasLimit | - userOp.maxFeePerGas | - userOp.maxPriorityFeePerGas; - require(maxGasValues <= type(uint120).max, "AA94 gas values overflow"); - - uint256 gasUsedByValidateAccountPrepayment; - uint256 requiredPreFund = _getRequiredPrefund(mUserOp); - ( - gasUsedByValidateAccountPrepayment, - validationData - ) = _validateAccountPrepayment( - opIndex, - userOp, - outOpInfo, - requiredPreFund - ); - //a "marker" where account opcode validation is done and paymaster opcode validation is about to start - // (used only by off-chain simulateValidation) - numberMarker(); - - bytes memory context; - if (mUserOp.paymaster != address(0)) { - (context, paymasterValidationData) = _validatePaymasterPrepayment( - opIndex, - userOp, - outOpInfo, - requiredPreFund, - gasUsedByValidateAccountPrepayment - ); - } - unchecked { - uint256 gasUsed = preGas - gasleft(); - - if (userOp.verificationGasLimit < gasUsed) { - revert FailedOp(opIndex, "AA40 over verificationGasLimit"); - } - outOpInfo.prefund = requiredPreFund; - outOpInfo.contextOffset = getOffsetOfMemoryBytes(context); - outOpInfo.preOpGas = preGas - gasleft() + userOp.preVerificationGas; - } - } - - /** - * process post-operation. - * called just after the callData is executed. - * if a paymaster is defined and its validation returned a non-empty context, its postOp is called. - * the excess amount is refunded to the account (or paymaster - if it was used in the request) - * @param opIndex index in the batch - * @param mode - whether is called from innerHandleOp, or outside (postOpReverted) - * @param opInfo userOp fields and info collected during validation - * @param context the context returned in validatePaymasterUserOp - * @param actualGas the gas used so far by this user operation - */ - function _handlePostOp( - uint256 opIndex, - IPaymaster.PostOpMode mode, - UserOpInfo memory opInfo, - bytes memory context, - uint256 actualGas - ) private returns (uint256 actualGasCost) { - uint256 preGas = gasleft(); - unchecked { - address refundAddress; - MemoryUserOp memory mUserOp = opInfo.mUserOp; - uint256 gasPrice = getUserOpGasPrice(mUserOp); - - address paymaster = mUserOp.paymaster; - if (paymaster == address(0)) { - refundAddress = mUserOp.sender; - } else { - refundAddress = paymaster; - if (context.length > 0) { - actualGasCost = actualGas * gasPrice; - if (mode != IPaymaster.PostOpMode.postOpReverted) { - IPaymaster(paymaster).postOp{ - gas: mUserOp.verificationGasLimit - }(mode, context, actualGasCost); - } else { - // solhint-disable-next-line no-empty-blocks - try - IPaymaster(paymaster).postOp{ - gas: mUserOp.verificationGasLimit - }(mode, context, actualGasCost) - {} catch Error(string memory reason) { - revert FailedOp( - opIndex, - string.concat("AA50 postOp reverted: ", reason) - ); - } catch { - revert FailedOp(opIndex, "AA50 postOp revert"); - } - } - } - } - actualGas += preGas - gasleft(); - actualGasCost = actualGas * gasPrice; - if (opInfo.prefund < actualGasCost) { - revert FailedOp(opIndex, "AA51 prefund below actualGasCost"); - } - uint256 refund = opInfo.prefund - actualGasCost; - _incrementDeposit(refundAddress, refund); - bool success = mode == IPaymaster.PostOpMode.opSucceeded; - emit UserOperationEvent( - opInfo.userOpHash, - mUserOp.sender, - mUserOp.paymaster, - mUserOp.nonce, - success, - actualGasCost, - actualGas - ); - } // unchecked - } - - /** - * the gas price this UserOp agrees to pay. - * relayer/block builder might submit the TX with higher priorityFee, but the user should not - */ - function getUserOpGasPrice(MemoryUserOp memory mUserOp) - internal - view - returns (uint256) - { - unchecked { - uint256 maxFeePerGas = mUserOp.maxFeePerGas; - uint256 maxPriorityFeePerGas = mUserOp.maxPriorityFeePerGas; - if (maxFeePerGas == maxPriorityFeePerGas) { - //legacy mode (for networks that don't support basefee opcode) - return maxFeePerGas; - } - return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee); - } - } - - function min(uint256 a, uint256 b) internal pure returns (uint256) { - return a < b ? a : b; - } - - function getOffsetOfMemoryBytes(bytes memory data) - internal - pure - returns (uint256 offset) - { - assembly { - offset := data - } - } - - function getMemoryBytesFromOffset(uint256 offset) - internal - pure - returns (bytes memory data) - { - assembly { - data := offset - } - } - - //place the NUMBER opcode in the code. - // this is used as a marker during simulation, as this OP is completely banned from the simulated code of the - // account and paymaster. - function numberMarker() internal view { - assembly { - mstore(0, number()) - } - } -} diff --git a/contracts/src/v0.8/vendor/entrypoint/core/Helpers.sol b/contracts/src/v0.8/vendor/entrypoint/core/Helpers.sol deleted file mode 100644 index 71a6dc3d16b..00000000000 --- a/contracts/src/v0.8/vendor/entrypoint/core/Helpers.sol +++ /dev/null @@ -1,68 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity ^0.8.12; - -/** - * returned data from validateUserOp. - * validateUserOp returns a uint256, with is created by `_packedValidationData` and parsed by `_parseValidationData` - * @param aggregator - address(0) - the account validated the signature by itself. - * address(1) - the account failed to validate the signature. - * otherwise - this is an address of a signature aggregator that must be used to validate the signature. - * @param validAfter - this UserOp is valid only after this timestamp. - * @param validaUntil - this UserOp is valid only up to this timestamp. - */ -struct ValidationData { - address aggregator; - uint48 validAfter; - uint48 validUntil; -} - -//extract sigFailed, validAfter, validUntil. -// also convert zero validUntil to type(uint48).max -function _parseValidationData(uint validationData) pure returns (ValidationData memory data) { - address aggregator = address(uint160(validationData)); - uint48 validUntil = uint48(validationData >> 160); - if (validUntil == 0) { - validUntil = type(uint48).max; - } - uint48 validAfter = uint48(validationData >> (48 + 160)); - return ValidationData(aggregator, validAfter, validUntil); -} - -// intersect account and paymaster ranges. -function _intersectTimeRange( - uint256 validationData, - uint256 paymasterValidationData -) pure returns (ValidationData memory) { - ValidationData memory accountValidationData = _parseValidationData(validationData); - ValidationData memory pmValidationData = _parseValidationData(paymasterValidationData); - address aggregator = accountValidationData.aggregator; - if (aggregator == address(0)) { - aggregator = pmValidationData.aggregator; - } - uint48 validAfter = accountValidationData.validAfter; - uint48 validUntil = accountValidationData.validUntil; - uint48 pmValidAfter = pmValidationData.validAfter; - uint48 pmValidUntil = pmValidationData.validUntil; - - if (validAfter < pmValidAfter) validAfter = pmValidAfter; - if (validUntil > pmValidUntil) validUntil = pmValidUntil; - return ValidationData(aggregator, validAfter, validUntil); -} - -/** - * helper to pack the return value for validateUserOp - * @param data - the ValidationData to pack - */ -function _packValidationData(ValidationData memory data) pure returns (uint256) { - return uint160(data.aggregator) | (uint256(data.validUntil) << 160) | (uint256(data.validAfter) << (160 + 48)); -} - -/** - * helper to pack the return value for validateUserOp, when not using an aggregator - * @param sigFailed - true for signature failure, false for success - * @param validUntil last timestamp this UserOperation is valid (or zero for infinite) - * @param validAfter first timestamp this UserOperation is valid - */ -function _packValidationData(bool sigFailed, uint48 validUntil, uint48 validAfter) pure returns (uint256) { - return (sigFailed ? 1 : 0) | (uint256(validUntil) << 160) | (uint256(validAfter) << (160 + 48)); -} diff --git a/contracts/src/v0.8/vendor/entrypoint/core/SenderCreator.sol b/contracts/src/v0.8/vendor/entrypoint/core/SenderCreator.sol deleted file mode 100644 index 36fad7b91f1..00000000000 --- a/contracts/src/v0.8/vendor/entrypoint/core/SenderCreator.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity ^0.8.12; - -/** - * helper contract for EntryPoint, to call userOp.initCode from a "neutral" address, - * which is explicitly not the entryPoint itself. - */ -contract SenderCreator { - - /** - * call the "initCode" factory to create and return the sender account address - * @param initCode the initCode value from a UserOp. contains 20 bytes of factory address, followed by calldata - * @return sender the returned address of the created account, or zero address on failure. - */ - function createSender(bytes calldata initCode) external returns (address sender) { - address factory = address(bytes20(initCode[0 : 20])); - bytes memory initCallData = initCode[20 :]; - bool success; - /* solhint-disable no-inline-assembly */ - assembly { - success := call(gas(), factory, 0, add(initCallData, 0x20), mload(initCallData), 0, 32) - sender := mload(0) - } - if (!success) { - sender = address(0); - } - } -} diff --git a/contracts/src/v0.8/vendor/entrypoint/core/StakeManager.sol b/contracts/src/v0.8/vendor/entrypoint/core/StakeManager.sol deleted file mode 100644 index e5ca2b97dd4..00000000000 --- a/contracts/src/v0.8/vendor/entrypoint/core/StakeManager.sol +++ /dev/null @@ -1,124 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -pragma solidity ^0.8.12; - -import "../interfaces/IStakeManager.sol"; - -/* solhint-disable avoid-low-level-calls */ -/* solhint-disable not-rely-on-time */ -/** - * manage deposits and stakes. - * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account) - * stake is value locked for at least "unstakeDelay" by a paymaster. - */ -abstract contract StakeManager is IStakeManager { - - /// maps paymaster to their deposits and stakes - mapping(address => DepositInfo) public deposits; - - /// @inheritdoc IStakeManager - function getDepositInfo(address account) public view returns (DepositInfo memory info) { - return deposits[account]; - } - - // internal method to return just the stake info - function _getStakeInfo(address addr) internal view returns (StakeInfo memory info) { - DepositInfo storage depositInfo = deposits[addr]; - info.stake = depositInfo.stake; - info.unstakeDelaySec = depositInfo.unstakeDelaySec; - } - - /// return the deposit (for gas payment) of the account - function balanceOf(address account) public view returns (uint256) { - return deposits[account].deposit; - } - - receive() external payable { - depositTo(msg.sender); - } - - function _incrementDeposit(address account, uint256 amount) internal { - DepositInfo storage info = deposits[account]; - uint256 newAmount = info.deposit + amount; - require(newAmount <= type(uint112).max, "deposit overflow"); - info.deposit = uint112(newAmount); - } - - /** - * add to the deposit of the given account - */ - function depositTo(address account) public payable { - _incrementDeposit(account, msg.value); - DepositInfo storage info = deposits[account]; - emit Deposited(account, info.deposit); - } - - /** - * add to the account's stake - amount and delay - * any pending unstake is first cancelled. - * @param unstakeDelaySec the new lock duration before the deposit can be withdrawn. - */ - function addStake(uint32 unstakeDelaySec) public payable { - DepositInfo storage info = deposits[msg.sender]; - require(unstakeDelaySec > 0, "must specify unstake delay"); - require(unstakeDelaySec >= info.unstakeDelaySec, "cannot decrease unstake time"); - uint256 stake = info.stake + msg.value; - require(stake > 0, "no stake specified"); - require(stake <= type(uint112).max, "stake overflow"); - deposits[msg.sender] = DepositInfo( - info.deposit, - true, - uint112(stake), - unstakeDelaySec, - 0 - ); - emit StakeLocked(msg.sender, stake, unstakeDelaySec); - } - - /** - * attempt to unlock the stake. - * the value can be withdrawn (using withdrawStake) after the unstake delay. - */ - function unlockStake() external { - DepositInfo storage info = deposits[msg.sender]; - require(info.unstakeDelaySec != 0, "not staked"); - require(info.staked, "already unstaking"); - uint48 withdrawTime = uint48(block.timestamp) + info.unstakeDelaySec; - info.withdrawTime = withdrawTime; - info.staked = false; - emit StakeUnlocked(msg.sender, withdrawTime); - } - - - /** - * withdraw from the (unlocked) stake. - * must first call unlockStake and wait for the unstakeDelay to pass - * @param withdrawAddress the address to send withdrawn value. - */ - function withdrawStake(address payable withdrawAddress) external { - DepositInfo storage info = deposits[msg.sender]; - uint256 stake = info.stake; - require(stake > 0, "No stake to withdraw"); - require(info.withdrawTime > 0, "must call unlockStake() first"); - require(info.withdrawTime <= block.timestamp, "Stake withdrawal is not due"); - info.unstakeDelaySec = 0; - info.withdrawTime = 0; - info.stake = 0; - emit StakeWithdrawn(msg.sender, withdrawAddress, stake); - (bool success,) = withdrawAddress.call{value : stake}(""); - require(success, "failed to withdraw stake"); - } - - /** - * withdraw from the deposit. - * @param withdrawAddress the address to send withdrawn value. - * @param withdrawAmount the amount to withdraw. - */ - function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external { - DepositInfo storage info = deposits[msg.sender]; - require(withdrawAmount <= info.deposit, "Withdraw amount too large"); - info.deposit = uint112(info.deposit - withdrawAmount); - emit Withdrawn(msg.sender, withdrawAddress, withdrawAmount); - (bool success,) = withdrawAddress.call{value : withdrawAmount}(""); - require(success, "failed to withdraw"); - } -} diff --git a/contracts/src/v0.8/vendor/entrypoint/interfaces/IAccount.sol b/contracts/src/v0.8/vendor/entrypoint/interfaces/IAccount.sol deleted file mode 100644 index 1600de3d71e..00000000000 --- a/contracts/src/v0.8/vendor/entrypoint/interfaces/IAccount.sol +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity ^0.8.12; - -import "./UserOperation.sol"; - -interface IAccount { - - /** - * Validate user's signature and nonce - * the entryPoint will make the call to the recipient only if this validation call returns successfully. - * signature failure should be reported by returning SIG_VALIDATION_FAILED (1). - * This allows making a "simulation call" without a valid signature - * Other failures (e.g. nonce mismatch, or invalid signature format) should still revert to signal failure. - * - * @dev Must validate caller is the entryPoint. - * Must validate the signature and nonce - * @param userOp the operation that is about to be executed. - * @param userOpHash hash of the user's request data. can be used as the basis for signature. - * @param missingAccountFunds missing funds on the account's deposit in the entrypoint. - * This is the minimum amount to transfer to the sender(entryPoint) to be able to make the call. - * The excess is left as a deposit in the entrypoint, for future calls. - * can be withdrawn anytime using "entryPoint.withdrawTo()" - * In case there is a paymaster in the request (or the current deposit is high enough), this value will be zero. - * @return validationData packaged ValidationData structure. use `_packValidationData` and `_unpackValidationData` to encode and decode - * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure, - * otherwise, an address of an "authorizer" contract. - * <6-byte> validUntil - last timestamp this operation is valid. 0 for "indefinite" - * <6-byte> validAfter - first timestamp this operation is valid - * If an account doesn't use time-range, it is enough to return SIG_VALIDATION_FAILED value (1) for signature failure. - * Note that the validation code cannot use block.timestamp (or block.number) directly. - */ - function validateUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds) - external returns (uint256 validationData); -} diff --git a/contracts/src/v0.8/vendor/entrypoint/interfaces/IAggregator.sol b/contracts/src/v0.8/vendor/entrypoint/interfaces/IAggregator.sol deleted file mode 100644 index 086c6f32241..00000000000 --- a/contracts/src/v0.8/vendor/entrypoint/interfaces/IAggregator.sol +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity ^0.8.12; - -import "./UserOperation.sol"; - -/** - * Aggregated Signatures validator. - */ -interface IAggregator { - - /** - * validate aggregated signature. - * revert if the aggregated signature does not match the given list of operations. - */ - function validateSignatures(UserOperation[] calldata userOps, bytes calldata signature) external view; - - /** - * validate signature of a single userOp - * This method is should be called by bundler after EntryPoint.simulateValidation() returns (reverts) with ValidationResultWithAggregation - * First it validates the signature over the userOp. Then it returns data to be used when creating the handleOps. - * @param userOp the userOperation received from the user. - * @return sigForUserOp the value to put into the signature field of the userOp when calling handleOps. - * (usually empty, unless account and aggregator support some kind of "multisig" - */ - function validateUserOpSignature(UserOperation calldata userOp) - external view returns (bytes memory sigForUserOp); - - /** - * aggregate multiple signatures into a single value. - * This method is called off-chain to calculate the signature to pass with handleOps() - * bundler MAY use optimized custom code perform this aggregation - * @param userOps array of UserOperations to collect the signatures from. - * @return aggregatedSignature the aggregated signature - */ - function aggregateSignatures(UserOperation[] calldata userOps) external view returns (bytes memory aggregatedSignature); -} diff --git a/contracts/src/v0.8/vendor/entrypoint/interfaces/IEntryPoint.sol b/contracts/src/v0.8/vendor/entrypoint/interfaces/IEntryPoint.sol deleted file mode 100644 index 22bb1b7a6e7..00000000000 --- a/contracts/src/v0.8/vendor/entrypoint/interfaces/IEntryPoint.sol +++ /dev/null @@ -1,197 +0,0 @@ -/** - ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation. - ** Only one instance required on each chain. - **/ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity ^0.8.12; - -/* solhint-disable avoid-low-level-calls */ -/* solhint-disable no-inline-assembly */ -/* solhint-disable reason-string */ - -import "./UserOperation.sol"; -import "./IStakeManager.sol"; -import "./IAggregator.sol"; - -interface IEntryPoint is IStakeManager { - - /*** - * An event emitted after each successful request - * @param userOpHash - unique identifier for the request (hash its entire content, except signature). - * @param sender - the account that generates this request. - * @param paymaster - if non-null, the paymaster that pays for this request. - * @param nonce - the nonce value from the request. - * @param success - true if the sender transaction succeeded, false if reverted. - * @param actualGasCost - actual amount paid (by account or paymaster) for this UserOperation. - * @param actualGasUsed - total gas used by this UserOperation (including preVerification, creation, validation and execution). - */ - event UserOperationEvent(bytes32 indexed userOpHash, address indexed sender, address indexed paymaster, uint256 nonce, bool success, uint256 actualGasCost, uint256 actualGasUsed); - - /** - * account "sender" was deployed. - * @param userOpHash the userOp that deployed this account. UserOperationEvent will follow. - * @param sender the account that is deployed - * @param factory the factory used to deploy this account (in the initCode) - * @param paymaster the paymaster used by this UserOp - */ - event AccountDeployed(bytes32 indexed userOpHash, address indexed sender, address factory, address paymaster); - - /** - * An event emitted if the UserOperation "callData" reverted with non-zero length - * @param userOpHash the request unique identifier. - * @param sender the sender of this request - * @param nonce the nonce used in the request - * @param revertReason - the return bytes from the (reverted) call to "callData". - */ - event UserOperationRevertReason(bytes32 indexed userOpHash, address indexed sender, uint256 nonce, bytes revertReason); - - /** - * signature aggregator used by the following UserOperationEvents within this bundle. - */ - event SignatureAggregatorChanged(address indexed aggregator); - - /** - * a custom revert error of handleOps, to identify the offending op. - * NOTE: if simulateValidation passes successfully, there should be no reason for handleOps to fail on it. - * @param opIndex - index into the array of ops to the failed one (in simulateValidation, this is always zero) - * @param reason - revert reason - * The string starts with a unique code "AAmn", where "m" is "1" for factory, "2" for account and "3" for paymaster issues, - * so a failure can be attributed to the correct entity. - * Should be caught in off-chain handleOps simulation and not happen on-chain. - * Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts. - */ - error FailedOp(uint256 opIndex, string reason); - - /** - * error case when a signature aggregator fails to verify the aggregated signature it had created. - */ - error SignatureValidationFailed(address aggregator); - - /** - * Successful result from simulateValidation. - * @param returnInfo gas and time-range returned values - * @param senderInfo stake information about the sender - * @param factoryInfo stake information about the factory (if any) - * @param paymasterInfo stake information about the paymaster (if any) - */ - error ValidationResult(ReturnInfo returnInfo, - StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo); - - /** - * Successful result from simulateValidation, if the account returns a signature aggregator - * @param returnInfo gas and time-range returned values - * @param senderInfo stake information about the sender - * @param factoryInfo stake information about the factory (if any) - * @param paymasterInfo stake information about the paymaster (if any) - * @param aggregatorInfo signature aggregation info (if the account requires signature aggregator) - * bundler MUST use it to verify the signature, or reject the UserOperation - */ - error ValidationResultWithAggregation(ReturnInfo returnInfo, - StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo, - AggregatorStakeInfo aggregatorInfo); - - /** - * return value of getSenderAddress - */ - error SenderAddressResult(address sender); - - /** - * return value of simulateHandleOp - */ - error ExecutionResult(uint256 preOpGas, uint256 paid, uint48 validAfter, uint48 validUntil, bool targetSuccess, bytes targetResult); - - //UserOps handled, per aggregator - struct UserOpsPerAggregator { - UserOperation[] userOps; - - // aggregator address - IAggregator aggregator; - // aggregated signature - bytes signature; - } - - /** - * Execute a batch of UserOperation. - * no signature aggregator is used. - * if any account requires an aggregator (that is, it returned an aggregator when - * performing simulateValidation), then handleAggregatedOps() must be used instead. - * @param ops the operations to execute - * @param beneficiary the address to receive the fees - */ - function handleOps(UserOperation[] calldata ops, address payable beneficiary) external; - - /** - * Execute a batch of UserOperation with Aggregators - * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts) - * @param beneficiary the address to receive the fees - */ - function handleAggregatedOps( - UserOpsPerAggregator[] calldata opsPerAggregator, - address payable beneficiary - ) external; - - /** - * generate a request Id - unique identifier for this request. - * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid. - */ - function getUserOpHash(UserOperation calldata userOp) external view returns (bytes32); - - /** - * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp. - * @dev this method always revert. Successful result is ValidationResult error. other errors are failures. - * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data. - * @param userOp the user operation to validate. - */ - function simulateValidation(UserOperation calldata userOp) external; - - /** - * gas and return values during simulation - * @param preOpGas the gas used for validation (including preValidationGas) - * @param prefund the required prefund for this operation - * @param sigFailed validateUserOp's (or paymaster's) signature check failed - * @param validAfter - first timestamp this UserOp is valid (merging account and paymaster time-range) - * @param validUntil - last timestamp this UserOp is valid (merging account and paymaster time-range) - * @param paymasterContext returned by validatePaymasterUserOp (to be passed into postOp) - */ - struct ReturnInfo { - uint256 preOpGas; - uint256 prefund; - bool sigFailed; - uint48 validAfter; - uint48 validUntil; - bytes paymasterContext; - } - - /** - * returned aggregated signature info. - * the aggregator returned by the account, and its current stake. - */ - struct AggregatorStakeInfo { - address aggregator; - StakeInfo stakeInfo; - } - - /** - * Get counterfactual sender address. - * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation. - * this method always revert, and returns the address in SenderAddressResult error - * @param initCode the constructor code to be passed into the UserOperation. - */ - function getSenderAddress(bytes memory initCode) external; - - - /** - * simulate full execution of a UserOperation (including both validation and target execution) - * this method will always revert with "ExecutionResult". - * it performs full validation of the UserOperation, but ignores signature error. - * an optional target address is called after the userop succeeds, and its value is returned - * (before the entire call is reverted) - * Note that in order to collect the the success/failure of the target call, it must be executed - * with trace enabled to track the emitted events. - * @param op the UserOperation to simulate - * @param target if nonzero, a target address to call after userop simulation. If called, the targetSuccess and targetResult - * are set to the return from that call. - * @param targetCallData callData to pass to target address - */ - function simulateHandleOp(UserOperation calldata op, address target, bytes calldata targetCallData) external; -} diff --git a/contracts/src/v0.8/vendor/entrypoint/interfaces/IPaymaster.sol b/contracts/src/v0.8/vendor/entrypoint/interfaces/IPaymaster.sol deleted file mode 100644 index af50367acfc..00000000000 --- a/contracts/src/v0.8/vendor/entrypoint/interfaces/IPaymaster.sol +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity ^0.8.12; - -import "./UserOperation.sol"; - -/** - * the interface exposed by a paymaster contract, who agrees to pay the gas for user's operations. - * a paymaster must hold a stake to cover the required entrypoint stake and also the gas for the transaction. - */ -interface IPaymaster { - - enum PostOpMode { - opSucceeded, // user op succeeded - opReverted, // user op reverted. still has to pay for gas. - postOpReverted //user op succeeded, but caused postOp to revert. Now it's a 2nd call, after user's op was deliberately reverted. - } - - /** - * payment validation: check if paymaster agrees to pay. - * Must verify sender is the entryPoint. - * Revert to reject this request. - * Note that bundlers will reject this method if it changes the state, unless the paymaster is trusted (whitelisted) - * The paymaster pre-pays using its deposit, and receive back a refund after the postOp method returns. - * @param userOp the user operation - * @param userOpHash hash of the user's request data. - * @param maxCost the maximum cost of this transaction (based on maximum gas and gas price from userOp) - * @return context value to send to a postOp - * zero length to signify postOp is not required. - * @return validationData signature and time-range of this operation, encoded the same as the return value of validateUserOperation - * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure, - * otherwise, an address of an "authorizer" contract. - * <6-byte> validUntil - last timestamp this operation is valid. 0 for "indefinite" - * <6-byte> validAfter - first timestamp this operation is valid - * Note that the validation code cannot use block.timestamp (or block.number) directly. - */ - function validatePaymasterUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost) - external returns (bytes memory context, uint256 validationData); - - /** - * post-operation handler. - * Must verify sender is the entryPoint - * @param mode enum with the following options: - * opSucceeded - user operation succeeded. - * opReverted - user op reverted. still has to pay for gas. - * postOpReverted - user op succeeded, but caused postOp (in mode=opSucceeded) to revert. - * Now this is the 2nd call, after user's op was deliberately reverted. - * @param context - the context value returned by validatePaymasterUserOp - * @param actualGasCost - actual gas used so far (without this postOp call). - */ - function postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost) external; -} diff --git a/contracts/src/v0.8/vendor/entrypoint/interfaces/IStakeManager.sol b/contracts/src/v0.8/vendor/entrypoint/interfaces/IStakeManager.sol deleted file mode 100644 index c19c1bab88b..00000000000 --- a/contracts/src/v0.8/vendor/entrypoint/interfaces/IStakeManager.sol +++ /dev/null @@ -1,104 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -pragma solidity ^0.8.12; - -/** - * manage deposits and stakes. - * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account) - * stake is value locked for at least "unstakeDelay" by the staked entity. - */ -interface IStakeManager { - - event Deposited( - address indexed account, - uint256 totalDeposit - ); - - event Withdrawn( - address indexed account, - address withdrawAddress, - uint256 amount - ); - - /// Emitted when stake or unstake delay are modified - event StakeLocked( - address indexed account, - uint256 totalStaked, - uint256 unstakeDelaySec - ); - - /// Emitted once a stake is scheduled for withdrawal - event StakeUnlocked( - address indexed account, - uint256 withdrawTime - ); - - event StakeWithdrawn( - address indexed account, - address withdrawAddress, - uint256 amount - ); - - /** - * @param deposit the entity's deposit - * @param staked true if this entity is staked. - * @param stake actual amount of ether staked for this entity. - * @param unstakeDelaySec minimum delay to withdraw the stake. - * @param withdrawTime - first block timestamp where 'withdrawStake' will be callable, or zero if already locked - * @dev sizes were chosen so that (deposit,staked, stake) fit into one cell (used during handleOps) - * and the rest fit into a 2nd cell. - * 112 bit allows for 10^15 eth - * 48 bit for full timestamp - * 32 bit allows 150 years for unstake delay - */ - struct DepositInfo { - uint112 deposit; - bool staked; - uint112 stake; - uint32 unstakeDelaySec; - uint48 withdrawTime; - } - - //API struct used by getStakeInfo and simulateValidation - struct StakeInfo { - uint256 stake; - uint256 unstakeDelaySec; - } - - /// @return info - full deposit information of given account - function getDepositInfo(address account) external view returns (DepositInfo memory info); - - /// @return the deposit (for gas payment) of the account - function balanceOf(address account) external view returns (uint256); - - /** - * add to the deposit of the given account - */ - function depositTo(address account) external payable; - - /** - * add to the account's stake - amount and delay - * any pending unstake is first cancelled. - * @param _unstakeDelaySec the new lock duration before the deposit can be withdrawn. - */ - function addStake(uint32 _unstakeDelaySec) external payable; - - /** - * attempt to unlock the stake. - * the value can be withdrawn (using withdrawStake) after the unstake delay. - */ - function unlockStake() external; - - /** - * withdraw from the (unlocked) stake. - * must first call unlockStake and wait for the unstakeDelay to pass - * @param withdrawAddress the address to send withdrawn value. - */ - function withdrawStake(address payable withdrawAddress) external; - - /** - * withdraw from the deposit. - * @param withdrawAddress the address to send withdrawn value. - * @param withdrawAmount the amount to withdraw. - */ - function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external; -} diff --git a/contracts/src/v0.8/vendor/entrypoint/interfaces/UserOperation.sol b/contracts/src/v0.8/vendor/entrypoint/interfaces/UserOperation.sol deleted file mode 100644 index dfff42791f3..00000000000 --- a/contracts/src/v0.8/vendor/entrypoint/interfaces/UserOperation.sol +++ /dev/null @@ -1,84 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity ^0.8.12; - -/* solhint-disable no-inline-assembly */ - - /** - * User Operation struct - * @param sender the sender account of this request. - * @param nonce unique value the sender uses to verify it is not a replay. - * @param initCode if set, the account contract will be created by this constructor/ - * @param callData the method call to execute on this account. - * @param callGasLimit the gas limit passed to the callData method call. - * @param verificationGasLimit gas used for validateUserOp and validatePaymasterUserOp. - * @param preVerificationGas gas not calculated by the handleOps method, but added to the gas paid. Covers batch overhead. - * @param maxFeePerGas same as EIP-1559 gas parameter. - * @param maxPriorityFeePerGas same as EIP-1559 gas parameter. - * @param paymasterAndData if set, this field holds the paymaster address and paymaster-specific data. the paymaster will pay for the transaction instead of the sender. - * @param signature sender-verified signature over the entire request, the EntryPoint address and the chain ID. - */ - struct UserOperation { - - address sender; - uint256 nonce; - bytes initCode; - bytes callData; - uint256 callGasLimit; - uint256 verificationGasLimit; - uint256 preVerificationGas; - uint256 maxFeePerGas; - uint256 maxPriorityFeePerGas; - bytes paymasterAndData; - bytes signature; - } - -/** - * Utility functions helpful when working with UserOperation structs. - */ -library UserOperationLib { - - function getSender(UserOperation calldata userOp) internal pure returns (address) { - address data; - //read sender from userOp, which is first userOp member (saves 800 gas...) - assembly {data := calldataload(userOp)} - return address(uint160(data)); - } - - //relayer/block builder might submit the TX with higher priorityFee, but the user should not - // pay above what he signed for. - function gasPrice(UserOperation calldata userOp) internal view returns (uint256) { - unchecked { - uint256 maxFeePerGas = userOp.maxFeePerGas; - uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas; - if (maxFeePerGas == maxPriorityFeePerGas) { - //legacy mode (for networks that don't support basefee opcode) - return maxFeePerGas; - } - return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee); - } - } - - function pack(UserOperation calldata userOp) internal pure returns (bytes memory ret) { - //lighter signature scheme. must match UserOp.ts#packUserOp - bytes calldata sig = userOp.signature; - // copy directly the userOp from calldata up to (but not including) the signature. - // this encoding depends on the ABI encoding of calldata, but is much lighter to copy - // than referencing each field separately. - assembly { - let ofs := userOp - let len := sub(sub(sig.offset, ofs), 32) - ret := mload(0x40) - mstore(0x40, add(ret, add(len, 32))) - mstore(ret, len) - calldatacopy(add(ret, 32), ofs, len) - } - } - - function hash(UserOperation calldata userOp) internal pure returns (bytes32) { - return keccak256(pack(userOp)); - } - - function min(uint256 a, uint256 b) internal pure returns (uint256) { - return a < b ? a : b; - } -} diff --git a/contracts/src/v0.8/vendor/entrypoint/utils/Exec.sol b/contracts/src/v0.8/vendor/entrypoint/utils/Exec.sol deleted file mode 100644 index 69d653d938a..00000000000 --- a/contracts/src/v0.8/vendor/entrypoint/utils/Exec.sol +++ /dev/null @@ -1,70 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.7.5 <0.9.0; - -// solhint-disable no-inline-assembly - -/** - * Utility functions helpful when making different kinds of contract calls in Solidity. - */ -library Exec { - - function call( - address to, - uint256 value, - bytes memory data, - uint256 txGas - ) internal returns (bool success) { - assembly { - success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0) - } - } - - function staticcall( - address to, - bytes memory data, - uint256 txGas - ) internal view returns (bool success) { - assembly { - success := staticcall(txGas, to, add(data, 0x20), mload(data), 0, 0) - } - } - - function delegateCall( - address to, - bytes memory data, - uint256 txGas - ) internal returns (bool success) { - assembly { - success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0) - } - } - - // get returned data from last call or calldelegate - function getReturnData(uint256 maxLen) internal pure returns (bytes memory returnData) { - assembly { - let len := returndatasize() - if gt(len, maxLen) { - len := maxLen - } - let ptr := mload(0x40) - mstore(0x40, add(ptr, add(len, 0x20))) - mstore(ptr, len) - returndatacopy(add(ptr, 0x20), 0, len) - returnData := ptr - } - } - - // revert with explicit byte array (probably reverted info from call) - function revertWithData(bytes memory returnData) internal pure { - assembly { - revert(add(returnData, 32), mload(returnData)) - } - } - - function callAndRevert(address to, bytes memory data, uint256 maxLen) internal { - bool success = call(to,0,data,gasleft()); - if (!success) { - revertWithData(getReturnData(maxLen)); - } - } -} diff --git a/contracts/src/v0.8/vrf/BatchBlockhashStore.sol b/contracts/src/v0.8/vrf/BatchBlockhashStore.sol index cf29f148a54..4ed6f28d381 100644 --- a/contracts/src/v0.8/vrf/BatchBlockhashStore.sol +++ b/contracts/src/v0.8/vrf/BatchBlockhashStore.sol @@ -2,7 +2,7 @@ // solhint-disable-next-line one-contract-per-file pragma solidity 0.8.19; -import {ChainSpecificUtil} from "../ChainSpecificUtil.sol"; +import {ChainSpecificUtil} from "../shared/util/ChainSpecificUtil.sol"; /** * @title BatchBlockhashStore diff --git a/contracts/src/v0.8/ChainSpecificUtil_v0_8_6.sol b/contracts/src/v0.8/vrf/ChainSpecificUtil_v0_8_6.sol similarity index 96% rename from contracts/src/v0.8/ChainSpecificUtil_v0_8_6.sol rename to contracts/src/v0.8/vrf/ChainSpecificUtil_v0_8_6.sol index 0379dc86ca0..eabc061e3f5 100644 --- a/contracts/src/v0.8/ChainSpecificUtil_v0_8_6.sol +++ b/contracts/src/v0.8/vrf/ChainSpecificUtil_v0_8_6.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.6; -import {ArbSys} from "./vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; -import {ArbGasInfo} from "./vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; -import {OVM_GasPriceOracle} from "./vendor/@eth-optimism/contracts/v0.8.6/contracts/L2/predeploys/OVM_GasPriceOracle.sol"; +import {ArbSys} from "../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; +import {ArbGasInfo} from "../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; +import {OVM_GasPriceOracle} from "../vendor/@eth-optimism/contracts/v0.8.6/contracts/L2/predeploys/OVM_GasPriceOracle.sol"; /// @dev A library that abstracts out opcodes that behave differently across chains. /// @dev The methods below return values that are pertinent to the given chain. diff --git a/contracts/src/v0.8/vrf/VRFCoordinatorV2.sol b/contracts/src/v0.8/vrf/VRFCoordinatorV2.sol index 717826a3b95..ab0eecd6c45 100644 --- a/contracts/src/v0.8/vrf/VRFCoordinatorV2.sol +++ b/contracts/src/v0.8/vrf/VRFCoordinatorV2.sol @@ -5,13 +5,13 @@ import {LinkTokenInterface} from "../shared/interfaces/LinkTokenInterface.sol"; import {BlockhashStoreInterface} from "./interfaces/BlockhashStoreInterface.sol"; import {AggregatorV3Interface} from "../shared/interfaces/AggregatorV3Interface.sol"; import {VRFCoordinatorV2Interface} from "./interfaces/VRFCoordinatorV2Interface.sol"; -import {TypeAndVersionInterface} from "../interfaces/TypeAndVersionInterface.sol"; +import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; import {IERC677Receiver} from "../shared/interfaces/IERC677Receiver.sol"; import {VRF} from "./VRF.sol"; import {ConfirmedOwner} from "../shared/access/ConfirmedOwner.sol"; import {VRFConsumerBaseV2} from "./VRFConsumerBaseV2.sol"; -import {ChainSpecificUtil} from "../ChainSpecificUtil_v0_8_6.sol"; -contract VRFCoordinatorV2 is VRF, ConfirmedOwner, TypeAndVersionInterface, VRFCoordinatorV2Interface, IERC677Receiver { +import {ChainSpecificUtil} from "./ChainSpecificUtil_v0_8_6.sol"; +contract VRFCoordinatorV2 is VRF, ConfirmedOwner, ITypeAndVersion, VRFCoordinatorV2Interface, IERC677Receiver { // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i LinkTokenInterface public immutable LINK; // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i diff --git a/contracts/src/v0.8/vrf/VRFV2Wrapper.sol b/contracts/src/v0.8/vrf/VRFV2Wrapper.sol index a656ef071f1..584136e3beb 100644 --- a/contracts/src/v0.8/vrf/VRFV2Wrapper.sol +++ b/contracts/src/v0.8/vrf/VRFV2Wrapper.sol @@ -3,20 +3,20 @@ pragma solidity ^0.8.6; import {ConfirmedOwner} from "../shared/access/ConfirmedOwner.sol"; -import {TypeAndVersionInterface} from "../interfaces/TypeAndVersionInterface.sol"; +import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; import {VRFConsumerBaseV2} from "./VRFConsumerBaseV2.sol"; import {LinkTokenInterface} from "../shared/interfaces/LinkTokenInterface.sol"; import {AggregatorV3Interface} from "../shared/interfaces/AggregatorV3Interface.sol"; import {VRFCoordinatorV2Interface} from "./interfaces/VRFCoordinatorV2Interface.sol"; import {VRFV2WrapperInterface} from "./interfaces/VRFV2WrapperInterface.sol"; import {VRFV2WrapperConsumerBase} from "./VRFV2WrapperConsumerBase.sol"; -import {ChainSpecificUtil} from "../ChainSpecificUtil_v0_8_6.sol"; +import {ChainSpecificUtil} from "./ChainSpecificUtil_v0_8_6.sol"; /** * @notice A wrapper for VRFCoordinatorV2 that provides an interface better suited to one-off * @notice requests for randomness. */ -contract VRFV2Wrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsumerBaseV2, VRFV2WrapperInterface { +contract VRFV2Wrapper is ConfirmedOwner, ITypeAndVersion, VRFConsumerBaseV2, VRFV2WrapperInterface { event WrapperFulfillmentFailed(uint256 indexed requestId, address indexed consumer); // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i diff --git a/contracts/src/v0.8/vrf/dev/BlockhashStore.sol b/contracts/src/v0.8/vrf/dev/BlockhashStore.sol index 0bef7aeada5..8889060922b 100644 --- a/contracts/src/v0.8/vrf/dev/BlockhashStore.sol +++ b/contracts/src/v0.8/vrf/dev/BlockhashStore.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.19; -import {ChainSpecificUtil} from "../../ChainSpecificUtil.sol"; +import {ChainSpecificUtil} from "../../shared/util/ChainSpecificUtil.sol"; /** * @title BlockhashStore diff --git a/contracts/src/v0.8/vrf/dev/TrustedBlockhashStore.sol b/contracts/src/v0.8/vrf/dev/TrustedBlockhashStore.sol index b3b77c8095d..b6a770168e5 100644 --- a/contracts/src/v0.8/vrf/dev/TrustedBlockhashStore.sol +++ b/contracts/src/v0.8/vrf/dev/TrustedBlockhashStore.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.19; -import {ChainSpecificUtil} from "../../ChainSpecificUtil.sol"; +import {ChainSpecificUtil} from "../../shared/util/ChainSpecificUtil.sol"; import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; import {BlockhashStore} from "./BlockhashStore.sol"; diff --git a/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol b/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol index 40fd8a90612..fced5822642 100644 --- a/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol +++ b/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.19; import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {VRFConsumerBaseV2Plus} from "./VRFConsumerBaseV2Plus.sol"; import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol"; @@ -15,7 +15,7 @@ import {VRFV2PlusWrapperConsumerBase} from "./VRFV2PlusWrapperConsumerBase.sol"; * @notice requests for randomness. */ // solhint-disable-next-line max-states-count -contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsumerBaseV2Plus, IVRFV2PlusWrapper { +contract VRFV2PlusWrapper is ConfirmedOwner, ITypeAndVersion, VRFConsumerBaseV2Plus, IVRFV2PlusWrapper { event WrapperFulfillmentFailed(uint256 indexed requestId, address indexed consumer); // upper bound limit for premium percentages to make sure fee calculations don't overflow diff --git a/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorTestV2_5.sol b/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorTestV2_5.sol index 2e9c4a2da75..62dfddbee8d 100644 --- a/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorTestV2_5.sol +++ b/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorTestV2_5.sol @@ -5,7 +5,7 @@ import {BlockhashStoreInterface} from "../../interfaces/BlockhashStoreInterface. import {VRFOld} from "./VRFOld.sol"; import {VRFTypes} from "../../VRFTypes.sol"; import {VRFConsumerBaseV2Plus, IVRFMigratableConsumerV2Plus} from "../VRFConsumerBaseV2Plus.sol"; -import {ChainSpecificUtil} from "../../../ChainSpecificUtil.sol"; +import {ChainSpecificUtil} from "../../../shared/util/ChainSpecificUtil.sol"; import {SubscriptionAPI} from "../SubscriptionAPI.sol"; import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; import {IVRFCoordinatorV2PlusMigration} from "../interfaces/IVRFCoordinatorV2PlusMigration.sol"; diff --git a/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorV2PlusUpgradedVersion.sol b/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorV2PlusUpgradedVersion.sol index af5c56bde6c..c16a498fcb7 100644 --- a/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorV2PlusUpgradedVersion.sol +++ b/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorV2PlusUpgradedVersion.sol @@ -7,7 +7,7 @@ import {IVRFCoordinatorV2Plus, IVRFSubscriptionV2Plus} from "../interfaces/IVRFC import {VRF} from "../../../vrf/VRF.sol"; import {VRFTypes} from "../../VRFTypes.sol"; import {VRFConsumerBaseV2Plus, IVRFMigratableConsumerV2Plus} from "../VRFConsumerBaseV2Plus.sol"; -import {ChainSpecificUtil} from "../../../ChainSpecificUtil.sol"; +import {ChainSpecificUtil} from "../../../shared/util/ChainSpecificUtil.sol"; import {SubscriptionAPI} from "../SubscriptionAPI.sol"; import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; import {IVRFCoordinatorV2PlusMigration} from "../interfaces/IVRFCoordinatorV2PlusMigration.sol"; diff --git a/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusLoadTestWithMetrics.sol b/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusLoadTestWithMetrics.sol index 87e70f60e35..f70c0331cd1 100644 --- a/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusLoadTestWithMetrics.sol +++ b/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusLoadTestWithMetrics.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {ChainSpecificUtil} from "../../../ChainSpecificUtil.sol"; +import {ChainSpecificUtil} from "../../../shared/util/ChainSpecificUtil.sol"; import {VRFConsumerBaseV2Plus} from "../VRFConsumerBaseV2Plus.sol"; import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; diff --git a/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusWrapperLoadTestConsumer.sol b/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusWrapperLoadTestConsumer.sol index 6935723d931..ae76fed365a 100644 --- a/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusWrapperLoadTestConsumer.sol +++ b/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusWrapperLoadTestConsumer.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.6; import {VRFV2PlusWrapperConsumerBase} from "../VRFV2PlusWrapperConsumerBase.sol"; import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; -import {ChainSpecificUtil} from "../../../ChainSpecificUtil.sol"; +import {ChainSpecificUtil} from "../../../shared/util/ChainSpecificUtil.sol"; import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; contract VRFV2PlusWrapperLoadTestConsumer is VRFV2PlusWrapperConsumerBase, ConfirmedOwner { diff --git a/contracts/src/v0.8/vrf/test/ChainSpecificUtil.t.sol b/contracts/src/v0.8/vrf/test/ChainSpecificUtil.t.sol index efeb9027462..3e81dd2d3c9 100644 --- a/contracts/src/v0.8/vrf/test/ChainSpecificUtil.t.sol +++ b/contracts/src/v0.8/vrf/test/ChainSpecificUtil.t.sol @@ -1,7 +1,7 @@ pragma solidity 0.8.6; import "./BaseTest.t.sol"; -import {ChainSpecificUtil} from "../../ChainSpecificUtil_v0_8_6.sol"; +import {ChainSpecificUtil} from "../ChainSpecificUtil_v0_8_6.sol"; import {ArbSys} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; import {ArbGasInfo} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; diff --git a/contracts/src/v0.8/vrf/test/FixtureVRFCoordinatorV2_5.t.sol b/contracts/src/v0.8/vrf/test/FixtureVRFCoordinatorV2_5.t.sol index c1c2c7eb27c..3574143f6c5 100644 --- a/contracts/src/v0.8/vrf/test/FixtureVRFCoordinatorV2_5.t.sol +++ b/contracts/src/v0.8/vrf/test/FixtureVRFCoordinatorV2_5.t.sol @@ -8,8 +8,8 @@ import {BlockhashStore} from "../dev/BlockhashStore.sol"; import {VRFV2PlusClient} from "../dev/libraries/VRFV2PlusClient.sol"; import {ExposedVRFCoordinatorV2_5} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5.sol"; import {VRFV2PlusConsumerExample} from "../dev/testhelpers/VRFV2PlusConsumerExample.sol"; -import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; -import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; +import {MockLinkToken} from "../../functions/tests/v1_X/testhelpers/MockLinkToken.sol"; +import {MockV3Aggregator} from "../../shared/mocks/MockV3Aggregator.sol"; import "./BaseTest.t.sol"; contract FixtureVRFCoordinatorV2_5 is BaseTest, VRF { diff --git a/contracts/src/v0.8/vrf/test/VRFCoordinatorV2Mock.t.sol b/contracts/src/v0.8/vrf/test/VRFCoordinatorV2Mock.t.sol index 1716118b765..c0c0a2a2f52 100644 --- a/contracts/src/v0.8/vrf/test/VRFCoordinatorV2Mock.t.sol +++ b/contracts/src/v0.8/vrf/test/VRFCoordinatorV2Mock.t.sol @@ -2,8 +2,8 @@ pragma solidity 0.8.6; import "./BaseTest.t.sol"; import {VRF} from "../VRF.sol"; -import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; -import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; +import {MockLinkToken} from "../../functions/tests/v1_X/testhelpers/MockLinkToken.sol"; +import {MockV3Aggregator} from "../../shared/mocks/MockV3Aggregator.sol"; import {VRFCoordinatorV2Mock} from "../mocks/VRFCoordinatorV2Mock.sol"; import {VRFConsumerV2} from "../testhelpers/VRFConsumerV2.sol"; diff --git a/contracts/src/v0.8/vrf/test/VRFCoordinatorV2Plus_Migration.t.sol b/contracts/src/v0.8/vrf/test/VRFCoordinatorV2Plus_Migration.t.sol index ad239592d41..2d12f5ec82e 100644 --- a/contracts/src/v0.8/vrf/test/VRFCoordinatorV2Plus_Migration.t.sol +++ b/contracts/src/v0.8/vrf/test/VRFCoordinatorV2Plus_Migration.t.sol @@ -6,8 +6,8 @@ import {ExposedVRFCoordinatorV2_5} from "../dev/testhelpers/ExposedVRFCoordinato import {VRFCoordinatorV2_5} from "../dev/VRFCoordinatorV2_5.sol"; import {SubscriptionAPI} from "../dev/SubscriptionAPI.sol"; import {VRFV2PlusConsumerExample} from "../dev/testhelpers/VRFV2PlusConsumerExample.sol"; -import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; -import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; +import {MockLinkToken} from "../../functions/tests/v1_X/testhelpers/MockLinkToken.sol"; +import {MockV3Aggregator} from "../../shared/mocks/MockV3Aggregator.sol"; import {VRFV2PlusMaliciousMigrator} from "../dev/testhelpers/VRFV2PlusMaliciousMigrator.sol"; contract VRFCoordinatorV2Plus_Migration is BaseTest { diff --git a/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5Mock.t.sol b/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5Mock.t.sol index 75c763c88cb..d379ab9679d 100644 --- a/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5Mock.t.sol +++ b/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5Mock.t.sol @@ -5,7 +5,7 @@ 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"; +import {MockLinkToken} from "../../functions/tests/v1_X/testhelpers/MockLinkToken.sol"; contract VRFCoordinatorV2_5MockTest is BaseTest { MockLinkToken internal s_linkToken; diff --git a/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5_Arbitrum.t.sol b/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5_Arbitrum.t.sol index 8e47b800ee5..a6c2c88d016 100644 --- a/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5_Arbitrum.t.sol +++ b/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5_Arbitrum.t.sol @@ -1,8 +1,8 @@ pragma solidity 0.8.19; import "./BaseTest.t.sol"; -import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; -import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; +import {MockLinkToken} from "../../functions/tests/v1_X/testhelpers/MockLinkToken.sol"; +import {MockV3Aggregator} from "../../shared/mocks/MockV3Aggregator.sol"; import {ExposedVRFCoordinatorV2_5_Arbitrum} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5_Arbitrum.sol"; import {BlockhashStore} from "../dev/BlockhashStore.sol"; import {ArbGasInfo} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; diff --git a/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5_Optimism.t.sol b/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5_Optimism.t.sol index b54dbbaaa04..0ebec3b1c56 100644 --- a/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5_Optimism.t.sol +++ b/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5_Optimism.t.sol @@ -1,8 +1,8 @@ pragma solidity 0.8.19; import "./BaseTest.t.sol"; -import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; -import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; +import {MockLinkToken} from "../../functions/tests/v1_X/testhelpers/MockLinkToken.sol"; +import {MockV3Aggregator} from "../../shared/mocks/MockV3Aggregator.sol"; import {ExposedVRFCoordinatorV2_5_Optimism} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5_Optimism.sol"; import {OptimismL1Fees} from "../dev/OptimismL1Fees.sol"; import {BlockhashStore} from "../dev/BlockhashStore.sol"; diff --git a/contracts/src/v0.8/vrf/test/VRFV2Plus.t.sol b/contracts/src/v0.8/vrf/test/VRFV2Plus.t.sol index dd3f54b580a..5d8366b5c7f 100644 --- a/contracts/src/v0.8/vrf/test/VRFV2Plus.t.sol +++ b/contracts/src/v0.8/vrf/test/VRFV2Plus.t.sol @@ -2,8 +2,8 @@ pragma solidity 0.8.19; import "./BaseTest.t.sol"; import {VRF} from "../VRF.sol"; -import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; -import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; +import {MockLinkToken} from "../../functions/tests/v1_X/testhelpers/MockLinkToken.sol"; +import {MockV3Aggregator} from "../../shared/mocks/MockV3Aggregator.sol"; import {ExposedVRFCoordinatorV2_5} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5.sol"; import {VRFCoordinatorV2_5} from "../dev/VRFCoordinatorV2_5.sol"; import {SubscriptionAPI} from "../dev/SubscriptionAPI.sol"; diff --git a/contracts/src/v0.8/vrf/test/VRFV2PlusSubscriptionAPI.t.sol b/contracts/src/v0.8/vrf/test/VRFV2PlusSubscriptionAPI.t.sol index 4fbb44ea717..4e89c0ec5f7 100644 --- a/contracts/src/v0.8/vrf/test/VRFV2PlusSubscriptionAPI.t.sol +++ b/contracts/src/v0.8/vrf/test/VRFV2PlusSubscriptionAPI.t.sol @@ -4,8 +4,8 @@ import "./BaseTest.t.sol"; import {ExposedVRFCoordinatorV2_5} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5.sol"; import {VRFV2PlusLoadTestWithMetrics} from "../dev/testhelpers/VRFV2PlusLoadTestWithMetrics.sol"; import {SubscriptionAPI} from "../dev/SubscriptionAPI.sol"; -import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; -import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; +import {MockLinkToken} from "../../functions/tests/v1_X/testhelpers/MockLinkToken.sol"; +import {MockV3Aggregator} from "../../shared/mocks/MockV3Aggregator.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; // for Strings.toString import {VmSafe} from "forge-std/Vm.sol"; diff --git a/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper.t.sol b/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper.t.sol index 4b3a893fe1f..45e2131ce7a 100644 --- a/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper.t.sol +++ b/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper.t.sol @@ -2,8 +2,8 @@ pragma solidity 0.8.19; import {BaseTest} from "./BaseTest.t.sol"; -import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; -import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; +import {MockLinkToken} from "../../functions/tests/v1_X/testhelpers/MockLinkToken.sol"; +import {MockV3Aggregator} from "../../shared/mocks/MockV3Aggregator.sol"; import {ExposedVRFCoordinatorV2_5} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5.sol"; import {SubscriptionAPI} from "../dev/SubscriptionAPI.sol"; import {VRFV2PlusWrapperConsumerExample} from "../dev/testhelpers/VRFV2PlusWrapperConsumerExample.sol"; diff --git a/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Arbitrum.t.sol b/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Arbitrum.t.sol index 96f14847c41..f88dd15f2d5 100644 --- a/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Arbitrum.t.sol +++ b/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Arbitrum.t.sol @@ -2,8 +2,8 @@ pragma solidity 0.8.19; import {BaseTest} from "./BaseTest.t.sol"; -import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; -import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; +import {MockLinkToken} from "../../functions/tests/v1_X/testhelpers/MockLinkToken.sol"; +import {MockV3Aggregator} from "../../shared/mocks/MockV3Aggregator.sol"; import {ExposedVRFCoordinatorV2_5_Arbitrum} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5_Arbitrum.sol"; import {VRFV2PlusWrapper_Arbitrum} from "../dev/VRFV2PlusWrapper_Arbitrum.sol"; import {ArbGasInfo} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; diff --git a/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Migration.t.sol b/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Migration.t.sol index ba77686088e..26cc5a213ec 100644 --- a/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Migration.t.sol +++ b/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Migration.t.sol @@ -2,8 +2,8 @@ pragma solidity 0.8.19; import {BaseTest} from "./BaseTest.t.sol"; -import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; -import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; +import {MockLinkToken} from "../../functions/tests/v1_X/testhelpers/MockLinkToken.sol"; +import {MockV3Aggregator} from "../../shared/mocks/MockV3Aggregator.sol"; import {ExposedVRFCoordinatorV2_5} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5.sol"; import {VRFCoordinatorV2Plus_V2Example} from "../dev/testhelpers/VRFCoordinatorV2Plus_V2Example.sol"; import {VRFV2PlusWrapperConsumerExample} from "../dev/testhelpers/VRFV2PlusWrapperConsumerExample.sol"; diff --git a/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Optimism.t.sol b/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Optimism.t.sol index a8a97a57f0e..de56a9a7e2b 100644 --- a/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Optimism.t.sol +++ b/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Optimism.t.sol @@ -2,8 +2,8 @@ pragma solidity 0.8.19; import {BaseTest} from "./BaseTest.t.sol"; -import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; -import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; +import {MockLinkToken} from "../../functions/tests/v1_X/testhelpers/MockLinkToken.sol"; +import {MockV3Aggregator} from "../../shared/mocks/MockV3Aggregator.sol"; import {ExposedVRFCoordinatorV2_5_Optimism} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5_Optimism.sol"; import {VRFV2PlusWrapper_Optimism} from "../dev/VRFV2PlusWrapper_Optimism.sol"; import {OptimismL1Fees} from "../dev/OptimismL1Fees.sol"; diff --git a/contracts/src/v0.8/vrf/testhelpers/ChainSpecificUtilHelper.sol b/contracts/src/v0.8/vrf/testhelpers/ChainSpecificUtilHelper.sol index 16a157e3547..96a088a652e 100644 --- a/contracts/src/v0.8/vrf/testhelpers/ChainSpecificUtilHelper.sol +++ b/contracts/src/v0.8/vrf/testhelpers/ChainSpecificUtilHelper.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {ChainSpecificUtil} from "../../ChainSpecificUtil_v0_8_6.sol"; +import {ChainSpecificUtil} from "../ChainSpecificUtil_v0_8_6.sol"; /// @dev A helper contract that exposes ChainSpecificUtil methods for testing contract ChainSpecificUtilHelper { diff --git a/contracts/src/v0.8/vrf/testhelpers/VRFCoordinatorTestV2.sol b/contracts/src/v0.8/vrf/testhelpers/VRFCoordinatorTestV2.sol index 5774b770750..5c42a4070dc 100644 --- a/contracts/src/v0.8/vrf/testhelpers/VRFCoordinatorTestV2.sol +++ b/contracts/src/v0.8/vrf/testhelpers/VRFCoordinatorTestV2.sol @@ -5,19 +5,13 @@ import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol import {BlockhashStoreInterface} from "../interfaces/BlockhashStoreInterface.sol"; import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol"; import {VRFCoordinatorV2Interface} from "../interfaces/VRFCoordinatorV2Interface.sol"; -import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IERC677Receiver} from "../../shared/interfaces/IERC677Receiver.sol"; import {VRF} from "../VRF.sol"; import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; import {VRFConsumerBaseV2} from "../VRFConsumerBaseV2.sol"; -contract VRFCoordinatorTestV2 is - VRF, - ConfirmedOwner, - TypeAndVersionInterface, - VRFCoordinatorV2Interface, - IERC677Receiver -{ +contract VRFCoordinatorTestV2 is VRF, ConfirmedOwner, ITypeAndVersion, VRFCoordinatorV2Interface, IERC677Receiver { LinkTokenInterface public immutable LINK; AggregatorV3Interface public immutable LINK_ETH_FEED; BlockhashStoreInterface public immutable BLOCKHASH_STORE; diff --git a/contracts/src/v0.8/vrf/testhelpers/VRFV2LoadTestWithMetrics.sol b/contracts/src/v0.8/vrf/testhelpers/VRFV2LoadTestWithMetrics.sol index b4d0104acee..3e9e7bfc47a 100644 --- a/contracts/src/v0.8/vrf/testhelpers/VRFV2LoadTestWithMetrics.sol +++ b/contracts/src/v0.8/vrf/testhelpers/VRFV2LoadTestWithMetrics.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; import {VRFCoordinatorV2Interface} from "../interfaces/VRFCoordinatorV2Interface.sol"; import {VRFConsumerBaseV2} from "../VRFConsumerBaseV2.sol"; -import {ChainSpecificUtil} from "../../ChainSpecificUtil_v0_8_6.sol"; +import {ChainSpecificUtil} from "../ChainSpecificUtil_v0_8_6.sol"; import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; /** diff --git a/contracts/src/v0.8/vrf/testhelpers/VRFV2OwnerTestConsumer.sol b/contracts/src/v0.8/vrf/testhelpers/VRFV2OwnerTestConsumer.sol index 8f1b275397c..c0c1c659fe1 100644 --- a/contracts/src/v0.8/vrf/testhelpers/VRFV2OwnerTestConsumer.sol +++ b/contracts/src/v0.8/vrf/testhelpers/VRFV2OwnerTestConsumer.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; import {VRFCoordinatorV2Interface} from "../interfaces/VRFCoordinatorV2Interface.sol"; import {VRFConsumerBaseV2} from "../VRFConsumerBaseV2.sol"; import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {ChainSpecificUtil} from "../../ChainSpecificUtil_v0_8_6.sol"; +import {ChainSpecificUtil} from "../ChainSpecificUtil_v0_8_6.sol"; import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; contract VRFV2OwnerTestConsumer is VRFConsumerBaseV2, ConfirmedOwner { diff --git a/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperLoadTestConsumer.sol b/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperLoadTestConsumer.sol index 3da8f17469a..9501a74b220 100644 --- a/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperLoadTestConsumer.sol +++ b/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperLoadTestConsumer.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.6; import {VRFV2WrapperConsumerBase} from "../VRFV2WrapperConsumerBase.sol"; import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {ChainSpecificUtil} from "../../ChainSpecificUtil_v0_8_6.sol"; +import {ChainSpecificUtil} from "../ChainSpecificUtil_v0_8_6.sol"; import {VRFV2WrapperInterface} from "../interfaces/VRFV2WrapperInterface.sol"; contract VRFV2WrapperLoadTestConsumer is VRFV2WrapperConsumerBase, ConfirmedOwner { diff --git a/contracts/src/v0.8/workflow/dev/WorkflowRegistry.sol b/contracts/src/v0.8/workflow/dev/WorkflowRegistry.sol index 2454374b2fb..2a5f797d3c8 100644 --- a/contracts/src/v0.8/workflow/dev/WorkflowRegistry.sol +++ b/contracts/src/v0.8/workflow/dev/WorkflowRegistry.sol @@ -89,6 +89,7 @@ contract WorkflowRegistry is Ownable2StepMsgSender, ITypeAndVersion { event RegistryUnlockedV1(address unlockedBy); error AddressNotAuthorized(address caller); + error BinaryURLRequired(); error CallerIsNotWorkflowOwner(address caller); error DONNotAllowed(uint32 donID); error InvalidWorkflowID(); @@ -99,7 +100,7 @@ contract WorkflowRegistry is Ownable2StepMsgSender, ITypeAndVersion { error WorkflowContentNotUpdated(); error WorkflowDoesNotExist(); error WorkflowIDAlreadyExists(); - error WorkflowIDNotUpdated(); + error WorkflowNameRequired(); error WorkflowNameTooLong(uint256 providedLength, uint8 maxAllowedLength); modifier registryNotLocked() { @@ -119,10 +120,12 @@ contract WorkflowRegistry is Ownable2StepMsgSender, ITypeAndVersion { /// @param allowed True if they should be added to the allowlist, false to remove them. function updateAllowedDONs(uint32[] calldata donIDs, bool allowed) external onlyOwner registryNotLocked { uint256 length = donIDs.length; - for (uint256 i = 0; i < length; ++i) { - if (allowed) { + if (allowed) { + for (uint256 i = 0; i < length; ++i) { s_allowedDONs.add(donIDs[i]); - } else { + } + } else { + for (uint256 i = 0; i < length; ++i) { s_allowedDONs.remove(donIDs[i]); } } @@ -136,10 +139,12 @@ contract WorkflowRegistry is Ownable2StepMsgSender, ITypeAndVersion { /// @param allowed True if they should be added to whitelist, false to remove them. function updateAuthorizedAddresses(address[] calldata addresses, bool allowed) external onlyOwner registryNotLocked { uint256 length = addresses.length; - for (uint256 i = 0; i < length; ++i) { - if (allowed) { + if (allowed) { + for (uint256 i = 0; i < length; ++i) { s_authorizedAddresses.add(addresses[i]); - } else { + } + } else { + for (uint256 i = 0; i < length; ++i) { s_authorizedAddresses.remove(addresses[i]); } } @@ -286,11 +291,6 @@ contract WorkflowRegistry is Ownable2StepMsgSender, ITypeAndVersion { // Store the old workflowID for event emission. bytes32 currentWorkflowID = workflow.workflowID; - // Condition to revert: WorkflowID must change, and at least one URL must change - if (currentWorkflowID == newWorkflowID) { - revert WorkflowIDNotUpdated(); - } - // Determine which URLs have changed bool sameBinaryURL = Strings.equal(workflow.binaryURL, binaryURL); bool sameConfigURL = Strings.equal(workflow.configURL, configURL); @@ -489,20 +489,16 @@ contract WorkflowRegistry is Ownable2StepMsgSender, ITypeAndVersion { revert WorkflowAlreadyInDesiredStatus(); } - // Check if the DON ID is allowed when activating a workflow + // Emit the appropriate event based on newStatus if (newStatus == WorkflowStatus.ACTIVE) { _validatePermissions(donID, msg.sender); + emit WorkflowActivatedV1(workflow.workflowID, msg.sender, donID, workflow.workflowName); + } else if (newStatus == WorkflowStatus.PAUSED) { + emit WorkflowPausedV1(workflow.workflowID, msg.sender, donID, workflow.workflowName); } // Update the workflow status workflow.status = newStatus; - - // Emit the appropriate event based on newStatus - if (newStatus == WorkflowStatus.PAUSED) { - emit WorkflowPausedV1(workflow.workflowID, msg.sender, donID, workflow.workflowName); - } else if (newStatus == WorkflowStatus.ACTIVE) { - emit WorkflowActivatedV1(workflow.workflowID, msg.sender, donID, workflow.workflowName); - } } /// @dev Internal function to retrieve a workflow from storage. @@ -669,6 +665,10 @@ contract WorkflowRegistry is Ownable2StepMsgSender, ITypeAndVersion { uint256 configURLLength, uint256 secretsURLLength ) internal pure { + if (binaryURLLength == 0) { + revert BinaryURLRequired(); + } + if (binaryURLLength > MAX_URL_LENGTH) { revert URLTooLong(binaryURLLength, MAX_URL_LENGTH); } @@ -688,6 +688,10 @@ contract WorkflowRegistry is Ownable2StepMsgSender, ITypeAndVersion { function _validateWorkflowName( uint256 workflowNameLength ) internal pure { + if (workflowNameLength == 0) { + revert WorkflowNameRequired(); + } + if (workflowNameLength > MAX_WORKFLOW_NAME_LENGTH) { revert WorkflowNameTooLong(workflowNameLength, MAX_WORKFLOW_NAME_LENGTH); } diff --git a/contracts/src/v0.8/workflow/dev/WorkflowRegistryManager.sol b/contracts/src/v0.8/workflow/dev/WorkflowRegistryManager.sol index 818d4a1a8ae..cf55aaeffb8 100644 --- a/contracts/src/v0.8/workflow/dev/WorkflowRegistryManager.sol +++ b/contracts/src/v0.8/workflow/dev/WorkflowRegistryManager.sol @@ -39,12 +39,13 @@ contract WorkflowRegistryManager is Ownable2StepMsgSender, ITypeAndVersion { uint32 private s_latestVersionNumber = 0; // Errors + error ContractAlreadyRegistered(address contractAddress, uint64 chainID); error InvalidContractAddress(address invalidAddress); error InvalidContractType(address invalidAddress); error NoActiveVersionAvailable(); error NoVersionsRegistered(); - error VersionNotRegistered(uint32 versionNumber); error VersionAlreadyActive(uint32 versionNumber); + error VersionNotRegistered(uint32 versionNumber); // Events event VersionAdded(address indexed contractAddress, uint64 chainID, uint32 deployedAt, uint32 version); @@ -63,6 +64,12 @@ contract WorkflowRegistryManager is Ownable2StepMsgSender, ITypeAndVersion { /// @param autoActivate A boolean indicating whether the new version should be activated immediately. /// @custom:throws InvalidContractType if the provided contract address is zero or not a WorkflowRegistry. function addVersion(address contractAddress, uint64 chainID, uint32 deployedAt, bool autoActivate) external onlyOwner { + // Check if the contract is already registered. If it is, you can just activate that existing version. + bytes32 key = keccak256(abi.encodePacked(contractAddress, chainID)); + if (s_versionNumberByAddressAndChainID[key] != 0) { + revert ContractAlreadyRegistered(contractAddress, chainID); + } + string memory typeVer = _getTypeAndVersionForContract(contractAddress); uint32 latestVersionNumber = ++s_latestVersionNumber; @@ -74,7 +81,6 @@ contract WorkflowRegistryManager is Ownable2StepMsgSender, ITypeAndVersion { }); // Store the version number associated with the hash of contract address and chainID - bytes32 key = keccak256(abi.encodePacked(contractAddress, chainID)); s_versionNumberByAddressAndChainID[key] = latestVersionNumber; if (autoActivate) { diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.registerWorkflow.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.registerWorkflow.t.sol index 859437196cd..c44c28520a4 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.registerWorkflow.t.sol +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.registerWorkflow.t.sol @@ -55,6 +55,22 @@ contract WorkflowRegistry_registerWorkflow is WorkflowRegistrySetup { ); } + // whenTheCallerIsAnAuthorizedAddress whenTheRegistryIsNotLocked whenTheDonIDIsAllowed + function test_RevertWhen_TheWorkflowNameIsEmpty() external { + vm.prank(s_authorizedAddress); + + vm.expectRevert(WorkflowRegistry.WorkflowNameRequired.selector); + s_registry.registerWorkflow( + "", + s_validWorkflowID, + s_allowedDonID, + WorkflowRegistry.WorkflowStatus.ACTIVE, + s_validBinaryURL, + s_validConfigURL, + s_validSecretsURL + ); + } + // whenTheCallerIsAnAuthorizedAddress whenTheRegistryIsNotLocked whenTheDonIDIsAllowed function test_RevertWhen_TheWorkflowNameIsTooLong() external { vm.prank(s_authorizedAddress); @@ -74,6 +90,22 @@ contract WorkflowRegistry_registerWorkflow is WorkflowRegistrySetup { ); } + // whenTheCallerIsAnAuthorizedAddress whenTheRegistryIsNotLocked whenTheDonIDIsAllowed + function test_RevertWhen_TheBinaryURLIsEmpty() external { + vm.prank(s_authorizedAddress); + + vm.expectRevert(WorkflowRegistry.BinaryURLRequired.selector); + s_registry.registerWorkflow( + s_validWorkflowName, + s_validWorkflowID, + s_allowedDonID, + WorkflowRegistry.WorkflowStatus.ACTIVE, + "", + s_validConfigURL, + s_validSecretsURL + ); + } + // whenTheCallerIsAnAuthorizedAddress whenTheRegistryIsNotLocked whenTheDonIDIsAllowed function test_RevertWhen_TheBinaryURLIsTooLong() external { vm.prank(s_authorizedAddress); diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.registerWorkflow.tree b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.registerWorkflow.tree index eabbf58d464..143ee46c394 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.registerWorkflow.tree +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.registerWorkflow.tree @@ -2,14 +2,18 @@ WorkflowRegistry.registerWorkflow ├── when the caller is not an authorized address │ └── it should revert └── when the caller is an authorized address - └── when the registry is locked + ├── when the registry is locked │ └── it should revert └── when the registry is not locked - └── when the donID is not allowed + ├── when the donID is not allowed │ └── it should revert └── when the donID is allowed + ├── when the workflow name is empty + │ └── it should revert ├── when the workflow name is too long │ └── it should revert + ├── when the binaryURL is empty + │ └── it should revert ├── when the binaryURL is too long │ └── it should revert ├── when the configURL is too long diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateWorkflow.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateWorkflow.t.sol index 4082874a91e..b60d44d8df6 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateWorkflow.t.sol +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateWorkflow.t.sol @@ -83,29 +83,27 @@ contract WorkflowRegistry_updateWorkflow is WorkflowRegistrySetup { } // whenTheCallerIsAnAuthorizedAddress whenTheRegistryIsNotLocked whenTheDonIDIsAllowed whenTheCallerIsTheWorkflowOwner - function test_RevertWhen_TheNewWorkflowIDIsTheSameAsTheExistingWorkflowID() external { + function test_RevertWhen_NoneOfTheURLsAreUpdated() external { // Register a workflow first _registerValidWorkflow(); - // Update the workflow now with the same workflow ID + // Update the workflow with no changes to any URLs vm.prank(s_authorizedAddress); - vm.expectRevert(WorkflowRegistry.WorkflowIDNotUpdated.selector); + vm.expectRevert(WorkflowRegistry.WorkflowContentNotUpdated.selector); s_registry.updateWorkflow( - s_validWorkflowKey, s_validWorkflowID, s_validBinaryURL, s_validConfigURL, s_newValidSecretsURL + s_validWorkflowKey, s_newValidWorkflowID, s_validBinaryURL, s_validConfigURL, s_validSecretsURL ); } // whenTheCallerIsAnAuthorizedAddress whenTheRegistryIsNotLocked whenTheDonIDIsAllowed whenTheCallerIsTheWorkflowOwner - function test_RevertWhen_NoneOfTheURLsAreUpdated() external { + function test_RevertWhen_TheBinaryURLIsEmpty() external { // Register a workflow first _registerValidWorkflow(); - // Update the workflow with no changes to any URLs + // Update the workflow with a binary URL that is empty vm.prank(s_authorizedAddress); - vm.expectRevert(WorkflowRegistry.WorkflowContentNotUpdated.selector); - s_registry.updateWorkflow( - s_validWorkflowKey, s_newValidWorkflowID, s_validBinaryURL, s_validConfigURL, s_validSecretsURL - ); + vm.expectRevert(WorkflowRegistry.BinaryURLRequired.selector); + s_registry.updateWorkflow(s_validWorkflowKey, s_newValidWorkflowID, "", s_validConfigURL, s_validSecretsURL); } // whenTheCallerIsAnAuthorizedAddress whenTheRegistryIsNotLocked whenTheDonIDIsAllowed whenTheCallerIsTheWorkflowOwner diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateWorkflow.tree b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateWorkflow.tree index 9b8243a8672..5577ea8e17e 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateWorkflow.tree +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateWorkflow.tree @@ -13,10 +13,10 @@ WorkflowRegistry.updateWorkflow └── when the caller is the workflow owner ├── when an existing workflow is not found with the given workflow name │ └── it should revert - ├── when the new workflowID is the same as the existing workflowID - │ └── it should revert ├── when none of the URLs are updated │ └── it should revert + ├── when the binaryURL is empty + │ └── it should revert ├── when the binaryURL is too long │ └── it should revert ├── when the configURL is too long diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.addVersion.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.addVersion.t.sol index 218ac44eaa6..79eec6f71e5 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.addVersion.t.sol +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.addVersion.t.sol @@ -21,21 +21,29 @@ contract WorkflowRegistryManager_addVersion is WorkflowRegistryManagerSetup { // whenTheCallerIsTheOwner function test_RevertWhen_TheContractAddressIsInvalid() external { - // Deploy a random contract - MockContract mockContract = new MockContract(); + // Add a 0 address to the WorkflowRegistryManager + vm.prank(s_owner); + vm.expectRevert(abi.encodeWithSelector(WorkflowRegistryManager.InvalidContractAddress.selector, address(0))); + s_registryManager.addVersion(address(0), s_chainID, s_deployedAt, true); + } + + // whenTheCallerIsTheOwner whenTheContractAddressIsValid + function test_RevertWhen_TheContractIsAlreadyRegistered() external { + // Deploy a MockWorkflowRegistryContract contract + MockWorkflowRegistryContract mockWfrContract = new MockWorkflowRegistryContract(); // Add it to the WorkflowRegistryManager vm.prank(s_owner); - vm.expectRevert(abi.encodeWithSelector(WorkflowRegistryManager.InvalidContractType.selector, address(mockContract))); - s_registryManager.addVersion(address(mockContract), s_chainID, s_deployedAt, true); - } + s_registryManager.addVersion(address(mockWfrContract), s_chainID, s_deployedAt, true); - // whenTheCallerIsTheOwner - function test_RevertWhen_TheContractAddressIsValid() external { - // Add a 0 address to the WorkflowRegistryManager + // Try to add it again vm.prank(s_owner); - vm.expectRevert(abi.encodeWithSelector(WorkflowRegistryManager.InvalidContractAddress.selector, address(0))); - s_registryManager.addVersion(address(0), s_chainID, s_deployedAt, true); + vm.expectRevert( + abi.encodeWithSelector( + WorkflowRegistryManager.ContractAlreadyRegistered.selector, address(mockWfrContract), s_chainID + ) + ); + s_registryManager.addVersion(address(mockWfrContract), s_chainID, s_deployedAt, true); } // whenTheCallerIsTheOwner whenTheContractAddressIsValid diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.addVersion.tree b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.addVersion.tree index 5e1c22b7840..60ccc6013d5 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.addVersion.tree +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.addVersion.tree @@ -5,7 +5,9 @@ WorkflowRegistryManager.addVersion ├── when the contract address is invalid │ └── it should revert └── when the contract address is valid - ├── when the contract type is invalid + ├── when the contract is already registered + │ └── it should revert + └── when the contract type is invalid │ └── it should revert └── when the contract type is valid ├── when autoActivate is true diff --git a/contracts/test/v0.8/Chainlink.test.ts b/contracts/test/v0.8/Chainlink.test.ts deleted file mode 100644 index 30063ca1024..00000000000 --- a/contracts/test/v0.8/Chainlink.test.ts +++ /dev/null @@ -1,182 +0,0 @@ -import { ethers } from 'hardhat' -import { publicAbi, decodeDietCBOR, hexToBuf } from '../test-helpers/helpers' -import { assert } from 'chai' -import { Contract, ContractFactory, providers, Signer } from 'ethers' -import { Roles, getUsers } from '../test-helpers/setup' -import { makeDebug } from '../test-helpers/debug' - -const debug = makeDebug('ChainlinkTestHelper') -let concreteChainlinkFactory: ContractFactory - -let roles: Roles - -before(async () => { - roles = (await getUsers()).roles - concreteChainlinkFactory = await ethers.getContractFactory( - 'src/v0.8/tests/ChainlinkTestHelper.sol:ChainlinkTestHelper', - roles.defaultAccount, - ) -}) - -describe('ChainlinkTestHelper', () => { - let ccl: Contract - let defaultAccount: Signer - - beforeEach(async () => { - defaultAccount = roles.defaultAccount - ccl = await concreteChainlinkFactory.connect(defaultAccount).deploy() - }) - - it('has a limited public interface [ @skip-coverage ]', () => { - publicAbi(ccl, [ - 'add', - 'addBytes', - 'addInt', - 'addStringArray', - 'addUint', - 'closeEvent', - 'setBuffer', - ]) - }) - - async function parseCCLEvent(tx: providers.TransactionResponse) { - const receipt = await tx.wait() - const data = receipt.logs?.[0].data - const d = debug.extend('parseCCLEvent') - d('data %s', data) - return ethers.utils.defaultAbiCoder.decode(['bytes'], data ?? '') - } - - describe('#close', () => { - it('handles empty payloads', async () => { - const tx = await ccl.closeEvent() - const [payload] = await parseCCLEvent(tx) - const decoded = await decodeDietCBOR(payload) - assert.deepEqual(decoded, {}) - }) - }) - - describe('#setBuffer', () => { - it('emits the buffer', async () => { - await ccl.setBuffer('0xA161616162') - const tx = await ccl.closeEvent() - const [payload] = await parseCCLEvent(tx) - const decoded = await decodeDietCBOR(payload) - assert.deepEqual(decoded, { a: 'b' }) - }) - }) - - describe('#add', () => { - it('stores and logs keys and values', async () => { - await ccl.add('first', 'word!!') - const tx = await ccl.closeEvent() - const [payload] = await parseCCLEvent(tx) - const decoded = await decodeDietCBOR(payload) - assert.deepEqual(decoded, { first: 'word!!' }) - }) - - it('handles two entries', async () => { - await ccl.add('first', 'uno') - await ccl.add('second', 'dos') - const tx = await ccl.closeEvent() - const [payload] = await parseCCLEvent(tx) - const decoded = await decodeDietCBOR(payload) - - assert.deepEqual(decoded, { - first: 'uno', - second: 'dos', - }) - }) - }) - - describe('#addBytes', () => { - it('stores and logs keys and values', async () => { - await ccl.addBytes('first', '0xaabbccddeeff') - const tx = await ccl.closeEvent() - const [payload] = await parseCCLEvent(tx) - const decoded = await decodeDietCBOR(payload) - const expected = hexToBuf('0xaabbccddeeff') - assert.deepEqual(decoded, { first: expected }) - }) - - it('handles two entries', async () => { - await ccl.addBytes('first', '0x756E6F') - await ccl.addBytes('second', '0x646F73') - const tx = await ccl.closeEvent() - const [payload] = await parseCCLEvent(tx) - const decoded = await decodeDietCBOR(payload) - - const expectedFirst = hexToBuf('0x756E6F') - const expectedSecond = hexToBuf('0x646F73') - assert.deepEqual(decoded, { - first: expectedFirst, - second: expectedSecond, - }) - }) - - it('handles strings', async () => { - await ccl.addBytes('first', ethers.utils.toUtf8Bytes('apple')) - const tx = await ccl.closeEvent() - const [payload] = await parseCCLEvent(tx) - const decoded = await decodeDietCBOR(payload) - const expected = ethers.utils.toUtf8Bytes('apple') - assert.deepEqual(decoded, { first: expected }) - }) - }) - - describe('#addInt', () => { - it('stores and logs keys and values', async () => { - await ccl.addInt('first', 1) - const tx = await ccl.closeEvent() - const [payload] = await parseCCLEvent(tx) - const decoded = await decodeDietCBOR(payload) - assert.deepEqual(decoded, { first: 1 }) - }) - - it('handles two entries', async () => { - await ccl.addInt('first', 1) - await ccl.addInt('second', 2) - const tx = await ccl.closeEvent() - const [payload] = await parseCCLEvent(tx) - const decoded = await decodeDietCBOR(payload) - - assert.deepEqual(decoded, { - first: 1, - second: 2, - }) - }) - }) - - describe('#addUint', () => { - it('stores and logs keys and values', async () => { - await ccl.addUint('first', 1) - const tx = await ccl.closeEvent() - const [payload] = await parseCCLEvent(tx) - const decoded = await decodeDietCBOR(payload) - assert.deepEqual(decoded, { first: 1 }) - }) - - it('handles two entries', async () => { - await ccl.addUint('first', 1) - await ccl.addUint('second', 2) - const tx = await ccl.closeEvent() - const [payload] = await parseCCLEvent(tx) - const decoded = await decodeDietCBOR(payload) - - assert.deepEqual(decoded, { - first: 1, - second: 2, - }) - }) - }) - - describe('#addStringArray', () => { - it('stores and logs keys and values', async () => { - await ccl.addStringArray('word', ['seinfeld', '"4"', 'LIFE']) - const tx = await ccl.closeEvent() - const [payload] = await parseCCLEvent(tx) - const decoded = await decodeDietCBOR(payload) - assert.deepEqual(decoded, { word: ['seinfeld', '"4"', 'LIFE'] }) - }) - }) -}) diff --git a/contracts/test/v0.8/ChainlinkClient.test.ts b/contracts/test/v0.8/ChainlinkClient.test.ts deleted file mode 100644 index c5691211c1a..00000000000 --- a/contracts/test/v0.8/ChainlinkClient.test.ts +++ /dev/null @@ -1,452 +0,0 @@ -import { ethers } from 'hardhat' -import { assert } from 'chai' -import { Contract, ContractFactory } from 'ethers' -import { getUsers, Roles } from '../test-helpers/setup' -import { - convertFufillParams, - decodeCCRequest, - decodeRunRequest, - RunRequest, -} from '../test-helpers/oracle' -import { decodeDietCBOR } from '../test-helpers/helpers' -import { evmRevert } from '../test-helpers/matchers' - -let concreteChainlinkClientFactory: ContractFactory -let emptyOracleFactory: ContractFactory -let getterSetterFactory: ContractFactory -let operatorFactory: ContractFactory -let linkTokenFactory: ContractFactory - -let roles: Roles - -before(async () => { - roles = (await getUsers()).roles - - concreteChainlinkClientFactory = await ethers.getContractFactory( - 'src/v0.8/tests/ChainlinkClientTestHelper.sol:ChainlinkClientTestHelper', - roles.defaultAccount, - ) - emptyOracleFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/test/testhelpers/EmptyOracle.sol:EmptyOracle', - roles.defaultAccount, - ) - getterSetterFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/test/testhelpers/GetterSetter.sol:GetterSetter', - roles.defaultAccount, - ) - operatorFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/Operator.sol:Operator', - roles.defaultAccount, - ) - linkTokenFactory = await ethers.getContractFactory( - 'src/v0.8/shared/test/helpers/LinkTokenTestHelper.sol:LinkTokenTestHelper', - roles.defaultAccount, - ) -}) - -describe('ChainlinkClientTestHelper', () => { - const specId = - '0x4c7b7ffb66b344fbaa64995af81e355a00000000000000000000000000000000' - let cc: Contract - let gs: Contract - let oc: Contract - let newoc: Contract - let link: Contract - - beforeEach(async () => { - link = await linkTokenFactory.connect(roles.defaultAccount).deploy() - oc = await operatorFactory - .connect(roles.defaultAccount) - .deploy(link.address, await roles.defaultAccount.getAddress()) - newoc = await operatorFactory - .connect(roles.defaultAccount) - .deploy(link.address, await roles.defaultAccount.getAddress()) - gs = await getterSetterFactory.connect(roles.defaultAccount).deploy() - cc = await concreteChainlinkClientFactory - .connect(roles.defaultAccount) - .deploy(link.address, oc.address) - }) - - describe('#newRequest', () => { - it('forwards the information to the oracle contract through the link token', async () => { - const tx = await cc.publicNewRequest( - specId, - gs.address, - ethers.utils.toUtf8Bytes('requestedBytes32(bytes32,bytes32)'), - ) - const receipt = await tx.wait() - - assert.equal(1, receipt.logs?.length) - const [jId, cbAddr, cbFId, cborData] = receipt.logs - ? decodeCCRequest(receipt.logs[0]) - : [] - const params = decodeDietCBOR(cborData ?? '') - - assert.equal(specId, jId) - assert.equal(gs.address, cbAddr) - assert.equal('0xed53e511', cbFId) - assert.deepEqual({}, params) - }) - }) - - describe('#chainlinkRequest(Request)', () => { - it('emits an event from the contract showing the run ID', async () => { - const tx = await cc.publicRequest( - specId, - cc.address, - ethers.utils.toUtf8Bytes('fulfillRequest(bytes32,bytes32)'), - 0, - ) - - const { events, logs } = await tx.wait() - - assert.equal(4, events?.length) - - assert.equal(logs?.[0].address, cc.address) - assert.equal(events?.[0].event, 'ChainlinkRequested') - }) - }) - - describe('#chainlinkRequestTo(Request)', () => { - it('emits an event from the contract showing the run ID', async () => { - const tx = await cc.publicRequestRunTo( - newoc.address, - specId, - cc.address, - ethers.utils.toUtf8Bytes('fulfillRequest(bytes32,bytes32)'), - 0, - ) - const { events } = await tx.wait() - - assert.equal(4, events?.length) - assert.equal(events?.[0].event, 'ChainlinkRequested') - }) - - it('emits an event on the target oracle contract', async () => { - const tx = await cc.publicRequestRunTo( - newoc.address, - specId, - cc.address, - ethers.utils.toUtf8Bytes('fulfillRequest(bytes32,bytes32)'), - 0, - ) - const { logs } = await tx.wait() - const event = logs && newoc.interface.parseLog(logs[3]) - - assert.equal(4, logs?.length) - assert.equal(event?.name, 'OracleRequest') - }) - - it('does not modify the stored oracle address', async () => { - await cc.publicRequestRunTo( - newoc.address, - specId, - cc.address, - ethers.utils.toUtf8Bytes('fulfillRequest(bytes32,bytes32)'), - 0, - ) - - const actualOracleAddress = await cc.publicOracleAddress() - assert.equal(oc.address, actualOracleAddress) - }) - }) - - describe('#requestOracleData', () => { - it('emits an event from the contract showing the run ID', async () => { - const tx = await cc.publicRequestOracleData( - specId, - ethers.utils.toUtf8Bytes('fulfillRequest(bytes32,bytes32)'), - 0, - ) - - const { events, logs } = await tx.wait() - - assert.equal(4, events?.length) - - assert.equal(logs?.[0].address, cc.address) - assert.equal(events?.[0].event, 'ChainlinkRequested') - }) - }) - - describe('#requestOracleDataFrom', () => { - it('emits an event from the contract showing the run ID', async () => { - const tx = await cc.publicRequestOracleDataFrom( - newoc.address, - specId, - ethers.utils.toUtf8Bytes('fulfillRequest(bytes32,bytes32)'), - 0, - ) - const { events } = await tx.wait() - - assert.equal(4, events?.length) - assert.equal(events?.[0].event, 'ChainlinkRequested') - }) - - it('emits an event on the target oracle contract', async () => { - const tx = await cc.publicRequestOracleDataFrom( - newoc.address, - specId, - ethers.utils.toUtf8Bytes('fulfillRequest(bytes32,bytes32)'), - 0, - ) - const { logs } = await tx.wait() - const event = logs && newoc.interface.parseLog(logs[3]) - - assert.equal(4, logs?.length) - assert.equal(event?.name, 'OracleRequest') - }) - - it('does not modify the stored oracle address', async () => { - await cc.publicRequestOracleDataFrom( - newoc.address, - specId, - ethers.utils.toUtf8Bytes('fulfillRequest(bytes32,bytes32)'), - 0, - ) - - const actualOracleAddress = await cc.publicOracleAddress() - assert.equal(oc.address, actualOracleAddress) - }) - }) - - describe('#cancelChainlinkRequest', () => { - let requestId: string - // a concrete chainlink attached to an empty oracle - let ecc: Contract - - beforeEach(async () => { - const emptyOracle = await emptyOracleFactory - .connect(roles.defaultAccount) - .deploy() - ecc = await concreteChainlinkClientFactory - .connect(roles.defaultAccount) - .deploy(link.address, emptyOracle.address) - - const tx = await ecc.publicRequest( - specId, - ecc.address, - ethers.utils.toUtf8Bytes('fulfillRequest(bytes32,bytes32)'), - 0, - ) - const { events } = await tx.wait() - requestId = (events?.[0]?.args as any).id - }) - - it('emits an event from the contract showing the run was cancelled', async () => { - const tx = await ecc.publicCancelRequest( - requestId, - 0, - ethers.utils.hexZeroPad('0x', 4), - 0, - ) - const { events } = await tx.wait() - - assert.equal(1, events?.length) - assert.equal(events?.[0].event, 'ChainlinkCancelled') - assert.equal(requestId, (events?.[0].args as any).id) - }) - - it('throws if given a bogus event ID', async () => { - await evmRevert( - ecc.publicCancelRequest( - ethers.utils.formatBytes32String('bogusId'), - 0, - ethers.utils.hexZeroPad('0x', 4), - 0, - ), - ) - }) - }) - - describe('#recordChainlinkFulfillment(modifier)', () => { - let request: RunRequest - - beforeEach(async () => { - await oc.setAuthorizedSenders([await roles.defaultAccount.getAddress()]) - const tx = await cc.publicRequest( - specId, - cc.address, - ethers.utils.toUtf8Bytes('fulfillRequest(bytes32,bytes32)'), - 0, - ) - const { logs } = await tx.wait() - - request = decodeRunRequest(logs?.[3]) - }) - - it('emits an event marking the request fulfilled', async () => { - const tx = await oc - .connect(roles.defaultAccount) - .fulfillOracleRequest( - ...convertFufillParams( - request, - ethers.utils.formatBytes32String('hi mom!'), - ), - ) - const { logs } = await tx.wait() - - const event = logs && cc.interface.parseLog(logs[1]) - - assert.equal(2, logs?.length) - assert.equal(event?.name, 'ChainlinkFulfilled') - assert.equal(request.requestId, event?.args.id) - }) - - it('should only allow one fulfillment per id', async () => { - await oc - .connect(roles.defaultAccount) - .fulfillOracleRequest( - ...convertFufillParams( - request, - ethers.utils.formatBytes32String('hi mom!'), - ), - ) - - await evmRevert( - oc - .connect(roles.defaultAccount) - .fulfillOracleRequest( - ...convertFufillParams( - request, - ethers.utils.formatBytes32String('hi mom!'), - ), - ), - 'Must have a valid requestId', - ) - }) - - it('should only allow the oracle to fulfill the request', async () => { - await evmRevert( - oc - .connect(roles.stranger) - .fulfillOracleRequest( - ...convertFufillParams( - request, - ethers.utils.formatBytes32String('hi mom!'), - ), - ), - 'Not authorized sender', - ) - }) - }) - - describe('#fulfillChainlinkRequest(function)', () => { - let request: RunRequest - - beforeEach(async () => { - await oc.setAuthorizedSenders([await roles.defaultAccount.getAddress()]) - const tx = await cc.publicRequest( - specId, - cc.address, - ethers.utils.toUtf8Bytes( - 'publicFulfillChainlinkRequest(bytes32,bytes32)', - ), - 0, - ) - const { logs } = await tx.wait() - - request = decodeRunRequest(logs?.[3]) - }) - - it('emits an event marking the request fulfilled', async () => { - await oc.setAuthorizedSenders([await roles.defaultAccount.getAddress()]) - const tx = await oc - .connect(roles.defaultAccount) - .fulfillOracleRequest( - ...convertFufillParams( - request, - ethers.utils.formatBytes32String('hi mom!'), - ), - ) - - const { logs } = await tx.wait() - const event = logs && cc.interface.parseLog(logs[1]) - - assert.equal(2, logs?.length) - assert.equal(event?.name, 'ChainlinkFulfilled') - assert.equal(request.requestId, event?.args?.id) - }) - - it('should only allow one fulfillment per id', async () => { - await oc - .connect(roles.defaultAccount) - .fulfillOracleRequest( - ...convertFufillParams( - request, - ethers.utils.formatBytes32String('hi mom!'), - ), - ) - - await evmRevert( - oc - .connect(roles.defaultAccount) - .fulfillOracleRequest( - ...convertFufillParams( - request, - ethers.utils.formatBytes32String('hi mom!'), - ), - ), - 'Must have a valid requestId', - ) - }) - - it('should only allow the oracle to fulfill the request', async () => { - await evmRevert( - oc - .connect(roles.stranger) - .fulfillOracleRequest( - ...convertFufillParams( - request, - ethers.utils.formatBytes32String('hi mom!'), - ), - ), - 'Not authorized sender', - ) - }) - }) - - describe('#chainlinkToken', () => { - it('returns the Link Token address', async () => { - const addr = await cc.publicChainlinkToken() - assert.equal(addr, link.address) - }) - }) - - describe('#addExternalRequest', () => { - let mock: Contract - let request: RunRequest - - beforeEach(async () => { - mock = await concreteChainlinkClientFactory - .connect(roles.defaultAccount) - .deploy(link.address, oc.address) - - const tx = await cc.publicRequest( - specId, - mock.address, - ethers.utils.toUtf8Bytes('fulfillRequest(bytes32,bytes32)'), - 0, - ) - const receipt = await tx.wait() - - request = decodeRunRequest(receipt.logs?.[3]) - await mock.publicAddExternalRequest(oc.address, request.requestId) - }) - - it('allows the external request to be fulfilled', async () => { - await oc.setAuthorizedSenders([await roles.defaultAccount.getAddress()]) - await oc.fulfillOracleRequest( - ...convertFufillParams( - request, - ethers.utils.formatBytes32String('hi mom!'), - ), - ) - }) - - it('does not allow the same requestId to be used', async () => { - await evmRevert( - cc.publicAddExternalRequest(newoc.address, request.requestId), - ) - }) - }) -}) diff --git a/contracts/test/v0.8/Flags.test.ts b/contracts/test/v0.8/Flags.test.ts deleted file mode 100644 index eff0912c9e1..00000000000 --- a/contracts/test/v0.8/Flags.test.ts +++ /dev/null @@ -1,405 +0,0 @@ -import { ethers } from 'hardhat' -import { publicAbi } from '../test-helpers/helpers' -import { assert, expect } from 'chai' -import { Contract, ContractFactory } from 'ethers' -import { Personas, getUsers } from '../test-helpers/setup' - -let personas: Personas - -let controllerFactory: ContractFactory -let flagsFactory: ContractFactory -let consumerFactory: ContractFactory - -let controller: Contract -let flags: Contract -let consumer: Contract - -before(async () => { - personas = (await getUsers()).personas - controllerFactory = await ethers.getContractFactory( - 'src/v0.8/shared/access/SimpleWriteAccessController.sol:SimpleWriteAccessController', - personas.Nelly, - ) - consumerFactory = await ethers.getContractFactory( - 'src/v0.8/tests/FlagsTestHelper.sol:FlagsTestHelper', - personas.Nelly, - ) - flagsFactory = await ethers.getContractFactory( - 'src/v0.8/Flags.sol:Flags', - personas.Nelly, - ) -}) - -describe('Flags', () => { - beforeEach(async () => { - controller = await controllerFactory.deploy() - flags = await flagsFactory.deploy(controller.address) - await flags.disableAccessCheck() - consumer = await consumerFactory.deploy(flags.address) - }) - - it('has a limited public interface [ @skip-coverage ]', async () => { - publicAbi(flags, [ - 'getFlag', - 'getFlags', - 'lowerFlags', - 'raiseFlag', - 'raiseFlags', - 'raisingAccessController', - 'setRaisingAccessController', - // Ownable methods: - 'acceptOwnership', - 'owner', - 'transferOwnership', - // AccessControl methods: - 'addAccess', - 'disableAccessCheck', - 'enableAccessCheck', - 'removeAccess', - 'checkEnabled', - 'hasAccess', - ]) - }) - - describe('#raiseFlag', () => { - describe('when called by the owner', () => { - it('updates the warning flag', async () => { - assert.equal(false, await flags.getFlag(consumer.address)) - - await flags.connect(personas.Nelly).raiseFlag(consumer.address) - - assert.equal(true, await flags.getFlag(consumer.address)) - }) - - it('emits an event log', async () => { - await expect(flags.connect(personas.Nelly).raiseFlag(consumer.address)) - .to.emit(flags, 'FlagRaised') - .withArgs(consumer.address) - }) - - describe('if a flag has already been raised', () => { - beforeEach(async () => { - await flags.connect(personas.Nelly).raiseFlag(consumer.address) - }) - - it('emits an event log', async () => { - const tx = await flags - .connect(personas.Nelly) - .raiseFlag(consumer.address) - const receipt = await tx.wait() - assert.equal(0, receipt.events?.length) - }) - }) - }) - - describe('when called by an enabled setter', () => { - beforeEach(async () => { - await controller - .connect(personas.Nelly) - .addAccess(await personas.Neil.getAddress()) - }) - - it('sets the flags', async () => { - await flags.connect(personas.Neil).raiseFlag(consumer.address), - assert.equal(true, await flags.getFlag(consumer.address)) - }) - }) - - describe('when called by a non-enabled setter', () => { - it('reverts', async () => { - await expect( - flags.connect(personas.Neil).raiseFlag(consumer.address), - ).to.be.revertedWith('Not allowed to raise flags') - }) - }) - - describe('when called when there is no raisingAccessController', () => { - beforeEach(async () => { - await expect( - flags - .connect(personas.Nelly) - .setRaisingAccessController( - '0x0000000000000000000000000000000000000000', - ), - ).to.emit(flags, 'RaisingAccessControllerUpdated') - assert.equal( - '0x0000000000000000000000000000000000000000', - await flags.raisingAccessController(), - ) - }) - - it('succeeds for the owner', async () => { - await flags.connect(personas.Nelly).raiseFlag(consumer.address) - assert.equal(true, await flags.getFlag(consumer.address)) - }) - - it('reverts for non-owner', async () => { - await expect(flags.connect(personas.Neil).raiseFlag(consumer.address)) - .to.be.reverted - }) - }) - }) - - describe('#raiseFlags', () => { - describe('when called by the owner', () => { - it('updates the warning flag', async () => { - assert.equal(false, await flags.getFlag(consumer.address)) - - await flags.connect(personas.Nelly).raiseFlags([consumer.address]) - - assert.equal(true, await flags.getFlag(consumer.address)) - }) - - it('emits an event log', async () => { - await expect( - flags.connect(personas.Nelly).raiseFlags([consumer.address]), - ) - .to.emit(flags, 'FlagRaised') - .withArgs(consumer.address) - }) - - describe('if a flag has already been raised', () => { - beforeEach(async () => { - await flags.connect(personas.Nelly).raiseFlags([consumer.address]) - }) - - it('emits an event log', async () => { - const tx = await flags - .connect(personas.Nelly) - .raiseFlags([consumer.address]) - const receipt = await tx.wait() - assert.equal(0, receipt.events?.length) - }) - }) - }) - - describe('when called by an enabled setter', () => { - beforeEach(async () => { - await controller - .connect(personas.Nelly) - .addAccess(await personas.Neil.getAddress()) - }) - - it('sets the flags', async () => { - await flags.connect(personas.Neil).raiseFlags([consumer.address]), - assert.equal(true, await flags.getFlag(consumer.address)) - }) - }) - - describe('when called by a non-enabled setter', () => { - it('reverts', async () => { - await expect( - flags.connect(personas.Neil).raiseFlags([consumer.address]), - ).to.be.revertedWith('Not allowed to raise flags') - }) - }) - - describe('when called when there is no raisingAccessController', () => { - beforeEach(async () => { - await expect( - flags - .connect(personas.Nelly) - .setRaisingAccessController( - '0x0000000000000000000000000000000000000000', - ), - ).to.emit(flags, 'RaisingAccessControllerUpdated') - - assert.equal( - '0x0000000000000000000000000000000000000000', - await flags.raisingAccessController(), - ) - }) - - it('succeeds for the owner', async () => { - await flags.connect(personas.Nelly).raiseFlags([consumer.address]) - assert.equal(true, await flags.getFlag(consumer.address)) - }) - - it('reverts for non-owners', async () => { - await expect( - flags.connect(personas.Neil).raiseFlags([consumer.address]), - ).to.be.reverted - }) - }) - }) - - describe('#lowerFlags', () => { - beforeEach(async () => { - await flags.connect(personas.Nelly).raiseFlags([consumer.address]) - }) - - describe('when called by the owner', () => { - it('updates the warning flag', async () => { - assert.equal(true, await flags.getFlag(consumer.address)) - - await flags.connect(personas.Nelly).lowerFlags([consumer.address]) - - assert.equal(false, await flags.getFlag(consumer.address)) - }) - - it('emits an event log', async () => { - await expect( - flags.connect(personas.Nelly).lowerFlags([consumer.address]), - ) - .to.emit(flags, 'FlagLowered') - .withArgs(consumer.address) - }) - - describe('if a flag has already been raised', () => { - beforeEach(async () => { - await flags.connect(personas.Nelly).lowerFlags([consumer.address]) - }) - - it('emits an event log', async () => { - const tx = await flags - .connect(personas.Nelly) - .lowerFlags([consumer.address]) - const receipt = await tx.wait() - assert.equal(0, receipt.events?.length) - }) - }) - }) - - describe('when called by a non-owner', () => { - it('reverts', async () => { - await expect( - flags.connect(personas.Neil).lowerFlags([consumer.address]), - ).to.be.revertedWith('Only callable by owner') - }) - }) - }) - - describe('#getFlag', () => { - describe('if the access control is turned on', () => { - beforeEach(async () => { - await flags.connect(personas.Nelly).enableAccessCheck() - }) - - it('reverts', async () => { - await expect(consumer.getFlag(consumer.address)).to.be.revertedWith( - 'No access', - ) - }) - - describe('if access is granted to the address', () => { - beforeEach(async () => { - await flags.connect(personas.Nelly).addAccess(consumer.address) - }) - - it('does not revert', async () => { - await consumer.getFlag(consumer.address) - }) - }) - }) - - describe('if the access control is turned off', () => { - beforeEach(async () => { - await flags.connect(personas.Nelly).disableAccessCheck() - }) - - it('does not revert', async () => { - await consumer.getFlag(consumer.address) - }) - - describe('if access is granted to the address', () => { - beforeEach(async () => { - await flags.connect(personas.Nelly).addAccess(consumer.address) - }) - - it('does not revert', async () => { - await consumer.getFlag(consumer.address) - }) - }) - }) - }) - - describe('#getFlags', () => { - beforeEach(async () => { - await flags.connect(personas.Nelly).disableAccessCheck() - await flags - .connect(personas.Nelly) - .raiseFlags([ - await personas.Neil.getAddress(), - await personas.Norbert.getAddress(), - ]) - }) - - it('respects the access controls of #getFlag', async () => { - await flags.connect(personas.Nelly).enableAccessCheck() - - await expect(consumer.getFlag(consumer.address)).to.be.revertedWith( - 'No access', - ) - - await flags.connect(personas.Nelly).addAccess(consumer.address) - - await consumer.getFlag(consumer.address) - }) - - it('returns the flags in the order they are requested', async () => { - const response = await consumer.getFlags([ - await personas.Nelly.getAddress(), - await personas.Neil.getAddress(), - await personas.Ned.getAddress(), - await personas.Norbert.getAddress(), - ]) - - assert.deepEqual([false, true, false, true], response) - }) - }) - - describe('#setRaisingAccessController', () => { - let controller2: Contract - - beforeEach(async () => { - controller2 = await controllerFactory.connect(personas.Nelly).deploy() - await controller2.connect(personas.Nelly).enableAccessCheck() - }) - - it('updates access control rules', async () => { - const neilAddress = await personas.Neil.getAddress() - await controller.connect(personas.Nelly).addAccess(neilAddress) - await flags.connect(personas.Neil).raiseFlags([consumer.address]) // doesn't raise - - await flags - .connect(personas.Nelly) - .setRaisingAccessController(controller2.address) - - await expect( - flags.connect(personas.Neil).raiseFlags([consumer.address]), - ).to.be.revertedWith('Not allowed to raise flags') - }) - - it('emits a log announcing the change', async () => { - await expect( - flags - .connect(personas.Nelly) - .setRaisingAccessController(controller2.address), - ) - .to.emit(flags, 'RaisingAccessControllerUpdated') - .withArgs(controller.address, controller2.address) - }) - - it('does not emit a log when there is no change', async () => { - await flags - .connect(personas.Nelly) - .setRaisingAccessController(controller2.address) - - await expect( - flags - .connect(personas.Nelly) - .setRaisingAccessController(controller2.address), - ).to.not.emit(flags, 'RaisingAccessControllerUpdated') - }) - - describe('when called by a non-owner', () => { - it('reverts', async () => { - await expect( - flags - .connect(personas.Neil) - .setRaisingAccessController(controller2.address), - ).to.be.revertedWith('Only callable by owner') - }) - }) - }) -}) diff --git a/contracts/test/v0.8/HeartbeatRequester.test.ts b/contracts/test/v0.8/HeartbeatRequester.test.ts deleted file mode 100644 index bb58192337d..00000000000 --- a/contracts/test/v0.8/HeartbeatRequester.test.ts +++ /dev/null @@ -1,142 +0,0 @@ -import { getUsers, Personas } from '../test-helpers/setup' -import { ethers } from 'hardhat' -import { Signer } from 'ethers' -import { - HeartbeatRequester, - MockAggregatorProxy, - MockOffchainAggregator, -} from '../../typechain' -import { HeartbeatRequester__factory as HeartbeatRequesterFactory } from '../../typechain/factories/HeartbeatRequester__factory' -import { MockAggregatorProxy__factory as MockAggregatorProxyFactory } from '../../typechain/factories/MockAggregatorProxy__factory' -import { MockOffchainAggregator__factory as MockOffchainAggregatorFactory } from '../../typechain/factories/MockOffchainAggregator__factory' -import { assert, expect } from 'chai' - -let personas: Personas -let owner: Signer -let caller1: Signer -let proxy1: Signer -let proxy2: Signer -let aggregator: MockOffchainAggregator -let aggregatorFactory: MockOffchainAggregatorFactory -let aggregatorProxy: MockAggregatorProxy -let aggregatorProxyFactory: MockAggregatorProxyFactory -let requester: HeartbeatRequester -let requesterFactory: HeartbeatRequesterFactory - -describe('HeartbeatRequester', () => { - beforeEach(async () => { - personas = (await getUsers()).personas - owner = personas.Default - caller1 = personas.Carol - proxy1 = personas.Nelly - proxy2 = personas.Eddy - - // deploy heartbeat requester - requesterFactory = await ethers.getContractFactory('HeartbeatRequester') - requester = await requesterFactory.connect(owner).deploy() - await requester.deployed() - }) - - describe('#permitHeartbeat', () => { - it('adds a heartbeat and emits an event', async () => { - const callerAddress = await caller1.getAddress() - const proxyAddress1 = await proxy1.getAddress() - const proxyAddress2 = await proxy2.getAddress() - const tx1 = await requester - .connect(owner) - .permitHeartbeat(callerAddress, proxyAddress1) - await expect(tx1) - .to.emit(requester, 'HeartbeatPermitted') - .withArgs(callerAddress, proxyAddress1, ethers.constants.AddressZero) - - const tx2 = await requester - .connect(owner) - .permitHeartbeat(callerAddress, proxyAddress2) - await expect(tx2) - .to.emit(requester, 'HeartbeatPermitted') - .withArgs(callerAddress, proxyAddress2, proxyAddress1) - }) - - it('reverts when not called by its owner', async () => { - const callerAddress = await caller1.getAddress() - const proxyAddress = await proxy1.getAddress() - await expect( - requester.connect(caller1).permitHeartbeat(callerAddress, proxyAddress), - ).to.be.revertedWith('Only callable by owner') - }) - }) - - describe('#removeHeartbeat', () => { - it('removes a heartbeat and emits an event', async () => { - const callerAddress = await caller1.getAddress() - const proxyAddress = await proxy1.getAddress() - const tx1 = await requester - .connect(owner) - .permitHeartbeat(callerAddress, proxyAddress) - await expect(tx1) - .to.emit(requester, 'HeartbeatPermitted') - .withArgs(callerAddress, proxyAddress, ethers.constants.AddressZero) - - const tx2 = await requester.connect(owner).removeHeartbeat(callerAddress) - await expect(tx2) - .to.emit(requester, 'HeartbeatRemoved') - .withArgs(callerAddress, proxyAddress) - }) - - it('reverts when not called by its owner', async () => { - await expect( - requester.connect(caller1).removeHeartbeat(await caller1.getAddress()), - ).to.be.revertedWith('Only callable by owner') - }) - }) - - describe('#getAggregatorAndRequestHeartbeat', () => { - it('reverts if caller and proxy combination is not allowed', async () => { - const callerAddress = await caller1.getAddress() - const proxyAddress = await proxy1.getAddress() - await requester - .connect(owner) - .permitHeartbeat(callerAddress, proxyAddress) - - await expect( - requester - .connect(caller1) - .getAggregatorAndRequestHeartbeat(await owner.getAddress()), - ).to.be.revertedWithCustomError(requester, 'HeartbeatNotPermitted') - }) - - it('calls corresponding aggregator to request a new round', async () => { - aggregatorFactory = await ethers.getContractFactory( - 'MockOffchainAggregator', - ) - aggregator = await aggregatorFactory.connect(owner).deploy() - await aggregator.deployed() - - aggregatorProxyFactory = await ethers.getContractFactory( - 'MockAggregatorProxy', - ) - aggregatorProxy = await aggregatorProxyFactory - .connect(owner) - .deploy(aggregator.address) - await aggregatorProxy.deployed() - - await requester - .connect(owner) - .permitHeartbeat(await caller1.getAddress(), aggregatorProxy.address) - - const tx1 = await requester - .connect(caller1) - .getAggregatorAndRequestHeartbeat(aggregatorProxy.address) - - await expect(tx1).to.emit(aggregator, 'RoundIdUpdated').withArgs(1) - assert.equal((await aggregator.roundId()).toNumber(), 1) - - const tx2 = await requester - .connect(caller1) - .getAggregatorAndRequestHeartbeat(aggregatorProxy.address) - - await expect(tx2).to.emit(aggregator, 'RoundIdUpdated').withArgs(2) - assert.equal((await aggregator.roundId()).toNumber(), 2) - }) - }) -}) diff --git a/contracts/test/v0.8/PermissionedForwardProxy.test.ts b/contracts/test/v0.8/PermissionedForwardProxy.test.ts deleted file mode 100644 index 12ce63cd9b4..00000000000 --- a/contracts/test/v0.8/PermissionedForwardProxy.test.ts +++ /dev/null @@ -1,176 +0,0 @@ -import { ethers } from 'hardhat' -import { publicAbi } from '../test-helpers/helpers' -import { assert, expect } from 'chai' -import { Contract, ContractFactory } from 'ethers' -import { getUsers, Personas } from '../test-helpers/setup' - -const PERMISSION_NOT_SET = 'PermissionNotSet' - -let personas: Personas - -let controllerFactory: ContractFactory -let counterFactory: ContractFactory -let controller: Contract -let counter: Contract - -before(async () => { - personas = (await getUsers()).personas - controllerFactory = await ethers.getContractFactory( - 'src/v0.8/PermissionedForwardProxy.sol:PermissionedForwardProxy', - personas.Carol, - ) - counterFactory = await ethers.getContractFactory( - 'src/v0.8/tests/Counter.sol:Counter', - personas.Carol, - ) -}) - -describe('PermissionedForwardProxy', () => { - beforeEach(async () => { - controller = await controllerFactory.connect(personas.Carol).deploy() - counter = await counterFactory.connect(personas.Carol).deploy() - }) - - it('has a limited public interface [ @skip-coverage ]', async () => { - publicAbi(controller, [ - 'forward', - 'setPermission', - 'removePermission', - 'getPermission', - // Owned - 'acceptOwnership', - 'owner', - 'transferOwnership', - ]) - }) - - describe('#setPermission', () => { - describe('when called by a non-owner', () => { - it('reverts', async () => { - await expect( - controller - .connect(personas.Eddy) - .setPermission( - await personas.Carol.getAddress(), - await personas.Eddy.getAddress(), - ), - ).to.be.revertedWith('Only callable by owner') - }) - }) - - describe('when called by the owner', () => { - it('adds the permission to the proxy', async () => { - const tx = await controller - .connect(personas.Carol) - .setPermission( - await personas.Carol.getAddress(), - await personas.Eddy.getAddress(), - ) - const receipt = await tx.wait() - const eventLog = receipt?.events - - assert.equal(eventLog?.length, 1) - assert.equal(eventLog?.[0].event, 'PermissionSet') - assert.equal(eventLog?.[0].args?.[0], await personas.Carol.getAddress()) - assert.equal(eventLog?.[0].args?.[1], await personas.Eddy.getAddress()) - - expect( - await controller.getPermission(await personas.Carol.getAddress()), - ).to.be.equal(await personas.Eddy.getAddress()) - }) - }) - }) - - describe('#removePermission', () => { - beforeEach(async () => { - // Add permission before testing - await controller - .connect(personas.Carol) - .setPermission( - await personas.Carol.getAddress(), - await personas.Eddy.getAddress(), - ) - }) - - describe('when called by a non-owner', () => { - it('reverts', async () => { - await expect( - controller - .connect(personas.Eddy) - .removePermission(await personas.Carol.getAddress()), - ).to.be.revertedWith('Only callable by owner') - }) - }) - - describe('when called by the owner', () => { - it('removes the permission to the proxy', async () => { - const tx = await controller - .connect(personas.Carol) - .removePermission(await personas.Carol.getAddress()) - - const receipt = await tx.wait() - const eventLog = receipt?.events - - assert.equal(eventLog?.length, 1) - assert.equal(eventLog?.[0].event, 'PermissionRemoved') - assert.equal(eventLog?.[0].args?.[0], await personas.Carol.getAddress()) - - expect( - await controller.getPermission(await personas.Carol.getAddress()), - ).to.be.equal(ethers.constants.AddressZero) - }) - }) - }) - - describe('#forward', () => { - describe('when permission does not exist', () => { - it('reverts', async () => { - await expect( - controller - .connect(personas.Carol) - .forward(await personas.Eddy.getAddress(), '0x'), - ).to.be.revertedWithCustomError(controller, PERMISSION_NOT_SET) - }) - }) - - describe('when permission exists', () => { - beforeEach(async () => { - // Add permission before testing - await controller - .connect(personas.Carol) - .setPermission(await personas.Carol.getAddress(), counter.address) - }) - - it('calls target successfully', async () => { - await controller - .connect(personas.Carol) - .forward( - counter.address, - counter.interface.encodeFunctionData('increment'), - ) - - expect(await counter.count()).to.be.equal(1) - }) - - it('reverts when target reverts and bubbles up error', async () => { - await expect( - controller - .connect(personas.Carol) - .forward( - counter.address, - counter.interface.encodeFunctionData('alwaysRevertWithString'), - ), - ).to.be.revertedWith('always revert') // Revert strings should be bubbled up - - await expect( - controller - .connect(personas.Carol) - .forward( - counter.address, - counter.interface.encodeFunctionData('alwaysRevert'), - ), - ).to.be.reverted // Javascript VM not able to parse custom errors defined on another contract - }) - }) - }) -}) diff --git a/contracts/test/v0.8/ValidatorProxy.test.ts b/contracts/test/v0.8/ValidatorProxy.test.ts deleted file mode 100644 index 2d274245de4..00000000000 --- a/contracts/test/v0.8/ValidatorProxy.test.ts +++ /dev/null @@ -1,403 +0,0 @@ -import { ethers } from 'hardhat' -import { publicAbi } from '../test-helpers/helpers' -import { assert, expect } from 'chai' -import { Signer, Contract, constants } from 'ethers' -import { Users, getUsers } from '../test-helpers/setup' - -let users: Users - -let owner: Signer -let ownerAddress: string -let aggregator: Signer -let aggregatorAddress: string -let validator: Signer -let validatorAddress: string -let validatorProxy: Contract - -before(async () => { - users = await getUsers() - owner = users.personas.Default - aggregator = users.contracts.contract1 - validator = users.contracts.contract2 - ownerAddress = await owner.getAddress() - aggregatorAddress = await aggregator.getAddress() - validatorAddress = await validator.getAddress() -}) - -describe('ValidatorProxy', () => { - beforeEach(async () => { - const vpf = await ethers.getContractFactory( - 'src/v0.8/ValidatorProxy.sol:ValidatorProxy', - owner, - ) - validatorProxy = await vpf.deploy(aggregatorAddress, validatorAddress) - validatorProxy = await validatorProxy.deployed() - }) - - it('has a limited public interface [ @skip-coverage ]', async () => { - publicAbi(validatorProxy, [ - // ConfirmedOwner functions - 'acceptOwnership', - 'owner', - 'transferOwnership', - // ValidatorProxy functions - 'validate', - 'proposeNewAggregator', - 'upgradeAggregator', - 'getAggregators', - 'proposeNewValidator', - 'upgradeValidator', - 'getValidators', - 'typeAndVersion', - ]) - }) - - describe('#constructor', () => { - it('should set the aggregator addresses correctly', async () => { - const response = await validatorProxy.getAggregators() - assert.equal(response.current, aggregatorAddress) - assert.equal(response.hasProposal, false) - assert.equal(response.proposed, constants.AddressZero) - }) - - it('should set the validator addresses conrrectly', async () => { - const response = await validatorProxy.getValidators() - assert.equal(response.current, validatorAddress) - assert.equal(response.hasProposal, false) - assert.equal(response.proposed, constants.AddressZero) - }) - - it('should set the owner correctly', async () => { - const response = await validatorProxy.owner() - assert.equal(response, ownerAddress) - }) - }) - - describe('#proposeNewAggregator', () => { - let newAggregator: Signer - let newAggregatorAddress: string - beforeEach(async () => { - newAggregator = users.contracts.contract3 - newAggregatorAddress = await newAggregator.getAddress() - }) - - describe('failure', () => { - it('should only be called by the owner', async () => { - const stranger = users.contracts.contract4 - await expect( - validatorProxy - .connect(stranger) - .proposeNewAggregator(newAggregatorAddress), - ).to.be.revertedWith('Only callable by owner') - }) - - it('should revert if no change in proposal', async () => { - await validatorProxy.proposeNewAggregator(newAggregatorAddress) - await expect( - validatorProxy.proposeNewAggregator(newAggregatorAddress), - ).to.be.revertedWith('Invalid proposal') - }) - - it('should revert if the proposal is the same as the current', async () => { - await expect( - validatorProxy.proposeNewAggregator(aggregatorAddress), - ).to.be.revertedWith('Invalid proposal') - }) - }) - - describe('success', () => { - it('should emit an event', async () => { - await expect(validatorProxy.proposeNewAggregator(newAggregatorAddress)) - .to.emit(validatorProxy, 'AggregatorProposed') - .withArgs(newAggregatorAddress) - }) - - it('should set the correct address and hasProposal is true', async () => { - await validatorProxy.proposeNewAggregator(newAggregatorAddress) - const response = await validatorProxy.getAggregators() - assert.equal(response.current, aggregatorAddress) - assert.equal(response.hasProposal, true) - assert.equal(response.proposed, newAggregatorAddress) - }) - - it('should set a zero address and hasProposal is false', async () => { - await validatorProxy.proposeNewAggregator(newAggregatorAddress) - await validatorProxy.proposeNewAggregator(constants.AddressZero) - const response = await validatorProxy.getAggregators() - assert.equal(response.current, aggregatorAddress) - assert.equal(response.hasProposal, false) - assert.equal(response.proposed, constants.AddressZero) - }) - }) - }) - - describe('#upgradeAggregator', () => { - describe('failure', () => { - it('should only be called by the owner', async () => { - const stranger = users.contracts.contract4 - await expect( - validatorProxy.connect(stranger).upgradeAggregator(), - ).to.be.revertedWith('Only callable by owner') - }) - - it('should revert if there is no proposal', async () => { - await expect(validatorProxy.upgradeAggregator()).to.be.revertedWith( - 'No proposal', - ) - }) - }) - - describe('success', () => { - let newAggregator: Signer - let newAggregatorAddress: string - beforeEach(async () => { - newAggregator = users.contracts.contract3 - newAggregatorAddress = await newAggregator.getAddress() - await validatorProxy.proposeNewAggregator(newAggregatorAddress) - }) - - it('should emit an event', async () => { - await expect(validatorProxy.upgradeAggregator()) - .to.emit(validatorProxy, 'AggregatorUpgraded') - .withArgs(aggregatorAddress, newAggregatorAddress) - }) - - it('should upgrade the addresses', async () => { - await validatorProxy.upgradeAggregator() - const response = await validatorProxy.getAggregators() - assert.equal(response.current, newAggregatorAddress) - assert.equal(response.hasProposal, false) - assert.equal(response.proposed, constants.AddressZero) - }) - }) - }) - - describe('#proposeNewValidator', () => { - let newValidator: Signer - let newValidatorAddress: string - - beforeEach(async () => { - newValidator = users.contracts.contract3 - newValidatorAddress = await newValidator.getAddress() - }) - - describe('failure', () => { - it('should only be called by the owner', async () => { - const stranger = users.contracts.contract4 - await expect( - validatorProxy - .connect(stranger) - .proposeNewAggregator(newValidatorAddress), - ).to.be.revertedWith('Only callable by owner') - }) - - it('should revert if no change in proposal', async () => { - await validatorProxy.proposeNewValidator(newValidatorAddress) - await expect( - validatorProxy.proposeNewValidator(newValidatorAddress), - ).to.be.revertedWith('Invalid proposal') - }) - - it('should revert if the proposal is the same as the current', async () => { - await expect( - validatorProxy.proposeNewValidator(validatorAddress), - ).to.be.revertedWith('Invalid proposal') - }) - }) - - describe('success', () => { - it('should emit an event', async () => { - await expect(validatorProxy.proposeNewValidator(newValidatorAddress)) - .to.emit(validatorProxy, 'ValidatorProposed') - .withArgs(newValidatorAddress) - }) - - it('should set the correct address and hasProposal is true', async () => { - await validatorProxy.proposeNewValidator(newValidatorAddress) - const response = await validatorProxy.getValidators() - assert.equal(response.current, validatorAddress) - assert.equal(response.hasProposal, true) - assert.equal(response.proposed, newValidatorAddress) - }) - - it('should set a zero address and hasProposal is false', async () => { - await validatorProxy.proposeNewValidator(newValidatorAddress) - await validatorProxy.proposeNewValidator(constants.AddressZero) - const response = await validatorProxy.getValidators() - assert.equal(response.current, validatorAddress) - assert.equal(response.hasProposal, false) - assert.equal(response.proposed, constants.AddressZero) - }) - }) - }) - - describe('#upgradeValidator', () => { - describe('failure', () => { - it('should only be called by the owner', async () => { - const stranger = users.contracts.contract4 - await expect( - validatorProxy.connect(stranger).upgradeValidator(), - ).to.be.revertedWith('Only callable by owner') - }) - - it('should revert if there is no proposal', async () => { - await expect(validatorProxy.upgradeValidator()).to.be.revertedWith( - 'No proposal', - ) - }) - }) - - describe('success', () => { - let newValidator: Signer - let newValidatorAddress: string - beforeEach(async () => { - newValidator = users.contracts.contract3 - newValidatorAddress = await newValidator.getAddress() - await validatorProxy.proposeNewValidator(newValidatorAddress) - }) - - it('should emit an event', async () => { - await expect(validatorProxy.upgradeValidator()) - .to.emit(validatorProxy, 'ValidatorUpgraded') - .withArgs(validatorAddress, newValidatorAddress) - }) - - it('should upgrade the addresses', async () => { - await validatorProxy.upgradeValidator() - const response = await validatorProxy.getValidators() - assert.equal(response.current, newValidatorAddress) - assert.equal(response.hasProposal, false) - assert.equal(response.proposed, constants.AddressZero) - }) - }) - }) - - describe('#validate', () => { - describe('failure', () => { - it('reverts when not called by aggregator or proposed aggregator', async () => { - const stranger = users.contracts.contract5 - await expect( - validatorProxy.connect(stranger).validate(99, 88, 77, 66), - ).to.be.revertedWith('Not a configured aggregator') - }) - - it('reverts when there is no validator set', async () => { - const vpf = await ethers.getContractFactory( - 'src/v0.8/ValidatorProxy.sol:ValidatorProxy', - owner, - ) - validatorProxy = await vpf.deploy( - aggregatorAddress, - constants.AddressZero, - ) - await validatorProxy.deployed() - await expect( - validatorProxy.connect(aggregator).validate(99, 88, 77, 66), - ).to.be.revertedWith('No validator set') - }) - }) - - describe('success', () => { - describe('from the aggregator', () => { - let mockValidator1: Contract - beforeEach(async () => { - const mvf = await ethers.getContractFactory( - 'src/v0.8/mocks/MockAggregatorValidator.sol:MockAggregatorValidator', - owner, - ) - mockValidator1 = await mvf.deploy(1) - mockValidator1 = await mockValidator1.deployed() - const vpf = await ethers.getContractFactory( - 'src/v0.8/ValidatorProxy.sol:ValidatorProxy', - owner, - ) - validatorProxy = await vpf.deploy( - aggregatorAddress, - mockValidator1.address, - ) - validatorProxy = await validatorProxy.deployed() - }) - - describe('for a single validator', () => { - it('calls validate on the validator', async () => { - await expect( - validatorProxy.connect(aggregator).validate(200, 300, 400, 500), - ) - .to.emit(mockValidator1, 'ValidateCalled') - .withArgs(1, 200, 300, 400, 500) - }) - - it('uses a specific amount of gas [ @skip-coverage ]', async () => { - const resp = await validatorProxy - .connect(aggregator) - .validate(200, 300, 400, 500) - const receipt = await resp.wait() - assert.equal(receipt.gasUsed.toString(), '32373') - }) - }) - - describe('for a validator and a proposed validator', () => { - let mockValidator2: Contract - - beforeEach(async () => { - const mvf = await ethers.getContractFactory( - 'src/v0.8/mocks/MockAggregatorValidator.sol:MockAggregatorValidator', - owner, - ) - mockValidator2 = await mvf.deploy(2) - mockValidator2 = await mockValidator2.deployed() - await validatorProxy.proposeNewValidator(mockValidator2.address) - }) - - it('calls validate on the validator', async () => { - await expect( - validatorProxy - .connect(aggregator) - .validate(2000, 3000, 4000, 5000), - ) - .to.emit(mockValidator1, 'ValidateCalled') - .withArgs(1, 2000, 3000, 4000, 5000) - }) - - it('also calls validate on the proposed validator', async () => { - await expect( - validatorProxy - .connect(aggregator) - .validate(2000, 3000, 4000, 5000), - ) - .to.emit(mockValidator2, 'ValidateCalled') - .withArgs(2, 2000, 3000, 4000, 5000) - }) - - it('uses a specific amount of gas [ @skip-coverage ]', async () => { - const resp = await validatorProxy - .connect(aggregator) - .validate(2000, 3000, 4000, 5000) - const receipt = await resp.wait() - assert.equal(receipt.gasUsed.toString(), '40429') - }) - }) - }) - - describe('from the proposed aggregator', () => { - let newAggregator: Signer - let newAggregatorAddress: string - beforeEach(async () => { - newAggregator = users.contracts.contract3 - newAggregatorAddress = await newAggregator.getAddress() - await validatorProxy - .connect(owner) - .proposeNewAggregator(newAggregatorAddress) - }) - - it('emits an event', async () => { - await expect( - validatorProxy.connect(newAggregator).validate(555, 666, 777, 888), - ) - .to.emit(validatorProxy, 'ProposedAggregatorValidateCall') - .withArgs(newAggregatorAddress, 555, 666, 777, 888) - }) - }) - }) - }) -}) diff --git a/contracts/test/v0.8/automation/AutomationGasAnalysis.test.ts b/contracts/test/v0.8/automation/AutomationGasAnalysis.test.ts deleted file mode 100644 index c2e08f4cd81..00000000000 --- a/contracts/test/v0.8/automation/AutomationGasAnalysis.test.ts +++ /dev/null @@ -1,258 +0,0 @@ -import { ethers } from 'hardhat' -import { BigNumber } from 'ethers' -import { expect, assert } from 'chai' -import { getUsers } from '../../test-helpers/setup' -import { randomAddress, toWei } from '../../test-helpers/helpers' -import { deployRegistry21 } from './helpers' - -// don't run these tests in CI -const describeMaybe = process.env.CI ? describe.skip : describe - -// registry settings -const f = 1 -const linkEth = BigNumber.from(300000000) -const gasWei = BigNumber.from(100) -const minUpkeepSpend = BigNumber.from('1000000000000000000') -const paymentPremiumPPB = BigNumber.from(250000000) -const flatFeeMicroLink = BigNumber.from(0) -const blockCountPerTurn = 20 -const checkGasLimit = BigNumber.from(20000000) -const fallbackGasPrice = BigNumber.from(200) -const fallbackLinkPrice = BigNumber.from(200000000) -const maxCheckDataSize = BigNumber.from(10000) -const maxPerformDataSize = BigNumber.from(10000) -const maxRevertDataSize = BigNumber.from(1000) -const maxPerformGas = BigNumber.from(5000000) -const stalenessSeconds = BigNumber.from(43820) -const gasCeilingMultiplier = BigNumber.from(1) -const signers = [ - randomAddress(), - randomAddress(), - randomAddress(), - randomAddress(), -] -const transmitters = [ - randomAddress(), - randomAddress(), - randomAddress(), - randomAddress(), -] -const transcoder = ethers.constants.AddressZero - -// registrar settings -const triggerType = 0 // conditional -const autoApproveType = 2 // auto-approve enabled -const autoApproveMaxAllowed = 100 // auto-approve enabled - -// upkeep settings -const name = 'test upkeep' -const encryptedEmail = '0xabcd1234' -const gasLimit = 100_000 -const checkData = '0xdeadbeef' -const amount = toWei('5') -const source = 5 -const triggerConfig = '0x' -const offchainConfig = '0x' - -describeMaybe('Automation Gas Analysis', () => { - it('Compares gas usage amongst registries / registrars', async () => { - assert( - Boolean(process.env.REPORT_GAS), - 'this test must be run with REPORT_GAS=true', - ) - - const personas = (await getUsers()).personas - const owner = personas.Default - const ownerAddress = await owner.getAddress() - - // factories - const getFact = ethers.getContractFactory - const linkTokenFactory = await getFact('LinkToken') - const mockV3AggregatorFactory = await getFact( - 'src/v0.8/tests/MockV3Aggregator.sol:MockV3Aggregator', - ) - const upkeepMockFactory = await getFact('UpkeepMock') - const registry12Factory = await getFact('KeeperRegistry1_2') - const registrar12Factory = await getFact('KeeperRegistrar') - const registry20Factory = await getFact('KeeperRegistry2_0') - const registryLogic20Factory = await getFact('KeeperRegistryLogic2_0') - const registrar20Factory = await getFact('KeeperRegistrar2_0') - const registrar21Factory = await getFact('AutomationRegistrar2_1') - const forwarderLogicFactory = await getFact('AutomationForwarderLogic') - - // deploy dependancy contracts - const linkToken = await linkTokenFactory.connect(owner).deploy() - const gasPriceFeed = await mockV3AggregatorFactory - .connect(owner) - .deploy(0, gasWei) - const linkEthFeed = await mockV3AggregatorFactory - .connect(owner) - .deploy(9, linkEth) - const upkeep = await upkeepMockFactory.connect(owner).deploy() - - // deploy v1.2 - const registrar12 = await registrar12Factory.connect(owner).deploy( - linkToken.address, - autoApproveType, - autoApproveMaxAllowed, - ethers.constants.AddressZero, // set later - minUpkeepSpend, - ) - const registry12 = await registry12Factory - .connect(owner) - .deploy(linkToken.address, linkEthFeed.address, gasPriceFeed.address, { - paymentPremiumPPB, - flatFeeMicroLink, - blockCountPerTurn, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder, - registrar: registrar12.address, - }) - await registrar12.setRegistrationConfig( - autoApproveType, - autoApproveMaxAllowed, - registry12.address, - minUpkeepSpend, - ) - - // deploy v2.0 - const registryLogic20 = await registryLogic20Factory - .connect(owner) - .deploy(0, linkToken.address, linkEthFeed.address, gasPriceFeed.address) - const registry20 = await registry20Factory - .connect(owner) - .deploy(registryLogic20.address) - const registrar20 = await registrar20Factory - .connect(owner) - .deploy( - linkToken.address, - autoApproveType, - autoApproveMaxAllowed, - registry20.address, - minUpkeepSpend, - ) - const config20 = { - paymentPremiumPPB, - flatFeeMicroLink, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxCheckDataSize, - maxPerformDataSize, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder, - registrar: registrar20.address, - } - const onchainConfig20 = ethers.utils.defaultAbiCoder.encode( - [ - 'tuple(uint32 paymentPremiumPPB,uint32 flatFeeMicroLink,uint32 checkGasLimit,uint24 stalenessSeconds\ - ,uint16 gasCeilingMultiplier,uint96 minUpkeepSpend,uint32 maxPerformGas,uint32 maxCheckDataSize,\ - uint32 maxPerformDataSize,uint256 fallbackGasPrice,uint256 fallbackLinkPrice,address transcoder,\ - address registrar)', - ], - [config20], - ) - await registry20 - .connect(owner) - .setConfig(signers, transmitters, f, onchainConfig20, 1, '0x') - - // deploy v2.1 - const forwarderLogic = await forwarderLogicFactory.connect(owner).deploy() - const registry21 = await deployRegistry21( - owner, - 0, - linkToken.address, - linkEthFeed.address, - gasPriceFeed.address, - forwarderLogic.address, - ) - const registrar21 = await registrar21Factory - .connect(owner) - .deploy(linkToken.address, registry21.address, minUpkeepSpend, [ - { - triggerType, - autoApproveType, - autoApproveMaxAllowed, - }, - ]) - const onchainConfig21 = { - paymentPremiumPPB, - flatFeeMicroLink, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxCheckDataSize, - maxPerformDataSize, - maxRevertDataSize, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder, - registrars: [registrar21.address], - upkeepPrivilegeManager: randomAddress(), - } - await registry21 - .connect(owner) - .setConfigTypeSafe(signers, transmitters, f, onchainConfig21, 1, '0x') - - // approve LINK - await linkToken.connect(owner).approve(registrar20.address, amount) - await linkToken.connect(owner).approve(registrar21.address, amount) - - const abiEncodedBytes = registrar12.interface.encodeFunctionData( - 'register', - [ - name, - encryptedEmail, - upkeep.address, - gasLimit, - ownerAddress, - checkData, - amount, - source, - ownerAddress, - ], - ) - - let tx = await linkToken - .connect(owner) - .transferAndCall(registrar12.address, amount, abiEncodedBytes) - await expect(tx).to.emit(registry12, 'UpkeepRegistered') - - tx = await registrar20.connect(owner).registerUpkeep({ - name, - encryptedEmail, - upkeepContract: upkeep.address, - gasLimit, - adminAddress: ownerAddress, - checkData, - amount, - offchainConfig, - }) - await expect(tx).to.emit(registry20, 'UpkeepRegistered') - - tx = await registrar21.connect(owner).registerUpkeep({ - name, - encryptedEmail, - upkeepContract: upkeep.address, - gasLimit, - adminAddress: ownerAddress, - triggerType, - checkData, - amount, - triggerConfig, - offchainConfig, - }) - await expect(tx).to.emit(registry21, 'UpkeepRegistered') - }) -}) diff --git a/contracts/test/v0.8/automation/AutomationRegistrar2_1.test.ts b/contracts/test/v0.8/automation/AutomationRegistrar2_1.test.ts deleted file mode 100644 index a096ee4f481..00000000000 --- a/contracts/test/v0.8/automation/AutomationRegistrar2_1.test.ts +++ /dev/null @@ -1,1022 +0,0 @@ -import { ethers } from 'hardhat' -import { assert } from 'chai' -import { AutomationRegistrar2_1__factory as AutomationRegistrarFactory } from '../../../typechain/factories/AutomationRegistrar2_1__factory' - -////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////// - -/*********************************** REGISTRAR v2.1 IS FROZEN ************************************/ - -// As 2.1 is still actively being deployed, we keep the tests below. - -describe('AutomationRegistrar2_1 - Frozen [ @skip-coverage ]', () => { - it('has not changed', () => { - assert.equal( - ethers.utils.id(AutomationRegistrarFactory.bytecode), - '0x9633058bd81e8479f88baaee9bda533406295c80ccbc43d4509701001bbea6e3', - 'KeeperRegistry bytecode has changed', - ) - }) -}) - -////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////// -// -// // copied from KeeperRegistryBase2_1.sol -// enum Trigger { -// CONDITION, -// LOG, -// } -// -// let linkTokenFactory: LinkTokenFactory -// let mockV3AggregatorFactory: MockV3AggregatorFactory -// let upkeepMockFactory: UpkeepMockFactory -// -// let personas: Personas -// -// before(async () => { -// personas = (await getUsers()).personas -// -// linkTokenFactory = await ethers.getContractFactory( -// 'src/v0.8/shared/test/helpers/LinkTokenTestHelper.sol:LinkTokenTestHelper', -// ) -// mockV3AggregatorFactory = (await ethers.getContractFactory( -// 'src/v0.8/tests/MockV3Aggregator.sol:MockV3Aggregator', -// )) as unknown as MockV3AggregatorFactory -// upkeepMockFactory = await ethers.getContractFactory('UpkeepMock') -// }) -// -// const errorMsgs = { -// onlyOwner: 'revert Only callable by owner', -// onlyAdmin: 'OnlyAdminOrOwner()', -// hashPayload: 'HashMismatch()', -// requestNotFound: 'RequestNotFound()', -// } -// -// describe('AutomationRegistrar2_1', () => { -// const upkeepName = 'SampleUpkeep' -// -// const linkEth = BigNumber.from(300000000) -// const gasWei = BigNumber.from(100) -// const performGas = BigNumber.from(100000) -// const paymentPremiumPPB = BigNumber.from(250000000) -// const flatFeeMicroLink = BigNumber.from(0) -// const maxAllowedAutoApprove = 5 -// const trigger = '0xdeadbeef' -// const offchainConfig = '0x01234567' -// -// const emptyBytes = '0x00' -// const stalenessSeconds = BigNumber.from(43820) -// const gasCeilingMultiplier = BigNumber.from(1) -// const checkGasLimit = BigNumber.from(20000000) -// const fallbackGasPrice = BigNumber.from(200) -// const fallbackLinkPrice = BigNumber.from(200000000) -// const maxCheckDataSize = BigNumber.from(10000) -// const maxPerformDataSize = BigNumber.from(10000) -// const maxRevertDataSize = BigNumber.from(1000) -// const maxPerformGas = BigNumber.from(5000000) -// const minUpkeepSpend = BigNumber.from('1000000000000000000') -// const amount = BigNumber.from('5000000000000000000') -// const amount1 = BigNumber.from('6000000000000000000') -// const transcoder = ethers.constants.AddressZero -// const upkeepManager = ethers.Wallet.createRandom().address -// -// // Enum values are not auto exported in ABI so have to manually declare -// const autoApproveType_DISABLED = 0 -// const autoApproveType_ENABLED_SENDER_ALLOWLIST = 1 -// const autoApproveType_ENABLED_ALL = 2 -// -// let owner: Signer -// let admin: Signer -// let someAddress: Signer -// let registrarOwner: Signer -// let stranger: Signer -// let requestSender: Signer -// -// let linkToken: LinkToken -// let linkEthFeed: MockV3Aggregator -// let gasPriceFeed: MockV3Aggregator -// let mock: UpkeepMock -// let registry: IKeeperRegistry -// let registrar: Registrar -// -// beforeEach(async () => { -// owner = personas.Default -// admin = personas.Neil -// someAddress = personas.Ned -// registrarOwner = personas.Nelly -// stranger = personas.Nancy -// requestSender = personas.Norbert -// -// linkToken = await linkTokenFactory.connect(owner).deploy() -// gasPriceFeed = await mockV3AggregatorFactory -// .connect(owner) -// .deploy(0, gasWei) -// linkEthFeed = await mockV3AggregatorFactory -// .connect(owner) -// .deploy(9, linkEth) -// -// registry = await deployRegistry21( -// owner, -// 0, -// linkToken.address, -// linkEthFeed.address, -// gasPriceFeed.address, -// ) -// -// mock = await upkeepMockFactory.deploy() -// -// const registrarFactory = await ethers.getContractFactory( -// 'AutomationRegistrar2_1', -// ) -// registrar = await registrarFactory -// .connect(registrarOwner) -// .deploy(linkToken.address, registry.address, minUpkeepSpend, [ -// { -// triggerType: Trigger.CONDITION, -// autoApproveType: autoApproveType_DISABLED, -// autoApproveMaxAllowed: 0, -// }, -// { -// triggerType: Trigger.LOG, -// autoApproveType: autoApproveType_DISABLED, -// autoApproveMaxAllowed: 0, -// }, -// ]) -// -// await linkToken -// .connect(owner) -// .transfer(await requestSender.getAddress(), toWei('1000')) -// -// const keepers = [ -// await personas.Carol.getAddress(), -// await personas.Nancy.getAddress(), -// await personas.Ned.getAddress(), -// await personas.Neil.getAddress(), -// ] -// const onchainConfig = { -// paymentPremiumPPB, -// flatFeeMicroLink, -// checkGasLimit, -// stalenessSeconds, -// gasCeilingMultiplier, -// minUpkeepSpend, -// maxCheckDataSize, -// maxPerformDataSize, -// maxRevertDataSize, -// maxPerformGas, -// fallbackGasPrice, -// fallbackLinkPrice, -// transcoder, -// registrars: [registrar.address], -// upkeepPrivilegeManager: upkeepManager, -// } -// await registry -// .connect(owner) -// .setConfigTypeSafe(keepers, keepers, 1, onchainConfig, 1, '0x') -// }) -// -// describe('#typeAndVersion', () => { -// it('uses the correct type and version', async () => { -// const typeAndVersion = await registrar.typeAndVersion() -// assert.equal(typeAndVersion, 'AutomationRegistrar 2.1.0') -// }) -// }) -// -// describe('#register', () => { -// it('reverts if not called by the LINK token', async () => { -// await evmRevert( -// registrar -// .connect(someAddress) -// .register( -// upkeepName, -// emptyBytes, -// mock.address, -// performGas, -// await admin.getAddress(), -// 0, -// emptyBytes, -// trigger, -// offchainConfig, -// amount, -// await requestSender.getAddress(), -// ), -// 'OnlyLink()', -// ) -// }) -// -// it('reverts if the amount passed in data mismatches actual amount sent', async () => { -// await registrar -// .connect(registrarOwner) -// .setTriggerConfig( -// Trigger.CONDITION, -// autoApproveType_ENABLED_ALL, -// maxAllowedAutoApprove, -// ) -// -// const abiEncodedBytes = registrar.interface.encodeFunctionData( -// 'register', -// [ -// upkeepName, -// emptyBytes, -// mock.address, -// performGas, -// await admin.getAddress(), -// 0, -// emptyBytes, -// trigger, -// offchainConfig, -// amount1, -// await requestSender.getAddress(), -// ], -// ) -// -// await evmRevert( -// linkToken -// .connect(requestSender) -// .transferAndCall(registrar.address, amount, abiEncodedBytes), -// 'AmountMismatch()', -// ) -// }) -// -// it('reverts if the sender passed in data mismatches actual sender', async () => { -// const abiEncodedBytes = registrar.interface.encodeFunctionData( -// 'register', -// [ -// upkeepName, -// emptyBytes, -// mock.address, -// performGas, -// await admin.getAddress(), -// 0, -// emptyBytes, -// trigger, -// offchainConfig, -// amount, -// await admin.getAddress(), // Should have been requestSender.getAddress() -// ], -// ) -// await evmRevert( -// linkToken -// .connect(requestSender) -// .transferAndCall(registrar.address, amount, abiEncodedBytes), -// 'SenderMismatch()', -// ) -// }) -// -// it('reverts if the admin address is 0x0000...', async () => { -// const abiEncodedBytes = registrar.interface.encodeFunctionData( -// 'register', -// [ -// upkeepName, -// emptyBytes, -// mock.address, -// performGas, -// '0x0000000000000000000000000000000000000000', -// 0, -// emptyBytes, -// trigger, -// offchainConfig, -// amount, -// await requestSender.getAddress(), -// ], -// ) -// -// await evmRevert( -// linkToken -// .connect(requestSender) -// .transferAndCall(registrar.address, amount, abiEncodedBytes), -// 'RegistrationRequestFailed()', -// ) -// }) -// -// it('Auto Approve ON - registers an upkeep on KeeperRegistry instantly and emits both RegistrationRequested and RegistrationApproved events', async () => { -// //set auto approve ON with high threshold limits -// await registrar -// .connect(registrarOwner) -// .setTriggerConfig( -// Trigger.CONDITION, -// autoApproveType_ENABLED_ALL, -// maxAllowedAutoApprove, -// ) -// -// //register with auto approve ON -// const abiEncodedBytes = registrar.interface.encodeFunctionData( -// 'register', -// [ -// upkeepName, -// emptyBytes, -// mock.address, -// performGas, -// await admin.getAddress(), -// 0, -// emptyBytes, -// trigger, -// offchainConfig, -// amount, -// await requestSender.getAddress(), -// ], -// ) -// const tx = await linkToken -// .connect(requestSender) -// .transferAndCall(registrar.address, amount, abiEncodedBytes) -// -// const [id] = await registry.getActiveUpkeepIDs(0, 1) -// -// //confirm if a new upkeep has been registered and the details are the same as the one just registered -// const newupkeep = await registry.getUpkeep(id) -// assert.equal(newupkeep.target, mock.address) -// assert.equal(newupkeep.admin, await admin.getAddress()) -// assert.equal(newupkeep.checkData, emptyBytes) -// assert.equal(newupkeep.balance.toString(), amount.toString()) -// assert.equal(newupkeep.performGas, performGas.toNumber()) -// assert.equal(newupkeep.offchainConfig, offchainConfig) -// -// await expect(tx).to.emit(registrar, 'RegistrationRequested') -// await expect(tx).to.emit(registrar, 'RegistrationApproved') -// }) -// -// it('Auto Approve OFF - does not registers an upkeep on KeeperRegistry, emits only RegistrationRequested event', async () => { -// //get upkeep count before attempting registration -// const beforeCount = (await registry.getState()).state.numUpkeeps -// -// //set auto approve OFF, threshold limits dont matter in this case -// await registrar -// .connect(registrarOwner) -// .setTriggerConfig( -// Trigger.CONDITION, -// autoApproveType_DISABLED, -// maxAllowedAutoApprove, -// ) -// -// //register with auto approve OFF -// const abiEncodedBytes = registrar.interface.encodeFunctionData( -// 'register', -// [ -// upkeepName, -// emptyBytes, -// mock.address, -// performGas, -// await admin.getAddress(), -// 0, -// emptyBytes, -// trigger, -// offchainConfig, -// amount, -// await requestSender.getAddress(), -// ], -// ) -// const tx = await linkToken -// .connect(requestSender) -// .transferAndCall(registrar.address, amount, abiEncodedBytes) -// const receipt = await tx.wait() -// -// //get upkeep count after attempting registration -// const afterCount = (await registry.getState()).state.numUpkeeps -// //confirm that a new upkeep has NOT been registered and upkeep count is still the same -// assert.deepEqual(beforeCount, afterCount) -// -// //confirm that only RegistrationRequested event is emitted and RegistrationApproved event is not -// await expect(tx).to.emit(registrar, 'RegistrationRequested') -// await expect(tx).not.to.emit(registrar, 'RegistrationApproved') -// -// const hash = receipt.logs[2].topics[1] -// const pendingRequest = await registrar.getPendingRequest(hash) -// assert.equal(await admin.getAddress(), pendingRequest[0]) -// assert.ok(amount.eq(pendingRequest[1])) -// }) -// -// it('Auto Approve ON - Throttle max approvals - does not register an upkeep on KeeperRegistry beyond the max limit, emits only RegistrationRequested event after limit is hit', async () => { -// assert.equal((await registry.getState()).state.numUpkeeps.toNumber(), 0) -// -// //set auto approve on, with max 1 allowed -// await registrar -// .connect(registrarOwner) -// .setTriggerConfig(Trigger.CONDITION, autoApproveType_ENABLED_ALL, 1) -// -// //set auto approve on, with max 1 allowed -// await registrar -// .connect(registrarOwner) -// .setTriggerConfig(Trigger.LOG, autoApproveType_ENABLED_ALL, 1) -// -// // register within threshold, new upkeep should be registered -// let abiEncodedBytes = registrar.interface.encodeFunctionData('register', [ -// upkeepName, -// emptyBytes, -// mock.address, -// performGas, -// await admin.getAddress(), -// 0, -// emptyBytes, -// trigger, -// offchainConfig, -// amount, -// await requestSender.getAddress(), -// ]) -// await linkToken -// .connect(requestSender) -// .transferAndCall(registrar.address, amount, abiEncodedBytes) -// assert.equal((await registry.getState()).state.numUpkeeps.toNumber(), 1) // 0 -> 1 -// -// // try registering another one, new upkeep should not be registered -// abiEncodedBytes = registrar.interface.encodeFunctionData('register', [ -// upkeepName, -// emptyBytes, -// mock.address, -// performGas.toNumber() + 1, // make unique hash -// await admin.getAddress(), -// 0, -// emptyBytes, -// trigger, -// offchainConfig, -// amount, -// await requestSender.getAddress(), -// ]) -// await linkToken -// .connect(requestSender) -// .transferAndCall(registrar.address, amount, abiEncodedBytes) -// assert.equal((await registry.getState()).state.numUpkeeps.toNumber(), 1) // Still 1 -// -// // register a second type of upkeep, different limit -// abiEncodedBytes = registrar.interface.encodeFunctionData('register', [ -// upkeepName, -// emptyBytes, -// mock.address, -// performGas, -// await admin.getAddress(), -// Trigger.LOG, -// emptyBytes, -// trigger, -// offchainConfig, -// amount, -// await requestSender.getAddress(), -// ]) -// await linkToken -// .connect(requestSender) -// .transferAndCall(registrar.address, amount, abiEncodedBytes) -// assert.equal((await registry.getState()).state.numUpkeeps.toNumber(), 2) // 1 -> 2 -// -// // Now set new max limit to 2. One more upkeep should get auto approved -// await registrar -// .connect(registrarOwner) -// .setTriggerConfig(Trigger.CONDITION, autoApproveType_ENABLED_ALL, 2) -// -// abiEncodedBytes = registrar.interface.encodeFunctionData('register', [ -// upkeepName, -// emptyBytes, -// mock.address, -// performGas.toNumber() + 2, // make unique hash -// await admin.getAddress(), -// 0, -// emptyBytes, -// trigger, -// offchainConfig, -// amount, -// await requestSender.getAddress(), -// ]) -// await linkToken -// .connect(requestSender) -// .transferAndCall(registrar.address, amount, abiEncodedBytes) -// assert.equal((await registry.getState()).state.numUpkeeps.toNumber(), 3) // 2 -> 3 -// -// // One more upkeep should not get registered -// abiEncodedBytes = registrar.interface.encodeFunctionData('register', [ -// upkeepName, -// emptyBytes, -// mock.address, -// performGas.toNumber() + 3, // make unique hash -// await admin.getAddress(), -// 0, -// emptyBytes, -// trigger, -// offchainConfig, -// amount, -// await requestSender.getAddress(), -// ]) -// await linkToken -// .connect(requestSender) -// .transferAndCall(registrar.address, amount, abiEncodedBytes) -// assert.equal((await registry.getState()).state.numUpkeeps.toNumber(), 3) // Still 3 -// }) -// -// it('Auto Approve Sender Allowlist - sender in allowlist - registers an upkeep on KeeperRegistry instantly and emits both RegistrationRequested and RegistrationApproved events', async () => { -// const senderAddress = await requestSender.getAddress() -// -// //set auto approve to ENABLED_SENDER_ALLOWLIST type with high threshold limits -// await registrar -// .connect(registrarOwner) -// .setTriggerConfig( -// Trigger.CONDITION, -// autoApproveType_ENABLED_SENDER_ALLOWLIST, -// maxAllowedAutoApprove, -// ) -// -// // Add sender to allowlist -// await registrar -// .connect(registrarOwner) -// .setAutoApproveAllowedSender(senderAddress, true) -// -// //register with auto approve ON -// const abiEncodedBytes = registrar.interface.encodeFunctionData( -// 'register', -// [ -// upkeepName, -// emptyBytes, -// mock.address, -// performGas, -// await admin.getAddress(), -// 0, -// emptyBytes, -// trigger, -// offchainConfig, -// amount, -// await requestSender.getAddress(), -// ], -// ) -// const tx = await linkToken -// .connect(requestSender) -// .transferAndCall(registrar.address, amount, abiEncodedBytes) -// -// const [id] = await registry.getActiveUpkeepIDs(0, 1) -// -// //confirm if a new upkeep has been registered and the details are the same as the one just registered -// const newupkeep = await registry.getUpkeep(id) -// assert.equal(newupkeep.target, mock.address) -// assert.equal(newupkeep.admin, await admin.getAddress()) -// assert.equal(newupkeep.checkData, emptyBytes) -// assert.equal(newupkeep.balance.toString(), amount.toString()) -// assert.equal(newupkeep.performGas, performGas.toNumber()) -// -// await expect(tx).to.emit(registrar, 'RegistrationRequested') -// await expect(tx).to.emit(registrar, 'RegistrationApproved') -// }) -// -// it('Auto Approve Sender Allowlist - sender NOT in allowlist - does not registers an upkeep on KeeperRegistry, emits only RegistrationRequested event', async () => { -// const beforeCount = (await registry.getState()).state.numUpkeeps -// const senderAddress = await requestSender.getAddress() -// -// //set auto approve to ENABLED_SENDER_ALLOWLIST type with high threshold limits -// await registrar -// .connect(registrarOwner) -// .setTriggerConfig( -// Trigger.CONDITION, -// autoApproveType_ENABLED_SENDER_ALLOWLIST, -// maxAllowedAutoApprove, -// ) -// -// // Explicitly remove sender from allowlist -// await registrar -// .connect(registrarOwner) -// .setAutoApproveAllowedSender(senderAddress, false) -// -// //register. auto approve shouldn't happen -// const abiEncodedBytes = registrar.interface.encodeFunctionData( -// 'register', -// [ -// upkeepName, -// emptyBytes, -// mock.address, -// performGas, -// await admin.getAddress(), -// 0, -// emptyBytes, -// trigger, -// offchainConfig, -// amount, -// await requestSender.getAddress(), -// ], -// ) -// const tx = await linkToken -// .connect(requestSender) -// .transferAndCall(registrar.address, amount, abiEncodedBytes) -// const receipt = await tx.wait() -// -// //get upkeep count after attempting registration -// const afterCount = (await registry.getState()).state.numUpkeeps -// //confirm that a new upkeep has NOT been registered and upkeep count is still the same -// assert.deepEqual(beforeCount, afterCount) -// -// //confirm that only RegistrationRequested event is emitted and RegistrationApproved event is not -// await expect(tx).to.emit(registrar, 'RegistrationRequested') -// await expect(tx).not.to.emit(registrar, 'RegistrationApproved') -// -// const hash = receipt.logs[2].topics[1] -// const pendingRequest = await registrar.getPendingRequest(hash) -// assert.equal(await admin.getAddress(), pendingRequest[0]) -// assert.ok(amount.eq(pendingRequest[1])) -// }) -// }) -// -// describe('#registerUpkeep', () => { -// it('reverts with empty message if amount sent is not available in LINK allowance', async () => { -// await evmRevert( -// registrar.connect(someAddress).registerUpkeep({ -// name: upkeepName, -// upkeepContract: mock.address, -// gasLimit: performGas, -// adminAddress: await admin.getAddress(), -// triggerType: 0, -// checkData: emptyBytes, -// triggerConfig: trigger, -// offchainConfig: emptyBytes, -// amount, -// encryptedEmail: emptyBytes, -// }), -// '', -// ) -// }) -// -// it('reverts if the amount passed in data is less than configured minimum', async () => { -// await registrar -// .connect(registrarOwner) -// .setTriggerConfig( -// Trigger.CONDITION, -// autoApproveType_ENABLED_ALL, -// maxAllowedAutoApprove, -// ) -// -// // amt is one order of magnitude less than minUpkeepSpend -// const amt = BigNumber.from('100000000000000000') -// -// await evmRevert( -// registrar.connect(someAddress).registerUpkeep({ -// name: upkeepName, -// upkeepContract: mock.address, -// gasLimit: performGas, -// adminAddress: await admin.getAddress(), -// triggerType: 0, -// checkData: emptyBytes, -// triggerConfig: trigger, -// offchainConfig: emptyBytes, -// amount: amt, -// encryptedEmail: emptyBytes, -// }), -// 'InsufficientPayment()', -// ) -// }) -// -// it('Auto Approve ON - registers an upkeep on KeeperRegistry instantly and emits both RegistrationRequested and RegistrationApproved events', async () => { -// //set auto approve ON with high threshold limits -// await registrar -// .connect(registrarOwner) -// .setTriggerConfig( -// Trigger.CONDITION, -// autoApproveType_ENABLED_ALL, -// maxAllowedAutoApprove, -// ) -// -// await linkToken.connect(requestSender).approve(registrar.address, amount) -// -// const tx = await registrar.connect(requestSender).registerUpkeep({ -// name: upkeepName, -// upkeepContract: mock.address, -// gasLimit: performGas, -// adminAddress: await admin.getAddress(), -// triggerType: 0, -// checkData: emptyBytes, -// triggerConfig: trigger, -// offchainConfig, -// amount, -// encryptedEmail: emptyBytes, -// }) -// assert.equal((await registry.getState()).state.numUpkeeps.toNumber(), 1) // 0 -> 1 -// -// //confirm if a new upkeep has been registered and the details are the same as the one just registered -// const [id] = await registry.getActiveUpkeepIDs(0, 1) -// const newupkeep = await registry.getUpkeep(id) -// assert.equal(newupkeep.target, mock.address) -// assert.equal(newupkeep.admin, await admin.getAddress()) -// assert.equal(newupkeep.checkData, emptyBytes) -// assert.equal(newupkeep.balance.toString(), amount.toString()) -// assert.equal(newupkeep.performGas, performGas.toNumber()) -// assert.equal(newupkeep.offchainConfig, offchainConfig) -// -// await expect(tx).to.emit(registrar, 'RegistrationRequested') -// await expect(tx).to.emit(registrar, 'RegistrationApproved') -// }) -// }) -// -// describe('#setAutoApproveAllowedSender', () => { -// it('reverts if not called by the owner', async () => { -// const tx = registrar -// .connect(stranger) -// .setAutoApproveAllowedSender(await admin.getAddress(), false) -// await evmRevert(tx, 'Only callable by owner') -// }) -// -// it('sets the allowed status correctly and emits log', async () => { -// const senderAddress = await stranger.getAddress() -// let tx = await registrar -// .connect(registrarOwner) -// .setAutoApproveAllowedSender(senderAddress, true) -// await expect(tx) -// .to.emit(registrar, 'AutoApproveAllowedSenderSet') -// .withArgs(senderAddress, true) -// -// let senderAllowedStatus = await registrar -// .connect(owner) -// .getAutoApproveAllowedSender(senderAddress) -// assert.isTrue(senderAllowedStatus) -// -// tx = await registrar -// .connect(registrarOwner) -// .setAutoApproveAllowedSender(senderAddress, false) -// await expect(tx) -// .to.emit(registrar, 'AutoApproveAllowedSenderSet') -// .withArgs(senderAddress, false) -// -// senderAllowedStatus = await registrar -// .connect(owner) -// .getAutoApproveAllowedSender(senderAddress) -// assert.isFalse(senderAllowedStatus) -// }) -// }) -// -// describe('#setTriggerConfig', () => { -// it('reverts if not called by the owner', async () => { -// const tx = registrar -// .connect(stranger) -// .setTriggerConfig(Trigger.LOG, autoApproveType_ENABLED_ALL, 100) -// await evmRevert(tx, 'Only callable by owner') -// }) -// -// it('changes the config', async () => { -// const tx = await registrar -// .connect(registrarOwner) -// .setTriggerConfig(Trigger.LOG, autoApproveType_ENABLED_ALL, 100) -// await registrar.getTriggerRegistrationDetails(Trigger.LOG) -// await expect(tx) -// .to.emit(registrar, 'TriggerConfigSet') -// .withArgs(Trigger.LOG, autoApproveType_ENABLED_ALL, 100) -// }) -// }) -// -// describe('#approve', () => { -// let hash: string -// -// beforeEach(async () => { -// await registrar -// .connect(registrarOwner) -// .setTriggerConfig( -// Trigger.CONDITION, -// autoApproveType_DISABLED, -// maxAllowedAutoApprove, -// ) -// -// //register with auto approve OFF -// const abiEncodedBytes = registrar.interface.encodeFunctionData( -// 'register', -// [ -// upkeepName, -// emptyBytes, -// mock.address, -// performGas, -// await admin.getAddress(), -// 0, -// emptyBytes, -// trigger, -// offchainConfig, -// amount, -// await requestSender.getAddress(), -// ], -// ) -// -// const tx = await linkToken -// .connect(requestSender) -// .transferAndCall(registrar.address, amount, abiEncodedBytes) -// const receipt = await tx.wait() -// hash = receipt.logs[2].topics[1] -// }) -// -// it('reverts if not called by the owner', async () => { -// const tx = registrar -// .connect(stranger) -// .approve( -// upkeepName, -// mock.address, -// performGas, -// await admin.getAddress(), -// 0, -// emptyBytes, -// trigger, -// emptyBytes, -// hash, -// ) -// await evmRevert(tx, 'Only callable by owner') -// }) -// -// it('reverts if the hash does not exist', async () => { -// const tx = registrar -// .connect(registrarOwner) -// .approve( -// upkeepName, -// mock.address, -// performGas, -// await admin.getAddress(), -// 0, -// emptyBytes, -// trigger, -// emptyBytes, -// '0x000000000000000000000000322813fd9a801c5507c9de605d63cea4f2ce6c44', -// ) -// await evmRevert(tx, errorMsgs.requestNotFound) -// }) -// -// it('reverts if any member of the payload changes', async () => { -// let tx = registrar -// .connect(registrarOwner) -// .approve( -// upkeepName, -// ethers.Wallet.createRandom().address, -// performGas, -// await admin.getAddress(), -// 0, -// emptyBytes, -// trigger, -// emptyBytes, -// hash, -// ) -// await evmRevert(tx, errorMsgs.hashPayload) -// tx = registrar -// .connect(registrarOwner) -// .approve( -// upkeepName, -// mock.address, -// 10000, -// await admin.getAddress(), -// 0, -// emptyBytes, -// trigger, -// emptyBytes, -// hash, -// ) -// await evmRevert(tx, errorMsgs.hashPayload) -// tx = registrar -// .connect(registrarOwner) -// .approve( -// upkeepName, -// mock.address, -// performGas, -// ethers.Wallet.createRandom().address, -// 0, -// emptyBytes, -// trigger, -// emptyBytes, -// hash, -// ) -// await evmRevert(tx, errorMsgs.hashPayload) -// tx = registrar -// .connect(registrarOwner) -// .approve( -// upkeepName, -// mock.address, -// performGas, -// await admin.getAddress(), -// 0, -// '0x1234', -// trigger, -// emptyBytes, -// hash, -// ) -// await evmRevert(tx, errorMsgs.hashPayload) -// }) -// -// it('approves an existing registration request', async () => { -// const tx = await registrar -// .connect(registrarOwner) -// .approve( -// upkeepName, -// mock.address, -// performGas, -// await admin.getAddress(), -// 0, -// emptyBytes, -// trigger, -// offchainConfig, -// hash, -// ) -// await expect(tx).to.emit(registrar, 'RegistrationApproved') -// }) -// -// it('deletes the request afterwards / reverts if the request DNE', async () => { -// await registrar -// .connect(registrarOwner) -// .approve( -// upkeepName, -// mock.address, -// performGas, -// await admin.getAddress(), -// 0, -// emptyBytes, -// trigger, -// offchainConfig, -// hash, -// ) -// const tx = registrar -// .connect(registrarOwner) -// .approve( -// upkeepName, -// mock.address, -// performGas, -// await admin.getAddress(), -// 0, -// emptyBytes, -// trigger, -// offchainConfig, -// hash, -// ) -// await evmRevert(tx, errorMsgs.requestNotFound) -// }) -// }) -// -// describe('#cancel', () => { -// let hash: string -// -// beforeEach(async () => { -// await registrar -// .connect(registrarOwner) -// .setTriggerConfig( -// Trigger.CONDITION, -// autoApproveType_DISABLED, -// maxAllowedAutoApprove, -// ) -// -// //register with auto approve OFF -// const abiEncodedBytes = registrar.interface.encodeFunctionData( -// 'register', -// [ -// upkeepName, -// emptyBytes, -// mock.address, -// performGas, -// await admin.getAddress(), -// 0, -// emptyBytes, -// trigger, -// offchainConfig, -// amount, -// await requestSender.getAddress(), -// ], -// ) -// const tx = await linkToken -// .connect(requestSender) -// .transferAndCall(registrar.address, amount, abiEncodedBytes) -// const receipt = await tx.wait() -// hash = receipt.logs[2].topics[1] -// // submit duplicate request (increase balance) -// await linkToken -// .connect(requestSender) -// .transferAndCall(registrar.address, amount, abiEncodedBytes) -// }) -// -// it('reverts if not called by the admin / owner', async () => { -// const tx = registrar.connect(stranger).cancel(hash) -// await evmRevert(tx, errorMsgs.onlyAdmin) -// }) -// -// it('reverts if the hash does not exist', async () => { -// const tx = registrar -// .connect(registrarOwner) -// .cancel( -// '0x000000000000000000000000322813fd9a801c5507c9de605d63cea4f2ce6c44', -// ) -// await evmRevert(tx, errorMsgs.requestNotFound) -// }) -// -// it('refunds the total request balance to the admin address if owner cancels', async () => { -// const before = await linkToken.balanceOf(await admin.getAddress()) -// const tx = await registrar.connect(registrarOwner).cancel(hash) -// const after = await linkToken.balanceOf(await admin.getAddress()) -// assert.isTrue(after.sub(before).eq(amount.mul(BigNumber.from(2)))) -// await expect(tx).to.emit(registrar, 'RegistrationRejected') -// }) -// -// it('refunds the total request balance to the admin address if admin cancels', async () => { -// const before = await linkToken.balanceOf(await admin.getAddress()) -// const tx = await registrar.connect(admin).cancel(hash) -// const after = await linkToken.balanceOf(await admin.getAddress()) -// assert.isTrue(after.sub(before).eq(amount.mul(BigNumber.from(2)))) -// await expect(tx).to.emit(registrar, 'RegistrationRejected') -// }) -// -// it('deletes the request hash', async () => { -// await registrar.connect(registrarOwner).cancel(hash) -// let tx = registrar.connect(registrarOwner).cancel(hash) -// await evmRevert(tx, errorMsgs.requestNotFound) -// tx = registrar -// .connect(registrarOwner) -// .approve( -// upkeepName, -// mock.address, -// performGas, -// await admin.getAddress(), -// 0, -// emptyBytes, -// trigger, -// emptyBytes, -// hash, -// ) -// await evmRevert(tx, errorMsgs.requestNotFound) -// }) -// }) -// }) diff --git a/contracts/test/v0.8/automation/AutomationRegistrar2_3.test.ts b/contracts/test/v0.8/automation/AutomationRegistrar2_3.test.ts index 31712e1380b..e98218ec214 100644 --- a/contracts/test/v0.8/automation/AutomationRegistrar2_3.test.ts +++ b/contracts/test/v0.8/automation/AutomationRegistrar2_3.test.ts @@ -44,7 +44,7 @@ before(async () => { 'src/v0.8/shared/test/helpers/LinkTokenTestHelper.sol:LinkTokenTestHelper', ) mockV3AggregatorFactory = (await ethers.getContractFactory( - 'src/v0.8/tests/MockV3Aggregator.sol:MockV3Aggregator', + 'src/v0.8/shared/mocks/MockV3Aggregator.sol:MockV3Aggregator', )) as unknown as MockV3AggregatorFactory upkeepMockFactory = await ethers.getContractFactory('UpkeepMock') }) diff --git a/contracts/test/v0.8/automation/AutomationRegistry2_2.test.ts b/contracts/test/v0.8/automation/AutomationRegistry2_2.test.ts deleted file mode 100644 index 6b220f2f7cb..00000000000 --- a/contracts/test/v0.8/automation/AutomationRegistry2_2.test.ts +++ /dev/null @@ -1,5962 +0,0 @@ -import { ethers } from 'hardhat' -import { loadFixture } from '@nomicfoundation/hardhat-network-helpers' -import { assert, expect } from 'chai' -import { - BigNumber, - BigNumberish, - BytesLike, - Contract, - ContractFactory, - ContractReceipt, - ContractTransaction, - Signer, - Wallet, -} from 'ethers' -import { evmRevert, evmRevertCustomError } from '../../test-helpers/matchers' -import { getUsers, Personas } from '../../test-helpers/setup' -import { randomAddress, toWei } from '../../test-helpers/helpers' -import { StreamsLookupUpkeep__factory as StreamsLookupUpkeepFactory } from '../../../typechain/factories/StreamsLookupUpkeep__factory' -import { MockV3Aggregator__factory as MockV3AggregatorFactory } from '../../../typechain/factories/MockV3Aggregator__factory' -import { UpkeepMock__factory as UpkeepMockFactory } from '../../../typechain/factories/UpkeepMock__factory' -import { UpkeepAutoFunder__factory as UpkeepAutoFunderFactory } from '../../../typechain/factories/UpkeepAutoFunder__factory' -import { MockArbGasInfo__factory as MockArbGasInfoFactory } from '../../../typechain/factories/MockArbGasInfo__factory' -import { MockOVMGasPriceOracle__factory as MockOVMGasPriceOracleFactory } from '../../../typechain/factories/MockOVMGasPriceOracle__factory' -import { ChainModuleBase__factory as ChainModuleBaseFactory } from '../../../typechain/factories/ChainModuleBase__factory' -import { ArbitrumModule__factory as ArbitrumModuleFactory } from '../../../typechain/factories/ArbitrumModule__factory' -import { OptimismModuleV2__factory as OptimismModuleV2Factory } from '../../../typechain/factories/OptimismModuleV2__factory' -import { ILogAutomation__factory as ILogAutomationactory } from '../../../typechain/factories/ILogAutomation__factory' -import { IAutomationForwarder__factory as IAutomationForwarderFactory } from '../../../typechain/factories/IAutomationForwarder__factory' -import { MockArbSys__factory as MockArbSysFactory } from '../../../typechain/factories/MockArbSys__factory' -import { AutomationCompatibleUtils } from '../../../typechain/AutomationCompatibleUtils' -import { MockArbGasInfo } from '../../../typechain/MockArbGasInfo' -import { MockOVMGasPriceOracle } from '../../../typechain/MockOVMGasPriceOracle' -import { StreamsLookupUpkeep } from '../../../typechain/StreamsLookupUpkeep' -import { MockV3Aggregator } from '../../../typechain/MockV3Aggregator' -import { UpkeepMock } from '../../../typechain/UpkeepMock' -import { ChainModuleBase } from '../../../typechain/ChainModuleBase' -import { ArbitrumModule } from '../../../typechain/ArbitrumModule' -import { OptimismModuleV2 } from '../../../typechain/OptimismModuleV2' -import { UpkeepTranscoder } from '../../../typechain/UpkeepTranscoder' -import { IChainModule, UpkeepAutoFunder } from '../../../typechain' -import { - CancelledUpkeepReportEvent, - IAutomationRegistryMaster as IAutomationRegistry, - ReorgedUpkeepReportEvent, - StaleUpkeepReportEvent, - UpkeepPerformedEvent, -} from '../../../typechain/IAutomationRegistryMaster' -import { - deployMockContract, - MockContract, -} from '@ethereum-waffle/mock-contract' -import { deployRegistry22 } from './helpers' - -const describeMaybe = process.env.SKIP_SLOW ? describe.skip : describe -const itMaybe = process.env.SKIP_SLOW ? it.skip : it - -// copied from AutomationRegistryInterface2_2.sol -enum UpkeepFailureReason { - NONE, - UPKEEP_CANCELLED, - UPKEEP_PAUSED, - TARGET_CHECK_REVERTED, - UPKEEP_NOT_NEEDED, - PERFORM_DATA_EXCEEDS_LIMIT, - INSUFFICIENT_BALANCE, - CHECK_CALLBACK_REVERTED, - REVERT_DATA_EXCEEDS_LIMIT, - REGISTRY_PAUSED, -} - -// copied from AutomationRegistryBase2_2.sol -enum Trigger { - CONDITION, - LOG, -} - -// un-exported types that must be extracted from the utils contract -type Report = Parameters[0] -type LogTrigger = Parameters[0] -type ConditionalTrigger = Parameters< - AutomationCompatibleUtils['_conditionalTrigger'] ->[0] -type Log = Parameters[0] - -// ----------------------------------------------------------------------------------------------- - -// These values should match the constants declared in registry -let registryConditionalOverhead: BigNumber -let registryLogOverhead: BigNumber -let registryPerSignerGasOverhead: BigNumber -let registryPerPerformByteGasOverhead: BigNumber -let registryTransmitCalldataFixedBytesOverhead: BigNumber -let registryTransmitCalldataPerSignerBytesOverhead: BigNumber -let cancellationDelay: number - -// This is the margin for gas that we test for. Gas charged should always be greater -// than total gas used in tx but should not increase beyond this margin -const gasCalculationMargin = BigNumber.from(5000) -// This is the margin for gas overhead estimation in checkUpkeep. The estimated gas -// overhead should be larger than actual gas overhead but should not increase beyond this margin -const gasEstimationMargin = BigNumber.from(5000) - -const linkEth = BigNumber.from(5000000000000000) // 1 Link = 0.005 Eth -const gasWei = BigNumber.from(1000000000) // 1 gwei -// ----------------------------------------------------------------------------------------------- -// test-wide configs for upkeeps -const linkDivisibility = BigNumber.from('1000000000000000000') -const performGas = BigNumber.from('1000000') -const paymentPremiumBase = BigNumber.from('1000000000') -const paymentPremiumPPB = BigNumber.from('250000000') -const flatFeeMicroLink = BigNumber.from(0) - -const randomBytes = '0x1234abcd' -const emptyBytes = '0x' -const emptyBytes32 = - '0x0000000000000000000000000000000000000000000000000000000000000000' - -const transmitGasOverhead = 1_000_000 -const checkGasOverhead = 500_000 - -const stalenessSeconds = BigNumber.from(43820) -const gasCeilingMultiplier = BigNumber.from(2) -const checkGasLimit = BigNumber.from(10000000) -const fallbackGasPrice = gasWei.mul(BigNumber.from('2')) -const fallbackLinkPrice = linkEth.div(BigNumber.from('2')) -const maxCheckDataSize = BigNumber.from(1000) -const maxPerformDataSize = BigNumber.from(1000) -const maxRevertDataSize = BigNumber.from(1000) -const maxPerformGas = BigNumber.from(5000000) -const minUpkeepSpend = BigNumber.from(0) -const f = 1 -const offchainVersion = 1 -const offchainBytes = '0x' -const zeroAddress = ethers.constants.AddressZero -const epochAndRound5_1 = - '0x0000000000000000000000000000000000000000000000000000000000000501' - -let logTriggerConfig: string - -// ----------------------------------------------------------------------------------------------- - -// Smart contract factories -let linkTokenFactory: ContractFactory -let mockArbGasInfoFactory: MockArbGasInfoFactory -let mockOVMGasPriceOracleFactory: MockOVMGasPriceOracleFactory -let mockV3AggregatorFactory: MockV3AggregatorFactory -let upkeepMockFactory: UpkeepMockFactory -let upkeepAutoFunderFactory: UpkeepAutoFunderFactory -let chainModuleBaseFactory: ChainModuleBaseFactory -let arbitrumModuleFactory: ArbitrumModuleFactory -let optimismModuleV2Factory: OptimismModuleV2Factory -let streamsLookupUpkeepFactory: StreamsLookupUpkeepFactory -let personas: Personas - -// contracts -let linkToken: Contract -let linkEthFeed: MockV3Aggregator -let gasPriceFeed: MockV3Aggregator -let registry: IAutomationRegistry // default registry, used for most tests -let arbRegistry: IAutomationRegistry // arbitrum registry -let opRegistry: IAutomationRegistry // optimism registry -let mgRegistry: IAutomationRegistry // "migrate registry" used in migration tests -let blankRegistry: IAutomationRegistry // used to test initial configurations -let mockArbGasInfo: MockArbGasInfo -let mockOVMGasPriceOracle: MockOVMGasPriceOracle -let mock: UpkeepMock -let autoFunderUpkeep: UpkeepAutoFunder -let ltUpkeep: MockContract -let transcoder: UpkeepTranscoder -let chainModuleBase: ChainModuleBase -let arbitrumModule: ArbitrumModule -let optimismModule: OptimismModuleV2 -let streamsLookupUpkeep: StreamsLookupUpkeep -let automationUtils: AutomationCompatibleUtils - -function now() { - return Math.floor(Date.now() / 1000) -} - -async function getUpkeepID(tx: ContractTransaction): Promise { - const receipt = await tx.wait() - for (const event of receipt.events || []) { - if ( - event.args && - event.eventSignature == 'UpkeepRegistered(uint256,uint32,address)' - ) { - return event.args[0] - } - } - throw new Error('could not find upkeep ID in tx event logs') -} - -const getTriggerType = (upkeepId: BigNumber): Trigger => { - const hexBytes = ethers.utils.defaultAbiCoder.encode(['uint256'], [upkeepId]) - const bytes = ethers.utils.arrayify(hexBytes) - for (let idx = 4; idx < 15; idx++) { - if (bytes[idx] != 0) { - return Trigger.CONDITION - } - } - return bytes[15] as Trigger -} - -const encodeBlockTrigger = (conditionalTrigger: ConditionalTrigger) => { - return ( - '0x' + - automationUtils.interface - .encodeFunctionData('_conditionalTrigger', [conditionalTrigger]) - .slice(10) - ) -} - -const encodeLogTrigger = (logTrigger: LogTrigger) => { - return ( - '0x' + - automationUtils.interface - .encodeFunctionData('_logTrigger', [logTrigger]) - .slice(10) - ) -} - -const encodeLog = (log: Log) => { - return ( - '0x' + automationUtils.interface.encodeFunctionData('_log', [log]).slice(10) - ) -} - -const encodeReport = (report: Report) => { - return ( - '0x' + - automationUtils.interface.encodeFunctionData('_report', [report]).slice(10) - ) -} - -type UpkeepData = { - Id: BigNumberish - performGas: BigNumberish - performData: BytesLike - trigger: BytesLike -} - -const makeReport = (upkeeps: UpkeepData[]) => { - const upkeepIds = upkeeps.map((u) => u.Id) - const performGases = upkeeps.map((u) => u.performGas) - const triggers = upkeeps.map((u) => u.trigger) - const performDatas = upkeeps.map((u) => u.performData) - return encodeReport({ - fastGasWei: gasWei, - linkNative: linkEth, - upkeepIds, - gasLimits: performGases, - triggers, - performDatas, - }) -} - -const makeLatestBlockReport = async (upkeepsIDs: BigNumberish[]) => { - const latestBlock = await ethers.provider.getBlock('latest') - const upkeeps: UpkeepData[] = [] - for (let i = 0; i < upkeepsIDs.length; i++) { - upkeeps.push({ - Id: upkeepsIDs[i], - performGas, - trigger: encodeBlockTrigger({ - blockNum: latestBlock.number, - blockHash: latestBlock.hash, - }), - performData: '0x', - }) - } - return makeReport(upkeeps) -} - -const signReport = ( - reportContext: string[], - report: any, - signers: Wallet[], -) => { - const reportDigest = ethers.utils.keccak256(report) - const packedArgs = ethers.utils.solidityPack( - ['bytes32', 'bytes32[3]'], - [reportDigest, reportContext], - ) - const packedDigest = ethers.utils.keccak256(packedArgs) - - const signatures = [] - for (const signer of signers) { - signatures.push(signer._signingKey().signDigest(packedDigest)) - } - const vs = signatures.map((i) => '0' + (i.v - 27).toString(16)).join('') - return { - vs: '0x' + vs.padEnd(64, '0'), - rs: signatures.map((i) => i.r), - ss: signatures.map((i) => i.s), - } -} - -const parseUpkeepPerformedLogs = (receipt: ContractReceipt) => { - const parsedLogs = [] - for (const rawLog of receipt.logs) { - try { - const log = registry.interface.parseLog(rawLog) - if ( - log.name == - registry.interface.events[ - 'UpkeepPerformed(uint256,bool,uint96,uint256,uint256,bytes)' - ].name - ) { - parsedLogs.push(log as unknown as UpkeepPerformedEvent) - } - } catch { - continue - } - } - return parsedLogs -} - -const parseReorgedUpkeepReportLogs = (receipt: ContractReceipt) => { - const parsedLogs = [] - for (const rawLog of receipt.logs) { - try { - const log = registry.interface.parseLog(rawLog) - if ( - log.name == - registry.interface.events['ReorgedUpkeepReport(uint256,bytes)'].name - ) { - parsedLogs.push(log as unknown as ReorgedUpkeepReportEvent) - } - } catch { - continue - } - } - return parsedLogs -} - -const parseStaleUpkeepReportLogs = (receipt: ContractReceipt) => { - const parsedLogs = [] - for (const rawLog of receipt.logs) { - try { - const log = registry.interface.parseLog(rawLog) - if ( - log.name == - registry.interface.events['StaleUpkeepReport(uint256,bytes)'].name - ) { - parsedLogs.push(log as unknown as StaleUpkeepReportEvent) - } - } catch { - continue - } - } - return parsedLogs -} - -const parseCancelledUpkeepReportLogs = (receipt: ContractReceipt) => { - const parsedLogs = [] - for (const rawLog of receipt.logs) { - try { - const log = registry.interface.parseLog(rawLog) - if ( - log.name == - registry.interface.events['CancelledUpkeepReport(uint256,bytes)'].name - ) { - parsedLogs.push(log as unknown as CancelledUpkeepReportEvent) - } - } catch { - continue - } - } - return parsedLogs -} - -describe('AutomationRegistry2_2', () => { - let owner: Signer - let keeper1: Signer - let keeper2: Signer - let keeper3: Signer - let keeper4: Signer - let keeper5: Signer - let nonkeeper: Signer - let signer1: Wallet - let signer2: Wallet - let signer3: Wallet - let signer4: Wallet - let signer5: Wallet - let admin: Signer - let payee1: Signer - let payee2: Signer - let payee3: Signer - let payee4: Signer - let payee5: Signer - - let upkeepId: BigNumber // conditional upkeep - let afUpkeepId: BigNumber // auto funding upkeep - let logUpkeepId: BigNumber // log trigger upkeepID - let streamsLookupUpkeepId: BigNumber // streams lookup upkeep - const numUpkeeps = 4 // see above - let keeperAddresses: string[] - let payees: string[] - let signers: Wallet[] - let signerAddresses: string[] - let config: any - let arbConfig: any - let opConfig: any - let baseConfig: Parameters - let arbConfigParams: Parameters - let opConfigParams: Parameters - let upkeepManager: string - - before(async () => { - personas = (await getUsers()).personas - - const convFactory = await ethers.getContractFactory( - 'AutomationCompatibleUtils', - ) - automationUtils = await convFactory.deploy() - - linkTokenFactory = await ethers.getContractFactory( - 'src/v0.8/shared/test/helpers/LinkTokenTestHelper.sol:LinkTokenTestHelper', - ) - // need full path because there are two contracts with name MockV3Aggregator - mockV3AggregatorFactory = (await ethers.getContractFactory( - 'src/v0.8/tests/MockV3Aggregator.sol:MockV3Aggregator', - )) as unknown as MockV3AggregatorFactory - mockArbGasInfoFactory = await ethers.getContractFactory('MockArbGasInfo') - mockOVMGasPriceOracleFactory = await ethers.getContractFactory( - 'MockOVMGasPriceOracle', - ) - upkeepMockFactory = await ethers.getContractFactory('UpkeepMock') - upkeepAutoFunderFactory = - await ethers.getContractFactory('UpkeepAutoFunder') - chainModuleBaseFactory = await ethers.getContractFactory('ChainModuleBase') - arbitrumModuleFactory = await ethers.getContractFactory('ArbitrumModule') - optimismModuleV2Factory = - await ethers.getContractFactory('OptimismModuleV2') - streamsLookupUpkeepFactory = await ethers.getContractFactory( - 'StreamsLookupUpkeep', - ) - - owner = personas.Default - keeper1 = personas.Carol - keeper2 = personas.Eddy - keeper3 = personas.Nancy - keeper4 = personas.Norbert - keeper5 = personas.Nick - nonkeeper = personas.Ned - admin = personas.Neil - payee1 = personas.Nelly - payee2 = personas.Norbert - payee3 = personas.Nick - payee4 = personas.Eddy - payee5 = personas.Carol - upkeepManager = await personas.Norbert.getAddress() - // signers - signer1 = new ethers.Wallet( - '0x7777777000000000000000000000000000000000000000000000000000000001', - ) - signer2 = new ethers.Wallet( - '0x7777777000000000000000000000000000000000000000000000000000000002', - ) - signer3 = new ethers.Wallet( - '0x7777777000000000000000000000000000000000000000000000000000000003', - ) - signer4 = new ethers.Wallet( - '0x7777777000000000000000000000000000000000000000000000000000000004', - ) - signer5 = new ethers.Wallet( - '0x7777777000000000000000000000000000000000000000000000000000000005', - ) - - keeperAddresses = [ - await keeper1.getAddress(), - await keeper2.getAddress(), - await keeper3.getAddress(), - await keeper4.getAddress(), - await keeper5.getAddress(), - ] - payees = [ - await payee1.getAddress(), - await payee2.getAddress(), - await payee3.getAddress(), - await payee4.getAddress(), - await payee5.getAddress(), - ] - signers = [signer1, signer2, signer3, signer4, signer5] - - // We append 26 random addresses to keepers, payees and signers to get a system of 31 oracles - // This allows f value of 1 - 10 - for (let i = 0; i < 26; i++) { - keeperAddresses.push(randomAddress()) - payees.push(randomAddress()) - signers.push(ethers.Wallet.createRandom()) - } - signerAddresses = [] - for (const signer of signers) { - signerAddresses.push(await signer.getAddress()) - } - - logTriggerConfig = - '0x' + - automationUtils.interface - .encodeFunctionData('_logTriggerConfig', [ - { - contractAddress: randomAddress(), - filterSelector: 0, - topic0: ethers.utils.randomBytes(32), - topic1: ethers.utils.randomBytes(32), - topic2: ethers.utils.randomBytes(32), - topic3: ethers.utils.randomBytes(32), - }, - ]) - .slice(10) - }) - - // This function is similar to registry's _calculatePaymentAmount - // It uses global fastGasWei, linkEth, and assumes isExecution = false (gasFee = fastGasWei*multiplier) - // rest of the parameters are the same - const linkForGas = ( - upkeepGasSpent: BigNumber, - gasOverhead: BigNumber, - gasMultiplier: BigNumber, - premiumPPB: BigNumber, - flatFee: BigNumber, - l1CostWei?: BigNumber, - ) => { - l1CostWei = l1CostWei === undefined ? BigNumber.from(0) : l1CostWei - - const gasSpent = gasOverhead.add(BigNumber.from(upkeepGasSpent)) - const base = gasWei - .mul(gasMultiplier) - .mul(gasSpent) - .mul(linkDivisibility) - .div(linkEth) - const l1Fee = l1CostWei.mul(linkDivisibility).div(linkEth) - const gasPayment = base.add(l1Fee) - - const premium = gasWei - .mul(gasMultiplier) - .mul(upkeepGasSpent) - .add(l1CostWei) - .mul(linkDivisibility) - .div(linkEth) - .mul(premiumPPB) - .div(paymentPremiumBase) - .add(BigNumber.from(flatFee).mul('1000000000000')) - - return { - total: gasPayment.add(premium), - gasPayment, - premium, - } - } - - const verifyMaxPayment = async ( - registry: IAutomationRegistry, - chainModule: IChainModule, - maxl1CostWeWithoutMultiplier?: BigNumber, - ) => { - type TestCase = { - name: string - multiplier: number - gas: number - premium: number - flatFee: number - } - - const tests: TestCase[] = [ - { - name: 'no fees', - multiplier: 1, - gas: 100000, - premium: 0, - flatFee: 0, - }, - { - name: 'basic fees', - multiplier: 1, - gas: 100000, - premium: 250000000, - flatFee: 1000000, - }, - { - name: 'max fees', - multiplier: 3, - gas: 10000000, - premium: 250000000, - flatFee: 1000000, - }, - ] - - const fPlusOne = BigNumber.from(f + 1) - const chainModuleOverheads = await chainModule.getGasOverhead() - const totalConditionalOverhead = registryConditionalOverhead - .add(registryPerSignerGasOverhead.mul(fPlusOne)) - .add( - registryPerPerformByteGasOverhead - .add(chainModuleOverheads.chainModulePerByteOverhead) - .mul( - maxPerformDataSize - .add(registryTransmitCalldataFixedBytesOverhead) - .add( - registryTransmitCalldataPerSignerBytesOverhead.mul(fPlusOne), - ), - ), - ) - .add(chainModuleOverheads.chainModuleFixedOverhead) - - const totalLogOverhead = registryLogOverhead - .add(registryPerSignerGasOverhead.mul(fPlusOne)) - .add( - registryPerPerformByteGasOverhead - .add(chainModuleOverheads.chainModulePerByteOverhead) - .mul( - maxPerformDataSize - .add(registryTransmitCalldataFixedBytesOverhead) - .add( - registryTransmitCalldataPerSignerBytesOverhead.mul(fPlusOne), - ), - ), - ) - .add(chainModuleOverheads.chainModuleFixedOverhead) - - for (const test of tests) { - await registry.connect(owner).setConfigTypeSafe( - signerAddresses, - keeperAddresses, - f, - { - paymentPremiumPPB: test.premium, - flatFeeMicroLink: test.flatFee, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier: test.multiplier, - minUpkeepSpend, - maxCheckDataSize, - maxPerformDataSize, - maxRevertDataSize, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrars: [], - upkeepPrivilegeManager: upkeepManager, - chainModule: chainModule.address, - reorgProtectionEnabled: true, - }, - offchainVersion, - offchainBytes, - ) - - const conditionalPrice = await registry.getMaxPaymentForGas( - Trigger.CONDITION, - test.gas, - ) - expect(conditionalPrice).to.equal( - linkForGas( - BigNumber.from(test.gas), - totalConditionalOverhead, - BigNumber.from(test.multiplier), - BigNumber.from(test.premium), - BigNumber.from(test.flatFee), - maxl1CostWeWithoutMultiplier?.mul(BigNumber.from(test.multiplier)), - ).total, - ) - - const logPrice = await registry.getMaxPaymentForGas(Trigger.LOG, test.gas) - expect(logPrice).to.equal( - linkForGas( - BigNumber.from(test.gas), - totalLogOverhead, - BigNumber.from(test.multiplier), - BigNumber.from(test.premium), - BigNumber.from(test.flatFee), - maxl1CostWeWithoutMultiplier?.mul(BigNumber.from(test.multiplier)), - ).total, - ) - } - } - - const verifyConsistentAccounting = async ( - maxAllowedSpareChange: BigNumber, - ) => { - const expectedLinkBalance = (await registry.getState()).state - .expectedLinkBalance - const linkTokenBalance = await linkToken.balanceOf(registry.address) - const upkeepIdBalance = (await registry.getUpkeep(upkeepId)).balance - let totalKeeperBalance = BigNumber.from(0) - for (let i = 0; i < keeperAddresses.length; i++) { - totalKeeperBalance = totalKeeperBalance.add( - (await registry.getTransmitterInfo(keeperAddresses[i])).balance, - ) - } - const ownerBalance = (await registry.getState()).state.ownerLinkBalance - assert.isTrue(expectedLinkBalance.eq(linkTokenBalance)) - assert.isTrue( - upkeepIdBalance - .add(totalKeeperBalance) - .add(ownerBalance) - .lte(expectedLinkBalance), - ) - assert.isTrue( - expectedLinkBalance - .sub(upkeepIdBalance) - .sub(totalKeeperBalance) - .sub(ownerBalance) - .lte(maxAllowedSpareChange), - ) - } - - interface GetTransmitTXOptions { - numSigners?: number - startingSignerIndex?: number - gasLimit?: BigNumberish - gasPrice?: BigNumberish - performGas?: BigNumberish - performDatas?: string[] - checkBlockNum?: number - checkBlockHash?: string - logBlockHash?: BytesLike - txHash?: BytesLike - logIndex?: number - timestamp?: number - } - - const getTransmitTx = async ( - registry: IAutomationRegistry, - transmitter: Signer, - upkeepIds: BigNumber[], - overrides: GetTransmitTXOptions = {}, - ) => { - const latestBlock = await ethers.provider.getBlock('latest') - const configDigest = (await registry.getState()).state.latestConfigDigest - const config = { - numSigners: f + 1, - startingSignerIndex: 0, - performDatas: undefined, - performGas, - checkBlockNum: latestBlock.number, - checkBlockHash: latestBlock.hash, - logIndex: 0, - txHash: undefined, // assigned uniquely below - logBlockHash: undefined, // assigned uniquely below - timestamp: now(), - gasLimit: undefined, - gasPrice: undefined, - } - Object.assign(config, overrides) - const upkeeps: UpkeepData[] = [] - for (let i = 0; i < upkeepIds.length; i++) { - let trigger: string - switch (getTriggerType(upkeepIds[i])) { - case Trigger.CONDITION: - trigger = encodeBlockTrigger({ - blockNum: config.checkBlockNum, - blockHash: config.checkBlockHash, - }) - break - case Trigger.LOG: - trigger = encodeLogTrigger({ - logBlockHash: config.logBlockHash || ethers.utils.randomBytes(32), - txHash: config.txHash || ethers.utils.randomBytes(32), - logIndex: config.logIndex, - blockNum: config.checkBlockNum, - blockHash: config.checkBlockHash, - }) - break - } - upkeeps.push({ - Id: upkeepIds[i], - performGas: config.performGas, - trigger, - performData: config.performDatas ? config.performDatas[i] : '0x', - }) - } - - const report = makeReport(upkeeps) - const reportContext = [configDigest, epochAndRound5_1, emptyBytes32] - const sigs = signReport( - reportContext, - report, - signers.slice( - config.startingSignerIndex, - config.startingSignerIndex + config.numSigners, - ), - ) - - type txOverride = { - gasLimit?: BigNumberish | Promise - gasPrice?: BigNumberish | Promise - } - const txOverrides: txOverride = {} - if (config.gasLimit) { - txOverrides.gasLimit = config.gasLimit - } - if (config.gasPrice) { - txOverrides.gasPrice = config.gasPrice - } - - return registry - .connect(transmitter) - .transmit( - [configDigest, epochAndRound5_1, emptyBytes32], - report, - sigs.rs, - sigs.ss, - sigs.vs, - txOverrides, - ) - } - - const getTransmitTxWithReport = async ( - registry: IAutomationRegistry, - transmitter: Signer, - report: BytesLike, - ) => { - const configDigest = (await registry.getState()).state.latestConfigDigest - const reportContext = [configDigest, epochAndRound5_1, emptyBytes32] - const sigs = signReport(reportContext, report, signers.slice(0, f + 1)) - - return registry - .connect(transmitter) - .transmit( - [configDigest, epochAndRound5_1, emptyBytes32], - report, - sigs.rs, - sigs.ss, - sigs.vs, - ) - } - - const setup = async () => { - linkToken = await linkTokenFactory.connect(owner).deploy() - gasPriceFeed = await mockV3AggregatorFactory - .connect(owner) - .deploy(0, gasWei) - linkEthFeed = await mockV3AggregatorFactory - .connect(owner) - .deploy(9, linkEth) - const upkeepTranscoderFactory = await ethers.getContractFactory( - 'UpkeepTranscoder4_0', - ) - transcoder = await upkeepTranscoderFactory.connect(owner).deploy() - mockArbGasInfo = await mockArbGasInfoFactory.connect(owner).deploy() - mockOVMGasPriceOracle = await mockOVMGasPriceOracleFactory - .connect(owner) - .deploy() - chainModuleBase = await chainModuleBaseFactory.connect(owner).deploy() - arbitrumModule = await arbitrumModuleFactory.connect(owner).deploy() - optimismModule = await optimismModuleV2Factory.connect(owner).deploy() - streamsLookupUpkeep = await streamsLookupUpkeepFactory - .connect(owner) - .deploy( - BigNumber.from('10000'), - BigNumber.from('100'), - false /* useArbBlock */, - true /* staging */, - false /* verify mercury response */, - ) - - const arbOracleCode = await ethers.provider.send('eth_getCode', [ - mockArbGasInfo.address, - ]) - await ethers.provider.send('hardhat_setCode', [ - '0x000000000000000000000000000000000000006C', - arbOracleCode, - ]) - - const optOracleCode = await ethers.provider.send('eth_getCode', [ - mockOVMGasPriceOracle.address, - ]) - await ethers.provider.send('hardhat_setCode', [ - '0x420000000000000000000000000000000000000F', - optOracleCode, - ]) - - const mockArbSys = await new MockArbSysFactory(owner).deploy() - const arbSysCode = await ethers.provider.send('eth_getCode', [ - mockArbSys.address, - ]) - await ethers.provider.send('hardhat_setCode', [ - '0x0000000000000000000000000000000000000064', - arbSysCode, - ]) - - config = { - paymentPremiumPPB, - flatFeeMicroLink, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxCheckDataSize, - maxPerformDataSize, - maxRevertDataSize, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrars: [], - upkeepPrivilegeManager: upkeepManager, - chainModule: chainModuleBase.address, - reorgProtectionEnabled: true, - } - - arbConfig = { ...config } - arbConfig.chainModule = arbitrumModule.address - opConfig = { ...config } - opConfig.chainModule = optimismModule.address - - baseConfig = [ - signerAddresses, - keeperAddresses, - f, - config, - offchainVersion, - offchainBytes, - ] - arbConfigParams = [ - signerAddresses, - keeperAddresses, - f, - arbConfig, - offchainVersion, - offchainBytes, - ] - opConfigParams = [ - signerAddresses, - keeperAddresses, - f, - opConfig, - offchainVersion, - offchainBytes, - ] - - registry = await deployRegistry22( - owner, - linkToken.address, - linkEthFeed.address, - gasPriceFeed.address, - zeroAddress, - ) - - arbRegistry = await deployRegistry22( - owner, - linkToken.address, - linkEthFeed.address, - gasPriceFeed.address, - zeroAddress, - ) - - opRegistry = await deployRegistry22( - owner, - linkToken.address, - linkEthFeed.address, - gasPriceFeed.address, - zeroAddress, - ) - - mgRegistry = await deployRegistry22( - owner, - linkToken.address, - linkEthFeed.address, - gasPriceFeed.address, - zeroAddress, - ) - - blankRegistry = await deployRegistry22( - owner, - linkToken.address, - linkEthFeed.address, - gasPriceFeed.address, - zeroAddress, - ) - - registryConditionalOverhead = await registry.getConditionalGasOverhead() - registryLogOverhead = await registry.getLogGasOverhead() - registryPerSignerGasOverhead = await registry.getPerSignerGasOverhead() - registryPerPerformByteGasOverhead = - await registry.getPerPerformByteGasOverhead() - registryTransmitCalldataFixedBytesOverhead = - await registry.getTransmitCalldataFixedBytesOverhead() - registryTransmitCalldataPerSignerBytesOverhead = - await registry.getTransmitCalldataPerSignerBytesOverhead() - cancellationDelay = (await registry.getCancellationDelay()).toNumber() - - await registry.connect(owner).setConfigTypeSafe(...baseConfig) - await mgRegistry.connect(owner).setConfigTypeSafe(...baseConfig) - await arbRegistry.connect(owner).setConfigTypeSafe(...arbConfigParams) - await opRegistry.connect(owner).setConfigTypeSafe(...opConfigParams) - for (const reg of [registry, arbRegistry, opRegistry, mgRegistry]) { - await reg.connect(owner).setPayees(payees) - await linkToken.connect(admin).approve(reg.address, toWei('1000')) - await linkToken.connect(owner).approve(reg.address, toWei('1000')) - } - - mock = await upkeepMockFactory.deploy() - await linkToken - .connect(owner) - .transfer(await admin.getAddress(), toWei('1000')) - let tx = await registry - .connect(owner) - [ - 'registerUpkeep(address,uint32,address,bytes,bytes)' - ](mock.address, performGas, await admin.getAddress(), randomBytes, '0x') - upkeepId = await getUpkeepID(tx) - - autoFunderUpkeep = await upkeepAutoFunderFactory - .connect(owner) - .deploy(linkToken.address, registry.address) - tx = await registry - .connect(owner) - [ - 'registerUpkeep(address,uint32,address,bytes,bytes)' - ](autoFunderUpkeep.address, performGas, autoFunderUpkeep.address, randomBytes, '0x') - afUpkeepId = await getUpkeepID(tx) - - ltUpkeep = await deployMockContract(owner, ILogAutomationactory.abi) - tx = await registry - .connect(owner) - [ - 'registerUpkeep(address,uint32,address,uint8,bytes,bytes,bytes)' - ](ltUpkeep.address, performGas, await admin.getAddress(), Trigger.LOG, '0x', logTriggerConfig, emptyBytes) - logUpkeepId = await getUpkeepID(tx) - - await autoFunderUpkeep.setUpkeepId(afUpkeepId) - // Give enough funds for upkeep as well as to the upkeep contract - await linkToken - .connect(owner) - .transfer(autoFunderUpkeep.address, toWei('1000')) - - tx = await registry - .connect(owner) - [ - 'registerUpkeep(address,uint32,address,bytes,bytes)' - ](streamsLookupUpkeep.address, performGas, await admin.getAddress(), randomBytes, '0x') - streamsLookupUpkeepId = await getUpkeepID(tx) - } - - const getMultipleUpkeepsDeployedAndFunded = async ( - numPassingConditionalUpkeeps: number, - numPassingLogUpkeeps: number, - numFailingUpkeeps: number, - ) => { - const passingConditionalUpkeepIds = [] - const passingLogUpkeepIds = [] - const failingUpkeepIds = [] - for (let i = 0; i < numPassingConditionalUpkeeps; i++) { - const mock = await upkeepMockFactory.deploy() - await mock.setCanPerform(true) - await mock.setPerformGasToBurn(BigNumber.from('0')) - const tx = await registry - .connect(owner) - [ - 'registerUpkeep(address,uint32,address,bytes,bytes)' - ](mock.address, performGas, await admin.getAddress(), randomBytes, '0x') - const condUpkeepId = await getUpkeepID(tx) - passingConditionalUpkeepIds.push(condUpkeepId) - - // Add funds to passing upkeeps - await registry.connect(admin).addFunds(condUpkeepId, toWei('100')) - } - for (let i = 0; i < numPassingLogUpkeeps; i++) { - const mock = await upkeepMockFactory.deploy() - await mock.setCanPerform(true) - await mock.setPerformGasToBurn(BigNumber.from('0')) - const tx = await registry - .connect(owner) - [ - 'registerUpkeep(address,uint32,address,uint8,bytes,bytes,bytes)' - ](mock.address, performGas, await admin.getAddress(), Trigger.LOG, '0x', logTriggerConfig, emptyBytes) - const logUpkeepId = await getUpkeepID(tx) - passingLogUpkeepIds.push(logUpkeepId) - - // Add funds to passing upkeeps - await registry.connect(admin).addFunds(logUpkeepId, toWei('100')) - } - for (let i = 0; i < numFailingUpkeeps; i++) { - const mock = await upkeepMockFactory.deploy() - await mock.setCanPerform(true) - await mock.setPerformGasToBurn(BigNumber.from('0')) - const tx = await registry - .connect(owner) - [ - 'registerUpkeep(address,uint32,address,bytes,bytes)' - ](mock.address, performGas, await admin.getAddress(), randomBytes, '0x') - const failingUpkeepId = await getUpkeepID(tx) - failingUpkeepIds.push(failingUpkeepId) - } - return { - passingConditionalUpkeepIds, - passingLogUpkeepIds, - failingUpkeepIds, - } - } - - beforeEach(async () => { - await loadFixture(setup) - }) - - describe('#transmit', () => { - const fArray = [1, 5, 10] - - it('reverts when registry is paused', async () => { - await registry.connect(owner).pause() - await evmRevertCustomError( - getTransmitTx(registry, keeper1, [upkeepId]), - registry, - 'RegistryPaused', - ) - }) - - it('reverts when called by non active transmitter', async () => { - await evmRevertCustomError( - getTransmitTx(registry, payee1, [upkeepId]), - registry, - 'OnlyActiveTransmitters', - ) - }) - - it('reverts when report data lengths mismatches', async () => { - const upkeepIds = [] - const gasLimits: BigNumber[] = [] - const triggers: string[] = [] - const performDatas = [] - - upkeepIds.push(upkeepId) - gasLimits.push(performGas) - triggers.push('0x') - performDatas.push('0x') - // Push an extra perform data - performDatas.push('0x') - - const report = encodeReport({ - fastGasWei: 0, - linkNative: 0, - upkeepIds, - gasLimits, - triggers, - performDatas, - }) - - await evmRevertCustomError( - getTransmitTxWithReport(registry, keeper1, report), - registry, - 'InvalidReport', - ) - }) - - it('returns early when invalid upkeepIds are included in report', async () => { - const tx = await getTransmitTx(registry, keeper1, [ - upkeepId.add(BigNumber.from('1')), - ]) - - const receipt = await tx.wait() - const cancelledUpkeepReportLogs = parseCancelledUpkeepReportLogs(receipt) - // exactly 1 CancelledUpkeepReport log should be emitted - assert.equal(cancelledUpkeepReportLogs.length, 1) - }) - - it('performs even when the upkeep has insufficient funds and the upkeep pays out all the remaining balance', async () => { - // add very little fund to this upkeep - await registry.connect(admin).addFunds(upkeepId, BigNumber.from(10)) - const tx = await getTransmitTx(registry, keeper1, [upkeepId]) - const receipt = await tx.wait() - // the upkeep is underfunded in transmit but still performed - const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) - assert.equal(upkeepPerformedLogs.length, 1) - const balance = (await registry.getUpkeep(upkeepId)).balance - assert.equal(balance.toNumber(), 0) - }) - - context('When the upkeep is funded', async () => { - beforeEach(async () => { - // Fund the upkeep - await Promise.all([ - registry.connect(admin).addFunds(upkeepId, toWei('100')), - registry.connect(admin).addFunds(logUpkeepId, toWei('100')), - ]) - }) - - it('handles duplicate upkeepIDs', async () => { - const tests: [string, BigNumber, number, number][] = [ - // [name, upkeep, num stale, num performed] - ['conditional', upkeepId, 1, 1], // checkBlocks must be sequential - ['log-trigger', logUpkeepId, 0, 2], // logs are deduped based on the "trigger ID" - ] - for (const [type, id, nStale, nPerformed] of tests) { - const tx = await getTransmitTx(registry, keeper1, [id, id]) - const receipt = await tx.wait() - const staleUpkeepReport = parseStaleUpkeepReportLogs(receipt) - const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) - assert.equal( - staleUpkeepReport.length, - nStale, - `wrong log count for ${type} upkeep`, - ) - assert.equal( - upkeepPerformedLogs.length, - nPerformed, - `wrong log count for ${type} upkeep`, - ) - } - }) - - it('handles duplicate log triggers', async () => { - const logBlockHash = ethers.utils.randomBytes(32) - const txHash = ethers.utils.randomBytes(32) - const logIndex = 0 - const expectedDedupKey = ethers.utils.solidityKeccak256( - ['uint256', 'bytes32', 'bytes32', 'uint32'], - [logUpkeepId, logBlockHash, txHash, logIndex], - ) - assert.isFalse(await registry.hasDedupKey(expectedDedupKey)) - const tx = await getTransmitTx( - registry, - keeper1, - [logUpkeepId, logUpkeepId], - { logBlockHash, txHash, logIndex }, // will result in the same dedup key - ) - const receipt = await tx.wait() - const staleUpkeepReport = parseStaleUpkeepReportLogs(receipt) - const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) - assert.equal(staleUpkeepReport.length, 1) - assert.equal(upkeepPerformedLogs.length, 1) - assert.isTrue(await registry.hasDedupKey(expectedDedupKey)) - await expect(tx) - .to.emit(registry, 'DedupKeyAdded') - .withArgs(expectedDedupKey) - }) - - it('returns early when check block number is less than last perform (block)', async () => { - // First perform an upkeep to put last perform block number on upkeep state - const tx = await getTransmitTx(registry, keeper1, [upkeepId]) - await tx.wait() - const lastPerformed = (await registry.getUpkeep(upkeepId)) - .lastPerformedBlockNumber - const lastPerformBlock = await ethers.provider.getBlock(lastPerformed) - assert.equal(lastPerformed.toString(), tx.blockNumber?.toString()) - // Try to transmit a report which has checkBlockNumber = lastPerformed-1, should result in stale report - const transmitTx = await getTransmitTx(registry, keeper1, [upkeepId], { - checkBlockNum: lastPerformBlock.number - 1, - checkBlockHash: lastPerformBlock.parentHash, - }) - const receipt = await transmitTx.wait() - const staleUpkeepReportLogs = parseStaleUpkeepReportLogs(receipt) - // exactly 1 StaleUpkeepReportLogs log should be emitted - assert.equal(staleUpkeepReportLogs.length, 1) - }) - - it('handles case when check block hash does not match', async () => { - const tests: [string, BigNumber][] = [ - ['conditional', upkeepId], - ['log-trigger', logUpkeepId], - ] - for (const [type, id] of tests) { - const latestBlock = await ethers.provider.getBlock('latest') - // Try to transmit a report which has incorrect checkBlockHash - const tx = await getTransmitTx(registry, keeper1, [id], { - checkBlockNum: latestBlock.number - 1, - checkBlockHash: latestBlock.hash, // should be latestBlock.parentHash - }) - - const receipt = await tx.wait() - const reorgedUpkeepReportLogs = parseReorgedUpkeepReportLogs(receipt) - // exactly 1 ReorgedUpkeepReportLogs log should be emitted - assert.equal( - reorgedUpkeepReportLogs.length, - 1, - `wrong log count for ${type} upkeep`, - ) - } - }) - - it('handles case when check block number is older than 256 blocks', async () => { - for (let i = 0; i < 256; i++) { - await ethers.provider.send('evm_mine', []) - } - const tests: [string, BigNumber][] = [ - ['conditional', upkeepId], - ['log-trigger', logUpkeepId], - ] - for (const [type, id] of tests) { - const latestBlock = await ethers.provider.getBlock('latest') - const old = await ethers.provider.getBlock(latestBlock.number - 256) - // Try to transmit a report which has incorrect checkBlockHash - const tx = await getTransmitTx(registry, keeper1, [id], { - checkBlockNum: old.number, - checkBlockHash: old.hash, - }) - - const receipt = await tx.wait() - const reorgedUpkeepReportLogs = parseReorgedUpkeepReportLogs(receipt) - // exactly 1 ReorgedUpkeepReportLogs log should be emitted - assert.equal( - reorgedUpkeepReportLogs.length, - 1, - `wrong log count for ${type} upkeep`, - ) - } - }) - - it('allows bypassing reorg protection with empty blockhash', async () => { - const tests: [string, BigNumber][] = [ - ['conditional', upkeepId], - ['log-trigger', logUpkeepId], - ] - for (const [type, id] of tests) { - const latestBlock = await ethers.provider.getBlock('latest') - const tx = await getTransmitTx(registry, keeper1, [id], { - checkBlockNum: latestBlock.number, - checkBlockHash: emptyBytes32, - }) - const receipt = await tx.wait() - const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) - assert.equal( - upkeepPerformedLogs.length, - 1, - `wrong log count for ${type} upkeep`, - ) - } - }) - - it('allows bypassing reorg protection with reorgProtectionEnabled false config', async () => { - const tests: [string, BigNumber][] = [ - ['conditional', upkeepId], - ['log-trigger', logUpkeepId], - ] - const newConfig = config - newConfig.reorgProtectionEnabled = false - await registry // used to test initial configurations - .connect(owner) - .setConfigTypeSafe( - signerAddresses, - keeperAddresses, - f, - newConfig, - offchainVersion, - offchainBytes, - ) - - for (const [type, id] of tests) { - const latestBlock = await ethers.provider.getBlock('latest') - // Try to transmit a report which has incorrect checkBlockHash - const tx = await getTransmitTx(registry, keeper1, [id], { - checkBlockNum: latestBlock.number - 1, - checkBlockHash: latestBlock.hash, // should be latestBlock.parentHash - }) - - const receipt = await tx.wait() - const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) - assert.equal( - upkeepPerformedLogs.length, - 1, - `wrong log count for ${type} upkeep`, - ) - } - }) - - it('allows very old trigger block numbers when bypassing reorg protection with reorgProtectionEnabled config', async () => { - const newConfig = config - newConfig.reorgProtectionEnabled = false - await registry // used to test initial configurations - .connect(owner) - .setConfigTypeSafe( - signerAddresses, - keeperAddresses, - f, - newConfig, - offchainVersion, - offchainBytes, - ) - for (let i = 0; i < 256; i++) { - await ethers.provider.send('evm_mine', []) - } - const tests: [string, BigNumber][] = [ - ['conditional', upkeepId], - ['log-trigger', logUpkeepId], - ] - for (const [type, id] of tests) { - const latestBlock = await ethers.provider.getBlock('latest') - const old = await ethers.provider.getBlock(latestBlock.number - 256) - // Try to transmit a report which has incorrect checkBlockHash - const tx = await getTransmitTx(registry, keeper1, [id], { - checkBlockNum: old.number, - checkBlockHash: old.hash, - }) - - const receipt = await tx.wait() - const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) - assert.equal( - upkeepPerformedLogs.length, - 1, - `wrong log count for ${type} upkeep`, - ) - } - }) - - it('allows very old trigger block numbers when bypassing reorg protection with empty blockhash', async () => { - // mine enough blocks so that blockhash(1) is unavailable - for (let i = 0; i <= 256; i++) { - await ethers.provider.send('evm_mine', []) - } - const tests: [string, BigNumber][] = [ - ['conditional', upkeepId], - ['log-trigger', logUpkeepId], - ] - for (const [type, id] of tests) { - const tx = await getTransmitTx(registry, keeper1, [id], { - checkBlockNum: 1, - checkBlockHash: emptyBytes32, - }) - const receipt = await tx.wait() - const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) - assert.equal( - upkeepPerformedLogs.length, - 1, - `wrong log count for ${type} upkeep`, - ) - } - }) - - it('returns early when future block number is provided as trigger, irrespective of blockhash being present', async () => { - const tests: [string, BigNumber][] = [ - ['conditional', upkeepId], - ['log-trigger', logUpkeepId], - ] - for (const [type, id] of tests) { - const latestBlock = await ethers.provider.getBlock('latest') - - // Should fail when blockhash is empty - let tx = await getTransmitTx(registry, keeper1, [id], { - checkBlockNum: latestBlock.number + 100, - checkBlockHash: emptyBytes32, - }) - let receipt = await tx.wait() - let reorgedUpkeepReportLogs = parseReorgedUpkeepReportLogs(receipt) - // exactly 1 ReorgedUpkeepReportLogs log should be emitted - assert.equal( - reorgedUpkeepReportLogs.length, - 1, - `wrong log count for ${type} upkeep`, - ) - - // Should also fail when blockhash is not empty - tx = await getTransmitTx(registry, keeper1, [id], { - checkBlockNum: latestBlock.number + 100, - checkBlockHash: latestBlock.hash, - }) - receipt = await tx.wait() - reorgedUpkeepReportLogs = parseReorgedUpkeepReportLogs(receipt) - // exactly 1 ReorgedUpkeepReportLogs log should be emitted - assert.equal( - reorgedUpkeepReportLogs.length, - 1, - `wrong log count for ${type} upkeep`, - ) - } - }) - - it('returns early when future block number is provided as trigger, irrespective of reorgProtectionEnabled config', async () => { - const newConfig = config - newConfig.reorgProtectionEnabled = false - await registry // used to test initial configurations - .connect(owner) - .setConfigTypeSafe( - signerAddresses, - keeperAddresses, - f, - newConfig, - offchainVersion, - offchainBytes, - ) - const tests: [string, BigNumber][] = [ - ['conditional', upkeepId], - ['log-trigger', logUpkeepId], - ] - for (const [type, id] of tests) { - const latestBlock = await ethers.provider.getBlock('latest') - - // Should fail when blockhash is empty - let tx = await getTransmitTx(registry, keeper1, [id], { - checkBlockNum: latestBlock.number + 100, - checkBlockHash: emptyBytes32, - }) - let receipt = await tx.wait() - let reorgedUpkeepReportLogs = parseReorgedUpkeepReportLogs(receipt) - // exactly 1 ReorgedUpkeepReportLogs log should be emitted - assert.equal( - reorgedUpkeepReportLogs.length, - 1, - `wrong log count for ${type} upkeep`, - ) - - // Should also fail when blockhash is not empty - tx = await getTransmitTx(registry, keeper1, [id], { - checkBlockNum: latestBlock.number + 100, - checkBlockHash: latestBlock.hash, - }) - receipt = await tx.wait() - reorgedUpkeepReportLogs = parseReorgedUpkeepReportLogs(receipt) - // exactly 1 ReorgedUpkeepReportLogs log should be emitted - assert.equal( - reorgedUpkeepReportLogs.length, - 1, - `wrong log count for ${type} upkeep`, - ) - } - }) - - it('returns early when upkeep is cancelled and cancellation delay has gone', async () => { - const latestBlockReport = await makeLatestBlockReport([upkeepId]) - await registry.connect(admin).cancelUpkeep(upkeepId) - - for (let i = 0; i < cancellationDelay; i++) { - await ethers.provider.send('evm_mine', []) - } - - const tx = await getTransmitTxWithReport( - registry, - keeper1, - latestBlockReport, - ) - - const receipt = await tx.wait() - const cancelledUpkeepReportLogs = - parseCancelledUpkeepReportLogs(receipt) - // exactly 1 CancelledUpkeepReport log should be emitted - assert.equal(cancelledUpkeepReportLogs.length, 1) - }) - - it('does not revert if the target cannot execute', async () => { - await mock.setCanPerform(false) - const tx = await getTransmitTx(registry, keeper1, [upkeepId]) - - const receipt = await tx.wait() - const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) - // exactly 1 Upkeep Performed should be emitted - assert.equal(upkeepPerformedLogs.length, 1) - const upkeepPerformedLog = upkeepPerformedLogs[0] - - const success = upkeepPerformedLog.args.success - assert.equal(success, false) - }) - - it('does not revert if the target runs out of gas', async () => { - await mock.setCanPerform(false) - - const tx = await getTransmitTx(registry, keeper1, [upkeepId], { - performGas: 10, // too little gas - }) - - const receipt = await tx.wait() - const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) - // exactly 1 Upkeep Performed should be emitted - assert.equal(upkeepPerformedLogs.length, 1) - const upkeepPerformedLog = upkeepPerformedLogs[0] - - const success = upkeepPerformedLog.args.success - assert.equal(success, false) - }) - - it('reverts if not enough gas supplied', async () => { - await evmRevert( - getTransmitTx(registry, keeper1, [upkeepId], { - gasLimit: performGas, - }), - ) - }) - - it('executes the data passed to the registry', async () => { - await mock.setCanPerform(true) - - const tx = await getTransmitTx(registry, keeper1, [upkeepId], { - performDatas: [randomBytes], - }) - const receipt = await tx.wait() - - const upkeepPerformedWithABI = [ - 'event UpkeepPerformedWith(bytes upkeepData)', - ] - const iface = new ethers.utils.Interface(upkeepPerformedWithABI) - const parsedLogs = [] - for (let i = 0; i < receipt.logs.length; i++) { - const log = receipt.logs[i] - try { - parsedLogs.push(iface.parseLog(log)) - } catch (e) { - // ignore log - } - } - assert.equal(parsedLogs.length, 1) - assert.equal(parsedLogs[0].args.upkeepData, randomBytes) - }) - - it('uses actual execution price for payment and premium calculation', async () => { - // Actual multiplier is 2, but we set gasPrice to be 1x gasWei - const gasPrice = gasWei.mul(BigNumber.from('1')) - await mock.setCanPerform(true) - const registryPremiumBefore = (await registry.getState()).state - .totalPremium - const tx = await getTransmitTx(registry, keeper1, [upkeepId], { - gasPrice, - }) - const receipt = await tx.wait() - const registryPremiumAfter = (await registry.getState()).state - .totalPremium - const premium = registryPremiumAfter.sub(registryPremiumBefore) - - const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) - // exactly 1 Upkeep Performed should be emitted - assert.equal(upkeepPerformedLogs.length, 1) - const upkeepPerformedLog = upkeepPerformedLogs[0] - - const gasUsed = upkeepPerformedLog.args.gasUsed - const gasOverhead = upkeepPerformedLog.args.gasOverhead - const totalPayment = upkeepPerformedLog.args.totalPayment - - assert.equal( - linkForGas( - gasUsed, - gasOverhead, - BigNumber.from('1'), // Not the config multiplier, but the actual gas used - paymentPremiumPPB, - flatFeeMicroLink, - ).total.toString(), - totalPayment.toString(), - ) - - assert.equal( - linkForGas( - gasUsed, - gasOverhead, - BigNumber.from('1'), // Not the config multiplier, but the actual gas used - paymentPremiumPPB, - flatFeeMicroLink, - ).premium.toString(), - premium.toString(), - ) - }) - - it('only pays at a rate up to the gas ceiling [ @skip-coverage ]', async () => { - // Actual multiplier is 2, but we set gasPrice to be 10x - const gasPrice = gasWei.mul(BigNumber.from('10')) - await mock.setCanPerform(true) - - const tx = await getTransmitTx(registry, keeper1, [upkeepId], { - gasPrice, - }) - const receipt = await tx.wait() - const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) - // exactly 1 Upkeep Performed should be emitted - assert.equal(upkeepPerformedLogs.length, 1) - const upkeepPerformedLog = upkeepPerformedLogs[0] - - const gasUsed = upkeepPerformedLog.args.gasUsed - const gasOverhead = upkeepPerformedLog.args.gasOverhead - const totalPayment = upkeepPerformedLog.args.totalPayment - - assert.equal( - linkForGas( - gasUsed, - gasOverhead, - gasCeilingMultiplier, // Should be same with exisitng multiplier - paymentPremiumPPB, - flatFeeMicroLink, - ).total.toString(), - totalPayment.toString(), - ) - }) - - it('correctly accounts for l payment', async () => { - await mock.setCanPerform(true) - // Same as MockArbGasInfo.sol - const l1CostWeiArb = BigNumber.from(1000000) - - let tx = await arbRegistry - .connect(owner) - [ - 'registerUpkeep(address,uint32,address,bytes,bytes)' - ](mock.address, performGas, await admin.getAddress(), randomBytes, '0x') - const testUpkeepId = await getUpkeepID(tx) - await arbRegistry.connect(owner).addFunds(testUpkeepId, toWei('100')) - - // Do the thing - tx = await getTransmitTx( - arbRegistry, - keeper1, - [testUpkeepId], - - { gasPrice: gasWei.mul('5') }, // High gas price so that it gets capped - ) - const receipt = await tx.wait() - const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) - // exactly 1 Upkeep Performed should be emitted - assert.equal(upkeepPerformedLogs.length, 1) - const upkeepPerformedLog = upkeepPerformedLogs[0] - - const gasUsed = upkeepPerformedLog.args.gasUsed - const gasOverhead = upkeepPerformedLog.args.gasOverhead - const totalPayment = upkeepPerformedLog.args.totalPayment - - assert.equal( - linkForGas( - gasUsed, - gasOverhead, - gasCeilingMultiplier, - paymentPremiumPPB, - flatFeeMicroLink, - l1CostWeiArb, - ).total.toString(), - totalPayment.toString(), - ) - }) - - itMaybe('can self fund', async () => { - const maxPayment = await registry.getMaxPaymentForGas( - Trigger.CONDITION, - performGas, - ) - - // First set auto funding amount to 0 and verify that balance is deducted upon performUpkeep - let initialBalance = toWei('100') - await registry.connect(owner).addFunds(afUpkeepId, initialBalance) - await autoFunderUpkeep.setAutoFundLink(0) - await autoFunderUpkeep.setIsEligible(true) - await getTransmitTx(registry, keeper1, [afUpkeepId]) - - let postUpkeepBalance = (await registry.getUpkeep(afUpkeepId)).balance - assert.isTrue(postUpkeepBalance.lt(initialBalance)) // Balance should be deducted - assert.isTrue(postUpkeepBalance.gte(initialBalance.sub(maxPayment))) // Balance should not be deducted more than maxPayment - - // Now set auto funding amount to 100 wei and verify that the balance increases - initialBalance = postUpkeepBalance - const autoTopupAmount = toWei('100') - await autoFunderUpkeep.setAutoFundLink(autoTopupAmount) - await autoFunderUpkeep.setIsEligible(true) - await getTransmitTx(registry, keeper1, [afUpkeepId]) - - postUpkeepBalance = (await registry.getUpkeep(afUpkeepId)).balance - // Balance should increase by autoTopupAmount and decrease by max maxPayment - assert.isTrue( - postUpkeepBalance.gte( - initialBalance.add(autoTopupAmount).sub(maxPayment), - ), - ) - }) - - it('can self cancel', async () => { - await registry.connect(owner).addFunds(afUpkeepId, toWei('100')) - - await autoFunderUpkeep.setIsEligible(true) - await autoFunderUpkeep.setShouldCancel(true) - - let registration = await registry.getUpkeep(afUpkeepId) - const oldExpiration = registration.maxValidBlocknumber - - // Do the thing - await getTransmitTx(registry, keeper1, [afUpkeepId]) - - // Verify upkeep gets cancelled - registration = await registry.getUpkeep(afUpkeepId) - const newExpiration = registration.maxValidBlocknumber - assert.isTrue(newExpiration.lt(oldExpiration)) - }) - - it('reverts when configDigest mismatches', async () => { - const report = await makeLatestBlockReport([upkeepId]) - const reportContext = [emptyBytes32, epochAndRound5_1, emptyBytes32] // wrong config digest - const sigs = signReport(reportContext, report, signers.slice(0, f + 1)) - await evmRevertCustomError( - registry - .connect(keeper1) - .transmit( - [reportContext[0], reportContext[1], reportContext[2]], - report, - sigs.rs, - sigs.ss, - sigs.vs, - ), - registry, - 'ConfigDigestMismatch', - ) - }) - - it('reverts with incorrect number of signatures', async () => { - const configDigest = (await registry.getState()).state - .latestConfigDigest - const report = await makeLatestBlockReport([upkeepId]) - const reportContext = [configDigest, epochAndRound5_1, emptyBytes32] // wrong config digest - const sigs = signReport(reportContext, report, signers.slice(0, f + 2)) - await evmRevertCustomError( - registry - .connect(keeper1) - .transmit( - [reportContext[0], reportContext[1], reportContext[2]], - report, - sigs.rs, - sigs.ss, - sigs.vs, - ), - registry, - 'IncorrectNumberOfSignatures', - ) - }) - - it('reverts with invalid signature for inactive signers', async () => { - const configDigest = (await registry.getState()).state - .latestConfigDigest - const report = await makeLatestBlockReport([upkeepId]) - const reportContext = [configDigest, epochAndRound5_1, emptyBytes32] // wrong config digest - const sigs = signReport(reportContext, report, [ - new ethers.Wallet(ethers.Wallet.createRandom()), - new ethers.Wallet(ethers.Wallet.createRandom()), - ]) - await evmRevertCustomError( - registry - .connect(keeper1) - .transmit( - [reportContext[0], reportContext[1], reportContext[2]], - report, - sigs.rs, - sigs.ss, - sigs.vs, - ), - registry, - 'OnlyActiveSigners', - ) - }) - - it('reverts with invalid signature for duplicated signers', async () => { - const configDigest = (await registry.getState()).state - .latestConfigDigest - const report = await makeLatestBlockReport([upkeepId]) - const reportContext = [configDigest, epochAndRound5_1, emptyBytes32] // wrong config digest - const sigs = signReport(reportContext, report, [signer1, signer1]) - await evmRevertCustomError( - registry - .connect(keeper1) - .transmit( - [reportContext[0], reportContext[1], reportContext[2]], - report, - sigs.rs, - sigs.ss, - sigs.vs, - ), - registry, - 'DuplicateSigners', - ) - }) - - itMaybe( - 'has a large enough gas overhead to cover upkeep that use all its gas [ @skip-coverage ]', - async () => { - await registry.connect(owner).setConfigTypeSafe( - signerAddresses, - keeperAddresses, - 10, // maximise f to maximise overhead - config, - offchainVersion, - offchainBytes, - ) - const tx = await registry - .connect(owner) - ['registerUpkeep(address,uint32,address,bytes,bytes)']( - mock.address, - maxPerformGas, // max allowed gas - await admin.getAddress(), - randomBytes, - '0x', - ) - const testUpkeepId = await getUpkeepID(tx) - await registry.connect(admin).addFunds(testUpkeepId, toWei('100')) - - let performData = '0x' - for (let i = 0; i < maxPerformDataSize.toNumber(); i++) { - performData += '11' - } // max allowed performData - - await mock.setCanPerform(true) - await mock.setPerformGasToBurn(maxPerformGas) - - await getTransmitTx(registry, keeper1, [testUpkeepId], { - gasLimit: maxPerformGas.add(transmitGasOverhead), - numSigners: 11, - performDatas: [performData], - }) // Should not revert - }, - ) - - itMaybe( - 'performs upkeep, deducts payment, updates lastPerformed and emits events', - async () => { - await mock.setCanPerform(true) - - for (const i in fArray) { - const newF = fArray[i] - await registry - .connect(owner) - .setConfigTypeSafe( - signerAddresses, - keeperAddresses, - newF, - config, - offchainVersion, - offchainBytes, - ) - const checkBlock = await ethers.provider.getBlock('latest') - - const keeperBefore = await registry.getTransmitterInfo( - await keeper1.getAddress(), - ) - const registrationBefore = await registry.getUpkeep(upkeepId) - const registryPremiumBefore = (await registry.getState()).state - .totalPremium - const keeperLinkBefore = await linkToken.balanceOf( - await keeper1.getAddress(), - ) - const registryLinkBefore = await linkToken.balanceOf( - registry.address, - ) - - // Do the thing - const tx = await getTransmitTx(registry, keeper1, [upkeepId], { - checkBlockNum: checkBlock.number, - checkBlockHash: checkBlock.hash, - numSigners: newF + 1, - }) - - const receipt = await tx.wait() - - const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) - // exactly 1 Upkeep Performed should be emitted - assert.equal(upkeepPerformedLogs.length, 1) - const upkeepPerformedLog = upkeepPerformedLogs[0] - - const id = upkeepPerformedLog.args.id - const success = upkeepPerformedLog.args.success - const trigger = upkeepPerformedLog.args.trigger - const gasUsed = upkeepPerformedLog.args.gasUsed - const gasOverhead = upkeepPerformedLog.args.gasOverhead - const totalPayment = upkeepPerformedLog.args.totalPayment - assert.equal(id.toString(), upkeepId.toString()) - assert.equal(success, true) - assert.equal( - trigger, - encodeBlockTrigger({ - blockNum: checkBlock.number, - blockHash: checkBlock.hash, - }), - ) - assert.isTrue(gasUsed.gt(BigNumber.from('0'))) - assert.isTrue(gasOverhead.gt(BigNumber.from('0'))) - assert.isTrue(totalPayment.gt(BigNumber.from('0'))) - - const keeperAfter = await registry.getTransmitterInfo( - await keeper1.getAddress(), - ) - const registrationAfter = await registry.getUpkeep(upkeepId) - const keeperLinkAfter = await linkToken.balanceOf( - await keeper1.getAddress(), - ) - const registryLinkAfter = await linkToken.balanceOf( - registry.address, - ) - const registryPremiumAfter = (await registry.getState()).state - .totalPremium - const premium = registryPremiumAfter.sub(registryPremiumBefore) - // Keeper payment is gasPayment + premium / num keepers - const keeperPayment = totalPayment - .sub(premium) - .add(premium.div(BigNumber.from(keeperAddresses.length))) - - assert.equal( - keeperAfter.balance.sub(keeperPayment).toString(), - keeperBefore.balance.toString(), - ) - assert.equal( - registrationBefore.balance.sub(totalPayment).toString(), - registrationAfter.balance.toString(), - ) - assert.isTrue(keeperLinkAfter.eq(keeperLinkBefore)) - assert.isTrue(registryLinkBefore.eq(registryLinkAfter)) - - // Amount spent should be updated correctly - assert.equal( - registrationAfter.amountSpent.sub(totalPayment).toString(), - registrationBefore.amountSpent.toString(), - ) - assert.isTrue( - registrationAfter.amountSpent - .sub(registrationBefore.amountSpent) - .eq(registrationBefore.balance.sub(registrationAfter.balance)), - ) - // Last perform block number should be updated - assert.equal( - registrationAfter.lastPerformedBlockNumber.toString(), - tx.blockNumber?.toString(), - ) - - // Latest epoch should be 5 - assert.equal((await registry.getState()).state.latestEpoch, 5) - } - }, - ) - - // skipping it for now as it is passing in local but failing in CI - describe.skip('Gas benchmarking conditional upkeeps [ @skip-coverage ]', function () { - const fs = [1, 10] - fs.forEach(function (newF) { - it( - 'When f=' + - newF + - ' calculates gas overhead appropriately within a margin for different scenarios', - async () => { - // Perform the upkeep once to remove non-zero storage slots and have predictable gas measurement - let tx = await getTransmitTx(registry, keeper1, [upkeepId]) - await tx.wait() - - // Different test scenarios - let longBytes = '0x' - for (let i = 0; i < maxPerformDataSize.toNumber(); i++) { - longBytes += '11' - } - const upkeepSuccessArray = [true, false] - const performGasArray = [5000, performGas] - const performDataArray = ['0x', longBytes] - const chainModuleOverheads = - await chainModuleBase.getGasOverhead() - - for (const i in upkeepSuccessArray) { - for (const j in performGasArray) { - for (const k in performDataArray) { - const upkeepSuccess = upkeepSuccessArray[i] - const performGas = performGasArray[j] - const performData = performDataArray[k] - - await mock.setCanPerform(upkeepSuccess) - await mock.setPerformGasToBurn(performGas) - await registry - .connect(owner) - .setConfigTypeSafe( - signerAddresses, - keeperAddresses, - newF, - config, - offchainVersion, - offchainBytes, - ) - tx = await getTransmitTx(registry, keeper1, [upkeepId], { - numSigners: newF + 1, - performDatas: [performData], - }) - const receipt = await tx.wait() - const upkeepPerformedLogs = - parseUpkeepPerformedLogs(receipt) - // exactly 1 Upkeep Performed should be emitted - assert.equal(upkeepPerformedLogs.length, 1) - const upkeepPerformedLog = upkeepPerformedLogs[0] - - const upkeepGasUsed = upkeepPerformedLog.args.gasUsed - const chargedGasOverhead = - upkeepPerformedLog.args.gasOverhead - const actualGasOverhead = receipt.gasUsed.sub(upkeepGasUsed) - const estimatedGasOverhead = registryConditionalOverhead - .add( - registryPerSignerGasOverhead.mul( - BigNumber.from(newF + 1), - ), - ) - .add( - registryPerPerformByteGasOverhead - .add(chainModuleOverheads.chainModulePerByteOverhead) - .mul( - BigNumber.from(performData.length / 2 - 1) - .add(registryTransmitCalldataFixedBytesOverhead) - .add( - registryTransmitCalldataPerSignerBytesOverhead.mul( - BigNumber.from(newF + 1), - ), - ), - ), - ) - .add(chainModuleOverheads.chainModuleFixedOverhead) - - assert.isTrue(upkeepGasUsed.gt(BigNumber.from('0'))) - assert.isTrue(chargedGasOverhead.gt(BigNumber.from('0'))) - assert.isTrue(actualGasOverhead.gt(BigNumber.from('0'))) - - console.log( - 'Gas Benchmarking conditional upkeeps:', - 'upkeepSuccess=', - upkeepSuccess, - 'performGas=', - performGas.toString(), - 'performData length=', - performData.length / 2 - 1, - 'sig verification ( f =', - newF, - '): estimated overhead: ', - estimatedGasOverhead.toString(), - ' charged overhead: ', - chargedGasOverhead.toString(), - ' actual overhead: ', - actualGasOverhead.toString(), - ' calculation margin over gasUsed: ', - chargedGasOverhead.sub(actualGasOverhead).toString(), - ' estimation margin over gasUsed: ', - estimatedGasOverhead.sub(actualGasOverhead).toString(), - ) - - // The actual gas overhead should be less than charged gas overhead, but not by a lot - // The charged gas overhead is controlled by ACCOUNTING_FIXED_GAS_OVERHEAD and - // ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD, and their correct values should be set to - // satisfy constraints in multiple places - assert.isTrue( - chargedGasOverhead.gt(actualGasOverhead), - 'Gas overhead calculated is too low, increase account gas variables (ACCOUNTING_FIXED_GAS_OVERHEAD/ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD) by at least ' + - actualGasOverhead.sub(chargedGasOverhead).toString(), - ) - assert.isTrue( - chargedGasOverhead - .sub(actualGasOverhead) - .lt(gasCalculationMargin), - 'Gas overhead calculated is too high, decrease account gas variables (ACCOUNTING_FIXED_GAS_OVERHEAD/ACCOUNTING_PER_SIGNER_GAS_OVERHEAD) by at least ' + - chargedGasOverhead - .sub(actualGasOverhead) - .sub(gasCalculationMargin) - .toString(), - ) - - // The estimated overhead during checkUpkeep should be close to the actual overhead in transaction - // It should be greater than the actual overhead but not by a lot - // The estimated overhead is controlled by variables - // REGISTRY_CONDITIONAL_OVERHEAD, REGISTRY_LOG_OVERHEAD, REGISTRY_PER_SIGNER_GAS_OVERHEAD - // REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD - assert.isTrue( - estimatedGasOverhead.gt(actualGasOverhead), - 'Gas overhead estimated in check upkeep is too low, increase estimation gas variables (REGISTRY_CONDITIONAL_OVERHEAD/REGISTRY_LOG_OVERHEAD/REGISTRY_PER_SIGNER_GAS_OVERHEAD/REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD) by at least ' + - estimatedGasOverhead.sub(chargedGasOverhead).toString(), - ) - assert.isTrue( - estimatedGasOverhead - .sub(actualGasOverhead) - .lt(gasEstimationMargin), - 'Gas overhead estimated is too high, decrease estimation gas variables (REGISTRY_CONDITIONAL_OVERHEAD/REGISTRY_LOG_OVERHEAD/REGISTRY_PER_SIGNER_GAS_OVERHEAD/REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD) by at least ' + - estimatedGasOverhead - .sub(actualGasOverhead) - .sub(gasEstimationMargin) - .toString(), - ) - } - } - } - }, - ) - }) - }) - - describe('Gas benchmarking log upkeeps [ @skip-coverage ]', function () { - const fs = [1, 10] - fs.forEach(function (newF) { - it( - 'When f=' + - newF + - ' calculates gas overhead appropriately within a margin', - async () => { - // Perform the upkeep once to remove non-zero storage slots and have predictable gas measurement - let tx = await getTransmitTx(registry, keeper1, [logUpkeepId]) - await tx.wait() - const performData = '0x' - await mock.setCanPerform(true) - await mock.setPerformGasToBurn(performGas) - await registry.setConfigTypeSafe( - signerAddresses, - keeperAddresses, - newF, - config, - offchainVersion, - offchainBytes, - ) - tx = await getTransmitTx(registry, keeper1, [logUpkeepId], { - numSigners: newF + 1, - performDatas: [performData], - }) - const receipt = await tx.wait() - const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) - // exactly 1 Upkeep Performed should be emitted - assert.equal(upkeepPerformedLogs.length, 1) - const upkeepPerformedLog = upkeepPerformedLogs[0] - const chainModuleOverheads = - await chainModuleBase.getGasOverhead() - - const upkeepGasUsed = upkeepPerformedLog.args.gasUsed - const chargedGasOverhead = upkeepPerformedLog.args.gasOverhead - const actualGasOverhead = receipt.gasUsed.sub(upkeepGasUsed) - const estimatedGasOverhead = registryLogOverhead - .add(registryPerSignerGasOverhead.mul(BigNumber.from(newF + 1))) - .add( - registryPerPerformByteGasOverhead - .add(chainModuleOverheads.chainModulePerByteOverhead) - .mul( - BigNumber.from(performData.length / 2 - 1) - .add(registryTransmitCalldataFixedBytesOverhead) - .add( - registryTransmitCalldataPerSignerBytesOverhead.mul( - BigNumber.from(newF + 1), - ), - ), - ), - ) - .add(chainModuleOverheads.chainModuleFixedOverhead) - - assert.isTrue(upkeepGasUsed.gt(BigNumber.from('0'))) - assert.isTrue(chargedGasOverhead.gt(BigNumber.from('0'))) - assert.isTrue(actualGasOverhead.gt(BigNumber.from('0'))) - - console.log( - 'Gas Benchmarking log upkeeps:', - 'upkeepSuccess=', - true, - 'performGas=', - performGas.toString(), - 'performData length=', - performData.length / 2 - 1, - 'sig verification ( f =', - newF, - '): estimated overhead: ', - estimatedGasOverhead.toString(), - ' charged overhead: ', - chargedGasOverhead.toString(), - ' actual overhead: ', - actualGasOverhead.toString(), - ' calculation margin over gasUsed: ', - chargedGasOverhead.sub(actualGasOverhead).toString(), - ' estimation margin over gasUsed: ', - estimatedGasOverhead.sub(actualGasOverhead).toString(), - ) - - assert.isTrue( - chargedGasOverhead.gt(actualGasOverhead), - 'Gas overhead calculated is too low, increase account gas variables (ACCOUNTING_FIXED_GAS_OVERHEAD/ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD) by at least ' + - actualGasOverhead.sub(chargedGasOverhead).toString(), - ) - assert.isTrue( - chargedGasOverhead - .sub(actualGasOverhead) - .lt(gasCalculationMargin), - 'Gas overhead calculated is too high, decrease account gas variables (ACCOUNTING_FIXED_GAS_OVERHEAD/ACCOUNTING_PER_SIGNER_GAS_OVERHEAD) by at least ' + - chargedGasOverhead - .sub(actualGasOverhead) - .sub(gasCalculationMargin) - .toString(), - ) - - assert.isTrue( - estimatedGasOverhead.gt(actualGasOverhead), - 'Gas overhead estimated in check upkeep is too low, increase estimation gas variables (REGISTRY_CONDITIONAL_OVERHEAD/REGISTRY_LOG_OVERHEAD/REGISTRY_PER_SIGNER_GAS_OVERHEAD/REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD) by at least ' + - estimatedGasOverhead.sub(chargedGasOverhead).toString(), - ) - assert.isTrue( - estimatedGasOverhead - .sub(actualGasOverhead) - .lt(gasEstimationMargin), - 'Gas overhead estimated is too high, decrease estimation gas variables (REGISTRY_CONDITIONAL_OVERHEAD/REGISTRY_LOG_OVERHEAD/REGISTRY_PER_SIGNER_GAS_OVERHEAD/REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD) by at least ' + - estimatedGasOverhead - .sub(actualGasOverhead) - .sub(gasEstimationMargin) - .toString(), - ) - }, - ) - }) - }) - }) - }) - - describe('#transmit with upkeep batches [ @skip-coverage ]', function () { - const numPassingConditionalUpkeepsArray = [0, 1, 5] - const numPassingLogUpkeepsArray = [0, 1, 5] - const numFailingUpkeepsArray = [0, 3] - - for (let idx = 0; idx < numPassingConditionalUpkeepsArray.length; idx++) { - for (let jdx = 0; jdx < numPassingLogUpkeepsArray.length; jdx++) { - for (let kdx = 0; kdx < numFailingUpkeepsArray.length; kdx++) { - const numPassingConditionalUpkeeps = - numPassingConditionalUpkeepsArray[idx] - const numPassingLogUpkeeps = numPassingLogUpkeepsArray[jdx] - const numFailingUpkeeps = numFailingUpkeepsArray[kdx] - if (numPassingConditionalUpkeeps == 0 && numPassingLogUpkeeps == 0) { - continue - } - it( - '[Conditional:' + - numPassingConditionalUpkeeps + - ',Log:' + - numPassingLogUpkeeps + - ',Failures:' + - numFailingUpkeeps + - '] performs successful upkeeps and does not charge failing upkeeps', - async () => { - const allUpkeeps = await getMultipleUpkeepsDeployedAndFunded( - numPassingConditionalUpkeeps, - numPassingLogUpkeeps, - numFailingUpkeeps, - ) - const passingConditionalUpkeepIds = - allUpkeeps.passingConditionalUpkeepIds - const passingLogUpkeepIds = allUpkeeps.passingLogUpkeepIds - const failingUpkeepIds = allUpkeeps.failingUpkeepIds - - const keeperBefore = await registry.getTransmitterInfo( - await keeper1.getAddress(), - ) - const keeperLinkBefore = await linkToken.balanceOf( - await keeper1.getAddress(), - ) - const registryLinkBefore = await linkToken.balanceOf( - registry.address, - ) - const registryPremiumBefore = (await registry.getState()).state - .totalPremium - const registrationConditionalPassingBefore = await Promise.all( - passingConditionalUpkeepIds.map(async (id) => { - const reg = await registry.getUpkeep(BigNumber.from(id)) - assert.equal(reg.lastPerformedBlockNumber.toString(), '0') - return reg - }), - ) - const registrationLogPassingBefore = await Promise.all( - passingLogUpkeepIds.map(async (id) => { - const reg = await registry.getUpkeep(BigNumber.from(id)) - assert.equal(reg.lastPerformedBlockNumber.toString(), '0') - return reg - }), - ) - const registrationFailingBefore = await Promise.all( - failingUpkeepIds.map(async (id) => { - const reg = await registry.getUpkeep(BigNumber.from(id)) - assert.equal(reg.lastPerformedBlockNumber.toString(), '0') - return reg - }), - ) - - // cancel upkeeps so they will fail in the transmit process - // must call the cancel upkeep as the owner to avoid the CANCELLATION_DELAY - for (let ldx = 0; ldx < failingUpkeepIds.length; ldx++) { - await registry - .connect(owner) - .cancelUpkeep(failingUpkeepIds[ldx]) - } - - const tx = await getTransmitTx( - registry, - keeper1, - passingConditionalUpkeepIds.concat( - passingLogUpkeepIds.concat(failingUpkeepIds), - ), - ) - - const receipt = await tx.wait() - const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) - // exactly numPassingUpkeeps Upkeep Performed should be emitted - assert.equal( - upkeepPerformedLogs.length, - numPassingConditionalUpkeeps + numPassingLogUpkeeps, - ) - const cancelledUpkeepReportLogs = - parseCancelledUpkeepReportLogs(receipt) - // exactly numFailingUpkeeps Upkeep Performed should be emitted - assert.equal(cancelledUpkeepReportLogs.length, numFailingUpkeeps) - - const keeperAfter = await registry.getTransmitterInfo( - await keeper1.getAddress(), - ) - const keeperLinkAfter = await linkToken.balanceOf( - await keeper1.getAddress(), - ) - const registryLinkAfter = await linkToken.balanceOf( - registry.address, - ) - const registrationConditionalPassingAfter = await Promise.all( - passingConditionalUpkeepIds.map(async (id) => { - return await registry.getUpkeep(BigNumber.from(id)) - }), - ) - const registrationLogPassingAfter = await Promise.all( - passingLogUpkeepIds.map(async (id) => { - return await registry.getUpkeep(BigNumber.from(id)) - }), - ) - const registrationFailingAfter = await Promise.all( - failingUpkeepIds.map(async (id) => { - return await registry.getUpkeep(BigNumber.from(id)) - }), - ) - const registryPremiumAfter = (await registry.getState()).state - .totalPremium - const premium = registryPremiumAfter.sub(registryPremiumBefore) - - let netPayment = BigNumber.from('0') - for (let i = 0; i < numPassingConditionalUpkeeps; i++) { - const id = upkeepPerformedLogs[i].args.id - const gasUsed = upkeepPerformedLogs[i].args.gasUsed - const gasOverhead = upkeepPerformedLogs[i].args.gasOverhead - const totalPayment = upkeepPerformedLogs[i].args.totalPayment - - expect(id).to.equal(passingConditionalUpkeepIds[i]) - assert.isTrue(gasUsed.gt(BigNumber.from('0'))) - assert.isTrue(gasOverhead.gt(BigNumber.from('0'))) - assert.isTrue(totalPayment.gt(BigNumber.from('0'))) - - // Balance should be deducted - assert.equal( - registrationConditionalPassingBefore[i].balance - .sub(totalPayment) - .toString(), - registrationConditionalPassingAfter[i].balance.toString(), - ) - - // Amount spent should be updated correctly - assert.equal( - registrationConditionalPassingAfter[i].amountSpent - .sub(totalPayment) - .toString(), - registrationConditionalPassingBefore[ - i - ].amountSpent.toString(), - ) - - // Last perform block number should be updated - assert.equal( - registrationConditionalPassingAfter[ - i - ].lastPerformedBlockNumber.toString(), - tx.blockNumber?.toString(), - ) - - netPayment = netPayment.add(totalPayment) - } - - for (let i = 0; i < numPassingLogUpkeeps; i++) { - const id = - upkeepPerformedLogs[numPassingConditionalUpkeeps + i].args.id - const gasUsed = - upkeepPerformedLogs[numPassingConditionalUpkeeps + i].args - .gasUsed - const gasOverhead = - upkeepPerformedLogs[numPassingConditionalUpkeeps + i].args - .gasOverhead - const totalPayment = - upkeepPerformedLogs[numPassingConditionalUpkeeps + i].args - .totalPayment - - expect(id).to.equal(passingLogUpkeepIds[i]) - assert.isTrue(gasUsed.gt(BigNumber.from('0'))) - assert.isTrue(gasOverhead.gt(BigNumber.from('0'))) - assert.isTrue(totalPayment.gt(BigNumber.from('0'))) - - // Balance should be deducted - assert.equal( - registrationLogPassingBefore[i].balance - .sub(totalPayment) - .toString(), - registrationLogPassingAfter[i].balance.toString(), - ) - - // Amount spent should be updated correctly - assert.equal( - registrationLogPassingAfter[i].amountSpent - .sub(totalPayment) - .toString(), - registrationLogPassingBefore[i].amountSpent.toString(), - ) - - // Last perform block number should not be updated for log triggers - assert.equal( - registrationLogPassingAfter[ - i - ].lastPerformedBlockNumber.toString(), - '0', - ) - - netPayment = netPayment.add(totalPayment) - } - - for (let i = 0; i < numFailingUpkeeps; i++) { - // CancelledUpkeep log should be emitted - const id = cancelledUpkeepReportLogs[i].args.id - expect(id).to.equal(failingUpkeepIds[i]) - - // Balance and amount spent should be same - assert.equal( - registrationFailingBefore[i].balance.toString(), - registrationFailingAfter[i].balance.toString(), - ) - assert.equal( - registrationFailingBefore[i].amountSpent.toString(), - registrationFailingAfter[i].amountSpent.toString(), - ) - - // Last perform block number should not be updated - assert.equal( - registrationFailingAfter[ - i - ].lastPerformedBlockNumber.toString(), - '0', - ) - } - - // Keeper payment is gasPayment + premium / num keepers - const keeperPayment = netPayment - .sub(premium) - .add(premium.div(BigNumber.from(keeperAddresses.length))) - - // Keeper should be paid net payment for all passed upkeeps - assert.equal( - keeperAfter.balance.sub(keeperPayment).toString(), - keeperBefore.balance.toString(), - ) - - assert.isTrue(keeperLinkAfter.eq(keeperLinkBefore)) - assert.isTrue(registryLinkBefore.eq(registryLinkAfter)) - }, - ) - - it( - '[Conditional:' + - numPassingConditionalUpkeeps + - ',Log' + - numPassingLogUpkeeps + - ',Failures:' + - numFailingUpkeeps + - '] splits gas overhead appropriately among performed upkeeps [ @skip-coverage ]', - async () => { - const allUpkeeps = await getMultipleUpkeepsDeployedAndFunded( - numPassingConditionalUpkeeps, - numPassingLogUpkeeps, - numFailingUpkeeps, - ) - const passingConditionalUpkeepIds = - allUpkeeps.passingConditionalUpkeepIds - const passingLogUpkeepIds = allUpkeeps.passingLogUpkeepIds - const failingUpkeepIds = allUpkeeps.failingUpkeepIds - - // Perform the upkeeps once to remove non-zero storage slots and have predictable gas measurement - let tx = await getTransmitTx( - registry, - keeper1, - passingConditionalUpkeepIds.concat( - passingLogUpkeepIds.concat(failingUpkeepIds), - ), - ) - - await tx.wait() - - // cancel upkeeps so they will fail in the transmit process - // must call the cancel upkeep as the owner to avoid the CANCELLATION_DELAY - for (let ldx = 0; ldx < failingUpkeepIds.length; ldx++) { - await registry - .connect(owner) - .cancelUpkeep(failingUpkeepIds[ldx]) - } - - // Do the actual thing - - tx = await getTransmitTx( - registry, - keeper1, - passingConditionalUpkeepIds.concat( - passingLogUpkeepIds.concat(failingUpkeepIds), - ), - ) - - const receipt = await tx.wait() - const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) - // exactly numPassingUpkeeps Upkeep Performed should be emitted - assert.equal( - upkeepPerformedLogs.length, - numPassingConditionalUpkeeps + numPassingLogUpkeeps, - ) - - let netGasUsedPlusChargedOverhead = BigNumber.from('0') - for (let i = 0; i < numPassingConditionalUpkeeps; i++) { - const gasUsed = upkeepPerformedLogs[i].args.gasUsed - const chargedGasOverhead = - upkeepPerformedLogs[i].args.gasOverhead - - assert.isTrue(gasUsed.gt(BigNumber.from('0'))) - assert.isTrue(chargedGasOverhead.gt(BigNumber.from('0'))) - - // Overhead should be same for every upkeep - assert.isTrue( - chargedGasOverhead.eq( - upkeepPerformedLogs[0].args.gasOverhead, - ), - ) - netGasUsedPlusChargedOverhead = netGasUsedPlusChargedOverhead - .add(gasUsed) - .add(chargedGasOverhead) - } - - for (let i = 0; i < numPassingLogUpkeeps; i++) { - const gasUsed = - upkeepPerformedLogs[numPassingConditionalUpkeeps + i].args - .gasUsed - const chargedGasOverhead = - upkeepPerformedLogs[numPassingConditionalUpkeeps + i].args - .gasOverhead - - assert.isTrue(gasUsed.gt(BigNumber.from('0'))) - assert.isTrue(chargedGasOverhead.gt(BigNumber.from('0'))) - - // Overhead should be same for every upkeep - assert.isTrue( - chargedGasOverhead.eq( - upkeepPerformedLogs[numPassingConditionalUpkeeps].args - .gasOverhead, - ), - ) - netGasUsedPlusChargedOverhead = netGasUsedPlusChargedOverhead - .add(gasUsed) - .add(chargedGasOverhead) - } - - console.log( - 'Gas Benchmarking - batching (passedConditionalUpkeeps: ', - numPassingConditionalUpkeeps, - 'passedLogUpkeeps:', - numPassingLogUpkeeps, - 'failedUpkeeps:', - numFailingUpkeeps, - '): ', - numPassingConditionalUpkeeps > 0 - ? 'charged conditional overhead' - : '', - numPassingConditionalUpkeeps > 0 - ? upkeepPerformedLogs[0].args.gasOverhead.toString() - : '', - numPassingLogUpkeeps > 0 ? 'charged log overhead' : '', - numPassingLogUpkeeps > 0 - ? upkeepPerformedLogs[ - numPassingConditionalUpkeeps - ].args.gasOverhead.toString() - : '', - ' margin over gasUsed', - netGasUsedPlusChargedOverhead.sub(receipt.gasUsed).toString(), - ) - - // The total gas charged should be greater than tx gas - assert.isTrue( - netGasUsedPlusChargedOverhead.gt(receipt.gasUsed), - 'Charged gas overhead is too low for batch upkeeps, increase ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD', - ) - }, - ) - } - } - } - - it('has enough perform gas overhead for large batches [ @skip-coverage ]', async () => { - const numUpkeeps = 20 - const upkeepIds: BigNumber[] = [] - let totalPerformGas = BigNumber.from('0') - for (let i = 0; i < numUpkeeps; i++) { - const mock = await upkeepMockFactory.deploy() - const tx = await registry - .connect(owner) - [ - 'registerUpkeep(address,uint32,address,bytes,bytes)' - ](mock.address, performGas, await admin.getAddress(), randomBytes, '0x') - const testUpkeepId = await getUpkeepID(tx) - upkeepIds.push(testUpkeepId) - - // Add funds to passing upkeeps - await registry.connect(owner).addFunds(testUpkeepId, toWei('10')) - - await mock.setCanPerform(true) - await mock.setPerformGasToBurn(performGas) - - totalPerformGas = totalPerformGas.add(performGas) - } - - // Should revert with no overhead added - await evmRevert( - getTransmitTx(registry, keeper1, upkeepIds, { - gasLimit: totalPerformGas, - }), - ) - // Should not revert with overhead added - await getTransmitTx(registry, keeper1, upkeepIds, { - gasLimit: totalPerformGas.add(transmitGasOverhead), - }) - }) - - it('splits l2 payment among performed upkeeps according to perform data weight', async () => { - const numUpkeeps = 7 - const upkeepIds: BigNumber[] = [] - const performDataSizes = [0, 10, 1000, 50, 33, 69, 420] - const performDatas: string[] = [] - const upkeepCalldataWeights: BigNumber[] = [] - let totalCalldataWeight = BigNumber.from('0') - // Same as MockArbGasInfo.sol - const l1CostWeiArb = BigNumber.from(1000000) - - for (let i = 0; i < numUpkeeps; i++) { - const mock = await upkeepMockFactory.deploy() - const tx = await arbRegistry - .connect(owner) - [ - 'registerUpkeep(address,uint32,address,bytes,bytes)' - ](mock.address, performGas, await admin.getAddress(), randomBytes, '0x') - const testUpkeepId = await getUpkeepID(tx) - upkeepIds.push(testUpkeepId) - - // Add funds to passing upkeeps - await arbRegistry.connect(owner).addFunds(testUpkeepId, toWei('100')) - - // Generate performData - let pd = '0x' - for (let j = 0; j < performDataSizes[i]; j++) { - pd += '11' - } - performDatas.push(pd) - const w = BigNumber.from(performDataSizes[i]) - .add(registryTransmitCalldataFixedBytesOverhead) - .add( - registryTransmitCalldataPerSignerBytesOverhead.mul( - BigNumber.from(f + 1), - ), - ) - upkeepCalldataWeights.push(w) - totalCalldataWeight = totalCalldataWeight.add(w) - } - - // Do the thing - const tx = await getTransmitTx(arbRegistry, keeper1, upkeepIds, { - gasPrice: gasWei.mul('5'), // High gas price so that it gets capped - performDatas, - }) - - const receipt = await tx.wait() - const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) - // exactly numPassingUpkeeps Upkeep Performed should be emitted - assert.equal(upkeepPerformedLogs.length, numUpkeeps) - - for (let i = 0; i < numUpkeeps; i++) { - const upkeepPerformedLog = upkeepPerformedLogs[i] - - const gasUsed = upkeepPerformedLog.args.gasUsed - const gasOverhead = upkeepPerformedLog.args.gasOverhead - const totalPayment = upkeepPerformedLog.args.totalPayment - - assert.equal( - linkForGas( - gasUsed, - gasOverhead, - gasCeilingMultiplier, - paymentPremiumPPB, - flatFeeMicroLink, - l1CostWeiArb.mul(upkeepCalldataWeights[i]).div(totalCalldataWeight), - ).total.toString(), - totalPayment.toString(), - ) - } - }) - }) - - describe('#recoverFunds', () => { - const sent = toWei('7') - - beforeEach(async () => { - await linkToken.connect(admin).approve(registry.address, toWei('100')) - await linkToken - .connect(owner) - .transfer(await keeper1.getAddress(), toWei('1000')) - - // add funds to upkeep 1 and perform and withdraw some payment - const tx = await registry - .connect(owner) - [ - 'registerUpkeep(address,uint32,address,bytes,bytes)' - ](mock.address, performGas, await admin.getAddress(), emptyBytes, emptyBytes) - - const id1 = await getUpkeepID(tx) - await registry.connect(admin).addFunds(id1, toWei('5')) - - await getTransmitTx(registry, keeper1, [id1]) - await getTransmitTx(registry, keeper2, [id1]) - await getTransmitTx(registry, keeper3, [id1]) - - await registry - .connect(payee1) - .withdrawPayment( - await keeper1.getAddress(), - await nonkeeper.getAddress(), - ) - - // transfer funds directly to the registry - await linkToken.connect(keeper1).transfer(registry.address, sent) - - // add funds to upkeep 2 and perform and withdraw some payment - const tx2 = await registry - .connect(owner) - [ - 'registerUpkeep(address,uint32,address,bytes,bytes)' - ](mock.address, performGas, await admin.getAddress(), emptyBytes, emptyBytes) - const id2 = await getUpkeepID(tx2) - await registry.connect(admin).addFunds(id2, toWei('5')) - - await getTransmitTx(registry, keeper1, [id2]) - await getTransmitTx(registry, keeper2, [id2]) - await getTransmitTx(registry, keeper3, [id2]) - - await registry - .connect(payee2) - .withdrawPayment( - await keeper2.getAddress(), - await nonkeeper.getAddress(), - ) - - // transfer funds using onTokenTransfer - const data = ethers.utils.defaultAbiCoder.encode(['uint256'], [id2]) - await linkToken - .connect(owner) - .transferAndCall(registry.address, toWei('1'), data) - - // withdraw some funds - await registry.connect(owner).cancelUpkeep(id1) - await registry - .connect(admin) - .withdrawFunds(id1, await nonkeeper.getAddress()) - }) - - it('reverts if not called by owner', async () => { - await evmRevert( - registry.connect(keeper1).recoverFunds(), - 'Only callable by owner', - ) - }) - - it('allows any funds that have been accidentally transfered to be moved', async () => { - const balanceBefore = await linkToken.balanceOf(registry.address) - const ownerBefore = await linkToken.balanceOf(await owner.getAddress()) - - await registry.connect(owner).recoverFunds() - - const balanceAfter = await linkToken.balanceOf(registry.address) - const ownerAfter = await linkToken.balanceOf(await owner.getAddress()) - - assert.isTrue(balanceBefore.eq(balanceAfter.add(sent))) - assert.isTrue(ownerAfter.eq(ownerBefore.add(sent))) - }) - }) - - describe('#getMinBalanceForUpkeep / #checkUpkeep / #transmit', () => { - it('calculates the minimum balance appropriately', async () => { - await mock.setCanCheck(true) - - const oneWei = BigNumber.from(1) - const minBalance = await registry.getMinBalanceForUpkeep(upkeepId) - const tooLow = minBalance.sub(oneWei) - - await registry.connect(admin).addFunds(upkeepId, tooLow) - let checkUpkeepResult = await registry - .connect(zeroAddress) - .callStatic['checkUpkeep(uint256)'](upkeepId) - - assert.equal(checkUpkeepResult.upkeepNeeded, false) - assert.equal( - checkUpkeepResult.upkeepFailureReason, - UpkeepFailureReason.INSUFFICIENT_BALANCE, - ) - - await registry.connect(admin).addFunds(upkeepId, oneWei) - checkUpkeepResult = await registry - .connect(zeroAddress) - .callStatic['checkUpkeep(uint256)'](upkeepId) - assert.equal(checkUpkeepResult.upkeepNeeded, true) - }) - - it('uses maxPerformData size in checkUpkeep but actual performDataSize in transmit', async () => { - const tx = await registry - .connect(owner) - [ - 'registerUpkeep(address,uint32,address,bytes,bytes)' - ](mock.address, performGas, await admin.getAddress(), randomBytes, '0x') - const upkeepID = await getUpkeepID(tx) - await mock.setCanCheck(true) - await mock.setCanPerform(true) - - // upkeep is underfunded by 1 wei - const minBalance1 = (await registry.getMinBalanceForUpkeep(upkeepID)).sub( - 1, - ) - await registry.connect(owner).addFunds(upkeepID, minBalance1) - - // upkeep check should return false, 2 should return true - const checkUpkeepResult = await registry - .connect(zeroAddress) - .callStatic['checkUpkeep(uint256)'](upkeepID) - assert.equal(checkUpkeepResult.upkeepNeeded, false) - assert.equal( - checkUpkeepResult.upkeepFailureReason, - UpkeepFailureReason.INSUFFICIENT_BALANCE, - ) - - // however upkeep should perform and pay all the remaining balance - let maxPerformData = '0x' - for (let i = 0; i < maxPerformDataSize.toNumber(); i++) { - maxPerformData += '11' - } - - const tx2 = await getTransmitTx(registry, keeper1, [upkeepID], { - gasPrice: gasWei.mul(gasCeilingMultiplier), - performDatas: [maxPerformData], - }) - - const receipt = await tx2.wait() - const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) - assert.equal(upkeepPerformedLogs.length, 1) - }) - }) - - describe('#withdrawFunds', () => { - let upkeepId2: BigNumber - - beforeEach(async () => { - const tx = await registry - .connect(owner) - [ - 'registerUpkeep(address,uint32,address,bytes,bytes)' - ](mock.address, performGas, await admin.getAddress(), randomBytes, '0x') - upkeepId2 = await getUpkeepID(tx) - - await registry.connect(admin).addFunds(upkeepId, toWei('100')) - await registry.connect(admin).addFunds(upkeepId2, toWei('100')) - - // Do a perform so that upkeep is charged some amount - await getTransmitTx(registry, keeper1, [upkeepId]) - await getTransmitTx(registry, keeper1, [upkeepId2]) - }) - - it('reverts if called on a non existing ID', async () => { - await evmRevertCustomError( - registry - .connect(admin) - .withdrawFunds(upkeepId.add(1), await payee1.getAddress()), - registry, - 'OnlyCallableByAdmin', - ) - }) - - it('reverts if called by anyone but the admin', async () => { - await evmRevertCustomError( - registry - .connect(owner) - .withdrawFunds(upkeepId, await payee1.getAddress()), - registry, - 'OnlyCallableByAdmin', - ) - }) - - it('reverts if called on an uncanceled upkeep', async () => { - await evmRevertCustomError( - registry - .connect(admin) - .withdrawFunds(upkeepId, await payee1.getAddress()), - registry, - 'UpkeepNotCanceled', - ) - }) - - it('reverts if called with the 0 address', async () => { - await evmRevertCustomError( - registry.connect(admin).withdrawFunds(upkeepId, zeroAddress), - registry, - 'InvalidRecipient', - ) - }) - - describe('after the registration is paused, then cancelled', () => { - it('allows the admin to withdraw', async () => { - const balance = await registry.getBalance(upkeepId) - const payee = await payee1.getAddress() - await registry.connect(admin).pauseUpkeep(upkeepId) - await registry.connect(owner).cancelUpkeep(upkeepId) - await expect(() => - registry.connect(admin).withdrawFunds(upkeepId, payee), - ).to.changeTokenBalance(linkToken, payee1, balance) - }) - }) - - describe('after the registration is cancelled', () => { - beforeEach(async () => { - await registry.connect(owner).cancelUpkeep(upkeepId) - await registry.connect(owner).cancelUpkeep(upkeepId2) - }) - - it('can be called successively on two upkeeps', async () => { - await registry - .connect(admin) - .withdrawFunds(upkeepId, await payee1.getAddress()) - await registry - .connect(admin) - .withdrawFunds(upkeepId2, await payee1.getAddress()) - }) - - it('moves the funds out and updates the balance and emits an event', async () => { - const payee1Before = await linkToken.balanceOf( - await payee1.getAddress(), - ) - const registryBefore = await linkToken.balanceOf(registry.address) - - let registration = await registry.getUpkeep(upkeepId) - const previousBalance = registration.balance - - const tx = await registry - .connect(admin) - .withdrawFunds(upkeepId, await payee1.getAddress()) - await expect(tx) - .to.emit(registry, 'FundsWithdrawn') - .withArgs(upkeepId, previousBalance, await payee1.getAddress()) - - const payee1After = await linkToken.balanceOf(await payee1.getAddress()) - const registryAfter = await linkToken.balanceOf(registry.address) - - assert.isTrue(payee1Before.add(previousBalance).eq(payee1After)) - assert.isTrue(registryBefore.sub(previousBalance).eq(registryAfter)) - - registration = await registry.getUpkeep(upkeepId) - assert.equal(0, registration.balance.toNumber()) - }) - }) - }) - - describe('#simulatePerformUpkeep', () => { - it('reverts if called by non zero address', async () => { - await evmRevertCustomError( - registry - .connect(await owner.getAddress()) - .callStatic.simulatePerformUpkeep(upkeepId, '0x'), - registry, - 'OnlySimulatedBackend', - ) - }) - - it('reverts when registry is paused', async () => { - await registry.connect(owner).pause() - await evmRevertCustomError( - registry - .connect(zeroAddress) - .callStatic.simulatePerformUpkeep(upkeepId, '0x'), - registry, - 'RegistryPaused', - ) - }) - - it('returns false and gasUsed when perform fails', async () => { - await mock.setCanPerform(false) - - const simulatePerformResult = await registry - .connect(zeroAddress) - .callStatic.simulatePerformUpkeep(upkeepId, '0x') - - assert.equal(simulatePerformResult.success, false) - assert.isTrue(simulatePerformResult.gasUsed.gt(BigNumber.from('0'))) // Some gas should be used - }) - - it('returns true, gasUsed, and performGas when perform succeeds', async () => { - await mock.setCanPerform(true) - - const simulatePerformResult = await registry - .connect(zeroAddress) - .callStatic.simulatePerformUpkeep(upkeepId, '0x') - - assert.equal(simulatePerformResult.success, true) - assert.isTrue(simulatePerformResult.gasUsed.gt(BigNumber.from('0'))) // Some gas should be used - }) - - it('returns correct amount of gasUsed when perform succeeds', async () => { - await mock.setCanPerform(true) - await mock.setPerformGasToBurn(performGas) - - const simulatePerformResult = await registry - .connect(zeroAddress) - .callStatic.simulatePerformUpkeep(upkeepId, '0x') - - assert.equal(simulatePerformResult.success, true) - // Full execute gas should be used, with some performGasBuffer(1000) - assert.isTrue( - simulatePerformResult.gasUsed.gt( - performGas.sub(BigNumber.from('1000')), - ), - ) - }) - }) - - describe('#checkUpkeep', () => { - it('reverts if called by non zero address', async () => { - await evmRevertCustomError( - registry - .connect(await owner.getAddress()) - .callStatic['checkUpkeep(uint256)'](upkeepId), - registry, - 'OnlySimulatedBackend', - ) - }) - - it('returns false and error code if the upkeep is cancelled by admin', async () => { - await registry.connect(admin).cancelUpkeep(upkeepId) - - const checkUpkeepResult = await registry - .connect(zeroAddress) - .callStatic['checkUpkeep(uint256)'](upkeepId) - - assert.equal(checkUpkeepResult.upkeepNeeded, false) - assert.equal(checkUpkeepResult.performData, '0x') - assert.equal( - checkUpkeepResult.upkeepFailureReason, - UpkeepFailureReason.UPKEEP_CANCELLED, - ) - expect(checkUpkeepResult.gasUsed).to.equal(0) - expect(checkUpkeepResult.gasLimit).to.equal(performGas) - }) - - it('returns false and error code if the upkeep is cancelled by owner', async () => { - await registry.connect(owner).cancelUpkeep(upkeepId) - - const checkUpkeepResult = await registry - .connect(zeroAddress) - .callStatic['checkUpkeep(uint256)'](upkeepId) - - assert.equal(checkUpkeepResult.upkeepNeeded, false) - assert.equal(checkUpkeepResult.performData, '0x') - assert.equal( - checkUpkeepResult.upkeepFailureReason, - UpkeepFailureReason.UPKEEP_CANCELLED, - ) - expect(checkUpkeepResult.gasUsed).to.equal(0) - expect(checkUpkeepResult.gasLimit).to.equal(performGas) - }) - - it('returns false and error code if the registry is paused', async () => { - await registry.connect(owner).pause() - - const checkUpkeepResult = await registry - .connect(zeroAddress) - .callStatic['checkUpkeep(uint256)'](upkeepId) - - assert.equal(checkUpkeepResult.upkeepNeeded, false) - assert.equal(checkUpkeepResult.performData, '0x') - assert.equal( - checkUpkeepResult.upkeepFailureReason, - UpkeepFailureReason.REGISTRY_PAUSED, - ) - expect(checkUpkeepResult.gasUsed).to.equal(0) - expect(checkUpkeepResult.gasLimit).to.equal(performGas) - }) - - it('returns false and error code if the upkeep is paused', async () => { - await registry.connect(admin).pauseUpkeep(upkeepId) - - const checkUpkeepResult = await registry - .connect(zeroAddress) - .callStatic['checkUpkeep(uint256)'](upkeepId) - - assert.equal(checkUpkeepResult.upkeepNeeded, false) - assert.equal(checkUpkeepResult.performData, '0x') - assert.equal( - checkUpkeepResult.upkeepFailureReason, - UpkeepFailureReason.UPKEEP_PAUSED, - ) - expect(checkUpkeepResult.gasUsed).to.equal(0) - expect(checkUpkeepResult.gasLimit).to.equal(performGas) - }) - - it('returns false and error code if user is out of funds', async () => { - const checkUpkeepResult = await registry - .connect(zeroAddress) - .callStatic['checkUpkeep(uint256)'](upkeepId) - - assert.equal(checkUpkeepResult.upkeepNeeded, false) - assert.equal(checkUpkeepResult.performData, '0x') - assert.equal( - checkUpkeepResult.upkeepFailureReason, - UpkeepFailureReason.INSUFFICIENT_BALANCE, - ) - expect(checkUpkeepResult.gasUsed).to.equal(0) - expect(checkUpkeepResult.gasLimit).to.equal(performGas) - }) - - context('when the registration is funded', () => { - beforeEach(async () => { - await linkToken.connect(admin).approve(registry.address, toWei('200')) - await registry.connect(admin).addFunds(upkeepId, toWei('100')) - await registry.connect(admin).addFunds(logUpkeepId, toWei('100')) - }) - - it('returns false, error code, and revert data if the target check reverts', async () => { - await mock.setShouldRevertCheck(true) - await mock.setCheckRevertReason( - 'custom revert error, clever way to insert offchain data', - ) - const checkUpkeepResult = await registry - .connect(zeroAddress) - .callStatic['checkUpkeep(uint256)'](upkeepId) - assert.equal(checkUpkeepResult.upkeepNeeded, false) - - const revertReasonBytes = `0x${checkUpkeepResult.performData.slice(10)}` // remove sighash - assert.equal( - ethers.utils.defaultAbiCoder.decode(['string'], revertReasonBytes)[0], - 'custom revert error, clever way to insert offchain data', - ) - assert.equal( - checkUpkeepResult.upkeepFailureReason, - UpkeepFailureReason.TARGET_CHECK_REVERTED, - ) - assert.isTrue(checkUpkeepResult.gasUsed.gt(BigNumber.from('0'))) // Some gas should be used - expect(checkUpkeepResult.gasLimit).to.equal(performGas) - // Feed data should be returned here - assert.isTrue(checkUpkeepResult.fastGasWei.gt(BigNumber.from('0'))) - assert.isTrue(checkUpkeepResult.linkNative.gt(BigNumber.from('0'))) - }) - - it('returns false, error code, and no revert data if the target check revert data exceeds maxRevertDataSize', async () => { - await mock.setShouldRevertCheck(true) - let longRevertReason = '' - for (let i = 0; i <= maxRevertDataSize.toNumber(); i++) { - longRevertReason += 'x' - } - await mock.setCheckRevertReason(longRevertReason) - const checkUpkeepResult = await registry - .connect(zeroAddress) - .callStatic['checkUpkeep(uint256)'](upkeepId) - assert.equal(checkUpkeepResult.upkeepNeeded, false) - - assert.equal(checkUpkeepResult.performData, '0x') - assert.equal( - checkUpkeepResult.upkeepFailureReason, - UpkeepFailureReason.REVERT_DATA_EXCEEDS_LIMIT, - ) - assert.isTrue(checkUpkeepResult.gasUsed.gt(BigNumber.from('0'))) // Some gas should be used - expect(checkUpkeepResult.gasLimit).to.equal(performGas) - }) - - it('returns false and error code if the upkeep is not needed', async () => { - await mock.setCanCheck(false) - const checkUpkeepResult = await registry - .connect(zeroAddress) - .callStatic['checkUpkeep(uint256)'](upkeepId) - - assert.equal(checkUpkeepResult.upkeepNeeded, false) - assert.equal(checkUpkeepResult.performData, '0x') - assert.equal( - checkUpkeepResult.upkeepFailureReason, - UpkeepFailureReason.UPKEEP_NOT_NEEDED, - ) - assert.isTrue(checkUpkeepResult.gasUsed.gt(BigNumber.from('0'))) // Some gas should be used - expect(checkUpkeepResult.gasLimit).to.equal(performGas) - }) - - it('returns false and error code if the performData exceeds limit', async () => { - let longBytes = '0x' - for (let i = 0; i < 5000; i++) { - longBytes += '1' - } - await mock.setCanCheck(true) - await mock.setPerformData(longBytes) - - const checkUpkeepResult = await registry - .connect(zeroAddress) - .callStatic['checkUpkeep(uint256)'](upkeepId) - - assert.equal(checkUpkeepResult.upkeepNeeded, false) - assert.equal(checkUpkeepResult.performData, '0x') - assert.equal( - checkUpkeepResult.upkeepFailureReason, - UpkeepFailureReason.PERFORM_DATA_EXCEEDS_LIMIT, - ) - assert.isTrue(checkUpkeepResult.gasUsed.gt(BigNumber.from('0'))) // Some gas should be used - expect(checkUpkeepResult.gasLimit).to.equal(performGas) - }) - - it('returns true with gas used if the target can execute', async () => { - await mock.setCanCheck(true) - await mock.setPerformData(randomBytes) - - const latestBlock = await ethers.provider.getBlock('latest') - - const checkUpkeepResult = await registry - .connect(zeroAddress) - .callStatic['checkUpkeep(uint256)'](upkeepId, { - blockTag: latestBlock.number, - }) - - assert.equal(checkUpkeepResult.upkeepNeeded, true) - assert.equal(checkUpkeepResult.performData, randomBytes) - assert.equal( - checkUpkeepResult.upkeepFailureReason, - UpkeepFailureReason.NONE, - ) - assert.isTrue(checkUpkeepResult.gasUsed.gt(BigNumber.from('0'))) // Some gas should be used - expect(checkUpkeepResult.gasLimit).to.equal(performGas) - assert.isTrue(checkUpkeepResult.fastGasWei.eq(gasWei)) - assert.isTrue(checkUpkeepResult.linkNative.eq(linkEth)) - }) - - it('calls checkLog for log-trigger upkeeps', async () => { - const log: Log = { - index: 0, - timestamp: 0, - txHash: ethers.utils.randomBytes(32), - blockNumber: 100, - blockHash: ethers.utils.randomBytes(32), - source: randomAddress(), - topics: [ethers.utils.randomBytes(32), ethers.utils.randomBytes(32)], - data: ethers.utils.randomBytes(1000), - } - - await ltUpkeep.mock.checkLog.withArgs(log, '0x').returns(true, '0x1234') - - const checkData = encodeLog(log) - - const checkUpkeepResult = await registry - .connect(zeroAddress) - .callStatic['checkUpkeep(uint256,bytes)'](logUpkeepId, checkData) - - expect(checkUpkeepResult.upkeepNeeded).to.be.true - expect(checkUpkeepResult.performData).to.equal('0x1234') - }) - - itMaybe( - 'has a large enough gas overhead to cover upkeeps that use all their gas [ @skip-coverage ]', - async () => { - await mock.setCanCheck(true) - await mock.setCheckGasToBurn(checkGasLimit) - const gas = checkGasLimit.add(checkGasOverhead) - const checkUpkeepResult = await registry - .connect(zeroAddress) - .callStatic['checkUpkeep(uint256)'](upkeepId, { - gasLimit: gas, - }) - - assert.equal(checkUpkeepResult.upkeepNeeded, true) - }, - ) - }) - }) - - describe('#addFunds', () => { - const amount = toWei('1') - - it('reverts if the registration does not exist', async () => { - await evmRevertCustomError( - registry.connect(keeper1).addFunds(upkeepId.add(1), amount), - registry, - 'UpkeepCancelled', - ) - }) - - it('adds to the balance of the registration', async () => { - await registry.connect(admin).addFunds(upkeepId, amount) - const registration = await registry.getUpkeep(upkeepId) - assert.isTrue(amount.eq(registration.balance)) - }) - - it('lets anyone add funds to an upkeep not just admin', async () => { - await linkToken.connect(owner).transfer(await payee1.getAddress(), amount) - await linkToken.connect(payee1).approve(registry.address, amount) - - await registry.connect(payee1).addFunds(upkeepId, amount) - const registration = await registry.getUpkeep(upkeepId) - assert.isTrue(amount.eq(registration.balance)) - }) - - it('emits a log', async () => { - const tx = await registry.connect(admin).addFunds(upkeepId, amount) - await expect(tx) - .to.emit(registry, 'FundsAdded') - .withArgs(upkeepId, await admin.getAddress(), amount) - }) - - it('reverts if the upkeep is canceled', async () => { - await registry.connect(admin).cancelUpkeep(upkeepId) - await evmRevertCustomError( - registry.connect(keeper1).addFunds(upkeepId, amount), - registry, - 'UpkeepCancelled', - ) - }) - }) - - describe('#getActiveUpkeepIDs', () => { - it('reverts if startIndex is out of bounds ', async () => { - await evmRevertCustomError( - registry.getActiveUpkeepIDs(numUpkeeps, 0), - registry, - 'IndexOutOfRange', - ) - await evmRevertCustomError( - registry.getActiveUpkeepIDs(numUpkeeps + 1, 0), - registry, - 'IndexOutOfRange', - ) - }) - - it('returns upkeep IDs bounded by maxCount', async () => { - let upkeepIds = await registry.getActiveUpkeepIDs(0, 1) - assert(upkeepIds.length == 1) - assert(upkeepIds[0].eq(upkeepId)) - upkeepIds = await registry.getActiveUpkeepIDs(1, 3) - assert(upkeepIds.length == 3) - expect(upkeepIds).to.deep.equal([ - afUpkeepId, - logUpkeepId, - streamsLookupUpkeepId, - ]) - }) - - it('returns as many ids as possible if maxCount > num available', async () => { - const upkeepIds = await registry.getActiveUpkeepIDs(1, numUpkeeps + 100) - assert(upkeepIds.length == numUpkeeps - 1) - }) - - it('returns all upkeep IDs if maxCount is 0', async () => { - let upkeepIds = await registry.getActiveUpkeepIDs(0, 0) - assert(upkeepIds.length == numUpkeeps) - upkeepIds = await registry.getActiveUpkeepIDs(2, 0) - assert(upkeepIds.length == numUpkeeps - 2) - }) - }) - - describe('#getMaxPaymentForGas', () => { - let maxl1CostWeiArbWithoutMultiplier: BigNumber - let maxl1CostWeiOptWithoutMultiplier: BigNumber - - beforeEach(async () => { - const arbL1PriceinWei = BigNumber.from(1000) // Same as MockArbGasInfo.sol - maxl1CostWeiArbWithoutMultiplier = arbL1PriceinWei.mul( - maxPerformDataSize - .add(registryTransmitCalldataFixedBytesOverhead) - .add( - registryTransmitCalldataPerSignerBytesOverhead.mul( - BigNumber.from(f + 1), - ), - ), - ) - maxl1CostWeiOptWithoutMultiplier = BigNumber.from(2000000) // Same as MockOVMGasPriceOracle.sol - }) - - itMaybe('calculates the max fee appropriately', async () => { - await verifyMaxPayment(registry, chainModuleBase) - }) - - itMaybe('calculates the max fee appropriately for Arbitrum', async () => { - await verifyMaxPayment( - arbRegistry, - arbitrumModule, - maxl1CostWeiArbWithoutMultiplier, - ) - }) - - itMaybe('calculates the max fee appropriately for Optimism', async () => { - await verifyMaxPayment( - opRegistry, - optimismModule, - maxl1CostWeiOptWithoutMultiplier, - ) - }) - - it('uses the fallback gas price if the feed has issues', async () => { - const chainModuleOverheads = await chainModuleBase.getGasOverhead() - const expectedFallbackMaxPayment = linkForGas( - performGas, - registryConditionalOverhead - .add(registryPerSignerGasOverhead.mul(f + 1)) - .add( - maxPerformDataSize - .add(registryTransmitCalldataFixedBytesOverhead) - .add( - registryTransmitCalldataPerSignerBytesOverhead.mul( - BigNumber.from(f + 1), - ), - ) - .mul( - registryPerPerformByteGasOverhead.add( - chainModuleOverheads.chainModulePerByteOverhead, - ), - ), - ) - .add(chainModuleOverheads.chainModuleFixedOverhead), - gasCeilingMultiplier.mul('2'), // fallbackGasPrice is 2x gas price - paymentPremiumPPB, - flatFeeMicroLink, - ).total - - // Stale feed - let roundId = 99 - const answer = 100 - let updatedAt = 946684800 // New Years 2000 🥳 - let startedAt = 946684799 - await gasPriceFeed - .connect(owner) - .updateRoundData(roundId, answer, updatedAt, startedAt) - - assert.equal( - expectedFallbackMaxPayment.toString(), - ( - await registry.getMaxPaymentForGas(Trigger.CONDITION, performGas) - ).toString(), - ) - - // Negative feed price - roundId = 100 - updatedAt = now() - startedAt = 946684799 - await gasPriceFeed - .connect(owner) - .updateRoundData(roundId, -100, updatedAt, startedAt) - - assert.equal( - expectedFallbackMaxPayment.toString(), - ( - await registry.getMaxPaymentForGas(Trigger.CONDITION, performGas) - ).toString(), - ) - - // Zero feed price - roundId = 101 - updatedAt = now() - startedAt = 946684799 - await gasPriceFeed - .connect(owner) - .updateRoundData(roundId, 0, updatedAt, startedAt) - - assert.equal( - expectedFallbackMaxPayment.toString(), - ( - await registry.getMaxPaymentForGas(Trigger.CONDITION, performGas) - ).toString(), - ) - }) - - it('uses the fallback link price if the feed has issues', async () => { - const chainModuleOverheads = await chainModuleBase.getGasOverhead() - const expectedFallbackMaxPayment = linkForGas( - performGas, - registryConditionalOverhead - .add(registryPerSignerGasOverhead.mul(f + 1)) - .add( - maxPerformDataSize - .add(registryTransmitCalldataFixedBytesOverhead) - .add( - registryTransmitCalldataPerSignerBytesOverhead.mul( - BigNumber.from(f + 1), - ), - ) - .mul( - registryPerPerformByteGasOverhead.add( - chainModuleOverheads.chainModulePerByteOverhead, - ), - ), - ) - .add(chainModuleOverheads.chainModuleFixedOverhead), - gasCeilingMultiplier.mul('2'), // fallbackLinkPrice is 1/2 link price, so multiply by 2 - paymentPremiumPPB, - flatFeeMicroLink, - ).total - - // Stale feed - let roundId = 99 - const answer = 100 - let updatedAt = 946684800 // New Years 2000 🥳 - let startedAt = 946684799 - await linkEthFeed - .connect(owner) - .updateRoundData(roundId, answer, updatedAt, startedAt) - - assert.equal( - expectedFallbackMaxPayment.toString(), - ( - await registry.getMaxPaymentForGas(Trigger.CONDITION, performGas) - ).toString(), - ) - - // Negative feed price - roundId = 100 - updatedAt = now() - startedAt = 946684799 - await linkEthFeed - .connect(owner) - .updateRoundData(roundId, -100, updatedAt, startedAt) - - assert.equal( - expectedFallbackMaxPayment.toString(), - ( - await registry.getMaxPaymentForGas(Trigger.CONDITION, performGas) - ).toString(), - ) - - // Zero feed price - roundId = 101 - updatedAt = now() - startedAt = 946684799 - await linkEthFeed - .connect(owner) - .updateRoundData(roundId, 0, updatedAt, startedAt) - - assert.equal( - expectedFallbackMaxPayment.toString(), - ( - await registry.getMaxPaymentForGas(Trigger.CONDITION, performGas) - ).toString(), - ) - }) - }) - - describe('#typeAndVersion', () => { - it('uses the correct type and version', async () => { - const typeAndVersion = await registry.typeAndVersion() - assert.equal(typeAndVersion, 'AutomationRegistry 2.2.0') - }) - }) - - describe('#onTokenTransfer', () => { - const amount = toWei('1') - - it('reverts if not called by the LINK token', async () => { - const data = ethers.utils.defaultAbiCoder.encode(['uint256'], [upkeepId]) - - await evmRevertCustomError( - registry - .connect(keeper1) - .onTokenTransfer(await keeper1.getAddress(), amount, data), - registry, - 'OnlyCallableByLINKToken', - ) - }) - - it('reverts if not called with more or less than 32 bytes', async () => { - const longData = ethers.utils.defaultAbiCoder.encode( - ['uint256', 'uint256'], - ['33', '34'], - ) - const shortData = '0x12345678' - - await evmRevert( - linkToken - .connect(owner) - .transferAndCall(registry.address, amount, longData), - ) - await evmRevert( - linkToken - .connect(owner) - .transferAndCall(registry.address, amount, shortData), - ) - }) - - it('reverts if the upkeep is canceled', async () => { - await registry.connect(admin).cancelUpkeep(upkeepId) - await evmRevertCustomError( - registry.connect(keeper1).addFunds(upkeepId, amount), - registry, - 'UpkeepCancelled', - ) - }) - - it('updates the funds of the job id passed', async () => { - const data = ethers.utils.defaultAbiCoder.encode(['uint256'], [upkeepId]) - - const before = (await registry.getUpkeep(upkeepId)).balance - await linkToken - .connect(owner) - .transferAndCall(registry.address, amount, data) - const after = (await registry.getUpkeep(upkeepId)).balance - - assert.isTrue(before.add(amount).eq(after)) - }) - }) - - describeMaybe('#setConfig - onchain', async () => { - const payment = BigNumber.from(1) - const flatFee = BigNumber.from(2) - const maxGas = BigNumber.from(6) - const staleness = BigNumber.from(4) - const ceiling = BigNumber.from(5) - const newMinUpkeepSpend = BigNumber.from(9) - const newMaxCheckDataSize = BigNumber.from(10000) - const newMaxPerformDataSize = BigNumber.from(10000) - const newMaxRevertDataSize = BigNumber.from(10000) - const newMaxPerformGas = BigNumber.from(10000000) - const fbGasEth = BigNumber.from(7) - const fbLinkEth = BigNumber.from(8) - const newTranscoder = randomAddress() - const newRegistrars = [randomAddress(), randomAddress()] - const upkeepManager = randomAddress() - - const newConfig = { - paymentPremiumPPB: payment, - flatFeeMicroLink: flatFee, - checkGasLimit: maxGas, - stalenessSeconds: staleness, - gasCeilingMultiplier: ceiling, - minUpkeepSpend: newMinUpkeepSpend, - maxCheckDataSize: newMaxCheckDataSize, - maxPerformDataSize: newMaxPerformDataSize, - maxRevertDataSize: newMaxRevertDataSize, - maxPerformGas: newMaxPerformGas, - fallbackGasPrice: fbGasEth, - fallbackLinkPrice: fbLinkEth, - transcoder: newTranscoder, - registrars: newRegistrars, - upkeepPrivilegeManager: upkeepManager, - chainModule: chainModuleBase.address, - reorgProtectionEnabled: true, - } - - it('reverts when called by anyone but the proposed owner', async () => { - await evmRevert( - registry - .connect(payee1) - .setConfigTypeSafe( - signerAddresses, - keeperAddresses, - f, - newConfig, - offchainVersion, - offchainBytes, - ), - 'Only callable by owner', - ) - }) - - it('reverts if signers or transmitters are the zero address', async () => { - await evmRevertCustomError( - registry - .connect(owner) - .setConfigTypeSafe( - [randomAddress(), randomAddress(), randomAddress(), zeroAddress], - [ - randomAddress(), - randomAddress(), - randomAddress(), - randomAddress(), - ], - f, - newConfig, - offchainVersion, - offchainBytes, - ), - registry, - 'InvalidSigner', - ) - - await evmRevertCustomError( - registry - .connect(owner) - .setConfigTypeSafe( - [ - randomAddress(), - randomAddress(), - randomAddress(), - randomAddress(), - ], - [randomAddress(), randomAddress(), randomAddress(), zeroAddress], - f, - newConfig, - offchainVersion, - offchainBytes, - ), - registry, - 'InvalidTransmitter', - ) - }) - - it('updates the onchainConfig and configDigest', async () => { - const old = await registry.getState() - const oldConfig = old.config - const oldState = old.state - assert.isTrue(paymentPremiumPPB.eq(oldConfig.paymentPremiumPPB)) - assert.isTrue(flatFeeMicroLink.eq(oldConfig.flatFeeMicroLink)) - assert.isTrue(stalenessSeconds.eq(oldConfig.stalenessSeconds)) - assert.isTrue(gasCeilingMultiplier.eq(oldConfig.gasCeilingMultiplier)) - - await registry - .connect(owner) - .setConfigTypeSafe( - signerAddresses, - keeperAddresses, - f, - newConfig, - offchainVersion, - offchainBytes, - ) - - const updated = await registry.getState() - const updatedConfig = updated.config - const updatedState = updated.state - assert.equal(updatedConfig.paymentPremiumPPB, payment.toNumber()) - assert.equal(updatedConfig.flatFeeMicroLink, flatFee.toNumber()) - assert.equal(updatedConfig.stalenessSeconds, staleness.toNumber()) - assert.equal(updatedConfig.gasCeilingMultiplier, ceiling.toNumber()) - assert.equal( - updatedConfig.minUpkeepSpend.toString(), - newMinUpkeepSpend.toString(), - ) - assert.equal( - updatedConfig.maxCheckDataSize, - newMaxCheckDataSize.toNumber(), - ) - assert.equal( - updatedConfig.maxPerformDataSize, - newMaxPerformDataSize.toNumber(), - ) - assert.equal( - updatedConfig.maxRevertDataSize, - newMaxRevertDataSize.toNumber(), - ) - assert.equal(updatedConfig.maxPerformGas, newMaxPerformGas.toNumber()) - assert.equal(updatedConfig.checkGasLimit, maxGas.toNumber()) - assert.equal( - updatedConfig.fallbackGasPrice.toNumber(), - fbGasEth.toNumber(), - ) - assert.equal( - updatedConfig.fallbackLinkPrice.toNumber(), - fbLinkEth.toNumber(), - ) - assert.equal(updatedState.latestEpoch, 0) - - assert(oldState.configCount + 1 == updatedState.configCount) - assert( - oldState.latestConfigBlockNumber != - updatedState.latestConfigBlockNumber, - ) - assert(oldState.latestConfigDigest != updatedState.latestConfigDigest) - - assert.equal(updatedConfig.transcoder, newTranscoder) - assert.deepEqual(updatedConfig.registrars, newRegistrars) - assert.equal(updatedConfig.upkeepPrivilegeManager, upkeepManager) - }) - - it('maintains paused state when config is changed', async () => { - await registry.pause() - const old = await registry.getState() - assert.isTrue(old.state.paused) - - await registry - .connect(owner) - .setConfigTypeSafe( - signerAddresses, - keeperAddresses, - f, - newConfig, - offchainVersion, - offchainBytes, - ) - - const updated = await registry.getState() - assert.isTrue(updated.state.paused) - }) - - it('emits an event', async () => { - const tx = await registry - .connect(owner) - .setConfigTypeSafe( - signerAddresses, - keeperAddresses, - f, - newConfig, - offchainVersion, - offchainBytes, - ) - await expect(tx).to.emit(registry, 'ConfigSet') - }) - }) - - describe('#setConfig - offchain', () => { - let newKeepers: string[] - - beforeEach(async () => { - newKeepers = [ - await personas.Eddy.getAddress(), - await personas.Nick.getAddress(), - await personas.Neil.getAddress(), - await personas.Carol.getAddress(), - ] - }) - - it('reverts when called by anyone but the owner', async () => { - await evmRevert( - registry - .connect(payee1) - .setConfigTypeSafe( - newKeepers, - newKeepers, - f, - config, - offchainVersion, - offchainBytes, - ), - 'Only callable by owner', - ) - }) - - it('reverts if too many keeperAddresses set', async () => { - for (let i = 0; i < 40; i++) { - newKeepers.push(randomAddress()) - } - await evmRevertCustomError( - registry - .connect(owner) - .setConfigTypeSafe( - newKeepers, - newKeepers, - f, - config, - offchainVersion, - offchainBytes, - ), - registry, - 'TooManyOracles', - ) - }) - - it('reverts if f=0', async () => { - await evmRevertCustomError( - registry - .connect(owner) - .setConfigTypeSafe( - newKeepers, - newKeepers, - 0, - config, - offchainVersion, - offchainBytes, - ), - registry, - 'IncorrectNumberOfFaultyOracles', - ) - }) - - it('reverts if signers != transmitters length', async () => { - const signers = [randomAddress()] - await evmRevertCustomError( - registry - .connect(owner) - .setConfigTypeSafe( - signers, - newKeepers, - f, - config, - offchainVersion, - offchainBytes, - ), - registry, - 'IncorrectNumberOfSigners', - ) - }) - - it('reverts if signers <= 3f', async () => { - newKeepers.pop() - await evmRevertCustomError( - registry - .connect(owner) - .setConfigTypeSafe( - newKeepers, - newKeepers, - f, - config, - offchainVersion, - offchainBytes, - ), - registry, - 'IncorrectNumberOfSigners', - ) - }) - - it('reverts on repeated signers', async () => { - const newSigners = [ - await personas.Eddy.getAddress(), - await personas.Eddy.getAddress(), - await personas.Eddy.getAddress(), - await personas.Eddy.getAddress(), - ] - await evmRevertCustomError( - registry - .connect(owner) - .setConfigTypeSafe( - newSigners, - newKeepers, - f, - config, - offchainVersion, - offchainBytes, - ), - registry, - 'RepeatedSigner', - ) - }) - - it('reverts on repeated transmitters', async () => { - const newTransmitters = [ - await personas.Eddy.getAddress(), - await personas.Eddy.getAddress(), - await personas.Eddy.getAddress(), - await personas.Eddy.getAddress(), - ] - await evmRevertCustomError( - registry - .connect(owner) - .setConfigTypeSafe( - newKeepers, - newTransmitters, - f, - config, - offchainVersion, - offchainBytes, - ), - registry, - 'RepeatedTransmitter', - ) - }) - - itMaybe('stores new config and emits event', async () => { - // Perform an upkeep so that totalPremium is updated - await registry.connect(admin).addFunds(upkeepId, toWei('100')) - let tx = await getTransmitTx(registry, keeper1, [upkeepId]) - await tx.wait() - - const newOffChainVersion = BigNumber.from('2') - const newOffChainConfig = '0x1122' - - const old = await registry.getState() - const oldState = old.state - assert(oldState.totalPremium.gt(BigNumber.from('0'))) - - const newSigners = newKeepers - tx = await registry - .connect(owner) - .setConfigTypeSafe( - newSigners, - newKeepers, - f, - config, - newOffChainVersion, - newOffChainConfig, - ) - - const updated = await registry.getState() - const updatedState = updated.state - assert(oldState.totalPremium.eq(updatedState.totalPremium)) - - // Old signer addresses which are not in new signers should be non active - for (let i = 0; i < signerAddresses.length; i++) { - const signer = signerAddresses[i] - if (!newSigners.includes(signer)) { - assert(!(await registry.getSignerInfo(signer)).active) - assert((await registry.getSignerInfo(signer)).index == 0) - } - } - // New signer addresses should be active - for (let i = 0; i < newSigners.length; i++) { - const signer = newSigners[i] - assert((await registry.getSignerInfo(signer)).active) - assert((await registry.getSignerInfo(signer)).index == i) - } - // Old transmitter addresses which are not in new transmitter should be non active, update lastCollected but retain other info - for (let i = 0; i < keeperAddresses.length; i++) { - const transmitter = keeperAddresses[i] - if (!newKeepers.includes(transmitter)) { - assert(!(await registry.getTransmitterInfo(transmitter)).active) - assert((await registry.getTransmitterInfo(transmitter)).index == i) - assert( - (await registry.getTransmitterInfo(transmitter)).lastCollected.eq( - oldState.totalPremium.sub( - oldState.totalPremium.mod(keeperAddresses.length), - ), - ), - ) - } - } - // New transmitter addresses should be active - for (let i = 0; i < newKeepers.length; i++) { - const transmitter = newKeepers[i] - assert((await registry.getTransmitterInfo(transmitter)).active) - assert((await registry.getTransmitterInfo(transmitter)).index == i) - assert( - (await registry.getTransmitterInfo(transmitter)).lastCollected.eq( - oldState.totalPremium, - ), - ) - } - - // config digest should be updated - assert(oldState.configCount + 1 == updatedState.configCount) - assert( - oldState.latestConfigBlockNumber != - updatedState.latestConfigBlockNumber, - ) - assert(oldState.latestConfigDigest != updatedState.latestConfigDigest) - - //New config should be updated - assert.deepEqual(updated.signers, newKeepers) - assert.deepEqual(updated.transmitters, newKeepers) - - // Event should have been emitted - await expect(tx).to.emit(registry, 'ConfigSet') - }) - }) - - describe('#setPeerRegistryMigrationPermission() / #getPeerRegistryMigrationPermission()', () => { - const peer = randomAddress() - it('allows the owner to set the peer registries', async () => { - let permission = await registry.getPeerRegistryMigrationPermission(peer) - expect(permission).to.equal(0) - await registry.setPeerRegistryMigrationPermission(peer, 1) - permission = await registry.getPeerRegistryMigrationPermission(peer) - expect(permission).to.equal(1) - await registry.setPeerRegistryMigrationPermission(peer, 2) - permission = await registry.getPeerRegistryMigrationPermission(peer) - expect(permission).to.equal(2) - await registry.setPeerRegistryMigrationPermission(peer, 0) - permission = await registry.getPeerRegistryMigrationPermission(peer) - expect(permission).to.equal(0) - }) - it('reverts if passed an unsupported permission', async () => { - await expect( - registry.connect(admin).setPeerRegistryMigrationPermission(peer, 10), - ).to.be.reverted - }) - it('reverts if not called by the owner', async () => { - await expect( - registry.connect(admin).setPeerRegistryMigrationPermission(peer, 1), - ).to.be.revertedWith('Only callable by owner') - }) - }) - - describe('#registerUpkeep', () => { - it('reverts when registry is paused', async () => { - await registry.connect(owner).pause() - await evmRevertCustomError( - registry - .connect(owner) - [ - 'registerUpkeep(address,uint32,address,bytes,bytes)' - ](mock.address, performGas, await admin.getAddress(), emptyBytes, '0x'), - registry, - 'RegistryPaused', - ) - }) - - it('reverts if the target is not a contract', async () => { - await evmRevertCustomError( - registry - .connect(owner) - [ - 'registerUpkeep(address,uint32,address,bytes,bytes)' - ](zeroAddress, performGas, await admin.getAddress(), emptyBytes, '0x'), - registry, - 'NotAContract', - ) - }) - - it('reverts if called by a non-owner', async () => { - await evmRevertCustomError( - registry - .connect(keeper1) - [ - 'registerUpkeep(address,uint32,address,bytes,bytes)' - ](mock.address, performGas, await admin.getAddress(), emptyBytes, '0x'), - registry, - 'OnlyCallableByOwnerOrRegistrar', - ) - }) - - it('reverts if execute gas is too low', async () => { - await evmRevertCustomError( - registry - .connect(owner) - [ - 'registerUpkeep(address,uint32,address,bytes,bytes)' - ](mock.address, 2299, await admin.getAddress(), emptyBytes, '0x'), - registry, - 'GasLimitOutsideRange', - ) - }) - - it('reverts if execute gas is too high', async () => { - await evmRevertCustomError( - registry - .connect(owner) - [ - 'registerUpkeep(address,uint32,address,bytes,bytes)' - ](mock.address, 5000001, await admin.getAddress(), emptyBytes, '0x'), - registry, - 'GasLimitOutsideRange', - ) - }) - - it('reverts if checkData is too long', async () => { - let longBytes = '0x' - for (let i = 0; i < 10000; i++) { - longBytes += '1' - } - await evmRevertCustomError( - registry - .connect(owner) - [ - 'registerUpkeep(address,uint32,address,bytes,bytes)' - ](mock.address, performGas, await admin.getAddress(), longBytes, '0x'), - registry, - 'CheckDataExceedsLimit', - ) - }) - - it('creates a record of the registration', async () => { - const performGases = [100000, 500000] - const checkDatas = [emptyBytes, '0x12'] - - for (let jdx = 0; jdx < performGases.length; jdx++) { - const performGas = performGases[jdx] - for (let kdx = 0; kdx < checkDatas.length; kdx++) { - const checkData = checkDatas[kdx] - const tx = await registry - .connect(owner) - [ - 'registerUpkeep(address,uint32,address,bytes,bytes)' - ](mock.address, performGas, await admin.getAddress(), checkData, '0x') - - //confirm the upkeep details and verify emitted events - const testUpkeepId = await getUpkeepID(tx) - await expect(tx) - .to.emit(registry, 'UpkeepRegistered') - .withArgs(testUpkeepId, performGas, await admin.getAddress()) - - await expect(tx) - .to.emit(registry, 'UpkeepCheckDataSet') - .withArgs(testUpkeepId, checkData) - await expect(tx) - .to.emit(registry, 'UpkeepTriggerConfigSet') - .withArgs(testUpkeepId, '0x') - - const registration = await registry.getUpkeep(testUpkeepId) - - assert.equal(mock.address, registration.target) - assert.notEqual( - ethers.constants.AddressZero, - await registry.getForwarder(testUpkeepId), - ) - assert.equal( - performGas.toString(), - registration.performGas.toString(), - ) - assert.equal(await admin.getAddress(), registration.admin) - assert.equal(0, registration.balance.toNumber()) - assert.equal(0, registration.amountSpent.toNumber()) - assert.equal(0, registration.lastPerformedBlockNumber) - assert.equal(checkData, registration.checkData) - assert.equal(registration.paused, false) - assert.equal(registration.offchainConfig, '0x') - assert(registration.maxValidBlocknumber.eq('0xffffffff')) - } - } - }) - }) - - describe('#pauseUpkeep', () => { - it('reverts if the registration does not exist', async () => { - await evmRevertCustomError( - registry.connect(keeper1).pauseUpkeep(upkeepId.add(1)), - registry, - 'OnlyCallableByAdmin', - ) - }) - - it('reverts if the upkeep is already canceled', async () => { - await registry.connect(admin).cancelUpkeep(upkeepId) - - await evmRevertCustomError( - registry.connect(admin).pauseUpkeep(upkeepId), - registry, - 'UpkeepCancelled', - ) - }) - - it('reverts if the upkeep is already paused', async () => { - await registry.connect(admin).pauseUpkeep(upkeepId) - - await evmRevertCustomError( - registry.connect(admin).pauseUpkeep(upkeepId), - registry, - 'OnlyUnpausedUpkeep', - ) - }) - - it('reverts if the caller is not the upkeep admin', async () => { - await evmRevertCustomError( - registry.connect(keeper1).pauseUpkeep(upkeepId), - registry, - 'OnlyCallableByAdmin', - ) - }) - - it('pauses the upkeep and emits an event', async () => { - const tx = await registry.connect(admin).pauseUpkeep(upkeepId) - await expect(tx).to.emit(registry, 'UpkeepPaused').withArgs(upkeepId) - - const registration = await registry.getUpkeep(upkeepId) - assert.equal(registration.paused, true) - }) - }) - - describe('#unpauseUpkeep', () => { - it('reverts if the registration does not exist', async () => { - await evmRevertCustomError( - registry.connect(keeper1).unpauseUpkeep(upkeepId.add(1)), - registry, - 'OnlyCallableByAdmin', - ) - }) - - it('reverts if the upkeep is already canceled', async () => { - await registry.connect(owner).cancelUpkeep(upkeepId) - - await evmRevertCustomError( - registry.connect(admin).unpauseUpkeep(upkeepId), - registry, - 'UpkeepCancelled', - ) - }) - - it('marks the contract as paused', async () => { - assert.isFalse((await registry.getState()).state.paused) - - await registry.connect(owner).pause() - - assert.isTrue((await registry.getState()).state.paused) - }) - - it('reverts if the upkeep is not paused', async () => { - await evmRevertCustomError( - registry.connect(admin).unpauseUpkeep(upkeepId), - registry, - 'OnlyPausedUpkeep', - ) - }) - - it('reverts if the caller is not the upkeep admin', async () => { - await registry.connect(admin).pauseUpkeep(upkeepId) - - const registration = await registry.getUpkeep(upkeepId) - - assert.equal(registration.paused, true) - - await evmRevertCustomError( - registry.connect(keeper1).unpauseUpkeep(upkeepId), - registry, - 'OnlyCallableByAdmin', - ) - }) - - it('unpauses the upkeep and emits an event', async () => { - const originalCount = (await registry.getActiveUpkeepIDs(0, 0)).length - - await registry.connect(admin).pauseUpkeep(upkeepId) - - const tx = await registry.connect(admin).unpauseUpkeep(upkeepId) - - await expect(tx).to.emit(registry, 'UpkeepUnpaused').withArgs(upkeepId) - - const registration = await registry.getUpkeep(upkeepId) - assert.equal(registration.paused, false) - - const upkeepIds = await registry.getActiveUpkeepIDs(0, 0) - assert.equal(upkeepIds.length, originalCount) - }) - }) - - describe('#setUpkeepCheckData', () => { - it('reverts if the registration does not exist', async () => { - await evmRevertCustomError( - registry - .connect(keeper1) - .setUpkeepCheckData(upkeepId.add(1), randomBytes), - registry, - 'OnlyCallableByAdmin', - ) - }) - - it('reverts if the caller is not upkeep admin', async () => { - await evmRevertCustomError( - registry.connect(keeper1).setUpkeepCheckData(upkeepId, randomBytes), - registry, - 'OnlyCallableByAdmin', - ) - }) - - it('reverts if the upkeep is cancelled', async () => { - await registry.connect(admin).cancelUpkeep(upkeepId) - - await evmRevertCustomError( - registry.connect(admin).setUpkeepCheckData(upkeepId, randomBytes), - registry, - 'UpkeepCancelled', - ) - }) - - it('is allowed to update on paused upkeep', async () => { - await registry.connect(admin).pauseUpkeep(upkeepId) - await registry.connect(admin).setUpkeepCheckData(upkeepId, randomBytes) - - const registration = await registry.getUpkeep(upkeepId) - assert.equal(randomBytes, registration.checkData) - }) - - it('reverts if new data exceeds limit', async () => { - let longBytes = '0x' - for (let i = 0; i < 10000; i++) { - longBytes += '1' - } - - await evmRevertCustomError( - registry.connect(admin).setUpkeepCheckData(upkeepId, longBytes), - registry, - 'CheckDataExceedsLimit', - ) - }) - - it('updates the upkeep check data and emits an event', async () => { - const tx = await registry - .connect(admin) - .setUpkeepCheckData(upkeepId, randomBytes) - await expect(tx) - .to.emit(registry, 'UpkeepCheckDataSet') - .withArgs(upkeepId, randomBytes) - - const registration = await registry.getUpkeep(upkeepId) - assert.equal(randomBytes, registration.checkData) - }) - }) - - describe('#setUpkeepGasLimit', () => { - const newGasLimit = BigNumber.from('300000') - - it('reverts if the registration does not exist', async () => { - await evmRevertCustomError( - registry.connect(admin).setUpkeepGasLimit(upkeepId.add(1), newGasLimit), - registry, - 'OnlyCallableByAdmin', - ) - }) - - it('reverts if the upkeep is canceled', async () => { - await registry.connect(admin).cancelUpkeep(upkeepId) - await evmRevertCustomError( - registry.connect(admin).setUpkeepGasLimit(upkeepId, newGasLimit), - registry, - 'UpkeepCancelled', - ) - }) - - it('reverts if called by anyone but the admin', async () => { - await evmRevertCustomError( - registry.connect(owner).setUpkeepGasLimit(upkeepId, newGasLimit), - registry, - 'OnlyCallableByAdmin', - ) - }) - - it('reverts if new gas limit is out of bounds', async () => { - await evmRevertCustomError( - registry - .connect(admin) - .setUpkeepGasLimit(upkeepId, BigNumber.from('100')), - registry, - 'GasLimitOutsideRange', - ) - await evmRevertCustomError( - registry - .connect(admin) - .setUpkeepGasLimit(upkeepId, BigNumber.from('6000000')), - registry, - 'GasLimitOutsideRange', - ) - }) - - it('updates the gas limit successfully', async () => { - const initialGasLimit = (await registry.getUpkeep(upkeepId)).performGas - assert.equal(initialGasLimit, performGas.toNumber()) - await registry.connect(admin).setUpkeepGasLimit(upkeepId, newGasLimit) - const updatedGasLimit = (await registry.getUpkeep(upkeepId)).performGas - assert.equal(updatedGasLimit, newGasLimit.toNumber()) - }) - - it('emits a log', async () => { - const tx = await registry - .connect(admin) - .setUpkeepGasLimit(upkeepId, newGasLimit) - await expect(tx) - .to.emit(registry, 'UpkeepGasLimitSet') - .withArgs(upkeepId, newGasLimit) - }) - }) - - describe('#setUpkeepOffchainConfig', () => { - const newConfig = '0xc0ffeec0ffee' - - it('reverts if the registration does not exist', async () => { - await evmRevertCustomError( - registry - .connect(admin) - .setUpkeepOffchainConfig(upkeepId.add(1), newConfig), - registry, - 'OnlyCallableByAdmin', - ) - }) - - it('reverts if the upkeep is canceled', async () => { - await registry.connect(admin).cancelUpkeep(upkeepId) - await evmRevertCustomError( - registry.connect(admin).setUpkeepOffchainConfig(upkeepId, newConfig), - registry, - 'UpkeepCancelled', - ) - }) - - it('reverts if called by anyone but the admin', async () => { - await evmRevertCustomError( - registry.connect(owner).setUpkeepOffchainConfig(upkeepId, newConfig), - registry, - 'OnlyCallableByAdmin', - ) - }) - - it('updates the config successfully', async () => { - const initialConfig = (await registry.getUpkeep(upkeepId)).offchainConfig - assert.equal(initialConfig, '0x') - await registry.connect(admin).setUpkeepOffchainConfig(upkeepId, newConfig) - const updatedConfig = (await registry.getUpkeep(upkeepId)).offchainConfig - assert.equal(newConfig, updatedConfig) - }) - - it('emits a log', async () => { - const tx = await registry - .connect(admin) - .setUpkeepOffchainConfig(upkeepId, newConfig) - await expect(tx) - .to.emit(registry, 'UpkeepOffchainConfigSet') - .withArgs(upkeepId, newConfig) - }) - }) - - describe('#setUpkeepTriggerConfig', () => { - const newConfig = '0xdeadbeef' - - it('reverts if the registration does not exist', async () => { - await evmRevertCustomError( - registry - .connect(admin) - .setUpkeepTriggerConfig(upkeepId.add(1), newConfig), - registry, - 'OnlyCallableByAdmin', - ) - }) - - it('reverts if the upkeep is canceled', async () => { - await registry.connect(admin).cancelUpkeep(upkeepId) - await evmRevertCustomError( - registry.connect(admin).setUpkeepTriggerConfig(upkeepId, newConfig), - registry, - 'UpkeepCancelled', - ) - }) - - it('reverts if called by anyone but the admin', async () => { - await evmRevertCustomError( - registry.connect(owner).setUpkeepTriggerConfig(upkeepId, newConfig), - registry, - 'OnlyCallableByAdmin', - ) - }) - - it('emits a log', async () => { - const tx = await registry - .connect(admin) - .setUpkeepTriggerConfig(upkeepId, newConfig) - await expect(tx) - .to.emit(registry, 'UpkeepTriggerConfigSet') - .withArgs(upkeepId, newConfig) - }) - }) - - describe('#transferUpkeepAdmin', () => { - it('reverts when called by anyone but the current upkeep admin', async () => { - await evmRevertCustomError( - registry - .connect(payee1) - .transferUpkeepAdmin(upkeepId, await payee2.getAddress()), - registry, - 'OnlyCallableByAdmin', - ) - }) - - it('reverts when transferring to self', async () => { - await evmRevertCustomError( - registry - .connect(admin) - .transferUpkeepAdmin(upkeepId, await admin.getAddress()), - registry, - 'ValueNotChanged', - ) - }) - - it('reverts when the upkeep is cancelled', async () => { - await registry.connect(admin).cancelUpkeep(upkeepId) - - await evmRevertCustomError( - registry - .connect(admin) - .transferUpkeepAdmin(upkeepId, await keeper1.getAddress()), - registry, - 'UpkeepCancelled', - ) - }) - - it('allows cancelling transfer by reverting to zero address', async () => { - await registry - .connect(admin) - .transferUpkeepAdmin(upkeepId, await payee1.getAddress()) - const tx = await registry - .connect(admin) - .transferUpkeepAdmin(upkeepId, ethers.constants.AddressZero) - - await expect(tx) - .to.emit(registry, 'UpkeepAdminTransferRequested') - .withArgs( - upkeepId, - await admin.getAddress(), - ethers.constants.AddressZero, - ) - }) - - it('does not change the upkeep admin', async () => { - await registry - .connect(admin) - .transferUpkeepAdmin(upkeepId, await payee1.getAddress()) - - const upkeep = await registry.getUpkeep(upkeepId) - assert.equal(await admin.getAddress(), upkeep.admin) - }) - - it('emits an event announcing the new upkeep admin', async () => { - const tx = await registry - .connect(admin) - .transferUpkeepAdmin(upkeepId, await payee1.getAddress()) - - await expect(tx) - .to.emit(registry, 'UpkeepAdminTransferRequested') - .withArgs(upkeepId, await admin.getAddress(), await payee1.getAddress()) - }) - - it('does not emit an event when called with the same proposed upkeep admin', async () => { - await registry - .connect(admin) - .transferUpkeepAdmin(upkeepId, await payee1.getAddress()) - - const tx = await registry - .connect(admin) - .transferUpkeepAdmin(upkeepId, await payee1.getAddress()) - const receipt = await tx.wait() - assert.equal(0, receipt.logs.length) - }) - }) - - describe('#acceptUpkeepAdmin', () => { - beforeEach(async () => { - // Start admin transfer to payee1 - await registry - .connect(admin) - .transferUpkeepAdmin(upkeepId, await payee1.getAddress()) - }) - - it('reverts when not called by the proposed upkeep admin', async () => { - await evmRevertCustomError( - registry.connect(payee2).acceptUpkeepAdmin(upkeepId), - registry, - 'OnlyCallableByProposedAdmin', - ) - }) - - it('reverts when the upkeep is cancelled', async () => { - await registry.connect(admin).cancelUpkeep(upkeepId) - - await evmRevertCustomError( - registry.connect(payee1).acceptUpkeepAdmin(upkeepId), - registry, - 'UpkeepCancelled', - ) - }) - - it('does change the admin', async () => { - await registry.connect(payee1).acceptUpkeepAdmin(upkeepId) - - const upkeep = await registry.getUpkeep(upkeepId) - assert.equal(await payee1.getAddress(), upkeep.admin) - }) - - it('emits an event announcing the new upkeep admin', async () => { - const tx = await registry.connect(payee1).acceptUpkeepAdmin(upkeepId) - await expect(tx) - .to.emit(registry, 'UpkeepAdminTransferred') - .withArgs(upkeepId, await admin.getAddress(), await payee1.getAddress()) - }) - }) - - describe('#withdrawOwnerFunds', () => { - it('can only be called by owner', async () => { - await evmRevert( - registry.connect(keeper1).withdrawOwnerFunds(), - 'Only callable by owner', - ) - }) - - itMaybe('withdraws the collected fees to owner', async () => { - await registry.connect(admin).addFunds(upkeepId, toWei('100')) - // Very high min spend, whole balance as cancellation fees - const minUpkeepSpend = toWei('1000') - await registry.connect(owner).setConfigTypeSafe( - signerAddresses, - keeperAddresses, - f, - { - paymentPremiumPPB, - flatFeeMicroLink, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxCheckDataSize, - maxPerformDataSize, - maxRevertDataSize, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrars: [], - upkeepPrivilegeManager: upkeepManager, - chainModule: chainModuleBase.address, - reorgProtectionEnabled: true, - }, - offchainVersion, - offchainBytes, - ) - const upkeepBalance = (await registry.getUpkeep(upkeepId)).balance - const ownerBefore = await linkToken.balanceOf(await owner.getAddress()) - - await registry.connect(owner).cancelUpkeep(upkeepId) - - // Transfered to owner balance on registry - let ownerRegistryBalance = (await registry.getState()).state - .ownerLinkBalance - assert.isTrue(ownerRegistryBalance.eq(upkeepBalance)) - - // Now withdraw - await registry.connect(owner).withdrawOwnerFunds() - - ownerRegistryBalance = (await registry.getState()).state.ownerLinkBalance - const ownerAfter = await linkToken.balanceOf(await owner.getAddress()) - - // Owner registry balance should be changed to 0 - assert.isTrue(ownerRegistryBalance.eq(BigNumber.from('0'))) - - // Owner should be credited with the balance - assert.isTrue(ownerBefore.add(upkeepBalance).eq(ownerAfter)) - }) - }) - - describe('#transferPayeeship', () => { - it('reverts when called by anyone but the current payee', async () => { - await evmRevertCustomError( - registry - .connect(payee2) - .transferPayeeship( - await keeper1.getAddress(), - await payee2.getAddress(), - ), - registry, - 'OnlyCallableByPayee', - ) - }) - - it('reverts when transferring to self', async () => { - await evmRevertCustomError( - registry - .connect(payee1) - .transferPayeeship( - await keeper1.getAddress(), - await payee1.getAddress(), - ), - registry, - 'ValueNotChanged', - ) - }) - - it('does not change the payee', async () => { - await registry - .connect(payee1) - .transferPayeeship( - await keeper1.getAddress(), - await payee2.getAddress(), - ) - - const info = await registry.getTransmitterInfo(await keeper1.getAddress()) - assert.equal(await payee1.getAddress(), info.payee) - }) - - it('emits an event announcing the new payee', async () => { - const tx = await registry - .connect(payee1) - .transferPayeeship( - await keeper1.getAddress(), - await payee2.getAddress(), - ) - await expect(tx) - .to.emit(registry, 'PayeeshipTransferRequested') - .withArgs( - await keeper1.getAddress(), - await payee1.getAddress(), - await payee2.getAddress(), - ) - }) - - it('does not emit an event when called with the same proposal', async () => { - await registry - .connect(payee1) - .transferPayeeship( - await keeper1.getAddress(), - await payee2.getAddress(), - ) - - const tx = await registry - .connect(payee1) - .transferPayeeship( - await keeper1.getAddress(), - await payee2.getAddress(), - ) - const receipt = await tx.wait() - assert.equal(0, receipt.logs.length) - }) - }) - - describe('#acceptPayeeship', () => { - beforeEach(async () => { - await registry - .connect(payee1) - .transferPayeeship( - await keeper1.getAddress(), - await payee2.getAddress(), - ) - }) - - it('reverts when called by anyone but the proposed payee', async () => { - await evmRevertCustomError( - registry.connect(payee1).acceptPayeeship(await keeper1.getAddress()), - registry, - 'OnlyCallableByProposedPayee', - ) - }) - - it('emits an event announcing the new payee', async () => { - const tx = await registry - .connect(payee2) - .acceptPayeeship(await keeper1.getAddress()) - await expect(tx) - .to.emit(registry, 'PayeeshipTransferred') - .withArgs( - await keeper1.getAddress(), - await payee1.getAddress(), - await payee2.getAddress(), - ) - }) - - it('does change the payee', async () => { - await registry.connect(payee2).acceptPayeeship(await keeper1.getAddress()) - - const info = await registry.getTransmitterInfo(await keeper1.getAddress()) - assert.equal(await payee2.getAddress(), info.payee) - }) - }) - - describe('#pause', () => { - it('reverts if called by a non-owner', async () => { - await evmRevert( - registry.connect(keeper1).pause(), - 'Only callable by owner', - ) - }) - - it('marks the contract as paused', async () => { - assert.isFalse((await registry.getState()).state.paused) - - await registry.connect(owner).pause() - - assert.isTrue((await registry.getState()).state.paused) - }) - - it('Does not allow transmits when paused', async () => { - await registry.connect(owner).pause() - - await evmRevertCustomError( - getTransmitTx(registry, keeper1, [upkeepId]), - registry, - 'RegistryPaused', - ) - }) - - it('Does not allow creation of new upkeeps when paused', async () => { - await registry.connect(owner).pause() - - await evmRevertCustomError( - registry - .connect(owner) - [ - 'registerUpkeep(address,uint32,address,bytes,bytes)' - ](mock.address, performGas, await admin.getAddress(), emptyBytes, '0x'), - registry, - 'RegistryPaused', - ) - }) - }) - - describe('#unpause', () => { - beforeEach(async () => { - await registry.connect(owner).pause() - }) - - it('reverts if called by a non-owner', async () => { - await evmRevert( - registry.connect(keeper1).unpause(), - 'Only callable by owner', - ) - }) - - it('marks the contract as not paused', async () => { - assert.isTrue((await registry.getState()).state.paused) - - await registry.connect(owner).unpause() - - assert.isFalse((await registry.getState()).state.paused) - }) - }) - - describe('#migrateUpkeeps() / #receiveUpkeeps()', async () => { - context('when permissions are set', () => { - beforeEach(async () => { - await linkToken.connect(owner).approve(registry.address, toWei('100')) - await registry.connect(owner).addFunds(upkeepId, toWei('100')) - await registry.setPeerRegistryMigrationPermission(mgRegistry.address, 1) - await mgRegistry.setPeerRegistryMigrationPermission(registry.address, 2) - }) - - it('migrates an upkeep', async () => { - const offchainBytes = '0x987654abcd' - await registry - .connect(admin) - .setUpkeepOffchainConfig(upkeepId, offchainBytes) - const reg1Upkeep = await registry.getUpkeep(upkeepId) - const forwarderAddress = await registry.getForwarder(upkeepId) - expect(reg1Upkeep.balance).to.equal(toWei('100')) - expect(reg1Upkeep.checkData).to.equal(randomBytes) - expect(forwarderAddress).to.not.equal(ethers.constants.AddressZero) - expect(reg1Upkeep.offchainConfig).to.equal(offchainBytes) - expect((await registry.getState()).state.numUpkeeps).to.equal( - numUpkeeps, - ) - const forwarder = IAutomationForwarderFactory.connect( - forwarderAddress, - owner, - ) - expect(await forwarder.getRegistry()).to.equal(registry.address) - // Set an upkeep admin transfer in progress too - await registry - .connect(admin) - .transferUpkeepAdmin(upkeepId, await payee1.getAddress()) - - // migrate - await registry - .connect(admin) - .migrateUpkeeps([upkeepId], mgRegistry.address) - expect((await registry.getState()).state.numUpkeeps).to.equal( - numUpkeeps - 1, - ) - expect((await mgRegistry.getState()).state.numUpkeeps).to.equal(1) - expect((await registry.getUpkeep(upkeepId)).balance).to.equal(0) - expect((await registry.getUpkeep(upkeepId)).checkData).to.equal('0x') - expect((await mgRegistry.getUpkeep(upkeepId)).balance).to.equal( - toWei('100'), - ) - expect( - (await mgRegistry.getState()).state.expectedLinkBalance, - ).to.equal(toWei('100')) - expect((await mgRegistry.getUpkeep(upkeepId)).checkData).to.equal( - randomBytes, - ) - expect((await mgRegistry.getUpkeep(upkeepId)).offchainConfig).to.equal( - offchainBytes, - ) - expect(await mgRegistry.getForwarder(upkeepId)).to.equal( - forwarderAddress, - ) - // test that registry is updated on forwarder - expect(await forwarder.getRegistry()).to.equal(mgRegistry.address) - // migration will delete the upkeep and nullify admin transfer - await expect( - registry.connect(payee1).acceptUpkeepAdmin(upkeepId), - ).to.be.revertedWithCustomError(registry, 'UpkeepCancelled') - await expect( - mgRegistry.connect(payee1).acceptUpkeepAdmin(upkeepId), - ).to.be.revertedWithCustomError( - mgRegistry, - 'OnlyCallableByProposedAdmin', - ) - }) - - it('migrates a paused upkeep', async () => { - expect((await registry.getUpkeep(upkeepId)).balance).to.equal( - toWei('100'), - ) - expect((await registry.getUpkeep(upkeepId)).checkData).to.equal( - randomBytes, - ) - expect((await registry.getState()).state.numUpkeeps).to.equal( - numUpkeeps, - ) - await registry.connect(admin).pauseUpkeep(upkeepId) - // verify the upkeep is paused - expect((await registry.getUpkeep(upkeepId)).paused).to.equal(true) - // migrate - await registry - .connect(admin) - .migrateUpkeeps([upkeepId], mgRegistry.address) - expect((await registry.getState()).state.numUpkeeps).to.equal( - numUpkeeps - 1, - ) - expect((await mgRegistry.getState()).state.numUpkeeps).to.equal(1) - expect((await registry.getUpkeep(upkeepId)).balance).to.equal(0) - expect((await mgRegistry.getUpkeep(upkeepId)).balance).to.equal( - toWei('100'), - ) - expect((await registry.getUpkeep(upkeepId)).checkData).to.equal('0x') - expect((await mgRegistry.getUpkeep(upkeepId)).checkData).to.equal( - randomBytes, - ) - expect( - (await mgRegistry.getState()).state.expectedLinkBalance, - ).to.equal(toWei('100')) - // verify the upkeep is still paused after migration - expect((await mgRegistry.getUpkeep(upkeepId)).paused).to.equal(true) - }) - - it('emits an event on both contracts', async () => { - expect((await registry.getUpkeep(upkeepId)).balance).to.equal( - toWei('100'), - ) - expect((await registry.getUpkeep(upkeepId)).checkData).to.equal( - randomBytes, - ) - expect((await registry.getState()).state.numUpkeeps).to.equal( - numUpkeeps, - ) - const tx = registry - .connect(admin) - .migrateUpkeeps([upkeepId], mgRegistry.address) - await expect(tx) - .to.emit(registry, 'UpkeepMigrated') - .withArgs(upkeepId, toWei('100'), mgRegistry.address) - await expect(tx) - .to.emit(mgRegistry, 'UpkeepReceived') - .withArgs(upkeepId, toWei('100'), registry.address) - }) - - it('is only migratable by the admin', async () => { - await expect( - registry - .connect(owner) - .migrateUpkeeps([upkeepId], mgRegistry.address), - ).to.be.revertedWithCustomError(registry, 'OnlyCallableByAdmin') - await registry - .connect(admin) - .migrateUpkeeps([upkeepId], mgRegistry.address) - }) - }) - - context('when permissions are not set', () => { - it('reverts', async () => { - // no permissions - await registry.setPeerRegistryMigrationPermission(mgRegistry.address, 0) - await mgRegistry.setPeerRegistryMigrationPermission(registry.address, 0) - await expect(registry.migrateUpkeeps([upkeepId], mgRegistry.address)).to - .be.reverted - // only outgoing permissions - await registry.setPeerRegistryMigrationPermission(mgRegistry.address, 1) - await mgRegistry.setPeerRegistryMigrationPermission(registry.address, 0) - await expect(registry.migrateUpkeeps([upkeepId], mgRegistry.address)).to - .be.reverted - // only incoming permissions - await registry.setPeerRegistryMigrationPermission(mgRegistry.address, 0) - await mgRegistry.setPeerRegistryMigrationPermission(registry.address, 2) - await expect(registry.migrateUpkeeps([upkeepId], mgRegistry.address)).to - .be.reverted - // permissions opposite direction - await registry.setPeerRegistryMigrationPermission(mgRegistry.address, 2) - await mgRegistry.setPeerRegistryMigrationPermission(registry.address, 1) - await expect(registry.migrateUpkeeps([upkeepId], mgRegistry.address)).to - .be.reverted - }) - }) - }) - - describe('#setPayees', () => { - const IGNORE_ADDRESS = '0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF' - - it('reverts when not called by the owner', async () => { - await evmRevert( - registry.connect(keeper1).setPayees(payees), - 'Only callable by owner', - ) - }) - - it('reverts with different numbers of payees than transmitters', async () => { - await evmRevertCustomError( - registry.connect(owner).setPayees([...payees, randomAddress()]), - registry, - 'ParameterLengthError', - ) - }) - - it('reverts if the payee is the zero address', async () => { - await blankRegistry.connect(owner).setConfigTypeSafe(...baseConfig) // used to test initial config - - await evmRevertCustomError( - blankRegistry // used to test initial config - .connect(owner) - .setPayees([ethers.constants.AddressZero, ...payees.slice(1)]), - registry, - 'InvalidPayee', - ) - }) - - itMaybe( - 'sets the payees when exisitng payees are zero address', - async () => { - //Initial payees should be zero address - await blankRegistry.connect(owner).setConfigTypeSafe(...baseConfig) // used to test initial config - - for (let i = 0; i < keeperAddresses.length; i++) { - const payee = ( - await blankRegistry.getTransmitterInfo(keeperAddresses[i]) - ).payee // used to test initial config - assert.equal(payee, zeroAddress) - } - - await blankRegistry.connect(owner).setPayees(payees) // used to test initial config - - for (let i = 0; i < keeperAddresses.length; i++) { - const payee = ( - await blankRegistry.getTransmitterInfo(keeperAddresses[i]) - ).payee - assert.equal(payee, payees[i]) - } - }, - ) - - it('does not change the payee if IGNORE_ADDRESS is used as payee', async () => { - const signers = Array.from({ length: 5 }, randomAddress) - const keepers = Array.from({ length: 5 }, randomAddress) - const payees = Array.from({ length: 5 }, randomAddress) - const newTransmitter = randomAddress() - const newPayee = randomAddress() - const ignoreAddresses = new Array(payees.length).fill(IGNORE_ADDRESS) - const newPayees = [...ignoreAddresses, newPayee] - // arbitrum registry - // configure registry with 5 keepers // optimism registry - await blankRegistry // used to test initial configurations - .connect(owner) - .setConfigTypeSafe( - signers, - keepers, - f, - config, - offchainVersion, - offchainBytes, - ) - // arbitrum registry - // set initial payees // optimism registry - await blankRegistry.connect(owner).setPayees(payees) // used to test initial configurations - // arbitrum registry - // add another keeper // optimism registry - await blankRegistry // used to test initial configurations - .connect(owner) - .setConfigTypeSafe( - [...signers, randomAddress()], - [...keepers, newTransmitter], - f, - config, - offchainVersion, - offchainBytes, - ) - // arbitrum registry - // update payee list // optimism registry // arbitrum registry - await blankRegistry.connect(owner).setPayees(newPayees) // used to test initial configurations // optimism registry - const ignored = await blankRegistry.getTransmitterInfo(newTransmitter) // used to test initial configurations - assert.equal(newPayee, ignored.payee) - assert.equal(true, ignored.active) - }) - - it('reverts if payee is non zero and owner tries to change payee', async () => { - const newPayees = [randomAddress(), ...payees.slice(1)] - - await evmRevertCustomError( - registry.connect(owner).setPayees(newPayees), - registry, - 'InvalidPayee', - ) - }) - - it('emits events for every payee added and removed', async () => { - const tx = await registry.connect(owner).setPayees(payees) - await expect(tx) - .to.emit(registry, 'PayeesUpdated') - .withArgs(keeperAddresses, payees) - }) - }) - - describe('#cancelUpkeep', () => { - it('reverts if the ID is not valid', async () => { - await evmRevertCustomError( - registry.connect(owner).cancelUpkeep(upkeepId.add(1)), - registry, - 'CannotCancel', - ) - }) - - it('reverts if called by a non-owner/non-admin', async () => { - await evmRevertCustomError( - registry.connect(keeper1).cancelUpkeep(upkeepId), - registry, - 'OnlyCallableByOwnerOrAdmin', - ) - }) - - describe('when called by the owner', async () => { - it('sets the registration to invalid immediately', async () => { - const tx = await registry.connect(owner).cancelUpkeep(upkeepId) - const receipt = await tx.wait() - const registration = await registry.getUpkeep(upkeepId) - assert.equal( - registration.maxValidBlocknumber.toNumber(), - receipt.blockNumber, - ) - }) - - it('emits an event', async () => { - const tx = await registry.connect(owner).cancelUpkeep(upkeepId) - const receipt = await tx.wait() - await expect(tx) - .to.emit(registry, 'UpkeepCanceled') - .withArgs(upkeepId, BigNumber.from(receipt.blockNumber)) - }) - - it('immediately prevents upkeep', async () => { - await registry.connect(owner).cancelUpkeep(upkeepId) - - const tx = await getTransmitTx(registry, keeper1, [upkeepId]) - const receipt = await tx.wait() - const cancelledUpkeepReportLogs = - parseCancelledUpkeepReportLogs(receipt) - // exactly 1 CancelledUpkeepReport log should be emitted - assert.equal(cancelledUpkeepReportLogs.length, 1) - }) - - it('does not revert if reverts if called multiple times', async () => { - await registry.connect(owner).cancelUpkeep(upkeepId) - await evmRevertCustomError( - registry.connect(owner).cancelUpkeep(upkeepId), - registry, - 'UpkeepCancelled', - ) - }) - - describe('when called by the owner when the admin has just canceled', () => { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - let oldExpiration: BigNumber - - beforeEach(async () => { - await registry.connect(admin).cancelUpkeep(upkeepId) - const registration = await registry.getUpkeep(upkeepId) - oldExpiration = registration.maxValidBlocknumber - }) - - it('reverts with proper error', async () => { - await evmRevertCustomError( - registry.connect(owner).cancelUpkeep(upkeepId), - registry, - 'UpkeepCancelled', - ) - }) - }) - }) - - describe('when called by the admin', async () => { - it('reverts if called again by the admin', async () => { - await registry.connect(admin).cancelUpkeep(upkeepId) - - await evmRevertCustomError( - registry.connect(admin).cancelUpkeep(upkeepId), - registry, - 'UpkeepCancelled', - ) - }) - - it('reverts if called by the owner after the timeout', async () => { - await registry.connect(admin).cancelUpkeep(upkeepId) - - for (let i = 0; i < cancellationDelay; i++) { - await ethers.provider.send('evm_mine', []) - } - - await evmRevertCustomError( - registry.connect(owner).cancelUpkeep(upkeepId), - registry, - 'UpkeepCancelled', - ) - }) - - it('sets the registration to invalid in 50 blocks', async () => { - const tx = await registry.connect(admin).cancelUpkeep(upkeepId) - const receipt = await tx.wait() - const registration = await registry.getUpkeep(upkeepId) - assert.equal( - registration.maxValidBlocknumber.toNumber(), - receipt.blockNumber + 50, - ) - }) - - it('emits an event', async () => { - const tx = await registry.connect(admin).cancelUpkeep(upkeepId) - const receipt = await tx.wait() - await expect(tx) - .to.emit(registry, 'UpkeepCanceled') - .withArgs( - upkeepId, - BigNumber.from(receipt.blockNumber + cancellationDelay), - ) - }) - - it('immediately prevents upkeep', async () => { - await linkToken.connect(owner).approve(registry.address, toWei('100')) - await registry.connect(owner).addFunds(upkeepId, toWei('100')) - await registry.connect(admin).cancelUpkeep(upkeepId) - - await getTransmitTx(registry, keeper1, [upkeepId]) - - for (let i = 0; i < cancellationDelay; i++) { - await ethers.provider.send('evm_mine', []) - } - - const tx = await getTransmitTx(registry, keeper1, [upkeepId]) - - const receipt = await tx.wait() - const cancelledUpkeepReportLogs = - parseCancelledUpkeepReportLogs(receipt) - // exactly 1 CancelledUpkeepReport log should be emitted - assert.equal(cancelledUpkeepReportLogs.length, 1) - }) - - describeMaybe('when an upkeep has been performed', async () => { - beforeEach(async () => { - await linkToken.connect(owner).approve(registry.address, toWei('100')) - await registry.connect(owner).addFunds(upkeepId, toWei('100')) - await getTransmitTx(registry, keeper1, [upkeepId]) - }) - - it('deducts a cancellation fee from the upkeep and gives to owner', async () => { - const minUpkeepSpend = toWei('10') - - await registry.connect(owner).setConfigTypeSafe( - signerAddresses, - keeperAddresses, - f, - { - paymentPremiumPPB, - flatFeeMicroLink, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxCheckDataSize, - maxPerformDataSize, - maxRevertDataSize, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrars: [], - upkeepPrivilegeManager: upkeepManager, - chainModule: chainModuleBase.address, - reorgProtectionEnabled: true, - }, - offchainVersion, - offchainBytes, - ) - - const payee1Before = await linkToken.balanceOf( - await payee1.getAddress(), - ) - const upkeepBefore = (await registry.getUpkeep(upkeepId)).balance - const ownerBefore = (await registry.getState()).state.ownerLinkBalance - - const amountSpent = toWei('100').sub(upkeepBefore) - const cancellationFee = minUpkeepSpend.sub(amountSpent) - - await registry.connect(admin).cancelUpkeep(upkeepId) - - const payee1After = await linkToken.balanceOf( - await payee1.getAddress(), - ) - const upkeepAfter = (await registry.getUpkeep(upkeepId)).balance - const ownerAfter = (await registry.getState()).state.ownerLinkBalance - - // post upkeep balance should be previous balance minus cancellation fee - assert.isTrue(upkeepBefore.sub(cancellationFee).eq(upkeepAfter)) - // payee balance should not change - assert.isTrue(payee1Before.eq(payee1After)) - // owner should receive the cancellation fee - assert.isTrue(ownerAfter.sub(ownerBefore).eq(cancellationFee)) - }) - - it('deducts up to balance as cancellation fee', async () => { - // Very high min spend, should deduct whole balance as cancellation fees - const minUpkeepSpend = toWei('1000') - await registry.connect(owner).setConfigTypeSafe( - signerAddresses, - keeperAddresses, - f, - { - paymentPremiumPPB, - flatFeeMicroLink, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxCheckDataSize, - maxPerformDataSize, - maxRevertDataSize, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrars: [], - upkeepPrivilegeManager: upkeepManager, - chainModule: chainModuleBase.address, - reorgProtectionEnabled: true, - }, - offchainVersion, - offchainBytes, - ) - const payee1Before = await linkToken.balanceOf( - await payee1.getAddress(), - ) - const upkeepBefore = (await registry.getUpkeep(upkeepId)).balance - const ownerBefore = (await registry.getState()).state.ownerLinkBalance - - await registry.connect(admin).cancelUpkeep(upkeepId) - const payee1After = await linkToken.balanceOf( - await payee1.getAddress(), - ) - const ownerAfter = (await registry.getState()).state.ownerLinkBalance - const upkeepAfter = (await registry.getUpkeep(upkeepId)).balance - - // all upkeep balance is deducted for cancellation fee - assert.equal(0, upkeepAfter.toNumber()) - // payee balance should not change - assert.isTrue(payee1After.eq(payee1Before)) - // all upkeep balance is transferred to the owner - assert.isTrue(ownerAfter.sub(ownerBefore).eq(upkeepBefore)) - }) - - it('does not deduct cancellation fee if more than minUpkeepSpend is spent', async () => { - // Very low min spend, already spent in one perform upkeep - const minUpkeepSpend = BigNumber.from(420) - await registry.connect(owner).setConfigTypeSafe( - signerAddresses, - keeperAddresses, - f, - { - paymentPremiumPPB, - flatFeeMicroLink, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxCheckDataSize, - maxPerformDataSize, - maxRevertDataSize, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrars: [], - upkeepPrivilegeManager: upkeepManager, - chainModule: chainModuleBase.address, - reorgProtectionEnabled: true, - }, - offchainVersion, - offchainBytes, - ) - const payee1Before = await linkToken.balanceOf( - await payee1.getAddress(), - ) - const upkeepBefore = (await registry.getUpkeep(upkeepId)).balance - const ownerBefore = (await registry.getState()).state.ownerLinkBalance - - await registry.connect(admin).cancelUpkeep(upkeepId) - const payee1After = await linkToken.balanceOf( - await payee1.getAddress(), - ) - const ownerAfter = (await registry.getState()).state.ownerLinkBalance - const upkeepAfter = (await registry.getUpkeep(upkeepId)).balance - - // upkeep does not pay cancellation fee after cancellation because minimum upkeep spent is met - assert.isTrue(upkeepBefore.eq(upkeepAfter)) - // owner balance does not change - assert.isTrue(ownerAfter.eq(ownerBefore)) - // payee balance does not change - assert.isTrue(payee1Before.eq(payee1After)) - }) - }) - }) - }) - - describe('#withdrawPayment', () => { - beforeEach(async () => { - await linkToken.connect(owner).approve(registry.address, toWei('100')) - await registry.connect(owner).addFunds(upkeepId, toWei('100')) - await getTransmitTx(registry, keeper1, [upkeepId]) - }) - - it('reverts if called by anyone but the payee', async () => { - await evmRevertCustomError( - registry - .connect(payee2) - .withdrawPayment( - await keeper1.getAddress(), - await nonkeeper.getAddress(), - ), - registry, - 'OnlyCallableByPayee', - ) - }) - - it('reverts if called with the 0 address', async () => { - await evmRevertCustomError( - registry - .connect(payee2) - .withdrawPayment(await keeper1.getAddress(), zeroAddress), - registry, - 'InvalidRecipient', - ) - }) - - it('updates the balances', async () => { - const to = await nonkeeper.getAddress() - const keeperBefore = await registry.getTransmitterInfo( - await keeper1.getAddress(), - ) - const registrationBefore = (await registry.getUpkeep(upkeepId)).balance - const toLinkBefore = await linkToken.balanceOf(to) - const registryLinkBefore = await linkToken.balanceOf(registry.address) - const registryPremiumBefore = (await registry.getState()).state - .totalPremium - const ownerBefore = (await registry.getState()).state.ownerLinkBalance - - // Withdrawing for first time, last collected = 0 - assert.equal(keeperBefore.lastCollected.toString(), '0') - - //// Do the thing - await registry - .connect(payee1) - .withdrawPayment(await keeper1.getAddress(), to) - - const keeperAfter = await registry.getTransmitterInfo( - await keeper1.getAddress(), - ) - const registrationAfter = (await registry.getUpkeep(upkeepId)).balance - const toLinkAfter = await linkToken.balanceOf(to) - const registryLinkAfter = await linkToken.balanceOf(registry.address) - const registryPremiumAfter = (await registry.getState()).state - .totalPremium - const ownerAfter = (await registry.getState()).state.ownerLinkBalance - - // registry total premium should not change - assert.isTrue(registryPremiumBefore.eq(registryPremiumAfter)) - - // Last collected should be updated to premium-change - assert.isTrue( - keeperAfter.lastCollected.eq( - registryPremiumBefore.sub( - registryPremiumBefore.mod(keeperAddresses.length), - ), - ), - ) - - // owner balance should remain unchanged - assert.isTrue(ownerAfter.eq(ownerBefore)) - - assert.isTrue(keeperAfter.balance.eq(BigNumber.from(0))) - assert.isTrue(registrationBefore.eq(registrationAfter)) - assert.isTrue(toLinkBefore.add(keeperBefore.balance).eq(toLinkAfter)) - assert.isTrue( - registryLinkBefore.sub(keeperBefore.balance).eq(registryLinkAfter), - ) - }) - - it('emits a log announcing the withdrawal', async () => { - const balance = ( - await registry.getTransmitterInfo(await keeper1.getAddress()) - ).balance - const tx = await registry - .connect(payee1) - .withdrawPayment( - await keeper1.getAddress(), - await nonkeeper.getAddress(), - ) - await expect(tx) - .to.emit(registry, 'PaymentWithdrawn') - .withArgs( - await keeper1.getAddress(), - balance, - await nonkeeper.getAddress(), - await payee1.getAddress(), - ) - }) - }) - - describe('#checkCallback', () => { - it('returns false with appropriate failure reason when target callback reverts', async () => { - await streamsLookupUpkeep.setShouldRevertCallback(true) - - const values: any[] = ['0x1234', '0xabcd'] - const res = await registry - .connect(zeroAddress) - .callStatic.checkCallback(streamsLookupUpkeepId, values, '0x') - - assert.isFalse(res.upkeepNeeded) - assert.equal(res.performData, '0x') - assert.equal( - res.upkeepFailureReason, - UpkeepFailureReason.CHECK_CALLBACK_REVERTED, - ) - assert.isTrue(res.gasUsed.gt(BigNumber.from('0'))) // Some gas should be used - }) - - it('returns false with appropriate failure reason when target callback returns big performData', async () => { - let longBytes = '0x' - for (let i = 0; i <= maxPerformDataSize.toNumber(); i++) { - longBytes += '11' - } - const values: any[] = [longBytes, longBytes] - const res = await registry - .connect(zeroAddress) - .callStatic.checkCallback(streamsLookupUpkeepId, values, '0x') - - assert.isFalse(res.upkeepNeeded) - assert.equal(res.performData, '0x') - assert.equal( - res.upkeepFailureReason, - UpkeepFailureReason.PERFORM_DATA_EXCEEDS_LIMIT, - ) - assert.isTrue(res.gasUsed.gt(BigNumber.from('0'))) // Some gas should be used - }) - - it('returns false with appropriate failure reason when target callback returns false', async () => { - await streamsLookupUpkeep.setCallbackReturnBool(false) - const values: any[] = ['0x1234', '0xabcd'] - const res = await registry - .connect(zeroAddress) - .callStatic.checkCallback(streamsLookupUpkeepId, values, '0x') - - assert.isFalse(res.upkeepNeeded) - assert.equal(res.performData, '0x') - assert.equal( - res.upkeepFailureReason, - UpkeepFailureReason.UPKEEP_NOT_NEEDED, - ) - assert.isTrue(res.gasUsed.gt(BigNumber.from('0'))) // Some gas should be used - }) - - it('succeeds with upkeep needed', async () => { - const values: any[] = ['0x1234', '0xabcd'] - - const res = await registry - .connect(zeroAddress) - .callStatic.checkCallback(streamsLookupUpkeepId, values, '0x') - const expectedPerformData = ethers.utils.defaultAbiCoder.encode( - ['bytes[]', 'bytes'], - [values, '0x'], - ) - - assert.isTrue(res.upkeepNeeded) - assert.equal(res.performData, expectedPerformData) - assert.equal(res.upkeepFailureReason, UpkeepFailureReason.NONE) - assert.isTrue(res.gasUsed.gt(BigNumber.from('0'))) // Some gas should be used - }) - }) - - describe('#setUpkeepPrivilegeConfig() / #getUpkeepPrivilegeConfig()', () => { - it('reverts when non manager tries to set privilege config', async () => { - await evmRevertCustomError( - registry.connect(payee3).setUpkeepPrivilegeConfig(upkeepId, '0x1234'), - registry, - 'OnlyCallableByUpkeepPrivilegeManager', - ) - }) - - it('returns empty bytes for upkeep privilege config before setting', async () => { - const cfg = await registry.getUpkeepPrivilegeConfig(upkeepId) - assert.equal(cfg, '0x') - }) - - it('allows upkeep manager to set privilege config', async () => { - const tx = await registry - .connect(personas.Norbert) - .setUpkeepPrivilegeConfig(upkeepId, '0x1234') - await expect(tx) - .to.emit(registry, 'UpkeepPrivilegeConfigSet') - .withArgs(upkeepId, '0x1234') - - const cfg = await registry.getUpkeepPrivilegeConfig(upkeepId) - assert.equal(cfg, '0x1234') - }) - }) - - describe('#setAdminPrivilegeConfig() / #getAdminPrivilegeConfig()', () => { - const admin = randomAddress() - - it('reverts when non manager tries to set privilege config', async () => { - await evmRevertCustomError( - registry.connect(payee3).setAdminPrivilegeConfig(admin, '0x1234'), - registry, - 'OnlyCallableByUpkeepPrivilegeManager', - ) - }) - - it('returns empty bytes for upkeep privilege config before setting', async () => { - const cfg = await registry.getAdminPrivilegeConfig(admin) - assert.equal(cfg, '0x') - }) - - it('allows upkeep manager to set privilege config', async () => { - const tx = await registry - .connect(personas.Norbert) - .setAdminPrivilegeConfig(admin, '0x1234') - await expect(tx) - .to.emit(registry, 'AdminPrivilegeConfigSet') - .withArgs(admin, '0x1234') - - const cfg = await registry.getAdminPrivilegeConfig(admin) - assert.equal(cfg, '0x1234') - }) - }) - - describe('transmitterPremiumSplit [ @skip-coverage ]', () => { - beforeEach(async () => { - await linkToken.connect(owner).approve(registry.address, toWei('100')) - await registry.connect(owner).addFunds(upkeepId, toWei('100')) - }) - - it('splits premium evenly across transmitters', async () => { - // Do a transmit from keeper1 - await getTransmitTx(registry, keeper1, [upkeepId]) - - const registryPremium = (await registry.getState()).state.totalPremium - assert.isTrue(registryPremium.gt(BigNumber.from(0))) - - const premiumPerTransmitter = registryPremium.div( - BigNumber.from(keeperAddresses.length), - ) - const k1Balance = ( - await registry.getTransmitterInfo(await keeper1.getAddress()) - ).balance - // transmitter should be reimbursed for gas and get the premium - assert.isTrue(k1Balance.gt(premiumPerTransmitter)) - const k1GasReimbursement = k1Balance.sub(premiumPerTransmitter) - - const k2Balance = ( - await registry.getTransmitterInfo(await keeper2.getAddress()) - ).balance - // non transmitter should get its share of premium - assert.isTrue(k2Balance.eq(premiumPerTransmitter)) - - // Now do a transmit from keeper 2 - await getTransmitTx(registry, keeper2, [upkeepId]) - const registryPremiumNew = (await registry.getState()).state.totalPremium - assert.isTrue(registryPremiumNew.gt(registryPremium)) - const premiumPerTransmitterNew = registryPremiumNew.div( - BigNumber.from(keeperAddresses.length), - ) - const additionalPremium = premiumPerTransmitterNew.sub( - premiumPerTransmitter, - ) - - const k1BalanceNew = ( - await registry.getTransmitterInfo(await keeper1.getAddress()) - ).balance - // k1 should get the new premium - assert.isTrue( - k1BalanceNew.eq(k1GasReimbursement.add(premiumPerTransmitterNew)), - ) - - const k2BalanceNew = ( - await registry.getTransmitterInfo(await keeper2.getAddress()) - ).balance - // k2 should get gas reimbursement in addition to new premium - assert.isTrue(k2BalanceNew.gt(k2Balance.add(additionalPremium))) - }) - - it('updates last collected upon payment withdrawn', async () => { - // Do a transmit from keeper1 - await getTransmitTx(registry, keeper1, [upkeepId]) - - const registryPremium = (await registry.getState()).state.totalPremium - const k1 = await registry.getTransmitterInfo(await keeper1.getAddress()) - const k2 = await registry.getTransmitterInfo(await keeper2.getAddress()) - - // Withdrawing for first time, last collected = 0 - assert.isTrue(k1.lastCollected.eq(BigNumber.from(0))) - assert.isTrue(k2.lastCollected.eq(BigNumber.from(0))) - - //// Do the thing - await registry - .connect(payee1) - .withdrawPayment( - await keeper1.getAddress(), - await nonkeeper.getAddress(), - ) - - const k1New = await registry.getTransmitterInfo( - await keeper1.getAddress(), - ) - const k2New = await registry.getTransmitterInfo( - await keeper2.getAddress(), - ) - - // transmitter info lastCollected should be updated for k1, not for k2 - assert.isTrue( - k1New.lastCollected.eq( - registryPremium.sub(registryPremium.mod(keeperAddresses.length)), - ), - ) - assert.isTrue(k2New.lastCollected.eq(BigNumber.from(0))) - }) - - itMaybe( - 'maintains consistent balance information across all parties', - async () => { - // throughout transmits, withdrawals, setConfigs total claim on balances should remain less than expected balance - // some spare change can get lost but it should be less than maxAllowedSpareChange - - let maxAllowedSpareChange = BigNumber.from('0') - await verifyConsistentAccounting(maxAllowedSpareChange) - - await getTransmitTx(registry, keeper1, [upkeepId]) - maxAllowedSpareChange = maxAllowedSpareChange.add(BigNumber.from('31')) - await verifyConsistentAccounting(maxAllowedSpareChange) - - await registry - .connect(payee1) - .withdrawPayment( - await keeper1.getAddress(), - await nonkeeper.getAddress(), - ) - await verifyConsistentAccounting(maxAllowedSpareChange) - - await registry - .connect(payee2) - .withdrawPayment( - await keeper2.getAddress(), - await nonkeeper.getAddress(), - ) - await verifyConsistentAccounting(maxAllowedSpareChange) - - await getTransmitTx(registry, keeper1, [upkeepId]) - maxAllowedSpareChange = maxAllowedSpareChange.add(BigNumber.from('31')) - await verifyConsistentAccounting(maxAllowedSpareChange) - - await registry.connect(owner).setConfigTypeSafe( - signerAddresses.slice(2, 15), // only use 2-14th index keepers - keeperAddresses.slice(2, 15), - f, - config, - offchainVersion, - offchainBytes, - ) - await verifyConsistentAccounting(maxAllowedSpareChange) - - await getTransmitTx(registry, keeper3, [upkeepId], { - startingSignerIndex: 2, - }) - maxAllowedSpareChange = maxAllowedSpareChange.add(BigNumber.from('13')) - await verifyConsistentAccounting(maxAllowedSpareChange) - - await registry - .connect(payee1) - .withdrawPayment( - await keeper1.getAddress(), - await nonkeeper.getAddress(), - ) - await verifyConsistentAccounting(maxAllowedSpareChange) - - await registry - .connect(payee3) - .withdrawPayment( - await keeper3.getAddress(), - await nonkeeper.getAddress(), - ) - await verifyConsistentAccounting(maxAllowedSpareChange) - - await registry.connect(owner).setConfigTypeSafe( - signerAddresses.slice(0, 4), // only use 0-3rd index keepers - keeperAddresses.slice(0, 4), - f, - config, - offchainVersion, - offchainBytes, - ) - await verifyConsistentAccounting(maxAllowedSpareChange) - await getTransmitTx(registry, keeper1, [upkeepId]) - maxAllowedSpareChange = maxAllowedSpareChange.add(BigNumber.from('4')) - await getTransmitTx(registry, keeper3, [upkeepId]) - maxAllowedSpareChange = maxAllowedSpareChange.add(BigNumber.from('4')) - - await verifyConsistentAccounting(maxAllowedSpareChange) - await registry - .connect(payee5) - .withdrawPayment( - await keeper5.getAddress(), - await nonkeeper.getAddress(), - ) - await verifyConsistentAccounting(maxAllowedSpareChange) - - await registry - .connect(payee1) - .withdrawPayment( - await keeper1.getAddress(), - await nonkeeper.getAddress(), - ) - await verifyConsistentAccounting(maxAllowedSpareChange) - }, - ) - }) -}) diff --git a/contracts/test/v0.8/automation/AutomationRegistry2_3.test.ts b/contracts/test/v0.8/automation/AutomationRegistry2_3.test.ts index f3c2d9bb984..11282bdff94 100644 --- a/contracts/test/v0.8/automation/AutomationRegistry2_3.test.ts +++ b/contracts/test/v0.8/automation/AutomationRegistry2_3.test.ts @@ -117,7 +117,7 @@ const emptyBytes = '0x' const emptyBytes32 = '0x0000000000000000000000000000000000000000000000000000000000000000' -const transmitGasOverhead = 1_040_000 +const transmitGasOverhead = 1_080_000 const checkGasOverhead = 600_000 const stalenessSeconds = BigNumber.from(43820) @@ -165,7 +165,6 @@ let registry: IAutomationRegistry // default registry, used for most tests let arbRegistry: IAutomationRegistry // arbitrum registry let opRegistry: IAutomationRegistry // optimism registry let mgRegistry: IAutomationRegistry // "migrate registry" used in migration tests -let blankRegistry: IAutomationRegistry // used to test initial configurations let mockArbGasInfo: MockArbGasInfo let mockOVMGasPriceOracle: MockOVMGasPriceOracle let mock: UpkeepMock @@ -402,7 +401,6 @@ describe('AutomationRegistry2_3', () => { let afUpkeepId: BigNumber // auto funding upkeep let logUpkeepId: BigNumber // log trigger upkeepID let streamsLookupUpkeepId: BigNumber // streams lookup upkeep - const numUpkeeps = 4 // see above let keeperAddresses: string[] let payees: string[] let signers: Wallet[] @@ -431,7 +429,7 @@ describe('AutomationRegistry2_3', () => { ) // need full path because there are two contracts with name MockV3Aggregator mockV3AggregatorFactory = (await ethers.getContractFactory( - 'src/v0.8/tests/MockV3Aggregator.sol:MockV3Aggregator', + 'src/v0.8/shared/mocks/MockV3Aggregator.sol:MockV3Aggregator', )) as unknown as MockV3AggregatorFactory mockArbGasInfoFactory = await ethers.getContractFactory('MockArbGasInfo') mockOVMGasPriceOracleFactory = await ethers.getContractFactory( @@ -1017,7 +1015,6 @@ describe('AutomationRegistry2_3', () => { arbRegistry = await deployRegistry23(...registryParams) opRegistry = await deployRegistry23(...registryParams) mgRegistry = await deployRegistry23(...registryParams) - blankRegistry = await deployRegistry23(...registryParams) registryConditionalOverhead = await registry.getConditionalGasOverhead() registryLogOverhead = await registry.getLogGasOverhead() diff --git a/contracts/test/v0.8/automation/CronUpkeep.test.ts b/contracts/test/v0.8/automation/CronUpkeep.test.ts deleted file mode 100644 index 7b769797f12..00000000000 --- a/contracts/test/v0.8/automation/CronUpkeep.test.ts +++ /dev/null @@ -1,576 +0,0 @@ -import moment from 'moment' -import { ethers } from 'hardhat' -import { Contract } from 'ethers' -import { assert, expect } from 'chai' -import { CronUpkeepTestHelper } from '../../../typechain/CronUpkeepTestHelper' -import { CronUpkeepDelegate } from '../../../typechain/CronUpkeepDelegate' -import { CronUpkeepFactory } from '../../../typechain/CronUpkeepFactory' -import { CronUpkeepTestHelper__factory as CronUpkeepTestHelperFactory } from '../../../typechain/factories/CronUpkeepTestHelper__factory' -import { CronInternalTestHelper } from '../../../typechain/CronInternalTestHelper' -import { CronReceiver } from '../../../typechain/CronReceiver' -import { BigNumber, BigNumberish } from '@ethersproject/bignumber' -import type { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -import { validCrons } from '../../test-helpers/fixtures' -import * as h from '../../test-helpers/helpers' - -const { utils } = ethers -const { AddressZero } = ethers.constants - -const OWNABLE_ERR = 'Only callable by owner' -const CRON_NOT_FOUND_ERR = 'CronJobIDNotFound' - -let cron: CronUpkeepTestHelper -let cronFactory: CronUpkeepTestHelperFactory // the typechain factory that deploys cron upkeep contracts -let cronFactoryContract: CronUpkeepFactory // the cron factory contract -let cronDelegate: CronUpkeepDelegate -let cronTestHelper: CronInternalTestHelper -let cronReceiver1: CronReceiver -let cronReceiver2: CronReceiver - -let admin: SignerWithAddress -let owner: SignerWithAddress -let stranger: SignerWithAddress - -const timeStamp = 32503680000 // Jan 1, 3000 12:00AM -const basicCronString = '0 * * * *' - -let handler1Sig: string -let handler2Sig: string -let revertHandlerSig: string -let basicSpec: string - -async function assertJobIDsEqual(expected: number[]) { - const ids = (await cron.getActiveCronJobIDs()).map((n) => n.toNumber()) - assert.deepEqual(ids.sort(), expected.sort()) -} - -function decodePayload(payload: string) { - return utils.defaultAbiCoder.decode( - ['uint256', 'uint256', 'address', 'bytes'], - payload, - ) as [BigNumber, BigNumber, string, string] -} - -function encodePayload(payload: [BigNumberish, BigNumberish, string, string]) { - return utils.defaultAbiCoder.encode( - ['uint256', 'uint256', 'address', 'bytes'], - payload, - ) -} - -async function createBasicCron() { - return await cron.createCronJobFromEncodedSpec( - cronReceiver1.address, - handler1Sig, - basicSpec, - ) -} - -describe('CronUpkeep', () => { - beforeEach(async () => { - const accounts = await ethers.getSigners() - admin = accounts[0] - owner = accounts[1] - stranger = accounts[2] - const crFactory = await ethers.getContractFactory('CronReceiver', owner) - cronReceiver1 = await crFactory.deploy() - cronReceiver2 = await crFactory.deploy() - const cronDelegateFactory = await ethers.getContractFactory( - 'CronUpkeepDelegate', - admin, - ) - cronDelegate = await cronDelegateFactory.deploy() - const cronExternalFactory = await ethers.getContractFactory( - 'src/v0.8/automation/libraries/external/Cron.sol:Cron', - admin, - ) - const cronExternalLib = await cronExternalFactory.deploy() - cronFactory = await ethers.getContractFactory('CronUpkeepTestHelper', { - signer: admin, - libraries: { Cron: cronExternalLib.address }, - }) - cron = ( - await cronFactory.deploy(owner.address, cronDelegate.address, 5, []) - ).connect(owner) - const cronFactoryContractFactory = await ethers.getContractFactory( - 'CronUpkeepFactory', - { signer: admin, libraries: { Cron: cronExternalLib.address } }, - ) // the typechain factory that creates the cron factory contract - cronFactoryContract = await cronFactoryContractFactory.deploy() - const fs = cronReceiver1.interface.functions - handler1Sig = utils.id(fs['handler1()'].format('sighash')).slice(0, 10) - handler2Sig = utils.id(fs['handler2()'].format('sighash')).slice(0, 10) - revertHandlerSig = utils - .id(fs['revertHandler()'].format('sighash')) - .slice(0, 10) - const cronTHFactory = await ethers.getContractFactory( - 'CronInternalTestHelper', - ) - cronTestHelper = await cronTHFactory.deploy() - basicSpec = await cronFactoryContract.encodeCronString(basicCronString) - }) - - afterEach(async () => { - await h.reset() - }) - - it('has a limited public ABI [ @skip-coverage ]', () => { - // Casting cron is necessary due to a tricky versioning mismatch issue, likely between ethers - // and typechain. Remove once the version issue is resolved. - // https://smartcontract-it.atlassian.net/browse/ARCHIVE-22094 - h.publicAbi(cron as unknown as Contract, [ - 's_maxJobs', - 'performUpkeep', - 'createCronJobFromEncodedSpec', - 'updateCronJob', - 'deleteCronJob', - 'checkUpkeep', - 'getActiveCronJobIDs', - 'getCronJob', - // Ownable methods: - 'acceptOwnership', - 'owner', - 'transferOwnership', - // Pausable methods - 'paused', - 'pause', - 'unpause', - // Cron helper methods - 'createCronJobFromString', - 'txCheckUpkeep', - ]) - }) - - describe('constructor()', () => { - it('sets the initial values', async () => { - expect(await cron.owner()).to.equal(owner.address) - expect(await cron.s_maxJobs()).to.equal(5) - }) - - it('optionally creates a first job', async () => { - const payload = await cronFactoryContract.encodeCronJob( - cronReceiver1.address, - handler1Sig, - basicCronString, - ) - cron = ( - await cronFactory.deploy( - owner.address, - cronDelegate.address, - 5, - payload, - ) - ).connect(owner) - const job = await cron.getCronJob(1) - assert.equal(job.target, cronReceiver1.address) - assert.equal(job.handler, handler1Sig) - assert.equal(job.cronString, basicCronString) - }) - }) - - describe('checkUpkeep() / performUpkeep()', () => { - beforeEach(async () => { - await h.setTimestamp(timeStamp) - // id 1 - await cron.createCronJobFromString( - cronReceiver1.address, - handler1Sig, - '0 0 31 * *', // 31st day of every month - ) - // id 2 - await cron.createCronJobFromString( - cronReceiver1.address, - handler2Sig, - '10 * * * *', // on the 10 min mark - ) - // id 3 - await cron.createCronJobFromString( - cronReceiver2.address, - handler1Sig, - '0 0 * 7 *', // every day in July - ) - // id 4 - await cron.createCronJobFromString( - cronReceiver2.address, - revertHandlerSig, - '20 * * * *', // on the 20 min mark - ) - }) - - describe('checkUpkeep()', () => { - it('returns false if no one is elligible', async () => { - const [needsUpkeep] = await cron - .connect(AddressZero) - .callStatic.checkUpkeep('0x') - assert.isFalse(needsUpkeep) - }) - - it('returns the id of eligible cron jobs', async () => { - await h.fastForward(moment.duration(11, 'minutes').asSeconds()) - const [needsUpkeep, payload] = await cron - .connect(AddressZero) - .callStatic.checkUpkeep('0x') - assert.isTrue(needsUpkeep) - const [id, ..._] = decodePayload(payload) - assert.equal(id.toNumber(), 2) - }) - - describe('when mutiple crons are elligible', () => { - it('cycles through the cron IDs based on block number', async () => { - await h.fastForward(moment.duration(1, 'year').asSeconds()) - let [_, payload] = await cron - .connect(AddressZero) - .callStatic.checkUpkeep('0x') - const [id1] = decodePayload(payload) - await h.mineBlock(ethers.provider) - ;[_, payload] = await cron - .connect(AddressZero) - .callStatic.checkUpkeep('0x') - const [id2] = decodePayload(payload) - await h.mineBlock(ethers.provider) - ;[_, payload] = await cron - .connect(AddressZero) - .callStatic.checkUpkeep('0x') - const [id3] = decodePayload(payload) - await h.mineBlock(ethers.provider) - ;[_, payload] = await cron - .connect(AddressZero) - .callStatic.checkUpkeep('0x') - const [id4] = decodePayload(payload) - assert.deepEqual( - [id1, id2, id3, id4].map((n) => n.toNumber()).sort(), - [1, 2, 3, 4], - ) - }) - }) - }) - - describe('performUpkeep()', () => { - it('forwards the call to the appropriate target/handler', async () => { - await h.fastForward(moment.duration(11, 'minutes').asSeconds()) - const [needsUpkeep, payload] = await cron - .connect(AddressZero) - .callStatic.checkUpkeep('0x') - assert.isTrue(needsUpkeep) - await expect(cron.performUpkeep(payload)).to.emit( - cronReceiver1, - 'Received2', - ) - }) - - it('emits an event', async () => { - await h.fastForward(moment.duration(11, 'minutes').asSeconds()) - const [needsUpkeep, payload] = await cron - .connect(AddressZero) - .callStatic.checkUpkeep('0x') - assert.isTrue(needsUpkeep) - await expect(cron.performUpkeep(payload)) - .to.emit(cron, 'CronJobExecuted') - .withArgs(2, true) - }) - - it('succeeds even if the call to the target fails', async () => { - await cron.deleteCronJob(2) - await h.fastForward(moment.duration(21, 'minutes').asSeconds()) - const payload = encodePayload([ - 4, - moment.unix(timeStamp).add(20, 'minutes').unix(), - cronReceiver2.address, - revertHandlerSig, - ]) - await expect(cron.performUpkeep(payload)) - .to.emit(cron, 'CronJobExecuted') - .withArgs(4, false) - }) - - it('is only callable by anyone', async () => { - await h.fastForward(moment.duration(11, 'minutes').asSeconds()) - const [needsUpkeep, payload] = await cron - .connect(AddressZero) - .callStatic.checkUpkeep('0x') - assert.isTrue(needsUpkeep) - await cron.connect(stranger).performUpkeep(payload) - }) - - it('is only callable once for a given tick', async () => { - await h.fastForward(moment.duration(10, 'minutes').asSeconds()) - const [needsUpkeep, payload] = await cron - .connect(AddressZero) - .callStatic.checkUpkeep('0x') - assert.isTrue(needsUpkeep) - const maliciousPayload = encodePayload([ - 2, - moment.unix(timeStamp).add(10, 'minutes').add(59, 'seconds').unix(), - cronReceiver1.address, - handler2Sig, - ]) - await cron.performUpkeep(payload) - await expect(cron.performUpkeep(payload)).to.be.reverted - await expect(cron.performUpkeep(maliciousPayload)).to.be.reverted - await h.fastForward(moment.duration(1, 'minute').asSeconds()) - await expect(cron.performUpkeep(payload)).to.be.reverted - await expect(cron.performUpkeep(maliciousPayload)).to.be.reverted - await h.fastForward(moment.duration(10, 'minute').asSeconds()) - await expect(cron.performUpkeep(payload)).to.be.reverted - await expect(cron.performUpkeep(maliciousPayload)).to.be.reverted - }) - }) - }) - - describe('createCronJobFromEncodedSpec()', () => { - it('creates jobs with sequential IDs', async () => { - const cronString1 = '0 * * * *' - const cronString2 = '0 1,2,3 */4 5-6 1-2' - const encodedSpec1 = - await cronFactoryContract.encodeCronString(cronString1) - const encodedSpec2 = - await cronFactoryContract.encodeCronString(cronString2) - const nextTick1 = ( - await cronTestHelper.calculateNextTick(cronString1) - ).toNumber() - const nextTick2 = ( - await cronTestHelper.calculateNextTick(cronString2) - ).toNumber() - await cron.createCronJobFromEncodedSpec( - cronReceiver1.address, - handler1Sig, - encodedSpec1, - ) - await assertJobIDsEqual([1]) - await cron.createCronJobFromEncodedSpec( - cronReceiver1.address, - handler2Sig, - encodedSpec1, - ) - await assertJobIDsEqual([1, 2]) - await cron.createCronJobFromEncodedSpec( - cronReceiver2.address, - handler1Sig, - encodedSpec2, - ) - await assertJobIDsEqual([1, 2, 3]) - await cron.createCronJobFromEncodedSpec( - cronReceiver2.address, - handler2Sig, - encodedSpec2, - ) - await assertJobIDsEqual([1, 2, 3, 4]) - const cron1 = await cron.getCronJob(1) - const cron2 = await cron.getCronJob(2) - const cron3 = await cron.getCronJob(3) - const cron4 = await cron.getCronJob(4) - assert.equal(cron1.target, cronReceiver1.address) - assert.equal(cron1.handler, handler1Sig) - assert.equal(cron1.cronString, cronString1) - assert.equal(cron1.nextTick.toNumber(), nextTick1) - assert.equal(cron2.target, cronReceiver1.address) - assert.equal(cron2.handler, handler2Sig) - assert.equal(cron2.cronString, cronString1) - assert.equal(cron2.nextTick.toNumber(), nextTick1) - assert.equal(cron3.target, cronReceiver2.address) - assert.equal(cron3.handler, handler1Sig) - assert.equal(cron3.cronString, cronString2) - assert.equal(cron3.nextTick.toNumber(), nextTick2) - assert.equal(cron4.target, cronReceiver2.address) - assert.equal(cron4.handler, handler2Sig) - assert.equal(cron4.cronString, cronString2) - assert.equal(cron4.nextTick.toNumber(), nextTick2) - }) - - it('emits an event', async () => { - await expect(createBasicCron()).to.emit(cron, 'CronJobCreated') - }) - - it('is only callable by the owner', async () => { - await expect( - cron - .connect(stranger) - .createCronJobFromEncodedSpec( - cronReceiver1.address, - handler1Sig, - basicSpec, - ), - ).to.be.revertedWith(OWNABLE_ERR) - }) - - it('errors if trying to create more jobs than allowed', async () => { - for (let idx = 0; idx < 5; idx++) { - await createBasicCron() - } - await expect(createBasicCron()).to.be.revertedWithCustomError( - cron, - 'ExceedsMaxJobs', - ) - }) - }) - - describe('updateCronJob()', () => { - const newCronString = '0 0 1 1 1' - let newEncodedSpec: string - beforeEach(async () => { - await createBasicCron() - newEncodedSpec = await cronFactoryContract.encodeCronString(newCronString) - }) - - it('updates a cron job', async () => { - let cron1 = await cron.getCronJob(1) - assert.equal(cron1.target, cronReceiver1.address) - assert.equal(cron1.handler, handler1Sig) - assert.equal(cron1.cronString, basicCronString) - await cron.updateCronJob( - 1, - cronReceiver2.address, - handler2Sig, - newEncodedSpec, - ) - cron1 = await cron.getCronJob(1) - assert.equal(cron1.target, cronReceiver2.address) - assert.equal(cron1.handler, handler2Sig) - assert.equal(cron1.cronString, newCronString) - }) - - it('emits an event', async () => { - await expect( - await cron.updateCronJob( - 1, - cronReceiver2.address, - handler2Sig, - newEncodedSpec, - ), - ).to.emit(cron, 'CronJobUpdated') - }) - - it('is only callable by the owner', async () => { - await expect( - cron - .connect(stranger) - .updateCronJob(1, cronReceiver2.address, handler2Sig, newEncodedSpec), - ).to.be.revertedWith(OWNABLE_ERR) - }) - - it('reverts if trying to update a non-existent ID', async () => { - await expect( - cron.updateCronJob( - 2, - cronReceiver2.address, - handler2Sig, - newEncodedSpec, - ), - ).to.be.revertedWithCustomError(cron, CRON_NOT_FOUND_ERR) - }) - }) - - describe('deleteCronJob()', () => { - it("deletes a jobs by it's ID", async () => { - await createBasicCron() - await createBasicCron() - await createBasicCron() - await createBasicCron() - await assertJobIDsEqual([1, 2, 3, 4]) - await cron.deleteCronJob(2) - await expect(cron.getCronJob(2)).to.be.revertedWithCustomError( - cron, - CRON_NOT_FOUND_ERR, - ) - await expect(cron.deleteCronJob(2)).to.be.revertedWithCustomError( - cron, - CRON_NOT_FOUND_ERR, - ) - await assertJobIDsEqual([1, 3, 4]) - await cron.deleteCronJob(1) - await assertJobIDsEqual([3, 4]) - await cron.deleteCronJob(4) - await assertJobIDsEqual([3]) - await cron.deleteCronJob(3) - await assertJobIDsEqual([]) - }) - - it('emits an event', async () => { - await createBasicCron() - await expect(cron.deleteCronJob(1)).to.emit(cron, 'CronJobDeleted') - }) - - it('reverts if trying to delete a non-existent ID', async () => { - await createBasicCron() - await createBasicCron() - await expect(cron.deleteCronJob(0)).to.be.revertedWithCustomError( - cron, - CRON_NOT_FOUND_ERR, - ) - await expect(cron.deleteCronJob(3)).to.be.revertedWithCustomError( - cron, - CRON_NOT_FOUND_ERR, - ) - }) - }) - - describe('pause() / unpause()', () => { - it('is only callable by the owner', async () => { - await expect(cron.connect(stranger).pause()).to.be.reverted - await expect(cron.connect(stranger).unpause()).to.be.reverted - }) - - it('pauses / unpauses the contract', async () => { - expect(await cron.paused()).to.be.false - await cron.pause() - expect(await cron.paused()).to.be.true - await cron.unpause() - expect(await cron.paused()).to.be.false - }) - }) -}) - -// only run during pnpm test:gas -describe.skip('Cron Gas Usage', () => { - before(async () => { - const accounts = await ethers.getSigners() - admin = accounts[0] - owner = accounts[1] - const crFactory = await ethers.getContractFactory('CronReceiver', owner) - cronReceiver1 = await crFactory.deploy() - const cronDelegateFactory = await ethers.getContractFactory( - 'CronUpkeepDelegate', - owner, - ) - const cronDelegate = await cronDelegateFactory.deploy() - const cronExternalFactory = await ethers.getContractFactory( - 'src/v0.8/automation/libraries/external/Cron.sol:Cron', - admin, - ) - const cronExternalLib = await cronExternalFactory.deploy() - const cronFactory = await ethers.getContractFactory( - 'CronUpkeepTestHelper', - { - signer: owner, - libraries: { Cron: cronExternalLib.address }, - }, - ) - cron = await cronFactory.deploy(owner.address, cronDelegate.address, 5, []) - const fs = cronReceiver1.interface.functions - handler1Sig = utils - .id(fs['handler1()'].format('sighash')) // TODO this seems like an ethers bug - .slice(0, 10) - }) - - describe('checkUpkeep() / performUpkeep()', () => { - it('uses gas', async () => { - for (let idx = 0; idx < validCrons.length; idx++) { - const cronString = validCrons[idx] - const cronID = idx + 1 - await cron.createCronJobFromString( - cronReceiver1.address, - handler1Sig, - cronString, - ) - await h.fastForward(moment.duration(100, 'years').asSeconds()) // long enough that at least 1 tick occurs - const [needsUpkeep, data] = await cron - .connect(AddressZero) - .callStatic.checkUpkeep('0x') - assert.isTrue(needsUpkeep, `failed for cron string ${cronString}`) - await cron.txCheckUpkeep('0x') - await cron.performUpkeep(data) - await cron.deleteCronJob(cronID) - } - }) - }) -}) diff --git a/contracts/test/v0.8/automation/CronUpkeepFactory.test.ts b/contracts/test/v0.8/automation/CronUpkeepFactory.test.ts deleted file mode 100644 index e9a7de837b7..00000000000 --- a/contracts/test/v0.8/automation/CronUpkeepFactory.test.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { ethers } from 'hardhat' -import { Contract } from 'ethers' -import { assert, expect } from 'chai' -import { CronUpkeepFactory } from '../../../typechain/CronUpkeepFactory' -import type { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -import * as h from '../../test-helpers/helpers' -import { reset } from '../../test-helpers/helpers' - -const OWNABLE_ERR = 'Only callable by owner' - -let cronExternalLib: Contract -let factory: CronUpkeepFactory - -let admin: SignerWithAddress -let owner: SignerWithAddress -let stranger: SignerWithAddress - -describe('CronUpkeepFactory', () => { - beforeEach(async () => { - const accounts = await ethers.getSigners() - admin = accounts[0] - owner = accounts[1] - stranger = accounts[2] - const cronExternalFactory = await ethers.getContractFactory( - 'src/v0.8/automation/libraries/external/Cron.sol:Cron', - admin, - ) - cronExternalLib = await cronExternalFactory.deploy() - const cronUpkeepFactoryFactory = await ethers.getContractFactory( - 'CronUpkeepFactory', - { - signer: admin, - libraries: { - Cron: cronExternalLib.address, - }, - }, - ) - factory = await cronUpkeepFactoryFactory.deploy() - }) - - afterEach(async () => { - await reset() - }) - - it('has a limited public ABI [ @skip-coverage ]', () => { - h.publicAbi(factory as unknown as Contract, [ - 's_maxJobs', - 'newCronUpkeep', - 'newCronUpkeepWithJob', - 'setMaxJobs', - 'cronDelegateAddress', - 'encodeCronString', - 'encodeCronJob', - // Ownable methods: - 'acceptOwnership', - 'owner', - 'transferOwnership', - ]) - }) - - describe('constructor()', () => { - it('deploys a delegate contract', async () => { - assert.notEqual( - await factory.cronDelegateAddress(), - ethers.constants.AddressZero, - ) - }) - }) - - describe('newCronUpkeep()', () => { - it('emits an event', async () => { - await expect(factory.connect(owner).newCronUpkeep()).to.emit( - factory, - 'NewCronUpkeepCreated', - ) - }) - it('sets the deployer as the owner', async () => { - const response = await factory.connect(owner).newCronUpkeep() - const { events } = await response.wait() - if (!events) { - assert.fail('no events emitted') - } - const upkeepAddress = events[0].args?.upkeep - const cronUpkeepFactory = await ethers.getContractFactory('CronUpkeep', { - libraries: { Cron: cronExternalLib.address }, - }) - assert( - await cronUpkeepFactory.attach(upkeepAddress).owner(), - owner.address, - ) - }) - }) - - describe('setMaxJobs()', () => { - it('sets the max jobs value', async () => { - expect(await factory.s_maxJobs()).to.equal(5) - await factory.setMaxJobs(6) - expect(await factory.s_maxJobs()).to.equal(6) - }) - - it('is only callable by the owner', async () => { - await expect(factory.connect(stranger).setMaxJobs(6)).to.be.revertedWith( - OWNABLE_ERR, - ) - }) - }) -}) diff --git a/contracts/test/v0.8/automation/ERC20BalanceMonitor.test.ts b/contracts/test/v0.8/automation/ERC20BalanceMonitor.test.ts deleted file mode 100644 index 2d5d113abca..00000000000 --- a/contracts/test/v0.8/automation/ERC20BalanceMonitor.test.ts +++ /dev/null @@ -1,695 +0,0 @@ -import { ethers } from 'hardhat' -import { assert, expect } from 'chai' -import type { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -import { ReceiveEmitter } from '../../../typechain/ReceiveEmitter' -import { ReceiveFallbackEmitter } from '../../../typechain/ReceiveFallbackEmitter' -import * as h from '../../test-helpers/helpers' -import { ERC20BalanceMonitorExposed, LinkToken } from '../../../typechain' -import { BigNumber } from 'ethers' - -const OWNABLE_ERR = 'Only callable by owner' -const INVALID_WATCHLIST_ERR = `InvalidWatchList` -const PAUSED_ERR = 'Pausable: paused' -const ONLY_KEEPER_ERR = `OnlyKeeperRegistry` - -const zeroLINK = ethers.utils.parseEther('0') -const oneLINK = ethers.utils.parseEther('1') -const twoLINK = ethers.utils.parseEther('2') -const threeLINK = ethers.utils.parseEther('3') -const fiveLINK = ethers.utils.parseEther('5') -const sixLINK = ethers.utils.parseEther('6') -const tenLINK = ethers.utils.parseEther('10') - -const oneHundredLINK = ethers.utils.parseEther('100') - -const watchAddress1 = ethers.Wallet.createRandom().address -const watchAddress2 = ethers.Wallet.createRandom().address -const watchAddress3 = ethers.Wallet.createRandom().address -const watchAddress4 = ethers.Wallet.createRandom().address -let watchAddress5: string -let watchAddress6: string - -let bm: ERC20BalanceMonitorExposed -let lt: LinkToken -let receiveEmitter: ReceiveEmitter -let receiveFallbackEmitter: ReceiveFallbackEmitter -let owner: SignerWithAddress -let stranger: SignerWithAddress -let keeperRegistry: SignerWithAddress - -async function assertWatchlistBalances( - balance1: BigNumber, - balance2: BigNumber, - balance3: BigNumber, - balance4: BigNumber, - balance5: BigNumber, - balance6: BigNumber, -) { - await h.assertLinkTokenBalance(lt, watchAddress1, balance1, 'address 1') - await h.assertLinkTokenBalance(lt, watchAddress2, balance2, 'address 2') - await h.assertLinkTokenBalance(lt, watchAddress3, balance3, 'address 3') - await h.assertLinkTokenBalance(lt, watchAddress4, balance4, 'address 4') - await h.assertLinkTokenBalance(lt, watchAddress5, balance5, 'address 5') - await h.assertLinkTokenBalance(lt, watchAddress6, balance6, 'address 6') -} - -describe('ERC20BalanceMonitor', () => { - beforeEach(async () => { - const accounts = await ethers.getSigners() - owner = accounts[0] - stranger = accounts[1] - keeperRegistry = accounts[2] - watchAddress5 = accounts[3].address - watchAddress6 = accounts[4].address - - const bmFactory = await ethers.getContractFactory( - 'ERC20BalanceMonitorExposed', - owner, - ) - const ltFactory = await ethers.getContractFactory( - 'src/v0.8/shared/test/helpers/LinkTokenTestHelper.sol:LinkTokenTestHelper', - owner, - ) - const reFactory = await ethers.getContractFactory('ReceiveEmitter', owner) - const rfeFactory = await ethers.getContractFactory( - 'ReceiveFallbackEmitter', - owner, - ) - - lt = await ltFactory.deploy() - bm = await bmFactory.deploy(lt.address, keeperRegistry.address, 0) - - for (let i = 1; i <= 4; i++) { - const recipient = await accounts[i].getAddress() - await lt.connect(owner).transfer(recipient, oneHundredLINK) - } - - receiveEmitter = await reFactory.deploy() - receiveFallbackEmitter = await rfeFactory.deploy() - await Promise.all([ - bm.deployed(), - receiveEmitter.deployed(), - receiveFallbackEmitter.deployed(), - ]) - }) - - afterEach(async () => { - await h.reset() - }) - - describe('add funds', () => { - it('Should allow anyone to add funds', async () => { - await lt.transfer(bm.address, oneLINK) - await lt.connect(stranger).transfer(bm.address, oneLINK) - }) - }) - - describe('withdraw()', () => { - beforeEach(async () => { - const tx = await lt.connect(owner).transfer(bm.address, oneLINK) - await tx.wait() - }) - - it('Should allow the owner to withdraw', async () => { - const beforeBalance = await lt.balanceOf(owner.address) - const tx = await bm.connect(owner).withdraw(oneLINK, owner.address) - await tx.wait() - const afterBalance = await lt.balanceOf(owner.address) - assert.isTrue( - afterBalance.gt(beforeBalance), - 'balance did not increase after withdraw', - ) - }) - - it('Should emit an event', async () => { - const tx = await bm.connect(owner).withdraw(oneLINK, owner.address) - await expect(tx) - .to.emit(bm, 'FundsWithdrawn') - .withArgs(oneLINK, owner.address) - }) - - it('Should allow the owner to withdraw to anyone', async () => { - const beforeBalance = await lt.balanceOf(stranger.address) - const tx = await bm.connect(owner).withdraw(oneLINK, stranger.address) - await tx.wait() - const afterBalance = await lt.balanceOf(stranger.address) - assert.isTrue( - beforeBalance.add(oneLINK).eq(afterBalance), - 'balance did not increase after withdraw', - ) - }) - - it('Should not allow strangers to withdraw', async () => { - const tx = bm.connect(stranger).withdraw(oneLINK, owner.address) - await expect(tx).to.be.revertedWith(OWNABLE_ERR) - }) - }) - - describe('pause() / unpause()', () => { - it('Should allow owner to pause / unpause', async () => { - const pauseTx = await bm.connect(owner).pause() - await pauseTx.wait() - const unpauseTx = await bm.connect(owner).unpause() - await unpauseTx.wait() - }) - - it('Should not allow strangers to pause / unpause', async () => { - const pauseTxStranger = bm.connect(stranger).pause() - await expect(pauseTxStranger).to.be.revertedWith(OWNABLE_ERR) - const pauseTxOwner = await bm.connect(owner).pause() - await pauseTxOwner.wait() - const unpauseTxStranger = bm.connect(stranger).unpause() - await expect(unpauseTxStranger).to.be.revertedWith(OWNABLE_ERR) - }) - }) - - describe('setWatchList() / getWatchList() / getAccountInfo()', () => { - it('Should allow owner to set the watchlist', async () => { - // should start unactive - assert.isFalse((await bm.getAccountInfo(watchAddress1)).isActive) - // add first watchlist - let setTx = await bm - .connect(owner) - .setWatchList([watchAddress1], [oneLINK], [twoLINK]) - await setTx.wait() - let watchList = await bm.getWatchList() - assert.deepEqual(watchList, [watchAddress1]) - const accountInfo = await bm.getAccountInfo(watchAddress1) - assert.isTrue(accountInfo.isActive) - expect(accountInfo.minBalance).to.equal(oneLINK) - expect(accountInfo.topUpLevel).to.equal(twoLINK) - // add more to watchlist - setTx = await bm - .connect(owner) - .setWatchList( - [watchAddress1, watchAddress2, watchAddress3], - [oneLINK, twoLINK, threeLINK], - [twoLINK, threeLINK, fiveLINK], - ) - await setTx.wait() - watchList = await bm.getWatchList() - assert.deepEqual(watchList, [watchAddress1, watchAddress2, watchAddress3]) - let accountInfo1 = await bm.getAccountInfo(watchAddress1) - let accountInfo2 = await bm.getAccountInfo(watchAddress2) - let accountInfo3 = await bm.getAccountInfo(watchAddress3) - expect(accountInfo1.isActive).to.be.true - expect(accountInfo1.minBalance).to.equal(oneLINK) - expect(accountInfo1.topUpLevel).to.equal(twoLINK) - expect(accountInfo2.isActive).to.be.true - expect(accountInfo2.minBalance).to.equal(twoLINK) - expect(accountInfo2.topUpLevel).to.equal(threeLINK) - expect(accountInfo3.isActive).to.be.true - expect(accountInfo3.minBalance).to.equal(threeLINK) - expect(accountInfo3.topUpLevel).to.equal(fiveLINK) - // remove some from watchlist - setTx = await bm - .connect(owner) - .setWatchList( - [watchAddress3, watchAddress1], - [threeLINK, oneLINK], - [fiveLINK, twoLINK], - ) - await setTx.wait() - watchList = await bm.getWatchList() - assert.deepEqual(watchList, [watchAddress3, watchAddress1]) - accountInfo1 = await bm.getAccountInfo(watchAddress1) - accountInfo2 = await bm.getAccountInfo(watchAddress2) - accountInfo3 = await bm.getAccountInfo(watchAddress3) - expect(accountInfo1.isActive).to.be.true - expect(accountInfo2.isActive).to.be.false - expect(accountInfo3.isActive).to.be.true - }) - - it('Should not allow duplicates in the watchlist', async () => { - const errMsg = `DuplicateAddress` - const setTx = bm - .connect(owner) - .setWatchList( - [watchAddress1, watchAddress2, watchAddress1], - [oneLINK, twoLINK, threeLINK], - [twoLINK, threeLINK, fiveLINK], - ) - await expect(setTx) - .to.be.revertedWithCustomError(bm, errMsg) - .withArgs(watchAddress1) - }) - - it('Should not allow a topUpLevel les than or equal to minBalance in the watchlist', async () => { - const setTx = bm - .connect(owner) - .setWatchList( - [watchAddress1, watchAddress2, watchAddress1], - [oneLINK, twoLINK, threeLINK], - [zeroLINK, twoLINK, threeLINK], - ) - await expect(setTx).to.be.revertedWithCustomError( - bm, - INVALID_WATCHLIST_ERR, - ) - }) - - it('Should not allow larger than maximum watchlist size', async () => { - const watchlist: any[][] = [[], [], []] - Array.from(Array(301).keys()).forEach(() => { - watchlist[0].push(owner.address) - watchlist[1].push(oneLINK) - watchlist[2].push(twoLINK) - }) - const tx = bm - .connect(owner) - .setWatchList(watchlist[0], watchlist[1], watchlist[2]) - await expect(tx).to.be.revertedWithCustomError(bm, INVALID_WATCHLIST_ERR) - }) - - it('Should not allow strangers to set the watchlist', async () => { - const setTxStranger = bm - .connect(stranger) - .setWatchList([watchAddress1], [oneLINK], [twoLINK]) - await expect(setTxStranger).to.be.revertedWith(OWNABLE_ERR) - }) - - it('Should revert if the list lengths differ', async () => { - let tx = bm.connect(owner).setWatchList([watchAddress1], [], [twoLINK]) - await expect(tx).to.be.revertedWithCustomError(bm, INVALID_WATCHLIST_ERR) - tx = bm.connect(owner).setWatchList([watchAddress1], [oneLINK], []) - await expect(tx).to.be.revertedWithCustomError(bm, INVALID_WATCHLIST_ERR) - tx = bm.connect(owner).setWatchList([], [oneLINK], [twoLINK]) - await expect(tx).to.be.revertedWithCustomError(bm, INVALID_WATCHLIST_ERR) - }) - - it('Should revert if any of the addresses are empty', async () => { - let tx = bm - .connect(owner) - .setWatchList( - [watchAddress1, ethers.constants.AddressZero], - [oneLINK, oneLINK], - [twoLINK, twoLINK], - ) - await expect(tx).to.be.revertedWithCustomError(bm, INVALID_WATCHLIST_ERR) - }) - - it('Should revert if any of the top up amounts are 0', async () => { - const tx = bm - .connect(owner) - .setWatchList( - [watchAddress1, watchAddress2], - [oneLINK, oneLINK], - [twoLINK, zeroLINK], - ) - await expect(tx).to.be.revertedWithCustomError(bm, INVALID_WATCHLIST_ERR) - }) - }) - - describe('getKeeperRegistryAddress() / setKeeperRegistryAddress()', () => { - const newAddress = ethers.Wallet.createRandom().address - - it('Should initialize with the registry address provided to the constructor', async () => { - const address = await bm.getKeeperRegistryAddress() - assert.equal(address, keeperRegistry.address) - }) - - it('Should allow the owner to set the registry address', async () => { - const setTx = await bm.connect(owner).setKeeperRegistryAddress(newAddress) - await setTx.wait() - const address = await bm.getKeeperRegistryAddress() - assert.equal(address, newAddress) - }) - - it('Should not allow strangers to set the registry address', async () => { - const setTx = bm.connect(stranger).setKeeperRegistryAddress(newAddress) - await expect(setTx).to.be.revertedWith(OWNABLE_ERR) - }) - - it('Should emit an event', async () => { - const setTx = await bm.connect(owner).setKeeperRegistryAddress(newAddress) - await expect(setTx) - .to.emit(bm, 'KeeperRegistryAddressUpdated') - .withArgs(keeperRegistry.address, newAddress) - }) - }) - - describe('getMinWaitPeriodSeconds / setMinWaitPeriodSeconds()', () => { - const newWaitPeriod = BigNumber.from(1) - - it('Should initialize with the wait period provided to the constructor', async () => { - const minWaitPeriod = await bm.getMinWaitPeriodSeconds() - expect(minWaitPeriod).to.equal(0) - }) - - it('Should allow owner to set the wait period', async () => { - const setTx = await bm - .connect(owner) - .setMinWaitPeriodSeconds(newWaitPeriod) - await setTx.wait() - const minWaitPeriod = await bm.getMinWaitPeriodSeconds() - expect(minWaitPeriod).to.equal(newWaitPeriod) - }) - - it('Should not allow strangers to set the wait period', async () => { - const setTx = bm.connect(stranger).setMinWaitPeriodSeconds(newWaitPeriod) - await expect(setTx).to.be.revertedWith(OWNABLE_ERR) - }) - - it('Should emit an event', async () => { - const setTx = await bm - .connect(owner) - .setMinWaitPeriodSeconds(newWaitPeriod) - await expect(setTx) - .to.emit(bm, 'MinWaitPeriodUpdated') - .withArgs(0, newWaitPeriod) - }) - }) - - describe('checkUpkeep() / getUnderfundedAddresses()', () => { - beforeEach(async () => { - const setTx = await bm.connect(owner).setWatchList( - [ - watchAddress1, // needs funds - watchAddress5, // funded - watchAddress2, // needs funds - watchAddress6, // funded - watchAddress3, // needs funds - ], - new Array(5).fill(oneLINK), - new Array(5).fill(twoLINK), - ) - await setTx.wait() - }) - - it('Should return list of address that are underfunded', async () => { - const fundTx = await lt.connect(owner).transfer( - bm.address, - sixLINK, // needs 6 total - ) - await fundTx.wait() - const [should, payload] = await bm.checkUpkeep('0x') - assert.isTrue(should) - let [addresses] = ethers.utils.defaultAbiCoder.decode( - ['address[]'], - payload, - ) - assert.deepEqual(addresses, [watchAddress1, watchAddress2, watchAddress3]) - // checkUpkeep payload should match getUnderfundedAddresses() - addresses = await bm.getUnderfundedAddresses() - assert.deepEqual(addresses, [watchAddress1, watchAddress2, watchAddress3]) - }) - - it('Should return some results even if contract cannot fund all eligible targets', async () => { - const fundTx = await lt.connect(owner).transfer( - bm.address, - fiveLINK, // needs 6 total - ) - await fundTx.wait() - const [should, payload] = await bm.checkUpkeep('0x') - assert.isTrue(should) - const [addresses] = ethers.utils.defaultAbiCoder.decode( - ['address[]'], - payload, - ) - assert.deepEqual(addresses, [watchAddress1, watchAddress2]) - }) - - it('Should omit addresses that have been funded recently', async () => { - const setWaitPdTx = await bm.setMinWaitPeriodSeconds(3600) // 1 hour - const fundTx = await lt.connect(owner).transfer(bm.address, sixLINK) - await Promise.all([setWaitPdTx.wait(), fundTx.wait()]) - const block = await ethers.provider.getBlock('latest') - const setTopUpTx = await bm.setLastTopUpXXXTestOnly( - watchAddress2, - block.timestamp - 100, - ) - await setTopUpTx.wait() - const [should, payload] = await bm.checkUpkeep('0x') - assert.isTrue(should) - const [addresses] = ethers.utils.defaultAbiCoder.decode( - ['address[]'], - payload, - ) - assert.deepEqual(addresses, [watchAddress1, watchAddress3]) - }) - - it('Should revert when paused', async () => { - const tx = await bm.connect(owner).pause() - await tx.wait() - const ethCall = bm.checkUpkeep('0x') - await expect(ethCall).to.be.revertedWith(PAUSED_ERR) - }) - }) - - describe('performUpkeep()', () => { - let validPayload: string - let invalidPayload: string - - beforeEach(async () => { - validPayload = ethers.utils.defaultAbiCoder.encode( - ['address[]'], - [[watchAddress1, watchAddress2, watchAddress3]], - ) - invalidPayload = ethers.utils.defaultAbiCoder.encode( - ['address[]'], - [[watchAddress1, watchAddress2, watchAddress4, watchAddress5]], - ) - const setTx = await bm.connect(owner).setWatchList( - [ - watchAddress1, // needs funds - watchAddress5, // funded - watchAddress2, // needs funds - watchAddress6, // funded - watchAddress3, // needs funds - // watchAddress4 - omitted - ], - new Array(5).fill(oneLINK), - new Array(5).fill(twoLINK), - ) - await setTx.wait() - }) - - it('Should revert when paused', async () => { - const pauseTx = await bm.connect(owner).pause() - await pauseTx.wait() - const performTx = bm.connect(keeperRegistry).performUpkeep(validPayload) - await expect(performTx).to.be.revertedWith(PAUSED_ERR) - }) - - context('when partially funded', () => { - it('Should fund as many addresses as possible', async () => { - const fundTx = await lt.connect(owner).transfer( - bm.address, - fiveLINK, // only enough LINK to fund 2 addresses - ) - await fundTx.wait() - await assertWatchlistBalances( - zeroLINK, - zeroLINK, - zeroLINK, - zeroLINK, - oneHundredLINK, - oneHundredLINK, - ) - const performTx = await bm - .connect(keeperRegistry) - .performUpkeep(validPayload) - await assertWatchlistBalances( - twoLINK, - twoLINK, - zeroLINK, - zeroLINK, - oneHundredLINK, - oneHundredLINK, - ) - await expect(performTx) - .to.emit(bm, 'TopUpSucceeded') - .withArgs(watchAddress1) - await expect(performTx) - .to.emit(bm, 'TopUpSucceeded') - .withArgs(watchAddress2) - }) - }) - - context('when fully funded', () => { - beforeEach(async () => { - const fundTx = await lt.connect(owner).transfer(bm.address, tenLINK) - await fundTx.wait() - }) - - it('Should fund the appropriate addresses', async () => { - await assertWatchlistBalances( - zeroLINK, - zeroLINK, - zeroLINK, - zeroLINK, - oneHundredLINK, - oneHundredLINK, - ) - const performTx = await bm - .connect(keeperRegistry) - .performUpkeep(validPayload, { gasLimit: 2_500_000 }) - await performTx.wait() - await assertWatchlistBalances( - twoLINK, - twoLINK, - twoLINK, - zeroLINK, - oneHundredLINK, - oneHundredLINK, - ) - }) - - it('Should only fund active, underfunded addresses', async () => { - await assertWatchlistBalances( - zeroLINK, - zeroLINK, - zeroLINK, - zeroLINK, - oneHundredLINK, - oneHundredLINK, - ) - const performTx = await bm - .connect(keeperRegistry) - .performUpkeep(invalidPayload, { gasLimit: 2_500_000 }) - await performTx.wait() - await assertWatchlistBalances( - twoLINK, - twoLINK, - zeroLINK, - zeroLINK, - oneHundredLINK, - oneHundredLINK, - ) - }) - - it('Should not fund addresses that have been funded recently', async () => { - const setWaitPdTx = await bm.setMinWaitPeriodSeconds(3600) // 1 hour - await setWaitPdTx.wait() - const block = await ethers.provider.getBlock('latest') - const setTopUpTx = await bm.setLastTopUpXXXTestOnly( - watchAddress2, - block.timestamp - 100, - ) - await setTopUpTx.wait() - await assertWatchlistBalances( - zeroLINK, - zeroLINK, - zeroLINK, - zeroLINK, - oneHundredLINK, - oneHundredLINK, - ) - const performTx = await bm - .connect(keeperRegistry) - .performUpkeep(validPayload, { gasLimit: 2_500_000 }) - await performTx.wait() - await assertWatchlistBalances( - twoLINK, - zeroLINK, - twoLINK, - zeroLINK, - oneHundredLINK, - oneHundredLINK, - ) - }) - - it('Should only be callable by the keeper registry contract', async () => { - let performTx = bm.connect(owner).performUpkeep(validPayload) - await expect(performTx).to.be.revertedWithCustomError( - bm, - ONLY_KEEPER_ERR, - ) - performTx = bm.connect(stranger).performUpkeep(validPayload) - await expect(performTx).to.be.revertedWithCustomError( - bm, - ONLY_KEEPER_ERR, - ) - }) - - it('Should protect against running out of gas', async () => { - await assertWatchlistBalances( - zeroLINK, - zeroLINK, - zeroLINK, - zeroLINK, - oneHundredLINK, - oneHundredLINK, - ) - const performTx = await bm - .connect(keeperRegistry) - .performUpkeep(validPayload, { gasLimit: 130_000 }) // too little for all 3 transfers - await performTx.wait() - const balance1 = await lt.balanceOf(watchAddress1) - const balance2 = await lt.balanceOf(watchAddress2) - const balance3 = await lt.balanceOf(watchAddress3) - const balances = [balance1, balance2, balance3].map((n) => n.toString()) - expect(balances) - .to.include(twoLINK.toString()) // expect at least 1 transfer - .to.include(zeroLINK.toString()) // expect at least 1 out of funds - }) - - it('Should provide enough gas to support receive and fallback functions', async () => { - const addresses = [ - receiveEmitter.address, - receiveFallbackEmitter.address, - ] - const payload = ethers.utils.defaultAbiCoder.encode( - ['address[]'], - [addresses], - ) - const setTx = await bm - .connect(owner) - .setWatchList( - addresses, - new Array(2).fill(oneLINK), - new Array(2).fill(twoLINK), - ) - await setTx.wait() - - const reBalanceBefore = await lt.balanceOf(receiveEmitter.address) - const rfeBalanceBefore = await lt.balanceOf( - receiveFallbackEmitter.address, - ) - const performTx = await bm - .connect(keeperRegistry) - .performUpkeep(payload, { gasLimit: 2_500_000 }) - await h.assertLinkTokenBalance( - lt, - receiveEmitter.address, - reBalanceBefore.add(twoLINK), - ) - await h.assertLinkTokenBalance( - lt, - receiveFallbackEmitter.address, - rfeBalanceBefore.add(twoLINK), - ) - - await expect(performTx) - .to.emit(bm, 'TopUpSucceeded') - .withArgs(receiveEmitter.address) - await expect(performTx) - .to.emit(bm, 'TopUpSucceeded') - .withArgs(receiveFallbackEmitter.address) - }) - }) - }) - - describe('topUp()', () => { - context('when not paused', () => { - it('Should be callable by anyone', async () => { - const users = [owner, keeperRegistry, stranger] - for (let idx = 0; idx < users.length; idx++) { - const user = users[idx] - await bm.connect(user).topUp([]) - } - }) - }) - context('when paused', () => { - it('Should be callable by no one', async () => { - await bm.connect(owner).pause() - const users = [owner, keeperRegistry, stranger] - for (let idx = 0; idx < users.length; idx++) { - const user = users[idx] - const tx = bm.connect(user).topUp([]) - await expect(tx).to.be.revertedWith(PAUSED_ERR) - } - }) - }) - }) -}) diff --git a/contracts/test/v0.8/automation/EthBalanceMonitor.test.ts b/contracts/test/v0.8/automation/EthBalanceMonitor.test.ts deleted file mode 100644 index edcf1b564c9..00000000000 --- a/contracts/test/v0.8/automation/EthBalanceMonitor.test.ts +++ /dev/null @@ -1,663 +0,0 @@ -import { ethers } from 'hardhat' -import { assert, expect } from 'chai' -import type { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -import { EthBalanceMonitorExposed } from '../../../typechain/EthBalanceMonitorExposed' -import { ReceiveReverter } from '../../../typechain/ReceiveReverter' -import { ReceiveEmitter } from '../../../typechain/ReceiveEmitter' -import { ReceiveFallbackEmitter } from '../../../typechain/ReceiveFallbackEmitter' -import { BigNumber } from 'ethers' -import * as h from '../../test-helpers/helpers' - -const OWNABLE_ERR = 'Only callable by owner' -const INVALID_WATCHLIST_ERR = `InvalidWatchList` -const PAUSED_ERR = 'Pausable: paused' -const ONLY_KEEPER_ERR = `OnlyKeeperRegistry` - -const zeroEth = ethers.utils.parseEther('0') -const oneEth = ethers.utils.parseEther('1') -const twoEth = ethers.utils.parseEther('2') -const threeEth = ethers.utils.parseEther('3') -const fiveEth = ethers.utils.parseEther('5') -const sixEth = ethers.utils.parseEther('6') -const tenEth = ethers.utils.parseEther('10') - -const watchAddress1 = ethers.Wallet.createRandom().address -const watchAddress2 = ethers.Wallet.createRandom().address -const watchAddress3 = ethers.Wallet.createRandom().address -const watchAddress4 = ethers.Wallet.createRandom().address -let watchAddress5: string -let watchAddress6: string - -async function assertWatchlistBalances( - balance1: number, - balance2: number, - balance3: number, - balance4: number, - balance5: number, - balance6: number, -) { - const toEth = (n: number) => ethers.utils.parseUnits(n.toString(), 'ether') - await h.assertBalance(watchAddress1, toEth(balance1), 'address 1') - await h.assertBalance(watchAddress2, toEth(balance2), 'address 2') - await h.assertBalance(watchAddress3, toEth(balance3), 'address 3') - await h.assertBalance(watchAddress4, toEth(balance4), 'address 4') - await h.assertBalance(watchAddress5, toEth(balance5), 'address 5') - await h.assertBalance(watchAddress6, toEth(balance6), 'address 6') -} - -let bm: EthBalanceMonitorExposed -let receiveReverter: ReceiveReverter -let receiveEmitter: ReceiveEmitter -let receiveFallbackEmitter: ReceiveFallbackEmitter -let owner: SignerWithAddress -let stranger: SignerWithAddress -let keeperRegistry: SignerWithAddress - -describe('EthBalanceMonitor', () => { - beforeEach(async () => { - const accounts = await ethers.getSigners() - owner = accounts[0] - stranger = accounts[1] - keeperRegistry = accounts[2] - watchAddress5 = accounts[3].address - watchAddress6 = accounts[4].address - - const bmFactory = await ethers.getContractFactory( - 'EthBalanceMonitorExposed', - owner, - ) - const rrFactory = await ethers.getContractFactory('ReceiveReverter', owner) - const reFactory = await ethers.getContractFactory('ReceiveEmitter', owner) - const rfeFactory = await ethers.getContractFactory( - 'ReceiveFallbackEmitter', - owner, - ) - - bm = await bmFactory.deploy(keeperRegistry.address, 0) - receiveReverter = await rrFactory.deploy() - receiveEmitter = await reFactory.deploy() - receiveFallbackEmitter = await rfeFactory.deploy() - await Promise.all([ - bm.deployed(), - receiveReverter.deployed(), - receiveEmitter.deployed(), - receiveFallbackEmitter.deployed(), - ]) - }) - - afterEach(async () => { - await h.reset() - }) - - describe('receive()', () => { - it('Should allow anyone to add funds', async () => { - await owner.sendTransaction({ - to: bm.address, - value: oneEth, - }) - await stranger.sendTransaction({ - to: bm.address, - value: oneEth, - }) - }) - - it('Should emit an event', async () => { - await owner.sendTransaction({ - to: bm.address, - value: oneEth, - }) - const tx = stranger.sendTransaction({ - to: bm.address, - value: oneEth, - }) - await expect(tx) - .to.emit(bm, 'FundsAdded') - .withArgs(oneEth, twoEth, stranger.address) - }) - }) - - describe('withdraw()', () => { - beforeEach(async () => { - const tx = await owner.sendTransaction({ - to: bm.address, - value: oneEth, - }) - await tx.wait() - }) - - it('Should allow the owner to withdraw', async () => { - const beforeBalance = await owner.getBalance() - const tx = await bm.connect(owner).withdraw(oneEth, owner.address) - await tx.wait() - const afterBalance = await owner.getBalance() - assert.isTrue( - afterBalance.gt(beforeBalance), - 'balance did not increase after withdraw', - ) - }) - - it('Should emit an event', async () => { - const tx = await bm.connect(owner).withdraw(oneEth, owner.address) - await expect(tx) - .to.emit(bm, 'FundsWithdrawn') - .withArgs(oneEth, owner.address) - }) - - it('Should allow the owner to withdraw to anyone', async () => { - const beforeBalance = await stranger.getBalance() - const tx = await bm.connect(owner).withdraw(oneEth, stranger.address) - await tx.wait() - const afterBalance = await stranger.getBalance() - assert.isTrue( - beforeBalance.add(oneEth).eq(afterBalance), - 'balance did not increase after withdraw', - ) - }) - - it('Should not allow strangers to withdraw', async () => { - const tx = bm.connect(stranger).withdraw(oneEth, owner.address) - await expect(tx).to.be.revertedWith(OWNABLE_ERR) - }) - }) - - describe('pause() / unpause()', () => { - it('Should allow owner to pause / unpause', async () => { - const pauseTx = await bm.connect(owner).pause() - await pauseTx.wait() - const unpauseTx = await bm.connect(owner).unpause() - await unpauseTx.wait() - }) - - it('Should not allow strangers to pause / unpause', async () => { - const pauseTxStranger = bm.connect(stranger).pause() - await expect(pauseTxStranger).to.be.revertedWith(OWNABLE_ERR) - const pauseTxOwner = await bm.connect(owner).pause() - await pauseTxOwner.wait() - const unpauseTxStranger = bm.connect(stranger).unpause() - await expect(unpauseTxStranger).to.be.revertedWith(OWNABLE_ERR) - }) - }) - - describe('setWatchList() / getWatchList() / getAccountInfo()', () => { - it('Should allow owner to set the watchlist', async () => { - // should start unactive - assert.isFalse((await bm.getAccountInfo(watchAddress1)).isActive) - // add first watchlist - let setTx = await bm - .connect(owner) - .setWatchList([watchAddress1], [oneEth], [twoEth]) - await setTx.wait() - let watchList = await bm.getWatchList() - assert.deepEqual(watchList, [watchAddress1]) - const accountInfo = await bm.getAccountInfo(watchAddress1) - assert.isTrue(accountInfo.isActive) - expect(accountInfo.minBalanceWei).to.equal(oneEth) - expect(accountInfo.topUpAmountWei).to.equal(twoEth) - // add more to watchlist - setTx = await bm - .connect(owner) - .setWatchList( - [watchAddress1, watchAddress2, watchAddress3], - [oneEth, twoEth, threeEth], - [oneEth, twoEth, threeEth], - ) - await setTx.wait() - watchList = await bm.getWatchList() - assert.deepEqual(watchList, [watchAddress1, watchAddress2, watchAddress3]) - let accountInfo1 = await bm.getAccountInfo(watchAddress1) - let accountInfo2 = await bm.getAccountInfo(watchAddress2) - let accountInfo3 = await bm.getAccountInfo(watchAddress3) - expect(accountInfo1.isActive).to.be.true - expect(accountInfo1.minBalanceWei).to.equal(oneEth) - expect(accountInfo1.topUpAmountWei).to.equal(oneEth) - expect(accountInfo2.isActive).to.be.true - expect(accountInfo2.minBalanceWei).to.equal(twoEth) - expect(accountInfo2.topUpAmountWei).to.equal(twoEth) - expect(accountInfo3.isActive).to.be.true - expect(accountInfo3.minBalanceWei).to.equal(threeEth) - expect(accountInfo3.topUpAmountWei).to.equal(threeEth) - // remove some from watchlist - setTx = await bm - .connect(owner) - .setWatchList( - [watchAddress3, watchAddress1], - [threeEth, oneEth], - [threeEth, oneEth], - ) - await setTx.wait() - watchList = await bm.getWatchList() - assert.deepEqual(watchList, [watchAddress3, watchAddress1]) - accountInfo1 = await bm.getAccountInfo(watchAddress1) - accountInfo2 = await bm.getAccountInfo(watchAddress2) - accountInfo3 = await bm.getAccountInfo(watchAddress3) - expect(accountInfo1.isActive).to.be.true - expect(accountInfo2.isActive).to.be.false - expect(accountInfo3.isActive).to.be.true - }) - - it('Should not allow duplicates in the watchlist', async () => { - const errMsg = `DuplicateAddress` - const setTx = bm - .connect(owner) - .setWatchList( - [watchAddress1, watchAddress2, watchAddress1], - [oneEth, twoEth, threeEth], - [oneEth, twoEth, threeEth], - ) - await expect(setTx) - .to.be.revertedWithCustomError(bm, errMsg) - .withArgs(watchAddress1) - }) - - it('Should not allow strangers to set the watchlist', async () => { - const setTxStranger = bm - .connect(stranger) - .setWatchList([watchAddress1], [oneEth], [twoEth]) - await expect(setTxStranger).to.be.revertedWith(OWNABLE_ERR) - }) - - it('Should revert if the list lengths differ', async () => { - let tx = bm.connect(owner).setWatchList([watchAddress1], [], [twoEth]) - await expect(tx).to.be.revertedWithCustomError(bm, INVALID_WATCHLIST_ERR) - tx = bm.connect(owner).setWatchList([watchAddress1], [oneEth], []) - await expect(tx).to.be.revertedWithCustomError(bm, INVALID_WATCHLIST_ERR) - tx = bm.connect(owner).setWatchList([], [oneEth], [twoEth]) - await expect(tx).to.be.revertedWithCustomError(bm, INVALID_WATCHLIST_ERR) - }) - - it('Should revert if any of the addresses are empty', async () => { - let tx = bm - .connect(owner) - .setWatchList( - [watchAddress1, ethers.constants.AddressZero], - [oneEth, oneEth], - [twoEth, twoEth], - ) - await expect(tx).to.be.revertedWithCustomError(bm, INVALID_WATCHLIST_ERR) - }) - - it('Should revert if any of the top up amounts are 0', async () => { - const tx = bm - .connect(owner) - .setWatchList( - [watchAddress1, watchAddress2], - [oneEth, oneEth], - [twoEth, zeroEth], - ) - await expect(tx).to.be.revertedWithCustomError(bm, INVALID_WATCHLIST_ERR) - }) - }) - - describe('getKeeperRegistryAddress() / setKeeperRegistryAddress()', () => { - const newAddress = ethers.Wallet.createRandom().address - - it('Should initialize with the registry address provided to the constructor', async () => { - const address = await bm.getKeeperRegistryAddress() - assert.equal(address, keeperRegistry.address) - }) - - it('Should allow the owner to set the registry address', async () => { - const setTx = await bm.connect(owner).setKeeperRegistryAddress(newAddress) - await setTx.wait() - const address = await bm.getKeeperRegistryAddress() - assert.equal(address, newAddress) - }) - - it('Should not allow strangers to set the registry address', async () => { - const setTx = bm.connect(stranger).setKeeperRegistryAddress(newAddress) - await expect(setTx).to.be.revertedWith(OWNABLE_ERR) - }) - - it('Should emit an event', async () => { - const setTx = await bm.connect(owner).setKeeperRegistryAddress(newAddress) - await expect(setTx) - .to.emit(bm, 'KeeperRegistryAddressUpdated') - .withArgs(keeperRegistry.address, newAddress) - }) - }) - - describe('getMinWaitPeriodSeconds / setMinWaitPeriodSeconds()', () => { - const newWaitPeriod = BigNumber.from(1) - - it('Should initialize with the wait period provided to the constructor', async () => { - const minWaitPeriod = await bm.getMinWaitPeriodSeconds() - expect(minWaitPeriod).to.equal(0) - }) - - it('Should allow owner to set the wait period', async () => { - const setTx = await bm - .connect(owner) - .setMinWaitPeriodSeconds(newWaitPeriod) - await setTx.wait() - const minWaitPeriod = await bm.getMinWaitPeriodSeconds() - expect(minWaitPeriod).to.equal(newWaitPeriod) - }) - - it('Should not allow strangers to set the wait period', async () => { - const setTx = bm.connect(stranger).setMinWaitPeriodSeconds(newWaitPeriod) - await expect(setTx).to.be.revertedWith(OWNABLE_ERR) - }) - - it('Should emit an event', async () => { - const setTx = await bm - .connect(owner) - .setMinWaitPeriodSeconds(newWaitPeriod) - await expect(setTx) - .to.emit(bm, 'MinWaitPeriodUpdated') - .withArgs(0, newWaitPeriod) - }) - }) - - describe('checkUpkeep() / getUnderfundedAddresses()', () => { - beforeEach(async () => { - const setTx = await bm.connect(owner).setWatchList( - [ - watchAddress1, // needs funds - watchAddress5, // funded - watchAddress2, // needs funds - watchAddress6, // funded - watchAddress3, // needs funds - ], - new Array(5).fill(oneEth), - new Array(5).fill(twoEth), - ) - await setTx.wait() - }) - - it('Should return list of address that are underfunded', async () => { - const fundTx = await owner.sendTransaction({ - to: bm.address, - value: sixEth, // needs 6 total - }) - await fundTx.wait() - const [should, payload] = await bm.checkUpkeep('0x') - assert.isTrue(should) - let [addresses] = ethers.utils.defaultAbiCoder.decode( - ['address[]'], - payload, - ) - assert.deepEqual(addresses, [watchAddress1, watchAddress2, watchAddress3]) - // checkUpkeep payload should match getUnderfundedAddresses() - addresses = await bm.getUnderfundedAddresses() - assert.deepEqual(addresses, [watchAddress1, watchAddress2, watchAddress3]) - }) - - it('Should return some results even if contract cannot fund all eligible targets', async () => { - const fundTx = await owner.sendTransaction({ - to: bm.address, - value: fiveEth, // needs 6 total - }) - await fundTx.wait() - const [should, payload] = await bm.checkUpkeep('0x') - assert.isTrue(should) - const [addresses] = ethers.utils.defaultAbiCoder.decode( - ['address[]'], - payload, - ) - assert.deepEqual(addresses, [watchAddress1, watchAddress2]) - }) - - it('Should omit addresses that have been funded recently', async () => { - const setWaitPdTx = await bm.setMinWaitPeriodSeconds(3600) // 1 hour - const fundTx = await owner.sendTransaction({ - to: bm.address, - value: sixEth, - }) - await Promise.all([setWaitPdTx.wait(), fundTx.wait()]) - const block = await ethers.provider.getBlock('latest') - const setTopUpTx = await bm.setLastTopUpXXXTestOnly( - watchAddress2, - block.timestamp - 100, - ) - await setTopUpTx.wait() - const [should, payload] = await bm.checkUpkeep('0x') - assert.isTrue(should) - const [addresses] = ethers.utils.defaultAbiCoder.decode( - ['address[]'], - payload, - ) - assert.deepEqual(addresses, [watchAddress1, watchAddress3]) - }) - - it('Should revert when paused', async () => { - const tx = await bm.connect(owner).pause() - await tx.wait() - const ethCall = bm.checkUpkeep('0x') - await expect(ethCall).to.be.revertedWith(PAUSED_ERR) - }) - }) - - describe('performUpkeep()', () => { - let validPayload: string - let invalidPayload: string - - beforeEach(async () => { - validPayload = ethers.utils.defaultAbiCoder.encode( - ['address[]'], - [[watchAddress1, watchAddress2, watchAddress3]], - ) - invalidPayload = ethers.utils.defaultAbiCoder.encode( - ['address[]'], - [[watchAddress1, watchAddress2, watchAddress4, watchAddress5]], - ) - const setTx = await bm.connect(owner).setWatchList( - [ - watchAddress1, // needs funds - watchAddress5, // funded - watchAddress2, // needs funds - watchAddress6, // funded - watchAddress3, // needs funds - // watchAddress4 - omitted - ], - new Array(5).fill(oneEth), - new Array(5).fill(twoEth), - ) - await setTx.wait() - }) - - it('Should revert when paused', async () => { - const pauseTx = await bm.connect(owner).pause() - await pauseTx.wait() - const performTx = bm.connect(keeperRegistry).performUpkeep(validPayload) - await expect(performTx).to.be.revertedWith(PAUSED_ERR) - }) - - context('when partially funded', () => { - it('Should fund as many addresses as possible', async () => { - const fundTx = await owner.sendTransaction({ - to: bm.address, - value: fiveEth, // only enough eth to fund 2 addresses - }) - await fundTx.wait() - await assertWatchlistBalances(0, 0, 0, 0, 10_000, 10_000) - const performTx = await bm - .connect(keeperRegistry) - .performUpkeep(validPayload) - await assertWatchlistBalances(2, 2, 0, 0, 10_000, 10_000) - await expect(performTx) - .to.emit(bm, 'TopUpSucceeded') - .withArgs(watchAddress1) - await expect(performTx) - .to.emit(bm, 'TopUpSucceeded') - .withArgs(watchAddress2) - }) - }) - - context('when fully funded', () => { - beforeEach(async () => { - const fundTx = await owner.sendTransaction({ - to: bm.address, - value: tenEth, - }) - await fundTx.wait() - }) - - it('Should fund the appropriate addresses', async () => { - await assertWatchlistBalances(0, 0, 0, 0, 10_000, 10_000) - const performTx = await bm - .connect(keeperRegistry) - .performUpkeep(validPayload, { gasLimit: 2_500_000 }) - await performTx.wait() - await assertWatchlistBalances(2, 2, 2, 0, 10_000, 10_000) - }) - - it('Should only fund active, underfunded addresses', async () => { - await assertWatchlistBalances(0, 0, 0, 0, 10_000, 10_000) - const performTx = await bm - .connect(keeperRegistry) - .performUpkeep(invalidPayload, { gasLimit: 2_500_000 }) - await performTx.wait() - await assertWatchlistBalances(2, 2, 0, 0, 10_000, 10_000) - }) - - it('Should continue funding addresses even if one reverts', async () => { - await assertWatchlistBalances(0, 0, 0, 0, 10_000, 10_000) - const addresses = [ - watchAddress1, - receiveReverter.address, - watchAddress2, - ] - const setTx = await bm - .connect(owner) - .setWatchList( - addresses, - new Array(3).fill(oneEth), - new Array(3).fill(twoEth), - ) - await setTx.wait() - const payload = ethers.utils.defaultAbiCoder.encode( - ['address[]'], - [addresses], - ) - const performTx = await bm - .connect(keeperRegistry) - .performUpkeep(payload, { gasLimit: 2_500_000 }) - await performTx.wait() - await assertWatchlistBalances(2, 2, 0, 0, 10_000, 10_000) - await h.assertBalance(receiveReverter.address, 0) - await expect(performTx) - .to.emit(bm, 'TopUpSucceeded') - .withArgs(watchAddress1) - await expect(performTx) - .to.emit(bm, 'TopUpSucceeded') - .withArgs(watchAddress2) - await expect(performTx) - .to.emit(bm, 'TopUpFailed') - .withArgs(receiveReverter.address) - }) - - it('Should not fund addresses that have been funded recently', async () => { - const setWaitPdTx = await bm.setMinWaitPeriodSeconds(3600) // 1 hour - await setWaitPdTx.wait() - const block = await ethers.provider.getBlock('latest') - const setTopUpTx = await bm.setLastTopUpXXXTestOnly( - watchAddress2, - block.timestamp - 100, - ) - await setTopUpTx.wait() - await assertWatchlistBalances(0, 0, 0, 0, 10_000, 10_000) - const performTx = await bm - .connect(keeperRegistry) - .performUpkeep(validPayload, { gasLimit: 2_500_000 }) - await performTx.wait() - await assertWatchlistBalances(2, 0, 2, 0, 10_000, 10_000) - }) - - it('Should only be callable by the keeper registry contract', async () => { - let performTx = bm.connect(owner).performUpkeep(validPayload) - await expect(performTx).to.be.revertedWithCustomError( - bm, - ONLY_KEEPER_ERR, - ) - performTx = bm.connect(stranger).performUpkeep(validPayload) - await expect(performTx).to.be.revertedWithCustomError( - bm, - ONLY_KEEPER_ERR, - ) - }) - - it('Should protect against running out of gas', async () => { - await assertWatchlistBalances(0, 0, 0, 0, 10_000, 10_000) - const performTx = await bm - .connect(keeperRegistry) - .performUpkeep(validPayload, { gasLimit: 130_000 }) // too little for all 3 transfers - await performTx.wait() - const balance1 = await ethers.provider.getBalance(watchAddress1) - const balance2 = await ethers.provider.getBalance(watchAddress2) - const balance3 = await ethers.provider.getBalance(watchAddress3) - const balances = [balance1, balance2, balance3].map((n) => n.toString()) - expect(balances) - .to.include(twoEth.toString()) // expect at least 1 transfer - .to.include(zeroEth.toString()) // expect at least 1 out of funds - }) - - it('Should provide enough gas to support receive and fallback functions', async () => { - const addresses = [ - receiveEmitter.address, - receiveFallbackEmitter.address, - ] - const payload = ethers.utils.defaultAbiCoder.encode( - ['address[]'], - [addresses], - ) - const setTx = await bm - .connect(owner) - .setWatchList( - addresses, - new Array(2).fill(oneEth), - new Array(2).fill(twoEth), - ) - await setTx.wait() - - const reBalanceBefore = await ethers.provider.getBalance( - receiveEmitter.address, - ) - const rfeBalanceBefore = await ethers.provider.getBalance( - receiveFallbackEmitter.address, - ) - - const performTx = await bm - .connect(keeperRegistry) - .performUpkeep(payload, { gasLimit: 2_500_000 }) - await h.assertBalance( - receiveEmitter.address, - reBalanceBefore.add(twoEth), - ) - await h.assertBalance( - receiveFallbackEmitter.address, - rfeBalanceBefore.add(twoEth), - ) - - await expect(performTx) - .to.emit(bm, 'TopUpSucceeded') - .withArgs(receiveEmitter.address) - await expect(performTx) - .to.emit(bm, 'TopUpSucceeded') - .withArgs(receiveFallbackEmitter.address) - }) - }) - }) - - describe('topUp()', () => { - context('when not paused', () => { - it('Should be callable by anyone', async () => { - const users = [owner, keeperRegistry, stranger] - for (let idx = 0; idx < users.length; idx++) { - const user = users[idx] - await bm.connect(user).topUp([]) - } - }) - }) - context('when paused', () => { - it('Should be callable by no one', async () => { - await bm.connect(owner).pause() - const users = [owner, keeperRegistry, stranger] - for (let idx = 0; idx < users.length; idx++) { - const user = users[idx] - const tx = bm.connect(user).topUp([]) - await expect(tx).to.be.revertedWith(PAUSED_ERR) - } - }) - }) - }) -}) diff --git a/contracts/test/v0.8/automation/IAutomationRegistryMaster2_2.test.ts b/contracts/test/v0.8/automation/IAutomationRegistryMaster2_2.test.ts deleted file mode 100644 index 11da7273ab9..00000000000 --- a/contracts/test/v0.8/automation/IAutomationRegistryMaster2_2.test.ts +++ /dev/null @@ -1,117 +0,0 @@ -import fs from 'fs' -import { ethers } from 'hardhat' -import { assert } from 'chai' -import { AutomationRegistry2_2__factory as AutomationRegistryFactory } from '../../../typechain/factories/AutomationRegistry2_2__factory' -import { AutomationRegistryLogicA2_2__factory as AutomationRegistryLogicAFactory } from '../../../typechain/factories/AutomationRegistryLogicA2_2__factory' -import { AutomationRegistryLogicB2_2__factory as AutomationRegistryLogicBFactory } from '../../../typechain/factories/AutomationRegistryLogicB2_2__factory' -import { AutomationRegistryBase2_2__factory as AutomationRegistryBaseFactory } from '../../../typechain/factories/AutomationRegistryBase2_2__factory' -import { Chainable__factory as ChainableFactory } from '../../../typechain/factories/Chainable__factory' -import { IAutomationRegistryMaster__factory as IAutomationRegistryMasterFactory } from '../../../typechain/factories/IAutomationRegistryMaster__factory' -import { IAutomationRegistryConsumer__factory as IAutomationRegistryConsumerFactory } from '../../../typechain/factories/IAutomationRegistryConsumer__factory' -import { MigratableKeeperRegistryInterface__factory as MigratableKeeperRegistryInterfaceFactory } from '../../../typechain/factories/MigratableKeeperRegistryInterface__factory' -import { MigratableKeeperRegistryInterfaceV2__factory as MigratableKeeperRegistryInterfaceV2Factory } from '../../../typechain/factories/MigratableKeeperRegistryInterfaceV2__factory' -import { OCR2Abstract__factory as OCR2AbstractFactory } from '../../../typechain/factories/OCR2Abstract__factory' -import { IAutomationV21PlusCommon__factory as IAutomationV21PlusCommonFactory } from '../../../typechain/factories/IAutomationV21PlusCommon__factory' -import { - assertSatisfiesEvents, - assertSatisfiesInterface, - entryID, -} from './helpers' - -const compositeABIs = [ - AutomationRegistryFactory.abi, - AutomationRegistryLogicAFactory.abi, - AutomationRegistryLogicBFactory.abi, -] - -/** - * @dev because the keeper master interface is a composite of several different contracts, - * it is possible that an interface could be satisfied by functions across different - * contracts, and therefore not enforceable by the compiler directly. Instead, we use this - * test to assert that the master interface satisfies the constraints of an individual interface - */ -describe('IAutomationRegistryMaster2_2', () => { - it('is up to date', async () => { - const checksum = ethers.utils.id(compositeABIs.join('')) - const knownChecksum = fs - .readFileSync( - 'src/v0.8/automation/interfaces/v2_2/IAutomationRegistryMaster.sol', - ) - .toString() - .slice(17, 83) // checksum located at top of file - assert.equal( - checksum, - knownChecksum, - 'master interface is out of date - regenerate using "pnpm ts-node ./scripts/generate-automation-master-interface.ts"', - ) - }) - - it('is generated from composite contracts without competing definitions', async () => { - const sharedEntries = [ - ...ChainableFactory.abi, - ...AutomationRegistryBaseFactory.abi, - ] - const abiSet = new Set() - const sharedSet = new Set() - for (const entry of sharedEntries) { - sharedSet.add(entryID(entry)) - } - for (const abi of compositeABIs) { - for (const entry of abi) { - const id = entryID(entry) - if (!abiSet.has(id)) { - abiSet.add(id) - } else if (!sharedSet.has(id)) { - assert.fail( - `composite contracts contain duplicate entry: ${JSON.stringify( - entry, - )}`, - ) - } - } - } - }) - - it('satisfies the IAutomationRegistryConsumer interface', async () => { - assertSatisfiesInterface( - IAutomationRegistryMasterFactory.abi, - IAutomationRegistryConsumerFactory.abi, - ) - }) - - it('satisfies the MigratableKeeperRegistryInterface interface', async () => { - assertSatisfiesInterface( - IAutomationRegistryMasterFactory.abi, - MigratableKeeperRegistryInterfaceFactory.abi, - ) - }) - - it('satisfies the MigratableKeeperRegistryInterfaceV2 interface', async () => { - assertSatisfiesInterface( - IAutomationRegistryMasterFactory.abi, - MigratableKeeperRegistryInterfaceV2Factory.abi, - ) - }) - - // temporarily disable this test due to this update: https://github.com/smartcontractkit/chainlink/pull/14369/files#diff-6e79d46ea0ef204dea679ffd2a9f4dfccd090d8f405ba2d9bffad527d7b862c6L44 - it.skip('satisfies the OCR2Abstract interface', async () => { - assertSatisfiesInterface( - IAutomationRegistryMasterFactory.abi, - OCR2AbstractFactory.abi, - ) - }) - - it('satisfies the IAutomationV2Common interface', async () => { - assertSatisfiesInterface( - IAutomationRegistryMasterFactory.abi, - IAutomationV21PlusCommonFactory.abi, - ) - }) - - it('satisfies the IAutomationV2Common events', async () => { - assertSatisfiesEvents( - IAutomationRegistryMasterFactory.abi, - IAutomationV21PlusCommonFactory.abi, - ) - }) -}) diff --git a/contracts/test/v0.8/automation/KeeperCompatible.test.ts b/contracts/test/v0.8/automation/KeeperCompatible.test.ts index 13d1d0deff5..17c83790811 100644 --- a/contracts/test/v0.8/automation/KeeperCompatible.test.ts +++ b/contracts/test/v0.8/automation/KeeperCompatible.test.ts @@ -10,7 +10,7 @@ describe('KeeperCompatible', () => { before(async () => { const factory = await ethers.getContractFactory( - `src/v0.${version}/tests/KeeperCompatibleTestHelper.sol:KeeperCompatibleTestHelper`, + `src/v0.${version}/automation/testhelpers/KeeperCompatibleTestHelper.sol:KeeperCompatibleTestHelper`, ) contract = await factory.deploy() }) diff --git a/contracts/test/v0.8/automation/LinkAvailableBalanceMonitor.test.ts b/contracts/test/v0.8/automation/LinkAvailableBalanceMonitor.test.ts deleted file mode 100644 index f63de3498b1..00000000000 --- a/contracts/test/v0.8/automation/LinkAvailableBalanceMonitor.test.ts +++ /dev/null @@ -1,1077 +0,0 @@ -import { ethers } from 'hardhat' -import chai, { assert, expect } from 'chai' -import type { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -import { loadFixture } from '@nomicfoundation/hardhat-network-helpers' -import * as h from '../../test-helpers/helpers' -import { mineBlock } from '../../test-helpers/helpers' -import { IAggregatorProxy__factory as IAggregatorProxyFactory } from '../../../typechain/factories/IAggregatorProxy__factory' -import { ILinkAvailable__factory as ILinkAvailableFactory } from '../../../typechain/factories/ILinkAvailable__factory' -import { LinkAvailableBalanceMonitor, LinkToken } from '../../../typechain' -import { BigNumber } from 'ethers' -import deepEqualInAnyOrder from 'deep-equal-in-any-order' -import { - deployMockContract, - MockContract, -} from '@ethereum-waffle/mock-contract' - -chai.use(deepEqualInAnyOrder) - -//////////////////////////////// GAS USAGE LIMITS - CHANGE WITH CAUTION ////////////////////////// -// // -// we try to keep gas usage under this amount (max is 5M) // -const TARGET_PERFORM_GAS_LIMIT = 2_000_000 -// we try to keep gas usage under this amount (max is 5M) the test is not a perfectly accurate // -// measurement of gas usage because it relies on mocks which may do fewer storage reads // -// therefore, we keep a healthy margin to avoid running over the limit! // -const TARGET_CHECK_GAS_LIMIT = 3_500_000 -// // -////////////////////////////////////////////////////////////////////////////////////////////////// -const INVALID_WATCHLIST_ERR = `InvalidWatchList` -const PAUSED_ERR = 'Pausable: paused' - -const zeroLINK = ethers.utils.parseEther('0') -const oneLINK = ethers.utils.parseEther('1') -const twoLINK = ethers.utils.parseEther('2') -const fourLINK = ethers.utils.parseEther('4') -const tenLINK = ethers.utils.parseEther('10') -const oneHundredLINK = ethers.utils.parseEther('100') - -const randAddr = () => ethers.Wallet.createRandom().address - -let labm: LinkAvailableBalanceMonitor -let lt: LinkToken -let owner: SignerWithAddress -let stranger: SignerWithAddress -let keeperRegistry: SignerWithAddress -let proxy1: MockContract -let proxy2: MockContract -let proxy3: MockContract -let proxy4: MockContract // leave this proxy / aggregator unconfigured for topUp() testing -let aggregator1: MockContract -let aggregator2: MockContract -let aggregator3: MockContract -let aggregator4: MockContract // leave this proxy / aggregator unconfigured for topUp() testing - -let directTarget1: MockContract // Contracts which are direct target of balance monitoring without proxy -let directTarget2: MockContract - -let watchListAddresses: string[] -let watchListMinBalances: BigNumber[] -let watchListTopUpAmounts: BigNumber[] -let watchListDstChainSelectors: number[] - -async function assertContractLinkBalances( - balance1: BigNumber, - balance2: BigNumber, - balance3: BigNumber, - balance4: BigNumber, - balance5: BigNumber, -) { - await h.assertLinkTokenBalance(lt, aggregator1.address, balance1, 'address 1') - await h.assertLinkTokenBalance(lt, aggregator2.address, balance2, 'address 2') - await h.assertLinkTokenBalance(lt, aggregator3.address, balance3, 'address 3') - await h.assertLinkTokenBalance( - lt, - directTarget1.address, - balance4, - 'address 4', - ) - await h.assertLinkTokenBalance( - lt, - directTarget2.address, - balance5, - 'address 5', - ) -} - -const setup = async () => { - const accounts = await ethers.getSigners() - owner = accounts[0] - stranger = accounts[1] - keeperRegistry = accounts[2] - - proxy1 = await deployMockContract(owner, IAggregatorProxyFactory.abi) - proxy2 = await deployMockContract(owner, IAggregatorProxyFactory.abi) - proxy3 = await deployMockContract(owner, IAggregatorProxyFactory.abi) - proxy4 = await deployMockContract(owner, IAggregatorProxyFactory.abi) - aggregator1 = await deployMockContract(owner, ILinkAvailableFactory.abi) - aggregator2 = await deployMockContract(owner, ILinkAvailableFactory.abi) - aggregator3 = await deployMockContract(owner, ILinkAvailableFactory.abi) - aggregator4 = await deployMockContract(owner, ILinkAvailableFactory.abi) - directTarget1 = await deployMockContract(owner, ILinkAvailableFactory.abi) - directTarget2 = await deployMockContract(owner, ILinkAvailableFactory.abi) - - await proxy1.deployed() - await proxy2.deployed() - await proxy3.deployed() - await proxy4.deployed() - await aggregator1.deployed() - await aggregator2.deployed() - await aggregator3.deployed() - await aggregator4.deployed() - await directTarget1.deployed() - await directTarget2.deployed() - - watchListAddresses = [ - proxy1.address, - proxy2.address, - proxy3.address, - directTarget1.address, - directTarget2.address, - ] - watchListMinBalances = [oneLINK, oneLINK, oneLINK, twoLINK, twoLINK] - watchListTopUpAmounts = [twoLINK, twoLINK, twoLINK, twoLINK, twoLINK] - watchListDstChainSelectors = [1, 2, 3, 4, 5] - - await proxy1.mock.aggregator.returns(aggregator1.address) - await proxy2.mock.aggregator.returns(aggregator2.address) - await proxy3.mock.aggregator.returns(aggregator3.address) - - await aggregator1.mock.linkAvailableForPayment.returns(0) - await aggregator2.mock.linkAvailableForPayment.returns(0) - await aggregator3.mock.linkAvailableForPayment.returns(0) - - await directTarget1.mock.linkAvailableForPayment.returns(0) - await directTarget2.mock.linkAvailableForPayment.returns(0) - - const labmFactory = await ethers.getContractFactory( - 'LinkAvailableBalanceMonitor', - owner, - ) - const ltFactory = await ethers.getContractFactory( - 'src/v0.8/shared/test/helpers/LinkTokenTestHelper.sol:LinkTokenTestHelper', - owner, - ) - - // New parameters needed by the constructor - const maxPerform = 5 - const maxCheck = 20 - const minWaitPeriodSeconds = 0 - const upkeepInterval = 10 - - lt = (await ltFactory.deploy()) as LinkToken - labm = await labmFactory.deploy( - owner.address, - lt.address, - minWaitPeriodSeconds, - maxPerform, - maxCheck, - upkeepInterval, - ) - await labm.deployed() - - for (let i = 1; i <= 4; i++) { - const recipient = await accounts[i].getAddress() - await lt.connect(owner).transfer(recipient, oneHundredLINK) - } - - const setTx = await labm - .connect(owner) - .setWatchList( - watchListAddresses, - watchListMinBalances, - watchListTopUpAmounts, - watchListDstChainSelectors, - ) - await setTx.wait() -} - -describe('LinkAvailableBalanceMonitor', () => { - beforeEach(async () => { - await loadFixture(setup) - }) - - describe('add funds', () => { - it('should allow anyone to add funds', async () => { - await lt.transfer(labm.address, oneLINK) - await lt.connect(stranger).transfer(labm.address, oneLINK) - }) - }) - - describe('setTopUpAmount()', () => { - it('configures the top-up amount', async () => { - await labm - .connect(owner) - .setTopUpAmount(directTarget1.address, BigNumber.from(100)) - const report = await labm.getAccountInfo(directTarget1.address) - assert.equal(report.topUpAmount.toString(), '100') - }) - - it('is only callable by the owner', async () => { - await expect( - labm.connect(stranger).setTopUpAmount(directTarget1.address, 100), - ).to.be.reverted - }) - }) - - describe('setMinBalance()', () => { - it('configures the min balance', async () => { - await labm - .connect(owner) - .setMinBalance(proxy1.address, BigNumber.from(100)) - const report = await labm.getAccountInfo(proxy1.address) - assert.equal(report.minBalance.toString(), '100') - }) - - it('reverts if address is not in the watchlist', async () => { - await expect(labm.connect(owner).setMinBalance(proxy4.address, 100)).to.be - .reverted - }) - - it('is only callable by the owner', async () => { - await expect(labm.connect(stranger).setMinBalance(proxy1.address, 100)).to - .be.reverted - }) - }) - - describe('setMaxPerform()', () => { - it('configures the MaxPerform', async () => { - await labm.connect(owner).setMaxPerform(BigNumber.from(100)) - const report = await labm.getMaxPerform() - assert.equal(report.toString(), '100') - }) - - it('is only callable by the owner', async () => { - await expect(labm.connect(stranger).setMaxPerform(100)).to.be.reverted - }) - }) - - describe('setMaxCheck()', () => { - it('configures the MaxCheck', async () => { - await labm.connect(owner).setMaxCheck(BigNumber.from(100)) - const report = await labm.getMaxCheck() - assert.equal(report.toString(), '100') - }) - - it('is only callable by the owner', async () => { - await expect(labm.connect(stranger).setMaxCheck(100)).to.be.reverted - }) - }) - - describe('setUpkeepInterval()', () => { - it('configures the UpkeepInterval', async () => { - await labm.connect(owner).setUpkeepInterval(BigNumber.from(100)) - const report = await labm.getUpkeepInterval() - assert.equal(report.toString(), '100') - }) - - it('is only callable by the owner', async () => { - await expect(labm.connect(stranger).setUpkeepInterval(100)).to.be.reverted - }) - }) - - describe('withdraw()', () => { - beforeEach(async () => { - const tx = await lt.connect(owner).transfer(labm.address, oneLINK) - await tx.wait() - }) - - it('should allow the owner to withdraw', async () => { - const beforeBalance = await lt.balanceOf(owner.address) - const tx = await labm.connect(owner).withdraw(oneLINK, owner.address) - await tx.wait() - const afterBalance = await lt.balanceOf(owner.address) - assert.isTrue( - afterBalance.gt(beforeBalance), - 'balance did not increase after withdraw', - ) - }) - - it('should emit an event', async () => { - const tx = await labm.connect(owner).withdraw(oneLINK, owner.address) - await expect(tx) - .to.emit(labm, 'FundsWithdrawn') - .withArgs(oneLINK, owner.address) - }) - - it('should allow the owner to withdraw to anyone', async () => { - const beforeBalance = await lt.balanceOf(stranger.address) - const tx = await labm.connect(owner).withdraw(oneLINK, stranger.address) - await tx.wait() - const afterBalance = await lt.balanceOf(stranger.address) - assert.isTrue( - beforeBalance.add(oneLINK).eq(afterBalance), - 'balance did not increase after withdraw', - ) - }) - - it('should not allow strangers to withdraw', async () => { - const tx = labm.connect(stranger).withdraw(oneLINK, owner.address) - await expect(tx).to.be.reverted - }) - }) - - describe('pause() / unpause()', () => { - it('should allow owner to pause / unpause', async () => { - const pauseTx = await labm.connect(owner).pause() - await pauseTx.wait() - const unpauseTx = await labm.connect(owner).unpause() - await unpauseTx.wait() - }) - - it('should not allow strangers to pause / unpause', async () => { - const pauseTxStranger = labm.connect(stranger).pause() - await expect(pauseTxStranger).to.be.reverted - const pauseTxOwner = await labm.connect(owner).pause() - await pauseTxOwner.wait() - const unpauseTxStranger = labm.connect(stranger).unpause() - await expect(unpauseTxStranger).to.be.reverted - }) - }) - - describe('setWatchList() / addToWatchListOrDecommissionOrDecommission() / removeFromWatchlist() / getWatchList()', () => { - const watchAddress1 = randAddr() - const watchAddress2 = randAddr() - const watchAddress3 = randAddr() - - beforeEach(async () => { - // reset watchlist to empty before running these tests - await labm.connect(owner).setWatchList([], [], [], []) - const watchList = await labm.getWatchList() - assert.deepEqual(watchList, []) - }) - - it('should allow owner to adjust the watchlist', async () => { - // add first watchlist - await labm - .connect(owner) - .setWatchList([watchAddress1], [oneLINK], [oneLINK], [0]) - let watchList = await labm.getWatchList() - assert.deepEqual(watchList[0], watchAddress1) - // add more to watchlist - const tx = await labm - .connect(owner) - .setWatchList( - [watchAddress1, watchAddress2, watchAddress3], - [oneLINK, oneLINK, oneLINK], - [oneLINK, oneLINK, oneLINK], - [1, 2, 3], - ) - await tx.wait() - watchList = await labm.getWatchList() - assert.deepEqual(watchList, [watchAddress1, watchAddress2, watchAddress3]) - }) - - it('should not allow different length arrays in the watchlist', async () => { - const tx = labm - .connect(owner) - .setWatchList( - [watchAddress1, watchAddress2, watchAddress1], - [oneLINK, oneLINK], - [oneLINK, oneLINK], - [1, 2], - ) - await expect(tx).to.be.revertedWithCustomError( - labm, - INVALID_WATCHLIST_ERR, - ) - }) - - it('should not allow duplicates in the watchlist', async () => { - const tx = labm - .connect(owner) - .setWatchList( - [watchAddress1, watchAddress2, watchAddress1], - [oneLINK, oneLINK, oneLINK], - [oneLINK, oneLINK, oneLINK], - [1, 2, 3], - ) - await expect(tx) - .to.be.revertedWithCustomError(labm, 'DuplicateAddress') - .withArgs(watchAddress1) - }) - - it('should not allow strangers to set the watchlist', async () => { - const setTxStranger = labm - .connect(stranger) - .setWatchList([watchAddress1], [oneLINK], [oneLINK], [0]) - await expect(setTxStranger).to.be.reverted - }) - - it('should revert if any of the addresses are empty', async () => { - const tx = labm - .connect(owner) - .setWatchList( - [watchAddress1, ethers.constants.AddressZero], - [oneLINK, oneLINK], - [oneLINK, oneLINK], - [1, 2], - ) - await expect(tx).to.be.revertedWithCustomError( - labm, - INVALID_WATCHLIST_ERR, - ) - }) - - it('should allow owner to add multiple addresses with dstChainSelector 0 to the watchlist', async () => { - let tx = await labm - .connect(owner) - .addToWatchListOrDecommission(watchAddress1, 0) - await tx.wait - let watchList = await labm.getWatchList() - assert.deepEqual(watchList[0], watchAddress1) - - tx = await labm - .connect(owner) - .addToWatchListOrDecommission(watchAddress2, 0) - await tx.wait - watchList = await labm.getWatchList() - assert.deepEqual(watchList[0], watchAddress1) - assert.deepEqual(watchList[1], watchAddress2) - - tx = await labm - .connect(owner) - .addToWatchListOrDecommission(watchAddress3, 0) - await tx.wait - watchList = await labm.getWatchList() - assert.deepEqual(watchList[0], watchAddress1) - assert.deepEqual(watchList[1], watchAddress2) - assert.deepEqual(watchList[2], watchAddress3) - }) - - it('should allow owner to add only one address with an unique non-zero dstChainSelector 0 to the watchlist', async () => { - let tx = await labm - .connect(owner) - .addToWatchListOrDecommission(watchAddress1, 1) - await tx.wait - let watchList = await labm.getWatchList() - assert.deepEqual(watchList[0], watchAddress1) - - // 1 is active - let report = await labm.getAccountInfo(watchAddress1) - assert.isTrue(report.isActive) - - tx = await labm - .connect(owner) - .addToWatchListOrDecommission(watchAddress2, 1) - await tx.wait - watchList = await labm.getWatchList() - assert.deepEqual(watchList[0], watchAddress2) - - // 2 is active, 1 should be false - report = await labm.getAccountInfo(watchAddress2) - assert.isTrue(report.isActive) - report = await labm.getAccountInfo(watchAddress1) - assert.isFalse(report.isActive) - - tx = await labm - .connect(owner) - .addToWatchListOrDecommission(watchAddress3, 1) - await tx.wait - watchList = await labm.getWatchList() - assert.deepEqual(watchList[0], watchAddress3) - - // 3 is active, 1 and 2 should be false - report = await labm.getAccountInfo(watchAddress3) - assert.isTrue(report.isActive) - report = await labm.getAccountInfo(watchAddress2) - assert.isFalse(report.isActive) - report = await labm.getAccountInfo(watchAddress1) - assert.isFalse(report.isActive) - }) - - it('should not add address 0 to the watchlist', async () => { - await labm - .connect(owner) - .addToWatchListOrDecommission(ethers.constants.AddressZero, 1) - expect(await labm.getWatchList()).to.not.contain( - ethers.constants.AddressZero, - ) - }) - - it('should not allow stangers to add addresses to the watchlist', async () => { - await expect( - labm.connect(stranger).addToWatchListOrDecommission(watchAddress1, 1), - ).to.be.reverted - }) - - it('should allow owner to remove addresses from the watchlist', async () => { - const tx = await labm - .connect(owner) - .addToWatchListOrDecommission(watchAddress1, 1) - await tx.wait - let watchList = await labm.getWatchList() - assert.deepEqual(watchList[0], watchAddress1) - let report = await labm.getAccountInfo(watchAddress1) - assert.isTrue(report.isActive) - - // remove address - await labm.connect(owner).removeFromWatchList(watchAddress1) - - // address should be false - report = await labm.getAccountInfo(watchAddress1) - assert.isFalse(report.isActive) - - watchList = await labm.getWatchList() - assert.deepEqual(watchList, []) - }) - - it('should allow only one address per dstChainSelector', async () => { - // add address1 - await labm.connect(owner).addToWatchListOrDecommission(watchAddress1, 1) - expect(await labm.getWatchList()).to.contain(watchAddress1) - - // add address2 - await labm.connect(owner).addToWatchListOrDecommission(watchAddress2, 1) - - // only address2 has to be in the watchlist - const watchlist = await labm.getWatchList() - expect(watchlist).to.not.contain(watchAddress1) - expect(watchlist).to.contain(watchAddress2) - }) - - it('should delete the onRamp address on a zero-address with same dstChainSelector', async () => { - // add address1 - await labm.connect(owner).addToWatchListOrDecommission(watchAddress1, 1) - expect(await labm.getWatchList()).to.contain(watchAddress1) - - // simulates an onRampSet(zeroAddress, same dstChainSelector) - await labm - .connect(owner) - .addToWatchListOrDecommission(ethers.constants.AddressZero, 1) - - // address1 should be cleaned - const watchlist = await labm.getWatchList() - expect(watchlist).to.not.contain(watchAddress1) - assert.deepEqual(watchlist, []) - }) - }) - - describe('checkUpkeep() / sampleUnderfundedAddresses() [ @skip-coverage ]', () => { - it('should return list of address that are underfunded', async () => { - const fundTx = await lt - .connect(owner) - .transfer(labm.address, oneHundredLINK) - await fundTx.wait() - - await labm.setWatchList( - watchListAddresses, - watchListMinBalances, - watchListTopUpAmounts, - watchListDstChainSelectors, - ) - - const [should, payload] = await labm.checkUpkeep('0x') - assert.isTrue(should) - let [addresses] = ethers.utils.defaultAbiCoder.decode( - ['address[]'], - payload, - ) - - expect(addresses).to.deep.equalInAnyOrder(watchListAddresses) - addresses = await labm.sampleUnderfundedAddresses() - expect(addresses).to.deep.equalInAnyOrder(watchListAddresses) - }) - - it('should return false because the monitor is underfunded', async () => { - // it needs 10 LINKs to fund all 5 upkeeps, but it only has 8 LINKs - const fundTx = await lt - .connect(owner) - .transfer(labm.address, fourLINK.add(fourLINK)) - await fundTx.wait() - - await labm.setWatchList( - watchListAddresses, - watchListMinBalances, - watchListTopUpAmounts, - watchListDstChainSelectors, - ) - - const [should, _] = await labm.checkUpkeep('0x') - assert.isFalse(should) - }) - - it('should omit aggregators that have sufficient funding', async () => { - const fundTx = await lt.connect(owner).transfer( - labm.address, - oneHundredLINK, // enough for anything that needs funding - ) - await fundTx.wait() - - await labm.setWatchList( - [aggregator2.address, directTarget1.address, directTarget2.address], - [oneLINK, twoLINK, twoLINK], - [oneLINK, oneLINK, oneLINK], - [1, 2, 3], - ) - - // all of them are underfunded, return 3 - await aggregator2.mock.linkAvailableForPayment.returns(zeroLINK) - await directTarget1.mock.linkAvailableForPayment.returns(zeroLINK) - await directTarget2.mock.linkAvailableForPayment.returns(zeroLINK) - - let addresses = await labm.sampleUnderfundedAddresses() - expect(addresses).to.deep.equalInAnyOrder([ - aggregator2.address, - directTarget1.address, - directTarget2.address, - ]) - - await aggregator2.mock.linkAvailableForPayment.returns(oneLINK) // aggregator2 is enough funded - await directTarget1.mock.linkAvailableForPayment.returns(oneLINK) // directTarget1 is NOT enough funded - await directTarget2.mock.linkAvailableForPayment.returns(oneLINK) // directTarget2 is NOT funded - addresses = await labm.sampleUnderfundedAddresses() - expect(addresses).to.deep.equalInAnyOrder([ - directTarget1.address, - directTarget2.address, - ]) - - await directTarget1.mock.linkAvailableForPayment.returns(tenLINK) - addresses = await labm.sampleUnderfundedAddresses() - expect(addresses).to.deep.equalInAnyOrder([directTarget2.address]) - - await directTarget2.mock.linkAvailableForPayment.returns(tenLINK) - addresses = await labm.sampleUnderfundedAddresses() - expect(addresses).to.deep.equalInAnyOrder([]) - }) - - it('should revert when paused', async () => { - const tx = await labm.connect(owner).pause() - await tx.wait() - const ethCall = labm.checkUpkeep('0x') - await expect(ethCall).to.be.revertedWith(PAUSED_ERR) - }) - - context('with a large set of proxies', async () => { - // in this test, we cheat a little bit and point each proxy to the same aggregator, - // which helps cut down on test time - let MAX_PERFORM: number - let MAX_CHECK: number - let proxyAddresses: string[] - let minBalances: BigNumber[] - let topUpAmount: BigNumber[] - let aggregators: MockContract[] - let dstChainSelectors: number[] - - beforeEach(async () => { - MAX_PERFORM = await labm.getMaxPerform() - MAX_CHECK = await labm.getMaxCheck() - proxyAddresses = [] - minBalances = [] - topUpAmount = [] - aggregators = [] - dstChainSelectors = [] - const numAggregators = MAX_CHECK + 50 - for (let idx = 0; idx < numAggregators; idx++) { - const proxy = await deployMockContract( - owner, - IAggregatorProxyFactory.abi, - ) - const aggregator = await deployMockContract( - owner, - ILinkAvailableFactory.abi, - ) - await proxy.mock.aggregator.returns(aggregator.address) - await aggregator.mock.linkAvailableForPayment.returns(0) - proxyAddresses.push(proxy.address) - minBalances.push(oneLINK) - topUpAmount.push(oneLINK) - aggregators.push(aggregator) - dstChainSelectors.push(0) - } - await labm.setWatchList( - proxyAddresses, - minBalances, - topUpAmount, - dstChainSelectors, - ) - const watchlist = await labm.getWatchList() - expect(watchlist).to.deep.equalInAnyOrder(proxyAddresses) - assert.equal(watchlist.length, minBalances.length) - }) - - it('should not include more than MAX_PERFORM addresses', async () => { - const addresses = await labm.sampleUnderfundedAddresses() - expect(addresses.length).to.be.lessThanOrEqual(MAX_PERFORM) - }) - - it('should sample from the list of addresses pseudorandomly', async () => { - const firstAddress: string[] = [] - for (let idx = 0; idx < 10; idx++) { - const addresses = await labm.sampleUnderfundedAddresses() - assert.equal(addresses.length, MAX_PERFORM) - assert.equal( - new Set(addresses).size, - MAX_PERFORM, - 'duplicate address found', - ) - firstAddress.push(addresses[0]) - await mineBlock(ethers.provider) - } - assert( - new Set(firstAddress).size > 1, - 'sample did not shuffle starting index', - ) - }) - - it('can check MAX_CHECK upkeeps within the allotted gas limit', async () => { - for (const aggregator of aggregators) { - // here we make no aggregators eligible for funding, requiring the function to - // traverse the whole list - await aggregator.mock.linkAvailableForPayment.returns(tenLINK) - } - await labm.checkUpkeep('0x', { gasLimit: TARGET_CHECK_GAS_LIMIT }) - }) - }) - }) - - describe('performUpkeep()', () => { - let validPayload: string - - beforeEach(async () => { - validPayload = ethers.utils.defaultAbiCoder.encode( - ['address[]'], - [watchListAddresses], - ) - await labm - .connect(owner) - .setWatchList( - watchListAddresses, - watchListMinBalances, - watchListTopUpAmounts, - watchListDstChainSelectors, - ) - }) - - it('should revert when paused', async () => { - await labm.connect(owner).pause() - const performTx = labm.connect(keeperRegistry).performUpkeep(validPayload) - await expect(performTx).to.be.revertedWith(PAUSED_ERR) - }) - - it('should fund the appropriate addresses', async () => { - await aggregator1.mock.linkAvailableForPayment.returns(zeroLINK) - await aggregator2.mock.linkAvailableForPayment.returns(zeroLINK) - await aggregator3.mock.linkAvailableForPayment.returns(zeroLINK) - await directTarget1.mock.linkAvailableForPayment.returns(zeroLINK) - await directTarget2.mock.linkAvailableForPayment.returns(zeroLINK) - - const fundTx = await lt.connect(owner).transfer(labm.address, tenLINK) - await fundTx.wait() - - await h.assertLinkTokenBalance(lt, aggregator1.address, zeroLINK) - await h.assertLinkTokenBalance(lt, aggregator2.address, zeroLINK) - await h.assertLinkTokenBalance(lt, aggregator3.address, zeroLINK) - await h.assertLinkTokenBalance(lt, directTarget1.address, zeroLINK) - await h.assertLinkTokenBalance(lt, directTarget2.address, zeroLINK) - - const performTx = await labm - .connect(keeperRegistry) - .performUpkeep(validPayload, { gasLimit: 1_500_000 }) - await performTx.wait() - - await h.assertLinkTokenBalance(lt, aggregator1.address, twoLINK) - await h.assertLinkTokenBalance(lt, aggregator2.address, twoLINK) - await h.assertLinkTokenBalance(lt, aggregator3.address, twoLINK) - await h.assertLinkTokenBalance(lt, directTarget1.address, twoLINK) - await h.assertLinkTokenBalance(lt, directTarget2.address, twoLINK) - }) - - it('can handle MAX_PERFORM proxies within gas limit', async () => { - const MAX_PERFORM = await labm.getMaxPerform() - const proxyAddresses = [] - const minBalances = [] - const topUpAmount = [] - const dstChainSelectors = [] - for (let idx = 0; idx < MAX_PERFORM; idx++) { - const proxy = await deployMockContract( - owner, - IAggregatorProxyFactory.abi, - ) - const aggregator = await deployMockContract( - owner, - ILinkAvailableFactory.abi, - ) - await proxy.mock.aggregator.returns(aggregator.address) - await aggregator.mock.linkAvailableForPayment.returns(0) - proxyAddresses.push(proxy.address) - minBalances.push(oneLINK) - topUpAmount.push(oneLINK) - dstChainSelectors.push(0) - } - await labm.setWatchList( - proxyAddresses, - minBalances, - topUpAmount, - dstChainSelectors, - ) - const watchlist = await labm.getWatchList() - expect(watchlist).to.deep.equalInAnyOrder(proxyAddresses) - assert.equal(watchlist.length, minBalances.length) - - // add funds - const wl = await labm.getWatchList() - const fundsNeeded = BigNumber.from(0) - for (let idx = 0; idx < wl.length; idx++) { - const targetInfo = await labm.getAccountInfo(wl[idx]) - const targetTopUpAmount = targetInfo.topUpAmount - fundsNeeded.add(targetTopUpAmount) - } - await lt.connect(owner).transfer(labm.address, fundsNeeded) - - // encode payload - const payload = ethers.utils.defaultAbiCoder.encode( - ['address[]'], - [proxyAddresses], - ) - - // do the thing - await labm - .connect(keeperRegistry) - .performUpkeep(payload, { gasLimit: TARGET_PERFORM_GAS_LIMIT }) - }) - }) - - describe('topUp()', () => { - it('should revert topUp address(0)', async () => { - const tx = await labm.connect(owner).topUp([ethers.constants.AddressZero]) - await expect(tx).to.emit(labm, 'TopUpBlocked') - }) - - context('when not paused', () => { - it('should be callable by anyone', async () => { - const users = [owner, keeperRegistry, stranger] - for (let idx = 0; idx < users.length; idx++) { - const user = users[idx] - await labm.connect(user).topUp([]) - } - }) - }) - - context('when paused', () => { - it('should be callable by no one', async () => { - await labm.connect(owner).pause() - const users = [owner, keeperRegistry, stranger] - for (let idx = 0; idx < users.length; idx++) { - const user = users[idx] - const tx = labm.connect(user).topUp([]) - await expect(tx).to.be.revertedWith(PAUSED_ERR) - } - }) - }) - - context('when fully funded', () => { - beforeEach(async () => { - await lt.connect(owner).transfer(labm.address, tenLINK) - await assertContractLinkBalances( - zeroLINK, - zeroLINK, - zeroLINK, - zeroLINK, - zeroLINK, - ) - }) - - it('should fund the appropriate addresses', async () => { - const ai1 = await labm.getAccountInfo(proxy1.address) - assert.equal(0, ai1.lastTopUpTimestamp.toNumber()) - const ai4 = await labm.getAccountInfo(directTarget1.address) - assert.equal(0, ai4.lastTopUpTimestamp.toNumber()) - - const tx = await labm.connect(keeperRegistry).topUp(watchListAddresses) - - await aggregator1.mock.linkAvailableForPayment.returns(twoLINK) - await aggregator2.mock.linkAvailableForPayment.returns(twoLINK) - await aggregator3.mock.linkAvailableForPayment.returns(twoLINK) - await directTarget1.mock.linkAvailableForPayment.returns(twoLINK) - await directTarget2.mock.linkAvailableForPayment.returns(twoLINK) - - await expect(tx) - .to.emit(labm, 'TopUpSucceeded') - .withArgs(aggregator1.address, twoLINK) - assert.equal( - (await lt.balanceOf(aggregator1.address)).toBigInt(), - twoLINK.toBigInt(), - ) - const targetInfo1 = await labm.getAccountInfo(proxy1.address) - assert.notEqual(0, targetInfo1.lastTopUpTimestamp.toNumber()) - await expect(tx) - .to.emit(labm, 'TopUpSucceeded') - .withArgs(aggregator2.address, twoLINK) - await expect(tx) - .to.emit(labm, 'TopUpSucceeded') - .withArgs(aggregator3.address, twoLINK) - await expect(tx) - .to.emit(labm, 'TopUpSucceeded') - .withArgs(directTarget1.address, twoLINK) - assert.equal( - (await lt.balanceOf(directTarget1.address)).toBigInt(), - twoLINK.toBigInt(), - ) - const targetInfo4 = await labm.getAccountInfo(directTarget1.address) - assert.notEqual(0, targetInfo4.lastTopUpTimestamp.toNumber()) - await expect(tx) - .to.emit(labm, 'TopUpSucceeded') - .withArgs(directTarget2.address, twoLINK) - }) - - it('should only fund the addresses provided', async () => { - await labm - .connect(keeperRegistry) - .topUp([proxy1.address, directTarget1.address]) - - await aggregator1.mock.linkAvailableForPayment.returns(twoLINK) - await aggregator2.mock.linkAvailableForPayment.returns(zeroLINK) - await aggregator3.mock.linkAvailableForPayment.returns(zeroLINK) - await directTarget1.mock.linkAvailableForPayment.returns(twoLINK) - await directTarget2.mock.linkAvailableForPayment.returns(zeroLINK) - }) - - it('should skip un-approved addresses', async () => { - await labm - .connect(owner) - .setWatchList( - [proxy1.address, directTarget1.address], - [oneLINK, oneLINK], - [oneLINK, oneLINK], - [1, 2], - ) - const tx = await labm - .connect(keeperRegistry) - .topUp([ - proxy1.address, - proxy2.address, - proxy3.address, - directTarget1.address, - directTarget2.address, - ]) - - await h.assertLinkTokenBalance(lt, aggregator1.address, oneLINK) - await h.assertLinkTokenBalance(lt, aggregator2.address, zeroLINK) - await h.assertLinkTokenBalance(lt, aggregator3.address, zeroLINK) - await h.assertLinkTokenBalance(lt, directTarget1.address, oneLINK) - await h.assertLinkTokenBalance(lt, directTarget2.address, zeroLINK) - - await expect(tx) - .to.emit(labm, 'TopUpSucceeded') - .withArgs(aggregator1.address, oneLINK) - const targetInfo1 = await labm.getAccountInfo(proxy1.address) - assert.notEqual(0, targetInfo1.lastTopUpTimestamp.toNumber()) - - await expect(tx) - .to.emit(labm, 'TopUpSucceeded') - .withArgs(directTarget1.address, oneLINK) - await expect(tx).to.emit(labm, 'TopUpBlocked').withArgs(proxy2.address) - await expect(tx).to.emit(labm, 'TopUpBlocked').withArgs(proxy3.address) - await expect(tx) - .to.emit(labm, 'TopUpBlocked') - .withArgs(directTarget2.address) - const targetInfo5 = await labm.getAccountInfo(directTarget2.address) - assert.equal(0, targetInfo5.lastTopUpTimestamp.toNumber()) - }) - - it('should skip an address if the proxy is invalid and it is not a direct target', async () => { - await labm - .connect(owner) - .setWatchList( - [proxy1.address, proxy4.address], - [oneLINK, oneLINK], - [oneLINK, oneLINK], - [1, 2], - ) - const tx = await labm - .connect(keeperRegistry) - .topUp([proxy1.address, proxy4.address]) - await expect(tx) - .to.emit(labm, 'TopUpSucceeded') - .withArgs(aggregator1.address, oneLINK) - await expect(tx).to.emit(labm, 'TopUpBlocked').withArgs(proxy4.address) - }) - - it('should skip an address if the aggregator is invalid', async () => { - await proxy4.mock.aggregator.returns(aggregator4.address) - await labm - .connect(owner) - .setWatchList( - [proxy1.address, proxy4.address], - [oneLINK, oneLINK], - [oneLINK, oneLINK], - [1, 2], - ) - const tx = await labm - .connect(keeperRegistry) - .topUp([proxy1.address, proxy4.address]) - await expect(tx) - .to.emit(labm, 'TopUpSucceeded') - .withArgs(aggregator1.address, oneLINK) - await expect(tx).to.emit(labm, 'TopUpBlocked').withArgs(proxy4.address) - }) - - it('should skip an address if the aggregator has sufficient funding', async () => { - await proxy4.mock.aggregator.returns(aggregator4.address) - await aggregator4.mock.linkAvailableForPayment.returns(tenLINK) - await labm - .connect(owner) - .setWatchList( - [proxy1.address, proxy4.address], - [oneLINK, oneLINK], - [oneLINK, oneLINK], - [1, 2], - ) - const tx = await labm - .connect(keeperRegistry) - .topUp([proxy1.address, proxy4.address]) - await expect(tx) - .to.emit(labm, 'TopUpSucceeded') - .withArgs(aggregator1.address, oneLINK) - await expect(tx).to.emit(labm, 'TopUpBlocked').withArgs(proxy4.address) - }) - - it('should skip an address if the direct target has sufficient funding', async () => { - await directTarget1.mock.linkAvailableForPayment.returns(tenLINK) - await labm - .connect(owner) - .setWatchList( - [proxy1.address, directTarget1.address], - [oneLINK, oneLINK], - [oneLINK, oneLINK], - [1, 2], - ) - const tx = await labm - .connect(keeperRegistry) - .topUp([proxy1.address, directTarget1.address]) - await expect(tx) - .to.emit(labm, 'TopUpSucceeded') - .withArgs(aggregator1.address, oneLINK) - assert.equal( - (await lt.balanceOf(aggregator1.address)).toBigInt(), - oneLINK.toBigInt(), - ) - await expect(tx) - .to.emit(labm, 'TopUpBlocked') - .withArgs(directTarget1.address) - }) - }) - - context('when partially funded', () => { - it('should fund as many addresses as possible', async () => { - await lt.connect(owner).transfer( - labm.address, - fourLINK, // only enough LINK to fund 2 addresses - ) - - await aggregator1.mock.linkAvailableForPayment.returns(twoLINK) - await aggregator2.mock.linkAvailableForPayment.returns(twoLINK) - await aggregator3.mock.linkAvailableForPayment.returns(zeroLINK) - await directTarget1.mock.linkAvailableForPayment.returns(zeroLINK) - await directTarget2.mock.linkAvailableForPayment.returns(zeroLINK) - - const tx = await labm.connect(keeperRegistry).topUp(watchListAddresses) - await expect(tx) - .to.emit(labm, 'TopUpSucceeded') - .withArgs(aggregator3.address, twoLINK) - await expect(tx) - .to.emit(labm, 'TopUpSucceeded') - .withArgs(directTarget1.address, twoLINK) - assert.equal( - (await lt.balanceOf(aggregator3.address)).toBigInt(), - twoLINK.toBigInt(), - ) - assert.equal( - (await lt.balanceOf(directTarget1.address)).toBigInt(), - twoLINK.toBigInt(), - ) - }) - }) - }) -}) diff --git a/contracts/test/v0.8/automation/UpkeepBalanceMonitor.test.ts b/contracts/test/v0.8/automation/UpkeepBalanceMonitor.test.ts deleted file mode 100644 index 0ee244130ab..00000000000 --- a/contracts/test/v0.8/automation/UpkeepBalanceMonitor.test.ts +++ /dev/null @@ -1,402 +0,0 @@ -import { ethers } from 'hardhat' -import { expect } from 'chai' -import type { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -import { randomAddress } from '../../test-helpers/helpers' -import { loadFixture } from '@nomicfoundation/hardhat-network-helpers' -import { IKeeperRegistryMaster__factory as RegistryFactory } from '../../../typechain/factories/IKeeperRegistryMaster__factory' -import { IAutomationForwarder__factory as ForwarderFactory } from '../../../typechain/factories/IAutomationForwarder__factory' -import { UpkeepBalanceMonitor } from '../../../typechain/UpkeepBalanceMonitor' -import { LinkToken } from '../../../typechain/LinkToken' -import { BigNumber } from 'ethers' -import { - deployMockContract, - MockContract, -} from '@ethereum-waffle/mock-contract' - -let owner: SignerWithAddress -let stranger: SignerWithAddress -let registry: MockContract -let registry2: MockContract -let forwarder: MockContract -let linkToken: LinkToken -let upkeepBalanceMonitor: UpkeepBalanceMonitor - -const setup = async () => { - const accounts = await ethers.getSigners() - owner = accounts[0] - stranger = accounts[1] - - const ltFactory = await ethers.getContractFactory( - 'src/v0.8/shared/test/helpers/LinkTokenTestHelper.sol:LinkTokenTestHelper', - owner, - ) - linkToken = (await ltFactory.deploy()) as LinkToken - const bmFactory = await ethers.getContractFactory( - 'UpkeepBalanceMonitor', - owner, - ) - upkeepBalanceMonitor = await bmFactory.deploy(linkToken.address, { - maxBatchSize: 10, - minPercentage: 120, - targetPercentage: 300, - maxTopUpAmount: ethers.utils.parseEther('100'), - }) - registry = await deployMockContract(owner, RegistryFactory.abi) - registry2 = await deployMockContract(owner, RegistryFactory.abi) - forwarder = await deployMockContract(owner, ForwarderFactory.abi) - await forwarder.mock.getRegistry.returns(registry.address) - await upkeepBalanceMonitor.setForwarder(forwarder.address) - await linkToken - .connect(owner) - .transfer(upkeepBalanceMonitor.address, ethers.utils.parseEther('10000')) - await upkeepBalanceMonitor - .connect(owner) - .setWatchList(registry.address, [0, 1, 2, 3, 4, 5, 6, 7, 8]) - await upkeepBalanceMonitor - .connect(owner) - .setWatchList(registry2.address, [9, 10, 11]) - for (let i = 0; i < 9; i++) { - await registry.mock.getMinBalance.withArgs(i).returns(100) - await registry.mock.getBalance.withArgs(i).returns(121) // all upkeeps are sufficiently funded - } - for (let i = 9; i < 12; i++) { - await registry2.mock.getMinBalance.withArgs(i).returns(100) - await registry2.mock.getBalance.withArgs(i).returns(121) // all upkeeps are sufficiently funded - } -} - -describe('UpkeepBalanceMonitor', () => { - beforeEach(async () => { - await loadFixture(setup) - }) - - describe('constructor()', () => { - it('should set the initial values correctly', async () => { - const config = await upkeepBalanceMonitor.getConfig() - expect(config.maxBatchSize).to.equal(10) - expect(config.minPercentage).to.equal(120) - expect(config.targetPercentage).to.equal(300) - expect(config.maxTopUpAmount).to.equal(ethers.utils.parseEther('100')) - }) - }) - - describe('setConfig()', () => { - const newConfig = { - maxBatchSize: 100, - minPercentage: 150, - targetPercentage: 500, - maxTopUpAmount: 1, - } - - it('should set config correctly', async () => { - await upkeepBalanceMonitor.connect(owner).setConfig(newConfig) - const config = await upkeepBalanceMonitor.getConfig() - expect(config.maxBatchSize).to.equal(newConfig.maxBatchSize) - expect(config.minPercentage).to.equal(newConfig.minPercentage) - expect(config.targetPercentage).to.equal(newConfig.targetPercentage) - expect(config.maxTopUpAmount).to.equal(newConfig.maxTopUpAmount) - }) - - it('cannot be called by a non-owner', async () => { - await expect( - upkeepBalanceMonitor.connect(stranger).setConfig(newConfig), - ).to.be.revertedWith('Only callable by owner') - }) - - it('should emit an event', async () => { - await expect( - upkeepBalanceMonitor.connect(owner).setConfig(newConfig), - ).to.emit(upkeepBalanceMonitor, 'ConfigSet') - }) - }) - - describe('setForwarder()', () => { - const newForwarder = randomAddress() - - it('should set the forwarder correctly', async () => { - await upkeepBalanceMonitor.connect(owner).setForwarder(newForwarder) - const forwarderAddress = await upkeepBalanceMonitor.getForwarder() - expect(forwarderAddress).to.equal(newForwarder) - }) - - it('cannot be called by a non-owner', async () => { - await expect( - upkeepBalanceMonitor.connect(stranger).setForwarder(randomAddress()), - ).to.be.revertedWith('Only callable by owner') - }) - - it('should emit an event', async () => { - await expect( - upkeepBalanceMonitor.connect(owner).setForwarder(newForwarder), - ) - .to.emit(upkeepBalanceMonitor, 'ForwarderSet') - .withArgs(newForwarder) - }) - }) - - describe('setWatchList()', () => { - const newWatchList = [ - BigNumber.from(1), - BigNumber.from(2), - BigNumber.from(10), - ] - - it('should add addresses to the watchlist', async () => { - await upkeepBalanceMonitor - .connect(owner) - .setWatchList(registry.address, newWatchList) - const [_, upkeepIDs] = await upkeepBalanceMonitor.getWatchList() - expect(upkeepIDs[0]).to.deep.equal(newWatchList) - }) - - it('cannot be called by a non-owner', async () => { - await expect( - upkeepBalanceMonitor - .connect(stranger) - .setWatchList(registry.address, [1, 2, 3]), - ).to.be.revertedWith('Only callable by owner') - }) - - it('should emit an event', async () => { - await expect( - upkeepBalanceMonitor - .connect(owner) - .setWatchList(registry.address, newWatchList), - ) - .to.emit(upkeepBalanceMonitor, 'WatchListSet') - .withArgs(registry.address) - }) - }) - - describe('withdraw()', () => { - const payee = randomAddress() - const withdrawAmount = 100 - - it('should withdraw funds to a payee', async () => { - const initialBalance = await linkToken.balanceOf( - upkeepBalanceMonitor.address, - ) - await upkeepBalanceMonitor.connect(owner).withdraw(withdrawAmount, payee) - const finalBalance = await linkToken.balanceOf( - upkeepBalanceMonitor.address, - ) - const payeeBalance = await linkToken.balanceOf(payee) - expect(finalBalance).to.equal(initialBalance.sub(withdrawAmount)) - expect(payeeBalance).to.equal(withdrawAmount) - }) - - it('cannot be called by a non-owner', async () => { - await expect( - upkeepBalanceMonitor.connect(stranger).withdraw(withdrawAmount, payee), - ).to.be.revertedWith('Only callable by owner') - }) - - it('should emit an event', async () => { - await expect( - upkeepBalanceMonitor.connect(owner).withdraw(withdrawAmount, payee), - ) - .to.emit(upkeepBalanceMonitor, 'FundsWithdrawn') - .withArgs(100, payee) - }) - }) - - describe('pause() and unpause()', () => { - it('should pause and unpause the contract', async () => { - await upkeepBalanceMonitor.connect(owner).pause() - expect(await upkeepBalanceMonitor.paused()).to.be.true - await upkeepBalanceMonitor.connect(owner).unpause() - expect(await upkeepBalanceMonitor.paused()).to.be.false - }) - - it('cannot be called by a non-owner', async () => { - await expect( - upkeepBalanceMonitor.connect(stranger).pause(), - ).to.be.revertedWith('Only callable by owner') - await upkeepBalanceMonitor.connect(owner).pause() - await expect( - upkeepBalanceMonitor.connect(stranger).unpause(), - ).to.be.revertedWith('Only callable by owner') - }) - }) - - describe('checkUpkeep() / getUnderfundedUpkeeps()', () => { - it('should find the underfunded upkeeps', async () => { - let [upkeepIDs, registries, topUpAmounts] = - await upkeepBalanceMonitor.getUnderfundedUpkeeps() - expect(upkeepIDs.length).to.equal(0) - expect(registries.length).to.equal(0) - expect(topUpAmounts.length).to.equal(0) - let [upkeepNeeded, performData] = - await upkeepBalanceMonitor.checkUpkeep('0x') - expect(upkeepNeeded).to.be.false - expect(performData).to.equal('0x') - // update the balance for some upkeeps - await registry.mock.getBalance.withArgs(2).returns(120) - await registry.mock.getBalance.withArgs(4).returns(15) - await registry.mock.getBalance.withArgs(5).returns(0) - ;[upkeepIDs, registries, topUpAmounts] = - await upkeepBalanceMonitor.getUnderfundedUpkeeps() - expect(upkeepIDs.map((v) => v.toNumber())).to.deep.equal([2, 4, 5]) - expect(registries).to.deep.equal([ - registry.address, - registry.address, - registry.address, - ]) - expect(topUpAmounts.map((v) => v.toNumber())).to.deep.equal([ - 180, 285, 300, - ]) - ;[upkeepNeeded, performData] = - await upkeepBalanceMonitor.checkUpkeep('0x') - expect(upkeepNeeded).to.be.true - expect(performData).to.equal( - ethers.utils.defaultAbiCoder.encode( - ['uint256[]', 'address[]', 'uint256[]'], - [ - [2, 4, 5], - [registry.address, registry.address, registry.address], - [180, 285, 300], - ], - ), - ) - // update all to need funding - for (let i = 0; i < 9; i++) { - await registry.mock.getBalance.withArgs(i).returns(0) - } - for (let i = 9; i < 12; i++) { - await registry2.mock.getBalance.withArgs(i).returns(0) - } - // only the max batch size are included in the list - ;[upkeepIDs, registries, topUpAmounts] = - await upkeepBalanceMonitor.getUnderfundedUpkeeps() - expect(upkeepIDs.length).to.equal(10) - expect(topUpAmounts.length).to.equal(10) - expect(upkeepIDs.map((v) => v.toNumber())).to.deep.equal([ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, - ]) - expect(registries).to.deep.equal([ - ...Array(9).fill(registry.address), - registry2.address, - ]) - expect(topUpAmounts.map((v) => v.toNumber())).to.deep.equal([ - ...Array(10).fill(300), - ]) - // update the balance for some upkeeps - await registry.mock.getBalance.withArgs(0).returns(300) - await registry.mock.getBalance.withArgs(5).returns(300) - ;[upkeepIDs, registries, topUpAmounts] = - await upkeepBalanceMonitor.getUnderfundedUpkeeps() - expect(upkeepIDs.length).to.equal(10) - expect(topUpAmounts.length).to.equal(10) - expect(upkeepIDs.map((v) => v.toNumber())).to.deep.equal([ - 1, 2, 3, 4, 6, 7, 8, 9, 10, 11, - ]) - expect(registries).to.deep.equal([ - ...Array(7).fill(registry.address), - ...Array(3).fill(registry2.address), - ]) - expect(topUpAmounts.map((v) => v.toNumber())).to.deep.equal([ - ...Array(10).fill(300), - ]) - }) - }) - - describe('topUp()', () => { - beforeEach(async () => { - await registry.mock.onTokenTransfer - .withArgs( - upkeepBalanceMonitor.address, - 100, - ethers.utils.defaultAbiCoder.encode(['uint256'], [1]), - ) - .returns() - await registry.mock.onTokenTransfer - .withArgs( - upkeepBalanceMonitor.address, - 50, - ethers.utils.defaultAbiCoder.encode(['uint256'], [7]), - ) - .returns() - }) - - it('cannot be called by a non-owner', async () => { - await expect( - upkeepBalanceMonitor.connect(stranger).topUp([], [], []), - ).to.be.revertedWithCustomError( - upkeepBalanceMonitor, - 'OnlyForwarderOrOwner', - ) - }) - - it('should revert if the contract is paused', async () => { - await upkeepBalanceMonitor.connect(owner).pause() - await expect( - upkeepBalanceMonitor.connect(owner).topUp([], [], []), - ).to.be.revertedWith('Pausable: paused') - }) - - it('tops up the upkeeps by the amounts provided', async () => { - const initialBalance = await linkToken.balanceOf(registry.address) - const tx = await upkeepBalanceMonitor - .connect(owner) - .topUp([1, 7], [registry.address, registry.address], [100, 50]) - const finalBalance = await linkToken.balanceOf(registry.address) - expect(finalBalance).to.equal(initialBalance.add(150)) - await expect(tx) - .to.emit(upkeepBalanceMonitor, 'TopUpSucceeded') - .withArgs(1, 100) - await expect(tx) - .to.emit(upkeepBalanceMonitor, 'TopUpSucceeded') - .withArgs(7, 50) - }) - - it('does not abort if one top-up fails', async () => { - const initialBalance = await linkToken.balanceOf(registry.address) - const tx = await upkeepBalanceMonitor - .connect(owner) - .topUp( - [1, 7, 100], - [registry.address, registry.address, registry.address], - [100, 50, 100], - ) - const finalBalance = await linkToken.balanceOf(registry.address) - expect(finalBalance).to.equal(initialBalance.add(150)) - await expect(tx) - .to.emit(upkeepBalanceMonitor, 'TopUpSucceeded') - .withArgs(1, 100) - await expect(tx) - .to.emit(upkeepBalanceMonitor, 'TopUpSucceeded') - .withArgs(7, 50) - await expect(tx) - .to.emit(upkeepBalanceMonitor, 'TopUpFailed') - .withArgs(100) - }) - }) - - describe('checkUpkeep() / performUpkeep()', () => { - it('works round-trip', async () => { - await registry.mock.getBalance.withArgs(1).returns(100) // needs 200 - await registry.mock.getBalance.withArgs(7).returns(0) // needs 300 - await registry.mock.onTokenTransfer - .withArgs( - upkeepBalanceMonitor.address, - 200, - ethers.utils.defaultAbiCoder.encode(['uint256'], [1]), - ) - .returns() - await registry.mock.onTokenTransfer - .withArgs( - upkeepBalanceMonitor.address, - 300, - ethers.utils.defaultAbiCoder.encode(['uint256'], [7]), - ) - .returns() - const [upkeepNeeded, performData] = - await upkeepBalanceMonitor.checkUpkeep('0x') - expect(upkeepNeeded).to.be.true - const initialBalance = await linkToken.balanceOf(registry.address) - await upkeepBalanceMonitor.connect(owner).performUpkeep(performData) - const finalBalance = await linkToken.balanceOf(registry.address) - expect(finalBalance).to.equal(initialBalance.add(500)) - }) - }) -}) diff --git a/contracts/test/v0.8/automation/UpkeepTranscoder3_0.test.ts b/contracts/test/v0.8/automation/UpkeepTranscoder3_0.test.ts deleted file mode 100644 index d58cfd377f7..00000000000 --- a/contracts/test/v0.8/automation/UpkeepTranscoder3_0.test.ts +++ /dev/null @@ -1,576 +0,0 @@ -import { ethers } from 'hardhat' -import { assert, expect } from 'chai' -import { UpkeepTranscoder30__factory as UpkeepTranscoderFactory } from '../../../typechain/factories/UpkeepTranscoder30__factory' -import { UpkeepTranscoder30 as UpkeepTranscoder } from '../../../typechain/UpkeepTranscoder30' -import { KeeperRegistry2_0__factory as KeeperRegistry2_0Factory } from '../../../typechain/factories/KeeperRegistry2_0__factory' -import { LinkToken__factory as LinkTokenFactory } from '../../../typechain/factories/LinkToken__factory' -import { MockV3Aggregator__factory as MockV3AggregatorFactory } from '../../../typechain/factories/MockV3Aggregator__factory' -import { UpkeepMock__factory as UpkeepMockFactory } from '../../../typechain/factories/UpkeepMock__factory' -import { evmRevert } from '../../test-helpers/matchers' -import { BigNumber, Signer } from 'ethers' -import { getUsers, Personas } from '../../test-helpers/setup' -import { KeeperRegistryLogic2_0__factory as KeeperRegistryLogic20Factory } from '../../../typechain/factories/KeeperRegistryLogic2_0__factory' -import { KeeperRegistry1_3__factory as KeeperRegistry1_3Factory } from '../../../typechain/factories/KeeperRegistry1_3__factory' -import { KeeperRegistryLogic1_3__factory as KeeperRegistryLogicFactory } from '../../../typechain/factories/KeeperRegistryLogic1_3__factory' -import { toWei } from '../../test-helpers/helpers' -import { LinkToken } from '../../../typechain' - -let upkeepMockFactory: UpkeepMockFactory -let upkeepTranscoderFactory: UpkeepTranscoderFactory -let transcoder: UpkeepTranscoder -let linkTokenFactory: LinkTokenFactory -let mockV3AggregatorFactory: MockV3AggregatorFactory -let keeperRegistryFactory20: KeeperRegistry2_0Factory -let keeperRegistryFactory13: KeeperRegistry1_3Factory -let keeperRegistryLogicFactory20: KeeperRegistryLogic20Factory -let keeperRegistryLogicFactory13: KeeperRegistryLogicFactory -let personas: Personas -let owner: Signer -let upkeepsV1: any[] -let upkeepsV2: any[] -let upkeepsV3: any[] -let admins: string[] -let admin0: Signer -let admin1: Signer -const executeGas = BigNumber.from('100000') -const paymentPremiumPPB = BigNumber.from('250000000') -const flatFeeMicroLink = BigNumber.from(0) -const blockCountPerTurn = BigNumber.from(3) -const randomBytes = '0x1234abcd' -const stalenessSeconds = BigNumber.from(43820) -const gasCeilingMultiplier = BigNumber.from(1) -const checkGasLimit = BigNumber.from(20000000) -const fallbackGasPrice = BigNumber.from(200) -const fallbackLinkPrice = BigNumber.from(200000000) -const maxPerformGas = BigNumber.from(5000000) -const minUpkeepSpend = BigNumber.from(0) -const maxCheckDataSize = BigNumber.from(1000) -const maxPerformDataSize = BigNumber.from(1000) -const mode = BigNumber.from(0) -const linkEth = BigNumber.from(300000000) -const gasWei = BigNumber.from(100) -const registryGasOverhead = BigNumber.from('80000') -const balance = 50000000000000 -const amountSpent = 200000000000000 -const target0 = '0xffffffffffffffffffffffffffffffffffffffff' -const target1 = '0xfffffffffffffffffffffffffffffffffffffffe' -const lastKeeper0 = '0x233a95ccebf3c9f934482c637c08b4015cdd6ddd' -const lastKeeper1 = '0x233a95ccebf3c9f934482c637c08b4015cdd6ddc' -enum UpkeepFormat { - V1, - V2, - V3, - V4, -} -const idx = [123, 124] - -async function getUpkeepID(tx: any) { - const receipt = await tx.wait() - return receipt.events[0].args.id -} - -const encodeConfig = (config: any) => { - return ethers.utils.defaultAbiCoder.encode( - [ - 'tuple(uint32 paymentPremiumPPB,uint32 flatFeeMicroLink,uint32 checkGasLimit,uint24 stalenessSeconds\ - ,uint16 gasCeilingMultiplier,uint96 minUpkeepSpend,uint32 maxPerformGas,uint32 maxCheckDataSize,\ - uint32 maxPerformDataSize,uint256 fallbackGasPrice,uint256 fallbackLinkPrice,address transcoder,\ - address registrar)', - ], - [config], - ) -} - -const encodeUpkeepV1 = (ids: number[], upkeeps: any[], checkDatas: any[]) => { - return ethers.utils.defaultAbiCoder.encode( - [ - 'uint256[]', - 'tuple(uint96,address,uint32,uint64,address,uint96,address)[]', - 'bytes[]', - ], - [ids, upkeeps, checkDatas], - ) -} - -const encodeUpkeepV2 = (ids: number[], upkeeps: any[], checkDatas: any[]) => { - return ethers.utils.defaultAbiCoder.encode( - [ - 'uint256[]', - 'tuple(uint96,address,uint96,address,uint32,uint32,address,bool)[]', - 'bytes[]', - ], - [ids, upkeeps, checkDatas], - ) -} - -const encodeUpkeepV3 = ( - ids: number[], - upkeeps: any[], - checkDatas: any[], - admins: string[], -) => { - return ethers.utils.defaultAbiCoder.encode( - [ - 'uint256[]', - 'tuple(uint32,uint32,bool,address,uint96,uint96,uint32)[]', - 'bytes[]', - 'address[]', - ], - [ids, upkeeps, checkDatas, admins], - ) -} - -before(async () => { - // @ts-ignore bug in autogen file - upkeepTranscoderFactory = await ethers.getContractFactory( - 'UpkeepTranscoder3_0', - ) - personas = (await getUsers()).personas - - linkTokenFactory = await ethers.getContractFactory( - 'src/v0.8/shared/test/helpers/LinkTokenTestHelper.sol:LinkTokenTestHelper', - ) - // need full path because there are two contracts with name MockV3Aggregator - mockV3AggregatorFactory = (await ethers.getContractFactory( - 'src/v0.8/tests/MockV3Aggregator.sol:MockV3Aggregator', - )) as unknown as MockV3AggregatorFactory - - upkeepMockFactory = await ethers.getContractFactory('UpkeepMock') - - owner = personas.Norbert - admin0 = personas.Neil - admin1 = personas.Nick - admins = [ - (await admin0.getAddress()).toLowerCase(), - (await admin1.getAddress()).toLowerCase(), - ] -}) - -async function deployLinkToken() { - return await linkTokenFactory.connect(owner).deploy() -} - -async function deployFeeds() { - return [ - await mockV3AggregatorFactory.connect(owner).deploy(0, gasWei), - await mockV3AggregatorFactory.connect(owner).deploy(9, linkEth), - ] -} - -async function deployLegacyRegistry1_2( - linkToken: LinkToken, - gasPriceFeed: any, - linkEthFeed: any, -) { - const mock = await upkeepMockFactory.deploy() - // @ts-ignore bug in autogen file - const keeperRegistryFactory = - await ethers.getContractFactory('KeeperRegistry1_2') - transcoder = await upkeepTranscoderFactory.connect(owner).deploy() - const legacyRegistry = await keeperRegistryFactory - .connect(owner) - .deploy(linkToken.address, linkEthFeed.address, gasPriceFeed.address, { - paymentPremiumPPB, - flatFeeMicroLink, - blockCountPerTurn, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }) - const tx = await legacyRegistry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin0.getAddress(), - randomBytes, - ) - const id = await getUpkeepID(tx) - return [id, legacyRegistry] -} - -async function deployLegacyRegistry1_3( - linkToken: LinkToken, - gasPriceFeed: any, - linkEthFeed: any, -) { - const mock = await upkeepMockFactory.deploy() - // @ts-ignore bug in autogen file - keeperRegistryFactory13 = await ethers.getContractFactory('KeeperRegistry1_3') - // @ts-ignore bug in autogen file - keeperRegistryLogicFactory13 = await ethers.getContractFactory( - 'KeeperRegistryLogic1_3', - ) - - const registryLogic13 = await keeperRegistryLogicFactory13 - .connect(owner) - .deploy( - 0, - registryGasOverhead, - linkToken.address, - linkEthFeed.address, - gasPriceFeed.address, - ) - - const config = { - paymentPremiumPPB, - flatFeeMicroLink, - blockCountPerTurn, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - } - const Registry1_3 = await keeperRegistryFactory13 - .connect(owner) - .deploy(registryLogic13.address, config) - - const tx = await Registry1_3.connect(owner).registerUpkeep( - mock.address, - executeGas, - await admin0.getAddress(), - randomBytes, - ) - const id = await getUpkeepID(tx) - - return [id, Registry1_3] -} - -async function deployRegistry2_0( - linkToken: LinkToken, - gasPriceFeed: any, - linkEthFeed: any, -) { - // @ts-ignore bug in autogen file - keeperRegistryFactory20 = await ethers.getContractFactory('KeeperRegistry2_0') - // @ts-ignore bug in autogen file - keeperRegistryLogicFactory20 = await ethers.getContractFactory( - 'KeeperRegistryLogic2_0', - ) - - const config = { - paymentPremiumPPB, - flatFeeMicroLink, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxCheckDataSize, - maxPerformDataSize, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - } - - const registryLogic = await keeperRegistryLogicFactory20 - .connect(owner) - .deploy(mode, linkToken.address, linkEthFeed.address, gasPriceFeed.address) - - const Registry2_0 = await keeperRegistryFactory20 - .connect(owner) - .deploy(registryLogic.address) - - // deploys a registry, setups of initial configuration, registers an upkeep - const keeper1 = personas.Carol - const keeper2 = personas.Eddy - const keeper3 = personas.Nancy - const keeper4 = personas.Norbert - const keeper5 = personas.Nick - const payee1 = personas.Nelly - const payee2 = personas.Norbert - const payee3 = personas.Nick - const payee4 = personas.Eddy - const payee5 = personas.Carol - // signers - const signer1 = new ethers.Wallet( - '0x7777777000000000000000000000000000000000000000000000000000000001', - ) - const signer2 = new ethers.Wallet( - '0x7777777000000000000000000000000000000000000000000000000000000002', - ) - const signer3 = new ethers.Wallet( - '0x7777777000000000000000000000000000000000000000000000000000000003', - ) - const signer4 = new ethers.Wallet( - '0x7777777000000000000000000000000000000000000000000000000000000004', - ) - const signer5 = new ethers.Wallet( - '0x7777777000000000000000000000000000000000000000000000000000000005', - ) - - const keeperAddresses = [ - await keeper1.getAddress(), - await keeper2.getAddress(), - await keeper3.getAddress(), - await keeper4.getAddress(), - await keeper5.getAddress(), - ] - const payees = [ - await payee1.getAddress(), - await payee2.getAddress(), - await payee3.getAddress(), - await payee4.getAddress(), - await payee5.getAddress(), - ] - const signers = [signer1, signer2, signer3, signer4, signer5] - - const signerAddresses = [] - for (const signer of signers) { - signerAddresses.push(await signer.getAddress()) - } - - const f = 1 - const offchainVersion = 1 - const offchainBytes = '0x' - - await Registry2_0.connect(owner).setConfig( - signerAddresses, - keeperAddresses, - f, - encodeConfig(config), - offchainVersion, - offchainBytes, - ) - await Registry2_0.connect(owner).setPayees(payees) - return Registry2_0 -} - -describe('UpkeepTranscoder3_0', () => { - beforeEach(async () => { - transcoder = await upkeepTranscoderFactory.connect(owner).deploy() - }) - - describe('#typeAndVersion', () => { - it('uses the correct type and version', async () => { - const typeAndVersion = await transcoder.typeAndVersion() - assert.equal(typeAndVersion, 'UpkeepTranscoder 3.0.0') - }) - }) - - describe('#transcodeUpkeeps', () => { - const encodedData = '0xabcd' - - it('reverts if the from type is not V1 or V2', async () => { - await evmRevert( - transcoder.transcodeUpkeeps( - UpkeepFormat.V3, - UpkeepFormat.V1, - encodedData, - ), - ) - await evmRevert( - transcoder.transcodeUpkeeps( - UpkeepFormat.V4, - UpkeepFormat.V1, - encodedData, - ), - ) - }) - - context('when from and to versions are correct', () => { - upkeepsV3 = [ - [executeGas, 2 ** 32 - 1, false, target0, amountSpent, balance, 0], - [executeGas, 2 ** 32 - 1, false, target1, amountSpent, balance, 0], - ] - - it('transcodes V1 upkeeps to V3 properly, regardless of toVersion value', async () => { - upkeepsV1 = [ - [ - balance, - lastKeeper0, - executeGas, - 2 ** 32, - target0, - amountSpent, - await admin0.getAddress(), - ], - [ - balance, - lastKeeper1, - executeGas, - 2 ** 32, - target1, - amountSpent, - await admin1.getAddress(), - ], - ] - - const data = await transcoder.transcodeUpkeeps( - UpkeepFormat.V1, - UpkeepFormat.V1, - encodeUpkeepV1(idx, upkeepsV1, ['0xabcd', '0xffff']), - ) - assert.equal( - encodeUpkeepV3(idx, upkeepsV3, ['0xabcd', '0xffff'], admins), - data, - ) - }) - - it('transcodes V2 upkeeps to V3 properly, regardless of toVersion value', async () => { - upkeepsV2 = [ - [ - balance, - lastKeeper0, - amountSpent, - await admin0.getAddress(), - executeGas, - 2 ** 32 - 1, - target0, - false, - ], - [ - balance, - lastKeeper1, - amountSpent, - await admin1.getAddress(), - executeGas, - 2 ** 32 - 1, - target1, - false, - ], - ] - - const data = await transcoder.transcodeUpkeeps( - UpkeepFormat.V2, - UpkeepFormat.V2, - encodeUpkeepV2(idx, upkeepsV2, ['0xabcd', '0xffff']), - ) - assert.equal( - encodeUpkeepV3(idx, upkeepsV3, ['0xabcd', '0xffff'], admins), - data, - ) - }) - - it('migrates upkeeps from 1.2 registry to 2.0', async () => { - const linkToken = await deployLinkToken() - const [gasPriceFeed, linkEthFeed] = await deployFeeds() - const [id, legacyRegistry] = await deployLegacyRegistry1_2( - linkToken, - gasPriceFeed, - linkEthFeed, - ) - const Registry2_0 = await deployRegistry2_0( - linkToken, - gasPriceFeed, - linkEthFeed, - ) - - await linkToken - .connect(owner) - .approve(legacyRegistry.address, toWei('1000')) - await legacyRegistry.connect(owner).addFunds(id, toWei('1000')) - - // set outgoing permission to registry 2_0 and incoming permission for registry 1_2 - await legacyRegistry.setPeerRegistryMigrationPermission( - Registry2_0.address, - 1, - ) - await Registry2_0.setPeerRegistryMigrationPermission( - legacyRegistry.address, - 2, - ) - - expect((await legacyRegistry.getUpkeep(id)).balance).to.equal( - toWei('1000'), - ) - expect((await legacyRegistry.getUpkeep(id)).checkData).to.equal( - randomBytes, - ) - expect((await legacyRegistry.getState()).state.numUpkeeps).to.equal(1) - - await legacyRegistry - .connect(admin0) - .migrateUpkeeps([id], Registry2_0.address) - - expect((await legacyRegistry.getState()).state.numUpkeeps).to.equal(0) - expect((await Registry2_0.getState()).state.numUpkeeps).to.equal(1) - expect((await legacyRegistry.getUpkeep(id)).balance).to.equal(0) - expect((await legacyRegistry.getUpkeep(id)).checkData).to.equal('0x') - expect((await Registry2_0.getUpkeep(id)).balance).to.equal( - toWei('1000'), - ) - expect( - (await Registry2_0.getState()).state.expectedLinkBalance, - ).to.equal(toWei('1000')) - expect(await linkToken.balanceOf(Registry2_0.address)).to.equal( - toWei('1000'), - ) - expect((await Registry2_0.getUpkeep(id)).checkData).to.equal( - randomBytes, - ) - }) - - it('migrates upkeeps from 1.3 registry to 2.0', async () => { - const linkToken = await deployLinkToken() - const [gasPriceFeed, linkEthFeed] = await deployFeeds() - const [id, legacyRegistry] = await deployLegacyRegistry1_3( - linkToken, - gasPriceFeed, - linkEthFeed, - ) - const Registry2_0 = await deployRegistry2_0( - linkToken, - gasPriceFeed, - linkEthFeed, - ) - - await linkToken - .connect(owner) - .approve(legacyRegistry.address, toWei('1000')) - await legacyRegistry.connect(owner).addFunds(id, toWei('1000')) - - // set outgoing permission to registry 2_0 and incoming permission for registry 1_3 - await legacyRegistry.setPeerRegistryMigrationPermission( - Registry2_0.address, - 1, - ) - await Registry2_0.setPeerRegistryMigrationPermission( - legacyRegistry.address, - 2, - ) - - expect((await legacyRegistry.getUpkeep(id)).balance).to.equal( - toWei('1000'), - ) - expect((await legacyRegistry.getUpkeep(id)).checkData).to.equal( - randomBytes, - ) - expect((await legacyRegistry.getState()).state.numUpkeeps).to.equal(1) - - await legacyRegistry - .connect(admin0) - .migrateUpkeeps([id], Registry2_0.address) - - expect((await legacyRegistry.getState()).state.numUpkeeps).to.equal(0) - expect((await Registry2_0.getState()).state.numUpkeeps).to.equal(1) - expect((await legacyRegistry.getUpkeep(id)).balance).to.equal(0) - expect((await legacyRegistry.getUpkeep(id)).checkData).to.equal('0x') - expect((await Registry2_0.getUpkeep(id)).balance).to.equal( - toWei('1000'), - ) - expect( - (await Registry2_0.getState()).state.expectedLinkBalance, - ).to.equal(toWei('1000')) - expect(await linkToken.balanceOf(Registry2_0.address)).to.equal( - toWei('1000'), - ) - expect((await Registry2_0.getUpkeep(id)).checkData).to.equal( - randomBytes, - ) - }) - }) - }) -}) diff --git a/contracts/test/v0.8/automation/UpkeepTranscoder4_0.test.ts b/contracts/test/v0.8/automation/UpkeepTranscoder4_0.test.ts deleted file mode 100644 index 392a1cb5966..00000000000 --- a/contracts/test/v0.8/automation/UpkeepTranscoder4_0.test.ts +++ /dev/null @@ -1,654 +0,0 @@ -import { ethers } from 'hardhat' -import { assert, expect } from 'chai' -import { UpkeepTranscoder4_0 as UpkeepTranscoder } from '../../../typechain/UpkeepTranscoder4_0' -import { KeeperRegistry2_0__factory as KeeperRegistry2_0Factory } from '../../../typechain/factories/KeeperRegistry2_0__factory' -import { LinkToken__factory as LinkTokenFactory } from '../../../typechain/factories/LinkToken__factory' -import { MockV3Aggregator__factory as MockV3AggregatorFactory } from '../../../typechain/factories/MockV3Aggregator__factory' -import { evmRevert } from '../../test-helpers/matchers' -import { BigNumber, Signer } from 'ethers' -import { getUsers, Personas } from '../../test-helpers/setup' -import { KeeperRegistryLogic2_0__factory as KeeperRegistryLogic20Factory } from '../../../typechain/factories/KeeperRegistryLogic2_0__factory' -import { KeeperRegistry1_3__factory as KeeperRegistry1_3Factory } from '../../../typechain/factories/KeeperRegistry1_3__factory' -import { KeeperRegistryLogic1_3__factory as KeeperRegistryLogicFactory } from '../../../typechain/factories/KeeperRegistryLogic1_3__factory' -import { UpkeepTranscoder4_0__factory as UpkeepTranscoderFactory } from '../../../typechain/factories/UpkeepTranscoder4_0__factory' -import { toWei } from '../../test-helpers/helpers' -import { loadFixture } from '@nomicfoundation/hardhat-network-helpers' -import { - IKeeperRegistryMaster, - KeeperRegistry1_2, - KeeperRegistry1_3, - KeeperRegistry2_0, - LinkToken, - MockV3Aggregator, - UpkeepMock, -} from '../../../typechain' -import { deployRegistry21 } from './helpers' - -////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////// - -/*********************************** TRANSCODER v4.0 IS FROZEN ************************************/ - -// We are leaving the original tests enabled, however as automation v2.1 is still actively being deployed - -describe('UpkeepTranscoder v4.0 - Frozen [ @skip-coverage ]', () => { - it('has not changed', () => { - assert.equal( - ethers.utils.id(UpkeepTranscoderFactory.bytecode), - '0xf22c4701b0088e6e69c389a34a22041a69f00890a89246e3c2a6d38172222dae', - 'UpkeepTranscoder bytecode has changed', - ) - }) -}) - -////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////// - -let transcoder: UpkeepTranscoder -let linkTokenFactory: LinkTokenFactory -let keeperRegistryFactory20: KeeperRegistry2_0Factory -let keeperRegistryFactory13: KeeperRegistry1_3Factory -let keeperRegistryLogicFactory20: KeeperRegistryLogic20Factory -let keeperRegistryLogicFactory13: KeeperRegistryLogicFactory -let linkToken: LinkToken -let registry12: KeeperRegistry1_2 -let registry13: KeeperRegistry1_3 -let registry20: KeeperRegistry2_0 -let registry21: IKeeperRegistryMaster -let gasPriceFeed: MockV3Aggregator -let linkEthFeed: MockV3Aggregator -let mock: UpkeepMock -let personas: Personas -let owner: Signer -let upkeepsV12: any[] -let upkeepsV13: any[] -let upkeepsV21: any[] -let admins: string[] -let admin0: Signer -let admin1: Signer -let id12: BigNumber -let id13: BigNumber -let id20: BigNumber -const executeGas = BigNumber.from('100000') -const paymentPremiumPPB = BigNumber.from('250000000') -const flatFeeMicroLink = BigNumber.from(0) -const blockCountPerTurn = BigNumber.from(3) -const randomBytes = '0x1234abcd' -const stalenessSeconds = BigNumber.from(43820) -const gasCeilingMultiplier = BigNumber.from(1) -const checkGasLimit = BigNumber.from(20000000) -const fallbackGasPrice = BigNumber.from(200) -const fallbackLinkPrice = BigNumber.from(200000000) -const maxPerformGas = BigNumber.from(5000000) -const minUpkeepSpend = BigNumber.from(0) -const maxCheckDataSize = BigNumber.from(1000) -const maxPerformDataSize = BigNumber.from(1000) -const mode = BigNumber.from(0) -const linkEth = BigNumber.from(300000000) -const gasWei = BigNumber.from(100) -const registryGasOverhead = BigNumber.from('80000') -const balance = 50000000000000 -const amountSpent = 200000000000000 -const { AddressZero } = ethers.constants -const target0 = '0xffffffffffffffffffffffffffffffffffffffff' -const target1 = '0xfffffffffffffffffffffffffffffffffffffffe' -const lastKeeper0 = '0x233a95ccebf3c9f934482c637c08b4015cdd6ddd' -const lastKeeper1 = '0x233a95ccebf3c9f934482c637c08b4015cdd6ddc' - -const f = 1 -const offchainVersion = 1 -const offchainBytes = '0x' -let keeperAddresses: string[] -let signerAddresses: string[] -let payees: string[] - -enum UpkeepFormat { - V12, - V13, - V20, - V21, - V30, // Does not exist -} -const idx = [123, 124] - -async function getUpkeepID(tx: any): Promise { - const receipt = await tx.wait() - return receipt.events[0].args.id -} - -const encodeConfig20 = (config: any) => { - return ethers.utils.defaultAbiCoder.encode( - [ - 'tuple(uint32 paymentPremiumPPB,uint32 flatFeeMicroLink,uint32 checkGasLimit,uint24 stalenessSeconds\ - ,uint16 gasCeilingMultiplier,uint96 minUpkeepSpend,uint32 maxPerformGas,uint32 maxCheckDataSize,\ - uint32 maxPerformDataSize,uint256 fallbackGasPrice,uint256 fallbackLinkPrice,address transcoder,\ - address registrar)', - ], - [config], - ) -} - -const encodeUpkeepV12 = (ids: number[], upkeeps: any[], checkDatas: any[]) => { - return ethers.utils.defaultAbiCoder.encode( - [ - 'uint256[]', - 'tuple(uint96,address,uint32,uint64,address,uint96,address)[]', - 'bytes[]', - ], - [ids, upkeeps, checkDatas], - ) -} - -async function deployRegistry1_2(): Promise<[BigNumber, KeeperRegistry1_2]> { - const keeperRegistryFactory = - await ethers.getContractFactory('KeeperRegistry1_2') - const registry12 = await keeperRegistryFactory - .connect(owner) - .deploy(linkToken.address, linkEthFeed.address, gasPriceFeed.address, { - paymentPremiumPPB, - flatFeeMicroLink, - blockCountPerTurn, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }) - const tx = await registry12 - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin0.getAddress(), - randomBytes, - ) - const id = await getUpkeepID(tx) - return [id, registry12] -} - -async function deployRegistry1_3(): Promise<[BigNumber, KeeperRegistry1_3]> { - keeperRegistryFactory13 = await ethers.getContractFactory('KeeperRegistry1_3') - keeperRegistryLogicFactory13 = await ethers.getContractFactory( - 'KeeperRegistryLogic1_3', - ) - - const registryLogic13 = await keeperRegistryLogicFactory13 - .connect(owner) - .deploy( - 0, - registryGasOverhead, - linkToken.address, - linkEthFeed.address, - gasPriceFeed.address, - ) - - const config = { - paymentPremiumPPB, - flatFeeMicroLink, - blockCountPerTurn, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - } - const registry13 = await keeperRegistryFactory13 - .connect(owner) - .deploy(registryLogic13.address, config) - - const tx = await registry13 - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin0.getAddress(), - randomBytes, - ) - const id = await getUpkeepID(tx) - - return [id, registry13] -} - -async function deployRegistry2_0(): Promise<[BigNumber, KeeperRegistry2_0]> { - keeperRegistryFactory20 = await ethers.getContractFactory('KeeperRegistry2_0') - keeperRegistryLogicFactory20 = await ethers.getContractFactory( - 'KeeperRegistryLogic2_0', - ) - - const config = { - paymentPremiumPPB, - flatFeeMicroLink, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxCheckDataSize, - maxPerformDataSize, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - } - - const registryLogic = await keeperRegistryLogicFactory20 - .connect(owner) - .deploy(mode, linkToken.address, linkEthFeed.address, gasPriceFeed.address) - - const registry20 = await keeperRegistryFactory20 - .connect(owner) - .deploy(registryLogic.address) - - await registry20 - .connect(owner) - .setConfig( - signerAddresses, - keeperAddresses, - f, - encodeConfig20(config), - offchainVersion, - offchainBytes, - ) - await registry20.connect(owner).setPayees(payees) - - const tx = await registry20 - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin0.getAddress(), - randomBytes, - randomBytes, - ) - const id = await getUpkeepID(tx) - - return [id, registry20] -} - -async function deployRegistry2_1() { - const registry = await deployRegistry21( - owner, - mode, - linkToken.address, - linkEthFeed.address, - gasPriceFeed.address, - ) - - const onchainConfig = { - paymentPremiumPPB, - flatFeeMicroLink, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxCheckDataSize, - maxPerformDataSize, - maxRevertDataSize: 1000, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: ethers.constants.AddressZero, - registrars: [], - upkeepPrivilegeManager: await owner.getAddress(), - } - - await registry - .connect(owner) - .setConfigTypeSafe( - signerAddresses, - keeperAddresses, - f, - onchainConfig, - offchainVersion, - offchainBytes, - ) - - return registry -} - -const setup = async () => { - personas = (await getUsers()).personas - owner = personas.Norbert - admin0 = personas.Neil - admin1 = personas.Nick - admins = [ - (await admin0.getAddress()).toLowerCase(), - (await admin1.getAddress()).toLowerCase(), - ] - - const upkeepTranscoderFactory = await ethers.getContractFactory( - 'UpkeepTranscoder4_0', - ) - transcoder = await upkeepTranscoderFactory.connect(owner).deploy() - - linkTokenFactory = await ethers.getContractFactory( - 'src/v0.8/shared/test/helpers/LinkTokenTestHelper.sol:LinkTokenTestHelper', - ) - linkToken = await linkTokenFactory.connect(owner).deploy() - // need full path because there are two contracts with name MockV3Aggregator - const mockV3AggregatorFactory = (await ethers.getContractFactory( - 'src/v0.8/tests/MockV3Aggregator.sol:MockV3Aggregator', - )) as unknown as MockV3AggregatorFactory - - gasPriceFeed = await mockV3AggregatorFactory.connect(owner).deploy(0, gasWei) - linkEthFeed = await mockV3AggregatorFactory.connect(owner).deploy(9, linkEth) - - const upkeepMockFactory = await ethers.getContractFactory('UpkeepMock') - mock = await upkeepMockFactory.deploy() - - const keeper1 = personas.Carol - const keeper2 = personas.Eddy - const keeper3 = personas.Nancy - const keeper4 = personas.Norbert - const keeper5 = personas.Nick - const payee1 = personas.Nelly - const payee2 = personas.Norbert - const payee3 = personas.Nick - const payee4 = personas.Eddy - const payee5 = personas.Carol - // signers - const signer1 = new ethers.Wallet( - '0x7777777000000000000000000000000000000000000000000000000000000001', - ) - const signer2 = new ethers.Wallet( - '0x7777777000000000000000000000000000000000000000000000000000000002', - ) - const signer3 = new ethers.Wallet( - '0x7777777000000000000000000000000000000000000000000000000000000003', - ) - const signer4 = new ethers.Wallet( - '0x7777777000000000000000000000000000000000000000000000000000000004', - ) - const signer5 = new ethers.Wallet( - '0x7777777000000000000000000000000000000000000000000000000000000005', - ) - - keeperAddresses = [ - await keeper1.getAddress(), - await keeper2.getAddress(), - await keeper3.getAddress(), - await keeper4.getAddress(), - await keeper5.getAddress(), - ] - - payees = [ - await payee1.getAddress(), - await payee2.getAddress(), - await payee3.getAddress(), - await payee4.getAddress(), - await payee5.getAddress(), - ] - const signers = [signer1, signer2, signer3, signer4, signer5] - - signerAddresses = signers.map((signer) => signer.address) - ;[id12, registry12] = await deployRegistry1_2() - ;[id13, registry13] = await deployRegistry1_3() - ;[id20, registry20] = await deployRegistry2_0() - registry21 = await deployRegistry2_1() - - upkeepsV12 = [ - [ - balance, - lastKeeper0, - executeGas, - 2 ** 32, - target0, - amountSpent, - await admin0.getAddress(), - ], - [ - balance, - lastKeeper1, - executeGas, - 2 ** 32, - target1, - amountSpent, - await admin1.getAddress(), - ], - ] - - upkeepsV13 = [ - [ - balance, - lastKeeper0, - amountSpent, - await admin0.getAddress(), - executeGas, - 2 ** 32 - 1, - target0, - false, - ], - [ - balance, - lastKeeper1, - amountSpent, - await admin1.getAddress(), - executeGas, - 2 ** 32 - 1, - target1, - false, - ], - ] - - upkeepsV21 = [ - [ - false, - executeGas, - 2 ** 32 - 1, - AddressZero, // forwarder will always be zero - amountSpent, - balance, - 0, - target0, - ], - [ - false, - executeGas, - 2 ** 32 - 1, - AddressZero, // forwarder will always be zero - amountSpent, - balance, - 0, - target1, - ], - ] -} - -describe('UpkeepTranscoder4_0', () => { - beforeEach(async () => { - await loadFixture(setup) - }) - - describe('#typeAndVersion', () => { - it('uses the correct type and version', async () => { - const typeAndVersion = await transcoder.typeAndVersion() - assert.equal(typeAndVersion, 'UpkeepTranscoder 4.0.0') - }) - }) - - describe('#transcodeUpkeeps', () => { - const encodedData = '0xabcd' - - it('reverts if the from type is not v1.2, v1.3, v2.0, or v2.1', async () => { - await evmRevert( - transcoder.transcodeUpkeeps( - UpkeepFormat.V30, - UpkeepFormat.V12, - encodedData, - ), - ) - }) - - context('when from version is correct', () => { - // note this is a bugfix - the "to" version should be accounted for in - // future versions of the transcoder - it('transcodes to v2.1, regardless of toVersion value', async () => { - const data1 = await transcoder.transcodeUpkeeps( - UpkeepFormat.V12, - UpkeepFormat.V12, - encodeUpkeepV12(idx, upkeepsV12, ['0xabcd', '0xffff']), - ) - const data2 = await transcoder.transcodeUpkeeps( - UpkeepFormat.V12, - UpkeepFormat.V13, - encodeUpkeepV12(idx, upkeepsV12, ['0xabcd', '0xffff']), - ) - const data3 = await transcoder.transcodeUpkeeps( - UpkeepFormat.V12, - 100, - encodeUpkeepV12(idx, upkeepsV12, ['0xabcd', '0xffff']), - ) - assert.equal(data1, data2) - assert.equal(data1, data3) - }) - - it('migrates upkeeps from 1.2 registry to 2.1', async () => { - await linkToken - .connect(owner) - .approve(registry12.address, toWei('1000')) - await registry12.connect(owner).addFunds(id12, toWei('1000')) - - await registry12.setPeerRegistryMigrationPermission( - registry21.address, - 1, - ) - await registry21.setPeerRegistryMigrationPermission( - registry12.address, - 2, - ) - - expect((await registry12.getUpkeep(id12)).balance).to.equal( - toWei('1000'), - ) - expect((await registry12.getUpkeep(id12)).checkData).to.equal( - randomBytes, - ) - expect((await registry12.getState()).state.numUpkeeps).to.equal(1) - - await registry12 - .connect(admin0) - .migrateUpkeeps([id12], registry21.address) - - expect((await registry12.getState()).state.numUpkeeps).to.equal(0) - expect((await registry21.getState()).state.numUpkeeps).to.equal(1) - expect((await registry12.getUpkeep(id12)).balance).to.equal(0) - expect((await registry12.getUpkeep(id12)).checkData).to.equal('0x') - expect((await registry21.getUpkeep(id12)).balance).to.equal( - toWei('1000'), - ) - expect( - (await registry21.getState()).state.expectedLinkBalance, - ).to.equal(toWei('1000')) - expect(await linkToken.balanceOf(registry21.address)).to.equal( - toWei('1000'), - ) - expect((await registry21.getUpkeep(id12)).checkData).to.equal( - randomBytes, - ) - expect((await registry21.getUpkeep(id12)).offchainConfig).to.equal('0x') - expect(await registry21.getUpkeepTriggerConfig(id12)).to.equal('0x') - }) - - it('migrates upkeeps from 1.3 registry to 2.1', async () => { - await linkToken - .connect(owner) - .approve(registry13.address, toWei('1000')) - await registry13.connect(owner).addFunds(id13, toWei('1000')) - - await registry13.setPeerRegistryMigrationPermission( - registry21.address, - 1, - ) - await registry21.setPeerRegistryMigrationPermission( - registry13.address, - 2, - ) - - expect((await registry13.getUpkeep(id13)).balance).to.equal( - toWei('1000'), - ) - expect((await registry13.getUpkeep(id13)).checkData).to.equal( - randomBytes, - ) - expect((await registry13.getState()).state.numUpkeeps).to.equal(1) - - await registry13 - .connect(admin0) - .migrateUpkeeps([id13], registry21.address) - - expect((await registry13.getState()).state.numUpkeeps).to.equal(0) - expect((await registry21.getState()).state.numUpkeeps).to.equal(1) - expect((await registry13.getUpkeep(id13)).balance).to.equal(0) - expect((await registry13.getUpkeep(id13)).checkData).to.equal('0x') - expect((await registry21.getUpkeep(id13)).balance).to.equal( - toWei('1000'), - ) - expect( - (await registry21.getState()).state.expectedLinkBalance, - ).to.equal(toWei('1000')) - expect(await linkToken.balanceOf(registry21.address)).to.equal( - toWei('1000'), - ) - expect((await registry21.getUpkeep(id13)).checkData).to.equal( - randomBytes, - ) - expect((await registry21.getUpkeep(id13)).offchainConfig).to.equal('0x') - expect(await registry21.getUpkeepTriggerConfig(id13)).to.equal('0x') - }) - - it('migrates upkeeps from 2.0 registry to 2.1', async () => { - await linkToken - .connect(owner) - .approve(registry20.address, toWei('1000')) - await registry20.connect(owner).addFunds(id20, toWei('1000')) - - await registry20.setPeerRegistryMigrationPermission( - registry21.address, - 1, - ) - await registry21.setPeerRegistryMigrationPermission( - registry20.address, - 2, - ) - - expect((await registry20.getUpkeep(id20)).balance).to.equal( - toWei('1000'), - ) - expect((await registry20.getUpkeep(id20)).checkData).to.equal( - randomBytes, - ) - expect((await registry20.getState()).state.numUpkeeps).to.equal(1) - - await registry20 - .connect(admin0) - .migrateUpkeeps([id20], registry21.address) - - expect((await registry20.getState()).state.numUpkeeps).to.equal(0) - expect((await registry21.getState()).state.numUpkeeps).to.equal(1) - expect((await registry20.getUpkeep(id20)).balance).to.equal(0) - expect((await registry20.getUpkeep(id20)).checkData).to.equal('0x') - expect((await registry21.getUpkeep(id20)).balance).to.equal( - toWei('1000'), - ) - expect( - (await registry21.getState()).state.expectedLinkBalance, - ).to.equal(toWei('1000')) - expect(await linkToken.balanceOf(registry21.address)).to.equal( - toWei('1000'), - ) - expect((await registry21.getUpkeep(id20)).checkData).to.equal( - randomBytes, - ) - expect(await registry21.getUpkeepTriggerConfig(id20)).to.equal('0x') - }) - }) - }) -}) diff --git a/contracts/test/v0.8/automation/ZKSyncAutomationRegistry2_3.test.ts b/contracts/test/v0.8/automation/ZKSyncAutomationRegistry2_3.test.ts index 95210cf6444..21af6fcbf0a 100644 --- a/contracts/test/v0.8/automation/ZKSyncAutomationRegistry2_3.test.ts +++ b/contracts/test/v0.8/automation/ZKSyncAutomationRegistry2_3.test.ts @@ -84,9 +84,6 @@ type OnChainConfig = Parameters[3] let registryConditionalOverhead: BigNumber let registryLogOverhead: BigNumber let registryPerSignerGasOverhead: BigNumber -// let registryPerPerformByteGasOverhead: BigNumber -// let registryTransmitCalldataFixedBytesOverhead: BigNumber -// let registryTransmitCalldataPerSignerBytesOverhead: BigNumber let cancellationDelay: number // This is the margin for gas that we test for. Gas charged should always be greater @@ -416,7 +413,7 @@ describe('ZKSyncAutomationRegistry2_3', () => { ) // need full path because there are two contracts with name MockV3Aggregator mockV3AggregatorFactory = (await ethers.getContractFactory( - 'src/v0.8/tests/MockV3Aggregator.sol:MockV3Aggregator', + 'src/v0.8/shared/mocks/MockV3Aggregator.sol:MockV3Aggregator', )) as unknown as MockV3AggregatorFactory mockZKSyncSystemContextFactory = await ethers.getContractFactory( 'MockZKSyncSystemContext', @@ -1618,7 +1615,6 @@ describe('ZKSyncAutomationRegistry2_3', () => { BigNumber.from('1'), // Not the config multiplier, but the actual gas used paymentPremiumPPB, flatFeeMilliCents, - // pubdataGas.mul(gasPrice), ).total.toString(), totalPayment.toString(), ) @@ -1630,7 +1626,6 @@ describe('ZKSyncAutomationRegistry2_3', () => { BigNumber.from('1'), // Not the config multiplier, but the actual gas used paymentPremiumPPB, flatFeeMilliCents, - // pubdataGas.mul(gasPrice), ).premium.toString(), premium.toString(), ) @@ -1661,7 +1656,6 @@ describe('ZKSyncAutomationRegistry2_3', () => { gasCeilingMultiplier, // Should be same with exisitng multiplier paymentPremiumPPB, flatFeeMilliCents, - // pubdataGas.mul(gasPrice), ).total.toString(), totalPayment.toString(), ) diff --git a/contracts/test/v0.8/automation/helpers.ts b/contracts/test/v0.8/automation/helpers.ts index 99f2cef9b87..130bdcbfecf 100644 --- a/contracts/test/v0.8/automation/helpers.ts +++ b/contracts/test/v0.8/automation/helpers.ts @@ -1,11 +1,5 @@ import { Signer } from 'ethers' import { ethers } from 'hardhat' -import { KeeperRegistryLogicB2_1__factory as KeeperRegistryLogicBFactory } from '../../../typechain/factories/KeeperRegistryLogicB2_1__factory' -import { IKeeperRegistryMaster as IKeeperRegistry } from '../../../typechain/IKeeperRegistryMaster' -import { IKeeperRegistryMaster__factory as IKeeperRegistryMasterFactory } from '../../../typechain/factories/IKeeperRegistryMaster__factory' -import { AutomationRegistryLogicB2_2__factory as AutomationRegistryLogicBFactory } from '../../../typechain/factories/AutomationRegistryLogicB2_2__factory' -import { IAutomationRegistryMaster as IAutomationRegistry } from '../../../typechain/IAutomationRegistryMaster' -import { IAutomationRegistryMaster__factory as IAutomationRegistryMasterFactory } from '../../../typechain/factories/IAutomationRegistryMaster__factory' import { assert } from 'chai' import { FunctionFragment } from '@ethersproject/abi' import { AutomationRegistryLogicC2_3__factory as AutomationRegistryLogicC2_3Factory } from '../../../typechain/factories/AutomationRegistryLogicC2_3__factory' @@ -13,32 +7,6 @@ import { ZKSyncAutomationRegistryLogicC2_3__factory as ZKSyncAutomationRegistryL import { IAutomationRegistryMaster2_3 as IAutomationRegistry2_3 } from '../../../typechain/IAutomationRegistryMaster2_3' import { IAutomationRegistryMaster2_3__factory as IAutomationRegistryMaster2_3Factory } from '../../../typechain/factories/IAutomationRegistryMaster2_3__factory' -export const deployRegistry21 = async ( - from: Signer, - mode: Parameters[0], - link: Parameters[1], - linkNative: Parameters[2], - fastgas: Parameters[3], -): Promise => { - const logicBFactory = await ethers.getContractFactory( - 'KeeperRegistryLogicB2_1', - ) - const logicAFactory = await ethers.getContractFactory( - 'KeeperRegistryLogicA2_1', - ) - const registryFactory = await ethers.getContractFactory('KeeperRegistry2_1') - const forwarderLogicFactory = await ethers.getContractFactory( - 'AutomationForwarderLogic', - ) - const forwarderLogic = await forwarderLogicFactory.connect(from).deploy() - const logicB = await logicBFactory - .connect(from) - .deploy(mode, link, linkNative, fastgas, forwarderLogic.address) - const logicA = await logicAFactory.connect(from).deploy(logicB.address) - const master = await registryFactory.connect(from).deploy(logicA.address) - return IKeeperRegistryMasterFactory.connect(master.address, from) -} - type InterfaceABI = ConstructorParameters[0] type Entry = { inputs?: any[] @@ -130,42 +98,6 @@ export const assertSatisfiesInterface = ( } } -export const deployRegistry22 = async ( - from: Signer, - link: Parameters[0], - linkNative: Parameters[1], - fastgas: Parameters[2], - allowedReadOnlyAddress: Parameters< - AutomationRegistryLogicBFactory['deploy'] - >[3], -): Promise => { - const logicBFactory = await ethers.getContractFactory( - 'AutomationRegistryLogicB2_2', - ) - const logicAFactory = await ethers.getContractFactory( - 'AutomationRegistryLogicA2_2', - ) - const registryFactory = await ethers.getContractFactory( - 'AutomationRegistry2_2', - ) - const forwarderLogicFactory = await ethers.getContractFactory( - 'AutomationForwarderLogic', - ) - const forwarderLogic = await forwarderLogicFactory.connect(from).deploy() - const logicB = await logicBFactory - .connect(from) - .deploy( - link, - linkNative, - fastgas, - forwarderLogic.address, - allowedReadOnlyAddress, - ) - const logicA = await logicAFactory.connect(from).deploy(logicB.address) - const master = await registryFactory.connect(from).deploy(logicA.address) - return IAutomationRegistryMasterFactory.connect(master.address, from) -} - export const deployRegistry23 = async ( from: Signer, link: Parameters[0], diff --git a/contracts/test/v0.8/operatorforwarder/AuthorizedForwarder.test.ts b/contracts/test/v0.8/operatorforwarder/AuthorizedForwarder.test.ts index d4e1918c976..6530a2f3c4e 100644 --- a/contracts/test/v0.8/operatorforwarder/AuthorizedForwarder.test.ts +++ b/contracts/test/v0.8/operatorforwarder/AuthorizedForwarder.test.ts @@ -22,7 +22,7 @@ before(async () => { roles.defaultAccount, ) brokenFactory = await ethers.getContractFactory( - 'src/v0.8/tests/Broken.sol:Broken', + 'src/v0.8/operatorforwarder/test/Broken.sol:Broken', roles.defaultAccount, ) forwarderFactory = await ethers.getContractFactory( diff --git a/core/bridges/mocks/orm.go b/core/bridges/mocks/orm.go index 54dd6ef4d3c..d1ecd7c6adc 100644 --- a/core/bridges/mocks/orm.go +++ b/core/bridges/mocks/orm.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/build/platform_arch_guard.go b/core/build/platform_arch_guard.go new file mode 100644 index 00000000000..3a22f7df537 --- /dev/null +++ b/core/build/platform_arch_guard.go @@ -0,0 +1,3 @@ +//go:build !amd64 && !arm64 +package build +"non-64-bits architectures are not supported" diff --git a/core/capabilities/ccip/ccip_integration_tests/integrationhelpers/integration_helpers.go b/core/capabilities/ccip/ccip_integration_tests/integrationhelpers/integration_helpers.go index ea52438edad..4d016d9bd98 100644 --- a/core/capabilities/ccip/ccip_integration_tests/integrationhelpers/integration_helpers.go +++ b/core/capabilities/ccip/ccip_integration_tests/integrationhelpers/integration_helpers.go @@ -33,7 +33,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -420,7 +420,7 @@ func GenerateRMNHomeConfigs( SourceChains: []rmn_home.RMNHomeSourceChain{ { ChainSelector: chainSelector, - F: f, + FObserve: f, ObserverNodesBitmap: observerBitmap, }, }, diff --git a/core/capabilities/ccip/ccip_integration_tests/usdcreader/usdcreader_test.go b/core/capabilities/ccip/ccip_integration_tests/usdcreader/usdcreader_test.go index efa4f193ed9..9a786aaf029 100644 --- a/core/capabilities/ccip/ccip_integration_tests/usdcreader/usdcreader_test.go +++ b/core/capabilities/ccip/ccip_integration_tests/usdcreader/usdcreader_test.go @@ -23,11 +23,12 @@ import ( ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" + "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-ccip/pkg/contractreader" "github.com/smartcontractkit/chainlink-ccip/pkg/reader" cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink-ccip/pluginconfig" - "github.com/smartcontractkit/chainlink-common/pkg/types" evmconfig "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/configs/evm" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" @@ -195,7 +196,7 @@ func Test_USDCReader_MessageHashes(t *testing.T) { for _, tc := range tt { t.Run(tc.name, func(t *testing.T) { - hashes, err1 := usdcReader.MessageHashes(ctx, tc.sourceChain, tc.destChain, tc.tokens) + hashes, err1 := usdcReader.MessagesByTokenID(ctx, tc.sourceChain, tc.destChain, tc.tokens) require.NoError(t, err1) require.Equal(t, len(tc.expectedMsgIDs), len(hashes)) @@ -270,7 +271,7 @@ func Benchmark_MessageHashes(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { - hashes, err := usdcReader.MessageHashes(ctx, sourceChain, destChain, tokens) + hashes, err := usdcReader.MessagesByTokenID(ctx, sourceChain, destChain, tokens) require.NoError(b, err) require.Len(b, hashes, tc.tokenCount) // Ensure the number of matches is as expected } diff --git a/core/capabilities/ccip/ccipevm/extraargscodec.go b/core/capabilities/ccip/ccipevm/extraargscodec.go new file mode 100644 index 00000000000..8cd8bda48f7 --- /dev/null +++ b/core/capabilities/ccip/ccipevm/extraargscodec.go @@ -0,0 +1,16 @@ +package ccipevm + +import ( + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" +) + +type ExtraArgsCodec struct{} + +func NewExtraArgsCodec() ExtraArgsCodec { + return ExtraArgsCodec{} +} + +func (ExtraArgsCodec) DecodeExtraData(extraArgs cciptypes.Bytes, sourceChainSelector cciptypes.ChainSelector) (map[string]any, error) { + // Not implemented and not return error + return nil, nil +} diff --git a/core/capabilities/ccip/ccipevm/gas_helpers.go b/core/capabilities/ccip/ccipevm/gas_helpers.go index 2706650f48e..838c78f8fb8 100644 --- a/core/capabilities/ccip/ccipevm/gas_helpers.go +++ b/core/capabilities/ccip/ccipevm/gas_helpers.go @@ -4,13 +4,17 @@ import ( "fmt" "math" + "github.com/pkg/errors" + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" ) const ( EvmAddressLengthBytes = 20 EvmWordBytes = 32 - CalldataGasPerByte = 16 + CalldataGasPerByteBase = 16 + CalldataGasPerByteHigh = 40 + CalldataGasPerByteThreshold = 3000 TokenAdminRegistryWarmupCost = 2_500 TokenAdminRegistryPoolLookupGas = 100 + // WARM_ACCESS_COST TokenAdminRegistry 700 + // CALL cost for TokenAdminRegistry @@ -44,7 +48,7 @@ func (gp EstimateProvider) CalculateMerkleTreeGas(numRequests int) uint64 { return 0 } merkleProofBytes := (math.Ceil(math.Log2(float64(numRequests))))*32 + (1+2)*32 // only ever one outer root hash - return uint64(merkleProofBytes * CalldataGasPerByte) + return uint64(merkleProofBytes * CalldataGasPerByteBase) } // return the size of bytes for msg tokens @@ -86,7 +90,11 @@ func (gp EstimateProvider) CalculateMessageMaxGasWithError(msg cciptypes.Message bytesForMsgTokens(numTokens) + dataLength - messageCallDataGas := uint64(messageBytes * CalldataGasPerByte) + if messageBytes < 0 { + return 0, errors.New("message bytes cannot be negative") + } + + messageCallDataGas := uint64(messageBytes) * CalldataGasPerByteBase // Rate limiter only limits value in tokens. It's not called if there are no // tokens in the message. The same goes for the admin registry, it's only loaded diff --git a/core/capabilities/ccip/common/common_test.go b/core/capabilities/ccip/common/common_test.go index a7484a83ad9..156499021fa 100644 --- a/core/capabilities/ccip/common/common_test.go +++ b/core/capabilities/ccip/common/common_test.go @@ -11,7 +11,7 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" ) diff --git a/core/capabilities/ccip/configs/evm/contract_reader.go b/core/capabilities/ccip/configs/evm/contract_reader.go index dca590094f8..857235661a6 100644 --- a/core/capabilities/ccip/configs/evm/contract_reader.go +++ b/core/capabilities/ccip/configs/evm/contract_reader.go @@ -20,8 +20,8 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_remote" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/aggregator_v3_interface" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/aggregator_v3_interface" evmrelaytypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) @@ -33,7 +33,7 @@ var ( nonceManagerABI = evmtypes.MustGetABI(nonce_manager.NonceManagerABI) priceFeedABI = evmtypes.MustGetABI(aggregator_v3_interface.AggregatorV3InterfaceABI) rmnRemoteABI = evmtypes.MustGetABI(rmn_remote.RMNRemoteABI) - rmnProxyABI = evmtypes.MustGetABI(rmn_proxy_contract.RMNProxyContractABI) + rmnProxyABI = evmtypes.MustGetABI(rmn_proxy_contract.RMNProxyABI) rmnHomeABI = evmtypes.MustGetABI(rmn_home.RMNHomeABI) routerABI = evmtypes.MustGetABI(router.RouterABI) ) @@ -190,7 +190,7 @@ var DestReaderConfig = evmrelaytypes.ChainReaderConfig{ }, }, consts.ContractNameRMNProxy: { - ContractABI: rmn_proxy_contract.RMNProxyContractABI, + ContractABI: rmn_proxy_contract.RMNProxyABI, Configs: map[string]*evmrelaytypes.ChainReaderDefinition{ consts.MethodNameGetARM: { ChainSpecificName: mustGetMethodName("getARM", rmnProxyABI), diff --git a/core/capabilities/ccip/delegate.go b/core/capabilities/ccip/delegate.go index 1af4f44cd4a..93004a80f04 100644 --- a/core/capabilities/ccip/delegate.go +++ b/core/capabilities/ccip/delegate.go @@ -35,7 +35,7 @@ import ( cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" "github.com/smartcontractkit/chainlink/v2/core/config" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" @@ -170,7 +170,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) (services hcr := ccipreaderpkg.NewObservedHomeChainReader( homeChainContractReader, d.lggr.Named("HomeChainReader"), - 100*time.Millisecond, + 15*time.Second, ccipConfigBinding, d.capabilityConfig.ExternalRegistry().ChainID(), ) diff --git a/core/capabilities/ccip/launcher/deployment.go b/core/capabilities/ccip/launcher/deployment.go index 870c0409494..c2d59a19cf2 100644 --- a/core/capabilities/ccip/launcher/deployment.go +++ b/core/capabilities/ccip/launcher/deployment.go @@ -2,6 +2,7 @@ package launcher import ( "fmt" + mapset "github.com/deckarep/golang-set/v2" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "golang.org/x/exp/maps" diff --git a/core/capabilities/ccip/launcher/diff_test.go b/core/capabilities/ccip/launcher/diff_test.go index a098bf816ab..1c049a0e3d1 100644 --- a/core/capabilities/ccip/launcher/diff_test.go +++ b/core/capabilities/ccip/launcher/diff_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/require" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" "github.com/smartcontractkit/chainlink/v2/core/services/registrysyncer" diff --git a/core/capabilities/ccip/launcher/launcher.go b/core/capabilities/ccip/launcher/launcher.go index 76a6c204058..5e4aef934a0 100644 --- a/core/capabilities/ccip/launcher/launcher.go +++ b/core/capabilities/ccip/launcher/launcher.go @@ -23,7 +23,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" ) var ( @@ -294,7 +294,6 @@ func (l *launcher) processRemoved(removed map[registrysyncer.DonID]registrysynce if err := p.CloseAll(); err != nil { return fmt.Errorf("failed to shutdown oracles for CCIP DON %d: %w", id, err) - } // after a successful shutdown we can safely remove the DON deployment from the map. diff --git a/core/capabilities/ccip/ocrimpls/contract_transmitter.go b/core/capabilities/ccip/ocrimpls/contract_transmitter.go index e89acac7baa..478bdaed3ad 100644 --- a/core/capabilities/ccip/ocrimpls/contract_transmitter.go +++ b/core/capabilities/ccip/ocrimpls/contract_transmitter.go @@ -7,18 +7,30 @@ import ( "math/big" "github.com/google/uuid" + "github.com/smartcontractkit/libocr/offchainreporting2/chains/evmutil" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/smartcontractkit/chainlink-ccip/pkg/consts" + "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" ) -type ToCalldataFunc func(rawReportCtx [2][32]byte, report []byte, rs, ss [][32]byte, vs [32]byte) any - -func ToCommitCalldata(rawReportCtx [2][32]byte, report []byte, rs, ss [][32]byte, vs [32]byte) any { +type ToCalldataFunc func( + rawReportCtx [2][32]byte, + report ocr3types.ReportWithInfo[[]byte], + rs, ss [][32]byte, + vs [32]byte, +) (any, error) + +func ToCommitCalldata( + rawReportCtx [2][32]byte, + report ocr3types.ReportWithInfo[[]byte], + rs, ss [][32]byte, + vs [32]byte, +) (any, error) { // Note that the name of the struct field is very important, since the encoder used // by the chainwriter uses mapstructure, which will use the struct field name to map // to the argument name in the function call. @@ -36,14 +48,19 @@ func ToCommitCalldata(rawReportCtx [2][32]byte, report []byte, rs, ss [][32]byte RawVs [32]byte }{ ReportContext: rawReportCtx, - Report: report, + Report: report.Report, Rs: rs, Ss: ss, RawVs: vs, - } + }, nil } -func ToExecCalldata(rawReportCtx [2][32]byte, report []byte, _, _ [][32]byte, _ [32]byte) any { +func ToExecCalldata( + rawReportCtx [2][32]byte, + report ocr3types.ReportWithInfo[[]byte], + _, _ [][32]byte, + _ [32]byte, +) (any, error) { // Note that the name of the struct field is very important, since the encoder used // by the chainwriter uses mapstructure, which will use the struct field name to map // to the argument name in the function call. @@ -53,18 +70,29 @@ func ToExecCalldata(rawReportCtx [2][32]byte, report []byte, _, _ [][32]byte, _ // WARNING: Be careful if you change the data types. // Using a different type e.g. `type Foo [32]byte` instead of `[32]byte` // will trigger undefined chainWriter behavior, e.g. transactions submitted with wrong arguments. + var info ccipocr3.ExecuteReportInfo + if len(report.Info) != 0 { + var err error + info, err = ccipocr3.DecodeExecuteReportInfo(report.Info) + if err != nil { + return nil, err + } + } + return struct { ReportContext [2][32]byte Report []byte + Info ccipocr3.ExecuteReportInfo }{ ReportContext: rawReportCtx, - Report: report, - } + Report: report.Report, + Info: info, + }, nil } -var _ ocr3types.ContractTransmitter[[]byte] = &commitTransmitter[[]byte]{} +var _ ocr3types.ContractTransmitter[[]byte] = &commitTransmitter{} -type commitTransmitter[RI any] struct { +type commitTransmitter struct { cw commontypes.ContractWriter fromAccount ocrtypes.Account contractName string @@ -73,15 +101,15 @@ type commitTransmitter[RI any] struct { toCalldataFn ToCalldataFunc } -func XXXNewContractTransmitterTestsOnly[RI any]( +func XXXNewContractTransmitterTestsOnly( cw commontypes.ContractWriter, fromAccount ocrtypes.Account, contractName string, method string, offrampAddress string, toCalldataFn ToCalldataFunc, -) ocr3types.ContractTransmitter[RI] { - return &commitTransmitter[RI]{ +) ocr3types.ContractTransmitter[[]byte] { + return &commitTransmitter{ cw: cw, fromAccount: fromAccount, contractName: contractName, @@ -91,12 +119,12 @@ func XXXNewContractTransmitterTestsOnly[RI any]( } } -func NewCommitContractTransmitter[RI any]( +func NewCommitContractTransmitter( cw commontypes.ContractWriter, fromAccount ocrtypes.Account, offrampAddress string, -) ocr3types.ContractTransmitter[RI] { - return &commitTransmitter[RI]{ +) ocr3types.ContractTransmitter[[]byte] { + return &commitTransmitter{ cw: cw, fromAccount: fromAccount, contractName: consts.ContractNameOffRamp, @@ -106,12 +134,12 @@ func NewCommitContractTransmitter[RI any]( } } -func NewExecContractTransmitter[RI any]( +func NewExecContractTransmitter( cw commontypes.ContractWriter, fromAccount ocrtypes.Account, offrampAddress string, -) ocr3types.ContractTransmitter[RI] { - return &commitTransmitter[RI]{ +) ocr3types.ContractTransmitter[[]byte] { + return &commitTransmitter{ cw: cw, fromAccount: fromAccount, contractName: consts.ContractNameOffRamp, @@ -122,16 +150,16 @@ func NewExecContractTransmitter[RI any]( } // FromAccount implements ocr3types.ContractTransmitter. -func (c *commitTransmitter[RI]) FromAccount(context.Context) (ocrtypes.Account, error) { +func (c *commitTransmitter) FromAccount(context.Context) (ocrtypes.Account, error) { return c.fromAccount, nil } // Transmit implements ocr3types.ContractTransmitter. -func (c *commitTransmitter[RI]) Transmit( +func (c *commitTransmitter) Transmit( ctx context.Context, configDigest ocrtypes.ConfigDigest, seqNr uint64, - reportWithInfo ocr3types.ReportWithInfo[RI], + reportWithInfo ocr3types.ReportWithInfo[[]byte], sigs []ocrtypes.AttributedOnchainSignature, ) error { var rs [][32]byte @@ -160,7 +188,10 @@ func (c *commitTransmitter[RI]) Transmit( } // chain writer takes in the raw calldata and packs it on its own. - args := c.toCalldataFn(rawReportCtx, reportWithInfo.Report, rs, ss, vs) + args, err := c.toCalldataFn(rawReportCtx, reportWithInfo, rs, ss, vs) + if err != nil { + return fmt.Errorf("failed to generate call data: %w", err) + } // TODO: no meta fields yet, what should we add? // probably whats in the info part of the report? diff --git a/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go b/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go index 16546b26999..adc4057fd56 100644 --- a/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go +++ b/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go @@ -103,7 +103,7 @@ func testTransmitter( report []byte, ) { ctx := tests.Context(t) - uni := newTestUniverse[[]byte](t, nil) + uni := newTestUniverse(t, nil) c, err := uni.wrapper.LatestConfigDetails(nil, pluginType) require.NoError(t, err, "failed to get latest config details") @@ -199,7 +199,7 @@ type keyringsAndSigners[RI any] struct { signers []common.Address } -func newTestUniverse[RI any](t *testing.T, ks *keyringsAndSigners[RI]) *testUniverse[RI] { +func newTestUniverse(t *testing.T, ks *keyringsAndSigners[[]byte]) *testUniverse[[]byte] { t.Helper() db := pgtest.NewSqlxDB(t) @@ -233,7 +233,7 @@ func newTestUniverse[RI any](t *testing.T, ks *keyringsAndSigners[RI]) *testUniv // create the oracle identities for setConfig // need to create at least 4 identities otherwise setConfig will fail var ( - keyrings []ocr3types.OnchainKeyring[RI] + keyrings []ocr3types.OnchainKeyring[[]byte] signers []common.Address ) if ks != nil { @@ -243,7 +243,7 @@ func newTestUniverse[RI any](t *testing.T, ks *keyringsAndSigners[RI]) *testUniv for i := 0; i < 4; i++ { kb, err2 := ocr2key.New(kschaintype.EVM) require.NoError(t, err2, "failed to create key") - kr := ocrimpls.NewOnchainKeyring[RI](kb, logger.TestLogger(t)) + kr := ocrimpls.NewOnchainKeyring[[]byte](kb, logger.TestLogger(t)) signers = append(signers, common.BytesToAddress(kr.PublicKey())) keyrings = append(keyrings, kr) } @@ -309,7 +309,7 @@ func newTestUniverse[RI any](t *testing.T, ks *keyringsAndSigners[RI]) *testUniv require.NoError(t, chainWriter.Start(testutils.Context(t)), "failed to start chain writer") t.Cleanup(func() { require.NoError(t, chainWriter.Close()) }) - transmitterWithSigs := ocrimpls.XXXNewContractTransmitterTestsOnly[RI]( + transmitterWithSigs := ocrimpls.XXXNewContractTransmitterTestsOnly( chainWriter, ocrtypes.Account(transmitters[0].Hex()), contractName, @@ -317,7 +317,7 @@ func newTestUniverse[RI any](t *testing.T, ks *keyringsAndSigners[RI]) *testUniv ocr3HelperAddr.Hex(), ocrimpls.ToCommitCalldata, ) - transmitterWithoutSigs := ocrimpls.XXXNewContractTransmitterTestsOnly[RI]( + transmitterWithoutSigs := ocrimpls.XXXNewContractTransmitterTestsOnly( chainWriter, ocrtypes.Account(transmitters[0].Hex()), contractName, @@ -326,7 +326,7 @@ func newTestUniverse[RI any](t *testing.T, ks *keyringsAndSigners[RI]) *testUniv ocrimpls.ToExecCalldata, ) - return &testUniverse[RI]{ + return &testUniverse[[]byte]{ simClient: simClient, backend: backend, deployer: owner, @@ -476,7 +476,8 @@ func makeTestEvmTxm( lp, keyStore, estimator, - ht) + ht, + nil) require.NoError(t, err, "can't create tx manager") _, unsub := broadcaster.Subscribe(txm) diff --git a/core/capabilities/ccip/oraclecreator/bootstrap.go b/core/capabilities/ccip/oraclecreator/bootstrap.go index 8dfe3e99ffb..4f9f44a9cf0 100644 --- a/core/capabilities/ccip/oraclecreator/bootstrap.go +++ b/core/capabilities/ccip/oraclecreator/bootstrap.go @@ -12,6 +12,7 @@ import ( "time" mapset "github.com/deckarep/golang-set/v2" + logger2 "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/smartcontractkit/libocr/networking" @@ -239,8 +240,8 @@ type peerGroupDialer struct { oraclePeerIDs []ragep2ptypes.PeerID commitConfigDigest [32]byte - activePeerGroups []networking.PeerGroup - activeConfigDigests []cciptypes.Bytes32 + activePeerGroups []networking.PeerGroup + activeEndpointConfigDigests []cciptypes.Bytes32 syncInterval time.Duration @@ -249,8 +250,9 @@ type peerGroupDialer struct { } type syncAction struct { - actionType actionType - configDigest cciptypes.Bytes32 + actionType actionType + endpointConfigDigest cciptypes.Bytes32 + rmnHomeConfigDigest cciptypes.Bytes32 } type actionType string @@ -328,21 +330,31 @@ func (d *peerGroupDialer) Close() error { // Pure function for calculating sync actions func calculateSyncActions( - currentConfigDigests []cciptypes.Bytes32, - activeConfigDigest cciptypes.Bytes32, - candidateConfigDigest cciptypes.Bytes32, + commitConfigDigest cciptypes.Bytes32, + currentEndpointConfigDigests []cciptypes.Bytes32, + activeRmnHomeConfigDigest cciptypes.Bytes32, + candidateRmnHomeConfigDigest cciptypes.Bytes32, ) []syncAction { current := mapset.NewSet[cciptypes.Bytes32]() - for _, digest := range currentConfigDigests { + for _, digest := range currentEndpointConfigDigests { current.Add(digest) } + endpointDigestToRmnHomeDigest := make(map[cciptypes.Bytes32]cciptypes.Bytes32, 2) + desired := mapset.NewSet[cciptypes.Bytes32]() - if !activeConfigDigest.IsEmpty() { - desired.Add(activeConfigDigest) + if !activeRmnHomeConfigDigest.IsEmpty() { + endpointDigest := writePrefix(ocr2types.ConfigDigestPrefixCCIPMultiRoleRMNCombo, + sha256.Sum256(append(commitConfigDigest[:], activeRmnHomeConfigDigest[:]...))) + desired.Add(endpointDigest) + endpointDigestToRmnHomeDigest[endpointDigest] = activeRmnHomeConfigDigest } - if !candidateConfigDigest.IsEmpty() { - desired.Add(candidateConfigDigest) + + if !candidateRmnHomeConfigDigest.IsEmpty() { + endpointDigest := writePrefix(ocr2types.ConfigDigestPrefixCCIPMultiRoleRMNCombo, + sha256.Sum256(append(commitConfigDigest[:], candidateRmnHomeConfigDigest[:]...))) + desired.Add(endpointDigest) + endpointDigestToRmnHomeDigest[endpointDigest] = candidateRmnHomeConfigDigest } closeCount := current.Difference(desired).Cardinality() @@ -352,16 +364,18 @@ func calculateSyncActions( // Configs to close: in current but not in desired for digest := range current.Difference(desired).Iterator().C { actions = append(actions, syncAction{ - actionType: ActionClose, - configDigest: digest, + actionType: ActionClose, + rmnHomeConfigDigest: endpointDigestToRmnHomeDigest[digest], + endpointConfigDigest: digest, }) } // Configs to create: in desired but not in current for digest := range desired.Difference(current).Iterator().C { actions = append(actions, syncAction{ - actionType: ActionCreate, - configDigest: digest, + actionType: ActionCreate, + rmnHomeConfigDigest: endpointDigestToRmnHomeDigest[digest], + endpointConfigDigest: digest, }) } @@ -372,25 +386,39 @@ func (d *peerGroupDialer) sync() { d.mu.Lock() defer d.mu.Unlock() - activeDigest, candidateDigest := d.rmnHomeReader.GetAllConfigDigests() - actions := calculateSyncActions(d.activeConfigDigests, activeDigest, candidateDigest) + activeRmnHomeDigest, candidateRmnHomeDigest := d.rmnHomeReader.GetAllConfigDigests() + + lggr := logger2.With( + d.lggr, + "method", "sync", + "activeRmnHomeDigest", activeRmnHomeDigest.String(), + "candidateRmnHomeDigest", candidateRmnHomeDigest.String(), + "activeEndpointConfigDigests", fmt.Sprintf("%s", d.activeEndpointConfigDigests), + ) + + actions := calculateSyncActions( + d.commitConfigDigest, d.activeEndpointConfigDigests, activeRmnHomeDigest, candidateRmnHomeDigest) if len(actions) == 0 { - d.lggr.Debugw("No peer group actions needed") + lggr.Debugw("No peer group actions needed") return } - d.lggr.Infow("Syncing peer groups", "actions", actions) + lggr.Infof("Syncing peer groups by applying the actions: %v", actions) // Handle each action for _, action := range actions { + actionLggr := logger2.With(lggr, + "action", action.actionType, + "endpointConfigDigest", action.endpointConfigDigest, + "rmnHomeConfigDigest", action.rmnHomeConfigDigest) + switch action.actionType { case ActionClose: - d.closePeerGroup(action.configDigest) + d.closePeerGroup(action.endpointConfigDigest) + actionLggr.Infow("Peer group closed successfully") case ActionCreate: - if err := d.createPeerGroup(action.configDigest); err != nil { - d.lggr.Errorw("Failed to create peer group", - "configDigest", action.configDigest, - "err", err) + if err := d.createPeerGroup(action.endpointConfigDigest, action.rmnHomeConfigDigest); err != nil { + actionLggr.Errorw("Failed to create peer group", "err", err) // Consider closing all groups on error d.closeExistingPeerGroups() return @@ -400,53 +428,43 @@ func (d *peerGroupDialer) sync() { } // Helper function to close specific peer group -func (d *peerGroupDialer) closePeerGroup(configDigest cciptypes.Bytes32) { - for i, digest := range d.activeConfigDigests { - if digest == configDigest { +func (d *peerGroupDialer) closePeerGroup(endpointConfigDigest cciptypes.Bytes32) { + lggr := d.lggr.With("genericEndpointConfigDigest", endpointConfigDigest.String()) + + for i, digest := range d.activeEndpointConfigDigests { + if digest == endpointConfigDigest { if err := d.activePeerGroups[i].Close(); err != nil { - d.lggr.Warnw("Failed to close peer group", - "configDigest", configDigest, - "err", err) + lggr.Warnw("Failed to close peer group", "err", err) } else { - d.lggr.Infow("Closed peer group successfully", - "configDigest", configDigest) + d.lggr.Infow("Closed peer group successfully") } + // Remove from active groups and digests d.activePeerGroups = append(d.activePeerGroups[:i], d.activePeerGroups[i+1:]...) - d.activeConfigDigests = append(d.activeConfigDigests[:i], d.activeConfigDigests[i+1:]...) + d.activeEndpointConfigDigests = append( + d.activeEndpointConfigDigests[:i], d.activeEndpointConfigDigests[i+1:]...) return } } } -func (d *peerGroupDialer) createPeerGroup(rmnHomeConfigDigest cciptypes.Bytes32) error { +func (d *peerGroupDialer) createPeerGroup( + endpointConfigDigest cciptypes.Bytes32, + rmnHomeConfigDigest cciptypes.Bytes32, +) error { rmnNodesInfo, err := d.rmnHomeReader.GetRMNNodesInfo(rmnHomeConfigDigest) if err != nil { return fmt.Errorf("get RMN nodes info: %w", err) } - // Create generic endpoint config digest by hashing commit config digest and rmn home config digest - h := sha256.Sum256(append(d.commitConfigDigest[:], rmnHomeConfigDigest[:]...)) - genericEndpointConfigDigest := writePrefix(ocr2types.ConfigDigestPrefixCCIPMultiRoleRMNCombo, h) - - // Combine oracle peer IDs with RMN node peer IDs - peerIDs := make([]string, 0, len(d.oraclePeerIDs)+len(rmnNodesInfo)) - for _, p := range d.oraclePeerIDs { - peerIDs = append(peerIDs, p.String()) - } - for _, n := range rmnNodesInfo { - peerIDs = append(peerIDs, n.PeerID.String()) - } - lggr := d.lggr.With( - "genericEndpointConfigDigest", genericEndpointConfigDigest.String(), - "peerIDs", peerIDs, - "bootstrappers", d.bootstrapLocators, + "genericEndpointConfigDigest", endpointConfigDigest.String(), + "rmnHomeConfigDigest", rmnHomeConfigDigest.String(), ) lggr.Infow("Creating new peer group") peerGroup, err := d.peerGroupCreator.Create(peergroup.CreateOpts{ - CommitConfigDigest: cciptypes.Bytes32(d.commitConfigDigest), + CommitConfigDigest: d.commitConfigDigest, RMNHomeConfigDigest: rmnHomeConfigDigest, OraclePeerIDs: d.oraclePeerIDs, RMNNodes: rmnNodesInfo, @@ -454,10 +472,11 @@ func (d *peerGroupDialer) createPeerGroup(rmnHomeConfigDigest cciptypes.Bytes32) if err != nil { return fmt.Errorf("new peer group: %w", err) } + lggr.Infow("Created new peer group successfully") d.activePeerGroups = append(d.activePeerGroups, peerGroup.PeerGroup) - d.activeConfigDigests = append(d.activeConfigDigests, genericEndpointConfigDigest) + d.activeEndpointConfigDigests = append(d.activeEndpointConfigDigests, endpointConfigDigest) return nil } @@ -473,7 +492,7 @@ func (d *peerGroupDialer) closeExistingPeerGroups() { } d.activePeerGroups = []networking.PeerGroup{} - d.activeConfigDigests = []cciptypes.Bytes32{} + d.activeEndpointConfigDigests = []cciptypes.Bytes32{} } func writePrefix(prefix ocr2types.ConfigDigestPrefix, hash cciptypes.Bytes32) cciptypes.Bytes32 { diff --git a/core/capabilities/ccip/oraclecreator/bootstrap_test.go b/core/capabilities/ccip/oraclecreator/bootstrap_test.go index 1b1cc9dc0d2..95887cc2684 100644 --- a/core/capabilities/ccip/oraclecreator/bootstrap_test.go +++ b/core/capabilities/ccip/oraclecreator/bootstrap_test.go @@ -2,9 +2,11 @@ package oraclecreator import ( "bytes" + "crypto/sha256" "sort" "testing" + ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/stretchr/testify/require" cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" @@ -31,7 +33,7 @@ func TestCalculateSyncActions(t *testing.T) { activeDigest: cciptypes.Bytes32{1}, candidateDigest: cciptypes.Bytes32{}, // empty expectedActions: []syncAction{ - {actionType: ActionClose, configDigest: cciptypes.Bytes32{2}}, + {actionType: ActionClose, endpointConfigDigest: cciptypes.Bytes32{2}}, }, }, { @@ -40,7 +42,7 @@ func TestCalculateSyncActions(t *testing.T) { activeDigest: cciptypes.Bytes32{1}, candidateDigest: cciptypes.Bytes32{2}, expectedActions: []syncAction{ - {actionType: ActionCreate, configDigest: cciptypes.Bytes32{2}}, + {actionType: ActionCreate, endpointConfigDigest: cciptypes.Bytes32{2}}, }, }, { @@ -49,8 +51,8 @@ func TestCalculateSyncActions(t *testing.T) { activeDigest: cciptypes.Bytes32{}, candidateDigest: cciptypes.Bytes32{}, expectedActions: []syncAction{ - {actionType: ActionClose, configDigest: cciptypes.Bytes32{1}}, - {actionType: ActionClose, configDigest: cciptypes.Bytes32{2}}, + {actionType: ActionClose, endpointConfigDigest: cciptypes.Bytes32{1}}, + {actionType: ActionClose, endpointConfigDigest: cciptypes.Bytes32{2}}, }, }, { @@ -59,18 +61,27 @@ func TestCalculateSyncActions(t *testing.T) { activeDigest: cciptypes.Bytes32{3}, candidateDigest: cciptypes.Bytes32{4}, expectedActions: []syncAction{ - {actionType: ActionClose, configDigest: cciptypes.Bytes32{1}}, - {actionType: ActionClose, configDigest: cciptypes.Bytes32{2}}, - {actionType: ActionCreate, configDigest: cciptypes.Bytes32{3}}, - {actionType: ActionCreate, configDigest: cciptypes.Bytes32{4}}, + {actionType: ActionClose, endpointConfigDigest: cciptypes.Bytes32{1}}, + {actionType: ActionClose, endpointConfigDigest: cciptypes.Bytes32{2}}, + {actionType: ActionCreate, endpointConfigDigest: cciptypes.Bytes32{3}}, + {actionType: ActionCreate, endpointConfigDigest: cciptypes.Bytes32{4}}, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + commitConfigDigest := cciptypes.Bytes32{1} + + currentDigests := make([]cciptypes.Bytes32, len(tt.currentDigests)) + for i, d := range tt.currentDigests { + currentDigests[i] = writePrefix(ocr2types.ConfigDigestPrefixCCIPMultiRoleRMNCombo, + sha256.Sum256(append(commitConfigDigest[:], d[:]...))) + } + actions := calculateSyncActions( - tt.currentDigests, + commitConfigDigest, + currentDigests, tt.activeDigest, tt.candidateDigest, ) @@ -82,18 +93,22 @@ func TestCalculateSyncActions(t *testing.T) { if actions[i].actionType != actions[j].actionType { return actions[i].actionType < actions[j].actionType } - return bytes.Compare(actions[i].configDigest[:], actions[j].configDigest[:]) < 0 + return bytes.Compare(actions[i].endpointConfigDigest[:], actions[j].endpointConfigDigest[:]) < 0 }) sort.Slice(tt.expectedActions, func(i, j int) bool { if tt.expectedActions[i].actionType != tt.expectedActions[j].actionType { return tt.expectedActions[i].actionType < tt.expectedActions[j].actionType } - return bytes.Compare(tt.expectedActions[i].configDigest[:], tt.expectedActions[j].configDigest[:]) < 0 + return bytes.Compare(tt.expectedActions[i].endpointConfigDigest[:], tt.expectedActions[j].endpointConfigDigest[:]) < 0 }) for i := range actions { require.Equal(t, tt.expectedActions[i].actionType, actions[i].actionType) - require.Equal(t, tt.expectedActions[i].configDigest, actions[i].configDigest) + + expEndpointConfigDigest := writePrefix(ocr2types.ConfigDigestPrefixCCIPMultiRoleRMNCombo, + sha256.Sum256(append(commitConfigDigest[:], tt.expectedActions[i].endpointConfigDigest[:]...))) + + require.Equal(t, expEndpointConfigDigest, actions[i].endpointConfigDigest) } }) } diff --git a/core/capabilities/ccip/oraclecreator/plugin.go b/core/capabilities/ccip/oraclecreator/plugin.go index a716d96418a..f791a804586 100644 --- a/core/capabilities/ccip/oraclecreator/plugin.go +++ b/core/capabilities/ccip/oraclecreator/plugin.go @@ -263,6 +263,7 @@ func (i *pluginOracleCreator) createFactoryAndTransmitter( ccipreaderpkg.OCR3ConfigWithMeta(config), ccipevm.NewCommitPluginCodecV1(), ccipevm.NewMessageHasherV1(i.lggr.Named("MessageHasherV1")), + ccipevm.NewExtraArgsCodec(), i.homeChainReader, i.homeChainSelector, contractReaders, @@ -271,7 +272,7 @@ func (i *pluginOracleCreator) createFactoryAndTransmitter( rmnCrypto, ) factory = promwrapper.NewReportingPluginFactory[[]byte](factory, i.lggr, chainID, "CCIPCommit") - transmitter = ocrimpls.NewCommitContractTransmitter[[]byte](destChainWriter, + transmitter = ocrimpls.NewCommitContractTransmitter(destChainWriter, ocrtypes.Account(destFromAccounts[0]), hexutil.Encode(config.Config.OfframpAddress), // TODO: this works for evm only, how about non-evm? ) @@ -285,6 +286,7 @@ func (i *pluginOracleCreator) createFactoryAndTransmitter( ccipreaderpkg.OCR3ConfigWithMeta(config), ccipevm.NewExecutePluginCodecV1(), ccipevm.NewMessageHasherV1(i.lggr.Named("MessageHasherV1")), + ccipevm.NewExtraArgsCodec(), i.homeChainReader, ccipevm.NewEVMTokenDataEncoder(), ccipevm.NewGasEstimateProvider(), @@ -292,7 +294,7 @@ func (i *pluginOracleCreator) createFactoryAndTransmitter( chainWriters, ) factory = promwrapper.NewReportingPluginFactory[[]byte](factory, i.lggr, chainID, "CCIPExec") - transmitter = ocrimpls.NewExecContractTransmitter[[]byte](destChainWriter, + transmitter = ocrimpls.NewExecContractTransmitter(destChainWriter, ocrtypes.Account(destFromAccounts[0]), hexutil.Encode(config.Config.OfframpAddress), // TODO: this works for evm only, how about non-evm? ) diff --git a/core/capabilities/ccip/types/mocks/ccip_oracle.go b/core/capabilities/ccip/types/mocks/ccip_oracle.go index 5ab860cc62e..5f1b7202e52 100644 --- a/core/capabilities/ccip/types/mocks/ccip_oracle.go +++ b/core/capabilities/ccip/types/mocks/ccip_oracle.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -17,7 +17,7 @@ func (_m *CCIPOracle) EXPECT() *CCIPOracle_Expecter { return &CCIPOracle_Expecter{mock: &_m.Mock} } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *CCIPOracle) Close() error { ret := _m.Called() @@ -62,7 +62,7 @@ func (_c *CCIPOracle_Close_Call) RunAndReturn(run func() error) *CCIPOracle_Clos return _c } -// Start provides a mock function with given fields: +// Start provides a mock function with no fields func (_m *CCIPOracle) Start() error { ret := _m.Called() diff --git a/core/capabilities/ccip/types/mocks/oracle_creator.go b/core/capabilities/ccip/types/mocks/oracle_creator.go index 1906df7e063..3618e70e7b7 100644 --- a/core/capabilities/ccip/types/mocks/oracle_creator.go +++ b/core/capabilities/ccip/types/mocks/oracle_creator.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -82,7 +82,7 @@ func (_c *OracleCreator_Create_Call) RunAndReturn(run func(context.Context, uint return _c } -// Type provides a mock function with given fields: +// Type provides a mock function with no fields func (_m *OracleCreator) Type() types.OracleType { ret := _m.Called() diff --git a/core/capabilities/compute/cache.go b/core/capabilities/compute/cache.go index dbcc42c1606..e15678a6e6d 100644 --- a/core/capabilities/compute/cache.go +++ b/core/capabilities/compute/cache.go @@ -1,6 +1,7 @@ package compute import ( + "fmt" "sync" "time" @@ -82,12 +83,18 @@ func (mc *moduleCache) reapLoop() { } } -func (mc *moduleCache) add(id string, mod *module) { +func (mc *moduleCache) add(id string, mod *module) error { mc.mu.Lock() defer mc.mu.Unlock() + + if mc.m[id] != nil { + return fmt.Errorf("module with id %q already exists in cache", id) + } + mod.lastFetchedAt = mc.clock.Now() mc.m[id] = mod moduleCacheAddition.Inc() + return nil } func (mc *moduleCache) get(id string) (*module, bool) { diff --git a/core/capabilities/compute/cache_test.go b/core/capabilities/compute/cache_test.go index ad075f493b5..fb55eba285b 100644 --- a/core/capabilities/compute/cache_test.go +++ b/core/capabilities/compute/cache_test.go @@ -1,6 +1,7 @@ package compute import ( + "fmt" "testing" "time" @@ -16,8 +17,8 @@ import ( ) const ( - binaryLocation = "test/simple/cmd/testmodule.wasm" - binaryCmd = "core/capabilities/compute/test/simple/cmd" + simpleBinaryLocation = "test/simple/cmd/testmodule.wasm" + simpleBinaryCmd = "core/capabilities/compute/test/simple/cmd" ) // Verify that cache evicts an expired module. @@ -34,7 +35,7 @@ func TestCache(t *testing.T) { cache.start() defer cache.close() - binary := wasmtest.CreateTestBinary(binaryCmd, binaryLocation, false, t) + binary := wasmtest.CreateTestBinary(simpleBinaryCmd, simpleBinaryLocation, false, t) hmod, err := host.NewModule(&host.ModuleConfig{ Logger: logger.TestLogger(t), IsUncompressed: true, @@ -74,7 +75,7 @@ func TestCache_EvictAfterSize(t *testing.T) { cache.start() defer cache.close() - binary := wasmtest.CreateTestBinary(binaryCmd, binaryLocation, false, t) + binary := wasmtest.CreateTestBinary(simpleBinaryCmd, simpleBinaryLocation, false, t) hmod, err := host.NewModule(&host.ModuleConfig{ Logger: logger.TestLogger(t), IsUncompressed: true, @@ -103,3 +104,55 @@ func TestCache_EvictAfterSize(t *testing.T) { _, ok = cache.get(id) assert.True(t, ok) } + +func TestCache_AddDuplicatedModule(t *testing.T) { + t.Parallel() + clock := clockwork.NewFakeClock() + tick := 1 * time.Second + timeout := 1 * time.Second + reapTicker := make(chan time.Time) + + cache := newModuleCache(clock, tick, timeout, 0) + cache.onReaper = make(chan struct{}, 1) + cache.reapTicker = reapTicker + cache.start() + defer cache.close() + + simpleBinary := wasmtest.CreateTestBinary(simpleBinaryCmd, simpleBinaryLocation, false, t) + shmod, err := host.NewModule(&host.ModuleConfig{ + Logger: logger.TestLogger(t), + IsUncompressed: true, + }, simpleBinary) + require.NoError(t, err) + + // we will use the same id for both modules, but should only be associated to the simple module + duplicatedID := uuid.New().String() + smod := &module{ + module: shmod, + } + err = cache.add(duplicatedID, smod) + require.NoError(t, err) + + got, ok := cache.get(duplicatedID) + assert.True(t, ok) + assert.Equal(t, got, smod) + + // Adding a different module but with the same id should not overwrite the existing module + fetchBinary := wasmtest.CreateTestBinary(fetchBinaryCmd, fetchBinaryLocation, false, t) + fhmod, err := host.NewModule(&host.ModuleConfig{ + Logger: logger.TestLogger(t), + IsUncompressed: true, + }, fetchBinary) + require.NoError(t, err) + + fmod := &module{ + module: fhmod, + } + err = cache.add(duplicatedID, fmod) + require.ErrorContains(t, err, fmt.Sprintf("module with id %q already exists in cache", duplicatedID)) + + // validate that the module is still the same + got, ok = cache.get(duplicatedID) + assert.True(t, ok) + assert.Equal(t, got, smod) +} diff --git a/core/capabilities/compute/compute.go b/core/capabilities/compute/compute.go index 2ba5daefaa6..4508d47534e 100644 --- a/core/capabilities/compute/compute.go +++ b/core/capabilities/compute/compute.go @@ -197,7 +197,10 @@ func (c *Compute) initModule(id string, cfg *host.ModuleConfig, binary []byte, r computeWASMInit.WithLabelValues(requestMetadata.WorkflowID, requestMetadata.ReferenceID).Observe(float64(initDuration)) m := &module{module: mod} - c.modules.add(id, m) + err = c.modules.add(id, m) + if err != nil { + c.log.Warnf("failed to add module to cache: %s", err.Error()) + } return m, nil } @@ -300,7 +303,7 @@ func (c *Compute) createFetcher() func(ctx context.Context, req *wasmpb.FetchReq cma := c.emitter.With( platform.KeyWorkflowID, req.Metadata.WorkflowId, - platform.KeyWorkflowName, req.Metadata.WorkflowName, + platform.KeyWorkflowName, req.Metadata.DecodedWorkflowName, platform.KeyWorkflowOwner, req.Metadata.WorkflowOwner, platform.KeyWorkflowExecutionID, req.Metadata.WorkflowExecutionId, timestampKey, time.Now().UTC().Format(time.RFC3339Nano), diff --git a/core/capabilities/compute/compute_test.go b/core/capabilities/compute/compute_test.go index 3e5f501fa61..98c8223409d 100644 --- a/core/capabilities/compute/compute_test.go +++ b/core/capabilities/compute/compute_test.go @@ -91,7 +91,7 @@ func TestComputeExecuteMissingConfig(t *testing.T) { th := setup(t, defaultConfig) require.NoError(t, th.compute.Start(tests.Context(t))) - binary := wasmtest.CreateTestBinary(binaryCmd, binaryLocation, true, t) + binary := wasmtest.CreateTestBinary(simpleBinaryCmd, simpleBinaryLocation, true, t) config, err := values.WrapMap(map[string]any{ "binary": binary, @@ -134,7 +134,7 @@ func TestComputeExecute(t *testing.T) { require.NoError(t, th.compute.Start(tests.Context(t))) - binary := wasmtest.CreateTestBinary(binaryCmd, binaryLocation, true, t) + binary := wasmtest.CreateTestBinary(simpleBinaryCmd, simpleBinaryLocation, true, t) config, err := values.WrapMap(map[string]any{ "config": []byte(""), diff --git a/core/capabilities/integration_tests/framework/capabilities_registry.go b/core/capabilities/integration_tests/framework/capabilities_registry.go index 5c23d2ebc1a..3ebbb5081d3 100644 --- a/core/capabilities/integration_tests/framework/capabilities_registry.go +++ b/core/capabilities/integration_tests/framework/capabilities_registry.go @@ -11,7 +11,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" "github.com/smartcontractkit/chainlink-common/pkg/values" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/stretchr/testify/require" ) diff --git a/core/capabilities/integration_tests/framework/don.go b/core/capabilities/integration_tests/framework/don.go index 999966bdc1d..c9b78a0db96 100644 --- a/core/capabilities/integration_tests/framework/don.go +++ b/core/capabilities/integration_tests/framework/don.go @@ -28,7 +28,7 @@ import ( remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" diff --git a/core/capabilities/integration_tests/framework/peer.go b/core/capabilities/integration_tests/framework/peer.go index d97abadf646..c4f73629450 100644 --- a/core/capabilities/integration_tests/framework/peer.go +++ b/core/capabilities/integration_tests/framework/peer.go @@ -11,7 +11,7 @@ import ( ragetypes "github.com/smartcontractkit/libocr/ragep2p/types" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" diff --git a/core/capabilities/integration_tests/keystone/contracts_setup.go b/core/capabilities/integration_tests/keystone/contracts_setup.go index d7b98327889..ad87850bf5f 100644 --- a/core/capabilities/integration_tests/keystone/contracts_setup.go +++ b/core/capabilities/integration_tests/keystone/contracts_setup.go @@ -7,8 +7,8 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/v2/core/capabilities/integration_tests/framework" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/feeds_consumer" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder" + feeds_consumer "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/feeds_consumer_1_0_0" + forwarder "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder_1_0_0" ) func SetupForwarderContract(t *testing.T, reportCreator *framework.DON, diff --git a/core/capabilities/integration_tests/keystone/keystone_test.go b/core/capabilities/integration_tests/keystone/keystone_test.go index 17bfde7cda9..6cfa8c9f0df 100644 --- a/core/capabilities/integration_tests/keystone/keystone_test.go +++ b/core/capabilities/integration_tests/keystone/keystone_test.go @@ -16,7 +16,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/capabilities/datastreams" "github.com/smartcontractkit/chainlink-common/pkg/values" "github.com/smartcontractkit/chainlink/v2/core/capabilities/integration_tests/framework" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/feeds_consumer" + feeds_consumer "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/feeds_consumer_1_0_0" "github.com/smartcontractkit/chainlink/v2/core/logger" reporttypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v3/types" ) diff --git a/core/capabilities/integration_tests/keystone/setup.go b/core/capabilities/integration_tests/keystone/setup.go index f4b29323537..690e176e491 100644 --- a/core/capabilities/integration_tests/keystone/setup.go +++ b/core/capabilities/integration_tests/keystone/setup.go @@ -18,7 +18,7 @@ import ( v3 "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v3" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink/v2/core/capabilities/integration_tests/framework" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/feeds_consumer" + feeds_consumer "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/feeds_consumer_1_0_0" ocrTypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" diff --git a/core/capabilities/launcher.go b/core/capabilities/launcher.go index 98318853e2a..51df7eeebfc 100644 --- a/core/capabilities/launcher.go +++ b/core/capabilities/launcher.go @@ -19,6 +19,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/values" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/aggregation" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/executable" remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" "github.com/smartcontractkit/chainlink/v2/core/capabilities/streams" @@ -280,7 +281,7 @@ func (w *launcher) addRemoteCapabilities(ctx context.Context, myDON registrysync w.lggr, ) } else { - aggregator = remote.NewDefaultModeAggregator(uint32(remoteDON.F) + 1) + aggregator = aggregation.NewDefaultModeAggregator(uint32(remoteDON.F) + 1) } // TODO: We need to implement a custom, Mercury-specific diff --git a/core/capabilities/launcher_test.go b/core/capabilities/launcher_test.go index c130f9833d9..167a2fcbd1b 100644 --- a/core/capabilities/launcher_test.go +++ b/core/capabilities/launcher_test.go @@ -23,7 +23,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote" remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" remoteMocks "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types/mocks" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" diff --git a/core/capabilities/remote/aggregation/default_mode.go b/core/capabilities/remote/aggregation/default_mode.go new file mode 100644 index 00000000000..3d5e262920f --- /dev/null +++ b/core/capabilities/remote/aggregation/default_mode.go @@ -0,0 +1,58 @@ +package aggregation + +import ( + "crypto/sha256" + "encoding/hex" + "errors" + "fmt" + + commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" + remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" +) + +// Default MODE Aggregator needs a configurable number of identical responses for aggregation to succeed +type defaultModeAggregator struct { + minIdenticalResponses uint32 +} + +var _ remotetypes.Aggregator = &defaultModeAggregator{} + +func NewDefaultModeAggregator(minIdenticalResponses uint32) *defaultModeAggregator { + return &defaultModeAggregator{ + minIdenticalResponses: minIdenticalResponses, + } +} + +func (a *defaultModeAggregator) Aggregate(_ string, responses [][]byte) (commoncap.TriggerResponse, error) { + found, err := AggregateModeRaw(responses, a.minIdenticalResponses) + if err != nil { + return commoncap.TriggerResponse{}, fmt.Errorf("failed to aggregate responses, err: %w", err) + } + + unmarshaled, err := pb.UnmarshalTriggerResponse(found) + if err != nil { + return commoncap.TriggerResponse{}, fmt.Errorf("failed to unmarshal aggregated responses, err: %w", err) + } + return unmarshaled, nil +} + +func AggregateModeRaw(elemList [][]byte, minIdenticalResponses uint32) ([]byte, error) { + hashToCount := make(map[string]uint32) + var found []byte + for _, elem := range elemList { + hasher := sha256.New() + hasher.Write(elem) + sha := hex.EncodeToString(hasher.Sum(nil)) + hashToCount[sha]++ + if hashToCount[sha] >= minIdenticalResponses { + found = elem + // update in case we find another elem with an even higher count + minIdenticalResponses = hashToCount[sha] + } + } + if found == nil { + return nil, errors.New("not enough identical responses found") + } + return found, nil +} diff --git a/core/capabilities/remote/aggregation/default_mode_test.go b/core/capabilities/remote/aggregation/default_mode_test.go new file mode 100644 index 00000000000..7c7d615e17a --- /dev/null +++ b/core/capabilities/remote/aggregation/default_mode_test.go @@ -0,0 +1,51 @@ +package aggregation + +import ( + "testing" + + "github.com/stretchr/testify/require" + + commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" + "github.com/smartcontractkit/chainlink-common/pkg/values" +) + +var ( + triggerEvent1 = map[string]any{"event": "triggerEvent1"} + triggerEvent2 = map[string]any{"event": "triggerEvent2"} +) + +func TestDefaultModeAggregator_Aggregate(t *testing.T) { + val, err := values.NewMap(triggerEvent1) + require.NoError(t, err) + capResponse1 := commoncap.TriggerResponse{ + Event: commoncap.TriggerEvent{ + Outputs: val, + }, + Err: nil, + } + marshaled1, err := pb.MarshalTriggerResponse(capResponse1) + require.NoError(t, err) + + val2, err := values.NewMap(triggerEvent2) + require.NoError(t, err) + capResponse2 := commoncap.TriggerResponse{ + Event: commoncap.TriggerEvent{ + Outputs: val2, + }, + Err: nil, + } + marshaled2, err := pb.MarshalTriggerResponse(capResponse2) + require.NoError(t, err) + + agg := NewDefaultModeAggregator(2) + _, err = agg.Aggregate("", [][]byte{marshaled1}) + require.Error(t, err) + + _, err = agg.Aggregate("", [][]byte{marshaled1, marshaled2}) + require.Error(t, err) + + res, err := agg.Aggregate("", [][]byte{marshaled1, marshaled2, marshaled1}) + require.NoError(t, err) + require.Equal(t, res, capResponse1) +} diff --git a/core/capabilities/remote/dispatcher.go b/core/capabilities/remote/dispatcher.go index e3229d35c1e..905eda9d72d 100644 --- a/core/capabilities/remote/dispatcher.go +++ b/core/capabilities/remote/dispatcher.go @@ -3,6 +3,7 @@ package remote import ( "context" "fmt" + "strconv" "sync" "time" @@ -42,8 +43,8 @@ type dispatcher struct { } type key struct { - capId string - donId uint32 + capID string + donID uint32 } var _ services.Service = &dispatcher{} @@ -74,7 +75,7 @@ func (d *dispatcher) Start(ctx context.Context) error { d.peer = d.peerWrapper.GetPeer() d.peerID = d.peer.ID() if d.peer == nil { - return fmt.Errorf("peer is not initialized") + return errors.New("peer is not initialized") } d.wg.Add(1) go func() { @@ -103,13 +104,13 @@ type receiver struct { ch chan *types.MessageBody } -func (d *dispatcher) SetReceiver(capabilityId string, donId uint32, rec types.Receiver) error { +func (d *dispatcher) SetReceiver(capabilityID string, donID uint32, rec types.Receiver) error { d.mu.Lock() defer d.mu.Unlock() - k := key{capabilityId, donId} + k := key{capabilityID, donID} _, ok := d.receivers[k] if ok { - return fmt.Errorf("%w: receiver already exists for capability %s and don %d", ErrReceiverExists, capabilityId, donId) + return fmt.Errorf("%w: receiver already exists for capability %s and don %d", ErrReceiverExists, capabilityID, donID) } receiverCh := make(chan *types.MessageBody, d.cfg.ReceiverBufferSize()) @@ -134,23 +135,24 @@ func (d *dispatcher) SetReceiver(capabilityId string, donId uint32, rec types.Re ch: receiverCh, } - d.lggr.Debugw("receiver set", "capabilityId", capabilityId, "donId", donId) + d.lggr.Debugw("receiver set", "capabilityId", capabilityID, "donId", donID) return nil } -func (d *dispatcher) RemoveReceiver(capabilityId string, donId uint32) { +func (d *dispatcher) RemoveReceiver(capabilityID string, donID uint32) { d.mu.Lock() defer d.mu.Unlock() - receiverKey := key{capabilityId, donId} + receiverKey := key{capabilityID, donID} if receiver, ok := d.receivers[receiverKey]; ok { receiver.cancel() delete(d.receivers, receiverKey) - d.lggr.Debugw("receiver removed", "capabilityId", capabilityId, "donId", donId) + d.lggr.Debugw("receiver removed", "capabilityId", capabilityID, "donId", donID) } } func (d *dispatcher) Send(peerID p2ptypes.PeerID, msgBody *types.MessageBody) error { + //nolint:gosec // disable G115 msgBody.Version = uint32(d.cfg.SupportedVersion()) msgBody.Sender = d.peerID[:] msgBody.Receiver = peerID[:] @@ -194,17 +196,17 @@ func (d *dispatcher) receive() { receiver, ok := d.receivers[k] d.mu.RUnlock() if !ok { - d.lggr.Debugw("received message for unregistered capability", "capabilityId", SanitizeLogString(k.capId), "donId", k.donId) + d.lggr.Debugw("received message for unregistered capability", "capabilityId", SanitizeLogString(k.capID), "donId", k.donID) d.tryRespondWithError(msg.Sender, body, types.Error_CAPABILITY_NOT_FOUND) continue } receiverQueueUsage := float64(len(receiver.ch)) / float64(d.cfg.ReceiverBufferSize()) - capReceiveChannelUsage.WithLabelValues(k.capId, fmt.Sprint(k.donId)).Set(receiverQueueUsage) + capReceiveChannelUsage.WithLabelValues(k.capID, strconv.FormatUint(uint64(k.donID), 10)).Set(receiverQueueUsage) select { case receiver.ch <- body: default: - d.lggr.Warnw("receiver channel full, dropping message", "capabilityId", k.capId, "donId", k.donId) + d.lggr.Warnw("receiver channel full, dropping message", "capabilityId", k.capID, "donId", k.donID) } } } diff --git a/core/capabilities/remote/dispatcher_test.go b/core/capabilities/remote/dispatcher_test.go index 50edc5f3530..fbc9dbb4b49 100644 --- a/core/capabilities/remote/dispatcher_test.go +++ b/core/capabilities/remote/dispatcher_test.go @@ -104,13 +104,13 @@ func TestDispatcher_CleanStartClose(t *testing.T) { func TestDispatcher_Receive(t *testing.T) { lggr := logger.TestLogger(t) ctx := testutils.Context(t) - privKey1, peerId1 := newKeyPair(t) - _, peerId2 := newKeyPair(t) + privKey1, peerID1 := newKeyPair(t) + _, peerID2 := newKeyPair(t) peer := mocks.NewPeer(t) recvCh := make(chan p2ptypes.Message) peer.On("Receive", mock.Anything).Return((<-chan p2ptypes.Message)(recvCh)) - peer.On("ID", mock.Anything).Return(peerId2) + peer.On("ID", mock.Anything).Return(peerID2) wrapper := mocks.NewPeerWrapper(t) wrapper.On("GetPeer").Return(peer) signer := mocks.NewSigner(t) @@ -131,39 +131,39 @@ func TestDispatcher_Receive(t *testing.T) { require.NoError(t, dispatcher.Start(ctx)) rcv := newReceiver() - err = dispatcher.SetReceiver(capId1, donId1, rcv) + err = dispatcher.SetReceiver(capID1, donID1, rcv) require.NoError(t, err) // supported capability - recvCh <- encodeAndSign(t, privKey1, peerId1, peerId2, capId1, donId1, []byte(payload1)) + recvCh <- encodeAndSign(t, privKey1, peerID1, peerID2, capID1, donID1, []byte(payload1)) // unknown capability - recvCh <- encodeAndSign(t, privKey1, peerId1, peerId2, capId2, donId1, []byte(payload1)) + recvCh <- encodeAndSign(t, privKey1, peerID1, peerID2, capID2, donID1, []byte(payload1)) // sender doesn't match - invalid := encodeAndSign(t, privKey1, peerId1, peerId2, capId2, donId1, []byte(payload1)) - invalid.Sender = peerId2 + invalid := encodeAndSign(t, privKey1, peerID1, peerID2, capID2, donID1, []byte(payload1)) + invalid.Sender = peerID2 recvCh <- invalid // supported capability again - recvCh <- encodeAndSign(t, privKey1, peerId1, peerId2, capId1, donId1, []byte(payload2)) + recvCh <- encodeAndSign(t, privKey1, peerID1, peerID2, capID1, donID1, []byte(payload2)) m := <-rcv.ch require.Equal(t, payload1, string(m.Payload)) m = <-rcv.ch require.Equal(t, payload2, string(m.Payload)) - dispatcher.RemoveReceiver(capId1, donId1) + dispatcher.RemoveReceiver(capID1, donID1) require.NoError(t, dispatcher.Close()) } func TestDispatcher_RespondWithError(t *testing.T) { lggr := logger.TestLogger(t) ctx := testutils.Context(t) - privKey1, peerId1 := newKeyPair(t) - _, peerId2 := newKeyPair(t) + privKey1, peerID1 := newKeyPair(t) + _, peerID2 := newKeyPair(t) peer := mocks.NewPeer(t) recvCh := make(chan p2ptypes.Message) peer.On("Receive", mock.Anything).Return((<-chan p2ptypes.Message)(recvCh)) - peer.On("ID", mock.Anything).Return(peerId2) + peer.On("ID", mock.Anything).Return(peerID2) sendCh := make(chan p2ptypes.PeerID) peer.On("Send", mock.Anything, mock.Anything).Run(func(args mock.Arguments) { peerID := args.Get(0).(p2ptypes.PeerID) @@ -189,9 +189,9 @@ func TestDispatcher_RespondWithError(t *testing.T) { require.NoError(t, dispatcher.Start(ctx)) // unknown capability - recvCh <- encodeAndSign(t, privKey1, peerId1, peerId2, capId1, donId1, []byte(payload1)) + recvCh <- encodeAndSign(t, privKey1, peerID1, peerID2, capID1, donID1, []byte(payload1)) responseDestPeerID := <-sendCh - require.Equal(t, peerId1, responseDestPeerID) + require.Equal(t, peerID1, responseDestPeerID) require.NoError(t, dispatcher.Close()) } diff --git a/core/capabilities/remote/executable/client.go b/core/capabilities/remote/executable/client.go index 776ddb692ad..9f23ff4ce4a 100644 --- a/core/capabilities/remote/executable/client.go +++ b/core/capabilities/remote/executable/client.go @@ -43,6 +43,11 @@ var _ services.Service = &client{} const expiryCheckInterval = 30 * time.Second +var ( + ErrRequestExpired = errors.New("request expired by executable client") + ErrContextDoneBeforeResponseQuorum = errors.New("context done before remote client received a quorum of responses") +) + func NewClient(remoteCapabilityInfo commoncap.CapabilityInfo, localDonInfo commoncap.DON, dispatcher types.Dispatcher, requestTimeout time.Duration, lggr logger.Logger) *client { return &client{ @@ -122,7 +127,7 @@ func (c *client) expireRequests() { for messageID, req := range c.requestIDToCallerRequest { if req.Expired() { - req.Cancel(errors.New("request expired by executable client")) + req.Cancel(ErrRequestExpired) delete(c.requestIDToCallerRequest, messageID) } @@ -164,12 +169,22 @@ func (c *client) Execute(ctx context.Context, capReq commoncap.CapabilityRequest return commoncap.CapabilityResponse{}, fmt.Errorf("failed to send request: %w", err) } - resp := <-req.ResponseChan() - if resp.Err != nil { - return commoncap.CapabilityResponse{}, fmt.Errorf("error executing request: %w", resp.Err) + var respResult []byte + var respErr error + select { + case resp := <-req.ResponseChan(): + respResult = resp.Result + respErr = resp.Err + case <-ctx.Done(): + // NOTE: ClientRequest will not block on sending to ResponseChan() because that channel is buffered (with size 1) + return commoncap.CapabilityResponse{}, errors.Join(ErrContextDoneBeforeResponseQuorum, ctx.Err()) + } + + if respErr != nil { + return commoncap.CapabilityResponse{}, fmt.Errorf("error executing request: %w", respErr) } - capabilityResponse, err := pb.UnmarshalCapabilityResponse(resp.Result) + capabilityResponse, err := pb.UnmarshalCapabilityResponse(respResult) if err != nil { return commoncap.CapabilityResponse{}, fmt.Errorf("failed to unmarshal capability response: %w", err) } diff --git a/core/capabilities/remote/executable/client_test.go b/core/capabilities/remote/executable/client_test.go index f4e6add82b0..4e7d940a3b9 100644 --- a/core/capabilities/remote/executable/client_test.go +++ b/core/capabilities/remote/executable/client_test.go @@ -12,7 +12,6 @@ import ( commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink-common/pkg/values" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/executable" @@ -31,7 +30,6 @@ const ( ) func Test_Client_DonTopologies(t *testing.T) { - tests.SkipFlakey(t, "https://smartcontract-it.atlassian.net/browse/CAPPL-363") ctx := testutils.Context(t) transmissionSchedule, err := values.NewMap(map[string]any{ @@ -59,18 +57,6 @@ func Test_Client_DonTopologies(t *testing.T) { executeMethod(ctx, caller, transmissionSchedule, executeInputs, responseTest, t) }) - methods = append(methods, func(caller commoncap.ExecutableCapability) { - registerToWorkflowMethod(ctx, caller, transmissionSchedule, func(t *testing.T, responseError error) { - require.NoError(t, responseError) - }, t) - }) - - methods = append(methods, func(caller commoncap.ExecutableCapability) { - unregisterFromWorkflowMethod(ctx, caller, transmissionSchedule, func(t *testing.T, responseError error) { - require.NoError(t, responseError) - }, t) - }) - for _, method := range methods { testClient(t, 1, responseTimeOut, 1, 0, capability, method) @@ -90,7 +76,6 @@ func Test_Client_DonTopologies(t *testing.T) { } func Test_Client_TransmissionSchedules(t *testing.T) { - tests.SkipFlakey(t, "https://smartcontract-it.atlassian.net/browse/CAPPL-363") ctx := testutils.Context(t) responseTest := func(t *testing.T, response commoncap.CapabilityResponse, responseError error) { @@ -147,7 +132,8 @@ func Test_Client_TimesOutIfInsufficientCapabilityPeerResponses(t *testing.T) { ctx := testutils.Context(t) responseTest := func(t *testing.T, response commoncap.CapabilityResponse, responseError error) { - assert.Error(t, responseError) + require.Error(t, responseError) + require.ErrorIs(t, responseError, executable.ErrRequestExpired) } capability := &TestCapability{} @@ -169,6 +155,31 @@ func Test_Client_TimesOutIfInsufficientCapabilityPeerResponses(t *testing.T) { }) } +func Test_Client_ContextCanceledBeforeQuorumReached(t *testing.T) { + ctx, cancel := context.WithCancel(testutils.Context(t)) + + responseTest := func(t *testing.T, response commoncap.CapabilityResponse, responseError error) { + require.Error(t, responseError) + require.ErrorIs(t, responseError, executable.ErrContextDoneBeforeResponseQuorum) + } + + capability := &TestCapability{} + transmissionSchedule, err := values.NewMap(map[string]any{ + "schedule": transmission.Schedule_AllAtOnce, + "deltaStage": "20s", + }) + require.NoError(t, err) + + cancel() + testClient(t, 2, 20*time.Second, 2, 2, + capability, + func(caller commoncap.ExecutableCapability) { + executeInputs, err := values.NewMap(map[string]any{"executeValue1": "aValue1"}) + require.NoError(t, err) + executeMethod(ctx, caller, transmissionSchedule, executeInputs, responseTest, t) + }) +} + func testClient(t *testing.T, numWorkflowPeers int, workflowNodeResponseTimeout time.Duration, numCapabilityPeers int, capabilityDonF uint8, underlying commoncap.ExecutableCapability, method func(caller commoncap.ExecutableCapability)) { @@ -238,34 +249,6 @@ func testClient(t *testing.T, numWorkflowPeers int, workflowNodeResponseTimeout wg.Wait() } -func registerToWorkflowMethod(ctx context.Context, caller commoncap.ExecutableCapability, transmissionSchedule *values.Map, - responseTest func(t *testing.T, responseError error), t *testing.T) { - err := caller.RegisterToWorkflow(ctx, commoncap.RegisterToWorkflowRequest{ - Metadata: commoncap.RegistrationMetadata{ - WorkflowID: workflowID1, - ReferenceID: stepReferenceID1, - WorkflowOwner: workflowOwnerID, - }, - Config: transmissionSchedule, - }) - - responseTest(t, err) -} - -func unregisterFromWorkflowMethod(ctx context.Context, caller commoncap.ExecutableCapability, transmissionSchedule *values.Map, - responseTest func(t *testing.T, responseError error), t *testing.T) { - err := caller.UnregisterFromWorkflow(ctx, commoncap.UnregisterFromWorkflowRequest{ - Metadata: commoncap.RegistrationMetadata{ - WorkflowID: workflowID1, - ReferenceID: stepReferenceID1, - WorkflowOwner: workflowOwnerID, - }, - Config: transmissionSchedule, - }) - - responseTest(t, err) -} - func executeMethod(ctx context.Context, caller commoncap.ExecutableCapability, transmissionSchedule *values.Map, executeInputs *values.Map, responseTest func(t *testing.T, responseCh commoncap.CapabilityResponse, responseError error), t *testing.T) { responseCh, err := caller.Execute(ctx, @@ -336,21 +319,6 @@ func (t *clientTestServer) Receive(_ context.Context, msg *remotetypes.MessageBo resp, responseErr := t.executableCapability.Execute(context.Background(), capabilityRequest) payload, marshalErr := pb.MarshalCapabilityResponse(resp) t.sendResponse(messageID, responseErr, payload, marshalErr) - - case remotetypes.MethodRegisterToWorkflow: - registerRequest, err := pb.UnmarshalRegisterToWorkflowRequest(msg.Payload) - if err != nil { - panic(err) - } - responseErr := t.executableCapability.RegisterToWorkflow(context.Background(), registerRequest) - t.sendResponse(messageID, responseErr, nil, nil) - case remotetypes.MethodUnregisterFromWorkflow: - unregisterRequest, err := pb.UnmarshalUnregisterFromWorkflowRequest(msg.Payload) - if err != nil { - panic(err) - } - responseErr := t.executableCapability.UnregisterFromWorkflow(context.Background(), unregisterRequest) - t.sendResponse(messageID, responseErr, nil, nil) default: panic("unknown method") } diff --git a/core/capabilities/remote/executable/endtoend_test.go b/core/capabilities/remote/executable/endtoend_test.go index 5f445db4235..886bde9d33d 100644 --- a/core/capabilities/remote/executable/endtoend_test.go +++ b/core/capabilities/remote/executable/endtoend_test.go @@ -224,9 +224,9 @@ func (a *testAsyncMessageBroker) start(ctx context.Context) error { case <-ctx.Done(): return case msg := <-a.sendCh: - receiverId := toPeerID(msg.Receiver) + receiverID := toPeerID(msg.Receiver) - receiver, ok := a.nodes[receiverId] + receiver, ok := a.nodes[receiverID] if !ok { panic("server not found for peer id") } @@ -299,10 +299,10 @@ func (t *nodeDispatcher) Send(peerID p2ptypes.PeerID, msgBody *remotetypes.Messa return nil } -func (t *nodeDispatcher) SetReceiver(capabilityId string, donId uint32, receiver remotetypes.Receiver) error { +func (t *nodeDispatcher) SetReceiver(capabilityID string, donID uint32, receiver remotetypes.Receiver) error { return nil } -func (t *nodeDispatcher) RemoveReceiver(capabilityId string, donId uint32) {} +func (t *nodeDispatcher) RemoveReceiver(capabilityID string, donID uint32) {} type abstractTestCapability struct { } @@ -407,29 +407,3 @@ func executeCapability(ctx context.Context, t *testing.T, caller commoncap.Execu responseTest(t, response, err) } - -func registerWorkflow(ctx context.Context, t *testing.T, caller commoncap.ExecutableCapability, transmissionSchedule *values.Map, responseTest func(t *testing.T, responseError error)) { - err := caller.RegisterToWorkflow(ctx, commoncap.RegisterToWorkflowRequest{ - Metadata: commoncap.RegistrationMetadata{ - WorkflowID: workflowID1, - ReferenceID: stepReferenceID1, - WorkflowOwner: workflowOwnerID, - }, - Config: transmissionSchedule, - }) - - responseTest(t, err) -} - -func unregisterWorkflow(ctx context.Context, t *testing.T, caller commoncap.ExecutableCapability, transmissionSchedule *values.Map, responseTest func(t *testing.T, responseError error)) { - err := caller.UnregisterFromWorkflow(ctx, commoncap.UnregisterFromWorkflowRequest{ - Metadata: commoncap.RegistrationMetadata{ - WorkflowID: workflowID1, - ReferenceID: stepReferenceID1, - WorkflowOwner: workflowOwnerID, - }, - Config: transmissionSchedule, - }) - - responseTest(t, err) -} diff --git a/core/capabilities/remote/executable/request/client_request.go b/core/capabilities/remote/executable/request/client_request.go index 6b4b9e3a0cd..1d98e3366f1 100644 --- a/core/capabilities/remote/executable/request/client_request.go +++ b/core/capabilities/remote/executable/request/client_request.go @@ -48,54 +48,6 @@ type ClientRequest struct { wg *sync.WaitGroup } -func NewClientRegisterToWorkflowRequest(ctx context.Context, lggr logger.Logger, req commoncap.RegisterToWorkflowRequest, - remoteCapabilityInfo commoncap.CapabilityInfo, localDonInfo capabilities.DON, dispatcher types.Dispatcher, - requestTimeout time.Duration) (*ClientRequest, error) { - rawRequest, err := proto.MarshalOptions{Deterministic: true}.Marshal(pb.RegisterToWorkflowRequestToProto(req)) - if err != nil { - return nil, fmt.Errorf("failed to marshal register to workflow request: %w", err) - } - - workflowID := req.Metadata.WorkflowID - if err := validation.ValidateWorkflowOrExecutionID(workflowID); err != nil { - return nil, fmt.Errorf("workflow ID is invalid: %w", err) - } - - requestID := types.MethodRegisterToWorkflow + ":" + workflowID - - tc := transmission.TransmissionConfig{ - Schedule: transmission.Schedule_AllAtOnce, - DeltaStage: 0, - } - - return newClientRequest(ctx, lggr, requestID, remoteCapabilityInfo, localDonInfo, dispatcher, requestTimeout, - tc, types.MethodRegisterToWorkflow, rawRequest) -} - -func NewClientUnregisterFromWorkflowRequest(ctx context.Context, lggr logger.Logger, req commoncap.UnregisterFromWorkflowRequest, - remoteCapabilityInfo commoncap.CapabilityInfo, localDonInfo capabilities.DON, dispatcher types.Dispatcher, - requestTimeout time.Duration) (*ClientRequest, error) { - rawRequest, err := proto.MarshalOptions{Deterministic: true}.Marshal(pb.UnregisterFromWorkflowRequestToProto(req)) - if err != nil { - return nil, fmt.Errorf("failed to marshal unregister from workflow request: %w", err) - } - - workflowID := req.Metadata.WorkflowID - if err := validation.ValidateWorkflowOrExecutionID(workflowID); err != nil { - return nil, fmt.Errorf("workflow ID is invalid: %w", err) - } - - requestID := types.MethodUnregisterFromWorkflow + ":" + workflowID - - tc := transmission.TransmissionConfig{ - Schedule: transmission.Schedule_AllAtOnce, - DeltaStage: 0, - } - - return newClientRequest(ctx, lggr, requestID, remoteCapabilityInfo, localDonInfo, dispatcher, requestTimeout, - tc, types.MethodUnregisterFromWorkflow, rawRequest) -} - func NewClientExecuteRequest(ctx context.Context, lggr logger.Logger, req commoncap.CapabilityRequest, remoteCapabilityInfo commoncap.CapabilityInfo, localDonInfo capabilities.DON, dispatcher types.Dispatcher, requestTimeout time.Duration) (*ClientRequest, error) { @@ -212,7 +164,7 @@ func (c *ClientRequest) OnMessage(_ context.Context, msg *types.MessageBody) err } if msg.Sender == nil { - return fmt.Errorf("sender missing from message") + return errors.New("sender missing from message") } c.lggr.Debugw("OnMessage called for client request", "messageID", msg.MessageId) diff --git a/core/capabilities/remote/executable/request/client_request_test.go b/core/capabilities/remote/executable/request/client_request_test.go index c46fd1363a0..212b7265e4f 100644 --- a/core/capabilities/remote/executable/request/client_request_test.go +++ b/core/capabilities/remote/executable/request/client_request_test.go @@ -80,15 +80,6 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { Config: transmissionSchedule, } - registerToWorkflowRequest := commoncap.RegisterToWorkflowRequest{ - Metadata: commoncap.RegistrationMetadata{ - WorkflowID: workflowID1, - WorkflowOwner: "0xaa", - ReferenceID: "refID", - }, - Config: transmissionSchedule, - } - m, err := values.NewMap(map[string]any{"response": "response1"}) require.NoError(t, err) capabilityResponse := commoncap.CapabilityResponse{ @@ -167,7 +158,7 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { nonDonPeer := NewP2PPeerID(t) msg.Sender = nonDonPeer[:] err = request.OnMessage(ctx, msg) - require.NotNil(t, err) + require.Error(t, err) select { case <-request.ResponseChan(): @@ -190,7 +181,7 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { err = request.OnMessage(ctx, msg) require.NoError(t, err) err = request.OnMessage(ctx, msg) - require.NotNil(t, err) + require.Error(t, err) select { case <-request.ResponseChan(): @@ -211,7 +202,7 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { <-dispatcher.msgs <-dispatcher.msgs - assert.Equal(t, 0, len(dispatcher.msgs)) + assert.Empty(t, dispatcher.msgs) msgWithError := &types.MessageBody{ CapabilityId: capInfo.ID, @@ -249,7 +240,7 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { <-dispatcher.msgs <-dispatcher.msgs - assert.Equal(t, 0, len(dispatcher.msgs)) + assert.Empty(t, dispatcher.msgs) msgWithError := &types.MessageBody{ CapabilityId: capInfo.ID, @@ -299,7 +290,7 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { <-dispatcher.msgs <-dispatcher.msgs - assert.Equal(t, 0, len(dispatcher.msgs)) + assert.Empty(t, dispatcher.msgs) msg.Sender = capabilityPeers[0][:] err = request.OnMessage(ctx, msg) @@ -317,160 +308,6 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { assert.Equal(t, resp, values.NewString("response1")) }) - - t.Run("Register To Workflow Request", func(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - dispatcher := &clientRequestTestDispatcher{msgs: make(chan *types.MessageBody, 100)} - request, err := request.NewClientRegisterToWorkflowRequest(ctx, lggr, registerToWorkflowRequest, capInfo, - workflowDonInfo, dispatcher, 10*time.Minute) - require.NoError(t, err) - defer request.Cancel(errors.New("test end")) - - <-dispatcher.msgs - <-dispatcher.msgs - assert.Empty(t, dispatcher.msgs) - - msg := &types.MessageBody{ - CapabilityId: capInfo.ID, - CapabilityDonId: capDonInfo.ID, - CallerDonId: workflowDonInfo.ID, - Method: types.MethodRegisterToWorkflow, - Payload: nil, - MessageId: []byte("messageID"), - } - - msg.Sender = capabilityPeers[0][:] - err = request.OnMessage(ctx, msg) - require.NoError(t, err) - - msg.Sender = capabilityPeers[1][:] - err = request.OnMessage(ctx, msg) - require.NoError(t, err) - - response := <-request.ResponseChan() - require.Nil(t, response.Result) - require.NoError(t, response.Err) - }) - - t.Run("Register To Workflow Request with error", func(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - dispatcher := &clientRequestTestDispatcher{msgs: make(chan *types.MessageBody, 100)} - request, err := request.NewClientRegisterToWorkflowRequest(ctx, lggr, registerToWorkflowRequest, capInfo, - workflowDonInfo, dispatcher, 10*time.Minute) - require.NoError(t, err) - defer request.Cancel(errors.New("test end")) - - <-dispatcher.msgs - <-dispatcher.msgs - assert.Empty(t, dispatcher.msgs) - - msg := &types.MessageBody{ - CapabilityId: capInfo.ID, - CapabilityDonId: capDonInfo.ID, - CallerDonId: workflowDonInfo.ID, - Method: types.MethodRegisterToWorkflow, - Payload: nil, - MessageId: []byte("messageID"), - Error: types.Error_INTERNAL_ERROR, - ErrorMsg: "an error", - } - - msg.Sender = capabilityPeers[0][:] - err = request.OnMessage(ctx, msg) - require.NoError(t, err) - - msg.Sender = capabilityPeers[1][:] - err = request.OnMessage(ctx, msg) - require.NoError(t, err) - - response := <-request.ResponseChan() - require.Nil(t, response.Result) - assert.Equal(t, "an error", response.Err.Error()) - }) - - t.Run("Unregister From Workflow Request", func(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - dispatcher := &clientRequestTestDispatcher{msgs: make(chan *types.MessageBody, 100)} - request, err := request.NewClientUnregisterFromWorkflowRequest(ctx, lggr, commoncap.UnregisterFromWorkflowRequest{ - Metadata: commoncap.RegistrationMetadata{ - WorkflowID: workflowID1, - }, - }, capInfo, workflowDonInfo, dispatcher, 10*time.Minute) - require.NoError(t, err) - defer request.Cancel(errors.New("test end")) - - <-dispatcher.msgs - <-dispatcher.msgs - assert.Empty(t, dispatcher.msgs) - - msg := &types.MessageBody{ - CapabilityId: capInfo.ID, - CapabilityDonId: capDonInfo.ID, - CallerDonId: workflowDonInfo.ID, - Method: types.MethodUnregisterFromWorkflow, - Payload: nil, - MessageId: []byte("messageID"), - } - - msg.Sender = capabilityPeers[0][:] - err = request.OnMessage(ctx, msg) - require.NoError(t, err) - - msg.Sender = capabilityPeers[1][:] - err = request.OnMessage(ctx, msg) - require.NoError(t, err) - - response := <-request.ResponseChan() - require.Nil(t, response.Result) - require.NoError(t, response.Err) - }) - - t.Run("Unregister From Workflow Request with error", func(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - dispatcher := &clientRequestTestDispatcher{msgs: make(chan *types.MessageBody, 100)} - request, err := request.NewClientUnregisterFromWorkflowRequest(ctx, lggr, commoncap.UnregisterFromWorkflowRequest{ - Metadata: commoncap.RegistrationMetadata{ - WorkflowID: workflowID1, - }, - }, capInfo, workflowDonInfo, dispatcher, 10*time.Minute) - require.NoError(t, err) - defer request.Cancel(errors.New("test end")) - - <-dispatcher.msgs - <-dispatcher.msgs - assert.Empty(t, dispatcher.msgs) - - msg := &types.MessageBody{ - CapabilityId: capInfo.ID, - CapabilityDonId: capDonInfo.ID, - CallerDonId: workflowDonInfo.ID, - Method: types.MethodUnregisterFromWorkflow, - Payload: nil, - MessageId: []byte("messageID"), - Error: types.Error_INTERNAL_ERROR, - ErrorMsg: "an error", - } - - msg.Sender = capabilityPeers[0][:] - err = request.OnMessage(ctx, msg) - require.NoError(t, err) - - msg.Sender = capabilityPeers[1][:] - err = request.OnMessage(ctx, msg) - require.NoError(t, err) - - response := <-request.ResponseChan() - require.Nil(t, response.Result) - assert.Equal(t, "an error", response.Err.Error()) - }) } type clientRequestTestDispatcher struct { @@ -497,11 +334,11 @@ func (t *clientRequestTestDispatcher) HealthReport() map[string]error { return nil } -func (t *clientRequestTestDispatcher) SetReceiver(capabilityId string, donId uint32, receiver types.Receiver) error { +func (t *clientRequestTestDispatcher) SetReceiver(capabilityID string, donID uint32, receiver types.Receiver) error { return nil } -func (t *clientRequestTestDispatcher) RemoveReceiver(capabilityId string, donId uint32) {} +func (t *clientRequestTestDispatcher) RemoveReceiver(capabilityID string, donID uint32) {} func (t *clientRequestTestDispatcher) Send(peerID p2ptypes.PeerID, msgBody *types.MessageBody) error { t.msgs <- msgBody diff --git a/core/capabilities/remote/executable/request/server_request.go b/core/capabilities/remote/executable/request/server_request.go index 629622494a4..a4f58194328 100644 --- a/core/capabilities/remote/executable/request/server_request.go +++ b/core/capabilities/remote/executable/request/server_request.go @@ -26,7 +26,7 @@ type response struct { type ServerRequest struct { capability capabilities.ExecutableCapability - capabilityPeerId p2ptypes.PeerID + capabilityPeerID p2ptypes.PeerID capabilityID string capabilityDonID uint32 @@ -60,7 +60,7 @@ func NewServerRequest(capability capabilities.ExecutableCapability, method strin createdTime: time.Now(), capabilityID: capabilityID, capabilityDonID: capabilityDonID, - capabilityPeerId: capabilityPeerID, + capabilityPeerID: capabilityPeerID, dispatcher: dispatcher, requesters: map[p2ptypes.PeerID]bool{}, responseSentToRequester: map[p2ptypes.PeerID]bool{}, @@ -77,7 +77,7 @@ func (e *ServerRequest) OnMessage(ctx context.Context, msg *types.MessageBody) e defer e.mux.Unlock() if msg.Sender == nil { - return fmt.Errorf("sender missing from message") + return errors.New("sender missing from message") } requester, err := remote.ToPeerID(msg.Sender) @@ -94,10 +94,6 @@ func (e *ServerRequest) OnMessage(ctx context.Context, msg *types.MessageBody) e switch e.method { case types.MethodExecute: e.executeRequest(ctx, msg.Payload, executeCapabilityRequest) - case types.MethodRegisterToWorkflow: - e.executeRequest(ctx, msg.Payload, registerToWorkflow) - case types.MethodUnregisterFromWorkflow: - e.executeRequest(ctx, msg.Payload, unregisterFromWorkflow) default: e.setError(types.Error_INTERNAL_ERROR, "unknown method %s"+e.method) } @@ -206,7 +202,7 @@ func (e *ServerRequest) sendResponse(requester p2ptypes.PeerID) error { CallerDonId: e.callingDon.ID, Method: types.MethodExecute, MessageId: []byte(e.requestMessageID), - Sender: e.capabilityPeerId[:], + Sender: e.capabilityPeerID[:], Receiver: requester[:], } @@ -252,33 +248,3 @@ func executeCapabilityRequest(ctx context.Context, lggr logger.Logger, capabilit lggr.Debugw("received execution results", "workflowExecutionID", capabilityRequest.Metadata.WorkflowExecutionID) return responsePayload, nil } - -func registerToWorkflow(ctx context.Context, _ logger.Logger, capability capabilities.ExecutableCapability, - payload []byte) ([]byte, error) { - registerRequest, err := pb.UnmarshalRegisterToWorkflowRequest(payload) - if err != nil { - return nil, fmt.Errorf("failed to unmarshal register to workflow request: %w", err) - } - - err = capability.RegisterToWorkflow(ctx, registerRequest) - if err != nil { - return nil, fmt.Errorf("failed to register to workflow: %w", err) - } - - return nil, nil -} - -func unregisterFromWorkflow(ctx context.Context, _ logger.Logger, capability capabilities.ExecutableCapability, - payload []byte) ([]byte, error) { - unregisterRequest, err := pb.UnmarshalUnregisterFromWorkflowRequest(payload) - if err != nil { - return nil, fmt.Errorf("failed to unmarshal unregister from workflow request: %w", err) - } - - err = capability.UnregisterFromWorkflow(ctx, unregisterRequest) - if err != nil { - return nil, fmt.Errorf("failed to unregister from workflow: %w", err) - } - - return nil, nil -} diff --git a/core/capabilities/remote/executable/request/server_request_test.go b/core/capabilities/remote/executable/request/server_request_test.go index ce539154d93..d58b6edf3f2 100644 --- a/core/capabilities/remote/executable/request/server_request_test.go +++ b/core/capabilities/remote/executable/request/server_request_test.go @@ -165,107 +165,6 @@ func Test_ServerRequest_MessageValidation(t *testing.T) { assert.Equal(t, types.Error_OK, dispatcher.msgs[0].Error) assert.Equal(t, types.Error_OK, dispatcher.msgs[1].Error) }) - t.Run("Register to workflow request", func(t *testing.T) { - dispatcher := &testDispatcher{} - request := request.NewServerRequest(capability, types.MethodRegisterToWorkflow, "capabilityID", 2, - capabilityPeerID, callingDon, "requestMessageID", dispatcher, 10*time.Minute, lggr) - - err := sendValidRequest(request, workflowPeers, capabilityPeerID, rawRequest) - require.NoError(t, err) - - err = request.OnMessage(context.Background(), &types.MessageBody{ - Version: 0, - Sender: workflowPeers[1][:], - Receiver: capabilityPeerID[:], - MessageId: []byte("workflowID" + "workflowExecutionID"), - CapabilityId: "capabilityID", - CapabilityDonId: 2, - CallerDonId: 1, - Method: types.MethodRegisterToWorkflow, - Payload: rawRequest, - }) - require.NoError(t, err) - assert.Len(t, dispatcher.msgs, 2) - assert.Equal(t, types.Error_OK, dispatcher.msgs[0].Error) - assert.Equal(t, types.Error_OK, dispatcher.msgs[1].Error) - }) - t.Run("Register to workflow request errors", func(t *testing.T) { - dispatcher := &testDispatcher{} - req := request.NewServerRequest(TestErrorCapability{}, types.MethodRegisterToWorkflow, "capabilityID", 2, - capabilityPeerID, callingDon, "requestMessageID", dispatcher, 10*time.Minute, lggr) - - err := sendValidRequest(req, workflowPeers, capabilityPeerID, rawRequest) - require.NoError(t, err) - - err = req.OnMessage(context.Background(), &types.MessageBody{ - Version: 0, - Sender: workflowPeers[1][:], - Receiver: capabilityPeerID[:], - MessageId: []byte("workflowID" + "workflowExecutionID"), - CapabilityId: "capabilityID", - CapabilityDonId: 2, - CallerDonId: 1, - Method: types.MethodRegisterToWorkflow, - Payload: rawRequest, - }) - require.NoError(t, err) - assert.Len(t, dispatcher.msgs, 2) - assert.Equal(t, types.Error_INTERNAL_ERROR, dispatcher.msgs[0].Error) - assert.Equal(t, "failed to register to workflow: an error", dispatcher.msgs[0].ErrorMsg) - assert.Equal(t, types.Error_INTERNAL_ERROR, dispatcher.msgs[1].Error) - assert.Equal(t, "failed to register to workflow: an error", dispatcher.msgs[1].ErrorMsg) - }) - t.Run("Unregister from workflow request", func(t *testing.T) { - dispatcher := &testDispatcher{} - request := request.NewServerRequest(capability, types.MethodUnregisterFromWorkflow, "capabilityID", 2, - capabilityPeerID, callingDon, "requestMessageID", dispatcher, 10*time.Minute, lggr) - - err := sendValidRequest(request, workflowPeers, capabilityPeerID, rawRequest) - require.NoError(t, err) - - err = request.OnMessage(context.Background(), &types.MessageBody{ - Version: 0, - Sender: workflowPeers[1][:], - Receiver: capabilityPeerID[:], - MessageId: []byte("workflowID" + "workflowExecutionID"), - CapabilityId: "capabilityID", - CapabilityDonId: 2, - CallerDonId: 1, - Method: types.MethodUnregisterFromWorkflow, - Payload: rawRequest, - }) - require.NoError(t, err) - assert.Len(t, dispatcher.msgs, 2) - assert.Equal(t, types.Error_OK, dispatcher.msgs[0].Error) - assert.Equal(t, types.Error_OK, dispatcher.msgs[1].Error) - }) - - t.Run("Unregister from workflow request errors", func(t *testing.T) { - dispatcher := &testDispatcher{} - req := request.NewServerRequest(TestErrorCapability{}, types.MethodUnregisterFromWorkflow, "capabilityID", 2, - capabilityPeerID, callingDon, "requestMessageID", dispatcher, 10*time.Minute, lggr) - - err := sendValidRequest(req, workflowPeers, capabilityPeerID, rawRequest) - require.NoError(t, err) - - err = req.OnMessage(context.Background(), &types.MessageBody{ - Version: 0, - Sender: workflowPeers[1][:], - Receiver: capabilityPeerID[:], - MessageId: []byte("workflowID" + "workflowExecutionID"), - CapabilityId: "capabilityID", - CapabilityDonId: 2, - CallerDonId: 1, - Method: types.MethodUnregisterFromWorkflow, - Payload: rawRequest, - }) - require.NoError(t, err) - assert.Len(t, dispatcher.msgs, 2) - assert.Equal(t, types.Error_INTERNAL_ERROR, dispatcher.msgs[0].Error) - assert.Equal(t, "failed to unregister from workflow: an error", dispatcher.msgs[0].ErrorMsg) - assert.Equal(t, types.Error_INTERNAL_ERROR, dispatcher.msgs[1].Error) - assert.Equal(t, "failed to unregister from workflow: an error", dispatcher.msgs[1].ErrorMsg) - }) } type serverRequest interface { @@ -311,11 +210,11 @@ func (t *testDispatcher) HealthReport() map[string]error { return nil } -func (t *testDispatcher) SetReceiver(capabilityId string, donId uint32, receiver types.Receiver) error { +func (t *testDispatcher) SetReceiver(capabilityID string, donID uint32, receiver types.Receiver) error { return nil } -func (t *testDispatcher) RemoveReceiver(capabilityId string, donId uint32) {} +func (t *testDispatcher) RemoveReceiver(capabilityID string, donID uint32) {} func (t *testDispatcher) Send(peerID p2ptypes.PeerID, msgBody *types.MessageBody) error { t.msgs = append(t.msgs, msgBody) diff --git a/core/capabilities/remote/executable/server.go b/core/capabilities/remote/executable/server.go index d43c7ab5c41..5d6a0aff490 100644 --- a/core/capabilities/remote/executable/server.go +++ b/core/capabilities/remote/executable/server.go @@ -4,6 +4,7 @@ import ( "context" "crypto/sha256" "encoding/hex" + "errors" "fmt" "sync" "time" @@ -137,12 +138,13 @@ func (r *server) Receive(ctx context.Context, msg *types.MessageBody) { defer r.receiveLock.Unlock() switch msg.Method { - case types.MethodExecute, types.MethodRegisterToWorkflow, types.MethodUnregisterFromWorkflow: + case types.MethodExecute: default: r.lggr.Errorw("received request for unsupported method type", "method", remote.SanitizeLogString(msg.Method)) + return } - messageId, err := GetMessageID(msg) + messageID, err := GetMessageID(msg) if err != nil { r.lggr.Errorw("invalid message id", "err", err, "id", remote.SanitizeLogString(string(msg.MessageId))) return @@ -156,21 +158,21 @@ func (r *server) Receive(ctx context.Context, msg *types.MessageBody) { // A request is uniquely identified by the message id and the hash of the payload to prevent a malicious // actor from sending a different payload with the same message id - requestID := messageId + hex.EncodeToString(msgHash[:]) + requestID := messageID + hex.EncodeToString(msgHash[:]) r.lggr.Debugw("received request", "msgId", msg.MessageId, "requestID", requestID) - if requestIDs, ok := r.messageIDToRequestIDsCount[messageId]; ok { - requestIDs[requestID] = requestIDs[requestID] + 1 + if requestIDs, ok := r.messageIDToRequestIDsCount[messageID]; ok { + requestIDs[requestID]++ } else { - r.messageIDToRequestIDsCount[messageId] = map[string]int{requestID: 1} + r.messageIDToRequestIDsCount[messageID] = map[string]int{requestID: 1} } - requestIDs := r.messageIDToRequestIDsCount[messageId] + requestIDs := r.messageIDToRequestIDsCount[messageID] if len(requestIDs) > 1 { // This is a potential attack vector as well as a situation that will occur if the client is sending non-deterministic payloads // so a warning is logged - r.lggr.Warnw("received messages with the same id and different payloads", "messageID", messageId, "lenRequestIDs", len(requestIDs)) + r.lggr.Warnw("received messages with the same id and different payloads", "messageID", messageID, "lenRequestIDs", len(requestIDs)) } if _, ok := r.requestIDToRequest[requestID]; !ok { @@ -182,8 +184,8 @@ func (r *server) Receive(ctx context.Context, msg *types.MessageBody) { r.requestIDToRequest[requestID] = requestAndMsgID{ request: request.NewServerRequest(r.underlying, msg.Method, r.capInfo.ID, r.localDonInfo.ID, r.peerID, - callingDon, messageId, r.dispatcher, r.requestTimeout, r.lggr), - messageID: messageId, + callingDon, messageID, r.dispatcher, r.requestTimeout, r.lggr), + messageID: messageID, } } @@ -218,7 +220,7 @@ func (r *server) getMessageHash(msg *types.MessageBody) ([32]byte, error) { func GetMessageID(msg *types.MessageBody) (string, error) { idStr := string(msg.MessageId) if !validation.IsValidID(idStr) { - return "", fmt.Errorf("invalid message id") + return "", errors.New("invalid message id") } return idStr, nil } diff --git a/core/capabilities/remote/executable/server_test.go b/core/capabilities/remote/executable/server_test.go index 1fb5c2dd413..c92a996f846 100644 --- a/core/capabilities/remote/executable/server_test.go +++ b/core/capabilities/remote/executable/server_test.go @@ -83,89 +83,6 @@ func Test_Server_Execute_RespondsAfterSufficientRequests(t *testing.T) { closeServices(t, srvcs) } -func Test_Server_RegisterToWorkflow_RespondsAfterSufficientRequests(t *testing.T) { - ctx := testutils.Context(t) - - numCapabilityPeers := 4 - - callers, srvcs := testRemoteExecutableCapabilityServer(ctx, t, &commoncap.RemoteExecutableConfig{}, &TestCapability{}, 10, 9, numCapabilityPeers, 3, 10*time.Minute) - - for _, caller := range callers { - err := caller.RegisterToWorkflow(context.Background(), commoncap.RegisterToWorkflowRequest{ - Metadata: commoncap.RegistrationMetadata{ - WorkflowID: workflowID1, - ReferenceID: stepReferenceID1, - WorkflowOwner: workflowOwnerID, - }, - }) - - require.NoError(t, err) - } - - for _, caller := range callers { - for i := 0; i < numCapabilityPeers; i++ { - msg := <-caller.receivedMessages - assert.Equal(t, remotetypes.Error_OK, msg.Error) - } - } - closeServices(t, srvcs) -} - -func Test_Server_RegisterToWorkflow_Error(t *testing.T) { - ctx := testutils.Context(t) - - numCapabilityPeers := 4 - - callers, srvcs := testRemoteExecutableCapabilityServer(ctx, t, &commoncap.RemoteExecutableConfig{}, &TestErrorCapability{}, 10, 9, numCapabilityPeers, 3, 10*time.Minute) - - for _, caller := range callers { - err := caller.RegisterToWorkflow(context.Background(), commoncap.RegisterToWorkflowRequest{ - Metadata: commoncap.RegistrationMetadata{ - WorkflowID: workflowID1, - ReferenceID: stepReferenceID1, - WorkflowOwner: workflowOwnerID, - }, - }) - - require.NoError(t, err) - } - - for _, caller := range callers { - for i := 0; i < numCapabilityPeers; i++ { - msg := <-caller.receivedMessages - assert.Equal(t, remotetypes.Error_INTERNAL_ERROR, msg.Error) - } - } - closeServices(t, srvcs) -} - -func Test_Server_UnregisterFromWorkflow_RespondsAfterSufficientRequests(t *testing.T) { - ctx := testutils.Context(t) - - numCapabilityPeers := 4 - - callers, srvcs := testRemoteExecutableCapabilityServer(ctx, t, &commoncap.RemoteExecutableConfig{}, &TestCapability{}, 10, 9, numCapabilityPeers, 3, 10*time.Minute) - - for _, caller := range callers { - err := caller.UnregisterFromWorkflow(context.Background(), commoncap.UnregisterFromWorkflowRequest{ - Metadata: commoncap.RegistrationMetadata{ - WorkflowID: workflowID1, - ReferenceID: stepReferenceID1, - WorkflowOwner: workflowOwnerID, - }, - }) - require.NoError(t, err) - } - - for _, caller := range callers { - for i := 0; i < numCapabilityPeers; i++ { - msg := <-caller.receivedMessages - assert.Equal(t, remotetypes.Error_OK, msg.Error) - } - } - closeServices(t, srvcs) -} - func Test_Server_InsufficientCallers(t *testing.T) { ctx := testutils.Context(t) @@ -319,62 +236,6 @@ func (r *serverTestClient) Info(ctx context.Context) (commoncap.CapabilityInfo, panic("not implemented") } -func (r *serverTestClient) RegisterToWorkflow(ctx context.Context, req commoncap.RegisterToWorkflowRequest) error { - rawRequest, err := pb.MarshalRegisterToWorkflowRequest(req) - if err != nil { - return err - } - - messageID := remotetypes.MethodRegisterToWorkflow + ":" + req.Metadata.WorkflowID - - for _, node := range r.capabilityDonInfo.Members { - message := &remotetypes.MessageBody{ - CapabilityId: "capability-id", - CapabilityDonId: 1, - CallerDonId: 2, - Method: remotetypes.MethodRegisterToWorkflow, - Payload: rawRequest, - MessageId: []byte(messageID), - Sender: r.peerID[:], - Receiver: node[:], - } - - if err = r.dispatcher.Send(node, message); err != nil { - return err - } - } - - return nil -} - -func (r *serverTestClient) UnregisterFromWorkflow(ctx context.Context, req commoncap.UnregisterFromWorkflowRequest) error { - rawRequest, err := pb.MarshalUnregisterFromWorkflowRequest(req) - if err != nil { - return err - } - - messageID := remotetypes.MethodUnregisterFromWorkflow + ":" + req.Metadata.WorkflowID - - for _, node := range r.capabilityDonInfo.Members { - message := &remotetypes.MessageBody{ - CapabilityId: "capability-id", - CapabilityDonId: 1, - CallerDonId: 2, - Method: remotetypes.MethodUnregisterFromWorkflow, - Payload: rawRequest, - MessageId: []byte(messageID), - Sender: r.peerID[:], - Receiver: node[:], - } - - if err = r.dispatcher.Send(node, message); err != nil { - return err - } - } - - return nil -} - func (r *serverTestClient) Execute(ctx context.Context, req commoncap.CapabilityRequest) (<-chan commoncap.CapabilityResponse, error) { rawRequest, err := pb.MarshalCapabilityRequest(req) if err != nil { diff --git a/core/capabilities/remote/message_cache.go b/core/capabilities/remote/messagecache/message_cache.go similarity index 81% rename from core/capabilities/remote/message_cache.go rename to core/capabilities/remote/messagecache/message_cache.go index f3a3a79b2c6..28ef57ab875 100644 --- a/core/capabilities/remote/message_cache.go +++ b/core/capabilities/remote/messagecache/message_cache.go @@ -1,9 +1,9 @@ -package remote +package messagecache // MessageCache is a simple store for messages, grouped by event ID and peer ID. // It is used to collect messages from multiple peers until they are ready for aggregation // based on quantity and freshness. -type messageCache[EventID comparable, PeerID comparable] struct { +type MessageCache[EventID comparable, PeerID comparable] struct { events map[EventID]*eventState[PeerID] } @@ -18,14 +18,14 @@ type msgState struct { payload []byte } -func NewMessageCache[EventID comparable, PeerID comparable]() *messageCache[EventID, PeerID] { - return &messageCache[EventID, PeerID]{ +func NewMessageCache[EventID comparable, PeerID comparable]() *MessageCache[EventID, PeerID] { + return &MessageCache[EventID, PeerID]{ events: make(map[EventID]*eventState[PeerID]), } } // Insert or overwrite a message for . Return creation timestamp of the event. -func (c *messageCache[EventID, PeerID]) Insert(eventID EventID, peerID PeerID, timestamp int64, payload []byte) int64 { +func (c *MessageCache[EventID, PeerID]) Insert(eventID EventID, peerID PeerID, timestamp int64, payload []byte) int64 { if _, ok := c.events[eventID]; !ok { c.events[eventID] = &eventState[PeerID]{ peerMsgs: make(map[PeerID]*msgState), @@ -43,7 +43,7 @@ func (c *messageCache[EventID, PeerID]) Insert(eventID EventID, peerID PeerID, t // received more recently than . // Return all messages that satisfy the above condition. // Ready() will return true at most once per event if is true. -func (c *messageCache[EventID, PeerID]) Ready(eventID EventID, minCount uint32, minTimestamp int64, once bool) (bool, [][]byte) { +func (c *MessageCache[EventID, PeerID]) Ready(eventID EventID, minCount uint32, minTimestamp int64, once bool) (bool, [][]byte) { ev, ok := c.events[eventID] if !ok { return false, nil @@ -51,6 +51,7 @@ func (c *messageCache[EventID, PeerID]) Ready(eventID EventID, minCount uint32, if ev.wasReady && once { return false, nil } + //nolint:gosec // G115 if uint32(len(ev.peerMsgs)) < minCount { return false, nil } @@ -69,13 +70,13 @@ func (c *messageCache[EventID, PeerID]) Ready(eventID EventID, minCount uint32, return false, nil } -func (c *messageCache[EventID, PeerID]) Delete(eventID EventID) { +func (c *MessageCache[EventID, PeerID]) Delete(eventID EventID) { delete(c.events, eventID) } // Return the number of events deleted. // Scans all keys, which might be slow for large caches. -func (c *messageCache[EventID, PeerID]) DeleteOlderThan(cutoffTimestamp int64) int { +func (c *MessageCache[EventID, PeerID]) DeleteOlderThan(cutoffTimestamp int64) int { nDeleted := 0 for id, event := range c.events { if event.creationTimestamp < cutoffTimestamp { diff --git a/core/capabilities/remote/message_cache_test.go b/core/capabilities/remote/messagecache/message_cache_test.go similarity index 59% rename from core/capabilities/remote/message_cache_test.go rename to core/capabilities/remote/messagecache/message_cache_test.go index 5ca909ca4ec..2d059adef32 100644 --- a/core/capabilities/remote/message_cache_test.go +++ b/core/capabilities/remote/messagecache/message_cache_test.go @@ -1,53 +1,53 @@ -package remote_test +package messagecache_test import ( "testing" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/messagecache" ) const ( - eventId1 = "event1" - eventId2 = "event2" - peerId1 = "peer1" - peerId2 = "peer2" + eventID1 = "event1" + eventID2 = "event2" + peerID1 = "peer1" + peerID2 = "peer2" payloadA = "payloadA" ) func TestMessageCache_InsertReady(t *testing.T) { - cache := remote.NewMessageCache[string, string]() + cache := messagecache.NewMessageCache[string, string]() // not ready with one message - ts := cache.Insert(eventId1, peerId1, 100, []byte(payloadA)) + ts := cache.Insert(eventID1, peerID1, 100, []byte(payloadA)) require.Equal(t, int64(100), ts) - ready, _ := cache.Ready(eventId1, 2, 100, true) + ready, _ := cache.Ready(eventID1, 2, 100, true) require.False(t, ready) // not ready with two messages but only one fresh enough - ts = cache.Insert(eventId1, peerId2, 200, []byte(payloadA)) + ts = cache.Insert(eventID1, peerID2, 200, []byte(payloadA)) require.Equal(t, int64(100), ts) - ready, _ = cache.Ready(eventId1, 2, 150, true) + ready, _ = cache.Ready(eventID1, 2, 150, true) require.False(t, ready) // ready with two messages (once only) - ready, messages := cache.Ready(eventId1, 2, 100, true) + ready, messages := cache.Ready(eventID1, 2, 100, true) require.True(t, ready) require.Equal(t, []byte(payloadA), messages[0]) require.Equal(t, []byte(payloadA), messages[1]) // not ready again for the same event ID - ready, _ = cache.Ready(eventId1, 2, 100, true) + ready, _ = cache.Ready(eventID1, 2, 100, true) require.False(t, ready) } func TestMessageCache_DeleteOlderThan(t *testing.T) { - cache := remote.NewMessageCache[string, string]() + cache := messagecache.NewMessageCache[string, string]() - ts := cache.Insert(eventId1, peerId1, 100, []byte(payloadA)) + ts := cache.Insert(eventID1, peerID1, 100, []byte(payloadA)) require.Equal(t, int64(100), ts) - ts = cache.Insert(eventId2, peerId2, 200, []byte(payloadA)) + ts = cache.Insert(eventID2, peerID2, 200, []byte(payloadA)) require.Equal(t, int64(200), ts) deleted := cache.DeleteOlderThan(150) diff --git a/core/capabilities/remote/trigger_publisher.go b/core/capabilities/remote/trigger_publisher.go index 315959605e8..24bd26757ac 100644 --- a/core/capabilities/remote/trigger_publisher.go +++ b/core/capabilities/remote/trigger_publisher.go @@ -10,6 +10,8 @@ import ( commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/aggregation" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/messagecache" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" "github.com/smartcontractkit/chainlink/v2/core/capabilities/validation" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -30,7 +32,7 @@ type triggerPublisher struct { workflowDONs map[uint32]commoncap.DON membersCache map[uint32]map[p2ptypes.PeerID]bool dispatcher types.Dispatcher - messageCache *messageCache[registrationKey, p2ptypes.PeerID] + messageCache *messagecache.MessageCache[registrationKey, p2ptypes.PeerID] registrations map[registrationKey]*pubRegState mu sync.RWMutex // protects messageCache and registrations batchingQueue map[[32]byte]*batchedResponse @@ -42,8 +44,8 @@ type triggerPublisher struct { } type registrationKey struct { - callerDonId uint32 - workflowId string + callerDonID uint32 + workflowID string } type pubRegState struct { @@ -84,7 +86,7 @@ func NewTriggerPublisher(config *commoncap.RemoteTriggerConfig, underlying commo workflowDONs: workflowDONs, membersCache: membersCache, dispatcher: dispatcher, - messageCache: NewMessageCache[registrationKey, p2ptypes.PeerID](), + messageCache: messagecache.NewMessageCache[registrationKey, p2ptypes.PeerID](), registrations: make(map[registrationKey]*pubRegState), batchingQueue: make(map[[32]byte]*batchedResponse), batchingEnabled: config.MaxBatchSize > 1 && config.BatchCollectionPeriod >= minAllowedBatchCollectionPeriod, @@ -148,7 +150,7 @@ func (p *triggerPublisher) Receive(_ context.Context, msg *types.MessageBody) { p.lggr.Debugw("not ready to aggregate yet", "capabilityId", p.capInfo.ID, "workflowId", req.Metadata.WorkflowID, "minRequired", minRequired) return } - aggregated, err := AggregateModeRaw(payloads, uint32(callerDon.F+1)) + aggregated, err := aggregation.AggregateModeRaw(payloads, uint32(callerDon.F+1)) if err != nil { p.lggr.Errorw("failed to aggregate trigger registrations", "capabilityId", p.capInfo.ID, "workflowId", req.Metadata.WorkflowID, "err", err) return @@ -189,14 +191,14 @@ func (p *triggerPublisher) registrationCleanupLoop() { now := time.Now().UnixMilli() p.mu.Lock() for key, req := range p.registrations { - callerDon := p.workflowDONs[key.callerDonId] + callerDon := p.workflowDONs[key.callerDonID] ready, _ := p.messageCache.Ready(key, uint32(2*callerDon.F+1), now-p.config.RegistrationExpiry.Milliseconds(), false) if !ready { - p.lggr.Infow("trigger registration expired", "capabilityId", p.capInfo.ID, "callerDonID", key.callerDonId, "workflowId", key.workflowId) + p.lggr.Infow("trigger registration expired", "capabilityId", p.capInfo.ID, "callerDonID", key.callerDonID, "workflowId", key.workflowID) ctx, cancel := p.stopCh.NewCtx() err := p.underlying.UnregisterTrigger(ctx, req.request) cancel() - p.lggr.Infow("unregistered trigger", "capabilityId", p.capInfo.ID, "callerDonID", key.callerDonId, "workflowId", key.workflowId, "err", err) + p.lggr.Infow("unregistered trigger", "capabilityId", p.capInfo.ID, "callerDonID", key.callerDonID, "workflowId", key.workflowID, "err", err) // after calling UnregisterTrigger, the underlying trigger will not send any more events to the channel delete(p.registrations, key) p.messageCache.Delete(key) @@ -215,11 +217,11 @@ func (p *triggerPublisher) triggerEventLoop(callbackCh <-chan commoncap.TriggerR return case response, ok := <-callbackCh: if !ok { - p.lggr.Infow("triggerEventLoop channel closed", "capabilityId", p.capInfo.ID, "workflowId", key.workflowId) + p.lggr.Infow("triggerEventLoop channel closed", "capabilityId", p.capInfo.ID, "workflowId", key.workflowID) return } triggerEvent := response.Event - p.lggr.Debugw("received trigger event", "capabilityId", p.capInfo.ID, "workflowId", key.workflowId, "triggerEventID", triggerEvent.ID) + p.lggr.Debugw("received trigger event", "capabilityId", p.capInfo.ID, "workflowId", key.workflowID, "triggerEventID", triggerEvent.ID) marshaledResponse, err := pb.MarshalTriggerResponse(response) if err != nil { p.lggr.Debugw("can't marshal trigger event", "err", err) @@ -232,9 +234,9 @@ func (p *triggerPublisher) triggerEventLoop(callbackCh <-chan commoncap.TriggerR // a single-element "batch" p.sendBatch(&batchedResponse{ rawResponse: marshaledResponse, - callerDonID: key.callerDonId, + callerDonID: key.callerDonID, triggerEventID: triggerEvent.ID, - workflowIDs: []string{key.workflowId}, + workflowIDs: []string{key.workflowID}, }) } } @@ -244,7 +246,7 @@ func (p *triggerPublisher) triggerEventLoop(callbackCh <-chan commoncap.TriggerR func (p *triggerPublisher) enqueueForBatching(rawResponse []byte, key registrationKey, triggerEventID string) { // put in batching queue, group by hash(callerDonId, triggerEventID, response) combined := make([]byte, 4) - binary.LittleEndian.PutUint32(combined, key.callerDonId) + binary.LittleEndian.PutUint32(combined, key.callerDonID) combined = append(combined, []byte(triggerEventID)...) combined = append(combined, rawResponse...) sha := sha256.Sum256(combined) @@ -253,13 +255,13 @@ func (p *triggerPublisher) enqueueForBatching(rawResponse []byte, key registrati if !exists { elem = &batchedResponse{ rawResponse: rawResponse, - callerDonID: key.callerDonId, + callerDonID: key.callerDonID, triggerEventID: triggerEventID, - workflowIDs: []string{key.workflowId}, + workflowIDs: []string{key.workflowID}, } p.batchingQueue[sha] = elem } else { - elem.workflowIDs = append(elem.workflowIDs, key.workflowId) + elem.workflowIDs = append(elem.workflowIDs, key.workflowID) } p.bqMu.Unlock() } diff --git a/core/capabilities/remote/trigger_subscriber.go b/core/capabilities/remote/trigger_subscriber.go index 2638d9ca5f3..7edcbf5eba7 100644 --- a/core/capabilities/remote/trigger_subscriber.go +++ b/core/capabilities/remote/trigger_subscriber.go @@ -9,6 +9,8 @@ import ( commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/aggregation" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/messagecache" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" "github.com/smartcontractkit/chainlink/v2/core/logger" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" @@ -29,7 +31,7 @@ type triggerSubscriber struct { localDonInfo commoncap.DON dispatcher types.Dispatcher aggregator types.Aggregator - messageCache *messageCache[triggerEventKey, p2ptypes.PeerID] + messageCache *messagecache.MessageCache[triggerEventKey, p2ptypes.PeerID] registeredWorkflows map[string]*subRegState mu sync.RWMutex // protects registeredWorkflows and messageCache stopCh services.StopChan @@ -38,8 +40,8 @@ type triggerSubscriber struct { } type triggerEventKey struct { - triggerEventId string - workflowId string + triggerEventID string + workflowID string } type subRegState struct { @@ -65,7 +67,7 @@ const ( func NewTriggerSubscriber(config *commoncap.RemoteTriggerConfig, capInfo commoncap.CapabilityInfo, capDonInfo commoncap.DON, localDonInfo commoncap.DON, dispatcher types.Dispatcher, aggregator types.Aggregator, lggr logger.Logger) *triggerSubscriber { if aggregator == nil { lggr.Warnw("no aggregator provided, using default MODE aggregator", "capabilityId", capInfo.ID) - aggregator = NewDefaultModeAggregator(uint32(capDonInfo.F + 1)) + aggregator = aggregation.NewDefaultModeAggregator(uint32(capDonInfo.F + 1)) } if config == nil { lggr.Info("no config provided, using default values") @@ -84,7 +86,7 @@ func NewTriggerSubscriber(config *commoncap.RemoteTriggerConfig, capInfo commonc localDonInfo: localDonInfo, dispatcher: dispatcher, aggregator: aggregator, - messageCache: NewMessageCache[triggerEventKey, p2ptypes.PeerID](), + messageCache: messagecache.NewMessageCache[triggerEventKey, p2ptypes.PeerID](), registeredWorkflows: make(map[string]*subRegState), stopCh: make(services.StopChan), lggr: lggr.Named("TriggerSubscriber"), @@ -200,17 +202,17 @@ func (s *triggerSubscriber) Receive(_ context.Context, msg *types.MessageBody) { s.lggr.Errorw("received message with too many workflow IDs - truncating", "capabilityId", s.capInfo.ID, "nWorkflows", len(meta.WorkflowIds), "sender", sender) meta.WorkflowIds = meta.WorkflowIds[:maxBatchedWorkflowIDs] } - for _, workflowId := range meta.WorkflowIds { + for _, workflowID := range meta.WorkflowIds { s.mu.RLock() - registration, found := s.registeredWorkflows[workflowId] + registration, found := s.registeredWorkflows[workflowID] s.mu.RUnlock() if !found { - s.lggr.Errorw("received message for unregistered workflow", "capabilityId", s.capInfo.ID, "workflowID", SanitizeLogString(workflowId), "sender", sender) + s.lggr.Errorw("received message for unregistered workflow", "capabilityId", s.capInfo.ID, "workflowID", SanitizeLogString(workflowID), "sender", sender) continue } key := triggerEventKey{ - triggerEventId: meta.TriggerEventId, - workflowId: workflowId, + triggerEventID: meta.TriggerEventId, + workflowID: workflowID, } nowMs := time.Now().UnixMilli() s.mu.Lock() @@ -218,17 +220,17 @@ func (s *triggerSubscriber) Receive(_ context.Context, msg *types.MessageBody) { ready, payloads := s.messageCache.Ready(key, s.config.MinResponsesToAggregate, nowMs-s.config.MessageExpiry.Milliseconds(), true) s.mu.Unlock() if nowMs-creationTs > s.config.RegistrationExpiry.Milliseconds() { - s.lggr.Warnw("received trigger event for an expired ID", "triggerEventID", meta.TriggerEventId, "capabilityId", s.capInfo.ID, "workflowId", workflowId, "sender", sender) + s.lggr.Warnw("received trigger event for an expired ID", "triggerEventID", meta.TriggerEventId, "capabilityId", s.capInfo.ID, "workflowId", workflowID, "sender", sender) continue } if ready { - s.lggr.Debugw("trigger event ready to aggregate", "triggerEventID", meta.TriggerEventId, "capabilityId", s.capInfo.ID, "workflowId", workflowId) + s.lggr.Debugw("trigger event ready to aggregate", "triggerEventID", meta.TriggerEventId, "capabilityId", s.capInfo.ID, "workflowId", workflowID) aggregatedResponse, err := s.aggregator.Aggregate(meta.TriggerEventId, payloads) if err != nil { - s.lggr.Errorw("failed to aggregate responses", "triggerEventID", meta.TriggerEventId, "capabilityId", s.capInfo.ID, "workflowId", workflowId, "err", err) + s.lggr.Errorw("failed to aggregate responses", "triggerEventID", meta.TriggerEventId, "capabilityId", s.capInfo.ID, "workflowId", workflowID, "err", err) continue } - s.lggr.Infow("remote trigger event aggregated", "triggerEventID", meta.TriggerEventId, "capabilityId", s.capInfo.ID, "workflowId", workflowId) + s.lggr.Infow("remote trigger event aggregated", "triggerEventID", meta.TriggerEventId, "capabilityId", s.capInfo.ID, "workflowId", workflowID) registration.callback <- aggregatedResponse } } diff --git a/core/capabilities/remote/trigger_subscriber_test.go b/core/capabilities/remote/trigger_subscriber_test.go index b8cc3ddc7bd..d5b48bc1dc8 100644 --- a/core/capabilities/remote/trigger_subscriber_test.go +++ b/core/capabilities/remote/trigger_subscriber_test.go @@ -26,7 +26,6 @@ const ( var ( triggerEvent1 = map[string]any{"event": "triggerEvent1"} - triggerEvent2 = map[string]any{"event": "triggerEvent2"} ) func TestTriggerSubscriber_RegisterAndReceive(t *testing.T) { diff --git a/core/capabilities/remote/types/mocks/dispatcher.go b/core/capabilities/remote/types/mocks/dispatcher.go index 0948698b935..161cec75b2f 100644 --- a/core/capabilities/remote/types/mocks/dispatcher.go +++ b/core/capabilities/remote/types/mocks/dispatcher.go @@ -1,11 +1,11 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks import ( context "context" - p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" + ragep2ptypes "github.com/smartcontractkit/libocr/ragep2p/types" mock "github.com/stretchr/testify/mock" types "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" @@ -24,7 +24,7 @@ func (_m *Dispatcher) EXPECT() *Dispatcher_Expecter { return &Dispatcher_Expecter{mock: &_m.Mock} } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *Dispatcher) Close() error { ret := _m.Called() @@ -69,7 +69,7 @@ func (_c *Dispatcher_Close_Call) RunAndReturn(run func() error) *Dispatcher_Clos return _c } -// HealthReport provides a mock function with given fields: +// HealthReport provides a mock function with no fields func (_m *Dispatcher) HealthReport() map[string]error { ret := _m.Called() @@ -116,7 +116,7 @@ func (_c *Dispatcher_HealthReport_Call) RunAndReturn(run func() map[string]error return _c } -// Name provides a mock function with given fields: +// Name provides a mock function with no fields func (_m *Dispatcher) Name() string { ret := _m.Called() @@ -161,7 +161,7 @@ func (_c *Dispatcher_Name_Call) RunAndReturn(run func() string) *Dispatcher_Name return _c } -// Ready provides a mock function with given fields: +// Ready provides a mock function with no fields func (_m *Dispatcher) Ready() error { ret := _m.Called() @@ -206,9 +206,9 @@ func (_c *Dispatcher_Ready_Call) RunAndReturn(run func() error) *Dispatcher_Read return _c } -// RemoveReceiver provides a mock function with given fields: capabilityId, donId -func (_m *Dispatcher) RemoveReceiver(capabilityId string, donId uint32) { - _m.Called(capabilityId, donId) +// RemoveReceiver provides a mock function with given fields: capabilityID, donID +func (_m *Dispatcher) RemoveReceiver(capabilityID string, donID uint32) { + _m.Called(capabilityID, donID) } // Dispatcher_RemoveReceiver_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RemoveReceiver' @@ -217,13 +217,13 @@ type Dispatcher_RemoveReceiver_Call struct { } // RemoveReceiver is a helper method to define mock.On call -// - capabilityId string -// - donId uint32 -func (_e *Dispatcher_Expecter) RemoveReceiver(capabilityId interface{}, donId interface{}) *Dispatcher_RemoveReceiver_Call { - return &Dispatcher_RemoveReceiver_Call{Call: _e.mock.On("RemoveReceiver", capabilityId, donId)} +// - capabilityID string +// - donID uint32 +func (_e *Dispatcher_Expecter) RemoveReceiver(capabilityID interface{}, donID interface{}) *Dispatcher_RemoveReceiver_Call { + return &Dispatcher_RemoveReceiver_Call{Call: _e.mock.On("RemoveReceiver", capabilityID, donID)} } -func (_c *Dispatcher_RemoveReceiver_Call) Run(run func(capabilityId string, donId uint32)) *Dispatcher_RemoveReceiver_Call { +func (_c *Dispatcher_RemoveReceiver_Call) Run(run func(capabilityID string, donID uint32)) *Dispatcher_RemoveReceiver_Call { _c.Call.Run(func(args mock.Arguments) { run(args[0].(string), args[1].(uint32)) }) @@ -236,12 +236,12 @@ func (_c *Dispatcher_RemoveReceiver_Call) Return() *Dispatcher_RemoveReceiver_Ca } func (_c *Dispatcher_RemoveReceiver_Call) RunAndReturn(run func(string, uint32)) *Dispatcher_RemoveReceiver_Call { - _c.Call.Return(run) + _c.Run(run) return _c } // Send provides a mock function with given fields: peerID, msgBody -func (_m *Dispatcher) Send(peerID p2ptypes.PeerID, msgBody *types.MessageBody) error { +func (_m *Dispatcher) Send(peerID ragep2ptypes.PeerID, msgBody *types.MessageBody) error { ret := _m.Called(peerID, msgBody) if len(ret) == 0 { @@ -249,7 +249,7 @@ func (_m *Dispatcher) Send(peerID p2ptypes.PeerID, msgBody *types.MessageBody) e } var r0 error - if rf, ok := ret.Get(0).(func(p2ptypes.PeerID, *types.MessageBody) error); ok { + if rf, ok := ret.Get(0).(func(ragep2ptypes.PeerID, *types.MessageBody) error); ok { r0 = rf(peerID, msgBody) } else { r0 = ret.Error(0) @@ -264,15 +264,15 @@ type Dispatcher_Send_Call struct { } // Send is a helper method to define mock.On call -// - peerID p2ptypes.PeerID +// - peerID ragep2ptypes.PeerID // - msgBody *types.MessageBody func (_e *Dispatcher_Expecter) Send(peerID interface{}, msgBody interface{}) *Dispatcher_Send_Call { return &Dispatcher_Send_Call{Call: _e.mock.On("Send", peerID, msgBody)} } -func (_c *Dispatcher_Send_Call) Run(run func(peerID p2ptypes.PeerID, msgBody *types.MessageBody)) *Dispatcher_Send_Call { +func (_c *Dispatcher_Send_Call) Run(run func(peerID ragep2ptypes.PeerID, msgBody *types.MessageBody)) *Dispatcher_Send_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(p2ptypes.PeerID), args[1].(*types.MessageBody)) + run(args[0].(ragep2ptypes.PeerID), args[1].(*types.MessageBody)) }) return _c } @@ -282,14 +282,14 @@ func (_c *Dispatcher_Send_Call) Return(_a0 error) *Dispatcher_Send_Call { return _c } -func (_c *Dispatcher_Send_Call) RunAndReturn(run func(p2ptypes.PeerID, *types.MessageBody) error) *Dispatcher_Send_Call { +func (_c *Dispatcher_Send_Call) RunAndReturn(run func(ragep2ptypes.PeerID, *types.MessageBody) error) *Dispatcher_Send_Call { _c.Call.Return(run) return _c } -// SetReceiver provides a mock function with given fields: capabilityId, donId, receiver -func (_m *Dispatcher) SetReceiver(capabilityId string, donId uint32, receiver types.Receiver) error { - ret := _m.Called(capabilityId, donId, receiver) +// SetReceiver provides a mock function with given fields: capabilityID, donID, receiver +func (_m *Dispatcher) SetReceiver(capabilityID string, donID uint32, receiver types.Receiver) error { + ret := _m.Called(capabilityID, donID, receiver) if len(ret) == 0 { panic("no return value specified for SetReceiver") @@ -297,7 +297,7 @@ func (_m *Dispatcher) SetReceiver(capabilityId string, donId uint32, receiver ty var r0 error if rf, ok := ret.Get(0).(func(string, uint32, types.Receiver) error); ok { - r0 = rf(capabilityId, donId, receiver) + r0 = rf(capabilityID, donID, receiver) } else { r0 = ret.Error(0) } @@ -311,14 +311,14 @@ type Dispatcher_SetReceiver_Call struct { } // SetReceiver is a helper method to define mock.On call -// - capabilityId string -// - donId uint32 +// - capabilityID string +// - donID uint32 // - receiver types.Receiver -func (_e *Dispatcher_Expecter) SetReceiver(capabilityId interface{}, donId interface{}, receiver interface{}) *Dispatcher_SetReceiver_Call { - return &Dispatcher_SetReceiver_Call{Call: _e.mock.On("SetReceiver", capabilityId, donId, receiver)} +func (_e *Dispatcher_Expecter) SetReceiver(capabilityID interface{}, donID interface{}, receiver interface{}) *Dispatcher_SetReceiver_Call { + return &Dispatcher_SetReceiver_Call{Call: _e.mock.On("SetReceiver", capabilityID, donID, receiver)} } -func (_c *Dispatcher_SetReceiver_Call) Run(run func(capabilityId string, donId uint32, receiver types.Receiver)) *Dispatcher_SetReceiver_Call { +func (_c *Dispatcher_SetReceiver_Call) Run(run func(capabilityID string, donID uint32, receiver types.Receiver)) *Dispatcher_SetReceiver_Call { _c.Call.Run(func(args mock.Arguments) { run(args[0].(string), args[1].(uint32), args[2].(types.Receiver)) }) diff --git a/core/capabilities/remote/types/mocks/receiver.go b/core/capabilities/remote/types/mocks/receiver.go index e14e4d0e98f..143c57ab079 100644 --- a/core/capabilities/remote/types/mocks/receiver.go +++ b/core/capabilities/remote/types/mocks/receiver.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -52,7 +52,7 @@ func (_c *Receiver_Receive_Call) Return() *Receiver_Receive_Call { } func (_c *Receiver_Receive_Call) RunAndReturn(run func(context.Context, *types.MessageBody)) *Receiver_Receive_Call { - _c.Call.Return(run) + _c.Run(run) return _c } diff --git a/core/capabilities/remote/types/types.go b/core/capabilities/remote/types/types.go index fefc9a9b5fe..983ac6a8ed2 100644 --- a/core/capabilities/remote/types/types.go +++ b/core/capabilities/remote/types/types.go @@ -13,18 +13,16 @@ import ( ) const ( - MethodRegisterTrigger = "RegisterTrigger" - MethodUnRegisterTrigger = "UnregisterTrigger" - MethodTriggerEvent = "TriggerEvent" - MethodExecute = "Execute" - MethodRegisterToWorkflow = "RegisterToWorkflow" - MethodUnregisterFromWorkflow = "UnregisterFromWorkflow" + MethodRegisterTrigger = "RegisterTrigger" + MethodUnRegisterTrigger = "UnregisterTrigger" + MethodTriggerEvent = "TriggerEvent" + MethodExecute = "Execute" ) type Dispatcher interface { services.Service - SetReceiver(capabilityId string, donId uint32, receiver Receiver) error - RemoveReceiver(capabilityId string, donId uint32) + SetReceiver(capabilityID string, donID uint32, receiver Receiver) error + RemoveReceiver(capabilityID string, donID uint32) Send(peerID p2ptypes.PeerID, msgBody *MessageBody) error } diff --git a/core/capabilities/remote/utils.go b/core/capabilities/remote/utils.go index ea6a3efb186..7af34c5c946 100644 --- a/core/capabilities/remote/utils.go +++ b/core/capabilities/remote/utils.go @@ -3,7 +3,6 @@ package remote import ( "bytes" "crypto/ed25519" - "crypto/sha256" "encoding/hex" "errors" "fmt" @@ -11,8 +10,6 @@ import ( "google.golang.org/protobuf/proto" - commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" - "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" ) @@ -25,25 +22,25 @@ func ValidateMessage(msg p2ptypes.Message, expectedReceiver p2ptypes.PeerID) (*r var topLevelMessage remotetypes.Message err := proto.Unmarshal(msg.Payload, &topLevelMessage) if err != nil { - return nil, fmt.Errorf("failed to unmarshal message, err: %v", err) + return nil, fmt.Errorf("failed to unmarshal message, err: %w", err) } var body remotetypes.MessageBody err = proto.Unmarshal(topLevelMessage.Body, &body) if err != nil { - return nil, fmt.Errorf("failed to unmarshal message body, err: %v", err) + return nil, fmt.Errorf("failed to unmarshal message body, err: %w", err) } if len(body.Sender) != p2ptypes.PeerIDLength || len(body.Receiver) != p2ptypes.PeerIDLength { return &body, fmt.Errorf("invalid sender length (%d) or receiver length (%d)", len(body.Sender), len(body.Receiver)) } if !ed25519.Verify(body.Sender, topLevelMessage.Body, topLevelMessage.Signature) { - return &body, fmt.Errorf("failed to verify message signature") + return &body, errors.New("failed to verify message signature") } // NOTE we currently don't support relaying messages so the p2p message sender needs to be the message author if !bytes.Equal(body.Sender, msg.Sender[:]) { - return &body, fmt.Errorf("sender in message body does not match sender of p2p message") + return &body, errors.New("sender in message body does not match sender of p2p message") } if !bytes.Equal(body.Receiver, expectedReceiver[:]) { - return &body, fmt.Errorf("receiver in message body does not match expected receiver") + return &body, errors.New("receiver in message body does not match expected receiver") } return &body, nil } @@ -58,52 +55,6 @@ func ToPeerID(peerID []byte) (p2ptypes.PeerID, error) { return id, nil } -// Default MODE Aggregator needs a configurable number of identical responses for aggregation to succeed -type defaultModeAggregator struct { - minIdenticalResponses uint32 -} - -var _ remotetypes.Aggregator = &defaultModeAggregator{} - -func NewDefaultModeAggregator(minIdenticalResponses uint32) *defaultModeAggregator { - return &defaultModeAggregator{ - minIdenticalResponses: minIdenticalResponses, - } -} - -func (a *defaultModeAggregator) Aggregate(_ string, responses [][]byte) (commoncap.TriggerResponse, error) { - found, err := AggregateModeRaw(responses, a.minIdenticalResponses) - if err != nil { - return commoncap.TriggerResponse{}, fmt.Errorf("failed to aggregate responses, err: %w", err) - } - - unmarshaled, err := pb.UnmarshalTriggerResponse(found) - if err != nil { - return commoncap.TriggerResponse{}, fmt.Errorf("failed to unmarshal aggregated responses, err: %w", err) - } - return unmarshaled, nil -} - -func AggregateModeRaw(elemList [][]byte, minIdenticalResponses uint32) ([]byte, error) { - hashToCount := make(map[string]uint32) - var found []byte - for _, elem := range elemList { - hasher := sha256.New() - hasher.Write(elem) - sha := hex.EncodeToString(hasher.Sum(nil)) - hashToCount[sha]++ - if hashToCount[sha] >= minIdenticalResponses { - found = elem - // update in case we find another elem with an even higher count - minIdenticalResponses = hashToCount[sha] - } - } - if found == nil { - return nil, errors.New("not enough identical responses found") - } - return found, nil -} - func SanitizeLogString(s string) string { tooLongSuffix := "" if len(s) > maxLoggedStringLen { diff --git a/core/capabilities/remote/utils_test.go b/core/capabilities/remote/utils_test.go index 6707e6ffb25..360ef9000ba 100644 --- a/core/capabilities/remote/utils_test.go +++ b/core/capabilities/remote/utils_test.go @@ -10,43 +10,39 @@ import ( ragetypes "github.com/smartcontractkit/libocr/ragep2p/types" - commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" - "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" - "github.com/smartcontractkit/chainlink-common/pkg/values" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote" remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" ) const ( - capId1 = "cap1" - capId2 = "cap2" - donId1 = uint32(1) + capID1 = "cap1" + capID2 = "cap2" + donID1 = uint32(1) payload1 = "hello world" payload2 = "goodbye world" ) func TestValidateMessage(t *testing.T) { - privKey1, peerId1 := newKeyPair(t) - _, peerId2 := newKeyPair(t) + privKey1, peerID1 := newKeyPair(t) + _, peerID2 := newKeyPair(t) // valid - p2pMsg := encodeAndSign(t, privKey1, peerId1, peerId2, capId1, donId1, []byte(payload1)) - body, err := remote.ValidateMessage(p2pMsg, peerId2) + p2pMsg := encodeAndSign(t, privKey1, peerID1, peerID2, capID1, donID1, []byte(payload1)) + body, err := remote.ValidateMessage(p2pMsg, peerID2) require.NoError(t, err) - require.Equal(t, peerId1[:], body.Sender) + require.Equal(t, peerID1[:], body.Sender) require.Equal(t, payload1, string(body.Payload)) // invalid sender - p2pMsg = encodeAndSign(t, privKey1, peerId1, peerId2, capId1, donId1, []byte(payload1)) - p2pMsg.Sender = peerId2 - _, err = remote.ValidateMessage(p2pMsg, peerId2) + p2pMsg = encodeAndSign(t, privKey1, peerID1, peerID2, capID1, donID1, []byte(payload1)) + p2pMsg.Sender = peerID2 + _, err = remote.ValidateMessage(p2pMsg, peerID2) require.Error(t, err) // invalid receiver - p2pMsg = encodeAndSign(t, privKey1, peerId1, peerId2, capId1, donId1, []byte(payload1)) - _, err = remote.ValidateMessage(p2pMsg, peerId1) + p2pMsg = encodeAndSign(t, privKey1, peerID1, peerID2, capID1, donID1, []byte(payload1)) + _, err = remote.ValidateMessage(p2pMsg, peerID1) require.Error(t, err) } @@ -58,12 +54,12 @@ func newKeyPair(t *testing.T) (ed25519.PrivateKey, ragetypes.PeerID) { return privKey, peerID } -func encodeAndSign(t *testing.T, senderPrivKey ed25519.PrivateKey, senderId p2ptypes.PeerID, receiverId p2ptypes.PeerID, capabilityId string, donId uint32, payload []byte) p2ptypes.Message { +func encodeAndSign(t *testing.T, senderPrivKey ed25519.PrivateKey, senderID p2ptypes.PeerID, receiverID p2ptypes.PeerID, capabilityID string, donID uint32, payload []byte) p2ptypes.Message { body := remotetypes.MessageBody{ - Sender: senderId[:], - Receiver: receiverId[:], - CapabilityId: capabilityId, - CapabilityDonId: donId, + Sender: senderID[:], + Receiver: receiverID[:], + CapabilityId: capabilityID, + CapabilityDonId: donID, Payload: payload, } rawBody, err := proto.Marshal(&body) @@ -78,7 +74,7 @@ func encodeAndSign(t *testing.T, senderPrivKey ed25519.PrivateKey, senderId p2pt require.NoError(t, err) return p2ptypes.Message{ - Sender: senderId, + Sender: senderID, Payload: rawMsg, } } @@ -89,41 +85,6 @@ func TestToPeerID(t *testing.T) { require.Equal(t, "12D3KooWD8QYTQVYjB6oog4Ej8PcPpqTrPRnxLQap8yY8KUQRVvq", id.String()) } -func TestDefaultModeAggregator_Aggregate(t *testing.T) { - val, err := values.NewMap(triggerEvent1) - require.NoError(t, err) - capResponse1 := commoncap.TriggerResponse{ - Event: commoncap.TriggerEvent{ - Outputs: val, - }, - Err: nil, - } - marshaled1, err := pb.MarshalTriggerResponse(capResponse1) - require.NoError(t, err) - - val2, err := values.NewMap(triggerEvent2) - require.NoError(t, err) - capResponse2 := commoncap.TriggerResponse{ - Event: commoncap.TriggerEvent{ - Outputs: val2, - }, - Err: nil, - } - marshaled2, err := pb.MarshalTriggerResponse(capResponse2) - require.NoError(t, err) - - agg := remote.NewDefaultModeAggregator(2) - _, err = agg.Aggregate("", [][]byte{marshaled1}) - require.Error(t, err) - - _, err = agg.Aggregate("", [][]byte{marshaled1, marshaled2}) - require.Error(t, err) - - res, err := agg.Aggregate("", [][]byte{marshaled1, marshaled2, marshaled1}) - require.NoError(t, err) - require.Equal(t, res, capResponse1) -} - func TestSanitizeLogString(t *testing.T) { require.Equal(t, "hello", remote.SanitizeLogString("hello")) require.Equal(t, "[UNPRINTABLE] 0a", remote.SanitizeLogString("\n")) diff --git a/core/capabilities/targets/mocks/contract_value_getter.go b/core/capabilities/targets/mocks/contract_value_getter.go index b662562ba44..e342442e3a5 100644 --- a/core/capabilities/targets/mocks/contract_value_getter.go +++ b/core/capabilities/targets/mocks/contract_value_getter.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -72,7 +72,7 @@ func (_c *ContractValueGetter_Bind_Call) RunAndReturn(run func(context.Context, } // GetLatestValue provides a mock function with given fields: _a0, _a1, _a2, _a3, _a4 -func (_m *ContractValueGetter) GetLatestValue(_a0 context.Context, _a1 string, _a2 primitives.ConfidenceLevel, _a3 any, _a4 any) error { +func (_m *ContractValueGetter) GetLatestValue(_a0 context.Context, _a1 string, _a2 primitives.ConfidenceLevel, _a3 interface{}, _a4 interface{}) error { ret := _m.Called(_a0, _a1, _a2, _a3, _a4) if len(ret) == 0 { @@ -80,7 +80,7 @@ func (_m *ContractValueGetter) GetLatestValue(_a0 context.Context, _a1 string, _ } var r0 error - if rf, ok := ret.Get(0).(func(context.Context, string, primitives.ConfidenceLevel, any, any) error); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, primitives.ConfidenceLevel, interface{}, interface{}) error); ok { r0 = rf(_a0, _a1, _a2, _a3, _a4) } else { r0 = ret.Error(0) @@ -98,15 +98,15 @@ type ContractValueGetter_GetLatestValue_Call struct { // - _a0 context.Context // - _a1 string // - _a2 primitives.ConfidenceLevel -// - _a3 any -// - _a4 any +// - _a3 interface{} +// - _a4 interface{} func (_e *ContractValueGetter_Expecter) GetLatestValue(_a0 interface{}, _a1 interface{}, _a2 interface{}, _a3 interface{}, _a4 interface{}) *ContractValueGetter_GetLatestValue_Call { return &ContractValueGetter_GetLatestValue_Call{Call: _e.mock.On("GetLatestValue", _a0, _a1, _a2, _a3, _a4)} } -func (_c *ContractValueGetter_GetLatestValue_Call) Run(run func(_a0 context.Context, _a1 string, _a2 primitives.ConfidenceLevel, _a3 any, _a4 any)) *ContractValueGetter_GetLatestValue_Call { +func (_c *ContractValueGetter_GetLatestValue_Call) Run(run func(_a0 context.Context, _a1 string, _a2 primitives.ConfidenceLevel, _a3 interface{}, _a4 interface{})) *ContractValueGetter_GetLatestValue_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string), args[2].(primitives.ConfidenceLevel), args[3].(any), args[4].(any)) + run(args[0].(context.Context), args[1].(string), args[2].(primitives.ConfidenceLevel), args[3].(interface{}), args[4].(interface{})) }) return _c } @@ -116,7 +116,7 @@ func (_c *ContractValueGetter_GetLatestValue_Call) Return(_a0 error) *ContractVa return _c } -func (_c *ContractValueGetter_GetLatestValue_Call) RunAndReturn(run func(context.Context, string, primitives.ConfidenceLevel, any, any) error) *ContractValueGetter_GetLatestValue_Call { +func (_c *ContractValueGetter_GetLatestValue_Call) RunAndReturn(run func(context.Context, string, primitives.ConfidenceLevel, interface{}, interface{}) error) *ContractValueGetter_GetLatestValue_Call { _c.Call.Return(run) return _c } diff --git a/core/capabilities/targets/mocks/contract_writer.go b/core/capabilities/targets/mocks/contract_writer.go index c6128e68fc7..55eb88b9ce2 100644 --- a/core/capabilities/targets/mocks/contract_writer.go +++ b/core/capabilities/targets/mocks/contract_writer.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -24,7 +24,7 @@ func (_m *ContractWriter) EXPECT() *ContractWriter_Expecter { return &ContractWriter_Expecter{mock: &_m.Mock} } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *ContractWriter) Close() error { ret := _m.Called() @@ -184,7 +184,7 @@ func (_c *ContractWriter_GetTransactionStatus_Call) RunAndReturn(run func(contex return _c } -// HealthReport provides a mock function with given fields: +// HealthReport provides a mock function with no fields func (_m *ContractWriter) HealthReport() map[string]error { ret := _m.Called() @@ -231,7 +231,7 @@ func (_c *ContractWriter_HealthReport_Call) RunAndReturn(run func() map[string]e return _c } -// Name provides a mock function with given fields: +// Name provides a mock function with no fields func (_m *ContractWriter) Name() string { ret := _m.Called() @@ -276,7 +276,7 @@ func (_c *ContractWriter_Name_Call) RunAndReturn(run func() string) *ContractWri return _c } -// Ready provides a mock function with given fields: +// Ready provides a mock function with no fields func (_m *ContractWriter) Ready() error { ret := _m.Called() @@ -368,7 +368,7 @@ func (_c *ContractWriter_Start_Call) RunAndReturn(run func(context.Context) erro } // SubmitTransaction provides a mock function with given fields: ctx, contractName, method, args, transactionID, toAddress, meta, value -func (_m *ContractWriter) SubmitTransaction(ctx context.Context, contractName string, method string, args any, transactionID string, toAddress string, meta *types.TxMeta, value *big.Int) error { +func (_m *ContractWriter) SubmitTransaction(ctx context.Context, contractName string, method string, args interface{}, transactionID string, toAddress string, meta *types.TxMeta, value *big.Int) error { ret := _m.Called(ctx, contractName, method, args, transactionID, toAddress, meta, value) if len(ret) == 0 { @@ -376,7 +376,7 @@ func (_m *ContractWriter) SubmitTransaction(ctx context.Context, contractName st } var r0 error - if rf, ok := ret.Get(0).(func(context.Context, string, string, any, string, string, *types.TxMeta, *big.Int) error); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, string, interface{}, string, string, *types.TxMeta, *big.Int) error); ok { r0 = rf(ctx, contractName, method, args, transactionID, toAddress, meta, value) } else { r0 = ret.Error(0) @@ -394,7 +394,7 @@ type ContractWriter_SubmitTransaction_Call struct { // - ctx context.Context // - contractName string // - method string -// - args any +// - args interface{} // - transactionID string // - toAddress string // - meta *types.TxMeta @@ -403,9 +403,9 @@ func (_e *ContractWriter_Expecter) SubmitTransaction(ctx interface{}, contractNa return &ContractWriter_SubmitTransaction_Call{Call: _e.mock.On("SubmitTransaction", ctx, contractName, method, args, transactionID, toAddress, meta, value)} } -func (_c *ContractWriter_SubmitTransaction_Call) Run(run func(ctx context.Context, contractName string, method string, args any, transactionID string, toAddress string, meta *types.TxMeta, value *big.Int)) *ContractWriter_SubmitTransaction_Call { +func (_c *ContractWriter_SubmitTransaction_Call) Run(run func(ctx context.Context, contractName string, method string, args interface{}, transactionID string, toAddress string, meta *types.TxMeta, value *big.Int)) *ContractWriter_SubmitTransaction_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].(any), args[4].(string), args[5].(string), args[6].(*types.TxMeta), args[7].(*big.Int)) + run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].(interface{}), args[4].(string), args[5].(string), args[6].(*types.TxMeta), args[7].(*big.Int)) }) return _c } @@ -415,7 +415,7 @@ func (_c *ContractWriter_SubmitTransaction_Call) Return(_a0 error) *ContractWrit return _c } -func (_c *ContractWriter_SubmitTransaction_Call) RunAndReturn(run func(context.Context, string, string, any, string, string, *types.TxMeta, *big.Int) error) *ContractWriter_SubmitTransaction_Call { +func (_c *ContractWriter_SubmitTransaction_Call) RunAndReturn(run func(context.Context, string, string, interface{}, string, string, *types.TxMeta, *big.Int) error) *ContractWriter_SubmitTransaction_Call { _c.Call.Return(run) return _c } diff --git a/core/capabilities/targets/write_target.go b/core/capabilities/targets/write_target.go index 09a0bbd2b36..3fc51270c86 100644 --- a/core/capabilities/targets/write_target.go +++ b/core/capabilities/targets/write_target.go @@ -345,10 +345,11 @@ func (cap *WriteTarget) Execute(ctx context.Context, rawRequest capabilities.Cap return capabilities.CapabilityResponse{}, nil case commontypes.Failed, commontypes.Fatal: cap.lggr.Error("Transaction failed", "request", request, "transaction", txID) + msg := "failed to submit transaction with ID: " + txID.String() err = cap.emitter.With( platform.KeyWorkflowID, request.Metadata.WorkflowID, - platform.KeyWorkflowName, request.Metadata.WorkflowName, + platform.KeyWorkflowName, request.Metadata.DecodedWorkflowName, platform.KeyWorkflowOwner, request.Metadata.WorkflowOwner, platform.KeyWorkflowExecutionID, request.Metadata.WorkflowExecutionID, ).Emit(ctx, msg) diff --git a/core/chains/evm/client/chain_client.go b/core/chains/evm/client/chain_client.go index 0835b4c0ed8..612a95b7461 100644 --- a/core/chains/evm/client/chain_client.go +++ b/core/chains/evm/client/chain_client.go @@ -14,7 +14,7 @@ import ( commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets" "github.com/smartcontractkit/chainlink-common/pkg/logger" - commonclient "github.com/smartcontractkit/chainlink/v2/common/client" + "github.com/smartcontractkit/chainlink-framework/multinode" evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" @@ -60,7 +60,7 @@ type Client interface { // to use HeadTracker to get latest finalized block. LatestFinalizedBlock(ctx context.Context) (head *evmtypes.Head, err error) - SendTransactionReturnCode(ctx context.Context, tx *types.Transaction, fromAddress common.Address) (commonclient.SendTxReturnCode, error) + SendTransactionReturnCode(ctx context.Context, tx *types.Transaction, fromAddress common.Address) (multinode.SendTxReturnCode, error) // Wrapped Geth client methods // blockNumber can be specified as `nil` to imply latest block @@ -97,11 +97,11 @@ type Client interface { } type chainClient struct { - multiNode *commonclient.MultiNode[ + multiNode *multinode.MultiNode[ *big.Int, *RPCClient, ] - txSender *commonclient.TransactionSender[*types.Transaction, *SendTxResult, *big.Int, *RPCClient] + txSender *multinode.TransactionSender[*types.Transaction, *SendTxResult, *big.Int, *RPCClient] logger logger.SugaredLogger chainType chaintype.ChainType clientErrors evmconfig.ClientErrors @@ -111,15 +111,15 @@ func NewChainClient( lggr logger.Logger, selectionMode string, leaseDuration time.Duration, - nodes []commonclient.Node[*big.Int, *RPCClient], - sendonlys []commonclient.SendOnlyNode[*big.Int, *RPCClient], + nodes []multinode.Node[*big.Int, *RPCClient], + sendonlys []multinode.SendOnlyNode[*big.Int, *RPCClient], chainID *big.Int, clientErrors evmconfig.ClientErrors, deathDeclarationDelay time.Duration, chainType chaintype.ChainType, ) Client { chainFamily := "EVM" - multiNode := commonclient.NewMultiNode[*big.Int, *RPCClient]( + multiNode := multinode.NewMultiNode[*big.Int, *RPCClient]( lggr, selectionMode, leaseDuration, @@ -130,7 +130,7 @@ func NewChainClient( deathDeclarationDelay, ) - txSender := commonclient.NewTransactionSender[*types.Transaction, *SendTxResult, *big.Int, *RPCClient]( + txSender := multinode.NewTransactionSender[*types.Transaction, *SendTxResult, *big.Int, *RPCClient]( lggr, chainID, chainFamily, @@ -389,7 +389,7 @@ func (c *chainClient) SendTransaction(ctx context.Context, tx *types.Transaction return result.Error() } -func (c *chainClient) SendTransactionReturnCode(ctx context.Context, tx *types.Transaction, fromAddress common.Address) (commonclient.SendTxReturnCode, error) { +func (c *chainClient) SendTransactionReturnCode(ctx context.Context, tx *types.Transaction, fromAddress common.Address) (multinode.SendTxReturnCode, error) { err := c.SendTransaction(ctx, tx) returnCode := ClassifySendError(err, c.clientErrors, c.logger, tx, fromAddress, c.IsL2()) return returnCode, err diff --git a/core/chains/evm/client/chain_client_test.go b/core/chains/evm/client/chain_client_test.go index 77e11db7a90..e775feb1434 100644 --- a/core/chains/evm/client/chain_client_test.go +++ b/core/chains/evm/client/chain_client_test.go @@ -25,8 +25,8 @@ import ( "github.com/tidwall/gjson" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink-framework/multinode" - commonclient "github.com/smartcontractkit/chainlink/v2/common/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/testutils" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" @@ -39,7 +39,7 @@ func mustNewChainClient(t *testing.T, wsURL string, sendonlys ...url.URL) client func mustNewChainClientWithChainID(t *testing.T, wsURL string, chainID *big.Int, sendonlys ...url.URL) client.Client { cfg := client.TestNodePoolConfig{ - NodeSelectionMode: commonclient.NodeSelectionModeRoundRobin, + NodeSelectionMode: multinode.NodeSelectionModeRoundRobin, } c, err := client.NewChainClientWithTestNode(t, cfg, time.Second*0, cfg.NodeLeaseDuration, wsURL, nil, sendonlys, 42, chainID) require.NoError(t, err) @@ -491,7 +491,7 @@ func TestEthClient_SendTransactionReturnCode(t *testing.T) { errType, err := ethClient.SendTransactionReturnCode(tests.Context(t), tx, fromAddress) assert.Error(t, err) - assert.Equal(t, errType, commonclient.Fatal) + assert.Equal(t, multinode.Fatal, errType) }) t.Run("returns TransactionAlreadyKnown error type when error message is nonce too low", func(t *testing.T) { @@ -517,7 +517,7 @@ func TestEthClient_SendTransactionReturnCode(t *testing.T) { errType, err := ethClient.SendTransactionReturnCode(tests.Context(t), tx, fromAddress) assert.Error(t, err) - assert.Equal(t, errType, commonclient.TransactionAlreadyKnown) + assert.Equal(t, multinode.TransactionAlreadyKnown, errType) }) t.Run("returns Successful error type when there is no error message", func(t *testing.T) { @@ -542,7 +542,7 @@ func TestEthClient_SendTransactionReturnCode(t *testing.T) { errType, err := ethClient.SendTransactionReturnCode(tests.Context(t), tx, fromAddress) assert.NoError(t, err) - assert.Equal(t, errType, commonclient.Successful) + assert.Equal(t, multinode.Successful, errType) }) t.Run("returns Underpriced error type when transaction is terminally underpriced", func(t *testing.T) { @@ -568,7 +568,7 @@ func TestEthClient_SendTransactionReturnCode(t *testing.T) { errType, err := ethClient.SendTransactionReturnCode(tests.Context(t), tx, fromAddress) assert.Error(t, err) - assert.Equal(t, errType, commonclient.Underpriced) + assert.Equal(t, multinode.Underpriced, errType) }) t.Run("returns Unsupported error type when error message is queue full", func(t *testing.T) { @@ -594,7 +594,7 @@ func TestEthClient_SendTransactionReturnCode(t *testing.T) { errType, err := ethClient.SendTransactionReturnCode(tests.Context(t), tx, fromAddress) assert.Error(t, err) - assert.Equal(t, errType, commonclient.Unsupported) + assert.Equal(t, multinode.Unsupported, errType) }) t.Run("returns Retryable error type when there is a transaction gap", func(t *testing.T) { @@ -620,7 +620,7 @@ func TestEthClient_SendTransactionReturnCode(t *testing.T) { errType, err := ethClient.SendTransactionReturnCode(tests.Context(t), tx, fromAddress) assert.Error(t, err) - assert.Equal(t, errType, commonclient.Retryable) + assert.Equal(t, multinode.Retryable, errType) }) t.Run("returns InsufficientFunds error type when the sender address doesn't have enough funds", func(t *testing.T) { @@ -646,7 +646,7 @@ func TestEthClient_SendTransactionReturnCode(t *testing.T) { errType, err := ethClient.SendTransactionReturnCode(tests.Context(t), tx, fromAddress) assert.Error(t, err) - assert.Equal(t, errType, commonclient.InsufficientFunds) + assert.Equal(t, multinode.InsufficientFunds, errType) }) t.Run("returns ExceedsFeeCap error type when gas price is too high for the node", func(t *testing.T) { @@ -672,7 +672,7 @@ func TestEthClient_SendTransactionReturnCode(t *testing.T) { errType, err := ethClient.SendTransactionReturnCode(tests.Context(t), tx, fromAddress) assert.Error(t, err) - assert.Equal(t, errType, commonclient.ExceedsMaxFee) + assert.Equal(t, multinode.ExceedsMaxFee, errType) }) t.Run("returns Unknown error type when the error can't be categorized", func(t *testing.T) { @@ -698,7 +698,7 @@ func TestEthClient_SendTransactionReturnCode(t *testing.T) { errType, err := ethClient.SendTransactionReturnCode(tests.Context(t), tx, fromAddress) assert.Error(t, err) - assert.Equal(t, errType, commonclient.Unknown) + assert.Equal(t, multinode.Unknown, errType) }) } @@ -793,34 +793,34 @@ func TestEthClient_ErroringClient(t *testing.T) { ctx := tests.Context(t) // Empty node means there are no active nodes to select from, causing client to always return error. - erroringClient := client.NewChainClientWithEmptyNode(t, commonclient.NodeSelectionModeRoundRobin, time.Second*0, time.Second*0, testutils.FixtureChainID) + erroringClient := client.NewChainClientWithEmptyNode(t, multinode.NodeSelectionModeRoundRobin, time.Second*0, time.Second*0, testutils.FixtureChainID) _, err := erroringClient.BalanceAt(ctx, common.Address{}, nil) - require.Equal(t, err, commonclient.ErroringNodeError) + require.Equal(t, multinode.ErrNodeError, err) err = erroringClient.BatchCallContext(ctx, nil) - require.Equal(t, err, commonclient.ErroringNodeError) + require.Equal(t, multinode.ErrNodeError, err) err = erroringClient.BatchCallContextAll(ctx, nil) - require.Equal(t, err, commonclient.ErroringNodeError) + require.Equal(t, multinode.ErrNodeError, err) _, err = erroringClient.BlockByHash(ctx, common.Hash{}) - require.Equal(t, err, commonclient.ErroringNodeError) + require.Equal(t, multinode.ErrNodeError, err) _, err = erroringClient.BlockByNumber(ctx, nil) - require.Equal(t, err, commonclient.ErroringNodeError) + require.Equal(t, multinode.ErrNodeError, err) err = erroringClient.CallContext(ctx, nil, "") - require.Equal(t, err, commonclient.ErroringNodeError) + require.Equal(t, multinode.ErrNodeError, err) _, err = erroringClient.CallContract(ctx, ethereum.CallMsg{}, nil) - require.Equal(t, err, commonclient.ErroringNodeError) + require.Equal(t, multinode.ErrNodeError, err) id := erroringClient.ConfiguredChainID() require.Equal(t, id, big.NewInt(0)) _, err = erroringClient.CodeAt(ctx, common.Address{}, nil) - require.Equal(t, err, commonclient.ErroringNodeError) + require.Equal(t, multinode.ErrNodeError, err) id = erroringClient.ConfiguredChainID() require.Equal(t, id, testutils.FixtureChainID) @@ -829,67 +829,67 @@ func TestEthClient_ErroringClient(t *testing.T) { require.ErrorContains(t, err, "no available nodes for chain") _, err = erroringClient.EstimateGas(ctx, ethereum.CallMsg{}) - require.Equal(t, err, commonclient.ErroringNodeError) + require.Equal(t, multinode.ErrNodeError, err) _, err = erroringClient.FilterLogs(ctx, ethereum.FilterQuery{}) - require.Equal(t, err, commonclient.ErroringNodeError) + require.Equal(t, multinode.ErrNodeError, err) _, err = erroringClient.HeaderByHash(ctx, common.Hash{}) - require.Equal(t, err, commonclient.ErroringNodeError) + require.Equal(t, multinode.ErrNodeError, err) _, err = erroringClient.HeaderByNumber(ctx, nil) - require.Equal(t, err, commonclient.ErroringNodeError) + require.Equal(t, multinode.ErrNodeError, err) _, err = erroringClient.HeadByHash(ctx, common.Hash{}) - require.Equal(t, err, commonclient.ErroringNodeError) + require.Equal(t, multinode.ErrNodeError, err) _, err = erroringClient.HeadByNumber(ctx, nil) - require.Equal(t, err, commonclient.ErroringNodeError) + require.Equal(t, multinode.ErrNodeError, err) _, err = erroringClient.LINKBalance(ctx, common.Address{}, common.Address{}) - require.Equal(t, err, commonclient.ErroringNodeError) + require.Equal(t, multinode.ErrNodeError, err) _, err = erroringClient.LatestBlockHeight(ctx) - require.Equal(t, err, commonclient.ErroringNodeError) + require.Equal(t, multinode.ErrNodeError, err) _, err = erroringClient.PendingCodeAt(ctx, common.Address{}) - require.Equal(t, err, commonclient.ErroringNodeError) + require.Equal(t, multinode.ErrNodeError, err) _, err = erroringClient.PendingNonceAt(ctx, common.Address{}) - require.Equal(t, err, commonclient.ErroringNodeError) + require.Equal(t, multinode.ErrNodeError, err) txSenderNotStarted := errors.New("TransactionSender not started") err = erroringClient.SendTransaction(ctx, nil) - require.Equal(t, err, txSenderNotStarted) + require.Equal(t, txSenderNotStarted, err) tx := testutils.NewLegacyTransaction(uint64(42), testutils.NewAddress(), big.NewInt(142), 242, big.NewInt(342), []byte{1, 2, 3}) code, err := erroringClient.SendTransactionReturnCode(ctx, tx, common.Address{}) - require.Equal(t, code, commonclient.Unknown) - require.Equal(t, err, txSenderNotStarted) + require.Equal(t, multinode.Unknown, code) + require.Equal(t, txSenderNotStarted, err) _, err = erroringClient.NonceAt(ctx, common.Address{}, nil) - require.Equal(t, err, commonclient.ErroringNodeError) + require.Equal(t, multinode.ErrNodeError, err) _, err = erroringClient.SubscribeFilterLogs(ctx, ethereum.FilterQuery{}, nil) - require.Equal(t, err, commonclient.ErroringNodeError) + require.Equal(t, multinode.ErrNodeError, err) _, _, err = erroringClient.SubscribeToHeads(ctx) - require.Equal(t, err, commonclient.ErroringNodeError) + require.Equal(t, multinode.ErrNodeError, err) _, err = erroringClient.SuggestGasPrice(ctx) - require.Equal(t, err, commonclient.ErroringNodeError) + require.Equal(t, multinode.ErrNodeError, err) _, err = erroringClient.SuggestGasTipCap(ctx) - require.Equal(t, err, commonclient.ErroringNodeError) + require.Equal(t, multinode.ErrNodeError, err) _, err = erroringClient.TokenBalance(ctx, common.Address{}, common.Address{}) - require.Equal(t, err, commonclient.ErroringNodeError) + require.Equal(t, multinode.ErrNodeError, err) _, err = erroringClient.TransactionByHash(ctx, common.Hash{}) - require.Equal(t, err, commonclient.ErroringNodeError) + require.Equal(t, multinode.ErrNodeError, err) _, err = erroringClient.TransactionReceipt(ctx, common.Hash{}) - require.Equal(t, err, commonclient.ErroringNodeError) + require.Equal(t, multinode.ErrNodeError, err) } const headResult = client.HeadResult diff --git a/core/chains/evm/client/config_builder.go b/core/chains/evm/client/config_builder.go index 66bdfc2614f..7b412815557 100644 --- a/core/chains/evm/client/config_builder.go +++ b/core/chains/evm/client/config_builder.go @@ -8,8 +8,8 @@ import ( "go.uber.org/multierr" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink-framework/multinode" - commonclient "github.com/smartcontractkit/chainlink/v2/common/client" evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" @@ -44,7 +44,7 @@ func NewClientConfigs( noNewFinalizedHeadsThreshold time.Duration, finalizedBlockPollInterval time.Duration, newHeadsPollInterval time.Duration, -) (commonclient.ChainConfig, evmconfig.NodePool, []*toml.Node, error) { +) (multinode.ChainConfig, evmconfig.NodePool, []*toml.Node, error) { nodes, err := parseNodeConfigs(nodeCfgs) if err != nil { return nil, nil, nil, err diff --git a/core/chains/evm/client/errors.go b/core/chains/evm/client/errors.go index bde97185580..a19e03d50cb 100644 --- a/core/chains/evm/client/errors.go +++ b/core/chains/evm/client/errors.go @@ -14,8 +14,8 @@ import ( pkgerrors "github.com/pkg/errors" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-framework/multinode" - commonclient "github.com/smartcontractkit/chainlink/v2/common/client" commontypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/label" ) @@ -265,9 +265,11 @@ var aStar = ClientErrors{ } var mantle = ClientErrors{ - InsufficientEth: regexp.MustCompile(`(: |^)'*insufficient funds for gas \* price \+ value`), - Fatal: regexp.MustCompile(`(: |^)'*invalid sender`), - NonceTooLow: regexp.MustCompile(`(: |^)'*nonce too low`), + InsufficientEth: regexp.MustCompile(`(: |^)'*insufficient funds for gas \* price \+ value`), + Fatal: regexp.MustCompile(`(: |^)'*invalid sender`), + NonceTooLow: regexp.MustCompile(`(: |^)'*nonce too low`), + ReplacementTransactionUnderpriced: regexp.MustCompile(`(: |^)'*replacement transaction underpriced`), + TransactionAlreadyInMempool: regexp.MustCompile(`(: |^)'*already known`), } var hederaFatal = regexp.MustCompile(`(: |^)(execution reverted)(:|$) | ^Transaction gas limit '(\d+)' exceeds block gas limit '(\d+)' | ^Transaction gas limit provided '(\d+)' is insufficient of intrinsic gas required '(\d+)' | ^Oversized data:|status INVALID_SIGNATURE`) @@ -284,6 +286,16 @@ var gnosis = ClientErrors{ TransactionAlreadyInMempool: regexp.MustCompile(`(: |^)(alreadyknown)`), } +var sei = ClientErrors{ + // https://github.com/sei-protocol/sei-tendermint/blob/e9a22c961e83579d8a68cd045c532980d82fb2a0/types/mempool.go#L12 + TransactionAlreadyInMempool: regexp.MustCompile("tx already exists in cache"), + // https://github.com/sei-protocol/sei-cosmos/blob/a4eb451c957b1ca7ca9118406682f93fe83d1f61/types/errors/errors.go#L50 + // https://github.com/sei-protocol/sei-cosmos/blob/a4eb451c957b1ca7ca9118406682f93fe83d1f61/types/errors/errors.go#L56 + // https://github.com/sei-protocol/sei-cosmos/blob/a4eb451c957b1ca7ca9118406682f93fe83d1f61/client/broadcast.go#L27 + // https://github.com/sei-protocol/sei-cosmos/blob/a4eb451c957b1ca7ca9118406682f93fe83d1f61/types/errors/errors.go#L32 + Fatal: regexp.MustCompile(`(: |^)'*out of gas|insufficient fee|Tx too large. Max size is \d+, but got \d+|: insufficient funds`), +} + const TerminallyStuckMsg = "transaction terminally stuck" // Tx.Error messages that are set internally so they are not chain or client specific @@ -291,7 +303,7 @@ var internal = ClientErrors{ TerminallyStuck: regexp.MustCompile(TerminallyStuckMsg), } -var clients = []ClientErrors{parity, geth, arbitrum, metis, substrate, avalanche, nethermind, harmony, besu, erigon, klaytn, celo, zkSync, zkEvm, treasure, mantle, aStar, hedera, gnosis, internal} +var clients = []ClientErrors{parity, geth, arbitrum, metis, substrate, avalanche, nethermind, harmony, besu, erigon, klaytn, celo, zkSync, zkEvm, treasure, mantle, aStar, hedera, gnosis, sei, internal} // ClientErrorRegexes returns a map of compiled regexes for each error type func ClientErrorRegexes(errsRegex config.ClientErrors) *ClientErrors { @@ -397,7 +409,7 @@ func (s *SendError) IsServiceUnavailable(configErrors *ClientErrors) bool { return false } - return s.is(ServiceUnavailable, configErrors) || pkgerrors.Is(s.err, commonclient.ErroringNodeError) + return s.is(ServiceUnavailable, configErrors) || pkgerrors.Is(s.err, multinode.ErrNodeError) } // IsServiceTimeout indicates if the error was caused by a service timeout @@ -561,10 +573,10 @@ func ExtractRPCError(baseErr error) (*JsonError, error) { return &jErr, nil } -func ClassifySendError(err error, clientErrors config.ClientErrors, lggr logger.SugaredLogger, tx *types.Transaction, fromAddress common.Address, isL2 bool) commonclient.SendTxReturnCode { +func ClassifySendError(err error, clientErrors config.ClientErrors, lggr logger.SugaredLogger, tx *types.Transaction, fromAddress common.Address, isL2 bool) multinode.SendTxReturnCode { sendError := NewSendError(err) if sendError == nil { - return commonclient.Successful + return multinode.Successful } configErrors := ClientErrorRegexes(clientErrors) @@ -572,13 +584,13 @@ func ClassifySendError(err error, clientErrors config.ClientErrors, lggr logger. if sendError.Fatal(configErrors) { lggr.Criticalw("Fatal error sending transaction", "err", sendError, "etx", tx) // Attempt is thrown away in this case; we don't need it since it never got accepted by a node - return commonclient.Fatal + return multinode.Fatal } if sendError.IsNonceTooLowError(configErrors) || sendError.IsTransactionAlreadyMined(configErrors) { lggr.Debugw(fmt.Sprintf("Transaction already confirmed for this nonce: %d", tx.Nonce()), "err", sendError, "etx", tx) // Nonce too low indicated that a transaction at this nonce was confirmed already. // Mark it as TransactionAlreadyKnown. - return commonclient.TransactionAlreadyKnown + return multinode.TransactionAlreadyKnown } if sendError.IsReplacementUnderpriced(configErrors) { lggr.Errorw(fmt.Sprintf("Replacement transaction underpriced for eth_tx %x. "+ @@ -586,57 +598,57 @@ func ClassifySendError(err error, clientErrors config.ClientErrors, lggr logger. tx.Hash()), "gasPrice", tx.GasPrice, "gasTipCap", tx.GasTipCap, "gasFeeCap", tx.GasFeeCap, "err", sendError, "etx", tx) // Assume success and hand off to the next cycle. - return commonclient.Successful + return multinode.Successful } if sendError.IsTransactionAlreadyInMempool(configErrors) { lggr.Debugw("Transaction already in mempool", "etx", tx, "err", sendError) - return commonclient.Successful + return multinode.Successful } if sendError.IsTemporarilyUnderpriced(configErrors) { lggr.Infow("Transaction temporarily underpriced", "err", sendError) - return commonclient.Successful + return multinode.Successful } if sendError.IsTerminallyUnderpriced(configErrors) { lggr.Errorw("Transaction terminally underpriced", "etx", tx, "err", sendError) - return commonclient.Underpriced + return multinode.Underpriced } if sendError.L2FeeTooLow(configErrors) || sendError.IsL2FeeTooHigh(configErrors) || sendError.IsL2Full(configErrors) { if isL2 { lggr.Errorw("Transaction fee out of range", "err", sendError, "etx", tx) - return commonclient.FeeOutOfValidRange + return multinode.FeeOutOfValidRange } lggr.Errorw("this error type only handled for L2s", "err", sendError, "etx", tx) - return commonclient.Unsupported + return multinode.Unsupported } if sendError.IsNonceTooHighError(configErrors) { // This error occurs when the tx nonce is greater than current_nonce + tx_count_in_mempool, // instead of keeping the tx in mempool. This can happen if previous transactions haven't // reached the client yet. The correct thing to do is to mark it as retryable. lggr.Warnw("Transaction has a nonce gap.", "err", sendError, "etx", tx) - return commonclient.Retryable + return multinode.Retryable } if sendError.IsInsufficientEth(configErrors) { lggr.Criticalw(fmt.Sprintf("Tx %x with type 0x%d was rejected due to insufficient eth: %s\n"+ "ACTION REQUIRED: Chainlink wallet with address 0x%x is OUT OF FUNDS", tx.Hash(), tx.Type(), sendError.Error(), fromAddress, ), "err", sendError, "etx", tx) - return commonclient.InsufficientFunds + return multinode.InsufficientFunds } if sendError.IsServiceUnavailable(configErrors) { lggr.Errorw(fmt.Sprintf("service unavailable while sending transaction %x", tx.Hash()), "err", sendError, "etx", tx) - return commonclient.Retryable + return multinode.Retryable } if sendError.IsServiceTimeout(configErrors) { lggr.Errorw(fmt.Sprintf("service timed out while sending transaction %x", tx.Hash()), "err", sendError, "etx", tx) - return commonclient.Retryable + return multinode.Retryable } if sendError.IsTimeout() { lggr.Errorw(fmt.Sprintf("timeout while sending transaction %x", tx.Hash()), "err", sendError, "etx", tx) - return commonclient.Retryable + return multinode.Retryable } if sendError.IsCanceled() { lggr.Errorw(fmt.Sprintf("context was canceled while sending transaction %x", tx.Hash()), "err", sendError, "etx", tx) - return commonclient.Retryable + return multinode.Retryable } if sendError.IsTxFeeExceedsCap(configErrors) { lggr.Criticalw(fmt.Sprintf("Sending transaction failed: %s", label.RPCTxFeeCapConfiguredIncorrectlyWarning), @@ -644,15 +656,15 @@ func ClassifySendError(err error, clientErrors config.ClientErrors, lggr logger. "err", sendError, "id", "RPCTxFeeCapExceeded", ) - return commonclient.ExceedsMaxFee + return multinode.ExceedsMaxFee } if sendError.IsTerminallyStuckConfigError(configErrors) { lggr.Warnw("Transaction that would have been terminally stuck in the mempool detected on send. Marking as fatal error.", "err", sendError, "etx", tx) // Attempt is thrown away in this case; we don't need it since it never got accepted by a node - return commonclient.TerminallyStuck + return multinode.TerminallyStuck } lggr.Criticalw("Unknown error encountered when sending transaction", "err", err, "etx", tx) - return commonclient.Unknown + return multinode.Unknown } var infura = ClientErrors{ diff --git a/core/chains/evm/client/errors_test.go b/core/chains/evm/client/errors_test.go index 1f9aaa53365..2a28fe3c2c8 100644 --- a/core/chains/evm/client/errors_test.go +++ b/core/chains/evm/client/errors_test.go @@ -9,7 +9,8 @@ import ( pkgerrors "github.com/pkg/errors" "github.com/stretchr/testify/assert" - commonclient "github.com/smartcontractkit/chainlink/v2/common/client" + "github.com/smartcontractkit/chainlink-framework/multinode" + evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" ) @@ -111,6 +112,7 @@ func Test_Eth_Errors(t *testing.T) { {"gas price too low", false, "Arbitrum"}, {"client error replacement underpriced", true, "tomlConfig"}, {"", false, "tomlConfig"}, + {"failed to forward tx to sequencer, please try again. Error message: 'replacement transaction underpriced'", true, "Mantle"}, } for _, test := range tests { @@ -143,6 +145,9 @@ func Test_Eth_Errors(t *testing.T) { {"ErrorObject { code: ServerError(3), message: \\\"known transaction. transaction with hash 0xf016…ad63 is already in the system\\\", data: Some(RawValue(\\\"0x\\\")) }", true, "zkSync"}, {"client error transaction already in mempool", true, "tomlConfig"}, {"alreadyknown", true, "Gnosis"}, + {"tx already exists in cache", true, "Sei"}, + {"failed to forward tx to sequencer, please try again. Error message: 'already known'", true, "Mantle"}, + {"tx already exists in cache", true, "Sei"}, } for _, test := range tests { err = evmclient.NewSendErrorS(test.message) @@ -254,9 +259,9 @@ func Test_Eth_Errors(t *testing.T) { assert.Equal(t, err.IsServiceUnavailable(clientErrors), test.expect) } { - err = evmclient.NewSendError(commonclient.ErroringNodeError) + err = evmclient.NewSendError(multinode.ErrNodeError) assert.True(t, err.IsServiceUnavailable(clientErrors)) - err = evmclient.NewSendError(fmt.Errorf("failed to send transaction: %w", commonclient.ErroringNodeError)) + err = evmclient.NewSendError(fmt.Errorf("failed to send transaction: %w", multinode.ErrNodeError)) assert.True(t, err.IsServiceUnavailable(clientErrors)) } }) @@ -442,6 +447,11 @@ func Test_Eth_Errors_Fatal(t *testing.T) { {"client error fatal", true, "tomlConfig"}, {"[Request ID: d9711488-4c1e-4af2-bc1f-7969913d7b60] Error invoking RPC: transaction 0.0.4425573@1718213476.914320044 failed precheck with status INVALID_SIGNATURE", true, "hedera"}, {"invalid chain id for signer", true, "Treasure"}, + + {": out of gas", true, "Sei"}, + {"Tx too large. Max size is 2048576, but got 2097431", true, "Sei"}, + {": insufficient funds", true, "Sei"}, + {"insufficient fee", true, "Sei"}, } for _, test := range tests { diff --git a/core/chains/evm/client/evm_client.go b/core/chains/evm/client/evm_client.go index 18206265fd7..5dbf67014da 100644 --- a/core/chains/evm/client/evm_client.go +++ b/core/chains/evm/client/evm_client.go @@ -6,29 +6,31 @@ import ( "time" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-framework/multinode" - commonclient "github.com/smartcontractkit/chainlink/v2/common/client" evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" ) -func NewEvmClient(cfg evmconfig.NodePool, chainCfg commonclient.ChainConfig, clientErrors evmconfig.ClientErrors, lggr logger.Logger, chainID *big.Int, nodes []*toml.Node, chainType chaintype.ChainType) (Client, error) { - var primaries []commonclient.Node[*big.Int, *RPCClient] - var sendonlys []commonclient.SendOnlyNode[*big.Int, *RPCClient] +const QueryTimeout = 10 * time.Second + +func NewEvmClient(cfg evmconfig.NodePool, chainCfg multinode.ChainConfig, clientErrors evmconfig.ClientErrors, lggr logger.Logger, chainID *big.Int, nodes []*toml.Node, chainType chaintype.ChainType) (Client, error) { + var primaries []multinode.Node[*big.Int, *RPCClient] + var sendonlys []multinode.SendOnlyNode[*big.Int, *RPCClient] largePayloadRPCTimeout, defaultRPCTimeout := getRPCTimeouts(chainType) for i, node := range nodes { if node.SendOnly != nil && *node.SendOnly { rpc := NewRPCClient(cfg, lggr, nil, node.HTTPURL.URL(), *node.Name, i, chainID, - commonclient.Secondary, largePayloadRPCTimeout, defaultRPCTimeout, chainType) - sendonly := commonclient.NewSendOnlyNode(lggr, (url.URL)(*node.HTTPURL), + multinode.Secondary, largePayloadRPCTimeout, defaultRPCTimeout, chainType) + sendonly := multinode.NewSendOnlyNode(lggr, (url.URL)(*node.HTTPURL), *node.Name, chainID, rpc) sendonlys = append(sendonlys, sendonly) } else { rpc := NewRPCClient(cfg, lggr, node.WSURL.URL(), node.HTTPURL.URL(), *node.Name, i, - chainID, commonclient.Primary, largePayloadRPCTimeout, defaultRPCTimeout, chainType) - primaryNode := commonclient.NewNode(cfg, chainCfg, + chainID, multinode.Primary, largePayloadRPCTimeout, defaultRPCTimeout, chainType) + primaryNode := multinode.NewNode(cfg, chainCfg, lggr, node.WSURL.URL(), node.HTTPURL.URL(), *node.Name, i, chainID, *node.Order, rpc, "EVM") primaries = append(primaries, primaryNode) @@ -41,8 +43,8 @@ func NewEvmClient(cfg evmconfig.NodePool, chainCfg commonclient.ChainConfig, cli func getRPCTimeouts(chainType chaintype.ChainType) (largePayload, defaultTimeout time.Duration) { if chaintype.ChainHedera == chainType { - return 30 * time.Second, commonclient.QueryTimeout + return 30 * time.Second, QueryTimeout } - return commonclient.QueryTimeout, commonclient.QueryTimeout + return QueryTimeout, QueryTimeout } diff --git a/core/chains/evm/client/helpers_test.go b/core/chains/evm/client/helpers_test.go index f9751be765c..71cdd25b8d2 100644 --- a/core/chains/evm/client/helpers_test.go +++ b/core/chains/evm/client/helpers_test.go @@ -4,15 +4,17 @@ import ( "fmt" "math/big" "net/url" + "sync" "testing" "time" pkgerrors "github.com/pkg/errors" "github.com/smartcontractkit/chainlink-common/pkg/logger" + client "github.com/smartcontractkit/chainlink-solana/pkg/solana/client/multinode" - commonclient "github.com/smartcontractkit/chainlink/v2/common/client" - clientMocks "github.com/smartcontractkit/chainlink/v2/common/client/mocks" + "github.com/smartcontractkit/chainlink-framework/multinode" + "github.com/smartcontractkit/chainlink-framework/multinode/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" @@ -128,7 +130,7 @@ func (tc TestNodePoolConfig) DeathDeclarationDelay() time.Duration { func NewChainClientWithTestNode( t *testing.T, - nodeCfg commonclient.NodeConfig, + nodeCfg multinode.NodeConfig, noNewHeadsThreshold time.Duration, leaseDuration time.Duration, rpcUrl string, @@ -150,21 +152,21 @@ func NewChainClientWithTestNode( nodePoolCfg := TestNodePoolConfig{ NodeFinalizedBlockPollInterval: 1 * time.Second, } - rpc := NewRPCClient(nodePoolCfg, lggr, parsed, rpcHTTPURL, "eth-primary-rpc-0", id, chainID, commonclient.Primary, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + rpc := NewRPCClient(nodePoolCfg, lggr, parsed, rpcHTTPURL, "eth-primary-rpc-0", id, chainID, multinode.Primary, client.QueryTimeout, client.QueryTimeout, "") - n := commonclient.NewNode[*big.Int, *evmtypes.Head, *RPCClient]( - nodeCfg, clientMocks.ChainConfig{NoNewHeadsThresholdVal: noNewHeadsThreshold}, lggr, parsed, rpcHTTPURL, "eth-primary-node-0", id, chainID, 1, rpc, "EVM") - primaries := []commonclient.Node[*big.Int, *RPCClient]{n} + n := multinode.NewNode[*big.Int, *evmtypes.Head, *RPCClient]( + nodeCfg, mocks.ChainConfig{NoNewHeadsThresholdVal: noNewHeadsThreshold}, lggr, parsed, rpcHTTPURL, "eth-primary-node-0", id, chainID, 1, rpc, "EVM") + primaries := []multinode.Node[*big.Int, *RPCClient]{n} - var sendonlys []commonclient.SendOnlyNode[*big.Int, *RPCClient] + sendonlys := make([]multinode.SendOnlyNode[*big.Int, *RPCClient], len(sendonlyRPCURLs)) for i, u := range sendonlyRPCURLs { if u.Scheme != "http" && u.Scheme != "https" { return nil, pkgerrors.Errorf("sendonly ethereum rpc url scheme must be http(s): %s", u.String()) } - rpc := NewRPCClient(nodePoolCfg, lggr, nil, &sendonlyRPCURLs[i], fmt.Sprintf("eth-sendonly-rpc-%d", i), id, chainID, commonclient.Secondary, commonclient.QueryTimeout, commonclient.QueryTimeout, "") - s := commonclient.NewSendOnlyNode[*big.Int, *RPCClient]( + rpc := NewRPCClient(nodePoolCfg, lggr, nil, &sendonlyRPCURLs[i], fmt.Sprintf("eth-sendonly-rpc-%d", i), id, chainID, multinode.Secondary, client.QueryTimeout, client.QueryTimeout, "") + s := multinode.NewSendOnlyNode[*big.Int, *RPCClient]( lggr, u, fmt.Sprintf("eth-sendonly-%d", i), chainID, rpc) - sendonlys = append(sendonlys, s) + sendonlys[i] = s } clientErrors := NewTestClientErrors() @@ -198,13 +200,13 @@ func NewChainClientWithMockedRpc( lggr := logger.Test(t) cfg := TestNodePoolConfig{ - NodeSelectionMode: commonclient.NodeSelectionModeRoundRobin, + NodeSelectionMode: multinode.NodeSelectionModeRoundRobin, } parsed, _ := url.ParseRequestURI("ws://test") - n := commonclient.NewNode[*big.Int, *evmtypes.Head, *RPCClient]( - cfg, clientMocks.ChainConfig{NoNewHeadsThresholdVal: noNewHeadsThreshold}, lggr, parsed, nil, "eth-primary-node-0", 1, chainID, 1, rpc, "EVM") - primaries := []commonclient.Node[*big.Int, *RPCClient]{n} + n := multinode.NewNode[*big.Int, *evmtypes.Head, *RPCClient]( + cfg, mocks.ChainConfig{NoNewHeadsThresholdVal: noNewHeadsThreshold}, lggr, parsed, nil, "eth-primary-node-0", 1, chainID, 1, rpc, "EVM") + primaries := []multinode.Node[*big.Int, *RPCClient]{n} clientErrors := NewTestClientErrors() c := NewChainClient(lggr, selectionMode, leaseDuration, primaries, nil, chainID, &clientErrors, 0, "") t.Cleanup(c.Close) @@ -216,6 +218,7 @@ const HeadResult = `{"difficulty":"0xf3a00","extraData":"0xd88301050384676574688 type mockSubscription struct { unsubscribed bool Errors chan error + unsub sync.Once } func NewMockSubscription() *mockSubscription { @@ -225,8 +228,10 @@ func NewMockSubscription() *mockSubscription { func (mes *mockSubscription) Err() <-chan error { return mes.Errors } func (mes *mockSubscription) Unsubscribe() { - mes.unsubscribed = true - close(mes.Errors) + mes.unsub.Do(func() { + mes.unsubscribed = true + close(mes.Errors) + }) } func ParseTestNodeConfigs(nodes []NodeConfig) ([]*toml.Node, error) { diff --git a/core/chains/evm/client/mocks/client.go b/core/chains/evm/client/mocks/client.go index 25ed3698fe9..b712c297c18 100644 --- a/core/chains/evm/client/mocks/client.go +++ b/core/chains/evm/client/mocks/client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -11,8 +11,6 @@ import ( common "github.com/ethereum/go-ethereum/common" - commonclient "github.com/smartcontractkit/chainlink/v2/common/client" - context "context" ethereum "github.com/ethereum/go-ethereum" @@ -21,6 +19,8 @@ import ( mock "github.com/stretchr/testify/mock" + multinode "github.com/smartcontractkit/chainlink-framework/multinode" + rpc "github.com/ethereum/go-ethereum/rpc" types "github.com/ethereum/go-ethereum/core/types" @@ -481,7 +481,7 @@ func (_c *Client_CheckTxValidity_Call) RunAndReturn(run func(context.Context, co return _c } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *Client) Close() { _m.Called() } @@ -509,7 +509,7 @@ func (_c *Client_Close_Call) Return() *Client_Close_Call { } func (_c *Client_Close_Call) RunAndReturn(run func()) *Client_Close_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -573,7 +573,7 @@ func (_c *Client_CodeAt_Call) RunAndReturn(run func(context.Context, common.Addr return _c } -// ConfiguredChainID provides a mock function with given fields: +// ConfiguredChainID provides a mock function with no fields func (_m *Client) ConfiguredChainID() *big.Int { ret := _m.Called() @@ -1079,7 +1079,7 @@ func (_c *Client_HeaderByNumber_Call) RunAndReturn(run func(context.Context, *bi return _c } -// IsL2 provides a mock function with given fields: +// IsL2 provides a mock function with no fields func (_m *Client) IsL2() bool { ret := _m.Called() @@ -1300,7 +1300,7 @@ func (_c *Client_LatestFinalizedBlock_Call) RunAndReturn(run func(context.Contex return _c } -// NodeStates provides a mock function with given fields: +// NodeStates provides a mock function with no fields func (_m *Client) NodeStates() map[string]string { ret := _m.Called() @@ -1628,22 +1628,22 @@ func (_c *Client_SendTransaction_Call) RunAndReturn(run func(context.Context, *t } // SendTransactionReturnCode provides a mock function with given fields: ctx, tx, fromAddress -func (_m *Client) SendTransactionReturnCode(ctx context.Context, tx *types.Transaction, fromAddress common.Address) (commonclient.SendTxReturnCode, error) { +func (_m *Client) SendTransactionReturnCode(ctx context.Context, tx *types.Transaction, fromAddress common.Address) (multinode.SendTxReturnCode, error) { ret := _m.Called(ctx, tx, fromAddress) if len(ret) == 0 { panic("no return value specified for SendTransactionReturnCode") } - var r0 commonclient.SendTxReturnCode + var r0 multinode.SendTxReturnCode var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.Transaction, common.Address) (commonclient.SendTxReturnCode, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *types.Transaction, common.Address) (multinode.SendTxReturnCode, error)); ok { return rf(ctx, tx, fromAddress) } - if rf, ok := ret.Get(0).(func(context.Context, *types.Transaction, common.Address) commonclient.SendTxReturnCode); ok { + if rf, ok := ret.Get(0).(func(context.Context, *types.Transaction, common.Address) multinode.SendTxReturnCode); ok { r0 = rf(ctx, tx, fromAddress) } else { - r0 = ret.Get(0).(commonclient.SendTxReturnCode) + r0 = ret.Get(0).(multinode.SendTxReturnCode) } if rf, ok := ret.Get(1).(func(context.Context, *types.Transaction, common.Address) error); ok { @@ -1675,12 +1675,12 @@ func (_c *Client_SendTransactionReturnCode_Call) Run(run func(ctx context.Contex return _c } -func (_c *Client_SendTransactionReturnCode_Call) Return(_a0 commonclient.SendTxReturnCode, _a1 error) *Client_SendTransactionReturnCode_Call { +func (_c *Client_SendTransactionReturnCode_Call) Return(_a0 multinode.SendTxReturnCode, _a1 error) *Client_SendTransactionReturnCode_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *Client_SendTransactionReturnCode_Call) RunAndReturn(run func(context.Context, *types.Transaction, common.Address) (commonclient.SendTxReturnCode, error)) *Client_SendTransactionReturnCode_Call { +func (_c *Client_SendTransactionReturnCode_Call) RunAndReturn(run func(context.Context, *types.Transaction, common.Address) (multinode.SendTxReturnCode, error)) *Client_SendTransactionReturnCode_Call { _c.Call.Return(run) return _c } diff --git a/core/chains/evm/client/null_client.go b/core/chains/evm/client/null_client.go index b1dedd3f74a..6b40ba93eb7 100644 --- a/core/chains/evm/client/null_client.go +++ b/core/chains/evm/client/null_client.go @@ -11,8 +11,8 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/assets" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-framework/multinode" - commonclient "github.com/smartcontractkit/chainlink/v2/common/client" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) @@ -122,9 +122,9 @@ func (nc *NullClient) HeaderByHash(ctx context.Context, h common.Hash) (*types.H return nil, nil } -func (nc *NullClient) SendTransactionReturnCode(ctx context.Context, tx *types.Transaction, sender common.Address) (commonclient.SendTxReturnCode, error) { +func (nc *NullClient) SendTransactionReturnCode(ctx context.Context, tx *types.Transaction, sender common.Address) (multinode.SendTxReturnCode, error) { nc.lggr.Debug("SendTransactionReturnCode") - return commonclient.Successful, nil + return multinode.Successful, nil } func (nc *NullClient) SendTransaction(ctx context.Context, tx *types.Transaction) error { diff --git a/core/chains/evm/client/rpc_client.go b/core/chains/evm/client/rpc_client.go index 97046b4eff2..f560a26dda6 100644 --- a/core/chains/evm/client/rpc_client.go +++ b/core/chains/evm/client/rpc_client.go @@ -5,6 +5,7 @@ import ( "encoding/json" "errors" "fmt" + "math" "math/big" "net/url" "strconv" @@ -25,9 +26,8 @@ import ( commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-framework/multinode" - commonclient "github.com/smartcontractkit/chainlink/v2/common/client" - commontypes "github.com/smartcontractkit/chainlink/v2/common/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" @@ -92,7 +92,7 @@ type RPCClient struct { name string id int chainID *big.Int - tier commonclient.NodeTier + tier multinode.NodeTier largePayloadRPCTimeout time.Duration finalizedBlockPollInterval time.Duration newHeadsPollInterval time.Duration @@ -117,13 +117,13 @@ type RPCClient struct { chainInfoLock sync.RWMutex // intercepted values seen by callers of the RPCClient excluding health check calls. Need to ensure MultiNode provides repeatable read guarantee - highestUserObservations commonclient.ChainInfo + highestUserObservations multinode.ChainInfo // most recent chain info observed during current lifecycle (reseted on DisconnectAll) - latestChainInfo commonclient.ChainInfo + latestChainInfo multinode.ChainInfo } -var _ commonclient.RPCClient[*big.Int, *evmtypes.Head] = (*RPCClient)(nil) -var _ commonclient.SendTxRPCClient[*types.Transaction, *SendTxResult] = (*RPCClient)(nil) +var _ multinode.RPCClient[*big.Int, *evmtypes.Head] = (*RPCClient)(nil) +var _ multinode.SendTxRPCClient[*types.Transaction, *SendTxResult] = (*RPCClient)(nil) func NewRPCClient( cfg config.NodePool, @@ -133,7 +133,7 @@ func NewRPCClient( name string, id int, chainID *big.Int, - tier commonclient.NodeTier, + tier multinode.NodeTier, largePayloadRPCTimeout time.Duration, rpcTimeout time.Duration, chainType chaintype.ChainType, @@ -180,11 +180,11 @@ func (r *RPCClient) Ping(ctx context.Context) error { return err } -func (r *RPCClient) UnsubscribeAllExcept(subs ...commontypes.Subscription) { +func (r *RPCClient) UnsubscribeAllExcept(subs ...multinode.Subscription) { r.subsSliceMu.Lock() defer r.subsSliceMu.Unlock() - keepSubs := map[commontypes.Subscription]struct{}{} + keepSubs := map[multinode.Subscription]struct{}{} for _, sub := range subs { keepSubs[sub] = struct{}{} } @@ -264,7 +264,7 @@ func (r *RPCClient) Close() { r.cancelInflightRequests() r.UnsubscribeAllExcept() r.chainInfoLock.Lock() - r.latestChainInfo = commonclient.ChainInfo{} + r.latestChainInfo = multinode.ChainInfo{} r.chainInfoLock.Unlock() } @@ -376,6 +376,10 @@ func (r *RPCClient) BatchCallContext(rootCtx context.Context, b []rpc.BatchElem) var requestedFinalizedBlock bool if r.chainType == chaintype.ChainAstar { for _, el := range b { + if el.Method == "eth_getLogs" { + r.rpcLog.Critical("evmclient.BatchCallContext: eth_getLogs is not supported") + return errors.New("evmclient.BatchCallContext: eth_getLogs is not supported") + } if !isRequestingFinalizedBlock(el) { continue } @@ -447,7 +451,7 @@ func isRequestingFinalizedBlock(el rpc.BatchElem) bool { } } -func (r *RPCClient) SubscribeToHeads(ctx context.Context) (ch <-chan *evmtypes.Head, sub commontypes.Subscription, err error) { +func (r *RPCClient) SubscribeToHeads(ctx context.Context) (ch <-chan *evmtypes.Head, sub multinode.Subscription, err error) { ctx, cancel, chStopInFlight, ws, _ := r.acquireQueryCtx(ctx, r.rpcTimeout) defer cancel() args := []interface{}{rpcSubscriptionMethodNewHeads} @@ -458,10 +462,10 @@ func (r *RPCClient) SubscribeToHeads(ctx context.Context) (ch <-chan *evmtypes.H if r.newHeadsPollInterval > 0 { interval := r.newHeadsPollInterval timeout := interval - isHealthCheckRequest := commonclient.CtxIsHeathCheckRequest(ctx) - poller, channel := commonclient.NewPoller[*evmtypes.Head](interval, func(ctx context.Context) (*evmtypes.Head, error) { + isHealthCheckRequest := multinode.CtxIsHeathCheckRequest(ctx) + poller, channel := multinode.NewPoller[*evmtypes.Head](interval, func(ctx context.Context) (*evmtypes.Head, error) { if isHealthCheckRequest { - ctx = commonclient.CtxAddHealthCheckFlag(ctx) + ctx = multinode.CtxAddHealthCheckFlag(ctx) } return r.latestBlock(ctx) }, timeout, r.rpcLog) @@ -490,10 +494,10 @@ func (r *RPCClient) SubscribeToHeads(ctx context.Context) (ch <-chan *evmtypes.H }() channel := make(chan *evmtypes.Head) - forwarder := newSubForwarder(channel, func(head *evmtypes.Head) *evmtypes.Head { + forwarder := newSubForwarder(channel, func(head *evmtypes.Head) (*evmtypes.Head, error) { head.EVMChainID = ubig.New(r.chainID) r.onNewHead(ctx, chStopInFlight, head) - return head + return head, nil }, r.wrapRPCClientError) err = forwarder.start(ws.rpc.EthSubscribe(ctx, forwarder.srcCh, args...)) @@ -509,7 +513,7 @@ func (r *RPCClient) SubscribeToHeads(ctx context.Context) (ch <-chan *evmtypes.H return channel, forwarder, err } -func (r *RPCClient) SubscribeToFinalizedHeads(ctx context.Context) (<-chan *evmtypes.Head, commontypes.Subscription, error) { +func (r *RPCClient) SubscribeToFinalizedHeads(ctx context.Context) (<-chan *evmtypes.Head, multinode.Subscription, error) { ctx, cancel, chStopInFlight, _, _ := r.acquireQueryCtx(ctx, r.rpcTimeout) defer cancel() @@ -518,10 +522,10 @@ func (r *RPCClient) SubscribeToFinalizedHeads(ctx context.Context) (<-chan *evmt return nil, nil, errors.New("FinalizedBlockPollInterval is 0") } timeout := interval - isHealthCheckRequest := commonclient.CtxIsHeathCheckRequest(ctx) - poller, channel := commonclient.NewPoller[*evmtypes.Head](interval, func(ctx context.Context) (*evmtypes.Head, error) { + isHealthCheckRequest := multinode.CtxIsHeathCheckRequest(ctx) + poller, channel := multinode.NewPoller[*evmtypes.Head](interval, func(ctx context.Context) (*evmtypes.Head, error) { if isHealthCheckRequest { - ctx = commonclient.CtxAddHealthCheckFlag(ctx) + ctx = multinode.CtxAddHealthCheckFlag(ctx) } return r.LatestFinalizedBlock(ctx) }, timeout, r.rpcLog) @@ -806,10 +810,10 @@ func (r *RPCClient) BlockByNumberGeth(ctx context.Context, number *big.Int) (blo type SendTxResult struct { err error - code commonclient.SendTxReturnCode + code multinode.SendTxReturnCode } -var _ commonclient.SendTxResult = (*SendTxResult)(nil) +var _ multinode.SendTxResult = (*SendTxResult)(nil) func NewSendTxResult(err error) *SendTxResult { result := &SendTxResult{ @@ -822,7 +826,7 @@ func (r *SendTxResult) Error() error { return r.err } -func (r *SendTxResult) Code() commonclient.SendTxReturnCode { +func (r *SendTxResult) Code() multinode.SendTxReturnCode { return r.code } @@ -1199,8 +1203,11 @@ func (r *RPCClient) FilterLogs(ctx context.Context, q ethereum.FilterQuery) (l [ l, err = ws.geth.FilterLogs(ctx, q) err = r.wrapWS(err) } - duration := time.Since(start) + if err == nil { + err = r.makeLogsValid(l) + } + duration := time.Since(start) r.logResult(lggr, err, duration, r.getRPCDomain(), "FilterLogs", "log", l, ) @@ -1228,7 +1235,7 @@ func (r *RPCClient) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQu r.logResult(lggr, err, duration, r.getRPCDomain(), "SubscribeFilterLogs") err = r.wrapWS(err) }() - sub := newSubForwarder(ch, nil, r.wrapRPCClientError) + sub := newSubForwarder(ch, r.makeLogValid, r.wrapRPCClientError) err = sub.start(ws.geth.SubscribeFilterLogs(ctx, q, sub.srcCh)) if err != nil { return @@ -1410,9 +1417,9 @@ func (r *RPCClient) onNewHead(ctx context.Context, requestCh <-chan struct{}, he r.chainInfoLock.Lock() defer r.chainInfoLock.Unlock() - if !commonclient.CtxIsHeathCheckRequest(ctx) { + if !multinode.CtxIsHeathCheckRequest(ctx) { r.highestUserObservations.BlockNumber = max(r.highestUserObservations.BlockNumber, head.Number) - r.highestUserObservations.TotalDifficulty = commonclient.MaxTotalDifficulty(r.highestUserObservations.TotalDifficulty, head.TotalDifficulty) + r.highestUserObservations.TotalDifficulty = multinode.MaxTotalDifficulty(r.highestUserObservations.TotalDifficulty, head.TotalDifficulty) } select { case <-requestCh: // no need to update latestChainInfo, as RPCClient already started new life cycle @@ -1429,7 +1436,7 @@ func (r *RPCClient) onNewFinalizedHead(ctx context.Context, requestCh <-chan str } r.chainInfoLock.Lock() defer r.chainInfoLock.Unlock() - if !commonclient.CtxIsHeathCheckRequest(ctx) { + if !multinode.CtxIsHeathCheckRequest(ctx) { r.highestUserObservations.FinalizedBlockNumber = max(r.highestUserObservations.FinalizedBlockNumber, head.Number) } select { @@ -1440,7 +1447,7 @@ func (r *RPCClient) onNewFinalizedHead(ctx context.Context, requestCh <-chan str } } -func (r *RPCClient) GetInterceptedChainInfo() (latest, highestUserObservations commonclient.ChainInfo) { +func (r *RPCClient) GetInterceptedChainInfo() (latest, highestUserObservations multinode.ChainInfo) { r.chainInfoLock.Lock() defer r.chainInfoLock.Unlock() return r.latestChainInfo, r.highestUserObservations @@ -1452,3 +1459,38 @@ func ToBlockNumArg(number *big.Int) string { } return hexutil.EncodeBig(number) } + +func (r *RPCClient) makeLogsValid(logs []types.Log) error { + if r.chainType != chaintype.ChainSei { + return nil + } + + for i := range logs { + var err error + logs[i], err = r.makeLogValid(logs[i]) + if err != nil { + return err + } + } + + return nil +} + +func (r *RPCClient) makeLogValid(log types.Log) (types.Log, error) { + if r.chainType != chaintype.ChainSei { + return log, nil + } + + if log.TxIndex > math.MaxUint32 { + return types.Log{}, fmt.Errorf("TxIndex of tx %s exceeds max supported value of %d", log.TxHash, math.MaxUint32) + } + + if log.Index > math.MaxUint32 { + return types.Log{}, fmt.Errorf("log's index %d of tx %s exceeds max supported value of %d", log.Index, log.TxHash, math.MaxUint32) + } + + // it's safe as we have a build guard to guarantee 64-bit system + newIndex := uint64(log.TxIndex<<32) | uint64(log.Index) + log.Index = uint(newIndex) + return log, nil +} diff --git a/core/chains/evm/client/rpc_client_internal_test.go b/core/chains/evm/client/rpc_client_internal_test.go new file mode 100644 index 00000000000..92ea189c151 --- /dev/null +++ b/core/chains/evm/client/rpc_client_internal_test.go @@ -0,0 +1,94 @@ +package client + +import ( + "errors" + "math" + "testing" + + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-framework/multinode" + client "github.com/smartcontractkit/chainlink-solana/pkg/solana/client/multinode" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestRPCClient_MakeLogsValid(t *testing.T) { + testCases := []struct { + Name string + TxIndex uint + LogIndex uint + ExpectedLogIndex uint + ExpectedError error + }{ + { + Name: "TxIndex = 0 LogIndex = 0", + TxIndex: 0, + LogIndex: 0, + ExpectedLogIndex: 0, + ExpectedError: nil, + }, + { + Name: "TxIndex = 0 LogIndex = 1", + TxIndex: 0, + LogIndex: 1, + ExpectedLogIndex: 1, + ExpectedError: nil, + }, + { + Name: "TxIndex = 0 LogIndex = MaxUint32", + TxIndex: 0, + LogIndex: math.MaxUint32, + ExpectedLogIndex: math.MaxUint32, + ExpectedError: nil, + }, + { + Name: "LogIndex = MaxUint32 + 1 => returns an error", + TxIndex: 0, + LogIndex: math.MaxUint32 + 1, + ExpectedLogIndex: 0, + ExpectedError: errors.New("log's index 4294967296 of tx 0x0000000000000000000000000000000000000000000000000000000000000000 exceeds max supported value of 4294967295"), + }, + { + Name: "TxIndex = 1 LogIndex = 0", + TxIndex: 1, + LogIndex: 0, + ExpectedLogIndex: math.MaxUint32 + 1, + ExpectedError: nil, + }, + { + Name: "TxIndex = MaxUint32 LogIndex = MaxUint32", + TxIndex: math.MaxUint32, + LogIndex: math.MaxUint32, + ExpectedLogIndex: math.MaxUint64, + ExpectedError: nil, + }, + { + Name: "TxIndex = MaxUint32 + 1 => returns an error", + TxIndex: math.MaxUint32 + 1, + LogIndex: 0, + ExpectedLogIndex: 0, + ExpectedError: errors.New("TxIndex of tx 0x0000000000000000000000000000000000000000000000000000000000000000 exceeds max supported value of 4294967295"), + }, + } + for _, tc := range testCases { + t.Run(tc.Name, func(t *testing.T) { + rpc := NewRPCClient(TestNodePoolConfig{}, logger.TestLogger(t), nil, nil, "eth-primary-rpc-0", 0, nil, multinode.Primary, client.QueryTimeout, client.QueryTimeout, "") + log, err := rpc.makeLogValid(ethtypes.Log{TxIndex: tc.TxIndex, Index: tc.LogIndex}) + // non sei should return as is + require.NoError(t, err) + require.Equal(t, tc.TxIndex, log.TxIndex) + require.Equal(t, tc.LogIndex, log.Index) + seiRPC := NewRPCClient(TestNodePoolConfig{}, logger.TestLogger(t), nil, nil, "eth-primary-rpc-0", 0, nil, multinode.Primary, client.QueryTimeout, client.QueryTimeout, chaintype.ChainSei) + log, err = seiRPC.makeLogValid(ethtypes.Log{TxIndex: tc.TxIndex, Index: tc.LogIndex}) + if tc.ExpectedError != nil { + require.EqualError(t, err, tc.ExpectedError.Error()) + return + } + + require.Equal(t, tc.ExpectedLogIndex, log.Index) + require.Equal(t, tc.TxIndex, log.TxIndex) + }) + } +} diff --git a/core/chains/evm/client/rpc_client_test.go b/core/chains/evm/client/rpc_client_test.go index 109a49d6e2f..9b68e744e7d 100644 --- a/core/chains/evm/client/rpc_client_test.go +++ b/core/chains/evm/client/rpc_client_test.go @@ -5,13 +5,16 @@ import ( "encoding/json" "errors" "fmt" + "math" "math/big" "net/url" "sync" + "sync/atomic" "testing" "time" "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/rpc" "github.com/stretchr/testify/assert" @@ -22,22 +25,23 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - commonclient "github.com/smartcontractkit/chainlink/v2/common/client" - commontypes "github.com/smartcontractkit/chainlink/v2/common/types" + "github.com/smartcontractkit/chainlink-framework/multinode" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/testutils" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) -func makeNewHeadWSMessage(head *evmtypes.Head) string { - asJSON, err := json.Marshal(head) +func makeNewWSMessage[T any](v T) string { + asJSON, err := json.Marshal(v) if err != nil { panic(fmt.Errorf("failed to marshal head: %w", err)) } return fmt.Sprintf(`{"jsonrpc":"2.0","method":"eth_subscription","params":{"subscription":"0x00","result":%s}}`, string(asJSON)) } +var makeNewHeadWSMessage = makeNewWSMessage[*evmtypes.Head] + func TestRPCClient_SubscribeToHeads(t *testing.T) { t.Parallel() ctx, cancel := context.WithTimeout(tests.Context(t), tests.WaitTimeout(t)) @@ -69,7 +73,7 @@ func TestRPCClient_SubscribeToHeads(t *testing.T) { return } - checkClosedRPCClientShouldRemoveExistingSub := func(t tests.TestingT, ctx context.Context, sub commontypes.Subscription, rpcClient *client.RPCClient) { + checkClosedRPCClientShouldRemoveExistingSub := func(t tests.TestingT, ctx context.Context, sub multinode.Subscription, rpcClient *client.RPCClient) { errCh := sub.Err() rpcClient.UnsubscribeAllExcept() @@ -87,7 +91,7 @@ func TestRPCClient_SubscribeToHeads(t *testing.T) { t.Run("WS and HTTP URL cannot be both empty", func(t *testing.T) { // ws is optional when LogBroadcaster is disabled, however SubscribeFilterLogs will return error if ws is missing observedLggr := logger.Test(t) - rpcClient := client.NewRPCClient(nodePoolCfgHeadPolling, observedLggr, nil, nil, "rpc", 1, chainId, commonclient.Primary, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + rpcClient := client.NewRPCClient(nodePoolCfgHeadPolling, observedLggr, nil, nil, "rpc", 1, chainId, multinode.Primary, client.QueryTimeout, client.QueryTimeout, "") require.Equal(t, errors.New("cannot dial rpc client when both ws and http info are missing"), rpcClient.Dial(ctx)) }) @@ -95,7 +99,7 @@ func TestRPCClient_SubscribeToHeads(t *testing.T) { server := testutils.NewWSServer(t, chainId, serverCallBack) wsURL := server.WSURL() - rpc := client.NewRPCClient(nodePoolCfgWSSub, lggr, wsURL, nil, "rpc", 1, chainId, commonclient.Primary, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + rpc := client.NewRPCClient(nodePoolCfgWSSub, lggr, wsURL, nil, "rpc", 1, chainId, multinode.Primary, client.QueryTimeout, client.QueryTimeout, "") defer rpc.Close() require.NoError(t, rpc.Dial(ctx)) // set to default values @@ -122,7 +126,7 @@ func TestRPCClient_SubscribeToHeads(t *testing.T) { assert.Equal(t, int64(0), latest.FinalizedBlockNumber) assert.Equal(t, big.NewInt(500), latest.TotalDifficulty) - assertHighestUserObservations := func(highestUserObservations commonclient.ChainInfo) { + assertHighestUserObservations := func(highestUserObservations multinode.ChainInfo) { assert.Equal(t, int64(256), highestUserObservations.BlockNumber) assert.Equal(t, int64(0), highestUserObservations.FinalizedBlockNumber) assert.Equal(t, big.NewInt(1000), highestUserObservations.TotalDifficulty) @@ -144,11 +148,11 @@ func TestRPCClient_SubscribeToHeads(t *testing.T) { server := testutils.NewWSServer(t, chainId, serverCallBack) wsURL := server.WSURL() - rpc := client.NewRPCClient(nodePoolCfgWSSub, lggr, wsURL, nil, "rpc", 1, chainId, commonclient.Primary, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + rpc := client.NewRPCClient(nodePoolCfgWSSub, lggr, wsURL, nil, "rpc", 1, chainId, multinode.Primary, client.QueryTimeout, client.QueryTimeout, "") defer rpc.Close() require.NoError(t, rpc.Dial(ctx)) - ch, sub, err := rpc.SubscribeToHeads(commonclient.CtxAddHealthCheckFlag(tests.Context(t))) + ch, sub, err := rpc.SubscribeToHeads(multinode.CtxAddHealthCheckFlag(tests.Context(t))) require.NoError(t, err) defer sub.Unsubscribe() go server.MustWriteBinaryMessageSync(t, makeNewHeadWSMessage(&evmtypes.Head{Number: 256, TotalDifficulty: big.NewInt(1000)})) @@ -187,7 +191,7 @@ func TestRPCClient_SubscribeToHeads(t *testing.T) { } server := createRPCServer() - rpc := client.NewRPCClient(nodePoolCfgHeadPolling, lggr, server.URL, nil, "rpc", 1, chainId, commonclient.Primary, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + rpc := client.NewRPCClient(nodePoolCfgHeadPolling, lggr, server.URL, nil, "rpc", 1, chainId, multinode.Primary, client.QueryTimeout, client.QueryTimeout, "") defer rpc.Close() require.NoError(t, rpc.Dial(ctx)) latest, highestUserObservations := rpc.GetInterceptedChainInfo() @@ -210,7 +214,7 @@ func TestRPCClient_SubscribeToHeads(t *testing.T) { // subscription with health check flag won't affect user observations sub.Unsubscribe() // stop prev subscription server.Head = &evmtypes.Head{Number: 256} - headCh, sub, err = rpc.SubscribeToHeads(commonclient.CtxAddHealthCheckFlag(tests.Context(t))) + headCh, sub, err = rpc.SubscribeToHeads(multinode.CtxAddHealthCheckFlag(tests.Context(t))) require.NoError(t, err) defer sub.Unsubscribe() @@ -226,7 +230,7 @@ func TestRPCClient_SubscribeToHeads(t *testing.T) { server := testutils.NewWSServer(t, chainId, serverCallBack) wsURL := server.WSURL() - rpc := client.NewRPCClient(nodePoolCfgWSSub, lggr, wsURL, nil, "rpc", 1, chainId, commonclient.Primary, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + rpc := client.NewRPCClient(nodePoolCfgWSSub, lggr, wsURL, nil, "rpc", 1, chainId, multinode.Primary, client.QueryTimeout, client.QueryTimeout, "") defer rpc.Close() require.NoError(t, rpc.Dial(ctx)) var wg sync.WaitGroup @@ -249,7 +253,7 @@ func TestRPCClient_SubscribeToHeads(t *testing.T) { t.Run("Block's chain ID matched configured", func(t *testing.T) { server := testutils.NewWSServer(t, chainId, serverCallBack) wsURL := server.WSURL() - rpc := client.NewRPCClient(nodePoolCfgWSSub, lggr, wsURL, nil, "rpc", 1, chainId, commonclient.Primary, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + rpc := client.NewRPCClient(nodePoolCfgWSSub, lggr, wsURL, nil, "rpc", 1, chainId, multinode.Primary, client.QueryTimeout, client.QueryTimeout, "") defer rpc.Close() require.NoError(t, rpc.Dial(ctx)) ch, sub, err := rpc.SubscribeToHeads(tests.Context(t)) @@ -265,7 +269,7 @@ func TestRPCClient_SubscribeToHeads(t *testing.T) { }) wsURL := server.WSURL() observedLggr, observed := logger.TestObserved(t, zap.DebugLevel) - rpc := client.NewRPCClient(nodePoolCfgWSSub, observedLggr, wsURL, nil, "rpc", 1, chainId, commonclient.Primary, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + rpc := client.NewRPCClient(nodePoolCfgWSSub, observedLggr, wsURL, nil, "rpc", 1, chainId, multinode.Primary, client.QueryTimeout, client.QueryTimeout, "") require.NoError(t, rpc.Dial(ctx)) server.Close() _, _, err := rpc.SubscribeToHeads(ctx) @@ -275,7 +279,7 @@ func TestRPCClient_SubscribeToHeads(t *testing.T) { t.Run("Closed rpc client should remove existing SubscribeToHeads subscription with WS", func(t *testing.T) { server := testutils.NewWSServer(t, chainId, serverCallBack) wsURL := server.WSURL() - rpc := client.NewRPCClient(nodePoolCfgWSSub, lggr, wsURL, nil, "rpc", 1, chainId, commonclient.Primary, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + rpc := client.NewRPCClient(nodePoolCfgWSSub, lggr, wsURL, nil, "rpc", 1, chainId, multinode.Primary, client.QueryTimeout, client.QueryTimeout, "") defer rpc.Close() require.NoError(t, rpc.Dial(ctx)) @@ -287,7 +291,7 @@ func TestRPCClient_SubscribeToHeads(t *testing.T) { server := testutils.NewWSServer(t, chainId, serverCallBack) wsURL := server.WSURL() - rpc := client.NewRPCClient(nodePoolCfgHeadPolling, lggr, wsURL, nil, "rpc", 1, chainId, commonclient.Primary, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + rpc := client.NewRPCClient(nodePoolCfgHeadPolling, lggr, wsURL, nil, "rpc", 1, chainId, multinode.Primary, client.QueryTimeout, client.QueryTimeout, "") defer rpc.Close() require.NoError(t, rpc.Dial(ctx)) @@ -299,7 +303,7 @@ func TestRPCClient_SubscribeToHeads(t *testing.T) { server := testutils.NewWSServer(t, chainId, serverCallBack) wsURL := server.WSURL() - rpc := client.NewRPCClient(nodePoolCfgHeadPolling, lggr, wsURL, nil, "rpc", 1, chainId, commonclient.Primary, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + rpc := client.NewRPCClient(nodePoolCfgHeadPolling, lggr, wsURL, nil, "rpc", 1, chainId, multinode.Primary, client.QueryTimeout, client.QueryTimeout, "") defer rpc.Close() require.NoError(t, rpc.Dial(ctx)) @@ -310,7 +314,7 @@ func TestRPCClient_SubscribeToHeads(t *testing.T) { t.Run("Subscription error is properly wrapper", func(t *testing.T) { server := testutils.NewWSServer(t, chainId, serverCallBack) wsURL := server.WSURL() - rpc := client.NewRPCClient(nodePoolCfgWSSub, lggr, wsURL, nil, "rpc", 1, chainId, commonclient.Primary, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + rpc := client.NewRPCClient(nodePoolCfgWSSub, lggr, wsURL, nil, "rpc", 1, chainId, multinode.Primary, client.QueryTimeout, client.QueryTimeout, "") defer rpc.Close() require.NoError(t, rpc.Dial(ctx)) _, sub, err := rpc.SubscribeToHeads(ctx) @@ -340,7 +344,7 @@ func TestRPCClient_SubscribeFilterLogs(t *testing.T) { t.Run("Failed SubscribeFilterLogs when WSURL is empty", func(t *testing.T) { // ws is optional when LogBroadcaster is disabled, however SubscribeFilterLogs will return error if ws is missing observedLggr := logger.Test(t) - rpcClient := client.NewRPCClient(nodePoolCfg, observedLggr, nil, &url.URL{}, "rpc", 1, chainId, commonclient.Primary, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + rpcClient := client.NewRPCClient(nodePoolCfg, observedLggr, nil, &url.URL{}, "rpc", 1, chainId, multinode.Primary, client.QueryTimeout, client.QueryTimeout, "") require.Nil(t, rpcClient.Dial(ctx)) _, err := rpcClient.SubscribeFilterLogs(ctx, ethereum.FilterQuery{}, make(chan types.Log)) @@ -352,7 +356,7 @@ func TestRPCClient_SubscribeFilterLogs(t *testing.T) { }) wsURL := server.WSURL() observedLggr, observed := logger.TestObserved(t, zap.DebugLevel) - rpc := client.NewRPCClient(nodePoolCfg, observedLggr, wsURL, nil, "rpc", 1, chainId, commonclient.Primary, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + rpc := client.NewRPCClient(nodePoolCfg, observedLggr, wsURL, nil, "rpc", 1, chainId, multinode.Primary, client.QueryTimeout, client.QueryTimeout, "") require.NoError(t, rpc.Dial(ctx)) server.Close() _, err := rpc.SubscribeFilterLogs(ctx, ethereum.FilterQuery{}, make(chan types.Log)) @@ -369,7 +373,7 @@ func TestRPCClient_SubscribeFilterLogs(t *testing.T) { return resp }) wsURL := server.WSURL() - rpc := client.NewRPCClient(nodePoolCfg, lggr, wsURL, nil, "rpc", 1, chainId, commonclient.Primary, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + rpc := client.NewRPCClient(nodePoolCfg, lggr, wsURL, nil, "rpc", 1, chainId, multinode.Primary, client.QueryTimeout, client.QueryTimeout, "") defer rpc.Close() require.NoError(t, rpc.Dial(ctx)) sub, err := rpc.SubscribeFilterLogs(ctx, ethereum.FilterQuery{}, make(chan types.Log)) @@ -384,6 +388,135 @@ func TestRPCClient_SubscribeFilterLogs(t *testing.T) { t.Errorf("Expected subscription to return an error, but test timeout instead") } }) + t.Run("Log's index is properly set for Sei chain type", func(t *testing.T) { + server := testutils.NewWSServer(t, chainId, func(method string, params gjson.Result) (resp testutils.JSONRPCResponse) { + if method == "eth_unsubscribe" { + resp.Result = "true" + return + } else if method == "eth_subscribe" { + if assert.True(t, params.IsArray()) && assert.Equal(t, "logs", params.Array()[0].String()) { + resp.Result = `"0x00"` + } + return + } + return + }) + wsURL := server.WSURL() + rpc := client.NewRPCClient(nodePoolCfg, lggr, wsURL, nil, "rpc", 1, chainId, multinode.Primary, client.QueryTimeout, client.QueryTimeout, chaintype.ChainSei) + defer rpc.Close() + require.NoError(t, rpc.Dial(ctx)) + ch := make(chan types.Log) + sub, err := rpc.SubscribeFilterLogs(ctx, ethereum.FilterQuery{}, ch) + require.NoError(t, err) + testCases := []struct { + TxIndex uint + Index uint + ExpectedIndex uint + }{ + { + TxIndex: 0, + Index: 0, + ExpectedIndex: 0, + }, + { + TxIndex: 0, + Index: 1, + ExpectedIndex: 1, + }, + { + TxIndex: 1, + Index: 0, + ExpectedIndex: math.MaxUint32 + 1, + }, + } + go func() { + for _, testCase := range testCases { + server.MustWriteBinaryMessageSync(t, makeNewWSMessage(types.Log{TxIndex: testCase.TxIndex, Index: testCase.Index, Topics: []common.Hash{{}}})) + } + }() + defer sub.Unsubscribe() + for _, testCase := range testCases { + select { + case <-tests.Context(t).Done(): + require.Fail(t, "context timed out") + case err := <-sub.Err(): + require.NoError(t, err) + require.Fail(t, "Did not expect error channel to be closed or return error before all testcases were consumed") + case log := <-ch: + require.Equal(t, testCase.ExpectedIndex, log.Index, "Unexpected log index %d for test case %v", log.Index, testCase) + } + } + }) +} + +func TestRPCClientFilterLogs(t *testing.T) { + t.Parallel() + + nodePoolCfg := client.TestNodePoolConfig{ + NodeNewHeadsPollInterval: 1 * time.Second, + NodeFinalizedBlockPollInterval: 1 * time.Second, + } + + chainID := big.NewInt(123456) + lggr := logger.Test(t) + ctx, cancel := context.WithTimeout(tests.Context(t), tests.WaitTimeout(t)) + defer cancel() + t.Run("Log's index is properly set for Sei chain type", func(t *testing.T) { + testCases := []struct { + TxIndex uint + Index uint + ExpectedIndex uint + }{ + { + TxIndex: 0, + Index: 0, + ExpectedIndex: 0, + }, + { + TxIndex: 0, + Index: 1, + ExpectedIndex: 1, + }, + { + TxIndex: 1, + Index: 0, + ExpectedIndex: math.MaxUint32 + 1, + }, + } + server := testutils.NewWSServer(t, chainID, func(method string, params gjson.Result) (resp testutils.JSONRPCResponse) { + if method != "eth_getLogs" { + return + } + var logs []types.Log + for _, testCase := range testCases { + logs = append(logs, types.Log{TxIndex: testCase.TxIndex, Index: testCase.Index, Topics: []common.Hash{{}}}) + } + raw, err := json.Marshal(logs) + require.NoError(t, err) + resp.Result = string(raw) + return + }) + wsURL := server.WSURL() + seiRPC := client.NewRPCClient(nodePoolCfg, lggr, wsURL, nil, "rpc", 1, chainID, multinode.Primary, client.QueryTimeout, client.QueryTimeout, chaintype.ChainSei) + defer seiRPC.Close() + require.NoError(t, seiRPC.Dial(ctx)) + logs, err := seiRPC.FilterLogs(ctx, ethereum.FilterQuery{}) + require.NoError(t, err) + for i, testCase := range testCases { + require.Equal(t, testCase.ExpectedIndex, logs[i].Index, "Unexpected log index %d for test case %v", logs[i].Index, testCase) + } + + // non sei should return index as is + rpc := client.NewRPCClient(nodePoolCfg, lggr, wsURL, nil, "rpc", 1, chainID, multinode.Primary, client.QueryTimeout, client.QueryTimeout, "") + defer rpc.Close() + require.NoError(t, rpc.Dial(ctx)) + logs, err = rpc.FilterLogs(ctx, ethereum.FilterQuery{}) + require.NoError(t, err) + for i, testCase := range testCases { + require.Equal(t, testCase.Index, logs[i].Index, "Expected non sei log to be returned as is") + require.Equal(t, testCase.TxIndex, logs[i].TxIndex, "Expected non sei log to be returned as is") + } + }) } func TestRPCClient_LatestFinalizedBlock(t *testing.T) { @@ -400,7 +533,7 @@ func TestRPCClient_LatestFinalizedBlock(t *testing.T) { lggr := logger.Test(t) type rpcServer struct { - Head *evmtypes.Head + Head atomic.Pointer[evmtypes.Head] URL *url.URL } createRPCServer := func() *rpcServer { @@ -408,7 +541,7 @@ func TestRPCClient_LatestFinalizedBlock(t *testing.T) { server.URL = testutils.NewWSServer(t, chainId, func(method string, params gjson.Result) (resp testutils.JSONRPCResponse) { assert.Equal(t, "eth_getBlockByNumber", method) if assert.True(t, params.IsArray()) && assert.Equal(t, "finalized", params.Array()[0].String()) { - head := server.Head + head := server.Head.Load() jsonHead, err := json.Marshal(head) if err != nil { panic(fmt.Errorf("failed to marshal head: %w", err)) @@ -423,10 +556,10 @@ func TestRPCClient_LatestFinalizedBlock(t *testing.T) { } server := createRPCServer() - rpc := client.NewRPCClient(nodePoolCfg, lggr, server.URL, nil, "rpc", 1, chainId, commonclient.Primary, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + rpc := client.NewRPCClient(nodePoolCfg, lggr, server.URL, nil, "rpc", 1, chainId, multinode.Primary, client.QueryTimeout, client.QueryTimeout, "") require.NoError(t, rpc.Dial(ctx)) defer rpc.Close() - server.Head = &evmtypes.Head{Number: 128} + server.Head.Store(&evmtypes.Head{Number: 128}) // updates chain info _, err := rpc.LatestFinalizedBlock(ctx) require.NoError(t, err) @@ -439,7 +572,7 @@ func TestRPCClient_LatestFinalizedBlock(t *testing.T) { assert.Equal(t, int64(128), latest.FinalizedBlockNumber) // lower block number does not update highestUserObservations - server.Head = &evmtypes.Head{Number: 127} + server.Head.Store(&evmtypes.Head{Number: 127}) _, err = rpc.LatestFinalizedBlock(ctx) require.NoError(t, err) latest, highestUserObservations = rpc.GetInterceptedChainInfo() @@ -451,8 +584,8 @@ func TestRPCClient_LatestFinalizedBlock(t *testing.T) { assert.Equal(t, int64(127), latest.FinalizedBlockNumber) // health check flg prevents change in highestUserObservations - server.Head = &evmtypes.Head{Number: 256} - _, err = rpc.LatestFinalizedBlock(commonclient.CtxAddHealthCheckFlag(ctx)) + server.Head.Store(&evmtypes.Head{Number: 256}) + _, err = rpc.LatestFinalizedBlock(multinode.CtxAddHealthCheckFlag(ctx)) require.NoError(t, err) latest, highestUserObservations = rpc.GetInterceptedChainInfo() @@ -463,7 +596,7 @@ func TestRPCClient_LatestFinalizedBlock(t *testing.T) { assert.Equal(t, int64(256), latest.FinalizedBlockNumber) // subscription updates chain info - server.Head = &evmtypes.Head{Number: 512} + server.Head.Store(&evmtypes.Head{Number: 512}) ch, sub, err := rpc.SubscribeToFinalizedHeads(ctx) require.NoError(t, err) defer sub.Unsubscribe() @@ -479,8 +612,8 @@ func TestRPCClient_LatestFinalizedBlock(t *testing.T) { // health check subscription only updates latest sub.Unsubscribe() // close previous one - server.Head = &evmtypes.Head{Number: 1024} - ch, sub, err = rpc.SubscribeToFinalizedHeads(commonclient.CtxAddHealthCheckFlag(ctx)) + server.Head.Store(&evmtypes.Head{Number: 1024}) + ch, sub, err = rpc.SubscribeToFinalizedHeads(multinode.CtxAddHealthCheckFlag(ctx)) require.NoError(t, err) defer sub.Unsubscribe() head = <-ch @@ -570,7 +703,7 @@ func TestRpcClientLargePayloadTimeout(t *testing.T) { // use something unreasonably large for RPC timeout to ensure that we use largePayloadRPCTimeout const rpcTimeout = time.Hour const largePayloadRPCTimeout = tests.TestInterval - rpc := client.NewRPCClient(nodePoolCfg, logger.Test(t), rpcURL, nil, "rpc", 1, chainId, commonclient.Primary, largePayloadRPCTimeout, rpcTimeout, "") + rpc := client.NewRPCClient(nodePoolCfg, logger.Test(t), rpcURL, nil, "rpc", 1, chainId, multinode.Primary, largePayloadRPCTimeout, rpcTimeout, "") require.NoError(t, rpc.Dial(ctx)) defer rpc.Close() err := testCase.Fn(ctx, rpc) @@ -615,7 +748,7 @@ func TestAstarCustomFinality(t *testing.T) { const expectedFinalizedBlockNumber = int64(4) const expectedFinalizedBlockHash = "0x7441e97acf83f555e0deefef86db636bc8a37eb84747603412884e4df4d22804" - rpcClient := client.NewRPCClient(nodePoolCfg, logger.Test(t), wsURL, nil, "rpc", 1, chainId, commonclient.Primary, commonclient.QueryTimeout, commonclient.QueryTimeout, chaintype.ChainAstar) + rpcClient := client.NewRPCClient(nodePoolCfg, logger.Test(t), wsURL, nil, "rpc", 1, chainId, multinode.Primary, client.QueryTimeout, client.QueryTimeout, chaintype.ChainAstar) defer rpcClient.Close() err := rpcClient.Dial(tests.Context(t)) require.NoError(t, err) diff --git a/core/chains/evm/client/simulated_backend_client.go b/core/chains/evm/client/simulated_backend_client.go index a67670df318..7b325e861a5 100644 --- a/core/chains/evm/client/simulated_backend_client.go +++ b/core/chains/evm/client/simulated_backend_client.go @@ -24,8 +24,8 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink-framework/multinode" - commonclient "github.com/smartcontractkit/chainlink/v2/common/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" @@ -363,7 +363,7 @@ func (c *SimulatedBackendClient) SubscribeToHeads( } head = &evmtypes.Head{ Difficulty: h.Difficulty, - Timestamp: time.Unix(int64(h.Time), 0), //nolint:gosec // G115 false positive + Timestamp: time.Unix(int64(h.Time), 0), Number: h.Number.Int64(), Hash: h.Hash(), ParentHash: h.ParentHash, @@ -399,16 +399,16 @@ func (c *SimulatedBackendClient) HeaderByHash(ctx context.Context, h common.Hash return c.client.HeaderByHash(ctx, h) } -func (c *SimulatedBackendClient) SendTransactionReturnCode(ctx context.Context, tx *types.Transaction, fromAddress common.Address) (commonclient.SendTxReturnCode, error) { +func (c *SimulatedBackendClient) SendTransactionReturnCode(ctx context.Context, tx *types.Transaction, fromAddress common.Address) (multinode.SendTxReturnCode, error) { err := c.SendTransaction(ctx, tx) if err == nil { - return commonclient.Successful, nil + return multinode.Successful, nil } if strings.Contains(err.Error(), "could not fetch parent") || strings.Contains(err.Error(), "invalid transaction") { - return commonclient.Fatal, err + return multinode.Fatal, err } // All remaining error messages returned from SendTransaction are considered Unknown. - return commonclient.Unknown, err + return multinode.Unknown, err } // SendTransaction sends a transaction. diff --git a/core/chains/evm/client/sub_forwarder.go b/core/chains/evm/client/sub_forwarder.go index 93e9b106b4a..a9b5a97eee0 100644 --- a/core/chains/evm/client/sub_forwarder.go +++ b/core/chains/evm/client/sub_forwarder.go @@ -13,7 +13,7 @@ type subForwarder[T any] struct { srcCh chan T srcSub ethereum.Subscription - interceptResult func(T) T + interceptResult func(T) (T, error) interceptError func(error) error done chan struct{} @@ -21,14 +21,14 @@ type subForwarder[T any] struct { unSub chan struct{} } -func newSubForwarder[T any](destCh chan<- T, interceptResult func(T) T, interceptError func(error) error) *subForwarder[T] { +func newSubForwarder[T any](destCh chan<- T, interceptResult func(T) (T, error), interceptError func(error) error) *subForwarder[T] { return &subForwarder[T]{ interceptResult: interceptResult, interceptError: interceptError, destCh: destCh, srcCh: make(chan T), done: make(chan struct{}), - err: make(chan error), + err: make(chan error, 1), unSub: make(chan struct{}, 1), } } @@ -44,6 +44,14 @@ func (c *subForwarder[T]) start(sub ethereum.Subscription, err error) error { return nil } +func (c *subForwarder[T]) handleError(err error) { + if c.interceptError != nil { + err = c.interceptError(err) + } + c.err <- err // err is buffered, and we never write twice, so write is not blocking + c.srcSub.Unsubscribe() +} + // forwardLoop receives from src, adds the chainID, and then sends to dest. // It also handles Unsubscribing, which may interrupt either forwarding operation. func (c *subForwarder[T]) forwardLoop() { @@ -54,19 +62,17 @@ func (c *subForwarder[T]) forwardLoop() { for { select { case err := <-c.srcSub.Err(): - if c.interceptError != nil { - err = c.interceptError(err) - } - select { - case c.err <- err: - case <-c.unSub: - c.srcSub.Unsubscribe() - } + c.handleError(err) return case h := <-c.srcCh: if c.interceptResult != nil { - h = c.interceptResult(h) + var err error + h, err = c.interceptResult(h) + if err != nil { + c.handleError(err) + return + } } select { case c.destCh <- h: diff --git a/core/chains/evm/client/sub_forwarder_test.go b/core/chains/evm/client/sub_forwarder_test.go index 1bc0122603b..267fa1b8467 100644 --- a/core/chains/evm/client/sub_forwarder_test.go +++ b/core/chains/evm/client/sub_forwarder_test.go @@ -21,9 +21,9 @@ func TestChainIDSubForwarder(t *testing.T) { t.Parallel() newChainIDSubForwarder := func(chainID *big.Int, ch chan<- *evmtypes.Head) *subForwarder[*evmtypes.Head] { - return newSubForwarder(ch, func(head *evmtypes.Head) *evmtypes.Head { + return newSubForwarder(ch, func(head *evmtypes.Head) (*evmtypes.Head, error) { head.EVMChainID = ubig.New(chainID) - return head + return head, nil }, nil) } @@ -54,12 +54,14 @@ func TestChainIDSubForwarder(t *testing.T) { sub := NewMockSubscription() err := forwarder.start(sub, nil) assert.NoError(t, err) - sub.Errors <- errors.New("boo") + expectedError := errors.New("boo") + sub.Errors <- expectedError forwarder.Unsubscribe() assert.True(t, sub.unsubscribed) - _, ok := <-sub.Err() - assert.False(t, ok) + err, ok := <-forwarder.Err() + assert.True(t, ok) + require.ErrorIs(t, err, expectedError) _, ok = <-forwarder.Err() assert.False(t, ok) }) @@ -117,6 +119,31 @@ func TestChainIDSubForwarder(t *testing.T) { }) } +func TestSubscriptionForwarder(t *testing.T) { + t.Run("Error returned by interceptResult is forwarded to err channel", func(t *testing.T) { + t.Parallel() + + ch := make(chan *evmtypes.Head) + expectedErr := errors.New("something went wrong during result interception") + forwarder := newSubForwarder(ch, func(head *evmtypes.Head) (*evmtypes.Head, error) { + return nil, expectedErr + }, nil) + mockedSub := NewMockSubscription() + require.NoError(t, forwarder.start(mockedSub, nil)) + + head := &evmtypes.Head{ + ID: 1, + } + forwarder.srcCh <- head + err := <-forwarder.Err() + require.ErrorIs(t, err, expectedErr) + // ensure forwarder is closed + _, ok := <-forwarder.Err() + assert.False(t, ok) + assert.True(t, mockedSub.unsubscribed) + }) +} + func TestSubscriptionErrorWrapper(t *testing.T) { t.Parallel() newSubscriptionErrorWrapper := func(t *testing.T, sub commontypes.Subscription, errorPrefix string) ethereum.Subscription { @@ -145,17 +172,6 @@ func TestSubscriptionErrorWrapper(t *testing.T) { // subsequence unsubscribe does not causes panic wrapper.Unsubscribe() }) - t.Run("Unsubscribe interrupts error delivery", func(t *testing.T) { - t.Parallel() - sub := NewMockSubscription() - const prefix = "RPC returned error" - wrapper := newSubscriptionErrorWrapper(t, sub, prefix) - sub.Errors <- fmt.Errorf("error") - - wrapper.Unsubscribe() - _, ok := <-wrapper.Err() - assert.False(t, ok) - }) t.Run("Successfully wraps error", func(t *testing.T) { t.Parallel() sub := NewMockSubscription() diff --git a/core/chains/evm/config/chain_scoped_transactions.go b/core/chains/evm/config/chain_scoped_transactions.go index 27edb12648a..3da171c98f0 100644 --- a/core/chains/evm/config/chain_scoped_transactions.go +++ b/core/chains/evm/config/chain_scoped_transactions.go @@ -11,6 +11,10 @@ type transactionsConfig struct { c toml.Transactions } +func (t *transactionsConfig) Enabled() bool { + return *t.c.Enabled +} + func (t *transactionsConfig) ForwardersEnabled() bool { return *t.c.ForwardersEnabled } @@ -35,6 +39,31 @@ func (t *transactionsConfig) MaxQueued() uint64 { return uint64(*t.c.MaxQueued) } +func (t *transactionsConfig) TransactionManagerV2() TransactionManagerV2 { + return &transactionManagerV2Config{c: t.c.TransactionManagerV2} +} + +type transactionManagerV2Config struct { + c toml.TransactionManagerV2Config +} + +func (t *transactionManagerV2Config) Enabled() bool { + return *t.c.Enabled +} + +func (t *transactionManagerV2Config) BlockTime() *time.Duration { + d := t.c.BlockTime.Duration() + return &d +} + +func (t *transactionManagerV2Config) CustomURL() *url.URL { + return t.c.CustomURL.URL() +} + +func (t *transactionManagerV2Config) DualBroadcast() *bool { + return t.c.DualBroadcast +} + func (t *transactionsConfig) AutoPurge() AutoPurgeConfig { return &autoPurgeConfig{c: t.c.AutoPurge} } diff --git a/core/chains/evm/config/chaintype/chaintype.go b/core/chains/evm/config/chaintype/chaintype.go index b2eff02834b..be3afa0ea62 100644 --- a/core/chains/evm/config/chaintype/chaintype.go +++ b/core/chains/evm/config/chaintype/chaintype.go @@ -17,6 +17,7 @@ const ( ChainMantle ChainType = "mantle" ChainMetis ChainType = "metis" ChainOptimismBedrock ChainType = "optimismBedrock" + ChainSei ChainType = "sei" ChainScroll ChainType = "scroll" ChainWeMix ChainType = "wemix" ChainXLayer ChainType = "xlayer" @@ -39,7 +40,7 @@ func (c ChainType) IsL2() bool { func (c ChainType) IsValid() bool { switch c { - case "", ChainArbitrum, ChainAstar, ChainCelo, ChainGnosis, ChainHedera, ChainKroma, ChainMantle, ChainMetis, ChainOptimismBedrock, ChainScroll, ChainWeMix, ChainXLayer, ChainZkEvm, ChainZkSync, ChainZircuit: + case "", ChainArbitrum, ChainAstar, ChainCelo, ChainGnosis, ChainHedera, ChainKroma, ChainMantle, ChainMetis, ChainOptimismBedrock, ChainSei, ChainScroll, ChainWeMix, ChainXLayer, ChainZkEvm, ChainZkSync, ChainZircuit: return true } return false @@ -65,6 +66,8 @@ func FromSlug(slug string) ChainType { return ChainMetis case "optimismBedrock": return ChainOptimismBedrock + case "sei": + return ChainSei case "scroll": return ChainScroll case "wemix": @@ -138,6 +141,7 @@ var ErrInvalid = fmt.Errorf("must be one of %s or omitted", strings.Join([]strin string(ChainMantle), string(ChainMetis), string(ChainOptimismBedrock), + string(ChainSei), string(ChainScroll), string(ChainWeMix), string(ChainXLayer), diff --git a/core/chains/evm/config/config.go b/core/chains/evm/config/config.go index f2a571f94b0..c76cb6953e5 100644 --- a/core/chains/evm/config/config.go +++ b/core/chains/evm/config/config.go @@ -103,6 +103,7 @@ type ClientErrors interface { } type Transactions interface { + Enabled() bool ForwardersEnabled() bool ReaperInterval() time.Duration ResendAfterThreshold() time.Duration @@ -110,6 +111,7 @@ type Transactions interface { MaxInFlight() uint32 MaxQueued() uint64 AutoPurge() AutoPurgeConfig + TransactionManagerV2() TransactionManagerV2 } type AutoPurgeConfig interface { @@ -119,6 +121,13 @@ type AutoPurgeConfig interface { DetectionApiUrl() *url.URL } +type TransactionManagerV2 interface { + Enabled() bool + BlockTime() *time.Duration + CustomURL() *url.URL + DualBroadcast() *bool +} + type GasEstimator interface { BlockHistory() BlockHistory FeeHistory() FeeHistory diff --git a/core/chains/evm/config/config_test.go b/core/chains/evm/config/config_test.go index 7eb13458f56..ab0d600efe0 100644 --- a/core/chains/evm/config/config_test.go +++ b/core/chains/evm/config/config_test.go @@ -219,9 +219,20 @@ func TestChainScopedConfig(t *testing.T) { assert.Equal(t, false, cfg3.EVM().LogBroadcasterEnabled()) }) + }) + + t.Run("EVM.Transactions.Enabled", func(t *testing.T) { + t.Run("turn on EVM.Transactions.Enabled by default", func(t *testing.T) { + assert.True(t, cfg.EVM().Transactions().Enabled()) + }) - t.Run("use Noop logBroadcaster when LogBroadcaster is disabled", func(t *testing.T) { + t.Run("verify EVM.Transactions.Enabled is set correctly", func(t *testing.T) { + val := false + cfg3 := testutils.NewTestChainScopedConfig(t, func(c *toml.EVMConfig) { + c.Transactions.Enabled = ptr(val) + }) + assert.False(t, cfg3.EVM().Transactions().Enabled()) }) }) } diff --git a/core/chains/evm/config/mocks/chain_scoped_config.go b/core/chains/evm/config/mocks/chain_scoped_config.go index a2fe703f98f..000d2a7287c 100644 --- a/core/chains/evm/config/mocks/chain_scoped_config.go +++ b/core/chains/evm/config/mocks/chain_scoped_config.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -20,7 +20,7 @@ func (_m *ChainScopedConfig) EXPECT() *ChainScopedConfig_Expecter { return &ChainScopedConfig_Expecter{mock: &_m.Mock} } -// EVM provides a mock function with given fields: +// EVM provides a mock function with no fields func (_m *ChainScopedConfig) EVM() config.EVM { ret := _m.Called() diff --git a/core/chains/evm/config/mocks/gas_estimator.go b/core/chains/evm/config/mocks/gas_estimator.go index 1ead5e68917..2f36086f947 100644 --- a/core/chains/evm/config/mocks/gas_estimator.go +++ b/core/chains/evm/config/mocks/gas_estimator.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -24,7 +24,7 @@ func (_m *GasEstimator) EXPECT() *GasEstimator_Expecter { return &GasEstimator_Expecter{mock: &_m.Mock} } -// BlockHistory provides a mock function with given fields: +// BlockHistory provides a mock function with no fields func (_m *GasEstimator) BlockHistory() config.BlockHistory { ret := _m.Called() @@ -71,7 +71,7 @@ func (_c *GasEstimator_BlockHistory_Call) RunAndReturn(run func() config.BlockHi return _c } -// BumpMin provides a mock function with given fields: +// BumpMin provides a mock function with no fields func (_m *GasEstimator) BumpMin() *assets.Wei { ret := _m.Called() @@ -118,7 +118,7 @@ func (_c *GasEstimator_BumpMin_Call) RunAndReturn(run func() *assets.Wei) *GasEs return _c } -// BumpPercent provides a mock function with given fields: +// BumpPercent provides a mock function with no fields func (_m *GasEstimator) BumpPercent() uint16 { ret := _m.Called() @@ -163,7 +163,7 @@ func (_c *GasEstimator_BumpPercent_Call) RunAndReturn(run func() uint16) *GasEst return _c } -// BumpThreshold provides a mock function with given fields: +// BumpThreshold provides a mock function with no fields func (_m *GasEstimator) BumpThreshold() uint64 { ret := _m.Called() @@ -208,7 +208,7 @@ func (_c *GasEstimator_BumpThreshold_Call) RunAndReturn(run func() uint64) *GasE return _c } -// BumpTxDepth provides a mock function with given fields: +// BumpTxDepth provides a mock function with no fields func (_m *GasEstimator) BumpTxDepth() uint32 { ret := _m.Called() @@ -253,7 +253,7 @@ func (_c *GasEstimator_BumpTxDepth_Call) RunAndReturn(run func() uint32) *GasEst return _c } -// DAOracle provides a mock function with given fields: +// DAOracle provides a mock function with no fields func (_m *GasEstimator) DAOracle() config.DAOracle { ret := _m.Called() @@ -300,7 +300,7 @@ func (_c *GasEstimator_DAOracle_Call) RunAndReturn(run func() config.DAOracle) * return _c } -// EIP1559DynamicFees provides a mock function with given fields: +// EIP1559DynamicFees provides a mock function with no fields func (_m *GasEstimator) EIP1559DynamicFees() bool { ret := _m.Called() @@ -345,7 +345,7 @@ func (_c *GasEstimator_EIP1559DynamicFees_Call) RunAndReturn(run func() bool) *G return _c } -// EstimateLimit provides a mock function with given fields: +// EstimateLimit provides a mock function with no fields func (_m *GasEstimator) EstimateLimit() bool { ret := _m.Called() @@ -390,7 +390,7 @@ func (_c *GasEstimator_EstimateLimit_Call) RunAndReturn(run func() bool) *GasEst return _c } -// FeeCapDefault provides a mock function with given fields: +// FeeCapDefault provides a mock function with no fields func (_m *GasEstimator) FeeCapDefault() *assets.Wei { ret := _m.Called() @@ -437,7 +437,7 @@ func (_c *GasEstimator_FeeCapDefault_Call) RunAndReturn(run func() *assets.Wei) return _c } -// FeeHistory provides a mock function with given fields: +// FeeHistory provides a mock function with no fields func (_m *GasEstimator) FeeHistory() config.FeeHistory { ret := _m.Called() @@ -484,7 +484,7 @@ func (_c *GasEstimator_FeeHistory_Call) RunAndReturn(run func() config.FeeHistor return _c } -// LimitDefault provides a mock function with given fields: +// LimitDefault provides a mock function with no fields func (_m *GasEstimator) LimitDefault() uint64 { ret := _m.Called() @@ -529,7 +529,7 @@ func (_c *GasEstimator_LimitDefault_Call) RunAndReturn(run func() uint64) *GasEs return _c } -// LimitJobType provides a mock function with given fields: +// LimitJobType provides a mock function with no fields func (_m *GasEstimator) LimitJobType() config.LimitJobType { ret := _m.Called() @@ -576,7 +576,7 @@ func (_c *GasEstimator_LimitJobType_Call) RunAndReturn(run func() config.LimitJo return _c } -// LimitMax provides a mock function with given fields: +// LimitMax provides a mock function with no fields func (_m *GasEstimator) LimitMax() uint64 { ret := _m.Called() @@ -621,7 +621,7 @@ func (_c *GasEstimator_LimitMax_Call) RunAndReturn(run func() uint64) *GasEstima return _c } -// LimitMultiplier provides a mock function with given fields: +// LimitMultiplier provides a mock function with no fields func (_m *GasEstimator) LimitMultiplier() float32 { ret := _m.Called() @@ -666,7 +666,7 @@ func (_c *GasEstimator_LimitMultiplier_Call) RunAndReturn(run func() float32) *G return _c } -// LimitTransfer provides a mock function with given fields: +// LimitTransfer provides a mock function with no fields func (_m *GasEstimator) LimitTransfer() uint64 { ret := _m.Called() @@ -711,7 +711,7 @@ func (_c *GasEstimator_LimitTransfer_Call) RunAndReturn(run func() uint64) *GasE return _c } -// Mode provides a mock function with given fields: +// Mode provides a mock function with no fields func (_m *GasEstimator) Mode() string { ret := _m.Called() @@ -756,7 +756,7 @@ func (_c *GasEstimator_Mode_Call) RunAndReturn(run func() string) *GasEstimator_ return _c } -// PriceDefault provides a mock function with given fields: +// PriceDefault provides a mock function with no fields func (_m *GasEstimator) PriceDefault() *assets.Wei { ret := _m.Called() @@ -803,7 +803,7 @@ func (_c *GasEstimator_PriceDefault_Call) RunAndReturn(run func() *assets.Wei) * return _c } -// PriceMax provides a mock function with given fields: +// PriceMax provides a mock function with no fields func (_m *GasEstimator) PriceMax() *assets.Wei { ret := _m.Called() @@ -898,7 +898,7 @@ func (_c *GasEstimator_PriceMaxKey_Call) RunAndReturn(run func(common.Address) * return _c } -// PriceMin provides a mock function with given fields: +// PriceMin provides a mock function with no fields func (_m *GasEstimator) PriceMin() *assets.Wei { ret := _m.Called() @@ -945,7 +945,7 @@ func (_c *GasEstimator_PriceMin_Call) RunAndReturn(run func() *assets.Wei) *GasE return _c } -// TipCapDefault provides a mock function with given fields: +// TipCapDefault provides a mock function with no fields func (_m *GasEstimator) TipCapDefault() *assets.Wei { ret := _m.Called() @@ -992,7 +992,7 @@ func (_c *GasEstimator_TipCapDefault_Call) RunAndReturn(run func() *assets.Wei) return _c } -// TipCapMin provides a mock function with given fields: +// TipCapMin provides a mock function with no fields func (_m *GasEstimator) TipCapMin() *assets.Wei { ret := _m.Called() diff --git a/core/chains/evm/config/toml/config.go b/core/chains/evm/config/toml/config.go index 0505449943e..7a3dddcb1de 100644 --- a/core/chains/evm/config/toml/config.go +++ b/core/chains/evm/config/toml/config.go @@ -6,6 +6,7 @@ import ( "net/url" "slices" "strconv" + "time" "github.com/ethereum/go-ethereum/core/txpool/legacypool" "github.com/pelletier/go-toml/v2" @@ -471,7 +472,29 @@ func (c *Chain) ValidateConfig() (err error) { return } +func (c *Transactions) ValidateConfig() (err error) { + if c.TransactionManagerV2.Enabled != nil && *c.TransactionManagerV2.Enabled && + c.TransactionManagerV2.DualBroadcast != nil && *c.TransactionManagerV2.DualBroadcast { + if c.TransactionManagerV2.CustomURL == nil { + err = multierr.Append(err, commonconfig.ErrMissing{Name: "TransactionManagerV2.CustomURL", Msg: "must be set if DualBroadcast is enabled"}) + } + if c.AutoPurge.Enabled != nil && !*c.AutoPurge.Enabled { + err = multierr.Append(err, commonconfig.ErrInvalid{Name: "AutoPurge.Enabled", Value: false, Msg: "cannot be false if DualBroadcast is enabled"}) + } + if c.AutoPurge.DetectionApiUrl == nil { + err = multierr.Append(err, commonconfig.ErrMissing{Name: "AutoPurge.DetectionApiUrl", Msg: "must be set if DualBroadcast is enabled"}) + } + if c.AutoPurge.Threshold == nil { + err = multierr.Append(err, commonconfig.ErrMissing{Name: "AutoPurge.Threshold", Msg: "needs to be set if auto-purge feature is enabled"}) + } else if *c.AutoPurge.Threshold == 0 { + err = multierr.Append(err, commonconfig.ErrInvalid{Name: "AutoPurge.Threshold", Value: 0, Msg: "cannot be 0 if auto-purge feature is enabled"}) + } + } + return +} + type Transactions struct { + Enabled *bool ForwardersEnabled *bool MaxInFlight *uint32 MaxQueued *uint32 @@ -479,10 +502,14 @@ type Transactions struct { ReaperThreshold *commonconfig.Duration ResendAfterThreshold *commonconfig.Duration - AutoPurge AutoPurgeConfig `toml:",omitempty"` + AutoPurge AutoPurgeConfig `toml:",omitempty"` + TransactionManagerV2 TransactionManagerV2Config `toml:",omitempty"` } func (t *Transactions) setFrom(f *Transactions) { + if v := f.Enabled; v != nil { + t.Enabled = v + } if v := f.ForwardersEnabled; v != nil { t.ForwardersEnabled = v } @@ -502,6 +529,7 @@ func (t *Transactions) setFrom(f *Transactions) { t.ResendAfterThreshold = v } t.AutoPurge.setFrom(&f.AutoPurge) + t.TransactionManagerV2.setFrom(&f.TransactionManagerV2) } type AutoPurgeConfig struct { @@ -526,6 +554,41 @@ func (a *AutoPurgeConfig) setFrom(f *AutoPurgeConfig) { } } +type TransactionManagerV2Config struct { + Enabled *bool `toml:",omitempty"` + BlockTime *commonconfig.Duration `toml:",omitempty"` + CustomURL *commonconfig.URL `toml:",omitempty"` + DualBroadcast *bool `toml:",omitempty"` +} + +func (t *TransactionManagerV2Config) setFrom(f *TransactionManagerV2Config) { + if v := f.Enabled; v != nil { + t.Enabled = f.Enabled + } + if v := f.BlockTime; v != nil { + t.BlockTime = f.BlockTime + } + if v := f.CustomURL; v != nil { + t.CustomURL = f.CustomURL + } + if v := f.DualBroadcast; v != nil { + t.DualBroadcast = f.DualBroadcast + } +} + +func (t *TransactionManagerV2Config) ValidateConfig() (err error) { + if t.Enabled != nil && *t.Enabled { + if t.BlockTime == nil { + err = multierr.Append(err, commonconfig.ErrMissing{Name: "BlockTime", Msg: "must be set if TransactionManagerV2 feature is enabled"}) + return + } + if t.BlockTime.Duration() < 2*time.Second { + err = multierr.Append(err, commonconfig.ErrInvalid{Name: "BlockTime", Msg: "must be equal to or greater than 2 seconds"}) + } + } + return +} + type OCR2 struct { Automation Automation `toml:",omitempty"` } diff --git a/core/chains/evm/config/toml/defaults.go b/core/chains/evm/config/toml/defaults.go index 0885d94e6df..60da9bded1b 100644 --- a/core/chains/evm/config/toml/defaults.go +++ b/core/chains/evm/config/toml/defaults.go @@ -4,7 +4,7 @@ import ( "bytes" "embed" "fmt" - "io" + "io/fs" "log" "os" "path/filepath" @@ -19,7 +19,6 @@ import ( ) var ( - //go:embed defaults/*.toml defaultsFS embed.FS fallback Chain @@ -33,48 +32,24 @@ var ( ) func init() { - // read the defaults first + var ( + fb *Chain + err error + ) - fes, err := defaultsFS.ReadDir("defaults") + // read all default configs + DefaultIDs, defaultNames, defaults, fb, err = initDefaults(defaultsFS.ReadDir, defaultsFS.ReadFile, "defaults") if err != nil { - log.Fatalf("failed to read defaults/: %v", err) + log.Fatalf("failed to read defaults: %s", err) } - for _, fe := range fes { - path := filepath.Join("defaults", fe.Name()) - b, err2 := defaultsFS.ReadFile(path) - if err2 != nil { - log.Fatalf("failed to read %q: %v", path, err2) - } - var config = struct { - ChainID *big.Big - Chain - }{} - if err3 := cconfig.DecodeTOML(bytes.NewReader(b), &config); err3 != nil { - log.Fatalf("failed to decode %q: %v", path, err3) - } - if fe.Name() == "fallback.toml" { - if config.ChainID != nil { - log.Fatalf("fallback ChainID must be nil, not: %s", config.ChainID) - } - fallback = config.Chain - continue - } - if config.ChainID == nil { - log.Fatalf("missing ChainID: %s", path) - } - DefaultIDs = append(DefaultIDs, config.ChainID) - id := config.ChainID.String() - if _, ok := defaults[id]; ok { - log.Fatalf("%q contains duplicate ChainID: %s", path, id) - } - defaults[id] = config.Chain - defaultNames[id] = strings.ReplaceAll(strings.TrimSuffix(fe.Name(), ".toml"), "_", " ") + if fb == nil { + log.Fatal("failed to set fallback chain config") } - slices.SortFunc(DefaultIDs, func(a, b *big.Big) int { - return a.Cmp(b) - }) + fallback = *fb + + // check for and apply any overrides // read the custom defaults overrides dir := env.CustomDefaults.Get() if dir == "" { @@ -83,54 +58,99 @@ func init() { } // use evm overrides specifically - evmDir := fmt.Sprintf("%s/evm", dir) + _, _, customDefaults, fb, err = initDefaults(os.ReadDir, os.ReadFile, dir+"/evm") + if err != nil { + log.Fatalf("failed to read custom overrides: %s", err) + } + + if fb != nil { + fallback = *fb + } +} - // Read directory contents for evm only - entries, err := os.ReadDir(evmDir) +func initDefaults( + dirReader func(name string) ([]fs.DirEntry, error), + fileReader func(name string) ([]byte, error), + root string, +) ([]*big.Big, map[string]string, map[string]Chain, *Chain, error) { + entries, err := dirReader(root) if err != nil { - log.Fatalf("error reading evm custom defaults override directory: %v", err) - return + return nil, nil, nil, nil, fmt.Errorf("failed to read directory: %w", err) } + var fb *Chain + + ids := make([]*big.Big, 0) + configs := make(map[string]Chain) + names := make(map[string]string) + for _, entry := range entries { if entry.IsDir() { // Skip directories continue } - path := evmDir + "/" + entry.Name() - file, err := os.Open(path) - if err != nil { - log.Fatalf("error opening file (name: %v) in custom defaults override directory: %v", entry.Name(), err) - } + // read the file to bytes + path := filepath.Join(root, entry.Name()) - // Read file contents - b, err := io.ReadAll(file) - file.Close() + chainID, chain, err := readConfig(path, fileReader) if err != nil { - log.Fatalf("error reading file (name: %v) contents in custom defaults override directory: %v", entry.Name(), err) + return nil, nil, nil, nil, err } - var config = struct { - ChainID *big.Big - Chain - }{} + if entry.Name() == "fallback.toml" { + if chainID != nil { + return nil, nil, nil, nil, fmt.Errorf("fallback ChainID must be nil: found: %s", chainID) + } - if err := cconfig.DecodeTOML(bytes.NewReader(b), &config); err != nil { - log.Fatalf("failed to decode %q in custom defaults override directory: %v", path, err) + fb = &chain + + continue } - if config.ChainID == nil { - log.Fatalf("missing ChainID in: %s in custom defaults override directory. exiting", path) + // ensure ChainID is set + if chainID == nil { + return nil, nil, nil, nil, fmt.Errorf("missing ChainID: %s", path) } - id := config.ChainID.String() + ids = append(ids, chainID) - if _, ok := customDefaults[id]; ok { + // ChainID as a default should not be duplicated + id := chainID.String() + if _, ok := configs[id]; ok { log.Fatalf("%q contains duplicate ChainID: %s", path, id) } - customDefaults[id] = config.Chain + + // set lookups + configs[id] = chain + names[id] = strings.ReplaceAll(strings.TrimSuffix(entry.Name(), ".toml"), "_", " ") } + + // sort IDs in numeric order + slices.SortFunc(ids, func(a, b *big.Big) int { + return a.Cmp(b) + }) + + return ids, names, configs, fb, nil +} + +func readConfig(path string, reader func(name string) ([]byte, error)) (*big.Big, Chain, error) { + bts, err := reader(path) + if err != nil { + return nil, Chain{}, fmt.Errorf("error reading file: %w", err) + } + + var config = struct { + ChainID *big.Big + Chain + }{} + + // decode from toml to a chain config + if err := cconfig.DecodeTOML(bytes.NewReader(bts), &config); err != nil { + return nil, Chain{}, fmt.Errorf("error in TOML decoding %s: %w", path, err) + } + + return config.ChainID, config.Chain, nil } // DefaultsNamed returns the default Chain values, optionally for the given chainID, as well as a name if the chainID is known. @@ -236,7 +256,6 @@ func (c *Chain) SetFrom(f *Chain) { if v := f.FinalizedBlockOffset; v != nil { c.FinalizedBlockOffset = v } - if v := f.NoNewFinalizedHeadsThreshold; v != nil { c.NoNewFinalizedHeadsThreshold = v } diff --git a/core/chains/evm/config/toml/defaults/Avalanche_Fuji.toml b/core/chains/evm/config/toml/defaults/Avalanche_Fuji.toml index fbcc8e6f058..2fd63004531 100644 --- a/core/chains/evm/config/toml/defaults/Avalanche_Fuji.toml +++ b/core/chains/evm/config/toml/defaults/Avalanche_Fuji.toml @@ -11,9 +11,8 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '1m' [GasEstimator] -PriceDefault = '25 gwei' -PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' -PriceMin = '25 gwei' +PriceMin = '1 gwei' +PriceDefault = '1 gwei' [GasEstimator.BlockHistory] BlockHistorySize = 24 diff --git a/core/chains/evm/config/toml/defaults/Avalanche_Mainnet.toml b/core/chains/evm/config/toml/defaults/Avalanche_Mainnet.toml index 309fdab1db9..9a8f32d3288 100644 --- a/core/chains/evm/config/toml/defaults/Avalanche_Mainnet.toml +++ b/core/chains/evm/config/toml/defaults/Avalanche_Mainnet.toml @@ -11,9 +11,8 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '1m' [GasEstimator] -PriceDefault = '25 gwei' -PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' -PriceMin = '25 gwei' +PriceMin = '1 gwei' +PriceDefault = '1 gwei' [GasEstimator.BlockHistory] # Average block time of 2s diff --git a/core/chains/evm/config/toml/defaults/Botanix_Testnet.toml b/core/chains/evm/config/toml/defaults/Botanix_Testnet.toml new file mode 100644 index 00000000000..570f360c878 --- /dev/null +++ b/core/chains/evm/config/toml/defaults/Botanix_Testnet.toml @@ -0,0 +1,12 @@ +ChainID = '3636' +FinalityTagEnabled = true + +[GasEstimator] +EIP1559DynamicFees = true + +[GasEstimator.BlockHistory] +BlockHistorySize = 4 +TransactionPercentile = 50 + +[HeadTracker] +FinalityTagBypass = false diff --git a/core/chains/evm/config/toml/defaults/Ink_Mainnet.toml b/core/chains/evm/config/toml/defaults/Ink_Mainnet.toml new file mode 100644 index 00000000000..d4b35f291d9 --- /dev/null +++ b/core/chains/evm/config/toml/defaults/Ink_Mainnet.toml @@ -0,0 +1,28 @@ +ChainID = '57073' +# OP stack: https://github.com/inkonchain/node +ChainType = 'optimismBedrock' +# finality_depth was: ~2094 +FinalityDepth = 3000 +# block_time was: ~1s, adding 1 second buffer +LogPollInterval = '2s' + +# batching_size_finalization_percentage = 30% according to the explorer batching view +# ( batching_size_finalization_percentage * finality_depth) * block_time / 60 secs = ~10 min (finality time) +NoNewFinalizedHeadsThreshold = '60m0s' + +FinalityTagEnabled = true + +[GasEstimator] +EIP1559DynamicFees = true +Mode = 'FeeHistory' + +[GasEstimator.FeeHistory] +# block_time was: 1s, per recommendation skip 1-2 blocks +CacheTimeout = '2s' + +[GasEstimator.BlockHistory] +BlockHistorySize = 100 + +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x420000000000000000000000000000000000000F' diff --git a/core/chains/evm/config/toml/defaults/Ink_Testnet.toml b/core/chains/evm/config/toml/defaults/Ink_Testnet.toml new file mode 100644 index 00000000000..936651bfb0c --- /dev/null +++ b/core/chains/evm/config/toml/defaults/Ink_Testnet.toml @@ -0,0 +1,28 @@ +ChainID = '763373' +# OP stack: https://github.com/inkonchain/node +ChainType = 'optimismBedrock' +# finality_depth was: ~2094 +FinalityDepth = 3000 +# block_time was: ~1s, adding 1 second buffer +LogPollInterval = '2s' + +# batching_size_finalization_percentage = 30% according to the explorer batching view +# ( batching_size_finalization_percentage * finality_depth) * block_time / 60 secs = ~10 min (finality time) +NoNewFinalizedHeadsThreshold = '60m0s' + +FinalityTagEnabled = true + +[GasEstimator] +EIP1559DynamicFees = true +Mode = 'FeeHistory' + +[GasEstimator.FeeHistory] +# block_time was: 1s, per recommendation skip 1-2 blocks +CacheTimeout = '2s' + +[GasEstimator.BlockHistory] +BlockHistorySize = 100 + +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x420000000000000000000000000000000000000F' diff --git a/core/chains/evm/config/toml/defaults/Mantle_Mainnet.toml b/core/chains/evm/config/toml/defaults/Mantle_Mainnet.toml new file mode 100644 index 00000000000..33a34184f0b --- /dev/null +++ b/core/chains/evm/config/toml/defaults/Mantle_Mainnet.toml @@ -0,0 +1,37 @@ +ChainID = '5000' +FinalityTagEnabled = true +FinalityDepth = 1200 +ChainType = 'optimismBedrock' +LogPollInterval = '2s' +MinIncomingConfirmations = 1 +NoNewFinalizedHeadsThreshold = '40m0s' + +[HeadTracker] +HistoryDepth = 1250 + +[GasEstimator] +PriceMax = '120 gwei' +# Limit values are high as Mantle's GasPrice is in native token (MNT) instead of ETH. Their proprietary TokenRatio parameter is used to adjust fees +LimitDefault = 80_000_000_000 +LimitMax = 100_000_000_000 +BumpMin = '100 wei' +BumpThreshold = 60 +EIP1559DynamicFees = true +FeeCapDefault = '120 gwei' +# Mantle recommends setting Priority Fee to 0 in their docs linked here: https://docs-v2.mantle.xyz/devs/concepts/tx-fee/eip-1559#application-of-eip-1559-in-mantle-v2-tectonic +TipCapDefault = '0 wei' +TipCapMin = '0 wei' + +[GasEstimator.BlockHistory] +# Default is 24, which leads to bumpy gas prices. In CCIP +# we want to smooth out the gas prices, so we increase the sample size. +BlockHistorySize = 200 +# The formula for FeeCap is (current block base fee * (1.125 ^ EIP1559FeeCapBufferBlocks) + tipcap) +# where tipcap is managed by the block history estimators. In the context of CCIP, +# the gas price is relayed to other changes for quotes so we want accurate/avg not pessimistic values. +# So we set this to zero so FeeCap = baseFee + tipcap. +EIP1559FeeCapBufferBlocks = 0 + +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x420000000000000000000000000000000000000F' diff --git a/core/chains/evm/config/toml/defaults/Mantle_Sepolia.toml b/core/chains/evm/config/toml/defaults/Mantle_Sepolia.toml new file mode 100644 index 00000000000..bdfa4a204f8 --- /dev/null +++ b/core/chains/evm/config/toml/defaults/Mantle_Sepolia.toml @@ -0,0 +1,38 @@ +ChainID = '5003' +FinalityTagEnabled = true +FinalityDepth = 1200 +ChainType = 'optimismBedrock' +LogPollInterval = '2s' +MinIncomingConfirmations = 1 +NoNewFinalizedHeadsThreshold = '60m0s' + +[HeadTracker] +HistoryDepth = 1250 + +[GasEstimator] +PriceMax = '120 gwei' +# Limit values are high as Mantle's GasPrice is in native token (MNT) instead of ETH. Their proprietary TokenRatio parameter is used to adjust fees +LimitDefault = 80000000000 +LimitMax = 100000000000 +BumpMin = '100 wei' +BumpPercent = 20 +BumpThreshold = 60 +EIP1559DynamicFees = true +FeeCapDefault = '120 gwei' +# Mantle recommends setting Priority Fee to 0 in their docs linked here: https://docs-v2.mantle.xyz/devs/concepts/tx-fee/eip-1559#application-of-eip-1559-in-mantle-v2-tectonic +TipCapDefault = '0 wei' +TipCapMin = '0 wei' + +[GasEstimator.BlockHistory] +# Default is 24, which leads to bumpy gas prices. In CCIP +# we want to smooth out the gas prices, so we increase the sample size. +BlockHistorySize = 200 +# The formula for FeeCap is (current block base fee * (1.125 ^ EIP1559FeeCapBufferBlocks) + tipcap) +# where tipcap is managed by the block history estimators. In the context of CCIP, +# the gas price is relayed to other changes for quotes so we want accurate/avg not pessimistic values. +# So we set this to zero so FeeCap = baseFee + tipcap. +EIP1559FeeCapBufferBlocks = 0 + +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x420000000000000000000000000000000000000F' diff --git a/core/chains/evm/config/toml/defaults/Soneium_Mainnet.toml b/core/chains/evm/config/toml/defaults/Soneium_Mainnet.toml new file mode 100644 index 00000000000..9dd633123cb --- /dev/null +++ b/core/chains/evm/config/toml/defaults/Soneium_Mainnet.toml @@ -0,0 +1,36 @@ +ChainID = '1868' +ChainType = 'optimismBedrock' +LinkContractAddress = '0x7ea13478Ea3961A0e8b538cb05a9DF0477c79Cd2' +FinalityDepth = 200 +LogPollInterval = '2s' +NoNewHeadsThreshold = '40s' +MinIncomingConfirmations = 1 +NoNewFinalizedHeadsThreshold = '120m' # Soneium can take upto 2Hours to finalize +FinalityTagEnabled = true + +[GasEstimator] +EIP1559DynamicFees = true +PriceMin = '1 wei' +BumpMin = '1 mwei' + +[GasEstimator.BlockHistory] +BlockHistorySize = 60 + +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x420000000000000000000000000000000000000F' + +[Transactions] +ResendAfterThreshold = '30s' + +[HeadTracker] +HistoryDepth = 300 + +[NodePool] +SyncThreshold = 10 + +[OCR] +ContractConfirmations = 1 + +[OCR2.Automation] +GasLimit = 6500000 diff --git a/core/chains/evm/config/toml/defaults/Sonic_Mainnet.toml b/core/chains/evm/config/toml/defaults/Sonic_Mainnet.toml new file mode 100644 index 00000000000..2483c736830 --- /dev/null +++ b/core/chains/evm/config/toml/defaults/Sonic_Mainnet.toml @@ -0,0 +1,28 @@ +ChainId = '146' +FinalityDepth = 10 +FinalityTagEnabled = false +LogPollInterval = "1s" #1s block rate +MinIncomingConfirmations = 5 +RPCBlockQueryDelay = 10 +RPCDefaultBatchSize = 100 + +[GasEstimator] +Mode = 'FeeHistory' +EIP1559DynamicFees = true +BumpPercent = 10 +LimitDefault = 8000000 # default ccip value + +[GasEstimator.FeeHistory] +CacheTimeout = '2s' + +[GasEstimator.BlockHistory] +BlockHistorySize = 100 + +[HeadTracker] +HistoryDepth = 50 + +[NodePool] +SyncThreshold = 10 + +[Transactions] +MaxQueued = 500 diff --git a/core/chains/evm/config/toml/defaults/Sonic_testnet.toml b/core/chains/evm/config/toml/defaults/Sonic_testnet.toml new file mode 100644 index 00000000000..83cd6c018a1 --- /dev/null +++ b/core/chains/evm/config/toml/defaults/Sonic_testnet.toml @@ -0,0 +1,28 @@ +ChainId = '57054' +FinalityDepth = 10 +FinalityTagEnabled = false +LogPollInterval = "1s" #1s block rate +MinIncomingConfirmations = 5 +RPCBlockQueryDelay = 10 +RPCDefaultBatchSize = 100 + +[GasEstimator] +Mode = 'FeeHistory' +EIP1559DynamicFees = true +BumpPercent = 10 +LimitDefault = 8000000 # default ccip value + +[GasEstimator.FeeHistory] +CacheTimeout = '2s' + +[GasEstimator.BlockHistory] +BlockHistorySize = 100 + +[HeadTracker] +HistoryDepth = 50 + +[NodePool] +SyncThreshold = 10 + +[Transactions] +MaxQueued = 500 diff --git a/core/chains/evm/config/toml/defaults/fallback.toml b/core/chains/evm/config/toml/defaults/fallback.toml index ab349ee4688..4b6caa20787 100644 --- a/core/chains/evm/config/toml/defaults/fallback.toml +++ b/core/chains/evm/config/toml/defaults/fallback.toml @@ -19,6 +19,7 @@ NoNewFinalizedHeadsThreshold = '0' LogBroadcasterEnabled = true [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -29,6 +30,9 @@ ResendAfterThreshold = '1m' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true diff --git a/core/chains/evm/forwarders/mocks/orm.go b/core/chains/evm/forwarders/mocks/orm.go index 860ddef855b..a98769ee8cc 100644 --- a/core/chains/evm/forwarders/mocks/orm.go +++ b/core/chains/evm/forwarders/mocks/orm.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/chains/evm/gas/arbitrum_estimator.go b/core/chains/evm/gas/arbitrum_estimator.go index 6a11932878b..a53760e45e6 100644 --- a/core/chains/evm/gas/arbitrum_estimator.go +++ b/core/chains/evm/gas/arbitrum_estimator.go @@ -11,7 +11,8 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" - feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" + + "github.com/smartcontractkit/chainlink/v2/common/fees" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups" ) @@ -96,14 +97,14 @@ func (a *arbitrumEstimator) HealthReport() map[string]error { // - Limit is computed from the dynamic values perL2Tx and perL1CalldataUnit, provided by the getPricesInArbGas() method // of the precompilie contract at ArbGasInfoAddress. perL2Tx is a constant amount of gas, and perL1CalldataUnit is // multiplied by the length of the tx calldata. The sum of these two values plus the original l2GasLimit is returned. -func (a *arbitrumEstimator) GetLegacyGas(ctx context.Context, calldata []byte, l2GasLimit uint64, maxGasPriceWei *assets.Wei, opts ...feetypes.Opt) (gasPrice *assets.Wei, chainSpecificGasLimit uint64, err error) { +func (a *arbitrumEstimator) GetLegacyGas(ctx context.Context, calldata []byte, l2GasLimit uint64, maxGasPriceWei *assets.Wei, opts ...fees.Opt) (gasPrice *assets.Wei, chainSpecificGasLimit uint64, err error) { gasPrice, _, err = a.EvmEstimator.GetLegacyGas(ctx, calldata, l2GasLimit, maxGasPriceWei, opts...) if err != nil { return } gasPrice = a.gasPriceWithBuffer(gasPrice, maxGasPriceWei) ok := a.IfStarted(func() { - if slices.Contains(opts, feetypes.OptForceRefetch) { + if slices.Contains(opts, fees.OptForceRefetch) { ch := make(chan struct{}) select { case a.chForceRefetch <- ch: diff --git a/core/chains/evm/gas/block_history_estimator.go b/core/chains/evm/gas/block_history_estimator.go index 12e2d915ee2..31dfdc54541 100644 --- a/core/chains/evm/gas/block_history_estimator.go +++ b/core/chains/evm/gas/block_history_estimator.go @@ -21,8 +21,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" "github.com/smartcontractkit/chainlink-common/pkg/utils/mathutil" - commonfee "github.com/smartcontractkit/chainlink/v2/common/fee" - feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" + "github.com/smartcontractkit/chainlink/v2/common/fees" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" @@ -235,7 +234,7 @@ func (b *BlockHistoryEstimator) HealthReport() map[string]error { return map[string]error{b.Name(): b.Healthy()} } -func (b *BlockHistoryEstimator) GetLegacyGas(_ context.Context, _ []byte, gasLimit uint64, maxGasPriceWei *assets.Wei, _ ...feetypes.Opt) (gasPrice *assets.Wei, chainSpecificGasLimit uint64, err error) { +func (b *BlockHistoryEstimator) GetLegacyGas(_ context.Context, _ []byte, gasLimit uint64, maxGasPriceWei *assets.Wei, _ ...fees.Opt) (gasPrice *assets.Wei, chainSpecificGasLimit uint64, err error) { ok := b.IfStarted(func() { gasPrice = b.getGasPrice() }) @@ -303,7 +302,7 @@ func (b *BlockHistoryEstimator) setMaxPercentileTipCap(tipCap *assets.Wei) { func (b *BlockHistoryEstimator) BumpLegacyGas(_ context.Context, originalGasPrice *assets.Wei, gasLimit uint64, maxGasPriceWei *assets.Wei, attempts []EvmPriorAttempt) (bumpedGasPrice *assets.Wei, chainSpecificGasLimit uint64, err error) { if b.bhConfig.CheckInclusionBlocks() > 0 { if err = b.haltBumping(attempts); err != nil { - if errors.Is(err, commonfee.ErrConnectivity) { + if errors.Is(err, fees.ErrConnectivity) { b.logger.Criticalw(BumpingHaltedLabel, "err", err) b.SvcErrBuffer.Append(err) promBlockHistoryEstimatorConnectivityFailureCount.WithLabelValues(b.chainID.String(), "legacy").Inc() @@ -365,7 +364,7 @@ func (b *BlockHistoryEstimator) haltBumping(attempts []EvmPriorAttempt) error { } if !attemptEip1559 { if attempt.GasPrice.Cmp(maxGasPrice) > 0 { - return fmt.Errorf("transaction %s has gas price of %s, which is above percentile=%d%% (percentile price: %s): %w", attempt.TxHash, attempt.GasPrice, percentile, maxGasPrice, commonfee.ErrConnectivity) + return fmt.Errorf("transaction %s has gas price of %s, which is above percentile=%d%% (percentile price: %s): %w", attempt.TxHash, attempt.GasPrice, percentile, maxGasPrice, fees.ErrConnectivity) } continue } @@ -382,7 +381,7 @@ func (b *BlockHistoryEstimator) haltBumping(attempts []EvmPriorAttempt) error { } } if sufficientFeeCap && attempt.DynamicFee.GasTipCap.Cmp(maxTipCap) > 0 { - return fmt.Errorf("transaction %s has tip cap of %s, which is above percentile=%d%% (percentile tip cap: %s): %w", attempt.TxHash, attempt.DynamicFee.GasTipCap, percentile, maxTipCap, commonfee.ErrConnectivity) + return fmt.Errorf("transaction %s has tip cap of %s, which is above percentile=%d%% (percentile tip cap: %s): %w", attempt.TxHash, attempt.DynamicFee.GasTipCap, percentile, maxTipCap, fees.ErrConnectivity) } } return nil @@ -461,7 +460,7 @@ func calcFeeCap(latestAvailableBaseFeePerGas *assets.Wei, bufferBlocks int, tipC func (b *BlockHistoryEstimator) BumpDynamicFee(_ context.Context, originalFee DynamicFee, maxGasPriceWei *assets.Wei, attempts []EvmPriorAttempt) (bumped DynamicFee, err error) { if b.bhConfig.CheckInclusionBlocks() > 0 { if err = b.haltBumping(attempts); err != nil { - if errors.Is(err, commonfee.ErrConnectivity) { + if errors.Is(err, fees.ErrConnectivity) { b.logger.Criticalw(BumpingHaltedLabel, "err", err) b.SvcErrBuffer.Append(err) promBlockHistoryEstimatorConnectivityFailureCount.WithLabelValues(b.chainID.String(), "eip1559").Inc() diff --git a/core/chains/evm/gas/block_history_estimator_test.go b/core/chains/evm/gas/block_history_estimator_test.go index e3df261f2cf..d3cb058064e 100644 --- a/core/chains/evm/gas/block_history_estimator_test.go +++ b/core/chains/evm/gas/block_history_estimator_test.go @@ -18,9 +18,10 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - commonfee "github.com/smartcontractkit/chainlink/v2/common/fee" + "github.com/smartcontractkit/chainlink/v2/common/fees" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" @@ -2317,7 +2318,7 @@ func TestBlockHistoryEstimator_HaltBumping(t *testing.T) { err := bhe.HaltBumping(attempts) require.Error(t, err) assert.Contains(t, err.Error(), fmt.Sprintf("transaction %s has gas price of 7 wei, which is above percentile=40%% (percentile price: 5 wei)", attempts[2].TxHash)) - require.ErrorIs(t, err, commonfee.ErrConnectivity) + require.ErrorIs(t, err, fees.ErrConnectivity) }) }) @@ -2351,7 +2352,7 @@ func TestBlockHistoryEstimator_HaltBumping(t *testing.T) { err := bhe.HaltBumping(attempts) require.Error(t, err) assert.Contains(t, err.Error(), fmt.Sprintf("transaction %s has gas price of 10 wei, which is above percentile=60%% (percentile price: 7 wei)", attempts[1].TxHash)) - require.ErrorIs(t, err, commonfee.ErrConnectivity) + require.ErrorIs(t, err, fees.ErrConnectivity) }) attempts = []gas.EvmPriorAttempt{ @@ -2369,7 +2370,7 @@ func TestBlockHistoryEstimator_HaltBumping(t *testing.T) { err := bhe.HaltBumping(attempts) require.Error(t, err) 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)", attempts[0].TxHash)) - require.ErrorIs(t, err, commonfee.ErrConnectivity) + require.ErrorIs(t, err, fees.ErrConnectivity) }) }) @@ -2428,7 +2429,7 @@ func TestBlockHistoryEstimator_HaltBumping(t *testing.T) { err := bhe.HaltBumping(attempts) require.Error(t, err) assert.Contains(t, err.Error(), fmt.Sprintf("transaction %s has tip cap of 5 wei, which is above percentile=20%% (percentile tip cap: 4 wei)", attempts[1].TxHash)) - require.ErrorIs(t, err, commonfee.ErrConnectivity) + require.ErrorIs(t, err, fees.ErrConnectivity) bhCfg.CheckInclusionBlocksF = 3 bhCfg.CheckInclusionPercentileF = 2 @@ -2437,7 +2438,7 @@ func TestBlockHistoryEstimator_HaltBumping(t *testing.T) { err = bhe.HaltBumping(attempts) require.Error(t, err) assert.Contains(t, err.Error(), fmt.Sprintf("transaction %s has tip cap of 3 wei, which is above percentile=2%% (percentile tip cap: 2 wei)", attempts[0].TxHash)) - require.ErrorIs(t, err, commonfee.ErrConnectivity) + require.ErrorIs(t, err, fees.ErrConnectivity) }) t.Run("passes check if, for at least one block, feecap < tipcap+basefee, even if percentile is not reached", func(t *testing.T) { @@ -2499,7 +2500,7 @@ func TestBlockHistoryEstimator_Bumps(t *testing.T) { } _, _, err = bhe.BumpLegacyGas(ctx, assets.NewWeiI(42), 100000, maxGasPrice, attempts) require.Error(t, err) - assert.True(t, pkgerrors.Is(err, commonfee.ErrConnectivity)) + assert.True(t, pkgerrors.Is(err, fees.ErrConnectivity)) assert.Contains(t, err.Error(), fmt.Sprintf("transaction %s has gas price of 1 kwei, which is above percentile=10%% (percentile price: 1 wei)", attempts[0].TxHash)) }) @@ -2627,7 +2628,7 @@ func TestBlockHistoryEstimator_Bumps(t *testing.T) { _, err = bhe.BumpDynamicFee(tests.Context(t), originalFee, maxGasPrice, attempts) require.Error(t, err) - assert.True(t, pkgerrors.Is(err, commonfee.ErrConnectivity)) + assert.True(t, pkgerrors.Is(err, fees.ErrConnectivity)) assert.Contains(t, err.Error(), fmt.Sprintf("transaction %s has tip cap of 25 wei, which is above percentile=10%% (percentile tip cap: 1 wei)", attempts[0].TxHash)) }) diff --git a/core/chains/evm/gas/fee_history_estimator.go b/core/chains/evm/gas/fee_history_estimator.go index 211528a1a7d..1b3f1a38416 100644 --- a/core/chains/evm/gas/fee_history_estimator.go +++ b/core/chains/evm/gas/fee_history_estimator.go @@ -15,10 +15,9 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" bigmath "github.com/smartcontractkit/chainlink-common/pkg/utils/big_math" - commonclient "github.com/smartcontractkit/chainlink/v2/common/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" - commonfee "github.com/smartcontractkit/chainlink/v2/common/fee" - feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" + "github.com/smartcontractkit/chainlink/v2/common/fees" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" @@ -162,7 +161,7 @@ func (f *FeeHistoryEstimator) run() { } // GetLegacyGas will fetch the cached gas price value. -func (f *FeeHistoryEstimator) GetLegacyGas(ctx context.Context, _ []byte, gasLimit uint64, maxPrice *assets.Wei, opts ...feetypes.Opt) (gasPrice *assets.Wei, chainSpecificGasLimit uint64, err error) { +func (f *FeeHistoryEstimator) GetLegacyGas(ctx context.Context, _ []byte, gasLimit uint64, maxPrice *assets.Wei, opts ...fees.Opt) (gasPrice *assets.Wei, chainSpecificGasLimit uint64, err error) { chainSpecificGasLimit = gasLimit if gasPrice, err = f.getGasPrice(); err != nil { return @@ -177,7 +176,7 @@ func (f *FeeHistoryEstimator) GetLegacyGas(ctx context.Context, _ []byte, gasLim // RefreshGasPrice will use eth_gasPrice to fetch and cache the latest gas price from the RPC. func (f *FeeHistoryEstimator) RefreshGasPrice() (*assets.Wei, error) { - ctx, cancel := f.stopCh.CtxWithTimeout(commonclient.QueryTimeout) + ctx, cancel := f.stopCh.CtxWithTimeout(client.QueryTimeout) defer cancel() gasPrice, err := f.client.SuggestGasPrice(ctx) @@ -231,7 +230,7 @@ func (f *FeeHistoryEstimator) GetDynamicFee(ctx context.Context, maxPrice *asset // the highest percentile we're willing to pay. A buffer is added on top of the latest baseFee to catch fluctuations in the next // blocks. On Ethereum the increase is baseFee * 1.125 per block, however in some chains that may vary. func (f *FeeHistoryEstimator) RefreshDynamicPrice() error { - ctx, cancel := f.stopCh.CtxWithTimeout(commonclient.QueryTimeout) + ctx, cancel := f.stopCh.CtxWithTimeout(client.QueryTimeout) defer cancel() // RewardPercentile will be used for maxPriorityFeePerGas estimations and connectivityPercentile to set the highest threshold for bumping. @@ -315,7 +314,7 @@ func (f *FeeHistoryEstimator) BumpLegacyGas(ctx context.Context, originalGasPric // Sanitize original fee input if originalGasPrice == nil || originalGasPrice.Cmp(maxPrice) >= 0 { return nil, 0, fmt.Errorf("%w: error while retrieving original gas price: originalGasPrice: %s. Maximum price configured: %s", - commonfee.ErrBump, originalGasPrice, maxPrice) + fees.ErrBump, originalGasPrice, maxPrice) } currentGasPrice, err := f.RefreshGasPrice() @@ -364,7 +363,7 @@ func (f *FeeHistoryEstimator) BumpDynamicFee(ctx context.Context, originalFee Dy ((originalFee.GasTipCap.Cmp(originalFee.GasFeeCap)) > 0) || (originalFee.GasFeeCap.Cmp(maxPrice) >= 0) { return bumped, fmt.Errorf("%w: error while retrieving original dynamic fees: (originalFeePerGas: %s - originalPriorityFeePerGas: %s). Maximum price configured: %s", - commonfee.ErrBump, originalFee.GasFeeCap, originalFee.GasTipCap, maxPrice) + fees.ErrBump, originalFee.GasFeeCap, originalFee.GasTipCap, maxPrice) } currentDynamicPrice, err := f.getDynamicPrice() @@ -387,7 +386,7 @@ func (f *FeeHistoryEstimator) BumpDynamicFee(ctx context.Context, originalFee Dy if bumpedMaxPriorityFeePerGas.Cmp(priorityFeeThreshold) > 0 { return bumped, fmt.Errorf("%w: bumpedMaxPriorityFeePerGas: %s is above market's %sth percentile: %s, bumping is halted", - commonfee.ErrConnectivity, bumpedMaxPriorityFeePerGas, strconv.Itoa(ConnectivityPercentile), priorityFeeThreshold) + fees.ErrConnectivity, bumpedMaxPriorityFeePerGas, strconv.Itoa(ConnectivityPercentile), priorityFeeThreshold) } bumpedMaxFeePerGas, err = LimitBumpedFee(originalFee.GasFeeCap, currentDynamicPrice.GasFeeCap, bumpedMaxFeePerGas, maxPrice) @@ -421,7 +420,7 @@ func LimitBumpedFee(originalFee *assets.Wei, currentFee *assets.Wei, bumpedFee * if bumpedFee.Cmp(originalFee) == 0 || bumpedFee.Cmp(originalFee.AddPercentage(MinimumBumpPercentage)) < 0 { return nil, fmt.Errorf("%w: %s is bumped less than minimum allowed percentage(%s) from originalFee: %s - maxPrice: %s", - commonfee.ErrBump, bumpedFee, strconv.Itoa(MinimumBumpPercentage), originalFee, maxPrice) + fees.ErrBump, bumpedFee, strconv.Itoa(MinimumBumpPercentage), originalFee, maxPrice) } return bumpedFee, nil } diff --git a/core/chains/evm/gas/fee_history_estimator_test.go b/core/chains/evm/gas/fee_history_estimator_test.go index 7d66b9375d7..e537538460f 100644 --- a/core/chains/evm/gas/fee_history_estimator_test.go +++ b/core/chains/evm/gas/fee_history_estimator_test.go @@ -12,8 +12,8 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink/v2/common/fee" + "github.com/smartcontractkit/chainlink/v2/common/fees" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks" @@ -412,7 +412,7 @@ func TestFeeHistoryEstimatorBumpDynamicFee(t *testing.T) { assert.NoError(t, err) _, err = u.BumpDynamicFee(tests.Context(t), originalFee, globalMaxPrice, nil) assert.Error(t, err) - assert.True(t, fee.IsBumpErr(err)) + assert.True(t, fees.IsBumpErr(err)) }) t.Run("returns max price if the aggregation of max and original bumped fee is higher", 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 43398ef4b19..e744cb8cb5f 100644 --- a/core/chains/evm/gas/fixed_price_estimator.go +++ b/core/chains/evm/gas/fixed_price_estimator.go @@ -6,8 +6,7 @@ import ( pkgerrors "github.com/pkg/errors" "github.com/smartcontractkit/chainlink-common/pkg/logger" - commonfee "github.com/smartcontractkit/chainlink/v2/common/fee" - feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" + "github.com/smartcontractkit/chainlink/v2/common/fees" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" @@ -59,8 +58,8 @@ func (f *fixedPriceEstimator) Start(context.Context) error { return nil } -func (f *fixedPriceEstimator) GetLegacyGas(_ context.Context, _ []byte, gasLimit uint64, maxGasPriceWei *assets.Wei, _ ...feetypes.Opt) (*assets.Wei, uint64, error) { - gasPrice := commonfee.CalculateFee(f.config.PriceDefault().ToInt(), maxGasPriceWei.ToInt(), f.config.PriceMax().ToInt()) +func (f *fixedPriceEstimator) GetLegacyGas(_ context.Context, _ []byte, gasLimit uint64, maxGasPriceWei *assets.Wei, _ ...fees.Opt) (*assets.Wei, uint64, error) { + gasPrice := fees.CalculateFee(f.config.PriceDefault().ToInt(), maxGasPriceWei.ToInt(), f.config.PriceMax().ToInt()) chainSpecificGasLimit := gasLimit return assets.NewWei(gasPrice), chainSpecificGasLimit, nil } @@ -72,7 +71,7 @@ func (f *fixedPriceEstimator) BumpLegacyGas( maxGasPriceWei *assets.Wei, _ []EvmPriorAttempt, ) (*assets.Wei, uint64, error) { - gasPrice, err := commonfee.CalculateBumpedFee( + gasPrice, err := fees.CalculateBumpedFee( f.lggr, f.config.PriceDefault().ToInt(), originalGasPrice.ToInt(), diff --git a/core/chains/evm/gas/mocks/evm_estimator.go b/core/chains/evm/gas/mocks/evm_estimator.go index 159adb1a037..b0396c656f2 100644 --- a/core/chains/evm/gas/mocks/evm_estimator.go +++ b/core/chains/evm/gas/mocks/evm_estimator.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -7,7 +7,7 @@ import ( assets "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + fees "github.com/smartcontractkit/chainlink/v2/common/fees" gas "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" @@ -15,7 +15,7 @@ import ( rollups "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups" - types "github.com/smartcontractkit/chainlink/v2/common/fee/types" + types "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) // EvmEstimator is an autogenerated mock type for the EvmEstimator type @@ -159,7 +159,7 @@ func (_c *EvmEstimator_BumpLegacyGas_Call) RunAndReturn(run func(context.Context return _c } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *EvmEstimator) Close() error { ret := _m.Called() @@ -262,7 +262,7 @@ func (_c *EvmEstimator_GetDynamicFee_Call) RunAndReturn(run func(context.Context } // GetLegacyGas provides a mock function with given fields: ctx, calldata, gasLimit, maxGasPriceWei, opts -func (_m *EvmEstimator) GetLegacyGas(ctx context.Context, calldata []byte, gasLimit uint64, maxGasPriceWei *assets.Wei, opts ...types.Opt) (*assets.Wei, uint64, error) { +func (_m *EvmEstimator) GetLegacyGas(ctx context.Context, calldata []byte, gasLimit uint64, maxGasPriceWei *assets.Wei, opts ...fees.Opt) (*assets.Wei, uint64, error) { _va := make([]interface{}, len(opts)) for _i := range opts { _va[_i] = opts[_i] @@ -279,10 +279,10 @@ func (_m *EvmEstimator) GetLegacyGas(ctx context.Context, calldata []byte, gasLi var r0 *assets.Wei var r1 uint64 var r2 error - if rf, ok := ret.Get(0).(func(context.Context, []byte, uint64, *assets.Wei, ...types.Opt) (*assets.Wei, uint64, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, []byte, uint64, *assets.Wei, ...fees.Opt) (*assets.Wei, uint64, error)); ok { return rf(ctx, calldata, gasLimit, maxGasPriceWei, opts...) } - if rf, ok := ret.Get(0).(func(context.Context, []byte, uint64, *assets.Wei, ...types.Opt) *assets.Wei); ok { + if rf, ok := ret.Get(0).(func(context.Context, []byte, uint64, *assets.Wei, ...fees.Opt) *assets.Wei); ok { r0 = rf(ctx, calldata, gasLimit, maxGasPriceWei, opts...) } else { if ret.Get(0) != nil { @@ -290,13 +290,13 @@ func (_m *EvmEstimator) GetLegacyGas(ctx context.Context, calldata []byte, gasLi } } - if rf, ok := ret.Get(1).(func(context.Context, []byte, uint64, *assets.Wei, ...types.Opt) uint64); ok { + if rf, ok := ret.Get(1).(func(context.Context, []byte, uint64, *assets.Wei, ...fees.Opt) uint64); ok { r1 = rf(ctx, calldata, gasLimit, maxGasPriceWei, opts...) } else { r1 = ret.Get(1).(uint64) } - if rf, ok := ret.Get(2).(func(context.Context, []byte, uint64, *assets.Wei, ...types.Opt) error); ok { + if rf, ok := ret.Get(2).(func(context.Context, []byte, uint64, *assets.Wei, ...fees.Opt) error); ok { r2 = rf(ctx, calldata, gasLimit, maxGasPriceWei, opts...) } else { r2 = ret.Error(2) @@ -315,18 +315,18 @@ type EvmEstimator_GetLegacyGas_Call struct { // - calldata []byte // - gasLimit uint64 // - maxGasPriceWei *assets.Wei -// - opts ...types.Opt +// - opts ...fees.Opt func (_e *EvmEstimator_Expecter) GetLegacyGas(ctx interface{}, calldata interface{}, gasLimit interface{}, maxGasPriceWei interface{}, opts ...interface{}) *EvmEstimator_GetLegacyGas_Call { return &EvmEstimator_GetLegacyGas_Call{Call: _e.mock.On("GetLegacyGas", append([]interface{}{ctx, calldata, gasLimit, maxGasPriceWei}, opts...)...)} } -func (_c *EvmEstimator_GetLegacyGas_Call) Run(run func(ctx context.Context, calldata []byte, gasLimit uint64, maxGasPriceWei *assets.Wei, opts ...types.Opt)) *EvmEstimator_GetLegacyGas_Call { +func (_c *EvmEstimator_GetLegacyGas_Call) Run(run func(ctx context.Context, calldata []byte, gasLimit uint64, maxGasPriceWei *assets.Wei, opts ...fees.Opt)) *EvmEstimator_GetLegacyGas_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]types.Opt, len(args)-4) + variadicArgs := make([]fees.Opt, len(args)-4) for i, a := range args[4:] { if a != nil { - variadicArgs[i] = a.(types.Opt) + variadicArgs[i] = a.(fees.Opt) } } run(args[0].(context.Context), args[1].([]byte), args[2].(uint64), args[3].(*assets.Wei), variadicArgs...) @@ -339,12 +339,12 @@ func (_c *EvmEstimator_GetLegacyGas_Call) Return(gasPrice *assets.Wei, chainSpec return _c } -func (_c *EvmEstimator_GetLegacyGas_Call) RunAndReturn(run func(context.Context, []byte, uint64, *assets.Wei, ...types.Opt) (*assets.Wei, uint64, error)) *EvmEstimator_GetLegacyGas_Call { +func (_c *EvmEstimator_GetLegacyGas_Call) RunAndReturn(run func(context.Context, []byte, uint64, *assets.Wei, ...fees.Opt) (*assets.Wei, uint64, error)) *EvmEstimator_GetLegacyGas_Call { _c.Call.Return(run) return _c } -// HealthReport provides a mock function with given fields: +// HealthReport provides a mock function with no fields func (_m *EvmEstimator) HealthReport() map[string]error { ret := _m.Called() @@ -391,7 +391,7 @@ func (_c *EvmEstimator_HealthReport_Call) RunAndReturn(run func() map[string]err return _c } -// L1Oracle provides a mock function with given fields: +// L1Oracle provides a mock function with no fields func (_m *EvmEstimator) L1Oracle() rollups.L1Oracle { ret := _m.Called() @@ -438,7 +438,7 @@ func (_c *EvmEstimator_L1Oracle_Call) RunAndReturn(run func() rollups.L1Oracle) return _c } -// Name provides a mock function with given fields: +// Name provides a mock function with no fields func (_m *EvmEstimator) Name() string { ret := _m.Called() @@ -484,7 +484,7 @@ func (_c *EvmEstimator_Name_Call) RunAndReturn(run func() string) *EvmEstimator_ } // OnNewLongestChain provides a mock function with given fields: ctx, head -func (_m *EvmEstimator) OnNewLongestChain(ctx context.Context, head *evmtypes.Head) { +func (_m *EvmEstimator) OnNewLongestChain(ctx context.Context, head *types.Head) { _m.Called(ctx, head) } @@ -495,14 +495,14 @@ type EvmEstimator_OnNewLongestChain_Call struct { // OnNewLongestChain is a helper method to define mock.On call // - ctx context.Context -// - head *evmtypes.Head +// - head *types.Head func (_e *EvmEstimator_Expecter) OnNewLongestChain(ctx interface{}, head interface{}) *EvmEstimator_OnNewLongestChain_Call { return &EvmEstimator_OnNewLongestChain_Call{Call: _e.mock.On("OnNewLongestChain", ctx, head)} } -func (_c *EvmEstimator_OnNewLongestChain_Call) Run(run func(ctx context.Context, head *evmtypes.Head)) *EvmEstimator_OnNewLongestChain_Call { +func (_c *EvmEstimator_OnNewLongestChain_Call) Run(run func(ctx context.Context, head *types.Head)) *EvmEstimator_OnNewLongestChain_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*evmtypes.Head)) + run(args[0].(context.Context), args[1].(*types.Head)) }) return _c } @@ -512,12 +512,12 @@ func (_c *EvmEstimator_OnNewLongestChain_Call) Return() *EvmEstimator_OnNewLonge return _c } -func (_c *EvmEstimator_OnNewLongestChain_Call) RunAndReturn(run func(context.Context, *evmtypes.Head)) *EvmEstimator_OnNewLongestChain_Call { - _c.Call.Return(run) +func (_c *EvmEstimator_OnNewLongestChain_Call) RunAndReturn(run func(context.Context, *types.Head)) *EvmEstimator_OnNewLongestChain_Call { + _c.Run(run) return _c } -// Ready provides a mock function with given fields: +// Ready provides a mock function with no fields func (_m *EvmEstimator) Ready() error { ret := _m.Called() diff --git a/core/chains/evm/gas/mocks/evm_fee_estimator.go b/core/chains/evm/gas/mocks/evm_fee_estimator.go index d0802f81ebd..1de0eb09ffa 100644 --- a/core/chains/evm/gas/mocks/evm_fee_estimator.go +++ b/core/chains/evm/gas/mocks/evm_fee_estimator.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -11,7 +11,7 @@ import ( context "context" - evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + fees "github.com/smartcontractkit/chainlink/v2/common/fees" gas "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" @@ -19,7 +19,7 @@ import ( rollups "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups" - types "github.com/smartcontractkit/chainlink/v2/common/fee/types" + types "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) // EvmFeeEstimator is an autogenerated mock type for the EvmFeeEstimator type @@ -102,7 +102,7 @@ func (_c *EvmFeeEstimator_BumpFee_Call) RunAndReturn(run func(context.Context, g return _c } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *EvmFeeEstimator) Close() error { ret := _m.Called() @@ -148,7 +148,7 @@ func (_c *EvmFeeEstimator_Close_Call) RunAndReturn(run func() error) *EvmFeeEsti } // GetFee provides a mock function with given fields: ctx, calldata, feeLimit, maxFeePrice, fromAddress, toAddress, opts -func (_m *EvmFeeEstimator) GetFee(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, fromAddress *common.Address, toAddress *common.Address, opts ...types.Opt) (gas.EvmFee, uint64, error) { +func (_m *EvmFeeEstimator) GetFee(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, fromAddress *common.Address, toAddress *common.Address, opts ...fees.Opt) (gas.EvmFee, uint64, error) { _va := make([]interface{}, len(opts)) for _i := range opts { _va[_i] = opts[_i] @@ -165,22 +165,22 @@ func (_m *EvmFeeEstimator) GetFee(ctx context.Context, calldata []byte, feeLimit var r0 gas.EvmFee var r1 uint64 var r2 error - if rf, ok := ret.Get(0).(func(context.Context, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...types.Opt) (gas.EvmFee, uint64, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...fees.Opt) (gas.EvmFee, uint64, error)); ok { return rf(ctx, calldata, feeLimit, maxFeePrice, fromAddress, toAddress, opts...) } - if rf, ok := ret.Get(0).(func(context.Context, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...types.Opt) gas.EvmFee); ok { + if rf, ok := ret.Get(0).(func(context.Context, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...fees.Opt) gas.EvmFee); ok { r0 = rf(ctx, calldata, feeLimit, maxFeePrice, fromAddress, toAddress, opts...) } else { r0 = ret.Get(0).(gas.EvmFee) } - if rf, ok := ret.Get(1).(func(context.Context, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...types.Opt) uint64); ok { + if rf, ok := ret.Get(1).(func(context.Context, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...fees.Opt) uint64); ok { r1 = rf(ctx, calldata, feeLimit, maxFeePrice, fromAddress, toAddress, opts...) } else { r1 = ret.Get(1).(uint64) } - if rf, ok := ret.Get(2).(func(context.Context, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...types.Opt) error); ok { + if rf, ok := ret.Get(2).(func(context.Context, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...fees.Opt) error); ok { r2 = rf(ctx, calldata, feeLimit, maxFeePrice, fromAddress, toAddress, opts...) } else { r2 = ret.Error(2) @@ -201,18 +201,18 @@ type EvmFeeEstimator_GetFee_Call struct { // - maxFeePrice *assets.Wei // - fromAddress *common.Address // - toAddress *common.Address -// - opts ...types.Opt +// - opts ...fees.Opt func (_e *EvmFeeEstimator_Expecter) GetFee(ctx interface{}, calldata interface{}, feeLimit interface{}, maxFeePrice interface{}, fromAddress interface{}, toAddress interface{}, opts ...interface{}) *EvmFeeEstimator_GetFee_Call { return &EvmFeeEstimator_GetFee_Call{Call: _e.mock.On("GetFee", append([]interface{}{ctx, calldata, feeLimit, maxFeePrice, fromAddress, toAddress}, opts...)...)} } -func (_c *EvmFeeEstimator_GetFee_Call) Run(run func(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, fromAddress *common.Address, toAddress *common.Address, opts ...types.Opt)) *EvmFeeEstimator_GetFee_Call { +func (_c *EvmFeeEstimator_GetFee_Call) Run(run func(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, fromAddress *common.Address, toAddress *common.Address, opts ...fees.Opt)) *EvmFeeEstimator_GetFee_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]types.Opt, len(args)-6) + variadicArgs := make([]fees.Opt, len(args)-6) for i, a := range args[6:] { if a != nil { - variadicArgs[i] = a.(types.Opt) + variadicArgs[i] = a.(fees.Opt) } } run(args[0].(context.Context), args[1].([]byte), args[2].(uint64), args[3].(*assets.Wei), args[4].(*common.Address), args[5].(*common.Address), variadicArgs...) @@ -225,13 +225,13 @@ func (_c *EvmFeeEstimator_GetFee_Call) Return(fee gas.EvmFee, estimatedFeeLimit return _c } -func (_c *EvmFeeEstimator_GetFee_Call) RunAndReturn(run func(context.Context, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...types.Opt) (gas.EvmFee, uint64, error)) *EvmFeeEstimator_GetFee_Call { +func (_c *EvmFeeEstimator_GetFee_Call) RunAndReturn(run func(context.Context, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...fees.Opt) (gas.EvmFee, uint64, error)) *EvmFeeEstimator_GetFee_Call { _c.Call.Return(run) return _c } // GetMaxCost provides a mock function with given fields: ctx, amount, calldata, feeLimit, maxFeePrice, fromAddress, toAddress, opts -func (_m *EvmFeeEstimator) GetMaxCost(ctx context.Context, amount assets.Eth, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, fromAddress *common.Address, toAddress *common.Address, opts ...types.Opt) (*big.Int, error) { +func (_m *EvmFeeEstimator) GetMaxCost(ctx context.Context, amount assets.Eth, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, fromAddress *common.Address, toAddress *common.Address, opts ...fees.Opt) (*big.Int, error) { _va := make([]interface{}, len(opts)) for _i := range opts { _va[_i] = opts[_i] @@ -247,10 +247,10 @@ func (_m *EvmFeeEstimator) GetMaxCost(ctx context.Context, amount assets.Eth, ca var r0 *big.Int var r1 error - if rf, ok := ret.Get(0).(func(context.Context, assets.Eth, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...types.Opt) (*big.Int, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, assets.Eth, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...fees.Opt) (*big.Int, error)); ok { return rf(ctx, amount, calldata, feeLimit, maxFeePrice, fromAddress, toAddress, opts...) } - if rf, ok := ret.Get(0).(func(context.Context, assets.Eth, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...types.Opt) *big.Int); ok { + if rf, ok := ret.Get(0).(func(context.Context, assets.Eth, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...fees.Opt) *big.Int); ok { r0 = rf(ctx, amount, calldata, feeLimit, maxFeePrice, fromAddress, toAddress, opts...) } else { if ret.Get(0) != nil { @@ -258,7 +258,7 @@ func (_m *EvmFeeEstimator) GetMaxCost(ctx context.Context, amount assets.Eth, ca } } - if rf, ok := ret.Get(1).(func(context.Context, assets.Eth, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...types.Opt) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, assets.Eth, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...fees.Opt) error); ok { r1 = rf(ctx, amount, calldata, feeLimit, maxFeePrice, fromAddress, toAddress, opts...) } else { r1 = ret.Error(1) @@ -280,18 +280,18 @@ type EvmFeeEstimator_GetMaxCost_Call struct { // - maxFeePrice *assets.Wei // - fromAddress *common.Address // - toAddress *common.Address -// - opts ...types.Opt +// - opts ...fees.Opt func (_e *EvmFeeEstimator_Expecter) GetMaxCost(ctx interface{}, amount interface{}, calldata interface{}, feeLimit interface{}, maxFeePrice interface{}, fromAddress interface{}, toAddress interface{}, opts ...interface{}) *EvmFeeEstimator_GetMaxCost_Call { return &EvmFeeEstimator_GetMaxCost_Call{Call: _e.mock.On("GetMaxCost", append([]interface{}{ctx, amount, calldata, feeLimit, maxFeePrice, fromAddress, toAddress}, opts...)...)} } -func (_c *EvmFeeEstimator_GetMaxCost_Call) Run(run func(ctx context.Context, amount assets.Eth, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, fromAddress *common.Address, toAddress *common.Address, opts ...types.Opt)) *EvmFeeEstimator_GetMaxCost_Call { +func (_c *EvmFeeEstimator_GetMaxCost_Call) Run(run func(ctx context.Context, amount assets.Eth, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, fromAddress *common.Address, toAddress *common.Address, opts ...fees.Opt)) *EvmFeeEstimator_GetMaxCost_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]types.Opt, len(args)-7) + variadicArgs := make([]fees.Opt, len(args)-7) for i, a := range args[7:] { if a != nil { - variadicArgs[i] = a.(types.Opt) + variadicArgs[i] = a.(fees.Opt) } } run(args[0].(context.Context), args[1].(assets.Eth), args[2].([]byte), args[3].(uint64), args[4].(*assets.Wei), args[5].(*common.Address), args[6].(*common.Address), variadicArgs...) @@ -304,12 +304,12 @@ func (_c *EvmFeeEstimator_GetMaxCost_Call) Return(_a0 *big.Int, _a1 error) *EvmF return _c } -func (_c *EvmFeeEstimator_GetMaxCost_Call) RunAndReturn(run func(context.Context, assets.Eth, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...types.Opt) (*big.Int, error)) *EvmFeeEstimator_GetMaxCost_Call { +func (_c *EvmFeeEstimator_GetMaxCost_Call) RunAndReturn(run func(context.Context, assets.Eth, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...fees.Opt) (*big.Int, error)) *EvmFeeEstimator_GetMaxCost_Call { _c.Call.Return(run) return _c } -// HealthReport provides a mock function with given fields: +// HealthReport provides a mock function with no fields func (_m *EvmFeeEstimator) HealthReport() map[string]error { ret := _m.Called() @@ -356,7 +356,7 @@ func (_c *EvmFeeEstimator_HealthReport_Call) RunAndReturn(run func() map[string] return _c } -// L1Oracle provides a mock function with given fields: +// L1Oracle provides a mock function with no fields func (_m *EvmFeeEstimator) L1Oracle() rollups.L1Oracle { ret := _m.Called() @@ -403,7 +403,7 @@ func (_c *EvmFeeEstimator_L1Oracle_Call) RunAndReturn(run func() rollups.L1Oracl return _c } -// Name provides a mock function with given fields: +// Name provides a mock function with no fields func (_m *EvmFeeEstimator) Name() string { ret := _m.Called() @@ -449,7 +449,7 @@ func (_c *EvmFeeEstimator_Name_Call) RunAndReturn(run func() string) *EvmFeeEsti } // OnNewLongestChain provides a mock function with given fields: ctx, head -func (_m *EvmFeeEstimator) OnNewLongestChain(ctx context.Context, head *evmtypes.Head) { +func (_m *EvmFeeEstimator) OnNewLongestChain(ctx context.Context, head *types.Head) { _m.Called(ctx, head) } @@ -460,14 +460,14 @@ type EvmFeeEstimator_OnNewLongestChain_Call struct { // OnNewLongestChain is a helper method to define mock.On call // - ctx context.Context -// - head *evmtypes.Head +// - head *types.Head func (_e *EvmFeeEstimator_Expecter) OnNewLongestChain(ctx interface{}, head interface{}) *EvmFeeEstimator_OnNewLongestChain_Call { return &EvmFeeEstimator_OnNewLongestChain_Call{Call: _e.mock.On("OnNewLongestChain", ctx, head)} } -func (_c *EvmFeeEstimator_OnNewLongestChain_Call) Run(run func(ctx context.Context, head *evmtypes.Head)) *EvmFeeEstimator_OnNewLongestChain_Call { +func (_c *EvmFeeEstimator_OnNewLongestChain_Call) Run(run func(ctx context.Context, head *types.Head)) *EvmFeeEstimator_OnNewLongestChain_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*evmtypes.Head)) + run(args[0].(context.Context), args[1].(*types.Head)) }) return _c } @@ -477,12 +477,12 @@ func (_c *EvmFeeEstimator_OnNewLongestChain_Call) Return() *EvmFeeEstimator_OnNe return _c } -func (_c *EvmFeeEstimator_OnNewLongestChain_Call) RunAndReturn(run func(context.Context, *evmtypes.Head)) *EvmFeeEstimator_OnNewLongestChain_Call { - _c.Call.Return(run) +func (_c *EvmFeeEstimator_OnNewLongestChain_Call) RunAndReturn(run func(context.Context, *types.Head)) *EvmFeeEstimator_OnNewLongestChain_Call { + _c.Run(run) return _c } -// Ready provides a mock function with given fields: +// Ready provides a mock function with no fields func (_m *EvmFeeEstimator) Ready() error { ret := _m.Called() diff --git a/core/chains/evm/gas/mocks/fee_estimator_client.go b/core/chains/evm/gas/mocks/fee_estimator_client.go index 782c897923b..e44c4f9d029 100644 --- a/core/chains/evm/gas/mocks/fee_estimator_client.go +++ b/core/chains/evm/gas/mocks/fee_estimator_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/chains/evm/gas/mocks/fee_history_estimator_client.go b/core/chains/evm/gas/mocks/fee_history_estimator_client.go index 24ad7e23ad9..19cadd700e8 100644 --- a/core/chains/evm/gas/mocks/fee_history_estimator_client.go +++ b/core/chains/evm/gas/mocks/fee_history_estimator_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/chains/evm/gas/models.go b/core/chains/evm/gas/models.go index 2d6fe971d9c..d71dcea680e 100644 --- a/core/chains/evm/gas/models.go +++ b/core/chains/evm/gas/models.go @@ -14,8 +14,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services" bigmath "github.com/smartcontractkit/chainlink-common/pkg/utils/big_math" - commonfee "github.com/smartcontractkit/chainlink/v2/common/fee" - feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" + "github.com/smartcontractkit/chainlink/v2/common/fees" "github.com/smartcontractkit/chainlink/v2/common/headtracker" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" @@ -35,11 +34,11 @@ type EvmFeeEstimator interface { // L1Oracle returns the L1 gas price oracle only if the chain has one, e.g. OP stack L2s and Arbitrum. L1Oracle() rollups.L1Oracle - GetFee(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, fromAddress, toAddress *common.Address, opts ...feetypes.Opt) (fee EvmFee, estimatedFeeLimit uint64, err error) + GetFee(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, fromAddress, toAddress *common.Address, opts ...fees.Opt) (fee EvmFee, estimatedFeeLimit uint64, err error) BumpFee(ctx context.Context, originalFee EvmFee, feeLimit uint64, maxFeePrice *assets.Wei, attempts []EvmPriorAttempt) (bumpedFee EvmFee, chainSpecificFeeLimit uint64, err error) // GetMaxCost returns the total value = max price x fee units + transferred value - GetMaxCost(ctx context.Context, amount assets.Eth, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, fromAddress, toAddress *common.Address, opts ...feetypes.Opt) (*big.Int, error) + GetMaxCost(ctx context.Context, amount assets.Eth, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, fromAddress, toAddress *common.Address, opts ...fees.Opt) (*big.Int, error) } type feeEstimatorClient interface { @@ -151,7 +150,7 @@ type EvmEstimator interface { // GetLegacyGas Calculates initial gas fee for non-EIP1559 transaction // maxGasPriceWei parameter is the highest possible gas fee cap that the function will return - GetLegacyGas(ctx context.Context, calldata []byte, gasLimit uint64, maxGasPriceWei *assets.Wei, opts ...feetypes.Opt) (gasPrice *assets.Wei, chainSpecificGasLimit uint64, err error) + GetLegacyGas(ctx context.Context, calldata []byte, gasLimit uint64, maxGasPriceWei *assets.Wei, opts ...fees.Opt) (gasPrice *assets.Wei, chainSpecificGasLimit uint64, err error) // BumpLegacyGas Increases gas price and/or limit for non-EIP1559 transactions // if the bumped gas fee is greater than maxGasPriceWei, the method returns an error // attempts must: @@ -171,7 +170,7 @@ type EvmEstimator interface { L1Oracle() rollups.L1Oracle } -var _ feetypes.Fee = (*EvmFee)(nil) +var _ fees.Fee = (*EvmFee)(nil) type EvmFee struct { GasPrice *assets.Wei @@ -277,7 +276,7 @@ func (e *evmFeeEstimator) L1Oracle() rollups.L1Oracle { // GetFee returns an initial estimated gas price and gas limit for a transaction // The gas limit provided by the caller can be adjusted by gas estimation or for 2D fees -func (e *evmFeeEstimator) GetFee(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, fromAddress, toAddress *common.Address, opts ...feetypes.Opt) (fee EvmFee, estimatedFeeLimit uint64, err error) { +func (e *evmFeeEstimator) GetFee(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, fromAddress, toAddress *common.Address, opts ...fees.Opt) (fee EvmFee, estimatedFeeLimit uint64, err error) { var chainSpecificFeeLimit uint64 // get dynamic fee if e.EIP1559Enabled { @@ -301,7 +300,7 @@ func (e *evmFeeEstimator) GetFee(ctx context.Context, calldata []byte, feeLimit return } -func (e *evmFeeEstimator) GetMaxCost(ctx context.Context, amount assets.Eth, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, fromAddress, toAddress *common.Address, opts ...feetypes.Opt) (*big.Int, error) { +func (e *evmFeeEstimator) GetMaxCost(ctx context.Context, amount assets.Eth, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, fromAddress, toAddress *common.Address, opts ...fees.Opt) (*big.Int, error) { fees, gasLimit, err := e.GetFee(ctx, calldata, feeLimit, maxFeePrice, fromAddress, toAddress, opts...) if err != nil { return nil, err @@ -338,7 +337,7 @@ func (e *evmFeeEstimator) BumpFee(ctx context.Context, originalFee EvmFee, feeLi if err != nil { return } - chainSpecificFeeLimit, err = commonfee.ApplyMultiplier(feeLimit, e.geCfg.LimitMultiplier()) + chainSpecificFeeLimit, err = fees.ApplyMultiplier(feeLimit, e.geCfg.LimitMultiplier()) bumpedFee.GasFeeCap = bumpedDynamic.GasFeeCap bumpedFee.GasTipCap = bumpedDynamic.GasTipCap return @@ -349,13 +348,13 @@ func (e *evmFeeEstimator) BumpFee(ctx context.Context, originalFee EvmFee, feeLi if err != nil { return } - chainSpecificFeeLimit, err = commonfee.ApplyMultiplier(chainSpecificFeeLimit, e.geCfg.LimitMultiplier()) + chainSpecificFeeLimit, err = fees.ApplyMultiplier(chainSpecificFeeLimit, e.geCfg.LimitMultiplier()) return } func (e *evmFeeEstimator) estimateFeeLimit(ctx context.Context, feeLimit uint64, calldata []byte, fromAddress, toAddress *common.Address) (estimatedFeeLimit uint64, err error) { // Use the feeLimit * LimitMultiplier as the provided gas limit since this multiplier is applied on top of the caller specified gas limit - providedGasLimit, err := commonfee.ApplyMultiplier(feeLimit, e.geCfg.LimitMultiplier()) + providedGasLimit, err := fees.ApplyMultiplier(feeLimit, e.geCfg.LimitMultiplier()) if err != nil { return estimatedFeeLimit, err } @@ -386,10 +385,10 @@ func (e *evmFeeEstimator) estimateFeeLimit(ctx context.Context, feeLimit uint64, // Transaction would be destined to run out of gas and fail if providedGasLimit > 0 && estimatedGas > providedGasLimit { e.lggr.Errorw("estimated gas exceeds provided gas limit with multiplier", "estimatedGas", estimatedGas, "providedGasLimitWithMultiplier", providedGasLimit) - return estimatedFeeLimit, commonfee.ErrFeeLimitTooLow + return estimatedFeeLimit, fees.ErrFeeLimitTooLow } // Apply EstimateGasBuffer to the estimated gas limit - estimatedFeeLimit, err = commonfee.ApplyMultiplier(estimatedGas, EstimateGasBuffer) + estimatedFeeLimit, err = fees.ApplyMultiplier(estimatedGas, EstimateGasBuffer) if err != nil { return } @@ -441,13 +440,13 @@ func bumpGasPrice(cfg bumpConfig, lggr logger.SugaredLogger, currentGasPrice, or bumpedGasPrice = maxBumpedFee(lggr, currentGasPrice, bumpedGasPrice, maxGasPrice, "gas price") if bumpedGasPrice.Cmp(maxGasPrice) > 0 { - return maxGasPrice, pkgerrors.Wrapf(commonfee.ErrBumpFeeExceedsLimit, "bumped gas price of %s would exceed configured max gas price of %s (original price was %s). %s", + return maxGasPrice, pkgerrors.Wrapf(fees.ErrBumpFeeExceedsLimit, "bumped gas price of %s would exceed configured max gas price of %s (original price was %s). %s", bumpedGasPrice.String(), maxGasPrice, originalGasPrice.String(), label.NodeConnectivityProblemWarning) } else if bumpedGasPrice.Cmp(originalGasPrice) == 0 { // NOTE: This really shouldn't happen since we enforce minimums for // EVM.GasEstimator.BumpPercent and EVM.GasEstimator.BumpMin in the config validation, // but it's here anyway for a "belts and braces" approach - return bumpedGasPrice, pkgerrors.Wrapf(commonfee.ErrBump, "bumped gas price of %s is equal to original gas price of %s."+ + return bumpedGasPrice, pkgerrors.Wrapf(fees.ErrBump, "bumped gas price of %s is equal to original gas price of %s."+ " ACTION REQUIRED: This is a configuration error, you must increase either "+ "EVM.GasEstimator.BumpPercent or EVM.GasEstimator.BumpMin", bumpedGasPrice.String(), originalGasPrice.String()) } @@ -482,13 +481,13 @@ func bumpDynamicFee(cfg bumpConfig, feeCapBufferBlocks uint16, lggr logger.Sugar bumpedTipCap = maxBumpedFee(lggr, currentTipCap, bumpedTipCap, maxGasPrice, "tip cap") if bumpedTipCap.Cmp(maxGasPrice) > 0 { - return bumpedFee, pkgerrors.Wrapf(commonfee.ErrBumpFeeExceedsLimit, "bumped tip cap of %s would exceed configured max gas price of %s (original fee: tip cap %s, fee cap %s). %s", + return bumpedFee, pkgerrors.Wrapf(fees.ErrBumpFeeExceedsLimit, "bumped tip cap of %s would exceed configured max gas price of %s (original fee: tip cap %s, fee cap %s). %s", bumpedTipCap.String(), maxGasPrice, originalFee.GasTipCap.String(), originalFee.GasFeeCap.String(), label.NodeConnectivityProblemWarning) } else if bumpedTipCap.Cmp(originalFee.GasTipCap) <= 0 { // NOTE: This really shouldn't happen since we enforce minimums for // EVM.GasEstimator.BumpPercent and EVM.GasEstimator.BumpMin in the config validation, // but it's here anyway for a "belts and braces" approach - return bumpedFee, pkgerrors.Wrapf(commonfee.ErrBump, "bumped gas tip cap of %s is less than or equal to original gas tip cap of %s."+ + return bumpedFee, pkgerrors.Wrapf(fees.ErrBump, "bumped gas tip cap of %s is less than or equal to original gas tip cap of %s."+ " ACTION REQUIRED: This is a configuration error, you must increase either "+ "EVM.GasEstimator.BumpPercent or EVM.GasEstimator.BumpMin", bumpedTipCap.String(), originalFee.GasTipCap.String()) } @@ -508,7 +507,7 @@ func bumpDynamicFee(cfg bumpConfig, feeCapBufferBlocks uint16, lggr logger.Sugar } if bumpedFeeCap.Cmp(maxGasPrice) > 0 { - return bumpedFee, pkgerrors.Wrapf(commonfee.ErrBumpFeeExceedsLimit, "bumped fee cap of %s would exceed configured max gas price of %s (original fee: tip cap %s, fee cap %s). %s", + return bumpedFee, pkgerrors.Wrapf(fees.ErrBumpFeeExceedsLimit, "bumped fee cap of %s would exceed configured max gas price of %s (original fee: tip cap %s, fee cap %s). %s", bumpedFeeCap.String(), maxGasPrice, originalFee.GasTipCap.String(), originalFee.GasFeeCap.String(), label.NodeConnectivityProblemWarning) } @@ -542,6 +541,6 @@ func getMaxGasPrice(userSpecifiedMax, maxGasPriceWei *assets.Wei) *assets.Wei { } func capGasPrice(calculatedGasPrice, userSpecifiedMax, maxGasPriceWei *assets.Wei) *assets.Wei { - maxGasPrice := commonfee.CalculateFee(calculatedGasPrice.ToInt(), userSpecifiedMax.ToInt(), maxGasPriceWei.ToInt()) + maxGasPrice := fees.CalculateFee(calculatedGasPrice.ToInt(), userSpecifiedMax.ToInt(), maxGasPriceWei.ToInt()) return assets.NewWei(maxGasPrice) } diff --git a/core/chains/evm/gas/models_test.go b/core/chains/evm/gas/models_test.go index 3cc83ec7034..6bec271f0ac 100644 --- a/core/chains/evm/gas/models_test.go +++ b/core/chains/evm/gas/models_test.go @@ -13,7 +13,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - commonfee "github.com/smartcontractkit/chainlink/v2/common/fee" + "github.com/smartcontractkit/chainlink/v2/common/fees" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" @@ -294,13 +294,13 @@ func TestWrappedEvmEstimator(t *testing.T) { ethClient.On("EstimateGas", mock.Anything, mock.Anything).Return(estimatedGasLimit, nil).Twice() estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) _, _, err := estimator.GetFee(ctx, []byte{}, gasLimit, nil, &fromAddress, &toAddress) - require.ErrorIs(t, err, commonfee.ErrFeeLimitTooLow) + require.ErrorIs(t, err, fees.ErrFeeLimitTooLow) // expect dynamic fee data dynamicFees = true estimator = gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) _, _, err = estimator.GetFee(ctx, []byte{}, gasLimit, nil, &fromAddress, &toAddress) - require.ErrorIs(t, err, commonfee.ErrFeeLimitTooLow) + require.ErrorIs(t, err, fees.ErrFeeLimitTooLow) }) t.Run("GetFee, estimate gas limit enabled, buffer exceeds provided limit, fallsback to provided limit", func(t *testing.T) { diff --git a/core/chains/evm/gas/rollups/arbitrum_l1_oracle.go b/core/chains/evm/gas/rollups/arbitrum_l1_oracle.go index 3182d920178..be0508649f9 100644 --- a/core/chains/evm/gas/rollups/arbitrum_l1_oracle.go +++ b/core/chains/evm/gas/rollups/arbitrum_l1_oracle.go @@ -15,8 +15,8 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" - commonclient "github.com/smartcontractkit/chainlink/v2/common/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" ) @@ -155,7 +155,7 @@ func (o *arbitrumL1Oracle) refresh() { } func (o *arbitrumL1Oracle) refreshWithError() error { - ctx, cancel := o.chStop.CtxWithTimeout(commonclient.QueryTimeout) + ctx, cancel := o.chStop.CtxWithTimeout(client.QueryTimeout) defer cancel() price, err := o.fetchL1GasPrice(ctx) @@ -221,7 +221,7 @@ func (o *arbitrumL1Oracle) GasPrice(_ context.Context) (l1GasPrice *assets.Wei, // https://github.com/OffchainLabs/nitro/blob/f7645453cfc77bf3e3644ea1ac031eff629df325/contracts/src/precompiles/ArbGasInfo.sol#L69 func (o *arbitrumL1Oracle) GetPricesInArbGas() (perL2Tx uint32, perL1CalldataUnit uint32, err error) { - ctx, cancel := o.chStop.CtxWithTimeout(commonclient.QueryTimeout) + ctx, cancel := o.chStop.CtxWithTimeout(client.QueryTimeout) defer cancel() precompile := common.HexToAddress(ArbGasInfoAddress) b, err := o.client.CallContract(ctx, ethereum.CallMsg{ diff --git a/core/chains/evm/gas/rollups/custom_calldata_da_oracle.go b/core/chains/evm/gas/rollups/custom_calldata_da_oracle.go index 2ed6408fd0c..7ac71d42f7a 100644 --- a/core/chains/evm/gas/rollups/custom_calldata_da_oracle.go +++ b/core/chains/evm/gas/rollups/custom_calldata_da_oracle.go @@ -15,8 +15,8 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" - commonclient "github.com/smartcontractkit/chainlink/v2/common/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" @@ -125,7 +125,7 @@ func (o *customCalldataDAOracle) refresh() { } func (o *customCalldataDAOracle) refreshWithError() error { - ctx, cancel := o.chStop.CtxWithTimeout(commonclient.QueryTimeout) + ctx, cancel := o.chStop.CtxWithTimeout(client.QueryTimeout) defer cancel() price, err := o.getCustomCalldataGasPrice(ctx) diff --git a/core/chains/evm/gas/rollups/l1_oracle.go b/core/chains/evm/gas/rollups/l1_oracle.go index d9f12dfa79e..50d5dff6e4e 100644 --- a/core/chains/evm/gas/rollups/l1_oracle.go +++ b/core/chains/evm/gas/rollups/l1_oracle.go @@ -50,7 +50,16 @@ const ( PollPeriod = 6 * time.Second ) -var supportedChainTypes = []chaintype.ChainType{chaintype.ChainArbitrum, chaintype.ChainOptimismBedrock, chaintype.ChainKroma, chaintype.ChainScroll, chaintype.ChainZkSync, chaintype.ChainMantle} +// Sort alphabetically +var supportedChainTypes = []chaintype.ChainType{ + chaintype.ChainArbitrum, + chaintype.ChainKroma, + chaintype.ChainMantle, + chaintype.ChainOptimismBedrock, + chaintype.ChainScroll, + chaintype.ChainZircuit, + chaintype.ChainZkSync, +} func IsRollupWithL1Support(chainType chaintype.ChainType) bool { return slices.Contains(supportedChainTypes, chainType) diff --git a/core/chains/evm/gas/rollups/mocks/l1_oracle.go b/core/chains/evm/gas/rollups/mocks/l1_oracle.go index 4ed067663e2..24246a9b30d 100644 --- a/core/chains/evm/gas/rollups/mocks/l1_oracle.go +++ b/core/chains/evm/gas/rollups/mocks/l1_oracle.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -23,7 +23,7 @@ func (_m *L1Oracle) EXPECT() *L1Oracle_Expecter { return &L1Oracle_Expecter{mock: &_m.Mock} } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *L1Oracle) Close() error { ret := _m.Called() @@ -126,7 +126,7 @@ func (_c *L1Oracle_GasPrice_Call) RunAndReturn(run func(context.Context) (*asset return _c } -// HealthReport provides a mock function with given fields: +// HealthReport provides a mock function with no fields func (_m *L1Oracle) HealthReport() map[string]error { ret := _m.Called() @@ -173,7 +173,7 @@ func (_c *L1Oracle_HealthReport_Call) RunAndReturn(run func() map[string]error) return _c } -// Name provides a mock function with given fields: +// Name provides a mock function with no fields func (_m *L1Oracle) Name() string { ret := _m.Called() @@ -218,7 +218,7 @@ func (_c *L1Oracle_Name_Call) RunAndReturn(run func() string) *L1Oracle_Name_Cal return _c } -// Ready provides a mock function with given fields: +// Ready provides a mock function with no fields func (_m *L1Oracle) Ready() error { ret := _m.Called() diff --git a/core/chains/evm/gas/rollups/mocks/l1_oracle_client.go b/core/chains/evm/gas/rollups/mocks/l1_oracle_client.go index 8ff0bfa0908..73fac2ae846 100644 --- a/core/chains/evm/gas/rollups/mocks/l1_oracle_client.go +++ b/core/chains/evm/gas/rollups/mocks/l1_oracle_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/chains/evm/gas/rollups/op_l1_oracle.go b/core/chains/evm/gas/rollups/op_l1_oracle.go index cd6f2347953..431b57dd019 100644 --- a/core/chains/evm/gas/rollups/op_l1_oracle.go +++ b/core/chains/evm/gas/rollups/op_l1_oracle.go @@ -17,7 +17,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" - commonclient "github.com/smartcontractkit/chainlink/v2/common/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" @@ -26,6 +26,8 @@ import ( ) // Reads L2-specific precompiles and caches the l1GasPrice set by the L2. +// +//nolint:unused // backported from CCIP type optimismL1Oracle struct { services.StateMachine client l1OracleClient @@ -233,7 +235,7 @@ func (o *optimismL1Oracle) refresh() { } func (o *optimismL1Oracle) refreshWithError() error { - ctx, cancel := o.chStop.CtxWithTimeout(commonclient.QueryTimeout) + ctx, cancel := o.chStop.CtxWithTimeout(client.QueryTimeout) defer cancel() price, err := o.GetDAGasPrice(ctx) diff --git a/core/chains/evm/gas/rollups/zkSync_l1_oracle.go b/core/chains/evm/gas/rollups/zkSync_l1_oracle.go index 6edfb8cd28b..a9502e2b3af 100644 --- a/core/chains/evm/gas/rollups/zkSync_l1_oracle.go +++ b/core/chains/evm/gas/rollups/zkSync_l1_oracle.go @@ -14,7 +14,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/utils" - commonclient "github.com/smartcontractkit/chainlink/v2/common/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" ) @@ -124,7 +124,7 @@ func (o *zkSyncL1Oracle) refresh() (t *time.Timer) { func (o *zkSyncL1Oracle) refreshWithError() (t *time.Timer, err error) { t = time.NewTimer(utils.WithJitter(o.pollPeriod)) - ctx, cancel := o.chStop.CtxWithTimeout(commonclient.QueryTimeout) + ctx, cancel := o.chStop.CtxWithTimeout(client.QueryTimeout) defer cancel() price, err := o.CalculateL1GasPrice(ctx) diff --git a/core/chains/evm/gas/suggested_price_estimator.go b/core/chains/evm/gas/suggested_price_estimator.go index 5035f76a947..68e23f75d28 100644 --- a/core/chains/evm/gas/suggested_price_estimator.go +++ b/core/chains/evm/gas/suggested_price_estimator.go @@ -13,11 +13,10 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" bigmath "github.com/smartcontractkit/chainlink-common/pkg/utils/big_math" - commonclient "github.com/smartcontractkit/chainlink/v2/common/client" - "github.com/smartcontractkit/chainlink/v2/common/fee" - feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" + "github.com/smartcontractkit/chainlink/v2/common/fees" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) @@ -124,7 +123,7 @@ func (o *SuggestedPriceEstimator) run() { func (o *SuggestedPriceEstimator) refreshPrice() { var res hexutil.Big - ctx, cancel := o.chStop.CtxWithTimeout(commonclient.QueryTimeout) + ctx, cancel := o.chStop.CtxWithTimeout(client.QueryTimeout) defer cancel() if err := o.client.CallContext(ctx, &res, "eth_gasPrice"); err != nil { @@ -172,17 +171,17 @@ func (*SuggestedPriceEstimator) BumpDynamicFee(_ context.Context, _ DynamicFee, return } -func (o *SuggestedPriceEstimator) GetLegacyGas(ctx context.Context, _ []byte, GasLimit uint64, maxGasPriceWei *assets.Wei, opts ...feetypes.Opt) (gasPrice *assets.Wei, chainSpecificGasLimit uint64, err error) { - chainSpecificGasLimit = GasLimit +func (o *SuggestedPriceEstimator) GetLegacyGas(ctx context.Context, _ []byte, gasLimit uint64, maxGasPriceWei *assets.Wei, opts ...fees.Opt) (gasPrice *assets.Wei, chainSpecificGasLimit uint64, err error) { + chainSpecificGasLimit = gasLimit ok := o.IfStarted(func() { - if slices.Contains(opts, feetypes.OptForceRefetch) { + if slices.Contains(opts, fees.OptForceRefetch) { err = o.forceRefresh(ctx) } if gasPrice = o.getGasPrice(); gasPrice == nil { err = pkgerrors.New("failed to estimate gas; gas price not set") return } - o.logger.Debugw("GetLegacyGas", "GasPrice", gasPrice, "GasLimit", GasLimit) + o.logger.Debugw("GetLegacyGas", "GasPrice", gasPrice, "GasLimit", gasLimit) }) if !ok { return nil, 0, pkgerrors.New("estimator is not started") @@ -227,7 +226,7 @@ func (o *SuggestedPriceEstimator) BumpLegacyGas(ctx context.Context, originalFee // Add a buffer on top of the gas price returned by the RPC. // Bump logic when using the suggested gas price from an RPC is realistically only needed when there is increased volatility in gas price. // This buffer is a precaution to increase the chance of getting this tx on chain - bufferedPrice := fee.MaxBumpedFee(newGasPrice.ToInt(), o.cfg.BumpPercent(), o.cfg.BumpMin().ToInt()) + bufferedPrice := fees.MaxBumpedFee(newGasPrice.ToInt(), o.cfg.BumpPercent(), o.cfg.BumpMin().ToInt()) // If the new suggested price is less than or equal to the max and the buffer puts the new price over the max, return the max price instead // The buffer is added on top of the suggested price during bumping as just a precaution. It is better to resubmit the transaction with the max gas price instead of erroring. newGasPrice = assets.NewWei(bigmath.Min(bufferedPrice, maxGasPriceWei.ToInt())) diff --git a/core/chains/evm/keystore/eth.go b/core/chains/evm/keystore/eth.go index ff71e0a4f18..9c0986d9c3d 100644 --- a/core/chains/evm/keystore/eth.go +++ b/core/chains/evm/keystore/eth.go @@ -13,5 +13,6 @@ type Eth interface { CheckEnabled(ctx context.Context, address common.Address, chainID *big.Int) error EnabledAddressesForChain(ctx context.Context, chainID *big.Int) (addresses []common.Address, err error) SignTx(ctx context.Context, fromAddress common.Address, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) + SignMessage(ctx context.Context, address common.Address, message []byte) ([]byte, error) SubscribeToKeyChanges(ctx context.Context) (ch chan struct{}, unsub func()) } diff --git a/core/chains/evm/keystore/mocks/eth.go b/core/chains/evm/keystore/mocks/eth.go index b481be1b5c8..96125e66936 100644 --- a/core/chains/evm/keystore/mocks/eth.go +++ b/core/chains/evm/keystore/mocks/eth.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -133,6 +133,66 @@ func (_c *Eth_EnabledAddressesForChain_Call) RunAndReturn(run func(context.Conte return _c } +// SignMessage provides a mock function with given fields: ctx, address, message +func (_m *Eth) SignMessage(ctx context.Context, address common.Address, message []byte) ([]byte, error) { + ret := _m.Called(ctx, address, message) + + if len(ret) == 0 { + panic("no return value specified for SignMessage") + } + + var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Address, []byte) ([]byte, error)); ok { + return rf(ctx, address, message) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Address, []byte) []byte); ok { + r0 = rf(ctx, address, message) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Address, []byte) error); ok { + r1 = rf(ctx, address, message) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Eth_SignMessage_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SignMessage' +type Eth_SignMessage_Call struct { + *mock.Call +} + +// SignMessage is a helper method to define mock.On call +// - ctx context.Context +// - address common.Address +// - message []byte +func (_e *Eth_Expecter) SignMessage(ctx interface{}, address interface{}, message interface{}) *Eth_SignMessage_Call { + return &Eth_SignMessage_Call{Call: _e.mock.On("SignMessage", ctx, address, message)} +} + +func (_c *Eth_SignMessage_Call) Run(run func(ctx context.Context, address common.Address, message []byte)) *Eth_SignMessage_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(common.Address), args[2].([]byte)) + }) + return _c +} + +func (_c *Eth_SignMessage_Call) Return(_a0 []byte, _a1 error) *Eth_SignMessage_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Eth_SignMessage_Call) RunAndReturn(run func(context.Context, common.Address, []byte) ([]byte, error)) *Eth_SignMessage_Call { + _c.Call.Return(run) + return _c +} + // SignTx provides a mock function with given fields: ctx, fromAddress, tx, chainID func (_m *Eth) SignTx(ctx context.Context, fromAddress common.Address, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { ret := _m.Called(ctx, fromAddress, tx, chainID) diff --git a/core/chains/evm/log/mocks/abigen_contract.go b/core/chains/evm/log/mocks/abigen_contract.go index 7db05b6e097..7fd1479810f 100644 --- a/core/chains/evm/log/mocks/abigen_contract.go +++ b/core/chains/evm/log/mocks/abigen_contract.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -24,7 +24,7 @@ func (_m *AbigenContract) EXPECT() *AbigenContract_Expecter { return &AbigenContract_Expecter{mock: &_m.Mock} } -// Address provides a mock function with given fields: +// Address provides a mock function with no fields func (_m *AbigenContract) Address() common.Address { ret := _m.Called() diff --git a/core/chains/evm/log/mocks/broadcast.go b/core/chains/evm/log/mocks/broadcast.go index 6aadbc50b6d..4d7367819a2 100644 --- a/core/chains/evm/log/mocks/broadcast.go +++ b/core/chains/evm/log/mocks/broadcast.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -25,7 +25,7 @@ func (_m *Broadcast) EXPECT() *Broadcast_Expecter { return &Broadcast_Expecter{mock: &_m.Mock} } -// DecodedLog provides a mock function with given fields: +// DecodedLog provides a mock function with no fields func (_m *Broadcast) DecodedLog() interface{} { ret := _m.Called() @@ -72,7 +72,7 @@ func (_c *Broadcast_DecodedLog_Call) RunAndReturn(run func() interface{}) *Broad return _c } -// EVMChainID provides a mock function with given fields: +// EVMChainID provides a mock function with no fields func (_m *Broadcast) EVMChainID() big.Int { ret := _m.Called() @@ -117,7 +117,7 @@ func (_c *Broadcast_EVMChainID_Call) RunAndReturn(run func() big.Int) *Broadcast return _c } -// JobID provides a mock function with given fields: +// JobID provides a mock function with no fields func (_m *Broadcast) JobID() int32 { ret := _m.Called() @@ -162,7 +162,7 @@ func (_c *Broadcast_JobID_Call) RunAndReturn(run func() int32) *Broadcast_JobID_ return _c } -// LatestBlockHash provides a mock function with given fields: +// LatestBlockHash provides a mock function with no fields func (_m *Broadcast) LatestBlockHash() common.Hash { ret := _m.Called() @@ -209,7 +209,7 @@ func (_c *Broadcast_LatestBlockHash_Call) RunAndReturn(run func() common.Hash) * return _c } -// LatestBlockNumber provides a mock function with given fields: +// LatestBlockNumber provides a mock function with no fields func (_m *Broadcast) LatestBlockNumber() uint64 { ret := _m.Called() @@ -254,7 +254,7 @@ func (_c *Broadcast_LatestBlockNumber_Call) RunAndReturn(run func() uint64) *Bro return _c } -// RawLog provides a mock function with given fields: +// RawLog provides a mock function with no fields func (_m *Broadcast) RawLog() types.Log { ret := _m.Called() @@ -299,7 +299,7 @@ func (_c *Broadcast_RawLog_Call) RunAndReturn(run func() types.Log) *Broadcast_R return _c } -// ReceiptsRoot provides a mock function with given fields: +// ReceiptsRoot provides a mock function with no fields func (_m *Broadcast) ReceiptsRoot() common.Hash { ret := _m.Called() @@ -346,7 +346,7 @@ func (_c *Broadcast_ReceiptsRoot_Call) RunAndReturn(run func() common.Hash) *Bro return _c } -// StateRoot provides a mock function with given fields: +// StateRoot provides a mock function with no fields func (_m *Broadcast) StateRoot() common.Hash { ret := _m.Called() @@ -393,7 +393,7 @@ func (_c *Broadcast_StateRoot_Call) RunAndReturn(run func() common.Hash) *Broadc return _c } -// String provides a mock function with given fields: +// String provides a mock function with no fields func (_m *Broadcast) String() string { ret := _m.Called() @@ -438,7 +438,7 @@ func (_c *Broadcast_String_Call) RunAndReturn(run func() string) *Broadcast_Stri return _c } -// TransactionsRoot provides a mock function with given fields: +// TransactionsRoot provides a mock function with no fields func (_m *Broadcast) TransactionsRoot() common.Hash { ret := _m.Called() diff --git a/core/chains/evm/log/mocks/broadcaster.go b/core/chains/evm/log/mocks/broadcaster.go index 1545624a83d..8e88fd7e30d 100644 --- a/core/chains/evm/log/mocks/broadcaster.go +++ b/core/chains/evm/log/mocks/broadcaster.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -55,11 +55,11 @@ func (_c *Broadcaster_AddDependents_Call) Return() *Broadcaster_AddDependents_Ca } func (_c *Broadcaster_AddDependents_Call) RunAndReturn(run func(int)) *Broadcaster_AddDependents_Call { - _c.Call.Return(run) + _c.Run(run) return _c } -// AwaitDependents provides a mock function with given fields: +// AwaitDependents provides a mock function with no fields func (_m *Broadcaster) AwaitDependents() <-chan struct{} { ret := _m.Called() @@ -106,7 +106,7 @@ func (_c *Broadcaster_AwaitDependents_Call) RunAndReturn(run func() <-chan struc return _c } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *Broadcaster) Close() error { ret := _m.Called() @@ -151,7 +151,7 @@ func (_c *Broadcaster_Close_Call) RunAndReturn(run func() error) *Broadcaster_Cl return _c } -// DependentReady provides a mock function with given fields: +// DependentReady provides a mock function with no fields func (_m *Broadcaster) DependentReady() { _m.Called() } @@ -179,11 +179,11 @@ func (_c *Broadcaster_DependentReady_Call) Return() *Broadcaster_DependentReady_ } func (_c *Broadcaster_DependentReady_Call) RunAndReturn(run func()) *Broadcaster_DependentReady_Call { - _c.Call.Return(run) + _c.Run(run) return _c } -// HealthReport provides a mock function with given fields: +// HealthReport provides a mock function with no fields func (_m *Broadcaster) HealthReport() map[string]error { ret := _m.Called() @@ -230,7 +230,7 @@ func (_c *Broadcaster_HealthReport_Call) RunAndReturn(run func() map[string]erro return _c } -// IsConnected provides a mock function with given fields: +// IsConnected provides a mock function with no fields func (_m *Broadcaster) IsConnected() bool { ret := _m.Called() @@ -323,7 +323,7 @@ func (_c *Broadcaster_MarkConsumed_Call) RunAndReturn(run func(context.Context, return _c } -// Name provides a mock function with given fields: +// Name provides a mock function with no fields func (_m *Broadcaster) Name() string { ret := _m.Called() @@ -398,11 +398,11 @@ func (_c *Broadcaster_OnNewLongestChain_Call) Return() *Broadcaster_OnNewLongest } func (_c *Broadcaster_OnNewLongestChain_Call) RunAndReturn(run func(context.Context, *types.Head)) *Broadcaster_OnNewLongestChain_Call { - _c.Call.Return(run) + _c.Run(run) return _c } -// Ready provides a mock function with given fields: +// Ready provides a mock function with no fields func (_m *Broadcaster) Ready() error { ret := _m.Called() @@ -526,7 +526,7 @@ func (_c *Broadcaster_ReplayFromBlock_Call) Return() *Broadcaster_ReplayFromBloc } func (_c *Broadcaster_ReplayFromBlock_Call) RunAndReturn(run func(int64, bool)) *Broadcaster_ReplayFromBlock_Call { - _c.Call.Return(run) + _c.Run(run) return _c } diff --git a/core/chains/evm/logpoller/helper_test.go b/core/chains/evm/logpoller/helper_test.go index b8d849d7d83..6a5959c5586 100644 --- a/core/chains/evm/logpoller/helper_test.go +++ b/core/chains/evm/logpoller/helper_test.go @@ -25,7 +25,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/log_emitter" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" ) diff --git a/core/chains/evm/logpoller/log_poller.go b/core/chains/evm/logpoller/log_poller.go index 725fdbda63c..6dae65fa29c 100644 --- a/core/chains/evm/logpoller/log_poller.go +++ b/core/chains/evm/logpoller/log_poller.go @@ -78,7 +78,7 @@ type LogPoller interface { type LogPollerTest interface { LogPoller PollAndSaveLogs(ctx context.Context, currentBlockNumber int64) - BackupPollAndSaveLogs(ctx context.Context) + BackupPollAndSaveLogs(ctx context.Context) error Filter(from, to *big.Int, bh *common.Hash) ethereum.FilterQuery GetReplayFromBlock(ctx context.Context, requested int64) (int64, error) PruneOldBlocks(ctx context.Context) (bool, error) @@ -419,6 +419,12 @@ func (lp *logPoller) Replay(ctx context.Context, fromBlock int64) (err error) { defer func() { if errors.Is(err, context.Canceled) { err = ErrReplayRequestAborted + } else if errors.Is(err, commontypes.ErrFinalityViolated) { + // Replay only declares finality violation and does not resolve it, as it's possible that [fromBlock, savedFinalizedBlockNumber] + // does not contain the violation. + lp.lggr.Criticalw("Replay failed due to finality violation", "fromBlock", fromBlock, "err", err) + lp.finalityViolated.Store(true) + lp.SvcErrBuffer.Append(err) } }() @@ -666,7 +672,17 @@ func (lp *logPoller) run() { lp.lggr.Warnw("Backup log poller ran before filters loaded, skipping") continue } - lp.BackupPollAndSaveLogs(ctx) + err := lp.BackupPollAndSaveLogs(ctx) + switch { + case errors.Is(err, commontypes.ErrFinalityViolated): + // BackupPoll only declares finality violation and does not resolve it, as it's possible that processed range + // does not contain the violation. + lp.lggr.Criticalw("Backup poll failed due to finality violation", "err", err) + lp.finalityViolated.Store(true) + lp.SvcErrBuffer.Append(err) + case err != nil: + lp.lggr.Errorw("Backup poller failed, retrying later", "err", err) + } } } } @@ -767,16 +783,16 @@ func (lp *logPoller) handleReplayRequest(ctx context.Context, fromBlockReq int64 } } -func (lp *logPoller) BackupPollAndSaveLogs(ctx context.Context) { +func (lp *logPoller) BackupPollAndSaveLogs(ctx context.Context) error { if lp.backupPollerNextBlock == 0 { lastProcessed, err := lp.orm.SelectLatestBlock(ctx) if err != nil { if pkgerrors.Is(err, sql.ErrNoRows) { lp.lggr.Warnw("Backup log poller ran before first successful log poller run, skipping") - } else { - lp.lggr.Errorw("Backup log poller unable to get starting block", "err", err) + return nil } - return + + return fmt.Errorf("unable to get starting block: %w", err) } // If this is our first run, start from block min(lastProcessed.FinalizedBlockNumber, lastProcessed.BlockNumber-backupPollerBlockDelay) backupStartBlock := mathutil.Min(lastProcessed.FinalizedBlockNumber, lastProcessed.BlockNumber-lp.backupPollerBlockDelay) @@ -787,7 +803,7 @@ func (lp *logPoller) BackupPollAndSaveLogs(ctx context.Context) { _, latestFinalizedBlockNumber, err := lp.latestBlocks(ctx) if err != nil { lp.lggr.Warnw("Backup logpoller failed to get latest block", "err", err) - return + return nil } lastSafeBackfillBlock := latestFinalizedBlockNumber - 1 @@ -796,12 +812,13 @@ func (lp *logPoller) BackupPollAndSaveLogs(ctx context.Context) { if err = lp.backfill(ctx, lp.backupPollerNextBlock, lastSafeBackfillBlock); err != nil { // If there's an error backfilling, we can just return and retry from the last block saved // since we don't save any blocks on backfilling. We may re-insert the same logs but thats ok. - lp.lggr.Warnw("Backup poller failed", "err", err) - return + return fmt.Errorf("backfill failed: %w", err) } lp.lggr.Infow("Backup poller finished backfilling", "start", lp.backupPollerNextBlock, "end", lastSafeBackfillBlock) lp.backupPollerNextBlock = lastSafeBackfillBlock + 1 } + + return nil } // convertLogs converts an array of geth logs ([]type.Log) to an array of logpoller logs ([]Log) @@ -850,17 +867,28 @@ func convertTopics(topics []common.Hash) [][]byte { return topicsForDB } -// blocksFromLogs fetches all of the blocks associated with a given list of logs. It will also unconditionally fetch endBlockNumber, +// blocksFromFinalizedLogs fetches all of the blocks associated with a given list of logs. It will also unconditionally fetch endBlockNumber, // whether or not there are any logs in the list from that block -func (lp *logPoller) blocksFromLogs(ctx context.Context, logs []types.Log, endBlockNumber uint64) (blocks []LogPollerBlock, err error) { - var numbers []uint64 +func (lp *logPoller) blocksFromFinalizedLogs(ctx context.Context, logs []types.Log, endBlockNumber uint64) (blocks []LogPollerBlock, err error) { + numbers := make([]uint64, 0, len(logs)) for _, log := range logs { numbers = append(numbers, log.BlockNumber) } if numbers[len(numbers)-1] != endBlockNumber { numbers = append(numbers, endBlockNumber) } - return lp.GetBlocksRange(ctx, numbers) + blocks, err = lp.GetBlocksRange(ctx, numbers) + if err != nil { + return nil, err + } + + for i, log := range logs { + if log.BlockHash != blocks[i].BlockHash { + return nil, fmt.Errorf("finalized log produced by tx %s has block hash %s that does not match fetched block's hash %s: %w", log.TxHash, log.BlockHash, blocks[i].BlockHash, commontypes.ErrFinalityViolated) + } + } + + return blocks, nil } // backfill will query FilterLogs in batches for logs in the @@ -891,7 +919,7 @@ func (lp *logPoller) backfill(ctx context.Context, start, end int64) error { if len(gethLogs) == 0 { continue } - blocks, err := lp.blocksFromLogs(ctx, gethLogs, uint64(to)) + blocks, err := lp.blocksFromFinalizedLogs(ctx, gethLogs, uint64(to)) //nolint:gosec // G115 if err != nil { return err } @@ -921,11 +949,6 @@ func (lp *logPoller) backfill(ctx context.Context, start, end int64) error { // 2. Delete all logs and blocks after the LCA // 3. Return the LCA+1, i.e. our new current (unprocessed) block. func (lp *logPoller) getCurrentBlockMaybeHandleReorg(ctx context.Context, currentBlockNumber int64, currentBlock *evmtypes.Head) (head *evmtypes.Head, err error) { - defer func() { - if err == nil { - lp.finalityViolated.Store(false) - } - }() var err1 error if currentBlock == nil { @@ -956,7 +979,7 @@ func (lp *logPoller) getCurrentBlockMaybeHandleReorg(ctx context.Context, curren // We will not have the previous currentBlock on initial poll. havePreviousBlock := err1 == nil if !havePreviousBlock { - lp.lggr.Infow("Do not have previous block, first poll ever on new chain or after backfill", "currentBlockNumber", currentBlockNumber) + lp.lggr.Infow("Do not have previous block, first poll ever on new chain", "currentBlockNumber", currentBlockNumber) return currentBlock, nil } // Check for reorg. @@ -966,8 +989,7 @@ func (lp *logPoller) getCurrentBlockMaybeHandleReorg(ctx context.Context, curren // Since we go currentBlock by currentBlock for unfinalized logs, the mismatch starts at currentBlockNumber - 1. blockAfterLCA, err2 := lp.findBlockAfterLCA(ctx, currentBlock, expectedParent.FinalizedBlockNumber) if err2 != nil { - lp.lggr.Warnw("Unable to find LCA after reorg, retrying", "err", err2) - return nil, pkgerrors.New("Unable to find LCA after reorg, retrying") + return nil, fmt.Errorf("unable to find LCA after reorg: %w", err2) } lp.lggr.Infow("Reorg detected", "blockAfterLCA", blockAfterLCA.Number, "currentBlockNumber", currentBlockNumber) @@ -994,20 +1016,40 @@ func (lp *logPoller) getCurrentBlockMaybeHandleReorg(ctx context.Context, curren // currentBlockNumber is the block from where new logs are to be polled & saved. Under normal // conditions this would be equal to lastProcessed.BlockNumber + 1. func (lp *logPoller) PollAndSaveLogs(ctx context.Context, currentBlockNumber int64) { + err := lp.pollAndSaveLogs(ctx, currentBlockNumber) + if errors.Is(err, commontypes.ErrFinalityViolated) { + lp.lggr.Criticalw("Failed to poll and save logs due to finality violation, retrying later", "err", err) + lp.finalityViolated.Store(true) + lp.SvcErrBuffer.Append(err) + return + } + + if err != nil { + lp.lggr.Errorw("Failed to poll and save logs, retrying later", "err", err) + return + } + + if lp.finalityViolated.Load() { + lp.lggr.Info("PollAndSaveLogs completed successfully - removing finality violation flag") + lp.finalityViolated.Store(false) + } +} + +func (lp *logPoller) pollAndSaveLogs(ctx context.Context, currentBlockNumber int64) (err error) { lp.lggr.Debugw("Polling for logs", "currentBlockNumber", currentBlockNumber) // Intentionally not using logPoller.finalityDepth directly but the latestFinalizedBlockNumber returned from lp.latestBlocks() // latestBlocks knows how to pick a proper latestFinalizedBlockNumber based on the logPoller's configuration latestBlock, latestFinalizedBlockNumber, err := lp.latestBlocks(ctx) if err != nil { lp.lggr.Warnw("Unable to get latestBlockNumber block", "err", err, "currentBlockNumber", currentBlockNumber) - return + return nil } latestBlockNumber := latestBlock.Number if currentBlockNumber > latestBlockNumber { // Note there can also be a reorg "shortening" i.e. chain height decreases but TDD increases. In that case // we also just wait until the new tip is longer and then detect the reorg. lp.lggr.Debugw("No new blocks since last poll", "currentBlockNumber", currentBlockNumber, "latestBlockNumber", latestBlockNumber) - return + return nil } var currentBlock *evmtypes.Head if currentBlockNumber == latestBlockNumber { @@ -1020,8 +1062,7 @@ func (lp *logPoller) PollAndSaveLogs(ctx context.Context, currentBlockNumber int if err != nil { // If there's an error handling the reorg, we can't be sure what state the db was left in. // Resume from the latest block saved and retry. - lp.lggr.Errorw("Unable to get current block, retrying", "err", err) - return + return fmt.Errorf("unable to get current block: %w", err) } currentBlockNumber = currentBlock.Number @@ -1036,8 +1077,7 @@ func (lp *logPoller) PollAndSaveLogs(ctx context.Context, currentBlockNumber int if err = lp.backfill(ctx, currentBlockNumber, lastSafeBackfillBlock); err != nil { // If there's an error backfilling, we can just return and retry from the last block saved // since we don't save any blocks on backfilling. We may re-insert the same logs but thats ok. - lp.lggr.Warnw("Unable to backfill finalized logs, retrying later", "err", err) - return + return fmt.Errorf("failed to backfill finalized logs: %w", err) } currentBlockNumber = lastSafeBackfillBlock + 1 } @@ -1048,8 +1088,7 @@ func (lp *logPoller) PollAndSaveLogs(ctx context.Context, currentBlockNumber int if err != nil { // If there's an error handling the reorg, we can't be sure what state the db was left in. // Resume from the latest block saved. - lp.lggr.Errorw("Unable to get current block", "err", err) - return + return fmt.Errorf("failed to get current block: %w", err) } currentBlockNumber = currentBlock.Number } @@ -1059,7 +1098,7 @@ func (lp *logPoller) PollAndSaveLogs(ctx context.Context, currentBlockNumber int logs, err = lp.ec.FilterLogs(ctx, lp.Filter(nil, nil, &h)) if err != nil { lp.lggr.Warnw("Unable to query for logs, retrying", "err", err, "block", currentBlockNumber) - return + return nil } lp.lggr.Debugw("Unfinalized log query", "logs", len(logs), "currentBlockNumber", currentBlockNumber, "blockHash", currentBlock.Hash, "timestamp", currentBlock.Timestamp) block := LogPollerBlock{ @@ -1075,7 +1114,7 @@ func (lp *logPoller) PollAndSaveLogs(ctx context.Context, currentBlockNumber int ) if err != nil { lp.lggr.Warnw("Unable to save logs resuming from last saved block + 1", "err", err, "block", currentBlockNumber) - return + return nil } // Update current block. // Same reorg detection on unfinalized blocks. @@ -1084,6 +1123,8 @@ func (lp *logPoller) PollAndSaveLogs(ctx context.Context, currentBlockNumber int break } } + + return nil } // Returns information about latestBlock, latestFinalizedBlockNumber provided by HeadTracker @@ -1119,12 +1160,14 @@ func (lp *logPoller) findBlockAfterLCA(ctx context.Context, current *evmtypes.He // We loop via parent instead of current so current always holds the LCA+1. // If the parent block number becomes < the first finalized block our reorg is too deep. // This can happen only if finalityTag is not enabled and fixed finalityDepth is provided via config. + var ourParentBlockHash common.Hash for parent.Number >= latestFinalizedBlockNumber { - ourParentBlockHash, err := lp.orm.SelectBlockByNumber(ctx, parent.Number) + outParentBlock, err := lp.orm.SelectBlockByNumber(ctx, parent.Number) if err != nil { return nil, err } - if parent.Hash == ourParentBlockHash.BlockHash { + ourParentBlockHash = outParentBlock.BlockHash + if parent.Hash == ourParentBlockHash { // If we do have the blockhash, return blockAfterLCA return blockAfterLCA, nil } @@ -1135,11 +1178,9 @@ func (lp *logPoller) findBlockAfterLCA(ctx context.Context, current *evmtypes.He return nil, err } } + lp.lggr.Criticalw("Reorg greater than finality depth detected", "finalityTag", lp.useFinalityTag, "current", current.Number, "latestFinalized", latestFinalizedBlockNumber) - rerr := pkgerrors.New("Reorg greater than finality depth") - lp.SvcErrBuffer.Append(rerr) - lp.finalityViolated.Store(true) - return nil, rerr + return nil, fmt.Errorf("%w: finalized block hash %s does not match RPC's %s at height %d", commontypes.ErrFinalityViolated, ourParentBlockHash, blockAfterLCA.Hash, blockAfterLCA.Number) } // PruneOldBlocks removes blocks that are > lp.keepFinalizedBlocksDepth behind the latest finalized block. @@ -1370,11 +1411,10 @@ func (lp *logPoller) fillRemainingBlocksFromRPC( blocksRequested map[uint64]struct{}, blocksFound map[uint64]LogPollerBlock, ) (map[uint64]LogPollerBlock, error) { - var remainingBlocks []string - + remainingBlocks := make([]uint64, 0, len(blocksRequested)) for num := range blocksRequested { if _, ok := blocksFound[num]; !ok { - remainingBlocks = append(remainingBlocks, hexutil.EncodeBig(new(big.Int).SetUint64(num))) + remainingBlocks = append(remainingBlocks, num) } } @@ -1383,23 +1423,7 @@ func (lp *logPoller) fillRemainingBlocksFromRPC( "remainingBlocks", remainingBlocks) } - evmBlocks, err := lp.batchFetchBlocks(ctx, remainingBlocks, lp.rpcBatchSize) - if err != nil { - return nil, err - } - - logPollerBlocks := make(map[uint64]LogPollerBlock) - for _, head := range evmBlocks { - logPollerBlocks[uint64(head.Number)] = LogPollerBlock{ - EvmChainId: head.EVMChainID, - BlockHash: head.Hash, - BlockNumber: head.Number, - BlockTimestamp: head.Timestamp, - FinalizedBlockNumber: head.Number, // always finalized; only matters if this block is returned by LatestBlock() - CreatedAt: head.CreatedAt, - } - } - return logPollerBlocks, nil + return lp.batchFetchBlocks(ctx, remainingBlocks, lp.rpcBatchSize) } // newBlockReq constructs an eth_getBlockByNumber request for particular block number @@ -1418,25 +1442,23 @@ var ( finalizedBlock blockValidationType = blockValidationType(rpc.FinalizedBlockNumber.String()) ) -// fetchBlocks fetches a list of blocks in a single batch. validationReq is the string to use for the +// fetchBlocks fetches a list of blocks in a single batch. finalityValidationReq is the string to use for the // additional validation request (either the "finalized" or "latest" string defined in rpc module), which // will be used to validate the finality of the other blocks. -func (lp *logPoller) fetchBlocks(ctx context.Context, blocksRequested []string, validationReq blockValidationType) (blocks []*evmtypes.Head, err error) { +// chainReference - is used to verify that fetched blocks belong to the same chain as referenced head. +func (lp *logPoller) fetchBlocks(ctx context.Context, blocksRequested []uint64, finalityValidationReq blockValidationType, chainReference *LogPollerBlock) (blocks map[uint64]*evmtypes.Head, err error) { n := len(blocksRequested) - blocks = make([]*evmtypes.Head, 0, n+1) - reqs := make([]rpc.BatchElem, 0, n+1) + blocks = make(map[uint64]*evmtypes.Head, n+2) + reqs := make([]rpc.BatchElem, 0, n+2) - validationBlockIndex := n - for k, num := range blocksRequested { - if num == string(validationReq) { - validationBlockIndex = k - } - reqs = append(reqs, newBlockReq(num)) + for _, num := range blocksRequested { + reqs = append(reqs, newBlockReq(hexutil.EncodeBig(big.NewInt(0).SetUint64(num)))) } - if validationBlockIndex == n { - // Add validation req if it wasn't in there already - reqs = append(reqs, newBlockReq(string(validationReq))) + reqs = append(reqs, newBlockReq(string(finalityValidationReq))) + + if chainReference != nil { + reqs = append(reqs, newBlockReq(hexutil.EncodeBig(big.NewInt(chainReference.BlockNumber)))) } err = lp.ec.BatchCallContext(ctx, reqs) @@ -1444,64 +1466,128 @@ func (lp *logPoller) fetchBlocks(ctx context.Context, blocksRequested []string, return nil, err } - validationBlock, err := validateBlockResponse(reqs[validationBlockIndex]) + // ensure that requested blocks belong to the same chain as referenced head + if chainReference != nil { + var rpcChainReference *evmtypes.Head + rpcChainReference, err = validateBlockResponse(reqs[len(reqs)-1]) + if err != nil { + return nil, err + } + + if rpcChainReference.Hash != chainReference.BlockHash { + return nil, fmt.Errorf("expected RPC's finalized block hash at hegiht %d to be %s but got %s: %w", + chainReference.BlockNumber, chainReference.BlockHash, rpcChainReference.Hash, commontypes.ErrFinalityViolated) + } + + reqs = reqs[:len(reqs)-1] // no need to include chain reference into results + } + + latestFinalized, err := validateBlockResponse(reqs[len(reqs)-1]) if err != nil { return nil, err } - latestFinalizedBlockNumber := validationBlock.Number - if validationReq == latestBlock { + latestFinalizedBlockNumber := latestFinalized.Number + if finalityValidationReq == latestBlock { // subtract finalityDepth from "latest" to get finalized, when useFinalityTags = false latestFinalizedBlockNumber = mathutil.Max(latestFinalizedBlockNumber-lp.finalityDepth, 0) } - if len(reqs) == n+1 { - reqs = reqs[:n] // ignore last req if we added it explicitly for validation - } - for k, r := range reqs { - if k == validationBlockIndex { - // Already validated this one, just insert it in proper place - blocks = append(blocks, validationBlock) - continue - } + reqs = reqs[:len(reqs)-1] // no need to include finality validation request into results - block, err2 := validateBlockResponse(r) - if err2 != nil { - return nil, err2 + for i, r := range reqs { + block, err := validateBlockResponse(r) + if err != nil { + return nil, err } blockRequested := r.Args[0].(string) if blockRequested != string(latestBlock) && block.Number > latestFinalizedBlockNumber { return nil, fmt.Errorf( - "Received unfinalized block %d while expecting finalized block (latestFinalizedBlockNumber = %d)", + "received unfinalized block %d while expecting finalized block (latestFinalizedBlockNumber = %d)", block.Number, latestFinalizedBlockNumber) } - blocks = append(blocks, block) + blocks[blocksRequested[i]] = block } return blocks, nil } -func (lp *logPoller) batchFetchBlocks(ctx context.Context, blocksRequested []string, batchSize int64) ([]*evmtypes.Head, error) { - var blocks = make([]*evmtypes.Head, 0, len(blocksRequested)+1) - +func (lp *logPoller) batchFetchBlocks(ctx context.Context, blocksRequested []uint64, batchSize int64) (map[uint64]LogPollerBlock, error) { validationReq := finalizedBlock if !lp.useFinalityTag { validationReq = latestBlock } + chainValidationHead, err := lp.orm.SelectLatestFinalizedBlock(ctx) + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return nil, fmt.Errorf("failed to fetch latest finalized block from db: %w", err) + } + + var logPollerBlocks = make(map[uint64]LogPollerBlock, len(blocksRequested)) for i := 0; i < len(blocksRequested); i += int(batchSize) { j := i + int(batchSize) if j > len(blocksRequested) { j = len(blocksRequested) } - moreBlocks, err := lp.fetchBlocks(ctx, blocksRequested[i:j], validationReq) + + // As batch requests are not atomic, there is a chance that some of the blocks were replaced due to a reorg once we've observed them. + // Example: + // 1. RPC's chain is 1,2',3',4',5' (latest finalized is 1). + // 2. Batch request reads blocks 1,2'. + // 3. RPC updates its state to 1,2,3,4,5 (latest finalized is 5). + // 4. Batch request reads 4,5. + // As a result, we'll treat block 2' as finalized. To address that, we have to fetch all blocks twice and verify that the results are identical. + fetched1, err := lp.fetchBlocks(ctx, blocksRequested[i:j], validationReq, chainValidationHead) if err != nil { return nil, err } - blocks = append(blocks, moreBlocks...) + + fetched2, err := lp.fetchBlocks(ctx, blocksRequested[i:j], validationReq, chainValidationHead) + if err != nil { + return nil, err + } + + err = ensureIdenticalBlocksBatches(fetched1, fetched2) + if err != nil { + return nil, err + } + + for _, head := range fetched1 { + lpBlock := LogPollerBlock{ + EvmChainId: head.EVMChainID, + BlockHash: head.Hash, + BlockNumber: head.Number, + BlockTimestamp: head.Timestamp, + FinalizedBlockNumber: head.Number, // always finalized; only matters if this block is returned by LatestBlock() + CreatedAt: head.CreatedAt, + } + logPollerBlocks[uint64(head.Number)] = lpBlock //nolint:gosec // G115 + if chainValidationHead == nil || chainValidationHead.BlockNumber < lpBlock.BlockNumber { + chainValidationHead = &lpBlock + } + } } - return blocks, nil + return logPollerBlocks, nil +} + +func ensureIdenticalBlocksBatches(fetched1, fetched2 map[uint64]*evmtypes.Head) error { + if len(fetched1) != len(fetched2) { + return fmt.Errorf("invariant violation: expected size of batches to be identical. Fetched1: %d, Fetched2: %d", len(fetched1), len(fetched2)) + } + + for num, head1 := range fetched1 { + head2, ok := fetched2[num] + if !ok { + return fmt.Errorf("invariant violation: expected fetched1 to contain same blocks as fetched2, but %d is missing from fetched2", num) + } + + if head1.Hash != head2.Hash { + return fmt.Errorf("expected block %d to be finalized but got different hashes %s and %s from RPC: %w", num, head1.Hash, head2.Hash, commontypes.ErrFinalityViolated) + } + } + + return nil } func validateBlockResponse(r rpc.BatchElem) (*evmtypes.Head, error) { diff --git a/core/chains/evm/logpoller/log_poller_internal_test.go b/core/chains/evm/logpoller/log_poller_internal_test.go index 620bbf14f41..ff5c133aae2 100644 --- a/core/chains/evm/logpoller/log_poller_internal_test.go +++ b/core/chains/evm/logpoller/log_poller_internal_test.go @@ -22,17 +22,20 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" + commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + + "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" - "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" htMocks "github.com/smartcontractkit/chainlink/v2/common/headtracker/mocks" evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/log_emitter" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" ) @@ -243,7 +246,7 @@ func TestLogPoller_BackupPollerStartup(t *testing.T) { BackupPollerBlockDelay: 0, } lp := NewLogPoller(orm, ec, lggr, headTracker, lpOpts) - lp.BackupPollAndSaveLogs(ctx) + require.NoError(t, lp.BackupPollAndSaveLogs(ctx)) assert.Equal(t, int64(0), lp.backupPollerNextBlock) assert.Equal(t, 1, observedLogs.FilterMessageSnippet("ran before first successful log poller run").Len()) @@ -253,11 +256,28 @@ func TestLogPoller_BackupPollerStartup(t *testing.T) { require.NoError(t, err) require.Equal(t, latestBlock, lastProcessed.BlockNumber) - lp.BackupPollAndSaveLogs(ctx) + require.NoError(t, lp.BackupPollAndSaveLogs(ctx)) assert.Equal(t, int64(2), lp.backupPollerNextBlock) } func mockBatchCallContext(t *testing.T, ec *evmclimocks.Client) { + mockBatchCallContextWithHead(t, ec, newHeadVal) +} + +func newHeadVal(num int64) evmtypes.Head { + return evmtypes.Head{ + Number: num, + Hash: common.BigToHash(big.NewInt(num)), + ParentHash: common.BigToHash(big.NewInt(num - 1)), + } +} + +func newHead(num int64) *evmtypes.Head { + r := newHeadVal(num) + return &r +} + +func mockBatchCallContextWithHead(t *testing.T, ec *evmclimocks.Client, newHead func(num int64) evmtypes.Head) { ec.On("BatchCallContext", mock.Anything, mock.Anything).Return(nil).Run(func(args mock.Arguments) { elems := args.Get(1).([]rpc.BatchElem) for _, e := range elems { @@ -274,7 +294,7 @@ func mockBatchCallContext(t *testing.T, ec *evmclimocks.Client) { num = int64(n) } result := e.Result.(*evmtypes.Head) - *result = evmtypes.Head{Number: num, Hash: utils.NewHash()} + *result = newHead(num) } }) } @@ -289,12 +309,12 @@ func TestLogPoller_Replay(t *testing.T) { orm := NewORM(chainID, db, lggr) var head atomic.Pointer[evmtypes.Head] - head.Store(&evmtypes.Head{Number: 4}) + head.Store(newHead(4)) events := []common.Hash{EmitterABI.Events["Log1"].ID} log1 := types.Log{ Index: 0, - BlockHash: common.Hash{}, + BlockHash: common.BigToHash(big.NewInt(head.Load().Number)), BlockNumber: uint64(head.Load().Number), Topics: events, Address: addr, @@ -303,6 +323,9 @@ func TestLogPoller_Replay(t *testing.T) { } ec := evmclimocks.NewClient(t) + ec.EXPECT().HeadByHash(mock.Anything, mock.Anything).RunAndReturn(func(ctx context.Context, hash common.Hash) (*evmtypes.Head, error) { + return &evmtypes.Head{Number: hash.Big().Int64(), Hash: hash}, nil + }).Maybe() ec.On("HeadByNumber", mock.Anything, mock.Anything).Return(func(context.Context, *big.Int) (*evmtypes.Head, error) { return head.Load(), nil }) @@ -321,7 +344,7 @@ func TestLogPoller_Replay(t *testing.T) { headTracker.On("LatestAndFinalizedBlock", mock.Anything).Return(func(ctx context.Context) (*evmtypes.Head, *evmtypes.Head, error) { h := head.Load() - finalized := &evmtypes.Head{Number: h.Number - lpOpts.FinalityDepth} + finalized := newHead(h.Number - lpOpts.FinalityDepth) return h, finalized, nil }) lp := NewLogPoller(orm, ec, lggr, headTracker, lpOpts) @@ -423,7 +446,7 @@ func TestLogPoller_Replay(t *testing.T) { ec.On("FilterLogs", mock.Anything, mock.Anything).Return([]types.Log{log1}, nil).Maybe() // in case task gets delayed by >= 100ms - head.Store(&evmtypes.Head{Number: 5}) + head.Store(newHead(5)) t.Cleanup(lp.reset) servicetest.Run(t, lp) @@ -450,7 +473,7 @@ func TestLogPoller_Replay(t *testing.T) { go func() { defer close(done) - head.Store(&evmtypes.Head{Number: 4}) // Restore latest block to 4, so this matches the fromBlock requested + head.Store(newHead(4)) // Restore latest block to 4, so this matches the fromBlock requested select { case lp.replayStart <- 4: case <-ctx.Done(): @@ -471,7 +494,7 @@ func TestLogPoller_Replay(t *testing.T) { ec.On("FilterLogs", mock.Anything, mock.Anything).Return([]types.Log{log1}, nil) t.Cleanup(lp.reset) - head.Store(&evmtypes.Head{Number: 5}) // Latest block must be > lastProcessed in order for SaveAndPollLogs() to call FilterLogs() + head.Store(newHead(6)) // Latest block must be > lastProcessed in order for SaveAndPollLogs() to call FilterLogs() servicetest.Run(t, lp) select { @@ -492,7 +515,7 @@ func TestLogPoller_Replay(t *testing.T) { lp.ReplayAsync(1) - recvStartReplay(testutils.Context(t), 2) + recvStartReplay(testutils.Context(t), 4) }) t.Run("ReplayAsync error", func(t *testing.T) { @@ -532,7 +555,7 @@ func TestLogPoller_Replay(t *testing.T) { require.NoError(t, err) h := head.Load() - err = lp.orm.InsertBlock(ctx, h.Hash, h.Number, h.Timestamp, h.Number) + err = lp.orm.InsertBlock(ctx, common.BigToHash(big.NewInt(h.Number)), h.Number, h.Timestamp, h.Number) require.NoError(t, err) ec.On("FilterLogs", mock.Anything, mock.Anything).Return([]types.Log{log1}, nil) @@ -603,25 +626,35 @@ func Test_FetchBlocks(t *testing.T) { cases := []struct { name string - blocksRequested []string + blocksRequested []uint64 + chainReference *LogPollerBlock expectedErr error - }{{ - "successful validation including finalized and latest", - []string{"0x3", "latest", "0x5", "finalized", "0x1"}, - nil, - }, { - "successful validation with all block numbers", - []string{"0x2", "0x5", "0x3", "0x4"}, - nil, - }, { - "finality violation including finalized and latest", - []string{"0x8", "0x2", "latest", "finalized"}, - errors.New("Received unfinalized block 8 while expecting finalized block (latestFinalizedBlockNumber = 5)"), - }, { - "finality violation with all block numbers", - []string{"0x9", "0x2", "finalized", "latest"}, - errors.New("Received unfinalized block 9 while expecting finalized block (latestFinalizedBlockNumber = 5)"), - }} + }{ + { + "All blocks are finalized from RPC's perspective, no reference", + []uint64{2, 5, 3, 4}, + nil, + nil, + }, + { + "RPC's latest finalized is lower than request, no reference", + []uint64{8, 2}, + nil, + errors.New("received unfinalized block 8 while expecting finalized block (latestFinalizedBlockNumber = 5)"), + }, + { + "All blocks are finalized, but chain reference does not match", + []uint64{2, 5, 3, 4}, + &LogPollerBlock{BlockNumber: 1, BlockHash: common.BigToHash(big.NewInt(2))}, + errors.New("expected RPC's finalized block hash at hegiht 1 to be 0x0000000000000000000000000000000000000000000000000000000000000002 but got 0x0000000000000000000000000000000000000000000000000000000000000001: finality violated"), + }, + { + "All blocks are finalized and chain reference matches", + []uint64{2, 5, 3, 4}, + &LogPollerBlock{BlockNumber: 1, BlockHash: common.BigToHash(big.NewInt(1))}, + nil, + }, + } lp := NewLogPoller(orm, ec, lggr, nil, lpOpts) for _, tc := range cases { @@ -631,29 +664,111 @@ func Test_FetchBlocks(t *testing.T) { blockValidationReq = finalizedBlock } t.Run(fmt.Sprintf("%s where useFinalityTag=%t", tc.name, lp.useFinalityTag), func(t *testing.T) { - blocks, err := lp.fetchBlocks(ctx, tc.blocksRequested, blockValidationReq) + blocks, err := lp.fetchBlocks(ctx, tc.blocksRequested, blockValidationReq, tc.chainReference) if tc.expectedErr != nil { require.Equal(t, err.Error(), tc.expectedErr.Error()) return // PASS } require.NoError(t, err) - for i, blockRequested := range tc.blocksRequested { - switch blockRequested { - case string(latestBlock): - assert.Equal(t, int64(8), blocks[i].Number) - case string(finalizedBlock): - assert.Equal(t, int64(5), blocks[i].Number) - default: - blockNum, err2 := hexutil.DecodeUint64(blockRequested) - require.NoError(t, err2) - assert.Equal(t, int64(blockNum), blocks[i].Number) - } + for _, blockRequested := range tc.blocksRequested { + assert.Equal(t, blockRequested, uint64(blocks[blockRequested].Number)) //nolint:gosec // G115 } }) } } } +func Test_PollAndSaveLogs_BackfillFinalityViolation(t *testing.T) { + t.Parallel() + + db := pgtest.NewSqlxDB(t) + lpOpts := Opts{ + PollPeriod: time.Second, + FinalityDepth: 3, + BackfillBatchSize: 3, + RpcBatchSize: 3, + KeepFinalizedBlocksDepth: 20, + BackupPollerBlockDelay: 0, + } + t.Run("Finalized DB block is not present in RPC's chain", func(t *testing.T) { + lggr, _ := logger.TestObserved(t, zapcore.ErrorLevel) + orm := NewORM(testutils.NewRandomEVMChainID(), db, lggr) + headTracker := htMocks.NewHeadTracker[*evmtypes.Head, common.Hash](t) + finalized := newHead(5) + latest := newHead(16) + headTracker.EXPECT().LatestAndFinalizedBlock(mock.Anything).RunAndReturn(func(ctx context.Context) (*evmtypes.Head, *evmtypes.Head, error) { + return latest, finalized, nil + }).Once() + ec := evmclimocks.NewClient(t) + ec.EXPECT().HeadByNumber(mock.Anything, mock.Anything).RunAndReturn(func(ctx context.Context, number *big.Int) (*evmtypes.Head, error) { + return newHead(number.Int64()), nil + }) + ec.EXPECT().FilterLogs(mock.Anything, mock.Anything).Return([]types.Log{{BlockNumber: 5}}, nil).Once() + mockBatchCallContext(t, ec) + // insert finalized block with different hash than in RPC + require.NoError(t, orm.InsertBlock(tests.Context(t), common.HexToHash("0x123"), 2, time.Unix(10, 0), 2)) + lp := NewLogPoller(orm, ec, lggr, headTracker, lpOpts) + lp.PollAndSaveLogs(tests.Context(t), 4) + require.ErrorIs(t, lp.HealthReport()[lp.Name()], commontypes.ErrFinalityViolated) + }) + t.Run("RPCs contradict each other and return different finalized blocks", func(t *testing.T) { + lggr, _ := logger.TestObserved(t, zapcore.ErrorLevel) + orm := NewORM(testutils.NewRandomEVMChainID(), db, lggr) + headTracker := htMocks.NewHeadTracker[*evmtypes.Head, common.Hash](t) + finalized := newHead(5) + latest := newHead(16) + headTracker.EXPECT().LatestAndFinalizedBlock(mock.Anything).Return(latest, finalized, nil).Once() + ec := evmclimocks.NewClient(t) + ec.EXPECT().HeadByNumber(mock.Anything, mock.Anything).RunAndReturn(func(ctx context.Context, number *big.Int) (*evmtypes.Head, error) { + return newHead(number.Int64()), nil + }) + ec.EXPECT().FilterLogs(mock.Anything, mock.Anything).Return([]types.Log{{BlockNumber: 5}}, nil).Once() + mockBatchCallContextWithHead(t, ec, func(num int64) evmtypes.Head { + // return new hash for every call + return evmtypes.Head{Number: num, Hash: utils.NewHash()} + }) + lp := NewLogPoller(orm, ec, lggr, headTracker, lpOpts) + lp.PollAndSaveLogs(tests.Context(t), 4) + require.ErrorIs(t, lp.HealthReport()[lp.Name()], commontypes.ErrFinalityViolated) + }) + t.Run("Log's hash does not match block's", func(t *testing.T) { + lggr, _ := logger.TestObserved(t, zapcore.ErrorLevel) + orm := NewORM(testutils.NewRandomEVMChainID(), db, lggr) + headTracker := htMocks.NewHeadTracker[*evmtypes.Head, common.Hash](t) + finalized := newHead(5) + latest := newHead(16) + headTracker.EXPECT().LatestAndFinalizedBlock(mock.Anything).Return(latest, finalized, nil).Once() + ec := evmclimocks.NewClient(t) + ec.EXPECT().HeadByNumber(mock.Anything, mock.Anything).RunAndReturn(func(ctx context.Context, number *big.Int) (*evmtypes.Head, error) { + return newHead(number.Int64()), nil + }) + ec.EXPECT().FilterLogs(mock.Anything, mock.Anything).Return([]types.Log{{BlockNumber: 5, BlockHash: common.HexToHash("0x123")}}, nil).Once() + mockBatchCallContext(t, ec) + lp := NewLogPoller(orm, ec, lggr, headTracker, lpOpts) + lp.PollAndSaveLogs(tests.Context(t), 4) + require.ErrorIs(t, lp.HealthReport()[lp.Name()], commontypes.ErrFinalityViolated) + }) + t.Run("Happy path", func(t *testing.T) { + lggr, _ := logger.TestObserved(t, zapcore.ErrorLevel) + chainID := testutils.NewRandomEVMChainID() + orm := NewORM(chainID, db, lggr) + headTracker := htMocks.NewHeadTracker[*evmtypes.Head, common.Hash](t) + finalized := newHead(5) + latest := newHead(16) + headTracker.EXPECT().LatestAndFinalizedBlock(mock.Anything).Return(latest, finalized, nil).Once() + ec := evmclimocks.NewClient(t) + ec.EXPECT().ConfiguredChainID().Return(chainID) + ec.EXPECT().HeadByNumber(mock.Anything, mock.Anything).RunAndReturn(func(ctx context.Context, number *big.Int) (*evmtypes.Head, error) { + return newHead(number.Int64()), nil + }) + ec.EXPECT().FilterLogs(mock.Anything, mock.Anything).Return([]types.Log{{BlockNumber: 5, BlockHash: common.BigToHash(big.NewInt(5)), Topics: []common.Hash{{}}}}, nil).Once() + mockBatchCallContext(t, ec) + lp := NewLogPoller(orm, ec, lggr, headTracker, lpOpts) + lp.PollAndSaveLogs(tests.Context(t), 4) + require.NoError(t, lp.HealthReport()[lp.Name()]) + }) +} + func benchmarkFilter(b *testing.B, nFilters, nAddresses, nEvents int) { lggr := logger.Test(b) lpOpts := Opts{ diff --git a/core/chains/evm/logpoller/log_poller_test.go b/core/chains/evm/logpoller/log_poller_test.go index df688cd5e5c..4fb7202942c 100644 --- a/core/chains/evm/logpoller/log_poller_test.go +++ b/core/chains/evm/logpoller/log_poller_test.go @@ -38,7 +38,7 @@ import ( 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/gethwrappers/generated/log_emitter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/log_emitter" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" @@ -1343,7 +1343,7 @@ func TestLogPoller_GetBlocks_Range(t *testing.T) { blockNums = []uint64{2} _, err = th.LogPoller.GetBlocksRange(testutils.Context(t), blockNums) require.Error(t, err) - assert.Equal(t, "Received unfinalized block 2 while expecting finalized block (latestFinalizedBlockNumber = 1)", err.Error()) + assert.Equal(t, "received unfinalized block 2 while expecting finalized block (latestFinalizedBlockNumber = 1)", err.Error()) th.Backend.Commit() // Commit block #4, so that block #2 is finalized @@ -1412,12 +1412,6 @@ func TestLogPoller_GetBlocks_Range(t *testing.T) { _, err = th.LogPoller.GetBlocksRange(ctx, blockNums) require.Error(t, err) assert.Contains(t, err.Error(), "context canceled") - - // test canceled ctx - ctx, cancel = context.WithCancel(testutils.Context(t)) - cancel() - _, err = th.LogPoller.GetBlocksRange(ctx, blockNums) - require.Equal(t, err, context.Canceled) } func TestGetReplayFromBlock(t *testing.T) { @@ -1672,11 +1666,11 @@ func TestTooManyLogResults(t *testing.T) { crit := obs.FilterLevelExact(zapcore.DPanicLevel).All() errors := obs.FilterLevelExact(zapcore.ErrorLevel).All() warns := obs.FilterLevelExact(zapcore.WarnLevel).All() - assert.Len(t, crit, 0) - require.Len(t, errors, 1) - assert.Equal(t, errors[0].Message, "Unable to query for logs") - require.Len(t, warns, 1) - assert.Contains(t, warns[0].Message, "retrying later") + assert.Empty(t, crit) + require.Len(t, errors, 2) + assert.Contains(t, errors[0].Message, "Unable to query for logs") + assert.Contains(t, errors[1].Message, "Failed to poll and save logs, retrying later") + require.Empty(t, warns) }) } diff --git a/core/chains/evm/logpoller/mocks/log_poller.go b/core/chains/evm/logpoller/mocks/log_poller.go index 592157efb1c..444ee7d7e69 100644 --- a/core/chains/evm/logpoller/mocks/log_poller.go +++ b/core/chains/evm/logpoller/mocks/log_poller.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -31,7 +31,7 @@ func (_m *LogPoller) EXPECT() *LogPoller_Expecter { return &LogPoller_Expecter{mock: &_m.Mock} } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *LogPoller) Close() error { ret := _m.Called() @@ -301,7 +301,7 @@ func (_c *LogPoller_GetBlocksRange_Call) RunAndReturn(run func(context.Context, return _c } -// GetFilters provides a mock function with given fields: +// GetFilters provides a mock function with no fields func (_m *LogPoller) GetFilters() map[string]logpoller.Filter { ret := _m.Called() @@ -394,7 +394,7 @@ func (_c *LogPoller_HasFilter_Call) RunAndReturn(run func(string) bool) *LogPoll return _c } -// HealthReport provides a mock function with given fields: +// HealthReport provides a mock function with no fields func (_m *LogPoller) HealthReport() map[string]error { ret := _m.Called() @@ -441,7 +441,7 @@ func (_c *LogPoller_HealthReport_Call) RunAndReturn(run func() map[string]error) return _c } -// Healthy provides a mock function with given fields: +// Healthy provides a mock function with no fields func (_m *LogPoller) Healthy() error { ret := _m.Called() @@ -1546,7 +1546,7 @@ func (_c *LogPoller_LogsWithSigs_Call) RunAndReturn(run func(context.Context, in return _c } -// Name provides a mock function with given fields: +// Name provides a mock function with no fields func (_m *LogPoller) Name() string { ret := _m.Called() @@ -1591,7 +1591,7 @@ func (_c *LogPoller_Name_Call) RunAndReturn(run func() string) *LogPoller_Name_C return _c } -// Ready provides a mock function with given fields: +// Ready provides a mock function with no fields func (_m *LogPoller) Ready() error { ret := _m.Called() @@ -1759,7 +1759,7 @@ func (_c *LogPoller_ReplayAsync_Call) Return() *LogPoller_ReplayAsync_Call { } func (_c *LogPoller_ReplayAsync_Call) RunAndReturn(run func(int64)) *LogPoller_ReplayAsync_Call { - _c.Call.Return(run) + _c.Run(run) return _c } diff --git a/core/chains/evm/logpoller/orm.go b/core/chains/evm/logpoller/orm.go index 4d7cf33ebec..7b1dcfd8a3b 100644 --- a/core/chains/evm/logpoller/orm.go +++ b/core/chains/evm/logpoller/orm.go @@ -47,6 +47,7 @@ type ORM interface { SelectBlockByHash(ctx context.Context, hash common.Hash) (*LogPollerBlock, error) SelectLatestBlock(ctx context.Context) (*LogPollerBlock, error) SelectOldestBlock(ctx context.Context, minAllowedBlockNumber int64) (*LogPollerBlock, error) + SelectLatestFinalizedBlock(ctx context.Context) (*LogPollerBlock, error) 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) @@ -260,6 +261,18 @@ func (o *DSORM) SelectLatestBlock(ctx context.Context) (*LogPollerBlock, error) return &b, nil } +func (o *DSORM) SelectLatestFinalizedBlock(ctx context.Context) (*LogPollerBlock, error) { + var b LogPollerBlock + if err := o.ds.GetContext(ctx, &b, + blocksQuery(`WHERE evm_chain_id = $1 AND block_number <= ( + SELECT finalized_block_number FROM evm.log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1 + ) ORDER BY block_number DESC LIMIT 1`), ubig.New(o.chainID), + ); err != nil { + return nil, err + } + return &b, nil +} + func (o *DSORM) SelectOldestBlock(ctx context.Context, minAllowedBlockNumber int64) (*LogPollerBlock, error) { var b LogPollerBlock if err := o.ds.GetContext(ctx, &b, diff --git a/core/chains/evm/logpoller/orm_test.go b/core/chains/evm/logpoller/orm_test.go index eeb6dfe3208..1beb47802ae 100644 --- a/core/chains/evm/logpoller/orm_test.go +++ b/core/chains/evm/logpoller/orm_test.go @@ -2419,3 +2419,35 @@ func TestSelectOldestBlock(t *testing.T) { require.Equal(t, block.BlockHash, common.HexToHash("0x1233")) }) } + +func TestSelectLatestFinalizedBlock(t *testing.T) { + t.Run("If finalized block is not present in DB return error", func(t *testing.T) { + th := SetupTH(t, lpOpts) + o1 := th.ORM + o2 := th.ORM2 + ctx := testutils.Context(t) + // o2's chain does not have finalized block + require.NoError(t, o2.InsertBlock(ctx, common.HexToHash("0x1231"), 11, time.Now(), 9)) + require.NoError(t, o2.InsertBlock(ctx, common.HexToHash("0x1234"), 10, time.Now(), 8)) + // o1 has finalized blocks + require.NoError(t, o1.InsertBlock(ctx, common.HexToHash("0x1233"), 11, time.Now(), 10)) + require.NoError(t, o1.InsertBlock(ctx, common.HexToHash("0x1232"), 10, time.Now(), 10)) + result, err := o2.SelectLatestFinalizedBlock(ctx) + require.ErrorIs(t, err, sql.ErrNoRows) + require.Nil(t, result) + }) + t.Run("Returns latest finalized block even if there is no exact match by block number", func(t *testing.T) { + th := SetupTH(t, lpOpts) + o1 := th.ORM + ctx := testutils.Context(t) + require.NoError(t, o1.InsertBlock(ctx, common.HexToHash("0x1233"), 12, time.Now(), 10)) + require.NoError(t, o1.InsertBlock(ctx, common.HexToHash("0x1232"), 11, time.Now(), 9)) + require.NoError(t, o1.InsertBlock(ctx, common.HexToHash("0x1231"), 5, time.Now(), 4)) + require.NoError(t, o1.InsertBlock(ctx, common.HexToHash("0x1230"), 4, time.Now(), 4)) + result, err := o1.SelectLatestFinalizedBlock(ctx) + require.NoError(t, err) + require.NotNil(t, result) + require.Equal(t, int64(5), result.BlockNumber) + require.Equal(t, common.HexToHash("0x1231"), result.BlockHash) + }) +} diff --git a/core/chains/evm/mocks/balance_monitor.go b/core/chains/evm/mocks/balance_monitor.go index 95382541179..abb86909046 100644 --- a/core/chains/evm/mocks/balance_monitor.go +++ b/core/chains/evm/mocks/balance_monitor.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -26,7 +26,7 @@ func (_m *BalanceMonitor) EXPECT() *BalanceMonitor_Expecter { return &BalanceMonitor_Expecter{mock: &_m.Mock} } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *BalanceMonitor) Close() error { ret := _m.Called() @@ -119,7 +119,7 @@ func (_c *BalanceMonitor_GetEthBalance_Call) RunAndReturn(run func(common.Addres return _c } -// HealthReport provides a mock function with given fields: +// HealthReport provides a mock function with no fields func (_m *BalanceMonitor) HealthReport() map[string]error { ret := _m.Called() @@ -166,7 +166,7 @@ func (_c *BalanceMonitor_HealthReport_Call) RunAndReturn(run func() map[string]e return _c } -// Name provides a mock function with given fields: +// Name provides a mock function with no fields func (_m *BalanceMonitor) Name() string { ret := _m.Called() @@ -241,11 +241,11 @@ func (_c *BalanceMonitor_OnNewLongestChain_Call) Return() *BalanceMonitor_OnNewL } func (_c *BalanceMonitor_OnNewLongestChain_Call) RunAndReturn(run func(context.Context, *types.Head)) *BalanceMonitor_OnNewLongestChain_Call { - _c.Call.Return(run) + _c.Run(run) return _c } -// Ready provides a mock function with given fields: +// Ready provides a mock function with no fields func (_m *BalanceMonitor) Ready() error { ret := _m.Called() diff --git a/core/chains/evm/txm/attempt_builder.go b/core/chains/evm/txm/attempt_builder.go new file mode 100644 index 00000000000..16ed0f1a86a --- /dev/null +++ b/core/chains/evm/txm/attempt_builder.go @@ -0,0 +1,161 @@ +package txm + +import ( + "context" + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/common" + evmtypes "github.com/ethereum/go-ethereum/core/types" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txm/types" +) + +type AttemptBuilderKeystore interface { + SignTx(ctx context.Context, fromAddress common.Address, tx *evmtypes.Transaction, chainID *big.Int) (*evmtypes.Transaction, error) +} + +type attemptBuilder struct { + gas.EvmFeeEstimator + chainID *big.Int + priceMaxKey func(common.Address) *assets.Wei + keystore AttemptBuilderKeystore +} + +func NewAttemptBuilder(chainID *big.Int, priceMaxKey func(common.Address) *assets.Wei, estimator gas.EvmFeeEstimator, keystore AttemptBuilderKeystore) *attemptBuilder { + return &attemptBuilder{ + chainID: chainID, + priceMaxKey: priceMaxKey, + EvmFeeEstimator: estimator, + keystore: keystore, + } +} + +func (a *attemptBuilder) NewAttempt(ctx context.Context, lggr logger.Logger, tx *types.Transaction, dynamic bool) (*types.Attempt, error) { + fee, estimatedGasLimit, err := a.EvmFeeEstimator.GetFee(ctx, tx.Data, tx.SpecifiedGasLimit, a.priceMaxKey(tx.FromAddress), &tx.FromAddress, &tx.ToAddress) + if err != nil { + return nil, err + } + txType := evmtypes.LegacyTxType + if dynamic { + txType = evmtypes.DynamicFeeTxType + } + return a.newCustomAttempt(ctx, tx, fee, estimatedGasLimit, byte(txType), lggr) +} + +func (a *attemptBuilder) NewBumpAttempt(ctx context.Context, lggr logger.Logger, tx *types.Transaction, previousAttempt types.Attempt) (*types.Attempt, error) { + bumpedFee, bumpedFeeLimit, err := a.EvmFeeEstimator.BumpFee(ctx, previousAttempt.Fee, tx.SpecifiedGasLimit, a.priceMaxKey(tx.FromAddress), nil) + if err != nil { + return nil, err + } + return a.newCustomAttempt(ctx, tx, bumpedFee, bumpedFeeLimit, previousAttempt.Type, lggr) +} + +func (a *attemptBuilder) newCustomAttempt( + ctx context.Context, + tx *types.Transaction, + fee gas.EvmFee, + estimatedGasLimit uint64, + txType byte, + lggr logger.Logger, +) (attempt *types.Attempt, err error) { + switch txType { + case 0x0: + if fee.GasPrice == nil { + err = fmt.Errorf("tried to create attempt of type %v for txID: %v but estimator did not return legacy fee", txType, tx.ID) + logger.Sugared(lggr).AssumptionViolation(err.Error()) + return + } + return a.newLegacyAttempt(ctx, tx, fee.GasPrice, estimatedGasLimit) + case 0x2: + if !fee.ValidDynamic() { + err = fmt.Errorf("tried to create attempt of type %v for txID: %v but estimator did not return dynamic fee", txType, tx.ID) + logger.Sugared(lggr).AssumptionViolation(err.Error()) + return + } + return a.newDynamicFeeAttempt(ctx, tx, fee.DynamicFee, estimatedGasLimit) + default: + return nil, fmt.Errorf("cannot build attempt, unrecognized transaction type: %v", txType) + } +} + +func (a *attemptBuilder) newLegacyAttempt(ctx context.Context, tx *types.Transaction, gasPrice *assets.Wei, estimatedGasLimit uint64) (*types.Attempt, error) { + var data []byte + var toAddress common.Address + value := big.NewInt(0) + if !tx.IsPurgeable { + data = tx.Data + toAddress = tx.ToAddress + value = tx.Value + } + if tx.Nonce == nil { + return nil, fmt.Errorf("failed to create attempt for txID: %v: nonce empty", tx.ID) + } + legacyTx := evmtypes.LegacyTx{ + Nonce: *tx.Nonce, + To: &toAddress, + Value: value, + Gas: estimatedGasLimit, + GasPrice: gasPrice.ToInt(), + Data: data, + } + + signedTx, err := a.keystore.SignTx(ctx, tx.FromAddress, evmtypes.NewTx(&legacyTx), a.chainID) + if err != nil { + return nil, fmt.Errorf("failed to sign attempt for txID: %v, err: %w", tx.ID, err) + } + + attempt := &types.Attempt{ + TxID: tx.ID, + Fee: gas.EvmFee{GasPrice: gasPrice}, + Hash: signedTx.Hash(), + GasLimit: estimatedGasLimit, + Type: evmtypes.LegacyTxType, + SignedTransaction: signedTx, + } + + return attempt, nil +} + +func (a *attemptBuilder) newDynamicFeeAttempt(ctx context.Context, tx *types.Transaction, dynamicFee gas.DynamicFee, estimatedGasLimit uint64) (*types.Attempt, error) { + var data []byte + var toAddress common.Address + value := big.NewInt(0) + if !tx.IsPurgeable { + data = tx.Data + toAddress = tx.ToAddress + value = tx.Value + } + if tx.Nonce == nil { + return nil, fmt.Errorf("failed to create attempt for txID: %v: nonce empty", tx.ID) + } + dynamicTx := evmtypes.DynamicFeeTx{ + Nonce: *tx.Nonce, + To: &toAddress, + Value: value, + Gas: estimatedGasLimit, + GasFeeCap: dynamicFee.GasFeeCap.ToInt(), + GasTipCap: dynamicFee.GasTipCap.ToInt(), + Data: data, + } + + signedTx, err := a.keystore.SignTx(ctx, tx.FromAddress, evmtypes.NewTx(&dynamicTx), a.chainID) + if err != nil { + return nil, fmt.Errorf("failed to sign attempt for txID: %v, err: %w", tx.ID, err) + } + + attempt := &types.Attempt{ + TxID: tx.ID, + Fee: gas.EvmFee{DynamicFee: gas.DynamicFee{GasFeeCap: dynamicFee.GasFeeCap, GasTipCap: dynamicFee.GasTipCap}}, + Hash: signedTx.Hash(), + GasLimit: estimatedGasLimit, + Type: evmtypes.DynamicFeeTxType, + SignedTransaction: signedTx, + } + + return attempt, nil +} diff --git a/core/chains/evm/txm/attempt_builder_test.go b/core/chains/evm/txm/attempt_builder_test.go new file mode 100644 index 00000000000..65330cd39d7 --- /dev/null +++ b/core/chains/evm/txm/attempt_builder_test.go @@ -0,0 +1,97 @@ +package txm + +import ( + "math/big" + "testing" + + evmtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/keystore/mocks" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/testutils" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txm/types" +) + +func TestAttemptBuilder_newLegacyAttempt(t *testing.T) { + ks := mocks.NewEth(t) + ab := NewAttemptBuilder(testutils.FixtureChainID, nil, nil, ks) + address := testutils.NewAddress() + toAddress := testutils.NewAddress() + lggr := logger.Test(t) + var gasLimit uint64 = 100 + + t.Run("fails if GasPrice is nil", func(t *testing.T) { + tx := &types.Transaction{ID: 10, FromAddress: address} + _, err := ab.newCustomAttempt(tests.Context(t), tx, gas.EvmFee{DynamicFee: gas.DynamicFee{GasTipCap: assets.NewWeiI(1), GasFeeCap: assets.NewWeiI(2)}}, gasLimit, evmtypes.LegacyTxType, lggr) + require.Error(t, err) + assert.Contains(t, err.Error(), "estimator did not return legacy fee") + }) + + t.Run("fails if tx doesn't have a nonce", func(t *testing.T) { + tx := &types.Transaction{ID: 10, FromAddress: address} + _, err := ab.newCustomAttempt(tests.Context(t), tx, gas.EvmFee{GasPrice: assets.NewWeiI(25)}, gasLimit, evmtypes.LegacyTxType, lggr) + require.Error(t, err) + assert.Contains(t, err.Error(), "nonce empty") + }) + + t.Run("creates attempt with fields", func(t *testing.T) { + var nonce uint64 = 77 + tx := &types.Transaction{ID: 10, FromAddress: address, Nonce: &nonce} + legacyTx := evmtypes.NewTx(&evmtypes.LegacyTx{Nonce: nonce, To: &toAddress, Gas: gasLimit, GasPrice: big.NewInt(25)}) + ks.On("SignTx", mock.Anything, mock.Anything, mock.Anything, testutils.FixtureChainID).Return(legacyTx, nil).Once() + a, err := ab.newCustomAttempt(tests.Context(t), tx, gas.EvmFee{GasPrice: assets.NewWeiI(25)}, gasLimit, evmtypes.LegacyTxType, lggr) + require.NoError(t, err) + assert.Equal(t, tx.ID, a.TxID) + assert.Equal(t, evmtypes.LegacyTxType, int(a.Type)) + assert.NotNil(t, a.Fee.GasPrice) + assert.Equal(t, "25 wei", a.Fee.GasPrice.String()) + assert.Nil(t, a.Fee.GasTipCap) + assert.Nil(t, a.Fee.GasFeeCap) + assert.Equal(t, gasLimit, a.GasLimit) + }) +} + +func TestAttemptBuilder_newDynamicFeeAttempt(t *testing.T) { + ks := mocks.NewEth(t) + ab := NewAttemptBuilder(testutils.FixtureChainID, nil, nil, ks) + address := testutils.NewAddress() + toAddress := testutils.NewAddress() + lggr := logger.Test(t) + var gasLimit uint64 = 100 + + t.Run("fails if DynamicFee is invalid", func(t *testing.T) { + tx := &types.Transaction{ID: 10, FromAddress: address} + _, err := ab.newCustomAttempt(tests.Context(t), tx, gas.EvmFee{GasPrice: assets.NewWeiI(1)}, gasLimit, evmtypes.DynamicFeeTxType, lggr) + require.Error(t, err) + assert.Contains(t, err.Error(), "estimator did not return dynamic fee") + }) + + t.Run("fails if tx doesn't have a nonce", func(t *testing.T) { + tx := &types.Transaction{ID: 10, FromAddress: address} + _, err := ab.newCustomAttempt(tests.Context(t), tx, gas.EvmFee{DynamicFee: gas.DynamicFee{GasTipCap: assets.NewWeiI(1), GasFeeCap: assets.NewWeiI(2)}}, gasLimit, evmtypes.DynamicFeeTxType, lggr) + require.Error(t, err) + assert.Contains(t, err.Error(), "nonce empty") + }) + + t.Run("creates attempt with fields", func(t *testing.T) { + var nonce uint64 = 77 + tx := &types.Transaction{ID: 10, FromAddress: address, Nonce: &nonce} + legacyTx := evmtypes.NewTx(&evmtypes.LegacyTx{Nonce: nonce, To: &toAddress, Gas: gasLimit, GasPrice: big.NewInt(25)}) + ks.On("SignTx", mock.Anything, mock.Anything, mock.Anything, testutils.FixtureChainID).Return(legacyTx, nil).Once() + a, err := ab.newCustomAttempt(tests.Context(t), tx, gas.EvmFee{DynamicFee: gas.DynamicFee{GasTipCap: assets.NewWeiI(1), GasFeeCap: assets.NewWeiI(2)}}, gasLimit, evmtypes.DynamicFeeTxType, lggr) + require.NoError(t, err) + assert.Equal(t, tx.ID, a.TxID) + assert.Equal(t, evmtypes.DynamicFeeTxType, int(a.Type)) + assert.Equal(t, "1 wei", a.Fee.DynamicFee.GasTipCap.String()) + assert.Equal(t, "2 wei", a.Fee.DynamicFee.GasFeeCap.String()) + assert.Nil(t, a.Fee.GasPrice) + assert.Equal(t, gasLimit, a.GasLimit) + }) +} diff --git a/core/chains/evm/txm/clientwrappers/chain_client.go b/core/chains/evm/txm/clientwrappers/chain_client.go new file mode 100644 index 00000000000..7638cc53443 --- /dev/null +++ b/core/chains/evm/txm/clientwrappers/chain_client.go @@ -0,0 +1,31 @@ +package clientwrappers + +import ( + "context" + "math/big" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txm/types" +) + +type ChainClient struct { + c client.Client +} + +func NewChainClient(client client.Client) *ChainClient { + return &ChainClient{c: client} +} + +func (c *ChainClient) NonceAt(ctx context.Context, address common.Address, blockNumber *big.Int) (uint64, error) { + return c.c.NonceAt(ctx, address, blockNumber) +} + +func (c *ChainClient) PendingNonceAt(ctx context.Context, address common.Address) (uint64, error) { + return c.c.PendingNonceAt(ctx, address) +} + +func (c *ChainClient) SendTransaction(ctx context.Context, _ *types.Transaction, attempt *types.Attempt) error { + return c.c.SendTransaction(ctx, attempt.SignedTransaction) +} diff --git a/core/chains/evm/txm/clientwrappers/dual_broadcast_client.go b/core/chains/evm/txm/clientwrappers/dual_broadcast_client.go new file mode 100644 index 00000000000..481c26cbc2b --- /dev/null +++ b/core/chains/evm/txm/clientwrappers/dual_broadcast_client.go @@ -0,0 +1,128 @@ +package clientwrappers + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "io" + "math/big" + "net/http" + "net/url" + + "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/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txm/types" +) + +type DualBroadcastClientKeystore interface { + SignMessage(ctx context.Context, address common.Address, message []byte) ([]byte, error) +} + +type DualBroadcastClient struct { + c client.Client + keystore DualBroadcastClientKeystore + customURL *url.URL +} + +func NewDualBroadcastClient(c client.Client, keystore DualBroadcastClientKeystore, customURL *url.URL) *DualBroadcastClient { + return &DualBroadcastClient{ + c: c, + keystore: keystore, + customURL: customURL, + } +} + +func (d *DualBroadcastClient) NonceAt(ctx context.Context, address common.Address, blockNumber *big.Int) (uint64, error) { + return d.c.NonceAt(ctx, address, blockNumber) +} + +func (d *DualBroadcastClient) PendingNonceAt(ctx context.Context, address common.Address) (uint64, error) { + body := []byte(fmt.Sprintf(`{"jsonrpc":"2.0","method":"eth_getTransactionCount","params":["%s","pending"], "id":1}`, address.String())) + response, err := d.signAndPostMessage(ctx, address, body, "") + if err != nil { + return 0, err + } + + nonce, err := hexutil.DecodeUint64(response) + if err != nil { + return 0, fmt.Errorf("failed to decode response %v into uint64: %w", response, err) + } + return nonce, nil +} + +func (d *DualBroadcastClient) SendTransaction(ctx context.Context, tx *types.Transaction, attempt *types.Attempt) error { + meta, err := tx.GetMeta() + if err != nil { + return err + } + + if meta != nil && meta.DualBroadcast != nil && *meta.DualBroadcast && !tx.IsPurgeable { + data, err := attempt.SignedTransaction.MarshalBinary() + if err != nil { + return err + } + params := "" + if meta.DualBroadcastParams != nil { + params = *meta.DualBroadcastParams + } + body := []byte(fmt.Sprintf(`{"jsonrpc":"2.0","method":"eth_sendRawTransaction","params":["%s"], "id":1}`, hexutil.Encode(data))) + _, err = d.signAndPostMessage(ctx, tx.FromAddress, body, params) + return err + } + + return d.c.SendTransaction(ctx, attempt.SignedTransaction) +} + +func (d *DualBroadcastClient) signAndPostMessage(ctx context.Context, address common.Address, body []byte, urlParams string) (result string, err error) { + bodyReader := bytes.NewReader(body) + postReq, err := http.NewRequestWithContext(ctx, http.MethodPost, d.customURL.String()+"?"+urlParams, bodyReader) + if err != nil { + return + } + + hashedBody := crypto.Keccak256Hash(body).Hex() + signedMessage, err := d.keystore.SignMessage(ctx, address, []byte(hashedBody)) + if err != nil { + return + } + + postReq.Header.Add("X-Flashbots-signature", address.String()+":"+hexutil.Encode(signedMessage)) + postReq.Header.Add("Content-Type", "application/json") + + resp, err := http.DefaultClient.Do(postReq) + if err != nil { + return result, fmt.Errorf("request %v failed: %w", postReq, err) + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return result, fmt.Errorf("request %v failed with status: %d", postReq, resp.StatusCode) + } + + keyJSON, err := io.ReadAll(resp.Body) + if err != nil { + return + } + var response postResponse + err = json.Unmarshal(keyJSON, &response) + if err != nil { + return result, fmt.Errorf("failed to unmarshal response into struct: %w: %s", err, string(keyJSON)) + } + if response.Error.Message != "" { + return result, errors.New(response.Error.Message) + } + return response.Result, nil +} + +type postResponse struct { + Result string `json:"result,omitempty"` + Error postError +} + +type postError struct { + Message string `json:"message,omitempty"` +} diff --git a/core/chains/evm/txm/clientwrappers/geth_client.go b/core/chains/evm/txm/clientwrappers/geth_client.go new file mode 100644 index 00000000000..d97e5cfae35 --- /dev/null +++ b/core/chains/evm/txm/clientwrappers/geth_client.go @@ -0,0 +1,51 @@ +package clientwrappers + +import ( + "context" + "math/big" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/rpc" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txm/types" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" +) + +type GethClient struct { + *ethclient.Client +} + +func NewGethClient(client *ethclient.Client) *GethClient { + return &GethClient{ + Client: client, + } +} + +func (g *GethClient) BatchCallContext(ctx context.Context, b []rpc.BatchElem) error { + return g.Client.Client().BatchCallContext(ctx, b) +} + +func (g *GethClient) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error { + return g.Client.Client().CallContext(ctx, result, method, args...) +} + +func (g *GethClient) CallContract(ctx context.Context, message ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) { + var hex hexutil.Bytes + err := g.CallContext(ctx, &hex, "eth_call", client.ToBackwardCompatibleCallArg(message), client.ToBackwardCompatibleBlockNumArg(blockNumber)) + return hex, err +} + +func (g *GethClient) HeadByNumber(ctx context.Context, number *big.Int) (*evmtypes.Head, error) { + hexNumber := client.ToBlockNumArg(number) + args := []interface{}{hexNumber, false} + head := new(evmtypes.Head) + err := g.CallContext(ctx, head, "eth_getBlockByNumber", args...) + return head, err +} + +func (g *GethClient) SendTransaction(ctx context.Context, _ *types.Transaction, attempt *types.Attempt) error { + return g.Client.SendTransaction(ctx, attempt.SignedTransaction) +} diff --git a/core/chains/evm/txm/docs/TRANSACTION_MANAGER_V2.md b/core/chains/evm/txm/docs/TRANSACTION_MANAGER_V2.md new file mode 100644 index 00000000000..29531f58ebc --- /dev/null +++ b/core/chains/evm/txm/docs/TRANSACTION_MANAGER_V2.md @@ -0,0 +1,14 @@ + +# Transaction Manager V2 + +## Configs +- `EIP1559`: enables EIP-1559 mode. This means the transaction manager will create and broadcast Dynamic attempts. Set this to false to broadcast Legacy transactions. +- `BlockTime`: controls the interval of the backfill loop. This dictates how frequently the transaction manager will check for confirmed transactions, rebroadcast stuck ones, and fill any nonce gaps. Transactions are getting confirmed only during new blocks so it's best if you set this to a value close to the block time. At least one RPC call is made during each BlockTime interval so the recommended minimum is 2s. A small jitter is applied so the timeout won't be exactly the same each time. +- `RetryBlockThreshold`: is the number of blocks to wait for a transaction stuck in the mempool before automatically rebroadcasting it with a new attempt. +- `EmptyTxLimitDefault`: sets default gas limit for empty transactions. Empty transactions are created in case there is a nonce gap or another stuck transaction in the mempool to fill a given nonce. These are empty transactions and they don't have any data or value. + +## Metrics +- `txm_num_broadcasted_transactions`: total number of successful broadcasted transactions. +- `txm_num_confirmed_transactions`: total number of confirmed transactions. Note that this can happen multiple times per transaction in the case of re-orgs. +- `txm_num_nonce_gaps`: total number of nonce gaps created that the transaction manager had to fill. +- `txm_time_until_tx_confirmed`: The amount of time elapsed from a transaction being broadcast to being included in a block. diff --git a/core/chains/evm/txm/dummy_keystore.go b/core/chains/evm/txm/dummy_keystore.go new file mode 100644 index 00000000000..01816dfcbbd --- /dev/null +++ b/core/chains/evm/txm/dummy_keystore.go @@ -0,0 +1,64 @@ +package txm + +import ( + "context" + "crypto/ecdsa" + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" +) + +type DummyKeystore struct { + privateKeyMap map[common.Address]*ecdsa.PrivateKey +} + +func NewKeystore() *DummyKeystore { + return &DummyKeystore{privateKeyMap: make(map[common.Address]*ecdsa.PrivateKey)} +} + +func (k *DummyKeystore) Add(privateKeyString string) error { + privateKey, err := crypto.HexToECDSA(privateKeyString) + if err != nil { + return err + } + + publicKey := privateKey.Public() + publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) + if !ok { + return fmt.Errorf("error casting public key: %v to ECDSA", publicKey) + } + + address := crypto.PubkeyToAddress(*publicKeyECDSA) + k.privateKeyMap[address] = privateKey + return nil +} + +func (k *DummyKeystore) SignTx(_ context.Context, fromAddress common.Address, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { + if key, exists := k.privateKeyMap[fromAddress]; exists { + return types.SignTx(tx, types.LatestSignerForChainID(chainID), key) + } + return nil, fmt.Errorf("private key for address: %v not found", fromAddress) +} + +func (k *DummyKeystore) SignMessage(ctx context.Context, address common.Address, data []byte) ([]byte, error) { + key, exists := k.privateKeyMap[address] + if !exists { + return nil, fmt.Errorf("private key for address: %v not found", address) + } + signature, err := crypto.Sign(accounts.TextHash(data), key) + if err != nil { + return nil, fmt.Errorf("failed to sign message for address: %v", address) + } + return signature, nil +} + +func (k *DummyKeystore) EnabledAddressesForChain(_ context.Context, _ *big.Int) (addresses []common.Address, err error) { + for address := range k.privateKeyMap { + addresses = append(addresses, address) + } + return +} diff --git a/core/chains/evm/txm/metrics.go b/core/chains/evm/txm/metrics.go new file mode 100644 index 00000000000..5ccc711ef09 --- /dev/null +++ b/core/chains/evm/txm/metrics.go @@ -0,0 +1,93 @@ +package txm + +import ( + "context" + "fmt" + "math/big" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" + "go.opentelemetry.io/otel/metric" + + "github.com/smartcontractkit/chainlink-common/pkg/beholder" + "github.com/smartcontractkit/chainlink-common/pkg/metrics" +) + +var ( + promNumBroadcastedTxs = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "txm_num_broadcasted_transactions", + Help: "Total number of successful broadcasted transactions.", + }, []string{"chainID"}) + promNumConfirmedTxs = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "txm_num_confirmed_transactions", + Help: "Total number of confirmed transactions. Note that this can happen multiple times per transaction in the case of re-orgs or when filling the nonce for untracked transactions.", + }, []string{"chainID"}) + promNumNonceGaps = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "txm_num_nonce_gaps", + Help: "Total number of nonce gaps created that the transaction manager had to fill.", + }, []string{"chainID"}) + promTimeUntilTxConfirmed = promauto.NewHistogramVec(prometheus.HistogramOpts{ + Name: "txm_time_until_tx_confirmed", + Help: "The amount of time elapsed from a transaction being broadcast to being included in a block.", + }, []string{"chainID"}) +) + +type txmMetrics struct { + metrics.Labeler + chainID *big.Int + numBroadcastedTxs metric.Int64Counter + numConfirmedTxs metric.Int64Counter + numNonceGaps metric.Int64Counter + timeUntilTxConfirmed metric.Float64Histogram +} + +func NewTxmMetrics(chainID *big.Int) (*txmMetrics, error) { + numBroadcastedTxs, err := beholder.GetMeter().Int64Counter("txm_num_broadcasted_transactions") + if err != nil { + return nil, fmt.Errorf("failed to register broadcasted txs number: %w", err) + } + + numConfirmedTxs, err := beholder.GetMeter().Int64Counter("txm_num_confirmed_transactions") + if err != nil { + return nil, fmt.Errorf("failed to register confirmed txs number: %w", err) + } + + numNonceGaps, err := beholder.GetMeter().Int64Counter("txm_num_nonce_gaps") + if err != nil { + return nil, fmt.Errorf("failed to register nonce gaps number: %w", err) + } + + timeUntilTxConfirmed, err := beholder.GetMeter().Float64Histogram("txm_time_until_tx_confirmed") + if err != nil { + return nil, fmt.Errorf("failed to register time until tx confirmed: %w", err) + } + + return &txmMetrics{ + chainID: chainID, + Labeler: metrics.NewLabeler().With("chainID", chainID.String()), + numBroadcastedTxs: numBroadcastedTxs, + numConfirmedTxs: numConfirmedTxs, + numNonceGaps: numNonceGaps, + timeUntilTxConfirmed: timeUntilTxConfirmed, + }, nil +} + +func (m *txmMetrics) IncrementNumBroadcastedTxs(ctx context.Context) { + promNumBroadcastedTxs.WithLabelValues(m.chainID.String()).Add(float64(1)) + m.numBroadcastedTxs.Add(ctx, 1) +} + +func (m *txmMetrics) IncrementNumConfirmedTxs(ctx context.Context, confirmedTransactions int) { + promNumConfirmedTxs.WithLabelValues(m.chainID.String()).Add(float64(confirmedTransactions)) + m.numConfirmedTxs.Add(ctx, int64(confirmedTransactions)) +} + +func (m *txmMetrics) IncrementNumNonceGaps(ctx context.Context) { + promNumNonceGaps.WithLabelValues(m.chainID.String()).Add(float64(1)) + m.numNonceGaps.Add(ctx, 1) +} + +func (m *txmMetrics) RecordTimeUntilTxConfirmed(ctx context.Context, duration float64) { + promTimeUntilTxConfirmed.WithLabelValues(m.chainID.String()).Observe(duration) + m.timeUntilTxConfirmed.Record(ctx, duration) +} diff --git a/core/chains/evm/txm/mocks/attempt_builder.go b/core/chains/evm/txm/mocks/attempt_builder.go new file mode 100644 index 00000000000..91961e5d420 --- /dev/null +++ b/core/chains/evm/txm/mocks/attempt_builder.go @@ -0,0 +1,161 @@ +// Code generated by mockery v2.50.0. DO NOT EDIT. + +package mocks + +import ( + context "context" + + logger "github.com/smartcontractkit/chainlink-common/pkg/logger" + mock "github.com/stretchr/testify/mock" + + types "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txm/types" +) + +// AttemptBuilder is an autogenerated mock type for the AttemptBuilder type +type AttemptBuilder struct { + mock.Mock +} + +type AttemptBuilder_Expecter struct { + mock *mock.Mock +} + +func (_m *AttemptBuilder) EXPECT() *AttemptBuilder_Expecter { + return &AttemptBuilder_Expecter{mock: &_m.Mock} +} + +// NewAttempt provides a mock function with given fields: _a0, _a1, _a2, _a3 +func (_m *AttemptBuilder) NewAttempt(_a0 context.Context, _a1 logger.Logger, _a2 *types.Transaction, _a3 bool) (*types.Attempt, error) { + ret := _m.Called(_a0, _a1, _a2, _a3) + + if len(ret) == 0 { + panic("no return value specified for NewAttempt") + } + + var r0 *types.Attempt + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, logger.Logger, *types.Transaction, bool) (*types.Attempt, error)); ok { + return rf(_a0, _a1, _a2, _a3) + } + if rf, ok := ret.Get(0).(func(context.Context, logger.Logger, *types.Transaction, bool) *types.Attempt); ok { + r0 = rf(_a0, _a1, _a2, _a3) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Attempt) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, logger.Logger, *types.Transaction, bool) error); ok { + r1 = rf(_a0, _a1, _a2, _a3) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// AttemptBuilder_NewAttempt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'NewAttempt' +type AttemptBuilder_NewAttempt_Call struct { + *mock.Call +} + +// NewAttempt is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 logger.Logger +// - _a2 *types.Transaction +// - _a3 bool +func (_e *AttemptBuilder_Expecter) NewAttempt(_a0 interface{}, _a1 interface{}, _a2 interface{}, _a3 interface{}) *AttemptBuilder_NewAttempt_Call { + return &AttemptBuilder_NewAttempt_Call{Call: _e.mock.On("NewAttempt", _a0, _a1, _a2, _a3)} +} + +func (_c *AttemptBuilder_NewAttempt_Call) Run(run func(_a0 context.Context, _a1 logger.Logger, _a2 *types.Transaction, _a3 bool)) *AttemptBuilder_NewAttempt_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(logger.Logger), args[2].(*types.Transaction), args[3].(bool)) + }) + return _c +} + +func (_c *AttemptBuilder_NewAttempt_Call) Return(_a0 *types.Attempt, _a1 error) *AttemptBuilder_NewAttempt_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *AttemptBuilder_NewAttempt_Call) RunAndReturn(run func(context.Context, logger.Logger, *types.Transaction, bool) (*types.Attempt, error)) *AttemptBuilder_NewAttempt_Call { + _c.Call.Return(run) + return _c +} + +// NewBumpAttempt provides a mock function with given fields: _a0, _a1, _a2, _a3 +func (_m *AttemptBuilder) NewBumpAttempt(_a0 context.Context, _a1 logger.Logger, _a2 *types.Transaction, _a3 types.Attempt) (*types.Attempt, error) { + ret := _m.Called(_a0, _a1, _a2, _a3) + + if len(ret) == 0 { + panic("no return value specified for NewBumpAttempt") + } + + var r0 *types.Attempt + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, logger.Logger, *types.Transaction, types.Attempt) (*types.Attempt, error)); ok { + return rf(_a0, _a1, _a2, _a3) + } + if rf, ok := ret.Get(0).(func(context.Context, logger.Logger, *types.Transaction, types.Attempt) *types.Attempt); ok { + r0 = rf(_a0, _a1, _a2, _a3) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Attempt) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, logger.Logger, *types.Transaction, types.Attempt) error); ok { + r1 = rf(_a0, _a1, _a2, _a3) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// AttemptBuilder_NewBumpAttempt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'NewBumpAttempt' +type AttemptBuilder_NewBumpAttempt_Call struct { + *mock.Call +} + +// NewBumpAttempt is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 logger.Logger +// - _a2 *types.Transaction +// - _a3 types.Attempt +func (_e *AttemptBuilder_Expecter) NewBumpAttempt(_a0 interface{}, _a1 interface{}, _a2 interface{}, _a3 interface{}) *AttemptBuilder_NewBumpAttempt_Call { + return &AttemptBuilder_NewBumpAttempt_Call{Call: _e.mock.On("NewBumpAttempt", _a0, _a1, _a2, _a3)} +} + +func (_c *AttemptBuilder_NewBumpAttempt_Call) Run(run func(_a0 context.Context, _a1 logger.Logger, _a2 *types.Transaction, _a3 types.Attempt)) *AttemptBuilder_NewBumpAttempt_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(logger.Logger), args[2].(*types.Transaction), args[3].(types.Attempt)) + }) + return _c +} + +func (_c *AttemptBuilder_NewBumpAttempt_Call) Return(_a0 *types.Attempt, _a1 error) *AttemptBuilder_NewBumpAttempt_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *AttemptBuilder_NewBumpAttempt_Call) RunAndReturn(run func(context.Context, logger.Logger, *types.Transaction, types.Attempt) (*types.Attempt, error)) *AttemptBuilder_NewBumpAttempt_Call { + _c.Call.Return(run) + return _c +} + +// NewAttemptBuilder creates a new instance of AttemptBuilder. 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 NewAttemptBuilder(t interface { + mock.TestingT + Cleanup(func()) +}) *AttemptBuilder { + mock := &AttemptBuilder{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/core/chains/evm/txm/mocks/client.go b/core/chains/evm/txm/mocks/client.go new file mode 100644 index 00000000000..cac2e55491a --- /dev/null +++ b/core/chains/evm/txm/mocks/client.go @@ -0,0 +1,204 @@ +// Code generated by mockery v2.50.0. DO NOT EDIT. + +package mocks + +import ( + context "context" + big "math/big" + + common "github.com/ethereum/go-ethereum/common" + + mock "github.com/stretchr/testify/mock" + + types "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txm/types" +) + +// Client is an autogenerated mock type for the Client type +type Client struct { + mock.Mock +} + +type Client_Expecter struct { + mock *mock.Mock +} + +func (_m *Client) EXPECT() *Client_Expecter { + return &Client_Expecter{mock: &_m.Mock} +} + +// NonceAt provides a mock function with given fields: _a0, _a1, _a2 +func (_m *Client) NonceAt(_a0 context.Context, _a1 common.Address, _a2 *big.Int) (uint64, error) { + ret := _m.Called(_a0, _a1, _a2) + + if len(ret) == 0 { + panic("no return value specified for NonceAt") + } + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int) (uint64, error)); ok { + return rf(_a0, _a1, _a2) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int) uint64); ok { + r0 = rf(_a0, _a1, _a2) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Address, *big.Int) error); ok { + r1 = rf(_a0, _a1, _a2) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Client_NonceAt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'NonceAt' +type Client_NonceAt_Call struct { + *mock.Call +} + +// NonceAt is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 common.Address +// - _a2 *big.Int +func (_e *Client_Expecter) NonceAt(_a0 interface{}, _a1 interface{}, _a2 interface{}) *Client_NonceAt_Call { + return &Client_NonceAt_Call{Call: _e.mock.On("NonceAt", _a0, _a1, _a2)} +} + +func (_c *Client_NonceAt_Call) Run(run func(_a0 context.Context, _a1 common.Address, _a2 *big.Int)) *Client_NonceAt_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(common.Address), args[2].(*big.Int)) + }) + return _c +} + +func (_c *Client_NonceAt_Call) Return(_a0 uint64, _a1 error) *Client_NonceAt_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_NonceAt_Call) RunAndReturn(run func(context.Context, common.Address, *big.Int) (uint64, error)) *Client_NonceAt_Call { + _c.Call.Return(run) + return _c +} + +// PendingNonceAt provides a mock function with given fields: _a0, _a1 +func (_m *Client) PendingNonceAt(_a0 context.Context, _a1 common.Address) (uint64, error) { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for PendingNonceAt") + } + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Address) (uint64, error)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Address) uint64); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Address) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Client_PendingNonceAt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'PendingNonceAt' +type Client_PendingNonceAt_Call struct { + *mock.Call +} + +// PendingNonceAt is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 common.Address +func (_e *Client_Expecter) PendingNonceAt(_a0 interface{}, _a1 interface{}) *Client_PendingNonceAt_Call { + return &Client_PendingNonceAt_Call{Call: _e.mock.On("PendingNonceAt", _a0, _a1)} +} + +func (_c *Client_PendingNonceAt_Call) Run(run func(_a0 context.Context, _a1 common.Address)) *Client_PendingNonceAt_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(common.Address)) + }) + return _c +} + +func (_c *Client_PendingNonceAt_Call) Return(_a0 uint64, _a1 error) *Client_PendingNonceAt_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_PendingNonceAt_Call) RunAndReturn(run func(context.Context, common.Address) (uint64, error)) *Client_PendingNonceAt_Call { + _c.Call.Return(run) + return _c +} + +// SendTransaction provides a mock function with given fields: ctx, tx, attempt +func (_m *Client) SendTransaction(ctx context.Context, tx *types.Transaction, attempt *types.Attempt) error { + ret := _m.Called(ctx, tx, attempt) + + if len(ret) == 0 { + panic("no return value specified for SendTransaction") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *types.Transaction, *types.Attempt) error); ok { + r0 = rf(ctx, tx, attempt) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Client_SendTransaction_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendTransaction' +type Client_SendTransaction_Call struct { + *mock.Call +} + +// SendTransaction is a helper method to define mock.On call +// - ctx context.Context +// - tx *types.Transaction +// - attempt *types.Attempt +func (_e *Client_Expecter) SendTransaction(ctx interface{}, tx interface{}, attempt interface{}) *Client_SendTransaction_Call { + return &Client_SendTransaction_Call{Call: _e.mock.On("SendTransaction", ctx, tx, attempt)} +} + +func (_c *Client_SendTransaction_Call) Run(run func(ctx context.Context, tx *types.Transaction, attempt *types.Attempt)) *Client_SendTransaction_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*types.Transaction), args[2].(*types.Attempt)) + }) + return _c +} + +func (_c *Client_SendTransaction_Call) Return(_a0 error) *Client_SendTransaction_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Client_SendTransaction_Call) RunAndReturn(run func(context.Context, *types.Transaction, *types.Attempt) error) *Client_SendTransaction_Call { + _c.Call.Return(run) + return _c +} + +// NewClient creates a new instance of Client. 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 NewClient(t interface { + mock.TestingT + Cleanup(func()) +}) *Client { + mock := &Client{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/core/chains/evm/txm/mocks/keystore.go b/core/chains/evm/txm/mocks/keystore.go new file mode 100644 index 00000000000..3d11a6fa549 --- /dev/null +++ b/core/chains/evm/txm/mocks/keystore.go @@ -0,0 +1,98 @@ +// Code generated by mockery v2.50.0. DO NOT EDIT. + +package mocks + +import ( + context "context" + big "math/big" + + common "github.com/ethereum/go-ethereum/common" + + mock "github.com/stretchr/testify/mock" +) + +// Keystore is an autogenerated mock type for the Keystore type +type Keystore struct { + mock.Mock +} + +type Keystore_Expecter struct { + mock *mock.Mock +} + +func (_m *Keystore) EXPECT() *Keystore_Expecter { + return &Keystore_Expecter{mock: &_m.Mock} +} + +// EnabledAddressesForChain provides a mock function with given fields: ctx, chainID +func (_m *Keystore) EnabledAddressesForChain(ctx context.Context, chainID *big.Int) ([]common.Address, error) { + ret := _m.Called(ctx, chainID) + + if len(ret) == 0 { + panic("no return value specified for EnabledAddressesForChain") + } + + var r0 []common.Address + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *big.Int) ([]common.Address, error)); ok { + return rf(ctx, chainID) + } + if rf, ok := ret.Get(0).(func(context.Context, *big.Int) []common.Address); ok { + r0 = rf(ctx, chainID) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]common.Address) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *big.Int) error); ok { + r1 = rf(ctx, chainID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Keystore_EnabledAddressesForChain_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EnabledAddressesForChain' +type Keystore_EnabledAddressesForChain_Call struct { + *mock.Call +} + +// EnabledAddressesForChain is a helper method to define mock.On call +// - ctx context.Context +// - chainID *big.Int +func (_e *Keystore_Expecter) EnabledAddressesForChain(ctx interface{}, chainID interface{}) *Keystore_EnabledAddressesForChain_Call { + return &Keystore_EnabledAddressesForChain_Call{Call: _e.mock.On("EnabledAddressesForChain", ctx, chainID)} +} + +func (_c *Keystore_EnabledAddressesForChain_Call) Run(run func(ctx context.Context, chainID *big.Int)) *Keystore_EnabledAddressesForChain_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*big.Int)) + }) + return _c +} + +func (_c *Keystore_EnabledAddressesForChain_Call) Return(addresses []common.Address, err error) *Keystore_EnabledAddressesForChain_Call { + _c.Call.Return(addresses, err) + return _c +} + +func (_c *Keystore_EnabledAddressesForChain_Call) RunAndReturn(run func(context.Context, *big.Int) ([]common.Address, error)) *Keystore_EnabledAddressesForChain_Call { + _c.Call.Return(run) + return _c +} + +// NewKeystore creates a new instance of Keystore. 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 NewKeystore(t interface { + mock.TestingT + Cleanup(func()) +}) *Keystore { + mock := &Keystore{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/core/chains/evm/txm/mocks/tx_store.go b/core/chains/evm/txm/mocks/tx_store.go new file mode 100644 index 00000000000..318b36942b8 --- /dev/null +++ b/core/chains/evm/txm/mocks/tx_store.go @@ -0,0 +1,647 @@ +// Code generated by mockery v2.50.0. DO NOT EDIT. + +package mocks + +import ( + context "context" + + common "github.com/ethereum/go-ethereum/common" + + mock "github.com/stretchr/testify/mock" + + types "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txm/types" +) + +// TxStore is an autogenerated mock type for the TxStore type +type TxStore struct { + mock.Mock +} + +type TxStore_Expecter struct { + mock *mock.Mock +} + +func (_m *TxStore) EXPECT() *TxStore_Expecter { + return &TxStore_Expecter{mock: &_m.Mock} +} + +// AbandonPendingTransactions provides a mock function with given fields: _a0, _a1 +func (_m *TxStore) AbandonPendingTransactions(_a0 context.Context, _a1 common.Address) error { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for AbandonPendingTransactions") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, common.Address) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// TxStore_AbandonPendingTransactions_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AbandonPendingTransactions' +type TxStore_AbandonPendingTransactions_Call struct { + *mock.Call +} + +// AbandonPendingTransactions is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 common.Address +func (_e *TxStore_Expecter) AbandonPendingTransactions(_a0 interface{}, _a1 interface{}) *TxStore_AbandonPendingTransactions_Call { + return &TxStore_AbandonPendingTransactions_Call{Call: _e.mock.On("AbandonPendingTransactions", _a0, _a1)} +} + +func (_c *TxStore_AbandonPendingTransactions_Call) Run(run func(_a0 context.Context, _a1 common.Address)) *TxStore_AbandonPendingTransactions_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(common.Address)) + }) + return _c +} + +func (_c *TxStore_AbandonPendingTransactions_Call) Return(_a0 error) *TxStore_AbandonPendingTransactions_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *TxStore_AbandonPendingTransactions_Call) RunAndReturn(run func(context.Context, common.Address) error) *TxStore_AbandonPendingTransactions_Call { + _c.Call.Return(run) + return _c +} + +// AppendAttemptToTransaction provides a mock function with given fields: _a0, _a1, _a2, _a3 +func (_m *TxStore) AppendAttemptToTransaction(_a0 context.Context, _a1 uint64, _a2 common.Address, _a3 *types.Attempt) error { + ret := _m.Called(_a0, _a1, _a2, _a3) + + if len(ret) == 0 { + panic("no return value specified for AppendAttemptToTransaction") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, common.Address, *types.Attempt) error); ok { + r0 = rf(_a0, _a1, _a2, _a3) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// TxStore_AppendAttemptToTransaction_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AppendAttemptToTransaction' +type TxStore_AppendAttemptToTransaction_Call struct { + *mock.Call +} + +// AppendAttemptToTransaction is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 uint64 +// - _a2 common.Address +// - _a3 *types.Attempt +func (_e *TxStore_Expecter) AppendAttemptToTransaction(_a0 interface{}, _a1 interface{}, _a2 interface{}, _a3 interface{}) *TxStore_AppendAttemptToTransaction_Call { + return &TxStore_AppendAttemptToTransaction_Call{Call: _e.mock.On("AppendAttemptToTransaction", _a0, _a1, _a2, _a3)} +} + +func (_c *TxStore_AppendAttemptToTransaction_Call) Run(run func(_a0 context.Context, _a1 uint64, _a2 common.Address, _a3 *types.Attempt)) *TxStore_AppendAttemptToTransaction_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(uint64), args[2].(common.Address), args[3].(*types.Attempt)) + }) + return _c +} + +func (_c *TxStore_AppendAttemptToTransaction_Call) Return(_a0 error) *TxStore_AppendAttemptToTransaction_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *TxStore_AppendAttemptToTransaction_Call) RunAndReturn(run func(context.Context, uint64, common.Address, *types.Attempt) error) *TxStore_AppendAttemptToTransaction_Call { + _c.Call.Return(run) + return _c +} + +// CreateEmptyUnconfirmedTransaction provides a mock function with given fields: _a0, _a1, _a2, _a3 +func (_m *TxStore) CreateEmptyUnconfirmedTransaction(_a0 context.Context, _a1 common.Address, _a2 uint64, _a3 uint64) (*types.Transaction, error) { + ret := _m.Called(_a0, _a1, _a2, _a3) + + if len(ret) == 0 { + panic("no return value specified for CreateEmptyUnconfirmedTransaction") + } + + var r0 *types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Address, uint64, uint64) (*types.Transaction, error)); ok { + return rf(_a0, _a1, _a2, _a3) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Address, uint64, uint64) *types.Transaction); ok { + r0 = rf(_a0, _a1, _a2, _a3) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Address, uint64, uint64) error); ok { + r1 = rf(_a0, _a1, _a2, _a3) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TxStore_CreateEmptyUnconfirmedTransaction_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateEmptyUnconfirmedTransaction' +type TxStore_CreateEmptyUnconfirmedTransaction_Call struct { + *mock.Call +} + +// CreateEmptyUnconfirmedTransaction is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 common.Address +// - _a2 uint64 +// - _a3 uint64 +func (_e *TxStore_Expecter) CreateEmptyUnconfirmedTransaction(_a0 interface{}, _a1 interface{}, _a2 interface{}, _a3 interface{}) *TxStore_CreateEmptyUnconfirmedTransaction_Call { + return &TxStore_CreateEmptyUnconfirmedTransaction_Call{Call: _e.mock.On("CreateEmptyUnconfirmedTransaction", _a0, _a1, _a2, _a3)} +} + +func (_c *TxStore_CreateEmptyUnconfirmedTransaction_Call) Run(run func(_a0 context.Context, _a1 common.Address, _a2 uint64, _a3 uint64)) *TxStore_CreateEmptyUnconfirmedTransaction_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(common.Address), args[2].(uint64), args[3].(uint64)) + }) + return _c +} + +func (_c *TxStore_CreateEmptyUnconfirmedTransaction_Call) Return(_a0 *types.Transaction, _a1 error) *TxStore_CreateEmptyUnconfirmedTransaction_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *TxStore_CreateEmptyUnconfirmedTransaction_Call) RunAndReturn(run func(context.Context, common.Address, uint64, uint64) (*types.Transaction, error)) *TxStore_CreateEmptyUnconfirmedTransaction_Call { + _c.Call.Return(run) + return _c +} + +// CreateTransaction provides a mock function with given fields: _a0, _a1 +func (_m *TxStore) CreateTransaction(_a0 context.Context, _a1 *types.TxRequest) (*types.Transaction, error) { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for CreateTransaction") + } + + var r0 *types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *types.TxRequest) (*types.Transaction, error)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(context.Context, *types.TxRequest) *types.Transaction); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *types.TxRequest) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TxStore_CreateTransaction_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateTransaction' +type TxStore_CreateTransaction_Call struct { + *mock.Call +} + +// CreateTransaction is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 *types.TxRequest +func (_e *TxStore_Expecter) CreateTransaction(_a0 interface{}, _a1 interface{}) *TxStore_CreateTransaction_Call { + return &TxStore_CreateTransaction_Call{Call: _e.mock.On("CreateTransaction", _a0, _a1)} +} + +func (_c *TxStore_CreateTransaction_Call) Run(run func(_a0 context.Context, _a1 *types.TxRequest)) *TxStore_CreateTransaction_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*types.TxRequest)) + }) + return _c +} + +func (_c *TxStore_CreateTransaction_Call) Return(_a0 *types.Transaction, _a1 error) *TxStore_CreateTransaction_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *TxStore_CreateTransaction_Call) RunAndReturn(run func(context.Context, *types.TxRequest) (*types.Transaction, error)) *TxStore_CreateTransaction_Call { + _c.Call.Return(run) + return _c +} + +// DeleteAttemptForUnconfirmedTx provides a mock function with given fields: _a0, _a1, _a2, _a3 +func (_m *TxStore) DeleteAttemptForUnconfirmedTx(_a0 context.Context, _a1 uint64, _a2 *types.Attempt, _a3 common.Address) error { + ret := _m.Called(_a0, _a1, _a2, _a3) + + if len(ret) == 0 { + panic("no return value specified for DeleteAttemptForUnconfirmedTx") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, *types.Attempt, common.Address) error); ok { + r0 = rf(_a0, _a1, _a2, _a3) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// TxStore_DeleteAttemptForUnconfirmedTx_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteAttemptForUnconfirmedTx' +type TxStore_DeleteAttemptForUnconfirmedTx_Call struct { + *mock.Call +} + +// DeleteAttemptForUnconfirmedTx is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 uint64 +// - _a2 *types.Attempt +// - _a3 common.Address +func (_e *TxStore_Expecter) DeleteAttemptForUnconfirmedTx(_a0 interface{}, _a1 interface{}, _a2 interface{}, _a3 interface{}) *TxStore_DeleteAttemptForUnconfirmedTx_Call { + return &TxStore_DeleteAttemptForUnconfirmedTx_Call{Call: _e.mock.On("DeleteAttemptForUnconfirmedTx", _a0, _a1, _a2, _a3)} +} + +func (_c *TxStore_DeleteAttemptForUnconfirmedTx_Call) Run(run func(_a0 context.Context, _a1 uint64, _a2 *types.Attempt, _a3 common.Address)) *TxStore_DeleteAttemptForUnconfirmedTx_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(uint64), args[2].(*types.Attempt), args[3].(common.Address)) + }) + return _c +} + +func (_c *TxStore_DeleteAttemptForUnconfirmedTx_Call) Return(_a0 error) *TxStore_DeleteAttemptForUnconfirmedTx_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *TxStore_DeleteAttemptForUnconfirmedTx_Call) RunAndReturn(run func(context.Context, uint64, *types.Attempt, common.Address) error) *TxStore_DeleteAttemptForUnconfirmedTx_Call { + _c.Call.Return(run) + return _c +} + +// FetchUnconfirmedTransactionAtNonceWithCount provides a mock function with given fields: _a0, _a1, _a2 +func (_m *TxStore) FetchUnconfirmedTransactionAtNonceWithCount(_a0 context.Context, _a1 uint64, _a2 common.Address) (*types.Transaction, int, error) { + ret := _m.Called(_a0, _a1, _a2) + + if len(ret) == 0 { + panic("no return value specified for FetchUnconfirmedTransactionAtNonceWithCount") + } + + var r0 *types.Transaction + var r1 int + var r2 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, common.Address) (*types.Transaction, int, error)); ok { + return rf(_a0, _a1, _a2) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, common.Address) *types.Transaction); ok { + r0 = rf(_a0, _a1, _a2) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, common.Address) int); ok { + r1 = rf(_a0, _a1, _a2) + } else { + r1 = ret.Get(1).(int) + } + + if rf, ok := ret.Get(2).(func(context.Context, uint64, common.Address) error); ok { + r2 = rf(_a0, _a1, _a2) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// TxStore_FetchUnconfirmedTransactionAtNonceWithCount_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FetchUnconfirmedTransactionAtNonceWithCount' +type TxStore_FetchUnconfirmedTransactionAtNonceWithCount_Call struct { + *mock.Call +} + +// FetchUnconfirmedTransactionAtNonceWithCount is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 uint64 +// - _a2 common.Address +func (_e *TxStore_Expecter) FetchUnconfirmedTransactionAtNonceWithCount(_a0 interface{}, _a1 interface{}, _a2 interface{}) *TxStore_FetchUnconfirmedTransactionAtNonceWithCount_Call { + return &TxStore_FetchUnconfirmedTransactionAtNonceWithCount_Call{Call: _e.mock.On("FetchUnconfirmedTransactionAtNonceWithCount", _a0, _a1, _a2)} +} + +func (_c *TxStore_FetchUnconfirmedTransactionAtNonceWithCount_Call) Run(run func(_a0 context.Context, _a1 uint64, _a2 common.Address)) *TxStore_FetchUnconfirmedTransactionAtNonceWithCount_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(uint64), args[2].(common.Address)) + }) + return _c +} + +func (_c *TxStore_FetchUnconfirmedTransactionAtNonceWithCount_Call) Return(_a0 *types.Transaction, _a1 int, _a2 error) *TxStore_FetchUnconfirmedTransactionAtNonceWithCount_Call { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *TxStore_FetchUnconfirmedTransactionAtNonceWithCount_Call) RunAndReturn(run func(context.Context, uint64, common.Address) (*types.Transaction, int, error)) *TxStore_FetchUnconfirmedTransactionAtNonceWithCount_Call { + _c.Call.Return(run) + return _c +} + +// MarkConfirmedAndReorgedTransactions provides a mock function with given fields: _a0, _a1, _a2 +func (_m *TxStore) MarkConfirmedAndReorgedTransactions(_a0 context.Context, _a1 uint64, _a2 common.Address) ([]*types.Transaction, []uint64, error) { + ret := _m.Called(_a0, _a1, _a2) + + if len(ret) == 0 { + panic("no return value specified for MarkConfirmedAndReorgedTransactions") + } + + var r0 []*types.Transaction + var r1 []uint64 + var r2 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, common.Address) ([]*types.Transaction, []uint64, error)); ok { + return rf(_a0, _a1, _a2) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, common.Address) []*types.Transaction); ok { + r0 = rf(_a0, _a1, _a2) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, common.Address) []uint64); ok { + r1 = rf(_a0, _a1, _a2) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).([]uint64) + } + } + + if rf, ok := ret.Get(2).(func(context.Context, uint64, common.Address) error); ok { + r2 = rf(_a0, _a1, _a2) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// TxStore_MarkConfirmedAndReorgedTransactions_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'MarkConfirmedAndReorgedTransactions' +type TxStore_MarkConfirmedAndReorgedTransactions_Call struct { + *mock.Call +} + +// MarkConfirmedAndReorgedTransactions is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 uint64 +// - _a2 common.Address +func (_e *TxStore_Expecter) MarkConfirmedAndReorgedTransactions(_a0 interface{}, _a1 interface{}, _a2 interface{}) *TxStore_MarkConfirmedAndReorgedTransactions_Call { + return &TxStore_MarkConfirmedAndReorgedTransactions_Call{Call: _e.mock.On("MarkConfirmedAndReorgedTransactions", _a0, _a1, _a2)} +} + +func (_c *TxStore_MarkConfirmedAndReorgedTransactions_Call) Run(run func(_a0 context.Context, _a1 uint64, _a2 common.Address)) *TxStore_MarkConfirmedAndReorgedTransactions_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(uint64), args[2].(common.Address)) + }) + return _c +} + +func (_c *TxStore_MarkConfirmedAndReorgedTransactions_Call) Return(_a0 []*types.Transaction, _a1 []uint64, _a2 error) *TxStore_MarkConfirmedAndReorgedTransactions_Call { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *TxStore_MarkConfirmedAndReorgedTransactions_Call) RunAndReturn(run func(context.Context, uint64, common.Address) ([]*types.Transaction, []uint64, error)) *TxStore_MarkConfirmedAndReorgedTransactions_Call { + _c.Call.Return(run) + return _c +} + +// MarkTxFatal provides a mock function with given fields: _a0, _a1, _a2 +func (_m *TxStore) MarkTxFatal(_a0 context.Context, _a1 *types.Transaction, _a2 common.Address) error { + ret := _m.Called(_a0, _a1, _a2) + + if len(ret) == 0 { + panic("no return value specified for MarkTxFatal") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *types.Transaction, common.Address) error); ok { + r0 = rf(_a0, _a1, _a2) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// TxStore_MarkTxFatal_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'MarkTxFatal' +type TxStore_MarkTxFatal_Call struct { + *mock.Call +} + +// MarkTxFatal is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 *types.Transaction +// - _a2 common.Address +func (_e *TxStore_Expecter) MarkTxFatal(_a0 interface{}, _a1 interface{}, _a2 interface{}) *TxStore_MarkTxFatal_Call { + return &TxStore_MarkTxFatal_Call{Call: _e.mock.On("MarkTxFatal", _a0, _a1, _a2)} +} + +func (_c *TxStore_MarkTxFatal_Call) Run(run func(_a0 context.Context, _a1 *types.Transaction, _a2 common.Address)) *TxStore_MarkTxFatal_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*types.Transaction), args[2].(common.Address)) + }) + return _c +} + +func (_c *TxStore_MarkTxFatal_Call) Return(_a0 error) *TxStore_MarkTxFatal_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *TxStore_MarkTxFatal_Call) RunAndReturn(run func(context.Context, *types.Transaction, common.Address) error) *TxStore_MarkTxFatal_Call { + _c.Call.Return(run) + return _c +} + +// MarkUnconfirmedTransactionPurgeable provides a mock function with given fields: _a0, _a1, _a2 +func (_m *TxStore) MarkUnconfirmedTransactionPurgeable(_a0 context.Context, _a1 uint64, _a2 common.Address) error { + ret := _m.Called(_a0, _a1, _a2) + + if len(ret) == 0 { + panic("no return value specified for MarkUnconfirmedTransactionPurgeable") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, common.Address) error); ok { + r0 = rf(_a0, _a1, _a2) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// TxStore_MarkUnconfirmedTransactionPurgeable_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'MarkUnconfirmedTransactionPurgeable' +type TxStore_MarkUnconfirmedTransactionPurgeable_Call struct { + *mock.Call +} + +// MarkUnconfirmedTransactionPurgeable is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 uint64 +// - _a2 common.Address +func (_e *TxStore_Expecter) MarkUnconfirmedTransactionPurgeable(_a0 interface{}, _a1 interface{}, _a2 interface{}) *TxStore_MarkUnconfirmedTransactionPurgeable_Call { + return &TxStore_MarkUnconfirmedTransactionPurgeable_Call{Call: _e.mock.On("MarkUnconfirmedTransactionPurgeable", _a0, _a1, _a2)} +} + +func (_c *TxStore_MarkUnconfirmedTransactionPurgeable_Call) Run(run func(_a0 context.Context, _a1 uint64, _a2 common.Address)) *TxStore_MarkUnconfirmedTransactionPurgeable_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(uint64), args[2].(common.Address)) + }) + return _c +} + +func (_c *TxStore_MarkUnconfirmedTransactionPurgeable_Call) Return(_a0 error) *TxStore_MarkUnconfirmedTransactionPurgeable_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *TxStore_MarkUnconfirmedTransactionPurgeable_Call) RunAndReturn(run func(context.Context, uint64, common.Address) error) *TxStore_MarkUnconfirmedTransactionPurgeable_Call { + _c.Call.Return(run) + return _c +} + +// UpdateTransactionBroadcast provides a mock function with given fields: _a0, _a1, _a2, _a3, _a4 +func (_m *TxStore) UpdateTransactionBroadcast(_a0 context.Context, _a1 uint64, _a2 uint64, _a3 common.Hash, _a4 common.Address) error { + ret := _m.Called(_a0, _a1, _a2, _a3, _a4) + + if len(ret) == 0 { + panic("no return value specified for UpdateTransactionBroadcast") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, uint64, common.Hash, common.Address) error); ok { + r0 = rf(_a0, _a1, _a2, _a3, _a4) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// TxStore_UpdateTransactionBroadcast_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateTransactionBroadcast' +type TxStore_UpdateTransactionBroadcast_Call struct { + *mock.Call +} + +// UpdateTransactionBroadcast is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 uint64 +// - _a2 uint64 +// - _a3 common.Hash +// - _a4 common.Address +func (_e *TxStore_Expecter) UpdateTransactionBroadcast(_a0 interface{}, _a1 interface{}, _a2 interface{}, _a3 interface{}, _a4 interface{}) *TxStore_UpdateTransactionBroadcast_Call { + return &TxStore_UpdateTransactionBroadcast_Call{Call: _e.mock.On("UpdateTransactionBroadcast", _a0, _a1, _a2, _a3, _a4)} +} + +func (_c *TxStore_UpdateTransactionBroadcast_Call) Run(run func(_a0 context.Context, _a1 uint64, _a2 uint64, _a3 common.Hash, _a4 common.Address)) *TxStore_UpdateTransactionBroadcast_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(uint64), args[2].(uint64), args[3].(common.Hash), args[4].(common.Address)) + }) + return _c +} + +func (_c *TxStore_UpdateTransactionBroadcast_Call) Return(_a0 error) *TxStore_UpdateTransactionBroadcast_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *TxStore_UpdateTransactionBroadcast_Call) RunAndReturn(run func(context.Context, uint64, uint64, common.Hash, common.Address) error) *TxStore_UpdateTransactionBroadcast_Call { + _c.Call.Return(run) + return _c +} + +// UpdateUnstartedTransactionWithNonce provides a mock function with given fields: _a0, _a1, _a2 +func (_m *TxStore) UpdateUnstartedTransactionWithNonce(_a0 context.Context, _a1 common.Address, _a2 uint64) (*types.Transaction, error) { + ret := _m.Called(_a0, _a1, _a2) + + if len(ret) == 0 { + panic("no return value specified for UpdateUnstartedTransactionWithNonce") + } + + var r0 *types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Address, uint64) (*types.Transaction, error)); ok { + return rf(_a0, _a1, _a2) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Address, uint64) *types.Transaction); ok { + r0 = rf(_a0, _a1, _a2) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Address, uint64) error); ok { + r1 = rf(_a0, _a1, _a2) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TxStore_UpdateUnstartedTransactionWithNonce_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateUnstartedTransactionWithNonce' +type TxStore_UpdateUnstartedTransactionWithNonce_Call struct { + *mock.Call +} + +// UpdateUnstartedTransactionWithNonce is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 common.Address +// - _a2 uint64 +func (_e *TxStore_Expecter) UpdateUnstartedTransactionWithNonce(_a0 interface{}, _a1 interface{}, _a2 interface{}) *TxStore_UpdateUnstartedTransactionWithNonce_Call { + return &TxStore_UpdateUnstartedTransactionWithNonce_Call{Call: _e.mock.On("UpdateUnstartedTransactionWithNonce", _a0, _a1, _a2)} +} + +func (_c *TxStore_UpdateUnstartedTransactionWithNonce_Call) Run(run func(_a0 context.Context, _a1 common.Address, _a2 uint64)) *TxStore_UpdateUnstartedTransactionWithNonce_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(common.Address), args[2].(uint64)) + }) + return _c +} + +func (_c *TxStore_UpdateUnstartedTransactionWithNonce_Call) Return(_a0 *types.Transaction, _a1 error) *TxStore_UpdateUnstartedTransactionWithNonce_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *TxStore_UpdateUnstartedTransactionWithNonce_Call) RunAndReturn(run func(context.Context, common.Address, uint64) (*types.Transaction, error)) *TxStore_UpdateUnstartedTransactionWithNonce_Call { + _c.Call.Return(run) + return _c +} + +// NewTxStore creates a new instance of TxStore. 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 NewTxStore(t interface { + mock.TestingT + Cleanup(func()) +}) *TxStore { + mock := &TxStore{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/core/chains/evm/txm/orchestrator.go b/core/chains/evm/txm/orchestrator.go new file mode 100644 index 00000000000..ae981e153b0 --- /dev/null +++ b/core/chains/evm/txm/orchestrator.go @@ -0,0 +1,363 @@ +package txm + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "math" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/google/uuid" + nullv4 "gopkg.in/guregu/null.v4" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" + commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/utils" + + "github.com/smartcontractkit/chainlink/v2/common/txmgr" + txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" + "github.com/smartcontractkit/chainlink/v2/common/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" + txmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txm/types" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" +) + +type OrchestratorTxStore interface { + Add(addresses ...common.Address) error + FetchUnconfirmedTransactionAtNonceWithCount(context.Context, uint64, common.Address) (*txmtypes.Transaction, int, error) + FindTxWithIdempotencyKey(context.Context, string) (*txmtypes.Transaction, error) +} + +type OrchestratorKeystore interface { + CheckEnabled(ctx context.Context, address common.Address, chainID *big.Int) error + EnabledAddressesForChain(ctx context.Context, chainID *big.Int) (addresses []common.Address, err error) +} + +type OrchestratorAttemptBuilder[ + BLOCK_HASH types.Hashable, + HEAD types.Head[BLOCK_HASH], +] interface { + services.Service + OnNewLongestChain(ctx context.Context, head HEAD) +} + +// Generics are necessary to keep TXMv2 backwards compatible +type Orchestrator[ + BLOCK_HASH types.Hashable, + HEAD types.Head[BLOCK_HASH], +] struct { + services.StateMachine + lggr logger.SugaredLogger + chainID *big.Int + txm *Txm + txStore OrchestratorTxStore + fwdMgr *forwarders.FwdMgr + keystore OrchestratorKeystore + attemptBuilder OrchestratorAttemptBuilder[BLOCK_HASH, HEAD] + resumeCallback txmgr.ResumeCallback +} + +func NewTxmOrchestrator[BLOCK_HASH types.Hashable, HEAD types.Head[BLOCK_HASH]]( + lggr logger.Logger, + chainID *big.Int, + txm *Txm, + txStore OrchestratorTxStore, + fwdMgr *forwarders.FwdMgr, + keystore OrchestratorKeystore, + attemptBuilder OrchestratorAttemptBuilder[BLOCK_HASH, HEAD], +) *Orchestrator[BLOCK_HASH, HEAD] { + return &Orchestrator[BLOCK_HASH, HEAD]{ + lggr: logger.Sugared(logger.Named(lggr, "Orchestrator")), + chainID: chainID, + txm: txm, + txStore: txStore, + keystore: keystore, + attemptBuilder: attemptBuilder, + fwdMgr: fwdMgr, + } +} + +func (o *Orchestrator[BLOCK_HASH, HEAD]) Start(ctx context.Context) error { + return o.StartOnce("Orchestrator", func() error { + var ms services.MultiStart + if err := ms.Start(ctx, o.attemptBuilder); err != nil { + return fmt.Errorf("Orchestrator: AttemptBuilder failed to start: %w", err) + } + addresses, err := o.keystore.EnabledAddressesForChain(ctx, o.chainID) + if err != nil { + return err + } + for _, address := range addresses { + err := o.txStore.Add(address) + if err != nil { + return err + } + } + if err := ms.Start(ctx, o.txm); err != nil { + return fmt.Errorf("Orchestrator: Txm failed to start: %w", err) + } + if o.fwdMgr != nil { + if err := ms.Start(ctx, o.fwdMgr); err != nil { + return fmt.Errorf("Orchestrator: ForwarderManager failed to start: %w", err) + } + } + return nil + }) +} + +func (o *Orchestrator[BLOCK_HASH, HEAD]) Close() (merr error) { + return o.StopOnce("Orchestrator", func() error { + if o.fwdMgr != nil { + if err := o.fwdMgr.Close(); err != nil { + merr = errors.Join(merr, fmt.Errorf("Orchestrator failed to stop ForwarderManager: %w", err)) + } + } + if err := o.txm.Close(); err != nil { + merr = errors.Join(merr, fmt.Errorf("Orchestrator failed to stop Txm: %w", err)) + } + if err := o.attemptBuilder.Close(); err != nil { + merr = errors.Join(merr, fmt.Errorf("Orchestrator failed to stop AttemptBuilder: %w", err)) + } + return merr + }) +} + +func (o *Orchestrator[BLOCK_HASH, HEAD]) Trigger(addr common.Address) { + o.txm.Trigger(addr) +} + +func (o *Orchestrator[BLOCK_HASH, HEAD]) Name() string { + return o.lggr.Name() +} + +func (o *Orchestrator[BLOCK_HASH, HEAD]) HealthReport() map[string]error { + return map[string]error{o.Name(): o.Healthy()} +} + +func (o *Orchestrator[BLOCK_HASH, HEAD]) RegisterResumeCallback(fn txmgr.ResumeCallback) { + o.resumeCallback = fn +} + +func (o *Orchestrator[BLOCK_HASH, HEAD]) Reset(addr common.Address, abandon bool) error { + ok := o.IfStarted(func() { + if err := o.txm.Abandon(addr); err != nil { + o.lggr.Error(err) + } + }) + if !ok { + return errors.New("Orchestrator not started yet") + } + return nil +} + +func (o *Orchestrator[BLOCK_HASH, HEAD]) OnNewLongestChain(ctx context.Context, head HEAD) { + ok := o.IfStarted(func() { + o.attemptBuilder.OnNewLongestChain(ctx, head) + }) + if !ok { + o.lggr.Debugw("Not started; ignoring head", "head", head, "state", o.State()) + } +} + +func (o *Orchestrator[BLOCK_HASH, HEAD]) CreateTransaction(ctx context.Context, request txmgrtypes.TxRequest[common.Address, common.Hash]) (tx txmgrtypes.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], err error) { + var wrappedTx *txmtypes.Transaction + if request.IdempotencyKey != nil { + wrappedTx, err = o.txStore.FindTxWithIdempotencyKey(ctx, *request.IdempotencyKey) + if err != nil { + return + } + } + + if wrappedTx != nil { + o.lggr.Infof("Found Tx with IdempotencyKey: %v. Returning existing Tx without creating a new one.", *wrappedTx.IdempotencyKey) + } else { + if kErr := o.keystore.CheckEnabled(ctx, request.FromAddress, o.chainID); kErr != nil { + return tx, fmt.Errorf("cannot send transaction from %s on chain ID %s: %w", request.FromAddress, o.chainID.String(), kErr) + } + + var pipelineTaskRunID uuid.NullUUID + if request.PipelineTaskRunID != nil { + pipelineTaskRunID.UUID = *request.PipelineTaskRunID + pipelineTaskRunID.Valid = true + } + + if o.fwdMgr != nil && (!utils.IsZero(request.ForwarderAddress)) { + fwdPayload, fwdErr := o.fwdMgr.ConvertPayload(request.ToAddress, request.EncodedPayload) + if fwdErr == nil { + // Handling meta not set at caller. + if request.Meta != nil { + request.Meta.FwdrDestAddress = &request.ToAddress + } else { + request.Meta = &txmgrtypes.TxMeta[common.Address, common.Hash]{ + FwdrDestAddress: &request.ToAddress, + } + } + request.ToAddress = request.ForwarderAddress + request.EncodedPayload = fwdPayload + } else { + o.lggr.Errorf("Failed to use forwarder set upstream: %v", fwdErr.Error()) + } + } + + var meta *sqlutil.JSON + if request.Meta != nil { + raw, mErr := json.Marshal(request.Meta) + if mErr != nil { + return tx, mErr + } + m := sqlutil.JSON(raw) + meta = &m + } + + wrappedTxRequest := &txmtypes.TxRequest{ + IdempotencyKey: request.IdempotencyKey, + ChainID: o.chainID, + FromAddress: request.FromAddress, + ToAddress: request.ToAddress, + Value: &request.Value, + Data: request.EncodedPayload, + SpecifiedGasLimit: request.FeeLimit, + Meta: meta, + ForwarderAddress: request.ForwarderAddress, + + PipelineTaskRunID: pipelineTaskRunID, + MinConfirmations: request.MinConfirmations, + SignalCallback: request.SignalCallback, + } + + wrappedTx, err = o.txm.CreateTransaction(ctx, wrappedTxRequest) + if err != nil { + return + } + o.txm.Trigger(request.FromAddress) + } + + if wrappedTx.ID > math.MaxInt64 { + return tx, fmt.Errorf("overflow for int64: %d", wrappedTx.ID) + } + + tx = txmgrtypes.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]{ + ID: int64(wrappedTx.ID), + IdempotencyKey: wrappedTx.IdempotencyKey, + FromAddress: wrappedTx.FromAddress, + ToAddress: wrappedTx.ToAddress, + EncodedPayload: wrappedTx.Data, + Value: *wrappedTx.Value, + FeeLimit: wrappedTx.SpecifiedGasLimit, + CreatedAt: wrappedTx.CreatedAt, + Meta: wrappedTx.Meta, + Subject: wrappedTx.Subject, + ChainID: wrappedTx.ChainID, + + PipelineTaskRunID: wrappedTx.PipelineTaskRunID, + MinConfirmations: wrappedTx.MinConfirmations, + SignalCallback: wrappedTx.SignalCallback, + CallbackCompleted: wrappedTx.CallbackCompleted, + } + return +} + +// CountTransactionsByState was required for backwards compatibility and it's used only for unconfirmed transactions. +func (o *Orchestrator[BLOCK_HASH, HEAD]) CountTransactionsByState(ctx context.Context, state txmgrtypes.TxState) (uint32, error) { + addresses, err := o.keystore.EnabledAddressesForChain(ctx, o.chainID) + if err != nil { + return 0, err + } + total := 0 + for _, address := range addresses { + _, count, err := o.txStore.FetchUnconfirmedTransactionAtNonceWithCount(ctx, 0, address) + if err != nil { + return 0, err + } + total += count + } + + //nolint:gosec // disable G115 + return uint32(total), nil +} + +func (o *Orchestrator[BLOCK_HASH, HEAD]) FindEarliestUnconfirmedBroadcastTime(ctx context.Context) (time nullv4.Time, err error) { + return +} + +func (o *Orchestrator[BLOCK_HASH, HEAD]) FindEarliestUnconfirmedTxAttemptBlock(ctx context.Context) (time nullv4.Int, err error) { + return +} + +func (o *Orchestrator[BLOCK_HASH, HEAD]) FindTxesByMetaFieldAndStates(ctx context.Context, metaField string, metaValue string, states []txmgrtypes.TxState, chainID *big.Int) (txs []*txmgrtypes.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], err error) { + return +} + +func (o *Orchestrator[BLOCK_HASH, HEAD]) FindTxesWithMetaFieldByStates(ctx context.Context, metaField string, states []txmgrtypes.TxState, chainID *big.Int) (txs []*txmgrtypes.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], err error) { + return +} + +func (o *Orchestrator[BLOCK_HASH, HEAD]) FindTxesWithMetaFieldByReceiptBlockNum(ctx context.Context, metaField string, blockNum int64, chainID *big.Int) (txs []*txmgrtypes.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], err error) { + return +} + +//nolint:revive // keep API backwards compatible +func (o *Orchestrator[BLOCK_HASH, HEAD]) FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.Context, ids []int64, states []txmgrtypes.TxState, chainID *big.Int) (txs []*txmgrtypes.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], err error) { + return +} + +func (o *Orchestrator[BLOCK_HASH, HEAD]) GetForwarderForEOA(ctx context.Context, eoa common.Address) (forwarder common.Address, err error) { + if o.fwdMgr != nil { + forwarder, err = o.fwdMgr.ForwarderFor(ctx, eoa) + } + return +} + +func (o *Orchestrator[BLOCK_HASH, HEAD]) GetForwarderForEOAOCR2Feeds(ctx context.Context, eoa, ocr2AggregatorID common.Address) (forwarder common.Address, err error) { + if o.fwdMgr != nil { + forwarder, err = o.fwdMgr.ForwarderForOCR2Feeds(ctx, eoa, ocr2AggregatorID) + } + return +} + +func (o *Orchestrator[BLOCK_HASH, HEAD]) GetTransactionStatus(ctx context.Context, transactionID string) (status commontypes.TransactionStatus, err error) { + // Loads attempts and receipts in the transaction + tx, err := o.txStore.FindTxWithIdempotencyKey(ctx, transactionID) + if err != nil || tx == nil { + return status, fmt.Errorf("failed to find transaction with IdempotencyKey %s: %w", transactionID, err) + } + + switch tx.State { + case txmgr.TxUnconfirmed: + return commontypes.Pending, nil + case txmgr.TxConfirmed: + // Return unconfirmed for confirmed transactions because they are not yet finalized + return commontypes.Unconfirmed, nil + case txmgr.TxFinalized: + return commontypes.Finalized, nil + case txmgr.TxFatalError: + return commontypes.Fatal, nil + default: + return commontypes.Unknown, nil + } +} + +func (o *Orchestrator[BLOCK_HASH, HEAD]) SendNativeToken(ctx context.Context, chainID *big.Int, from, to common.Address, value big.Int, gasLimit uint64) (tx txmgrtypes.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], err error) { + txRequest := txmgrtypes.TxRequest[common.Address, common.Hash]{ + FromAddress: from, + ToAddress: to, + EncodedPayload: []byte{}, + Value: value, + FeeLimit: gasLimit, + //Strategy: NewSendEveryStrategy(), + } + + tx, err = o.CreateTransaction(ctx, txRequest) + if err != nil { + return + } + + // Trigger the Txm to check for new transaction + o.txm.Trigger(from) + return tx, err +} diff --git a/core/chains/evm/txm/storage/inmemory_store.go b/core/chains/evm/txm/storage/inmemory_store.go new file mode 100644 index 00000000000..57217913d76 --- /dev/null +++ b/core/chains/evm/txm/storage/inmemory_store.go @@ -0,0 +1,358 @@ +package storage + +import ( + "errors" + "fmt" + "math/big" + "sort" + "sync" + "time" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + + txmgr "github.com/smartcontractkit/chainlink/v2/common/txmgr" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txm/types" +) + +const ( + // maxQueuedTransactions is the max limit of UnstartedTransactions and ConfirmedTransactions structures. + maxQueuedTransactions = 250 + // pruneSubset controls the subset of confirmed transactions to prune when the structure reaches its max limit. + // i.e. if the value is 3 and the limit is 90, 30 transactions will be pruned. + pruneSubset = 3 +) + +type InMemoryStore struct { + sync.RWMutex + lggr logger.Logger + txIDCount uint64 + address common.Address + chainID *big.Int + + UnstartedTransactions []*types.Transaction + UnconfirmedTransactions map[uint64]*types.Transaction + ConfirmedTransactions map[uint64]*types.Transaction + FatalTransactions []*types.Transaction + + Transactions map[uint64]*types.Transaction +} + +func NewInMemoryStore(lggr logger.Logger, address common.Address, chainID *big.Int) *InMemoryStore { + return &InMemoryStore{ + lggr: logger.Named(lggr, "InMemoryStore"), + address: address, + chainID: chainID, + UnstartedTransactions: make([]*types.Transaction, 0, maxQueuedTransactions), + UnconfirmedTransactions: make(map[uint64]*types.Transaction), + ConfirmedTransactions: make(map[uint64]*types.Transaction, maxQueuedTransactions), + Transactions: make(map[uint64]*types.Transaction), + } +} + +func (m *InMemoryStore) AbandonPendingTransactions() { + // TODO: append existing fatal transactions and cap the size + m.Lock() + defer m.Unlock() + + for _, tx := range m.UnstartedTransactions { + tx.State = txmgr.TxFatalError + } + for _, tx := range m.FatalTransactions { + delete(m.Transactions, tx.ID) + } + m.FatalTransactions = m.UnstartedTransactions + m.UnstartedTransactions = []*types.Transaction{} + + for _, tx := range m.UnconfirmedTransactions { + tx.State = txmgr.TxFatalError + m.FatalTransactions = append(m.FatalTransactions, tx) + } + m.UnconfirmedTransactions = make(map[uint64]*types.Transaction) +} + +func (m *InMemoryStore) AppendAttemptToTransaction(txNonce uint64, attempt *types.Attempt) error { + m.Lock() + defer m.Unlock() + + tx, exists := m.UnconfirmedTransactions[txNonce] + if !exists { + return fmt.Errorf("unconfirmed tx was not found for nonce: %d - txID: %v", txNonce, attempt.TxID) + } + + if tx.ID != attempt.TxID { + return fmt.Errorf("unconfirmed tx with nonce exists but attempt points to a different txID. Found Tx: %v - txID: %v", m.UnconfirmedTransactions[txNonce], attempt.TxID) + } + + attempt.CreatedAt = time.Now() + attempt.ID = uint64(len(tx.Attempts)) // Attempts are not collectively tracked by the in-memory store so attemptIDs are not unique between transactions and can be reused. + tx.AttemptCount++ + m.UnconfirmedTransactions[txNonce].Attempts = append(m.UnconfirmedTransactions[txNonce].Attempts, attempt.DeepCopy()) + + return nil +} + +func (m *InMemoryStore) CountUnstartedTransactions() int { + m.RLock() + defer m.RUnlock() + + return len(m.UnstartedTransactions) +} + +func (m *InMemoryStore) CreateEmptyUnconfirmedTransaction(nonce uint64, gasLimit uint64) (*types.Transaction, error) { + m.Lock() + defer m.Unlock() + + emptyTx := &types.Transaction{ + ID: m.txIDCount, + ChainID: m.chainID, + Nonce: &nonce, + FromAddress: m.address, + ToAddress: common.Address{}, + Value: big.NewInt(0), + SpecifiedGasLimit: gasLimit, + CreatedAt: time.Now(), + State: txmgr.TxUnconfirmed, + } + + if _, exists := m.UnconfirmedTransactions[nonce]; exists { + return nil, fmt.Errorf("an unconfirmed tx with the same nonce already exists: %v", m.UnconfirmedTransactions[nonce]) + } + + if _, exists := m.ConfirmedTransactions[nonce]; exists { + return nil, fmt.Errorf("a confirmed tx with the same nonce already exists: %v", m.ConfirmedTransactions[nonce]) + } + + m.txIDCount++ + m.UnconfirmedTransactions[nonce] = emptyTx + m.Transactions[emptyTx.ID] = emptyTx + + return emptyTx.DeepCopy(), nil +} + +func (m *InMemoryStore) CreateTransaction(txRequest *types.TxRequest) *types.Transaction { + m.Lock() + defer m.Unlock() + + tx := &types.Transaction{ + ID: m.txIDCount, + IdempotencyKey: txRequest.IdempotencyKey, + ChainID: m.chainID, + FromAddress: m.address, + ToAddress: txRequest.ToAddress, + Value: txRequest.Value, + Data: txRequest.Data, + SpecifiedGasLimit: txRequest.SpecifiedGasLimit, + CreatedAt: time.Now(), + State: txmgr.TxUnstarted, + Meta: txRequest.Meta, + MinConfirmations: txRequest.MinConfirmations, + PipelineTaskRunID: txRequest.PipelineTaskRunID, + SignalCallback: txRequest.SignalCallback, + } + + uLen := len(m.UnstartedTransactions) + if uLen >= maxQueuedTransactions { + m.lggr.Warnw(fmt.Sprintf("Unstarted transactions queue for address: %v reached max limit of: %d. Dropping oldest transactions", m.address, maxQueuedTransactions), + "txs", m.UnstartedTransactions[0:uLen-maxQueuedTransactions+1]) // need to make room for the new tx + for _, tx := range m.UnstartedTransactions[0 : uLen-maxQueuedTransactions+1] { + delete(m.Transactions, tx.ID) + } + m.UnstartedTransactions = m.UnstartedTransactions[uLen-maxQueuedTransactions+1:] + } + + m.txIDCount++ + txCopy := tx.DeepCopy() + m.Transactions[txCopy.ID] = txCopy + m.UnstartedTransactions = append(m.UnstartedTransactions, txCopy) + return tx +} + +func (m *InMemoryStore) FetchUnconfirmedTransactionAtNonceWithCount(latestNonce uint64) (txCopy *types.Transaction, unconfirmedCount int) { + m.RLock() + defer m.RUnlock() + + tx := m.UnconfirmedTransactions[latestNonce] + if tx != nil { + txCopy = tx.DeepCopy() + } + unconfirmedCount = len(m.UnconfirmedTransactions) + return +} + +func (m *InMemoryStore) MarkConfirmedAndReorgedTransactions(latestNonce uint64) ([]*types.Transaction, []uint64, error) { + m.Lock() + defer m.Unlock() + + var confirmedTransactions []*types.Transaction + for _, tx := range m.UnconfirmedTransactions { + if tx.Nonce == nil { + return nil, nil, fmt.Errorf("nonce for txID: %v is empty", tx.ID) + } + existingTx, exists := m.ConfirmedTransactions[*tx.Nonce] + if exists { + m.lggr.Errorw("Another confirmed transaction with the same nonce exists. Transaction will be overwritten.", + "existingTx", existingTx, "newTx", tx) + } + if *tx.Nonce < latestNonce { + tx.State = txmgr.TxConfirmed + confirmedTransactions = append(confirmedTransactions, tx.DeepCopy()) + m.ConfirmedTransactions[*tx.Nonce] = tx + delete(m.UnconfirmedTransactions, *tx.Nonce) + } + } + + var unconfirmedTransactionIDs []uint64 + for _, tx := range m.ConfirmedTransactions { + if tx.Nonce == nil { + return nil, nil, fmt.Errorf("nonce for txID: %v is empty", tx.ID) + } + existingTx, exists := m.UnconfirmedTransactions[*tx.Nonce] + if exists { + m.lggr.Errorw("Another unconfirmed transaction with the same nonce exists. Transaction will overwritten.", + "existingTx", existingTx, "newTx", tx) + } + if *tx.Nonce >= latestNonce { + tx.State = txmgr.TxUnconfirmed + tx.LastBroadcastAt = nil // Mark reorged transaction as if it wasn't broadcasted before + unconfirmedTransactionIDs = append(unconfirmedTransactionIDs, tx.ID) + m.UnconfirmedTransactions[*tx.Nonce] = tx + delete(m.ConfirmedTransactions, *tx.Nonce) + } + } + + if len(m.ConfirmedTransactions) > maxQueuedTransactions { + prunedTxIDs := m.pruneConfirmedTransactions() + m.lggr.Debugf("Confirmed transactions map for address: %v reached max limit of: %d. Pruned 1/%d of the oldest confirmed transactions. TxIDs: %v", + m.address, maxQueuedTransactions, pruneSubset, prunedTxIDs) + } + sort.Slice(confirmedTransactions, func(i, j int) bool { return confirmedTransactions[i].ID < confirmedTransactions[j].ID }) + sort.Slice(unconfirmedTransactionIDs, func(i, j int) bool { return unconfirmedTransactionIDs[i] < unconfirmedTransactionIDs[j] }) + return confirmedTransactions, unconfirmedTransactionIDs, nil +} + +func (m *InMemoryStore) MarkUnconfirmedTransactionPurgeable(nonce uint64) error { + m.Lock() + defer m.Unlock() + + tx, exists := m.UnconfirmedTransactions[nonce] + if !exists { + return fmt.Errorf("unconfirmed tx with nonce: %d was not found", nonce) + } + + tx.IsPurgeable = true + + return nil +} + +func (m *InMemoryStore) UpdateTransactionBroadcast(txID uint64, txNonce uint64, attemptHash common.Hash) error { + m.Lock() + defer m.Unlock() + + unconfirmedTx, exists := m.UnconfirmedTransactions[txNonce] + if !exists { + return fmt.Errorf("unconfirmed tx was not found for nonce: %d - txID: %v", txNonce, txID) + } + + // Set the same time for both the tx and its attempt + now := time.Now() + unconfirmedTx.LastBroadcastAt = &now + if unconfirmedTx.InitialBroadcastAt == nil { + unconfirmedTx.InitialBroadcastAt = &now + } + a, err := unconfirmedTx.FindAttemptByHash(attemptHash) + if err != nil { + return fmt.Errorf("UpdateTransactionBroadcast failed to find attempt. %w", err) + } + a.BroadcastAt = &now + + return nil +} + +func (m *InMemoryStore) UpdateUnstartedTransactionWithNonce(nonce uint64) (*types.Transaction, error) { + m.Lock() + defer m.Unlock() + + if len(m.UnstartedTransactions) == 0 { + m.lggr.Debugf("Unstarted transactions queue is empty for address: %v", m.address) + return nil, nil + } + + if tx, exists := m.UnconfirmedTransactions[nonce]; exists { + return nil, fmt.Errorf("an unconfirmed tx with the same nonce already exists: %v", tx) + } + + tx := m.UnstartedTransactions[0] + tx.Nonce = &nonce + tx.State = txmgr.TxUnconfirmed + + m.UnstartedTransactions = m.UnstartedTransactions[1:] + m.UnconfirmedTransactions[nonce] = tx + + return tx.DeepCopy(), nil +} + +// Shouldn't call lock because it's being called by a method that already has the lock +func (m *InMemoryStore) pruneConfirmedTransactions() []uint64 { + noncesToPrune := make([]uint64, 0, len(m.ConfirmedTransactions)) + for nonce := range m.ConfirmedTransactions { + noncesToPrune = append(noncesToPrune, nonce) + } + if len(noncesToPrune) == 0 { + return nil + } + sort.Slice(noncesToPrune, func(i, j int) bool { return noncesToPrune[i] < noncesToPrune[j] }) + minNonce := noncesToPrune[len(noncesToPrune)/pruneSubset] + + var txIDsToPrune []uint64 + for nonce, tx := range m.ConfirmedTransactions { + if nonce < minNonce { + txIDsToPrune = append(txIDsToPrune, tx.ID) + delete(m.Transactions, tx.ID) + delete(m.ConfirmedTransactions, nonce) + } + } + + sort.Slice(txIDsToPrune, func(i, j int) bool { return txIDsToPrune[i] < txIDsToPrune[j] }) + return txIDsToPrune +} + +// Error Handler +func (m *InMemoryStore) DeleteAttemptForUnconfirmedTx(transactionNonce uint64, attempt *types.Attempt) error { + m.Lock() + defer m.Unlock() + + tx, exists := m.UnconfirmedTransactions[transactionNonce] + if !exists { + return fmt.Errorf("unconfirmed tx was not found for nonce: %d - txID: %v", transactionNonce, attempt.TxID) + } + + for i, a := range tx.Attempts { + if a.Hash == attempt.Hash { + tx.Attempts = append(tx.Attempts[:i], tx.Attempts[i+1:]...) + return nil + } + } + + return fmt.Errorf("attempt with hash: %v for txID: %v was not found", attempt.Hash, attempt.TxID) +} + +func (m *InMemoryStore) MarkTxFatal(*types.Transaction) error { + return errors.New("not implemented") +} + +// Orchestrator +func (m *InMemoryStore) FindTxWithIdempotencyKey(idempotencyKey string) *types.Transaction { + m.RLock() + defer m.RUnlock() + + for _, tx := range m.Transactions { + if tx.IdempotencyKey != nil && *tx.IdempotencyKey == idempotencyKey { + return tx.DeepCopy() + } + } + + return nil +} diff --git a/core/chains/evm/txm/storage/inmemory_store_manager.go b/core/chains/evm/txm/storage/inmemory_store_manager.go new file mode 100644 index 00000000000..a7538823eea --- /dev/null +++ b/core/chains/evm/txm/storage/inmemory_store_manager.go @@ -0,0 +1,136 @@ +package storage + +import ( + "context" + "errors" + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txm/types" +) + +const StoreNotFoundForAddress string = "InMemoryStore for address: %v not found" + +type InMemoryStoreManager struct { + lggr logger.Logger + chainID *big.Int + InMemoryStoreMap map[common.Address]*InMemoryStore +} + +func NewInMemoryStoreManager(lggr logger.Logger, chainID *big.Int) *InMemoryStoreManager { + inMemoryStoreMap := make(map[common.Address]*InMemoryStore) + return &InMemoryStoreManager{ + lggr: lggr, + chainID: chainID, + InMemoryStoreMap: inMemoryStoreMap} +} + +func (m *InMemoryStoreManager) AbandonPendingTransactions(_ context.Context, fromAddress common.Address) error { + if store, exists := m.InMemoryStoreMap[fromAddress]; exists { + store.AbandonPendingTransactions() + return nil + } + return fmt.Errorf(StoreNotFoundForAddress, fromAddress) +} + +func (m *InMemoryStoreManager) Add(addresses ...common.Address) (err error) { + for _, address := range addresses { + if _, exists := m.InMemoryStoreMap[address]; exists { + err = errors.Join(err, fmt.Errorf("address %v already exists in store manager", address)) + } + m.InMemoryStoreMap[address] = NewInMemoryStore(m.lggr, address, m.chainID) + } + return +} + +func (m *InMemoryStoreManager) AppendAttemptToTransaction(_ context.Context, txNonce uint64, fromAddress common.Address, attempt *types.Attempt) error { + if store, exists := m.InMemoryStoreMap[fromAddress]; exists { + return store.AppendAttemptToTransaction(txNonce, attempt) + } + return fmt.Errorf(StoreNotFoundForAddress, fromAddress) +} + +func (m *InMemoryStoreManager) CountUnstartedTransactions(fromAddress common.Address) (int, error) { + if store, exists := m.InMemoryStoreMap[fromAddress]; exists { + return store.CountUnstartedTransactions(), nil + } + return 0, fmt.Errorf(StoreNotFoundForAddress, fromAddress) +} + +func (m *InMemoryStoreManager) CreateEmptyUnconfirmedTransaction(_ context.Context, fromAddress common.Address, nonce uint64, gasLimit uint64) (*types.Transaction, error) { + if store, exists := m.InMemoryStoreMap[fromAddress]; exists { + return store.CreateEmptyUnconfirmedTransaction(nonce, gasLimit) + } + return nil, fmt.Errorf(StoreNotFoundForAddress, fromAddress) +} + +func (m *InMemoryStoreManager) CreateTransaction(_ context.Context, txRequest *types.TxRequest) (*types.Transaction, error) { + if store, exists := m.InMemoryStoreMap[txRequest.FromAddress]; exists { + return store.CreateTransaction(txRequest), nil + } + return nil, fmt.Errorf(StoreNotFoundForAddress, txRequest.FromAddress) +} + +func (m *InMemoryStoreManager) FetchUnconfirmedTransactionAtNonceWithCount(_ context.Context, nonce uint64, fromAddress common.Address) (tx *types.Transaction, count int, err error) { + if store, exists := m.InMemoryStoreMap[fromAddress]; exists { + tx, count = store.FetchUnconfirmedTransactionAtNonceWithCount(nonce) + return + } + return nil, 0, fmt.Errorf(StoreNotFoundForAddress, fromAddress) +} + +func (m *InMemoryStoreManager) MarkConfirmedAndReorgedTransactions(_ context.Context, nonce uint64, fromAddress common.Address) (confirmedTxs []*types.Transaction, unconfirmedTxIDs []uint64, err error) { + if store, exists := m.InMemoryStoreMap[fromAddress]; exists { + confirmedTxs, unconfirmedTxIDs, err = store.MarkConfirmedAndReorgedTransactions(nonce) + return + } + return nil, nil, fmt.Errorf(StoreNotFoundForAddress, fromAddress) +} + +func (m *InMemoryStoreManager) MarkUnconfirmedTransactionPurgeable(_ context.Context, nonce uint64, fromAddress common.Address) error { + if store, exists := m.InMemoryStoreMap[fromAddress]; exists { + return store.MarkUnconfirmedTransactionPurgeable(nonce) + } + return fmt.Errorf(StoreNotFoundForAddress, fromAddress) +} + +func (m *InMemoryStoreManager) UpdateTransactionBroadcast(_ context.Context, txID uint64, nonce uint64, attemptHash common.Hash, fromAddress common.Address) error { + if store, exists := m.InMemoryStoreMap[fromAddress]; exists { + return store.UpdateTransactionBroadcast(txID, nonce, attemptHash) + } + return fmt.Errorf(StoreNotFoundForAddress, fromAddress) +} + +func (m *InMemoryStoreManager) UpdateUnstartedTransactionWithNonce(_ context.Context, fromAddress common.Address, nonce uint64) (*types.Transaction, error) { + if store, exists := m.InMemoryStoreMap[fromAddress]; exists { + return store.UpdateUnstartedTransactionWithNonce(nonce) + } + return nil, fmt.Errorf(StoreNotFoundForAddress, fromAddress) +} + +func (m *InMemoryStoreManager) DeleteAttemptForUnconfirmedTx(_ context.Context, nonce uint64, attempt *types.Attempt, fromAddress common.Address) error { + if store, exists := m.InMemoryStoreMap[fromAddress]; exists { + return store.DeleteAttemptForUnconfirmedTx(nonce, attempt) + } + return fmt.Errorf(StoreNotFoundForAddress, fromAddress) +} + +func (m *InMemoryStoreManager) MarkTxFatal(_ context.Context, tx *types.Transaction, fromAddress common.Address) error { + if store, exists := m.InMemoryStoreMap[fromAddress]; exists { + return store.MarkTxFatal(tx) + } + return fmt.Errorf(StoreNotFoundForAddress, fromAddress) +} + +func (m *InMemoryStoreManager) FindTxWithIdempotencyKey(_ context.Context, idempotencyKey string) (*types.Transaction, error) { + for _, store := range m.InMemoryStoreMap { + tx := store.FindTxWithIdempotencyKey(idempotencyKey) + if tx != nil { + return tx, nil + } + } + return nil, nil +} diff --git a/core/chains/evm/txm/storage/inmemory_store_manager_test.go b/core/chains/evm/txm/storage/inmemory_store_manager_test.go new file mode 100644 index 00000000000..aff589fb9e1 --- /dev/null +++ b/core/chains/evm/txm/storage/inmemory_store_manager_test.go @@ -0,0 +1,36 @@ +package storage + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/testutils" +) + +func TestAdd(t *testing.T) { + t.Parallel() + + fromAddress := testutils.NewAddress() + m := NewInMemoryStoreManager(logger.Test(t), testutils.FixtureChainID) + // Adds a new address + err := m.Add(fromAddress) + require.NoError(t, err) + assert.Len(t, m.InMemoryStoreMap, 1) + + // Fails if address exists + err = m.Add(fromAddress) + require.Error(t, err) + + // Adds multiple addresses + fromAddress1 := testutils.NewAddress() + fromAddress2 := testutils.NewAddress() + addresses := []common.Address{fromAddress1, fromAddress2} + err = m.Add(addresses...) + require.NoError(t, err) + assert.Len(t, m.InMemoryStoreMap, 3) +} diff --git a/core/chains/evm/txm/storage/inmemory_store_test.go b/core/chains/evm/txm/storage/inmemory_store_test.go new file mode 100644 index 00000000000..226cf284bba --- /dev/null +++ b/core/chains/evm/txm/storage/inmemory_store_test.go @@ -0,0 +1,559 @@ +package storage + +import ( + "fmt" + "math/big" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + + "github.com/smartcontractkit/chainlink/v2/common/txmgr" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/testutils" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txm/types" +) + +func TestAbandonPendingTransactions(t *testing.T) { + t.Parallel() + + fromAddress := testutils.NewAddress() + t.Run("abandons unstarted and unconfirmed transactions", func(t *testing.T) { + m := NewInMemoryStore(logger.Test(t), fromAddress, testutils.FixtureChainID) + // Unstarted + tx1 := insertUnstartedTransaction(m) + tx2 := insertUnstartedTransaction(m) + + // Unconfirmed + tx3, err := insertUnconfirmedTransaction(m, 3) + require.NoError(t, err) + tx4, err := insertUnconfirmedTransaction(m, 4) + require.NoError(t, err) + + m.AbandonPendingTransactions() + + assert.Equal(t, txmgr.TxFatalError, tx1.State) + assert.Equal(t, txmgr.TxFatalError, tx2.State) + assert.Equal(t, txmgr.TxFatalError, tx3.State) + assert.Equal(t, txmgr.TxFatalError, tx4.State) + }) + + t.Run("skips all types apart from unstarted and unconfirmed transactions", func(t *testing.T) { + m := NewInMemoryStore(logger.Test(t), fromAddress, testutils.FixtureChainID) + // Fatal + tx1 := insertFataTransaction(m) + tx2 := insertFataTransaction(m) + + // Confirmed + tx3, err := insertConfirmedTransaction(m, 3) + require.NoError(t, err) + tx4, err := insertConfirmedTransaction(m, 4) + require.NoError(t, err) + + m.AbandonPendingTransactions() + + assert.Equal(t, txmgr.TxFatalError, tx1.State) + assert.Equal(t, txmgr.TxFatalError, tx2.State) + assert.Equal(t, txmgr.TxConfirmed, tx3.State) + assert.Equal(t, txmgr.TxConfirmed, tx4.State) + assert.Len(t, m.Transactions, 2) // tx1, tx2 were dropped + }) +} + +func TestAppendAttemptToTransaction(t *testing.T) { + t.Parallel() + + fromAddress := testutils.NewAddress() + m := NewInMemoryStore(logger.Test(t), fromAddress, testutils.FixtureChainID) + + _, err := insertUnconfirmedTransaction(m, 10) // txID = 1, nonce = 10 + require.NoError(t, err) + _, err = insertConfirmedTransaction(m, 2) // txID = 2, nonce = 2 + require.NoError(t, err) + + t.Run("fails if corresponding unconfirmed transaction for attempt was not found", func(t *testing.T) { + var nonce uint64 = 1 + newAttempt := &types.Attempt{} + err := m.AppendAttemptToTransaction(nonce, newAttempt) + require.Error(t, err) + require.ErrorContains(t, err, "unconfirmed tx was not found") + }) + + t.Run("fails if unconfirmed transaction was found but doesn't match the txID", func(t *testing.T) { + var nonce uint64 = 10 + newAttempt := &types.Attempt{ + TxID: 2, + } + err := m.AppendAttemptToTransaction(nonce, newAttempt) + require.Error(t, err) + require.ErrorContains(t, err, "attempt points to a different txID") + }) + + t.Run("appends attempt to transaction", func(t *testing.T) { + var nonce uint64 = 10 + newAttempt := &types.Attempt{ + TxID: 1, + } + require.NoError(t, m.AppendAttemptToTransaction(nonce, newAttempt)) + tx, _ := m.FetchUnconfirmedTransactionAtNonceWithCount(10) + assert.Len(t, tx.Attempts, 1) + assert.Equal(t, uint16(1), tx.AttemptCount) + assert.False(t, tx.Attempts[0].CreatedAt.IsZero()) + }) +} + +func TestCountUnstartedTransactions(t *testing.T) { + t.Parallel() + + fromAddress := testutils.NewAddress() + m := NewInMemoryStore(logger.Test(t), fromAddress, testutils.FixtureChainID) + + assert.Equal(t, 0, m.CountUnstartedTransactions()) + + insertUnstartedTransaction(m) + assert.Equal(t, 1, m.CountUnstartedTransactions()) + + _, err := insertConfirmedTransaction(m, 10) + require.NoError(t, err) + assert.Equal(t, 1, m.CountUnstartedTransactions()) +} + +func TestCreateEmptyUnconfirmedTransaction(t *testing.T) { + t.Parallel() + + fromAddress := testutils.NewAddress() + m := NewInMemoryStore(logger.Test(t), fromAddress, testutils.FixtureChainID) + _, err := insertUnconfirmedTransaction(m, 1) + require.NoError(t, err) + _, err = insertConfirmedTransaction(m, 0) + require.NoError(t, err) + + t.Run("fails if unconfirmed transaction with the same nonce exists", func(t *testing.T) { + _, err := m.CreateEmptyUnconfirmedTransaction(1, 0) + require.Error(t, err) + }) + + t.Run("fails if confirmed transaction with the same nonce exists", func(t *testing.T) { + _, err := m.CreateEmptyUnconfirmedTransaction(0, 0) + require.Error(t, err) + }) + + t.Run("creates a new empty unconfirmed transaction", func(t *testing.T) { + tx, err := m.CreateEmptyUnconfirmedTransaction(2, 0) + require.NoError(t, err) + assert.Equal(t, txmgr.TxUnconfirmed, tx.State) + }) +} + +func TestCreateTransaction(t *testing.T) { + t.Parallel() + + fromAddress := testutils.NewAddress() + + t.Run("creates new transactions", func(t *testing.T) { + m := NewInMemoryStore(logger.Test(t), fromAddress, testutils.FixtureChainID) + now := time.Now() + txR1 := &types.TxRequest{} + txR2 := &types.TxRequest{} + tx1 := m.CreateTransaction(txR1) + assert.Equal(t, uint64(0), tx1.ID) + assert.LessOrEqual(t, now, tx1.CreatedAt) + + tx2 := m.CreateTransaction(txR2) + assert.Equal(t, uint64(1), tx2.ID) + assert.LessOrEqual(t, now, tx2.CreatedAt) + + assert.Equal(t, 2, m.CountUnstartedTransactions()) + }) + + t.Run("prunes oldest unstarted transactions if limit is reached", func(t *testing.T) { + m := NewInMemoryStore(logger.Test(t), fromAddress, testutils.FixtureChainID) + overshot := 5 + for i := 0; i < maxQueuedTransactions+overshot; i++ { + r := &types.TxRequest{} + tx := m.CreateTransaction(r) + //nolint:gosec // this won't overflow + assert.Equal(t, uint64(i), tx.ID) + } + // total shouldn't exceed maxQueuedTransactions + assert.Equal(t, maxQueuedTransactions, m.CountUnstartedTransactions()) + // earliest tx ID should be the same amount of the number of transactions that we dropped + tx, err := m.UpdateUnstartedTransactionWithNonce(0) + require.NoError(t, err) + //nolint:gosec // this won't overflow + assert.Equal(t, uint64(overshot), tx.ID) + }) +} + +func TestFetchUnconfirmedTransactionAtNonceWithCount(t *testing.T) { + t.Parallel() + + fromAddress := testutils.NewAddress() + m := NewInMemoryStore(logger.Test(t), fromAddress, testutils.FixtureChainID) + + tx, count := m.FetchUnconfirmedTransactionAtNonceWithCount(0) + assert.Nil(t, tx) + assert.Equal(t, 0, count) + + var nonce uint64 + _, err := insertUnconfirmedTransaction(m, nonce) + require.NoError(t, err) + tx, count = m.FetchUnconfirmedTransactionAtNonceWithCount(0) + assert.Equal(t, *tx.Nonce, nonce) + assert.Equal(t, 1, count) +} + +func TestMarkConfirmedAndReorgedTransactions(t *testing.T) { + t.Parallel() + + fromAddress := testutils.NewAddress() + + t.Run("returns 0 if there are no transactions", func(t *testing.T) { + m := NewInMemoryStore(logger.Test(t), fromAddress, testutils.FixtureChainID) + un, cn, err := m.MarkConfirmedAndReorgedTransactions(100) + require.NoError(t, err) + assert.Empty(t, un) + assert.Empty(t, cn) + }) + + t.Run("confirms transaction with nonce lower than the latest", func(t *testing.T) { + m := NewInMemoryStore(logger.Test(t), fromAddress, testutils.FixtureChainID) + ctx1, err := insertUnconfirmedTransaction(m, 0) + require.NoError(t, err) + + ctx2, err := insertUnconfirmedTransaction(m, 1) + require.NoError(t, err) + + ctxs, utxs, err := m.MarkConfirmedAndReorgedTransactions(1) + require.NoError(t, err) + assert.Equal(t, txmgr.TxConfirmed, ctx1.State) + assert.Equal(t, txmgr.TxUnconfirmed, ctx2.State) + assert.Equal(t, ctxs[0].ID, ctx1.ID) // Ensure order + assert.Empty(t, utxs) + }) + + t.Run("state remains the same if nonce didn't change", func(t *testing.T) { + m := NewInMemoryStore(logger.Test(t), fromAddress, testutils.FixtureChainID) + ctx1, err := insertConfirmedTransaction(m, 0) + require.NoError(t, err) + + ctx2, err := insertUnconfirmedTransaction(m, 1) + require.NoError(t, err) + + ctxs, utxs, err := m.MarkConfirmedAndReorgedTransactions(1) + require.NoError(t, err) + assert.Equal(t, txmgr.TxConfirmed, ctx1.State) + assert.Equal(t, txmgr.TxUnconfirmed, ctx2.State) + assert.Empty(t, ctxs) + assert.Empty(t, utxs) + }) + + t.Run("unconfirms transaction with nonce equal to or higher than the latest", func(t *testing.T) { + m := NewInMemoryStore(logger.Test(t), fromAddress, testutils.FixtureChainID) + ctx1, err := insertConfirmedTransaction(m, 0) + require.NoError(t, err) + + ctx2, err := insertConfirmedTransaction(m, 1) + require.NoError(t, err) + + ctxs, utxs, err := m.MarkConfirmedAndReorgedTransactions(1) + require.NoError(t, err) + assert.Equal(t, txmgr.TxConfirmed, ctx1.State) + assert.Equal(t, txmgr.TxUnconfirmed, ctx2.State) + assert.Equal(t, utxs[0], ctx2.ID) + assert.Empty(t, ctxs) + }) + + t.Run("logs an error during confirmation if a transaction with the same nonce already exists", func(t *testing.T) { + lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) + m := NewInMemoryStore(lggr, fromAddress, testutils.FixtureChainID) + _, err := insertConfirmedTransaction(m, 0) + require.NoError(t, err) + _, err = insertUnconfirmedTransaction(m, 0) + require.NoError(t, err) + + _, _, err = m.MarkConfirmedAndReorgedTransactions(1) + require.NoError(t, err) + tests.AssertLogEventually(t, observedLogs, "Another confirmed transaction with the same nonce exists") + }) + + t.Run("prunes confirmed transactions map if it reaches the limit", func(t *testing.T) { + m := NewInMemoryStore(logger.Test(t), fromAddress, testutils.FixtureChainID) + overshot := 5 + for i := 0; i < maxQueuedTransactions+overshot; i++ { + //nolint:gosec // this won't overflow + _, err := insertConfirmedTransaction(m, uint64(i)) + require.NoError(t, err) + } + assert.Len(t, m.ConfirmedTransactions, maxQueuedTransactions+overshot) + //nolint:gosec // this won't overflow + _, _, err := m.MarkConfirmedAndReorgedTransactions(uint64(maxQueuedTransactions + overshot)) + require.NoError(t, err) + assert.Len(t, m.ConfirmedTransactions, 170) + }) +} + +func TestMarkUnconfirmedTransactionPurgeable(t *testing.T) { + t.Parallel() + + fromAddress := testutils.NewAddress() + m := NewInMemoryStore(logger.Test(t), fromAddress, testutils.FixtureChainID) + + // fails if tx was not found + err := m.MarkUnconfirmedTransactionPurgeable(0) + require.Error(t, err) + + tx, err := insertUnconfirmedTransaction(m, 0) + require.NoError(t, err) + err = m.MarkUnconfirmedTransactionPurgeable(0) + require.NoError(t, err) + assert.True(t, tx.IsPurgeable) +} + +func TestUpdateTransactionBroadcast(t *testing.T) { + t.Parallel() + + fromAddress := testutils.NewAddress() + hash := testutils.NewHash() + t.Run("fails if unconfirmed transaction was not found", func(t *testing.T) { + m := NewInMemoryStore(logger.Test(t), fromAddress, testutils.FixtureChainID) + var nonce uint64 + require.Error(t, m.UpdateTransactionBroadcast(0, nonce, hash)) + }) + + t.Run("fails if attempt was not found for a given transaction", func(t *testing.T) { + m := NewInMemoryStore(logger.Test(t), fromAddress, testutils.FixtureChainID) + var nonce uint64 + tx, err := insertUnconfirmedTransaction(m, nonce) + require.NoError(t, err) + require.Error(t, m.UpdateTransactionBroadcast(0, nonce, hash)) + + // Attempt with different hash + attempt := &types.Attempt{TxID: tx.ID, Hash: testutils.NewHash()} + tx.Attempts = append(tx.Attempts, attempt) + require.Error(t, m.UpdateTransactionBroadcast(0, nonce, hash)) + }) + + t.Run("updates transaction's and attempt's broadcast times", func(t *testing.T) { + m := NewInMemoryStore(logger.Test(t), fromAddress, testutils.FixtureChainID) + var nonce uint64 + tx, err := insertUnconfirmedTransaction(m, nonce) + require.NoError(t, err) + attempt := &types.Attempt{TxID: tx.ID, Hash: hash} + tx.Attempts = append(tx.Attempts, attempt) + require.NoError(t, m.UpdateTransactionBroadcast(0, nonce, hash)) + assert.False(t, tx.LastBroadcastAt.IsZero()) + assert.False(t, attempt.BroadcastAt.IsZero()) + assert.False(t, tx.InitialBroadcastAt.IsZero()) + }) +} + +func TestUpdateUnstartedTransactionWithNonce(t *testing.T) { + t.Parallel() + + fromAddress := testutils.NewAddress() + t.Run("returns nil if there are no unstarted transactions", func(t *testing.T) { + m := NewInMemoryStore(logger.Test(t), fromAddress, testutils.FixtureChainID) + tx, err := m.UpdateUnstartedTransactionWithNonce(0) + require.NoError(t, err) + assert.Nil(t, tx) + }) + + t.Run("fails if there is already another unconfirmed transaction with the same nonce", func(t *testing.T) { + var nonce uint64 + m := NewInMemoryStore(logger.Test(t), fromAddress, testutils.FixtureChainID) + insertUnstartedTransaction(m) + _, err := insertUnconfirmedTransaction(m, nonce) + require.NoError(t, err) + + _, err = m.UpdateUnstartedTransactionWithNonce(nonce) + require.Error(t, err) + }) + + t.Run("updates unstarted transaction to unconfirmed and assigns a nonce", func(t *testing.T) { + var nonce uint64 + m := NewInMemoryStore(logger.Test(t), fromAddress, testutils.FixtureChainID) + insertUnstartedTransaction(m) + + tx, err := m.UpdateUnstartedTransactionWithNonce(nonce) + require.NoError(t, err) + assert.Equal(t, nonce, *tx.Nonce) + assert.Equal(t, txmgr.TxUnconfirmed, tx.State) + assert.Empty(t, m.UnstartedTransactions) + }) +} + +func TestDeleteAttemptForUnconfirmedTx(t *testing.T) { + t.Parallel() + + fromAddress := testutils.NewAddress() + t.Run("fails if corresponding unconfirmed transaction for attempt was not found", func(t *testing.T) { + m := NewInMemoryStore(logger.Test(t), fromAddress, testutils.FixtureChainID) + var nonce uint64 + tx := &types.Transaction{Nonce: &nonce} + attempt := &types.Attempt{TxID: 0} + err := m.DeleteAttemptForUnconfirmedTx(*tx.Nonce, attempt) + require.Error(t, err) + }) + + t.Run("fails if corresponding unconfirmed attempt for txID was not found", func(t *testing.T) { + m := NewInMemoryStore(logger.Test(t), fromAddress, testutils.FixtureChainID) + _, err := insertUnconfirmedTransaction(m, 0) + require.NoError(t, err) + + attempt := &types.Attempt{TxID: 2, Hash: testutils.NewHash()} + err = m.DeleteAttemptForUnconfirmedTx(0, attempt) + + require.Error(t, err) + }) + + t.Run("deletes attempt of unconfirmed transaction", func(t *testing.T) { + hash := testutils.NewHash() + var nonce uint64 + m := NewInMemoryStore(logger.Test(t), fromAddress, testutils.FixtureChainID) + tx, err := insertUnconfirmedTransaction(m, nonce) + require.NoError(t, err) + + attempt := &types.Attempt{TxID: 0, Hash: hash} + tx.Attempts = append(tx.Attempts, attempt) + err = m.DeleteAttemptForUnconfirmedTx(nonce, attempt) + require.NoError(t, err) + + assert.Empty(t, tx.Attempts) + }) +} + +func TestFindTxWithIdempotencyKey(t *testing.T) { + t.Parallel() + fromAddress := testutils.NewAddress() + m := NewInMemoryStore(logger.Test(t), fromAddress, testutils.FixtureChainID) + tx, err := insertConfirmedTransaction(m, 0) + require.NoError(t, err) + + ik := "IK" + tx.IdempotencyKey = &ik + itx := m.FindTxWithIdempotencyKey(ik) + assert.Equal(t, ik, *itx.IdempotencyKey) + + uik := "Unknown" + itx = m.FindTxWithIdempotencyKey(uik) + assert.Nil(t, itx) +} + +func TestPruneConfirmedTransactions(t *testing.T) { + t.Parallel() + fromAddress := testutils.NewAddress() + m := NewInMemoryStore(logger.Test(t), fromAddress, testutils.FixtureChainID) + total := 5 + for i := 0; i < total; i++ { + //nolint:gosec // this won't overflow + _, err := insertConfirmedTransaction(m, uint64(i)) + require.NoError(t, err) + } + prunedTxIDs := m.pruneConfirmedTransactions() + left := total - total/pruneSubset + assert.Len(t, m.ConfirmedTransactions, left) + assert.Len(t, prunedTxIDs, total/pruneSubset) +} + +func insertUnstartedTransaction(m *InMemoryStore) *types.Transaction { + m.Lock() + defer m.Unlock() + + var nonce uint64 + m.txIDCount++ + tx := &types.Transaction{ + ID: m.txIDCount, + ChainID: testutils.FixtureChainID, + Nonce: &nonce, + FromAddress: m.address, + ToAddress: testutils.NewAddress(), + Value: big.NewInt(0), + SpecifiedGasLimit: 0, + CreatedAt: time.Now(), + State: txmgr.TxUnstarted, + } + + m.UnstartedTransactions = append(m.UnstartedTransactions, tx) + m.Transactions[tx.ID] = tx + return tx +} + +func insertUnconfirmedTransaction(m *InMemoryStore, nonce uint64) (*types.Transaction, error) { + m.Lock() + defer m.Unlock() + + m.txIDCount++ + tx := &types.Transaction{ + ID: m.txIDCount, + ChainID: testutils.FixtureChainID, + Nonce: &nonce, + FromAddress: m.address, + ToAddress: testutils.NewAddress(), + Value: big.NewInt(0), + SpecifiedGasLimit: 0, + CreatedAt: time.Now(), + State: txmgr.TxUnconfirmed, + } + + if _, exists := m.UnconfirmedTransactions[nonce]; exists { + return nil, fmt.Errorf("an unconfirmed tx with the same nonce already exists: %v", m.UnconfirmedTransactions[nonce]) + } + + m.UnconfirmedTransactions[nonce] = tx + m.Transactions[tx.ID] = tx + return tx, nil +} + +func insertConfirmedTransaction(m *InMemoryStore, nonce uint64) (*types.Transaction, error) { + m.Lock() + defer m.Unlock() + + m.txIDCount++ + tx := &types.Transaction{ + ID: m.txIDCount, + ChainID: testutils.FixtureChainID, + Nonce: &nonce, + FromAddress: m.address, + ToAddress: testutils.NewAddress(), + Value: big.NewInt(0), + SpecifiedGasLimit: 0, + CreatedAt: time.Now(), + State: txmgr.TxConfirmed, + } + + if _, exists := m.ConfirmedTransactions[nonce]; exists { + return nil, fmt.Errorf("a confirmed tx with the same nonce already exists: %v", m.ConfirmedTransactions[nonce]) + } + + m.ConfirmedTransactions[nonce] = tx + m.Transactions[tx.ID] = tx + return tx, nil +} + +func insertFataTransaction(m *InMemoryStore) *types.Transaction { + m.Lock() + defer m.Unlock() + + var nonce uint64 + m.txIDCount++ + tx := &types.Transaction{ + ID: m.txIDCount, + ChainID: testutils.FixtureChainID, + Nonce: &nonce, + FromAddress: m.address, + ToAddress: testutils.NewAddress(), + Value: big.NewInt(0), + SpecifiedGasLimit: 0, + CreatedAt: time.Now(), + State: txmgr.TxFatalError, + } + + m.FatalTransactions = append(m.FatalTransactions, tx) + m.Transactions[tx.ID] = tx + return tx +} diff --git a/core/chains/evm/txm/stuck_tx_detector.go b/core/chains/evm/txm/stuck_tx_detector.go new file mode 100644 index 00000000000..2da4ad4cd67 --- /dev/null +++ b/core/chains/evm/txm/stuck_tx_detector.go @@ -0,0 +1,123 @@ +package txm + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "time" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txm/types" +) + +type StuckTxDetectorConfig struct { + BlockTime time.Duration + StuckTxBlockThreshold uint32 + DetectionURL string + DualBroadcast bool +} + +type stuckTxDetector struct { + lggr logger.Logger + chainType chaintype.ChainType + config StuckTxDetectorConfig + lastPurgeMap map[common.Address]time.Time +} + +func NewStuckTxDetector(lggr logger.Logger, chaintype chaintype.ChainType, config StuckTxDetectorConfig) *stuckTxDetector { + return &stuckTxDetector{ + lggr: lggr, + chainType: chaintype, + config: config, + lastPurgeMap: make(map[common.Address]time.Time), + } +} + +func (s *stuckTxDetector) DetectStuckTransaction(ctx context.Context, tx *types.Transaction) (bool, error) { + //nolint:gocritic //placeholder for upcoming chaintypes + switch s.chainType { + default: + return s.timeBasedDetection(tx), nil + } +} + +// timeBasedDetection marks a transaction if all the following conditions are met: +// - LastBroadcastAt is not nil +// - Time since last broadcast is above the threshold +// - Time since last purge is above threshold +// +// NOTE: Potentially we can use a subset of threhsold for last purge check, because the transaction would have already been broadcasted to the mempool +// so it is more likely to be picked up compared to a transaction that hasn't been broadcasted before. This would avoid slowing down TXM for sebsequent transactions +// in case the current one is stuck. +func (s *stuckTxDetector) timeBasedDetection(tx *types.Transaction) bool { + threshold := (s.config.BlockTime * time.Duration(s.config.StuckTxBlockThreshold)) + if tx.LastBroadcastAt != nil && min(time.Since(*tx.LastBroadcastAt), time.Since(s.lastPurgeMap[tx.FromAddress])) > threshold { + s.lggr.Debugf("TxID: %v last broadcast was: %v and last purge: %v which is more than the max configured duration: %v. Transaction is now considered stuck and will be purged.", + tx.ID, tx.LastBroadcastAt, s.lastPurgeMap[tx.FromAddress], threshold) + s.lastPurgeMap[tx.FromAddress] = time.Now() + return true + } + return false +} + +type APIResponse struct { + Status string `json:"status,omitempty"` + Hash common.Hash `json:"hash,omitempty"` +} + +const ( + APIStatusPending = "PENDING" + APIStatusIncluded = "INCLUDED" + APIStatusFailed = "FAILED" + APIStatusCancelled = "CANCELLED" + APIStatusUnknown = "UNKNOWN" +) + +// Deprecated: DualBroadcastDetection doesn't provide any significant benefits in terms of speed and time +// based detection can replace it. +func (s *stuckTxDetector) DualBroadcastDetection(ctx context.Context, tx *types.Transaction) (bool, error) { + for _, attempt := range tx.Attempts { + req, err := http.NewRequestWithContext(ctx, http.MethodGet, s.config.DetectionURL+attempt.Hash.String(), nil) + if err != nil { + return false, fmt.Errorf("failed to make request for txID: %v, attemptHash: %v - %w", tx.ID, attempt.Hash, err) + } + resp, err := http.DefaultClient.Do(req) + if err != nil { + return false, fmt.Errorf("failed to get transaction status for txID: %v, attemptHash: %v - %w", tx.ID, attempt.Hash, err) + } + if resp.StatusCode != http.StatusOK { + resp.Body.Close() + return false, fmt.Errorf("request %v failed with status: %d", req, resp.StatusCode) + } + body, err := io.ReadAll(resp.Body) + resp.Body.Close() + if err != nil { + return false, err + } + + var apiResponse APIResponse + err = json.Unmarshal(body, &apiResponse) + if err != nil { + return false, fmt.Errorf("failed to unmarshal response for txID: %v, attemptHash: %v - %w: %s", tx.ID, attempt.Hash, err, string(body)) + } + switch apiResponse.Status { + case APIStatusPending, APIStatusIncluded: + return false, nil + case APIStatusFailed, APIStatusCancelled: + s.lggr.Debugf("TxID: %v with attempHash: %v was marked as failed/cancelled by the RPC. Transaction is now considered stuck and will be purged.", + tx.ID, attempt.Hash) + return true, nil + case APIStatusUnknown: + continue + default: + continue + } + } + return false, nil +} diff --git a/core/chains/evm/txm/stuck_tx_detector_test.go b/core/chains/evm/txm/stuck_tx_detector_test.go new file mode 100644 index 00000000000..af5a765dcdb --- /dev/null +++ b/core/chains/evm/txm/stuck_tx_detector_test.go @@ -0,0 +1,80 @@ +package txm + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/testutils" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txm/types" +) + +func TestTimeBasedDetection(t *testing.T) { + t.Parallel() + + t.Run("returns false if transaction is not stuck", func(t *testing.T) { + config := StuckTxDetectorConfig{ + BlockTime: 10 * time.Second, + StuckTxBlockThreshold: 5, + } + fromAddress := testutils.NewAddress() + s := NewStuckTxDetector(logger.Test(t), "", config) + + // No previous broadcast + tx := &types.Transaction{ + ID: 1, + LastBroadcastAt: nil, + FromAddress: fromAddress, + } + assert.False(t, s.timeBasedDetection(tx)) + // Not enough time has passed since last broadcast + now := time.Now() + tx.LastBroadcastAt = &now + assert.False(t, s.timeBasedDetection(tx)) + // Not enough time has passed since last purge + tx.LastBroadcastAt = &time.Time{} + s.lastPurgeMap[fromAddress] = now + assert.False(t, s.timeBasedDetection(tx)) + }) + + t.Run("returns true if transaction is stuck", func(t *testing.T) { + config := StuckTxDetectorConfig{ + BlockTime: 10 * time.Second, + StuckTxBlockThreshold: 5, + } + fromAddress := testutils.NewAddress() + s := NewStuckTxDetector(logger.Test(t), "", config) + + tx := &types.Transaction{ + ID: 1, + LastBroadcastAt: &time.Time{}, + FromAddress: fromAddress, + } + assert.True(t, s.timeBasedDetection(tx)) + }) + + t.Run("marks first tx as stuck, updates purge time for address, and returns false for the second tx with the same broadcast time", func(t *testing.T) { + config := StuckTxDetectorConfig{ + BlockTime: 1 * time.Second, + StuckTxBlockThreshold: 10, + } + fromAddress := testutils.NewAddress() + s := NewStuckTxDetector(logger.Test(t), "", config) + + tx1 := &types.Transaction{ + ID: 1, + LastBroadcastAt: &time.Time{}, + FromAddress: fromAddress, + } + tx2 := &types.Transaction{ + ID: 2, + LastBroadcastAt: &time.Time{}, + FromAddress: fromAddress, + } + assert.True(t, s.timeBasedDetection(tx1)) + assert.False(t, s.timeBasedDetection(tx2)) + }) +} diff --git a/core/chains/evm/txm/txm.go b/core/chains/evm/txm/txm.go new file mode 100644 index 00000000000..c8b4b6f1688 --- /dev/null +++ b/core/chains/evm/txm/txm.go @@ -0,0 +1,447 @@ +package txm + +import ( + "context" + "fmt" + "math/big" + "sync" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/jpillora/backoff" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txm/types" +) + +const ( + broadcastInterval time.Duration = 30 * time.Second + maxInFlightTransactions int = 16 + maxInFlightSubset int = 5 + maxAllowedAttempts uint16 = 10 + pendingNonceDefaultTimeout time.Duration = 30 * time.Second + pendingNonceRecheckInterval time.Duration = 1 * time.Second +) + +type Client interface { + PendingNonceAt(context.Context, common.Address) (uint64, error) + NonceAt(context.Context, common.Address, *big.Int) (uint64, error) + SendTransaction(ctx context.Context, tx *types.Transaction, attempt *types.Attempt) error +} + +type TxStore interface { + AbandonPendingTransactions(context.Context, common.Address) error + AppendAttemptToTransaction(context.Context, uint64, common.Address, *types.Attempt) error + CreateEmptyUnconfirmedTransaction(context.Context, common.Address, uint64, uint64) (*types.Transaction, error) + CreateTransaction(context.Context, *types.TxRequest) (*types.Transaction, error) + FetchUnconfirmedTransactionAtNonceWithCount(context.Context, uint64, common.Address) (*types.Transaction, int, error) + MarkConfirmedAndReorgedTransactions(context.Context, uint64, common.Address) ([]*types.Transaction, []uint64, error) + MarkUnconfirmedTransactionPurgeable(context.Context, uint64, common.Address) error + UpdateTransactionBroadcast(context.Context, uint64, uint64, common.Hash, common.Address) error + UpdateUnstartedTransactionWithNonce(context.Context, common.Address, uint64) (*types.Transaction, error) + + // ErrorHandler + DeleteAttemptForUnconfirmedTx(context.Context, uint64, *types.Attempt, common.Address) error + MarkTxFatal(context.Context, *types.Transaction, common.Address) error +} + +type AttemptBuilder interface { + NewAttempt(context.Context, logger.Logger, *types.Transaction, bool) (*types.Attempt, error) + NewBumpAttempt(context.Context, logger.Logger, *types.Transaction, types.Attempt) (*types.Attempt, error) +} + +type ErrorHandler interface { + HandleError(*types.Transaction, error, AttemptBuilder, Client, TxStore, func(common.Address, uint64), bool) (err error) +} + +type StuckTxDetector interface { + DetectStuckTransaction(ctx context.Context, tx *types.Transaction) (bool, error) +} + +type Keystore interface { + EnabledAddressesForChain(ctx context.Context, chainID *big.Int) (addresses []common.Address, err error) +} + +type Config struct { + EIP1559 bool + BlockTime time.Duration + RetryBlockThreshold uint16 + EmptyTxLimitDefault uint64 +} + +type Txm struct { + services.StateMachine + lggr logger.SugaredLogger + chainID *big.Int + client Client + attemptBuilder AttemptBuilder + errorHandler ErrorHandler + stuckTxDetector StuckTxDetector + txStore TxStore + keystore Keystore + config Config + metrics *txmMetrics + + nonceMapMu sync.RWMutex + nonceMap map[common.Address]uint64 + + triggerCh map[common.Address]chan struct{} + stopCh services.StopChan + wg sync.WaitGroup +} + +func NewTxm(lggr logger.Logger, chainID *big.Int, client Client, attemptBuilder AttemptBuilder, txStore TxStore, stuckTxDetector StuckTxDetector, config Config, keystore Keystore) *Txm { + return &Txm{ + lggr: logger.Sugared(logger.Named(lggr, "Txm")), + keystore: keystore, + chainID: chainID, + client: client, + attemptBuilder: attemptBuilder, + txStore: txStore, + stuckTxDetector: stuckTxDetector, + config: config, + nonceMap: make(map[common.Address]uint64), + triggerCh: make(map[common.Address]chan struct{}), + } +} + +func (t *Txm) Start(ctx context.Context) error { + return t.StartOnce("Txm", func() error { + tm, err := NewTxmMetrics(t.chainID) + if err != nil { + return err + } + t.metrics = tm + t.stopCh = make(chan struct{}) + + addresses, err := t.keystore.EnabledAddressesForChain(ctx, t.chainID) + if err != nil { + return err + } + for _, address := range addresses { + t.startAddress(address) + } + return nil + }) +} + +func (t *Txm) startAddress(address common.Address) { + triggerCh := make(chan struct{}, 1) + t.triggerCh[address] = triggerCh + + t.wg.Add(2) + go t.broadcastLoop(address, triggerCh) + go t.backfillLoop(address) +} + +func (t *Txm) initializeNonce(ctx context.Context, address common.Address) { + ctxWithTimeout, cancel := context.WithTimeout(ctx, pendingNonceDefaultTimeout) + defer cancel() + for { + pendingNonce, err := t.client.PendingNonceAt(ctxWithTimeout, address) + if err != nil { + t.lggr.Errorw("Error when fetching initial nonce", "address", address, "err", err) + select { + case <-time.After(pendingNonceRecheckInterval): + case <-ctx.Done(): + t.lggr.Errorw("context error", "err", context.Cause(ctx)) + return + } + continue + } + t.setNonce(address, pendingNonce) + t.lggr.Debugf("Set initial nonce for address: %v to %d", address, pendingNonce) + return + } +} + +func (t *Txm) Close() error { + return t.StopOnce("Txm", func() error { + close(t.stopCh) + t.wg.Wait() + return nil + }) +} + +func (t *Txm) HealthReport() map[string]error { + return map[string]error{t.lggr.Name(): t.Healthy()} +} + +func (t *Txm) CreateTransaction(ctx context.Context, txRequest *types.TxRequest) (tx *types.Transaction, err error) { + tx, err = t.txStore.CreateTransaction(ctx, txRequest) + if err == nil { + t.lggr.Infow("Created transaction", "tx", tx) + } + return +} + +func (t *Txm) Trigger(address common.Address) { + if !t.IfStarted(func() { + triggerCh, exists := t.triggerCh[address] + if !exists { + return + } + triggerCh <- struct{}{} + }) { + t.lggr.Error("Txm unstarted") + } +} + +func (t *Txm) Abandon(address common.Address) error { + // TODO: restart txm + t.lggr.Infof("Dropping unstarted and unconfirmed transactions for address: %v", address) + return t.txStore.AbandonPendingTransactions(context.TODO(), address) +} + +func (t *Txm) getNonce(address common.Address) uint64 { + t.nonceMapMu.RLock() + defer t.nonceMapMu.RUnlock() + return t.nonceMap[address] +} + +func (t *Txm) setNonce(address common.Address, nonce uint64) { + t.nonceMapMu.Lock() + t.nonceMap[address] = nonce + defer t.nonceMapMu.Unlock() +} + +func newBackoff(minDuration time.Duration) backoff.Backoff { + return backoff.Backoff{ + Min: minDuration, + Max: 1 * time.Minute, + Jitter: true, + } +} + +func (t *Txm) broadcastLoop(address common.Address, triggerCh chan struct{}) { + defer t.wg.Done() + ctx, cancel := t.stopCh.NewCtx() + defer cancel() + broadcastWithBackoff := newBackoff(1 * time.Second) + var broadcastCh <-chan time.Time + + t.initializeNonce(ctx, address) + + for { + start := time.Now() + bo, err := t.broadcastTransaction(ctx, address) + if err != nil { + t.lggr.Errorw("Error during transaction broadcasting", "err", err) + } else { + t.lggr.Debug("Transaction broadcasting time elapsed: ", time.Since(start)) + } + if bo { + broadcastCh = time.After(broadcastWithBackoff.Duration()) + } else { + broadcastWithBackoff.Reset() + broadcastCh = time.After(utils.WithJitter(broadcastInterval)) + } + select { + case <-ctx.Done(): + return + case <-triggerCh: + continue + case <-broadcastCh: + continue + } + } +} + +func (t *Txm) backfillLoop(address common.Address) { + defer t.wg.Done() + ctx, cancel := t.stopCh.NewCtx() + defer cancel() + backfillWithBackoff := newBackoff(t.config.BlockTime) + backfillCh := time.After(utils.WithJitter(t.config.BlockTime)) + + for { + select { + case <-ctx.Done(): + return + case <-backfillCh: + start := time.Now() + bo, err := t.backfillTransactions(ctx, address) + if err != nil { + t.lggr.Errorw("Error during backfill", "err", err) + } else { + t.lggr.Debug("Backfill time elapsed: ", time.Since(start)) + } + if bo { + backfillCh = time.After(backfillWithBackoff.Duration()) + } else { + backfillWithBackoff.Reset() + backfillCh = time.After(utils.WithJitter(t.config.BlockTime)) + } + } + } +} + +func (t *Txm) broadcastTransaction(ctx context.Context, address common.Address) (bool, error) { + for { + _, unconfirmedCount, err := t.txStore.FetchUnconfirmedTransactionAtNonceWithCount(ctx, 0, address) + if err != nil { + return false, err + } + + // Optimistically send up to maxInFlightSubset of the maxInFlightTransactions. After that threshold, broadcast more cautiously + // by checking the pending nonce so no more than maxInFlightSubset can get stuck simultaneously i.e. due + // to insufficient balance. We're making this trade-off to avoid storing stuck transactions and making unnecessary + // RPC calls. The upper limit is always maxInFlightTransactions regardless of the pending nonce. + if unconfirmedCount >= maxInFlightSubset { + if unconfirmedCount > maxInFlightTransactions { + t.lggr.Warnf("Reached transaction limit: %d for unconfirmed transactions", maxInFlightTransactions) + return true, nil + } + pendingNonce, e := t.client.PendingNonceAt(ctx, address) + if e != nil { + return false, e + } + nonce := t.getNonce(address) + if nonce > pendingNonce { + t.lggr.Warnf("Reached transaction limit. LocalNonce: %d, PendingNonce %d, unconfirmedCount: %d", + nonce, pendingNonce, unconfirmedCount) + return true, nil + } + } + + nonce := t.getNonce(address) + tx, err := t.txStore.UpdateUnstartedTransactionWithNonce(ctx, address, nonce) + if err != nil { + return false, err + } + if tx == nil { + return false, nil + } + t.setNonce(address, nonce+1) + + if err := t.createAndSendAttempt(ctx, tx, address); err != nil { + return false, err + } + } +} + +func (t *Txm) createAndSendAttempt(ctx context.Context, tx *types.Transaction, address common.Address) error { + attempt, err := t.attemptBuilder.NewAttempt(ctx, t.lggr, tx, t.config.EIP1559) + if err != nil { + return err + } + + if tx.Nonce == nil { + return fmt.Errorf("nonce for txID: %v is empty", tx.ID) + } + if err = t.txStore.AppendAttemptToTransaction(ctx, *tx.Nonce, address, attempt); err != nil { + return err + } + + return t.sendTransactionWithError(ctx, tx, attempt, address) +} + +func (t *Txm) sendTransactionWithError(ctx context.Context, tx *types.Transaction, attempt *types.Attempt, address common.Address) (err error) { + if tx.Nonce == nil { + return fmt.Errorf("nonce for txID: %v is empty", tx.ID) + } + start := time.Now() + txErr := t.client.SendTransaction(ctx, tx, attempt) + tx.AttemptCount++ + t.lggr.Infow("Broadcasted attempt", "tx", tx, "attempt", attempt, "duration", time.Since(start), "txErr: ", txErr) + if txErr != nil && t.errorHandler != nil { + if err = t.errorHandler.HandleError(tx, txErr, t.attemptBuilder, t.client, t.txStore, t.setNonce, false); err != nil { + return + } + } else if txErr != nil { + pendingNonce, err := t.client.PendingNonceAt(ctx, address) + if err != nil { + return err + } + if pendingNonce <= *tx.Nonce { + return fmt.Errorf("Pending nonce for txID: %v didn't increase. PendingNonce: %d, TxNonce: %d. TxErr: %w", tx.ID, pendingNonce, *tx.Nonce, txErr) + } + } + + t.metrics.IncrementNumBroadcastedTxs(ctx) + return t.txStore.UpdateTransactionBroadcast(ctx, attempt.TxID, *tx.Nonce, attempt.Hash, address) +} + +func (t *Txm) backfillTransactions(ctx context.Context, address common.Address) (bool, error) { + latestNonce, err := t.client.NonceAt(ctx, address, nil) + if err != nil { + return false, err + } + + confirmedTransactions, unconfirmedTransactionIDs, err := t.txStore.MarkConfirmedAndReorgedTransactions(ctx, latestNonce, address) + if err != nil { + return false, err + } + if len(confirmedTransactions) > 0 || len(unconfirmedTransactionIDs) > 0 { + t.metrics.IncrementNumConfirmedTxs(ctx, len(confirmedTransactions)) + confirmedTransactionIDs := t.extractMetrics(ctx, confirmedTransactions) + t.lggr.Infof("Confirmed transaction IDs: %v . Re-orged transaction IDs: %v", confirmedTransactionIDs, unconfirmedTransactionIDs) + } + + tx, unconfirmedCount, err := t.txStore.FetchUnconfirmedTransactionAtNonceWithCount(ctx, latestNonce, address) + if err != nil { + return false, err + } + if unconfirmedCount == 0 { + t.lggr.Debugf("All transactions confirmed for address: %v", address) + return false, err // TODO: add backoff to optimize requests + } + + if tx == nil || *tx.Nonce != latestNonce { + t.lggr.Warnf("Nonce gap at nonce: %d - address: %v. Creating a new transaction\n", latestNonce, address) + t.metrics.IncrementNumNonceGaps(ctx) + return false, t.createAndSendEmptyTx(ctx, latestNonce, address) + } else { //nolint:revive //easier to read + if !tx.IsPurgeable && t.stuckTxDetector != nil { + isStuck, err := t.stuckTxDetector.DetectStuckTransaction(ctx, tx) + if err != nil { + return false, err + } + if isStuck { + tx.IsPurgeable = true + err = t.txStore.MarkUnconfirmedTransactionPurgeable(ctx, *tx.Nonce, address) + if err != nil { + return false, err + } + t.lggr.Infof("Marked tx as purgeable. Sending purge attempt for txID: %d", tx.ID) + return false, t.createAndSendAttempt(ctx, tx, address) + } + } + + if tx.AttemptCount >= maxAllowedAttempts { + return true, fmt.Errorf("reached max allowed attempts for txID: %d. TXM won't broadcast any more attempts."+ + "If this error persists, it means the transaction won't be confirmed and the TXM needs to be restarted."+ + "Look for any error messages from previous broadcasted attempts that may indicate why this happened, i.e. wallet is out of funds. Tx: %v", tx.ID, + tx.PrintWithAttempts()) + } + + if tx.LastBroadcastAt == nil || time.Since(*tx.LastBroadcastAt) > (t.config.BlockTime*time.Duration(t.config.RetryBlockThreshold)) { + // TODO: add optional graceful bumping strategy + t.lggr.Info("Rebroadcasting attempt for txID: ", tx.ID) + return false, t.createAndSendAttempt(ctx, tx, address) + } + } + return false, nil +} + +func (t *Txm) createAndSendEmptyTx(ctx context.Context, latestNonce uint64, address common.Address) error { + tx, err := t.txStore.CreateEmptyUnconfirmedTransaction(ctx, address, latestNonce, t.config.EmptyTxLimitDefault) + if err != nil { + return err + } + return t.createAndSendAttempt(ctx, tx, address) +} + +func (t *Txm) extractMetrics(ctx context.Context, txs []*types.Transaction) []uint64 { + confirmedTxIDs := make([]uint64, 0, len(txs)) + for _, tx := range txs { + confirmedTxIDs = append(confirmedTxIDs, tx.ID) + if tx.InitialBroadcastAt != nil { + t.metrics.RecordTimeUntilTxConfirmed(ctx, float64(time.Since(*tx.InitialBroadcastAt))) + } + } + return confirmedTxIDs +} diff --git a/core/chains/evm/txm/txm_test.go b/core/chains/evm/txm/txm_test.go new file mode 100644 index 00000000000..af77f3ac084 --- /dev/null +++ b/core/chains/evm/txm/txm_test.go @@ -0,0 +1,327 @@ +package txm + +import ( + "errors" + "fmt" + "testing" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "go.uber.org/zap" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/testutils" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txm/mocks" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txm/storage" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txm/types" +) + +func TestLifecycle(t *testing.T) { + t.Parallel() + + client := mocks.NewClient(t) + ab := mocks.NewAttemptBuilder(t) + address1 := testutils.NewAddress() + address2 := testutils.NewAddress() + assert.NotEqual(t, address1, address2) + addresses := []common.Address{address1, address2} + keystore := mocks.NewKeystore(t) + + t.Run("retries if initial pending nonce call fails", func(t *testing.T) { + lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) + config := Config{BlockTime: 1 * time.Minute} + txStore := storage.NewInMemoryStoreManager(lggr, testutils.FixtureChainID) + require.NoError(t, txStore.Add(address1)) + keystore.On("EnabledAddressesForChain", mock.Anything, mock.Anything).Return([]common.Address{address1}, nil).Once() + txm := NewTxm(lggr, testutils.FixtureChainID, client, nil, txStore, nil, config, keystore) + client.On("PendingNonceAt", mock.Anything, address1).Return(uint64(0), errors.New("error")).Once() + client.On("PendingNonceAt", mock.Anything, address1).Return(uint64(100), nil).Once() + require.NoError(t, txm.Start(tests.Context(t))) + tests.AssertLogEventually(t, observedLogs, "Error when fetching initial nonce") + tests.AssertLogEventually(t, observedLogs, fmt.Sprintf("Set initial nonce for address: %v to %d", address1, 100)) + }) + + t.Run("tests lifecycle successfully without any transactions", func(t *testing.T) { + config := Config{BlockTime: 200 * time.Millisecond} + keystore.On("EnabledAddressesForChain", mock.Anything, mock.Anything).Return(addresses, nil).Once() + lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) + txStore := storage.NewInMemoryStoreManager(lggr, testutils.FixtureChainID) + require.NoError(t, txStore.Add(addresses...)) + txm := NewTxm(lggr, testutils.FixtureChainID, client, ab, txStore, nil, config, keystore) + var nonce uint64 + // Start + client.On("PendingNonceAt", mock.Anything, address1).Return(nonce, nil).Once() + client.On("PendingNonceAt", mock.Anything, address2).Return(nonce, nil).Once() + // backfill loop (may or may not be executed multiple times) + client.On("NonceAt", mock.Anything, address1, mock.Anything).Return(nonce, nil).Maybe() + client.On("NonceAt", mock.Anything, address2, mock.Anything).Return(nonce, nil).Maybe() + + servicetest.Run(t, txm) + tests.AssertLogEventually(t, observedLogs, "Backfill time elapsed") + }) +} + +func TestTrigger(t *testing.T) { + t.Parallel() + + address := testutils.NewAddress() + keystore := mocks.NewKeystore(t) + t.Run("Trigger fails if Txm is unstarted", func(t *testing.T) { + lggr, observedLogs := logger.TestObserved(t, zap.ErrorLevel) + txm := NewTxm(lggr, nil, nil, nil, nil, nil, Config{}, keystore) + txm.Trigger(address) + tests.AssertLogEventually(t, observedLogs, "Txm unstarted") + }) + + t.Run("executes Trigger", func(t *testing.T) { + lggr := logger.Test(t) + txStore := storage.NewInMemoryStoreManager(lggr, testutils.FixtureChainID) + require.NoError(t, txStore.Add(address)) + client := mocks.NewClient(t) + ab := mocks.NewAttemptBuilder(t) + config := Config{BlockTime: 1 * time.Minute, RetryBlockThreshold: 10} + keystore.On("EnabledAddressesForChain", mock.Anything, mock.Anything).Return([]common.Address{address}, nil) + txm := NewTxm(lggr, testutils.FixtureChainID, client, ab, txStore, nil, config, keystore) + var nonce uint64 + // Start + client.On("PendingNonceAt", mock.Anything, address).Return(nonce, nil).Maybe() + servicetest.Run(t, txm) + txm.Trigger(address) + }) +} + +func TestBroadcastTransaction(t *testing.T) { + t.Parallel() + + ctx := tests.Context(t) + client := mocks.NewClient(t) + ab := mocks.NewAttemptBuilder(t) + config := Config{} + address := testutils.NewAddress() + keystore := mocks.NewKeystore(t) + + t.Run("fails if FetchUnconfirmedTransactionAtNonceWithCount for unconfirmed transactions fails", func(t *testing.T) { + mTxStore := mocks.NewTxStore(t) + mTxStore.On("FetchUnconfirmedTransactionAtNonceWithCount", mock.Anything, mock.Anything, mock.Anything).Return(nil, 0, errors.New("call failed")).Once() + txm := NewTxm(logger.Test(t), testutils.FixtureChainID, client, ab, mTxStore, nil, config, keystore) + bo, err := txm.broadcastTransaction(ctx, address) + require.Error(t, err) + assert.False(t, bo) + require.ErrorContains(t, err, "call failed") + }) + + t.Run("throws a warning and returns if unconfirmed transactions exceed maxInFlightTransactions", func(t *testing.T) { + lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) + mTxStore := mocks.NewTxStore(t) + mTxStore.On("FetchUnconfirmedTransactionAtNonceWithCount", mock.Anything, mock.Anything, mock.Anything).Return(nil, maxInFlightTransactions+1, nil).Once() + txm := NewTxm(lggr, testutils.FixtureChainID, client, ab, mTxStore, nil, config, keystore) + bo, err := txm.broadcastTransaction(ctx, address) + assert.True(t, bo) + require.NoError(t, err) + tests.AssertLogEventually(t, observedLogs, "Reached transaction limit") + }) + + t.Run("checks pending nonce if unconfirmed transactions are equal or more than maxInFlightSubset", func(t *testing.T) { + lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) + mTxStore := mocks.NewTxStore(t) + txm := NewTxm(lggr, testutils.FixtureChainID, client, ab, mTxStore, nil, config, keystore) + txm.setNonce(address, 1) + mTxStore.On("FetchUnconfirmedTransactionAtNonceWithCount", mock.Anything, mock.Anything, mock.Anything).Return(nil, maxInFlightSubset, nil).Twice() + + client.On("PendingNonceAt", mock.Anything, address).Return(uint64(0), nil).Once() // LocalNonce: 1, PendingNonce: 0 + bo, err := txm.broadcastTransaction(ctx, address) + assert.True(t, bo) + require.NoError(t, err) + + client.On("PendingNonceAt", mock.Anything, address).Return(uint64(1), nil).Once() // LocalNonce: 1, PendingNonce: 1 + mTxStore.On("UpdateUnstartedTransactionWithNonce", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil).Once() + bo, err = txm.broadcastTransaction(ctx, address) + assert.False(t, bo) + require.NoError(t, err) + tests.AssertLogCountEventually(t, observedLogs, "Reached transaction limit.", 1) + }) + + t.Run("fails if UpdateUnstartedTransactionWithNonce fails", func(t *testing.T) { + mTxStore := mocks.NewTxStore(t) + mTxStore.On("FetchUnconfirmedTransactionAtNonceWithCount", mock.Anything, mock.Anything, mock.Anything).Return(nil, 0, nil).Once() + txm := NewTxm(logger.Test(t), testutils.FixtureChainID, client, ab, mTxStore, nil, config, keystore) + mTxStore.On("UpdateUnstartedTransactionWithNonce", mock.Anything, mock.Anything, mock.Anything).Return(nil, errors.New("call failed")).Once() + bo, err := txm.broadcastTransaction(ctx, address) + assert.False(t, bo) + require.Error(t, err) + require.ErrorContains(t, err, "call failed") + }) + + t.Run("returns if there are no unstarted transactions", func(t *testing.T) { + lggr := logger.Test(t) + txStore := storage.NewInMemoryStoreManager(lggr, testutils.FixtureChainID) + require.NoError(t, txStore.Add(address)) + txm := NewTxm(lggr, testutils.FixtureChainID, client, ab, txStore, nil, config, keystore) + bo, err := txm.broadcastTransaction(ctx, address) + require.NoError(t, err) + assert.False(t, bo) + assert.Equal(t, uint64(0), txm.getNonce(address)) + }) + + t.Run("picks a new tx and creates a new attempt then sends it and updates the broadcast time", func(t *testing.T) { + lggr := logger.Test(t) + txStore := storage.NewInMemoryStoreManager(lggr, testutils.FixtureChainID) + require.NoError(t, txStore.Add(address)) + txm := NewTxm(lggr, testutils.FixtureChainID, client, ab, txStore, nil, config, keystore) + txm.setNonce(address, 8) + metrics, err := NewTxmMetrics(testutils.FixtureChainID) + require.NoError(t, err) + txm.metrics = metrics + IDK := "IDK" + txRequest := &types.TxRequest{ + Data: []byte{100, 200}, + IdempotencyKey: &IDK, + ChainID: testutils.FixtureChainID, + FromAddress: address, + ToAddress: testutils.NewAddress(), + SpecifiedGasLimit: 22000, + } + tx, err := txm.CreateTransaction(tests.Context(t), txRequest) + require.NoError(t, err) + attempt := &types.Attempt{ + TxID: tx.ID, + Fee: gas.EvmFee{GasPrice: assets.NewWeiI(1)}, + GasLimit: 22000, + } + ab.On("NewAttempt", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(attempt, nil).Once() + client.On("SendTransaction", mock.Anything, mock.Anything, mock.Anything).Return(nil).Once() + + bo, err := txm.broadcastTransaction(ctx, address) + require.NoError(t, err) + assert.False(t, bo) + assert.Equal(t, uint64(9), txm.getNonce(address)) + tx, err = txStore.FindTxWithIdempotencyKey(tests.Context(t), IDK) + require.NoError(t, err) + assert.Len(t, tx.Attempts, 1) + var zeroTime time.Time + assert.Greater(t, *tx.LastBroadcastAt, zeroTime) + assert.Greater(t, *tx.Attempts[0].BroadcastAt, zeroTime) + assert.Greater(t, *tx.InitialBroadcastAt, zeroTime) + }) +} + +func TestBackfillTransactions(t *testing.T) { + t.Parallel() + + ctx := tests.Context(t) + client := mocks.NewClient(t) + ab := mocks.NewAttemptBuilder(t) + txStore := mocks.NewTxStore(t) + config := Config{} + address := testutils.NewAddress() + keystore := mocks.NewKeystore(t) + + t.Run("fails if latest nonce fetching fails", func(t *testing.T) { + txm := NewTxm(logger.Test(t), testutils.FixtureChainID, client, ab, txStore, nil, config, keystore) + client.On("NonceAt", mock.Anything, address, mock.Anything).Return(uint64(0), errors.New("latest nonce fail")).Once() + bo, err := txm.backfillTransactions(ctx, address) + require.Error(t, err) + assert.False(t, bo) + require.ErrorContains(t, err, "latest nonce fail") + }) + + t.Run("fails if MarkConfirmedAndReorgedTransactions fails", func(t *testing.T) { + txm := NewTxm(logger.Test(t), testutils.FixtureChainID, client, ab, txStore, nil, config, keystore) + client.On("NonceAt", mock.Anything, address, mock.Anything).Return(uint64(0), nil).Once() + txStore.On("MarkConfirmedAndReorgedTransactions", mock.Anything, mock.Anything, address). + Return([]*types.Transaction{}, []uint64{}, errors.New("marking transactions confirmed failed")).Once() + bo, err := txm.backfillTransactions(ctx, address) + require.Error(t, err) + assert.False(t, bo) + require.ErrorContains(t, err, "marking transactions confirmed failed") + }) + + t.Run("fills nonce gap", func(t *testing.T) { + lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) + txStore := storage.NewInMemoryStoreManager(lggr, testutils.FixtureChainID) + require.NoError(t, txStore.Add(address)) + ab := mocks.NewAttemptBuilder(t) + c := Config{EIP1559: false, BlockTime: 10 * time.Minute, RetryBlockThreshold: 10, EmptyTxLimitDefault: 22000} + txm := NewTxm(lggr, testutils.FixtureChainID, client, ab, txStore, nil, c, keystore) + emptyMetrics, err := NewTxmMetrics(testutils.FixtureChainID) + require.NoError(t, err) + txm.metrics = emptyMetrics + + // Add a new transaction that will be assigned with nonce = 1. Nonce = 0 is not being tracked by the txStore. This will trigger a nonce gap. + txRequest := &types.TxRequest{ + ChainID: testutils.FixtureChainID, + FromAddress: address, + ToAddress: testutils.NewAddress(), + } + _, err = txm.CreateTransaction(tests.Context(t), txRequest) + require.NoError(t, err) + _, err = txStore.UpdateUnstartedTransactionWithNonce(tests.Context(t), address, 1) // Create nonce gap + require.NoError(t, err) + + // During backfill we observe nonce has changed. The transaction with nonce = 1 should be marked unconfirmed. + // For nonce = 0 there are no transactions stored in txStore, which results in a nonce gap. + // TXM creates a new empty transaction and fills the gap. + client.On("NonceAt", mock.Anything, address, mock.Anything).Return(uint64(0), nil).Once() + attempt := &types.Attempt{ + TxID: 1, + Fee: gas.EvmFee{GasPrice: assets.NewWeiI(1)}, + GasLimit: 22000, + } + ab.On("NewAttempt", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(attempt, nil).Once() + client.On("SendTransaction", mock.Anything, mock.Anything, mock.Anything).Return(nil).Once() + bo, err := txm.backfillTransactions(ctx, address) + require.NoError(t, err) + assert.False(t, bo) + tests.AssertLogEventually(t, observedLogs, fmt.Sprintf("Nonce gap at nonce: %d - address: %v. Creating a new transaction", 0, address)) + _, count, err := txStore.FetchUnconfirmedTransactionAtNonceWithCount(ctx, 0, address) + require.NoError(t, err) + assert.Equal(t, 2, count) + }) + + t.Run("retries attempt after threshold", func(t *testing.T) { + lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) + txStore := storage.NewInMemoryStoreManager(lggr, testutils.FixtureChainID) + require.NoError(t, txStore.Add(address)) + ab := mocks.NewAttemptBuilder(t) + c := Config{EIP1559: false, BlockTime: 1 * time.Second, RetryBlockThreshold: 1, EmptyTxLimitDefault: 22000} + txm := NewTxm(lggr, testutils.FixtureChainID, client, ab, txStore, nil, c, keystore) + emptyMetrics, err := NewTxmMetrics(testutils.FixtureChainID) + require.NoError(t, err) + txm.metrics = emptyMetrics + + IDK := "IDK" + txRequest := &types.TxRequest{ + Data: []byte{100, 200}, + IdempotencyKey: &IDK, + ChainID: testutils.FixtureChainID, + FromAddress: address, + ToAddress: testutils.NewAddress(), + SpecifiedGasLimit: 22000, + } + tx, err := txm.CreateTransaction(tests.Context(t), txRequest) + require.NoError(t, err) + _, err = txStore.UpdateUnstartedTransactionWithNonce(tests.Context(t), address, 0) + require.NoError(t, err) + + attempt := &types.Attempt{ + TxID: tx.ID, + Fee: gas.EvmFee{GasPrice: assets.NewWeiI(1)}, + GasLimit: 22000, + } + ab.On("NewAttempt", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(attempt, nil).Once() + + client.On("NonceAt", mock.Anything, address, mock.Anything).Return(uint64(0), nil).Once() + client.On("SendTransaction", mock.Anything, mock.Anything, mock.Anything).Return(nil).Once() + _, err = txm.backfillTransactions(tests.Context(t), address) + require.NoError(t, err) + tests.AssertLogEventually(t, observedLogs, fmt.Sprintf("Rebroadcasting attempt for txID: %d", attempt.TxID)) + }) +} diff --git a/core/chains/evm/txm/types/transaction.go b/core/chains/evm/txm/types/transaction.go new file mode 100644 index 00000000000..1d1104545d4 --- /dev/null +++ b/core/chains/evm/txm/types/transaction.go @@ -0,0 +1,192 @@ +package types + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "math/big" + "time" + + "github.com/google/uuid" + "gopkg.in/guregu/null.v4" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" + clnull "github.com/smartcontractkit/chainlink-common/pkg/utils/null" + + commontypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" +) + +type Transaction struct { + ID uint64 + IdempotencyKey *string + ChainID *big.Int + Nonce *uint64 + FromAddress common.Address + ToAddress common.Address + Value *big.Int + Data []byte + SpecifiedGasLimit uint64 + + CreatedAt time.Time + InitialBroadcastAt *time.Time + LastBroadcastAt *time.Time + + State commontypes.TxState + IsPurgeable bool + Attempts []*Attempt + AttemptCount uint16 // AttempCount is strictly kept in memory and prevents indefinite retrying + Meta *sqlutil.JSON + Subject uuid.NullUUID + + // Pipeline variables - if you aren't calling this from chain tx task within + // the pipeline, you don't need these variables + PipelineTaskRunID uuid.NullUUID + MinConfirmations clnull.Uint32 + SignalCallback bool + CallbackCompleted bool +} + +func (t *Transaction) String() string { + return fmt.Sprintf(`{txID:%d, IdempotencyKey:%v, ChainID:%v, Nonce:%s, FromAddress:%v, ToAddress:%v, Value:%v, `+ + `Data:%s, SpecifiedGasLimit:%d, CreatedAt:%v, InitialBroadcastAt:%v, LastBroadcastAt:%v, State:%v, IsPurgeable:%v, AttemptCount:%d, `+ + `Meta:%v, Subject:%v}`, + t.ID, stringOrNull(t.IdempotencyKey), t.ChainID, stringOrNull(t.Nonce), t.FromAddress, t.ToAddress, t.Value, + base64.StdEncoding.EncodeToString(t.Data), t.SpecifiedGasLimit, t.CreatedAt, stringOrNull(t.InitialBroadcastAt), stringOrNull(t.LastBroadcastAt), + t.State, t.IsPurgeable, t.AttemptCount, t.Meta, t.Subject) +} + +func stringOrNull[T any](t *T) string { + if t != nil { + return fmt.Sprintf("%v", *t) + } + return "null" +} + +func (t *Transaction) PrintWithAttempts() string { + attempts := " Attempts: [" + for _, a := range t.Attempts { + attempts += a.String() + ", " + } + attempts += "]" + + return t.String() + attempts +} + +func (t *Transaction) FindAttemptByHash(attemptHash common.Hash) (*Attempt, error) { + for _, a := range t.Attempts { + if a.Hash == attemptHash { + return a, nil + } + } + return nil, fmt.Errorf("attempt with hash: %v was not found", attemptHash) +} + +func (t *Transaction) DeepCopy() *Transaction { + txCopy := *t + attemptsCopy := make([]*Attempt, 0, len(t.Attempts)) + for _, attempt := range t.Attempts { + attemptsCopy = append(attemptsCopy, attempt.DeepCopy()) + } + txCopy.Attempts = attemptsCopy + return &txCopy +} + +func (t *Transaction) GetMeta() (*TxMeta, error) { + if t.Meta == nil { + return nil, nil + } + var m TxMeta + if err := json.Unmarshal(*t.Meta, &m); err != nil { + return nil, fmt.Errorf("unmarshalling meta: %w", err) + } + return &m, nil +} + +type Attempt struct { + ID uint64 + TxID uint64 + Hash common.Hash + Fee gas.EvmFee + GasLimit uint64 + Type byte + SignedTransaction *types.Transaction + + CreatedAt time.Time + BroadcastAt *time.Time +} + +func (a *Attempt) DeepCopy() *Attempt { + txCopy := *a + if a.SignedTransaction != nil { + txCopy.SignedTransaction = a.SignedTransaction.WithoutBlobTxSidecar() + } + return &txCopy +} + +func (a *Attempt) String() string { + return fmt.Sprintf(`{ID:%d, TxID:%d, Hash:%v, Fee:%v, GasLimit:%d, Type:%v, CreatedAt:%v, BroadcastAt:%v}`, + a.ID, a.TxID, a.Hash, a.Fee, a.GasLimit, a.Type, a.CreatedAt, stringOrNull(a.BroadcastAt)) +} + +type TxRequest struct { + IdempotencyKey *string + ChainID *big.Int + FromAddress common.Address + ToAddress common.Address + Value *big.Int + Data []byte + SpecifiedGasLimit uint64 + + Meta *sqlutil.JSON // TODO: *TxMeta after migration + ForwarderAddress common.Address + + // Pipeline variables - if you aren't calling this from chain tx task within + // the pipeline, you don't need these variables + PipelineTaskRunID uuid.NullUUID + MinConfirmations clnull.Uint32 + SignalCallback bool +} + +type TxMeta struct { + // Pipeline + JobID *int32 `json:"JobID,omitempty"` + FailOnRevert null.Bool `json:"FailOnRevert,omitempty"` + + // VRF + RequestID *common.Hash `json:"RequestID,omitempty"` + RequestTxHash *common.Hash `json:"RequestTxHash,omitempty"` + RequestIDs []common.Hash `json:"RequestIDs,omitempty"` + RequestTxHashes []common.Hash `json:"RequestTxHashes,omitempty"` + MaxLink *string `json:"MaxLink,omitempty"` + SubID *uint64 `json:"SubId,omitempty"` + GlobalSubID *string `json:"GlobalSubId,omitempty"` + MaxEth *string `json:"MaxEth,omitempty"` + ForceFulfilled *bool `json:"ForceFulfilled,omitempty"` + ForceFulfillmentAttempt *uint64 `json:"ForceFulfillmentAttempt,omitempty"` + + // Used for keepers + UpkeepID *string `json:"UpkeepID,omitempty"` + + // Used for Keystone Workflows + WorkflowExecutionID *string `json:"WorkflowExecutionID,omitempty"` + + // Forwarders + FwdrDestAddress *common.Address `json:"ForwarderDestAddress,omitempty"` + + // CCIP + MessageIDs []string `json:"MessageIDs,omitempty"` + SeqNumbers []uint64 `json:"SeqNumbers,omitempty"` + + // Dual Broadcast + DualBroadcast *bool `json:"DualBroadcast,omitempty"` + DualBroadcastParams *string `json:"DualBroadcastParams,omitempty"` +} + +type QueueingTxStrategy struct { + QueueSize uint32 + Subject uuid.NullUUID +} diff --git a/core/chains/evm/txmgr/attempts.go b/core/chains/evm/txmgr/attempts.go index bcdb28acb53..e0c24c08d9e 100644 --- a/core/chains/evm/txmgr/attempts.go +++ b/core/chains/evm/txmgr/attempts.go @@ -11,7 +11,8 @@ import ( pkgerrors "github.com/pkg/errors" "github.com/smartcontractkit/chainlink-common/pkg/logger" - feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" + + "github.com/smartcontractkit/chainlink/v2/common/fees" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" commontypes "github.com/smartcontractkit/chainlink/v2/common/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" @@ -44,7 +45,7 @@ func NewEvmTxAttemptBuilder(chainID big.Int, feeConfig evmTxAttemptBuilderFeeCon // NewTxAttempt builds an new attempt using the configured fee estimator + using the EIP1559 config to determine tx type // used for when a brand new transaction is being created in the txm -func (c *evmTxAttemptBuilder) NewTxAttempt(ctx context.Context, etx Tx, lggr logger.Logger, opts ...feetypes.Opt) (attempt TxAttempt, fee gas.EvmFee, feeLimit uint64, retryable bool, err error) { +func (c *evmTxAttemptBuilder) NewTxAttempt(ctx context.Context, etx Tx, lggr logger.Logger, opts ...fees.Opt) (attempt TxAttempt, fee gas.EvmFee, feeLimit uint64, retryable bool, err error) { txType := 0x0 if c.feeConfig.EIP1559DynamicFees() { txType = 0x2 @@ -54,7 +55,7 @@ func (c *evmTxAttemptBuilder) NewTxAttempt(ctx context.Context, etx Tx, lggr log // NewTxAttemptWithType builds a new attempt with a new fee estimation where the txType can be specified by the caller // used for L2 re-estimation on broadcasting (note EIP1559 must be disabled otherwise this will fail with mismatched fees + tx type) -func (c *evmTxAttemptBuilder) NewTxAttemptWithType(ctx context.Context, etx Tx, lggr logger.Logger, txType int, opts ...feetypes.Opt) (attempt TxAttempt, fee gas.EvmFee, feeLimit uint64, retryable bool, err error) { +func (c *evmTxAttemptBuilder) NewTxAttemptWithType(ctx context.Context, etx Tx, lggr logger.Logger, txType int, opts ...fees.Opt) (attempt TxAttempt, fee gas.EvmFee, feeLimit uint64, retryable bool, err error) { keySpecificMaxGasPriceWei := c.feeConfig.PriceMaxKey(etx.FromAddress) fee, feeLimit, err = c.EvmFeeEstimator.GetFee(ctx, etx.EncodedPayload, etx.FeeLimit, keySpecificMaxGasPriceWei, &etx.FromAddress, &etx.ToAddress, opts...) if err != nil { diff --git a/core/chains/evm/txmgr/broadcaster_test.go b/core/chains/evm/txmgr/broadcaster_test.go index 311f1aae648..561f7a3b93a 100644 --- a/core/chains/evm/txmgr/broadcaster_test.go +++ b/core/chains/evm/txmgr/broadcaster_test.go @@ -27,12 +27,11 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink-framework/multinode" - commonclient "github.com/smartcontractkit/chainlink/v2/common/client" - commmonfee "github.com/smartcontractkit/chainlink/v2/common/fee" + "github.com/smartcontractkit/chainlink/v2/common/fees" txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" @@ -261,7 +260,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) { } ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == uint64(2) && tx.Value().Cmp(big.NewInt(242)) == 0 - }), fromAddress).Return(commonclient.Successful, nil).Once() + }), fromAddress).Return(multinode.Successful, nil).Once() // Earlier tr := int32(99) @@ -289,7 +288,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) { require.Equal(t, value.String(), tx.Value().String()) require.Equal(t, earlierEthTx.EncodedPayload, tx.Data()) return true - }), fromAddress).Return(commonclient.Successful, nil).Once() + }), fromAddress).Return(multinode.Successful, nil).Once() // Later laterEthTx := txmgr.Tx{ @@ -312,7 +311,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) { require.Equal(t, value.String(), tx.Value().String()) require.Equal(t, laterEthTx.EncodedPayload, tx.Data()) return true - }), fromAddress).Return(commonclient.Successful, nil).Once() + }), fromAddress).Return(multinode.Successful, nil).Once() // Insertion order deliberately reversed to test ordering require.NoError(t, txStore.InsertTx(ctx, &expensiveEthTx)) @@ -394,7 +393,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) { t.Run("sends transactions with type 0x2 in EIP-1559 mode", func(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == uint64(343) && tx.Value().Cmp(big.NewInt(242)) == 0 - }), fromAddress).Return(commonclient.Successful, nil).Once() + }), fromAddress).Return(multinode.Successful, nil).Once() etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, []byte{42, 42, 0}, gasLimit, big.Int(assets.NewEthValue(242)), testutils.FixtureChainID) // Do the thing @@ -445,7 +444,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) { } ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == uint64(344) && tx.Value().Cmp(big.NewInt(442)) == 0 - }), fromAddress).Return(commonclient.Successful, nil).Once() + }), fromAddress).Return(multinode.Successful, nil).Once() ethClient.On("CallContext", mock.Anything, mock.AnythingOfType("*hexutil.Bytes"), "eth_call", mock.MatchedBy(func(callarg map[string]interface{}) bool { if fmt.Sprintf("%s", callarg["value"]) == "0x1ba" { // 442 assert.Equal(t, txRequest.FromAddress, callarg["from"]) @@ -478,7 +477,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) { t.Run("with unknown error, sends tx as normal", func(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == uint64(345) && tx.Value().Cmp(big.NewInt(542)) == 0 - }), fromAddress).Return(commonclient.Successful, nil).Once() + }), fromAddress).Return(multinode.Successful, nil).Once() ethClient.On("CallContext", mock.Anything, mock.AnythingOfType("*hexutil.Bytes"), "eth_call", mock.MatchedBy(func(callarg map[string]interface{}) bool { return fmt.Sprintf("%s", callarg["value"]) == "0x21e" // 542 }), "latest").Return(errors.New("this is not a revert, something unexpected went wrong")).Once() @@ -529,7 +528,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) { etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, []byte{42, 42, 0}, gasLimit, big.Int(assets.NewEthValue(243)), testutils.FixtureChainID) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == uint64(346) && tx.Value().Cmp(big.NewInt(243)) == 0 - }), fromAddress).Return(commonclient.Fatal, errors.New(terminallyStuckError)).Once() + }), fromAddress).Return(multinode.Fatal, errors.New(terminallyStuckError)).Once() // Start processing unstarted transactions retryable, err := eb.ProcessUnstartedTxs(tests.Context(t), fromAddress) @@ -569,7 +568,7 @@ func TestEthBroadcaster_TransmitChecking(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == 0 && tx.Value().Cmp(big.NewInt(442)) == 0 - }), fromAddress).Return(commonclient.Successful, nil).Once() + }), fromAddress).Return(multinode.Successful, nil).Once() ethTx := mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, testutils.FixtureChainID, txRequestWithValue(big.Int(assets.NewEthValue(442))), @@ -592,7 +591,7 @@ func TestEthBroadcaster_TransmitChecking(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == 1 && tx.Value().Cmp(big.NewInt(442)) == 0 - }), fromAddress).Return(commonclient.Successful, nil).Once() + }), fromAddress).Return(multinode.Successful, nil).Once() ethTx := mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, testutils.FixtureChainID, txRequestWithValue(big.Int(assets.NewEthValue(442))), @@ -713,7 +712,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success_WithMultiplier(t *testing ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { assert.Equal(t, int(1600), int(tx.Gas())) return true - }), fromAddress).Return(commonclient.Successful, nil).Once() + }), fromAddress).Return(multinode.Successful, nil).Once() txRequest := txmgr.TxRequest{ FromAddress: fromAddress, @@ -799,7 +798,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == uint64(firstNonce) - }), fromAddress).Return(commonclient.Successful, nil).Once() + }), fromAddress).Return(multinode.Successful, nil).Once() // Do the thing { @@ -836,7 +835,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == uint64(firstNonce) - }), fromAddress).Return(commonclient.Fatal, errors.New("exceeds block gas limit")).Once() + }), fromAddress).Return(multinode.Fatal, errors.New("exceeds block gas limit")).Once() // Do the thing { @@ -873,7 +872,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == uint64(firstNonce) - }), fromAddress).Return(commonclient.Successful, errors.New("known transaction: a1313bd99a81fb4d8ad1d2e90b67c6b3fa77545c990d6251444b83b70b6f8980")).Once() + }), fromAddress).Return(multinode.Successful, errors.New("known transaction: a1313bd99a81fb4d8ad1d2e90b67c6b3fa77545c990d6251444b83b70b6f8980")).Once() // Do the thing { @@ -909,7 +908,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == uint64(firstNonce) - }), fromAddress).Return(commonclient.TransactionAlreadyKnown, errors.New("nonce too low")).Once() + }), fromAddress).Return(multinode.TransactionAlreadyKnown, errors.New("nonce too low")).Once() // Do the thing { @@ -947,7 +946,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == uint64(firstNonce) - }), fromAddress).Return(commonclient.Retryable, failedToReachNodeError).Once() + }), fromAddress).Return(multinode.Retryable, failedToReachNodeError).Once() // Do the thing retryable, err := eb.ProcessUnstartedTxs(tests.Context(t), fromAddress) @@ -994,7 +993,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { s, e := txmgr.GetGethSignedTx(attempt.SignedRawTx) require.NoError(t, e) return tx.Nonce() == uint64(firstNonce) && tx.GasPrice().Int64() == s.GasPrice().Int64() - }), fromAddress).Return(commonclient.Successful, errors.New("known transaction: a1313bd99a81fb4d8ad1d2e90b67c6b3fa77545c990d6251444b83b70b6f8980")).Once() + }), fromAddress).Return(multinode.Successful, errors.New("known transaction: a1313bd99a81fb4d8ad1d2e90b67c6b3fa77545c990d6251444b83b70b6f8980")).Once() // Do the thing { @@ -1059,7 +1058,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { // First send, replacement underpriced ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == uint64(0) - }), fromAddress).Return(commonclient.Successful, errors.New("replacement transaction underpriced")).Once() + }), fromAddress).Return(multinode.Successful, errors.New("replacement transaction underpriced")).Once() // Do the thing retryable, err := eb.ProcessUnstartedTxs(ctx, fromAddress) @@ -1096,7 +1095,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, testutils.FixtureChainID) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNextNonce - }), fromAddress).Return(commonclient.Fatal, errors.New(fatalErrorExample)).Once() + }), fromAddress).Return(multinode.Fatal, errors.New(fatalErrorExample)).Once() retryable, err := eb.ProcessUnstartedTxs(ctx, fromAddress) assert.NoError(t, err) @@ -1146,7 +1145,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNextNonce - }), fromAddress).Return(commonclient.Fatal, errors.New(fatalErrorExample)).Once() + }), fromAddress).Return(multinode.Fatal, errors.New(fatalErrorExample)).Once() retryable, err := eb.ProcessUnstartedTxs(ctx, fromAddress) require.Error(t, err) @@ -1167,7 +1166,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNextNonce - }), fromAddress).Return(commonclient.Fatal, errors.New(fatalErrorExample)).Once() + }), fromAddress).Return(multinode.Fatal, errors.New(fatalErrorExample)).Once() { retryable, err := eb.ProcessUnstartedTxs(ctx, fromAddress) @@ -1200,7 +1199,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, testutils.FixtureChainID) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNextNonce - }), fromAddress).Return(commonclient.ExceedsMaxFee, errors.New(TxFeeExceedsCapError)).Twice() + }), fromAddress).Return(multinode.ExceedsMaxFee, errors.New(TxFeeExceedsCapError)).Twice() // In the first case, the tx was NOT accepted into the mempool. In the case // of multiple RPC nodes, it is possible that it can be accepted by // another node even if the primary one returns "exceeds the configured @@ -1258,7 +1257,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, testutils.FixtureChainID) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNextNonce - }), fromAddress).Return(commonclient.Unknown, errors.New(retryableErrorExample)).Once() + }), fromAddress).Return(multinode.Unknown, errors.New(retryableErrorExample)).Once() // Nonce is the same as localNextNonce, implying that this sent transaction has not been accepted ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(localNextNonce, nil).Once() @@ -1284,7 +1283,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { // Now on the second run, it is successful ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNextNonce - }), fromAddress).Return(commonclient.Successful, nil).Once() + }), fromAddress).Return(multinode.Successful, nil).Once() retryable, err = eb.ProcessUnstartedTxs(ctx, fromAddress) assert.NoError(t, err) @@ -1310,7 +1309,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, testutils.FixtureChainID) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNextNonce - }), fromAddress).Return(commonclient.Unknown, errors.New(retryableErrorExample)).Once() + }), fromAddress).Return(multinode.Unknown, errors.New(retryableErrorExample)).Once() ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), errors.New("pending nonce fetch failed")).Once() // Do the thing @@ -1336,7 +1335,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { // Now on the second run, it is successful ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNextNonce - }), fromAddress).Return(commonclient.Successful, nil).Once() + }), fromAddress).Return(multinode.Successful, nil).Once() retryable, err = eb.ProcessUnstartedTxs(ctx, fromAddress) assert.NoError(t, err) @@ -1362,7 +1361,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, testutils.FixtureChainID) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNextNonce - }), fromAddress).Return(commonclient.Unknown, errors.New(retryableErrorExample)).Once() + }), fromAddress).Return(multinode.Unknown, errors.New(retryableErrorExample)).Once() // Nonce is one higher than localNextNonce, implying that despite the error, this sent transaction has been accepted into the mempool ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(localNextNonce+1, nil).Once() @@ -1396,17 +1395,17 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { // First was underpriced ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNextNonce && tx.GasPrice().Cmp(evmcfg.EVM().GasEstimator().PriceDefault().ToInt()) == 0 - }), fromAddress).Return(commonclient.Underpriced, errors.New(underpricedError)).Once() + }), fromAddress).Return(multinode.Underpriced, errors.New(underpricedError)).Once() // Second with gas bump was still underpriced ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNextNonce && tx.GasPrice().Cmp(big.NewInt(25000000000)) == 0 - }), fromAddress).Return(commonclient.Underpriced, errors.New(underpricedError)).Once() + }), fromAddress).Return(multinode.Underpriced, errors.New(underpricedError)).Once() // Third succeeded ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNextNonce && tx.GasPrice().Cmp(big.NewInt(30000000000)) == 0 - }), fromAddress).Return(commonclient.Successful, nil).Once() + }), fromAddress).Return(multinode.Successful, nil).Once() // Do the thing retryable, err := eb.ProcessUnstartedTxs(ctx, fromAddress) @@ -1442,7 +1441,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNextNonce - }), fromAddress).Return(commonclient.Retryable, failedToReachNodeError).Once() + }), fromAddress).Return(multinode.Retryable, failedToReachNodeError).Once() // Do the thing retryable, err := eb.ProcessUnstartedTxs(ctx, fromAddress) @@ -1473,7 +1472,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNextNonce - }), fromAddress).Return(commonclient.Successful, errors.New(temporarilyUnderpricedError)).Once() + }), fromAddress).Return(multinode.Successful, errors.New(temporarilyUnderpricedError)).Once() // Do the thing retryable, err := eb.ProcessUnstartedTxs(ctx, fromAddress) @@ -1512,7 +1511,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { // First was underpriced ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNextNonce && tx.GasPrice().Cmp(evmcfg2.EVM().GasEstimator().PriceDefault().ToInt()) == 0 - }), fromAddress).Return(commonclient.Underpriced, errors.New(underpricedError)).Once() + }), fromAddress).Return(multinode.Underpriced, errors.New(underpricedError)).Once() // Do the thing retryable, err := eb2.ProcessUnstartedTxs(ctx, fromAddress) @@ -1530,7 +1529,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, testutils.FixtureChainID) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNextNonce - }), fromAddress).Return(commonclient.InsufficientFunds, errors.New(insufficientEthError)).Once() + }), fromAddress).Return(multinode.InsufficientFunds, errors.New(insufficientEthError)).Once() retryable, err := eb.ProcessUnstartedTxs(ctx, fromAddress) require.Error(t, err) @@ -1560,7 +1559,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, testutils.FixtureChainID) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNextNonce - }), fromAddress).Return(commonclient.Retryable, errors.New(nonceGapError)).Once() + }), fromAddress).Return(multinode.Retryable, errors.New(nonceGapError)).Once() retryable, err := eb.ProcessUnstartedTxs(ctx, fromAddress) require.Error(t, err) @@ -1604,7 +1603,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { localNextNonce = getLocalNextNonce(t, nonceTracker, fromAddress) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNextNonce && tx.GasTipCap().Cmp(big.NewInt(1)) == 0 - }), fromAddress).Return(commonclient.Underpriced, errors.New(underpricedError)).Once() + }), fromAddress).Return(multinode.Underpriced, errors.New(underpricedError)).Once() // Check gas tip cap verification retryable, err := eb2.ProcessUnstartedTxs(ctx, fromAddress) @@ -1635,15 +1634,15 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { // Second was underpriced but above minimum ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNextNonce && tx.GasTipCap().Cmp(gasTipCapDefault.ToInt()) == 0 - }), fromAddress).Return(commonclient.Underpriced, errors.New(underpricedError)).Once() + }), fromAddress).Return(multinode.Underpriced, errors.New(underpricedError)).Once() // Resend at the bumped price ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNextNonce && tx.GasTipCap().Cmp(big.NewInt(0).Add(gasTipCapDefault.ToInt(), evmcfg2.EVM().GasEstimator().BumpMin().ToInt())) == 0 - }), fromAddress).Return(commonclient.Underpriced, errors.New(underpricedError)).Once() + }), fromAddress).Return(multinode.Underpriced, errors.New(underpricedError)).Once() // Final bump succeeds ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNextNonce && tx.GasTipCap().Cmp(big.NewInt(0).Add(gasTipCapDefault.ToInt(), big.NewInt(0).Mul(evmcfg2.EVM().GasEstimator().BumpMin().ToInt(), big.NewInt(2)))) == 0 - }), fromAddress).Return(commonclient.Successful, nil).Once() + }), fromAddress).Return(multinode.Successful, nil).Once() retryable, err := eb2.ProcessUnstartedTxs(ctx, fromAddress) require.NoError(t, err) @@ -1693,7 +1692,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_GasEstimationError(t *testing.T) ethClient.On("EstimateGas", mock.Anything, mock.Anything).Return(estimatedGasLimit, nil).Once() ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == uint64(0) - }), fromAddress).Return(commonclient.Successful, nil).Once() + }), fromAddress).Return(multinode.Successful, nil).Once() // Do the thing retryable, err := eb.ProcessUnstartedTxs(ctx, fromAddress) @@ -1717,7 +1716,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_GasEstimationError(t *testing.T) dbEtx, err := txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) require.Equal(t, txmgrcommon.TxFatalError, dbEtx.State) - require.Equal(t, commmonfee.ErrFeeLimitTooLow.Error(), dbEtx.Error.String) + require.Equal(t, fees.ErrFeeLimitTooLow.Error(), dbEtx.Error.String) }) } @@ -1860,7 +1859,7 @@ func TestEthBroadcaster_NonceTracker_InProgressTx(t *testing.T) { inProgressTxNonce := uint64(0) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == inProgressTxNonce - }), fromAddress).Return(commonclient.Successful, nil).Once() + }), fromAddress).Return(multinode.Successful, nil).Once() // Tx with nonce 0 in DB will set local nonce map to value to 1 mustInsertInProgressEthTxWithAttempt(t, txStore, evmtypes.Nonce(inProgressTxNonce), fromAddress) @@ -1903,7 +1902,7 @@ func TestEthBroadcaster_HederaBroadcastValidation(t *testing.T) { localNonce := uint64(0) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNonce - }), fromAddress).Return(commonclient.Successful, nil).Once() + }), fromAddress).Return(multinode.Successful, nil).Once() ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(1), nil).Once() mustInsertInProgressEthTxWithAttempt(t, txStore, evmtypes.Nonce(localNonce), fromAddress) @@ -1923,7 +1922,7 @@ func TestEthBroadcaster_HederaBroadcastValidation(t *testing.T) { localNonce := uint64(0) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNonce - }), fromAddress).Return(commonclient.Successful, nil).Twice() + }), fromAddress).Return(multinode.Successful, nil).Twice() ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Once() ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(1), nil).Once() @@ -1945,7 +1944,7 @@ func TestEthBroadcaster_HederaBroadcastValidation(t *testing.T) { localNonce := uint64(0) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNonce - }), fromAddress).Return(commonclient.Successful, nil).Times(4) + }), fromAddress).Return(multinode.Successful, nil).Times(4) ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Times(4) etx := mustInsertInProgressEthTxWithAttempt(t, txStore, evmtypes.Nonce(localNonce), fromAddress) diff --git a/core/chains/evm/txmgr/builder.go b/core/chains/evm/txmgr/builder.go index 73c5614aba3..aa6b9f4575b 100644 --- a/core/chains/evm/txmgr/builder.go +++ b/core/chains/evm/txmgr/builder.go @@ -18,6 +18,9 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/keystore" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txm" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txm/clientwrappers" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txm/storage" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) @@ -40,6 +43,7 @@ func NewTxm( keyStore keystore.Eth, estimator gas.EvmFeeEstimator, headTracker latestAndFinalizedBlockHeadTracker, + txmv2wrapper TxManager, ) (txm TxManager, err error, ) { @@ -67,7 +71,7 @@ func NewTxm( if txConfig.ResendAfterThreshold() > 0 { evmResender = NewEvmResender(lggr, txStore, txmClient, evmTracker, keyStore, txmgr.DefaultResenderPollInterval, chainConfig, txConfig) } - txm = NewEvmTxm(chainID, txmCfg, txConfig, keyStore, lggr, checker, fwdMgr, txAttemptBuilder, txStore, evmBroadcaster, evmConfirmer, evmResender, evmTracker, evmFinalizer) + txm = NewEvmTxm(chainID, txmCfg, txConfig, keyStore, lggr, checker, fwdMgr, txAttemptBuilder, txStore, evmBroadcaster, evmConfirmer, evmResender, evmTracker, evmFinalizer, txmv2wrapper) return txm, nil } @@ -87,8 +91,59 @@ func NewEvmTxm( resender *Resender, tracker *Tracker, finalizer Finalizer, + txmv2wrapper TxManager, ) *Txm { - return txmgr.NewTxm(chainId, cfg, txCfg, keyStore, lggr, checkerFactory, fwdMgr, txAttemptBuilder, txStore, broadcaster, confirmer, resender, tracker, finalizer, client.NewTxError) + return txmgr.NewTxm(chainId, cfg, txCfg, keyStore, lggr, checkerFactory, fwdMgr, txAttemptBuilder, txStore, broadcaster, confirmer, resender, tracker, finalizer, client.NewTxError, txmv2wrapper) +} + +func NewTxmV2( + ds sqlutil.DataSource, + chainConfig ChainConfig, + fCfg FeeConfig, + txConfig config.Transactions, + txmV2Config config.TransactionManagerV2, + client client.Client, + lggr logger.Logger, + logPoller logpoller.LogPoller, + keyStore keystore.Eth, + estimator gas.EvmFeeEstimator, +) (TxManager, error) { + var fwdMgr *forwarders.FwdMgr + if txConfig.ForwardersEnabled() { + fwdMgr = forwarders.NewFwdMgr(ds, client, logPoller, lggr, chainConfig) + } else { + lggr.Info("ForwarderManager: Disabled") + } + + chainID := client.ConfiguredChainID() + + var stuckTxDetector txm.StuckTxDetector + if txConfig.AutoPurge().Enabled() { + stuckTxDetectorConfig := txm.StuckTxDetectorConfig{ + BlockTime: *txmV2Config.BlockTime(), + StuckTxBlockThreshold: *txConfig.AutoPurge().Threshold(), + DetectionURL: txConfig.AutoPurge().DetectionApiUrl().String(), + } + stuckTxDetector = txm.NewStuckTxDetector(lggr, chainConfig.ChainType(), stuckTxDetectorConfig) + } + + attemptBuilder := txm.NewAttemptBuilder(chainID, fCfg.PriceMaxKey, estimator, keyStore) + inMemoryStoreManager := storage.NewInMemoryStoreManager(lggr, chainID) + config := txm.Config{ + EIP1559: fCfg.EIP1559DynamicFees(), + BlockTime: *txmV2Config.BlockTime(), + //nolint:gosec // reuse existing config until migration + RetryBlockThreshold: uint16(fCfg.BumpThreshold()), + EmptyTxLimitDefault: fCfg.LimitDefault(), + } + var c txm.Client + if txmV2Config.DualBroadcast() != nil && *txmV2Config.DualBroadcast() { + c = clientwrappers.NewDualBroadcastClient(client, keyStore, txmV2Config.CustomURL()) + } else { + c = clientwrappers.NewChainClient(client) + } + t := txm.NewTxm(lggr, chainID, c, attemptBuilder, inMemoryStoreManager, stuckTxDetector, config, keyStore) + return txm.NewTxmOrchestrator(lggr, chainID, t, inMemoryStoreManager, fwdMgr, keyStore, attemptBuilder), nil } // NewEvmResender creates a new concrete EvmResender diff --git a/core/chains/evm/txmgr/client.go b/core/chains/evm/txmgr/client.go index 9ec175048d3..adb70b8c9ef 100644 --- a/core/chains/evm/txmgr/client.go +++ b/core/chains/evm/txmgr/client.go @@ -15,8 +15,8 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/utils" + "github.com/smartcontractkit/chainlink-framework/multinode" - commonclient "github.com/smartcontractkit/chainlink/v2/common/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" @@ -48,14 +48,14 @@ func (c *evmTxmClient) BatchSendTransactions( batchSize int, lggr logger.SugaredLogger, ) ( - codes []commonclient.SendTxReturnCode, + codes []multinode.SendTxReturnCode, txErrs []error, broadcastTime time.Time, successfulTxIDs []int64, err error, ) { // preallocate - codes = make([]commonclient.SendTxReturnCode, len(attempts)) + codes = make([]multinode.SendTxReturnCode, len(attempts)) txErrs = make([]error, len(attempts)) reqs, broadcastTime, successfulTxIDs, batchErr := batchSendTransactions(ctx, attempts, batchSize, lggr, c.client) @@ -95,11 +95,11 @@ func (c *evmTxmClient) BatchSendTransactions( return } -func (c *evmTxmClient) SendTransactionReturnCode(ctx context.Context, etx Tx, attempt TxAttempt, lggr logger.SugaredLogger) (commonclient.SendTxReturnCode, error) { +func (c *evmTxmClient) SendTransactionReturnCode(ctx context.Context, etx Tx, attempt TxAttempt, lggr logger.SugaredLogger) (multinode.SendTxReturnCode, error) { signedTx, err := GetGethSignedTx(attempt.SignedRawTx) if err != nil { lggr.Criticalw("Fatal error signing transaction", "err", err, "etx", etx) - return commonclient.Fatal, err + return multinode.Fatal, err } return c.client.SendTransactionReturnCode(ctx, signedTx, etx.FromAddress) } diff --git a/core/chains/evm/txmgr/confirmer_test.go b/core/chains/evm/txmgr/confirmer_test.go index ea251971860..a747ba65135 100644 --- a/core/chains/evm/txmgr/confirmer_test.go +++ b/core/chains/evm/txmgr/confirmer_test.go @@ -21,9 +21,9 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink-framework/multinode" - commonclient "github.com/smartcontractkit/chainlink/v2/common/client" - commonfee "github.com/smartcontractkit/chainlink/v2/common/fee" + "github.com/smartcontractkit/chainlink/v2/common/fees" txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" @@ -728,7 +728,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing estimator := gasmocks.NewEvmEstimator(t) newEst := func(logger.Logger) gas.EvmEstimator { return estimator } - estimator.On("BumpLegacyGas", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, uint64(0), pkgerrors.Wrapf(commonfee.ErrConnectivity, "transaction...")) + estimator.On("BumpLegacyGas", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, uint64(0), pkgerrors.Wrapf(fees.ErrConnectivity, "transaction...")) ge := ccfg.EVM().GasEstimator() feeEstimator := gas.NewEvmFeeEstimator(lggr, newEst, ge.EIP1559DynamicFees(), ge, ethClient) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, kst, feeEstimator) @@ -751,7 +751,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing require.NoError(t, db.Get(&dbAttempt, `UPDATE evm.tx_attempts SET broadcast_before_block_num=$1 WHERE id=$2 RETURNING *`, oldEnough, attempt1.ID)) // Send transaction and assume success. - ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, fromAddress).Return(commonclient.Successful, nil).Once() + ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, fromAddress).Return(multinode.Successful, nil).Once() err := ec.RebroadcastWhereNecessary(tests.Context(t), currentHead) require.NoError(t, err) @@ -776,7 +776,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing kst := ksmocks.NewEth(t) estimator := gasmocks.NewEvmEstimator(t) - estimator.On("BumpDynamicFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.DynamicFee{}, pkgerrors.Wrapf(commonfee.ErrConnectivity, "transaction...")) + estimator.On("BumpDynamicFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.DynamicFee{}, pkgerrors.Wrapf(fees.ErrConnectivity, "transaction...")) newEst := func(logger.Logger) gas.EvmEstimator { return estimator } // Create confirmer with necessary state ge := ccfg.EVM().GasEstimator() @@ -800,7 +800,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing require.NoError(t, db.Get(&dbAttempt, `UPDATE evm.tx_attempts SET broadcast_before_block_num=$1 WHERE id=$2 RETURNING *`, oldEnough, attempt1.ID)) // Send transaction and assume success. - ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, fromAddress).Return(commonclient.Successful, nil).Once() + ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, fromAddress).Return(multinode.Successful, nil).Once() err := ec.RebroadcastWhereNecessary(tests.Context(t), currentHead) require.NoError(t, err) @@ -862,7 +862,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_MaxFeeScenario(t *testing.T) { // Once for the bumped attempt which exceeds limit ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return tx.GasPrice().Int64() == int64(20000000000) && tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 - }), fromAddress).Return(commonclient.ExceedsMaxFee, errors.New("tx fee (1.10 ether) exceeds the configured cap (1.00 ether)")).Once() + }), fromAddress).Return(multinode.ExceedsMaxFee, errors.New("tx fee (1.10 ether) exceeds the configured cap (1.00 ether)")).Once() // Do the thing require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) @@ -940,7 +940,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 - }), fromAddress).Return(commonclient.Fatal, errors.New("exceeds block gas limit")).Once() + }), fromAddress).Return(multinode.Fatal, errors.New("exceeds block gas limit")).Once() require.NoError(t, ec.RebroadcastWhereNecessary(ctx, currentHead)) var err error @@ -960,7 +960,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 - }), fromAddress).Return(commonclient.Successful, nil).Once() + }), fromAddress).Return(multinode.Successful, nil).Once() require.NoError(t, ec.RebroadcastWhereNecessary(ctx, currentHead)) var err error @@ -1003,7 +1003,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 - }), fromAddress).Return(commonclient.Successful, fmt.Errorf("known transaction: %s", etx.TxAttempts[0].Hash.Hex())).Once() + }), fromAddress).Return(multinode.Successful, fmt.Errorf("known transaction: %s", etx.TxAttempts[0].Hash.Hex())).Once() require.NoError(t, ec.RebroadcastWhereNecessary(ctx, currentHead)) var err error @@ -1030,7 +1030,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 - }), fromAddress).Return(commonclient.TransactionAlreadyKnown, errors.New("nonce too low")).Once() + }), fromAddress).Return(multinode.TransactionAlreadyKnown, errors.New("nonce too low")).Once() require.NoError(t, ec.RebroadcastWhereNecessary(ctx, currentHead)) var err error @@ -1061,7 +1061,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 - }), fromAddress).Return(commonclient.Unknown, errors.New("some network error")).Once() + }), fromAddress).Return(multinode.Unknown, errors.New("some network error")).Once() err := ec.RebroadcastWhereNecessary(ctx, currentHead) require.Error(t, err) @@ -1085,7 +1085,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { // Try again and move the attempt into "broadcast" ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 - }), fromAddress).Return(commonclient.Successful, nil).Once() + }), fromAddress).Return(multinode.Successful, nil).Once() require.NoError(t, ec.RebroadcastWhereNecessary(ctx, currentHead)) @@ -1112,10 +1112,10 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 - }), fromAddress).Return(commonclient.Underpriced, errors.New("replacement transaction underpriced")).Once() + }), fromAddress).Return(multinode.Underpriced, errors.New("replacement transaction underpriced")).Once() ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 - }), fromAddress).Return(commonclient.Successful, nil).Once() + }), fromAddress).Return(multinode.Successful, nil).Once() // Do the thing require.NoError(t, ec.RebroadcastWhereNecessary(ctx, currentHead)) @@ -1148,7 +1148,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 - }), fromAddress).Return(commonclient.Underpriced, errors.New("underpriced")).Once() // we already submitted at this price, now it's time to bump and submit again but since we simply resubmitted rather than increasing gas price, geth already knows about this tx + }), fromAddress).Return(multinode.Underpriced, errors.New("underpriced")).Once() // we already submitted at this price, now it's time to bump and submit again but since we simply resubmitted rather than increasing gas price, geth already knows about this tx // Do the thing require.Error(t, ec.RebroadcastWhereNecessary(ctx, currentHead)) @@ -1179,7 +1179,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 - }), fromAddress).Return(commonclient.Underpriced, errors.New("underpriced")).Once() // we already submitted at this price, now it's time to bump and submit again but since we simply resubmitted rather than increasing gas price, geth already knows about this tx + }), fromAddress).Return(multinode.Underpriced, errors.New("underpriced")).Once() // we already submitted at this price, now it's time to bump and submit again but since we simply resubmitted rather than increasing gas price, geth already knows about this tx // Do the thing require.Error(t, ec.RebroadcastWhereNecessary(ctx, currentHead)) @@ -1210,7 +1210,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 - }), fromAddress).Return(commonclient.Successful, nil).Once() + }), fromAddress).Return(multinode.Successful, nil).Once() require.NoError(t, ec.RebroadcastWhereNecessary(ctx, currentHead)) etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -1242,7 +1242,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 - }), fromAddress).Return(commonclient.Underpriced, errors.New("underpriced")).Once() + }), fromAddress).Return(multinode.Underpriced, errors.New("underpriced")).Once() require.Error(t, ec.RebroadcastWhereNecessary(ctx, currentHead)) etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) @@ -1273,10 +1273,10 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 - }), fromAddress).Return(commonclient.Underpriced, errors.New("replacement transaction underpriced")).Once() + }), fromAddress).Return(multinode.Underpriced, errors.New("replacement transaction underpriced")).Once() ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 - }), fromAddress).Return(commonclient.Successful, nil).Once() + }), fromAddress).Return(multinode.Successful, nil).Once() // Do it require.NoError(t, ec.RebroadcastWhereNecessary(ctx, currentHead)) @@ -1330,10 +1330,10 @@ func TestEthConfirmer_RebroadcastWhereNecessary_TerminallyUnderpriced_ThenGoesTh // Fail the first time with terminally underpriced. ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, fromAddress).Return( - commonclient.Underpriced, errors.New("Transaction gas price is too low. It does not satisfy your node's minimal gas price")).Once() + multinode.Underpriced, errors.New("Transaction gas price is too low. It does not satisfy your node's minimal gas price")).Once() // Succeed the second time after bumping gas. ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, fromAddress).Return( - commonclient.Successful, nil).Once() + multinode.Successful, nil).Once() kst.On("SignTx", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return( signedTx, nil, ).Once() @@ -1353,10 +1353,10 @@ func TestEthConfirmer_RebroadcastWhereNecessary_TerminallyUnderpriced_ThenGoesTh // Fail a few times with terminally underpriced ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, fromAddress).Return( - commonclient.Underpriced, errors.New("Transaction gas price is too low. It does not satisfy your node's minimal gas price")).Times(3) + multinode.Underpriced, errors.New("Transaction gas price is too low. It does not satisfy your node's minimal gas price")).Times(3) // Succeed the second time after bumping gas. ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, fromAddress).Return( - commonclient.Successful, nil).Once() + multinode.Successful, nil).Once() signedLegacyTx := new(types.Transaction) kst.On("SignTx", mock.Anything, mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return tx.Type() == 0x0 && tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 @@ -1385,10 +1385,10 @@ func TestEthConfirmer_RebroadcastWhereNecessary_TerminallyUnderpriced_ThenGoesTh // Fail a few times with terminally underpriced ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, fromAddress).Return( - commonclient.Underpriced, errors.New("transaction underpriced")).Times(3) + multinode.Underpriced, errors.New("transaction underpriced")).Times(3) // Succeed the second time after bumping gas. ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, fromAddress).Return( - commonclient.Successful, nil).Once() + multinode.Successful, nil).Once() signedDxFeeTx := new(types.Transaction) kst.On("SignTx", mock.Anything, mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return tx.Type() == 0x2 && tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 @@ -1445,7 +1445,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return expectedBumpedGasPrice.Cmp(tx.GasPrice()) == 0 - }), fromAddress).Return(commonclient.InsufficientFunds, insufficientEthError).Once() + }), fromAddress).Return(multinode.InsufficientFunds, insufficientEthError).Once() // Do the thing require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) @@ -1471,7 +1471,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return expectedBumpedGasPrice.Cmp(tx.GasPrice()) == 0 - }), fromAddress).Return(commonclient.InsufficientFunds, insufficientEthError).Once() + }), fromAddress).Return(multinode.InsufficientFunds, insufficientEthError).Once() // Do the thing require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) @@ -1496,7 +1496,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return expectedBumpedGasPrice.Cmp(tx.GasPrice()) == 0 - }), fromAddress).Return(commonclient.Successful, nil).Once() + }), fromAddress).Return(multinode.Successful, nil).Once() // Do the thing require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) @@ -1528,7 +1528,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) { mustInsertUnconfirmedEthTxWithInsufficientEthAttempt(t, txStore, nonce, fromAddress) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return tx.Nonce() == uint64(n) - }), fromAddress).Return(commonclient.Successful, nil).Once() + }), fromAddress).Return(multinode.Successful, nil).Once() nonce++ } @@ -1576,11 +1576,11 @@ func TestEthConfirmer_RebroadcastWhereNecessary_TerminallyStuckError(t *testing. // Return terminally stuck error on first rebroadcast ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 - }), fromAddress).Return(commonclient.TerminallyStuck, errors.New(terminallyStuckError)).Once() + }), fromAddress).Return(multinode.TerminallyStuck, errors.New(terminallyStuckError)).Once() // Return successful for purge attempt ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 - }), fromAddress).Return(commonclient.Successful, nil).Once() + }), fromAddress).Return(multinode.Successful, nil).Once() // Start processing transactions for rebroadcast require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) @@ -1622,7 +1622,7 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) { tx.Gas() == overrideGasLimit && reflect.DeepEqual(tx.Data(), etx1.EncodedPayload) && tx.To().String() == etx1.ToAddress.String() - }), mock.Anything).Return(commonclient.Successful, nil).Once() + }), mock.Anything).Return(multinode.Successful, nil).Once() require.NoError(t, ec.ForceRebroadcast(tests.Context(t), []evmtypes.Nonce{1}, gasPriceWei, fromAddress, overrideGasLimit)) }) @@ -1637,7 +1637,7 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) { tx.Gas() == etx1.FeeLimit && reflect.DeepEqual(tx.Data(), etx1.EncodedPayload) && tx.To().String() == etx1.ToAddress.String() - }), mock.Anything).Return(commonclient.Successful, nil).Once() + }), mock.Anything).Return(multinode.Successful, nil).Once() require.NoError(t, ec.ForceRebroadcast(tests.Context(t), []evmtypes.Nonce{(1)}, gasPriceWei, fromAddress, 0)) }) @@ -1648,10 +1648,10 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return tx.Nonce() == uint64(*etx1.Sequence) && tx.GasPrice().Int64() == gasPriceWei.GasPrice.Int64() && tx.Gas() == overrideGasLimit - }), mock.Anything).Return(commonclient.Successful, nil).Once() + }), mock.Anything).Return(multinode.Successful, nil).Once() ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return tx.Nonce() == uint64(*etx2.Sequence) && tx.GasPrice().Int64() == gasPriceWei.GasPrice.Int64() && tx.Gas() == overrideGasLimit - }), mock.Anything).Return(commonclient.Successful, nil).Once() + }), mock.Anything).Return(multinode.Successful, nil).Once() require.NoError(t, ec.ForceRebroadcast(tests.Context(t), []evmtypes.Nonce{(1), (2)}, gasPriceWei, fromAddress, overrideGasLimit)) }) @@ -1662,10 +1662,10 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return tx.Nonce() == uint64(1) - }), mock.Anything).Return(commonclient.Successful, nil).Once() + }), mock.Anything).Return(multinode.Successful, nil).Once() ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return tx.Nonce() == uint64(2) - }), mock.Anything).Return(commonclient.Successful, nil).Once() + }), mock.Anything).Return(multinode.Successful, nil).Once() for i := 3; i <= 5; i++ { nonce := i ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { @@ -1675,7 +1675,7 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) { *tx.To() == fromAddress && tx.Value().Cmp(big.NewInt(0)) == 0 && len(tx.Data()) == 0 - }), mock.Anything).Return(commonclient.Successful, nil).Once() + }), mock.Anything).Return(multinode.Successful, nil).Once() } nonces := []evmtypes.Nonce{(1), (2), (3), (4), (5)} @@ -1688,7 +1688,7 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return tx.Nonce() == uint64(0) && tx.GasPrice().Int64() == gasPriceWei.GasPrice.Int64() && tx.Gas() == config.EVM().GasEstimator().LimitDefault() - }), mock.Anything).Return(commonclient.Successful, nil).Once() + }), mock.Anything).Return(multinode.Successful, nil).Once() require.NoError(t, ec.ForceRebroadcast(tests.Context(t), []evmtypes.Nonce{(0)}, gasPriceWei, fromAddress, 0)) }) @@ -1702,7 +1702,7 @@ func TestEthConfirmer_ProcessStuckTransactions(t *testing.T) { ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) ethClient := testutils.NewEthClientMockWithDefaultChain(t) - ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, fromAddress).Return(commonclient.Successful, nil).Once() + ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, fromAddress).Return(multinode.Successful, nil).Once() lggr := logger.Test(t) feeEstimator := gasmocks.NewEvmFeeEstimator(t) diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go index 95756790cf3..66e0cc84971 100644 --- a/core/chains/evm/txmgr/evm_tx_store.go +++ b/core/chains/evm/txmgr/evm_tx_store.go @@ -1786,8 +1786,17 @@ func (o *evmTxStore) Abandon(ctx context.Context, chainID *big.Int, addr common. var cancel context.CancelFunc ctx, cancel = o.stopCh.Ctx(ctx) defer cancel() - _, err := o.q.ExecContext(ctx, `UPDATE evm.txes SET state='fatal_error', nonce = NULL, error = 'abandoned' WHERE state IN ('unconfirmed', 'in_progress', 'unstarted') AND evm_chain_id = $1 AND from_address = $2`, chainID.String(), addr) - return err + return o.Transact(ctx, false, func(orm *evmTxStore) error { + var abandonedIDs []string + err := orm.q.SelectContext(ctx, &abandonedIDs, `UPDATE evm.txes SET state='fatal_error', nonce = NULL, error = 'abandoned' WHERE state IN ('unconfirmed', 'in_progress', 'unstarted') AND evm_chain_id = $1 AND from_address = $2 RETURNING id`, chainID.String(), addr) + if err != nil { + return fmt.Errorf("failed to mark transactions as abandoned: %w", err) + } + if _, err := orm.q.ExecContext(ctx, `DELETE FROM evm.tx_attempts WHERE eth_tx_id = ANY($1)`, pq.Array(abandonedIDs)); err != nil { + return fmt.Errorf("failed to delete attempts related to abandoned transactions: %w", err) + } + return nil + }) } // Find transactions by a field in the TxMeta blob and transaction states @@ -1916,7 +1925,7 @@ func (o *evmTxStore) FindAttemptsRequiringReceiptFetch(ctx context.Context, chai query := ` SELECT evm.tx_attempts.* FROM evm.tx_attempts JOIN evm.txes ON evm.txes.ID = evm.tx_attempts.eth_tx_id - WHERE evm.tx_attempts.state = 'broadcast' AND evm.txes.state IN ('confirmed', 'confirmed_missing_receipt', 'fatal_error') AND evm.txes.evm_chain_id = $1 AND evm.txes.ID NOT IN ( + WHERE evm.tx_attempts.state = 'broadcast' AND evm.txes.nonce IS NOT NULL AND evm.txes.state IN ('confirmed', 'confirmed_missing_receipt', 'fatal_error') AND evm.txes.evm_chain_id = $1 AND evm.txes.ID NOT IN ( SELECT DISTINCT evm.txes.ID FROM evm.txes JOIN evm.tx_attempts ON evm.tx_attempts.eth_tx_id = evm.txes.ID JOIN evm.receipts ON evm.receipts.tx_hash = evm.tx_attempts.hash diff --git a/core/chains/evm/txmgr/evm_tx_store_test.go b/core/chains/evm/txmgr/evm_tx_store_test.go index a05cf3f9010..4e85556b1e2 100644 --- a/core/chains/evm/txmgr/evm_tx_store_test.go +++ b/core/chains/evm/txmgr/evm_tx_store_test.go @@ -1286,7 +1286,7 @@ func TestORM_UpdateTxUnstartedToInProgress(t *testing.T) { evmTxmCfg := txmgr.NewEvmTxmConfig(ccfg.EVM()) ec := evmtest.NewEthClientMockWithDefaultChain(t) txMgr := txmgr.NewEvmTxm(ec.ConfiguredChainID(), evmTxmCfg, ccfg.EVM().Transactions(), nil, logger.Test(t), nil, nil, - nil, txStore, nil, nil, nil, nil, nil) + nil, txStore, nil, nil, nil, nil, nil, nil) err := txMgr.XXXTestAbandon(fromAddress) // mark transaction as abandoned require.NoError(t, err) @@ -1796,11 +1796,16 @@ func TestORM_FindAttemptsRequiringReceiptFetch(t *testing.T) { // Terminally stuck transaction with receipt should NOT be picked up for receipt fetch stuckTx := mustInsertTerminallyStuckTxWithAttempt(t, txStore, fromAddress, 1, blockNum) mustInsertEthReceipt(t, txStore, blockNum, utils.NewHash(), stuckTx.TxAttempts[0].Hash) + // Fatal transactions with nil nonce and stored attempts should NOT be picked up for receipt fetch + fatalTxWithAttempt := mustInsertFatalErrorEthTx(t, txStore, fromAddress) + attempt := newBroadcastLegacyEthTxAttempt(t, fatalTxWithAttempt.ID) + err := txStore.InsertTxAttempt(ctx, &attempt) + require.NoError(t, err) // Confirmed transaction without receipt should be picked up for receipt fetch confirmedTx := mustInsertConfirmedEthTx(t, txStore, 0, fromAddress) - attempt := newBroadcastLegacyEthTxAttempt(t, confirmedTx.ID) - err := txStore.InsertTxAttempt(ctx, &attempt) + attempt = newBroadcastLegacyEthTxAttempt(t, confirmedTx.ID) + err = txStore.InsertTxAttempt(ctx, &attempt) require.NoError(t, err) attempts, err := txStore.FindAttemptsRequiringReceiptFetch(ctx, testutils.FixtureChainID) @@ -1823,6 +1828,12 @@ func TestORM_FindAttemptsRequiringReceiptFetch(t *testing.T) { // Terminally stuck transaction with receipt should NOT be picked up for receipt fetch stuckTxWithReceipt := mustInsertTerminallyStuckTxWithAttempt(t, txStore, fromAddress, 1, blockNum) mustInsertEthReceipt(t, txStore, blockNum, utils.NewHash(), stuckTxWithReceipt.TxAttempts[0].Hash) + // Fatal transactions with nil nonce and stored attempts should NOT be picked up for receipt fetch + fatalTxWithAttempt := mustInsertFatalErrorEthTx(t, txStore, fromAddress) + attempt := newBroadcastLegacyEthTxAttempt(t, fatalTxWithAttempt.ID) + err := txStore.InsertTxAttempt(ctx, &attempt) + require.NoError(t, err) + // Terminally stuck transaction without receipt should be picked up for receipt fetch stuckTxWoutReceipt := mustInsertTerminallyStuckTxWithAttempt(t, txStore, fromAddress, 0, blockNum) @@ -2008,6 +2019,41 @@ func TestORM_DeleteReceiptsByTxHash(t *testing.T) { require.Len(t, etx2.TxAttempts[0].Receipts, 1) } +func TestORM_Abandon(t *testing.T) { + t.Parallel() + + db := pgtest.NewSqlxDB(t) + txStore := cltest.NewTestTxStore(t, db) + ctx := tests.Context(t) + ethKeyStore := cltest.NewKeyStore(t, db).Eth() + _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) + etx1 := mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, testutils.FixtureChainID) + etx2 := mustInsertInProgressEthTxWithAttempt(t, txStore, 1, fromAddress) + etx3 := mustInsertUnconfirmedEthTxWithAttemptState(t, txStore, 0, fromAddress, txmgrtypes.TxAttemptBroadcast) + + err := txStore.Abandon(ctx, testutils.FixtureChainID, fromAddress) + require.NoError(t, err) + + // transactions marked as fatal error with abandon reason, nil sequence, and no attempts + etx1, err = txStore.FindTxWithAttempts(ctx, etx1.ID) + require.NoError(t, err) + require.Equal(t, txmgrcommon.TxFatalError, etx1.State) + require.Nil(t, etx1.Sequence) + require.Empty(t, etx1.TxAttempts) + + etx2, err = txStore.FindTxWithAttempts(ctx, etx2.ID) + require.NoError(t, err) + require.Equal(t, txmgrcommon.TxFatalError, etx2.State) + require.Nil(t, etx2.Sequence) + require.Empty(t, etx2.TxAttempts) + + etx3, err = txStore.FindTxWithAttempts(ctx, etx3.ID) + require.NoError(t, err) + require.Equal(t, txmgrcommon.TxFatalError, etx3.State) + require.Nil(t, etx3.Sequence) + require.Empty(t, etx3.TxAttempts) +} + func mustInsertTerminallyStuckTxWithAttempt(t *testing.T, txStore txmgr.TestEvmTxStore, fromAddress common.Address, nonceInt int64, broadcastBeforeBlockNum int64) txmgr.Tx { ctx := tests.Context(t) broadcast := time.Now() diff --git a/core/chains/evm/txmgr/mocks/config.go b/core/chains/evm/txmgr/mocks/config.go index 011ba19a958..91fed44dc7c 100644 --- a/core/chains/evm/txmgr/mocks/config.go +++ b/core/chains/evm/txmgr/mocks/config.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -20,7 +20,7 @@ func (_m *Config) EXPECT() *Config_Expecter { return &Config_Expecter{mock: &_m.Mock} } -// ChainType provides a mock function with given fields: +// ChainType provides a mock function with no fields func (_m *Config) ChainType() chaintype.ChainType { ret := _m.Called() @@ -65,7 +65,7 @@ func (_c *Config_ChainType_Call) RunAndReturn(run func() chaintype.ChainType) *C return _c } -// FinalityDepth provides a mock function with given fields: +// FinalityDepth provides a mock function with no fields func (_m *Config) FinalityDepth() uint32 { ret := _m.Called() @@ -110,7 +110,7 @@ func (_c *Config_FinalityDepth_Call) RunAndReturn(run func() uint32) *Config_Fin return _c } -// FinalityTagEnabled provides a mock function with given fields: +// FinalityTagEnabled provides a mock function with no fields func (_m *Config) FinalityTagEnabled() bool { ret := _m.Called() @@ -155,7 +155,7 @@ func (_c *Config_FinalityTagEnabled_Call) RunAndReturn(run func() bool) *Config_ return _c } -// NonceAutoSync provides a mock function with given fields: +// NonceAutoSync provides a mock function with no fields func (_m *Config) NonceAutoSync() bool { ret := _m.Called() @@ -200,7 +200,7 @@ func (_c *Config_NonceAutoSync_Call) RunAndReturn(run func() bool) *Config_Nonce return _c } -// RPCDefaultBatchSize provides a mock function with given fields: +// RPCDefaultBatchSize provides a mock function with no fields func (_m *Config) RPCDefaultBatchSize() uint32 { ret := _m.Called() diff --git a/core/chains/evm/txmgr/mocks/evm_tx_store.go b/core/chains/evm/txmgr/mocks/evm_tx_store.go index ca98ad6ceb8..a00e280d752 100644 --- a/core/chains/evm/txmgr/mocks/evm_tx_store.go +++ b/core/chains/evm/txmgr/mocks/evm_tx_store.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -18,8 +18,6 @@ import ( time "time" - txmgr "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" - types "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" uuid "github.com/google/uuid" @@ -135,7 +133,7 @@ func (_c *EvmTxStore_CheckTxQueueCapacity_Call) RunAndReturn(run func(context.Co return _c } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *EvmTxStore) Close() { _m.Called() } @@ -163,7 +161,7 @@ func (_c *EvmTxStore_Close_Call) Return() *EvmTxStore_Close_Call { } func (_c *EvmTxStore_Close_Call) RunAndReturn(run func()) *EvmTxStore_Close_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -494,23 +492,23 @@ func (_c *EvmTxStore_DeleteReceiptByTxHash_Call) RunAndReturn(run func(context.C } // FindAttemptsRequiringReceiptFetch provides a mock function with given fields: ctx, chainID -func (_m *EvmTxStore) FindAttemptsRequiringReceiptFetch(ctx context.Context, chainID *big.Int) ([]txmgr.TxAttempt, error) { +func (_m *EvmTxStore) FindAttemptsRequiringReceiptFetch(ctx context.Context, chainID *big.Int) ([]types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error) { ret := _m.Called(ctx, chainID) if len(ret) == 0 { panic("no return value specified for FindAttemptsRequiringReceiptFetch") } - var r0 []txmgr.TxAttempt + var r0 []types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee] var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *big.Int) ([]txmgr.TxAttempt, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *big.Int) ([]types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error)); ok { return rf(ctx, chainID) } - if rf, ok := ret.Get(0).(func(context.Context, *big.Int) []txmgr.TxAttempt); ok { + if rf, ok := ret.Get(0).(func(context.Context, *big.Int) []types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]); ok { r0 = rf(ctx, chainID) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]txmgr.TxAttempt) + r0 = ret.Get(0).([]types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) } } @@ -542,12 +540,12 @@ func (_c *EvmTxStore_FindAttemptsRequiringReceiptFetch_Call) Run(run func(ctx co return _c } -func (_c *EvmTxStore_FindAttemptsRequiringReceiptFetch_Call) Return(hashes []txmgr.TxAttempt, err error) *EvmTxStore_FindAttemptsRequiringReceiptFetch_Call { +func (_c *EvmTxStore_FindAttemptsRequiringReceiptFetch_Call) Return(hashes []types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], err error) *EvmTxStore_FindAttemptsRequiringReceiptFetch_Call { _c.Call.Return(hashes, err) return _c } -func (_c *EvmTxStore_FindAttemptsRequiringReceiptFetch_Call) RunAndReturn(run func(context.Context, *big.Int) ([]txmgr.TxAttempt, error)) *EvmTxStore_FindAttemptsRequiringReceiptFetch_Call { +func (_c *EvmTxStore_FindAttemptsRequiringReceiptFetch_Call) RunAndReturn(run func(context.Context, *big.Int) ([]types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error)) *EvmTxStore_FindAttemptsRequiringReceiptFetch_Call { _c.Call.Return(run) return _c } @@ -915,23 +913,23 @@ func (_c *EvmTxStore_FindReorgOrIncludedTxs_Call) RunAndReturn(run func(context. } // FindTxAttempt provides a mock function with given fields: ctx, hash -func (_m *EvmTxStore) FindTxAttempt(ctx context.Context, hash common.Hash) (*txmgr.TxAttempt, error) { +func (_m *EvmTxStore) FindTxAttempt(ctx context.Context, hash common.Hash) (*types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error) { ret := _m.Called(ctx, hash) if len(ret) == 0 { panic("no return value specified for FindTxAttempt") } - var r0 *txmgr.TxAttempt + var r0 *types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee] var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Hash) (*txmgr.TxAttempt, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Hash) (*types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error)); ok { return rf(ctx, hash) } - if rf, ok := ret.Get(0).(func(context.Context, common.Hash) *txmgr.TxAttempt); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Hash) *types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]); ok { r0 = rf(ctx, hash) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*txmgr.TxAttempt) + r0 = ret.Get(0).(*types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) } } @@ -963,34 +961,34 @@ func (_c *EvmTxStore_FindTxAttempt_Call) Run(run func(ctx context.Context, hash return _c } -func (_c *EvmTxStore_FindTxAttempt_Call) Return(_a0 *txmgr.TxAttempt, _a1 error) *EvmTxStore_FindTxAttempt_Call { +func (_c *EvmTxStore_FindTxAttempt_Call) Return(_a0 *types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], _a1 error) *EvmTxStore_FindTxAttempt_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *EvmTxStore_FindTxAttempt_Call) RunAndReturn(run func(context.Context, common.Hash) (*txmgr.TxAttempt, error)) *EvmTxStore_FindTxAttempt_Call { +func (_c *EvmTxStore_FindTxAttempt_Call) RunAndReturn(run func(context.Context, common.Hash) (*types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error)) *EvmTxStore_FindTxAttempt_Call { _c.Call.Return(run) return _c } // FindTxAttemptConfirmedByTxIDs provides a mock function with given fields: ctx, ids -func (_m *EvmTxStore) FindTxAttemptConfirmedByTxIDs(ctx context.Context, ids []int64) ([]txmgr.TxAttempt, error) { +func (_m *EvmTxStore) FindTxAttemptConfirmedByTxIDs(ctx context.Context, ids []int64) ([]types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error) { ret := _m.Called(ctx, ids) if len(ret) == 0 { panic("no return value specified for FindTxAttemptConfirmedByTxIDs") } - var r0 []txmgr.TxAttempt + var r0 []types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee] var r1 error - if rf, ok := ret.Get(0).(func(context.Context, []int64) ([]txmgr.TxAttempt, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, []int64) ([]types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error)); ok { return rf(ctx, ids) } - if rf, ok := ret.Get(0).(func(context.Context, []int64) []txmgr.TxAttempt); ok { + if rf, ok := ret.Get(0).(func(context.Context, []int64) []types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]); ok { r0 = rf(ctx, ids) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]txmgr.TxAttempt) + r0 = ret.Get(0).([]types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) } } @@ -1022,12 +1020,12 @@ func (_c *EvmTxStore_FindTxAttemptConfirmedByTxIDs_Call) Run(run func(ctx contex return _c } -func (_c *EvmTxStore_FindTxAttemptConfirmedByTxIDs_Call) Return(_a0 []txmgr.TxAttempt, _a1 error) *EvmTxStore_FindTxAttemptConfirmedByTxIDs_Call { +func (_c *EvmTxStore_FindTxAttemptConfirmedByTxIDs_Call) Return(_a0 []types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], _a1 error) *EvmTxStore_FindTxAttemptConfirmedByTxIDs_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *EvmTxStore_FindTxAttemptConfirmedByTxIDs_Call) RunAndReturn(run func(context.Context, []int64) ([]txmgr.TxAttempt, error)) *EvmTxStore_FindTxAttemptConfirmedByTxIDs_Call { +func (_c *EvmTxStore_FindTxAttemptConfirmedByTxIDs_Call) RunAndReturn(run func(context.Context, []int64) ([]types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error)) *EvmTxStore_FindTxAttemptConfirmedByTxIDs_Call { _c.Call.Return(run) return _c } @@ -1154,23 +1152,23 @@ func (_c *EvmTxStore_FindTxAttemptsRequiringResend_Call) RunAndReturn(run func(c } // FindTxByHash provides a mock function with given fields: ctx, hash -func (_m *EvmTxStore) FindTxByHash(ctx context.Context, hash common.Hash) (*txmgr.Tx, error) { +func (_m *EvmTxStore) FindTxByHash(ctx context.Context, hash common.Hash) (*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error) { ret := _m.Called(ctx, hash) if len(ret) == 0 { panic("no return value specified for FindTxByHash") } - var r0 *txmgr.Tx + var r0 *types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee] var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Hash) (*txmgr.Tx, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Hash) (*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error)); ok { return rf(ctx, hash) } - if rf, ok := ret.Get(0).(func(context.Context, common.Hash) *txmgr.Tx); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Hash) *types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]); ok { r0 = rf(ctx, hash) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*txmgr.Tx) + r0 = ret.Get(0).(*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) } } @@ -1202,33 +1200,33 @@ func (_c *EvmTxStore_FindTxByHash_Call) Run(run func(ctx context.Context, hash c return _c } -func (_c *EvmTxStore_FindTxByHash_Call) Return(_a0 *txmgr.Tx, _a1 error) *EvmTxStore_FindTxByHash_Call { +func (_c *EvmTxStore_FindTxByHash_Call) Return(_a0 *types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], _a1 error) *EvmTxStore_FindTxByHash_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *EvmTxStore_FindTxByHash_Call) RunAndReturn(run func(context.Context, common.Hash) (*txmgr.Tx, error)) *EvmTxStore_FindTxByHash_Call { +func (_c *EvmTxStore_FindTxByHash_Call) RunAndReturn(run func(context.Context, common.Hash) (*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error)) *EvmTxStore_FindTxByHash_Call { _c.Call.Return(run) return _c } // FindTxWithAttempts provides a mock function with given fields: ctx, etxID -func (_m *EvmTxStore) FindTxWithAttempts(ctx context.Context, etxID int64) (txmgr.Tx, error) { +func (_m *EvmTxStore) FindTxWithAttempts(ctx context.Context, etxID int64) (types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error) { ret := _m.Called(ctx, etxID) if len(ret) == 0 { panic("no return value specified for FindTxWithAttempts") } - var r0 txmgr.Tx + var r0 types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee] var r1 error - if rf, ok := ret.Get(0).(func(context.Context, int64) (txmgr.Tx, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, int64) (types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error)); ok { return rf(ctx, etxID) } - if rf, ok := ret.Get(0).(func(context.Context, int64) txmgr.Tx); ok { + if rf, ok := ret.Get(0).(func(context.Context, int64) types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]); ok { r0 = rf(ctx, etxID) } else { - r0 = ret.Get(0).(txmgr.Tx) + r0 = ret.Get(0).(types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) } if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { @@ -1259,12 +1257,12 @@ func (_c *EvmTxStore_FindTxWithAttempts_Call) Run(run func(ctx context.Context, return _c } -func (_c *EvmTxStore_FindTxWithAttempts_Call) Return(etx txmgr.Tx, err error) *EvmTxStore_FindTxWithAttempts_Call { +func (_c *EvmTxStore_FindTxWithAttempts_Call) Return(etx types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], err error) *EvmTxStore_FindTxWithAttempts_Call { _c.Call.Return(etx, err) return _c } -func (_c *EvmTxStore_FindTxWithAttempts_Call) RunAndReturn(run func(context.Context, int64) (txmgr.Tx, error)) *EvmTxStore_FindTxWithAttempts_Call { +func (_c *EvmTxStore_FindTxWithAttempts_Call) RunAndReturn(run func(context.Context, int64) (types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error)) *EvmTxStore_FindTxWithAttempts_Call { _c.Call.Return(run) return _c } @@ -1390,23 +1388,23 @@ func (_c *EvmTxStore_FindTxWithSequence_Call) RunAndReturn(run func(context.Cont } // FindTxesByIDs provides a mock function with given fields: ctx, etxIDs, chainID -func (_m *EvmTxStore) FindTxesByIDs(ctx context.Context, etxIDs []int64, chainID *big.Int) ([]*txmgr.Tx, error) { +func (_m *EvmTxStore) FindTxesByIDs(ctx context.Context, etxIDs []int64, chainID *big.Int) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error) { ret := _m.Called(ctx, etxIDs, chainID) if len(ret) == 0 { panic("no return value specified for FindTxesByIDs") } - var r0 []*txmgr.Tx + var r0 []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee] var r1 error - if rf, ok := ret.Get(0).(func(context.Context, []int64, *big.Int) ([]*txmgr.Tx, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, []int64, *big.Int) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error)); ok { return rf(ctx, etxIDs, chainID) } - if rf, ok := ret.Get(0).(func(context.Context, []int64, *big.Int) []*txmgr.Tx); ok { + if rf, ok := ret.Get(0).(func(context.Context, []int64, *big.Int) []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]); ok { r0 = rf(ctx, etxIDs, chainID) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]*txmgr.Tx) + r0 = ret.Get(0).([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) } } @@ -1439,12 +1437,12 @@ func (_c *EvmTxStore_FindTxesByIDs_Call) Run(run func(ctx context.Context, etxID return _c } -func (_c *EvmTxStore_FindTxesByIDs_Call) Return(etxs []*txmgr.Tx, err error) *EvmTxStore_FindTxesByIDs_Call { +func (_c *EvmTxStore_FindTxesByIDs_Call) Return(etxs []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], err error) *EvmTxStore_FindTxesByIDs_Call { _c.Call.Return(etxs, err) return _c } -func (_c *EvmTxStore_FindTxesByIDs_Call) RunAndReturn(run func(context.Context, []int64, *big.Int) ([]*txmgr.Tx, error)) *EvmTxStore_FindTxesByIDs_Call { +func (_c *EvmTxStore_FindTxesByIDs_Call) RunAndReturn(run func(context.Context, []int64, *big.Int) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error)) *EvmTxStore_FindTxesByIDs_Call { _c.Call.Return(run) return _c } @@ -1512,23 +1510,23 @@ func (_c *EvmTxStore_FindTxesByMetaFieldAndStates_Call) RunAndReturn(run func(co } // FindTxesPendingCallback provides a mock function with given fields: ctx, latest, finalized, chainID -func (_m *EvmTxStore) FindTxesPendingCallback(ctx context.Context, latest int64, finalized int64, chainID *big.Int) ([]txmgr.ReceiptPlus, error) { +func (_m *EvmTxStore) FindTxesPendingCallback(ctx context.Context, latest int64, finalized int64, chainID *big.Int) ([]types.ReceiptPlus[*evmtypes.Receipt], error) { ret := _m.Called(ctx, latest, finalized, chainID) if len(ret) == 0 { panic("no return value specified for FindTxesPendingCallback") } - var r0 []txmgr.ReceiptPlus + var r0 []types.ReceiptPlus[*evmtypes.Receipt] var r1 error - if rf, ok := ret.Get(0).(func(context.Context, int64, int64, *big.Int) ([]txmgr.ReceiptPlus, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, int64, int64, *big.Int) ([]types.ReceiptPlus[*evmtypes.Receipt], error)); ok { return rf(ctx, latest, finalized, chainID) } - if rf, ok := ret.Get(0).(func(context.Context, int64, int64, *big.Int) []txmgr.ReceiptPlus); ok { + if rf, ok := ret.Get(0).(func(context.Context, int64, int64, *big.Int) []types.ReceiptPlus[*evmtypes.Receipt]); ok { r0 = rf(ctx, latest, finalized, chainID) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]txmgr.ReceiptPlus) + r0 = ret.Get(0).([]types.ReceiptPlus[*evmtypes.Receipt]) } } @@ -1562,12 +1560,12 @@ func (_c *EvmTxStore_FindTxesPendingCallback_Call) Run(run func(ctx context.Cont return _c } -func (_c *EvmTxStore_FindTxesPendingCallback_Call) Return(receiptsPlus []txmgr.ReceiptPlus, err error) *EvmTxStore_FindTxesPendingCallback_Call { +func (_c *EvmTxStore_FindTxesPendingCallback_Call) Return(receiptsPlus []types.ReceiptPlus[*evmtypes.Receipt], err error) *EvmTxStore_FindTxesPendingCallback_Call { _c.Call.Return(receiptsPlus, err) return _c } -func (_c *EvmTxStore_FindTxesPendingCallback_Call) RunAndReturn(run func(context.Context, int64, int64, *big.Int) ([]txmgr.ReceiptPlus, error)) *EvmTxStore_FindTxesPendingCallback_Call { +func (_c *EvmTxStore_FindTxesPendingCallback_Call) RunAndReturn(run func(context.Context, int64, int64, *big.Int) ([]types.ReceiptPlus[*evmtypes.Receipt], error)) *EvmTxStore_FindTxesPendingCallback_Call { _c.Call.Return(run) return _c } @@ -1756,23 +1754,23 @@ func (_c *EvmTxStore_FindTxesWithMetaFieldByStates_Call) RunAndReturn(run func(c } // FindTxsByStateAndFromAddresses provides a mock function with given fields: ctx, addresses, state, chainID -func (_m *EvmTxStore) FindTxsByStateAndFromAddresses(ctx context.Context, addresses []common.Address, state types.TxState, chainID *big.Int) ([]*txmgr.Tx, error) { +func (_m *EvmTxStore) FindTxsByStateAndFromAddresses(ctx context.Context, addresses []common.Address, state types.TxState, chainID *big.Int) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error) { ret := _m.Called(ctx, addresses, state, chainID) if len(ret) == 0 { panic("no return value specified for FindTxsByStateAndFromAddresses") } - var r0 []*txmgr.Tx + var r0 []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee] var r1 error - if rf, ok := ret.Get(0).(func(context.Context, []common.Address, types.TxState, *big.Int) ([]*txmgr.Tx, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, []common.Address, types.TxState, *big.Int) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error)); ok { return rf(ctx, addresses, state, chainID) } - if rf, ok := ret.Get(0).(func(context.Context, []common.Address, types.TxState, *big.Int) []*txmgr.Tx); ok { + if rf, ok := ret.Get(0).(func(context.Context, []common.Address, types.TxState, *big.Int) []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]); ok { r0 = rf(ctx, addresses, state, chainID) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]*txmgr.Tx) + r0 = ret.Get(0).([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) } } @@ -1806,12 +1804,12 @@ func (_c *EvmTxStore_FindTxsByStateAndFromAddresses_Call) Run(run func(ctx conte return _c } -func (_c *EvmTxStore_FindTxsByStateAndFromAddresses_Call) Return(txs []*txmgr.Tx, err error) *EvmTxStore_FindTxsByStateAndFromAddresses_Call { +func (_c *EvmTxStore_FindTxsByStateAndFromAddresses_Call) Return(txs []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], err error) *EvmTxStore_FindTxsByStateAndFromAddresses_Call { _c.Call.Return(txs, err) return _c } -func (_c *EvmTxStore_FindTxsByStateAndFromAddresses_Call) RunAndReturn(run func(context.Context, []common.Address, types.TxState, *big.Int) ([]*txmgr.Tx, error)) *EvmTxStore_FindTxsByStateAndFromAddresses_Call { +func (_c *EvmTxStore_FindTxsByStateAndFromAddresses_Call) RunAndReturn(run func(context.Context, []common.Address, types.TxState, *big.Int) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error)) *EvmTxStore_FindTxsByStateAndFromAddresses_Call { _c.Call.Return(run) return _c } @@ -2777,24 +2775,24 @@ func (_c *EvmTxStore_SetBroadcastBeforeBlockNum_Call) RunAndReturn(run func(cont } // Transactions provides a mock function with given fields: ctx, offset, limit -func (_m *EvmTxStore) Transactions(ctx context.Context, offset int, limit int) ([]txmgr.Tx, int, error) { +func (_m *EvmTxStore) Transactions(ctx context.Context, offset int, limit int) ([]types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], int, error) { ret := _m.Called(ctx, offset, limit) if len(ret) == 0 { panic("no return value specified for Transactions") } - var r0 []txmgr.Tx + var r0 []types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee] var r1 int var r2 error - if rf, ok := ret.Get(0).(func(context.Context, int, int) ([]txmgr.Tx, int, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, int, int) ([]types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], int, error)); ok { return rf(ctx, offset, limit) } - if rf, ok := ret.Get(0).(func(context.Context, int, int) []txmgr.Tx); ok { + if rf, ok := ret.Get(0).(func(context.Context, int, int) []types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]); ok { r0 = rf(ctx, offset, limit) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]txmgr.Tx) + r0 = ret.Get(0).([]types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) } } @@ -2833,35 +2831,35 @@ func (_c *EvmTxStore_Transactions_Call) Run(run func(ctx context.Context, offset return _c } -func (_c *EvmTxStore_Transactions_Call) Return(_a0 []txmgr.Tx, _a1 int, _a2 error) *EvmTxStore_Transactions_Call { +func (_c *EvmTxStore_Transactions_Call) Return(_a0 []types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], _a1 int, _a2 error) *EvmTxStore_Transactions_Call { _c.Call.Return(_a0, _a1, _a2) return _c } -func (_c *EvmTxStore_Transactions_Call) RunAndReturn(run func(context.Context, int, int) ([]txmgr.Tx, int, error)) *EvmTxStore_Transactions_Call { +func (_c *EvmTxStore_Transactions_Call) RunAndReturn(run func(context.Context, int, int) ([]types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], int, error)) *EvmTxStore_Transactions_Call { _c.Call.Return(run) return _c } // TransactionsWithAttempts provides a mock function with given fields: ctx, offset, limit -func (_m *EvmTxStore) TransactionsWithAttempts(ctx context.Context, offset int, limit int) ([]txmgr.Tx, int, error) { +func (_m *EvmTxStore) TransactionsWithAttempts(ctx context.Context, offset int, limit int) ([]types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], int, error) { ret := _m.Called(ctx, offset, limit) if len(ret) == 0 { panic("no return value specified for TransactionsWithAttempts") } - var r0 []txmgr.Tx + var r0 []types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee] var r1 int var r2 error - if rf, ok := ret.Get(0).(func(context.Context, int, int) ([]txmgr.Tx, int, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, int, int) ([]types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], int, error)); ok { return rf(ctx, offset, limit) } - if rf, ok := ret.Get(0).(func(context.Context, int, int) []txmgr.Tx); ok { + if rf, ok := ret.Get(0).(func(context.Context, int, int) []types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]); ok { r0 = rf(ctx, offset, limit) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]txmgr.Tx) + r0 = ret.Get(0).([]types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) } } @@ -2900,35 +2898,35 @@ func (_c *EvmTxStore_TransactionsWithAttempts_Call) Run(run func(ctx context.Con return _c } -func (_c *EvmTxStore_TransactionsWithAttempts_Call) Return(_a0 []txmgr.Tx, _a1 int, _a2 error) *EvmTxStore_TransactionsWithAttempts_Call { +func (_c *EvmTxStore_TransactionsWithAttempts_Call) Return(_a0 []types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], _a1 int, _a2 error) *EvmTxStore_TransactionsWithAttempts_Call { _c.Call.Return(_a0, _a1, _a2) return _c } -func (_c *EvmTxStore_TransactionsWithAttempts_Call) RunAndReturn(run func(context.Context, int, int) ([]txmgr.Tx, int, error)) *EvmTxStore_TransactionsWithAttempts_Call { +func (_c *EvmTxStore_TransactionsWithAttempts_Call) RunAndReturn(run func(context.Context, int, int) ([]types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], int, error)) *EvmTxStore_TransactionsWithAttempts_Call { _c.Call.Return(run) return _c } // TxAttempts provides a mock function with given fields: ctx, offset, limit -func (_m *EvmTxStore) TxAttempts(ctx context.Context, offset int, limit int) ([]txmgr.TxAttempt, int, error) { +func (_m *EvmTxStore) TxAttempts(ctx context.Context, offset int, limit int) ([]types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], int, error) { ret := _m.Called(ctx, offset, limit) if len(ret) == 0 { panic("no return value specified for TxAttempts") } - var r0 []txmgr.TxAttempt + var r0 []types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee] var r1 int var r2 error - if rf, ok := ret.Get(0).(func(context.Context, int, int) ([]txmgr.TxAttempt, int, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, int, int) ([]types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], int, error)); ok { return rf(ctx, offset, limit) } - if rf, ok := ret.Get(0).(func(context.Context, int, int) []txmgr.TxAttempt); ok { + if rf, ok := ret.Get(0).(func(context.Context, int, int) []types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]); ok { r0 = rf(ctx, offset, limit) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]txmgr.TxAttempt) + r0 = ret.Get(0).([]types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) } } @@ -2967,12 +2965,12 @@ func (_c *EvmTxStore_TxAttempts_Call) Run(run func(ctx context.Context, offset i return _c } -func (_c *EvmTxStore_TxAttempts_Call) Return(_a0 []txmgr.TxAttempt, _a1 int, _a2 error) *EvmTxStore_TxAttempts_Call { +func (_c *EvmTxStore_TxAttempts_Call) Return(_a0 []types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], _a1 int, _a2 error) *EvmTxStore_TxAttempts_Call { _c.Call.Return(_a0, _a1, _a2) return _c } -func (_c *EvmTxStore_TxAttempts_Call) RunAndReturn(run func(context.Context, int, int) ([]txmgr.TxAttempt, int, error)) *EvmTxStore_TxAttempts_Call { +func (_c *EvmTxStore_TxAttempts_Call) RunAndReturn(run func(context.Context, int, int) ([]types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], int, error)) *EvmTxStore_TxAttempts_Call { _c.Call.Return(run) return _c } diff --git a/core/chains/evm/txmgr/stuck_tx_detector.go b/core/chains/evm/txmgr/stuck_tx_detector.go index a8bb18af416..0550fb7a170 100644 --- a/core/chains/evm/txmgr/stuck_tx_detector.go +++ b/core/chains/evm/txmgr/stuck_tx_detector.go @@ -15,7 +15,8 @@ import ( "github.com/ethereum/go-ethereum/rpc" "github.com/smartcontractkit/chainlink-common/pkg/logger" - feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" + + "github.com/smartcontractkit/chainlink/v2/common/fees" "github.com/smartcontractkit/chainlink/v2/common/txmgr" "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" @@ -25,7 +26,7 @@ import ( ) type stuckTxDetectorGasEstimator interface { - GetFee(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, fromAddress, toAddress *common.Address, opts ...feetypes.Opt) (fee gas.EvmFee, chainSpecificFeeLimit uint64, err error) + GetFee(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, fromAddress, toAddress *common.Address, opts ...fees.Opt) (fee gas.EvmFee, chainSpecificFeeLimit uint64, err error) } type stuckTxDetectorClient interface { diff --git a/core/chains/evm/txmgr/txmgr_test.go b/core/chains/evm/txmgr/txmgr_test.go index 9ee2396846d..c02406a1c69 100644 --- a/core/chains/evm/txmgr/txmgr_test.go +++ b/core/chains/evm/txmgr/txmgr_test.go @@ -86,7 +86,8 @@ func makeTestEvmTxm( lp, keyStore, estimator, - ht) + ht, + nil) } func TestTxm_SendNativeToken_DoesNotSendToZero(t *testing.T) { diff --git a/core/chains/evm/types/models_test.go b/core/chains/evm/types/models_test.go index c06d683651a..a3f40a8bc2d 100644 --- a/core/chains/evm/types/models_test.go +++ b/core/chains/evm/types/models_test.go @@ -954,7 +954,7 @@ func TestBlock_UnmarshalJSON(t *testing.T) { t.Run("unmarshals geth block", func(t *testing.T) { b := new(evmtypes.Block) err := b.UnmarshalJSON([]byte(gethSampleBlock)) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, int64(15051090), b.Number) assert.Equal(t, "0x45eb0a650b6b0b9fd1ee676b870e43fa7614f1034f7404070327a332faed05c0", b.Hash.Hex()) @@ -966,14 +966,25 @@ func TestBlock_UnmarshalJSON(t *testing.T) { t.Run("handles empty result", func(t *testing.T) { b := new(evmtypes.Block) err := b.UnmarshalJSON([]byte("null")) - assert.Error(t, err) + require.Error(t, err) assert.Equal(t, pkgerrors.Cause(err), evmtypes.ErrMissingBlock) assert.True(t, pkgerrors.Is(err, evmtypes.ErrMissingBlock)) }) t.Run("unmarshals EIP-4844 block", func(t *testing.T) { b := new(evmtypes.Block) err := b.UnmarshalJSON([]byte(eip4844Block)) - assert.NoError(t, err) + require.NoError(t, err) + assert.Equal(t, int64(5300694), b.Number) + assert.Equal(t, "0x3edd900025edab70dde26a52377c3d0a9474c3f540bd0131d58f508711272590", b.Hash.Hex()) + assert.Equal(t, "0x077c1d68b52f8203cb90a71759a09b11c2a6577f97ea1fd4a8686a387fbedac8", b.ParentHash.Hex()) + assert.Equal(t, assets.NewWeiI(96436174005), b.BaseFeePerGas) + assert.Equal(t, int64(1708087260), b.Timestamp.Unix()) + assert.Len(t, b.Transactions, 6) + }) + t.Run("unmarshals EIP-4844 block", func(t *testing.T) { + b := new(evmtypes.Block) + err := b.UnmarshalJSON([]byte(eip4844Block)) + require.NoError(t, err) assert.Equal(t, int64(5300694), b.Number) assert.Equal(t, "0x3edd900025edab70dde26a52377c3d0a9474c3f540bd0131d58f508711272590", b.Hash.Hex()) assert.Equal(t, "0x077c1d68b52f8203cb90a71759a09b11c2a6577f97ea1fd4a8686a387fbedac8", b.ParentHash.Hex()) diff --git a/core/chains/legacyevm/chain.go b/core/chains/legacyevm/chain.go index d8eed88dedf..3e6aeef911c 100644 --- a/core/chains/legacyevm/chain.go +++ b/core/chains/legacyevm/chain.go @@ -194,10 +194,10 @@ func newChain(ctx context.Context, cfg *evmconfig.ChainScoped, nodes []*toml.Nod chainID := cfg.EVM().ChainID() l := opts.Logger var client evmclient.Client + var err error if !opts.AppConfig.EVMRPCEnabled() { client = evmclient.NewNullClient(chainID, l) } else if opts.GenEthClient == nil { - var err error client, err = evmclient.NewEvmClient(cfg.EVM().NodePool(), cfg.EVM(), cfg.EVM().NodePool().Errors(), l, chainID, nodes, cfg.EVM().ChainType()) if err != nil { return nil, err @@ -244,10 +244,24 @@ func newChain(ctx context.Context, cfg *evmconfig.ChainScoped, nodes []*toml.Nod } } - // note: gas estimator is started as a part of the txm - txm, gasEstimator, err := newEvmTxm(opts.DS, cfg.EVM(), opts.AppConfig.EVMRPCEnabled(), opts.AppConfig.Database(), opts.AppConfig.Database().Listener(), client, l, logPoller, opts, headTracker, clientsByChainID) + // initialize gas estimator + gasEstimator, err := newGasEstimator(cfg.EVM(), client, l, opts, clientsByChainID) if err != nil { - return nil, fmt.Errorf("failed to instantiate EvmTxm for chain with ID %s: %w", chainID.String(), err) + return nil, fmt.Errorf("failed to instantiate gas estimator for chain with ID %s: %w", chainID, err) + } + + // note: gas estimator is started as a part of the txm + var txm txmgr.TxManager + //nolint:gocritic // ignoring suggestion to convert to switch statement + if !opts.AppConfig.EVMRPCEnabled() { + txm = &txmgr.NullTxManager{ErrMsg: fmt.Sprintf("Ethereum is disabled for chain %d", chainID)} + } else if !cfg.EVM().Transactions().Enabled() { + txm = &txmgr.NullTxManager{ErrMsg: fmt.Sprintf("TXM disabled for chain %d", chainID)} + } else { + txm, err = newEvmTxm(opts.DS, cfg.EVM(), opts.AppConfig.Database(), opts.AppConfig.Database().Listener(), client, l, logPoller, opts, headTracker, gasEstimator) + if err != nil { + return nil, fmt.Errorf("failed to instantiate EvmTxm for chain with ID %s: %w", chainID, err) + } } headBroadcaster.Subscribe(txm) diff --git a/core/chains/legacyevm/evm_txm.go b/core/chains/legacyevm/evm_txm.go index 3a96a9da937..078bd413636 100644 --- a/core/chains/legacyevm/evm_txm.go +++ b/core/chains/legacyevm/evm_txm.go @@ -17,7 +17,6 @@ import ( func newEvmTxm( ds sqlutil.DataSource, cfg evmconfig.EVM, - evmRPCEnabled bool, databaseConfig txmgr.DatabaseConfig, listenerConfig txmgr.ListenerConfig, client evmclient.Client, @@ -25,16 +24,11 @@ func newEvmTxm( logPoller logpoller.LogPoller, opts ChainRelayOpts, headTracker httypes.HeadTracker, - clientsByChainID map[string]rollups.DAClient, -) (txm txmgr.TxManager, estimator gas.EvmFeeEstimator, +) (txm txmgr.TxManager, err error, ) { chainID := cfg.ChainID() - if !evmRPCEnabled { - txm = &txmgr.NullTxManager{ErrMsg: fmt.Sprintf("Ethereum is disabled for chain %d", chainID)} - return txm, nil, nil - } lggr = lggr.Named("Txm") lggr.Infow("Initializing EVM transaction manager", @@ -45,16 +39,25 @@ func newEvmTxm( "limitDefault", cfg.GasEstimator().LimitDefault(), ) - // build estimator from factory - if opts.GenGasEstimator == nil { - if estimator, err = gas.NewEstimator(lggr, client, cfg.ChainType(), chainID, cfg.GasEstimator(), clientsByChainID); err != nil { - return nil, nil, fmt.Errorf("failed to initialize estimator: %w", err) - } - } else { - estimator = opts.GenGasEstimator(chainID) - } - if opts.GenTxManager == nil { + var txmv2 txmgr.TxManager + if cfg.Transactions().TransactionManagerV2().Enabled() { + txmv2, err = txmgr.NewTxmV2( + ds, + cfg, + txmgr.NewEvmTxmFeeConfig(cfg.GasEstimator()), + cfg.Transactions(), + cfg.Transactions().TransactionManagerV2(), + client, + lggr, + logPoller, + opts.KeyStore, + estimator, + ) + if cfg.Transactions().TransactionManagerV2().DualBroadcast() != nil && *cfg.Transactions().TransactionManagerV2().DualBroadcast() { + return txmv2, err + } + } txm, err = txmgr.NewTxm( ds, cfg, @@ -68,9 +71,30 @@ func newEvmTxm( logPoller, opts.KeyStore, estimator, - headTracker) + headTracker, + txmv2) } else { txm = opts.GenTxManager(chainID) } return } + +func newGasEstimator( + cfg evmconfig.EVM, + client evmclient.Client, + lggr logger.Logger, + opts ChainRelayOpts, + clientsByChainID map[string]rollups.DAClient, +) (estimator gas.EvmFeeEstimator, err error) { + lggr = lggr.Named("Txm") + chainID := cfg.ChainID() + // build estimator from factory + if opts.GenGasEstimator == nil { + if estimator, err = gas.NewEstimator(lggr, client, cfg.ChainType(), chainID, cfg.GasEstimator(), clientsByChainID); err != nil { + return nil, fmt.Errorf("failed to initialize estimator: %w", err) + } + } else { + estimator = opts.GenGasEstimator(chainID) + } + return +} diff --git a/core/chains/legacyevm/mocks/chain.go b/core/chains/legacyevm/mocks/chain.go index 14a89027323..e642ca2c608 100644 --- a/core/chains/legacyevm/mocks/chain.go +++ b/core/chains/legacyevm/mocks/chain.go @@ -1,18 +1,22 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks import ( big "math/big" + common "github.com/ethereum/go-ethereum/common" client "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + config "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" context "context" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + gas "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" - headtrackertypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types" + headtracker "github.com/smartcontractkit/chainlink/v2/common/headtracker" log "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log" @@ -24,7 +28,7 @@ import ( monitor "github.com/smartcontractkit/chainlink/v2/core/chains/evm/monitor" - txmgr "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" + txmgr "github.com/smartcontractkit/chainlink/v2/common/txmgr" types "github.com/smartcontractkit/chainlink-common/pkg/types" ) @@ -42,7 +46,7 @@ func (_m *Chain) EXPECT() *Chain_Expecter { return &Chain_Expecter{mock: &_m.Mock} } -// BalanceMonitor provides a mock function with given fields: +// BalanceMonitor provides a mock function with no fields func (_m *Chain) BalanceMonitor() monitor.BalanceMonitor { ret := _m.Called() @@ -89,7 +93,7 @@ func (_c *Chain_BalanceMonitor_Call) RunAndReturn(run func() monitor.BalanceMoni return _c } -// Client provides a mock function with given fields: +// Client provides a mock function with no fields func (_m *Chain) Client() client.Client { ret := _m.Called() @@ -136,7 +140,7 @@ func (_c *Chain_Client_Call) RunAndReturn(run func() client.Client) *Chain_Clien return _c } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *Chain) Close() error { ret := _m.Called() @@ -181,7 +185,7 @@ func (_c *Chain_Close_Call) RunAndReturn(run func() error) *Chain_Close_Call { return _c } -// Config provides a mock function with given fields: +// Config provides a mock function with no fields func (_m *Chain) Config() config.ChainScopedConfig { ret := _m.Called() @@ -228,7 +232,7 @@ func (_c *Chain_Config_Call) RunAndReturn(run func() config.ChainScopedConfig) * return _c } -// GasEstimator provides a mock function with given fields: +// GasEstimator provides a mock function with no fields func (_m *Chain) GasEstimator() gas.EvmFeeEstimator { ret := _m.Called() @@ -331,20 +335,20 @@ func (_c *Chain_GetChainStatus_Call) RunAndReturn(run func(context.Context) (typ return _c } -// HeadBroadcaster provides a mock function with given fields: -func (_m *Chain) HeadBroadcaster() headtrackertypes.HeadBroadcaster { +// HeadBroadcaster provides a mock function with no fields +func (_m *Chain) HeadBroadcaster() headtracker.HeadBroadcaster[*evmtypes.Head, common.Hash] { ret := _m.Called() if len(ret) == 0 { panic("no return value specified for HeadBroadcaster") } - var r0 headtrackertypes.HeadBroadcaster - if rf, ok := ret.Get(0).(func() headtrackertypes.HeadBroadcaster); ok { + var r0 headtracker.HeadBroadcaster[*evmtypes.Head, common.Hash] + if rf, ok := ret.Get(0).(func() headtracker.HeadBroadcaster[*evmtypes.Head, common.Hash]); ok { r0 = rf() } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(headtrackertypes.HeadBroadcaster) + r0 = ret.Get(0).(headtracker.HeadBroadcaster[*evmtypes.Head, common.Hash]) } } @@ -368,30 +372,30 @@ func (_c *Chain_HeadBroadcaster_Call) Run(run func()) *Chain_HeadBroadcaster_Cal return _c } -func (_c *Chain_HeadBroadcaster_Call) Return(_a0 headtrackertypes.HeadBroadcaster) *Chain_HeadBroadcaster_Call { +func (_c *Chain_HeadBroadcaster_Call) Return(_a0 headtracker.HeadBroadcaster[*evmtypes.Head, common.Hash]) *Chain_HeadBroadcaster_Call { _c.Call.Return(_a0) return _c } -func (_c *Chain_HeadBroadcaster_Call) RunAndReturn(run func() headtrackertypes.HeadBroadcaster) *Chain_HeadBroadcaster_Call { +func (_c *Chain_HeadBroadcaster_Call) RunAndReturn(run func() headtracker.HeadBroadcaster[*evmtypes.Head, common.Hash]) *Chain_HeadBroadcaster_Call { _c.Call.Return(run) return _c } -// HeadTracker provides a mock function with given fields: -func (_m *Chain) HeadTracker() headtrackertypes.HeadTracker { +// HeadTracker provides a mock function with no fields +func (_m *Chain) HeadTracker() headtracker.HeadTracker[*evmtypes.Head, common.Hash] { ret := _m.Called() if len(ret) == 0 { panic("no return value specified for HeadTracker") } - var r0 headtrackertypes.HeadTracker - if rf, ok := ret.Get(0).(func() headtrackertypes.HeadTracker); ok { + var r0 headtracker.HeadTracker[*evmtypes.Head, common.Hash] + if rf, ok := ret.Get(0).(func() headtracker.HeadTracker[*evmtypes.Head, common.Hash]); ok { r0 = rf() } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(headtrackertypes.HeadTracker) + r0 = ret.Get(0).(headtracker.HeadTracker[*evmtypes.Head, common.Hash]) } } @@ -415,17 +419,17 @@ func (_c *Chain_HeadTracker_Call) Run(run func()) *Chain_HeadTracker_Call { return _c } -func (_c *Chain_HeadTracker_Call) Return(_a0 headtrackertypes.HeadTracker) *Chain_HeadTracker_Call { +func (_c *Chain_HeadTracker_Call) Return(_a0 headtracker.HeadTracker[*evmtypes.Head, common.Hash]) *Chain_HeadTracker_Call { _c.Call.Return(_a0) return _c } -func (_c *Chain_HeadTracker_Call) RunAndReturn(run func() headtrackertypes.HeadTracker) *Chain_HeadTracker_Call { +func (_c *Chain_HeadTracker_Call) RunAndReturn(run func() headtracker.HeadTracker[*evmtypes.Head, common.Hash]) *Chain_HeadTracker_Call { _c.Call.Return(run) return _c } -// HealthReport provides a mock function with given fields: +// HealthReport provides a mock function with no fields func (_m *Chain) HealthReport() map[string]error { ret := _m.Called() @@ -472,7 +476,7 @@ func (_c *Chain_HealthReport_Call) RunAndReturn(run func() map[string]error) *Ch return _c } -// ID provides a mock function with given fields: +// ID provides a mock function with no fields func (_m *Chain) ID() *big.Int { ret := _m.Called() @@ -649,7 +653,7 @@ func (_c *Chain_ListNodeStatuses_Call) RunAndReturn(run func(context.Context, in return _c } -// LogBroadcaster provides a mock function with given fields: +// LogBroadcaster provides a mock function with no fields func (_m *Chain) LogBroadcaster() log.Broadcaster { ret := _m.Called() @@ -696,7 +700,7 @@ func (_c *Chain_LogBroadcaster_Call) RunAndReturn(run func() log.Broadcaster) *C return _c } -// LogPoller provides a mock function with given fields: +// LogPoller provides a mock function with no fields func (_m *Chain) LogPoller() logpoller.LogPoller { ret := _m.Called() @@ -743,7 +747,7 @@ func (_c *Chain_LogPoller_Call) RunAndReturn(run func() logpoller.LogPoller) *Ch return _c } -// Logger provides a mock function with given fields: +// Logger provides a mock function with no fields func (_m *Chain) Logger() logger.Logger { ret := _m.Called() @@ -790,7 +794,7 @@ func (_c *Chain_Logger_Call) RunAndReturn(run func() logger.Logger) *Chain_Logge return _c } -// Name provides a mock function with given fields: +// Name provides a mock function with no fields func (_m *Chain) Name() string { ret := _m.Called() @@ -835,7 +839,7 @@ func (_c *Chain_Name_Call) RunAndReturn(run func() string) *Chain_Name_Call { return _c } -// Ready provides a mock function with given fields: +// Ready provides a mock function with no fields func (_m *Chain) Ready() error { ret := _m.Called() @@ -976,20 +980,20 @@ func (_c *Chain_Transact_Call) RunAndReturn(run func(context.Context, string, st return _c } -// TxManager provides a mock function with given fields: -func (_m *Chain) TxManager() txmgr.TxManager { +// TxManager provides a mock function with no fields +func (_m *Chain) TxManager() txmgr.TxManager[*big.Int, *evmtypes.Head, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee] { ret := _m.Called() if len(ret) == 0 { panic("no return value specified for TxManager") } - var r0 txmgr.TxManager - if rf, ok := ret.Get(0).(func() txmgr.TxManager); ok { + var r0 txmgr.TxManager[*big.Int, *evmtypes.Head, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee] + if rf, ok := ret.Get(0).(func() txmgr.TxManager[*big.Int, *evmtypes.Head, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]); ok { r0 = rf() } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(txmgr.TxManager) + r0 = ret.Get(0).(txmgr.TxManager[*big.Int, *evmtypes.Head, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) } } @@ -1013,12 +1017,12 @@ func (_c *Chain_TxManager_Call) Run(run func()) *Chain_TxManager_Call { return _c } -func (_c *Chain_TxManager_Call) Return(_a0 txmgr.TxManager) *Chain_TxManager_Call { +func (_c *Chain_TxManager_Call) Return(_a0 txmgr.TxManager[*big.Int, *evmtypes.Head, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) *Chain_TxManager_Call { _c.Call.Return(_a0) return _c } -func (_c *Chain_TxManager_Call) RunAndReturn(run func() txmgr.TxManager) *Chain_TxManager_Call { +func (_c *Chain_TxManager_Call) RunAndReturn(run func() txmgr.TxManager[*big.Int, *evmtypes.Head, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) *Chain_TxManager_Call { _c.Call.Return(run) return _c } diff --git a/core/chains/legacyevm/mocks/legacy_chain_container.go b/core/chains/legacyevm/mocks/legacy_chain_container.go index 0425a016014..b5ddfe4891f 100644 --- a/core/chains/legacyevm/mocks/legacy_chain_container.go +++ b/core/chains/legacyevm/mocks/legacy_chain_container.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -22,7 +22,7 @@ func (_m *LegacyChainContainer) EXPECT() *LegacyChainContainer_Expecter { return &LegacyChainContainer_Expecter{mock: &_m.Mock} } -// ChainNodeConfigs provides a mock function with given fields: +// ChainNodeConfigs provides a mock function with no fields func (_m *LegacyChainContainer) ChainNodeConfigs() types.Configs { ret := _m.Called() @@ -127,7 +127,7 @@ func (_c *LegacyChainContainer_Get_Call) RunAndReturn(run func(string) (legacyev return _c } -// Len provides a mock function with given fields: +// Len provides a mock function with no fields func (_m *LegacyChainContainer) Len() int { ret := _m.Called() @@ -243,7 +243,7 @@ func (_c *LegacyChainContainer_List_Call) RunAndReturn(run func(...string) ([]le return _c } -// Slice provides a mock function with given fields: +// Slice provides a mock function with no fields func (_m *LegacyChainContainer) Slice() []legacyevm.Chain { ret := _m.Called() diff --git a/core/cmd/app.go b/core/cmd/app.go index 8128d578238..f605b3973c7 100644 --- a/core/cmd/app.go +++ b/core/cmd/app.go @@ -201,6 +201,7 @@ func NewApp(s *Shell) *cli.App { keysCommand("Solana", NewSolanaKeysClient(s)), keysCommand("StarkNet", NewStarkNetKeysClient(s)), keysCommand("Aptos", NewAptosKeysClient(s)), + keysCommand("Tron", NewTronKeysClient(s)), initVRFKeysSubCmd(s), }, diff --git a/core/cmd/bridge_commands.go b/core/cmd/bridge_commands.go index 398d466c43a..cd314b23218 100644 --- a/core/cmd/bridge_commands.go +++ b/core/cmd/bridge_commands.go @@ -128,6 +128,29 @@ func (s *Shell) CreateBridge(c *cli.Context) (err error) { return s.renderAPIResponse(resp, &BridgePresenter{}) } +func (s *Shell) UpdateBridge(c *cli.Context) (err error) { + if !c.Args().Present() { + return s.errorOut(errors.New("must pass the name of the bridge to be updated")) + } + bridgeName := c.Args().First() + buf, err := getBufferFromJSON(c.Args().Get(1)) + if err != nil { + return s.errorOut(err) + } + + resp, err := s.HTTP.Patch(s.ctx(), "/v2/bridge_types/"+bridgeName, buf) + if err != nil { + return s.errorOut(err) + } + defer func() { + if cerr := resp.Body.Close(); cerr != nil { + err = multierr.Append(err, cerr) + } + }() + + return s.renderAPIResponse(resp, &BridgePresenter{}) +} + // RemoveBridge removes a specific Bridge by name. func (s *Shell) RemoveBridge(c *cli.Context) (err error) { if !c.Args().Present() { diff --git a/core/cmd/bridge_commands_test.go b/core/cmd/bridge_commands_test.go index f05aac52cd9..5523fc09605 100644 --- a/core/cmd/bridge_commands_test.go +++ b/core/cmd/bridge_commands_test.go @@ -3,6 +3,7 @@ package cmd_test import ( "bytes" "flag" + "fmt" "testing" "time" @@ -191,3 +192,44 @@ func TestShell_RemoveBridge(t *testing.T) { assert.Equal(t, bt.URL.String(), p.URL) assert.Equal(t, bt.Confirmations, p.Confirmations) } +func TestShell_UpdateBridge(t *testing.T) { + t.Parallel() + + app := startNewApplicationV2(t, nil) + client, _ := app.NewShellAndRenderer() + name := testutils.RandomizeName("updatebridge") + + bt := &bridges.BridgeType{ + Name: bridges.MustParseBridgeName(name), + URL: cltest.WebURL(t, "https://testing.com/bridges"), + Confirmations: 0, + } + require.NoError(t, app.BridgeORM().CreateBridgeType(testutils.Context(t), bt)) + tests := []struct { + name string + args []string + errored bool + }{ + {"NoArgs", []string{}, true}, + {"OnlyName", []string{name}, true}, + {"ValidUpdate", []string{name, fmt.Sprintf(`{ "name": "%s", "url": "http://localhost:3000/updated" }`, name)}, false}, + {"InvalidJSON", []string{name, `{ "url": "http://localhost:3000/updated"`}, true}, + } + + for _, tt := range tests { + test := tt + t.Run(test.name, func(t *testing.T) { + set := flag.NewFlagSet("bridge", 0) + flagSetApplyFromAction(client.UpdateBridge, set, "") + + require.NoError(t, set.Parse(test.args)) + + c := cli.NewContext(nil, set, nil) + if test.errored { + assert.Error(t, client.UpdateBridge(c)) + } else { + assert.NoError(t, client.UpdateBridge(c)) + } + }) + } +} diff --git a/core/cmd/mocks/prompter.go b/core/cmd/mocks/prompter.go index 03b6dae04cb..aca41d1ed4a 100644 --- a/core/cmd/mocks/prompter.go +++ b/core/cmd/mocks/prompter.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -17,7 +17,7 @@ func (_m *Prompter) EXPECT() *Prompter_Expecter { return &Prompter_Expecter{mock: &_m.Mock} } -// IsTerminal provides a mock function with given fields: +// IsTerminal provides a mock function with no fields func (_m *Prompter) IsTerminal() bool { ret := _m.Called() diff --git a/core/cmd/nodes_commands.go b/core/cmd/nodes_commands.go index 2afff31ace0..0420ef66ec4 100644 --- a/core/cmd/nodes_commands.go +++ b/core/cmd/nodes_commands.go @@ -6,9 +6,10 @@ import ( "slices" "strings" + "github.com/urfave/cli" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" - "github.com/urfave/cli" ) func initNodeSubCmds(s *Shell) []cli.Command { diff --git a/core/cmd/shell.go b/core/cmd/shell.go index 94664a3cf3d..09eacd7dc39 100644 --- a/core/cmd/shell.go +++ b/core/cmd/shell.go @@ -293,6 +293,13 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G } initOps = append(initOps, chainlink.InitAptos(ctx, relayerFactory, aptosCfg)) } + if cfg.TronEnabled() { + tronCfg := chainlink.TronFactoryConfig{ + Keystore: keyStore.Tron(), + TOMLConfigs: cfg.TronConfigs(), + } + initOps = append(initOps, chainlink.InitTron(ctx, relayerFactory, tronCfg)) + } relayChainInterops, err := chainlink.NewCoreRelayerChainInteroperators(initOps...) if err != nil { diff --git a/core/cmd/shell_local.go b/core/cmd/shell_local.go index 1fdc1a46d34..07b593ac978 100644 --- a/core/cmd/shell_local.go +++ b/core/cmd/shell_local.go @@ -434,6 +434,9 @@ func (s *Shell) runNode(c *cli.Context) error { if s.Config.AptosEnabled() { enabledChains = append(enabledChains, chaintype.Aptos) } + if s.Config.TronEnabled() { + enabledChains = append(enabledChains, chaintype.Tron) + } err2 := app.GetKeyStore().OCR2().EnsureKeys(rootCtx, enabledChains...) if err2 != nil { return errors.Wrap(err2, "failed to ensure ocr key") @@ -469,6 +472,12 @@ func (s *Shell) runNode(c *cli.Context) error { return errors.Wrap(err2, "failed to ensure aptos key") } } + if s.Config.TronEnabled() { + err2 := app.GetKeyStore().Tron().EnsureKey(rootCtx) + if err2 != nil { + return errors.Wrap(err2, "failed to ensure tron key") + } + } err2 := app.GetKeyStore().Workflow().EnsureKey(rootCtx) if err2 != nil { diff --git a/core/cmd/shell_local_test.go b/core/cmd/shell_local_test.go index 7cdc8c21840..5c9449b2107 100644 --- a/core/cmd/shell_local_test.go +++ b/core/cmd/shell_local_test.go @@ -12,8 +12,8 @@ import ( commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" pgcommon "github.com/smartcontractkit/chainlink-common/pkg/sqlutil/pg" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + "github.com/smartcontractkit/chainlink-framework/multinode" - "github.com/smartcontractkit/chainlink/v2/common/client" "github.com/smartcontractkit/chainlink/v2/core/capabilities" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/cmd" @@ -337,7 +337,7 @@ func TestShell_RebroadcastTransactions_Txm(t *testing.T) { n := i ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == n - }), mock.Anything).Once().Return(client.Successful, nil) + }), mock.Anything).Once().Return(multinode.Successful, nil) } assert.NoError(t, c.RebroadcastTransactions(ctx)) @@ -417,7 +417,7 @@ func TestShell_RebroadcastTransactions_OutsideRange_Txm(t *testing.T) { n := i ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return uint(tx.Nonce()) == n - }), mock.Anything).Once().Return(client.Successful, nil) + }), mock.Anything).Once().Return(multinode.Successful, nil) } assert.NoError(t, c.RebroadcastTransactions(ctx)) @@ -469,7 +469,7 @@ func TestShell_RebroadcastTransactions_AddressCheck(t *testing.T) { mockRelayerChainInteroperators := &chainlinkmocks.FakeRelayerChainInteroperators{EVMChains: legacy} app.On("GetRelayers").Return(mockRelayerChainInteroperators).Maybe() - ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, mock.Anything).Maybe().Return(client.Successful, nil) + ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, mock.Anything).Maybe().Return(multinode.Successful, nil) client := cmd.Shell{ Config: config, diff --git a/core/cmd/tron_keys_commands.go b/core/cmd/tron_keys_commands.go new file mode 100644 index 00000000000..67b3242e1f5 --- /dev/null +++ b/core/cmd/tron_keys_commands.go @@ -0,0 +1,57 @@ +package cmd + +import ( + "github.com/smartcontractkit/chainlink-common/pkg/utils" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/tronkey" + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +type TronKeyPresenter struct { + JAID + presenters.TronKeyResource +} + +// RenderTable implements TableRenderer +func (p TronKeyPresenter) RenderTable(rt RendererTable) error { + headers := []string{"ID", "Public key"} + rows := [][]string{p.ToRow()} + + if _, err := rt.Write([]byte("🔑 Tron Keys\n")); err != nil { + return err + } + renderList(headers, rows, rt.Writer) + + return utils.JustError(rt.Write([]byte("\n"))) +} + +func (p *TronKeyPresenter) ToRow() []string { + row := []string{ + p.ID, + p.PubKey, + } + + return row +} + +type TronKeyPresenters []TronKeyPresenter + +// RenderTable implements TableRenderer +func (ps TronKeyPresenters) RenderTable(rt RendererTable) error { + headers := []string{"ID", "Public key"} + rows := [][]string{} + + for _, p := range ps { + rows = append(rows, p.ToRow()) + } + + if _, err := rt.Write([]byte("🔑 Tron Keys\n")); err != nil { + return err + } + renderList(headers, rows, rt.Writer) + + return utils.JustError(rt.Write([]byte("\n"))) +} + +func NewTronKeysClient(s *Shell) KeysClient { + return newKeysClient[tronkey.Key, TronKeyPresenter, TronKeyPresenters]("Tron", s) +} diff --git a/core/cmd/tron_keys_commands_test.go b/core/cmd/tron_keys_commands_test.go new file mode 100644 index 00000000000..29480600d74 --- /dev/null +++ b/core/cmd/tron_keys_commands_test.go @@ -0,0 +1,174 @@ +package cmd_test + +import ( + "bytes" + "context" + "flag" + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/urfave/cli" + + "github.com/smartcontractkit/chainlink-common/pkg/utils" + "github.com/smartcontractkit/chainlink/v2/core/cmd" + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/tronkey" + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +func TestTronKeyPresenter_RenderTable(t *testing.T) { + t.Parallel() + + var ( + id = "1" + pubKey = "somepubkey" + buffer = bytes.NewBufferString("") + r = cmd.RendererTable{Writer: buffer} + ) + + p := cmd.TronKeyPresenter{ + JAID: cmd.JAID{ID: id}, + TronKeyResource: presenters.TronKeyResource{ + JAID: presenters.NewJAID(id), + PubKey: pubKey, + }, + } + + // Render a single resource + require.NoError(t, p.RenderTable(r)) + + output := buffer.String() + assert.Contains(t, output, id) + assert.Contains(t, output, pubKey) + + // Render many resources + buffer.Reset() + ps := cmd.TronKeyPresenters{p} + require.NoError(t, ps.RenderTable(r)) + + output = buffer.String() + assert.Contains(t, output, id) + assert.Contains(t, output, pubKey) +} + +func TestShell_TronKeys(t *testing.T) { + app := startNewApplicationV2(t, nil) + ks := app.GetKeyStore().Tron() + cleanup := func() { + ctx := context.Background() + keys, err := ks.GetAll() + require.NoError(t, err) + for _, key := range keys { + require.NoError(t, utils.JustError(ks.Delete(ctx, key.ID()))) + } + requireTronKeyCount(t, app, 0) + } + + t.Run("ListTronKeys", func(tt *testing.T) { + defer cleanup() + ctx := testutils.Context(t) + client, r := app.NewShellAndRenderer() + key, err := app.GetKeyStore().Tron().Create(ctx) + require.NoError(t, err) + requireTronKeyCount(t, app, 1) + require.NoError(t, cmd.NewTronKeysClient(client).ListKeys(cltest.EmptyCLIContext())) + require.Len(t, r.Renders, 1) + keys := *r.Renders[0].(*cmd.TronKeyPresenters) + assert.Equal(t, key.PublicKeyStr(), keys[0].PubKey) + }) + + t.Run("CreateTronKey", func(tt *testing.T) { + defer cleanup() + client, _ := app.NewShellAndRenderer() + require.NoError(t, cmd.NewTronKeysClient(client).CreateKey(nilContext)) + keys, err := app.GetKeyStore().Tron().GetAll() + require.NoError(t, err) + require.Len(t, keys, 1) + }) + + t.Run("DeleteTronKey", func(tt *testing.T) { + defer cleanup() + ctx := testutils.Context(t) + client, _ := app.NewShellAndRenderer() + key, err := app.GetKeyStore().Tron().Create(ctx) + require.NoError(t, err) + requireTronKeyCount(t, app, 1) + set := flag.NewFlagSet("test", 0) + flagSetApplyFromAction(cmd.NewTronKeysClient(client).DeleteKey, set, "tron") + + require.NoError(tt, set.Set("yes", "true")) + + strID := key.ID() + err = set.Parse([]string{strID}) + require.NoError(t, err) + c := cli.NewContext(nil, set, nil) + err = cmd.NewTronKeysClient(client).DeleteKey(c) + require.NoError(t, err) + requireTronKeyCount(t, app, 0) + }) + + t.Run("ImportExportTronKey", func(tt *testing.T) { + defer cleanup() + defer deleteKeyExportFile(t) + ctx := testutils.Context(t) + client, _ := app.NewShellAndRenderer() + + _, err := app.GetKeyStore().Tron().Create(ctx) + require.NoError(t, err) + + keys := requireTronKeyCount(t, app, 1) + key := keys[0] + keyName := keyNameForTest(t) + + // Export test invalid id + set := flag.NewFlagSet("test Tron export", 0) + flagSetApplyFromAction(cmd.NewTronKeysClient(client).ExportKey, set, "tron") + + require.NoError(tt, set.Parse([]string{"0"})) + require.NoError(tt, set.Set("new-password", "../internal/fixtures/incorrect_password.txt")) + require.NoError(tt, set.Set("output", keyName)) + + c := cli.NewContext(nil, set, nil) + err = cmd.NewTronKeysClient(client).ExportKey(c) + require.Error(t, err, "Error exporting") + require.Error(t, utils.JustError(os.Stat(keyName))) + + // Export test + set = flag.NewFlagSet("test Tron export", 0) + flagSetApplyFromAction(cmd.NewTronKeysClient(client).ExportKey, set, "tron") + + require.NoError(tt, set.Parse([]string{key.ID()})) + require.NoError(tt, set.Set("new-password", "../internal/fixtures/incorrect_password.txt")) + require.NoError(tt, set.Set("output", keyName)) + + c = cli.NewContext(nil, set, nil) + + require.NoError(t, cmd.NewTronKeysClient(client).ExportKey(c)) + require.NoError(t, utils.JustError(os.Stat(keyName))) + + require.NoError(t, utils.JustError(app.GetKeyStore().Tron().Delete(ctx, key.ID()))) + requireTronKeyCount(t, app, 0) + + set = flag.NewFlagSet("test Tron import", 0) + flagSetApplyFromAction(cmd.NewTronKeysClient(client).ImportKey, set, "tron") + + require.NoError(tt, set.Parse([]string{keyName})) + require.NoError(tt, set.Set("old-password", "../internal/fixtures/incorrect_password.txt")) + c = cli.NewContext(nil, set, nil) + require.NoError(t, cmd.NewTronKeysClient(client).ImportKey(c)) + + requireTronKeyCount(t, app, 1) + }) +} + +func requireTronKeyCount(t *testing.T, app chainlink.Application, length int) []tronkey.Key { + t.Helper() + keys, err := app.GetKeyStore().Tron().GetAll() + require.NoError(t, err) + require.Len(t, keys, length) + return keys +} diff --git a/core/config/app_config.go b/core/config/app_config.go index 3f2a5472b24..4ce8873bb96 100644 --- a/core/config/app_config.go +++ b/core/config/app_config.go @@ -25,6 +25,7 @@ type AppConfig interface { SolanaEnabled() bool StarkNetEnabled() bool AptosEnabled() bool + TronEnabled() bool Validate() error ValidateDB() error diff --git a/core/config/docs/chains-evm.toml b/core/config/docs/chains-evm.toml index 62360cb02cb..bdcb0e8c5d4 100644 --- a/core/config/docs/chains-evm.toml +++ b/core/config/docs/chains-evm.toml @@ -106,6 +106,8 @@ LogBroadcasterEnabled = true # Default NoNewFinalizedHeadsThreshold = '0' # Default [EVM.Transactions] +# Enabled is a feature flag for the Transaction Manager. This flag also enables or disables the gas estimator since it is dependent on the TXM to start it. +Enabled = true # Default # ForwardersEnabled enables or disables sending transactions through forwarder contracts. ForwardersEnabled = false # Default # MaxInFlight controls how many transactions are allowed to be "in-flight" i.e. broadcast but unconfirmed at any one time. You can consider this a form of transaction throttling. @@ -139,6 +141,16 @@ Threshold = 5 # Example # MinAttempts configures the minimum number of broadcasted attempts a transaction has to have before it is evaluated further for being terminally stuck. This threshold is only applied if there is no custom API to identify stuck transactions provided by the chain. Ensure the gas estimator configs take more bump attempts before reaching the configured max gas price. MinAttempts = 3 # Example +[EVM.Transactions.TransactionManagerV2] +# Enabled enables TransactionManagerV2. +Enabled = false # Default +# BlockTime controls the frequency of the backfill loop of TransactionManagerV2. +BlockTime = '10s' # Example +# CustomURL configures the base url of a custom endpoint used by the ChainDualBroadcast chain type. +CustomURL = 'https://example.api.io' # Example +# DualBroadcast enables DualBroadcast functionality. +DualBroadcast = false # Example + [EVM.BalanceMonitor] # Enabled balance monitoring for all keys. Enabled = true # Default diff --git a/core/config/docs/chains-solana.toml b/core/config/docs/chains-solana.toml index c979581b258..c4d757ffa85 100644 --- a/core/config/docs/chains-solana.toml +++ b/core/config/docs/chains-solana.toml @@ -17,6 +17,9 @@ TxTimeout = '1m' # Default TxRetryTimeout = '10s' # Default # TxConfirmTimeout is the duration to wait when confirming a tx signature, before discarding as unconfirmed. TxConfirmTimeout = '30s' # Default +# TxExpirationRebroadcast enables or disables transaction rebroadcast if expired. Expiration check is performed every `ConfirmPollPeriod` +# A transaction is considered expired if the blockhash it was sent with is 150 blocks older than the latest blockhash. +TxExpirationRebroadcast = false # Default # TxRetentionTimeout is the duration to retain transactions in storage after being marked as finalized or errored. Set to 0 to immediately drop transactions. TxRetentionTimeout = '0s' # Default # SkipPreflight enables or disables preflight checks when sending txs. diff --git a/core/config/docs/chains-tron.toml b/core/config/docs/chains-tron.toml new file mode 100644 index 00000000000..55a44bacd7a --- /dev/null +++ b/core/config/docs/chains-tron.toml @@ -0,0 +1,13 @@ +[[Tron]] +# ChainID is the Tron chain ID. +ChainID = 'foobar' # Example +# Enabled enables this chain. +Enabled = true # Default + +[[Tron.Nodes]] +# Name is a unique (per-chain) identifier for this node. +Name = 'primary' # Example +# URL is the full node HTTP endpoint for this node. +URL = 'https://api.trongrid.io/wallet' # Example +# SolidityURL is the solidity node HTTP endpoint for this node. +SolidityURL = 'http://api.trongrid.io/wallet' # Example diff --git a/core/config/docs/core.toml b/core/config/docs/core.toml index 20c519e81a1..f32b95ba4cf 100644 --- a/core/config/docs/core.toml +++ b/core/config/docs/core.toml @@ -686,13 +686,19 @@ CertFile = "/path/to/client/certs.pem" # Example # Mercury.Transmitter controls settings for the mercury transmitter [Mercury.Transmitter] +# Protocol is the protocol to use for the transmitter. +# +# Options are either: +# - "wsrpc" for the legacy websocket protocol +# - "grpc" for the gRPC protocol +Protocol = "wsrpc" # Default # TransmitQueueMaxSize controls the size of the transmit queue. This is scoped # per OCR instance. If the queue is full, the transmitter will start dropping # the oldest messages in order to make space. # # This is useful if mercury server goes offline and the nop needs to buffer # transmissions. -TransmitQueueMaxSize = 10_000 # Default +TransmitQueueMaxSize = 100_000 # Default # TransmitTimeout controls how long the transmitter will wait for a response # when sending a message to the mercury server, before aborting and considering # the transmission to be failed. diff --git a/core/config/docs/docs_test.go b/core/config/docs/docs_test.go index 9fca08ee99b..bc171caf8c1 100644 --- a/core/config/docs/docs_test.go +++ b/core/config/docs/docs_test.go @@ -97,6 +97,11 @@ func TestDoc(t *testing.T) { docDefaults.Transactions.AutoPurge.Threshold = nil docDefaults.Transactions.AutoPurge.MinAttempts = nil + // TransactionManagerV2 configs are only set if the feature is enabled + docDefaults.Transactions.TransactionManagerV2.BlockTime = nil + docDefaults.Transactions.TransactionManagerV2.CustomURL = nil + docDefaults.Transactions.TransactionManagerV2.DualBroadcast = nil + // Fallback DA oracle is not set docDefaults.GasEstimator.DAOracle = evmcfg.DAOracle{} diff --git a/core/config/env/env.go b/core/config/env/env.go index c34cd7f4f5e..68b79c7575c 100644 --- a/core/config/env/env.go +++ b/core/config/env/env.go @@ -29,6 +29,7 @@ var ( MercuryPlugin = NewPlugin("mercury") SolanaPlugin = NewPlugin("solana") StarknetPlugin = NewPlugin("starknet") + TronPlugin = NewPlugin("tron") // PrometheusDiscoveryHostName is the externally accessible hostname // published by the node in the `/discovery` endpoint. Generally, it is expected to match // the public hostname of node. diff --git a/core/config/mercury_config.go b/core/config/mercury_config.go index 2e58ff0ee9d..9b98686974c 100644 --- a/core/config/mercury_config.go +++ b/core/config/mercury_config.go @@ -18,6 +18,7 @@ type MercuryTLS interface { } type MercuryTransmitter interface { + Protocol() string TransmitQueueMaxSize() uint32 TransmitTimeout() commonconfig.Duration TransmitConcurrency() uint32 diff --git a/core/config/mocks/telemetry_ingress.go b/core/config/mocks/telemetry_ingress.go index 3e85cf7da09..e77a559cd7c 100644 --- a/core/config/mocks/telemetry_ingress.go +++ b/core/config/mocks/telemetry_ingress.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -22,7 +22,7 @@ func (_m *TelemetryIngress) EXPECT() *TelemetryIngress_Expecter { return &TelemetryIngress_Expecter{mock: &_m.Mock} } -// BufferSize provides a mock function with given fields: +// BufferSize provides a mock function with no fields func (_m *TelemetryIngress) BufferSize() uint { ret := _m.Called() @@ -67,7 +67,7 @@ func (_c *TelemetryIngress_BufferSize_Call) RunAndReturn(run func() uint) *Telem return _c } -// Endpoints provides a mock function with given fields: +// Endpoints provides a mock function with no fields func (_m *TelemetryIngress) Endpoints() []config.TelemetryIngressEndpoint { ret := _m.Called() @@ -114,7 +114,7 @@ func (_c *TelemetryIngress_Endpoints_Call) RunAndReturn(run func() []config.Tele return _c } -// Logging provides a mock function with given fields: +// Logging provides a mock function with no fields func (_m *TelemetryIngress) Logging() bool { ret := _m.Called() @@ -159,7 +159,7 @@ func (_c *TelemetryIngress_Logging_Call) RunAndReturn(run func() bool) *Telemetr return _c } -// MaxBatchSize provides a mock function with given fields: +// MaxBatchSize provides a mock function with no fields func (_m *TelemetryIngress) MaxBatchSize() uint { ret := _m.Called() @@ -204,7 +204,7 @@ func (_c *TelemetryIngress_MaxBatchSize_Call) RunAndReturn(run func() uint) *Tel return _c } -// SendInterval provides a mock function with given fields: +// SendInterval provides a mock function with no fields func (_m *TelemetryIngress) SendInterval() time.Duration { ret := _m.Called() @@ -249,7 +249,7 @@ func (_c *TelemetryIngress_SendInterval_Call) RunAndReturn(run func() time.Durat return _c } -// SendTimeout provides a mock function with given fields: +// SendTimeout provides a mock function with no fields func (_m *TelemetryIngress) SendTimeout() time.Duration { ret := _m.Called() @@ -294,7 +294,7 @@ func (_c *TelemetryIngress_SendTimeout_Call) RunAndReturn(run func() time.Durati return _c } -// UniConn provides a mock function with given fields: +// UniConn provides a mock function with no fields func (_m *TelemetryIngress) UniConn() bool { ret := _m.Called() @@ -339,7 +339,7 @@ func (_c *TelemetryIngress_UniConn_Call) RunAndReturn(run func() bool) *Telemetr return _c } -// UseBatchSend provides a mock function with given fields: +// UseBatchSend provides a mock function with no fields func (_m *TelemetryIngress) UseBatchSend() bool { ret := _m.Called() diff --git a/core/config/mocks/telemetry_ingress_endpoint.go b/core/config/mocks/telemetry_ingress_endpoint.go index 18b3b8a046b..b8fa4dfe485 100644 --- a/core/config/mocks/telemetry_ingress_endpoint.go +++ b/core/config/mocks/telemetry_ingress_endpoint.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -21,7 +21,7 @@ func (_m *TelemetryIngressEndpoint) EXPECT() *TelemetryIngressEndpoint_Expecter return &TelemetryIngressEndpoint_Expecter{mock: &_m.Mock} } -// ChainID provides a mock function with given fields: +// ChainID provides a mock function with no fields func (_m *TelemetryIngressEndpoint) ChainID() string { ret := _m.Called() @@ -66,7 +66,7 @@ func (_c *TelemetryIngressEndpoint_ChainID_Call) RunAndReturn(run func() string) return _c } -// Network provides a mock function with given fields: +// Network provides a mock function with no fields func (_m *TelemetryIngressEndpoint) Network() string { ret := _m.Called() @@ -111,7 +111,7 @@ func (_c *TelemetryIngressEndpoint_Network_Call) RunAndReturn(run func() string) return _c } -// ServerPubKey provides a mock function with given fields: +// ServerPubKey provides a mock function with no fields func (_m *TelemetryIngressEndpoint) ServerPubKey() string { ret := _m.Called() @@ -156,7 +156,7 @@ func (_c *TelemetryIngressEndpoint_ServerPubKey_Call) RunAndReturn(run func() st return _c } -// URL provides a mock function with given fields: +// URL provides a mock function with no fields func (_m *TelemetryIngressEndpoint) URL() *url.URL { ret := _m.Called() diff --git a/core/config/toml/types.go b/core/config/toml/types.go index 620f7d96eee..b644d1b27db 100644 --- a/core/config/toml/types.go +++ b/core/config/toml/types.go @@ -1327,12 +1327,16 @@ func (m *MercuryTLS) ValidateConfig() (err error) { } type MercuryTransmitter struct { + Protocol *string TransmitQueueMaxSize *uint32 TransmitTimeout *commonconfig.Duration TransmitConcurrency *uint32 } func (m *MercuryTransmitter) setFrom(f *MercuryTransmitter) { + if v := f.Protocol; v != nil { + m.Protocol = v + } if v := f.TransmitQueueMaxSize; v != nil { m.TransmitQueueMaxSize = v } diff --git a/core/gethwrappers/abigen_test.go b/core/gethwrappers/abigen_test.go index 5874bf0b57c..21858f67ee4 100644 --- a/core/gethwrappers/abigen_test.go +++ b/core/gethwrappers/abigen_test.go @@ -8,7 +8,7 @@ import ( "github.com/ethereum/go-ethereum/ethclient/simulated" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/log_emitter" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" ) diff --git a/core/gethwrappers/ccip/generated/burn_from_mint_token_pool/burn_from_mint_token_pool.go b/core/gethwrappers/ccip/generated/burn_from_mint_token_pool/burn_from_mint_token_pool.go index 884dc9e52e5..e30fb318f9d 100644 --- a/core/gethwrappers/ccip/generated/burn_from_mint_token_pool/burn_from_mint_token_pool.go +++ b/core/gethwrappers/ccip/generated/burn_from_mint_token_pool/burn_from_mint_token_pool.go @@ -81,8 +81,8 @@ type TokenPoolChainUpdate struct { } var BurnFromMintTokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"localTokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MismatchedArrayLengths\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"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\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectors\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"outboundConfigs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"inboundConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setChainRateLimiterConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"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\"}]", - Bin: "0x6101006040523480156200001257600080fd5b5060405162004ed638038062004ed6833981016040819052620000359162000918565b8484848484336000816200005c57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008f576200008f8162000206565b50506001600160a01b0385161580620000af57506001600160a01b038116155b80620000c257506001600160a01b038216155b15620000e1576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b03808616608081905290831660c0526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa92505050801562000151575060408051601f3d908101601f191682019092526200014e9181019062000a3a565b60015b1562000192578060ff168560ff161462000190576040516332ad3e0760e11b815260ff8087166004830152821660248201526044015b60405180910390fd5b505b60ff841660a052600480546001600160a01b0319166001600160a01b038316179055825115801560e052620001dc57604080516000815260208101909152620001dc908462000280565b50620001fb935050506001600160a01b038716905030600019620003dd565b505050505062000b84565b336001600160a01b038216036200023057604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e051620002a1576040516335f4a7b360e01b815260040160405180910390fd5b60005b82518110156200032c576000838281518110620002c557620002c562000a58565b60209081029190910101519050620002df600282620004c3565b1562000322576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101620002a4565b5060005b8151811015620003d857600082828151811062000351576200035162000a58565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200037d5750620003cf565b6200038a600282620004e3565b15620003cd576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010162000330565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa1580156200042f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000455919062000a6e565b62000461919062000a9e565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152919250620004bd91869190620004fa16565b50505050565b6000620004da836001600160a01b038416620005cb565b90505b92915050565b6000620004da836001600160a01b038416620006cf565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65649082015260009062000549906001600160a01b03851690849062000721565b805190915015620003d857808060200190518101906200056a919062000ab4565b620003d85760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000187565b60008181526001830160205260408120548015620006c4576000620005f260018362000adf565b8554909150600090620006089060019062000adf565b9050808214620006745760008660000182815481106200062c576200062c62000a58565b906000526020600020015490508087600001848154811062000652576200065262000a58565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000688576200068862000af5565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620004dd565b6000915050620004dd565b60008181526001830160205260408120546200071857508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620004dd565b506000620004dd565b60606200073284846000856200073a565b949350505050565b6060824710156200079d5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000187565b600080866001600160a01b03168587604051620007bb919062000b31565b60006040518083038185875af1925050503d8060008114620007fa576040519150601f19603f3d011682016040523d82523d6000602084013e620007ff565b606091505b50909250905062000813878383876200081e565b979650505050505050565b60608315620008925782516000036200088a576001600160a01b0385163b6200088a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000187565b508162000732565b620007328383815115620008a95781518083602001fd5b8060405162461bcd60e51b815260040162000187919062000b4f565b6001600160a01b0381168114620008db57600080fd5b50565b805160ff81168114620008f057600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b8051620008f081620008c5565b600080600080600060a086880312156200093157600080fd5b85516200093e81620008c5565b945060206200094f878201620008de565b60408801519095506001600160401b03808211156200096d57600080fd5b818901915089601f8301126200098257600080fd5b815181811115620009975762000997620008f5565b8060051b604051601f19603f83011681018181108582111715620009bf57620009bf620008f5565b60405291825284820192508381018501918c831115620009de57600080fd5b938501935b8285101562000a0757620009f7856200090b565b84529385019392850192620009e3565b80985050505050505062000a1e606087016200090b565b915062000a2e608087016200090b565b90509295509295909350565b60006020828403121562000a4d57600080fd5b620004da82620008de565b634e487b7160e01b600052603260045260246000fd5b60006020828403121562000a8157600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115620004dd57620004dd62000a88565b60006020828403121562000ac757600080fd5b8151801515811462000ad857600080fd5b9392505050565b81810381811115620004dd57620004dd62000a88565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000b2857818101518382015260200162000b0e565b50506000910152565b6000825162000b4581846020870162000b0b565b9190910192915050565b602081526000825180602084015262000b7081604085016020870162000b0b565b601f01601f19169190910160400192915050565b60805160a05160c05160e0516142a162000c356000396000818161056d01528181611efa0152612aed01526000818161054701528181611a1701526122d00152600081816102eb01528181610d2101528181611bc001528181611c7a01528181611cae01528181611ce101528181611d4601528181611d9f0152611e41015260008181610252015281816102a70152818161072601528181612453015281816128e10152612cd801526142a16000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c80639a4575b911610104578063c0d78655116100a2578063dc0bd97111610071578063dc0bd97114610545578063e0351e131461056b578063e8a1da1714610591578063f2fde38b146105a457600080fd5b8063c0d78655146104f7578063c4bffe2b1461050a578063c75eea9c1461051f578063cf7401f31461053257600080fd5b8063acfecf91116100de578063acfecf9114610444578063af58d59f14610457578063b0f479a1146104c6578063b7946580146104e457600080fd5b80639a4575b9146103ef578063a42a7b8b1461040f578063a7cd63b71461042f57600080fd5b806354c8a4f31161017c5780637d54534e1161014b5780637d54534e146103985780638926f54f146103ab5780638da5cb5b146103be578063962d4020146103dc57600080fd5b806354c8a4f31461034a57806362ddd3c41461035f5780636d3d1a581461037257806379ba50971461039057600080fd5b8063240028e8116101b8578063240028e81461029757806324f65ee7146102e457806339077537146103155780634c5ef0ed1461033757600080fd5b806301ffc9a7146101df578063181f5a771461020757806321df0da714610250575b600080fd5b6101f26101ed3660046132f6565b6105b7565b60405190151581526020015b60405180910390f35b6102436040518060400160405280601b81526020017f4275726e46726f6d4d696e74546f6b656e506f6f6c20312e352e31000000000081525081565b6040516101fe919061339c565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101fe565b6101f26102a53660046133d1565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016101fe565b6103286103233660046133ee565b61069c565b604051905181526020016101fe565b6101f2610345366004613447565b61086b565b61035d610358366004613516565b6108b5565b005b61035d61036d366004613447565b610930565b60095473ffffffffffffffffffffffffffffffffffffffff16610272565b61035d6109cd565b61035d6103a63660046133d1565b610a9b565b6101f26103b9366004613582565b610b1c565b60015473ffffffffffffffffffffffffffffffffffffffff16610272565b61035d6103ea3660046135e2565b610b33565b6104026103fd36600461367c565b610c8d565b6040516101fe91906136b7565b61042261041d366004613582565b610d66565b6040516101fe919061370e565b610437610ed1565b6040516101fe9190613790565b61035d610452366004613447565b610ee2565b61046a610465366004613582565b610ffa565b6040516101fe919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610272565b6102436104f2366004613582565b6110cf565b61035d6105053660046133d1565b61117f565b61051261125a565b6040516101fe91906137ea565b61046a61052d366004613582565b611312565b61035d610540366004613972565b6113e4565b7f0000000000000000000000000000000000000000000000000000000000000000610272565b7f00000000000000000000000000000000000000000000000000000000000000006101f2565b61035d61059f366004613516565b611468565b61035d6105b23660046133d1565b61197a565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061064a57507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061069657507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b6040805160208101909152600081526106b48261198e565b600061070d60608401356107086106ce60c08701876139b7565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611bb292505050565b611c76565b905073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166340c10f1961075b60608601604087016133d1565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260248101849052604401600060405180830381600087803b1580156107c857600080fd5b505af11580156107dc573d6000803e3d6000fd5b506107f19250505060608401604085016133d1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f08360405161084f91815260200190565b60405180910390a3604080516020810190915290815292915050565b60006108ad8383604051610880929190613a1c565b604080519182900390912067ffffffffffffffff8716600090815260076020529190912060050190611e8a565b949350505050565b6108bd611ea5565b61092a84848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250611ef892505050565b50505050565b610938611ea5565b61094183610b1c565b610988576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6109c88383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506120ae92505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a1e576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610aa3611ea5565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b6000610696600567ffffffffffffffff8416611e8a565b60095473ffffffffffffffffffffffffffffffffffffffff163314801590610b73575060015473ffffffffffffffffffffffffffffffffffffffff163314155b15610bac576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161097f565b8483141580610bbb5750848114155b15610bf2576040517f568efce200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b85811015610c8457610c7c878783818110610c1257610c12613a2c565b9050602002016020810190610c279190613582565b868684818110610c3957610c39613a2c565b905060600201803603810190610c4f9190613a5b565b858585818110610c6157610c61613a2c565b905060600201803603810190610c779190613a5b565b6121a8565b600101610bf5565b50505050505050565b6040805180820190915260608082526020820152610caa82612292565b610cb7826060013561241e565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610d118460200160208101906104f29190613582565b8152602001610d5e6040805160ff7f000000000000000000000000000000000000000000000000000000000000000016602082015260609101604051602081830303815290604052905090565b905292915050565b67ffffffffffffffff8116600090815260076020526040812060609190610d8f906005016124c0565b90506000815167ffffffffffffffff811115610dad57610dad61382c565b604051908082528060200260200182016040528015610de057816020015b6060815260200190600190039081610dcb5790505b50905060005b8251811015610ec95760086000848381518110610e0557610e05613a2c565b602002602001015181526020019081526020016000208054610e2690613a77565b80601f0160208091040260200160405190810160405280929190818152602001828054610e5290613a77565b8015610e9f5780601f10610e7457610100808354040283529160200191610e9f565b820191906000526020600020905b815481529060010190602001808311610e8257829003601f168201915b5050505050828281518110610eb657610eb6613a2c565b6020908102919091010152600101610de6565b509392505050565b6060610edd60026124c0565b905090565b610eea611ea5565b610ef383610b1c565b610f35576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161097f565b610f758282604051610f48929190613a1c565b604080519182900390912067ffffffffffffffff86166000908152600760205291909120600501906124cd565b610fb1578282826040517f74f23c7c00000000000000000000000000000000000000000000000000000000815260040161097f93929190613b13565b8267ffffffffffffffff167f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d768383604051610fed929190613b37565b60405180910390a2505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff161515948201949094526003909101548084166060830152919091049091166080820152610696906124d9565b67ffffffffffffffff811660009081526007602052604090206004018054606091906110fa90613a77565b80601f016020809104026020016040519081016040528092919081815260200182805461112690613a77565b80156111735780601f1061114857610100808354040283529160200191611173565b820191906000526020600020905b81548152906001019060200180831161115657829003601f168201915b50505050509050919050565b611187611ea5565b73ffffffffffffffffffffffffffffffffffffffff81166111d4576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b6060600061126860056124c0565b90506000815167ffffffffffffffff8111156112865761128661382c565b6040519080825280602002602001820160405280156112af578160200160208202803683370190505b50905060005b825181101561130b578281815181106112d0576112d0613a2c565b60200260200101518282815181106112ea576112ea613a2c565b67ffffffffffffffff909216602092830291909101909101526001016112b5565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff161515948201949094526001909101548084166060830152919091049091166080820152610696906124d9565b60095473ffffffffffffffffffffffffffffffffffffffff163314801590611424575060015473ffffffffffffffffffffffffffffffffffffffff163314155b1561145d576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161097f565b6109c88383836121a8565b611470611ea5565b60005b8381101561165d57600085858381811061148f5761148f613a2c565b90506020020160208101906114a49190613582565b90506114bb600567ffffffffffffffff83166124cd565b6114fd576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161097f565b67ffffffffffffffff81166000908152600760205260408120611522906005016124c0565b905060005b815181101561158e5761158582828151811061154557611545613a2c565b6020026020010151600760008667ffffffffffffffff1667ffffffffffffffff1681526020019081526020016000206005016124cd90919063ffffffff16565b50600101611527565b5067ffffffffffffffff8216600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906115f76004830182613289565b600582016000818161160982826132c3565b505060405167ffffffffffffffff871681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169450602001925061164b915050565b60405180910390a15050600101611473565b5060005b8181101561197357600083838381811061167d5761167d613a2c565b905060200281019061168f9190613b4b565b61169890613c17565b90506116a98160600151600061258b565b6116b88160800151600061258b565b8060400151516000036116f7576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805161170f9060059067ffffffffffffffff166126c8565b6117545780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161097f565b805167ffffffffffffffff16600090815260076020908152604091829020825160a08082018552606080870180518601516fffffffffffffffffffffffffffffffff90811680865263ffffffff42168689018190528351511515878b0181905284518a0151841686890181905294518b0151841660809889018190528954740100000000000000000000000000000000000000009283027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7001000000000000000000000000000000008087027fffffffffffffffffffffffff000000000000000000000000000000000000000094851690981788178216929092178d5592810290971760018c01558c519889018d52898e0180518d01518716808b528a8e019590955280515115158a8f018190528151909d01518716988a01899052518d0151909516979098018790526002890180549a9091029990931617179094169590951790925590920290911760038201559082015160048201906118d79082613d8e565b5060005b82602001515181101561191b5761191383600001518460200151838151811061190657611906613a2c565b60200260200101516120ae565b6001016118db565b507f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c282600001518360400151846060015185608001516040516119619493929190613ea8565b60405180910390a15050600101611661565b5050505050565b611982611ea5565b61198b816126d4565b50565b6119a16102a560a08301608084016133d1565b611a00576119b560a08201608083016133d1565b6040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161097f565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb611a4c6040840160208501613582565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015611abd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ae19190613f41565b15611b18576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b30611b2b6040830160208401613582565b612798565b611b50611b436040830160208401613582565b61034560a08401846139b7565b611b9557611b6160a08201826139b7565b6040517f24eb47e500000000000000000000000000000000000000000000000000000000815260040161097f929190613b37565b61198b611ba86040830160208401613582565b82606001356128be565b60008151600003611be457507f0000000000000000000000000000000000000000000000000000000000000000919050565b8151602014611c2157816040517f953576f700000000000000000000000000000000000000000000000000000000815260040161097f919061339c565b600082806020019051810190611c379190613f5e565b905060ff81111561069657826040517f953576f700000000000000000000000000000000000000000000000000000000815260040161097f919061339c565b60007f000000000000000000000000000000000000000000000000000000000000000060ff168260ff1603611cac575081610696565b7f000000000000000000000000000000000000000000000000000000000000000060ff168260ff161115611d97576000611d067f000000000000000000000000000000000000000000000000000000000000000084613fa6565b9050604d8160ff161115611d7a576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f00000000000000000000000000000000000000000000000000000000000000001660248201526044810185905260640161097f565b611d8581600a6140df565b611d8f90856140ee565b915050610696565b6000611dc3837f0000000000000000000000000000000000000000000000000000000000000000613fa6565b9050604d8160ff161180611e0a5750611ddd81600a6140df565b611e07907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6140ee565b84115b15611e75576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f00000000000000000000000000000000000000000000000000000000000000001660248201526044810185905260640161097f565b611e8081600a6140df565b6108ad9085614129565b600081815260018301602052604081205415155b9392505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611ef6576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b7f0000000000000000000000000000000000000000000000000000000000000000611f4f576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015611fe5576000838281518110611f6f57611f6f613a2c565b60200260200101519050611f8d81600261290590919063ffffffff16565b15611fdc5760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101611f52565b5060005b81518110156109c857600082828151811061200657612006613a2c565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361204a57506120a6565b612055600282612927565b156120a45760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611fe9565b80516000036120e9576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160208083019190912067ffffffffffffffff841660009081526007909252604090912061211b90600501826126c8565b6121555782826040517f393b8ad200000000000000000000000000000000000000000000000000000000815260040161097f929190614140565b600081815260086020526040902061216d8382613d8e565b508267ffffffffffffffff167f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea83604051610fed919061339c565b6121b183610b1c565b6121f3576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161097f565b6121fe82600061258b565b67ffffffffffffffff831660009081526007602052604090206122219083612949565b61222c81600061258b565b67ffffffffffffffff831660009081526007602052604090206122529060020182612949565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b83838360405161228593929190614163565b60405180910390a1505050565b6122a56102a560a08301608084016133d1565b6122b9576119b560a08201608083016133d1565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb6123056040840160208501613582565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015612376573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061239a9190613f41565b156123d1576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6123e96123e460608301604084016133d1565b612aeb565b6124016123fc6040830160208401613582565b612b6a565b61198b6124146040830160208401613582565b8260600135612cb8565b6040517f79cc6790000000000000000000000000000000000000000000000000000000008152306004820152602481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906379cc679090604401600060405180830381600087803b1580156124ac57600080fd5b505af1158015611973573d6000803e3d6000fd5b60606000611e9e83612cfc565b6000611e9e8383612d57565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915261256782606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff164261254b91906141e6565b85608001516fffffffffffffffffffffffffffffffff16612e4a565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b8151156126565781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff161015806125e1575060408201516fffffffffffffffffffffffffffffffff16155b1561261a57816040517f8020d12400000000000000000000000000000000000000000000000000000000815260040161097f91906141f9565b8015612652576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60408201516fffffffffffffffffffffffffffffffff1615158061268f575060208201516fffffffffffffffffffffffffffffffff1615155b1561265257816040517fd68af9cc00000000000000000000000000000000000000000000000000000000815260040161097f91906141f9565b6000611e9e8383612e72565b3373ffffffffffffffffffffffffffffffffffffffff821603612723576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6127a181610b1c565b6127e3576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161097f565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa158015612862573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128869190613f41565b61198b576040517f728fe07b00000000000000000000000000000000000000000000000000000000815233600482015260240161097f565b67ffffffffffffffff8216600090815260076020526040902061265290600201827f0000000000000000000000000000000000000000000000000000000000000000612ec1565b6000611e9e8373ffffffffffffffffffffffffffffffffffffffff8416612d57565b6000611e9e8373ffffffffffffffffffffffffffffffffffffffff8416612e72565b815460009061297290700100000000000000000000000000000000900463ffffffff16426141e6565b90508015612a1457600183015483546129ba916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612e4a565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612a3a916fffffffffffffffffffffffffffffffff9081169116613244565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19906122859084906141f9565b7f00000000000000000000000000000000000000000000000000000000000000001561198b57612b1c60028261325a565b61198b576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015260240161097f565b612b7381610b1c565b612bb5576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161097f565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015612c2e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c529190614235565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461198b576040517f728fe07b00000000000000000000000000000000000000000000000000000000815233600482015260240161097f565b67ffffffffffffffff8216600090815260076020526040902061265290827f0000000000000000000000000000000000000000000000000000000000000000612ec1565b60608160000180548060200260200160405190810160405280929190818152602001828054801561117357602002820191906000526020600020905b815481526020019060010190808311612d385750505050509050919050565b60008181526001830160205260408120548015612e40576000612d7b6001836141e6565b8554909150600090612d8f906001906141e6565b9050808214612df4576000866000018281548110612daf57612daf613a2c565b9060005260206000200154905080876000018481548110612dd257612dd2613a2c565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612e0557612e05614252565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610696565b6000915050610696565b6000612e6985612e5a8486614129565b612e649087614281565b613244565b95945050505050565b6000818152600183016020526040812054612eb957508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610696565b506000610696565b825474010000000000000000000000000000000000000000900460ff161580612ee8575081155b15612ef257505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090612f3890700100000000000000000000000000000000900463ffffffff16426141e6565b90508015612ff85781831115612f7a576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154612fb49083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612e4a565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156130af5773ffffffffffffffffffffffffffffffffffffffff8416613057576040517ff94ebcd1000000000000000000000000000000000000000000000000000000008152600481018390526024810186905260440161097f565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff8516604482015260640161097f565b848310156131c25760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906130f390826141e6565b6130fd878a6141e6565b6131079190614281565b61311191906140ee565b905073ffffffffffffffffffffffffffffffffffffffff861661316a576040517f15279c08000000000000000000000000000000000000000000000000000000008152600481018290526024810186905260440161097f565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff8716604482015260640161097f565b6131cc85846141e6565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b60008183106132535781611e9e565b5090919050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515611e9e565b50805461329590613a77565b6000825580601f106132a5575050565b601f01602090049060005260206000209081019061198b91906132dd565b508054600082559060005260206000209081019061198b91905b5b808211156132f257600081556001016132de565b5090565b60006020828403121561330857600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611e9e57600080fd5b6000815180845260005b8181101561335e57602081850181015186830182015201613342565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611e9e6020830184613338565b73ffffffffffffffffffffffffffffffffffffffff8116811461198b57600080fd5b6000602082840312156133e357600080fd5b8135611e9e816133af565b60006020828403121561340057600080fd5b813567ffffffffffffffff81111561341757600080fd5b82016101008185031215611e9e57600080fd5b803567ffffffffffffffff8116811461344257600080fd5b919050565b60008060006040848603121561345c57600080fd5b6134658461342a565b9250602084013567ffffffffffffffff8082111561348257600080fd5b818601915086601f83011261349657600080fd5b8135818111156134a557600080fd5b8760208285010111156134b757600080fd5b6020830194508093505050509250925092565b60008083601f8401126134dc57600080fd5b50813567ffffffffffffffff8111156134f457600080fd5b6020830191508360208260051b850101111561350f57600080fd5b9250929050565b6000806000806040858703121561352c57600080fd5b843567ffffffffffffffff8082111561354457600080fd5b613550888389016134ca565b9096509450602087013591508082111561356957600080fd5b50613576878288016134ca565b95989497509550505050565b60006020828403121561359457600080fd5b611e9e8261342a565b60008083601f8401126135af57600080fd5b50813567ffffffffffffffff8111156135c757600080fd5b60208301915083602060608302850101111561350f57600080fd5b600080600080600080606087890312156135fb57600080fd5b863567ffffffffffffffff8082111561361357600080fd5b61361f8a838b016134ca565b9098509650602089013591508082111561363857600080fd5b6136448a838b0161359d565b9096509450604089013591508082111561365d57600080fd5b5061366a89828a0161359d565b979a9699509497509295939492505050565b60006020828403121561368e57600080fd5b813567ffffffffffffffff8111156136a557600080fd5b820160a08185031215611e9e57600080fd5b6020815260008251604060208401526136d36060840182613338565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612e698282613338565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015613783577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452613771858351613338565b94509285019290850190600101613737565b5092979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156137de57835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016137ac565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b818110156137de57835167ffffffffffffffff1683529284019291840191600101613806565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561387e5761387e61382c565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156138cb576138cb61382c565b604052919050565b801515811461198b57600080fd5b80356fffffffffffffffffffffffffffffffff8116811461344257600080fd5b60006060828403121561391357600080fd5b6040516060810181811067ffffffffffffffff821117156139365761393661382c565b6040529050808235613947816138d3565b8152613955602084016138e1565b6020820152613966604084016138e1565b60408201525092915050565b600080600060e0848603121561398757600080fd5b6139908461342a565b925061399f8560208601613901565b91506139ae8560808601613901565b90509250925092565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126139ec57600080fd5b83018035915067ffffffffffffffff821115613a0757600080fd5b60200191503681900382131561350f57600080fd5b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060608284031215613a6d57600080fd5b611e9e8383613901565b600181811c90821680613a8b57607f821691505b602082108103613ac4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b67ffffffffffffffff84168152604060208201526000612e69604083018486613aca565b6020815260006108ad602083018486613aca565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee1833603018112613b7f57600080fd5b9190910192915050565b600082601f830112613b9a57600080fd5b813567ffffffffffffffff811115613bb457613bb461382c565b613be560207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613884565b818152846020838601011115613bfa57600080fd5b816020850160208301376000918101602001919091529392505050565b60006101208236031215613c2a57600080fd5b613c3261385b565b613c3b8361342a565b815260208084013567ffffffffffffffff80821115613c5957600080fd5b9085019036601f830112613c6c57600080fd5b813581811115613c7e57613c7e61382c565b8060051b613c8d858201613884565b9182528381018501918581019036841115613ca757600080fd5b86860192505b83831015613ce357823585811115613cc55760008081fd5b613cd33689838a0101613b89565b8352509186019190860190613cad565b8087890152505050506040860135925080831115613d0057600080fd5b5050613d0e36828601613b89565b604083015250613d213660608501613901565b6060820152613d333660c08501613901565b608082015292915050565b601f8211156109c8576000816000526020600020601f850160051c81016020861015613d675750805b601f850160051c820191505b81811015613d8657828155600101613d73565b505050505050565b815167ffffffffffffffff811115613da857613da861382c565b613dbc81613db68454613a77565b84613d3e565b602080601f831160018114613e0f5760008415613dd95750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613d86565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613e5c57888601518255948401946001909101908401613e3d565b5085821015613e9857878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff87168352806020840152613ecc81840187613338565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff9081166060870152908701511660808501529150613f0a9050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612e69565b600060208284031215613f5357600080fd5b8151611e9e816138d3565b600060208284031215613f7057600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff828116828216039081111561069657610696613f77565b600181815b8085111561401857817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613ffe57613ffe613f77565b8085161561400b57918102915b93841c9390800290613fc4565b509250929050565b60008261402f57506001610696565b8161403c57506000610696565b8160018114614052576002811461405c57614078565b6001915050610696565b60ff84111561406d5761406d613f77565b50506001821b610696565b5060208310610133831016604e8410600b841016171561409b575081810a610696565b6140a58383613fbf565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156140d7576140d7613f77565b029392505050565b6000611e9e60ff841683614020565b600082614124577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808202811582820484141761069657610696613f77565b67ffffffffffffffff831681526040602082015260006108ad6040830184613338565b67ffffffffffffffff8416815260e081016141af60208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c08301526108ad565b8181038181111561069657610696613f77565b6060810161069682848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561424757600080fd5b8151611e9e816133af565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8082018082111561069657610696613f7756fea164736f6c6343000818000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"contractIBurnMintERC20\"},{\"name\":\"localTokenDecimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"allowlist\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"rmnProxy\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"router\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"acceptOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"addRemotePool\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyAllowListUpdates\",\"inputs\":[{\"name\":\"removes\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"adds\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyChainUpdates\",\"inputs\":[{\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"},{\"name\":\"chainsToAdd\",\"type\":\"tuple[]\",\"internalType\":\"structTokenPool.ChainUpdate[]\",\"components\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"},{\"name\":\"remoteTokenAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getAllowList\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getAllowListEnabled\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCurrentInboundRateLimiterState\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.TokenBucket\",\"components\":[{\"name\":\"tokens\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"lastUpdated\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCurrentOutboundRateLimiterState\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.TokenBucket\",\"components\":[{\"name\":\"tokens\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"lastUpdated\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRateLimitAdmin\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRemotePools\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRemoteToken\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRmnProxy\",\"inputs\":[],\"outputs\":[{\"name\":\"rmnProxy\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRouter\",\"inputs\":[],\"outputs\":[{\"name\":\"router\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getSupportedChains\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getToken\",\"inputs\":[],\"outputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"contractIERC20\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTokenDecimals\",\"inputs\":[],\"outputs\":[{\"name\":\"decimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isRemotePool\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isSupportedChain\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isSupportedToken\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"lockOrBurn\",\"inputs\":[{\"name\":\"lockOrBurnIn\",\"type\":\"tuple\",\"internalType\":\"structPool.LockOrBurnInV1\",\"components\":[{\"name\":\"receiver\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"originalSender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"localToken\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structPool.LockOrBurnOutV1\",\"components\":[{\"name\":\"destTokenAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"destPoolData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"releaseOrMint\",\"inputs\":[{\"name\":\"releaseOrMintIn\",\"type\":\"tuple\",\"internalType\":\"structPool.ReleaseOrMintInV1\",\"components\":[{\"name\":\"originalSender\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"receiver\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"localToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"sourcePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"sourcePoolData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"offchainTokenData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"components\":[{\"name\":\"destinationAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"removeRemotePool\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setChainRateLimiterConfig\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"outboundConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setChainRateLimiterConfigs\",\"inputs\":[{\"name\":\"remoteChainSelectors\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"},{\"name\":\"outboundConfigs\",\"type\":\"tuple[]\",\"internalType\":\"structRateLimiter.Config[]\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundConfigs\",\"type\":\"tuple[]\",\"internalType\":\"structRateLimiter.Config[]\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setRateLimitAdmin\",\"inputs\":[{\"name\":\"rateLimitAdmin\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setRouter\",\"inputs\":[{\"name\":\"newRouter\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"typeAndVersion\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"AllowListAdd\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"AllowListRemove\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Burned\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChainAdded\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"remoteToken\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"},{\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChainConfigured\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChainRemoved\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ConfigChanged\",\"inputs\":[{\"name\":\"config\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Locked\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Minted\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferRequested\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RateLimitAdminSet\",\"inputs\":[{\"name\":\"rateLimitAdmin\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Released\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RemotePoolAdded\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RemotePoolRemoved\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RouterUpdated\",\"inputs\":[{\"name\":\"oldRouter\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"newRouter\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TokensConsumed\",\"inputs\":[{\"name\":\"tokens\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AggregateValueMaxCapacityExceeded\",\"inputs\":[{\"name\":\"capacity\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"requested\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"AggregateValueRateLimitReached\",\"inputs\":[{\"name\":\"minWaitInSeconds\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"available\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"AllowListNotEnabled\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BucketOverfilled\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CallerIsNotARampOnRouter\",\"inputs\":[{\"name\":\"caller\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"CannotTransferToSelf\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ChainAlreadyExists\",\"inputs\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"ChainNotAllowed\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"CursedByRMN\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"DisabledNonZeroRateLimit\",\"inputs\":[{\"name\":\"config\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}]},{\"type\":\"error\",\"name\":\"InvalidDecimalArgs\",\"inputs\":[{\"name\":\"expected\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"actual\",\"type\":\"uint8\",\"internalType\":\"uint8\"}]},{\"type\":\"error\",\"name\":\"InvalidRateLimitRate\",\"inputs\":[{\"name\":\"rateLimiterConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}]},{\"type\":\"error\",\"name\":\"InvalidRemoteChainDecimals\",\"inputs\":[{\"name\":\"sourcePoolData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidRemotePoolForChain\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidSourcePoolAddress\",\"inputs\":[{\"name\":\"sourcePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidToken\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"MismatchedArrayLengths\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MustBeProposedOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NonExistentChain\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"OnlyCallableByOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OverflowDetected\",\"inputs\":[{\"name\":\"remoteDecimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"localDecimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"remoteAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"OwnerCannotBeZero\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PoolAlreadyAdded\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"RateLimitMustBeDisabled\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"SenderNotAllowed\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"TokenMaxCapacityExceeded\",\"inputs\":[{\"name\":\"capacity\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"requested\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"tokenAddress\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"TokenRateLimitReached\",\"inputs\":[{\"name\":\"minWaitInSeconds\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"available\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"tokenAddress\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"Unauthorized\",\"inputs\":[{\"name\":\"caller\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ZeroAddressNotAllowed\",\"inputs\":[]}]", + Bin: "0x610100806040523461035457614bb5803803809161001d82856105b2565b8339810160a0828203126103545781516001600160a01b03811692908390036103545761004c602082016105d5565b60408201516001600160401b0381116103545782019280601f85011215610354578351936001600160401b038511610359578460051b90602082019561009560405197886105b2565b865260208087019282010192831161035457602001905b82821061059a575050506100ce60806100c7606085016105e3565b93016105e3565b91331561058957600180546001600160a01b0319163317905584158015610578575b8015610567575b61055657608085905260c05260405163313ce56760e01b8152602081600481885afa6000918161051a575b506104ef575b5060a052600480546001600160a01b0319166001600160a01b03929092169190911790558051151560e08190526103d2575b50604051636eb1769f60e11b81523060048201819052602482015290602082604481845afa9182156103c657600092610392575b50600019820180921161037c57604051602081019263095ea7b360e01b84523060248301526044820152604481526101c76064826105b2565b6000806040948551936101da87866105b2565b602085527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65646020860152519082865af13d1561036f573d906001600160401b03821161035957845161024b94909261023c601f8201601f1916602001856105b2565b83523d6000602085013e610781565b8051806102d9575b8251614363908161085282396080518181816115fc015281816117e80152818161220e015281816123ea01528181612707015261277f015260a0518181816118a90152818161268e0152818161316801526131eb015260c051818181610bd50152818161169801526122a9015260e051818181610b65015281816116db01526120050152f35b81602091810103126103545760200151801590811503610354576102fe573880610253565b5162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608490fd5b600080fd5b634e487b7160e01b600052604160045260246000fd5b9161024b92606091610781565b634e487b7160e01b600052601160045260246000fd5b9091506020813d6020116103be575b816103ae602093836105b2565b810103126103545751903861018e565b3d91506103a1565b6040513d6000823e3d90fd5b60206040516103e182826105b2565b60008152600036813760e051156104de5760005b815181101561045c576001906001600160a01b0361041382856105f7565b51168461041f82610639565b61042c575b5050016103f5565b7f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf756691604051908152a13884610424565b505060005b82518110156104d5576001906001600160a01b0361047f82866105f7565b511680156104cf578361049182610721565b61049f575b50505b01610461565b7f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d891604051908152a13883610496565b50610499565b5050503861015a565b6335f4a7b360e01b60005260046000fd5b60ff1660ff82168181036105035750610128565b6332ad3e0760e11b60005260045260245260446000fd5b9091506020813d60201161054e575b81610536602093836105b2565b8101031261035457610547906105d5565b9038610122565b3d9150610529565b6342bcdf7f60e11b60005260046000fd5b506001600160a01b038116156100f7565b506001600160a01b038316156100f0565b639b15e16f60e01b60005260046000fd5b602080916105a7846105e3565b8152019101906100ac565b601f909101601f19168101906001600160401b0382119082101761035957604052565b519060ff8216820361035457565b51906001600160a01b038216820361035457565b805182101561060b5760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b805482101561060b5760005260206000200190600090565b600081815260036020526040902054801561071a57600019810181811161037c5760025460001981019190821161037c578181036106c9575b50505060025480156106b3576000190161068d816002610621565b8154906000199060031b1b19169055600255600052600360205260006040812055600190565b634e487b7160e01b600052603160045260246000fd5b6107026106da6106eb936002610621565b90549060031b1c9283926002610621565b819391549060031b91821b91600019901b19161790565b90556000526003602052604060002055388080610672565b5050600090565b8060005260036020526040600020541560001461077b5760025468010000000000000000811015610359576107626106eb8260018594016002556002610621565b9055600254906000526003602052604060002055600190565b50600090565b919290156107e35750815115610795575090565b3b1561079e5790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b8251909150156107f65750805190602001fd5b6040519062461bcd60e51b8252602060048301528181519182602483015260005b8381106108395750508160006044809484010152601f80199101168101030190fd5b6020828201810151604487840101528593500161081756fe608080604052600436101561001357600080fd5b600090813560e01c90816301ffc9a71461282257508063181f5a77146127a357806321df0da714612734578063240028e8146126b257806324f65ee71461265657806339077537146121685780634c5ef0ed1461214e57806354c8a4f314611fd157806362ddd3c414611f4d5780636d3d1a5814611efb57806379ba509714611e165780637d54534e14611d695780638926f54f14611d055780638da5cb5b14611cb3578063962d402014611b0f5780639a4575b914611554578063a42a7b8b146113cf578063a7cd63b714611303578063acfecf91146111df578063af58d59f14611178578063b0f479a114611126578063b7946580146110cf578063c0d7865514610fd7578063c4bffe2b14610e8e578063c75eea9c14610dc8578063cf7401f314610bf9578063dc0bd97114610b8a578063e0351e1314610b2f578063e8a1da171461025a5763f2fde38b1461016b57600080fd5b346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575773ffffffffffffffffffffffffffffffffffffffff6101b7612a50565b6101bf6132f5565b1633811461022f57807fffffffffffffffffffffffff000000000000000000000000000000000000000083541617825573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12788380a380f35b6004827fdad89dca000000000000000000000000000000000000000000000000000000008152fd5b80fd5b50346102575761026936612b3e565b939190926102756132f5565b82915b80831061099a575050508063ffffffff4216917ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee1843603015b85821015610996578160051b85013581811215610992578501906101208236031261099257604051956102e387612978565b823567ffffffffffffffff8116810361098d578752602083013567ffffffffffffffff81116109895783019536601f880112156109895786359661032688612d6a565b97610334604051998a6129b0565b8089526020808a019160051b830101903682116109855760208301905b828210610952575050505060208801968752604084013567ffffffffffffffff811161094e5761038490369086016130c2565b9860408901998a526103ae61039c3660608801612bfc565b9560608b0196875260c0369101612bfc565b9660808a019788526103c0865161376c565b6103ca885161376c565b8a515115610926576103e667ffffffffffffffff8b5116613fbf565b156108ef5767ffffffffffffffff8a5116815260076020526040812061052687516fffffffffffffffffffffffffffffffff604082015116906104e16fffffffffffffffffffffffffffffffff6020830151169151151583608060405161044c81612978565b858152602081018c905260408101849052606081018690520152855474ff000000000000000000000000000000000000000091151560a01b919091167fffffffffffffffffffffff0000000000000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff84161773ffffffff0000000000000000000000000000000060808b901b1617178555565b60809190911b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff91909116176001830155565b61064c89516fffffffffffffffffffffffffffffffff604082015116906106076fffffffffffffffffffffffffffffffff6020830151169151151583608060405161057081612978565b858152602081018c9052604081018490526060810186905201526002860180547fffffffffffffffffffffff000000000000000000000000000000000000000000166fffffffffffffffffffffffffffffffff85161773ffffffff0000000000000000000000000000000060808c901b161791151560a01b74ff000000000000000000000000000000000000000016919091179055565b60809190911b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff91909116176003830155565b60048c5191019080519067ffffffffffffffff82116108c25761066f8354612e62565b601f8111610887575b50602090601f83116001146107e8576106c692918591836107dd575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b90555b805b8951805182101561070157906106fb6001926106f4838f67ffffffffffffffff90511692612e4e565b5190613340565b016106cb565b5050975097987f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c2929593966107cf67ffffffffffffffff600197949c511692519351915161079b610766604051968796875261010060208801526101008701906129f1565b9360408601906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b60a08401906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b0390a10190939492916102b1565b015190503880610694565b83855281852091907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08416865b81811061086f5750908460019594939210610838575b505050811b0190556106c9565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c1916905538808061082b565b92936020600181928786015181550195019301610815565b6108b29084865260208620601f850160051c810191602086106108b8575b601f0160051c0190613069565b38610678565b90915081906108a5565b6024847f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b60249067ffffffffffffffff8b51167f1d5ad3c5000000000000000000000000000000000000000000000000000000008252600452fd5b807f8579befe0000000000000000000000000000000000000000000000000000000060049252fd5b8680fd5b813567ffffffffffffffff81116109815760209161097683928336918901016130c2565b815201910190610351565b8a80fd5b8880fd5b8580fd5b600080fd5b8380fd5b8280f35b9092919367ffffffffffffffff6109ba6109b5878588612dea565b612e29565b16956109c587613cf3565b15610b035786845260076020526109e160056040862001613afa565b94845b8651811015610a1a576001908987526007602052610a1360056040892001610a0c838b612e4e565b5190613e1e565b50016109e4565b5093945094909580855260076020526005604086208681558660018201558660028201558660038201558660048201610a538154612e62565b80610ac2575b5050500180549086815581610aa4575b5050907f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599166020600193604051908152a1019190949394610278565b865260208620908101905b81811015610a6957868155600101610aaf565b601f8111600114610ad85750555b863880610a59565b81835260208320610af391601f01861c810190600101613069565b8082528160208120915555610ad0565b602484887f1e670e4b000000000000000000000000000000000000000000000000000000008252600452fd5b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575760206040517f000000000000000000000000000000000000000000000000000000000000000015158152f35b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346102575760e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757610c31612a73565b9060607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36011261025757604051610c6881612994565b6024358015158103610dc45781526044356fffffffffffffffffffffffffffffffff81168103610dc45760208201526064356fffffffffffffffffffffffffffffffff81168103610dc457604082015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7c360112610dc05760405190610cef82612994565b608435801515810361099257825260a4356fffffffffffffffffffffffffffffffff8116810361099257602083015260c4356fffffffffffffffffffffffffffffffff8116810361099257604083015273ffffffffffffffffffffffffffffffffffffffff6009541633141580610d9e575b610d7257610d6f92936135aa565b80f35b6024837f8e4a23d600000000000000000000000000000000000000000000000000000000815233600452fd5b5073ffffffffffffffffffffffffffffffffffffffff60015416331415610d61565b5080fd5b8280fd5b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757610e31610e2c6040610e8a9367ffffffffffffffff610e15612a73565b610e1d612fb6565b50168152600760205220612fe1565b6136e7565b6040519182918291909160806fffffffffffffffffffffffffffffffff8160a084019582815116855263ffffffff6020820151166020860152604081015115156040860152826060820151166060860152015116910152565b0390f35b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757604051906005548083528260208101600584526020842092845b818110610fbe575050610eec925003836129b0565b8151610f10610efa82612d6a565b91610f0860405193846129b0565b808352612d6a565b917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0602083019301368437805b8451811015610f6f578067ffffffffffffffff610f5c60019388612e4e565b5116610f688286612e4e565b5201610f3d565b50925090604051928392602084019060208552518091526040840192915b818110610f9b575050500390f35b825167ffffffffffffffff16845285945060209384019390920191600101610f8d565b8454835260019485019487945060209093019201610ed7565b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575773ffffffffffffffffffffffffffffffffffffffff611024612a50565b61102c6132f5565b1680156110a75760407f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f16849160045490807fffffffffffffffffffffffff000000000000000000000000000000000000000083161760045573ffffffffffffffffffffffffffffffffffffffff8351921682526020820152a180f35b6004827f8579befe000000000000000000000000000000000000000000000000000000008152fd5b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757610e8a61111261110d612a73565b613047565b6040519182916020835260208301906129f1565b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602073ffffffffffffffffffffffffffffffffffffffff60045416604051908152f35b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757610e31610e2c60026040610e8a9467ffffffffffffffff6111c7612a73565b6111cf612fb6565b5016815260076020522001612fe1565b50346102575767ffffffffffffffff6111f736612a8a565b9290916112026132f5565b169161121b836000526006602052604060002054151590565b156112d757828452600760205261124a6005604086200161123d368486612c99565b6020815191012090613e1e565b1561128f57907f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d7691611289604051928392602084526020840191612f77565b0390a280f35b826112d3836040519384937f74f23c7c0000000000000000000000000000000000000000000000000000000085526004850152604060248501526044840191612f77565b0390fd5b602484847f1e670e4b000000000000000000000000000000000000000000000000000000008252600452fd5b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757604051600254808252602082018091600285526020852090855b8181106113b957505050826113629103836129b0565b604051928392602084019060208552518091526040840192915b81811061138a575050500390f35b825173ffffffffffffffffffffffffffffffffffffffff1684528594506020938401939092019160010161137c565b825484526020909301926001928301920161134c565b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575767ffffffffffffffff611410612a73565b168152600760205261142760056040832001613afa565b80517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061146c61145683612d6a565b9261146460405194856129b0565b808452612d6a565b01835b818110611543575050825b82518110156114c0578061149060019285612e4e565b51855260086020526114a460408620612eb5565b6114ae8285612e4e565b526114b98184612e4e565b500161147a565b81846040519182916020830160208452825180915260408401602060408360051b870101940192905b8282106114f857505050500390f35b91936020611533827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0600195979984950301865288516129f1565b96019201920185949391926114e9565b80606060208093860101520161146f565b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575760043567ffffffffffffffff8111610dc05760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8236030112610dc057606060206040516115d28161295c565b8281520152608481016115e481612cfe565b73ffffffffffffffffffffffffffffffffffffffff807f000000000000000000000000000000000000000000000000000000000000000016911603611ac55750602481019177ffffffffffffffff0000000000000000000000000000000061164b84612e29565b60801b16604051907f2cbc26bb000000000000000000000000000000000000000000000000000000008252600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa908115611955578291611a96575b50611a6e576116d960448301612cfe565b7f0000000000000000000000000000000000000000000000000000000000000000611a1b575b5067ffffffffffffffff61171284612e29565b1661172a816000526006602052604060002054151590565b156119ef57602073ffffffffffffffffffffffffffffffffffffffff60045416916024604051809481937fa8d87a3b00000000000000000000000000000000000000000000000000000000835260048301525afa801561195557829061198c575b73ffffffffffffffffffffffffffffffffffffffff91501633036119605767ffffffffffffffff60646117bd85612e29565b930135921681526007602052816118106040832073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001692839161406e565b803b15610dc0576040517f79cc6790000000000000000000000000000000000000000000000000000000008152306004820152602481018490529082908290604490829084905af1801561195557611940575b61190f61189f61110d86866040519081527f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df760203392a2612e29565b610e8a60405160ff7f0000000000000000000000000000000000000000000000000000000000000000166020820152602081526118dd6040826129b0565b604051926118ea8461295c565b83526020830190815260405193849360208552516040602086015260608501906129f1565b90517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160408501526129f1565b61194b8280926129b0565b6102575780611863565b6040513d84823e3d90fd5b807f728fe07b000000000000000000000000000000000000000000000000000000006024925233600452fd5b506020813d6020116119e7575b816119a6602093836129b0565b81010312610dc0575173ffffffffffffffffffffffffffffffffffffffff81168103610dc05773ffffffffffffffffffffffffffffffffffffffff9061178b565b3d9150611999565b602492507fa9902c7e000000000000000000000000000000000000000000000000000000008252600452fd5b73ffffffffffffffffffffffffffffffffffffffff16808252600360205260408220546116ff57602492507fd0d25976000000000000000000000000000000000000000000000000000000008252600452fd5b807f53ad11d80000000000000000000000000000000000000000000000000000000060049252fd5b611ab8915060203d602011611abe575b611ab081836129b0565b8101906130dd565b386116c8565b503d611aa6565b8273ffffffffffffffffffffffffffffffffffffffff611ae6602493612cfe565b7f961c9a4f00000000000000000000000000000000000000000000000000000000835216600452fd5b50346102575760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575760043567ffffffffffffffff8111610dc057611b5f903690600401612b0d565b60243567ffffffffffffffff811161099257611b7f903690600401612bae565b60449291923567ffffffffffffffff811161098957611ba2903690600401612bae565b91909273ffffffffffffffffffffffffffffffffffffffff6009541633141580611c91575b611c6557818114801590611c5b575b611c3357865b818110611be7578780f35b80611c2d611bfb6109b5600194868c612dea565b611c0683878b612e3e565b611c27611c1f611c17868b8d612e3e565b923690612bfc565b913690612bfc565b916135aa565b01611bdc565b6004877f568efce2000000000000000000000000000000000000000000000000000000008152fd5b5082811415611bd6565b6024877f8e4a23d600000000000000000000000000000000000000000000000000000000815233600452fd5b5073ffffffffffffffffffffffffffffffffffffffff60015416331415611bc7565b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610257576020611d5f67ffffffffffffffff611d4b612a73565b166000526006602052604060002054151590565b6040519015158152f35b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610257577f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d09174602073ffffffffffffffffffffffffffffffffffffffff611dd9612a50565b611de16132f5565b16807fffffffffffffffffffffffff00000000000000000000000000000000000000006009541617600955604051908152a180f35b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757805473ffffffffffffffffffffffffffffffffffffffff81163303611ed3577fffffffffffffffffffffffff000000000000000000000000000000000000000060015491338284161760015516825573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b6004827f02b543c6000000000000000000000000000000000000000000000000000000008152fd5b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602073ffffffffffffffffffffffffffffffffffffffff60095416604051908152f35b503461025757611f5c36612a8a565b611f68939291936132f5565b67ffffffffffffffff8216611f8a816000526006602052604060002054151590565b15611fa65750610d6f9293611fa0913691612c99565b90613340565b7f1e670e4b000000000000000000000000000000000000000000000000000000008452600452602483fd5b503461025757611ffb90612003611fe736612b3e565b9591611ff49391936132f5565b3691612d82565b933691612d82565b7f00000000000000000000000000000000000000000000000000000000000000001561212657815b835181101561209e578073ffffffffffffffffffffffffffffffffffffffff61205660019387612e4e565b511661206181613b5d565b61206d575b500161202b565b60207f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf756691604051908152a138612066565b5090805b8251811015612122578073ffffffffffffffffffffffffffffffffffffffff6120cd60019386612e4e565b5116801561211c576120de81613f5f565b6120eb575b505b016120a2565b60207f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d891604051908152a1846120e3565b506120e5565b5080f35b6004827f35f4a7b3000000000000000000000000000000000000000000000000000000008152fd5b5034610257576020611d5f61216236612a8a565b91612d1f565b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575760043567ffffffffffffffff8111610dc057806004016101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8336030112610dc457826040516121e881612911565b52608482016121f681612cfe565b73ffffffffffffffffffffffffffffffffffffffff807f00000000000000000000000000000000000000000000000000000000000000001691160361263557506024820177ffffffffffffffff0000000000000000000000000000000061225c82612e29565b60801b16604051907f2cbc26bb000000000000000000000000000000000000000000000000000000008252600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9081156125b8578591612616575b506125ee5767ffffffffffffffff6122f082612e29565b16612308816000526006602052604060002054151590565b156125c357602073ffffffffffffffffffffffffffffffffffffffff60045416916044604051809481937f83826b2b00000000000000000000000000000000000000000000000000000000835260048301523360248301525afa9081156125b8578591612599575b501561256d5761237f81612e29565b61239160a48501916121628386612c48565b15612526575061242e67ffffffffffffffff9261242861242361241c6123b8604496612e29565b936064890135978895168a526007602052612412600260408c200173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016998a9161406e565b60c4890190612c48565b3691612c99565b6130f5565b906131e8565b9201908361243b83612cfe565b823b15610dc0576040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91909116600482015260248101859052918290604490829084905af1801561251b57916020946124c99273ffffffffffffffffffffffffffffffffffffffff9461250b575b5050612cfe565b166040518281527f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f0843392a38060405161250281612911565b52604051908152f35b81612515916129b0565b386124c2565b6040513d86823e3d90fd5b6125309083612c48565b6112d36040519283927f24eb47e5000000000000000000000000000000000000000000000000000000008452602060048501526024840191612f77565b6024847f728fe07b00000000000000000000000000000000000000000000000000000000815233600452fd5b6125b2915060203d602011611abe57611ab081836129b0565b38612370565b6040513d87823e3d90fd5b7fa9902c7e000000000000000000000000000000000000000000000000000000008552600452602484fd5b6004847f53ad11d8000000000000000000000000000000000000000000000000000000008152fd5b61262f915060203d602011611abe57611ab081836129b0565b386122d9565b8373ffffffffffffffffffffffffffffffffffffffff611ae6602493612cfe565b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602060405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610257576020906126ed612a50565b905073ffffffffffffffffffffffffffffffffffffffff807f0000000000000000000000000000000000000000000000000000000000000000169116146040519015158152f35b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575750610e8a6040516127e46040826129b0565b601b81527f4275726e46726f6d4d696e74546f6b656e506f6f6c20312e352e31000000000060208201526040519182916020835260208301906129f1565b905034610dc05760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610dc0576004357fffffffff000000000000000000000000000000000000000000000000000000008116809103610dc457602092507faff2afbf0000000000000000000000000000000000000000000000000000000081149081156128e7575b81156128bd575b5015158152f35b7f01ffc9a700000000000000000000000000000000000000000000000000000000915014386128b6565b7f0e64dd2900000000000000000000000000000000000000000000000000000000811491506128af565b6020810190811067ffffffffffffffff82111761292d57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040810190811067ffffffffffffffff82111761292d57604052565b60a0810190811067ffffffffffffffff82111761292d57604052565b6060810190811067ffffffffffffffff82111761292d57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761292d57604052565b919082519283825260005b848110612a3b5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b806020809284010151828286010152016129fc565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361098d57565b6004359067ffffffffffffffff8216820361098d57565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82011261098d5760043567ffffffffffffffff8116810361098d579160243567ffffffffffffffff811161098d578260238201121561098d5780600401359267ffffffffffffffff841161098d576024848301011161098d576024019190565b9181601f8401121561098d5782359167ffffffffffffffff831161098d576020808501948460051b01011161098d57565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82011261098d5760043567ffffffffffffffff811161098d5781612b8791600401612b0d565b929092916024359067ffffffffffffffff821161098d57612baa91600401612b0d565b9091565b9181601f8401121561098d5782359167ffffffffffffffff831161098d576020808501946060850201011161098d57565b35906fffffffffffffffffffffffffffffffff8216820361098d57565b919082606091031261098d57604051612c1481612994565b8092803590811515820361098d576040612c439181938552612c3860208201612bdf565b602086015201612bdf565b910152565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561098d570180359067ffffffffffffffff821161098d5760200191813603831361098d57565b92919267ffffffffffffffff821161292d5760405191612ce1601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016602001846129b0565b82948184528183011161098d578281602093846000960137010152565b3573ffffffffffffffffffffffffffffffffffffffff8116810361098d5790565b612d67929167ffffffffffffffff612d4a921660005260076020526005604060002001923691612c99565b602081519101209060019160005201602052604060002054151590565b90565b67ffffffffffffffff811161292d5760051b60200190565b9291612d8d82612d6a565b93612d9b60405195866129b0565b602085848152019260051b810191821161098d57915b818310612dbd57505050565b823573ffffffffffffffffffffffffffffffffffffffff8116810361098d57815260209283019201612db1565b9190811015612dfa5760051b0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b3567ffffffffffffffff8116810361098d5790565b9190811015612dfa576060020190565b8051821015612dfa5760209160051b010190565b90600182811c92168015612eab575b6020831014612e7c57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f1691612e71565b9060405191826000825492612ec984612e62565b8084529360018116908115612f375750600114612ef0575b50612eee925003836129b0565b565b90506000929192526020600020906000915b818310612f1b575050906020612eee9282010138612ee1565b6020919350806001915483858901015201910190918492612f02565b60209350612eee9592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b82010138612ee1565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b60405190612fc382612978565b60006080838281528260208201528260408201528260608201520152565b90604051612fee81612978565b60806001829460ff81546fffffffffffffffffffffffffffffffff8116865263ffffffff81861c16602087015260a01c161515604085015201546fffffffffffffffffffffffffffffffff81166060840152811c910152565b67ffffffffffffffff166000526007602052612d676004604060002001612eb5565b818110613074575050565b60008155600101613069565b8181029291811591840414171561309357565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9080601f8301121561098d57816020612d6793359101612c99565b9081602091031261098d5751801515810361098d5790565b80518015613164576020036131265760208180518101031261098d5760208101519060ff8211613126575060ff1690565b6112d3906040519182917f953576f70000000000000000000000000000000000000000000000000000000083526020600484015260248301906129f1565b50507f000000000000000000000000000000000000000000000000000000000000000090565b9060ff8091169116039060ff821161309357565b60ff16604d811161309357600a0a90565b81156131b9570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b907f00000000000000000000000000000000000000000000000000000000000000009060ff82169060ff8116928284146132ee578284116132c4579061322d9161318a565b91604d60ff841611801561328b575b6132555750509061324f612d679261319e565b90613080565b9091507fa9cb113d0000000000000000000000000000000000000000000000000000000060005260045260245260445260646000fd5b506132958361319e565b80156131b9577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04841161323c565b6132cd9161318a565b91604d60ff841611613255575050906132e8612d679261319e565b906131af565b5050505090565b73ffffffffffffffffffffffffffffffffffffffff60015416330361331657565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b908051156135805767ffffffffffffffff81516020830120921691826000526007602052613375816005604060002001614019565b1561353c5760005260086020526040600020815167ffffffffffffffff811161292d576133a28254612e62565b601f811161350a575b506020601f8211600114613444579161341e827f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea959361343495600091613439575b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b90556040519182916020835260208301906129f1565b0390a2565b9050840151386133ed565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082169083600052806000209160005b8181106134f25750926134349492600192827f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea9896106134bb575b5050811b019055611112565b8501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c1916905538806134af565b9192602060018192868a015181550194019201613474565b61353690836000526020600020601f840160051c810191602085106108b857601f0160051c0190613069565b386133ab565b50906112d36040519283927f393b8ad200000000000000000000000000000000000000000000000000000000845260048401526040602484015260448301906129f1565b7f8579befe0000000000000000000000000000000000000000000000000000000060005260046000fd5b67ffffffffffffffff1660008181526006602052604090205490929190156136ac57916136a960e092613675856136017f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b9761376c565b8460005260076020526136188160406000206138c7565b6136218361376c565b84600052600760205261363b8360026040600020016138c7565b60405194855260208501906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b60808301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565ba1565b827f1e670e4b0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b9190820391821161309357565b6136ef612fb6565b506fffffffffffffffffffffffffffffffff6060820151166fffffffffffffffffffffffffffffffff808351169161374c602085019361374661373963ffffffff875116426136da565b8560808901511690613080565b90613f52565b8082101561376557505b16825263ffffffff4216905290565b9050613756565b805115613820576fffffffffffffffffffffffffffffffff6040820151166fffffffffffffffffffffffffffffffff602083015116811090811591613817575b506137b45750565b606490613815604051917f8020d12400000000000000000000000000000000000000000000000000000000835260048301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565bfd5b905015386137ac565b6fffffffffffffffffffffffffffffffff604082015116158015906138a8575b6138475750565b606490613815604051917fd68af9cc00000000000000000000000000000000000000000000000000000000835260048301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b506fffffffffffffffffffffffffffffffff6020820151161515613840565b7f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1991613a00606092805461390463ffffffff8260801c16426136da565b9081613a3f575b50506fffffffffffffffffffffffffffffffff6001816020860151169282815416808510600014613a3757508280855b16167fffffffffffffffffffffffffffffffff000000000000000000000000000000008254161781556139b48651151582907fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff74ff0000000000000000000000000000000000000000835492151560a01b169116179055565b60408601517fffffffffffffffffffffffffffffffff0000000000000000000000000000000060809190911b16939092166fffffffffffffffffffffffffffffffff1692909217910155565b6136a960405180926fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b83809161393b565b6fffffffffffffffffffffffffffffffff91613a74839283613a6d6001880154948286169560801c90613080565b9116613f52565b80821015613af357505b83547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff9290911692909216167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116174260801b73ffffffff0000000000000000000000000000000016178155388061390b565b9050613a7e565b906040519182815491828252602082019060005260206000209260005b818110613b2c575050612eee925003836129b0565b8454835260019485019487945060209093019201613b17565b8054821015612dfa5760005260206000200190600090565b6000818152600360205260409020548015613cec577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811161309357600254907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820191821161309357818103613c7d575b5050506002548015613c4e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01613c0b816002613b45565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600255600052600360205260006040812055600190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b613cd4613c8e613c9f936002613b45565b90549060031b1c9283926002613b45565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b90556000526003602052604060002055388080613bd2565b5050600090565b6000818152600660205260409020548015613cec577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811161309357600554907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820191821161309357818103613de4575b5050506005548015613c4e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01613da1816005613b45565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600555600052600660205260006040812055600190565b613e06613df5613c9f936005613b45565b90549060031b1c9283926005613b45565b90556000526006602052604060002055388080613d68565b9060018201918160005282602052604060002054801515600014613f49577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101818111613093578254907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820191821161309357818103613f12575b50505080548015613c4e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190613ed38282613b45565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b191690555560005260205260006040812055600190565b613f32613f22613c9f9386613b45565b90549060031b1c92839286613b45565b905560005283602052604060002055388080613e9b565b50505050600090565b9190820180921161309357565b80600052600360205260406000205415600014613fb9576002546801000000000000000081101561292d57613fa0613c9f8260018594016002556002613b45565b9055600254906000526003602052604060002055600190565b50600090565b80600052600660205260406000205415600014613fb9576005546801000000000000000081101561292d57614000613c9f8260018594016005556005613b45565b9055600554906000526006602052604060002055600190565b6000828152600182016020526040902054613cec578054906801000000000000000082101561292d5782614057613c9f846001809601855584613b45565b905580549260005201602052604060002055600190565b929192805460ff8160a01c1615801561434e575b614347576fffffffffffffffffffffffffffffffff811690600183019081546140c763ffffffff6fffffffffffffffffffffffffffffffff83169360801c16426136da565b90816142a9575b5050848110614227575083821061415657507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a939450906fffffffffffffffffffffffffffffffff8061412485602096956136da565b16167fffffffffffffffffffffffffffffffff00000000000000000000000000000000825416179055604051908152a1565b81945061416892505460801c926136da565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810190808211613093576141b66141bb9273ffffffffffffffffffffffffffffffffffffffff94613f52565b6131af565b92169182156141f7577fd0c8d23a0000000000000000000000000000000000000000000000000000000060005260045260245260445260646000fd5b7f15279c080000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b8473ffffffffffffffffffffffffffffffffffffffff8816918215614279577f1a76572a0000000000000000000000000000000000000000000000000000000060005260045260245260445260646000fd5b7ff94ebcd10000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b82859293951161431d576142c4926137469160801c90613080565b808310156143185750815b83547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff164260801b73ffffffff00000000000000000000000000000000161784559138806140ce565b6142cf565b7f9725942a0000000000000000000000000000000000000000000000000000000060005260046000fd5b5050509050565b50821561408256fea164736f6c634300081a000a", } var BurnFromMintTokenPoolABI = BurnFromMintTokenPoolMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/burn_mint_token_pool/burn_mint_token_pool.go b/core/gethwrappers/ccip/generated/burn_mint_token_pool/burn_mint_token_pool.go index d789ab8e3bf..d79eab1236b 100644 --- a/core/gethwrappers/ccip/generated/burn_mint_token_pool/burn_mint_token_pool.go +++ b/core/gethwrappers/ccip/generated/burn_mint_token_pool/burn_mint_token_pool.go @@ -81,8 +81,8 @@ type TokenPoolChainUpdate struct { } var BurnMintTokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"localTokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MismatchedArrayLengths\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"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\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectors\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"outboundConfigs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"inboundConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setChainRateLimiterConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"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\"}]", - Bin: "0x6101006040523480156200001257600080fd5b5060405162004a7c38038062004a7c8339810160408190526200003591620005a2565b8484848484336000816200005c57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008f576200008f81620001eb565b50506001600160a01b0385161580620000af57506001600160a01b038116155b80620000c257506001600160a01b038216155b15620000e1576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b03808616608081905290831660c0526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa92505050801562000151575060408051601f3d908101601f191682019092526200014e91810190620006c4565b60015b1562000191578060ff168560ff16146200018f576040516332ad3e0760e11b815260ff80871660048301528216602482015260440160405180910390fd5b505b60ff841660a052600480546001600160a01b0319166001600160a01b038316179055825115801560e052620001db57604080516000815260208101909152620001db908462000265565b5050505050505050505062000730565b336001600160a01b038216036200021557604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e05162000286576040516335f4a7b360e01b815260040160405180910390fd5b60005b825181101562000311576000838281518110620002aa57620002aa620006e2565b60209081029190910101519050620002c4600282620003c2565b1562000307576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b5060010162000289565b5060005b8151811015620003bd576000828281518110620003365762000336620006e2565b6020026020010151905060006001600160a01b0316816001600160a01b031603620003625750620003b4565b6200036f600282620003e2565b15620003b2576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010162000315565b505050565b6000620003d9836001600160a01b038416620003f9565b90505b92915050565b6000620003d9836001600160a01b038416620004fd565b60008181526001830160205260408120548015620004f257600062000420600183620006f8565b85549091506000906200043690600190620006f8565b9050808214620004a25760008660000182815481106200045a576200045a620006e2565b9060005260206000200154905080876000018481548110620004805762000480620006e2565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620004b657620004b66200071a565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620003dc565b6000915050620003dc565b60008181526001830160205260408120546200054657508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620003dc565b506000620003dc565b6001600160a01b03811681146200056557600080fd5b50565b805160ff811681146200057a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b80516200057a816200054f565b600080600080600060a08688031215620005bb57600080fd5b8551620005c8816200054f565b94506020620005d987820162000568565b60408801519095506001600160401b0380821115620005f757600080fd5b818901915089601f8301126200060c57600080fd5b8151818111156200062157620006216200057f565b8060051b604051601f19603f830116810181811085821117156200064957620006496200057f565b60405291825284820192508381018501918c8311156200066857600080fd5b938501935b828510156200069157620006818562000595565b845293850193928501926200066d565b809850505050505050620006a86060870162000595565b9150620006b86080870162000595565b90509295509295909350565b600060208284031215620006d757600080fd5b620003d98262000568565b634e487b7160e01b600052603260045260246000fd5b81810381811115620003dc57634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c05160e05161429b620007e16000396000818161056d01528181611efa0152612ae701526000818161054701528181611a1701526122d00152600081816102eb01528181610d2101528181611bc001528181611c7a01528181611cae01528181611ce101528181611d4601528181611d9f0152611e41015260008181610252015281816102a7015281816107260152818161244d015281816128db0152612cd2015261429b6000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c80639a4575b911610104578063c0d78655116100a2578063dc0bd97111610071578063dc0bd97114610545578063e0351e131461056b578063e8a1da1714610591578063f2fde38b146105a457600080fd5b8063c0d78655146104f7578063c4bffe2b1461050a578063c75eea9c1461051f578063cf7401f31461053257600080fd5b8063acfecf91116100de578063acfecf9114610444578063af58d59f14610457578063b0f479a1146104c6578063b7946580146104e457600080fd5b80639a4575b9146103ef578063a42a7b8b1461040f578063a7cd63b71461042f57600080fd5b806354c8a4f31161017c5780637d54534e1161014b5780637d54534e146103985780638926f54f146103ab5780638da5cb5b146103be578063962d4020146103dc57600080fd5b806354c8a4f31461034a57806362ddd3c41461035f5780636d3d1a581461037257806379ba50971461039057600080fd5b8063240028e8116101b8578063240028e81461029757806324f65ee7146102e457806339077537146103155780634c5ef0ed1461033757600080fd5b806301ffc9a7146101df578063181f5a771461020757806321df0da714610250575b600080fd5b6101f26101ed3660046132f0565b6105b7565b60405190151581526020015b60405180910390f35b6102436040518060400160405280601781526020017f4275726e4d696e74546f6b656e506f6f6c20312e352e3100000000000000000081525081565b6040516101fe9190613396565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101fe565b6101f26102a53660046133cb565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016101fe565b6103286103233660046133e8565b61069c565b604051905181526020016101fe565b6101f2610345366004613441565b61086b565b61035d610358366004613510565b6108b5565b005b61035d61036d366004613441565b610930565b60095473ffffffffffffffffffffffffffffffffffffffff16610272565b61035d6109cd565b61035d6103a63660046133cb565b610a9b565b6101f26103b936600461357c565b610b1c565b60015473ffffffffffffffffffffffffffffffffffffffff16610272565b61035d6103ea3660046135dc565b610b33565b6104026103fd366004613676565b610c8d565b6040516101fe91906136b1565b61042261041d36600461357c565b610d66565b6040516101fe9190613708565b610437610ed1565b6040516101fe919061378a565b61035d610452366004613441565b610ee2565b61046a61046536600461357c565b610ffa565b6040516101fe919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610272565b6102436104f236600461357c565b6110cf565b61035d6105053660046133cb565b61117f565b61051261125a565b6040516101fe91906137e4565b61046a61052d36600461357c565b611312565b61035d61054036600461396c565b6113e4565b7f0000000000000000000000000000000000000000000000000000000000000000610272565b7f00000000000000000000000000000000000000000000000000000000000000006101f2565b61035d61059f366004613510565b611468565b61035d6105b23660046133cb565b61197a565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061064a57507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061069657507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b6040805160208101909152600081526106b48261198e565b600061070d60608401356107086106ce60c08701876139b1565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611bb292505050565b611c76565b905073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166340c10f1961075b60608601604087016133cb565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260248101849052604401600060405180830381600087803b1580156107c857600080fd5b505af11580156107dc573d6000803e3d6000fd5b506107f19250505060608401604085016133cb565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f08360405161084f91815260200190565b60405180910390a3604080516020810190915290815292915050565b60006108ad8383604051610880929190613a16565b604080519182900390912067ffffffffffffffff8716600090815260076020529190912060050190611e8a565b949350505050565b6108bd611ea5565b61092a84848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250611ef892505050565b50505050565b610938611ea5565b61094183610b1c565b610988576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6109c88383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506120ae92505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a1e576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610aa3611ea5565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b6000610696600567ffffffffffffffff8416611e8a565b60095473ffffffffffffffffffffffffffffffffffffffff163314801590610b73575060015473ffffffffffffffffffffffffffffffffffffffff163314155b15610bac576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161097f565b8483141580610bbb5750848114155b15610bf2576040517f568efce200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b85811015610c8457610c7c878783818110610c1257610c12613a26565b9050602002016020810190610c27919061357c565b868684818110610c3957610c39613a26565b905060600201803603810190610c4f9190613a55565b858585818110610c6157610c61613a26565b905060600201803603810190610c779190613a55565b6121a8565b600101610bf5565b50505050505050565b6040805180820190915260608082526020820152610caa82612292565b610cb7826060013561241e565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610d118460200160208101906104f2919061357c565b8152602001610d5e6040805160ff7f000000000000000000000000000000000000000000000000000000000000000016602082015260609101604051602081830303815290604052905090565b905292915050565b67ffffffffffffffff8116600090815260076020526040812060609190610d8f906005016124ba565b90506000815167ffffffffffffffff811115610dad57610dad613826565b604051908082528060200260200182016040528015610de057816020015b6060815260200190600190039081610dcb5790505b50905060005b8251811015610ec95760086000848381518110610e0557610e05613a26565b602002602001015181526020019081526020016000208054610e2690613a71565b80601f0160208091040260200160405190810160405280929190818152602001828054610e5290613a71565b8015610e9f5780601f10610e7457610100808354040283529160200191610e9f565b820191906000526020600020905b815481529060010190602001808311610e8257829003601f168201915b5050505050828281518110610eb657610eb6613a26565b6020908102919091010152600101610de6565b509392505050565b6060610edd60026124ba565b905090565b610eea611ea5565b610ef383610b1c565b610f35576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161097f565b610f758282604051610f48929190613a16565b604080519182900390912067ffffffffffffffff86166000908152600760205291909120600501906124c7565b610fb1578282826040517f74f23c7c00000000000000000000000000000000000000000000000000000000815260040161097f93929190613b0d565b8267ffffffffffffffff167f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d768383604051610fed929190613b31565b60405180910390a2505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff161515948201949094526003909101548084166060830152919091049091166080820152610696906124d3565b67ffffffffffffffff811660009081526007602052604090206004018054606091906110fa90613a71565b80601f016020809104026020016040519081016040528092919081815260200182805461112690613a71565b80156111735780601f1061114857610100808354040283529160200191611173565b820191906000526020600020905b81548152906001019060200180831161115657829003601f168201915b50505050509050919050565b611187611ea5565b73ffffffffffffffffffffffffffffffffffffffff81166111d4576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b6060600061126860056124ba565b90506000815167ffffffffffffffff81111561128657611286613826565b6040519080825280602002602001820160405280156112af578160200160208202803683370190505b50905060005b825181101561130b578281815181106112d0576112d0613a26565b60200260200101518282815181106112ea576112ea613a26565b67ffffffffffffffff909216602092830291909101909101526001016112b5565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff161515948201949094526001909101548084166060830152919091049091166080820152610696906124d3565b60095473ffffffffffffffffffffffffffffffffffffffff163314801590611424575060015473ffffffffffffffffffffffffffffffffffffffff163314155b1561145d576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161097f565b6109c88383836121a8565b611470611ea5565b60005b8381101561165d57600085858381811061148f5761148f613a26565b90506020020160208101906114a4919061357c565b90506114bb600567ffffffffffffffff83166124c7565b6114fd576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161097f565b67ffffffffffffffff81166000908152600760205260408120611522906005016124ba565b905060005b815181101561158e5761158582828151811061154557611545613a26565b6020026020010151600760008667ffffffffffffffff1667ffffffffffffffff1681526020019081526020016000206005016124c790919063ffffffff16565b50600101611527565b5067ffffffffffffffff8216600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906115f76004830182613283565b600582016000818161160982826132bd565b505060405167ffffffffffffffff871681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169450602001925061164b915050565b60405180910390a15050600101611473565b5060005b8181101561197357600083838381811061167d5761167d613a26565b905060200281019061168f9190613b45565b61169890613c11565b90506116a981606001516000612585565b6116b881608001516000612585565b8060400151516000036116f7576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805161170f9060059067ffffffffffffffff166126c2565b6117545780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161097f565b805167ffffffffffffffff16600090815260076020908152604091829020825160a08082018552606080870180518601516fffffffffffffffffffffffffffffffff90811680865263ffffffff42168689018190528351511515878b0181905284518a0151841686890181905294518b0151841660809889018190528954740100000000000000000000000000000000000000009283027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7001000000000000000000000000000000008087027fffffffffffffffffffffffff000000000000000000000000000000000000000094851690981788178216929092178d5592810290971760018c01558c519889018d52898e0180518d01518716808b528a8e019590955280515115158a8f018190528151909d01518716988a01899052518d0151909516979098018790526002890180549a9091029990931617179094169590951790925590920290911760038201559082015160048201906118d79082613d88565b5060005b82602001515181101561191b5761191383600001518460200151838151811061190657611906613a26565b60200260200101516120ae565b6001016118db565b507f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c282600001518360400151846060015185608001516040516119619493929190613ea2565b60405180910390a15050600101611661565b5050505050565b611982611ea5565b61198b816126ce565b50565b6119a16102a560a08301608084016133cb565b611a00576119b560a08201608083016133cb565b6040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161097f565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb611a4c604084016020850161357c565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015611abd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ae19190613f3b565b15611b18576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b30611b2b604083016020840161357c565b612792565b611b50611b43604083016020840161357c565b61034560a08401846139b1565b611b9557611b6160a08201826139b1565b6040517f24eb47e500000000000000000000000000000000000000000000000000000000815260040161097f929190613b31565b61198b611ba8604083016020840161357c565b82606001356128b8565b60008151600003611be457507f0000000000000000000000000000000000000000000000000000000000000000919050565b8151602014611c2157816040517f953576f700000000000000000000000000000000000000000000000000000000815260040161097f9190613396565b600082806020019051810190611c379190613f58565b905060ff81111561069657826040517f953576f700000000000000000000000000000000000000000000000000000000815260040161097f9190613396565b60007f000000000000000000000000000000000000000000000000000000000000000060ff168260ff1603611cac575081610696565b7f000000000000000000000000000000000000000000000000000000000000000060ff168260ff161115611d97576000611d067f000000000000000000000000000000000000000000000000000000000000000084613fa0565b9050604d8160ff161115611d7a576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f00000000000000000000000000000000000000000000000000000000000000001660248201526044810185905260640161097f565b611d8581600a6140d9565b611d8f90856140e8565b915050610696565b6000611dc3837f0000000000000000000000000000000000000000000000000000000000000000613fa0565b9050604d8160ff161180611e0a5750611ddd81600a6140d9565b611e07907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6140e8565b84115b15611e75576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f00000000000000000000000000000000000000000000000000000000000000001660248201526044810185905260640161097f565b611e8081600a6140d9565b6108ad9085614123565b600081815260018301602052604081205415155b9392505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611ef6576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b7f0000000000000000000000000000000000000000000000000000000000000000611f4f576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015611fe5576000838281518110611f6f57611f6f613a26565b60200260200101519050611f8d8160026128ff90919063ffffffff16565b15611fdc5760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101611f52565b5060005b81518110156109c857600082828151811061200657612006613a26565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361204a57506120a6565b612055600282612921565b156120a45760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611fe9565b80516000036120e9576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160208083019190912067ffffffffffffffff841660009081526007909252604090912061211b90600501826126c2565b6121555782826040517f393b8ad200000000000000000000000000000000000000000000000000000000815260040161097f92919061413a565b600081815260086020526040902061216d8382613d88565b508267ffffffffffffffff167f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea83604051610fed9190613396565b6121b183610b1c565b6121f3576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161097f565b6121fe826000612585565b67ffffffffffffffff831660009081526007602052604090206122219083612943565b61222c816000612585565b67ffffffffffffffff831660009081526007602052604090206122529060020182612943565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b8383836040516122859392919061415d565b60405180910390a1505050565b6122a56102a560a08301608084016133cb565b6122b9576119b560a08201608083016133cb565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb612305604084016020850161357c565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015612376573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061239a9190613f3b565b156123d1576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6123e96123e460608301604084016133cb565b612ae5565b6124016123fc604083016020840161357c565b612b64565b61198b612414604083016020840161357c565b8260600135612cb2565b6040517f42966c68000000000000000000000000000000000000000000000000000000008152600481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906342966c6890602401600060405180830381600087803b1580156124a657600080fd5b505af1158015611973573d6000803e3d6000fd5b60606000611e9e83612cf6565b6000611e9e8383612d51565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915261256182606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff164261254591906141e0565b85608001516fffffffffffffffffffffffffffffffff16612e44565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b8151156126505781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff161015806125db575060408201516fffffffffffffffffffffffffffffffff16155b1561261457816040517f8020d12400000000000000000000000000000000000000000000000000000000815260040161097f91906141f3565b801561264c576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60408201516fffffffffffffffffffffffffffffffff16151580612689575060208201516fffffffffffffffffffffffffffffffff1615155b1561264c57816040517fd68af9cc00000000000000000000000000000000000000000000000000000000815260040161097f91906141f3565b6000611e9e8383612e6c565b3373ffffffffffffffffffffffffffffffffffffffff82160361271d576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61279b81610b1c565b6127dd576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161097f565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa15801561285c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128809190613f3b565b61198b576040517f728fe07b00000000000000000000000000000000000000000000000000000000815233600482015260240161097f565b67ffffffffffffffff8216600090815260076020526040902061264c90600201827f0000000000000000000000000000000000000000000000000000000000000000612ebb565b6000611e9e8373ffffffffffffffffffffffffffffffffffffffff8416612d51565b6000611e9e8373ffffffffffffffffffffffffffffffffffffffff8416612e6c565b815460009061296c90700100000000000000000000000000000000900463ffffffff16426141e0565b90508015612a0e57600183015483546129b4916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612e44565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612a34916fffffffffffffffffffffffffffffffff908116911661323e565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19906122859084906141f3565b7f00000000000000000000000000000000000000000000000000000000000000001561198b57612b16600282613254565b61198b576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015260240161097f565b612b6d81610b1c565b612baf576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161097f565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015612c28573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c4c919061422f565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461198b576040517f728fe07b00000000000000000000000000000000000000000000000000000000815233600482015260240161097f565b67ffffffffffffffff8216600090815260076020526040902061264c90827f0000000000000000000000000000000000000000000000000000000000000000612ebb565b60608160000180548060200260200160405190810160405280929190818152602001828054801561117357602002820191906000526020600020905b815481526020019060010190808311612d325750505050509050919050565b60008181526001830160205260408120548015612e3a576000612d756001836141e0565b8554909150600090612d89906001906141e0565b9050808214612dee576000866000018281548110612da957612da9613a26565b9060005260206000200154905080876000018481548110612dcc57612dcc613a26565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612dff57612dff61424c565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610696565b6000915050610696565b6000612e6385612e548486614123565b612e5e908761427b565b61323e565b95945050505050565b6000818152600183016020526040812054612eb357508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610696565b506000610696565b825474010000000000000000000000000000000000000000900460ff161580612ee2575081155b15612eec57505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090612f3290700100000000000000000000000000000000900463ffffffff16426141e0565b90508015612ff25781831115612f74576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154612fae9083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612e44565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156130a95773ffffffffffffffffffffffffffffffffffffffff8416613051576040517ff94ebcd1000000000000000000000000000000000000000000000000000000008152600481018390526024810186905260440161097f565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff8516604482015260640161097f565b848310156131bc5760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906130ed90826141e0565b6130f7878a6141e0565b613101919061427b565b61310b91906140e8565b905073ffffffffffffffffffffffffffffffffffffffff8616613164576040517f15279c08000000000000000000000000000000000000000000000000000000008152600481018290526024810186905260440161097f565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff8716604482015260640161097f565b6131c685846141e0565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b600081831061324d5781611e9e565b5090919050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515611e9e565b50805461328f90613a71565b6000825580601f1061329f575050565b601f01602090049060005260206000209081019061198b91906132d7565b508054600082559060005260206000209081019061198b91905b5b808211156132ec57600081556001016132d8565b5090565b60006020828403121561330257600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611e9e57600080fd5b6000815180845260005b818110156133585760208185018101518683018201520161333c565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611e9e6020830184613332565b73ffffffffffffffffffffffffffffffffffffffff8116811461198b57600080fd5b6000602082840312156133dd57600080fd5b8135611e9e816133a9565b6000602082840312156133fa57600080fd5b813567ffffffffffffffff81111561341157600080fd5b82016101008185031215611e9e57600080fd5b803567ffffffffffffffff8116811461343c57600080fd5b919050565b60008060006040848603121561345657600080fd5b61345f84613424565b9250602084013567ffffffffffffffff8082111561347c57600080fd5b818601915086601f83011261349057600080fd5b81358181111561349f57600080fd5b8760208285010111156134b157600080fd5b6020830194508093505050509250925092565b60008083601f8401126134d657600080fd5b50813567ffffffffffffffff8111156134ee57600080fd5b6020830191508360208260051b850101111561350957600080fd5b9250929050565b6000806000806040858703121561352657600080fd5b843567ffffffffffffffff8082111561353e57600080fd5b61354a888389016134c4565b9096509450602087013591508082111561356357600080fd5b50613570878288016134c4565b95989497509550505050565b60006020828403121561358e57600080fd5b611e9e82613424565b60008083601f8401126135a957600080fd5b50813567ffffffffffffffff8111156135c157600080fd5b60208301915083602060608302850101111561350957600080fd5b600080600080600080606087890312156135f557600080fd5b863567ffffffffffffffff8082111561360d57600080fd5b6136198a838b016134c4565b9098509650602089013591508082111561363257600080fd5b61363e8a838b01613597565b9096509450604089013591508082111561365757600080fd5b5061366489828a01613597565b979a9699509497509295939492505050565b60006020828403121561368857600080fd5b813567ffffffffffffffff81111561369f57600080fd5b820160a08185031215611e9e57600080fd5b6020815260008251604060208401526136cd6060840182613332565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612e638282613332565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561377d577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261376b858351613332565b94509285019290850190600101613731565b5092979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156137d857835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016137a6565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b818110156137d857835167ffffffffffffffff1683529284019291840191600101613800565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561387857613878613826565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156138c5576138c5613826565b604052919050565b801515811461198b57600080fd5b80356fffffffffffffffffffffffffffffffff8116811461343c57600080fd5b60006060828403121561390d57600080fd5b6040516060810181811067ffffffffffffffff8211171561393057613930613826565b6040529050808235613941816138cd565b815261394f602084016138db565b6020820152613960604084016138db565b60408201525092915050565b600080600060e0848603121561398157600080fd5b61398a84613424565b925061399985602086016138fb565b91506139a885608086016138fb565b90509250925092565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126139e657600080fd5b83018035915067ffffffffffffffff821115613a0157600080fd5b60200191503681900382131561350957600080fd5b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060608284031215613a6757600080fd5b611e9e83836138fb565b600181811c90821680613a8557607f821691505b602082108103613abe577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b67ffffffffffffffff84168152604060208201526000612e63604083018486613ac4565b6020815260006108ad602083018486613ac4565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee1833603018112613b7957600080fd5b9190910192915050565b600082601f830112613b9457600080fd5b813567ffffffffffffffff811115613bae57613bae613826565b613bdf60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161387e565b818152846020838601011115613bf457600080fd5b816020850160208301376000918101602001919091529392505050565b60006101208236031215613c2457600080fd5b613c2c613855565b613c3583613424565b815260208084013567ffffffffffffffff80821115613c5357600080fd5b9085019036601f830112613c6657600080fd5b813581811115613c7857613c78613826565b8060051b613c8785820161387e565b9182528381018501918581019036841115613ca157600080fd5b86860192505b83831015613cdd57823585811115613cbf5760008081fd5b613ccd3689838a0101613b83565b8352509186019190860190613ca7565b8087890152505050506040860135925080831115613cfa57600080fd5b5050613d0836828601613b83565b604083015250613d1b36606085016138fb565b6060820152613d2d3660c085016138fb565b608082015292915050565b601f8211156109c8576000816000526020600020601f850160051c81016020861015613d615750805b601f850160051c820191505b81811015613d8057828155600101613d6d565b505050505050565b815167ffffffffffffffff811115613da257613da2613826565b613db681613db08454613a71565b84613d38565b602080601f831160018114613e095760008415613dd35750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613d80565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613e5657888601518255948401946001909101908401613e37565b5085821015613e9257878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff87168352806020840152613ec681840187613332565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff9081166060870152908701511660808501529150613f049050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612e63565b600060208284031215613f4d57600080fd5b8151611e9e816138cd565b600060208284031215613f6a57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff828116828216039081111561069657610696613f71565b600181815b8085111561401257817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613ff857613ff8613f71565b8085161561400557918102915b93841c9390800290613fbe565b509250929050565b60008261402957506001610696565b8161403657506000610696565b816001811461404c576002811461405657614072565b6001915050610696565b60ff84111561406757614067613f71565b50506001821b610696565b5060208310610133831016604e8410600b8410161715614095575081810a610696565b61409f8383613fb9565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156140d1576140d1613f71565b029392505050565b6000611e9e60ff84168361401a565b60008261411e577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808202811582820484141761069657610696613f71565b67ffffffffffffffff831681526040602082015260006108ad6040830184613332565b67ffffffffffffffff8416815260e081016141a960208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c08301526108ad565b8181038181111561069657610696613f71565b6060810161069682848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561424157600080fd5b8151611e9e816133a9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8082018082111561069657610696613f7156fea164736f6c6343000818000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"contractIBurnMintERC20\"},{\"name\":\"localTokenDecimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"allowlist\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"rmnProxy\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"router\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"acceptOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"addRemotePool\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyAllowListUpdates\",\"inputs\":[{\"name\":\"removes\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"adds\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyChainUpdates\",\"inputs\":[{\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"},{\"name\":\"chainsToAdd\",\"type\":\"tuple[]\",\"internalType\":\"structTokenPool.ChainUpdate[]\",\"components\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"},{\"name\":\"remoteTokenAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getAllowList\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getAllowListEnabled\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCurrentInboundRateLimiterState\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.TokenBucket\",\"components\":[{\"name\":\"tokens\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"lastUpdated\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCurrentOutboundRateLimiterState\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.TokenBucket\",\"components\":[{\"name\":\"tokens\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"lastUpdated\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRateLimitAdmin\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRemotePools\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRemoteToken\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRmnProxy\",\"inputs\":[],\"outputs\":[{\"name\":\"rmnProxy\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRouter\",\"inputs\":[],\"outputs\":[{\"name\":\"router\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getSupportedChains\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getToken\",\"inputs\":[],\"outputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"contractIERC20\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTokenDecimals\",\"inputs\":[],\"outputs\":[{\"name\":\"decimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isRemotePool\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isSupportedChain\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isSupportedToken\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"lockOrBurn\",\"inputs\":[{\"name\":\"lockOrBurnIn\",\"type\":\"tuple\",\"internalType\":\"structPool.LockOrBurnInV1\",\"components\":[{\"name\":\"receiver\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"originalSender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"localToken\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structPool.LockOrBurnOutV1\",\"components\":[{\"name\":\"destTokenAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"destPoolData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"releaseOrMint\",\"inputs\":[{\"name\":\"releaseOrMintIn\",\"type\":\"tuple\",\"internalType\":\"structPool.ReleaseOrMintInV1\",\"components\":[{\"name\":\"originalSender\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"receiver\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"localToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"sourcePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"sourcePoolData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"offchainTokenData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"components\":[{\"name\":\"destinationAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"removeRemotePool\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setChainRateLimiterConfig\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"outboundConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setChainRateLimiterConfigs\",\"inputs\":[{\"name\":\"remoteChainSelectors\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"},{\"name\":\"outboundConfigs\",\"type\":\"tuple[]\",\"internalType\":\"structRateLimiter.Config[]\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundConfigs\",\"type\":\"tuple[]\",\"internalType\":\"structRateLimiter.Config[]\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setRateLimitAdmin\",\"inputs\":[{\"name\":\"rateLimitAdmin\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setRouter\",\"inputs\":[{\"name\":\"newRouter\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"typeAndVersion\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"AllowListAdd\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"AllowListRemove\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Burned\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChainAdded\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"remoteToken\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"},{\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChainConfigured\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChainRemoved\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ConfigChanged\",\"inputs\":[{\"name\":\"config\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Locked\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Minted\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferRequested\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RateLimitAdminSet\",\"inputs\":[{\"name\":\"rateLimitAdmin\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Released\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RemotePoolAdded\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RemotePoolRemoved\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RouterUpdated\",\"inputs\":[{\"name\":\"oldRouter\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"newRouter\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TokensConsumed\",\"inputs\":[{\"name\":\"tokens\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AggregateValueMaxCapacityExceeded\",\"inputs\":[{\"name\":\"capacity\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"requested\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"AggregateValueRateLimitReached\",\"inputs\":[{\"name\":\"minWaitInSeconds\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"available\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"AllowListNotEnabled\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BucketOverfilled\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CallerIsNotARampOnRouter\",\"inputs\":[{\"name\":\"caller\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"CannotTransferToSelf\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ChainAlreadyExists\",\"inputs\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"ChainNotAllowed\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"CursedByRMN\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"DisabledNonZeroRateLimit\",\"inputs\":[{\"name\":\"config\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}]},{\"type\":\"error\",\"name\":\"InvalidDecimalArgs\",\"inputs\":[{\"name\":\"expected\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"actual\",\"type\":\"uint8\",\"internalType\":\"uint8\"}]},{\"type\":\"error\",\"name\":\"InvalidRateLimitRate\",\"inputs\":[{\"name\":\"rateLimiterConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}]},{\"type\":\"error\",\"name\":\"InvalidRemoteChainDecimals\",\"inputs\":[{\"name\":\"sourcePoolData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidRemotePoolForChain\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidSourcePoolAddress\",\"inputs\":[{\"name\":\"sourcePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidToken\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"MismatchedArrayLengths\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MustBeProposedOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NonExistentChain\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"OnlyCallableByOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OverflowDetected\",\"inputs\":[{\"name\":\"remoteDecimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"localDecimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"remoteAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"OwnerCannotBeZero\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PoolAlreadyAdded\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"RateLimitMustBeDisabled\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"SenderNotAllowed\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"TokenMaxCapacityExceeded\",\"inputs\":[{\"name\":\"capacity\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"requested\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"tokenAddress\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"TokenRateLimitReached\",\"inputs\":[{\"name\":\"minWaitInSeconds\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"available\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"tokenAddress\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"Unauthorized\",\"inputs\":[{\"name\":\"caller\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ZeroAddressNotAllowed\",\"inputs\":[]}]", + Bin: "0x61010080604052346103635761491c803803809161001d82856103e2565b833981019060a0818303126103635780516001600160a01b038116908190036103635761004c60208301610405565b60408301519091906001600160401b0381116103635783019380601f86011215610363578451946001600160401b0386116103cc578560051b90602082019661009860405198896103e2565b875260208088019282010192831161036357602001905b8282106103b4575050506100d160806100ca60608601610413565b9401610413565b9233156103a357600180546001600160a01b0319163317905581158015610392575b8015610381575b610370578160209160049360805260c0526040519283809263313ce56760e01b82525afa6000918161032f575b50610304575b5060a052600480546001600160a01b0319166001600160a01b03929092169190911790558051151560e08190526101e6575b60405161435490816105c882396080518181816115fc015281816117e801528181612204015281816123e0015281816126f80152612770015260a05181818161189f0152818161267f0152818161315901526131dc015260c051818181610bd501528181611698015261229f015260e051818181610b65015281816116db0152611ffb0152f35b60405160206101f581836103e2565b60008252600036813760e051156102f35760005b8251811015610270576001906001600160a01b036102278286610427565b51168361023382610469565b610240575b505001610209565b7f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf756691604051908152a13883610238565b50905060005b82518110156102ea576001906001600160a01b036102948286610427565b511680156102e457836102a682610567565b6102b4575b50505b01610276565b7f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d891604051908152a138836102ab565b506102ae565b5050503861015f565b6335f4a7b360e01b60005260046000fd5b60ff1660ff8216818103610318575061012d565b6332ad3e0760e11b60005260045260245260446000fd5b9091506020813d602011610368575b8161034b602093836103e2565b810103126103635761035c90610405565b9038610127565b600080fd5b3d915061033e565b6342bcdf7f60e11b60005260046000fd5b506001600160a01b038116156100fa565b506001600160a01b038416156100f3565b639b15e16f60e01b60005260046000fd5b602080916103c184610413565b8152019101906100af565b634e487b7160e01b600052604160045260246000fd5b601f909101601f19168101906001600160401b038211908210176103cc57604052565b519060ff8216820361036357565b51906001600160a01b038216820361036357565b805182101561043b5760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b805482101561043b5760005260206000200190600090565b600081815260036020526040902054801561056057600019810181811161054a5760025460001981019190821161054a578181036104f9575b50505060025480156104e357600019016104bd816002610451565b8154906000199060031b1b19169055600255600052600360205260006040812055600190565b634e487b7160e01b600052603160045260246000fd5b61053261050a61051b936002610451565b90549060031b1c9283926002610451565b819391549060031b91821b91600019901b19161790565b905560005260036020526040600020553880806104a2565b634e487b7160e01b600052601160045260246000fd5b5050600090565b806000526003602052604060002054156000146105c157600254680100000000000000008110156103cc576105a861051b8260018594016002556002610451565b9055600254906000526003602052604060002055600190565b5060009056fe608080604052600436101561001357600080fd5b600090813560e01c90816301ffc9a71461281357508063181f5a771461279457806321df0da714612725578063240028e8146126a357806324f65ee714612647578063390775371461215e5780634c5ef0ed1461214457806354c8a4f314611fc757806362ddd3c414611f435780636d3d1a5814611ef157806379ba509714611e0c5780637d54534e14611d5f5780638926f54f14611cfb5780638da5cb5b14611ca9578063962d402014611b055780639a4575b914611554578063a42a7b8b146113cf578063a7cd63b714611303578063acfecf91146111df578063af58d59f14611178578063b0f479a114611126578063b7946580146110cf578063c0d7865514610fd7578063c4bffe2b14610e8e578063c75eea9c14610dc8578063cf7401f314610bf9578063dc0bd97114610b8a578063e0351e1314610b2f578063e8a1da171461025a5763f2fde38b1461016b57600080fd5b346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575773ffffffffffffffffffffffffffffffffffffffff6101b7612a41565b6101bf6132e6565b1633811461022f57807fffffffffffffffffffffffff000000000000000000000000000000000000000083541617825573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12788380a380f35b6004827fdad89dca000000000000000000000000000000000000000000000000000000008152fd5b80fd5b50346102575761026936612b2f565b939190926102756132e6565b82915b80831061099a575050508063ffffffff4216917ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee1843603015b85821015610996578160051b85013581811215610992578501906101208236031261099257604051956102e387612969565b823567ffffffffffffffff8116810361098d578752602083013567ffffffffffffffff81116109895783019536601f880112156109895786359661032688612d5b565b97610334604051998a6129a1565b8089526020808a019160051b830101903682116109855760208301905b828210610952575050505060208801968752604084013567ffffffffffffffff811161094e5761038490369086016130b3565b9860408901998a526103ae61039c3660608801612bed565b9560608b0196875260c0369101612bed565b9660808a019788526103c0865161375d565b6103ca885161375d565b8a515115610926576103e667ffffffffffffffff8b5116613fb0565b156108ef5767ffffffffffffffff8a5116815260076020526040812061052687516fffffffffffffffffffffffffffffffff604082015116906104e16fffffffffffffffffffffffffffffffff6020830151169151151583608060405161044c81612969565b858152602081018c905260408101849052606081018690520152855474ff000000000000000000000000000000000000000091151560a01b919091167fffffffffffffffffffffff0000000000000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff84161773ffffffff0000000000000000000000000000000060808b901b1617178555565b60809190911b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff91909116176001830155565b61064c89516fffffffffffffffffffffffffffffffff604082015116906106076fffffffffffffffffffffffffffffffff6020830151169151151583608060405161057081612969565b858152602081018c9052604081018490526060810186905201526002860180547fffffffffffffffffffffff000000000000000000000000000000000000000000166fffffffffffffffffffffffffffffffff85161773ffffffff0000000000000000000000000000000060808c901b161791151560a01b74ff000000000000000000000000000000000000000016919091179055565b60809190911b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff91909116176003830155565b60048c5191019080519067ffffffffffffffff82116108c25761066f8354612e53565b601f8111610887575b50602090601f83116001146107e8576106c692918591836107dd575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b90555b805b8951805182101561070157906106fb6001926106f4838f67ffffffffffffffff90511692612e3f565b5190613331565b016106cb565b5050975097987f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c2929593966107cf67ffffffffffffffff600197949c511692519351915161079b610766604051968796875261010060208801526101008701906129e2565b9360408601906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b60a08401906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b0390a10190939492916102b1565b015190503880610694565b83855281852091907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08416865b81811061086f5750908460019594939210610838575b505050811b0190556106c9565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c1916905538808061082b565b92936020600181928786015181550195019301610815565b6108b29084865260208620601f850160051c810191602086106108b8575b601f0160051c019061305a565b38610678565b90915081906108a5565b6024847f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b60249067ffffffffffffffff8b51167f1d5ad3c5000000000000000000000000000000000000000000000000000000008252600452fd5b807f8579befe0000000000000000000000000000000000000000000000000000000060049252fd5b8680fd5b813567ffffffffffffffff81116109815760209161097683928336918901016130b3565b815201910190610351565b8a80fd5b8880fd5b8580fd5b600080fd5b8380fd5b8280f35b9092919367ffffffffffffffff6109ba6109b5878588612ddb565b612e1a565b16956109c587613ce4565b15610b035786845260076020526109e160056040862001613aeb565b94845b8651811015610a1a576001908987526007602052610a1360056040892001610a0c838b612e3f565b5190613e0f565b50016109e4565b5093945094909580855260076020526005604086208681558660018201558660028201558660038201558660048201610a538154612e53565b80610ac2575b5050500180549086815581610aa4575b5050907f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599166020600193604051908152a1019190949394610278565b865260208620908101905b81811015610a6957868155600101610aaf565b601f8111600114610ad85750555b863880610a59565b81835260208320610af391601f01861c81019060010161305a565b8082528160208120915555610ad0565b602484887f1e670e4b000000000000000000000000000000000000000000000000000000008252600452fd5b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575760206040517f000000000000000000000000000000000000000000000000000000000000000015158152f35b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346102575760e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757610c31612a64565b9060607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36011261025757604051610c6881612985565b6024358015158103610dc45781526044356fffffffffffffffffffffffffffffffff81168103610dc45760208201526064356fffffffffffffffffffffffffffffffff81168103610dc457604082015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7c360112610dc05760405190610cef82612985565b608435801515810361099257825260a4356fffffffffffffffffffffffffffffffff8116810361099257602083015260c4356fffffffffffffffffffffffffffffffff8116810361099257604083015273ffffffffffffffffffffffffffffffffffffffff6009541633141580610d9e575b610d7257610d6f929361359b565b80f35b6024837f8e4a23d600000000000000000000000000000000000000000000000000000000815233600452fd5b5073ffffffffffffffffffffffffffffffffffffffff60015416331415610d61565b5080fd5b8280fd5b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757610e31610e2c6040610e8a9367ffffffffffffffff610e15612a64565b610e1d612fa7565b50168152600760205220612fd2565b6136d8565b6040519182918291909160806fffffffffffffffffffffffffffffffff8160a084019582815116855263ffffffff6020820151166020860152604081015115156040860152826060820151166060860152015116910152565b0390f35b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757604051906005548083528260208101600584526020842092845b818110610fbe575050610eec925003836129a1565b8151610f10610efa82612d5b565b91610f0860405193846129a1565b808352612d5b565b917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0602083019301368437805b8451811015610f6f578067ffffffffffffffff610f5c60019388612e3f565b5116610f688286612e3f565b5201610f3d565b50925090604051928392602084019060208552518091526040840192915b818110610f9b575050500390f35b825167ffffffffffffffff16845285945060209384019390920191600101610f8d565b8454835260019485019487945060209093019201610ed7565b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575773ffffffffffffffffffffffffffffffffffffffff611024612a41565b61102c6132e6565b1680156110a75760407f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f16849160045490807fffffffffffffffffffffffff000000000000000000000000000000000000000083161760045573ffffffffffffffffffffffffffffffffffffffff8351921682526020820152a180f35b6004827f8579befe000000000000000000000000000000000000000000000000000000008152fd5b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757610e8a61111261110d612a64565b613038565b6040519182916020835260208301906129e2565b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602073ffffffffffffffffffffffffffffffffffffffff60045416604051908152f35b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757610e31610e2c60026040610e8a9467ffffffffffffffff6111c7612a64565b6111cf612fa7565b5016815260076020522001612fd2565b50346102575767ffffffffffffffff6111f736612a7b565b9290916112026132e6565b169161121b836000526006602052604060002054151590565b156112d757828452600760205261124a6005604086200161123d368486612c8a565b6020815191012090613e0f565b1561128f57907f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d7691611289604051928392602084526020840191612f68565b0390a280f35b826112d3836040519384937f74f23c7c0000000000000000000000000000000000000000000000000000000085526004850152604060248501526044840191612f68565b0390fd5b602484847f1e670e4b000000000000000000000000000000000000000000000000000000008252600452fd5b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757604051600254808252602082018091600285526020852090855b8181106113b957505050826113629103836129a1565b604051928392602084019060208552518091526040840192915b81811061138a575050500390f35b825173ffffffffffffffffffffffffffffffffffffffff1684528594506020938401939092019160010161137c565b825484526020909301926001928301920161134c565b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575767ffffffffffffffff611410612a64565b168152600760205261142760056040832001613aeb565b80517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061146c61145683612d5b565b9261146460405194856129a1565b808452612d5b565b01835b818110611543575050825b82518110156114c0578061149060019285612e3f565b51855260086020526114a460408620612ea6565b6114ae8285612e3f565b526114b98184612e3f565b500161147a565b81846040519182916020830160208452825180915260408401602060408360051b870101940192905b8282106114f857505050500390f35b91936020611533827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0600195979984950301865288516129e2565b96019201920185949391926114e9565b80606060208093860101520161146f565b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575760043567ffffffffffffffff8111610dc05760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8236030112610dc057606060206040516115d28161294d565b8281520152608481016115e481612cef565b73ffffffffffffffffffffffffffffffffffffffff807f000000000000000000000000000000000000000000000000000000000000000016911603611abb5750602481019177ffffffffffffffff0000000000000000000000000000000061164b84612e1a565b60801b16604051907f2cbc26bb000000000000000000000000000000000000000000000000000000008252600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa90811561194b578291611a8c575b50611a64576116d960448301612cef565b7f0000000000000000000000000000000000000000000000000000000000000000611a11575b5067ffffffffffffffff61171284612e1a565b1661172a816000526006602052604060002054151590565b156119e557602073ffffffffffffffffffffffffffffffffffffffff60045416916024604051809481937fa8d87a3b00000000000000000000000000000000000000000000000000000000835260048301525afa801561194b578290611982575b73ffffffffffffffffffffffffffffffffffffffff91501633036119565767ffffffffffffffff60646117bd85612e1a565b930135921681526007602052816118106040832073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001692839161405f565b803b15610dc0578180916024604051809481937f42966c680000000000000000000000000000000000000000000000000000000083528860048401525af1801561194b57611936575b61190561189561110d86866040519081527f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df760203392a2612e1a565b610e8a60405160ff7f0000000000000000000000000000000000000000000000000000000000000000166020820152602081526118d36040826129a1565b604051926118e08461294d565b83526020830190815260405193849360208552516040602086015260608501906129e2565b90517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160408501526129e2565b6119418280926129a1565b6102575780611859565b6040513d84823e3d90fd5b807f728fe07b000000000000000000000000000000000000000000000000000000006024925233600452fd5b506020813d6020116119dd575b8161199c602093836129a1565b81010312610dc0575173ffffffffffffffffffffffffffffffffffffffff81168103610dc05773ffffffffffffffffffffffffffffffffffffffff9061178b565b3d915061198f565b602492507fa9902c7e000000000000000000000000000000000000000000000000000000008252600452fd5b73ffffffffffffffffffffffffffffffffffffffff16808252600360205260408220546116ff57602492507fd0d25976000000000000000000000000000000000000000000000000000000008252600452fd5b807f53ad11d80000000000000000000000000000000000000000000000000000000060049252fd5b611aae915060203d602011611ab4575b611aa681836129a1565b8101906130ce565b386116c8565b503d611a9c565b8273ffffffffffffffffffffffffffffffffffffffff611adc602493612cef565b7f961c9a4f00000000000000000000000000000000000000000000000000000000835216600452fd5b50346102575760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575760043567ffffffffffffffff8111610dc057611b55903690600401612afe565b60243567ffffffffffffffff811161099257611b75903690600401612b9f565b60449291923567ffffffffffffffff811161098957611b98903690600401612b9f565b91909273ffffffffffffffffffffffffffffffffffffffff6009541633141580611c87575b611c5b57818114801590611c51575b611c2957865b818110611bdd578780f35b80611c23611bf16109b5600194868c612ddb565b611bfc83878b612e2f565b611c1d611c15611c0d868b8d612e2f565b923690612bed565b913690612bed565b9161359b565b01611bd2565b6004877f568efce2000000000000000000000000000000000000000000000000000000008152fd5b5082811415611bcc565b6024877f8e4a23d600000000000000000000000000000000000000000000000000000000815233600452fd5b5073ffffffffffffffffffffffffffffffffffffffff60015416331415611bbd565b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610257576020611d5567ffffffffffffffff611d41612a64565b166000526006602052604060002054151590565b6040519015158152f35b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610257577f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d09174602073ffffffffffffffffffffffffffffffffffffffff611dcf612a41565b611dd76132e6565b16807fffffffffffffffffffffffff00000000000000000000000000000000000000006009541617600955604051908152a180f35b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757805473ffffffffffffffffffffffffffffffffffffffff81163303611ec9577fffffffffffffffffffffffff000000000000000000000000000000000000000060015491338284161760015516825573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b6004827f02b543c6000000000000000000000000000000000000000000000000000000008152fd5b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602073ffffffffffffffffffffffffffffffffffffffff60095416604051908152f35b503461025757611f5236612a7b565b611f5e939291936132e6565b67ffffffffffffffff8216611f80816000526006602052604060002054151590565b15611f9c5750610d6f9293611f96913691612c8a565b90613331565b7f1e670e4b000000000000000000000000000000000000000000000000000000008452600452602483fd5b503461025757611ff190611ff9611fdd36612b2f565b9591611fea9391936132e6565b3691612d73565b933691612d73565b7f00000000000000000000000000000000000000000000000000000000000000001561211c57815b8351811015612094578073ffffffffffffffffffffffffffffffffffffffff61204c60019387612e3f565b511661205781613b4e565b612063575b5001612021565b60207f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf756691604051908152a13861205c565b5090805b8251811015612118578073ffffffffffffffffffffffffffffffffffffffff6120c360019386612e3f565b51168015612112576120d481613f50565b6120e1575b505b01612098565b60207f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d891604051908152a1846120d9565b506120db565b5080f35b6004827f35f4a7b3000000000000000000000000000000000000000000000000000000008152fd5b5034610257576020611d5561215836612a7b565b91612d10565b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575760043567ffffffffffffffff8111610dc057806004016101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8336030112610dc457826040516121de81612902565b52608482016121ec81612cef565b73ffffffffffffffffffffffffffffffffffffffff807f00000000000000000000000000000000000000000000000000000000000000001691160361262657506024820177ffffffffffffffff0000000000000000000000000000000061225282612e1a565b60801b16604051907f2cbc26bb000000000000000000000000000000000000000000000000000000008252600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9081156125a9578591612607575b506125df5767ffffffffffffffff6122e682612e1a565b166122fe816000526006602052604060002054151590565b156125b457602073ffffffffffffffffffffffffffffffffffffffff60045416916044604051809481937f83826b2b00000000000000000000000000000000000000000000000000000000835260048301523360248301525afa9081156125a957859161258a575b501561255e5761237581612e1a565b61238760a48501916121588386612c39565b15612517575061242467ffffffffffffffff9261241e6124196124126123ae604496612e1a565b936064890135978895168a526007602052612408600260408c200173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016998a9161405f565b60c4890190612c39565b3691612c8a565b6130e6565b906131d9565b9201908361243183612cef565b823b15610dc057604473ffffffffffffffffffffffffffffffffffffffff918360405195869485937f40c10f190000000000000000000000000000000000000000000000000000000085521660048401528860248401525af1801561250c57916020946124ba9273ffffffffffffffffffffffffffffffffffffffff946124fc575b5050612cef565b166040518281527f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f0843392a3806040516124f381612902565b52604051908152f35b81612506916129a1565b386124b3565b6040513d86823e3d90fd5b6125219083612c39565b6112d36040519283927f24eb47e5000000000000000000000000000000000000000000000000000000008452602060048501526024840191612f68565b6024847f728fe07b00000000000000000000000000000000000000000000000000000000815233600452fd5b6125a3915060203d602011611ab457611aa681836129a1565b38612366565b6040513d87823e3d90fd5b7fa9902c7e000000000000000000000000000000000000000000000000000000008552600452602484fd5b6004847f53ad11d8000000000000000000000000000000000000000000000000000000008152fd5b612620915060203d602011611ab457611aa681836129a1565b386122cf565b8373ffffffffffffffffffffffffffffffffffffffff611adc602493612cef565b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602060405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610257576020906126de612a41565b905073ffffffffffffffffffffffffffffffffffffffff807f0000000000000000000000000000000000000000000000000000000000000000169116146040519015158152f35b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575750610e8a6040516127d56040826129a1565b601781527f4275726e4d696e74546f6b656e506f6f6c20312e352e3100000000000000000060208201526040519182916020835260208301906129e2565b905034610dc05760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610dc0576004357fffffffff000000000000000000000000000000000000000000000000000000008116809103610dc457602092507faff2afbf0000000000000000000000000000000000000000000000000000000081149081156128d8575b81156128ae575b5015158152f35b7f01ffc9a700000000000000000000000000000000000000000000000000000000915014386128a7565b7f0e64dd2900000000000000000000000000000000000000000000000000000000811491506128a0565b6020810190811067ffffffffffffffff82111761291e57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040810190811067ffffffffffffffff82111761291e57604052565b60a0810190811067ffffffffffffffff82111761291e57604052565b6060810190811067ffffffffffffffff82111761291e57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761291e57604052565b919082519283825260005b848110612a2c5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b806020809284010151828286010152016129ed565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361098d57565b6004359067ffffffffffffffff8216820361098d57565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82011261098d5760043567ffffffffffffffff8116810361098d579160243567ffffffffffffffff811161098d578260238201121561098d5780600401359267ffffffffffffffff841161098d576024848301011161098d576024019190565b9181601f8401121561098d5782359167ffffffffffffffff831161098d576020808501948460051b01011161098d57565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82011261098d5760043567ffffffffffffffff811161098d5781612b7891600401612afe565b929092916024359067ffffffffffffffff821161098d57612b9b91600401612afe565b9091565b9181601f8401121561098d5782359167ffffffffffffffff831161098d576020808501946060850201011161098d57565b35906fffffffffffffffffffffffffffffffff8216820361098d57565b919082606091031261098d57604051612c0581612985565b8092803590811515820361098d576040612c349181938552612c2960208201612bd0565b602086015201612bd0565b910152565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561098d570180359067ffffffffffffffff821161098d5760200191813603831361098d57565b92919267ffffffffffffffff821161291e5760405191612cd2601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016602001846129a1565b82948184528183011161098d578281602093846000960137010152565b3573ffffffffffffffffffffffffffffffffffffffff8116810361098d5790565b612d58929167ffffffffffffffff612d3b921660005260076020526005604060002001923691612c8a565b602081519101209060019160005201602052604060002054151590565b90565b67ffffffffffffffff811161291e5760051b60200190565b9291612d7e82612d5b565b93612d8c60405195866129a1565b602085848152019260051b810191821161098d57915b818310612dae57505050565b823573ffffffffffffffffffffffffffffffffffffffff8116810361098d57815260209283019201612da2565b9190811015612deb5760051b0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b3567ffffffffffffffff8116810361098d5790565b9190811015612deb576060020190565b8051821015612deb5760209160051b010190565b90600182811c92168015612e9c575b6020831014612e6d57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f1691612e62565b9060405191826000825492612eba84612e53565b8084529360018116908115612f285750600114612ee1575b50612edf925003836129a1565b565b90506000929192526020600020906000915b818310612f0c575050906020612edf9282010138612ed2565b6020919350806001915483858901015201910190918492612ef3565b60209350612edf9592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b82010138612ed2565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b60405190612fb482612969565b60006080838281528260208201528260408201528260608201520152565b90604051612fdf81612969565b60806001829460ff81546fffffffffffffffffffffffffffffffff8116865263ffffffff81861c16602087015260a01c161515604085015201546fffffffffffffffffffffffffffffffff81166060840152811c910152565b67ffffffffffffffff166000526007602052612d586004604060002001612ea6565b818110613065575050565b6000815560010161305a565b8181029291811591840414171561308457565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9080601f8301121561098d57816020612d5893359101612c8a565b9081602091031261098d5751801515810361098d5790565b80518015613155576020036131175760208180518101031261098d5760208101519060ff8211613117575060ff1690565b6112d3906040519182917f953576f70000000000000000000000000000000000000000000000000000000083526020600484015260248301906129e2565b50507f000000000000000000000000000000000000000000000000000000000000000090565b9060ff8091169116039060ff821161308457565b60ff16604d811161308457600a0a90565b81156131aa570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b907f00000000000000000000000000000000000000000000000000000000000000009060ff82169060ff8116928284146132df578284116132b5579061321e9161317b565b91604d60ff841611801561327c575b61324657505090613240612d589261318f565b90613071565b9091507fa9cb113d0000000000000000000000000000000000000000000000000000000060005260045260245260445260646000fd5b506132868361318f565b80156131aa577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04841161322d565b6132be9161317b565b91604d60ff841611613246575050906132d9612d589261318f565b906131a0565b5050505090565b73ffffffffffffffffffffffffffffffffffffffff60015416330361330757565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b908051156135715767ffffffffffffffff8151602083012092169182600052600760205261336681600560406000200161400a565b1561352d5760005260086020526040600020815167ffffffffffffffff811161291e576133938254612e53565b601f81116134fb575b506020601f8211600114613435579161340f827f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea95936134259560009161342a575b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b90556040519182916020835260208301906129e2565b0390a2565b9050840151386133de565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082169083600052806000209160005b8181106134e35750926134259492600192827f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea9896106134ac575b5050811b019055611112565b8501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c1916905538806134a0565b9192602060018192868a015181550194019201613465565b61352790836000526020600020601f840160051c810191602085106108b857601f0160051c019061305a565b3861339c565b50906112d36040519283927f393b8ad200000000000000000000000000000000000000000000000000000000845260048401526040602484015260448301906129e2565b7f8579befe0000000000000000000000000000000000000000000000000000000060005260046000fd5b67ffffffffffffffff16600081815260066020526040902054909291901561369d579161369a60e092613666856135f27f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b9761375d565b8460005260076020526136098160406000206138b8565b6136128361375d565b84600052600760205261362c8360026040600020016138b8565b60405194855260208501906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b60808301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565ba1565b827f1e670e4b0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b9190820391821161308457565b6136e0612fa7565b506fffffffffffffffffffffffffffffffff6060820151166fffffffffffffffffffffffffffffffff808351169161373d602085019361373761372a63ffffffff875116426136cb565b8560808901511690613071565b90613f43565b8082101561375657505b16825263ffffffff4216905290565b9050613747565b805115613811576fffffffffffffffffffffffffffffffff6040820151166fffffffffffffffffffffffffffffffff602083015116811090811591613808575b506137a55750565b606490613806604051917f8020d12400000000000000000000000000000000000000000000000000000000835260048301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565bfd5b9050153861379d565b6fffffffffffffffffffffffffffffffff60408201511615801590613899575b6138385750565b606490613806604051917fd68af9cc00000000000000000000000000000000000000000000000000000000835260048301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b506fffffffffffffffffffffffffffffffff6020820151161515613831565b7f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19916139f160609280546138f563ffffffff8260801c16426136cb565b9081613a30575b50506fffffffffffffffffffffffffffffffff6001816020860151169282815416808510600014613a2857508280855b16167fffffffffffffffffffffffffffffffff000000000000000000000000000000008254161781556139a58651151582907fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff74ff0000000000000000000000000000000000000000835492151560a01b169116179055565b60408601517fffffffffffffffffffffffffffffffff0000000000000000000000000000000060809190911b16939092166fffffffffffffffffffffffffffffffff1692909217910155565b61369a60405180926fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b83809161392c565b6fffffffffffffffffffffffffffffffff91613a65839283613a5e6001880154948286169560801c90613071565b9116613f43565b80821015613ae457505b83547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff9290911692909216167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116174260801b73ffffffff000000000000000000000000000000001617815538806138fc565b9050613a6f565b906040519182815491828252602082019060005260206000209260005b818110613b1d575050612edf925003836129a1565b8454835260019485019487945060209093019201613b08565b8054821015612deb5760005260206000200190600090565b6000818152600360205260409020548015613cdd577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811161308457600254907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820191821161308457818103613c6e575b5050506002548015613c3f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01613bfc816002613b36565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600255600052600360205260006040812055600190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b613cc5613c7f613c90936002613b36565b90549060031b1c9283926002613b36565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b90556000526003602052604060002055388080613bc3565b5050600090565b6000818152600660205260409020548015613cdd577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811161308457600554907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820191821161308457818103613dd5575b5050506005548015613c3f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01613d92816005613b36565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600555600052600660205260006040812055600190565b613df7613de6613c90936005613b36565b90549060031b1c9283926005613b36565b90556000526006602052604060002055388080613d59565b9060018201918160005282602052604060002054801515600014613f3a577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101818111613084578254907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820191821161308457818103613f03575b50505080548015613c3f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190613ec48282613b36565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b191690555560005260205260006040812055600190565b613f23613f13613c909386613b36565b90549060031b1c92839286613b36565b905560005283602052604060002055388080613e8c565b50505050600090565b9190820180921161308457565b80600052600360205260406000205415600014613faa576002546801000000000000000081101561291e57613f91613c908260018594016002556002613b36565b9055600254906000526003602052604060002055600190565b50600090565b80600052600660205260406000205415600014613faa576005546801000000000000000081101561291e57613ff1613c908260018594016005556005613b36565b9055600554906000526006602052604060002055600190565b6000828152600182016020526040902054613cdd578054906801000000000000000082101561291e5782614048613c90846001809601855584613b36565b905580549260005201602052604060002055600190565b929192805460ff8160a01c1615801561433f575b614338576fffffffffffffffffffffffffffffffff811690600183019081546140b863ffffffff6fffffffffffffffffffffffffffffffff83169360801c16426136cb565b908161429a575b5050848110614218575083821061414757507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a939450906fffffffffffffffffffffffffffffffff8061411585602096956136cb565b16167fffffffffffffffffffffffffffffffff00000000000000000000000000000000825416179055604051908152a1565b81945061415992505460801c926136cb565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810190808211613084576141a76141ac9273ffffffffffffffffffffffffffffffffffffffff94613f43565b6131a0565b92169182156141e8577fd0c8d23a0000000000000000000000000000000000000000000000000000000060005260045260245260445260646000fd5b7f15279c080000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b8473ffffffffffffffffffffffffffffffffffffffff881691821561426a577f1a76572a0000000000000000000000000000000000000000000000000000000060005260045260245260445260646000fd5b7ff94ebcd10000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b82859293951161430e576142b5926137379160801c90613071565b808310156143095750815b83547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff164260801b73ffffffff00000000000000000000000000000000161784559138806140bf565b6142c0565b7f9725942a0000000000000000000000000000000000000000000000000000000060005260046000fd5b5050509050565b50821561407356fea164736f6c634300081a000a", } var BurnMintTokenPoolABI = BurnMintTokenPoolMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/burn_with_from_mint_token_pool/burn_with_from_mint_token_pool.go b/core/gethwrappers/ccip/generated/burn_with_from_mint_token_pool/burn_with_from_mint_token_pool.go index 46f233948ce..58ab79e69d4 100644 --- a/core/gethwrappers/ccip/generated/burn_with_from_mint_token_pool/burn_with_from_mint_token_pool.go +++ b/core/gethwrappers/ccip/generated/burn_with_from_mint_token_pool/burn_with_from_mint_token_pool.go @@ -81,8 +81,8 @@ type TokenPoolChainUpdate struct { } var BurnWithFromMintTokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"localTokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MismatchedArrayLengths\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"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\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectors\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"outboundConfigs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"inboundConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setChainRateLimiterConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"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\"}]", - Bin: "0x6101006040523480156200001257600080fd5b5060405162004ecf38038062004ecf833981016040819052620000359162000918565b8484848484336000816200005c57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008f576200008f8162000206565b50506001600160a01b0385161580620000af57506001600160a01b038116155b80620000c257506001600160a01b038216155b15620000e1576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b03808616608081905290831660c0526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa92505050801562000151575060408051601f3d908101601f191682019092526200014e9181019062000a3a565b60015b1562000192578060ff168560ff161462000190576040516332ad3e0760e11b815260ff8087166004830152821660248201526044015b60405180910390fd5b505b60ff841660a052600480546001600160a01b0319166001600160a01b038316179055825115801560e052620001dc57604080516000815260208101909152620001dc908462000280565b50620001fb935050506001600160a01b038716905030600019620003dd565b505050505062000b84565b336001600160a01b038216036200023057604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e051620002a1576040516335f4a7b360e01b815260040160405180910390fd5b60005b82518110156200032c576000838281518110620002c557620002c562000a58565b60209081029190910101519050620002df600282620004c3565b1562000322576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101620002a4565b5060005b8151811015620003d857600082828151811062000351576200035162000a58565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200037d5750620003cf565b6200038a600282620004e3565b15620003cd576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010162000330565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa1580156200042f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000455919062000a6e565b62000461919062000a9e565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152919250620004bd91869190620004fa16565b50505050565b6000620004da836001600160a01b038416620005cb565b90505b92915050565b6000620004da836001600160a01b038416620006cf565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65649082015260009062000549906001600160a01b03851690849062000721565b805190915015620003d857808060200190518101906200056a919062000ab4565b620003d85760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000187565b60008181526001830160205260408120548015620006c4576000620005f260018362000adf565b8554909150600090620006089060019062000adf565b9050808214620006745760008660000182815481106200062c576200062c62000a58565b906000526020600020015490508087600001848154811062000652576200065262000a58565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000688576200068862000af5565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620004dd565b6000915050620004dd565b60008181526001830160205260408120546200071857508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620004dd565b506000620004dd565b60606200073284846000856200073a565b949350505050565b6060824710156200079d5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000187565b600080866001600160a01b03168587604051620007bb919062000b31565b60006040518083038185875af1925050503d8060008114620007fa576040519150601f19603f3d011682016040523d82523d6000602084013e620007ff565b606091505b50909250905062000813878383876200081e565b979650505050505050565b60608315620008925782516000036200088a576001600160a01b0385163b6200088a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000187565b508162000732565b620007328383815115620008a95781518083602001fd5b8060405162461bcd60e51b815260040162000187919062000b4f565b6001600160a01b0381168114620008db57600080fd5b50565b805160ff81168114620008f057600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b8051620008f081620008c5565b600080600080600060a086880312156200093157600080fd5b85516200093e81620008c5565b945060206200094f878201620008de565b60408801519095506001600160401b03808211156200096d57600080fd5b818901915089601f8301126200098257600080fd5b815181811115620009975762000997620008f5565b8060051b604051601f19603f83011681018181108582111715620009bf57620009bf620008f5565b60405291825284820192508381018501918c831115620009de57600080fd5b938501935b8285101562000a0757620009f7856200090b565b84529385019392850192620009e3565b80985050505050505062000a1e606087016200090b565b915062000a2e608087016200090b565b90509295509295909350565b60006020828403121562000a4d57600080fd5b620004da82620008de565b634e487b7160e01b600052603260045260246000fd5b60006020828403121562000a8157600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115620004dd57620004dd62000a88565b60006020828403121562000ac757600080fd5b8151801515811462000ad857600080fd5b9392505050565b81810381811115620004dd57620004dd62000a88565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000b2857818101518382015260200162000b0e565b50506000910152565b6000825162000b4581846020870162000b0b565b9190910192915050565b602081526000825180602084015262000b7081604085016020870162000b0b565b601f01601f19169190910160400192915050565b60805160a05160c05160e05161429a62000c356000396000818161056601528181611ef30152612ae601526000818161054001528181611a1001526122c90152600081816102e401528181610d1a01528181611bb901528181611c7301528181611ca701528181611cda01528181611d3f01528181611d980152611e3a01526000818161024b015281816102a00152818161071f0152818161244c015281816128da0152612cd1015261429a6000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c80639a4575b911610104578063c0d78655116100a2578063dc0bd97111610071578063dc0bd9711461053e578063e0351e1314610564578063e8a1da171461058a578063f2fde38b1461059d57600080fd5b8063c0d78655146104f0578063c4bffe2b14610503578063c75eea9c14610518578063cf7401f31461052b57600080fd5b8063acfecf91116100de578063acfecf911461043d578063af58d59f14610450578063b0f479a1146104bf578063b7946580146104dd57600080fd5b80639a4575b9146103e8578063a42a7b8b14610408578063a7cd63b71461042857600080fd5b806354c8a4f31161017c5780637d54534e1161014b5780637d54534e146103915780638926f54f146103a45780638da5cb5b146103b7578063962d4020146103d557600080fd5b806354c8a4f31461034357806362ddd3c4146103585780636d3d1a581461036b57806379ba50971461038957600080fd5b8063240028e8116101b8578063240028e81461029057806324f65ee7146102dd578063390775371461030e5780634c5ef0ed1461033057600080fd5b806301ffc9a7146101df578063181f5a771461020757806321df0da714610249575b600080fd5b6101f26101ed3660046132ef565b6105b0565b60405190151581526020015b60405180910390f35b60408051808201909152601f81527f4275726e5769746846726f6d4d696e74546f6b656e506f6f6c20312e352e310060208201525b6040516101fe9190613395565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101fe565b6101f261029e3660046133ca565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016101fe565b61032161031c3660046133e7565b610695565b604051905181526020016101fe565b6101f261033e366004613440565b610864565b61035661035136600461350f565b6108ae565b005b610356610366366004613440565b610929565b60095473ffffffffffffffffffffffffffffffffffffffff1661026b565b6103566109c6565b61035661039f3660046133ca565b610a94565b6101f26103b236600461357b565b610b15565b60015473ffffffffffffffffffffffffffffffffffffffff1661026b565b6103566103e33660046135db565b610b2c565b6103fb6103f6366004613675565b610c86565b6040516101fe91906136b0565b61041b61041636600461357b565b610d5f565b6040516101fe9190613707565b610430610eca565b6040516101fe9190613789565b61035661044b366004613440565b610edb565b61046361045e36600461357b565b610ff3565b6040516101fe919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff1661026b565b61023c6104eb36600461357b565b6110c8565b6103566104fe3660046133ca565b611178565b61050b611253565b6040516101fe91906137e3565b61046361052636600461357b565b61130b565b61035661053936600461396b565b6113dd565b7f000000000000000000000000000000000000000000000000000000000000000061026b565b7f00000000000000000000000000000000000000000000000000000000000000006101f2565b61035661059836600461350f565b611461565b6103566105ab3660046133ca565b611973565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061064357507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061068f57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b6040805160208101909152600081526106ad82611987565b600061070660608401356107016106c760c08701876139b0565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611bab92505050565b611c6f565b905073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166340c10f1961075460608601604087016133ca565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260248101849052604401600060405180830381600087803b1580156107c157600080fd5b505af11580156107d5573d6000803e3d6000fd5b506107ea9250505060608401604085016133ca565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f08360405161084891815260200190565b60405180910390a3604080516020810190915290815292915050565b60006108a68383604051610879929190613a15565b604080519182900390912067ffffffffffffffff8716600090815260076020529190912060050190611e83565b949350505050565b6108b6611e9e565b61092384848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250611ef192505050565b50505050565b610931611e9e565b61093a83610b15565b610981576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6109c18383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506120a792505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a17576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610a9c611e9e565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b600061068f600567ffffffffffffffff8416611e83565b60095473ffffffffffffffffffffffffffffffffffffffff163314801590610b6c575060015473ffffffffffffffffffffffffffffffffffffffff163314155b15610ba5576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610978565b8483141580610bb45750848114155b15610beb576040517f568efce200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b85811015610c7d57610c75878783818110610c0b57610c0b613a25565b9050602002016020810190610c20919061357b565b868684818110610c3257610c32613a25565b905060600201803603810190610c489190613a54565b858585818110610c5a57610c5a613a25565b905060600201803603810190610c709190613a54565b6121a1565b600101610bee565b50505050505050565b6040805180820190915260608082526020820152610ca38261228b565b610cb08260600135612417565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610d0a8460200160208101906104eb919061357b565b8152602001610d576040805160ff7f000000000000000000000000000000000000000000000000000000000000000016602082015260609101604051602081830303815290604052905090565b905292915050565b67ffffffffffffffff8116600090815260076020526040812060609190610d88906005016124b9565b90506000815167ffffffffffffffff811115610da657610da6613825565b604051908082528060200260200182016040528015610dd957816020015b6060815260200190600190039081610dc45790505b50905060005b8251811015610ec25760086000848381518110610dfe57610dfe613a25565b602002602001015181526020019081526020016000208054610e1f90613a70565b80601f0160208091040260200160405190810160405280929190818152602001828054610e4b90613a70565b8015610e985780601f10610e6d57610100808354040283529160200191610e98565b820191906000526020600020905b815481529060010190602001808311610e7b57829003601f168201915b5050505050828281518110610eaf57610eaf613a25565b6020908102919091010152600101610ddf565b509392505050565b6060610ed660026124b9565b905090565b610ee3611e9e565b610eec83610b15565b610f2e576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610978565b610f6e8282604051610f41929190613a15565b604080519182900390912067ffffffffffffffff86166000908152600760205291909120600501906124c6565b610faa578282826040517f74f23c7c00000000000000000000000000000000000000000000000000000000815260040161097893929190613b0c565b8267ffffffffffffffff167f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d768383604051610fe6929190613b30565b60405180910390a2505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600390910154808416606083015291909104909116608082015261068f906124d2565b67ffffffffffffffff811660009081526007602052604090206004018054606091906110f390613a70565b80601f016020809104026020016040519081016040528092919081815260200182805461111f90613a70565b801561116c5780601f106111415761010080835404028352916020019161116c565b820191906000526020600020905b81548152906001019060200180831161114f57829003601f168201915b50505050509050919050565b611180611e9e565b73ffffffffffffffffffffffffffffffffffffffff81166111cd576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b6060600061126160056124b9565b90506000815167ffffffffffffffff81111561127f5761127f613825565b6040519080825280602002602001820160405280156112a8578160200160208202803683370190505b50905060005b8251811015611304578281815181106112c9576112c9613a25565b60200260200101518282815181106112e3576112e3613a25565b67ffffffffffffffff909216602092830291909101909101526001016112ae565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600190910154808416606083015291909104909116608082015261068f906124d2565b60095473ffffffffffffffffffffffffffffffffffffffff16331480159061141d575060015473ffffffffffffffffffffffffffffffffffffffff163314155b15611456576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610978565b6109c18383836121a1565b611469611e9e565b60005b8381101561165657600085858381811061148857611488613a25565b905060200201602081019061149d919061357b565b90506114b4600567ffffffffffffffff83166124c6565b6114f6576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610978565b67ffffffffffffffff8116600090815260076020526040812061151b906005016124b9565b905060005b81518110156115875761157e82828151811061153e5761153e613a25565b6020026020010151600760008667ffffffffffffffff1667ffffffffffffffff1681526020019081526020016000206005016124c690919063ffffffff16565b50600101611520565b5067ffffffffffffffff8216600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906115f06004830182613282565b600582016000818161160282826132bc565b505060405167ffffffffffffffff871681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d85991694506020019250611644915050565b60405180910390a1505060010161146c565b5060005b8181101561196c57600083838381811061167657611676613a25565b90506020028101906116889190613b44565b61169190613c10565b90506116a281606001516000612584565b6116b181608001516000612584565b8060400151516000036116f0576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516117089060059067ffffffffffffffff166126c1565b61174d5780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610978565b805167ffffffffffffffff16600090815260076020908152604091829020825160a08082018552606080870180518601516fffffffffffffffffffffffffffffffff90811680865263ffffffff42168689018190528351511515878b0181905284518a0151841686890181905294518b0151841660809889018190528954740100000000000000000000000000000000000000009283027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7001000000000000000000000000000000008087027fffffffffffffffffffffffff000000000000000000000000000000000000000094851690981788178216929092178d5592810290971760018c01558c519889018d52898e0180518d01518716808b528a8e019590955280515115158a8f018190528151909d01518716988a01899052518d0151909516979098018790526002890180549a9091029990931617179094169590951790925590920290911760038201559082015160048201906118d09082613d87565b5060005b8260200151518110156119145761190c8360000151846020015183815181106118ff576118ff613a25565b60200260200101516120a7565b6001016118d4565b507f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c2826000015183604001518460600151856080015160405161195a9493929190613ea1565b60405180910390a1505060010161165a565b5050505050565b61197b611e9e565b611984816126cd565b50565b61199a61029e60a08301608084016133ca565b6119f9576119ae60a08201608083016133ca565b6040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610978565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb611a45604084016020850161357b565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015611ab6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ada9190613f3a565b15611b11576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b29611b24604083016020840161357b565b612791565b611b49611b3c604083016020840161357b565b61033e60a08401846139b0565b611b8e57611b5a60a08201826139b0565b6040517f24eb47e5000000000000000000000000000000000000000000000000000000008152600401610978929190613b30565b611984611ba1604083016020840161357b565b82606001356128b7565b60008151600003611bdd57507f0000000000000000000000000000000000000000000000000000000000000000919050565b8151602014611c1a57816040517f953576f70000000000000000000000000000000000000000000000000000000081526004016109789190613395565b600082806020019051810190611c309190613f57565b905060ff81111561068f57826040517f953576f70000000000000000000000000000000000000000000000000000000081526004016109789190613395565b60007f000000000000000000000000000000000000000000000000000000000000000060ff168260ff1603611ca557508161068f565b7f000000000000000000000000000000000000000000000000000000000000000060ff168260ff161115611d90576000611cff7f000000000000000000000000000000000000000000000000000000000000000084613f9f565b9050604d8160ff161115611d73576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f000000000000000000000000000000000000000000000000000000000000000016602482015260448101859052606401610978565b611d7e81600a6140d8565b611d8890856140e7565b91505061068f565b6000611dbc837f0000000000000000000000000000000000000000000000000000000000000000613f9f565b9050604d8160ff161180611e035750611dd681600a6140d8565b611e00907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6140e7565b84115b15611e6e576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f000000000000000000000000000000000000000000000000000000000000000016602482015260448101859052606401610978565b611e7981600a6140d8565b6108a69085614122565b600081815260018301602052604081205415155b9392505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611eef576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b7f0000000000000000000000000000000000000000000000000000000000000000611f48576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015611fde576000838281518110611f6857611f68613a25565b60200260200101519050611f868160026128fe90919063ffffffff16565b15611fd55760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101611f4b565b5060005b81518110156109c1576000828281518110611fff57611fff613a25565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612043575061209f565b61204e600282612920565b1561209d5760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611fe2565b80516000036120e2576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160208083019190912067ffffffffffffffff841660009081526007909252604090912061211490600501826126c1565b61214e5782826040517f393b8ad2000000000000000000000000000000000000000000000000000000008152600401610978929190614139565b60008181526008602052604090206121668382613d87565b508267ffffffffffffffff167f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea83604051610fe69190613395565b6121aa83610b15565b6121ec576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610978565b6121f7826000612584565b67ffffffffffffffff8316600090815260076020526040902061221a9083612942565b612225816000612584565b67ffffffffffffffff8316600090815260076020526040902061224b9060020182612942565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b83838360405161227e9392919061415c565b60405180910390a1505050565b61229e61029e60a08301608084016133ca565b6122b2576119ae60a08201608083016133ca565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb6122fe604084016020850161357b565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa15801561236f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123939190613f3a565b156123ca576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6123e26123dd60608301604084016133ca565b612ae4565b6123fa6123f5604083016020840161357b565b612b63565b61198461240d604083016020840161357b565b8260600135612cb1565b6040517f9dc29fac000000000000000000000000000000000000000000000000000000008152306004820152602481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639dc29fac90604401600060405180830381600087803b1580156124a557600080fd5b505af115801561196c573d6000803e3d6000fd5b60606000611e9783612cf5565b6000611e978383612d50565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915261256082606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff164261254491906141df565b85608001516fffffffffffffffffffffffffffffffff16612e43565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b81511561264f5781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff161015806125da575060408201516fffffffffffffffffffffffffffffffff16155b1561261357816040517f8020d12400000000000000000000000000000000000000000000000000000000815260040161097891906141f2565b801561264b576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60408201516fffffffffffffffffffffffffffffffff16151580612688575060208201516fffffffffffffffffffffffffffffffff1615155b1561264b57816040517fd68af9cc00000000000000000000000000000000000000000000000000000000815260040161097891906141f2565b6000611e978383612e6b565b3373ffffffffffffffffffffffffffffffffffffffff82160361271c576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61279a81610b15565b6127dc576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610978565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa15801561285b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061287f9190613f3a565b611984576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610978565b67ffffffffffffffff8216600090815260076020526040902061264b90600201827f0000000000000000000000000000000000000000000000000000000000000000612eba565b6000611e978373ffffffffffffffffffffffffffffffffffffffff8416612d50565b6000611e978373ffffffffffffffffffffffffffffffffffffffff8416612e6b565b815460009061296b90700100000000000000000000000000000000900463ffffffff16426141df565b90508015612a0d57600183015483546129b3916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612e43565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612a33916fffffffffffffffffffffffffffffffff908116911661323d565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c199061227e9084906141f2565b7f00000000000000000000000000000000000000000000000000000000000000001561198457612b15600282613253565b611984576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610978565b612b6c81610b15565b612bae576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610978565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015612c27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c4b919061422e565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611984576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610978565b67ffffffffffffffff8216600090815260076020526040902061264b90827f0000000000000000000000000000000000000000000000000000000000000000612eba565b60608160000180548060200260200160405190810160405280929190818152602001828054801561116c57602002820191906000526020600020905b815481526020019060010190808311612d315750505050509050919050565b60008181526001830160205260408120548015612e39576000612d746001836141df565b8554909150600090612d88906001906141df565b9050808214612ded576000866000018281548110612da857612da8613a25565b9060005260206000200154905080876000018481548110612dcb57612dcb613a25565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612dfe57612dfe61424b565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061068f565b600091505061068f565b6000612e6285612e538486614122565b612e5d908761427a565b61323d565b95945050505050565b6000818152600183016020526040812054612eb25750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561068f565b50600061068f565b825474010000000000000000000000000000000000000000900460ff161580612ee1575081155b15612eeb57505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090612f3190700100000000000000000000000000000000900463ffffffff16426141df565b90508015612ff15781831115612f73576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154612fad9083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612e43565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156130a85773ffffffffffffffffffffffffffffffffffffffff8416613050576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610978565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610978565b848310156131bb5760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906130ec90826141df565b6130f6878a6141df565b613100919061427a565b61310a91906140e7565b905073ffffffffffffffffffffffffffffffffffffffff8616613163576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610978565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610978565b6131c585846141df565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b600081831061324c5781611e97565b5090919050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515611e97565b50805461328e90613a70565b6000825580601f1061329e575050565b601f01602090049060005260206000209081019061198491906132d6565b508054600082559060005260206000209081019061198491905b5b808211156132eb57600081556001016132d7565b5090565b60006020828403121561330157600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611e9757600080fd5b6000815180845260005b818110156133575760208185018101518683018201520161333b565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611e976020830184613331565b73ffffffffffffffffffffffffffffffffffffffff8116811461198457600080fd5b6000602082840312156133dc57600080fd5b8135611e97816133a8565b6000602082840312156133f957600080fd5b813567ffffffffffffffff81111561341057600080fd5b82016101008185031215611e9757600080fd5b803567ffffffffffffffff8116811461343b57600080fd5b919050565b60008060006040848603121561345557600080fd5b61345e84613423565b9250602084013567ffffffffffffffff8082111561347b57600080fd5b818601915086601f83011261348f57600080fd5b81358181111561349e57600080fd5b8760208285010111156134b057600080fd5b6020830194508093505050509250925092565b60008083601f8401126134d557600080fd5b50813567ffffffffffffffff8111156134ed57600080fd5b6020830191508360208260051b850101111561350857600080fd5b9250929050565b6000806000806040858703121561352557600080fd5b843567ffffffffffffffff8082111561353d57600080fd5b613549888389016134c3565b9096509450602087013591508082111561356257600080fd5b5061356f878288016134c3565b95989497509550505050565b60006020828403121561358d57600080fd5b611e9782613423565b60008083601f8401126135a857600080fd5b50813567ffffffffffffffff8111156135c057600080fd5b60208301915083602060608302850101111561350857600080fd5b600080600080600080606087890312156135f457600080fd5b863567ffffffffffffffff8082111561360c57600080fd5b6136188a838b016134c3565b9098509650602089013591508082111561363157600080fd5b61363d8a838b01613596565b9096509450604089013591508082111561365657600080fd5b5061366389828a01613596565b979a9699509497509295939492505050565b60006020828403121561368757600080fd5b813567ffffffffffffffff81111561369e57600080fd5b820160a08185031215611e9757600080fd5b6020815260008251604060208401526136cc6060840182613331565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612e628282613331565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561377c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261376a858351613331565b94509285019290850190600101613730565b5092979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156137d757835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016137a5565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b818110156137d757835167ffffffffffffffff16835292840192918401916001016137ff565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561387757613877613825565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156138c4576138c4613825565b604052919050565b801515811461198457600080fd5b80356fffffffffffffffffffffffffffffffff8116811461343b57600080fd5b60006060828403121561390c57600080fd5b6040516060810181811067ffffffffffffffff8211171561392f5761392f613825565b6040529050808235613940816138cc565b815261394e602084016138da565b602082015261395f604084016138da565b60408201525092915050565b600080600060e0848603121561398057600080fd5b61398984613423565b925061399885602086016138fa565b91506139a785608086016138fa565b90509250925092565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126139e557600080fd5b83018035915067ffffffffffffffff821115613a0057600080fd5b60200191503681900382131561350857600080fd5b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060608284031215613a6657600080fd5b611e9783836138fa565b600181811c90821680613a8457607f821691505b602082108103613abd577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b67ffffffffffffffff84168152604060208201526000612e62604083018486613ac3565b6020815260006108a6602083018486613ac3565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee1833603018112613b7857600080fd5b9190910192915050565b600082601f830112613b9357600080fd5b813567ffffffffffffffff811115613bad57613bad613825565b613bde60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161387d565b818152846020838601011115613bf357600080fd5b816020850160208301376000918101602001919091529392505050565b60006101208236031215613c2357600080fd5b613c2b613854565b613c3483613423565b815260208084013567ffffffffffffffff80821115613c5257600080fd5b9085019036601f830112613c6557600080fd5b813581811115613c7757613c77613825565b8060051b613c8685820161387d565b9182528381018501918581019036841115613ca057600080fd5b86860192505b83831015613cdc57823585811115613cbe5760008081fd5b613ccc3689838a0101613b82565b8352509186019190860190613ca6565b8087890152505050506040860135925080831115613cf957600080fd5b5050613d0736828601613b82565b604083015250613d1a36606085016138fa565b6060820152613d2c3660c085016138fa565b608082015292915050565b601f8211156109c1576000816000526020600020601f850160051c81016020861015613d605750805b601f850160051c820191505b81811015613d7f57828155600101613d6c565b505050505050565b815167ffffffffffffffff811115613da157613da1613825565b613db581613daf8454613a70565b84613d37565b602080601f831160018114613e085760008415613dd25750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613d7f565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613e5557888601518255948401946001909101908401613e36565b5085821015613e9157878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff87168352806020840152613ec581840187613331565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff9081166060870152908701511660808501529150613f039050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612e62565b600060208284031215613f4c57600080fd5b8151611e97816138cc565b600060208284031215613f6957600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff828116828216039081111561068f5761068f613f70565b600181815b8085111561401157817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613ff757613ff7613f70565b8085161561400457918102915b93841c9390800290613fbd565b509250929050565b6000826140285750600161068f565b816140355750600061068f565b816001811461404b576002811461405557614071565b600191505061068f565b60ff84111561406657614066613f70565b50506001821b61068f565b5060208310610133831016604e8410600b8410161715614094575081810a61068f565b61409e8383613fb8565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156140d0576140d0613f70565b029392505050565b6000611e9760ff841683614019565b60008261411d577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808202811582820484141761068f5761068f613f70565b67ffffffffffffffff831681526040602082015260006108a66040830184613331565b67ffffffffffffffff8416815260e081016141a860208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c08301526108a6565b8181038181111561068f5761068f613f70565b6060810161068f82848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561424057600080fd5b8151611e97816133a8565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8082018082111561068f5761068f613f7056fea164736f6c6343000818000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"contractIBurnMintERC20\"},{\"name\":\"localTokenDecimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"allowlist\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"rmnProxy\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"router\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"acceptOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"addRemotePool\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyAllowListUpdates\",\"inputs\":[{\"name\":\"removes\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"adds\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyChainUpdates\",\"inputs\":[{\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"},{\"name\":\"chainsToAdd\",\"type\":\"tuple[]\",\"internalType\":\"structTokenPool.ChainUpdate[]\",\"components\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"},{\"name\":\"remoteTokenAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getAllowList\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getAllowListEnabled\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCurrentInboundRateLimiterState\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.TokenBucket\",\"components\":[{\"name\":\"tokens\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"lastUpdated\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCurrentOutboundRateLimiterState\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.TokenBucket\",\"components\":[{\"name\":\"tokens\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"lastUpdated\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRateLimitAdmin\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRemotePools\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRemoteToken\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRmnProxy\",\"inputs\":[],\"outputs\":[{\"name\":\"rmnProxy\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRouter\",\"inputs\":[],\"outputs\":[{\"name\":\"router\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getSupportedChains\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getToken\",\"inputs\":[],\"outputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"contractIERC20\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTokenDecimals\",\"inputs\":[],\"outputs\":[{\"name\":\"decimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isRemotePool\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isSupportedChain\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isSupportedToken\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"lockOrBurn\",\"inputs\":[{\"name\":\"lockOrBurnIn\",\"type\":\"tuple\",\"internalType\":\"structPool.LockOrBurnInV1\",\"components\":[{\"name\":\"receiver\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"originalSender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"localToken\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structPool.LockOrBurnOutV1\",\"components\":[{\"name\":\"destTokenAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"destPoolData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"releaseOrMint\",\"inputs\":[{\"name\":\"releaseOrMintIn\",\"type\":\"tuple\",\"internalType\":\"structPool.ReleaseOrMintInV1\",\"components\":[{\"name\":\"originalSender\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"receiver\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"localToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"sourcePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"sourcePoolData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"offchainTokenData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"components\":[{\"name\":\"destinationAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"removeRemotePool\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setChainRateLimiterConfig\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"outboundConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setChainRateLimiterConfigs\",\"inputs\":[{\"name\":\"remoteChainSelectors\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"},{\"name\":\"outboundConfigs\",\"type\":\"tuple[]\",\"internalType\":\"structRateLimiter.Config[]\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundConfigs\",\"type\":\"tuple[]\",\"internalType\":\"structRateLimiter.Config[]\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setRateLimitAdmin\",\"inputs\":[{\"name\":\"rateLimitAdmin\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setRouter\",\"inputs\":[{\"name\":\"newRouter\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"typeAndVersion\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"pure\"},{\"type\":\"event\",\"name\":\"AllowListAdd\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"AllowListRemove\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Burned\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChainAdded\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"remoteToken\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"},{\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChainConfigured\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChainRemoved\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ConfigChanged\",\"inputs\":[{\"name\":\"config\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Locked\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Minted\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferRequested\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RateLimitAdminSet\",\"inputs\":[{\"name\":\"rateLimitAdmin\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Released\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RemotePoolAdded\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RemotePoolRemoved\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RouterUpdated\",\"inputs\":[{\"name\":\"oldRouter\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"newRouter\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TokensConsumed\",\"inputs\":[{\"name\":\"tokens\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AggregateValueMaxCapacityExceeded\",\"inputs\":[{\"name\":\"capacity\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"requested\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"AggregateValueRateLimitReached\",\"inputs\":[{\"name\":\"minWaitInSeconds\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"available\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"AllowListNotEnabled\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BucketOverfilled\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CallerIsNotARampOnRouter\",\"inputs\":[{\"name\":\"caller\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"CannotTransferToSelf\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ChainAlreadyExists\",\"inputs\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"ChainNotAllowed\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"CursedByRMN\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"DisabledNonZeroRateLimit\",\"inputs\":[{\"name\":\"config\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}]},{\"type\":\"error\",\"name\":\"InvalidDecimalArgs\",\"inputs\":[{\"name\":\"expected\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"actual\",\"type\":\"uint8\",\"internalType\":\"uint8\"}]},{\"type\":\"error\",\"name\":\"InvalidRateLimitRate\",\"inputs\":[{\"name\":\"rateLimiterConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}]},{\"type\":\"error\",\"name\":\"InvalidRemoteChainDecimals\",\"inputs\":[{\"name\":\"sourcePoolData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidRemotePoolForChain\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidSourcePoolAddress\",\"inputs\":[{\"name\":\"sourcePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidToken\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"MismatchedArrayLengths\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MustBeProposedOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NonExistentChain\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"OnlyCallableByOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OverflowDetected\",\"inputs\":[{\"name\":\"remoteDecimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"localDecimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"remoteAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"OwnerCannotBeZero\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PoolAlreadyAdded\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"RateLimitMustBeDisabled\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"SenderNotAllowed\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"TokenMaxCapacityExceeded\",\"inputs\":[{\"name\":\"capacity\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"requested\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"tokenAddress\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"TokenRateLimitReached\",\"inputs\":[{\"name\":\"minWaitInSeconds\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"available\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"tokenAddress\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"Unauthorized\",\"inputs\":[{\"name\":\"caller\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ZeroAddressNotAllowed\",\"inputs\":[]}]", + Bin: "0x610100806040523461035457614bb5803803809161001d82856105b2565b8339810160a0828203126103545781516001600160a01b03811692908390036103545761004c602082016105d5565b60408201516001600160401b0381116103545782019280601f85011215610354578351936001600160401b038511610359578460051b90602082019561009560405197886105b2565b865260208087019282010192831161035457602001905b82821061059a575050506100ce60806100c7606085016105e3565b93016105e3565b91331561058957600180546001600160a01b0319163317905584158015610578575b8015610567575b61055657608085905260c05260405163313ce56760e01b8152602081600481885afa6000918161051a575b506104ef575b5060a052600480546001600160a01b0319166001600160a01b03929092169190911790558051151560e08190526103d2575b50604051636eb1769f60e11b81523060048201819052602482015290602082604481845afa9182156103c657600092610392575b50600019820180921161037c57604051602081019263095ea7b360e01b84523060248301526044820152604481526101c76064826105b2565b6000806040948551936101da87866105b2565b602085527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65646020860152519082865af13d1561036f573d906001600160401b03821161035957845161024b94909261023c601f8201601f1916602001856105b2565b83523d6000602085013e610781565b8051806102d9575b8251614363908161085282396080518181816115fc015281816117e80152818161220e015281816123ea01528181612707015261277f015260a0518181816118a90152818161268e0152818161316801526131eb015260c051818181610bd50152818161169801526122a9015260e051818181610b65015281816116db01526120050152f35b81602091810103126103545760200151801590811503610354576102fe573880610253565b5162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608490fd5b600080fd5b634e487b7160e01b600052604160045260246000fd5b9161024b92606091610781565b634e487b7160e01b600052601160045260246000fd5b9091506020813d6020116103be575b816103ae602093836105b2565b810103126103545751903861018e565b3d91506103a1565b6040513d6000823e3d90fd5b60206040516103e182826105b2565b60008152600036813760e051156104de5760005b815181101561045c576001906001600160a01b0361041382856105f7565b51168461041f82610639565b61042c575b5050016103f5565b7f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf756691604051908152a13884610424565b505060005b82518110156104d5576001906001600160a01b0361047f82866105f7565b511680156104cf578361049182610721565b61049f575b50505b01610461565b7f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d891604051908152a13883610496565b50610499565b5050503861015a565b6335f4a7b360e01b60005260046000fd5b60ff1660ff82168181036105035750610128565b6332ad3e0760e11b60005260045260245260446000fd5b9091506020813d60201161054e575b81610536602093836105b2565b8101031261035457610547906105d5565b9038610122565b3d9150610529565b6342bcdf7f60e11b60005260046000fd5b506001600160a01b038116156100f7565b506001600160a01b038316156100f0565b639b15e16f60e01b60005260046000fd5b602080916105a7846105e3565b8152019101906100ac565b601f909101601f19168101906001600160401b0382119082101761035957604052565b519060ff8216820361035457565b51906001600160a01b038216820361035457565b805182101561060b5760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b805482101561060b5760005260206000200190600090565b600081815260036020526040902054801561071a57600019810181811161037c5760025460001981019190821161037c578181036106c9575b50505060025480156106b3576000190161068d816002610621565b8154906000199060031b1b19169055600255600052600360205260006040812055600190565b634e487b7160e01b600052603160045260246000fd5b6107026106da6106eb936002610621565b90549060031b1c9283926002610621565b819391549060031b91821b91600019901b19161790565b90556000526003602052604060002055388080610672565b5050600090565b8060005260036020526040600020541560001461077b5760025468010000000000000000811015610359576107626106eb8260018594016002556002610621565b9055600254906000526003602052604060002055600190565b50600090565b919290156107e35750815115610795575090565b3b1561079e5790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b8251909150156107f65750805190602001fd5b6040519062461bcd60e51b8252602060048301528181519182602483015260005b8381106108395750508160006044809484010152601f80199101168101030190fd5b6020828201810151604487840101528593500161081756fe608080604052600436101561001357600080fd5b600090813560e01c90816301ffc9a71461282257508063181f5a77146127a357806321df0da714612734578063240028e8146126b257806324f65ee71461265657806339077537146121685780634c5ef0ed1461214e57806354c8a4f314611fd157806362ddd3c414611f4d5780636d3d1a5814611efb57806379ba509714611e165780637d54534e14611d695780638926f54f14611d055780638da5cb5b14611cb3578063962d402014611b0f5780639a4575b914611554578063a42a7b8b146113cf578063a7cd63b714611303578063acfecf91146111df578063af58d59f14611178578063b0f479a114611126578063b7946580146110cf578063c0d7865514610fd7578063c4bffe2b14610e8e578063c75eea9c14610dc8578063cf7401f314610bf9578063dc0bd97114610b8a578063e0351e1314610b2f578063e8a1da171461025a5763f2fde38b1461016b57600080fd5b346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575773ffffffffffffffffffffffffffffffffffffffff6101b7612970565b6101bf6132f5565b1633811461022f57807fffffffffffffffffffffffff000000000000000000000000000000000000000083541617825573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12788380a380f35b6004827fdad89dca000000000000000000000000000000000000000000000000000000008152fd5b80fd5b50346102575761026936612a5e565b939190926102756132f5565b82915b80831061099a575050508063ffffffff4216917ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee1843603015b85821015610996578160051b85013581811215610992578501906101208236031261099257604051956102e387612b66565b823567ffffffffffffffff8116810361098d578752602083013567ffffffffffffffff81116109895783019536601f880112156109895786359661032688612d6a565b97610334604051998a612b9e565b8089526020808a019160051b830101903682116109855760208301905b828210610952575050505060208801968752604084013567ffffffffffffffff811161094e5761038490369086016130c2565b9860408901998a526103ae61039c3660608801612bfc565b9560608b0196875260c0369101612bfc565b9660808a019788526103c0865161376c565b6103ca885161376c565b8a515115610926576103e667ffffffffffffffff8b5116613fbf565b156108ef5767ffffffffffffffff8a5116815260076020526040812061052687516fffffffffffffffffffffffffffffffff604082015116906104e16fffffffffffffffffffffffffffffffff6020830151169151151583608060405161044c81612b66565b858152602081018c905260408101849052606081018690520152855474ff000000000000000000000000000000000000000091151560a01b919091167fffffffffffffffffffffff0000000000000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff84161773ffffffff0000000000000000000000000000000060808b901b1617178555565b60809190911b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff91909116176001830155565b61064c89516fffffffffffffffffffffffffffffffff604082015116906106076fffffffffffffffffffffffffffffffff6020830151169151151583608060405161057081612b66565b858152602081018c9052604081018490526060810186905201526002860180547fffffffffffffffffffffff000000000000000000000000000000000000000000166fffffffffffffffffffffffffffffffff85161773ffffffff0000000000000000000000000000000060808c901b161791151560a01b74ff000000000000000000000000000000000000000016919091179055565b60809190911b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff91909116176003830155565b60048c5191019080519067ffffffffffffffff82116108c25761066f8354612e62565b601f8111610887575b50602090601f83116001146107e8576106c692918591836107dd575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b90555b805b8951805182101561070157906106fb6001926106f4838f67ffffffffffffffff90511692612e4e565b5190613340565b016106cb565b5050975097987f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c2929593966107cf67ffffffffffffffff600197949c511692519351915161079b61076660405196879687526101006020880152610100870190612911565b9360408601906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b60a08401906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b0390a10190939492916102b1565b015190503880610694565b83855281852091907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08416865b81811061086f5750908460019594939210610838575b505050811b0190556106c9565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c1916905538808061082b565b92936020600181928786015181550195019301610815565b6108b29084865260208620601f850160051c810191602086106108b8575b601f0160051c0190613069565b38610678565b90915081906108a5565b6024847f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b60249067ffffffffffffffff8b51167f1d5ad3c5000000000000000000000000000000000000000000000000000000008252600452fd5b807f8579befe0000000000000000000000000000000000000000000000000000000060049252fd5b8680fd5b813567ffffffffffffffff81116109815760209161097683928336918901016130c2565b815201910190610351565b8a80fd5b8880fd5b8580fd5b600080fd5b8380fd5b8280f35b9092919367ffffffffffffffff6109ba6109b5878588612dea565b612e29565b16956109c587613cf3565b15610b035786845260076020526109e160056040862001613afa565b94845b8651811015610a1a576001908987526007602052610a1360056040892001610a0c838b612e4e565b5190613e1e565b50016109e4565b5093945094909580855260076020526005604086208681558660018201558660028201558660038201558660048201610a538154612e62565b80610ac2575b5050500180549086815581610aa4575b5050907f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599166020600193604051908152a1019190949394610278565b865260208620908101905b81811015610a6957868155600101610aaf565b601f8111600114610ad85750555b863880610a59565b81835260208320610af391601f01861c810190600101613069565b8082528160208120915555610ad0565b602484887f1e670e4b000000000000000000000000000000000000000000000000000000008252600452fd5b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575760206040517f000000000000000000000000000000000000000000000000000000000000000015158152f35b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346102575760e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757610c31612993565b9060607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36011261025757604051610c6881612b82565b6024358015158103610dc45781526044356fffffffffffffffffffffffffffffffff81168103610dc45760208201526064356fffffffffffffffffffffffffffffffff81168103610dc457604082015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7c360112610dc05760405190610cef82612b82565b608435801515810361099257825260a4356fffffffffffffffffffffffffffffffff8116810361099257602083015260c4356fffffffffffffffffffffffffffffffff8116810361099257604083015273ffffffffffffffffffffffffffffffffffffffff6009541633141580610d9e575b610d7257610d6f92936135aa565b80f35b6024837f8e4a23d600000000000000000000000000000000000000000000000000000000815233600452fd5b5073ffffffffffffffffffffffffffffffffffffffff60015416331415610d61565b5080fd5b8280fd5b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757610e31610e2c6040610e8a9367ffffffffffffffff610e15612993565b610e1d612fb6565b50168152600760205220612fe1565b6136e7565b6040519182918291909160806fffffffffffffffffffffffffffffffff8160a084019582815116855263ffffffff6020820151166020860152604081015115156040860152826060820151166060860152015116910152565b0390f35b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757604051906005548083528260208101600584526020842092845b818110610fbe575050610eec92500383612b9e565b8151610f10610efa82612d6a565b91610f086040519384612b9e565b808352612d6a565b917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0602083019301368437805b8451811015610f6f578067ffffffffffffffff610f5c60019388612e4e565b5116610f688286612e4e565b5201610f3d565b50925090604051928392602084019060208552518091526040840192915b818110610f9b575050500390f35b825167ffffffffffffffff16845285945060209384019390920191600101610f8d565b8454835260019485019487945060209093019201610ed7565b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575773ffffffffffffffffffffffffffffffffffffffff611024612970565b61102c6132f5565b1680156110a75760407f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f16849160045490807fffffffffffffffffffffffff000000000000000000000000000000000000000083161760045573ffffffffffffffffffffffffffffffffffffffff8351921682526020820152a180f35b6004827f8579befe000000000000000000000000000000000000000000000000000000008152fd5b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757610e8a61111261110d612993565b613047565b604051918291602083526020830190612911565b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602073ffffffffffffffffffffffffffffffffffffffff60045416604051908152f35b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757610e31610e2c60026040610e8a9467ffffffffffffffff6111c7612993565b6111cf612fb6565b5016815260076020522001612fe1565b50346102575767ffffffffffffffff6111f7366129aa565b9290916112026132f5565b169161121b836000526006602052604060002054151590565b156112d757828452600760205261124a6005604086200161123d368486612c99565b6020815191012090613e1e565b1561128f57907f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d7691611289604051928392602084526020840191612f77565b0390a280f35b826112d3836040519384937f74f23c7c0000000000000000000000000000000000000000000000000000000085526004850152604060248501526044840191612f77565b0390fd5b602484847f1e670e4b000000000000000000000000000000000000000000000000000000008252600452fd5b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757604051600254808252602082018091600285526020852090855b8181106113b95750505082611362910383612b9e565b604051928392602084019060208552518091526040840192915b81811061138a575050500390f35b825173ffffffffffffffffffffffffffffffffffffffff1684528594506020938401939092019160010161137c565b825484526020909301926001928301920161134c565b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575767ffffffffffffffff611410612993565b168152600760205261142760056040832001613afa565b80517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061146c61145683612d6a565b926114646040519485612b9e565b808452612d6a565b01835b818110611543575050825b82518110156114c0578061149060019285612e4e565b51855260086020526114a460408620612eb5565b6114ae8285612e4e565b526114b98184612e4e565b500161147a565b81846040519182916020830160208452825180915260408401602060408360051b870101940192905b8282106114f857505050500390f35b91936020611533827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc060019597998495030186528851612911565b96019201920185949391926114e9565b80606060208093860101520161146f565b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575760043567ffffffffffffffff8111610dc05760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8236030112610dc057606060206040516115d281612b4a565b8281520152608481016115e481612cfe565b73ffffffffffffffffffffffffffffffffffffffff807f000000000000000000000000000000000000000000000000000000000000000016911603611ac55750602481019177ffffffffffffffff0000000000000000000000000000000061164b84612e29565b60801b16604051907f2cbc26bb000000000000000000000000000000000000000000000000000000008252600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa908115611955578291611a96575b50611a6e576116d960448301612cfe565b7f0000000000000000000000000000000000000000000000000000000000000000611a1b575b5067ffffffffffffffff61171284612e29565b1661172a816000526006602052604060002054151590565b156119ef57602073ffffffffffffffffffffffffffffffffffffffff60045416916024604051809481937fa8d87a3b00000000000000000000000000000000000000000000000000000000835260048301525afa801561195557829061198c575b73ffffffffffffffffffffffffffffffffffffffff91501633036119605767ffffffffffffffff60646117bd85612e29565b930135921681526007602052816118106040832073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001692839161406e565b803b15610dc0576040517f9dc29fac000000000000000000000000000000000000000000000000000000008152306004820152602481018490529082908290604490829084905af1801561195557611940575b61190f61189f61110d86866040519081527f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df760203392a2612e29565b610e8a60405160ff7f0000000000000000000000000000000000000000000000000000000000000000166020820152602081526118dd604082612b9e565b604051926118ea84612b4a565b8352602083019081526040519384936020855251604060208601526060850190612911565b90517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612911565b61194b828092612b9e565b6102575780611863565b6040513d84823e3d90fd5b807f728fe07b000000000000000000000000000000000000000000000000000000006024925233600452fd5b506020813d6020116119e7575b816119a660209383612b9e565b81010312610dc0575173ffffffffffffffffffffffffffffffffffffffff81168103610dc05773ffffffffffffffffffffffffffffffffffffffff9061178b565b3d9150611999565b602492507fa9902c7e000000000000000000000000000000000000000000000000000000008252600452fd5b73ffffffffffffffffffffffffffffffffffffffff16808252600360205260408220546116ff57602492507fd0d25976000000000000000000000000000000000000000000000000000000008252600452fd5b807f53ad11d80000000000000000000000000000000000000000000000000000000060049252fd5b611ab8915060203d602011611abe575b611ab08183612b9e565b8101906130dd565b386116c8565b503d611aa6565b8273ffffffffffffffffffffffffffffffffffffffff611ae6602493612cfe565b7f961c9a4f00000000000000000000000000000000000000000000000000000000835216600452fd5b50346102575760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575760043567ffffffffffffffff8111610dc057611b5f903690600401612a2d565b60243567ffffffffffffffff811161099257611b7f903690600401612ace565b60449291923567ffffffffffffffff811161098957611ba2903690600401612ace565b91909273ffffffffffffffffffffffffffffffffffffffff6009541633141580611c91575b611c6557818114801590611c5b575b611c3357865b818110611be7578780f35b80611c2d611bfb6109b5600194868c612dea565b611c0683878b612e3e565b611c27611c1f611c17868b8d612e3e565b923690612bfc565b913690612bfc565b916135aa565b01611bdc565b6004877f568efce2000000000000000000000000000000000000000000000000000000008152fd5b5082811415611bd6565b6024877f8e4a23d600000000000000000000000000000000000000000000000000000000815233600452fd5b5073ffffffffffffffffffffffffffffffffffffffff60015416331415611bc7565b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610257576020611d5f67ffffffffffffffff611d4b612993565b166000526006602052604060002054151590565b6040519015158152f35b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610257577f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d09174602073ffffffffffffffffffffffffffffffffffffffff611dd9612970565b611de16132f5565b16807fffffffffffffffffffffffff00000000000000000000000000000000000000006009541617600955604051908152a180f35b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757805473ffffffffffffffffffffffffffffffffffffffff81163303611ed3577fffffffffffffffffffffffff000000000000000000000000000000000000000060015491338284161760015516825573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b6004827f02b543c6000000000000000000000000000000000000000000000000000000008152fd5b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602073ffffffffffffffffffffffffffffffffffffffff60095416604051908152f35b503461025757611f5c366129aa565b611f68939291936132f5565b67ffffffffffffffff8216611f8a816000526006602052604060002054151590565b15611fa65750610d6f9293611fa0913691612c99565b90613340565b7f1e670e4b000000000000000000000000000000000000000000000000000000008452600452602483fd5b503461025757611ffb90612003611fe736612a5e565b9591611ff49391936132f5565b3691612d82565b933691612d82565b7f00000000000000000000000000000000000000000000000000000000000000001561212657815b835181101561209e578073ffffffffffffffffffffffffffffffffffffffff61205660019387612e4e565b511661206181613b5d565b61206d575b500161202b565b60207f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf756691604051908152a138612066565b5090805b8251811015612122578073ffffffffffffffffffffffffffffffffffffffff6120cd60019386612e4e565b5116801561211c576120de81613f5f565b6120eb575b505b016120a2565b60207f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d891604051908152a1846120e3565b506120e5565b5080f35b6004827f35f4a7b3000000000000000000000000000000000000000000000000000000008152fd5b5034610257576020611d5f612162366129aa565b91612d1f565b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575760043567ffffffffffffffff8111610dc057806004016101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8336030112610dc457826040516121e881612aff565b52608482016121f681612cfe565b73ffffffffffffffffffffffffffffffffffffffff807f00000000000000000000000000000000000000000000000000000000000000001691160361263557506024820177ffffffffffffffff0000000000000000000000000000000061225c82612e29565b60801b16604051907f2cbc26bb000000000000000000000000000000000000000000000000000000008252600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9081156125b8578591612616575b506125ee5767ffffffffffffffff6122f082612e29565b16612308816000526006602052604060002054151590565b156125c357602073ffffffffffffffffffffffffffffffffffffffff60045416916044604051809481937f83826b2b00000000000000000000000000000000000000000000000000000000835260048301523360248301525afa9081156125b8578591612599575b501561256d5761237f81612e29565b61239160a48501916121628386612c48565b15612526575061242e67ffffffffffffffff9261242861242361241c6123b8604496612e29565b936064890135978895168a526007602052612412600260408c200173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016998a9161406e565b60c4890190612c48565b3691612c99565b6130f5565b906131e8565b9201908361243b83612cfe565b823b15610dc0576040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91909116600482015260248101859052918290604490829084905af1801561251b57916020946124c99273ffffffffffffffffffffffffffffffffffffffff9461250b575b5050612cfe565b166040518281527f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f0843392a38060405161250281612aff565b52604051908152f35b8161251591612b9e565b386124c2565b6040513d86823e3d90fd5b6125309083612c48565b6112d36040519283927f24eb47e5000000000000000000000000000000000000000000000000000000008452602060048501526024840191612f77565b6024847f728fe07b00000000000000000000000000000000000000000000000000000000815233600452fd5b6125b2915060203d602011611abe57611ab08183612b9e565b38612370565b6040513d87823e3d90fd5b7fa9902c7e000000000000000000000000000000000000000000000000000000008552600452602484fd5b6004847f53ad11d8000000000000000000000000000000000000000000000000000000008152fd5b61262f915060203d602011611abe57611ab08183612b9e565b386122d9565b8373ffffffffffffffffffffffffffffffffffffffff611ae6602493612cfe565b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602060405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610257576020906126ed612970565b905073ffffffffffffffffffffffffffffffffffffffff807f0000000000000000000000000000000000000000000000000000000000000000169116146040519015158152f35b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575750610e8a6040516127e4604082612b9e565b601f81527f4275726e5769746846726f6d4d696e74546f6b656e506f6f6c20312e352e31006020820152604051918291602083526020830190612911565b905034610dc05760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610dc0576004357fffffffff000000000000000000000000000000000000000000000000000000008116809103610dc457602092507faff2afbf0000000000000000000000000000000000000000000000000000000081149081156128e7575b81156128bd575b5015158152f35b7f01ffc9a700000000000000000000000000000000000000000000000000000000915014386128b6565b7f0e64dd2900000000000000000000000000000000000000000000000000000000811491506128af565b919082519283825260005b84811061295b5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b8060208092840101518282860101520161291c565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361098d57565b6004359067ffffffffffffffff8216820361098d57565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82011261098d5760043567ffffffffffffffff8116810361098d579160243567ffffffffffffffff811161098d578260238201121561098d5780600401359267ffffffffffffffff841161098d576024848301011161098d576024019190565b9181601f8401121561098d5782359167ffffffffffffffff831161098d576020808501948460051b01011161098d57565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82011261098d5760043567ffffffffffffffff811161098d5781612aa791600401612a2d565b929092916024359067ffffffffffffffff821161098d57612aca91600401612a2d565b9091565b9181601f8401121561098d5782359167ffffffffffffffff831161098d576020808501946060850201011161098d57565b6020810190811067ffffffffffffffff821117612b1b57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040810190811067ffffffffffffffff821117612b1b57604052565b60a0810190811067ffffffffffffffff821117612b1b57604052565b6060810190811067ffffffffffffffff821117612b1b57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117612b1b57604052565b35906fffffffffffffffffffffffffffffffff8216820361098d57565b919082606091031261098d57604051612c1481612b82565b8092803590811515820361098d576040612c439181938552612c3860208201612bdf565b602086015201612bdf565b910152565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561098d570180359067ffffffffffffffff821161098d5760200191813603831361098d57565b92919267ffffffffffffffff8211612b1b5760405191612ce1601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200184612b9e565b82948184528183011161098d578281602093846000960137010152565b3573ffffffffffffffffffffffffffffffffffffffff8116810361098d5790565b612d67929167ffffffffffffffff612d4a921660005260076020526005604060002001923691612c99565b602081519101209060019160005201602052604060002054151590565b90565b67ffffffffffffffff8111612b1b5760051b60200190565b9291612d8d82612d6a565b93612d9b6040519586612b9e565b602085848152019260051b810191821161098d57915b818310612dbd57505050565b823573ffffffffffffffffffffffffffffffffffffffff8116810361098d57815260209283019201612db1565b9190811015612dfa5760051b0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b3567ffffffffffffffff8116810361098d5790565b9190811015612dfa576060020190565b8051821015612dfa5760209160051b010190565b90600182811c92168015612eab575b6020831014612e7c57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f1691612e71565b9060405191826000825492612ec984612e62565b8084529360018116908115612f375750600114612ef0575b50612eee92500383612b9e565b565b90506000929192526020600020906000915b818310612f1b575050906020612eee9282010138612ee1565b6020919350806001915483858901015201910190918492612f02565b60209350612eee9592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b82010138612ee1565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b60405190612fc382612b66565b60006080838281528260208201528260408201528260608201520152565b90604051612fee81612b66565b60806001829460ff81546fffffffffffffffffffffffffffffffff8116865263ffffffff81861c16602087015260a01c161515604085015201546fffffffffffffffffffffffffffffffff81166060840152811c910152565b67ffffffffffffffff166000526007602052612d676004604060002001612eb5565b818110613074575050565b60008155600101613069565b8181029291811591840414171561309357565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9080601f8301121561098d57816020612d6793359101612c99565b9081602091031261098d5751801515810361098d5790565b80518015613164576020036131265760208180518101031261098d5760208101519060ff8211613126575060ff1690565b6112d3906040519182917f953576f7000000000000000000000000000000000000000000000000000000008352602060048401526024830190612911565b50507f000000000000000000000000000000000000000000000000000000000000000090565b9060ff8091169116039060ff821161309357565b60ff16604d811161309357600a0a90565b81156131b9570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b907f00000000000000000000000000000000000000000000000000000000000000009060ff82169060ff8116928284146132ee578284116132c4579061322d9161318a565b91604d60ff841611801561328b575b6132555750509061324f612d679261319e565b90613080565b9091507fa9cb113d0000000000000000000000000000000000000000000000000000000060005260045260245260445260646000fd5b506132958361319e565b80156131b9577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04841161323c565b6132cd9161318a565b91604d60ff841611613255575050906132e8612d679261319e565b906131af565b5050505090565b73ffffffffffffffffffffffffffffffffffffffff60015416330361331657565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b908051156135805767ffffffffffffffff81516020830120921691826000526007602052613375816005604060002001614019565b1561353c5760005260086020526040600020815167ffffffffffffffff8111612b1b576133a28254612e62565b601f811161350a575b506020601f8211600114613444579161341e827f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea959361343495600091613439575b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b9055604051918291602083526020830190612911565b0390a2565b9050840151386133ed565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082169083600052806000209160005b8181106134f25750926134349492600192827f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea9896106134bb575b5050811b019055611112565b8501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c1916905538806134af565b9192602060018192868a015181550194019201613474565b61353690836000526020600020601f840160051c810191602085106108b857601f0160051c0190613069565b386133ab565b50906112d36040519283927f393b8ad20000000000000000000000000000000000000000000000000000000084526004840152604060248401526044830190612911565b7f8579befe0000000000000000000000000000000000000000000000000000000060005260046000fd5b67ffffffffffffffff1660008181526006602052604090205490929190156136ac57916136a960e092613675856136017f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b9761376c565b8460005260076020526136188160406000206138c7565b6136218361376c565b84600052600760205261363b8360026040600020016138c7565b60405194855260208501906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b60808301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565ba1565b827f1e670e4b0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b9190820391821161309357565b6136ef612fb6565b506fffffffffffffffffffffffffffffffff6060820151166fffffffffffffffffffffffffffffffff808351169161374c602085019361374661373963ffffffff875116426136da565b8560808901511690613080565b90613f52565b8082101561376557505b16825263ffffffff4216905290565b9050613756565b805115613820576fffffffffffffffffffffffffffffffff6040820151166fffffffffffffffffffffffffffffffff602083015116811090811591613817575b506137b45750565b606490613815604051917f8020d12400000000000000000000000000000000000000000000000000000000835260048301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565bfd5b905015386137ac565b6fffffffffffffffffffffffffffffffff604082015116158015906138a8575b6138475750565b606490613815604051917fd68af9cc00000000000000000000000000000000000000000000000000000000835260048301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b506fffffffffffffffffffffffffffffffff6020820151161515613840565b7f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1991613a00606092805461390463ffffffff8260801c16426136da565b9081613a3f575b50506fffffffffffffffffffffffffffffffff6001816020860151169282815416808510600014613a3757508280855b16167fffffffffffffffffffffffffffffffff000000000000000000000000000000008254161781556139b48651151582907fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff74ff0000000000000000000000000000000000000000835492151560a01b169116179055565b60408601517fffffffffffffffffffffffffffffffff0000000000000000000000000000000060809190911b16939092166fffffffffffffffffffffffffffffffff1692909217910155565b6136a960405180926fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b83809161393b565b6fffffffffffffffffffffffffffffffff91613a74839283613a6d6001880154948286169560801c90613080565b9116613f52565b80821015613af357505b83547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff9290911692909216167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116174260801b73ffffffff0000000000000000000000000000000016178155388061390b565b9050613a7e565b906040519182815491828252602082019060005260206000209260005b818110613b2c575050612eee92500383612b9e565b8454835260019485019487945060209093019201613b17565b8054821015612dfa5760005260206000200190600090565b6000818152600360205260409020548015613cec577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811161309357600254907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820191821161309357818103613c7d575b5050506002548015613c4e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01613c0b816002613b45565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600255600052600360205260006040812055600190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b613cd4613c8e613c9f936002613b45565b90549060031b1c9283926002613b45565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b90556000526003602052604060002055388080613bd2565b5050600090565b6000818152600660205260409020548015613cec577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811161309357600554907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820191821161309357818103613de4575b5050506005548015613c4e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01613da1816005613b45565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600555600052600660205260006040812055600190565b613e06613df5613c9f936005613b45565b90549060031b1c9283926005613b45565b90556000526006602052604060002055388080613d68565b9060018201918160005282602052604060002054801515600014613f49577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101818111613093578254907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820191821161309357818103613f12575b50505080548015613c4e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190613ed38282613b45565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b191690555560005260205260006040812055600190565b613f32613f22613c9f9386613b45565b90549060031b1c92839286613b45565b905560005283602052604060002055388080613e9b565b50505050600090565b9190820180921161309357565b80600052600360205260406000205415600014613fb95760025468010000000000000000811015612b1b57613fa0613c9f8260018594016002556002613b45565b9055600254906000526003602052604060002055600190565b50600090565b80600052600660205260406000205415600014613fb95760055468010000000000000000811015612b1b57614000613c9f8260018594016005556005613b45565b9055600554906000526006602052604060002055600190565b6000828152600182016020526040902054613cec5780549068010000000000000000821015612b1b5782614057613c9f846001809601855584613b45565b905580549260005201602052604060002055600190565b929192805460ff8160a01c1615801561434e575b614347576fffffffffffffffffffffffffffffffff811690600183019081546140c763ffffffff6fffffffffffffffffffffffffffffffff83169360801c16426136da565b90816142a9575b5050848110614227575083821061415657507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a939450906fffffffffffffffffffffffffffffffff8061412485602096956136da565b16167fffffffffffffffffffffffffffffffff00000000000000000000000000000000825416179055604051908152a1565b81945061416892505460801c926136da565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810190808211613093576141b66141bb9273ffffffffffffffffffffffffffffffffffffffff94613f52565b6131af565b92169182156141f7577fd0c8d23a0000000000000000000000000000000000000000000000000000000060005260045260245260445260646000fd5b7f15279c080000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b8473ffffffffffffffffffffffffffffffffffffffff8816918215614279577f1a76572a0000000000000000000000000000000000000000000000000000000060005260045260245260445260646000fd5b7ff94ebcd10000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b82859293951161431d576142c4926137469160801c90613080565b808310156143185750815b83547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff164260801b73ffffffff00000000000000000000000000000000161784559138806140ce565b6142cf565b7f9725942a0000000000000000000000000000000000000000000000000000000060005260046000fd5b5050509050565b50821561408256fea164736f6c634300081a000a", } var BurnWithFromMintTokenPoolABI = BurnWithFromMintTokenPoolMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/ccip_encoding_utils/ccip_encoding_utils.go b/core/gethwrappers/ccip/generated/ccip_encoding_utils/ccip_encoding_utils.go index 208c0e37d63..4e34b55cfcf 100644 --- a/core/gethwrappers/ccip/generated/ccip_encoding_utils/ccip_encoding_utils.go +++ b/core/gethwrappers/ccip/generated/ccip_encoding_utils/ccip_encoding_utils.go @@ -89,7 +89,7 @@ type RMNRemoteReport struct { } var EncodingUtilsMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNRemote.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"commitReport\",\"type\":\"tuple\"}],\"name\":\"exposeCommitReport\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"FRoleDON\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"rmnHomeAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"signerKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"transmitterKey\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Config[]\",\"name\":\"config\",\"type\":\"tuple[]\"}],\"name\":\"exposeOCR3Config\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"rmnReportVersion\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnRemoteContractAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"offrampAddress\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"internalType\":\"structRMNRemote.Report\",\"name\":\"rmnReport\",\"type\":\"tuple\"}],\"name\":\"exposeRmnReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"type\":\"function\",\"name\":\"exposeCommitReport\",\"inputs\":[{\"name\":\"commitReport\",\"type\":\"tuple\",\"internalType\":\"structOffRamp.CommitReport\",\"components\":[{\"name\":\"priceUpdates\",\"type\":\"tuple\",\"internalType\":\"structInternal.PriceUpdates\",\"components\":[{\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"components\":[{\"name\":\"sourceToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"usdPerToken\",\"type\":\"uint224\",\"internalType\":\"uint224\"}]},{\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.GasPriceUpdate[]\",\"components\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"usdPerUnitGas\",\"type\":\"uint224\",\"internalType\":\"uint224\"}]}]},{\"name\":\"merkleRoots\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.MerkleRoot[]\",\"components\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"onRampAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"minSeqNr\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"maxSeqNr\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"merkleRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"rmnSignatures\",\"type\":\"tuple[]\",\"internalType\":\"structIRMNRemote.Signature[]\",\"components\":[{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]}]}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"exposeOCR3Config\",\"inputs\":[{\"name\":\"config\",\"type\":\"tuple[]\",\"internalType\":\"structCCIPHome.OCR3Config[]\",\"components\":[{\"name\":\"pluginType\",\"type\":\"uint8\",\"internalType\":\"enumInternal.OCRPluginType\"},{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"FRoleDON\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"offchainConfigVersion\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"offrampAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"rmnHomeAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"nodes\",\"type\":\"tuple[]\",\"internalType\":\"structCCIPHome.OCR3Node[]\",\"components\":[{\"name\":\"p2pId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"signerKey\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"transmitterKey\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"offchainConfig\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"exposeRmnReport\",\"inputs\":[{\"name\":\"rmnReportVersion\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"rmnReport\",\"type\":\"tuple\",\"internalType\":\"structRMNRemote.Report\",\"components\":[{\"name\":\"destChainId\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"rmnRemoteContractAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"offrampAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"merkleRoots\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.MerkleRoot[]\",\"components\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"onRampAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"minSeqNr\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"maxSeqNr\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"merkleRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"}]", } var EncodingUtilsABI = EncodingUtilsMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/ccip_home/ccip_home.go b/core/gethwrappers/ccip/generated/ccip_home/ccip_home.go index 7ea7f633147..83a854121f5 100644 --- a/core/gethwrappers/ccip/generated/ccip_home/ccip_home.go +++ b/core/gethwrappers/ccip/generated/ccip_home/ccip_home.go @@ -65,8 +65,8 @@ type CCIPHomeVersionedConfig struct { } var CCIPHomeMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"capabilitiesRegistry\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainSelectorNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ChainSelectorNotSet\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expectedConfigDigest\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"gotConfigDigest\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"callDonId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"capabilityRegistryDonId\",\"type\":\"uint32\"}],\"name\":\"DONIdMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FChainMustBePositive\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"fChain\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"FRoleDON\",\"type\":\"uint256\"}],\"name\":\"FChainTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"signerKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"transmitterKey\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Node\",\"name\":\"node\",\"type\":\"tuple\"}],\"name\":\"InvalidNode\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPluginType\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"selector\",\"type\":\"bytes4\"}],\"name\":\"InvalidSelector\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoOpStateTransitionNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minimum\",\"type\":\"uint256\"}],\"name\":\"NotEnoughTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OfframpAddressCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCapabilitiesRegistryCanCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RMNHomeAddressCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RevokingZeroDigestNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManySigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"ActiveConfigRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"CandidateConfigRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapabilityConfigurationSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainConfigRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structCCIPHome.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"ConfigPromoted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"FRoleDON\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"rmnHomeAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"signerKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"transmitterKey\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structCCIPHome.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"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\":[{\"internalType\":\"uint64[]\",\"name\":\"chainSelectorRemoves\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPHome.ChainConfigArgs[]\",\"name\":\"chainConfigAdds\",\"type\":\"tuple[]\"}],\"name\":\"applyChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"update\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"beforeCapabilityConfigSet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"}],\"name\":\"getActiveDigest\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"pageIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pageSize\",\"type\":\"uint256\"}],\"name\":\"getAllChainConfigs\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPHome.ChainConfigArgs[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"}],\"name\":\"getAllConfigs\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"FRoleDON\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"rmnHomeAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"signerKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"transmitterKey\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPHome.VersionedConfig\",\"name\":\"activeConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"FRoleDON\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"rmnHomeAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"signerKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"transmitterKey\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPHome.VersionedConfig\",\"name\":\"candidateConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"}],\"name\":\"getCandidateDigest\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"getCapabilityConfiguration\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"configuration\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilityRegistry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"getChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.ChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"getConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"FRoleDON\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"rmnHomeAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"signerKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"transmitterKey\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPHome.VersionedConfig\",\"name\":\"versionedConfig\",\"type\":\"tuple\"},{\"internalType\":\"bool\",\"name\":\"ok\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"}],\"name\":\"getConfigDigests\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"activeConfigDigest\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"candidateConfigDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumChainConfigurations\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"digestToPromote\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"digestToRevoke\",\"type\":\"bytes32\"}],\"name\":\"promoteCandidateAndRevokeActive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"revokeCandidate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"FRoleDON\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"rmnHomeAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"signerKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"transmitterKey\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"digestToOverwrite\",\"type\":\"bytes32\"}],\"name\":\"setCandidate\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"newConfigDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"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\"}]", - Bin: "0x60a06040526006805463ffffffff191690553480156200001e57600080fd5b5060405162004e0238038062004e0283398101604081905262000041916200014c565b336000816200006357604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b038481169190911790915581161562000096576200009681620000d2565b50506001600160a01b038116620000c0576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b03166080526200017e565b336001600160a01b03821603620000fc57604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000602082840312156200015f57600080fd5b81516001600160a01b03811681146200017757600080fd5b9392505050565b608051614c5a620001a86000396000818161019b015281816123600152612dba0152614c5a6000f3fe608060405234801561001057600080fd5b506004361061016c5760003560e01c80637ac0d41e116100cd578063b74b235611610081578063f2fde38b11610066578063f2fde38b14610391578063f442c89a146103a4578063fba64a7c146103b757600080fd5b8063b74b23561461035e578063bae4e0fa1461037e57600080fd5b80638da5cb5b116100b25780638da5cb5b1461030d578063922ea4061461032b578063b149092b1461033e57600080fd5b80637ac0d41e146102e45780638318ed5d146102ec57600080fd5b80634851d549116101245780635f1edd9c116101095780635f1edd9c146102a85780637524051a146102c957806379ba5097146102dc57600080fd5b80634851d5491461026b5780635a837f971461029357600080fd5b8063181f5a7711610155578063181f5a77146101e057806333d9704a146102295780633df45a721461024a57600080fd5b806301ffc9a714610171578063020330e614610199575b600080fd5b61018461017f366004613127565b6103ca565b60405190151581526020015b60405180910390f35b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610190565b61021c6040518060400160405280601281526020017f43434950486f6d6520312e362e302d646576000000000000000000000000000081525081565b60405161019091906131b9565b61023c610237366004613206565b610463565b60405161019092919061344d565b61025d610258366004613471565b61095d565b6040516101909291906134aa565b61027e610279366004613471565b61125d565b60408051928352602083019190915201610190565b6102a66102a13660046134cf565b611353565b005b6102bb6102b6366004613471565b611666565b604051908152602001610190565b6102a66102d7366004613206565b6116dd565b6102a66118c8565b6102bb611996565b61021c6102fa366004613515565b5060408051602081019091526000815290565b60015473ffffffffffffffffffffffffffffffffffffffff166101bb565b6102bb610339366004613471565b6119a7565b61035161034c366004613553565b6119f8565b60405161019091906135e7565b61037161036c3660046135fa565b611b32565b604051610190919061361c565b6102bb61038c3660046136ba565b611d97565b6102a661039f36600461372a565b611f95565b6102a66103b23660046137a5565b611fa9565b6102a66103c5366004613811565b612348565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f78bea72100000000000000000000000000000000000000000000000000000000148061045d57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b61046b612fb0565b6000805b600281101561094f5763ffffffff8616600090815260056020526040812085918760018111156104a1576104a1613247565b60018111156104b2576104b2613247565b815260200190815260200160002082600281106104d1576104d16138ce565b60070201600101541480156104e557508315155b156109475763ffffffff861660009081526005602052604081209086600181111561051257610512613247565b600181111561052357610523613247565b81526020019081526020016000208160028110610542576105426138ce565b6040805160608101825260079290920292909201805463ffffffff1682526001808201546020840152835161010081018552600283018054939592949386938501929190829060ff168781111561059b5761059b613247565b60018111156105ac576105ac613247565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a0100000000000000000000909104166060820152600182018054608090920191610604906138fd565b80601f0160208091040260200160405190810160405280929190818152602001828054610630906138fd565b801561067d5780601f106106525761010080835404028352916020019161067d565b820191906000526020600020905b81548152906001019060200180831161066057829003601f168201915b50505050508152602001600282018054610696906138fd565b80601f01602080910402602001604051908101604052809291908181526020018280546106c2906138fd565b801561070f5780601f106106e45761010080835404028352916020019161070f565b820191906000526020600020905b8154815290600101906020018083116106f257829003601f168201915b5050505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b8282101561089d57838290600052602060002090600302016040518060600160405290816000820154815260200160018201805461077a906138fd565b80601f01602080910402602001604051908101604052809291908181526020018280546107a6906138fd565b80156107f35780601f106107c8576101008083540402835291602001916107f3565b820191906000526020600020905b8154815290600101906020018083116107d657829003601f168201915b5050505050815260200160028201805461080c906138fd565b80601f0160208091040260200160405190810160405280929190818152602001828054610838906138fd565b80156108855780601f1061085a57610100808354040283529160200191610885565b820191906000526020600020905b81548152906001019060200180831161086857829003601f168201915b5050505050815250508152602001906001019061073d565b5050505081526020016004820180546108b5906138fd565b80601f01602080910402602001604051908101604052809291908181526020018280546108e1906138fd565b801561092e5780601f106109035761010080835404028352916020019161092e565b820191906000526020600020905b81548152906001019060200180831161091157829003601f168201915b5050505050815250508152505091509250925050610955565b60010161046f565b50600090505b935093915050565b610965612fb0565b61096d612fb0565b63ffffffff841660009081526005602052604081208185600181111561099557610995613247565b60018111156109a6576109a6613247565b81526020019081526020016000206109be8686612605565b63ffffffff16600281106109d4576109d46138ce565b6040805160608101825260079290920292909201805463ffffffff1682526001808201546020840152835161010081018552600283018054949593949386019391929091839160ff90911690811115610a2f57610a2f613247565b6001811115610a4057610a40613247565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a0100000000000000000000909104166060820152600182018054608090920191610a98906138fd565b80601f0160208091040260200160405190810160405280929190818152602001828054610ac4906138fd565b8015610b115780601f10610ae657610100808354040283529160200191610b11565b820191906000526020600020905b815481529060010190602001808311610af457829003601f168201915b50505050508152602001600282018054610b2a906138fd565b80601f0160208091040260200160405190810160405280929190818152602001828054610b56906138fd565b8015610ba35780601f10610b7857610100808354040283529160200191610ba3565b820191906000526020600020905b815481529060010190602001808311610b8657829003601f168201915b5050505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b82821015610d31578382906000526020600020906003020160405180606001604052908160008201548152602001600182018054610c0e906138fd565b80601f0160208091040260200160405190810160405280929190818152602001828054610c3a906138fd565b8015610c875780601f10610c5c57610100808354040283529160200191610c87565b820191906000526020600020905b815481529060010190602001808311610c6a57829003601f168201915b50505050508152602001600282018054610ca0906138fd565b80601f0160208091040260200160405190810160405280929190818152602001828054610ccc906138fd565b8015610d195780601f10610cee57610100808354040283529160200191610d19565b820191906000526020600020905b815481529060010190602001808311610cfc57829003601f168201915b50505050508152505081526020019060010190610bd1565b505050508152602001600482018054610d49906138fd565b80601f0160208091040260200160405190810160405280929190818152602001828054610d75906138fd565b8015610dc25780601f10610d9757610100808354040283529160200191610dc2565b820191906000526020600020905b815481529060010190602001808311610da557829003601f168201915b50505091909252505050905250602081015190915015610de0578092505b63ffffffff8516600090815260056020526040812081866001811115610e0857610e08613247565b6001811115610e1957610e19613247565b8152602001908152602001600020610e31878761265c565b63ffffffff1660028110610e4757610e476138ce565b6040805160608101825260079290920292909201805463ffffffff1682526001808201546020840152835161010081018552600283018054949593949386019391929091839160ff90911690811115610ea257610ea2613247565b6001811115610eb357610eb3613247565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a0100000000000000000000909104166060820152600182018054608090920191610f0b906138fd565b80601f0160208091040260200160405190810160405280929190818152602001828054610f37906138fd565b8015610f845780601f10610f5957610100808354040283529160200191610f84565b820191906000526020600020905b815481529060010190602001808311610f6757829003601f168201915b50505050508152602001600282018054610f9d906138fd565b80601f0160208091040260200160405190810160405280929190818152602001828054610fc9906138fd565b80156110165780601f10610feb57610100808354040283529160200191611016565b820191906000526020600020905b815481529060010190602001808311610ff957829003601f168201915b5050505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b828210156111a4578382906000526020600020906003020160405180606001604052908160008201548152602001600182018054611081906138fd565b80601f01602080910402602001604051908101604052809291908181526020018280546110ad906138fd565b80156110fa5780601f106110cf576101008083540402835291602001916110fa565b820191906000526020600020905b8154815290600101906020018083116110dd57829003601f168201915b50505050508152602001600282018054611113906138fd565b80601f016020809104026020016040519081016040528092919081815260200182805461113f906138fd565b801561118c5780601f106111615761010080835404028352916020019161118c565b820191906000526020600020905b81548152906001019060200180831161116f57829003601f168201915b50505050508152505081526020019060010190611044565b5050505081526020016004820180546111bc906138fd565b80601f01602080910402602001604051908101604052809291908181526020018280546111e8906138fd565b80156112355780601f1061120a57610100808354040283529160200191611235565b820191906000526020600020905b81548152906001019060200180831161121857829003601f168201915b50505091909252505050905250602081015190915015611253578092505b50505b9250929050565b63ffffffff8216600090815260056020526040812081908184600181111561128757611287613247565b600181111561129857611298613247565b81526020019081526020016000206112b08585612605565b63ffffffff16600281106112c6576112c66138ce565b6007020160010154600560008663ffffffff1663ffffffff168152602001908152602001600020600085600181111561130157611301613247565b600181111561131257611312613247565b815260200190815260200160002061132a868661265c565b63ffffffff1660028110611340576113406138ce565b6007020160010154915091509250929050565b61135b6126b7565b81158015611367575080155b1561139e576040517f7b4d1e4f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006113aa858561265c565b63ffffffff86811660009081526005602052604081209290911692508491908660018111156113db576113db613247565b60018111156113ec576113ec613247565b8152602001908152602001600020826002811061140b5761140b6138ce565b6007020160010154146114bf5763ffffffff851660009081526005602052604081209085600181111561144057611440613247565b600181111561145157611451613247565b81526020019081526020016000208160028110611470576114706138ce565b6007020160010154836040517f93df584c0000000000000000000000000000000000000000000000000000000081526004016114b6929190918252602082015260400190565b60405180910390fd5b63ffffffff85166000908152600560205260408120818660018111156114e7576114e7613247565b60018111156114f8576114f8613247565b81526020019081526020016000206115108787612605565b63ffffffff1660028110611526576115266138ce565b600702019050828160010154146115795760018101546040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018490526044016114b6565b6000600180830182905563ffffffff88168252600760205260408220909187838111156115a8576115a8613247565b60018111156115b9576115b9613247565b8152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000811663ffffffff918216939093181691909117905582156116335760405183907f0b31c0055e2d464bef7781994b98c4ff9ef4ae0d05f59feb6a68c42de5e201b890600090a25b60405184907ffc3e98dbbd47c3fa7c1c05b6ec711caeaf70eca4554192b9ada8fc11a37f298e90600090a2505050505050565b63ffffffff821660009081526005602052604081208183600181111561168e5761168e613247565b600181111561169f5761169f613247565b81526020019081526020016000206116b78484612605565b63ffffffff16600281106116cd576116cd6138ce565b6007020160010154905092915050565b6116e56126b7565b8061171c576040517f0849d8cc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611728848461265c565b63ffffffff858116600090815260056020526040812092909116925083919085600181111561175957611759613247565b600181111561176a5761176a613247565b81526020019081526020016000208260028110611789576117896138ce565b6007020160010154146118345763ffffffff84166000908152600560205260408120908460018111156117be576117be613247565b60018111156117cf576117cf613247565b815260200190815260200160002081600281106117ee576117ee6138ce565b6007020160010154826040517f93df584c0000000000000000000000000000000000000000000000000000000081526004016114b6929190918252602082015260400190565b60405182907f53f5d9228f0a4173bea6e5931c9b3afe6eeb6692ede1d182952970f152534e3b90600090a263ffffffff841660009081526005602052604081209084600181111561188757611887613247565b600181111561189857611898613247565b815260200190815260200160002081600281106118b7576118b76138ce565b600702016001016000905550505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611919576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60006119a260036126f2565b905090565b63ffffffff82166000908152600560205260408120818360018111156119cf576119cf613247565b60018111156119e0576119e0613247565b81526020019081526020016000206116b7848461265c565b6040805160608082018352808252600060208301529181019190915267ffffffffffffffff821660009081526002602090815260409182902082518154608093810282018401909452606081018481529093919284928491840182828015611a7f57602002820191906000526020600020905b815481526020019060010190808311611a6b575b5050509183525050600182015460ff166020820152600282018054604090920191611aa9906138fd565b80601f0160208091040260200160405190810160405280929190818152602001828054611ad5906138fd565b8015611b225780601f10611af757610100808354040283529160200191611b22565b820191906000526020600020905b815481529060010190602001808311611b0557829003601f168201915b5050505050815250509050919050565b60606000611b4060036126f2565b90506000611b4e848661397f565b9050831580611b5d5750818110155b15611b9d576040805160008082526020820190925290611b93565b611b8061302c565b815260200190600190039081611b785790505b509250505061045d565b6000611ba985836139c5565b905082811115611bb65750815b6000611bc283836139d8565b67ffffffffffffffff811115611bda57611bda613996565b604051908082528060200260200182016040528015611c1357816020015b611c0061302c565b815260200190600190039081611bf85790505b509050825b82811015611d8c576000611c2d6003836126fc565b60408051808201825267ffffffffffffffff83168082526000908152600260209081529083902083518154608081850283018101909652606082018181529697509395928601949093919284929091849190840182828015611cae57602002820191906000526020600020905b815481526020019060010190808311611c9a575b5050509183525050600182015460ff166020820152600282018054604090920191611cd8906138fd565b80601f0160208091040260200160405190810160405280929190818152602001828054611d04906138fd565b8015611d515780601f10611d2657610100808354040283529160200191611d51565b820191906000526020600020905b815481529060010190602001808311611d3457829003601f168201915b50505091909252505050905283611d6887856139d8565b81518110611d7857611d786138ce565b602090810291909101015250600101611c18565b509695505050505050565b6000611da16126b7565b611db2611dad84613c06565b61270f565b6000611dbe86866119a7565b9050828114611e03576040517f93df584c00000000000000000000000000000000000000000000000000000000815260048101829052602481018490526044016114b6565b8015611e355760405183907f53f5d9228f0a4173bea6e5931c9b3afe6eeb6692ede1d182952970f152534e3b90600090a25b60068054600091908290611e4e9063ffffffff16613d02565b91906101000a81548163ffffffff021916908363ffffffff16021790559050611e98878787604051602001611e839190613fde565b60405160208183030381529060405284612b7d565b63ffffffff881660009081526005602052604081209194509081886001811115611ec457611ec4613247565b6001811115611ed557611ed5613247565b8152602001908152602001600020611eed898961265c565b63ffffffff1660028110611f0357611f036138ce565b600702016001810185905580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff841617815590508560028201611f4d82826144c4565b905050837f94f085b7c57ec2a270befd0b7b2ec7452580040edee8bb0fb04609c81f0359c68388604051611f8292919061468b565b60405180910390a2505050949350505050565b611f9d612c3d565b611fa681612c8e565b50565b611fb1612c3d565b60005b8381101561219757611ff8858583818110611fd157611fd16138ce565b9050602002016020810190611fe69190613553565b60039067ffffffffffffffff16612d52565b6120625784848281811061200e5761200e6138ce565b90506020020160208101906120239190613553565b6040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016114b6565b60026000868684818110612078576120786138ce565b905060200201602081019061208d9190613553565b67ffffffffffffffff16815260208101919091526040016000908120906120b4828261306f565b6001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556120ec60028301600061308d565b505061212a858583818110612103576121036138ce565b90506020020160208101906121189190613553565b60039067ffffffffffffffff16612d6a565b507f2a680691fef3b2d105196805935232c661ce703e92d464ef0b94a7bc62d714f085858381811061215e5761215e6138ce565b90506020020160208101906121739190613553565b60405167ffffffffffffffff909116815260200160405180910390a1600101611fb4565b5060005b818110156123415760008383838181106121b7576121b76138ce565b90506020028101906121c991906146b2565b6121d7906020810190614227565b6121e0906146e6565b905060008484848181106121f6576121f66138ce565b905060200281019061220891906146b2565b612216906020810190613553565b90506122258260000151612d76565b816020015160ff16600003612266576040517fa9b3766e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff811660009081526002602090815260409091208351805185936122969284929101906130c7565b5060208201516001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff909216919091179055604082015160028201906122e390826147b8565b506122fd91506003905067ffffffffffffffff8316612e38565b507f05dd57854af2c291a94ea52e7c43d80bc3be7fa73022f98b735dea86642fa5e0818360405161232f9291906148b4565b60405180910390a1505060010161219b565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146123b7576040517fac7a7efd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006123c660048286886148d7565b6123cf91614901565b90507fffffffff0000000000000000000000000000000000000000000000000000000081167fbae4e0fa000000000000000000000000000000000000000000000000000000001480159061246557507fffffffff0000000000000000000000000000000000000000000000000000000081167f7524051a0000000000000000000000000000000000000000000000000000000014155b80156124b357507fffffffff0000000000000000000000000000000000000000000000000000000081167f5a837f970000000000000000000000000000000000000000000000000000000014155b1561250e576040517f12ba286f0000000000000000000000000000000000000000000000000000000081527fffffffff00000000000000000000000000000000000000000000000000000000821660048201526024016114b6565b600061251e6024600487896148d7565b81019061252b9190614949565b90508263ffffffff16811461257c576040517f8a6e4ce800000000000000000000000000000000000000000000000000000000815263ffffffff8083166004830152841660248201526044016114b6565b6000803073ffffffffffffffffffffffffffffffffffffffff1688886040516125a6929190614962565b6000604051808303816000865af19150503d80600081146125e3576040519150601f19603f3d011682016040523d82523d6000602084013e6125e8565b606091505b5091509150816125f9573d60208201fd5b50505050505050505050565b63ffffffff821660009081526007602052604081208183600181111561262d5761262d613247565b600181111561263e5761263e613247565b815260208101919091526040016000205463ffffffff169392505050565b63ffffffff821660009081526007602052604081208183600181111561268457612684613247565b600181111561269557612695613247565b815260208101919091526040016000205463ffffffff16600118905092915050565b3330146126f0576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b600061045d825490565b60006127088383612e44565b9392505050565b806020015167ffffffffffffffff16600003612757576040517f698cf8e000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008151600181111561276c5761276c613247565b1415801561278d575060018151600181111561278a5761278a613247565b14155b156127c4576040517f3302dbd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6080810151511580612801575060408051600060208201520160405160208183030381529060405280519060200120816080015180519060200120145b15612838576040517f358c192700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a08101515115806128755750604080516000602082015201604051602081830303815290604052805190602001208160a0015180519060200120145b156128ac576040517fdee9857400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208101516128c79060039067ffffffffffffffff16612d52565b61290f5760208101516040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016114b6565b60408082015160208084015167ffffffffffffffff1660009081526002909152919091206001015460ff918216911681811115612982576040517f2db2204000000000000000000000000000000000000000000000000000000000815260048101829052602481018390526044016114b6565b60c0830151516101008111156129c4576040517f1b925da600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6129cf83600361397f565b8111612a07576040517f4856694e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808267ffffffffffffffff811115612a2357612a23613996565b604051908082528060200260200182016040528015612a4c578160200160208202803683370190505b50905060005b83811015612b0c5760008760c001518281518110612a7257612a726138ce565b60200260200101519050806040015151600014612a975783612a9381614972565b9450505b6020810151511580612aa857508051155b15612ae157806040517f9fa403140000000000000000000000000000000000000000000000000000000081526004016114b691906149aa565b8060000151838381518110612af857612af86138ce565b602090810291909101015250600101612a52565b506000612b1a85600361397f565b612b259060016139c5565b905080831015612b6b576040517f548dd21f00000000000000000000000000000000000000000000000000000000815260048101849052602481018290526044016114b6565b612b7482612d76565b50505050505050565b6040516000907dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90612bdb907f45564d000000000000000000000000000000000000000000000000000000000090469030908a908a9089906020016149bd565b60408051601f1981840301815290829052612bfa918690602001614a16565b60408051808303601f190181529190528051602090910120167e0a0000000000000000000000000000000000000000000000000000000000001795945050505050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146126f0576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821603612cdd576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120541515612708565b60006127088383612e6e565b805115611fa6576040517f05a5196600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906305a5196690612def908490600401614a45565b600060405180830381865afa158015612e0c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612e349190810190614ac2565b5050565b60006127088383612f61565b6000826000018281548110612e5b57612e5b6138ce565b9060005260206000200154905092915050565b60008181526001830160205260408120548015612f57576000612e926001836139d8565b8554909150600090612ea6906001906139d8565b9050808214612f0b576000866000018281548110612ec657612ec66138ce565b9060005260206000200154905080876000018481548110612ee957612ee96138ce565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612f1c57612f1c614c1e565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061045d565b600091505061045d565b6000818152600183016020526040812054612fa85750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561045d565b50600061045d565b60408051606081018252600080825260208201529081016130276040805161010081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff168152602001606081526020016060815260200160608152602001606081525090565b905290565b6040518060400160405280600067ffffffffffffffff168152602001613027604051806060016040528060608152602001600060ff168152602001606081525090565b5080546000825590600052602060002090810190611fa69190613112565b508054613099906138fd565b6000825580601f106130a9575050565b601f016020900490600052602060002090810190611fa69190613112565b828054828255906000526020600020908101928215613102579160200282015b828111156131025782518255916020019190600101906130e7565b5061310e929150613112565b5090565b5b8082111561310e5760008155600101613113565b60006020828403121561313957600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461270857600080fd5b60005b8381101561318457818101518382015260200161316c565b50506000910152565b600081518084526131a5816020860160208601613169565b601f01601f19169290920160200192915050565b602081526000612708602083018461318d565b63ffffffff81168114611fa657600080fd5b80356131e9816131cc565b919050565b60028110611fa657600080fd5b80356131e9816131ee565b60008060006060848603121561321b57600080fd5b8335613226816131cc565b92506020840135613236816131ee565b929592945050506040919091013590565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600281106132ad577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b8051825260006020820151606060208501526132d0606085018261318d565b9050604083015184820360408601526132e9828261318d565b95945050505050565b60008282518085526020808601955060208260051b8401016020860160005b8481101561333f57601f1986840301895261332d8383516132b1565b98840198925090830190600101613311565b5090979650505050505050565b63ffffffff815116825260208101516020830152600060408201516060604085015261337c606085018251613276565b602081015167ffffffffffffffff8116608086015250604081015160ff811660a086015250606081015167ffffffffffffffff811660c08601525060808101516101008060e08701526133d361016087018361318d565b915060a08301517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa080888503018389015261340e848361318d565b935060c08501519250808885030161012089015261342c84846132f2565b935060e0850151945080888503016101408901525050506132e9818361318d565b604081526000613460604083018561334c565b905082151560208301529392505050565b6000806040838503121561348457600080fd5b823561348f816131cc565b9150602083013561349f816131ee565b809150509250929050565b6040815260006134bd604083018561334c565b82810360208401526132e9818561334c565b600080600080608085870312156134e557600080fd5b84356134f0816131cc565b93506020850135613500816131ee565b93969395505050506040820135916060013590565b60006020828403121561352757600080fd5b8135612708816131cc565b67ffffffffffffffff81168114611fa657600080fd5b80356131e981613532565b60006020828403121561356557600080fd5b813561270881613532565b60008151808452602080850194506020840160005b838110156135a157815187529582019590820190600101613585565b509495945050505050565b60008151606084526135c16060850182613570565b905060ff6020840151166020850152604083015184820360408601526132e9828261318d565b60208152600061270860208301846135ac565b6000806040838503121561360d57600080fd5b50508035926020909101359150565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b838110156136ac578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805167ffffffffffffffff168452870151878401879052613699878501826135ac565b9588019593505090860190600101613645565b509098975050505050505050565b600080600080608085870312156136d057600080fd5b84356136db816131cc565b935060208501356136eb816131ee565b9250604085013567ffffffffffffffff81111561370757600080fd5b8501610100818803121561371a57600080fd5b9396929550929360600135925050565b60006020828403121561373c57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461270857600080fd5b60008083601f84011261377257600080fd5b50813567ffffffffffffffff81111561378a57600080fd5b6020830191508360208260051b850101111561125657600080fd5b600080600080604085870312156137bb57600080fd5b843567ffffffffffffffff808211156137d357600080fd5b6137df88838901613760565b909650945060208701359150808211156137f857600080fd5b5061380587828801613760565b95989497509550505050565b6000806000806000806080878903121561382a57600080fd5b863567ffffffffffffffff8082111561384257600080fd5b61384e8a838b01613760565b9098509650602089013591508082111561386757600080fd5b818901915089601f83011261387b57600080fd5b81358181111561388a57600080fd5b8a602082850101111561389c57600080fd5b6020830196508095505050506138b460408801613548565b91506138c2606088016131de565b90509295509295509295565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181811c9082168061391157607f821691505b60208210810361394a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808202811582820484141761045d5761045d613950565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8082018082111561045d5761045d613950565b8181038181111561045d5761045d613950565b6040516060810167ffffffffffffffff81118282101715613a0e57613a0e613996565b60405290565b604051610100810167ffffffffffffffff81118282101715613a0e57613a0e613996565b604051601f8201601f1916810167ffffffffffffffff81118282101715613a6157613a61613996565b604052919050565b60ff81168114611fa657600080fd5b80356131e981613a69565b600082601f830112613a9457600080fd5b813567ffffffffffffffff811115613aae57613aae613996565b613ac16020601f19601f84011601613a38565b818152846020838601011115613ad657600080fd5b816020850160208301376000918101602001919091529392505050565b600067ffffffffffffffff821115613b0d57613b0d613996565b5060051b60200190565b600082601f830112613b2857600080fd5b81356020613b3d613b3883613af3565b613a38565b82815260059290921b84018101918181019086841115613b5c57600080fd5b8286015b84811015611d8c57803567ffffffffffffffff80821115613b815760008081fd5b8189019150606080601f19848d03011215613b9c5760008081fd5b613ba46139eb565b87840135815260408085013584811115613bbe5760008081fd5b613bcc8e8b83890101613a83565b838b015250918401359183831115613be45760008081fd5b613bf28d8a85880101613a83565b908201528652505050918301918301613b60565b60006101008236031215613c1957600080fd5b613c21613a14565b613c2a836131fb565b8152613c3860208401613548565b6020820152613c4960408401613a78565b6040820152613c5a60608401613548565b6060820152608083013567ffffffffffffffff80821115613c7a57600080fd5b613c8636838701613a83565b608084015260a0850135915080821115613c9f57600080fd5b613cab36838701613a83565b60a084015260c0850135915080821115613cc457600080fd5b613cd036838701613b17565b60c084015260e0850135915080821115613ce957600080fd5b50613cf636828601613a83565b60e08301525092915050565b600063ffffffff808316818103613d1b57613d1b613950565b6001019392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613d5a57600080fd5b830160208101925035905067ffffffffffffffff811115613d7a57600080fd5b80360382131561125657600080fd5b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613de957600080fd5b830160208101925035905067ffffffffffffffff811115613e0957600080fd5b8060051b360382131561125657600080fd5b60008383855260208086019550808560051b830101846000805b88811015613ed957601f19868503018a5282357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1893603018112613e77578283fd5b8801803585526060613e8b87830183613d25565b8289890152613e9d8389018284613d89565b925050506040613eaf81840184613d25565b935087830382890152613ec3838583613d89565b9d89019d97505050938601935050600101613e35565b509198975050505050505050565b6000610100613efe84613ef9856131fb565b613276565b613f0a60208401613548565b67ffffffffffffffff166020850152613f2560408401613a78565b60ff166040850152613f3960608401613548565b67ffffffffffffffff166060850152613f556080840184613d25565b826080870152613f688387018284613d89565b92505050613f7960a0840184613d25565b85830360a0870152613f8c838284613d89565b92505050613f9d60c0840184613db4565b85830360c0870152613fb0838284613e1b565b92505050613fc160e0840184613d25565b85830360e0870152613fd4838284613d89565b9695505050505050565b6020815260006127086020830184613ee7565b6000813561045d81613532565b6000813561045d81613a69565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261404057600080fd5b83018035915067ffffffffffffffff82111561405b57600080fd5b60200191503681900382131561125657600080fd5b5b81811015612e345760008155600101614071565b601f8211156140be57806000526020600020601f840160051c810160208510156140ac5750805b612341601f850160051c830182614070565b505050565b67ffffffffffffffff8311156140db576140db613996565b6140ef836140e983546138fd565b83614085565b6000601f841160018114614141576000851561410b5750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355612341565b600083815260209020601f19861690835b828110156141725786850135825560209485019460019092019101614152565b50868210156141ad577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126141f457600080fd5b83018035915067ffffffffffffffff82111561420f57600080fd5b6020019150600581901b360382131561125657600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811261425b57600080fd5b9190910192915050565b61426f81546138fd565b8015612e3457601f81116001811461428957505060009055565b8260005260206000206142a7601f840160051c820160018301614070565b60008085559055505050565b81358155600180820160206142cb602086018661400b565b67ffffffffffffffff8111156142e3576142e3613996565b6142f7816142f186546138fd565b86614085565b6000601f82116001811461434957600083156143135750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600385901b1c1916600184901b1786556143be565b600086815260209020601f19841690835b82811015614377578685013582559387019390890190870161435a565b50848210156143b2577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88660031b161c19848701351681555b505060018360011b0186555b505050505050506143d2604083018361400b565b6143e08183600286016140c3565b50505050565b680100000000000000008311156143ff576143ff613996565b80548382558084101561447e5760038160030260038104831461442457614424613950565b8560030260038104871461443a5761443a613950565b6000858152602081209283019291909101905b828210156144795780825561446460018301614265565b61447060028301614265565b9083019061444d565b505050505b5060008181526020812083915b858110156144bc576144a66144a08487614227565b836142b3565b602092909201916003919091019060010161448b565b505050505050565b81356144cf816131ee565b60028110614506577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541660ff821681178355505061457d61454360208401613ff1565b82547fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff1660089190911b68ffffffffffffffff0016178255565b6145c761458c60408401613ffe565b82547fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff1660489190911b69ff00000000000000000016178255565b6146196145d660608401613ff1565b82547fffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffff1660509190911b71ffffffffffffffff0000000000000000000016178255565b614626608083018361400b565b6146348183600186016140c3565b505061464360a083018361400b565b6146518183600286016140c3565b505061466060c08301836141bf565b61466e8183600386016143e6565b505061467d60e083018361400b565b6143e08183600486016140c3565b63ffffffff831681526040602082015260006146aa6040830184613ee7565b949350505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261425b57600080fd5b6000606082360312156146f857600080fd5b6147006139eb565b823567ffffffffffffffff8082111561471857600080fd5b9084019036601f83011261472b57600080fd5b8135602061473b613b3883613af3565b82815260059290921b8401810191818101903684111561475a57600080fd5b948201945b838610156147785785358252948201949082019061475f565b865250614786878201613a78565b9085015250604085013591508082111561479f57600080fd5b506147ac36828601613a83565b60408301525092915050565b815167ffffffffffffffff8111156147d2576147d2613996565b6147e6816147e084546138fd565b84614085565b602080601f83116001811461483957600084156148035750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556144bc565b600085815260208120601f198616915b8281101561486857888601518255948401946001909101908401614849565b50858210156148a457878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b67ffffffffffffffff831681526040602082015260006146aa60408301846135ac565b600080858511156148e757600080fd5b838611156148f457600080fd5b5050820193919092039150565b7fffffffff0000000000000000000000000000000000000000000000000000000081358181169160048510156149415780818660040360031b1b83161692505b505092915050565b60006020828403121561495b57600080fd5b5035919050565b8183823760009101908152919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036149a3576149a3613950565b5060010190565b60208152600061270860208301846132b1565b8681526020810186905273ffffffffffffffffffffffffffffffffffffffff8516604082015263ffffffff848116606083015260c0820190614a026080840186613276565b80841660a084015250979650505050505050565b60008351614a28818460208801613169565b835190830190614a3c818360208801613169565b01949350505050565b6020815260006127086020830184613570565b80516131e9816131cc565b600082601f830112614a7457600080fd5b81516020614a84613b3883613af3565b8083825260208201915060208460051b870101935086841115614aa657600080fd5b602086015b84811015611d8c5780518352918301918301614aab565b60006020808385031215614ad557600080fd5b825167ffffffffffffffff80821115614aed57600080fd5b818501915085601f830112614b0157600080fd5b8151614b0f613b3882613af3565b81815260059190911b83018401908481019088831115614b2e57600080fd5b8585015b83811015614c1157805185811115614b4957600080fd5b8601610100818c03601f1901811315614b6157600080fd5b614b69613a14565b614b748a8401614a58565b8152614b8260408401614a58565b8a820152614b9260608401614a58565b60408201526080830151606082015260a0830151608082015260c083015160a082015260e08084015189811115614bc95760008081fd5b614bd78f8d83880101614a63565b60c084015250918301519188831115614bf05760008081fd5b614bfe8e8c85870101614a63565b9082015285525050918601918601614b32565b5098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"capabilitiesRegistry\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"acceptOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyChainConfigUpdates\",\"inputs\":[{\"name\":\"chainSelectorRemoves\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"},{\"name\":\"chainConfigAdds\",\"type\":\"tuple[]\",\"internalType\":\"structCCIPHome.ChainConfigArgs[]\",\"components\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"chainConfig\",\"type\":\"tuple\",\"internalType\":\"structCCIPHome.ChainConfig\",\"components\":[{\"name\":\"readers\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"fChain\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"config\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"beforeCapabilityConfigSet\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"update\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"donId\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getActiveDigest\",\"inputs\":[{\"name\":\"donId\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"pluginType\",\"type\":\"uint8\",\"internalType\":\"enumInternal.OCRPluginType\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getAllChainConfigs\",\"inputs\":[{\"name\":\"pageIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"pageSize\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple[]\",\"internalType\":\"structCCIPHome.ChainConfigArgs[]\",\"components\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"chainConfig\",\"type\":\"tuple\",\"internalType\":\"structCCIPHome.ChainConfig\",\"components\":[{\"name\":\"readers\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"fChain\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"config\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getAllConfigs\",\"inputs\":[{\"name\":\"donId\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"pluginType\",\"type\":\"uint8\",\"internalType\":\"enumInternal.OCRPluginType\"}],\"outputs\":[{\"name\":\"activeConfig\",\"type\":\"tuple\",\"internalType\":\"structCCIPHome.VersionedConfig\",\"components\":[{\"name\":\"version\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"configDigest\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"config\",\"type\":\"tuple\",\"internalType\":\"structCCIPHome.OCR3Config\",\"components\":[{\"name\":\"pluginType\",\"type\":\"uint8\",\"internalType\":\"enumInternal.OCRPluginType\"},{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"FRoleDON\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"offchainConfigVersion\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"offrampAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"rmnHomeAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"nodes\",\"type\":\"tuple[]\",\"internalType\":\"structCCIPHome.OCR3Node[]\",\"components\":[{\"name\":\"p2pId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"signerKey\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"transmitterKey\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"offchainConfig\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"candidateConfig\",\"type\":\"tuple\",\"internalType\":\"structCCIPHome.VersionedConfig\",\"components\":[{\"name\":\"version\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"configDigest\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"config\",\"type\":\"tuple\",\"internalType\":\"structCCIPHome.OCR3Config\",\"components\":[{\"name\":\"pluginType\",\"type\":\"uint8\",\"internalType\":\"enumInternal.OCRPluginType\"},{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"FRoleDON\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"offchainConfigVersion\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"offrampAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"rmnHomeAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"nodes\",\"type\":\"tuple[]\",\"internalType\":\"structCCIPHome.OCR3Node[]\",\"components\":[{\"name\":\"p2pId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"signerKey\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"transmitterKey\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"offchainConfig\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCandidateDigest\",\"inputs\":[{\"name\":\"donId\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"pluginType\",\"type\":\"uint8\",\"internalType\":\"enumInternal.OCRPluginType\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCapabilityConfiguration\",\"inputs\":[{\"name\":\"\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[{\"name\":\"configuration\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"getCapabilityRegistry\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getChainConfig\",\"inputs\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structCCIPHome.ChainConfig\",\"components\":[{\"name\":\"readers\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"fChain\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"config\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getConfig\",\"inputs\":[{\"name\":\"donId\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"pluginType\",\"type\":\"uint8\",\"internalType\":\"enumInternal.OCRPluginType\"},{\"name\":\"configDigest\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"versionedConfig\",\"type\":\"tuple\",\"internalType\":\"structCCIPHome.VersionedConfig\",\"components\":[{\"name\":\"version\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"configDigest\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"config\",\"type\":\"tuple\",\"internalType\":\"structCCIPHome.OCR3Config\",\"components\":[{\"name\":\"pluginType\",\"type\":\"uint8\",\"internalType\":\"enumInternal.OCRPluginType\"},{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"FRoleDON\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"offchainConfigVersion\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"offrampAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"rmnHomeAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"nodes\",\"type\":\"tuple[]\",\"internalType\":\"structCCIPHome.OCR3Node[]\",\"components\":[{\"name\":\"p2pId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"signerKey\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"transmitterKey\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"offchainConfig\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"ok\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getConfigDigests\",\"inputs\":[{\"name\":\"donId\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"pluginType\",\"type\":\"uint8\",\"internalType\":\"enumInternal.OCRPluginType\"}],\"outputs\":[{\"name\":\"activeConfigDigest\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"candidateConfigDigest\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getNumChainConfigurations\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"promoteCandidateAndRevokeActive\",\"inputs\":[{\"name\":\"donId\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"pluginType\",\"type\":\"uint8\",\"internalType\":\"enumInternal.OCRPluginType\"},{\"name\":\"digestToPromote\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"digestToRevoke\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"revokeCandidate\",\"inputs\":[{\"name\":\"donId\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"pluginType\",\"type\":\"uint8\",\"internalType\":\"enumInternal.OCRPluginType\"},{\"name\":\"configDigest\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setCandidate\",\"inputs\":[{\"name\":\"donId\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"pluginType\",\"type\":\"uint8\",\"internalType\":\"enumInternal.OCRPluginType\"},{\"name\":\"config\",\"type\":\"tuple\",\"internalType\":\"structCCIPHome.OCR3Config\",\"components\":[{\"name\":\"pluginType\",\"type\":\"uint8\",\"internalType\":\"enumInternal.OCRPluginType\"},{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"FRoleDON\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"offchainConfigVersion\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"offrampAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"rmnHomeAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"nodes\",\"type\":\"tuple[]\",\"internalType\":\"structCCIPHome.OCR3Node[]\",\"components\":[{\"name\":\"p2pId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"signerKey\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"transmitterKey\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"offchainConfig\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"digestToOverwrite\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"newConfigDigest\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"typeAndVersion\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"ActiveConfigRevoked\",\"inputs\":[{\"name\":\"configDigest\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"CandidateConfigRevoked\",\"inputs\":[{\"name\":\"configDigest\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"CapabilityConfigurationSet\",\"inputs\":[],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChainConfigRemoved\",\"inputs\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChainConfigSet\",\"inputs\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"chainConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structCCIPHome.ChainConfig\",\"components\":[{\"name\":\"readers\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"fChain\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"config\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ConfigPromoted\",\"inputs\":[{\"name\":\"configDigest\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ConfigSet\",\"inputs\":[{\"name\":\"configDigest\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"version\",\"type\":\"uint32\",\"indexed\":false,\"internalType\":\"uint32\"},{\"name\":\"config\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structCCIPHome.OCR3Config\",\"components\":[{\"name\":\"pluginType\",\"type\":\"uint8\",\"internalType\":\"enumInternal.OCRPluginType\"},{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"FRoleDON\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"offchainConfigVersion\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"offrampAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"rmnHomeAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"nodes\",\"type\":\"tuple[]\",\"internalType\":\"structCCIPHome.OCR3Node[]\",\"components\":[{\"name\":\"p2pId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"signerKey\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"transmitterKey\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"offchainConfig\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferRequested\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"CanOnlySelfCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CannotTransferToSelf\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ChainSelectorNotFound\",\"inputs\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"ChainSelectorNotSet\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ConfigDigestMismatch\",\"inputs\":[{\"name\":\"expectedConfigDigest\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"gotConfigDigest\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"DONIdMismatch\",\"inputs\":[{\"name\":\"callDonId\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"capabilityRegistryDonId\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]},{\"type\":\"error\",\"name\":\"FChainMustBePositive\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"FChainTooHigh\",\"inputs\":[{\"name\":\"fChain\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"FRoleDON\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"FTooHigh\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidNode\",\"inputs\":[{\"name\":\"node\",\"type\":\"tuple\",\"internalType\":\"structCCIPHome.OCR3Node\",\"components\":[{\"name\":\"p2pId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"signerKey\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"transmitterKey\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"type\":\"error\",\"name\":\"InvalidPluginType\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidSelector\",\"inputs\":[{\"name\":\"selector\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}]},{\"type\":\"error\",\"name\":\"MustBeProposedOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NoOpStateTransitionNotAllowed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotEnoughTransmitters\",\"inputs\":[{\"name\":\"got\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"minimum\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"OfframpAddressCannotBeZero\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OnlyCallableByOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OnlyCapabilitiesRegistryCanCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OwnerCannotBeZero\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"RMNHomeAddressCannotBeZero\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"RevokingZeroDigestNotAllowed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TooManySigners\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ZeroAddressNotAllowed\",\"inputs\":[]}]", + Bin: "0x60a03460bf57601f613d6638819003918201601f19168301916001600160401b0383118484101760c45780849260209460405283398101031260bf57516001600160a01b03811680820360bf57331560ae57600180546001600160a01b031916331790556006805463ffffffff1916905515609d57608052604051613c8b90816100db823960805181818161026601528181612f3901526139bd0152f35b6342bcdf7f60e11b60005260046000fd5b639b15e16f60e01b60005260046000fd5b600080fd5b634e487b7160e01b600052604160045260246000fdfe6080604052600436101561001257600080fd5b60003560e01c806301ffc9a714610157578063020330e614610152578063181f5a771461014d57806333d9704a146101485780633df45a72146101435780634851d5491461013e5780635a837f97146101395780635f1edd9c146101345780637524051a1461012f57806379ba50971461012a5780637ac0d41e146101255780638318ed5d146101205780638da5cb5b1461011b578063922ea40614610116578063b149092b14610111578063b74b23561461010c578063bae4e0fa14610107578063f2fde38b14610102578063f442c89a146100fd5763fba64a7c146100f857600080fd5b61172d565b611472565b61134e565b6110e5565b61100a565b610f90565b610ee2565b610e90565b610e2f565b610df3565b610d0a565b610c0f565b610bbb565b610934565b6108ae565b6107ce565b61072c565b610415565b61021b565b346102165760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610216576004357fffffffff00000000000000000000000000000000000000000000000000000000811680910361021657807f78bea72100000000000000000000000000000000000000000000000000000000602092149081156101ec575b506040519015158152f35b7f01ffc9a700000000000000000000000000000000000000000000000000000000915014386101e1565b600080fd5b346102165760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261021657602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6060810190811067ffffffffffffffff8211176102d557604052565b61028a565b610100810190811067ffffffffffffffff8211176102d557604052565b6040810190811067ffffffffffffffff8211176102d557604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176102d557604052565b60405190610363604083610313565b565b6040519061036361010083610313565b67ffffffffffffffff81116102d557601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60005b8381106103c25750506000910152565b81810151838201526020016103b2565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209361040e815180928187528780880191016103af565b0116010190565b346102165760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102165761049260408051906104568183610313565b601282527f43434950486f6d6520312e362e302d64657600000000000000000000000000006020830152519182916020835260208301906103d2565b0390f35b63ffffffff81160361021657565b6064359061036382610496565b6002111561021657565b3590610363826104b1565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc6060910112610216576004356104fc81610496565b90602435610509816104b1565b9060443590565b6002111561051a57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b90600282101561051a5752565b61058a9181518152604061057960208401516060602085015260608401906103d2565b9201519060408184039101526103d2565b90565b9080602083519182815201916020808360051b8301019401926000915b8383106105b957505050505090565b90919293946020806105f5837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086600196030187528951610556565b970193019301919392906105aa565b90604061058a9263ffffffff81511683526020810151602084015201519060606040820152610637606082018351610549565b602082015167ffffffffffffffff166080820152604082015160ff1660a0820152606082015167ffffffffffffffff1660c082015260e06106f86106c361068e6080860151610100858701526101608601906103d2565b60a08601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0868303016101008701526103d2565b60c08501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08583030161012086015261058d565b920151906101407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0828503019101526103d2565b346102165761075a610746610740366104c6565b91611b23565b604051928392604084526040840190610604565b90151560208301520390f35b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60409101126102165760043561079c81610496565b9060243561058a816104b1565b90916107c061058a93604084526040840190610604565b916020818403910152610604565b34610216576107dc36610766565b906107e56117dc565b906107ee6117dc565b9261083d61083763ffffffff841680600052600560205261081384604060002061183b565b90600052600760205263ffffffff61082f85604060002061183b565b541690611882565b50611a52565b60208101516108a4575b508161087c82610876610837946108716108829763ffffffff166000526005602052604060002090565b61183b565b9261312a565b90611882565b602081015161089c575b50610492604051928392836107a9565b91503861088c565b9250610882610847565b346102165761091f60016108c136610766565b929061087c63ffffffff821694856000526005602052846109056108e983604060002061183b565b88600052600760205263ffffffff61082f85604060002061183b565b50015495600052600560205261087681604060002061183b565b50015460408051928352602083019190915290f35b346102165760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102165760043561096f81610496565b6024359061097c826104b1565b604435916064359161098c613150565b831580610bb3575b610b89576109ae6109a5838361312a565b63ffffffff1690565b8460016109d8836109d3876108718863ffffffff166000526005602052604060002090565b611882565b50015403610b2f57506001610a2f610a04846108718563ffffffff166000526005602052604060002090565b61087c610a25866108718763ffffffff166000526007602052604060002090565b5463ffffffff1690565b50018054848103610af9575091610871610a60926000610aa0955563ffffffff166000526007602052604060002090565b6001610a70825463ffffffff1690565b1863ffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000825416179055565b80610ace575b507ffc3e98dbbd47c3fa7c1c05b6ec711caeaf70eca4554192b9ada8fc11a37f298e600080a2005b7f0b31c0055e2d464bef7781994b98c4ff9ef4ae0d05f59feb6a68c42de5e201b8600080a238610aa6565b7f93df584c00000000000000000000000000000000000000000000000000000000600052600452602484905260446000fd5b6000fd5b610b576001916109d3610b2b95610871899663ffffffff166000526005602052604060002090565b5001547f93df584c00000000000000000000000000000000000000000000000000000000600052600452602452604490565b7f7b4d1e4f0000000000000000000000000000000000000000000000000000000060005260046000fd5b508215610994565b346102165760206001610c0463ffffffff8061082f610bd936610766565b9316928360005260058752610bf281604060002061183b565b9360005260078752604060002061183b565b500154604051908152f35b3461021657610c1d366104c6565b91610c26613150565b8215610ce05763ffffffff610c3b838361312a565b169263ffffffff82166000526005602052806001610c61866109d387604060002061183b565b50015403610cb957926109d3600193610871610cb4946000977f53f5d9228f0a4173bea6e5931c9b3afe6eeb6692ede1d182952970f152534e3b8980a263ffffffff166000526005602052604060002090565b500155005b6001610b57856109d386610871610b2b9763ffffffff166000526005602052604060002090565b7f0849d8cc0000000000000000000000000000000000000000000000000000000060005260046000fd5b346102165760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102165760005473ffffffffffffffffffffffffffffffffffffffff81163303610dc9577fffffffffffffffffffffffff00000000000000000000000000000000000000006001549133828416176001551660005573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b7f02b543c60000000000000000000000000000000000000000000000000000000060005260046000fd5b346102165760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610216576020600354604051908152f35b346102165760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261021657610e69600435610496565b6040516020610e788183610313565b600082526104926040519282849384528301906103d2565b346102165760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261021657602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b34610216576020610efb610ef536610766565b90611bed565b604051908152f35b67ffffffffffffffff81160361021657565b6044359061036382610f03565b359061036382610f03565b9190606081019083519160608252825180915260206080830193019060005b818110610f7a5750505060408460ff602061058a9697015116602084015201519060408184039101526103d2565b8251855260209485019490920191600101610f4c565b346102165760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102165767ffffffffffffffff600435610fd481610f03565b610fdc611c1a565b50166000526002602052610492610ff66040600020611c3a565b604051918291602083526020830190610f2d565b346102165760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261021657611047602435600435611e24565b6040518091602082016020835281518091526040830190602060408260051b8601019301916000905b82821061107f57505050500390f35b919360206110d5827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc060019597998495030186526040838a5167ffffffffffffffff815116845201519181858201520190610f2d565b9601920192018594939192611070565b346102165760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102165760043561112081610496565b60243561112c816104b1565b60443567ffffffffffffffff8111610216576101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc826004019236030112610216576064359261117b613150565b61118d611188368461206f565b613231565b6111978382611bed565b9380850361131c57917f94f085b7c57ec2a270befd0b7b2ec7452580040edee8bb0fb04609c81f0359c69161087c9493610492966112f1575b506112cf8260026112936111f16111ec60065463ffffffff1690565b612158565b946112278663ffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000006006541617600655565b6112728660405161126b8161123f8960208301612418565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282610313565b8b846135b0565b99896108768c9b6108718563ffffffff166000526005602052604060002090565b506001810188905580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff861617815501612936565b6112de60405192839283612abe565b0390a26040519081529081906020820190565b7f53f5d9228f0a4173bea6e5931c9b3afe6eeb6692ede1d182952970f152534e3b600080a2386111d0565b7f93df584c00000000000000000000000000000000000000000000000000000000600052600485905260245260446000fd5b346102165760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102165760043573ffffffffffffffffffffffffffffffffffffffff8116809103610216576113a66136c5565b33811461141757807fffffffffffffffffffffffff0000000000000000000000000000000000000000600054161760005573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b7fdad89dca0000000000000000000000000000000000000000000000000000000060005260046000fd5b9181601f840112156102165782359167ffffffffffffffff8311610216576020808501948460051b01011161021657565b346102165760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102165760043567ffffffffffffffff8111610216576114c1903690600401611441565b60243567ffffffffffffffff8111610216576114e1903690600401611441565b9190926114ec6136c5565b60005b8281106116015750505060005b81811061150557005b611525611520611516838587612b7a565b6020810190612662565b612bba565b90611539611534828587612b7a565b612429565b6115438351613948565b61155a611554602085015160ff1690565b60ff1690565b156115d75782816115ab6001956115a67f05dd57854af2c291a94ea52e7c43d80bc3be7fa73022f98b735dea86642fa5e09567ffffffffffffffff166000526002602052604060002090565b612d9a565b6115be67ffffffffffffffff8216613bed565b506115ce60405192839283612e2d565b0390a1016114fc565b7fa9b3766e0000000000000000000000000000000000000000000000000000000060005260046000fd5b61163c611638611625611618611534858888612adb565b67ffffffffffffffff1690565b6000526004602052604060002054151590565b1590565b6116e657806116766116716116576115346001958888612adb565b67ffffffffffffffff166000526002602052604060002090565b612b33565b61168f61168a611618611534848888612adb565b613b09565b507f2a680691fef3b2d105196805935232c661ce703e92d464ef0b94a7bc62d714f06116dd6116c2611534848888612adb565b60405167ffffffffffffffff90911681529081906020820190565b0390a1016114ef565b61153490610b2b936116f793612adb565b7f1bd4d2d20000000000000000000000000000000000000000000000000000000060005267ffffffffffffffff16600452602490565b346102165760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102165760043567ffffffffffffffff81116102165761177c903690600401611441565b505060243567ffffffffffffffff811161021657366023820112156102165780600401359067ffffffffffffffff8211610216573660248383010111610216576117da916117c8610f15565b5060246117d36104a4565b9201612f20565b005b604051906117e9826102b9565b8160008152600060208201526040805191611803836102da565b60008352600060208401526000828401526000606084015260606080840152606060a0840152606060c0840152606060e08401520152565b90600281101561051a57600052602052604060002090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b906002811015611896576007020190600090565b611853565b600282101561051a5752565b90600182811c921680156118f0575b60208310146118c157565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f16916118b6565b906040519182600082549261190e846118a7565b808452936001811690811561197a5750600114611933575b5061036392500383610313565b90506000929192526020600020906000915b81831061195e5750509060206103639282010138611926565b6020919350806001915483858901015201910190918492611945565b602093506103639592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b82010138611926565b67ffffffffffffffff81116102d55760051b60200190565b9081546119de816119ba565b926119ec6040519485610313565b818452602084019060005260206000206000915b838310611a0d5750505050565b60036020600192604051611a20816102b9565b85548152611a2f8587016118fa565b83820152611a3f600287016118fa565b6040820152815201920192019190611a00565b9060405191611a60836102b9565b60408363ffffffff835416815260018301546020820152611b1a6006835194611a88866102da565b611ae1611ad06002830154611aa060ff82168a61189b565b67ffffffffffffffff600882901c1660208a015260ff604882901c16888a015260501c67ffffffffffffffff1690565b67ffffffffffffffff166060880152565b611aed600382016118fa565b6080870152611afe600482016118fa565b60a0870152611b0f600582016119d2565b60c0870152016118fa565b60e08401520152565b90611b2c6117dc565b9260005b60028110611b42575050505090600090565b63ffffffff8416806000526005602052826001611b67846109d388604060002061183b565b5001541480611ba8575b611b7e5750600101611b30565b611ba2955061083794506109d392506000939193526005602052604060002061183b565b90600190565b50821515611b71565b91611be9918354907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b9055565b611c149061087c60019363ffffffff8316600052600560205261087681604060002061183b565b50015490565b60405190611c27826102b9565b6060604083828152600060208201520152565b90604051611c47816102b9565b809260405180602083549182815201908360005260206000209060005b818110611cab5750505060409282611c83611ca6946002940382610313565b8552611ca0611c96600183015460ff1690565b60ff166020870152565b016118fa565b910152565b8254845260209093019260019283019201611c64565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9081600302916003830403611d0157565b611cc1565b81810292918115918404141715611d0157565b60405190611d28602083610313565b600080835282815b828110611d3c57505050565b602090604051611d4b816102f7565b60008152611d57611c1a565b8382015282828501015201611d30565b90611d71826119ba565b611d7e6040519182610313565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611dac82946119ba565b019060005b828110611dbd57505050565b602090604051611dcc816102f7565b60008152611dd8611c1a565b8382015282828501015201611db1565b9060018201809211611d0157565b91908201809211611d0157565b91908203918211611d0157565b80518210156118965760209160051b010190565b611e318260035492611d06565b9180158015611f03575b611ef857611e499083611df6565b90808211611ef0575b50611e65611e608383611e03565b611d67565b91805b828110611e755750505090565b80611ee9611e87611618600194613a41565b611ec8611ea88267ffffffffffffffff166000526002602052604060002090565b611ec3611eb3610354565b67ffffffffffffffff9094168452565b611c3a565b6020820152611ed78584611e03565b90611ee28289611e10565b5286611e10565b5001611e68565b905038611e52565b50505061058a611d19565b5081831015611e3b565b60ff81160361021657565b359061036382611f0d565b81601f8201121561021657803590611f3a82610375565b92611f486040519485610313565b8284526020838301011161021657816000926020809301838601378301015290565b9080601f8301121561021657813591611f82836119ba565b92611f906040519485610313565b80845260208085019160051b830101918383116102165760208101915b838310611fbc57505050505090565b823567ffffffffffffffff81116102165782019060607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe083880301126102165760405190612009826102b9565b60208301358252604083013567ffffffffffffffff81116102165787602061203392860101611f23565b602083015260608301359167ffffffffffffffff83116102165761205f88602080969581960101611f23565b6040820152815201920191611fad565b9190916101008184031261021657612085610365565b9261208f826104bb565b845261209d60208301610f22565b60208501526120ae60408301611f18565b60408501526120bf60608301610f22565b6060850152608082013567ffffffffffffffff811161021657816120e4918401611f23565b608085015260a082013567ffffffffffffffff81116102165781612109918401611f23565b60a085015260c082013567ffffffffffffffff8111610216578161212e918401611f6a565b60c085015260e082013567ffffffffffffffff8111610216576121519201611f23565b60e0830152565b63ffffffff1663ffffffff8114611d015760010190565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561021657016020813591019167ffffffffffffffff821161021657813603831361021657565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561021657016020813591019167ffffffffffffffff8211610216578160051b3603831361021657565b90602083828152019060208160051b85010193836000915b8383106122795750505050505090565b9091929394957fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820301865286357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1843603018112156102165760206123206001938683940190813581526123126123076122f78685018561216f565b60608886015260608501916121bf565b92604081019061216f565b9160408185039101526121bf565b980196019493019190612269565b61058a916123448161233f846104bb565b610549565b61236461235360208401610f22565b67ffffffffffffffff166020830152565b61237d61237360408401611f18565b60ff166040830152565b61239d61238c60608401610f22565b67ffffffffffffffff166060830152565b61240a6123ff6123e46123c96123b6608087018761216f565b61010060808801526101008701916121bf565b6123d660a087018761216f565b9086830360a08801526121bf565b6123f160c08601866121fe565b9085830360c0870152612251565b9260e081019061216f565b9160e08185039101526121bf565b90602061058a92818152019061232e565b3561058a81610f03565b3561058a81611f0d565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610216570180359067ffffffffffffffff82116102165760200191813603831361021657565b818110612499575050565b6000815560010161248e565b9190601f81116124b457505050565b610363926000526020600020906020601f840160051c830193106124e0575b601f0160051c019061248e565b90915081906124d3565b90929167ffffffffffffffff81116102d5576125108161250a84546118a7565b846124a5565b6000601f821160011461256a578190611be993949560009261255f575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b01359050388061252d565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082169461259d84600052602060002090565b91805b8781106125f65750836001959697106125be575b505050811b019055565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88560031b161c199101351690553880806125b4565b909260206001819286860135815501940191016125a0565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610216570180359067ffffffffffffffff821161021657602001918160051b3603831361021657565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215610216570190565b61269f81546118a7565b90816126a9575050565b81601f600093116001146126bb575055565b818352602083206126d791601f0160051c81019060010161248e565b808252602082209081548360011b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8560031b1c191617905555565b90803582556001820161272a602083018361243d565b9067ffffffffffffffff82116102d55761274e8261274885546118a7565b856124a5565b600090601f83116001146127bd57926127a7836127b49460029794610363999760009261255f5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b90555b604081019061243d565b929091016124ea565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08316916127f085600052602060002090565b92815b81811061285957509360029693610363989693600193836127b49810612821575b505050811b0190556127aa565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88560031b161c19910135169055388080612814565b919360206001819287870135815501950192016127f3565b6801000000000000000083116102d55780548382558084106128d9575b50906128a08192600052602060002090565b906000925b8484106128b3575050505050565b60036020826128cd6128c760019587612662565b87612714565b019301930192916128a5565b80600302906003820403611d015783600302600381048503611d015782600052602060002091820191015b818110612911575061288e565b6003906000815561292460018201612695565b61293060028201612695565b01612904565b90803591612943836104b1565b600283101561051a576127b46004926103639460ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0085541691161783556129ca61299060208301612429565b84547fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff1660089190911b68ffffffffffffffff0016178455565b612a146129d960408301612433565b84547fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff1660489190911b69ff00000000000000000016178455565b612a66612a2360608301612429565b84547fffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffff1660509190911b71ffffffffffffffff0000000000000000000016178455565b612a80612a76608083018361243d565b90600186016124ea565b612a9a612a9060a083018361243d565b90600286016124ea565b612ab4612aaa60c083018361260e565b9060038601612871565b60e081019061243d565b60409063ffffffff61058a9493168152816020820152019061232e565b91908110156118965760051b0190565b906801000000000000000081116102d557815491818155828210612b0e57505050565b600052602060002091820191015b818110612b27575050565b60008155600101612b1c565b80546000825580612b53575b506002816000600161036394015501612695565b816000526020600020908101905b818110612b6e5750612b3f565b60008155600101612b61565b91908110156118965760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc181360301821215610216570190565b6060813603126102165760405190612bd1826102b9565b803567ffffffffffffffff811161021657810136601f8201121561021657803590612bfb826119ba565b91612c096040519384610313565b80835260208084019160051b8301019136831161021657602001905b828210612c6b575050508252612c3d60208201611f18565b602083015260408101359067ffffffffffffffff821161021657612c6391369101611f23565b604082015290565b8135815260209182019101612c25565b919091825167ffffffffffffffff81116102d557612c9d8161250a84546118a7565b6020601f8211600114612cf6578190611be9939495600092612ceb5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b01519050388061252d565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0821690612d2984600052602060002090565b9160005b818110612d8257509583600195969710612d4b57505050811b019055565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690553880806125b4565b9192602060018192868b015181550194019201612d2d565b90805180519067ffffffffffffffff82116102d557602090612dbc8386612aeb565b0183600052602060002060005b838110612e1957505050509060026040610363936001840160ff6020830151167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905501519101612c7b565b600190602084519401938184015501612dc9565b60409067ffffffffffffffff61058a94931681528160208201520190610f2d565b906004116102165790600490565b906024116102165760040190602090565b919091357fffffffff0000000000000000000000000000000000000000000000000000000081169260048110612ea1575050565b7fffffffff00000000000000000000000000000000000000000000000000000000929350829060040360031b1b161690565b90816020910312610216573590565b908092918237016000815290565b3d15612f1b573d90612f0182610375565b91612f0f6040519384610313565b82523d6000602084013e565b606090565b909173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361310057612f72612f6c8484612e4e565b90612e6d565b7fffffffff0000000000000000000000000000000000000000000000000000000081167fbae4e0fa0000000000000000000000000000000000000000000000000000000081141590816130d5575b816130aa575b5061305b5750612fe1612fd98484612e5c565b810190612ed3565b63ffffffff82168103613022575050600091829161300460405180938193612ee2565b039082305af1613012612ef0565b901561301b5750565b60203d9101fd5b7f8a6e4ce80000000000000000000000000000000000000000000000000000000060005263ffffffff9081166004521660245260446000fd5b7f12ba286f000000000000000000000000000000000000000000000000000000006000527fffffffff000000000000000000000000000000000000000000000000000000001660045260246000fd5b7f5a837f97000000000000000000000000000000000000000000000000000000009150141538612fc6565b7f7524051a000000000000000000000000000000000000000000000000000000008114159150612fc0565b7fac7a7efd0000000000000000000000000000000000000000000000000000000060005260046000fd5b61314a60019263ffffffff8093166000526007602052604060002061183b565b54161890565b30330361315957565b7f371a73280000000000000000000000000000000000000000000000000000000060005260046000fd5b6040516020810190600082526020815261319e604082610313565b51902090565b906131ae826119ba565b6131bb6040519182610313565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06131e982946119ba565b0190602036910137565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611d015760010190565b90602061058a928181520190610556565b6020810167ffffffffffffffff613250825167ffffffffffffffff1690565b161561358657815161326181610510565b61326a81610510565b151580613568575b61353e57608082015180518015918215613528575b50506134fe5760a0820151805180159182156134e8575b50506134be576132bf611638611625611618845167ffffffffffffffff1690565b6134aa576132f961155460016132f16116576132e2611554604089015160ff1690565b955167ffffffffffffffff1690565b015460ff1690565b918183116134765760c0019182515191610100831161344c5761331b90611cf0565b8211156134225760009161332e816131a4565b9360005b8281106133905750505061334861334d91611cf0565b611de8565b9081811061336057505061036390613948565b7f548dd21f0000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b61339b818351611e10565b51604081015151613412575b602081015151158015613409575b6133cf5790600191516133c88289611e10565b5201613332565b613405906040519182917f9fa4031400000000000000000000000000000000000000000000000000000000835260048301613220565b0390fd5b508051156133b5565b9461341c906131f3565b946133a7565b7f4856694e0000000000000000000000000000000000000000000000000000000060005260046000fd5b7f1b925da60000000000000000000000000000000000000000000000000000000060005260046000fd5b507f2db220400000000000000000000000000000000000000000000000000000000060005260049190915260245260446000fd5b51610b2b9067ffffffffffffffff166116f7565b7fdee985740000000000000000000000000000000000000000000000000000000060005260046000fd5b6020012090506134f6613183565b14388061329e565b7f358c19270000000000000000000000000000000000000000000000000000000060005260046000fd5b602001209050613536613183565b143880613287565b7f3302dbd70000000000000000000000000000000000000000000000000000000060005260046000fd5b506001825161357681610510565b61357f81610510565b1415613272565b7f698cf8e00000000000000000000000000000000000000000000000000000000060005260046000fd5b90613677929361360663ffffffff9283604051957f45564d0000000000000000000000000000000000000000000000000000000000602088015246604088015230606088015216608086015260a0850190610549565b1660c082015260c0815261361b60e082610313565b6020604051938261363586945180928580880191016103af565b8301613649825180938580850191016103af565b0101037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282610313565b602081519101207fffff00000000000000000000000000000000000000000000000000000000000019167e0a0000000000000000000000000000000000000000000000000000000000001790565b73ffffffffffffffffffffffffffffffffffffffff6001541633036136e657565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b519061036382610496565b9080601f83011215610216578151613732816119ba565b926137406040519485610313565b81845260208085019260051b82010192831161021657602001905b8282106137685750505090565b815181526020918201910161375b565b9080601f8301121561021657815161378f816119ba565b9261379d6040519485610313565b81845260208085019260051b82010192831161021657602001905b8282106137c55750505090565b81518152602091820191016137b8565b6020818303126102165780519067ffffffffffffffff821161021657019080601f830112156102165781519161380a836119ba565b926138186040519485610313565b80845260208085019160051b830101918383116102165760208101915b83831061384457505050505090565b825167ffffffffffffffff8111610216578201906101007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe083880301126102165761388d610365565b9061389a60208401613710565b82526138a860408401613710565b60208301526138b960608401613710565b60408301526080830151606083015260a0830151608083015260c083015160a083015260e083015167ffffffffffffffff8111610216578760206138ff9286010161371b565b60c08301526101008301519167ffffffffffffffff83116102165761392c88602080969581960101613778565b60e0820152815201920191613835565b6040513d6000823e3d90fd5b80516139515750565b60405180917f05a519660000000000000000000000000000000000000000000000000000000082526024820160206004840152815180915260206044840192019060005b818110613a10575050509080600092038173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa8015613a0b576139ec5750565b613a08903d806000833e613a008183610313565b8101906137d5565b50565b61393c565b8251845285945060209384019390920191600101613995565b80548210156118965760005260206000200190600090565b6003548110156118965760036000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b015490565b80548015613ada577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190613aab8282613a29565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b1916905555565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600081815260046020526040902054908115613be6577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820190828211611d0157600354927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8401938411611d01578383600095613ba59503613bab575b505050613b946003613a76565b600490600052602052604060002090565b55600190565b613b94613bd791613bcd613bc3613bdd956003613a29565b90549060031b1c90565b9283916003613a29565b90611bb1565b55388080613b87565b5050600090565b600081815260046020526040902054613c7857600354680100000000000000008110156102d557613c5f613c2a8260018594016003556003613a29565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b9055600354906000526004602052604060002055600190565b5060009056fea164736f6c634300081a000a", } var CCIPHomeABI = CCIPHomeMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go b/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go index 7397594d78d..c711c654ca5 100644 --- a/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go +++ b/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go @@ -100,8 +100,8 @@ type OffRampSourceChainConfig struct { } var CCIPReaderTesterMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPMessageSent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"emitCCIPMessageSent\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNRemote.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"emitCommitReportAccepted\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"emitExecutionStateChanged\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"}],\"name\":\"getInboundNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"setDestChainSeqNr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"testNonce\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"}],\"name\":\"setInboundNonce\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"seqNr\",\"type\":\"uint64\"}],\"name\":\"setLatestPriceSequenceNumber\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceChainConfig\",\"type\":\"tuple\"}],\"name\":\"setSourceChainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b50611960806100206000396000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c8063bfc9b78911610081578063c92236251161005b578063c9223625146101f9578063e83eabba1461020c578063e9d68a8e1461021f57600080fd5b8063bfc9b7891461017e578063c1a5a35514610191578063c7c1cba1146101e657600080fd5b806369600bca116100b257806369600bca1461010f5780639041be3d1461015857806393df28671461016b57600080fd5b80633f4b04aa146100ce5780634bf78697146100fa575b600080fd5b60035467ffffffffffffffff165b60405167ffffffffffffffff90911681526020015b60405180910390f35b61010d610108366004610a4e565b61023f565b005b61010d61011d366004610b89565b600380547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff92909216919091179055565b6100dc610166366004610b89565b610298565b61010d610179366004610bf4565b6102c8565b61010d61018c366004610ea2565b610343565b61010d61019f36600461102d565b67ffffffffffffffff918216600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001691909216179055565b61010d6101f4366004611060565b610385565b6100dc6102073660046110f2565b6103e2565b61010d61021a366004611145565b61042e565b61023261022d366004610b89565b610518565b6040516100f19190611265565b80600001516060015167ffffffffffffffff168267ffffffffffffffff167f192442a2b2adb6a7948f097023cb6b57d29d3a7a5dd33e6666d33c39cc456f328360405161028c91906113ab565b60405180910390a35050565b67ffffffffffffffff808216600090815260016020819052604082205491926102c2921690611503565b92915050565b67ffffffffffffffff84166000908152600260205260409081902090518491906102f59085908590611552565b908152604051908190036020019020805467ffffffffffffffff929092167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090921691909117905550505050565b602081015181516040517f35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e49261037a929091611656565b60405180910390a150565b848667ffffffffffffffff168867ffffffffffffffff167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b878787876040516103d1949392919061172e565b60405180910390a450505050505050565b67ffffffffffffffff8316600090815260026020526040808220905161040b9085908590611552565b9081526040519081900360200190205467ffffffffffffffff1690509392505050565b67ffffffffffffffff808316600090815260208181526040918290208451815492860151938601519094167501000000000000000000000000000000000000000000027fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff93151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00000000000000000000000000000000000000000090931673ffffffffffffffffffffffffffffffffffffffff909516949094179190911791909116919091178155606082015182919060018201906105119082611839565b5050505050565b604080516080808201835260008083526020808401829052838501829052606080850181905267ffffffffffffffff87811684528383529286902086519485018752805473ffffffffffffffffffffffffffffffffffffffff8116865274010000000000000000000000000000000000000000810460ff1615159386019390935275010000000000000000000000000000000000000000009092049092169483019490945260018401805493949293918401916105d490611795565b80601f016020809104026020016040519081016040528092919081815260200182805461060090611795565b801561064d5780601f106106225761010080835404028352916020019161064d565b820191906000526020600020905b81548152906001019060200180831161063057829003601f168201915b5050505050815250509050919050565b803567ffffffffffffffff8116811461067557600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff811182821017156106cc576106cc61067a565b60405290565b604051610120810167ffffffffffffffff811182821017156106cc576106cc61067a565b6040805190810167ffffffffffffffff811182821017156106cc576106cc61067a565b6040516060810167ffffffffffffffff811182821017156106cc576106cc61067a565b6040516080810167ffffffffffffffff811182821017156106cc576106cc61067a565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156107a6576107a661067a565b604052919050565b600060a082840312156107c057600080fd5b6107c86106a9565b9050813581526107da6020830161065d565b60208201526107eb6040830161065d565b60408201526107fc6060830161065d565b606082015261080d6080830161065d565b608082015292915050565b73ffffffffffffffffffffffffffffffffffffffff8116811461083a57600080fd5b50565b803561067581610818565b600082601f83011261085957600080fd5b813567ffffffffffffffff8111156108735761087361067a565b6108a460207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161075f565b8181528460208386010111156108b957600080fd5b816020850160208301376000918101602001919091529392505050565b600067ffffffffffffffff8211156108f0576108f061067a565b5060051b60200190565b600082601f83011261090b57600080fd5b8135602061092061091b836108d6565b61075f565b82815260059290921b8401810191818101908684111561093f57600080fd5b8286015b84811015610a4357803567ffffffffffffffff808211156109645760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d0301121561099d5760008081fd5b6109a56106a9565b6109b088850161083d565b8152604080850135848111156109c65760008081fd5b6109d48e8b83890101610848565b8a84015250606080860135858111156109ed5760008081fd5b6109fb8f8c838a0101610848565b83850152506080915081860135818401525082850135925083831115610a215760008081fd5b610a2f8d8a85880101610848565b908201528652505050918301918301610943565b509695505050505050565b60008060408385031215610a6157600080fd5b610a6a8361065d565b9150602083013567ffffffffffffffff80821115610a8757600080fd5b908401906101a08287031215610a9c57600080fd5b610aa46106d2565b610aae87846107ae565b8152610abc60a0840161083d565b602082015260c083013582811115610ad357600080fd5b610adf88828601610848565b60408301525060e083013582811115610af757600080fd5b610b0388828601610848565b6060830152506101008084013583811115610b1d57600080fd5b610b2989828701610848565b608084015250610b3c610120850161083d565b60a083015261014084013560c083015261016084013560e083015261018084013583811115610b6a57600080fd5b610b76898287016108fa565b8284015250508093505050509250929050565b600060208284031215610b9b57600080fd5b610ba48261065d565b9392505050565b60008083601f840112610bbd57600080fd5b50813567ffffffffffffffff811115610bd557600080fd5b602083019150836020828501011115610bed57600080fd5b9250929050565b60008060008060608587031215610c0a57600080fd5b610c138561065d565b9350610c216020860161065d565b9250604085013567ffffffffffffffff811115610c3d57600080fd5b610c4987828801610bab565b95989497509550505050565b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461067557600080fd5b600082601f830112610c9257600080fd5b81356020610ca261091b836108d6565b82815260069290921b84018101918181019086841115610cc157600080fd5b8286015b84811015610a435760408189031215610cde5760008081fd5b610ce66106f6565b610cef8261065d565b8152610cfc858301610c55565b81860152835291830191604001610cc5565b600082601f830112610d1f57600080fd5b81356020610d2f61091b836108d6565b82815260059290921b84018101918181019086841115610d4e57600080fd5b8286015b84811015610a4357803567ffffffffffffffff80821115610d735760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610dac5760008081fd5b610db46106a9565b610dbf88850161065d565b815260408085013584811115610dd55760008081fd5b610de38e8b83890101610848565b8a8401525060609350610df784860161065d565b908201526080610e0885820161065d565b93820193909352920135908201528352918301918301610d52565b600082601f830112610e3457600080fd5b81356020610e4461091b836108d6565b82815260069290921b84018101918181019086841115610e6357600080fd5b8286015b84811015610a435760408189031215610e805760008081fd5b610e886106f6565b813581528482013585820152835291830191604001610e67565b60006020808385031215610eb557600080fd5b823567ffffffffffffffff80821115610ecd57600080fd5b9084019060608287031215610ee157600080fd5b610ee9610719565b823582811115610ef857600080fd5b83016040818903811315610f0b57600080fd5b610f136106f6565b823585811115610f2257600080fd5b8301601f81018b13610f3357600080fd5b8035610f4161091b826108d6565b81815260069190911b8201890190898101908d831115610f6057600080fd5b928a01925b82841015610fb05785848f031215610f7d5760008081fd5b610f856106f6565b8435610f9081610818565b8152610f9d858d01610c55565b818d0152825292850192908a0190610f65565b845250505082870135915084821115610fc857600080fd5b610fd48a838501610c81565b81880152835250508284013582811115610fed57600080fd5b610ff988828601610d0e565b8583015250604083013593508184111561101257600080fd5b61101e87858501610e23565b60408201529695505050505050565b6000806040838503121561104057600080fd5b6110498361065d565b91506110576020840161065d565b90509250929050565b600080600080600080600060e0888a03121561107b57600080fd5b6110848861065d565b96506110926020890161065d565b955060408801359450606088013593506080880135600481106110b457600080fd5b925060a088013567ffffffffffffffff8111156110d057600080fd5b6110dc8a828b01610848565b92505060c0880135905092959891949750929550565b60008060006040848603121561110757600080fd5b6111108461065d565b9250602084013567ffffffffffffffff81111561112c57600080fd5b61113886828701610bab565b9497909650939450505050565b6000806040838503121561115857600080fd5b6111618361065d565b9150602083013567ffffffffffffffff8082111561117e57600080fd5b908401906080828703121561119257600080fd5b61119a61073c565b82356111a581610818565b8152602083013580151581146111ba57600080fd5b60208201526111cb6040840161065d565b60408201526060830135828111156111e257600080fd5b6111ee88828601610848565b6060830152508093505050509250929050565b6000815180845260005b818110156112275760208185018101518683018201520161120b565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815273ffffffffffffffffffffffffffffffffffffffff825116602082015260208201511515604082015267ffffffffffffffff6040830151166060820152600060608301516080808401526112c060a0840182611201565b949350505050565b600082825180855260208086019550808260051b84010181860160005b8481101561139e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a073ffffffffffffffffffffffffffffffffffffffff825116855285820151818787015261134782870182611201565b915050604080830151868303828801526113618382611201565b9250505060608083015181870152506080808301519250858203818701525061138a8183611201565b9a86019a94505050908301906001016112e5565b5090979650505050505050565b602081526113fc60208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b6000602083015161142560c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408301516101a08060e08501526114426101c0850183611201565b915060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06101008187860301818801526114808584611201565b945060808801519250818786030161012088015261149e8584611201565b945060a088015192506114ca61014088018473ffffffffffffffffffffffffffffffffffffffff169052565b60c088015161016088015260e08801516101808801528701518685039091018387015290506114f983826112c8565b9695505050505050565b67ffffffffffffffff81811683821601908082111561154b577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5092915050565b8183823760009101908152919050565b805160408084528151848201819052600092602091908201906060870190855b818110156115db578351805173ffffffffffffffffffffffffffffffffffffffff1684528501517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16858401529284019291850191600101611582565b50508583015187820388850152805180835290840192506000918401905b8083101561164a578351805167ffffffffffffffff1683528501517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16858301529284019260019290920191908501906115f9565b50979650505050505050565b60006040808301604084528086518083526060925060608601915060608160051b8701016020808a0160005b8481101561170e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08a8503018652815160a067ffffffffffffffff8083511687528583015182878901526116d983890182611201565b848d01518316898e01528b8501519092168b890152506080928301519290960191909152509482019490820190600101611682565b5050878203908801526117218189611562565b9998505050505050505050565b84815260006004851061176a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b846020830152608060408301526117846080830185611201565b905082606083015295945050505050565b600181811c908216806117a957607f821691505b6020821081036117e2577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f821115611834576000816000526020600020601f850160051c810160208610156118115750805b601f850160051c820191505b818110156118305782815560010161181d565b5050505b505050565b815167ffffffffffffffff8111156118535761185361067a565b611867816118618454611795565b846117e8565b602080601f8311600181146118ba57600084156118845750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555611830565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015611907578886015182559484019460019091019084016118e8565b508582101561194357878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c6343000818000a", + ABI: "[{\"type\":\"function\",\"name\":\"emitCCIPMessageSent\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"message\",\"type\":\"tuple\",\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"components\":[{\"name\":\"header\",\"type\":\"tuple\",\"internalType\":\"structInternal.RampMessageHeader\",\"components\":[{\"name\":\"messageId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sequenceNumber\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"receiver\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"extraArgs\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"feeToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"feeTokenAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"feeValueJuels\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"tokenAmounts\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"components\":[{\"name\":\"sourcePoolAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"destTokenAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"extraData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"destExecData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"emitCommitReportAccepted\",\"inputs\":[{\"name\":\"report\",\"type\":\"tuple\",\"internalType\":\"structOffRamp.CommitReport\",\"components\":[{\"name\":\"priceUpdates\",\"type\":\"tuple\",\"internalType\":\"structInternal.PriceUpdates\",\"components\":[{\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"components\":[{\"name\":\"sourceToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"usdPerToken\",\"type\":\"uint224\",\"internalType\":\"uint224\"}]},{\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.GasPriceUpdate[]\",\"components\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"usdPerUnitGas\",\"type\":\"uint224\",\"internalType\":\"uint224\"}]}]},{\"name\":\"merkleRoots\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.MerkleRoot[]\",\"components\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"onRampAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"minSeqNr\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"maxSeqNr\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"merkleRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"rmnSignatures\",\"type\":\"tuple[]\",\"internalType\":\"structIRMNRemote.Signature[]\",\"components\":[{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"emitExecutionStateChanged\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sequenceNumber\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"messageId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"messageHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"state\",\"type\":\"uint8\",\"internalType\":\"enumInternal.MessageExecutionState\"},{\"name\":\"returnData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"gasUsed\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getExpectedNextSequenceNumber\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getInboundNonce\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sender\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getLatestPriceSequenceNumber\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getSourceChainConfig\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structOffRamp.SourceChainConfig\",\"components\":[{\"name\":\"router\",\"type\":\"address\",\"internalType\":\"contractIRouter\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"minSeqNr\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"onRamp\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"setDestChainSeqNr\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sequenceNumber\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setInboundNonce\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"testNonce\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sender\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setLatestPriceSequenceNumber\",\"inputs\":[{\"name\":\"seqNr\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setSourceChainConfig\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sourceChainConfig\",\"type\":\"tuple\",\"internalType\":\"structOffRamp.SourceChainConfig\",\"components\":[{\"name\":\"router\",\"type\":\"address\",\"internalType\":\"contractIRouter\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"minSeqNr\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"onRamp\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"CCIPMessageSent\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"sequenceNumber\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"message\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"components\":[{\"name\":\"header\",\"type\":\"tuple\",\"internalType\":\"structInternal.RampMessageHeader\",\"components\":[{\"name\":\"messageId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sequenceNumber\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"receiver\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"extraArgs\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"feeToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"feeTokenAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"feeValueJuels\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"tokenAmounts\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"components\":[{\"name\":\"sourcePoolAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"destTokenAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"extraData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"destExecData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"CommitReportAccepted\",\"inputs\":[{\"name\":\"merkleRoots\",\"type\":\"tuple[]\",\"indexed\":false,\"internalType\":\"structInternal.MerkleRoot[]\",\"components\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"onRampAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"minSeqNr\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"maxSeqNr\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"merkleRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"priceUpdates\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structInternal.PriceUpdates\",\"components\":[{\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"components\":[{\"name\":\"sourceToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"usdPerToken\",\"type\":\"uint224\",\"internalType\":\"uint224\"}]},{\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.GasPriceUpdate[]\",\"components\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"usdPerUnitGas\",\"type\":\"uint224\",\"internalType\":\"uint224\"}]}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ExecutionStateChanged\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"sequenceNumber\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"messageId\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"messageHash\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"},{\"name\":\"state\",\"type\":\"uint8\",\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\"},{\"name\":\"returnData\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"},{\"name\":\"gasUsed\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false}]", + Bin: "0x608080604052346015576117e2908161001b8239f35b600080fdfe608080604052600436101561001357600080fd5b60003560e01c9081633f4b04aa14611503575080634bf7869714610f7457806369600bca14610f055780639041be3d14610e5657806393df286714610d97578063bfc9b789146107b9578063c1a5a3551461072b578063c7c1cba11461065b578063c9223625146105ca578063e83eabba1461029c5763e9d68a8e1461009857600080fd5b346102975760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102975767ffffffffffffffff6100d8611546565b6060806040516100e7816115c1565b60008152600060208201526000604082015201521660005260006020526040600020604051610115816115c1565b815473ffffffffffffffffffffffffffffffffffffffff811682526001602083019360ff8360a01c161515855267ffffffffffffffff604085019360a81c16835201926040519360009080549061016b82611782565b808852916001811690811561024057506001146101f0575b73ffffffffffffffffffffffffffffffffffffffff866101ec8967ffffffffffffffff89896101b4848b03856115dd565b6060860193845260405196879660208852511660208701525115156040860152511660608401525160808084015260a0830190611723565b0390f35b6000908152602081209092505b81831061022657505084016020018273ffffffffffffffffffffffffffffffffffffffff610183565b6001816020929493945483858b01015201910191906101fd565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166020808a019190915292151560051b8801909201925084915073ffffffffffffffffffffffffffffffffffffffff9050610183565b600080fd5b346102975760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610297576102d3611546565b60243567ffffffffffffffff81116102975760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82360301126102975760405161031d816115c1565b816004013573ffffffffffffffffffffffffffffffffffffffff8116810361029757815260248201358015158103610297576020820190815261036260448401611574565b6040830190815260648401359367ffffffffffffffff85116102975761039967ffffffffffffffff9160046001973692010161163f565b956060850196875216600052600060205273ffffffffffffffffffffffffffffffffffffffff60406000209351167fffffff00000000000000000000000000000000000000000000000000000000007cffffffffffffffff00000000000000000000000000000000000000000074ff000000000000000000000000000000000000000086549551151560a01b16935160a81b169316171717815501905190815167ffffffffffffffff811161059b576104528254611782565b601f8111610553575b50602092601f82116001146104b757928192936000926104ac575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c1916179055600080f35b015190508380610476565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082169383600052806000209160005b86811061053b5750836001959610610504575b505050811b019055005b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690558380806104fa565b919260206001819286850151815501940192016104e7565b826000526020600020601f830160051c81019160208410610591575b601f0160051c01905b818110610585575061045b565b60008155600101610578565b909150819061056f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b346102975760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029757610601611546565b60243567ffffffffffffffff81116102975767ffffffffffffffff6020809361062f839436906004016116cc565b939091166000526002825260406000208360405194859384378201908152030190205416604051908152f35b346102975760e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029757610692611546565b61069a61155d565b9060843560048110156102975760a43567ffffffffffffffff81116102975761070a6106eb7f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b92369060040161163f565b6040519360643585526020850152608060408501526080840190611723565b9160c43560608201528067ffffffffffffffff8060443597169516930390a4005b346102975760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029757610762611546565b67ffffffffffffffff61077361155d565b9116600052600160205267ffffffffffffffff604060002091167fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000825416179055600080f35b346102975760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102975760043567ffffffffffffffff81116102975760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc823603011261029757604051906060820182811067ffffffffffffffff82111761059b57604052806004013567ffffffffffffffff811161029757810160407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82360301126102975760405190610893826115a5565b600481013567ffffffffffffffff81116102975760049082010136601f820112156102975780356108c3816116b4565b916108d160405193846115dd565b81835260208084019260061b8201019036821161029757602001915b818310610d58575050508252602481013567ffffffffffffffff811161029757600491010136601f82011215610297578035610928816116b4565b9161093660405193846115dd565b81835260208084019260061b8201019036821161029757602001915b818310610d195750505060208201528252602481013567ffffffffffffffff81116102975781019036602383011215610297576004820135610993816116b4565b926109a160405194856115dd565b818452602060048186019360051b83010101903682116102975760248101925b828410610c5857505050506020830191825260448101359067ffffffffffffffff8211610297570136602382011215610297576004810135610a02816116b4565b91610a1060405193846115dd565b818352602060048185019360061b830101019036821161029757602401915b818310610c2757505050604083015251905160405190604082016040835283518091526060830190602060608260051b8601019501916000905b828210610b8f57505050508183036020830152604083019080519160408552825180915260206060860193019060005b818110610b3957505050602001519260208183039101526020808451928381520193019060005b818110610aef577f35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e484860385a1005b8251805167ffffffffffffffff1686526020908101517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168187015260409095019490920191600101610ac0565b8251805173ffffffffffffffffffffffffffffffffffffffff1686526020908101517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168187015260409095019490920191600101610a99565b90919295602080827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0896001950301855289519067ffffffffffffffff8251168152608080610beb8585015160a08786015260a0850190611723565b9367ffffffffffffffff604082015116604085015267ffffffffffffffff60608201511660608501520151910152980192019201909291610a69565b6040833603126102975760206040918251610c41816115a5565b853581528286013583820152815201920191610a2f565b833567ffffffffffffffff81116102975760049083010160a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082360301126102975760405191610ca883611589565b610cb460208301611574565b835260408201359267ffffffffffffffff84116102975760a060209493610ce1869586369184010161163f565b85840152610cf160608201611574565b6040840152610d0260808201611574565b6060840152013560808201528152019301926109c1565b6040833603126102975760206040918251610d33816115a5565b610d3c86611574565b8152610d498387016116fa565b83820152815201920191610952565b6040833603126102975760206040918251610d72816115a5565b610d7b8661161e565b8152610d888387016116fa565b838201528152019201916108ed565b346102975760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029757610dce611546565b610dd661155d565b906044359067ffffffffffffffff821161029757602067ffffffffffffffff9291610e06849336906004016116cc565b9390911660005260028252604060002083604051948593843782019081520301902091167fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000825416179055600080f35b346102975760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102975767ffffffffffffffff610e96611546565b166000526001602052600167ffffffffffffffff604060002054160167ffffffffffffffff8111610ed65760209067ffffffffffffffff60405191168152f35b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b346102975760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102975767ffffffffffffffff610f45611546565b167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006003541617600355600080f35b346102975760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029757610fab611546565b60243567ffffffffffffffff8111610297577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc813603016101a08112610297576040519061012082019082821067ffffffffffffffff83111761059b5760a091604052126102975760405161101f81611589565b8260040135815261103260248401611574565b602082015261104360448401611574565b604082015261105460648401611574565b606082015261106560848401611574565b6080820152815261107860a4830161161e565b926020820193845260c483013567ffffffffffffffff8111610297576110a4906004369186010161163f565b6040830190815260e484013567ffffffffffffffff8111610297576110cf906004369187010161163f565b936060840194855261010481013567ffffffffffffffff8111610297576110fc906004369184010161163f565b9460808501958652611111610124830161161e565b9560a0860196875260c0860191610144840135835260e087019361016481013585526101848101359067ffffffffffffffff821161029757019436602387011215610297576004860135611164816116b4565b9661117260405198896115dd565b81885260206004818a019360051b83010101903682116102975760248101925b8284106114115750505050610100880195865287516060015167ffffffffffffffff16996040519860208a5251805160208b0152602081015167ffffffffffffffff1660408b0152604081015167ffffffffffffffff1660608b0152606081015167ffffffffffffffff1660808b01526080015167ffffffffffffffff1660a08a01525173ffffffffffffffffffffffffffffffffffffffff1660c08901525160e088016101a090526101c0880161124991611723565b9051908781037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00161010089015261128091611723565b9051908681037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0016101208801526112b791611723565b955173ffffffffffffffffffffffffffffffffffffffff16610140860152516101608501525161018084015251928281037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0016101a0840152835180825260208201918160051b810160200195602001926000915b838310611367578867ffffffffffffffff87167f192442a2b2adb6a7948f097023cb6b57d29d3a7a5dd33e6666d33c39cc456f32898b038aa3005b9091929396602080611402837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086600196030187528b519073ffffffffffffffffffffffffffffffffffffffff825116815260806113e76113d58685015160a08886015260a0850190611723565b60408501518482036040860152611723565b92606081015160608401520151906080818403910152611723565b9901930193019193929061132c565b833567ffffffffffffffff81116102975760049083010160a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08236030112610297576040519161146183611589565b61146d6020830161161e565b8352604082013567ffffffffffffffff811161029757611493906020369185010161163f565b6020840152606082013567ffffffffffffffff8111610297576114bc906020369185010161163f565b60408401526080820135606084015260a08201359267ffffffffffffffff8411610297576114f3602094938580953692010161163f565b6080820152815201930192611192565b346102975760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102975760209067ffffffffffffffff600354168152f35b6004359067ffffffffffffffff8216820361029757565b6024359067ffffffffffffffff8216820361029757565b359067ffffffffffffffff8216820361029757565b60a0810190811067ffffffffffffffff82111761059b57604052565b6040810190811067ffffffffffffffff82111761059b57604052565b6080810190811067ffffffffffffffff82111761059b57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761059b57604052565b359073ffffffffffffffffffffffffffffffffffffffff8216820361029757565b81601f820112156102975780359067ffffffffffffffff821161059b576040519261169260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f86011601856115dd565b8284526020838301011161029757816000926020809301838601378301015290565b67ffffffffffffffff811161059b5760051b60200190565b9181601f840112156102975782359167ffffffffffffffff8311610297576020838186019501011161029757565b35907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8216820361029757565b919082519283825260005b84811061176d5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b8060208092840101518282860101520161172e565b90600182811c921680156117cb575b602083101461179c57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f169161179156fea164736f6c634300081a000a", } var CCIPReaderTesterABI = CCIPReaderTesterMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/ether_sender_receiver/ether_sender_receiver.go b/core/gethwrappers/ccip/generated/ether_sender_receiver/ether_sender_receiver.go index 505e42e98ec..f3d6ac3a928 100644 --- a/core/gethwrappers/ccip/generated/ether_sender_receiver/ether_sender_receiver.go +++ b/core/gethwrappers/ccip/generated/ether_sender_receiver/ether_sender_receiver.go @@ -50,8 +50,8 @@ type ClientEVMTokenAmount struct { } var EtherSenderReceiverMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"name\":\"InvalidRouter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"gotToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"expectedToken\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gotAmounts\",\"type\":\"uint256\"}],\"name\":\"InvalidTokenAmounts\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gotAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"msgValue\",\"type\":\"uint256\"}],\"name\":\"TokenAmountNotEqualToMsgValue\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destinationChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"ccipSend\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destinationChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_weth\",\"outputs\":[{\"internalType\":\"contractIWrappedNative\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", - Bin: "0x60c06040523480156200001157600080fd5b5060405162001a9838038062001a98833981016040819052620000349162000169565b806001600160a01b03811662000064576040516335fdcccd60e21b81526000600482015260240160405180910390fd5b806001600160a01b03166080816001600160a01b03168152505050806001600160a01b031663e861e9076040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000be573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000e4919062000169565b6001600160a01b0390811660a081905260405163095ea7b360e01b8152918316600483015260001960248301529063095ea7b3906044016020604051808303816000875af11580156200013b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016191906200019b565b5050620001bf565b6000602082840312156200017c57600080fd5b81516001600160a01b03811681146200019457600080fd5b9392505050565b600060208284031215620001ae57600080fd5b815180151581146200019457600080fd5b60805160a051611851620002476000396000818161014b015281816104030152818161059401528181610905015281816109cc01528181610a6401528181610b0201528181610bf70152610cbf0152600081816101d6015281816102df01528181610377015281816104ab0152818161060b015281816106ff01526107bf01526118516000f3fe6080604052600436106100745760003560e01c80634dbe7e921161004e5780634dbe7e921461013957806385572ffb1461019257806396f4e9f9146101b4578063b0f479a1146101c757600080fd5b806301ffc9a714610080578063181f5a77146100b557806320487ded1461010b57600080fd5b3661007b57005b600080fd5b34801561008c57600080fd5b506100a061009b3660046110e3565b6101fa565b60405190151581526020015b60405180910390f35b3480156100c157600080fd5b506100fe6040518060400160405280601981526020017f457468657253656e646572526563656976657220312e352e300000000000000081525081565b6040516100ac919061119a565b34801561011757600080fd5b5061012b6101263660046111e2565b610293565b6040519081526020016100ac565b34801561014557600080fd5b5061016d7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100ac565b34801561019e57600080fd5b506101b26101ad366004611230565b61035f565b005b61012b6101c23660046111e2565b6103e9565b3480156101d357600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061016d565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f85572ffb00000000000000000000000000000000000000000000000000000000148061028d57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b60008061029f83610844565b6040517f20487ded00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906320487ded906103169087908590600401611265565b602060405180830381865afa158015610333573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610357919061137a565b949350505050565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146103d5576040517fd7f733340000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b6103e66103e1826115c5565b610966565b50565b60006103f482610d38565b60006103ff83610844565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040015160008151811061045457610454611672565b6020026020010151602001516040518263ffffffff1660e01b81526004016000604051808303818588803b15801561048b57600080fd5b505af115801561049f573d6000803e3d6000fd5b505050505060006104cd7f000000000000000000000000000000000000000000000000000000000000000090565b73ffffffffffffffffffffffffffffffffffffffff166320487ded86846040518363ffffffff1660e01b8152600401610507929190611265565b602060405180830381865afa158015610524573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610548919061137a565b606083015190915073ffffffffffffffffffffffffffffffffffffffff16156107825760608201516105929073ffffffffffffffffffffffffffffffffffffffff16333084610df0565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16826060015173ffffffffffffffffffffffffffffffffffffffff16146106c257606082015173ffffffffffffffffffffffffffffffffffffffff1663095ea7b37f00000000000000000000000000000000000000000000000000000000000000006040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602481018490526044016020604051808303816000875af115801561069c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106c091906116a1565b505b6040517f96f4e9f900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906396f4e9f9906107369088908690600401611265565b6020604051808303816000875af1158015610755573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610779919061137a565b9250505061028d565b6040517f96f4e9f900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906396f4e9f99047906107f89089908790600401611265565b60206040518083038185885af1158015610816573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061083b919061137a565b95945050505050565b61088c6040518060a00160405280606081526020016060815260200160608152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001606081525090565b6000610897836116c3565b90508060400151516001146108e1578060400151516040517f83b9f0ae0000000000000000000000000000000000000000000000000000000081526004016103cc91815260200190565b604080513360208201520160405160208183030381529060405281602001819052507f0000000000000000000000000000000000000000000000000000000000000000816040015160008151811061093b5761093b611672565b602090810291909101015173ffffffffffffffffffffffffffffffffffffffff909116905292915050565b60008160600151806020019051810190610980919061177f565b90508160800151516001146109ca578160800151516040517f83b9f0ae0000000000000000000000000000000000000000000000000000000081526004016103cc91815260200190565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168260800151600081518110610a1857610a18611672565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1614610ad9578160800151600081518110610a5657610a56611672565b6020026020010151600001517f00000000000000000000000000000000000000000000000000000000000000006040517f0fc746a10000000000000000000000000000000000000000000000000000000081526004016103cc92919073ffffffffffffffffffffffffffffffffffffffff92831681529116602082015260400190565b60008260800151600081518110610af257610af2611672565b60200260200101516020015190507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d826040518263ffffffff1660e01b8152600401610b5b91815260200190565b600060405180830381600087803b158015610b7557600080fd5b505af1158015610b89573d6000803e3d6000fd5b5050505060008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114610be7576040519150601f19603f3d011682016040523d82523d6000602084013e610bec565b606091505b5050905080610d32577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0836040518263ffffffff1660e01b81526004016000604051808303818588803b158015610c5d57600080fd5b505af1158015610c71573d6000803e3d6000fd5b50506040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8781166004830152602482018790527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015610d0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3091906116a1565b505b50505050565b6000610d47604083018361179c565b6000818110610d5857610d58611672565b905060400201602001359050600073ffffffffffffffffffffffffffffffffffffffff16826060016020810190610d8f919061180b565b73ffffffffffffffffffffffffffffffffffffffff1614610dec57803414610dec576040517fba2f7467000000000000000000000000000000000000000000000000000000008152600481018290523460248201526044016103cc565b5050565b6040805173ffffffffffffffffffffffffffffffffffffffff8581166024830152848116604483015260648083018590528351808403909101815260849092018352602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905283518085019094528084527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656490840152610d3292879291600091610ec3918516908490610f72565b805190915015610f6d5780806020019051810190610ee191906116a1565b610f6d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016103cc565b505050565b60606103578484600085856000808673ffffffffffffffffffffffffffffffffffffffff168587604051610fa69190611828565b60006040518083038185875af1925050503d8060008114610fe3576040519150601f19603f3d011682016040523d82523d6000602084013e610fe8565b606091505b5091509150610ff987838387611004565b979650505050505050565b6060831561109a5782516000036110935773ffffffffffffffffffffffffffffffffffffffff85163b611093576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016103cc565b5081610357565b61035783838151156110af5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103cc919061119a565b6000602082840312156110f557600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461112557600080fd5b9392505050565b60005b8381101561114757818101518382015260200161112f565b50506000910152565b6000815180845261116881602086016020860161112c565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006111256020830184611150565b803567ffffffffffffffff811681146111c557600080fd5b919050565b600060a082840312156111dc57600080fd5b50919050565b600080604083850312156111f557600080fd5b6111fe836111ad565b9150602083013567ffffffffffffffff81111561121a57600080fd5b611226858286016111ca565b9150509250929050565b60006020828403121561124257600080fd5b813567ffffffffffffffff81111561125957600080fd5b610357848285016111ca565b6000604067ffffffffffffffff851683526020604081850152845160a0604086015261129460e0860182611150565b9050818601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0808784030160608801526112cf8383611150565b6040890151888203830160808a01528051808352908601945060009350908501905b80841015611330578451805173ffffffffffffffffffffffffffffffffffffffff168352860151868301529385019360019390930192908601906112f1565b50606089015173ffffffffffffffffffffffffffffffffffffffff1660a08901526080890151888203830160c08a0152955061136c8187611150565b9a9950505050505050505050565b60006020828403121561138c57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156113e5576113e5611393565b60405290565b60405160a0810167ffffffffffffffff811182821017156113e5576113e5611393565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561145557611455611393565b604052919050565b600082601f83011261146e57600080fd5b813567ffffffffffffffff81111561148857611488611393565b6114b960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161140e565b8181528460208386010111156114ce57600080fd5b816020850160208301376000918101602001919091529392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146103e657600080fd5b80356111c5816114eb565b600082601f83011261152957600080fd5b8135602067ffffffffffffffff82111561154557611545611393565b611553818360051b0161140e565b82815260069290921b8401810191818101908684111561157257600080fd5b8286015b848110156115ba576040818903121561158f5760008081fd5b6115976113c2565b81356115a2816114eb565b81528185013585820152835291830191604001611576565b509695505050505050565b600060a082360312156115d757600080fd5b6115df6113eb565b823581526115ef602084016111ad565b6020820152604083013567ffffffffffffffff8082111561160f57600080fd5b61161b3683870161145d565b6040840152606085013591508082111561163457600080fd5b6116403683870161145d565b6060840152608085013591508082111561165957600080fd5b5061166636828601611518565b60808301525092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156116b357600080fd5b8151801515811461112557600080fd5b600060a082360312156116d557600080fd5b6116dd6113eb565b823567ffffffffffffffff808211156116f557600080fd5b6117013683870161145d565b8352602085013591508082111561171757600080fd5b6117233683870161145d565b6020840152604085013591508082111561173c57600080fd5b61174836838701611518565b60408401526117596060860161150d565b6060840152608085013591508082111561177257600080fd5b506116663682860161145d565b60006020828403121561179157600080fd5b8151611125816114eb565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126117d157600080fd5b83018035915067ffffffffffffffff8211156117ec57600080fd5b6020019150600681901b360382131561180457600080fd5b9250929050565b60006020828403121561181d57600080fd5b8135611125816114eb565b6000825161183a81846020870161112c565b919091019291505056fea164736f6c6343000818000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"router\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"receive\",\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"ccipReceive\",\"inputs\":[{\"name\":\"message\",\"type\":\"tuple\",\"internalType\":\"structClient.Any2EVMMessage\",\"components\":[{\"name\":\"messageId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sender\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\",\"internalType\":\"structClient.EVMTokenAmount[]\",\"components\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"ccipSend\",\"inputs\":[{\"name\":\"destinationChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"message\",\"type\":\"tuple\",\"internalType\":\"structClient.EVM2AnyMessage\",\"components\":[{\"name\":\"receiver\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"tokenAmounts\",\"type\":\"tuple[]\",\"internalType\":\"structClient.EVMTokenAmount[]\",\"components\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"feeToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"extraArgs\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"getFee\",\"inputs\":[{\"name\":\"destinationChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"message\",\"type\":\"tuple\",\"internalType\":\"structClient.EVM2AnyMessage\",\"components\":[{\"name\":\"receiver\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"tokenAmounts\",\"type\":\"tuple[]\",\"internalType\":\"structClient.EVMTokenAmount[]\",\"components\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"feeToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"extraArgs\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"fee\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRouter\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"i_weth\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIWrappedNative\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"typeAndVersion\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"error\",\"name\":\"InvalidRouter\",\"inputs\":[{\"name\":\"router\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"InvalidToken\",\"inputs\":[{\"name\":\"gotToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"expectedToken\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"InvalidTokenAmounts\",\"inputs\":[{\"name\":\"gotAmounts\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"TokenAmountNotEqualToMsgValue\",\"inputs\":[{\"name\":\"gotAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"msgValue\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}]", + Bin: "0x60c080604052346101245761002a9061161380380380916100208285610180565b83398101906101b9565b6001600160a01b03811690811561016a5760805260405163e861e90760e01b815290602082600481845afa908115610131576044602092600094859161013d575b506001600160a01b031660a081905260405163095ea7b360e01b8152600481019390935284196024840152919384928391905af18015610131576100f4575b60405161143a90816101d9823960805181818160bd01528181610185015281816106170152610d44015260a0518181816102cf0152818161058601528181610ccc01526112d40152f35b6020813d602011610129575b8161010d60209383610180565b8101031261012457518015150361012457386100aa565b600080fd5b3d9150610100565b6040513d6000823e3d90fd5b61015d9150843d8611610163575b6101558183610180565b8101906101b9565b3861006b565b503d61014b565b6335fdcccd60e21b600052600060045260246000fd5b601f909101601f19168101906001600160401b038211908210176101a357604052565b634e487b7160e01b600052604160045260246000fd5b9081602091031261012457516001600160a01b0381168103610124579056fe608080604052600436101561001d575b50361561001b57600080fd5b005b600090813560e01c90816301ffc9a71461070b57508063181f5a771461068857806320487ded146105aa5780634dbe7e921461053b57806385572ffb1461010057806396f4e9f9146100e45763b0f479a10361000f57346100e157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100e157602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b80fd5b60206100f86100f2366108f2565b90610c23565b604051908152f35b50346100e15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100e15760043567ffffffffffffffff81116105375760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82360301126105375773ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361050b576040516101b7816107cd565b81600401358152602482013567ffffffffffffffff81168103610468576020820152604482013567ffffffffffffffff8111610468576101fd9060043691850101610ac0565b6040820152606482013567ffffffffffffffff8111610468576102269060043691850101610ac0565b9160608201928352608481013567ffffffffffffffff81116105075760809160046102549236920101610b28565b9101918183525160208180518101031261046857602001519073ffffffffffffffffffffffffffffffffffffffff82168092036104685751600181036104dc575073ffffffffffffffffffffffffffffffffffffffff6102b48351610bcf565b5151169173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001680930361048b5761030260209151610bcf565b51015190823b15610468576040517f2e1a7d4d000000000000000000000000000000000000000000000000000000008152826004820152848160248183885af180156104805761046c575b508380808085855af161035e61132d565b5015610368578380f35b823b1561046857836040517fd0e30db0000000000000000000000000000000000000000000000000000000008152818160048187895af180156104445761044f575b506040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff929092166004830152602482019290925291602091839160449183915af1801561044457610415575b80808380f35b6104369060203d60201161043d575b61042e8183610818565b810190610c0b565b503861040f565b503d610424565b6040513d84823e3d90fd5b8161045c91949394610818565b610468579083386103aa565b8380fd5b8461047991959295610818565b923861034d565b6040513d87823e3d90fd5b838373ffffffffffffffffffffffffffffffffffffffff6104ae60449451610bcf565b5151167f0fc746a1000000000000000000000000000000000000000000000000000000008352600452602452fd5b7f83b9f0ae000000000000000000000000000000000000000000000000000000008452600452602483fd5b8480fd5b6024827fd7f7333400000000000000000000000000000000000000000000000000000000815233600452fd5b5080fd5b50346100e157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100e157602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346100e1576105fe60206105c96105c1366108f2565b9190916111ae565b9060405193849283927f20487ded0000000000000000000000000000000000000000000000000000000084526004840161097c565b038173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa908115610444578291610652575b602082604051908152f35b90506020813d602011610680575b8161066d60209383610818565b8101031261053757602091505138610647565b3d9150610660565b50346100e157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100e157506107076040516106c9604082610818565b601981527f457468657253656e646572526563656976657220312e352e30000000000000006020820152604051918291602083526020830190610893565b0390f35b9050346105375760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610537576004357fffffffff0000000000000000000000000000000000000000000000000000000081168091036107c957602092507f85572ffb00000000000000000000000000000000000000000000000000000000811490811561079f575b5015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501438610798565b8280fd5b60a0810190811067ffffffffffffffff8211176107e957604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176107e957604052565b67ffffffffffffffff81116107e957601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b919082519283825260005b8481106108dd5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b8060208092840101518282860101520161089e565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126109775760043567ffffffffffffffff8116810361097757916024359067ffffffffffffffff8211610977577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8260a0920301126109775760040190565b600080fd5b9067ffffffffffffffff90939293168152604060208201526109e16109ad845160a0604085015260e0840190610893565b60208501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0848303016060850152610893565b906040840151917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08282030160808301526020808451928381520193019060005b818110610a885750505060808473ffffffffffffffffffffffffffffffffffffffff6060610a85969701511660a084015201519060c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc082850301910152610893565b90565b8251805173ffffffffffffffffffffffffffffffffffffffff1686526020908101518187015260409095019490920191600101610a22565b81601f8201121561097757803590610ad782610859565b92610ae56040519485610818565b8284526020838301011161097757816000926020809301838601378301015290565b359073ffffffffffffffffffffffffffffffffffffffff8216820361097757565b81601f820112156109775780359067ffffffffffffffff82116107e95760405192610b5960208460051b0185610818565b82845260208085019360061b8301019181831161097757602001925b828410610b83575050505090565b6040848303126109775760405190604082019082821067ffffffffffffffff8311176107e9576040926020928452610bba87610b07565b81528287013583820152815201930192610b75565b805115610bdc5760200190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90816020910312610977575180151581036109775790565b9060009060408101357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1823603018112156107c9578101803567ffffffffffffffff8111610468578060061b3603602083011361046857156111815760400135606082013573ffffffffffffffffffffffffffffffffffffffff81168091036104685761114b575b50610cb5906111ae565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166020610cfb6040840151610bcf565b510151813b156104685783600491604051928380927fd0e30db0000000000000000000000000000000000000000000000000000000008252865af180156111405761112c575b507f00000000000000000000000000000000000000000000000000000000000000009373ffffffffffffffffffffffffffffffffffffffff851691604051907f20487ded00000000000000000000000000000000000000000000000000000000825260208280610db588876004840161097c565b0381875afa9182156111215786926110ed575b50606085019673ffffffffffffffffffffffffffffffffffffffff8851169788610e805750505050610e319394509060209291476040518096819582947f96f4e9f90000000000000000000000000000000000000000000000000000000084526004840161097c565b03925af1918215610e745791610e45575090565b90506020813d602011610e6c575b81610e6060209383610818565b81010312610977575190565b3d9150610e53565b604051903d90823e3d90fd5b610f20604051602081019a7f23b872dd000000000000000000000000000000000000000000000000000000008c5233602483015230604483015286606483015260648252610ecf608483610818565b8a8060409d8e94610ee286519687610818565b602086527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65646020870152519082855af1610f1a61132d565b9161135d565b80518061104c575b50505173ffffffffffffffffffffffffffffffffffffffff16918203610fa9575b505050916020918493610f8a9587518097819582947f96f4e9f90000000000000000000000000000000000000000000000000000000084526004840161097c565b03925af1928315610f9f575091610e45575090565b51903d90823e3d90fd5b87517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91909116600482015260248101929092526020908290604490829089905af18015611042579160209391610f8a969593611025575b8193959650829450610f49565b61103b90853d871161043d5761042e8183610818565b5038611018565b86513d87823e3d90fd5b9060208061105e938301019101610c0b565b1561106a573880610f28565b608489517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152fd5b9091506020813d602011611119575b8161110960209383610818565b8101031261097757519038610dc8565b3d91506110fc565b6040513d88823e3d90fd5b8361113991949294610818565b9138610d41565b6040513d86823e3d90fd5b348114610cab577fba2f746700000000000000000000000000000000000000000000000000000000835260045234602452604482fd5b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526032600452fd5b606060806040516111be816107cd565b828152826020820152826040820152600083820152015260a08136031261097757604051906111ec826107cd565b803567ffffffffffffffff81116109775761120a9036908301610ac0565b8252602081013567ffffffffffffffff81116109775761122d9036908301610ac0565b60208301908152604082013567ffffffffffffffff8111610977576112559036908401610b28565b916040840192835261126960608201610b07565b606085015260808101359067ffffffffffffffff82116109775761128f91369101610ac0565b608084015281515160018103611300575060405190336020830152602082526112b9604083610818565b526112fb73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169151610bcf565b515290565b7f83b9f0ae0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b3d15611358573d9061133e82610859565b9161134c6040519384610818565b82523d6000602084013e565b606090565b919290156113d85750815115611371575090565b3b1561137a5790565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152fd5b8251909150156113eb5750805190602001fd5b611429906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352602060048401526024830190610893565b0390fdfea164736f6c634300081a000a", } var EtherSenderReceiverABI = EtherSenderReceiverMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go b/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go index 1f64166ac74..a8ee1906951 100644 --- a/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go +++ b/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go @@ -54,18 +54,20 @@ type FeeQuoterDestChainConfig struct { MaxDataBytes uint32 MaxPerMsgGasLimit uint32 DestGasOverhead uint32 - DestGasPerPayloadByte uint16 + DestGasPerPayloadByteBase uint8 + DestGasPerPayloadByteHigh uint8 + DestGasPerPayloadByteThreshold uint16 DestDataAvailabilityOverheadGas uint32 DestGasPerDataAvailabilityByte uint16 DestDataAvailabilityMultiplierBps uint16 + ChainFamilySelector [4]byte + EnforceOutOfOrder bool DefaultTokenFeeUSDCents uint16 DefaultTokenDestGasOverhead uint32 DefaultTxGasLimit uint32 GasMultiplierWeiPerEth uint64 - NetworkFeeUSDCents uint32 GasPriceStalenessThreshold uint32 - EnforceOutOfOrder bool - ChainFamilySelector [4]byte + NetworkFeeUSDCents uint32 } type FeeQuoterDestChainConfigArgs struct { @@ -156,8 +158,8 @@ type KeystoneFeedsPermissionHandlerPermission struct { } var FeeQuoterMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"tokenPriceStalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"priceUpdaters\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeeds\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DataFeedValueOutOfUint224Range\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"DestinationChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"FeeTokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"}],\"name\":\"InvalidDestBytesOverhead\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minFeeUSDCents\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint256\"}],\"name\":\"InvalidFeeRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint256\"}],\"name\":\"MessageFeeTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MessageGasLimitTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualSize\",\"type\":\"uint256\"}],\"name\":\"MessageTooLarge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"}],\"name\":\"ReportForwarderUnauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SourceTokenDataTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timePassed\",\"type\":\"uint256\"}],\"name\":\"StaleGasPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numberOfTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint256\"}],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenRemoved\",\"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\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"name\":\"PremiumMultiplierWeiPerEthUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"priceFeedConfig\",\"type\":\"tuple\"}],\"name\":\"PriceFeedPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"reportId\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission\",\"name\":\"permission\",\"type\":\"tuple\"}],\"name\":\"ReportPermissionSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenTransferFeeConfigDeleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"name\":\"TokenTransferFeeConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChain\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerUnitGasUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FEE_BASE_DECIMALS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"KEYSTONE_PRICE_DECIMALS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address[]\",\"name\":\"addedCallers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedCallers\",\"type\":\"address[]\"}],\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\"}],\"name\":\"applyAuthorizedCallerUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"feeTokensToRemove\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokensToAdd\",\"type\":\"address[]\"}],\"name\":\"applyFeeTokensUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyPremiumMultiplierWeiPerEthUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigRemoveArgs[]\",\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"tuple[]\"}],\"name\":\"applyTokenTransferFeeConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"fromToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"toToken\",\"type\":\"address\"}],\"name\":\"convertTokenAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedCallers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestinationChainGasPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFeeTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getPremiumMultiplierWeiPerEth\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"tokenPriceStalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getTokenAndGasPrices\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"tokenPrice\",\"type\":\"uint224\"},{\"internalType\":\"uint224\",\"name\":\"gasPriceValue\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPriceFeedConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getTokenPrices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenTransferFeeConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getValidatedFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getValidatedTokenPrice\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"onReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"onRampTokenTransfers\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"sourceTokenAmounts\",\"type\":\"tuple[]\"}],\"name\":\"processMessageArgs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isOutOfOrderExecution\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"convertedExtraArgs\",\"type\":\"bytes\"},{\"internalType\":\"bytes[]\",\"name\":\"destExecDataPerToken\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission[]\",\"name\":\"permissions\",\"type\":\"tuple[]\"}],\"name\":\"setReportPermissions\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"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\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"updatePrices\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeedUpdates\",\"type\":\"tuple[]\"}],\"name\":\"updateTokenPriceFeeds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60e06040523480156200001157600080fd5b5060405162007a6838038062007a6883398101604081905262000034916200189c565b85336000816200005757604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008a576200008a81620001d0565b5050604080518082018252828152815160008152602080820190935291810191909152620000b8906200024a565b5060208701516001600160a01b03161580620000dc575086516001600160601b0316155b80620000f05750604087015163ffffffff16155b156200010f5760405163d794ef9560e01b815260040160405180910390fd5b6020878101516001600160a01b031660a05287516001600160601b031660805260408089015163ffffffff1660c052805160008152918201905262000155908662000399565b6200016084620004e1565b6200016b81620005d9565b620001768262000a45565b60408051600080825260208201909252620001c391859190620001bc565b6040805180820190915260008082526020820152815260200190600190039081620001945790505b5062000b11565b5050505050505062001b5a565b336001600160a01b03821603620001fa57604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b8151811015620002da576000828281518110620002735762000273620019bb565b602090810291909101015190506200028d60028262000e97565b15620002d0576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b5060010162000252565b50815160005b815181101562000393576000828281518110620003015762000301620019bb565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200033f576040516342bcdf7f60e11b815260040160405180910390fd5b6200034c60028262000eb7565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101620002e0565b50505050565b60005b82518110156200043a57620003d8838281518110620003bf57620003bf620019bb565b6020026020010151600b62000ece60201b90919060201c565b156200043157828181518110620003f357620003f3620019bb565b60200260200101516001600160a01b03167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b6001016200039c565b5060005b8151811015620004dc576200047a828281518110620004615762000461620019bb565b6020026020010151600b62000eb760201b90919060201c565b15620004d357818181518110620004955762000495620019bb565b60200260200101516001600160a01b03167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b6001016200043e565b505050565b60005b8151811015620005d5576000828281518110620005055762000505620019bb565b6020908102919091018101518051818301516001600160a01b0380831660008181526007875260409081902084518154868a0180518589018051949098166001600160a81b03199093168317600160a01b60ff928316021760ff60a81b1916600160a81b9415159490940293909317909355835190815291511697810197909752915115159186019190915292945090929091907fe6a7a17d710bf0b2cd05e5397dc6f97a5da4ee79e31e234bf5f965ee2bd9a5bf9060600160405180910390a2505050806001019050620004e4565b5050565b60005b8151811015620005d5576000828281518110620005fd57620005fd620019bb565b6020026020010151905060008383815181106200061e576200061e620019bb565b6020026020010151600001519050600082602001519050816001600160401b03166000148062000657575061016081015163ffffffff16155b806200067957506102008101516001600160e01b031916630a04b54b60e21b14155b80620006995750806060015163ffffffff1681610160015163ffffffff16115b15620006c85760405163c35aa79d60e01b81526001600160401b03831660048201526024015b60405180910390fd5b6001600160401b038216600090815260096020526040812060010154600160a81b900460e01b6001600160e01b03191690036200074857816001600160401b03167f525e3d4e0c31cef19cf9426af8d2c0ddd2d576359ca26bed92aac5fadda46265826040516200073a9190620019d1565b60405180910390a26200078c565b816001600160401b03167f283b699f411baff8f1c29fe49f32a828c8151596244b8e7e4c164edd6569a83582604051620007839190620019d1565b60405180910390a25b8060096000846001600160401b03166001600160401b0316815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a8154816001600160401b0302191690836001600160401b031602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160146101000a81548160ff0219169083151502179055506102008201518160010160156101000a81548163ffffffff021916908360e01c0217905550905050505050806001019050620005dc565b60005b8151811015620005d557600082828151811062000a695762000a69620019bb565b6020026020010151600001519050600083838151811062000a8e5762000a8e620019bb565b6020908102919091018101518101516001600160a01b03841660008181526008845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010162000a48565b60005b825181101562000dd157600083828151811062000b355762000b35620019bb565b6020026020010151905060008160000151905060005b82602001515181101562000dc25760008360200151828151811062000b745762000b74620019bb565b602002602001015160200151905060008460200151838151811062000b9d5762000b9d620019bb565b6020026020010151600001519050816020015163ffffffff16826000015163ffffffff161062000bf857815160208301516040516305a7b3d160e11b815263ffffffff928316600482015291166024820152604401620006bf565b602063ffffffff16826080015163ffffffff16101562000c495760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff9091166024820152604401620006bf565b6001600160401b0384166000818152600a602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000daf908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000b4b565b50505080600101905062000b14565b5060005b8151811015620004dc57600082828151811062000df65762000df6620019bb565b6020026020010151600001519050600083838151811062000e1b5762000e1b620019bb565b6020908102919091018101518101516001600160401b0384166000818152600a845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010162000dd5565b600062000eae836001600160a01b03841662000ee5565b90505b92915050565b600062000eae836001600160a01b03841662000fe9565b600062000eae836001600160a01b0384166200103b565b6000818152600183016020526040812054801562000fde57600062000f0c60018362001b22565b855490915060009062000f229060019062001b22565b905081811462000f8e57600086600001828154811062000f465762000f46620019bb565b906000526020600020015490508087600001848154811062000f6c5762000f6c620019bb565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000fa25762000fa262001b44565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000eb1565b600091505062000eb1565b6000818152600183016020526040812054620010325750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000eb1565b50600062000eb1565b6000818152600183016020526040812054801562000fde5760006200106260018362001b22565b8554909150600090620010789060019062001b22565b905080821462000f8e57600086600001828154811062000f465762000f46620019bb565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b0381118282101715620010d757620010d76200109c565b60405290565b604080519081016001600160401b0381118282101715620010d757620010d76200109c565b60405160c081016001600160401b0381118282101715620010d757620010d76200109c565b60405161022081016001600160401b0381118282101715620010d757620010d76200109c565b604051601f8201601f191681016001600160401b03811182821017156200117857620011786200109c565b604052919050565b80516001600160a01b03811681146200119857600080fd5b919050565b805163ffffffff811681146200119857600080fd5b600060608284031215620011c557600080fd5b620011cf620010b2565b82519091506001600160601b0381168114620011ea57600080fd5b8152620011fa6020830162001180565b60208201526200120d604083016200119d565b604082015292915050565b60006001600160401b038211156200123457620012346200109c565b5060051b60200190565b600082601f8301126200125057600080fd5b8151602062001269620012638362001218565b6200114d565b8083825260208201915060208460051b8701019350868411156200128c57600080fd5b602086015b84811015620012b357620012a58162001180565b835291830191830162001291565b509695505050505050565b805180151581146200119857600080fd5b600082601f830112620012e157600080fd5b81516020620012f4620012638362001218565b82815260079290921b840181019181810190868411156200131457600080fd5b8286015b84811015620012b3578088036080811215620013345760008081fd5b6200133e620010dd565b620013498362001180565b8152606080601f1984011215620013605760008081fd5b6200136a620010b2565b92506200137987850162001180565b835260408085015160ff81168114620013925760008081fd5b84890152620013a3858301620012be565b90840152508086019190915283529183019160800162001318565b80516001600160401b03811681146200119857600080fd5b805161ffff811681146200119857600080fd5b600082601f830112620013fb57600080fd5b815160206200140e620012638362001218565b82815260059290921b840181019181810190868411156200142e57600080fd5b8286015b84811015620012b35780516001600160401b03808211156200145357600080fd5b908801906040601f19838c0381018213156200146e57600080fd5b62001478620010dd565b62001485898601620013be565b815282850151848111156200149957600080fd5b8086019550508c603f860112620014af57600080fd5b888501519350620014c4620012638562001218565b84815260e09094028501830193898101908e861115620014e357600080fd5b958401955b85871015620015bc57868f0360e08112156200150357600080fd5b6200150d620010dd565b620015188962001180565b815260c086830112156200152b57600080fd5b6200153562001102565b9150620015448d8a016200119d565b825262001553878a016200119d565b8d8301526200156560608a01620013d6565b878301526200157760808a016200119d565b60608301526200158a60a08a016200119d565b60808301526200159d60c08a01620012be565b60a0830152808d0191909152825260e09690960195908a0190620014e8565b828b01525087525050509284019250830162001432565b600082601f830112620015e557600080fd5b81516020620015f8620012638362001218565b82815260069290921b840181019181810190868411156200161857600080fd5b8286015b84811015620012b35760408189031215620016375760008081fd5b62001641620010dd565b6200164c8262001180565b81526200165b858301620013be565b818601528352918301916040016200161c565b80516001600160e01b0319811681146200119857600080fd5b600082601f8301126200169957600080fd5b81516020620016ac620012638362001218565b8281526102409283028501820192828201919087851115620016cd57600080fd5b8387015b858110156200188f5780890382811215620016ec5760008081fd5b620016f6620010dd565b6200170183620013be565b815261022080601f1984011215620017195760008081fd5b6200172362001127565b925062001732888501620012be565b8352604062001743818601620013d6565b898501526060620017568187016200119d565b82860152608091506200176b8287016200119d565b9085015260a06200177e8682016200119d565b8286015260c0915062001793828701620013d6565b9085015260e0620017a68682016200119d565b828601526101009150620017bc828701620013d6565b90850152610120620017d0868201620013d6565b828601526101409150620017e6828701620013d6565b90850152610160620017fa8682016200119d565b828601526101809150620018108287016200119d565b908501526101a062001824868201620013be565b828601526101c091506200183a8287016200119d565b908501526101e06200184e8682016200119d565b82860152610200915062001864828701620012be565b90850152620018758583016200166e565b9084015250808701919091528452928401928101620016d1565b5090979650505050505050565b6000806000806000806000610120888a031215620018b957600080fd5b620018c58989620011b2565b60608901519097506001600160401b0380821115620018e357600080fd5b620018f18b838c016200123e565b975060808a01519150808211156200190857600080fd5b620019168b838c016200123e565b965060a08a01519150808211156200192d57600080fd5b6200193b8b838c01620012cf565b955060c08a01519150808211156200195257600080fd5b620019608b838c01620013e9565b945060e08a01519150808211156200197757600080fd5b620019858b838c01620015d3565b93506101008a01519150808211156200199d57600080fd5b50620019ac8a828b0162001687565b91505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b81511515815261022081016020830151620019f2602084018261ffff169052565b50604083015162001a0b604084018263ffffffff169052565b50606083015162001a24606084018263ffffffff169052565b50608083015162001a3d608084018263ffffffff169052565b5060a083015162001a5460a084018261ffff169052565b5060c083015162001a6d60c084018263ffffffff169052565b5060e083015162001a8460e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501516001600160401b0316908401526101a0808501518216908401526101c080850151909116908301526101e080840151151590830152610200928301516001600160e01b031916929091019190915290565b8181038181111562000eb157634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c051615ebb62001bad6000396000818161032801526119170152600081816102ec0152818161103401526110940152600081816102b8015281816110bd015261112d0152615ebb6000f3fe608060405234801561001057600080fd5b50600436106101e45760003560e01c8063770e2dc41161010f578063bf78e03f116100a2578063d8694ccd11610071578063d8694ccd14610b04578063f2fde38b14610b17578063fbe3f77814610b2a578063ffdb4b3714610b3d57600080fd5b8063bf78e03f14610a03578063cdc73d5114610ae1578063d02641a014610ae9578063d63d3af214610afc57600080fd5b806382b49eb0116100de57806382b49eb0146108455780638da5cb5b146109b557806391a2749a146109dd578063a69c64c0146109f057600080fd5b8063770e2dc41461080457806379ba5097146108175780637afac3221461081f578063805f21321461083257600080fd5b80633937306f116101875780634ab35b0b116101565780634ab35b0b14610472578063514e8cff146104b25780636cb5f3dd146105555780636def4ce71461056857600080fd5b80633937306f1461040757806341ed29e71461041c578063430d138c1461042f57806345ac924d1461045257600080fd5b806306285c69116101c357806306285c691461028b578063181f5a77146103a15780632451a627146103ea578063325c868e146103ff57600080fd5b806241e5be146101e957806301ffc9a71461020f578063061877e314610232575b600080fd5b6101fc6101f7366004614568565b610b85565b6040519081526020015b60405180910390f35b61022261021d3660046145d4565b610bf3565b6040519015158152602001610206565b6102726102403660046145ef565b73ffffffffffffffffffffffffffffffffffffffff1660009081526008602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff9091168152602001610206565b610355604080516060810182526000808252602082018190529181019190915260405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000063ffffffff16815250905090565b6040805182516bffffffffffffffffffffffff16815260208084015173ffffffffffffffffffffffffffffffffffffffff16908201529181015163ffffffff1690820152606001610206565b6103dd6040518060400160405280601381526020017f46656551756f74657220312e362e302d6465760000000000000000000000000081525081565b604051610206919061466e565b6103f2610d24565b6040516102069190614681565b6101fc602481565b61041a6104153660046146db565b610d35565b005b61041a61042a366004614887565b610fea565b61044261043d366004614a72565b61102c565b6040516102069493929190614b66565b610465610460366004614c05565b61123c565b6040516102069190614c47565b6104856104803660046145ef565b611305565b6040517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9091168152602001610206565b6105486104c0366004614cc2565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600560209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b6040516102069190614cdd565b61041a610563366004614d3e565b611310565b6107f7610576366004614cc2565b6040805161022081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e081018290526102008101919091525067ffffffffffffffff908116600090815260096020908152604091829020825161022081018452815460ff8082161515835261ffff61010080840482169685019690965263ffffffff630100000084048116978501979097526701000000000000008304871660608501526b0100000000000000000000008304871660808501526f010000000000000000000000000000008304811660a0850152710100000000000000000000000000000000008304871660c08501527501000000000000000000000000000000000000000000808404821660e08087019190915277010000000000000000000000000000000000000000000000850483169786019790975279010000000000000000000000000000000000000000000000000084049091166101208501527b01000000000000000000000000000000000000000000000000000000909204861661014084015260019093015480861661016084015264010000000081049096166101808301526c01000000000000000000000000860485166101a083015270010000000000000000000000000000000086049094166101c082015274010000000000000000000000000000000000000000850490911615156101e08201527fffffffff0000000000000000000000000000000000000000000000000000000092909304901b1661020082015290565b6040516102069190614f5e565b61041a61081236600461515c565b611324565b61041a611336565b61041a61082d366004615476565b611404565b61041a6108403660046154da565b611416565b610955610853366004615546565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff919091166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff94909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b6040516102069190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60015460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610206565b61041a6109eb366004615570565b611852565b61041a6109fe366004615601565b611863565b610aa4610a113660046145ef565b60408051606080820183526000808352602080840182905292840181905273ffffffffffffffffffffffffffffffffffffffff9485168152600783528390208351918201845254938416815260ff74010000000000000000000000000000000000000000850481169282019290925275010000000000000000000000000000000000000000009093041615159082015290565b60408051825173ffffffffffffffffffffffffffffffffffffffff16815260208084015160ff169082015291810151151590820152606001610206565b6103f2611874565b610548610af73660046145ef565b611880565b6101fc601281565b6101fc610b123660046156c6565b611a35565b61041a610b253660046145ef565b611f6d565b61041a610b3836600461572a565b611f7e565b610b50610b4b36600461584a565b611f8f565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff938416815292909116602083015201610206565b6000610b9082612047565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16610bb785612047565b610bdf907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16856158a3565b610be991906158ba565b90505b9392505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f805f2132000000000000000000000000000000000000000000000000000000001480610c8657507fffffffff0000000000000000000000000000000000000000000000000000000082167f9b645f4100000000000000000000000000000000000000000000000000000000145b80610cd257507fffffffff0000000000000000000000000000000000000000000000000000000082167f181f5a7700000000000000000000000000000000000000000000000000000000145b80610d1e57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b6060610d3060026120e1565b905090565b610d3d6120ee565b6000610d4982806158f5565b9050905060005b81811015610e93576000610d6484806158f5565b83818110610d7457610d7461595d565b905060400201803603810190610d8a91906159b8565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885173ffffffffffffffffffffffffffffffffffffffff9081166000908152600690975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a92610e829290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610d50565b506000610ea360208401846158f5565b9050905060005b81811015610fe4576000610ec160208601866158f5565b83818110610ed157610ed161595d565b905060400201803603810190610ee791906159f5565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885167ffffffffffffffff9081166000908152600590975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e92610fd39290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610eaa565b50505050565b610ff2612133565b60005b8151811015611028576110208282815181106110135761101361595d565b6020026020010151612184565b600101610ff5565b5050565b6000806060807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168c73ffffffffffffffffffffffffffffffffffffffff160361108d578a93506110bb565b6110b88c8c7f0000000000000000000000000000000000000000000000000000000000000000610b85565b93505b7f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1684111561115f576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018590526bffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660248201526044015b60405180910390fd5b67ffffffffffffffff8d1660009081526009602052604081206001015463ffffffff169061118e8c8c84612356565b9050806020015194506111a48f8b8b8b8b6124ff565b92508585611224836040805182516024820152602092830151151560448083019190915282518083039091018152606490910190915290810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f181dcf100000000000000000000000000000000000000000000000000000000017905290565b95509550955050509950995099509995505050505050565b60608160008167ffffffffffffffff81111561125a5761125a614716565b60405190808252806020026020018201604052801561129f57816020015b60408051808201909152600080825260208201528152602001906001900390816112785790505b50905060005b828110156112fc576112d78686838181106112c2576112c261595d565b9050602002016020810190610af791906145ef565b8282815181106112e9576112e961595d565b60209081029190910101526001016112a5565b50949350505050565b6000610d1e82612047565b611318612133565b61132181612882565b50565b61132c612133565b6110288282612d54565b60005473ffffffffffffffffffffffffffffffffffffffff163314611387576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61140c612133565b61102882826131ca565b600080600061145a87878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061331192505050565b92509250925061146c3383858461332c565b600061147a85870187615a18565b905060005b8151811015611847576000600760008484815181106114a0576114a061595d565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff908116835282820193909352604091820160002082516060810184529054938416815260ff740100000000000000000000000000000000000000008504811692820192909252750100000000000000000000000000000000000000000090930416151590820181905290915061159b578282815181106115445761154461595d565b6020908102919091010151516040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401611156565b60006115e8601283602001518686815181106115b9576115b961595d565b6020026020010151602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16613484565b9050600660008585815181106116005761160061595d565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001601c9054906101000a900463ffffffff1663ffffffff168484815181106116725761167261595d565b60200260200101516040015163ffffffff16101561169157505061183f565b6040518060400160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681526020018585815181106116d2576116d261595d565b60200260200101516040015163ffffffff16815250600660008686815181106116fd576116fd61595d565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251929091015163ffffffff167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117905583518490849081106117955761179561595d565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff167f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a828686815181106117eb576117eb61595d565b6020026020010151604001516040516118349291907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216825263ffffffff16602082015260400190565b60405180910390a250505b60010161147f565b505050505050505050565b61185a612133565b61132181613547565b61186b612133565b611321816136d3565b6060610d30600b6120e1565b604080518082019091526000808252602082015273ffffffffffffffffffffffffffffffffffffffff82166000908152600660209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116835263ffffffff7c010000000000000000000000000000000000000000000000000000000090910481169183018290527f000000000000000000000000000000000000000000000000000000000000000016906119429042615adf565b101561194e5792915050565b73ffffffffffffffffffffffffffffffffffffffff80841660009081526007602090815260409182902082516060810184529054938416815260ff74010000000000000000000000000000000000000000850481169282019290925275010000000000000000000000000000000000000000009093041615801591830191909152806119ef5750805173ffffffffffffffffffffffffffffffffffffffff16155b156119fb575092915050565b6000611a06826137bd565b9050826020015163ffffffff16816020015163ffffffff161015611a2a5782611a2c565b805b95945050505050565b67ffffffffffffffff8083166000908152600960209081526040808320815161022081018352815460ff808216151580845261ffff61010080850482169886019890985263ffffffff630100000085048116978601979097526701000000000000008404871660608601526b0100000000000000000000008404871660808601526f010000000000000000000000000000008404811660a0860152710100000000000000000000000000000000008404871660c08601527501000000000000000000000000000000000000000000808504821660e08088019190915277010000000000000000000000000000000000000000000000860483169987019990995279010000000000000000000000000000000000000000000000000085049091166101208601527b01000000000000000000000000000000000000000000000000000000909304861661014085015260019094015480861661016085015264010000000081049098166101808401526c01000000000000000000000000880485166101a084015270010000000000000000000000000000000088049094166101c083015274010000000000000000000000000000000000000000870490931615156101e08201527fffffffff000000000000000000000000000000000000000000000000000000009290950490921b16610200840152909190611c6f576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401611156565b611c8a611c8260808501606086016145ef565b600b9061394f565b611ce957611c9e60808401606085016145ef565b6040517f2502348c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401611156565b6000611cf860408501856158f5565b9150611d54905082611d0d6020870187615af2565b905083611d1a8880615af2565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061397e92505050565b6000611d6e611d6960808701606088016145ef565b612047565b90506000611d8187856101c00151613a3b565b9050600080808515611dc157611db5878b611da260808d0160608e016145ef565b88611db060408f018f6158f5565b613b3b565b91945092509050611de1565b6101a0870151611dde9063ffffffff16662386f26fc100006158a3565b92505b61010087015160009061ffff1615611e2557611e22886dffffffffffffffffffffffffffff607088901c16611e1960208e018e615af2565b90508a86613e13565b90505b61018088015160009067ffffffffffffffff16611e4e611e4860808e018e615af2565b8c613ec3565b600001518563ffffffff168b60a0015161ffff168e8060200190611e729190615af2565b611e7d9291506158a3565b8c6080015163ffffffff16611e929190615b57565b611e9c9190615b57565b611ea69190615b57565b611ec0906dffffffffffffffffffffffffffff89166158a3565b611eca91906158a3565b9050867bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168282600860008f6060016020810190611f0491906145ef565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002054611f3f9067ffffffffffffffff16896158a3565b611f499190615b57565b611f539190615b57565b611f5d91906158ba565b9c9b505050505050505050505050565b611f75612133565b61132181613f84565b611f86612133565b61132181614048565b67ffffffffffffffff8116600090815260096020526040812054819060ff16611ff0576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401611156565b611ff984612047565b67ffffffffffffffff841660009081526009602052604090206001015461203b908590700100000000000000000000000000000000900463ffffffff16613a3b565b915091505b9250929050565b60008061205383611880565b9050806020015163ffffffff166000148061208b575080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16155b156120da576040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401611156565b5192915050565b60606000610bec8361419a565b6120f960023361394f565b612131576040517fd86ad9cf000000000000000000000000000000000000000000000000000000008152336004820152602401611156565b565b60015473ffffffffffffffffffffffffffffffffffffffff163314612131576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061223d82600001518360600151846020015185604001516040805173ffffffffffffffffffffffffffffffffffffffff80871660208301528516918101919091527fffffffffffffffffffff00000000000000000000000000000000000000000000831660608201527fffff0000000000000000000000000000000000000000000000000000000000008216608082015260009060a001604051602081830303815290604052805190602001209050949350505050565b60808301516000828152600460205260409081902080549215157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909316929092179091555190915081907f32a4ba3fa3351b11ad555d4c8ec70a744e8705607077a946807030d64b6ab1a39061234a908590600060a08201905073ffffffffffffffffffffffffffffffffffffffff8084511683527fffffffffffffffffffff0000000000000000000000000000000000000000000060208501511660208401527fffff00000000000000000000000000000000000000000000000000000000000060408501511660408401528060608501511660608401525060808301511515608083015292915050565b60405180910390a25050565b6040805180820190915260008082526020820152600083900361239757506040805180820190915267ffffffffffffffff8216815260006020820152610bec565b60006123a38486615b6a565b905060006123b48560048189615bb0565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050507fffffffff0000000000000000000000000000000000000000000000000000000082167fe7e230f0000000000000000000000000000000000000000000000000000000000161245157808060200190518101906124489190615bda565b92505050610bec565b7f6859a837000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316016124cd576040518060400160405280828060200190518101906124b99190615c06565b815260006020909101529250610bec915050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff808616600090815260096020526040902060010154606091750100000000000000000000000000000000000000000090910460e01b90859081111561254f5761254f614716565b60405190808252806020026020018201604052801561258257816020015b606081526020019060019003908161256d5790505b50915060005b858110156128775760008585838181106125a4576125a461595d565b6125ba92602060409092020190810191506145ef565b905060008888848181106125d0576125d061595d565b90506020028101906125e29190615c1f565b6125f0906040810190615af2565b91505060208111156126a05767ffffffffffffffff8a166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020546e010000000000000000000000000000900463ffffffff168111156126a0576040517f36f536ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401611156565b612710848a8a868181106126b6576126b661595d565b90506020028101906126c89190615c1f565b6126d6906020810190615af2565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506141f692505050565b67ffffffffffffffff8a166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684528252808320815160c081018352905463ffffffff8082168352640100000000820481169483019490945268010000000000000000810461ffff16928201929092526a01000000000000000000008204831660608201526e010000000000000000000000000000820490921660808301527201000000000000000000000000000000000000900460ff16151560a082018190529091906128225767ffffffffffffffff8c166000908152600960205260409020547b01000000000000000000000000000000000000000000000000000000900463ffffffff16612828565b81606001515b6040805163ffffffff831660208201529192500160405160208183030381529060405287868151811061285d5761285d61595d565b602002602001018190525050505050806001019050612588565b505095945050505050565b60005b81518110156110285760008282815181106128a2576128a261595d565b6020026020010151905060008383815181106128c0576128c061595d565b60200260200101516000015190506000826020015190508167ffffffffffffffff16600014806128f9575061016081015163ffffffff16155b8061294b57506102008101517fffffffff00000000000000000000000000000000000000000000000000000000167f2812d52c0000000000000000000000000000000000000000000000000000000014155b8061296a5750806060015163ffffffff1681610160015163ffffffff16115b156129ad576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401611156565b67ffffffffffffffff82166000908152600960205260408120600101547501000000000000000000000000000000000000000000900460e01b7fffffffff00000000000000000000000000000000000000000000000000000000169003612a55578167ffffffffffffffff167f525e3d4e0c31cef19cf9426af8d2c0ddd2d576359ca26bed92aac5fadda4626582604051612a489190614f5e565b60405180910390a2612a98565b8167ffffffffffffffff167f283b699f411baff8f1c29fe49f32a828c8151596244b8e7e4c164edd6569a83582604051612a8f9190614f5e565b60405180910390a25b80600960008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160146101000a81548160ff0219169083151502179055506102008201518160010160156101000a81548163ffffffff021916908360e01c0217905550905050505050806001019050612885565b60005b82518110156130e1576000838281518110612d7457612d7461595d565b6020026020010151905060008160000151905060005b8260200151518110156130d357600083602001518281518110612daf57612daf61595d565b6020026020010151602001519050600084602001518381518110612dd557612dd561595d565b6020026020010151600001519050816020015163ffffffff16826000015163ffffffff1610612e4757815160208301516040517f0b4f67a200000000000000000000000000000000000000000000000000000000815263ffffffff928316600482015291166024820152604401611156565b602063ffffffff16826080015163ffffffff161015612ebc5760808201516040517f24ecdc0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015263ffffffff9091166024820152604401611156565b67ffffffffffffffff84166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b5906130c1908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a35050600101612d8a565b505050806001019050612d57565b5060005b81518110156131c55760008282815181106131025761310261595d565b602002602001015160000151905060008383815181106131245761312461595d565b60209081029190910181015181015167ffffffffffffffff84166000818152600a8452604080822073ffffffffffffffffffffffffffffffffffffffff8516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a350506001016130e5565b505050565b60005b825181101561326d576132038382815181106131eb576131eb61595d565b6020026020010151600b61424890919063ffffffff16565b156132655782818151811061321a5761321a61595d565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b6001016131cd565b5060005b81518110156131c5576132a782828151811061328f5761328f61595d565b6020026020010151600b61426a90919063ffffffff16565b15613309578181815181106132be576132be61595d565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b600101613271565b6040810151604a820151605e90920151909260609290921c91565b6040805173ffffffffffffffffffffffffffffffffffffffff868116602080840191909152908616828401527fffffffffffffffffffff00000000000000000000000000000000000000000000851660608301527fffff00000000000000000000000000000000000000000000000000000000000084166080808401919091528351808403909101815260a09092018352815191810191909120600081815260049092529190205460ff1661347d576040517f097e17ff00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8087166004830152851660248201527fffffffffffffffffffff00000000000000000000000000000000000000000000841660448201527fffff00000000000000000000000000000000000000000000000000000000000083166064820152608401611156565b5050505050565b6000806134918486615c5d565b9050600060248260ff1611156134cb576134af602460ff8416615adf565b6134ba90600a615d96565b6134c490856158ba565b90506134f1565b6134d960ff83166024615adf565b6134e490600a615d96565b6134ee90856158a3565b90505b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811115611a2c576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081015160005b81518110156135e257600082828151811061356c5761356c61595d565b6020026020010151905061358a81600261428c90919063ffffffff16565b156135d95760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b5060010161354f565b50815160005b8151811015610fe45760008282815181106136055761360561595d565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603613675576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61368060028261426a565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a1506001016135e8565b60005b81518110156110285760008282815181106136f3576136f361595d565b602002602001015160000151905060008383815181106137155761371561595d565b60209081029190910181015181015173ffffffffffffffffffffffffffffffffffffffff841660008181526008845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a250506001016136d6565b60408051808201909152600080825260208201526000826000015190506000808273ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061384c9190615dbc565b50935050925050600082121561388e576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061390d8473ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156138de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139029190615e0c565b876020015185613484565b604080518082019091527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909116815263ffffffff909216602083015250949350505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610bec565b836040015163ffffffff168311156139d75760408085015190517f8693378900000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101849052604401611156565b836020015161ffff16821115613a2c5760208401516040517fd88dddd60000000000000000000000000000000000000000000000000000000081526004810184905261ffff9091166024820152604401611156565b610fe4846102000151826141f6565b67ffffffffffffffff821660009081526005602090815260408083208151808301909252547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116825263ffffffff7c010000000000000000000000000000000000000000000000000000000090910481169282019290925290831615613b33576000816020015163ffffffff1642613ad09190615adf565b90508363ffffffff16811115613b31576040517ff08bcb3e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8616600482015263ffffffff8516602482015260448101829052606401611156565b505b519392505050565b6000808083815b81811015613e05576000878783818110613b5e57613b5e61595d565b905060400201803603810190613b749190615e29565b67ffffffffffffffff8c166000908152600a60209081526040808320845173ffffffffffffffffffffffffffffffffffffffff168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a0820181905291925090613c94576101208d0151613c619061ffff16662386f26fc100006158a3565b613c6b9088615b57565b96508c610140015186613c7e9190615e62565b9550613c8b602086615e62565b94505050613dfd565b604081015160009061ffff1615613d4d5760008c73ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff1614613cf0578351613ce990612047565b9050613cf3565b508a5b620186a0836040015161ffff16613d358660200151847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166142ae90919063ffffffff16565b613d3f91906158a3565b613d4991906158ba565b9150505b6060820151613d5c9088615e62565b9650816080015186613d6e9190615e62565b8251909650600090613d8d9063ffffffff16662386f26fc100006158a3565b905080821015613dac57613da1818a615b57565b985050505050613dfd565b6000836020015163ffffffff16662386f26fc10000613dcb91906158a3565b905080831115613deb57613ddf818b615b57565b99505050505050613dfd565b613df5838b615b57565b995050505050505b600101613b42565b505096509650969350505050565b60008063ffffffff8316613e29610120866158a3565b613e35876101e0615b57565b613e3f9190615b57565b613e499190615b57565b905060008760c0015163ffffffff168860e0015161ffff1683613e6c91906158a3565b613e769190615b57565b61010089015190915061ffff16613e9d6dffffffffffffffffffffffffffff8916836158a3565b613ea791906158a3565b613eb790655af3107a40006158a3565b98975050505050505050565b60408051808201909152600080825260208201526000613eef858585610160015163ffffffff16612356565b9050826060015163ffffffff1681600001511115613f39576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826101e001518015613f4d57508060200151155b15610be9576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821603613fd3576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60005b81518110156110285760008282815181106140685761406861595d565b60209081029190910181015180518183015173ffffffffffffffffffffffffffffffffffffffff80831660008181526007875260409081902084518154868a0180518589018051949098167fffffffffffffffffffffff00000000000000000000000000000000000000000090931683177401000000000000000000000000000000000000000060ff92831602177fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000009415159490940293909317909355835190815291511697810197909752915115159186019190915292945090929091907fe6a7a17d710bf0b2cd05e5397dc6f97a5da4ee79e31e234bf5f965ee2bd9a5bf9060600160405180910390a250505080600101905061404b565b6060816000018054806020026020016040519081016040528092919081815260200182805480156141ea57602002820191906000526020600020905b8154815260200190600101908083116141d6575b50505050509050919050565b7fd7ed2ad4000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601611028576131c5816142eb565b6000610bec8373ffffffffffffffffffffffffffffffffffffffff841661439e565b6000610bec8373ffffffffffffffffffffffffffffffffffffffff8416614498565b6000610bec8373ffffffffffffffffffffffffffffffffffffffff84166144e7565b6000670de0b6b3a76400006142e1837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff86166158a3565b610bec91906158ba565b6000815160201461432a57816040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401611156919061466e565b6000828060200190518101906143409190615c06565b905073ffffffffffffffffffffffffffffffffffffffff811180614365575061040081105b15610d1e57826040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401611156919061466e565b600081815260018301602052604081205480156144875760006143c2600183615adf565b85549091506000906143d690600190615adf565b905080821461443b5760008660000182815481106143f6576143f661595d565b90600052602060002001549050808760000184815481106144195761441961595d565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061444c5761444c615e7f565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610d1e565b6000915050610d1e565b5092915050565b60008181526001830160205260408120546144df57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610d1e565b506000610d1e565b6000818152600183016020526040812054801561448757600061450b600183615adf565b855490915060009061451f90600190615adf565b905081811461443b5760008660000182815481106143f6576143f661595d565b803573ffffffffffffffffffffffffffffffffffffffff8116811461456357600080fd5b919050565b60008060006060848603121561457d57600080fd5b6145868461453f565b92506020840135915061459b6040850161453f565b90509250925092565b80357fffffffff000000000000000000000000000000000000000000000000000000008116811461456357600080fd5b6000602082840312156145e657600080fd5b610bec826145a4565b60006020828403121561460157600080fd5b610bec8261453f565b6000815180845260005b8181101561463057602081850181015186830182015201614614565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610bec602083018461460a565b6020808252825182820181905260009190848201906040850190845b818110156146cf57835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161469d565b50909695505050505050565b6000602082840312156146ed57600080fd5b813567ffffffffffffffff81111561470457600080fd5b820160408185031215610bec57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561476857614768614716565b60405290565b6040805190810167ffffffffffffffff8111828210171561476857614768614716565b604051610220810167ffffffffffffffff8111828210171561476857614768614716565b60405160c0810167ffffffffffffffff8111828210171561476857614768614716565b6040516060810167ffffffffffffffff8111828210171561476857614768614716565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561484257614842614716565b604052919050565b600067ffffffffffffffff82111561486457614864614716565b5060051b60200190565b801515811461132157600080fd5b80356145638161486e565b6000602080838503121561489a57600080fd5b823567ffffffffffffffff8111156148b157600080fd5b8301601f810185136148c257600080fd5b80356148d56148d08261484a565b6147fb565b81815260a091820283018401918482019190888411156148f457600080fd5b938501935b838510156149c75780858a0312156149115760008081fd5b614919614745565b6149228661453f565b8152868601357fffffffffffffffffffff00000000000000000000000000000000000000000000811681146149575760008081fd5b818801526040868101357fffff000000000000000000000000000000000000000000000000000000000000811681146149905760008081fd5b9082015260606149a187820161453f565b908201526080868101356149b48161486e565b90820152835293840193918501916148f9565b50979650505050505050565b803567ffffffffffffffff8116811461456357600080fd5b60008083601f8401126149fd57600080fd5b50813567ffffffffffffffff811115614a1557600080fd5b60208301915083602082850101111561204057600080fd5b60008083601f840112614a3f57600080fd5b50813567ffffffffffffffff811115614a5757600080fd5b6020830191508360208260051b850101111561204057600080fd5b600080600080600080600080600060c08a8c031215614a9057600080fd5b614a998a6149d3565b9850614aa760208b0161453f565b975060408a0135965060608a013567ffffffffffffffff80821115614acb57600080fd5b614ad78d838e016149eb565b909850965060808c0135915080821115614af057600080fd5b614afc8d838e01614a2d565b909650945060a08c0135915080821115614b1557600080fd5b818c0191508c601f830112614b2957600080fd5b813581811115614b3857600080fd5b8d60208260061b8501011115614b4d57600080fd5b6020830194508093505050509295985092959850929598565b848152600060208515158184015260806040840152614b88608084018661460a565b8381036060850152845180825282820190600581901b8301840184880160005b83811015614bf4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018552614be283835161460a565b94870194925090860190600101614ba8565b50909b9a5050505050505050505050565b60008060208385031215614c1857600080fd5b823567ffffffffffffffff811115614c2f57600080fd5b614c3b85828601614a2d565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b82811015614cb557614ca584835180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16825260209081015163ffffffff16910152565b9284019290850190600101614c64565b5091979650505050505050565b600060208284031215614cd457600080fd5b610bec826149d3565b81517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260208083015163ffffffff169082015260408101610d1e565b803561ffff8116811461456357600080fd5b803563ffffffff8116811461456357600080fd5b60006020808385031215614d5157600080fd5b823567ffffffffffffffff811115614d6857600080fd5b8301601f81018513614d7957600080fd5b8035614d876148d08261484a565b8181526102409182028301840191848201919088841115614da757600080fd5b938501935b838510156149c75784890381811215614dc55760008081fd5b614dcd61476e565b614dd6876149d3565b8152610220807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084011215614e0b5760008081fd5b614e13614791565b9250614e2089890161487c565b83526040614e2f818a01614d18565b8a8501526060614e40818b01614d2a565b8286015260809150614e53828b01614d2a565b9085015260a0614e648a8201614d2a565b8286015260c09150614e77828b01614d18565b9085015260e0614e888a8201614d2a565b828601526101009150614e9c828b01614d18565b90850152610120614eae8a8201614d18565b828601526101409150614ec2828b01614d18565b90850152610160614ed48a8201614d2a565b828601526101809150614ee8828b01614d2a565b908501526101a0614efa8a82016149d3565b828601526101c09150614f0e828b01614d2a565b908501526101e0614f208a8201614d2a565b828601526102009150614f34828b0161487c565b90850152614f438983016145a4565b90840152508088019190915283529384019391850191614dac565b81511515815261022081016020830151614f7e602084018261ffff169052565b506040830151614f96604084018263ffffffff169052565b506060830151614fae606084018263ffffffff169052565b506080830151614fc6608084018263ffffffff169052565b5060a0830151614fdc60a084018261ffff169052565b5060c0830151614ff460c084018263ffffffff169052565b5060e083015161500a60e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff90811691840191909152610160808501518216908401526101808085015167ffffffffffffffff16908401526101a0808501518216908401526101c080850151909116908301526101e080840151151590830152610200808401517fffffffff000000000000000000000000000000000000000000000000000000008116828501525b505092915050565b600082601f8301126150d557600080fd5b813560206150e56148d08361484a565b82815260069290921b8401810191818101908684111561510457600080fd5b8286015b8481101561515157604081890312156151215760008081fd5b61512961476e565b615132826149d3565b815261513f85830161453f565b81860152835291830191604001615108565b509695505050505050565b6000806040838503121561516f57600080fd5b67ffffffffffffffff8335111561518557600080fd5b83601f84358501011261519757600080fd5b6151a76148d0843585013561484a565b8335840180358083526020808401939260059290921b909101018610156151cd57600080fd5b602085358601015b85358601803560051b016020018110156153da5767ffffffffffffffff813511156151ff57600080fd5b8035863587010160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828a0301121561523857600080fd5b61524061476e565b61524c602083016149d3565b815267ffffffffffffffff6040830135111561526757600080fd5b88603f60408401358401011261527c57600080fd5b6152926148d0602060408501358501013561484a565b6020604084810135850182810135808552928401939260e00201018b10156152b957600080fd5b6040808501358501015b6040858101358601602081013560e00201018110156153bb5760e0818d0312156152ec57600080fd5b6152f461476e565b6152fd8261453f565b815260c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0838f0301121561533157600080fd5b6153396147b5565b61534560208401614d2a565b815261535360408401614d2a565b602082015261536460608401614d18565b604082015261537560808401614d2a565b606082015261538660a08401614d2a565b608082015261539860c084013561486e565b60c083013560a0820152602082810191909152908452929092019160e0016152c3565b50806020840152505080855250506020830192506020810190506151d5565b5092505067ffffffffffffffff602084013511156153f757600080fd5b61540784602085013585016150c4565b90509250929050565b600082601f83011261542157600080fd5b813560206154316148d08361484a565b8083825260208201915060208460051b87010193508684111561545357600080fd5b602086015b84811015615151576154698161453f565b8352918301918301615458565b6000806040838503121561548957600080fd5b823567ffffffffffffffff808211156154a157600080fd5b6154ad86838701615410565b935060208501359150808211156154c357600080fd5b506154d085828601615410565b9150509250929050565b600080600080604085870312156154f057600080fd5b843567ffffffffffffffff8082111561550857600080fd5b615514888389016149eb565b9096509450602087013591508082111561552d57600080fd5b5061553a878288016149eb565b95989497509550505050565b6000806040838503121561555957600080fd5b615562836149d3565b91506154076020840161453f565b60006020828403121561558257600080fd5b813567ffffffffffffffff8082111561559a57600080fd5b90830190604082860312156155ae57600080fd5b6155b661476e565b8235828111156155c557600080fd5b6155d187828601615410565b8252506020830135828111156155e657600080fd5b6155f287828601615410565b60208301525095945050505050565b6000602080838503121561561457600080fd5b823567ffffffffffffffff81111561562b57600080fd5b8301601f8101851361563c57600080fd5b803561564a6148d08261484a565b81815260069190911b8201830190838101908783111561566957600080fd5b928401925b828410156156bb57604084890312156156875760008081fd5b61568f61476e565b6156988561453f565b81526156a58686016149d3565b818701528252604093909301929084019061566e565b979650505050505050565b600080604083850312156156d957600080fd5b6156e2836149d3565b9150602083013567ffffffffffffffff8111156156fe57600080fd5b830160a0818603121561571057600080fd5b809150509250929050565b60ff8116811461132157600080fd5b6000602080838503121561573d57600080fd5b823567ffffffffffffffff81111561575457600080fd5b8301601f8101851361576557600080fd5b80356157736148d08261484a565b81815260079190911b8201830190838101908783111561579257600080fd5b928401925b828410156156bb5783880360808112156157b15760008081fd5b6157b961476e565b6157c28661453f565b81526060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156157f65760008081fd5b6157fe6147d8565b925061580b88880161453f565b835260408088013561581c8161571b565b848a0152908701359061582e8261486e565b8301528087019190915282526080939093019290840190615797565b6000806040838503121561585d57600080fd5b6158668361453f565b9150615407602084016149d3565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610d1e57610d1e615874565b6000826158f0577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261592a57600080fd5b83018035915067ffffffffffffffff82111561594557600080fd5b6020019150600681901b360382131561204057600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461456357600080fd5b6000604082840312156159ca57600080fd5b6159d261476e565b6159db8361453f565b81526159e96020840161598c565b60208201529392505050565b600060408284031215615a0757600080fd5b615a0f61476e565b6159db836149d3565b60006020808385031215615a2b57600080fd5b823567ffffffffffffffff811115615a4257600080fd5b8301601f81018513615a5357600080fd5b8035615a616148d08261484a565b81815260609182028301840191848201919088841115615a8057600080fd5b938501935b838510156149c75780858a031215615a9d5760008081fd5b615aa56147d8565b615aae8661453f565b8152615abb87870161598c565b878201526040615acc818801614d2a565b9082015283529384019391850191615a85565b81810381811115610d1e57610d1e615874565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112615b2757600080fd5b83018035915067ffffffffffffffff821115615b4257600080fd5b60200191503681900382131561204057600080fd5b80820180821115610d1e57610d1e615874565b7fffffffff0000000000000000000000000000000000000000000000000000000081358181169160048510156150bc5760049490940360031b84901b1690921692915050565b60008085851115615bc057600080fd5b83861115615bcd57600080fd5b5050820193919092039150565b600060408284031215615bec57600080fd5b615bf461476e565b8251815260208301516159e98161486e565b600060208284031215615c1857600080fd5b5051919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61833603018112615c5357600080fd5b9190910192915050565b60ff8181168382160190811115610d1e57610d1e615874565b600181815b80851115615ccf57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615cb557615cb5615874565b80851615615cc257918102915b93841c9390800290615c7b565b509250929050565b600082615ce657506001610d1e565b81615cf357506000610d1e565b8160018114615d095760028114615d1357615d2f565b6001915050610d1e565b60ff841115615d2457615d24615874565b50506001821b610d1e565b5060208310610133831016604e8410600b8410161715615d52575081810a610d1e565b615d5c8383615c76565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615d8e57615d8e615874565b029392505050565b6000610bec8383615cd7565b805169ffffffffffffffffffff8116811461456357600080fd5b600080600080600060a08688031215615dd457600080fd5b615ddd86615da2565b9450602086015193506040860151925060608601519150615e0060808701615da2565b90509295509295909350565b600060208284031215615e1e57600080fd5b8151610bec8161571b565b600060408284031215615e3b57600080fd5b615e4361476e565b615e4c8361453f565b8152602083013560208201528091505092915050565b63ffffffff81811683821601908082111561449157614491615874565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"staticConfig\",\"type\":\"tuple\",\"internalType\":\"structFeeQuoter.StaticConfig\",\"components\":[{\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\",\"internalType\":\"uint96\"},{\"name\":\"linkToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenPriceStalenessThreshold\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]},{\"name\":\"priceUpdaters\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"feeTokens\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"tokenPriceFeeds\",\"type\":\"tuple[]\",\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"components\":[{\"name\":\"sourceToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"feedConfig\",\"type\":\"tuple\",\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"components\":[{\"name\":\"dataFeedAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenDecimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"}]}]},{\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\",\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"components\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\",\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"components\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\",\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"components\":[{\"name\":\"minFeeUSDCents\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"deciBps\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"destGasOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destBytesOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"}]}]}]},{\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\",\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"components\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\",\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"components\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"destChainConfig\",\"type\":\"tuple\",\"internalType\":\"structFeeQuoter.DestChainConfig\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"maxDataBytes\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destGasOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destGasPerPayloadByteBase\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"destGasPerPayloadByteHigh\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"destGasPerPayloadByteThreshold\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"chainFamilySelector\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"},{\"name\":\"enforceOutOfOrder\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}]}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"FEE_BASE_DECIMALS\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"KEYSTONE_PRICE_DECIMALS\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"acceptOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyAuthorizedCallerUpdates\",\"inputs\":[{\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\",\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"components\":[{\"name\":\"addedCallers\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"removedCallers\",\"type\":\"address[]\",\"internalType\":\"address[]\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyDestChainConfigUpdates\",\"inputs\":[{\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\",\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"components\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"destChainConfig\",\"type\":\"tuple\",\"internalType\":\"structFeeQuoter.DestChainConfig\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"maxDataBytes\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destGasOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destGasPerPayloadByteBase\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"destGasPerPayloadByteHigh\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"destGasPerPayloadByteThreshold\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"chainFamilySelector\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"},{\"name\":\"enforceOutOfOrder\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyFeeTokensUpdates\",\"inputs\":[{\"name\":\"feeTokensToRemove\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"feeTokensToAdd\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyPremiumMultiplierWeiPerEthUpdates\",\"inputs\":[{\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\",\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"components\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyTokenTransferFeeConfigUpdates\",\"inputs\":[{\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\",\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"components\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\",\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"components\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\",\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"components\":[{\"name\":\"minFeeUSDCents\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"deciBps\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"destGasOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destBytesOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"}]}]}]},{\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"tuple[]\",\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigRemoveArgs[]\",\"components\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"convertTokenAmount\",\"inputs\":[{\"name\":\"fromToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"fromTokenAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"toToken\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getAllAuthorizedCallers\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getDestChainConfig\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structFeeQuoter.DestChainConfig\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"maxDataBytes\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destGasOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destGasPerPayloadByteBase\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"destGasPerPayloadByteHigh\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"destGasPerPayloadByteThreshold\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"chainFamilySelector\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"},{\"name\":\"enforceOutOfOrder\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getDestinationChainGasPrice\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structInternal.TimestampedPackedUint224\",\"components\":[{\"name\":\"value\",\"type\":\"uint224\",\"internalType\":\"uint224\"},{\"name\":\"timestamp\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getFeeTokens\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getPremiumMultiplierWeiPerEth\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getStaticConfig\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structFeeQuoter.StaticConfig\",\"components\":[{\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\",\"internalType\":\"uint96\"},{\"name\":\"linkToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenPriceStalenessThreshold\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTokenAndGasPrices\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"tokenPrice\",\"type\":\"uint224\",\"internalType\":\"uint224\"},{\"name\":\"gasPriceValue\",\"type\":\"uint224\",\"internalType\":\"uint224\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTokenPrice\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structInternal.TimestampedPackedUint224\",\"components\":[{\"name\":\"value\",\"type\":\"uint224\",\"internalType\":\"uint224\"},{\"name\":\"timestamp\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTokenPriceFeedConfig\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"components\":[{\"name\":\"dataFeedAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenDecimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTokenPrices\",\"inputs\":[{\"name\":\"tokens\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.TimestampedPackedUint224[]\",\"components\":[{\"name\":\"value\",\"type\":\"uint224\",\"internalType\":\"uint224\"},{\"name\":\"timestamp\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTokenTransferFeeConfig\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\",\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"components\":[{\"name\":\"minFeeUSDCents\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"deciBps\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"destGasOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destBytesOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getValidatedFee\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"message\",\"type\":\"tuple\",\"internalType\":\"structClient.EVM2AnyMessage\",\"components\":[{\"name\":\"receiver\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"tokenAmounts\",\"type\":\"tuple[]\",\"internalType\":\"structClient.EVMTokenAmount[]\",\"components\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"feeToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"extraArgs\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"feeTokenAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getValidatedTokenPrice\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint224\",\"internalType\":\"uint224\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"onReport\",\"inputs\":[{\"name\":\"metadata\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"report\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"processMessageArgs\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"feeToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"feeTokenAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"extraArgs\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"onRampTokenTransfers\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"components\":[{\"name\":\"sourcePoolAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"destTokenAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"extraData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"destExecData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"sourceTokenAmounts\",\"type\":\"tuple[]\",\"internalType\":\"structClient.EVMTokenAmount[]\",\"components\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"outputs\":[{\"name\":\"msgFeeJuels\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"isOutOfOrderExecution\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"convertedExtraArgs\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"destExecDataPerToken\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"setReportPermissions\",\"inputs\":[{\"name\":\"permissions\",\"type\":\"tuple[]\",\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission[]\",\"components\":[{\"name\":\"forwarder\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"workflowName\",\"type\":\"bytes10\",\"internalType\":\"bytes10\"},{\"name\":\"reportName\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"workflowOwner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"isAllowed\",\"type\":\"bool\",\"internalType\":\"bool\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"typeAndVersion\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"updatePrices\",\"inputs\":[{\"name\":\"priceUpdates\",\"type\":\"tuple\",\"internalType\":\"structInternal.PriceUpdates\",\"components\":[{\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"components\":[{\"name\":\"sourceToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"usdPerToken\",\"type\":\"uint224\",\"internalType\":\"uint224\"}]},{\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.GasPriceUpdate[]\",\"components\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"usdPerUnitGas\",\"type\":\"uint224\",\"internalType\":\"uint224\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"updateTokenPriceFeeds\",\"inputs\":[{\"name\":\"tokenPriceFeedUpdates\",\"type\":\"tuple[]\",\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"components\":[{\"name\":\"sourceToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"feedConfig\",\"type\":\"tuple\",\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"components\":[{\"name\":\"dataFeedAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenDecimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"AuthorizedCallerAdded\",\"inputs\":[{\"name\":\"caller\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"AuthorizedCallerRemoved\",\"inputs\":[{\"name\":\"caller\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DestChainAdded\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"destChainConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"maxDataBytes\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destGasOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destGasPerPayloadByteBase\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"destGasPerPayloadByteHigh\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"destGasPerPayloadByteThreshold\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"chainFamilySelector\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"},{\"name\":\"enforceOutOfOrder\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DestChainConfigUpdated\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"destChainConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"maxDataBytes\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destGasOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destGasPerPayloadByteBase\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"destGasPerPayloadByteHigh\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"destGasPerPayloadByteThreshold\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"chainFamilySelector\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"},{\"name\":\"enforceOutOfOrder\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"FeeTokenAdded\",\"inputs\":[{\"name\":\"feeToken\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"FeeTokenRemoved\",\"inputs\":[{\"name\":\"feeToken\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferRequested\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"PremiumMultiplierWeiPerEthUpdated\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"PriceFeedPerTokenUpdated\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"priceFeedConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"components\":[{\"name\":\"dataFeedAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenDecimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ReportPermissionSet\",\"inputs\":[{\"name\":\"reportId\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"permission\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission\",\"components\":[{\"name\":\"forwarder\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"workflowName\",\"type\":\"bytes10\",\"internalType\":\"bytes10\"},{\"name\":\"reportName\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"workflowOwner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"isAllowed\",\"type\":\"bool\",\"internalType\":\"bool\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TokenTransferFeeConfigDeleted\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"token\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TokenTransferFeeConfigUpdated\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"token\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"components\":[{\"name\":\"minFeeUSDCents\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"deciBps\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"destGasOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destBytesOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"UsdPerTokenUpdated\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"timestamp\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"UsdPerUnitGasUpdated\",\"inputs\":[{\"name\":\"destChain\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"timestamp\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"CannotTransferToSelf\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"DataFeedValueOutOfUint224Range\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"DestinationChainNotEnabled\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"FeeTokenNotSupported\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"InvalidChainFamilySelector\",\"inputs\":[{\"name\":\"chainFamilySelector\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}]},{\"type\":\"error\",\"name\":\"InvalidDestBytesOverhead\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"destBytesOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]},{\"type\":\"error\",\"name\":\"InvalidDestChainConfig\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"InvalidEVMAddress\",\"inputs\":[{\"name\":\"encodedAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidExtraArgsData\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidExtraArgsTag\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidFeeRange\",\"inputs\":[{\"name\":\"minFeeUSDCents\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"maxFeeUSDCents\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"InvalidSVMAddress\",\"inputs\":[{\"name\":\"SVMAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidStaticConfig\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidTokenReceiver\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MessageComputeUnitLimitTooHigh\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MessageFeeTooHigh\",\"inputs\":[{\"name\":\"msgFeeJuels\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"MessageGasLimitTooHigh\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MessageTooLarge\",\"inputs\":[{\"name\":\"maxSize\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"actualSize\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"MustBeProposedOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OnlyCallableByOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OwnerCannotBeZero\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ReportForwarderUnauthorized\",\"inputs\":[{\"name\":\"forwarder\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"workflowOwner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"workflowName\",\"type\":\"bytes10\",\"internalType\":\"bytes10\"},{\"name\":\"reportName\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"}]},{\"type\":\"error\",\"name\":\"SourceTokenDataTooLarge\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"StaleGasPrice\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"threshold\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"timePassed\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"TokenNotSupported\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"UnauthorizedCaller\",\"inputs\":[{\"name\":\"caller\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"UnsupportedNumberOfTokens\",\"inputs\":[{\"name\":\"numberOfTokens\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"ZeroAddressNotAllowed\",\"inputs\":[]}]", + Bin: "0x60e060405234611029576170618038038061001981611295565b9283398101908082036101208112611029576060136110295761003a611257565b81516001600160601b038116810361102957815261005a602083016112ba565b906020810191825261006e604084016112ce565b6040820190815260608401516001600160401b03811161102957856100949186016112f6565b60808501519094906001600160401b03811161102957866100b69183016112f6565b60a08201519096906001600160401b0381116110295782019080601f830112156110295781516100ed6100e8826112df565b611295565b9260208085848152019260071b8201019083821161102957602001915b8183106111e25750505060c08301516001600160401b0381116110295783019781601f8a011215611029578851986101446100e88b6112df565b996020808c838152019160051b830101918483116110295760208101915b838310611080575050505060e08401516001600160401b0381116110295784019382601f8601121561102957845161019c6100e8826112df565b9560208088848152019260061b8201019085821161102957602001915b81831061104457505050610100810151906001600160401b038211611029570182601f82011215611029578051906101f36100e8836112df565b93602061028081878681520194028301019181831161102957602001925b828410610e6757505050503315610e5657600180546001600160a01b031916331790556020986102408a611295565b97600089526000368137610252611276565b998a52888b8b015260005b89518110156102c4576001906001600160a01b0361027b828d61138f565b51168d6102878261157b565b610294575b50500161025d565b7fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda7758091604051908152a1388d61028c565b508a985089519660005b885181101561033f576001600160a01b036102e9828b61138f565b511690811561032e577feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef8c83610320600195611503565b50604051908152a1016102ce565b6342bcdf7f60e11b60005260046000fd5b5081518a985089906001600160a01b0316158015610e44575b8015610e35575b610e245791516001600160a01b031660a05290516001600160601b03166080525163ffffffff1660c05261039286611295565b9360008552600036813760005b855181101561040e576001906103c76001600160a01b036103c0838a61138f565b5116611410565b6103d2575b0161039f565b818060a01b036103e2828961138f565b51167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f91600080a26103cc565b508694508560005b84518110156104855760019061043e6001600160a01b03610437838961138f565b5116611542565b610449575b01610416565b818060a01b03610459828861138f565b51167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba23600080a2610443565b508593508460005b835181101561054757806104a36001928661138f565b517fe6a7a17d710bf0b2cd05e5397dc6f97a5da4ee79e31e234bf5f965ee2bd9a5bf606089858060a01b038451169301518360005260078b5260406000209060ff878060a01b038251169283898060a01b03198254161781558d8301908151604082549501948460a81b8651151560a81b16918560a01b9060a01b169061ffff60a01b19161717905560405193845251168c8301525115156040820152a20161048d565b5091509160005b8251811015610abc57610561818461138f565b51856001600160401b03610575848761138f565b5151169101519080158015610aa9575b8015610a8b575b610a7757600081815260098852604090205460019392919060081b6001600160e01b03191661092f57807f71e9302ab4e912a9678ae7f5a8542856706806f2817e1bf2a20b171e265cb4ad604051806106f5868291909161024063ffffffff8161026084019580511515855261ffff602082015116602086015282604082015116604086015282606082015116606086015282608082015116608086015260ff60a08201511660a086015260ff60c08201511660c086015261ffff60e08201511660e0860152826101008201511661010086015261ffff6101208201511661012086015261ffff610140820151166101408601528260e01b61016082015116610160860152610180810151151561018086015261ffff6101a0820151166101a0860152826101c0820151166101c0860152826101e0820151166101e086015260018060401b03610200820151166102008601528261022082015116610220860152015116910152565b0390a25b60005260098752826040600020825115158382549162ffff008c83015160081b169066ffffffff000000604084015160181b166affffffff00000000000000606085015160381b16926effffffff0000000000000000000000608086015160581b169260ff60781b60a087015160781b169460ff60801b60c088015160801b169161ffff60881b60e089015160881b169063ffffffff60981b6101008a015160981b169361ffff60b81b6101208b015160b81b169661ffff60c81b6101408c015160c81b169963ffffffff60d81b6101608d015160081c169b61018060ff60f81b910151151560f81b169c8f8060f81b039a63ffffffff60d81b199961ffff60c81b199861ffff60b81b199763ffffffff60981b199661ffff60881b199560ff60801b199460ff60781b19936effffffff0000000000000000000000199260ff6affffffff000000000000001992169066ffffffffffffff19161716171617161716171617161716171617161716179063ffffffff60d81b1617178155019061ffff6101a0820151169082549165ffffffff00006101c083015160101b169269ffffffff0000000000006101e084015160301b166a01000000000000000000008860901b0361020085015160501b169263ffffffff60901b61022086015160901b169461024063ffffffff60b01b91015160b01b169563ffffffff60b01b199363ffffffff60901b19926a01000000000000000000008c60901b0319918c8060501b03191617161716171617171790550161054e565b807f2431cc0363f2f66b21782c7e3d54dd9085927981a21bd0cc6be45a51b19689e360405180610a6f868291909161024063ffffffff8161026084019580511515855261ffff602082015116602086015282604082015116604086015282606082015116606086015282608082015116608086015260ff60a08201511660a086015260ff60c08201511660c086015261ffff60e08201511660e0860152826101008201511661010086015261ffff6101208201511661012086015261ffff610140820151166101408601528260e01b61016082015116610160860152610180810151151561018086015261ffff6101a0820151166101a0860152826101c0820151166101c0860152826101e0820151166101e086015260018060401b03610200820151166102008601528261022082015116610220860152015116910152565b0390a26106f9565b63c35aa79d60e01b60005260045260246000fd5b5063ffffffff6101e08301511663ffffffff6060840151161061058c565b5063ffffffff6101e08301511615610585565b84828560005b8151811015610b42576001906001600160a01b03610ae0828561138f565b5151167fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d86848060401b0381610b16868961138f565b510151168360005260088252604060002081878060401b0319825416179055604051908152a201610ac2565b83600184610b4f83611295565b9060008252600092610e1f575b909282935b8251851015610d5e57610b74858461138f565b5180516001600160401b0316939083019190855b83518051821015610d4d57610b9e82879261138f565b51015184516001600160a01b0390610bb790849061138f565b5151169063ffffffff815116908781019163ffffffff8351169081811015610d385750506080810163ffffffff815116898110610d21575090899291838c52600a8a5260408c20600160a01b6001900386168d528a5260408c2092825163ffffffff169380549180518d1b67ffffffff0000000016916040860192835160401b69ffff000000000000000016966060810195865160501b6dffffffff00000000000000000000169063ffffffff60701b895160701b169260a001998b60ff60901b8c51151560901b169560ff60901b199363ffffffff60701b19926dffffffff000000000000000000001991600160501b60019003191617161716171617171790556040519586525163ffffffff168c8601525161ffff1660408501525163ffffffff1660608401525163ffffffff16608083015251151560a082015260c07f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b591a3600101610b88565b6312766e0160e11b8c52600485905260245260448bfd5b6305a7b3d160e11b8c5260045260245260448afd5b505060019096019593509050610b61565b9150825b8251811015610de0576001906001600160401b03610d80828661138f565b515116828060a01b0384610d94848861138f565b5101511690808752600a855260408720848060a01b038316885285528660408120557f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b8780a301610d62565b604051615a519081611610823960805181818161044201526129ff015260a05181818161047801526129b0015260c05181818161049f01526136d60152f35b610b5c565b63d794ef9560e01b60005260046000fd5b5063ffffffff8251161561035f565b5080516001600160601b031615610358565b639b15e16f60e01b60005260046000fd5b838203610280811261102957610260610e7e611276565b91610e888761136c565b8352601f190112611029576040519161026083016001600160401b0381118482101761102e57604052610ebd6020870161135f565b8352610ecb60408701611380565b6020840152610edc606087016112ce565b6040840152610eed608087016112ce565b6060840152610efe60a087016112ce565b6080840152610f0f60c08701611351565b60a0840152610f2060e08701611351565b60c0840152610f326101008701611380565b60e0840152610f4461012087016112ce565b610100840152610f576101408701611380565b610120840152610f6a6101608701611380565b610140840152610180860151916001600160e01b0319831683036110295783602093610160610280960152610fa26101a0890161135f565b610180820152610fb56101c08901611380565b6101a0820152610fc86101e089016112ce565b6101c0820152610fdb61020089016112ce565b6101e0820152610fee610220890161136c565b61020082015261100161024089016112ce565b61022082015261101461026089016112ce565b61024082015283820152815201930192610211565b600080fd5b634e487b7160e01b600052604160045260246000fd5b60408387031261102957602060409161105b611276565b611064866112ba565b815261107183870161136c565b838201528152019201916101b9565b82516001600160401b0381116110295782016040818803601f190112611029576110a8611276565b906110b56020820161136c565b825260408101516001600160401b03811161102957602091010187601f820112156110295780516110e86100e8826112df565b91602060e08185858152019302820101908a821161102957602001915b8183106111245750505091816020938480940152815201920191610162565b828b0360e081126110295760c0611139611276565b91611143866112ba565b8352601f190112611029576040519160c08301916001600160401b0383118484101761102e5760e09360209360405261117d8488016112ce565b815261118b604088016112ce565b8482015261119b60608801611380565b60408201526111ac608088016112ce565b60608201526111bd60a088016112ce565b60808201526111ce60c0880161135f565b60a082015283820152815201920191611105565b828403608081126110295760606111f7611276565b91611201866112ba565b8352601f1901126110295760809160209161121a611257565b6112258488016112ba565b815261123360408801611351565b848201526112436060880161135f565b60408201528382015281520192019161010a565b60405190606082016001600160401b0381118382101761102e57604052565b60408051919082016001600160401b0381118382101761102e57604052565b6040519190601f01601f191682016001600160401b0381118382101761102e57604052565b51906001600160a01b038216820361102957565b519063ffffffff8216820361102957565b6001600160401b03811161102e5760051b60200190565b9080601f830112156110295781516113106100e8826112df565b9260208085848152019260051b82010192831161102957602001905b8282106113395750505090565b60208091611346846112ba565b81520191019061132c565b519060ff8216820361102957565b5190811515820361102957565b51906001600160401b038216820361102957565b519061ffff8216820361102957565b80518210156113a35760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b80548210156113a35760005260206000200190600090565b805480156113fa5760001901906113e882826113b9565b8154906000199060031b1b1916905555565b634e487b7160e01b600052603160045260246000fd5b6000818152600c602052604090205480156114d15760001981018181116114bb57600b546000198101919082116114bb5781810361146a575b505050611456600b6113d1565b600052600c60205260006040812055600190565b6114a361147b61148c93600b6113b9565b90549060031b1c928392600b6113b9565b819391549060031b91821b91600019901b19161790565b9055600052600c602052604060002055388080611449565b634e487b7160e01b600052601160045260246000fd5b5050600090565b8054906801000000000000000082101561102e578161148c9160016114ff940181556113b9565b9055565b8060005260036020526040600020541560001461153c576115258160026114d8565b600254906000526003602052604060002055600190565b50600090565b80600052600c6020526040600020541560001461153c5761156481600b6114d8565b600b5490600052600c602052604060002055600190565b60008181526003602052604090205480156114d15760001981018181116114bb576002546000198101919082116114bb578082036115d5575b5050506115c160026113d1565b600052600360205260006040812055600190565b6115f76115e661148c9360026113b9565b90549060031b1c92839260026113b9565b905560005260036020526040600020553880806115b456fe6080604052600436101561001257600080fd5b60003560e01c806241e5be1461020657806301ffc9a714610201578063061877e3146101fc57806306285c69146101f7578063181f5a77146101f25780632451a627146101ed578063325c868e146101e85780633937306f146101e357806341ed29e7146101de578063430d138c146101d957806345ac924d146101d45780634ab35b0b146101cf578063514e8cff146101ca5780636def4ce7146101c5578063770e2dc4146101c057806379ba5097146101bb5780637afac322146101b6578063805f2132146101b157806382b49eb0146101ac57806387b8d879146101a75780638da5cb5b146101a257806391a2749a1461019d578063a69c64c014610198578063bf78e03f14610193578063cdc73d511461018e578063d02641a014610189578063d63d3af214610184578063d8694ccd1461017f578063f2fde38b1461017a578063fbe3f778146101755763ffdb4b371461017057600080fd5b612556565b612459565b61239d565b611f78565b611f5c565b611f13565b611e9c565b611df6565b611d3d565b611ca9565b611c82565b611a66565b6118e9565b61164e565b611515565b6113fd565b6111de565b61105f565b610e88565b610e50565b610d87565b610c5a565b6109ff565b610743565b610727565b6106a4565b6105fe565b610406565b6103be565b61029a565b61022e565b6001600160a01b0381160361021c57565b600080fd5b359061022c8261020b565b565b3461021c57606060031936011261021c5760206102656004356102508161020b565b602435604435916102608361020b565b6126d8565b604051908152f35b35907fffffffff000000000000000000000000000000000000000000000000000000008216820361021c57565b3461021c57602060031936011261021c576004357fffffffff000000000000000000000000000000000000000000000000000000008116810361021c577fffffffff00000000000000000000000000000000000000000000000000000000602091167f805f2132000000000000000000000000000000000000000000000000000000008114908115610394575b811561036a575b8115610340575b506040519015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501438610335565b7f181f5a77000000000000000000000000000000000000000000000000000000008114915061032e565b7f9b645f410000000000000000000000000000000000000000000000000000000081149150610327565b3461021c57602060031936011261021c576001600160a01b036004356103e38161020b565b166000526008602052602067ffffffffffffffff60406000205416604051908152f35b3461021c57600060031936011261021c5761041f61270c565b50606060405161042e81610506565b63ffffffff6bffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016918281526001600160a01b0360406020830192827f00000000000000000000000000000000000000000000000000000000000000001684520191837f00000000000000000000000000000000000000000000000000000000000000001683526040519485525116602084015251166040820152f35b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6060810190811067ffffffffffffffff82111761052257604052565b6104d7565b60a0810190811067ffffffffffffffff82111761052257604052565b6040810190811067ffffffffffffffff82111761052257604052565b60c0810190811067ffffffffffffffff82111761052257604052565b90601f601f19910116810190811067ffffffffffffffff82111761052257604052565b6040519061022c60408361057b565b6040519061022c6102608361057b565b919082519283825260005b8481106105e9575050601f19601f8460006020809697860101520116010190565b806020809284010151828286010152016105c8565b3461021c57600060031936011261021c5761065d6040805190610621818361057b565b601382527f46656551756f74657220312e362e302d646576000000000000000000000000006020830152519182916020835260208301906105bd565b0390f35b602060408183019282815284518094520192019060005b8181106106855750505090565b82516001600160a01b0316845260209384019390920191600101610678565b3461021c57600060031936011261021c5760405180602060025491828152019060026000527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace9060005b8181106107115761065d856107058187038261057b565b60405191829182610661565b82548452602090930192600192830192016106ee565b3461021c57600060031936011261021c57602060405160248152f35b3461021c57602060031936011261021c5760043567ffffffffffffffff811161021c5780600401906040600319823603011261021c57610781613a0f565b61078b828061272b565b4263ffffffff1692915060005b8181106108fc575050602401906107af828461272b565b92905060005b8381106107be57005b806107dd6107d86001936107d2868a61272b565b906127ae565b61280e565b7fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e67ffffffffffffffff6108d86108ca60208501946108bc61082687516001600160e01b031690565b61084061083161059e565b6001600160e01b039092168252565b63ffffffff8c16602082015261087b610861845167ffffffffffffffff1690565b67ffffffffffffffff166000526005602052604060002090565b815160209092015160e01b7fffffffff00000000000000000000000000000000000000000000000000000000166001600160e01b0392909216919091179055565b5167ffffffffffffffff1690565b93516001600160e01b031690565b604080516001600160e01b039290921682524260208301529190931692a2016107b5565b806109156109106001936107d2898061272b565b6127d7565b7f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a6001600160a01b036109ae6108ca60208501946109a161095d87516001600160e01b031690565b61096861083161059e565b63ffffffff8d16602082015261087b61098884516001600160a01b031690565b6001600160a01b03166000526006602052604060002090565b516001600160a01b031690565b604080516001600160e01b039290921682524260208301529190931692a201610798565b67ffffffffffffffff81116105225760051b60200190565b8015150361021c57565b359061022c826109ea565b3461021c57602060031936011261021c5760043567ffffffffffffffff811161021c573660238201121561021c57806004013590610a3c826109d2565b90610a4a604051928361057b565b828252602460a06020840194028201019036821161021c57602401925b818410610a7957610a7783612833565b005b60a08436031261021c5760405190610a9082610527565b8435610a9b8161020b565b825260208501357fffffffffffffffffffff000000000000000000000000000000000000000000008116810361021c5760208301526040850135907fffff0000000000000000000000000000000000000000000000000000000000008216820361021c5782602092604060a0950152610b1660608801610221565b6060820152610b27608088016109f4565b6080820152815201930192610a67565b6004359067ffffffffffffffff8216820361021c57565b6024359067ffffffffffffffff8216820361021c57565b359067ffffffffffffffff8216820361021c57565b9181601f8401121561021c5782359167ffffffffffffffff831161021c576020838186019501011161021c57565b9181601f8401121561021c5782359167ffffffffffffffff831161021c576020808501948460051b01011161021c57565b929091610bfa928452151560208401526080604084015260808301906105bd565b906060818303910152815180825260208201916020808360051b8301019401926000915b838310610c2d57505050505090565b9091929394602080610c4b83601f19866001960301875289516105bd565b97019301930191939290610c1e565b3461021c5760c060031936011261021c57610c73610b37565b60243590610c808261020b565b60443560643567ffffffffffffffff811161021c57610ca3903690600401610b7a565b60849391933567ffffffffffffffff811161021c57610cc6903690600401610ba8565b9160a4359567ffffffffffffffff871161021c573660238801121561021c5786600401359567ffffffffffffffff871161021c573660248860061b8a01011161021c5761065d986024610d1a9901966129a5565b9060409492945194859485610bd9565b602060408183019282815284518094520192019060005b818110610d4e5750505090565b9091926020604082610d7c600194885163ffffffff602080926001600160e01b038151168552015116910152565b019401929101610d41565b3461021c57602060031936011261021c5760043567ffffffffffffffff811161021c57610db8903690600401610ba8565b610dc1816109d2565b91610dcf604051938461057b565b818352601f19610dde836109d2565b0160005b818110610e3957505060005b82811015610e2b57600190610e0f610e0a8260051b8501612cbc565b613682565b610e198287612991565b52610e248186612991565b5001610dee565b6040518061065d8682610d2a565b602090610e44612ca3565b82828801015201610de2565b3461021c57602060031936011261021c576020610e77600435610e728161020b565b613997565b6001600160e01b0360405191168152f35b3461021c57602060031936011261021c5767ffffffffffffffff610eaa610b37565b610eb2612ca3565b50166000526005602052604060002060405190610ece82610543565b546001600160e01b038116825260e01c6020820152604051809161065d82604081019263ffffffff602080926001600160e01b038151168552015116910152565b61022c9092919261024080610260830195610f2c84825115159052565b60208181015161ffff169085015260408181015163ffffffff169085015260608181015163ffffffff169085015260808181015163ffffffff169085015260a08181015160ff169085015260c08181015160ff169085015260e08181015161ffff16908501526101008181015163ffffffff16908501526101208181015161ffff16908501526101408181015161ffff1690850152610160818101517fffffffff000000000000000000000000000000000000000000000000000000001690850152610180818101511515908501526101a08181015161ffff16908501526101c08181015163ffffffff16908501526101e08181015163ffffffff16908501526102008181015167ffffffffffffffff16908501526102208181015163ffffffff1690850152015163ffffffff16910152565b3461021c57602060031936011261021c5761065d61112261111d611081610b37565b600061024061108e6105ad565b8281528260208201528260408201528260608201528260808201528260a08201528260c08201528260e08201528261010082015282610120820152826101408201528261016082015282610180820152826101a0820152826101c0820152826101e08201528261020082015282610220820152015267ffffffffffffffff166000526009602052604060002090565b612ceb565b60405191829182610f0f565b359063ffffffff8216820361021c57565b359061ffff8216820361021c57565b81601f8201121561021c57803590611165826109d2565b92611173604051948561057b565b82845260208085019360061b8301019181831161021c57602001925b82841061119d575050505090565b60408483031261021c57602060409182516111b781610543565b6111c087610b65565b8152828701356111cf8161020b565b8382015281520193019261118f565b3461021c57604060031936011261021c5760043567ffffffffffffffff811161021c573660238201121561021c57806004013561121a816109d2565b91611228604051938461057b565b8183526024602084019260051b8201019036821161021c5760248101925b828410611277576024358567ffffffffffffffff821161021c57611271610a7792369060040161114e565b90612e59565b833567ffffffffffffffff811161021c57820160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc823603011261021c57604051906112c382610543565b6112cf60248201610b65565b8252604481013567ffffffffffffffff811161021c57602491010136601f8201121561021c578035611300816109d2565b9161130e604051938461057b565b818352602060e081850193028201019036821161021c57602001915b8183106113495750505091816020938480940152815201930192611246565b82360360e0811261021c5760c0601f196040519261136684610543565b86356113718161020b565b8452011261021c5760e09160209160405161138b8161055f565b61139684880161112e565b81526113a46040880161112e565b848201526113b46060880161113f565b60408201526113c56080880161112e565b60608201526113d660a0880161112e565b608082015260c08701356113e9816109ea565b60a08201528382015281520192019161132a565b3461021c57600060031936011261021c576000546001600160a01b0381163303611484577fffffffffffffffffffffffff0000000000000000000000000000000000000000600154913382841617600155166000556001600160a01b033391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b7f02b543c60000000000000000000000000000000000000000000000000000000060005260046000fd5b9080601f8301121561021c5781356114c5816109d2565b926114d3604051948561057b565b81845260208085019260051b82010192831161021c57602001905b8282106114fb5750505090565b60208091833561150a8161020b565b8152019101906114ee565b3461021c57604060031936011261021c5760043567ffffffffffffffff811161021c576115469036906004016114ae565b60243567ffffffffffffffff811161021c576115669036906004016114ae565b9061156f613a53565b60005b81518110156115de578061159361158e6109a160019486612991565b615656565b61159e575b01611572565b6001600160a01b036115b36109a18386612991565b167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f91600080a2611598565b8260005b8151811015610a7757806116036115fe6109a160019486612991565b61566a565b61160e575b016115e2565b6001600160a01b036116236109a18386612991565b167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba23600080a2611608565b3461021c57604060031936011261021c5760043567ffffffffffffffff811161021c5761167f903690600401610b7a565b6024359167ffffffffffffffff831161021c576116d86116d06116b66116ac6116e0963690600401610b7a565b9490953691613108565b90604082015190605e604a84015160601c93015191929190565b919033613eb7565b81019061314f565b60005b8151811015610a775761172b61172661170d6116ff8486612991565b51516001600160a01b031690565b6001600160a01b03166000526007602052604060002090565b61320e565b61173f61173b6040830151151590565b1590565b6118a0579061178a6117576020600194015160ff1690565b61178461177860206117698689612991565b5101516001600160e01b031690565b6001600160e01b031690565b90613f89565b6117a560406117998487612991565b51015163ffffffff1690565b63ffffffff6117d06117c76117c06109886116ff888b612991565b5460e01c90565b63ffffffff1690565b91161061189a5761181e6117e960406117998588612991565b61180e6117f461059e565b6001600160e01b03851681529163ffffffff166020830152565b61087b6109886116ff8689612991565b7f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a6001600160a01b036118546116ff8588612991565b6118906118666040611799888b612991565b60405193849316958390929163ffffffff6020916001600160e01b03604085019616845216910152565b0390a25b016116e3565b50611894565b6118e56118b06116ff8486612991565b7f06439c6b000000000000000000000000000000000000000000000000000000006000526001600160a01b0316600452602490565b6000fd5b3461021c57604060031936011261021c5761065d611971611908610b37565b67ffffffffffffffff6024359161191e8361020b565b600060a060405161192e8161055f565b828152826020820152826040820152826060820152826080820152015216600052600a6020526040600020906001600160a01b0316600052602052604060002090565b6119ed6119e4604051926119848461055f565b5463ffffffff8116845263ffffffff8160201c16602085015261ffff8160401c1660408501526119cb6119be8263ffffffff9060501c1690565b63ffffffff166060860152565b63ffffffff607082901c16608085015260901c60ff1690565b151560a0830152565b6040519182918291909160a08060c083019463ffffffff815116845263ffffffff602082015116602085015261ffff604082015116604085015263ffffffff606082015116606085015263ffffffff608082015116608085015201511515910152565b60ff81160361021c57565b359061022c82611a50565b3461021c57602060031936011261021c5760043567ffffffffffffffff811161021c573660238201121561021c57806004013590611aa3826109d2565b90611ab1604051928361057b565b82825260246102806020840194028201019036821161021c57602401925b818410611adf57610a778361329e565b833603610280811261021c57610260601f1960405192611afe84610543565b611b0788610b65565b8452011261021c5761028091602091611b1e6105ad565b611b298489016109f4565b8152611b376040890161113f565b84820152611b476060890161112e565b6040820152611b586080890161112e565b6060820152611b6960a0890161112e565b6080820152611b7a60c08901611a5b565b60a0820152611b8b60e08901611a5b565b60c0820152611b9d610100890161113f565b60e0820152611baf610120890161112e565b610100820152611bc2610140890161113f565b610120820152611bd5610160890161113f565b610140820152611be8610180890161026d565b610160820152611bfb6101a089016109f4565b610180820152611c0e6101c0890161113f565b6101a0820152611c216101e0890161112e565b6101c0820152611c34610200890161112e565b6101e0820152611c476102208901610b65565b610200820152611c5a610240890161112e565b610220820152611c6d610260890161112e565b61024082015283820152815201930192611acf565b3461021c57600060031936011261021c5760206001600160a01b0360015416604051908152f35b3461021c57602060031936011261021c5760043567ffffffffffffffff811161021c576040600319823603011261021c57604051611ce681610543565b816004013567ffffffffffffffff811161021c57611d0a90600436918501016114ae565b8152602482013567ffffffffffffffff811161021c57610a77926004611d3392369201016114ae565b6020820152613454565b3461021c57602060031936011261021c5760043567ffffffffffffffff811161021c573660238201121561021c57806004013590611d7a826109d2565b90611d88604051928361057b565b8282526024602083019360061b8201019036821161021c57602401925b818410611db557610a77836135a6565b60408436031261021c5760206040918251611dcf81610543565b8635611dda8161020b565b8152611de7838801610b65565b83820152815201930192611da5565b3461021c57602060031936011261021c576001600160a01b03600435611e1b8161020b565b611e2361270c565b5016600052600760205261065d604060002060ff60405191611e4483610506565b546001600160a01b0381168352818160a01c16602084015260a81c16151560408201526040519182918291909160408060608301946001600160a01b03815116845260ff602082015116602085015201511515910152565b3461021c57600060031936011261021c57604051806020600b54918281520190600b6000527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db99060005b818110611efd5761065d856107058187038261057b565b8254845260209093019260019283019201611ee6565b3461021c57602060031936011261021c576040611f35600435610e0a8161020b565b611f5a8251809263ffffffff602080926001600160e01b038151168552015116910152565bf35b3461021c57600060031936011261021c57602060405160128152f35b3461021c57604060031936011261021c57611f91610b37565b60243567ffffffffffffffff811161021c57806004019060a0600319823603011261021c57611fd761111d8467ffffffffffffffff166000526009602052604060002090565b606482019161200a61173b611feb85612cbc565b6001600160a01b03166000526001600b01602052604060002054151590565b61235c579081604485930195612020878561272b565b959050602461203c85612036608487018961379e565b906148cb565b93019061206b61204c838861379e565b9050858961206461205d8b8061379e565b3691613108565b9289614a74565b84612078610e7283612cbc565b98899461209661209061022085015163ffffffff1690565b82614b36565b9b6000808c156123225750506120fc61ffff856121219961210899989661213c9661212f966120f36120e36101c06120d76101a06121429f015161ffff1690565b97015163ffffffff1690565b916120ed8c612cbc565b9461272b565b96909516614c27565b98919897909894612cbc565b6001600160a01b03166000526008602052604060002090565b5467ffffffffffffffff1690565b67ffffffffffffffff1690565b9061268c565b9560009761ffff61215961014089015161ffff1690565b166122c7575b509461213c61212f61020061222d61065d9d6dffffffffffffffffffffffffffff6122256122459f9e9b6122206001600160e01b039f9b9c61223d9f6122209e63ffffffff6121b46122209f6121be9461379e565b92905016906137ef565b908b60a081016121e16121db6121d5835160ff1690565b60ff1690565b8561268c565b9360e08301916121f3835161ffff1690565b9061ffff82168311612255575b5050505060800151612220916117c79163ffffffff1661382d565b61382d565b6137ef565b91169061268c565b93015167ffffffffffffffff1690565b91169061269f565b6040519081529081906020820190565b6117c7949650612220959361ffff6122b66122a561221b9661229f61229861228f60809960ff6122896122bd9b5160ff1690565b166137fc565b965161ffff1690565b61ffff1690565b90613675565b61213c6121d560c08d015160ff1690565b91166137ef565b9593839550612200565b909594989750826122ed8b989495986dffffffffffffffffffffffffffff9060701c1690565b6dffffffffffffffffffffffffffff1691612308848961379e565b90506123149388614e49565b96979394389693929661215f565b969593509650505061213c61212f6121216121086123566123516117c761024061214299015163ffffffff1690565b612645565b94612cbc565b6118e561236884612cbc565b7f2502348c000000000000000000000000000000000000000000000000000000006000526001600160a01b0316600452602490565b3461021c57602060031936011261021c576001600160a01b036004356123c28161020b565b6123ca613a53565b1633811461242f57807fffffffffffffffffffffffff000000000000000000000000000000000000000060005416176000556001600160a01b03600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b7fdad89dca0000000000000000000000000000000000000000000000000000000060005260046000fd5b3461021c57602060031936011261021c5760043567ffffffffffffffff811161021c573660238201121561021c57806004013590612496826109d2565b906124a4604051928361057b565b8282526024602083019360071b8201019036821161021c57602401925b8184106124d157610a7783613847565b8336036080811261021c576060601f19604051926124ee84610543565b87356124f98161020b565b8452011261021c5760809160209160405161251381610506565b838801356125208161020b565b8152604088013561253081611a50565b848201526060880135612542816109ea565b6040820152838201528152019301926124c1565b3461021c57604060031936011261021c576004356125738161020b565b61257b610b4e565b9067ffffffffffffffff82169182600052600960205260ff60406000205416156125e8576125ab6125cc92613997565b92600052600960205263ffffffff60016040600020015460901c1690614b36565b604080516001600160e01b039384168152919092166020820152f35b827f99ac52f20000000000000000000000000000000000000000000000000000000060005260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b90662386f26fc10000820291808304662386f26fc10000149015171561266757565b612616565b90655af3107a4000820291808304655af3107a4000149015171561266757565b8181029291811591840414171561266757565b81156126a9570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6127026126fc61270994936001600160e01b036126f58195613997565b169061268c565b92613997565b169061269f565b90565b6040519061271982610506565b60006040838281528260208201520152565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561021c570180359067ffffffffffffffff821161021c57602001918160061b3603831361021c57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b91908110156127be5760061b0190565b61277f565b35906001600160e01b038216820361021c57565b60408136031261021c576128066020604051926127f384610543565b80356127fe8161020b565b8452016127c3565b602082015290565b60408136031261021c5761280660206040519261282a84610543565b6127fe81610b65565b9061283c613a53565b60005b825181101561298c578061285560019285612991565b517f32a4ba3fa3351b11ad555d4c8ec70a744e8705607077a946807030d64b6ab1a360a06001600160a01b038351169260608101936001600160a01b0380865116957fffff0000000000000000000000000000000000000000000000000000000000006128f360208601947fffffffffffffffffffff00000000000000000000000000000000000000000000865116604088019a848c511692614eee565b977fffffffffffffffffffff00000000000000000000000000000000000000000000608087019561295f875115158c600052600460205260406000209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b8560405198511688525116602087015251166040850152511660608301525115156080820152a20161283f565b509050565b80518210156127be5760209160051b010190565b9895979692949391907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b0382166001600160a01b03821614600014612c93575050935b6bffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016808611612c62575090612a35918715158a613a91565b979096612a82612a598367ffffffffffffffff166000526009602052604060002090565b5460081b7fffffffff000000000000000000000000000000000000000000000000000000001690565b90612a8c81613cda565b9760005b828110612aa4575050505050505093929190565b612ab7612ab28284896127ae565b612cbc565b8388612ad1612ac7858484613d23565b604081019061379e565b905060208111612be7575b508392612b0b612b0561205d612afb600198612b4697612b4197613d23565b602081019061379e565b8961541f565b612b298967ffffffffffffffff16600052600a602052604060002090565b906001600160a01b0316600052602052604060002090565b613244565b60a081015115612bab57612b8f612b676060612b8193015163ffffffff1690565b6040805163ffffffff909216602083015290928391820190565b03601f19810183528261057b565b612b99828d612991565b52612ba4818c612991565b5001612a90565b50612b81612b8f612be284612bd48a67ffffffffffffffff166000526009602052604060002090565b015460101c63ffffffff1690565b612b67565b915050612c1f6117c7612c1284612b298b67ffffffffffffffff16600052600a602052604060002090565b5460701c63ffffffff1690565b10612c2c57838838612adc565b7f36f536ca000000000000000000000000000000000000000000000000000000006000526001600160a01b031660045260246000fd5b857f6a92a4830000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b91612c9d926126d8565b936129f0565b60405190612cb082610543565b60006020838281520152565b356127098161020b565b90604051612cd381610543565b91546001600160e01b038116835260e01c6020830152565b9061022c612e4b6001612cfc6105ad565b94612dea612de08254612d18612d128260ff1690565b15158a52565b61ffff600882901c1660208a015263ffffffff601882901c1660408a015263ffffffff603882901c1660608a015263ffffffff605882901c1660808a015260ff607882901c1660a08a015260ff608082901c1660c08a015261ffff608882901c1660e08a015263ffffffff609882901c166101008a015261ffff60b882901c166101208a015261ffff60c882901c166101408a01527fffffffff00000000000000000000000000000000000000000000000000000000600882901b166101608a015260f81c90565b1515610180880152565b015461ffff81166101a086015263ffffffff601082901c166101c086015263ffffffff603082901c166101e086015267ffffffffffffffff605082901c1661020086015263ffffffff609082901c1661022086015260b01c63ffffffff1690565b63ffffffff16610240840152565b90612e62613a53565b6000915b805183101561305457612e798382612991565b5190612e8d825167ffffffffffffffff1690565b946020600093019367ffffffffffffffff8716935b8551805182101561303f57612eb982602092612991565b510151612eca6116ff838951612991565b8151602083015163ffffffff908116911681811015613006575050608082015163ffffffff1660208110612fc5575090867f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b56001600160a01b0384612f54858f60019998612b29612f4f9267ffffffffffffffff16600052600a602052604060002090565b613d63565b612fbc60405192839216958291909160a08060c083019463ffffffff815116845263ffffffff602082015116602085015261ffff604082015116604085015263ffffffff606082015116606085015263ffffffff608082015116608085015201511515910152565b0390a301612ea2565b7f24ecdc02000000000000000000000000000000000000000000000000000000006000526001600160a01b0390911660045263ffffffff1660245260446000fd5b7f0b4f67a20000000000000000000000000000000000000000000000000000000060005263ffffffff9081166004521660245260446000fd5b50509550925092600191500191929092612e66565b50905060005b8151811015613104578061308261307360019385612991565b515167ffffffffffffffff1690565b67ffffffffffffffff6001600160a01b036130b160206130a28689612991565b5101516001600160a01b031690565b60006130d582612b298767ffffffffffffffff16600052600a602052604060002090565b551691167f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b600080a30161305a565b5050565b92919267ffffffffffffffff82116105225760405191613132601f8201601f19166020018461057b565b82948184528183011161021c578281602093846000960137010152565b60208183031261021c5780359067ffffffffffffffff821161021c570181601f8201121561021c57803590613183826109d2565b92613191604051948561057b565b8284526020606081860194028301019181831161021c57602001925b8284106131bb575050505090565b60608483031261021c5760206060916040516131d681610506565b86356131e18161020b565b81526131ee8388016127c3565b838201526131fe6040880161112e565b60408201528152019301926131ad565b9060405161321b81610506565b604060ff8294546001600160a01b0381168452818160a01c16602085015260a81c161515910152565b9061022c6040516132548161055f565b925463ffffffff8082168552602082811c821690860152604082811c61ffff1690860152605082901c81166060860152607082901c16608085015260901c60ff16151560a0840152565b906132a7613a53565b60005b825181101561298c576132bd8184612991565b5160206132cd6130738487612991565b9101519067ffffffffffffffff811680158015613435575b8015613407575b6133cf57916133958260019594613345613320612a5961339a9767ffffffffffffffff166000526009602052604060002090565b7fffffffff000000000000000000000000000000000000000000000000000000001690565b6133a0577f71e9302ab4e912a9678ae7f5a8542856706806f2817e1bf2a20b171e265cb4ad604051806133788782610f0f565b0390a267ffffffffffffffff166000526009602052604060002090565b614096565b016132aa565b7f2431cc0363f2f66b21782c7e3d54dd9085927981a21bd0cc6be45a51b19689e3604051806133788782610f0f565b7fc35aa79d0000000000000000000000000000000000000000000000000000000060005267ffffffffffffffff821660045260246000fd5b506101e083015163ffffffff1663ffffffff61342d6117c7606087015163ffffffff1690565b9116116132ec565b5063ffffffff61344d6101e085015163ffffffff1690565b16156132e5565b61345c613a53565b60208101519160005b83518110156134e9578061347e6109a160019387612991565b6134a061349b6001600160a01b0383165b6001600160a01b031690565b6159b9565b6134ac575b5001613465565b6040516001600160a01b039190911681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda7758090602090a1386134a5565b5091505160005b8151811015613104576135066109a18284612991565b906001600160a01b0382161561357c577feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef6135738361355861355361348f6001976001600160a01b031690565b615940565b506040516001600160a01b0390911681529081906020820190565b0390a1016134f0565b7f8579befe0000000000000000000000000000000000000000000000000000000060005260046000fd5b6135ae613a53565b60005b815181101561310457806001600160a01b036135cf60019385612991565b5151167fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d61366c67ffffffffffffffff602061360b8689612991565b51015116836000526008602052604060002067ffffffffffffffff82167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008254161790556040519182918291909167ffffffffffffffff6020820193169052565b0390a2016135b1565b9190820391821161266757565b61368a612ca3565b506136b06136ab826001600160a01b03166000526006602052604060002090565b612cc6565b60208101916136cf6136c96117c7855163ffffffff1690565b42613675565b63ffffffff7f000000000000000000000000000000000000000000000000000000000000000016116137775761172661371b916001600160a01b03166000526007602052604060002090565b61372b61173b6040830151151590565b801561377d575b6137775761373f90614764565b9163ffffffff6137676117c761375c602087015163ffffffff1690565b935163ffffffff1690565b911610613772575090565b905090565b50905090565b506001600160a01b0361379782516001600160a01b031690565b1615613732565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561021c570180359067ffffffffffffffff821161021c5760200191813603831361021c57565b9190820180921161266757565b9061ffff8091169116029061ffff821691820361266757565b63ffffffff60209116019063ffffffff821161266757565b9063ffffffff8091169116019063ffffffff821161266757565b90613850613a53565b60005b825181101561298c578061386960019285612991565b517fe6a7a17d710bf0b2cd05e5397dc6f97a5da4ee79e31e234bf5f965ee2bd9a5bf61398e60206001600160a01b0384511693015183600052600760205260406000206138ee6001600160a01b0383511682906001600160a01b03167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055565b602082015181547fffffffffffffffffffff0000ffffffffffffffffffffffffffffffffffffffff74ff000000000000000000000000000000000000000075ff0000000000000000000000000000000000000000006040870151151560a81b169360a01b169116171790556040519182918291909160408060608301946001600160a01b03815116845260ff602082015116602085015201511515910152565b0390a201613853565b6139a081613682565b9063ffffffff6020830151161580156139fd575b6139c65750516001600160e01b031690565b6001600160a01b03907f06439c6b000000000000000000000000000000000000000000000000000000006000521660045260246000fd5b506001600160e01b03825116156139b4565b33600052600360205260406000205415613a2557565b7fd86ad9cf000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b6001600160a01b03600154163303613a6757565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b61111d613ab791959493929567ffffffffffffffff166000526009602052604060002090565b936101608501947f2812d52c000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000613b2a88517fffffffff000000000000000000000000000000000000000000000000000000001690565b1614613ca6577f1e10bdc4000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000613b9c88517fffffffff000000000000000000000000000000000000000000000000000000001690565b1614613c1d576118e5613bcf87517fffffffff000000000000000000000000000000000000000000000000000000001690565b7f2ee82075000000000000000000000000000000000000000000000000000000006000527fffffffff0000000000000000000000000000000000000000000000000000000016600452602490565b60609192939495508063ffffffff613c4c610180613c4486613c5596015163ffffffff1690565b930151151590565b911686866152ba565b015181613c9d575b50613c7357613c6d913691613108565b90600190565b7f5bed51920000000000000000000000000000000000000000000000000000000060005260046000fd5b90501538613c5d565b6101e00151939450613ccb93919291613cc5915063ffffffff166117c7565b9161503b565b906127096020613c448461515c565b90613ce4826109d2565b613cf1604051918261057b565b828152601f19613d0182946109d2565b019060005b828110613d1257505050565b806060602080938501015201613d06565b91908110156127be5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff618136030182121561021c570190565b815181546020808501516040808701517fffffffffffffffffffffffffffffffffffffffffffff0000000000000000000090941663ffffffff958616179190921b67ffffffff00000000161791901b69ffff000000000000000016178255606083015161022c93613e739260a092613e15911685547fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff1660509190911b6dffffffff0000000000000000000016178555565b613e6c613e29608083015163ffffffff1690565b85547fffffffffffffffffffffffffffff00000000ffffffffffffffffffffffffffff1660709190911b71ffffffff000000000000000000000000000016178555565b0151151590565b81547fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff1690151560901b72ff00000000000000000000000000000000000016179055565b91929092613ec782828686614eee565b600052600460205260ff6040600020541615613ee35750505050565b6040517f097e17ff0000000000000000000000000000000000000000000000000000000081526001600160a01b0393841660048201529390921660248401527fffffffffffffffffffff0000000000000000000000000000000000000000000090911660448301527fffff000000000000000000000000000000000000000000000000000000000000166064820152608490fd5b0390fd5b604d811161266757600a0a90565b60ff1660120160ff81116126675760ff16906024821115614024577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc820191821161266757613fda613fe092613f7b565b9061269f565b6001600160e01b038111613ffa576001600160e01b031690565b7f10cb51d10000000000000000000000000000000000000000000000000000000060005260046000fd5b9060240390602482116126675761213c61403d92613f7b565b613fe0565b9060ff80911691160160ff81116126675760ff16906024821115614024577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc820191821161266757613fda613fe092613f7b565b906146b0610240600161022c946140e16140b08651151590565b829060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b6141276140f3602087015161ffff1690565b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ff1660089190911b62ffff0016178255565b61417361413b604087015163ffffffff1690565b82547fffffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffff1660189190911b66ffffffff00000016178255565b6141c3614187606087015163ffffffff1690565b82547fffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffff1660389190911b6affffffff0000000000000016178255565b6142176141d7608087015163ffffffff1690565b82547fffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffff1660589190911b6effffffff000000000000000000000016178255565b61426961422860a087015160ff1690565b82547fffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffff1660789190911b6fff00000000000000000000000000000016178255565b6142bc61427a60c087015160ff1690565b82547fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff1660809190911b70ff0000000000000000000000000000000016178255565b6143126142ce60e087015161ffff1690565b82547fffffffffffffffffffffffffff0000ffffffffffffffffffffffffffffffffff1660889190911b72ffff000000000000000000000000000000000016178255565b61436f61432761010087015163ffffffff1690565b82547fffffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffff1660989190911b76ffffffff0000000000000000000000000000000000000016178255565b6143cc61438261012087015161ffff1690565b82547fffffffffffffff0000ffffffffffffffffffffffffffffffffffffffffffffff1660b89190911b78ffff000000000000000000000000000000000000000000000016178255565b61442b6143df61014087015161ffff1690565b82547fffffffffff0000ffffffffffffffffffffffffffffffffffffffffffffffffff1660c89190911b7affff0000000000000000000000000000000000000000000000000016178255565b6144ac61445c6101608701517fffffffff000000000000000000000000000000000000000000000000000000001690565b82547fff00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffff1660089190911c7effffffff00000000000000000000000000000000000000000000000000000016178255565b61450d6144bd610180870151151590565b82547effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690151560f81b7fff0000000000000000000000000000000000000000000000000000000000000016178255565b01926145516145226101a083015161ffff1690565b859061ffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000825416179055565b61459d6145666101c083015163ffffffff1690565b85547fffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ffff1660109190911b65ffffffff000016178555565b6145ed6145b26101e083015163ffffffff1690565b85547fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1660309190911b69ffffffff00000000000016178555565b61464961460661020083015167ffffffffffffffff1690565b85547fffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffff1660509190911b71ffffffffffffffff0000000000000000000016178555565b6146a561465e61022083015163ffffffff1690565b85547fffffffffffffffffffff00000000ffffffffffffffffffffffffffffffffffff1660909190911b75ffffffff00000000000000000000000000000000000016178555565b015163ffffffff1690565b7fffffffffffff00000000ffffffffffffffffffffffffffffffffffffffffffff79ffffffff0000000000000000000000000000000000000000000083549260b01b169116179055565b519069ffffffffffffffffffff8216820361021c57565b908160a091031261021c57614725816146fa565b916020820151916040810151916127096080606084015193016146fa565b6040513d6000823e3d90fd5b9081602091031261021c575161270981611a50565b61476c612ca3565b5061478461348f61348f83516001600160a01b031690565b90604051907ffeaf968c00000000000000000000000000000000000000000000000000000000825260a082600481865afa92831561488c57600092600094614891575b5060008312613ffa576020600491604051928380927f313ce5670000000000000000000000000000000000000000000000000000000082525afa92831561488c576127099363ffffffff9361482d93600092614856575b506020015160ff165b90614042565b9261484861483961059e565b6001600160e01b039095168552565b1663ffffffff166020830152565b61482791925061487d602091823d8411614885575b614875818361057b565b81019061474f565b92915061481e565b503d61486b565b614743565b9093506148b791925060a03d60a0116148c4575b6148af818361057b565b810190614711565b50939250509192386147c7565b503d6148a5565b929190926101608201937f2812d52c000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000061494187517fffffffff000000000000000000000000000000000000000000000000000000001690565b1614614a2b577f1e10bdc4000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000006149b387517fffffffff000000000000000000000000000000000000000000000000000000001690565b16146149e6576118e5613bcf86517fffffffff000000000000000000000000000000000000000000000000000000001690565b61270993945091614a21916117c79363ffffffff614a19610180614a11606087015163ffffffff1690565b950151151590565b9316916152ba565b5163ffffffff1690565b614a70939450614a436101e084015163ffffffff1690565b9063ffffffff614a68610180614a60606088015163ffffffff1690565b960151151590565b94169261567e565b5190565b9493919063ffffffff604087015116808211614b0657505061ffff60208601511690818111614ad05750507fffffffff0000000000000000000000000000000000000000000000000000000061016061022c9495015116615568565b61ffff92507fd88dddd6000000000000000000000000000000000000000000000000000000006000526004521660245260446000fd5b7f869337890000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b67ffffffffffffffff8116600052600560205260406000209160405192614b5c84610543565b546001600160e01b038116845260e01c9182602085015263ffffffff82169283614b96575b5050505061270990516001600160e01b031690565b63ffffffff164290810393908411612667578311614bb45780614b81565b7ff08bcb3e0000000000000000000000000000000000000000000000000000000060005267ffffffffffffffff1660045263ffffffff1660245260445260646000fd5b60408136031261021c57602060405191614c1083610543565b8035614c1b8161020b565b83520135602082015290565b9694919695929390956000946000986000986000965b808810614c51575050505050505050929190565b9091929394959697999a614c6e614c698a848b6127ae565b614bf7565b9a614cbc612b418d614ca5614c978967ffffffffffffffff16600052600a602052604060002090565b91516001600160a01b031690565b6001600160a01b0316600052602052604060002090565b91614ccd61173b60a0850151151590565b614e165760009c6040840190614ce8612298835161ffff1690565b614d9e575b5050606083015163ffffffff16614d039161382d565b9c6080830151614d169063ffffffff1690565b614d1f9161382d565b9b8251614d2f9063ffffffff1690565b63ffffffff16614d3e90612645565b60019390808310614d9257506123516117c76020614d6193015163ffffffff1690565b808211614d815750614d72916137ef565b985b0196959493929190614c3d565b9050614d8c916137ef565b98614d74565b915050614d8c916137ef565b9061213c614e07939f614df5614dfe9460208f8e61229895506001600160a01b03614dd085516001600160a01b031690565b91166001600160a01b03821614614e0f57614deb9150613997565b915b0151906156e6565b925161ffff1690565b620186a0900490565b9b3880614ced565b5091614ded565b999b5060019150614e3d84614e37614e4393614e318b612645565b906137ef565b9b61382d565b9c613815565b9a614d74565b91939093806101e00193846101e011612667576101208102908082046101201490151715612667576101e091010180931161266757612298610140614edf612709966dffffffffffffffffffffffffffff612225614eca614eb7614ee99a63ffffffff61213c9a16906137ef565b61213c6122986101208c015161ffff1690565b614e316117c76101008b015163ffffffff1690565b93015161ffff1690565b61266c565b604080516001600160a01b039283166020820190815292909316908301527fffffffffffffffffffff0000000000000000000000000000000000000000000090921660608201527fffff000000000000000000000000000000000000000000000000000000000000909216608083015290614f6c8160a08101612b81565b51902090565b919091357fffffffff0000000000000000000000000000000000000000000000000000000081169260048110614fa6575050565b7fffffffff00000000000000000000000000000000000000000000000000000000929350829060040360031b1b161690565b909291928360041161021c57831161021c57600401916003190190565b9060041161021c5790600490565b9081602091031261021c575190565b9081604091031261021c5760206040519161502c83610543565b805183520151612806816109ea565b91615044612ca3565b50811561513a575061508561205d828061507f7fffffffff000000000000000000000000000000000000000000000000000000009587614f72565b95614fd8565b91167f181dcf100000000000000000000000000000000000000000000000000000000081036150c257508060208061270993518301019101615012565b7f97a657c90000000000000000000000000000000000000000000000000000000014615112577f5247fdce0000000000000000000000000000000000000000000000000000000060005260046000fd5b8060208061512593518301019101615003565b61512d61059e565b9081526000602082015290565b91505067ffffffffffffffff61514e61059e565b911681526000602082015290565b6020604051917f181dcf100000000000000000000000000000000000000000000000000000000082840152805160248401520151151560448201526044815261270960648261057b565b604051906151b382610527565b60606080836000815260006020820152600060408201526000838201520152565b60208183031261021c5780359067ffffffffffffffff821161021c57019060a08282031261021c576040519161520983610527565b6152128161112e565b835261522060208201610b65565b60208401526040810135615233816109ea565b60408401526060810135606084015260808101359067ffffffffffffffff821161021c57019080601f8301121561021c57813561526f816109d2565b9261527d604051948561057b565b81845260208085019260051b82010192831161021c57602001905b8282106152aa57505050608082015290565b8135815260209182019101615298565b6152c26151a6565b5081156153f5577f1f3b3aba000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000061531e6153188585614ff5565b90614f72565b16036153cb578161533a9261533292614fd8565b8101906151d4565b91806153b5575b61538b5763ffffffff615358835163ffffffff1690565b16116153615790565b7f2e2b0c290000000000000000000000000000000000000000000000000000000060005260046000fd5b7fee433e990000000000000000000000000000000000000000000000000000000060005260046000fd5b506153c661173b6040840151151590565b615341565b7f5247fdce0000000000000000000000000000000000000000000000000000000060005260046000fd5b7fb00b53dc0000000000000000000000000000000000000000000000000000000060005260046000fd5b907fffffffff0000000000000000000000000000000000000000000000000000000082167f2812d52c0000000000000000000000000000000000000000000000000000000081146154ed577f1e10bdc400000000000000000000000000000000000000000000000000000000146154e0577f2ee82075000000000000000000000000000000000000000000000000000000006000527fffffffff00000000000000000000000000000000000000000000000000000000821660045260246000fd5b61022c9150600190615717565b50905060208151036155265761550c6020825183010160208301615003565b6001600160a01b03811190811561555c575b506155265750565b613f77906040519182917f8d666f6000000000000000000000000000000000000000000000000000000000835260048301615706565b6104009150103861551e565b917fffffffff0000000000000000000000000000000000000000000000000000000083167f2812d52c000000000000000000000000000000000000000000000000000000008114615636577f1e10bdc40000000000000000000000000000000000000000000000000000000014615629577f2ee82075000000000000000000000000000000000000000000000000000000006000527fffffffff00000000000000000000000000000000000000000000000000000000831660045260246000fd5b61022c9250151590615717565b5050905060208151036155265761550c6020825183010160208301615003565b6001600160a01b036127099116600b615847565b6001600160a01b036127099116600b61597b565b9063ffffffff61569b93959495615693612ca3565b50169161503b565b918251116156bc57806156b0575b61538b5790565b506020810151156156a9565b7f4c4fc93a0000000000000000000000000000000000000000000000000000000060005260046000fd5b670de0b6b3a7640000916001600160e01b03615702921661268c565b0490565b9060206127099281815201906105bd565b90602082510361577f576157285750565b60208180518101031261021c576020810151156157425750565b613f77906040519182917fff828faa00000000000000000000000000000000000000000000000000000000835260206004840181815201906105bd565b6040517fff828faa0000000000000000000000000000000000000000000000000000000081526020600482015280613f7760248201856105bd565b80548210156127be5760005260206000200190600090565b916157ec918354906000199060031b92831b921b19161790565b9055565b8054801561581857600019019061580782826157ba565b60001982549160031b1b1916905555565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60018101918060005282602052604060002054928315156000146158f95760001984018481116126675783549360001985019485116126675760009585836158aa9761589b95036158b0575b5050506157f0565b90600052602052604060002090565b55600190565b6158e06158da916158d16158c76158f095886157ba565b90549060031b1c90565b928391876157ba565b906157d2565b8590600052602052604060002090565b55388080615893565b50505050600090565b8054906801000000000000000082101561052257816159299160016157ec940181556157ba565b81939154906000199060031b92831b921b19161790565b6000818152600360205260409020546159755761595e816002615902565b600254906000526003602052604060002055600190565b50600090565b60008281526001820160205260409020546159b2578061599d83600193615902565b80549260005201602052604060002055600190565b5050600090565b6000818152600360205260409020549081156159b257600019820190828211612667576002549260001984019384116126675783836158aa9460009603615a19575b505050615a0860026157f0565b600390600052602052604060002090565b615a086158da91615a316158c7615a3b9560026157ba565b92839160026157ba565b553880806159fb56fea164736f6c634300081a000a", } var FeeQuoterABI = FeeQuoterMetaData.ABI @@ -2875,11 +2877,11 @@ func (FeeQuoterAuthorizedCallerRemoved) Topic() common.Hash { } func (FeeQuoterDestChainAdded) Topic() common.Hash { - return common.HexToHash("0x525e3d4e0c31cef19cf9426af8d2c0ddd2d576359ca26bed92aac5fadda46265") + return common.HexToHash("0x71e9302ab4e912a9678ae7f5a8542856706806f2817e1bf2a20b171e265cb4ad") } func (FeeQuoterDestChainConfigUpdated) Topic() common.Hash { - return common.HexToHash("0x283b699f411baff8f1c29fe49f32a828c8151596244b8e7e4c164edd6569a835") + return common.HexToHash("0x2431cc0363f2f66b21782c7e3d54dd9085927981a21bd0cc6be45a51b19689e3") } func (FeeQuoterFeeTokenAdded) Topic() common.Hash { diff --git a/core/gethwrappers/ccip/generated/lock_release_token_pool/lock_release_token_pool.go b/core/gethwrappers/ccip/generated/lock_release_token_pool/lock_release_token_pool.go index fa5a6a4cdac..3e2ba32b69a 100644 --- a/core/gethwrappers/ccip/generated/lock_release_token_pool/lock_release_token_pool.go +++ b/core/gethwrappers/ccip/generated/lock_release_token_pool/lock_release_token_pool.go @@ -81,8 +81,8 @@ type TokenPoolChainUpdate struct { } var LockReleaseTokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"localTokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"acceptLiquidity\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLiquidity\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LiquidityNotAccepted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MismatchedArrayLengths\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LiquidityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LiquidityRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LiquidityTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"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\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"canAcceptLiquidity\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRebalancer\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"provideLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectors\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"outboundConfigs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"inboundConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setChainRateLimiterConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rebalancer\",\"type\":\"address\"}],\"name\":\"setRebalancer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferLiquidity\",\"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\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101206040523480156200001257600080fd5b50604051620053a2380380620053a28339810160408190526200003591620005bb565b8585858584336000816200005c57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008f576200008f81620001f3565b50506001600160a01b0385161580620000af57506001600160a01b038116155b80620000c257506001600160a01b038216155b15620000e1576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b03808616608081905290831660c0526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa92505050801562000151575060408051601f3d908101601f191682019092526200014e91810190620006ee565b60015b1562000191578060ff168560ff16146200018f576040516332ad3e0760e11b815260ff80871660048301528216602482015260440160405180910390fd5b505b60ff841660a052600480546001600160a01b0319166001600160a01b038316179055825115801560e052620001db57604080516000815260208101909152620001db90846200026d565b5050505091151561010052506200075a945050505050565b336001600160a01b038216036200021d57604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e0516200028e576040516335f4a7b360e01b815260040160405180910390fd5b60005b825181101562000319576000838281518110620002b257620002b26200070c565b60209081029190910101519050620002cc600282620003ca565b156200030f576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b5060010162000291565b5060005b8151811015620003c55760008282815181106200033e576200033e6200070c565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200036a5750620003bc565b62000377600282620003ea565b15620003ba576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b6001016200031d565b505050565b6000620003e1836001600160a01b03841662000401565b90505b92915050565b6000620003e1836001600160a01b03841662000505565b60008181526001830160205260408120548015620004fa5760006200042860018362000722565b85549091506000906200043e9060019062000722565b9050808214620004aa5760008660000182815481106200046257620004626200070c565b90600052602060002001549050808760000184815481106200048857620004886200070c565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620004be57620004be62000744565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620003e4565b6000915050620003e4565b60008181526001830160205260408120546200054e57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620003e4565b506000620003e4565b6001600160a01b03811681146200056d57600080fd5b50565b805160ff811681146200058257600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b8051620005828162000557565b805180151581146200058257600080fd5b60008060008060008060c08789031215620005d557600080fd5b8651620005e28162000557565b95506020620005f388820162000570565b60408901519096506001600160401b03808211156200061157600080fd5b818a0191508a601f8301126200062657600080fd5b8151818111156200063b576200063b62000587565b8060051b604051601f19603f8301168101818110858211171562000663576200066362000587565b60405291825284820192508381018501918d8311156200068257600080fd5b938501935b82851015620006ab576200069b856200059d565b8452938501939285019262000687565b809950505050505050620006c2606088016200059d565b9250620006d260808801620005aa565b9150620006e260a088016200059d565b90509295509295509295565b6000602082840312156200070157600080fd5b620003e18262000570565b634e487b7160e01b600052603260045260246000fd5b81810381811115620003e457634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c05160e05161010051614b776200082b600039600081816105d20152611c4e01526000818161066c015281816124a0015261315b01526000818161064601528181611fbd015261287601526000818161038201528181610ff301528181612166015281816122200152818161225401528181612287015281816122ec0152818161234501526123e70152600081816102e90152818161033e015281816107ad0152818161087f0152818161097301528181611d1001528181612f4f01526133460152614b776000f3fe608060405234801561001057600080fd5b506004361061025c5760003560e01c8063962d402011610145578063c0d78655116100bd578063dc0bd9711161008c578063e8a1da1711610071578063e8a1da1714610690578063eb521a4c146106a3578063f2fde38b146106b657600080fd5b8063dc0bd97114610644578063e0351e131461066a57600080fd5b8063c0d78655146105f6578063c4bffe2b14610609578063c75eea9c1461061e578063cf7401f31461063157600080fd5b8063acfecf9111610114578063b0f479a1116100f9578063b0f479a11461059f578063b7946580146105bd578063bb98546b146105d057600080fd5b8063acfecf911461051d578063af58d59f1461053057600080fd5b8063962d4020146104b55780639a4575b9146104c8578063a42a7b8b146104e8578063a7cd63b71461050857600080fd5b806354c8a4f3116101d85780636d3d1a58116101a75780637d54534e1161018c5780637d54534e146104715780638926f54f146104845780638da5cb5b1461049757600080fd5b80636d3d1a581461044b57806379ba50971461046957600080fd5b806354c8a4f3146103ff57806362ddd3c41461041257806366320087146104255780636cfd15531461043857600080fd5b8063240028e81161022f578063390775371161021457806339077537146103ac578063432a6ba3146103ce5780634c5ef0ed146103ec57600080fd5b8063240028e81461032e57806324f65ee71461037b57600080fd5b806301ffc9a7146102615780630a861f2a14610289578063181f5a771461029e57806321df0da7146102e7575b600080fd5b61027461026f366004613b6b565b6106c9565b60405190151581526020015b60405180910390f35b61029c610297366004613bad565b610725565b005b6102da6040518060400160405280601a81526020017f4c6f636b52656c65617365546f6b656e506f6f6c20312e352e3100000000000081525081565b6040516102809190613c34565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610280565b61027461033c366004613c69565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610280565b6103bf6103ba366004613c86565b6108d6565b60405190518152602001610280565b600a5473ffffffffffffffffffffffffffffffffffffffff16610309565b6102746103fa366004613cdf565b610a24565b61029c61040d366004613dae565b610a6e565b61029c610420366004613cdf565b610ae9565b61029c610433366004613e1a565b610b81565b61029c610446366004613c69565b610c5d565b60095473ffffffffffffffffffffffffffffffffffffffff16610309565b61029c610cac565b61029c61047f366004613c69565b610d7a565b610274610492366004613e46565b610dfb565b60015473ffffffffffffffffffffffffffffffffffffffff16610309565b61029c6104c3366004613ea6565b610e12565b6104db6104d6366004613f40565b610f6c565b6040516102809190613f7b565b6104fb6104f6366004613e46565b611038565b6040516102809190613fd2565b6105106111a3565b6040516102809190614054565b61029c61052b366004613cdf565b6111b4565b61054361053e366004613e46565b6112cc565b604051610280919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610309565b6102da6105cb366004613e46565b6113a1565b7f0000000000000000000000000000000000000000000000000000000000000000610274565b61029c610604366004613c69565b611451565b61061161152c565b60405161028091906140ae565b61054361062c366004613e46565b6115e4565b61029c61063f366004614236565b6116b6565b7f0000000000000000000000000000000000000000000000000000000000000000610309565b7f0000000000000000000000000000000000000000000000000000000000000000610274565b61029c61069e366004613dae565b61173a565b61029c6106b1366004613bad565b611c4c565b61029c6106c4366004613c69565b611d68565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fe1d4056600000000000000000000000000000000000000000000000000000000148061071f575061071f82611d7c565b92915050565b600a5473ffffffffffffffffffffffffffffffffffffffff16331461077d576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015281907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015610809573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061082d919061427b565b1015610865576040517fbb55fd2700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108a673ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163383611e60565b604051819033907fc2c3f06e49b9f15e7b4af9055e183b0d73362e033ad82a07dec9bf984017171990600090a350565b6040805160208101909152600081526108ee82611f34565b6000610947606084013561094261090860c0870187614294565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061215892505050565b61221c565b905061099a61095c6060850160408601613c69565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169083611e60565b6109aa6060840160408501613c69565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f5283604051610a0891815260200190565b60405180910390a3604080516020810190915290815292915050565b6000610a668383604051610a399291906142f9565b604080519182900390912067ffffffffffffffff8716600090815260076020529190912060050190612430565b949350505050565b610a7661244b565b610ae38484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060408051602080880282810182019093528782529093508792508691829185019084908082843760009201919091525061249e92505050565b50505050565b610af161244b565b610afa83610dfb565b610b3c576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610774565b610b7c8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061265492505050565b505050565b610b8961244b565b6040517f0a861f2a0000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff831690630a861f2a90602401600060405180830381600087803b158015610bf157600080fd5b505af1158015610c05573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff167f6fa7abcf1345d1d478e5ea0da6b5f26a90eadb0546ef15ed3833944fbfd1db6282604051610c5191815260200190565b60405180910390a25050565b610c6561244b565b600a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60005473ffffffffffffffffffffffffffffffffffffffff163314610cfd576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610d8261244b565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b600061071f600567ffffffffffffffff8416612430565b60095473ffffffffffffffffffffffffffffffffffffffff163314801590610e52575060015473ffffffffffffffffffffffffffffffffffffffff163314155b15610e8b576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610774565b8483141580610e9a5750848114155b15610ed1576040517f568efce200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b85811015610f6357610f5b878783818110610ef157610ef1614309565b9050602002016020810190610f069190613e46565b868684818110610f1857610f18614309565b905060600201803603810190610f2e9190614338565b858585818110610f4057610f40614309565b905060600201803603810190610f569190614338565b61274e565b600101610ed4565b50505050505050565b6040805180820190915260608082526020820152610f8982612838565b6040516060830135815233907f9f1ec8c880f76798e7b793325d625e9b60e4082a553c98f42b6cda368dd600089060200160405180910390a26040518060400160405280610fe38460200160208101906105cb9190613e46565b81526020016110306040805160ff7f000000000000000000000000000000000000000000000000000000000000000016602082015260609101604051602081830303815290604052905090565b905292915050565b67ffffffffffffffff8116600090815260076020526040812060609190611061906005016129c4565b90506000815167ffffffffffffffff81111561107f5761107f6140f0565b6040519080825280602002602001820160405280156110b257816020015b606081526020019060019003908161109d5790505b50905060005b825181101561119b57600860008483815181106110d7576110d7614309565b6020026020010151815260200190815260200160002080546110f890614354565b80601f016020809104026020016040519081016040528092919081815260200182805461112490614354565b80156111715780601f1061114657610100808354040283529160200191611171565b820191906000526020600020905b81548152906001019060200180831161115457829003601f168201915b505050505082828151811061118857611188614309565b60209081029190910101526001016110b8565b509392505050565b60606111af60026129c4565b905090565b6111bc61244b565b6111c583610dfb565b611207576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610774565b611247828260405161121a9291906142f9565b604080519182900390912067ffffffffffffffff86166000908152600760205291909120600501906129d1565b611283578282826040517f74f23c7c000000000000000000000000000000000000000000000000000000008152600401610774939291906143f0565b8267ffffffffffffffff167f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d7683836040516112bf929190614414565b60405180910390a2505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600390910154808416606083015291909104909116608082015261071f906129dd565b67ffffffffffffffff811660009081526007602052604090206004018054606091906113cc90614354565b80601f01602080910402602001604051908101604052809291908181526020018280546113f890614354565b80156114455780601f1061141a57610100808354040283529160200191611445565b820191906000526020600020905b81548152906001019060200180831161142857829003601f168201915b50505050509050919050565b61145961244b565b73ffffffffffffffffffffffffffffffffffffffff81166114a6576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b6060600061153a60056129c4565b90506000815167ffffffffffffffff811115611558576115586140f0565b604051908082528060200260200182016040528015611581578160200160208202803683370190505b50905060005b82518110156115dd578281815181106115a2576115a2614309565b60200260200101518282815181106115bc576115bc614309565b67ffffffffffffffff90921660209283029190910190910152600101611587565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600190910154808416606083015291909104909116608082015261071f906129dd565b60095473ffffffffffffffffffffffffffffffffffffffff1633148015906116f6575060015473ffffffffffffffffffffffffffffffffffffffff163314155b1561172f576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610774565b610b7c83838361274e565b61174261244b565b60005b8381101561192f57600085858381811061176157611761614309565b90506020020160208101906117769190613e46565b905061178d600567ffffffffffffffff83166129d1565b6117cf576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610774565b67ffffffffffffffff811660009081526007602052604081206117f4906005016129c4565b905060005b81518110156118605761185782828151811061181757611817614309565b6020026020010151600760008667ffffffffffffffff1667ffffffffffffffff1681526020019081526020016000206005016129d190919063ffffffff16565b506001016117f9565b5067ffffffffffffffff8216600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906118c96004830182613afe565b60058201600081816118db8282613b38565b505060405167ffffffffffffffff871681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169450602001925061191d915050565b60405180910390a15050600101611745565b5060005b81811015611c4557600083838381811061194f5761194f614309565b90506020028101906119619190614428565b61196a906144f4565b905061197b81606001516000612a8f565b61198a81608001516000612a8f565b8060400151516000036119c9576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516119e19060059067ffffffffffffffff16612bcc565b611a265780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610774565b805167ffffffffffffffff16600090815260076020908152604091829020825160a08082018552606080870180518601516fffffffffffffffffffffffffffffffff90811680865263ffffffff42168689018190528351511515878b0181905284518a0151841686890181905294518b0151841660809889018190528954740100000000000000000000000000000000000000009283027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7001000000000000000000000000000000008087027fffffffffffffffffffffffff000000000000000000000000000000000000000094851690981788178216929092178d5592810290971760018c01558c519889018d52898e0180518d01518716808b528a8e019590955280515115158a8f018190528151909d01518716988a01899052518d0151909516979098018790526002890180549a909102999093161717909416959095179092559092029091176003820155908201516004820190611ba9908261466b565b5060005b826020015151811015611bed57611be5836000015184602001518381518110611bd857611bd8614309565b6020026020010151612654565b600101611bad565b507f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c28260000151836040015184606001518560800151604051611c339493929190614785565b60405180910390a15050600101611933565b5050505050565b7f0000000000000000000000000000000000000000000000000000000000000000611ca3576040517fe93f8fa400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600a5473ffffffffffffffffffffffffffffffffffffffff163314611cf6576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610774565b611d3873ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333084612bd8565b604051819033907fc17cea59c2955cb181b03393209566960365771dbba9dc3d510180e7cb31208890600090a350565b611d7061244b565b611d7981612c36565b50565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf000000000000000000000000000000000000000000000000000000001480611e0f57507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061071f57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a7000000000000000000000000000000000000000000000000000000001492915050565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610b7c9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612cfa565b611f4761033c60a0830160808401613c69565b611fa657611f5b60a0820160808301613c69565b6040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610774565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb611ff26040840160208501613e46565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015612063573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612087919061481e565b156120be576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120d66120d16040830160208401613e46565b612e06565b6120f66120e96040830160208401613e46565b6103fa60a0840184614294565b61213b5761210760a0820182614294565b6040517f24eb47e5000000000000000000000000000000000000000000000000000000008152600401610774929190614414565b611d7961214e6040830160208401613e46565b8260600135612f2c565b6000815160000361218a57507f0000000000000000000000000000000000000000000000000000000000000000919050565b81516020146121c757816040517f953576f70000000000000000000000000000000000000000000000000000000081526004016107749190613c34565b6000828060200190518101906121dd919061427b565b905060ff81111561071f57826040517f953576f70000000000000000000000000000000000000000000000000000000081526004016107749190613c34565b60007f000000000000000000000000000000000000000000000000000000000000000060ff168260ff160361225257508161071f565b7f000000000000000000000000000000000000000000000000000000000000000060ff168260ff16111561233d5760006122ac7f00000000000000000000000000000000000000000000000000000000000000008461486a565b9050604d8160ff161115612320576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f000000000000000000000000000000000000000000000000000000000000000016602482015260448101859052606401610774565b61232b81600a6149a3565b61233590856149b2565b91505061071f565b6000612369837f000000000000000000000000000000000000000000000000000000000000000061486a565b9050604d8160ff1611806123b0575061238381600a6149a3565b6123ad907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6149b2565b84115b1561241b576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f000000000000000000000000000000000000000000000000000000000000000016602482015260448101859052606401610774565b61242681600a6149a3565b610a6690856149ed565b600081815260018301602052604081205415155b9392505050565b60015473ffffffffffffffffffffffffffffffffffffffff16331461249c576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b7f00000000000000000000000000000000000000000000000000000000000000006124f5576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b825181101561258b57600083828151811061251557612515614309565b60200260200101519050612533816002612f7390919063ffffffff16565b156125825760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b506001016124f8565b5060005b8151811015610b7c5760008282815181106125ac576125ac614309565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036125f0575061264c565b6125fb600282612f95565b1561264a5760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010161258f565b805160000361268f576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160208083019190912067ffffffffffffffff84166000908152600790925260409091206126c19060050182612bcc565b6126fb5782826040517f393b8ad2000000000000000000000000000000000000000000000000000000008152600401610774929190614a04565b6000818152600860205260409020612713838261466b565b508267ffffffffffffffff167f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea836040516112bf9190613c34565b61275783610dfb565b612799576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610774565b6127a4826000612a8f565b67ffffffffffffffff831660009081526007602052604090206127c79083612fb7565b6127d2816000612a8f565b67ffffffffffffffff831660009081526007602052604090206127f89060020182612fb7565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b83838360405161282b93929190614a27565b60405180910390a1505050565b61284b61033c60a0830160808401613c69565b61285f57611f5b60a0820160808301613c69565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb6128ab6040840160208501613e46565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa15801561291c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612940919061481e565b15612977576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61298f61298a6060830160408401613c69565b613159565b6129a76129a26040830160208401613e46565b6131d8565b611d796129ba6040830160208401613e46565b8260600135613326565b606060006124448361336a565b600061244483836133c5565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152612a6b82606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff1642612a4f9190614aaa565b85608001516fffffffffffffffffffffffffffffffff166134b8565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b815115612b5a5781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580612ae5575060408201516fffffffffffffffffffffffffffffffff16155b15612b1e57816040517f8020d1240000000000000000000000000000000000000000000000000000000081526004016107749190614abd565b8015612b56576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60408201516fffffffffffffffffffffffffffffffff16151580612b93575060208201516fffffffffffffffffffffffffffffffff1615155b15612b5657816040517fd68af9cc0000000000000000000000000000000000000000000000000000000081526004016107749190614abd565b600061244483836134e0565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052610ae39085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611eb2565b3373ffffffffffffffffffffffffffffffffffffffff821603612c85576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000612d5c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661352f9092919063ffffffff16565b805190915015610b7c5780806020019051810190612d7a919061481e565b610b7c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610774565b612e0f81610dfb565b612e51576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610774565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa158015612ed0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ef4919061481e565b611d79576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610774565b67ffffffffffffffff82166000908152600760205260409020612b5690600201827f000000000000000000000000000000000000000000000000000000000000000061353e565b60006124448373ffffffffffffffffffffffffffffffffffffffff84166133c5565b60006124448373ffffffffffffffffffffffffffffffffffffffff84166134e0565b8154600090612fe090700100000000000000000000000000000000900463ffffffff1642614aaa565b905080156130825760018301548354613028916fffffffffffffffffffffffffffffffff808216928116918591700100000000000000000000000000000000909104166134b8565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b602082015183546130a8916fffffffffffffffffffffffffffffffff90811691166138c1565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c199061282b908490614abd565b7f000000000000000000000000000000000000000000000000000000000000000015611d795761318a6002826138d7565b611d79576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610774565b6131e181610dfb565b613223576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610774565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa15801561329c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132c09190614af9565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611d79576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610774565b67ffffffffffffffff82166000908152600760205260409020612b5690827f000000000000000000000000000000000000000000000000000000000000000061353e565b60608160000180548060200260200160405190810160405280929190818152602001828054801561144557602002820191906000526020600020905b8154815260200190600101908083116133a65750505050509050919050565b600081815260018301602052604081205480156134ae5760006133e9600183614aaa565b85549091506000906133fd90600190614aaa565b905080821461346257600086600001828154811061341d5761341d614309565b906000526020600020015490508087600001848154811061344057613440614309565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061347357613473614b16565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061071f565b600091505061071f565b60006134d7856134c884866149ed565b6134d29087614b45565b6138c1565b95945050505050565b60008181526001830160205260408120546135275750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561071f565b50600061071f565b6060610a668484600085613906565b825474010000000000000000000000000000000000000000900460ff161580613565575081155b1561356f57505050565b825460018401546fffffffffffffffffffffffffffffffff808316929116906000906135b590700100000000000000000000000000000000900463ffffffff1642614aaa565b9050801561367557818311156135f7576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546136319083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff166134b8565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b8482101561372c5773ffffffffffffffffffffffffffffffffffffffff84166136d4576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610774565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610774565b8483101561383f5760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906137709082614aaa565b61377a878a614aaa565b6137849190614b45565b61378e91906149b2565b905073ffffffffffffffffffffffffffffffffffffffff86166137e7576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610774565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610774565b6138498584614aaa565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b60008183106138d05781612444565b5090919050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515612444565b606082471015613998576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610774565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516139c19190614b58565b60006040518083038185875af1925050503d80600081146139fe576040519150601f19603f3d011682016040523d82523d6000602084013e613a03565b606091505b5091509150613a1487838387613a1f565b979650505050505050565b60608315613ab5578251600003613aae5773ffffffffffffffffffffffffffffffffffffffff85163b613aae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610774565b5081610a66565b610a668383815115613aca5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107749190613c34565b508054613b0a90614354565b6000825580601f10613b1a575050565b601f016020900490600052602060002090810190611d799190613b52565b5080546000825590600052602060002090810190611d7991905b5b80821115613b675760008155600101613b53565b5090565b600060208284031215613b7d57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461244457600080fd5b600060208284031215613bbf57600080fd5b5035919050565b60005b83811015613be1578181015183820152602001613bc9565b50506000910152565b60008151808452613c02816020860160208601613bc6565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006124446020830184613bea565b73ffffffffffffffffffffffffffffffffffffffff81168114611d7957600080fd5b600060208284031215613c7b57600080fd5b813561244481613c47565b600060208284031215613c9857600080fd5b813567ffffffffffffffff811115613caf57600080fd5b8201610100818503121561244457600080fd5b803567ffffffffffffffff81168114613cda57600080fd5b919050565b600080600060408486031215613cf457600080fd5b613cfd84613cc2565b9250602084013567ffffffffffffffff80821115613d1a57600080fd5b818601915086601f830112613d2e57600080fd5b813581811115613d3d57600080fd5b876020828501011115613d4f57600080fd5b6020830194508093505050509250925092565b60008083601f840112613d7457600080fd5b50813567ffffffffffffffff811115613d8c57600080fd5b6020830191508360208260051b8501011115613da757600080fd5b9250929050565b60008060008060408587031215613dc457600080fd5b843567ffffffffffffffff80821115613ddc57600080fd5b613de888838901613d62565b90965094506020870135915080821115613e0157600080fd5b50613e0e87828801613d62565b95989497509550505050565b60008060408385031215613e2d57600080fd5b8235613e3881613c47565b946020939093013593505050565b600060208284031215613e5857600080fd5b61244482613cc2565b60008083601f840112613e7357600080fd5b50813567ffffffffffffffff811115613e8b57600080fd5b602083019150836020606083028501011115613da757600080fd5b60008060008060008060608789031215613ebf57600080fd5b863567ffffffffffffffff80821115613ed757600080fd5b613ee38a838b01613d62565b90985096506020890135915080821115613efc57600080fd5b613f088a838b01613e61565b90965094506040890135915080821115613f2157600080fd5b50613f2e89828a01613e61565b979a9699509497509295939492505050565b600060208284031215613f5257600080fd5b813567ffffffffffffffff811115613f6957600080fd5b820160a0818503121561244457600080fd5b602081526000825160406020840152613f976060840182613bea565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160408501526134d78282613bea565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015614047577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452614035858351613bea565b94509285019290850190600101613ffb565b5092979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156140a257835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101614070565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b818110156140a257835167ffffffffffffffff16835292840192918401916001016140ca565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715614142576141426140f0565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561418f5761418f6140f0565b604052919050565b8015158114611d7957600080fd5b80356fffffffffffffffffffffffffffffffff81168114613cda57600080fd5b6000606082840312156141d757600080fd5b6040516060810181811067ffffffffffffffff821117156141fa576141fa6140f0565b604052905080823561420b81614197565b8152614219602084016141a5565b602082015261422a604084016141a5565b60408201525092915050565b600080600060e0848603121561424b57600080fd5b61425484613cc2565b925061426385602086016141c5565b915061427285608086016141c5565b90509250925092565b60006020828403121561428d57600080fd5b5051919050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126142c957600080fd5b83018035915067ffffffffffffffff8211156142e457600080fd5b602001915036819003821315613da757600080fd5b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006060828403121561434a57600080fd5b61244483836141c5565b600181811c9082168061436857607f821691505b6020821081036143a1577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b67ffffffffffffffff841681526040602082015260006134d76040830184866143a7565b602081526000610a666020830184866143a7565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee183360301811261445c57600080fd5b9190910192915050565b600082601f83011261447757600080fd5b813567ffffffffffffffff811115614491576144916140f0565b6144c260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614148565b8181528460208386010111156144d757600080fd5b816020850160208301376000918101602001919091529392505050565b6000610120823603121561450757600080fd5b61450f61411f565b61451883613cc2565b815260208084013567ffffffffffffffff8082111561453657600080fd5b9085019036601f83011261454957600080fd5b81358181111561455b5761455b6140f0565b8060051b61456a858201614148565b918252838101850191858101903684111561458457600080fd5b86860192505b838310156145c0578235858111156145a25760008081fd5b6145b03689838a0101614466565b835250918601919086019061458a565b80878901525050505060408601359250808311156145dd57600080fd5b50506145eb36828601614466565b6040830152506145fe36606085016141c5565b60608201526146103660c085016141c5565b608082015292915050565b601f821115610b7c576000816000526020600020601f850160051c810160208610156146445750805b601f850160051c820191505b8181101561466357828155600101614650565b505050505050565b815167ffffffffffffffff811115614685576146856140f0565b614699816146938454614354565b8461461b565b602080601f8311600181146146ec57600084156146b65750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555614663565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156147395788860151825594840194600190910190840161471a565b508582101561477557878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff871683528060208401526147a981840187613bea565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff90811660608701529087015116608085015291506147e79050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e08301526134d7565b60006020828403121561483057600080fd5b815161244481614197565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff828116828216039081111561071f5761071f61483b565b600181815b808511156148dc57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156148c2576148c261483b565b808516156148cf57918102915b93841c9390800290614888565b509250929050565b6000826148f35750600161071f565b816149005750600061071f565b816001811461491657600281146149205761493c565b600191505061071f565b60ff8411156149315761493161483b565b50506001821b61071f565b5060208310610133831016604e8410600b841016171561495f575081810a61071f565b6149698383614883565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561499b5761499b61483b565b029392505050565b600061244460ff8416836148e4565b6000826149e8577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808202811582820484141761071f5761071f61483b565b67ffffffffffffffff83168152604060208201526000610a666040830184613bea565b67ffffffffffffffff8416815260e08101614a7360208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c0830152610a66565b8181038181111561071f5761071f61483b565b6060810161071f82848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b600060208284031215614b0b57600080fd5b815161244481613c47565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8082018082111561071f5761071f61483b565b6000825161445c818460208701613bc656fea164736f6c6343000818000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"contractIERC20\"},{\"name\":\"localTokenDecimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"allowlist\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"rmnProxy\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"acceptLiquidity\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"router\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"acceptOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"addRemotePool\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyAllowListUpdates\",\"inputs\":[{\"name\":\"removes\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"adds\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyChainUpdates\",\"inputs\":[{\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"},{\"name\":\"chainsToAdd\",\"type\":\"tuple[]\",\"internalType\":\"structTokenPool.ChainUpdate[]\",\"components\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"},{\"name\":\"remoteTokenAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"canAcceptLiquidity\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getAllowList\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getAllowListEnabled\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCurrentInboundRateLimiterState\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.TokenBucket\",\"components\":[{\"name\":\"tokens\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"lastUpdated\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCurrentOutboundRateLimiterState\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.TokenBucket\",\"components\":[{\"name\":\"tokens\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"lastUpdated\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRateLimitAdmin\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRebalancer\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRemotePools\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRemoteToken\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRmnProxy\",\"inputs\":[],\"outputs\":[{\"name\":\"rmnProxy\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRouter\",\"inputs\":[],\"outputs\":[{\"name\":\"router\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getSupportedChains\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getToken\",\"inputs\":[],\"outputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"contractIERC20\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTokenDecimals\",\"inputs\":[],\"outputs\":[{\"name\":\"decimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isRemotePool\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isSupportedChain\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isSupportedToken\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"lockOrBurn\",\"inputs\":[{\"name\":\"lockOrBurnIn\",\"type\":\"tuple\",\"internalType\":\"structPool.LockOrBurnInV1\",\"components\":[{\"name\":\"receiver\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"originalSender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"localToken\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structPool.LockOrBurnOutV1\",\"components\":[{\"name\":\"destTokenAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"destPoolData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"provideLiquidity\",\"inputs\":[{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"releaseOrMint\",\"inputs\":[{\"name\":\"releaseOrMintIn\",\"type\":\"tuple\",\"internalType\":\"structPool.ReleaseOrMintInV1\",\"components\":[{\"name\":\"originalSender\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"receiver\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"localToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"sourcePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"sourcePoolData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"offchainTokenData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"components\":[{\"name\":\"destinationAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"removeRemotePool\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setChainRateLimiterConfig\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"outboundConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setChainRateLimiterConfigs\",\"inputs\":[{\"name\":\"remoteChainSelectors\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"},{\"name\":\"outboundConfigs\",\"type\":\"tuple[]\",\"internalType\":\"structRateLimiter.Config[]\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundConfigs\",\"type\":\"tuple[]\",\"internalType\":\"structRateLimiter.Config[]\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setRateLimitAdmin\",\"inputs\":[{\"name\":\"rateLimitAdmin\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setRebalancer\",\"inputs\":[{\"name\":\"rebalancer\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setRouter\",\"inputs\":[{\"name\":\"newRouter\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"transferLiquidity\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"typeAndVersion\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"withdrawLiquidity\",\"inputs\":[{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"AllowListAdd\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"AllowListRemove\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Burned\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChainAdded\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"remoteToken\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"},{\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChainConfigured\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChainRemoved\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ConfigChanged\",\"inputs\":[{\"name\":\"config\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"LiquidityAdded\",\"inputs\":[{\"name\":\"provider\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"LiquidityRemoved\",\"inputs\":[{\"name\":\"provider\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"LiquidityTransferred\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Locked\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Minted\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferRequested\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RateLimitAdminSet\",\"inputs\":[{\"name\":\"rateLimitAdmin\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Released\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RemotePoolAdded\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RemotePoolRemoved\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RouterUpdated\",\"inputs\":[{\"name\":\"oldRouter\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"newRouter\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TokensConsumed\",\"inputs\":[{\"name\":\"tokens\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AggregateValueMaxCapacityExceeded\",\"inputs\":[{\"name\":\"capacity\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"requested\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"AggregateValueRateLimitReached\",\"inputs\":[{\"name\":\"minWaitInSeconds\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"available\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"AllowListNotEnabled\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BucketOverfilled\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CallerIsNotARampOnRouter\",\"inputs\":[{\"name\":\"caller\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"CannotTransferToSelf\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ChainAlreadyExists\",\"inputs\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"ChainNotAllowed\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"CursedByRMN\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"DisabledNonZeroRateLimit\",\"inputs\":[{\"name\":\"config\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}]},{\"type\":\"error\",\"name\":\"InsufficientLiquidity\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidDecimalArgs\",\"inputs\":[{\"name\":\"expected\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"actual\",\"type\":\"uint8\",\"internalType\":\"uint8\"}]},{\"type\":\"error\",\"name\":\"InvalidRateLimitRate\",\"inputs\":[{\"name\":\"rateLimiterConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}]},{\"type\":\"error\",\"name\":\"InvalidRemoteChainDecimals\",\"inputs\":[{\"name\":\"sourcePoolData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidRemotePoolForChain\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidSourcePoolAddress\",\"inputs\":[{\"name\":\"sourcePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidToken\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"LiquidityNotAccepted\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MismatchedArrayLengths\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MustBeProposedOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NonExistentChain\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"OnlyCallableByOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OverflowDetected\",\"inputs\":[{\"name\":\"remoteDecimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"localDecimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"remoteAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"OwnerCannotBeZero\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PoolAlreadyAdded\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"RateLimitMustBeDisabled\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"SenderNotAllowed\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"TokenMaxCapacityExceeded\",\"inputs\":[{\"name\":\"capacity\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"requested\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"tokenAddress\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"TokenRateLimitReached\",\"inputs\":[{\"name\":\"minWaitInSeconds\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"available\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"tokenAddress\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"Unauthorized\",\"inputs\":[{\"name\":\"caller\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ZeroAddressNotAllowed\",\"inputs\":[]}]", + Bin: "0x61012080604052346103945761504f803803809161001d8285610413565b8339810160c0828203126103945781516001600160a01b038116908181036103945761004b60208501610436565b60408501519091906001600160401b0381116103945785019380601f86011215610394578451946001600160401b0386116103fd578560051b9060208201966100976040519889610413565b875260208088019282010192831161039457602001905b8282106103e5575050506100c460608601610444565b9060808601519586151587036103945760a06100e09101610444565b9333156103d457600180546001600160a01b03191633179055801580156103c3575b80156103b2575b6103a15760049260209260805260c0526040519283809263313ce56760e01b82525afa60009181610360575b50610335575b5060a052600480546001600160a01b0319166001600160a01b03929092169190911790558051151560e0819052610218575b5061010052604051614a5690816105f9823960805181818161036301528181611800015281816119f70152818161258301528181612766015281816129e801528181612a600152612b57015260a051818181611a580152818161296f0152818161364f01526136d2015260c051818181610d7e0152818161189c015261261e015260e051818181610d0e015281816118df01526123270152610100518181816102d101526112ae0152f35b60206040516102278282610413565b60008152600036813760e051156103245760005b81518110156102a2576001906001600160a01b036102598285610458565b5116846102658261049a565b610272575b50500161023b565b7f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf756691604051908152a1388461026a565b505060005b825181101561031b576001906001600160a01b036102c58286610458565b5116801561031557836102d782610598565b6102e5575b50505b016102a7565b7f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d891604051908152a138836102dc565b506102df565b5050503861016d565b6335f4a7b360e01b60005260046000fd5b60ff1660ff8216818103610349575061013b565b6332ad3e0760e11b60005260045260245260446000fd5b9091506020813d602011610399575b8161037c60209383610413565b810103126103945761038d90610436565b9038610135565b600080fd5b3d915061036f565b6342bcdf7f60e11b60005260046000fd5b506001600160a01b03831615610109565b506001600160a01b03851615610102565b639b15e16f60e01b60005260046000fd5b602080916103f284610444565b8152019101906100ae565b634e487b7160e01b600052604160045260246000fd5b601f909101601f19168101906001600160401b038211908210176103fd57604052565b519060ff8216820361039457565b51906001600160a01b038216820361039457565b805182101561046c5760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b805482101561046c5760005260206000200190600090565b600081815260036020526040902054801561059157600019810181811161057b5760025460001981019190821161057b5781810361052a575b505050600254801561051457600019016104ee816002610482565b8154906000199060031b1b19169055600255600052600360205260006040812055600190565b634e487b7160e01b600052603160045260246000fd5b61056361053b61054c936002610482565b90549060031b1c9283926002610482565b819391549060031b91821b91600019901b19161790565b905560005260036020526040600020553880806104d3565b634e487b7160e01b600052601160045260246000fd5b5050600090565b806000526003602052604060002054156000146105f257600254680100000000000000008110156103fd576105d961054c8260018594016002556002610482565b9055600254906000526003602052604060002055600190565b5060009056fe608080604052600436101561001357600080fd5b600090813560e01c90816301ffc9a714612c67575080630a861f2a14612b03578063181f5a7714612a8457806321df0da714612a15578063240028e81461299357806324f65ee71461293757806339077537146124dc578063432a6ba31461248a5780634c5ef0ed1461247057806354c8a4f3146122f357806362ddd3c41461226f57806366320087146121675780636cfd1553146120e55780636d3d1a581461209357806379ba509714611fae5780637d54534e14611f015780638926f54f14611e9d5780638da5cb5b14611e4b578063962d402014611ca75780639a4575b914611758578063a42a7b8b146115d3578063a7cd63b714611507578063acfecf91146113e3578063af58d59f1461137c578063b0f479a11461132a578063b7946580146112d3578063bb98546b14611278578063c0d7865514611180578063c4bffe2b14611037578063c75eea9c14610f71578063cf7401f314610da2578063dc0bd97114610d33578063e0351e1314610cd8578063e8a1da1714610403578063eb521a4c1461029c5763f2fde38b146101ad57600080fd5b346102995760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102995773ffffffffffffffffffffffffffffffffffffffff6101f9612f02565b6102016137dc565b1633811461027157807fffffffffffffffffffffffff000000000000000000000000000000000000000083541617825573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12788380a380f35b6004827fdad89dca000000000000000000000000000000000000000000000000000000008152fd5b80fd5b50346102995760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610299576004357f0000000000000000000000000000000000000000000000000000000000000000156103db5773ffffffffffffffffffffffffffffffffffffffff600a541633036103af576103876040517f23b872dd00000000000000000000000000000000000000000000000000000000602082015233602482015230604482015282606482015260648152610361608482612e28565b7f0000000000000000000000000000000000000000000000000000000000000000613dae565b337fc17cea59c2955cb181b03393209566960365771dbba9dc3d510180e7cb3120888380a380f35b6024827f8e4a23d600000000000000000000000000000000000000000000000000000000815233600452fd5b6004827fe93f8fa4000000000000000000000000000000000000000000000000000000008152fd5b50346102995761041236612ff0565b9391909261041e6137dc565b82915b808310610b43575050508063ffffffff4216917ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee1843603015b85821015610b3f578160051b85013581811215610b3b5785019061012082360312610b3b576040519561048c87612df0565b823567ffffffffffffffff81168103610b36578752602083013567ffffffffffffffff8111610b325783019536601f88011215610b32578635966104cf886131ee565b976104dd604051998a612e28565b8089526020808a019160051b83010190368211610b2e5760208301905b828210610afb575050505060208801968752604084013567ffffffffffffffff8111610af75761052d9036908601613546565b9860408901998a5261055761054536606088016130ae565b9560608b0196875260c03691016130ae565b9660808a019788526105698651613c53565b6105738851613c53565b8a515115610acf5761058f67ffffffffffffffff8b51166145e6565b15610a985767ffffffffffffffff8a511681526007602052604081206106cf87516fffffffffffffffffffffffffffffffff6040820151169061068a6fffffffffffffffffffffffffffffffff602083015116915115158360806040516105f581612df0565b858152602081018c905260408101849052606081018690520152855474ff000000000000000000000000000000000000000091151560a01b919091167fffffffffffffffffffffff0000000000000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff84161773ffffffff0000000000000000000000000000000060808b901b1617178555565b60809190911b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff91909116176001830155565b6107f589516fffffffffffffffffffffffffffffffff604082015116906107b06fffffffffffffffffffffffffffffffff6020830151169151151583608060405161071981612df0565b858152602081018c9052604081018490526060810186905201526002860180547fffffffffffffffffffffff000000000000000000000000000000000000000000166fffffffffffffffffffffffffffffffff85161773ffffffff0000000000000000000000000000000060808c901b161791151560a01b74ff000000000000000000000000000000000000000016919091179055565b60809190911b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff91909116176003830155565b60048c5191019080519067ffffffffffffffff8211610a6b5761081883546132e6565b601f8111610a30575b50602090601f83116001146109915761086f9291859183610986575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b90555b805b895180518210156108aa57906108a460019261089d838f67ffffffffffffffff905116926132d2565b5190613827565b01610874565b5050975097987f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c29295939661097867ffffffffffffffff600197949c511692519351915161094461090f60405196879687526101006020880152610100870190612ea3565b9360408601906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b60a08401906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b0390a101909394929161045a565b01519050388061083d565b83855281852091907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08416865b818110610a1857509084600195949392106109e1575b505050811b019055610872565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690553880806109d4565b929360206001819287860151815501950193016109be565b610a5b9084865260208620601f850160051c81019160208610610a61575b601f0160051c01906134ed565b38610821565b9091508190610a4e565b6024847f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b60249067ffffffffffffffff8b51167f1d5ad3c5000000000000000000000000000000000000000000000000000000008252600452fd5b807f8579befe0000000000000000000000000000000000000000000000000000000060049252fd5b8680fd5b813567ffffffffffffffff8111610b2a57602091610b1f8392833691890101613546565b8152019101906104fa565b8a80fd5b8880fd5b8580fd5b600080fd5b8380fd5b8280f35b9092919367ffffffffffffffff610b63610b5e87858861326e565b6132ad565b1695610b6e8761431a565b15610cac578684526007602052610b8a60056040862001614121565b94845b8651811015610bc3576001908987526007602052610bbc60056040892001610bb5838b6132d2565b5190614445565b5001610b8d565b5093945094909580855260076020526005604086208681558660018201558660028201558660038201558660048201610bfc81546132e6565b80610c6b575b5050500180549086815581610c4d575b5050907f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599166020600193604051908152a1019190949394610421565b865260208620908101905b81811015610c1257868155600101610c58565b601f8111600114610c815750555b863880610c02565b81835260208320610c9c91601f01861c8101906001016134ed565b8082528160208120915555610c79565b602484887f1e670e4b000000000000000000000000000000000000000000000000000000008252600452fd5b503461029957807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102995760206040517f000000000000000000000000000000000000000000000000000000000000000015158152f35b503461029957807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029957602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346102995760e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029957610dda612f25565b9060607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36011261029957604051610e1181612e0c565b6024358015158103610f6d5781526044356fffffffffffffffffffffffffffffffff81168103610f6d5760208201526064356fffffffffffffffffffffffffffffffff81168103610f6d57604082015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7c360112610f695760405190610e9882612e0c565b6084358015158103610b3b57825260a4356fffffffffffffffffffffffffffffffff81168103610b3b57602083015260c4356fffffffffffffffffffffffffffffffff81168103610b3b57604083015273ffffffffffffffffffffffffffffffffffffffff6009541633141580610f47575b610f1b57610f189293613a91565b80f35b6024837f8e4a23d600000000000000000000000000000000000000000000000000000000815233600452fd5b5073ffffffffffffffffffffffffffffffffffffffff60015416331415610f0a565b5080fd5b8280fd5b50346102995760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029957610fda610fd560406110339367ffffffffffffffff610fbe612f25565b610fc661343a565b50168152600760205220613465565b613bce565b6040519182918291909160806fffffffffffffffffffffffffffffffff8160a084019582815116855263ffffffff6020820151166020860152604081015115156040860152826060820151166060860152015116910152565b0390f35b503461029957807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029957604051906005548083528260208101600584526020842092845b81811061116757505061109592500383612e28565b81516110b96110a3826131ee565b916110b16040519384612e28565b8083526131ee565b917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0602083019301368437805b8451811015611118578067ffffffffffffffff611105600193886132d2565b511661111182866132d2565b52016110e6565b50925090604051928392602084019060208552518091526040840192915b818110611144575050500390f35b825167ffffffffffffffff16845285945060209384019390920191600101611136565b8454835260019485019487945060209093019201611080565b50346102995760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102995773ffffffffffffffffffffffffffffffffffffffff6111cd612f02565b6111d56137dc565b1680156112505760407f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f16849160045490807fffffffffffffffffffffffff000000000000000000000000000000000000000083161760045573ffffffffffffffffffffffffffffffffffffffff8351921682526020820152a180f35b6004827f8579befe000000000000000000000000000000000000000000000000000000008152fd5b503461029957807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102995760206040517f000000000000000000000000000000000000000000000000000000000000000015158152f35b50346102995760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029957611033611316611311612f25565b6134cb565b604051918291602083526020830190612ea3565b503461029957807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029957602073ffffffffffffffffffffffffffffffffffffffff60045416604051908152f35b50346102995760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029957610fda610fd5600260406110339467ffffffffffffffff6113cb612f25565b6113d361343a565b5016815260076020522001613465565b50346102995767ffffffffffffffff6113fb36612f3c565b9290916114066137dc565b169161141f836000526006602052604060002054151590565b156114db57828452600760205261144e6005604086200161144136848661314b565b6020815191012090614445565b1561149357907f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d769161148d6040519283926020845260208401916133fb565b0390a280f35b826114d7836040519384937f74f23c7c00000000000000000000000000000000000000000000000000000000855260048501526040602485015260448401916133fb565b0390fd5b602484847f1e670e4b000000000000000000000000000000000000000000000000000000008252600452fd5b503461029957807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029957604051600254808252602082018091600285526020852090855b8181106115bd5750505082611566910383612e28565b604051928392602084019060208552518091526040840192915b81811061158e575050500390f35b825173ffffffffffffffffffffffffffffffffffffffff16845285945060209384019390920191600101611580565b8254845260209093019260019283019201611550565b50346102995760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102995767ffffffffffffffff611614612f25565b168152600760205261162b60056040832001614121565b80517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061167061165a836131ee565b926116686040519485612e28565b8084526131ee565b01835b818110611747575050825b82518110156116c45780611694600192856132d2565b51855260086020526116a860408620613339565b6116b282856132d2565b526116bd81846132d2565b500161167e565b81846040519182916020830160208452825180915260408401602060408360051b870101940192905b8282106116fc57505050500390f35b91936020611737827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc060019597998495030186528851612ea3565b96019201920185949391926116ed565b806060602080938601015201611673565b50346102995760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102995760043567ffffffffffffffff8111610f695760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8236030112610f6957606060206040516117d681612dd4565b8281520152608481016117e881613182565b73ffffffffffffffffffffffffffffffffffffffff807f000000000000000000000000000000000000000000000000000000000000000016911603611c5d5750602481019077ffffffffffffffff0000000000000000000000000000000061184f836132ad565b60801b16604051907f2cbc26bb000000000000000000000000000000000000000000000000000000008252600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa908115611b7e578491611c2e575b50611c06576118dd60448201613182565b7f0000000000000000000000000000000000000000000000000000000000000000611bb4575b5067ffffffffffffffff611916836132ad565b1661192e816000526006602052604060002054151590565b15611b8957602073ffffffffffffffffffffffffffffffffffffffff60045416916024604051809481937fa8d87a3b00000000000000000000000000000000000000000000000000000000835260048301525afa8015611b7e578490611b1b575b73ffffffffffffffffffffffffffffffffffffffff9150163303611aef578161131191611a1d6040611abe9667ffffffffffffffff60646119d2611a4e996132ad565b950135941681526007602052208273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691614695565b6040519081527f9f1ec8c880f76798e7b793325d625e9b60e4082a553c98f42b6cda368dd6000860203392a26132ad565b61103360405160ff7f000000000000000000000000000000000000000000000000000000000000000016602082015260208152611a8c604082612e28565b60405192611a9984612dd4565b8352602083019081526040519384936020855251604060208601526060850190612ea3565b90517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612ea3565b6024837f728fe07b00000000000000000000000000000000000000000000000000000000815233600452fd5b506020813d602011611b76575b81611b3560209383612e28565b81010312610b3b575173ffffffffffffffffffffffffffffffffffffffff81168103610b3b5773ffffffffffffffffffffffffffffffffffffffff9061198f565b3d9150611b28565b6040513d86823e3d90fd5b7fa9902c7e000000000000000000000000000000000000000000000000000000008452600452602483fd5b73ffffffffffffffffffffffffffffffffffffffff1680845260036020526040842054611903577fd0d25976000000000000000000000000000000000000000000000000000000008452600452602483fd5b6004837f53ad11d8000000000000000000000000000000000000000000000000000000008152fd5b611c50915060203d602011611c56575b611c488183612e28565b8101906135c3565b386118cc565b503d611c3e565b8273ffffffffffffffffffffffffffffffffffffffff611c7e602493613182565b7f961c9a4f00000000000000000000000000000000000000000000000000000000835216600452fd5b50346102995760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102995760043567ffffffffffffffff8111610f6957611cf7903690600401612fbf565b60243567ffffffffffffffff8111610b3b57611d17903690600401613060565b60449291923567ffffffffffffffff8111610b3257611d3a903690600401613060565b91909273ffffffffffffffffffffffffffffffffffffffff6009541633141580611e29575b611dfd57818114801590611df3575b611dcb57865b818110611d7f578780f35b80611dc5611d93610b5e600194868c61326e565b611d9e83878b6132c2565b611dbf611db7611daf868b8d6132c2565b9236906130ae565b9136906130ae565b91613a91565b01611d74565b6004877f568efce2000000000000000000000000000000000000000000000000000000008152fd5b5082811415611d6e565b6024877f8e4a23d600000000000000000000000000000000000000000000000000000000815233600452fd5b5073ffffffffffffffffffffffffffffffffffffffff60015416331415611d5f565b503461029957807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029957602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b50346102995760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610299576020611ef767ffffffffffffffff611ee3612f25565b166000526006602052604060002054151590565b6040519015158152f35b50346102995760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610299577f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d09174602073ffffffffffffffffffffffffffffffffffffffff611f71612f02565b611f796137dc565b16807fffffffffffffffffffffffff00000000000000000000000000000000000000006009541617600955604051908152a180f35b503461029957807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029957805473ffffffffffffffffffffffffffffffffffffffff8116330361206b577fffffffffffffffffffffffff000000000000000000000000000000000000000060015491338284161760015516825573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b6004827f02b543c6000000000000000000000000000000000000000000000000000000008152fd5b503461029957807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029957602073ffffffffffffffffffffffffffffffffffffffff60095416604051908152f35b50346102995760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102995773ffffffffffffffffffffffffffffffffffffffff612132612f02565b61213a6137dc565b167fffffffffffffffffffffffff0000000000000000000000000000000000000000600a541617600a5580f35b50346102995760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102995761219f612f02565b73ffffffffffffffffffffffffffffffffffffffff602435916121c06137dc565b1690813b15610f6d576040517f0a861f2a000000000000000000000000000000000000000000000000000000008152816004820152838160248183875af18015611b7e57612238575b5060207f6fa7abcf1345d1d478e5ea0da6b5f26a90eadb0546ef15ed3833944fbfd1db6291604051908152a280f35b836122677f6fa7abcf1345d1d478e5ea0da6b5f26a90eadb0546ef15ed3833944fbfd1db629395602093612e28565b939150612209565b50346102995761227e36612f3c565b61228a939291936137dc565b67ffffffffffffffff82166122ac816000526006602052604060002054151590565b156122c85750610f1892936122c291369161314b565b90613827565b7f1e670e4b000000000000000000000000000000000000000000000000000000008452600452602483fd5b50346102995761231d9061232561230936612ff0565b95916123169391936137dc565b3691613206565b933691613206565b7f00000000000000000000000000000000000000000000000000000000000000001561244857815b83518110156123c0578073ffffffffffffffffffffffffffffffffffffffff612378600193876132d2565b511661238381614184565b61238f575b500161234d565b60207f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf756691604051908152a138612388565b5090805b8251811015612444578073ffffffffffffffffffffffffffffffffffffffff6123ef600193866132d2565b5116801561243e5761240081614586565b61240d575b505b016123c4565b60207f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d891604051908152a184612405565b50612407565b5080f35b6004827f35f4a7b3000000000000000000000000000000000000000000000000000000008152fd5b5034610299576020611ef761248436612f3c565b916131a3565b503461029957807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029957602073ffffffffffffffffffffffffffffffffffffffff600a5416604051908152f35b50346102995760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102995760043567ffffffffffffffff8111610f695780600401916101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8336030112610299578060405161255d81612d89565b526084820161256b81613182565b73ffffffffffffffffffffffffffffffffffffffff807f00000000000000000000000000000000000000000000000000000000000000001691160361291657506024820177ffffffffffffffff000000000000000000000000000000006125d1826132ad565b60801b16604051907f2cbc26bb000000000000000000000000000000000000000000000000000000008252600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9081156128995783916128f7575b506128cf5767ffffffffffffffff612665826132ad565b1661267d816000526006602052604060002054151590565b156128a457602073ffffffffffffffffffffffffffffffffffffffff60045416916044604051809481937f83826b2b00000000000000000000000000000000000000000000000000000000835260048301523360248301525afa90811561289957839161287a575b501561284e576126f4816132ad565b61270660a485019161248483886130fa565b1561280757506020936127c06044946127ac73ffffffffffffffffffffffffffffffffffffffff956127a66127a161279a600260406127476127c59b6132ad565b9567ffffffffffffffff60648a01359716815260078f522001976127907f000000000000000000000000000000000000000000000000000000000000000099868d8c1691614695565b60c48701906130fa565b369161314b565b6135db565b906136cf565b95869101926127ba84613182565b90613561565b613182565b166040518281527f2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f52843392a3806040516127fe81612d89565b52604051908152f35b61281190856130fa565b6114d76040519283927f24eb47e50000000000000000000000000000000000000000000000000000000084526020600485015260248401916133fb565b6024827f728fe07b00000000000000000000000000000000000000000000000000000000815233600452fd5b612893915060203d602011611c5657611c488183612e28565b386126e5565b6040513d85823e3d90fd5b7fa9902c7e000000000000000000000000000000000000000000000000000000008352600452602482fd5b6004827f53ad11d8000000000000000000000000000000000000000000000000000000008152fd5b612910915060203d602011611c5657611c488183612e28565b3861264e565b9073ffffffffffffffffffffffffffffffffffffffff611c7e602493613182565b503461029957807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029957602060405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346102995760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610299576020906129ce612f02565b905073ffffffffffffffffffffffffffffffffffffffff807f0000000000000000000000000000000000000000000000000000000000000000169116146040519015158152f35b503461029957807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029957602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b503461029957807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102995750611033604051612ac5604082612e28565b601a81527f4c6f636b52656c65617365546f6b656e506f6f6c20312e352e310000000000006020820152604051918291602083526020830190612ea3565b50346102995760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102995760043573ffffffffffffffffffffffffffffffffffffffff600a541633036103af577f00000000000000000000000000000000000000000000000000000000000000006040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260208160248173ffffffffffffffffffffffffffffffffffffffff86165afa8015611b7e5783918591612c32575b5010612c0a5781612be2913390613561565b337fc2c3f06e49b9f15e7b4af9055e183b0d73362e033ad82a07dec9bf98401717198380a380f35b6004837fbb55fd27000000000000000000000000000000000000000000000000000000008152fd5b9150506020813d602011612c5f575b81612c4e60209383612e28565b81010312610b3b5782905138612bd0565b3d9150612c41565b905034610f695760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610f69576004357fffffffff000000000000000000000000000000000000000000000000000000008116809103610f6d57602092507fe1d40566000000000000000000000000000000000000000000000000000000008114908115612cfb575b5015158152f35b7faff2afbf00000000000000000000000000000000000000000000000000000000811491508115612d5f575b8115612d35575b5038612cf4565b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501438612d2e565b7f0e64dd290000000000000000000000000000000000000000000000000000000081149150612d27565b6020810190811067ffffffffffffffff821117612da557604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040810190811067ffffffffffffffff821117612da557604052565b60a0810190811067ffffffffffffffff821117612da557604052565b6060810190811067ffffffffffffffff821117612da557604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117612da557604052565b67ffffffffffffffff8111612da557601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b919082519283825260005b848110612eed5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b80602080928401015182828601015201612eae565b6004359073ffffffffffffffffffffffffffffffffffffffff82168203610b3657565b6004359067ffffffffffffffff82168203610b3657565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc820112610b365760043567ffffffffffffffff81168103610b36579160243567ffffffffffffffff8111610b365782602382011215610b365780600401359267ffffffffffffffff8411610b365760248483010111610b36576024019190565b9181601f84011215610b365782359167ffffffffffffffff8311610b36576020808501948460051b010111610b3657565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc820112610b365760043567ffffffffffffffff8111610b36578161303991600401612fbf565b929092916024359067ffffffffffffffff8211610b365761305c91600401612fbf565b9091565b9181601f84011215610b365782359167ffffffffffffffff8311610b365760208085019460608502010111610b3657565b35906fffffffffffffffffffffffffffffffff82168203610b3657565b9190826060910312610b36576040516130c681612e0c565b80928035908115158203610b365760406130f591819385526130ea60208201613091565b602086015201613091565b910152565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610b36570180359067ffffffffffffffff8211610b3657602001918136038313610b3657565b92919261315782612e69565b916131656040519384612e28565b829481845281830111610b36578281602093846000960137010152565b3573ffffffffffffffffffffffffffffffffffffffff81168103610b365790565b6131eb929167ffffffffffffffff6131ce92166000526007602052600560406000200192369161314b565b602081519101209060019160005201602052604060002054151590565b90565b67ffffffffffffffff8111612da55760051b60200190565b9291613211826131ee565b9361321f6040519586612e28565b602085848152019260051b8101918211610b3657915b81831061324157505050565b823573ffffffffffffffffffffffffffffffffffffffff81168103610b3657815260209283019201613235565b919081101561327e5760051b0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b3567ffffffffffffffff81168103610b365790565b919081101561327e576060020190565b805182101561327e5760209160051b010190565b90600182811c9216801561332f575b602083101461330057565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f16916132f5565b906040519182600082549261334d846132e6565b80845293600181169081156133bb5750600114613374575b5061337292500383612e28565b565b90506000929192526020600020906000915b81831061339f5750509060206133729282010138613365565b6020919350806001915483858901015201910190918492613386565b602093506133729592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b82010138613365565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b6040519061344782612df0565b60006080838281528260208201528260408201528260608201520152565b9060405161347281612df0565b60806001829460ff81546fffffffffffffffffffffffffffffffff8116865263ffffffff81861c16602087015260a01c161515604085015201546fffffffffffffffffffffffffffffffff81166060840152811c910152565b67ffffffffffffffff1660005260076020526131eb6004604060002001613339565b8181106134f8575050565b600081556001016134ed565b8181029291811591840414171561351757565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9080601f83011215610b36578160206131eb9335910161314b565b6133729273ffffffffffffffffffffffffffffffffffffffff604051937fa9059cbb0000000000000000000000000000000000000000000000000000000060208601521660248401526044830152604482526135be606483612e28565b613dae565b90816020910312610b3657518015158103610b365790565b8051801561364b5760200361360d578051602082810191830183900312610b3657519060ff821161360d575060ff1690565b6114d7906040519182917f953576f7000000000000000000000000000000000000000000000000000000008352602060048401526024830190612ea3565b50507f000000000000000000000000000000000000000000000000000000000000000090565b9060ff8091169116039060ff821161351757565b60ff16604d811161351757600a0a90565b81156136a0570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b907f00000000000000000000000000000000000000000000000000000000000000009060ff82169060ff8116928284146137d5578284116137ab579061371491613671565b91604d60ff8416118015613772575b61373c575050906137366131eb92613685565b90613504565b9091507fa9cb113d0000000000000000000000000000000000000000000000000000000060005260045260245260445260646000fd5b5061377c83613685565b80156136a0577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048411613723565b6137b491613671565b91604d60ff84161161373c575050906137cf6131eb92613685565b90613696565b5050505090565b73ffffffffffffffffffffffffffffffffffffffff6001541633036137fd57565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b90805115613a675767ffffffffffffffff8151602083012092169182600052600760205261385c816005604060002001614640565b15613a235760005260086020526040600020815167ffffffffffffffff8111612da55761388982546132e6565b601f81116139f1575b506020601f821160011461392b5791613905827f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea959361391b95600091613920575b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b9055604051918291602083526020830190612ea3565b0390a2565b9050840151386138d4565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082169083600052806000209160005b8181106139d957509261391b9492600192827f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea9896106139a2575b5050811b019055611316565b8501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690553880613996565b9192602060018192868a01518155019401920161395b565b613a1d90836000526020600020601f840160051c81019160208510610a6157601f0160051c01906134ed565b38613892565b50906114d76040519283927f393b8ad20000000000000000000000000000000000000000000000000000000084526004840152604060248401526044830190612ea3565b7f8579befe0000000000000000000000000000000000000000000000000000000060005260046000fd5b67ffffffffffffffff166000818152600660205260409020549092919015613b935791613b9060e092613b5c85613ae87f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b97613c53565b846000526007602052613aff816040600020613eee565b613b0883613c53565b846000526007602052613b22836002604060002001613eee565b60405194855260208501906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b60808301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565ba1565b827f1e670e4b0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b9190820391821161351757565b613bd661343a565b506fffffffffffffffffffffffffffffffff6060820151166fffffffffffffffffffffffffffffffff8083511691613c336020850193613c2d613c2063ffffffff87511642613bc1565b8560808901511690613504565b90614579565b80821015613c4c57505b16825263ffffffff4216905290565b9050613c3d565b805115613d07576fffffffffffffffffffffffffffffffff6040820151166fffffffffffffffffffffffffffffffff602083015116811090811591613cfe575b50613c9b5750565b606490613cfc604051917f8020d12400000000000000000000000000000000000000000000000000000000835260048301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565bfd5b90501538613c93565b6fffffffffffffffffffffffffffffffff60408201511615801590613d8f575b613d2e5750565b606490613cfc604051917fd68af9cc00000000000000000000000000000000000000000000000000000000835260048301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b506fffffffffffffffffffffffffffffffff6020820151161515613d27565b73ffffffffffffffffffffffffffffffffffffffff613e3d911691604092600080855193613ddc8786612e28565b602085527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564602086015260208151910182855af13d15613ee6573d91613e2183612e69565b92613e2e87519485612e28565b83523d6000602085013e61497d565b80519081613e4a57505050565b602080613e5b9383010191016135c3565b15613e635750565b608490517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152fd5b60609161497d565b7f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19916140276060928054613f2b63ffffffff8260801c1642613bc1565b9081614066575b50506fffffffffffffffffffffffffffffffff600181602086015116928281541680851060001461405e57508280855b16167fffffffffffffffffffffffffffffffff00000000000000000000000000000000825416178155613fdb8651151582907fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff74ff0000000000000000000000000000000000000000835492151560a01b169116179055565b60408601517fffffffffffffffffffffffffffffffff0000000000000000000000000000000060809190911b16939092166fffffffffffffffffffffffffffffffff1692909217910155565b613b9060405180926fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b838091613f62565b6fffffffffffffffffffffffffffffffff9161409b8392836140946001880154948286169560801c90613504565b9116614579565b8082101561411a57505b83547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff9290911692909216167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116174260801b73ffffffff00000000000000000000000000000000161781553880613f32565b90506140a5565b906040519182815491828252602082019060005260206000209260005b81811061415357505061337292500383612e28565b845483526001948501948794506020909301920161413e565b805482101561327e5760005260206000200190600090565b6000818152600360205260409020548015614313577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811161351757600254907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8201918211613517578181036142a4575b5050506002548015614275577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0161423281600261416c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600255600052600360205260006040812055600190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6142fb6142b56142c693600261416c565b90549060031b1c928392600261416c565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b905560005260036020526040600020553880806141f9565b5050600090565b6000818152600660205260409020548015614313577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811161351757600554907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82019182116135175781810361440b575b5050506005548015614275577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff016143c881600561416c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600555600052600660205260006040812055600190565b61442d61441c6142c693600561416c565b90549060031b1c928392600561416c565b9055600052600660205260406000205538808061438f565b9060018201918160005282602052604060002054801515600014614570577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101818111613517578254907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820191821161351757818103614539575b50505080548015614275577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01906144fa828261416c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b191690555560005260205260006040812055600190565b6145596145496142c6938661416c565b90549060031b1c9283928661416c565b9055600052836020526040600020553880806144c2565b50505050600090565b9190820180921161351757565b806000526003602052604060002054156000146145e05760025468010000000000000000811015612da5576145c76142c6826001859401600255600261416c565b9055600254906000526003602052604060002055600190565b50600090565b806000526006602052604060002054156000146145e05760055468010000000000000000811015612da5576146276142c6826001859401600555600561416c565b9055600554906000526006602052604060002055600190565b60008281526001820160205260409020546143135780549068010000000000000000821015612da5578261467e6142c684600180960185558461416c565b905580549260005201602052604060002055600190565b929192805460ff8160a01c16158015614975575b61496e576fffffffffffffffffffffffffffffffff811690600183019081546146ee63ffffffff6fffffffffffffffffffffffffffffffff83169360801c1642613bc1565b90816148d0575b505084811061484e575083821061477d57507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a939450906fffffffffffffffffffffffffffffffff8061474b8560209695613bc1565b16167fffffffffffffffffffffffffffffffff00000000000000000000000000000000825416179055604051908152a1565b81945061478f92505460801c92613bc1565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810190808211613517576147dd6147e29273ffffffffffffffffffffffffffffffffffffffff94614579565b613696565b921691821561481e577fd0c8d23a0000000000000000000000000000000000000000000000000000000060005260045260245260445260646000fd5b7f15279c080000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b8473ffffffffffffffffffffffffffffffffffffffff88169182156148a0577f1a76572a0000000000000000000000000000000000000000000000000000000060005260045260245260445260646000fd5b7ff94ebcd10000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b828592939511614944576148eb92613c2d9160801c90613504565b8083101561493f5750815b83547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff164260801b73ffffffff00000000000000000000000000000000161784559138806146f5565b6148f6565b7f9725942a0000000000000000000000000000000000000000000000000000000060005260046000fd5b5050509050565b5082156146a9565b919290156149f85750815115614991575090565b3b1561499a5790565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152fd5b825190915015614a0b5750805190602001fd5b6114d7906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352602060048401526024830190612ea356fea164736f6c634300081a000a", } var LockReleaseTokenPoolABI = LockReleaseTokenPoolMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/maybe_revert_message_receiver/maybe_revert_message_receiver.go b/core/gethwrappers/ccip/generated/maybe_revert_message_receiver/maybe_revert_message_receiver.go index 3b52e8c871b..8d3c36757aa 100644 --- a/core/gethwrappers/ccip/generated/maybe_revert_message_receiver/maybe_revert_message_receiver.go +++ b/core/gethwrappers/ccip/generated/maybe_revert_message_receiver/maybe_revert_message_receiver.go @@ -44,8 +44,8 @@ type ClientEVMTokenAmount struct { } var MaybeRevertMessageReceiverMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"toRevert\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"CustomError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReceiveRevert\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"MessageReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"ValueReceived\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_toRevert\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"setErr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"toRevert\",\"type\":\"bool\"}],\"name\":\"setRevert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", - Bin: "0x608060405234801561001057600080fd5b506040516107e73803806107e783398101604081905261002f9161005d565b600080546001600160a81b0319163360ff60a01b191617600160a01b92151592909202919091179055610086565b60006020828403121561006f57600080fd5b8151801515811461007f57600080fd5b9392505050565b610752806100956000396000f3fe60806040526004361061005e5760003560e01c806377f5b0e61161004357806377f5b0e61461015857806385572ffb1461017a5780638fb5f1711461019a57600080fd5b806301ffc9a7146100f25780635100fc211461012657600080fd5b366100ed5760005474010000000000000000000000000000000000000000900460ff16156100b8576040517f3085b8db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040513481527fe12e3b7047ff60a2dd763cf536a43597e5ce7fe7aa7476345bd4cd079912bcef9060200160405180910390a1005b600080fd5b3480156100fe57600080fd5b5061011261010d366004610335565b6101ff565b604051901515815260200160405180910390f35b34801561013257600080fd5b506000546101129074010000000000000000000000000000000000000000900460ff1681565b34801561016457600080fd5b506101786101733660046103ad565b610298565b005b34801561018657600080fd5b5061017861019536600461047c565b6102a8565b3480156101a657600080fd5b506101786101b53660046104b7565b6000805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f85572ffb00000000000000000000000000000000000000000000000000000000148061029257507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b60016102a4828261057d565b5050565b60005474010000000000000000000000000000000000000000900460ff16156103095760016040517f5a4ff6710000000000000000000000000000000000000000000000000000000081526004016103009190610697565b60405180910390fd5b6040517fd82ce31e3523f6eeb2d24317b2b4133001e8472729657f663b68624c45f8f3e890600090a150565b60006020828403121561034757600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461037757600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156103bf57600080fd5b813567ffffffffffffffff808211156103d757600080fd5b818401915084601f8301126103eb57600080fd5b8135818111156103fd576103fd61037e565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156104435761044361037e565b8160405282815287602084870101111561045c57600080fd5b826020860160208301376000928101602001929092525095945050505050565b60006020828403121561048e57600080fd5b813567ffffffffffffffff8111156104a557600080fd5b820160a0818503121561037757600080fd5b6000602082840312156104c957600080fd5b8135801515811461037757600080fd5b600181811c908216806104ed57607f821691505b602082108103610526577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f821115610578576000816000526020600020601f850160051c810160208610156105555750805b601f850160051c820191505b8181101561057457828155600101610561565b5050505b505050565b815167ffffffffffffffff8111156105975761059761037e565b6105ab816105a584546104d9565b8461052c565b602080601f8311600181146105fe57600084156105c85750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610574565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561064b5788860151825594840194600190910190840161062c565b508582101561068757878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b60006020808352600084546106ab816104d9565b80602087015260406001808416600081146106cd576001811461070757610737565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00851660408a0152604084151560051b8a01019550610737565b89600052602060002060005b8581101561072e5781548b8201860152908301908801610713565b8a016040019650505b50939897505050505050505056fea164736f6c6343000818000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"toRevert\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"receive\",\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"ccipReceive\",\"inputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structClient.Any2EVMMessage\",\"components\":[{\"name\":\"messageId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sender\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\",\"internalType\":\"structClient.EVMTokenAmount[]\",\"components\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"s_toRevert\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"setErr\",\"inputs\":[{\"name\":\"err\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setRevert\",\"inputs\":[{\"name\":\"toRevert\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"pure\"},{\"type\":\"event\",\"name\":\"MessageReceived\",\"inputs\":[],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValueReceived\",\"inputs\":[{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"CustomError\",\"inputs\":[{\"name\":\"err\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"ReceiveRevert\",\"inputs\":[]}]", + Bin: "0x608034607d57601f6107a838819003918201601f19168301916001600160401b03831184841017608257808492602094604052833981010312607d5751801515809103607d57600080546001600160a81b0319163360ff60a01b19161760a09290921b60ff60a01b1691909117905560405161070f90816100998239f35b600080fd5b634e487b7160e01b600052604160045260246000fdfe608080604052600436101561007e575b50361561001b57600080fd5b60ff60005460a01c16610054577fe12e3b7047ff60a2dd763cf536a43597e5ce7fe7aa7476345bd4cd079912bcef6020604051348152a1005b7f3085b8db0000000000000000000000000000000000000000000000000000000060005260046000fd5b60003560e01c90816301ffc9a7146105f3575080635100fc21146105af57806377f5b0e6146102da57806385572ffb1461014d57638fb5f171146100c2573861000f565b346101485760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014857600435801515809103610148577fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff74ff00000000000000000000000000000000000000006000549260a01b16911617600055600080f35b600080fd5b346101485760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101485760043567ffffffffffffffff8111610148577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60a091360301126101485760ff60005460a01c166101ee577fd82ce31e3523f6eeb2d24317b2b4133001e8472729657f663b68624c45f8f3e8600080a1005b6040517f5a4ff6710000000000000000000000000000000000000000000000000000000081526020600482015280600060015461022a816106af565b908160248501526001811690816000146102a2575060011461024b57500390fd5b6001600090815291507fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65b81831061028857505081010360440190fd5b805460448487010152849350602090920191600101610276565b604493507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b8201010390fd5b346101485760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101485760043567ffffffffffffffff8111610148573660238201121561014857806004013567ffffffffffffffff811161058057604051917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f81601f8501160116830183811067ffffffffffffffff82111761058057604052818352366024838301011161014857816000926024602093018386013783010152805167ffffffffffffffff8111610580576103be6001546106af565b601f81116104dd575b50602091601f821160011461042357918192600092610418575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c191617600155600080f35b0151905082806103e1565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082169260016000527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf69160005b8581106104c55750836001951061048e575b505050811b01600155005b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c19169055828080610483565b91926020600181928685015181550194019201610471565b6001600052601f820160051c7fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6019060208310610558575b601f0160051c7fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf601905b81811061054c57506103c7565b6000815560010161053f565b7fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf69150610515565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b346101485760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014857602060ff60005460a01c166040519015158152f35b346101485760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014857600435907fffffffff00000000000000000000000000000000000000000000000000000000821680920361014857817f85572ffb0000000000000000000000000000000000000000000000000000000060209314908115610685575b5015158152f35b7f01ffc9a7000000000000000000000000000000000000000000000000000000009150148361067e565b90600182811c921680156106f8575b60208310146106c957565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f16916106be56fea164736f6c634300081a000a", } var MaybeRevertMessageReceiverABI = MaybeRevertMessageReceiverMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go b/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go index 5b482517191..3625e6c1aed 100644 --- a/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go +++ b/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go @@ -71,8 +71,8 @@ type InternalRampMessageHeader struct { } var MessageHasherMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"}],\"name\":\"decodeEVMExtraArgsV1\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMExtraArgsV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"allowOutOfOrderExecution\",\"type\":\"bool\"}],\"name\":\"decodeEVMExtraArgsV2\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"allowOutOfOrderExecution\",\"type\":\"bool\"}],\"internalType\":\"structClient.EVMExtraArgsV2\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"name\":\"encodeAny2EVMTokenAmountsHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"tokenAmount\",\"type\":\"tuple[]\"}],\"name\":\"encodeEVM2AnyTokenAmountsHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMExtraArgsV1\",\"name\":\"extraArgs\",\"type\":\"tuple\"}],\"name\":\"encodeEVMExtraArgsV1\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"allowOutOfOrderExecution\",\"type\":\"bool\"}],\"internalType\":\"structClient.EVMExtraArgsV2\",\"name\":\"extraArgs\",\"type\":\"tuple\"}],\"name\":\"encodeEVMExtraArgsV2\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"leafDomainSeparator\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"metaDataHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"fixedSizeFieldsHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"senderHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"dataHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"tokenAmountsHash\",\"type\":\"bytes32\"}],\"name\":\"encodeFinalHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"name\":\"encodeFixedSizeFieldsHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"any2EVMMessageHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"onRampHash\",\"type\":\"bytes32\"}],\"name\":\"encodeMetadataHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"name\":\"hash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b50611053806100206000396000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c8063bf0619ad11610076578063c7ca9a181161005b578063c7ca9a1814610273578063e04767b814610286578063e733d2091461029957600080fd5b8063bf0619ad146101c9578063c63641bd1461021c57600080fd5b806394b6624b116100a757806394b6624b14610168578063ae5663d71461017b578063b17df7141461018e57600080fd5b80633ec7c377146100c35780638503839d14610147575b600080fd5b6101316100d136600461065b565b60408051602081019690965273ffffffffffffffffffffffffffffffffffffffff949094168585015267ffffffffffffffff928316606086015260808501919091521660a0808401919091528151808403909101815260c0909201905290565b60405161013e9190610716565b60405180910390f35b61015a610155366004610a5b565b6102ac565b60405190815260200161013e565b610131610176366004610b65565b610343565b610131610189366004610cd5565b61036c565b6101ba61019c366004610d12565b60408051602080820183526000909152815190810190915290815290565b6040519051815260200161013e565b6101316101d7366004610d2b565b604080516020810197909752868101959095526060860193909352608085019190915260a084015260c0808401919091528151808403909101815260e0909201905290565b61025661022a366004610d7e565b604080518082019091526000808252602082015250604080518082019091529182521515602082015290565b60408051825181526020928301511515928101929092520161013e565b610131610281366004610daa565b61037f565b610131610294366004610dfe565b610390565b6101316102a7366004610e42565b6103e3565b600061033c837f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f8560000151602001518660000151604001518680519060200120604051602001610321949392919093845267ffffffffffffffff928316602085015291166040830152606082015260800190565b604051602081830303815290604052805190602001206103ee565b9392505050565b6060816040516020016103569190610e84565b6040516020818303038152906040529050919050565b6060816040516020016103569190610f71565b606061038a82610521565b92915050565b6060848484846040516020016103ca949392919093845267ffffffffffffffff928316602085015291166040830152606082015260800190565b6040516020818303038152906040529050949350505050565b606061038a826105e3565b815180516060808501519083015160808087015194015160405160009586958895610460959194909391929160200194855273ffffffffffffffffffffffffffffffffffffffff93909316602085015267ffffffffffffffff9182166040850152606084015216608082015260a00190565b604051602081830303815290604052805190602001208560200151805190602001208660400151805190602001208760a001516040516020016104a39190610f71565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e00160405160208183030381529060405280519060200120905092915050565b604051815160248201526020820151151560448201526060907f181dcf1000000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915292915050565b604051815160248201526060907f97a657c90000000000000000000000000000000000000000000000000000000090604401610560565b803573ffffffffffffffffffffffffffffffffffffffff8116811461063e57600080fd5b919050565b803567ffffffffffffffff8116811461063e57600080fd5b600080600080600060a0868803121561067357600080fd5b853594506106836020870161061a565b935061069160408701610643565b9250606086013591506106a660808701610643565b90509295509295909350565b6000815180845260005b818110156106d8576020818501810151868301820152016106bc565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061033c60208301846106b2565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561077b5761077b610729565b60405290565b60405160c0810167ffffffffffffffff8111828210171561077b5761077b610729565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156107eb576107eb610729565b604052919050565b600060a0828403121561080557600080fd5b61080d610758565b90508135815261081f60208301610643565b602082015261083060408301610643565b604082015261084160608301610643565b606082015261085260808301610643565b608082015292915050565b600082601f83011261086e57600080fd5b813567ffffffffffffffff81111561088857610888610729565b6108b960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016107a4565b8181528460208386010111156108ce57600080fd5b816020850160208301376000918101602001919091529392505050565b600067ffffffffffffffff82111561090557610905610729565b5060051b60200190565b600082601f83011261092057600080fd5b81356020610935610930836108eb565b6107a4565b82815260059290921b8401810191818101908684111561095457600080fd5b8286015b84811015610a5057803567ffffffffffffffff808211156109795760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d030112156109b25760008081fd5b6109ba610758565b87840135838111156109cc5760008081fd5b6109da8d8a8388010161085d565b82525060406109ea81860161061a565b8983015260608086013563ffffffff81168114610a075760008081fd5b808385015250608091508186013585811115610a235760008081fd5b610a318f8c838a010161085d565b9184019190915250919093013590830152508352918301918301610958565b509695505050505050565b60008060408385031215610a6e57600080fd5b823567ffffffffffffffff80821115610a8657600080fd5b908401906101408287031215610a9b57600080fd5b610aa3610781565b610aad87846107f3565b815260a083013582811115610ac157600080fd5b610acd8882860161085d565b60208301525060c083013582811115610ae557600080fd5b610af18882860161085d565b604083015250610b0360e0840161061a565b6060820152610100830135608082015261012083013582811115610b2657600080fd5b610b328882860161090f565b60a08301525093506020850135915080821115610b4e57600080fd5b50610b5b8582860161085d565b9150509250929050565b60006020808385031215610b7857600080fd5b823567ffffffffffffffff80821115610b9057600080fd5b818501915085601f830112610ba457600080fd5b8135610bb2610930826108eb565b81815260059190911b83018401908481019088831115610bd157600080fd5b8585015b83811015610cc857803585811115610bec57600080fd5b860160a0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215610c215760008081fd5b610c29610758565b610c3489830161061a565b815260408083013588811115610c4a5760008081fd5b610c588e8c8387010161085d565b8b8401525060608084013589811115610c715760008081fd5b610c7f8f8d8388010161085d565b83850152506080915081840135818401525060a083013588811115610ca45760008081fd5b610cb28e8c8387010161085d565b9183019190915250845250918601918601610bd5565b5098975050505050505050565b600060208284031215610ce757600080fd5b813567ffffffffffffffff811115610cfe57600080fd5b610d0a8482850161090f565b949350505050565b600060208284031215610d2457600080fd5b5035919050565b60008060008060008060c08789031215610d4457600080fd5b505084359660208601359650604086013595606081013595506080810135945060a0013592509050565b8035801515811461063e57600080fd5b60008060408385031215610d9157600080fd5b82359150610da160208401610d6e565b90509250929050565b600060408284031215610dbc57600080fd5b6040516040810181811067ffffffffffffffff82111715610ddf57610ddf610729565b60405282358152610df260208401610d6e565b60208201529392505050565b60008060008060808587031215610e1457600080fd5b84359350610e2460208601610643565b9250610e3260408601610643565b9396929550929360600135925050565b600060208284031215610e5457600080fd5b6040516020810181811067ffffffffffffffff82111715610e7757610e77610729565b6040529135825250919050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015610f63577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0898403018552815160a073ffffffffffffffffffffffffffffffffffffffff825116855288820151818a870152610f0f828701826106b2565b9150508782015185820389870152610f2782826106b2565b915050606080830151818701525060808083015192508582038187015250610f4f81836106b2565b968901969450505090860190600101610ead565b509098975050505050505050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015610f63577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0898403018552815160a08151818652610fde828701826106b2565b91505073ffffffffffffffffffffffffffffffffffffffff89830151168986015263ffffffff8883015116888601526060808301518683038288015261102483826106b2565b6080948501519790940196909652505094870194925090860190600101610f9a56fea164736f6c6343000818000a", + ABI: "[{\"type\":\"function\",\"name\":\"decodeEVMExtraArgsV1\",\"inputs\":[{\"name\":\"gasLimit\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structClient.EVMExtraArgsV1\",\"components\":[{\"name\":\"gasLimit\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"decodeEVMExtraArgsV2\",\"inputs\":[{\"name\":\"gasLimit\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"allowOutOfOrderExecution\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structClient.EVMExtraArgsV2\",\"components\":[{\"name\":\"gasLimit\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"allowOutOfOrderExecution\",\"type\":\"bool\",\"internalType\":\"bool\"}]}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"encodeAny2EVMTokenAmountsHashPreimage\",\"inputs\":[{\"name\":\"tokenAmounts\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"components\":[{\"name\":\"sourcePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"destTokenAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"destGasAmount\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"extraData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"encodeEVM2AnyTokenAmountsHashPreimage\",\"inputs\":[{\"name\":\"tokenAmount\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"components\":[{\"name\":\"sourcePoolAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"destTokenAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"extraData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"destExecData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"encodeEVMExtraArgsV1\",\"inputs\":[{\"name\":\"extraArgs\",\"type\":\"tuple\",\"internalType\":\"structClient.EVMExtraArgsV1\",\"components\":[{\"name\":\"gasLimit\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"encodeEVMExtraArgsV2\",\"inputs\":[{\"name\":\"extraArgs\",\"type\":\"tuple\",\"internalType\":\"structClient.EVMExtraArgsV2\",\"components\":[{\"name\":\"gasLimit\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"allowOutOfOrderExecution\",\"type\":\"bool\",\"internalType\":\"bool\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"encodeFinalHashPreimage\",\"inputs\":[{\"name\":\"leafDomainSeparator\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"metaDataHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"fixedSizeFieldsHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"senderHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"dataHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"tokenAmountsHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"encodeFixedSizeFieldsHashPreimage\",\"inputs\":[{\"name\":\"messageId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"receiver\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"sequenceNumber\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"gasLimit\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"encodeMetadataHashPreimage\",\"inputs\":[{\"name\":\"any2EVMMessageHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"onRampHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"hash\",\"inputs\":[{\"name\":\"message\",\"type\":\"tuple\",\"internalType\":\"structInternal.Any2EVMRampMessage\",\"components\":[{\"name\":\"header\",\"type\":\"tuple\",\"internalType\":\"structInternal.RampMessageHeader\",\"components\":[{\"name\":\"messageId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sequenceNumber\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"sender\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"receiver\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"gasLimit\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"tokenAmounts\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"components\":[{\"name\":\"sourcePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"destTokenAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"destGasAmount\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"extraData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}]},{\"name\":\"onRamp\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"pure\"}]", + Bin: "0x60808060405234601557610e90908161001b8239f35b600080fdfe608080604052600436101561001357600080fd5b60003560e01c9081633ec7c377146109e3575080638503839d146106c457806394b6624b14610438578063ae5663d7146103d1578063b17df71414610378578063bf0619ad14610304578063c63641bd1461027d578063c7ca9a18146101b3578063e04767b81461012c5763e733d2091461008d57600080fd5b346101275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610127576101236040516100cb81610b6e565b6004358152604051907f97a657c90000000000000000000000000000000000000000000000000000000060208301525160248201526024815261010f604482610ba6565b604051918291602083526020830190610af3565b0390f35b600080fd5b346101275760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101275760243567ffffffffffffffff8116809103610127576101239067ffffffffffffffff610185610ac7565b604051926004356020850152604084015216606082015260643560808201526080815261010f60a082610ba6565b346101275760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101275761012361025161010f6040516101f781610b8a565b6004358152610204610d9e565b60208201526040519283917f181dcf100000000000000000000000000000000000000000000000000000000060208401526024830191909160208060408301948051845201511515910152565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282610ba6565b346101275760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610127576101236102b7610d9e565b600060206040516102c781610b8a565b8281520152604051906102d982610b8a565b6004358252151560208201526040519182918291909160208060408301948051845201511515910152565b346101275760c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012757610123604051600435602082015260243560408201526044356060820152606435608082015260843560a082015260a43560c082015260c0815261010f60e082610ba6565b346101275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012757602060043560006040516103ba81610b6e565b52806040516103c881610b6e565b52604051908152f35b346101275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101275760043567ffffffffffffffff81116101275761025161010f610429610123933690600401610c74565b60405192839160208301610dad565b346101275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101275760043567ffffffffffffffff811161012757366023820112156101275780600401359061049382610c5c565b906104a16040519283610ba6565b82825260208201906024829460051b820101903682116101275760248101925b8284106105d557858560405190604082019060208084015251809152606082019060608160051b84010193916000905b82821061052d576101238561010f8189037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282610ba6565b909192946020806105c7837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0896001960301865289519073ffffffffffffffffffffffffffffffffffffffff825116815260806105ac61059a8685015160a08886015260a0850190610af3565b60408501518482036040860152610af3565b92606081015160608401520151906080818403910152610af3565b9701920192019092916104f1565b833567ffffffffffffffff811161012757820160a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc8236030112610127576040519161062183610b52565b61062d60248301610aa6565b8352604482013567ffffffffffffffff8111610127576106539060243691850101610be7565b6020840152606482013567ffffffffffffffff81116101275761067c9060243691850101610be7565b60408401526084820135606084015260a48201359267ffffffffffffffff8411610127576106b4602094936024869536920101610be7565b60808201528152019301926104c1565b346101275760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101275760043567ffffffffffffffff8111610127577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc813603016101408112610127576040519060c082019082821067ffffffffffffffff8311176109b45760a091604052126101275760405161076681610b52565b8260040135815261077960248401610ade565b602082015261078a60448401610ade565b604082015261079b60648401610ade565b60608201526107ac60848401610ade565b6080820152815260a482013567ffffffffffffffff8111610127576107d79060043691850101610be7565b6020820190815260c483013567ffffffffffffffff8111610127576108029060043691860101610be7565b6040830190815261081560e48501610aa6565b60608401908152608084019461010481013586526101248101359067ffffffffffffffff821161012757600461084e9236920101610c74565b9060a085019182526024359567ffffffffffffffff87116101275761094861087c6020983690600401610be7565b87519067ffffffffffffffff6040818c8501511693015116908a8151910120604051918b8301937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f8552604084015260608301526080820152608081526108e460a082610ba6565b5190209651805193516060808301519451608093840151604080518e8101998a5273ffffffffffffffffffffffffffffffffffffffff9590951660208a015267ffffffffffffffff9788169089015291870152909316908401528160a08401610251565b519020925185815191012091518581519101209051604051610971816102518982019485610dad565b5190209160405193868501956000875260408601526060850152608084015260a083015260c082015260c081526109a960e082610ba6565b519020604051908152f35b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b346101275760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610127576024359073ffffffffffffffffffffffffffffffffffffffff8216820361012757610a3b610ac7565b916084359067ffffffffffffffff8216820361012757600435602084015273ffffffffffffffffffffffffffffffffffffffff16604083015267ffffffffffffffff9283166060830152606435608083015290911660a08201526101239061010f8160c08101610251565b359073ffffffffffffffffffffffffffffffffffffffff8216820361012757565b6044359067ffffffffffffffff8216820361012757565b359067ffffffffffffffff8216820361012757565b919082519283825260005b848110610b3d5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b80602080928401015182828601015201610afe565b60a0810190811067ffffffffffffffff8211176109b457604052565b6020810190811067ffffffffffffffff8211176109b457604052565b6040810190811067ffffffffffffffff8211176109b457604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176109b457604052565b81601f820112156101275780359067ffffffffffffffff82116109b45760405192610c3a60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8601160185610ba6565b8284526020838301011161012757816000926020809301838601378301015290565b67ffffffffffffffff81116109b45760051b60200190565b81601f8201121561012757803590610c8b82610c5c565b92610c996040519485610ba6565b82845260208085019360051b830101918183116101275760208101935b838510610cc557505050505090565b843567ffffffffffffffff811161012757820160a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082860301126101275760405191610d1183610b52565b602082013567ffffffffffffffff811161012757856020610d3492850101610be7565b8352610d4260408301610aa6565b6020840152606082013563ffffffff8116810361012757604084015260808201359267ffffffffffffffff84116101275760a083610d87886020809881980101610be7565b606084015201356080820152815201940193610cb6565b60243590811515820361012757565b602081016020825282518091526040820191602060408360051b8301019401926000915b838310610de057505050505090565b9091929394602080827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08560019503018652885190608080610e6e610e2e855160a0865260a0860190610af3565b73ffffffffffffffffffffffffffffffffffffffff87870151168786015263ffffffff604087015116604086015260608601518582036060870152610af3565b93015191015297019301930191939290610dd156fea164736f6c634300081a000a", } var MessageHasherABI = MessageHasherMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/mock_lbtc_token_pool/mock_lbtc_token_pool.go b/core/gethwrappers/ccip/generated/mock_lbtc_token_pool/mock_lbtc_token_pool.go new file mode 100644 index 00000000000..8fa1b3da14e --- /dev/null +++ b/core/gethwrappers/ccip/generated/mock_lbtc_token_pool/mock_lbtc_token_pool.go @@ -0,0 +1,3042 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package mock_lbtc_token_pool + +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 +) + +type PoolLockOrBurnInV1 struct { + Receiver []byte + RemoteChainSelector uint64 + OriginalSender common.Address + Amount *big.Int + LocalToken common.Address +} + +type PoolLockOrBurnOutV1 struct { + DestTokenAddress []byte + DestPoolData []byte +} + +type PoolReleaseOrMintInV1 struct { + OriginalSender []byte + RemoteChainSelector uint64 + Receiver common.Address + Amount *big.Int + LocalToken common.Address + SourcePoolAddress []byte + SourcePoolData []byte + OffchainTokenData []byte +} + +type PoolReleaseOrMintOutV1 struct { + DestinationAmount *big.Int +} + +type RateLimiterConfig struct { + IsEnabled bool + Capacity *big.Int + Rate *big.Int +} + +type RateLimiterTokenBucket struct { + Tokens *big.Int + LastUpdated uint32 + IsEnabled bool + Capacity *big.Int + Rate *big.Int +} + +type TokenPoolChainUpdate struct { + RemoteChainSelector uint64 + RemotePoolAddresses [][]byte + RemoteTokenAddress []byte + OutboundRateLimiterConfig RateLimiterConfig + InboundRateLimiterConfig RateLimiterConfig +} + +var MockLBTCTokenPoolMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"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\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_destPoolData\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"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\"}]", + Bin: "0x6101006040523480156200001257600080fd5b5060405162003a5138038062003a51833981016040819052620000359162000663565b846008858585336000816200005d57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b038481169190911790915581161562000090576200009081620001fe565b50506001600160a01b0385161580620000b057506001600160a01b038116155b80620000c357506001600160a01b038216155b15620000e2576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b03808616608081905290831660c0526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa92505050801562000152575060408051601f3d908101601f191682019092526200014f9181019062000785565b60015b1562000192578060ff168560ff161462000190576040516332ad3e0760e11b815260ff80871660048301528216602482015260440160405180910390fd5b505b60ff841660a052600480546001600160a01b0319166001600160a01b038316179055825115801560e052620001dc57604080516000815260208101909152620001dc908462000278565b505050505080600a9081620001f2919062000841565b5050505050506200095b565b336001600160a01b038216036200022857604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e05162000299576040516335f4a7b360e01b815260040160405180910390fd5b60005b825181101562000324576000838281518110620002bd57620002bd6200090d565b60209081029190910101519050620002d7600282620003d5565b156200031a576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b506001016200029c565b5060005b8151811015620003d05760008282815181106200034957620003496200090d565b6020026020010151905060006001600160a01b0316816001600160a01b031603620003755750620003c7565b62000382600282620003f5565b15620003c5576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010162000328565b505050565b6000620003ec836001600160a01b0384166200040c565b90505b92915050565b6000620003ec836001600160a01b03841662000510565b60008181526001830160205260408120548015620005055760006200043360018362000923565b8554909150600090620004499060019062000923565b9050808214620004b55760008660000182815481106200046d576200046d6200090d565b90600052602060002001549050808760000184815481106200049357620004936200090d565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620004c957620004c962000945565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620003ef565b6000915050620003ef565b60008181526001830160205260408120546200055957508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620003ef565b506000620003ef565b6001600160a01b03811681146200057857600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715620005bc57620005bc6200057b565b604052919050565b8051620005d18162000562565b919050565b600082601f830112620005e857600080fd5b81516001600160401b038111156200060457620006046200057b565b60206200061a601f8301601f1916820162000591565b82815285828487010111156200062f57600080fd5b60005b838110156200064f57858101830151828201840152820162000632565b506000928101909101919091529392505050565b600080600080600060a086880312156200067c57600080fd5b8551620006898162000562565b602087810151919650906001600160401b0380821115620006a957600080fd5b818901915089601f830112620006be57600080fd5b815181811115620006d357620006d36200057b565b8060051b620006e485820162000591565b918252838101850191858101908d841115620006ff57600080fd5b948601945b838610156200072d57855192506200071c8362000562565b828252948601949086019062000704565b9950620007419250505060408a01620005c4565b95506200075160608a01620005c4565b945060808901519250808311156200076857600080fd5b50506200077888828901620005d6565b9150509295509295909350565b6000602082840312156200079857600080fd5b815160ff81168114620007aa57600080fd5b9392505050565b600181811c90821680620007c657607f821691505b602082108103620007e757634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620003d0576000816000526020600020601f850160051c81016020861015620008185750805b601f850160051c820191505b81811015620008395782815560010162000824565b505050505050565b81516001600160401b038111156200085d576200085d6200057b565b62000875816200086e8454620007b1565b84620007ed565b602080601f831160018114620008ad5760008415620008945750858301515b600019600386901b1c1916600185901b17855562000839565b600085815260208120601f198616915b82811015620008de57888601518255948401946001909101908401620008bd565b5085821015620008fd5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052603260045260246000fd5b81810381811115620003ef57634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c05160e0516130a0620009b160003960008181610562015261199f0152600061053c015260006102eb015260008181610252015281816102a7015281816107450152610ba201526130a06000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c80639a4575b911610104578063c0d78655116100a2578063dc0bd97111610071578063dc0bd9711461053a578063e0351e1314610560578063e8a1da1714610586578063f2fde38b1461059957600080fd5b8063c0d78655146104ec578063c4bffe2b146104ff578063c75eea9c14610514578063cf7401f31461052757600080fd5b8063acfecf91116100de578063acfecf9114610439578063af58d59f1461044c578063b0f479a1146104bb578063b7946580146104d957600080fd5b80639a4575b9146103e4578063a42a7b8b14610404578063a7cd63b71461042457600080fd5b80634c5ef0ed1161017c57806379ba50971161014b57806379ba5097146103985780637d54534e146103a05780638926f54f146103b35780638da5cb5b146103c657600080fd5b80634c5ef0ed1461033f57806354c8a4f31461035257806362ddd3c4146103675780636d3d1a581461037a57600080fd5b8063240028e8116101b8578063240028e81461029757806324f65ee7146102e457806332a7a82214610315578063390775371461031d57600080fd5b806301ffc9a7146101df578063181f5a771461020757806321df0da714610250575b600080fd5b6101f26101ed36600461243d565b6105ac565b60405190151581526020015b60405180910390f35b6102436040518060400160405280601781526020017f4d6f636b4c425443546f6b656e506f6f6c20312e352e3100000000000000000081525081565b6040516101fe91906124e3565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101fe565b6101f26102a53660046124f6565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016101fe565b610243610691565b61033061032b36600461252c565b61071f565b604051905181526020016101fe565b6101f261034d366004612585565b610894565b610365610360366004612654565b6108de565b005b610365610375366004612585565b610959565b60095473ffffffffffffffffffffffffffffffffffffffff16610272565b6103656109f6565b6103656103ae3660046124f6565b610ac4565b6101f26103c13660046126c0565b610b45565b60015473ffffffffffffffffffffffffffffffffffffffff16610272565b6103f76103f23660046126db565b610b5c565b6040516101fe9190612716565b6104176104123660046126c0565b610d07565b6040516101fe919061276d565b61042c610e72565b6040516101fe91906127ef565b610365610447366004612585565b610e83565b61045f61045a3660046126c0565b610f9b565b6040516101fe919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610272565b6102436104e73660046126c0565b611070565b6103656104fa3660046124f6565b611120565b6105076111fb565b6040516101fe9190612849565b61045f6105223660046126c0565b6112b3565b6103656105353660046129c8565b611385565b7f0000000000000000000000000000000000000000000000000000000000000000610272565b7f00000000000000000000000000000000000000000000000000000000000000006101f2565b610365610594366004612654565b611409565b6103656105a73660046124f6565b61191b565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061063f57507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061068b57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b600a805461069e90612a0d565b80601f01602080910402602001604051908101604052809291908181526020018280546106ca90612a0d565b80156107175780601f106106ec57610100808354040283529160200191610717565b820191906000526020600020905b8154815290600101906020018083116106fa57829003601f168201915b505050505081565b60408051602081019091526000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166340c10f1961077a60608501604086016124f6565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260608501356024820152604401600060405180830381600087803b1580156107ea57600080fd5b505af11580156107fe573d6000803e3d6000fd5b506108139250505060608301604084016124f6565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f0846060013560405161087591815260200190565b60405180910390a3506040805160208101909152606090910135815290565b60006108d683836040516108a9929190612a60565b604080519182900390912067ffffffffffffffff871660009081526007602052919091206005019061192f565b949350505050565b6108e661194a565b6109538484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060408051602080880282810182019093528782529093508792508691829185019084908082843760009201919091525061199d92505050565b50505050565b61096161194a565b61096a83610b45565b6109b1576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6109f18383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611b5392505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a47576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610acc61194a565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b600061068b600567ffffffffffffffff841661192f565b60408051808201909152606080825260208201526040517f42966c68000000000000000000000000000000000000000000000000000000008152606083013560048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906342966c6890602401600060405180830381600087803b158015610bfb57600080fd5b505af1158015610c0f573d6000803e3d6000fd5b5050604051606085013581523392507f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df7915060200160405180910390a26040518060400160405280610c6d8460200160208101906104e791906126c0565b8152602001600a8054610c7f90612a0d565b80601f0160208091040260200160405190810160405280929190818152602001828054610cab90612a0d565b8015610cf85780601f10610ccd57610100808354040283529160200191610cf8565b820191906000526020600020905b815481529060010190602001808311610cdb57829003601f168201915b50505050508152509050919050565b67ffffffffffffffff8116600090815260076020526040812060609190610d3090600501611c4d565b90506000815167ffffffffffffffff811115610d4e57610d4e61288b565b604051908082528060200260200182016040528015610d8157816020015b6060815260200190600190039081610d6c5790505b50905060005b8251811015610e6a5760086000848381518110610da657610da6612a70565b602002602001015181526020019081526020016000208054610dc790612a0d565b80601f0160208091040260200160405190810160405280929190818152602001828054610df390612a0d565b8015610e405780601f10610e1557610100808354040283529160200191610e40565b820191906000526020600020905b815481529060010190602001808311610e2357829003601f168201915b5050505050828281518110610e5757610e57612a70565b6020908102919091010152600101610d87565b509392505050565b6060610e7e6002611c4d565b905090565b610e8b61194a565b610e9483610b45565b610ed6576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016109a8565b610f168282604051610ee9929190612a60565b604080519182900390912067ffffffffffffffff8616600090815260076020529190912060050190611c5a565b610f52578282826040517f74f23c7c0000000000000000000000000000000000000000000000000000000081526004016109a893929190612ae8565b8267ffffffffffffffff167f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d768383604051610f8e929190612b0c565b60405180910390a2505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600390910154808416606083015291909104909116608082015261068b90611c66565b67ffffffffffffffff8116600090815260076020526040902060040180546060919061109b90612a0d565b80601f01602080910402602001604051908101604052809291908181526020018280546110c790612a0d565b80156111145780601f106110e957610100808354040283529160200191611114565b820191906000526020600020905b8154815290600101906020018083116110f757829003601f168201915b50505050509050919050565b61112861194a565b73ffffffffffffffffffffffffffffffffffffffff8116611175576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b606060006112096005611c4d565b90506000815167ffffffffffffffff8111156112275761122761288b565b604051908082528060200260200182016040528015611250578160200160208202803683370190505b50905060005b82518110156112ac5782818151811061127157611271612a70565b602002602001015182828151811061128b5761128b612a70565b67ffffffffffffffff90921660209283029190910190910152600101611256565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600190910154808416606083015291909104909116608082015261068b90611c66565b60095473ffffffffffffffffffffffffffffffffffffffff1633148015906113c5575060015473ffffffffffffffffffffffffffffffffffffffff163314155b156113fe576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024016109a8565b6109f1838383611d18565b61141161194a565b60005b838110156115fe57600085858381811061143057611430612a70565b905060200201602081019061144591906126c0565b905061145c600567ffffffffffffffff8316611c5a565b61149e576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016109a8565b67ffffffffffffffff811660009081526007602052604081206114c390600501611c4d565b905060005b815181101561152f576115268282815181106114e6576114e6612a70565b6020026020010151600760008667ffffffffffffffff1667ffffffffffffffff168152602001908152602001600020600501611c5a90919063ffffffff16565b506001016114c8565b5067ffffffffffffffff8216600090815260076020526040812080547fffffffffffffffffffffff0000000000000000000000000000000000000000009081168255600182018390556002820180549091169055600381018290559061159860048301826123d0565b60058201600081816115aa828261240a565b505060405167ffffffffffffffff871681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d859916945060200192506115ec915050565b60405180910390a15050600101611414565b5060005b8181101561191457600083838381811061161e5761161e612a70565b90506020028101906116309190612b20565b61163990612bec565b905061164a81606001516000611e02565b61165981608001516000611e02565b806040015151600003611698576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516116b09060059067ffffffffffffffff16611f3f565b6116f55780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016109a8565b805167ffffffffffffffff16600090815260076020908152604091829020825160a08082018552606080870180518601516fffffffffffffffffffffffffffffffff90811680865263ffffffff42168689018190528351511515878b0181905284518a0151841686890181905294518b0151841660809889018190528954740100000000000000000000000000000000000000009283027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7001000000000000000000000000000000008087027fffffffffffffffffffffffff000000000000000000000000000000000000000094851690981788178216929092178d5592810290971760018c01558c519889018d52898e0180518d01518716808b528a8e019590955280515115158a8f018190528151909d01518716988a01899052518d0151909516979098018790526002890180549a9091029990931617179094169590951790925590920290911760038201559082015160048201906118789082612d63565b5060005b8260200151518110156118bc576118b48360000151846020015183815181106118a7576118a7612a70565b6020026020010151611b53565b60010161187c565b507f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c282600001518360400151846060015185608001516040516119029493929190612e7d565b60405180910390a15050600101611602565b5050505050565b61192361194a565b61192c81611f4b565b50565b600081815260018301602052604081205415155b9392505050565b60015473ffffffffffffffffffffffffffffffffffffffff16331461199b576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b7f00000000000000000000000000000000000000000000000000000000000000006119f4576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015611a8a576000838281518110611a1457611a14612a70565b60200260200101519050611a3281600261200f90919063ffffffff16565b15611a815760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b506001016119f7565b5060005b81518110156109f1576000828281518110611aab57611aab612a70565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611aef5750611b4b565b611afa600282612031565b15611b495760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611a8e565b8051600003611b8e576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160208083019190912067ffffffffffffffff8416600090815260079092526040909120611bc09060050182611f3f565b611bfa5782826040517f393b8ad20000000000000000000000000000000000000000000000000000000081526004016109a8929190612f16565b6000818152600860205260409020611c128382612d63565b508267ffffffffffffffff167f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea83604051610f8e91906124e3565b6060600061194383612053565b600061194383836120ae565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152611cf482606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff1642611cd89190612f68565b85608001516fffffffffffffffffffffffffffffffff166121a1565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b611d2183610b45565b611d63576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016109a8565b611d6e826000611e02565b67ffffffffffffffff83166000908152600760205260409020611d9190836121c9565b611d9c816000611e02565b67ffffffffffffffff83166000908152600760205260409020611dc290600201826121c9565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b838383604051611df593929190612f7b565b60405180910390a1505050565b815115611ecd5781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580611e58575060408201516fffffffffffffffffffffffffffffffff16155b15611e9157816040517f8020d1240000000000000000000000000000000000000000000000000000000081526004016109a89190612ffe565b8015611ec9576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60408201516fffffffffffffffffffffffffffffffff16151580611f06575060208201516fffffffffffffffffffffffffffffffff1615155b15611ec957816040517fd68af9cc0000000000000000000000000000000000000000000000000000000081526004016109a89190612ffe565b6000611943838361236b565b3373ffffffffffffffffffffffffffffffffffffffff821603611f9a576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60006119438373ffffffffffffffffffffffffffffffffffffffff84166120ae565b60006119438373ffffffffffffffffffffffffffffffffffffffff841661236b565b60608160000180548060200260200160405190810160405280929190818152602001828054801561111457602002820191906000526020600020905b81548152602001906001019080831161208f5750505050509050919050565b600081815260018301602052604081205480156121975760006120d2600183612f68565b85549091506000906120e690600190612f68565b905080821461214b57600086600001828154811061210657612106612a70565b906000526020600020015490508087600001848154811061212957612129612a70565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061215c5761215c61303a565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061068b565b600091505061068b565b60006121c0856121b18486613069565b6121bb9087613080565b6123ba565b95945050505050565b81546000906121f290700100000000000000000000000000000000900463ffffffff1642612f68565b90508015612294576001830154835461223a916fffffffffffffffffffffffffffffffff808216928116918591700100000000000000000000000000000000909104166121a1565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b602082015183546122ba916fffffffffffffffffffffffffffffffff90811691166123ba565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1990611df5908490612ffe565b60008181526001830160205260408120546123b25750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561068b565b50600061068b565b60008183106123c95781611943565b5090919050565b5080546123dc90612a0d565b6000825580601f106123ec575050565b601f01602090049060005260206000209081019061192c9190612424565b508054600082559060005260206000209081019061192c91905b5b808211156124395760008155600101612425565b5090565b60006020828403121561244f57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461194357600080fd5b6000815180845260005b818110156124a557602081850181015186830182015201612489565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611943602083018461247f565b60006020828403121561250857600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461194357600080fd5b60006020828403121561253e57600080fd5b813567ffffffffffffffff81111561255557600080fd5b8201610100818503121561194357600080fd5b803567ffffffffffffffff8116811461258057600080fd5b919050565b60008060006040848603121561259a57600080fd5b6125a384612568565b9250602084013567ffffffffffffffff808211156125c057600080fd5b818601915086601f8301126125d457600080fd5b8135818111156125e357600080fd5b8760208285010111156125f557600080fd5b6020830194508093505050509250925092565b60008083601f84011261261a57600080fd5b50813567ffffffffffffffff81111561263257600080fd5b6020830191508360208260051b850101111561264d57600080fd5b9250929050565b6000806000806040858703121561266a57600080fd5b843567ffffffffffffffff8082111561268257600080fd5b61268e88838901612608565b909650945060208701359150808211156126a757600080fd5b506126b487828801612608565b95989497509550505050565b6000602082840312156126d257600080fd5b61194382612568565b6000602082840312156126ed57600080fd5b813567ffffffffffffffff81111561270457600080fd5b820160a0818503121561194357600080fd5b602081526000825160406020840152612732606084018261247f565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160408501526121c0828261247f565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156127e2577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526127d085835161247f565b94509285019290850190600101612796565b5092979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561283d57835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161280b565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561283d57835167ffffffffffffffff1683529284019291840191600101612865565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff811182821017156128dd576128dd61288b565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561292a5761292a61288b565b604052919050565b80356fffffffffffffffffffffffffffffffff8116811461258057600080fd5b60006060828403121561296457600080fd5b6040516060810181811067ffffffffffffffff821117156129875761298761288b565b6040529050808235801515811461299d57600080fd5b81526129ab60208401612932565b60208201526129bc60408401612932565b60408201525092915050565b600080600060e084860312156129dd57600080fd5b6129e684612568565b92506129f58560208601612952565b9150612a048560808601612952565b90509250925092565b600181811c90821680612a2157607f821691505b602082108103612a5a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b67ffffffffffffffff841681526040602082015260006121c0604083018486612a9f565b6020815260006108d6602083018486612a9f565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee1833603018112612b5457600080fd5b9190910192915050565b600082601f830112612b6f57600080fd5b813567ffffffffffffffff811115612b8957612b8961288b565b612bba60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016128e3565b818152846020838601011115612bcf57600080fd5b816020850160208301376000918101602001919091529392505050565b60006101208236031215612bff57600080fd5b612c076128ba565b612c1083612568565b815260208084013567ffffffffffffffff80821115612c2e57600080fd5b9085019036601f830112612c4157600080fd5b813581811115612c5357612c5361288b565b8060051b612c628582016128e3565b9182528381018501918581019036841115612c7c57600080fd5b86860192505b83831015612cb857823585811115612c9a5760008081fd5b612ca83689838a0101612b5e565b8352509186019190860190612c82565b8087890152505050506040860135925080831115612cd557600080fd5b5050612ce336828601612b5e565b604083015250612cf63660608501612952565b6060820152612d083660c08501612952565b608082015292915050565b601f8211156109f1576000816000526020600020601f850160051c81016020861015612d3c5750805b601f850160051c820191505b81811015612d5b57828155600101612d48565b505050505050565b815167ffffffffffffffff811115612d7d57612d7d61288b565b612d9181612d8b8454612a0d565b84612d13565b602080601f831160018114612de45760008415612dae5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612d5b565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015612e3157888601518255948401946001909101908401612e12565b5085821015612e6d57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff87168352806020840152612ea18184018761247f565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff9081166060870152908701511660808501529150612edf9050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e08301526121c0565b67ffffffffffffffff831681526040602082015260006108d6604083018461247f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561068b5761068b612f39565b67ffffffffffffffff8416815260e08101612fc760208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c08301526108d6565b6060810161068b82848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b808202811582820484141761068b5761068b612f39565b8082018082111561068b5761068b612f3956fea164736f6c6343000818000a", +} + +var MockLBTCTokenPoolABI = MockLBTCTokenPoolMetaData.ABI + +var MockLBTCTokenPoolBin = MockLBTCTokenPoolMetaData.Bin + +func DeployMockLBTCTokenPool(auth *bind.TransactOpts, backend bind.ContractBackend, token common.Address, allowlist []common.Address, rmnProxy common.Address, router common.Address, destPoolData []byte) (common.Address, *types.Transaction, *MockLBTCTokenPool, error) { + parsed, err := MockLBTCTokenPoolMetaData.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(MockLBTCTokenPoolBin), backend, token, allowlist, rmnProxy, router, destPoolData) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &MockLBTCTokenPool{address: address, abi: *parsed, MockLBTCTokenPoolCaller: MockLBTCTokenPoolCaller{contract: contract}, MockLBTCTokenPoolTransactor: MockLBTCTokenPoolTransactor{contract: contract}, MockLBTCTokenPoolFilterer: MockLBTCTokenPoolFilterer{contract: contract}}, nil +} + +type MockLBTCTokenPool struct { + address common.Address + abi abi.ABI + MockLBTCTokenPoolCaller + MockLBTCTokenPoolTransactor + MockLBTCTokenPoolFilterer +} + +type MockLBTCTokenPoolCaller struct { + contract *bind.BoundContract +} + +type MockLBTCTokenPoolTransactor struct { + contract *bind.BoundContract +} + +type MockLBTCTokenPoolFilterer struct { + contract *bind.BoundContract +} + +type MockLBTCTokenPoolSession struct { + Contract *MockLBTCTokenPool + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type MockLBTCTokenPoolCallerSession struct { + Contract *MockLBTCTokenPoolCaller + CallOpts bind.CallOpts +} + +type MockLBTCTokenPoolTransactorSession struct { + Contract *MockLBTCTokenPoolTransactor + TransactOpts bind.TransactOpts +} + +type MockLBTCTokenPoolRaw struct { + Contract *MockLBTCTokenPool +} + +type MockLBTCTokenPoolCallerRaw struct { + Contract *MockLBTCTokenPoolCaller +} + +type MockLBTCTokenPoolTransactorRaw struct { + Contract *MockLBTCTokenPoolTransactor +} + +func NewMockLBTCTokenPool(address common.Address, backend bind.ContractBackend) (*MockLBTCTokenPool, error) { + abi, err := abi.JSON(strings.NewReader(MockLBTCTokenPoolABI)) + if err != nil { + return nil, err + } + contract, err := bindMockLBTCTokenPool(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &MockLBTCTokenPool{address: address, abi: abi, MockLBTCTokenPoolCaller: MockLBTCTokenPoolCaller{contract: contract}, MockLBTCTokenPoolTransactor: MockLBTCTokenPoolTransactor{contract: contract}, MockLBTCTokenPoolFilterer: MockLBTCTokenPoolFilterer{contract: contract}}, nil +} + +func NewMockLBTCTokenPoolCaller(address common.Address, caller bind.ContractCaller) (*MockLBTCTokenPoolCaller, error) { + contract, err := bindMockLBTCTokenPool(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &MockLBTCTokenPoolCaller{contract: contract}, nil +} + +func NewMockLBTCTokenPoolTransactor(address common.Address, transactor bind.ContractTransactor) (*MockLBTCTokenPoolTransactor, error) { + contract, err := bindMockLBTCTokenPool(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &MockLBTCTokenPoolTransactor{contract: contract}, nil +} + +func NewMockLBTCTokenPoolFilterer(address common.Address, filterer bind.ContractFilterer) (*MockLBTCTokenPoolFilterer, error) { + contract, err := bindMockLBTCTokenPool(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &MockLBTCTokenPoolFilterer{contract: contract}, nil +} + +func bindMockLBTCTokenPool(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := MockLBTCTokenPoolMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _MockLBTCTokenPool.Contract.MockLBTCTokenPoolCaller.contract.Call(opts, result, method, params...) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _MockLBTCTokenPool.Contract.MockLBTCTokenPoolTransactor.contract.Transfer(opts) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _MockLBTCTokenPool.Contract.MockLBTCTokenPoolTransactor.contract.Transact(opts, method, params...) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _MockLBTCTokenPool.Contract.contract.Call(opts, result, method, params...) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _MockLBTCTokenPool.Contract.contract.Transfer(opts) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _MockLBTCTokenPool.Contract.contract.Transact(opts, method, params...) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCaller) GetAllowList(opts *bind.CallOpts) ([]common.Address, error) { + var out []interface{} + err := _MockLBTCTokenPool.contract.Call(opts, &out, "getAllowList") + + if err != nil { + return *new([]common.Address), err + } + + out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) + + return out0, err + +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolSession) GetAllowList() ([]common.Address, error) { + return _MockLBTCTokenPool.Contract.GetAllowList(&_MockLBTCTokenPool.CallOpts) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCallerSession) GetAllowList() ([]common.Address, error) { + return _MockLBTCTokenPool.Contract.GetAllowList(&_MockLBTCTokenPool.CallOpts) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCaller) GetAllowListEnabled(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _MockLBTCTokenPool.contract.Call(opts, &out, "getAllowListEnabled") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolSession) GetAllowListEnabled() (bool, error) { + return _MockLBTCTokenPool.Contract.GetAllowListEnabled(&_MockLBTCTokenPool.CallOpts) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCallerSession) GetAllowListEnabled() (bool, error) { + return _MockLBTCTokenPool.Contract.GetAllowListEnabled(&_MockLBTCTokenPool.CallOpts) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCaller) GetCurrentInboundRateLimiterState(opts *bind.CallOpts, remoteChainSelector uint64) (RateLimiterTokenBucket, error) { + var out []interface{} + err := _MockLBTCTokenPool.contract.Call(opts, &out, "getCurrentInboundRateLimiterState", remoteChainSelector) + + if err != nil { + return *new(RateLimiterTokenBucket), err + } + + out0 := *abi.ConvertType(out[0], new(RateLimiterTokenBucket)).(*RateLimiterTokenBucket) + + return out0, err + +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolSession) GetCurrentInboundRateLimiterState(remoteChainSelector uint64) (RateLimiterTokenBucket, error) { + return _MockLBTCTokenPool.Contract.GetCurrentInboundRateLimiterState(&_MockLBTCTokenPool.CallOpts, remoteChainSelector) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCallerSession) GetCurrentInboundRateLimiterState(remoteChainSelector uint64) (RateLimiterTokenBucket, error) { + return _MockLBTCTokenPool.Contract.GetCurrentInboundRateLimiterState(&_MockLBTCTokenPool.CallOpts, remoteChainSelector) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCaller) GetCurrentOutboundRateLimiterState(opts *bind.CallOpts, remoteChainSelector uint64) (RateLimiterTokenBucket, error) { + var out []interface{} + err := _MockLBTCTokenPool.contract.Call(opts, &out, "getCurrentOutboundRateLimiterState", remoteChainSelector) + + if err != nil { + return *new(RateLimiterTokenBucket), err + } + + out0 := *abi.ConvertType(out[0], new(RateLimiterTokenBucket)).(*RateLimiterTokenBucket) + + return out0, err + +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolSession) GetCurrentOutboundRateLimiterState(remoteChainSelector uint64) (RateLimiterTokenBucket, error) { + return _MockLBTCTokenPool.Contract.GetCurrentOutboundRateLimiterState(&_MockLBTCTokenPool.CallOpts, remoteChainSelector) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCallerSession) GetCurrentOutboundRateLimiterState(remoteChainSelector uint64) (RateLimiterTokenBucket, error) { + return _MockLBTCTokenPool.Contract.GetCurrentOutboundRateLimiterState(&_MockLBTCTokenPool.CallOpts, remoteChainSelector) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCaller) GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _MockLBTCTokenPool.contract.Call(opts, &out, "getRateLimitAdmin") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolSession) GetRateLimitAdmin() (common.Address, error) { + return _MockLBTCTokenPool.Contract.GetRateLimitAdmin(&_MockLBTCTokenPool.CallOpts) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCallerSession) GetRateLimitAdmin() (common.Address, error) { + return _MockLBTCTokenPool.Contract.GetRateLimitAdmin(&_MockLBTCTokenPool.CallOpts) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCaller) GetRemotePools(opts *bind.CallOpts, remoteChainSelector uint64) ([][]byte, error) { + var out []interface{} + err := _MockLBTCTokenPool.contract.Call(opts, &out, "getRemotePools", remoteChainSelector) + + if err != nil { + return *new([][]byte), err + } + + out0 := *abi.ConvertType(out[0], new([][]byte)).(*[][]byte) + + return out0, err + +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolSession) GetRemotePools(remoteChainSelector uint64) ([][]byte, error) { + return _MockLBTCTokenPool.Contract.GetRemotePools(&_MockLBTCTokenPool.CallOpts, remoteChainSelector) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCallerSession) GetRemotePools(remoteChainSelector uint64) ([][]byte, error) { + return _MockLBTCTokenPool.Contract.GetRemotePools(&_MockLBTCTokenPool.CallOpts, remoteChainSelector) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCaller) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { + var out []interface{} + err := _MockLBTCTokenPool.contract.Call(opts, &out, "getRemoteToken", remoteChainSelector) + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolSession) GetRemoteToken(remoteChainSelector uint64) ([]byte, error) { + return _MockLBTCTokenPool.Contract.GetRemoteToken(&_MockLBTCTokenPool.CallOpts, remoteChainSelector) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCallerSession) GetRemoteToken(remoteChainSelector uint64) ([]byte, error) { + return _MockLBTCTokenPool.Contract.GetRemoteToken(&_MockLBTCTokenPool.CallOpts, remoteChainSelector) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCaller) GetRmnProxy(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _MockLBTCTokenPool.contract.Call(opts, &out, "getRmnProxy") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolSession) GetRmnProxy() (common.Address, error) { + return _MockLBTCTokenPool.Contract.GetRmnProxy(&_MockLBTCTokenPool.CallOpts) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCallerSession) GetRmnProxy() (common.Address, error) { + return _MockLBTCTokenPool.Contract.GetRmnProxy(&_MockLBTCTokenPool.CallOpts) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCaller) GetRouter(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _MockLBTCTokenPool.contract.Call(opts, &out, "getRouter") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolSession) GetRouter() (common.Address, error) { + return _MockLBTCTokenPool.Contract.GetRouter(&_MockLBTCTokenPool.CallOpts) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCallerSession) GetRouter() (common.Address, error) { + return _MockLBTCTokenPool.Contract.GetRouter(&_MockLBTCTokenPool.CallOpts) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCaller) GetSupportedChains(opts *bind.CallOpts) ([]uint64, error) { + var out []interface{} + err := _MockLBTCTokenPool.contract.Call(opts, &out, "getSupportedChains") + + if err != nil { + return *new([]uint64), err + } + + out0 := *abi.ConvertType(out[0], new([]uint64)).(*[]uint64) + + return out0, err + +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolSession) GetSupportedChains() ([]uint64, error) { + return _MockLBTCTokenPool.Contract.GetSupportedChains(&_MockLBTCTokenPool.CallOpts) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCallerSession) GetSupportedChains() ([]uint64, error) { + return _MockLBTCTokenPool.Contract.GetSupportedChains(&_MockLBTCTokenPool.CallOpts) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCaller) GetToken(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _MockLBTCTokenPool.contract.Call(opts, &out, "getToken") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolSession) GetToken() (common.Address, error) { + return _MockLBTCTokenPool.Contract.GetToken(&_MockLBTCTokenPool.CallOpts) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCallerSession) GetToken() (common.Address, error) { + return _MockLBTCTokenPool.Contract.GetToken(&_MockLBTCTokenPool.CallOpts) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCaller) GetTokenDecimals(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _MockLBTCTokenPool.contract.Call(opts, &out, "getTokenDecimals") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolSession) GetTokenDecimals() (uint8, error) { + return _MockLBTCTokenPool.Contract.GetTokenDecimals(&_MockLBTCTokenPool.CallOpts) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCallerSession) GetTokenDecimals() (uint8, error) { + return _MockLBTCTokenPool.Contract.GetTokenDecimals(&_MockLBTCTokenPool.CallOpts) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCaller) IDestPoolData(opts *bind.CallOpts) ([]byte, error) { + var out []interface{} + err := _MockLBTCTokenPool.contract.Call(opts, &out, "i_destPoolData") + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolSession) IDestPoolData() ([]byte, error) { + return _MockLBTCTokenPool.Contract.IDestPoolData(&_MockLBTCTokenPool.CallOpts) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCallerSession) IDestPoolData() ([]byte, error) { + return _MockLBTCTokenPool.Contract.IDestPoolData(&_MockLBTCTokenPool.CallOpts) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCaller) IsRemotePool(opts *bind.CallOpts, remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { + var out []interface{} + err := _MockLBTCTokenPool.contract.Call(opts, &out, "isRemotePool", remoteChainSelector, remotePoolAddress) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolSession) IsRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { + return _MockLBTCTokenPool.Contract.IsRemotePool(&_MockLBTCTokenPool.CallOpts, remoteChainSelector, remotePoolAddress) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCallerSession) IsRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { + return _MockLBTCTokenPool.Contract.IsRemotePool(&_MockLBTCTokenPool.CallOpts, remoteChainSelector, remotePoolAddress) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCaller) IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error) { + var out []interface{} + err := _MockLBTCTokenPool.contract.Call(opts, &out, "isSupportedChain", remoteChainSelector) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolSession) IsSupportedChain(remoteChainSelector uint64) (bool, error) { + return _MockLBTCTokenPool.Contract.IsSupportedChain(&_MockLBTCTokenPool.CallOpts, remoteChainSelector) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCallerSession) IsSupportedChain(remoteChainSelector uint64) (bool, error) { + return _MockLBTCTokenPool.Contract.IsSupportedChain(&_MockLBTCTokenPool.CallOpts, remoteChainSelector) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCaller) IsSupportedToken(opts *bind.CallOpts, token common.Address) (bool, error) { + var out []interface{} + err := _MockLBTCTokenPool.contract.Call(opts, &out, "isSupportedToken", token) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolSession) IsSupportedToken(token common.Address) (bool, error) { + return _MockLBTCTokenPool.Contract.IsSupportedToken(&_MockLBTCTokenPool.CallOpts, token) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCallerSession) IsSupportedToken(token common.Address) (bool, error) { + return _MockLBTCTokenPool.Contract.IsSupportedToken(&_MockLBTCTokenPool.CallOpts, token) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _MockLBTCTokenPool.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 (_MockLBTCTokenPool *MockLBTCTokenPoolSession) Owner() (common.Address, error) { + return _MockLBTCTokenPool.Contract.Owner(&_MockLBTCTokenPool.CallOpts) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCallerSession) Owner() (common.Address, error) { + return _MockLBTCTokenPool.Contract.Owner(&_MockLBTCTokenPool.CallOpts) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + var out []interface{} + err := _MockLBTCTokenPool.contract.Call(opts, &out, "supportsInterface", interfaceId) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _MockLBTCTokenPool.Contract.SupportsInterface(&_MockLBTCTokenPool.CallOpts, interfaceId) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _MockLBTCTokenPool.Contract.SupportsInterface(&_MockLBTCTokenPool.CallOpts, interfaceId) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _MockLBTCTokenPool.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolSession) TypeAndVersion() (string, error) { + return _MockLBTCTokenPool.Contract.TypeAndVersion(&_MockLBTCTokenPool.CallOpts) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolCallerSession) TypeAndVersion() (string, error) { + return _MockLBTCTokenPool.Contract.TypeAndVersion(&_MockLBTCTokenPool.CallOpts) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _MockLBTCTokenPool.contract.Transact(opts, "acceptOwnership") +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolSession) AcceptOwnership() (*types.Transaction, error) { + return _MockLBTCTokenPool.Contract.AcceptOwnership(&_MockLBTCTokenPool.TransactOpts) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _MockLBTCTokenPool.Contract.AcceptOwnership(&_MockLBTCTokenPool.TransactOpts) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolTransactor) AddRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _MockLBTCTokenPool.contract.Transact(opts, "addRemotePool", remoteChainSelector, remotePoolAddress) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolSession) AddRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _MockLBTCTokenPool.Contract.AddRemotePool(&_MockLBTCTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolTransactorSession) AddRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _MockLBTCTokenPool.Contract.AddRemotePool(&_MockLBTCTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolTransactor) ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) { + return _MockLBTCTokenPool.contract.Transact(opts, "applyAllowListUpdates", removes, adds) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolSession) ApplyAllowListUpdates(removes []common.Address, adds []common.Address) (*types.Transaction, error) { + return _MockLBTCTokenPool.Contract.ApplyAllowListUpdates(&_MockLBTCTokenPool.TransactOpts, removes, adds) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolTransactorSession) ApplyAllowListUpdates(removes []common.Address, adds []common.Address) (*types.Transaction, error) { + return _MockLBTCTokenPool.Contract.ApplyAllowListUpdates(&_MockLBTCTokenPool.TransactOpts, removes, adds) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolTransactor) ApplyChainUpdates(opts *bind.TransactOpts, remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { + return _MockLBTCTokenPool.contract.Transact(opts, "applyChainUpdates", remoteChainSelectorsToRemove, chainsToAdd) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolSession) ApplyChainUpdates(remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { + return _MockLBTCTokenPool.Contract.ApplyChainUpdates(&_MockLBTCTokenPool.TransactOpts, remoteChainSelectorsToRemove, chainsToAdd) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolTransactorSession) ApplyChainUpdates(remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { + return _MockLBTCTokenPool.Contract.ApplyChainUpdates(&_MockLBTCTokenPool.TransactOpts, remoteChainSelectorsToRemove, chainsToAdd) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolTransactor) LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) { + return _MockLBTCTokenPool.contract.Transact(opts, "lockOrBurn", lockOrBurnIn) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolSession) LockOrBurn(lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) { + return _MockLBTCTokenPool.Contract.LockOrBurn(&_MockLBTCTokenPool.TransactOpts, lockOrBurnIn) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolTransactorSession) LockOrBurn(lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) { + return _MockLBTCTokenPool.Contract.LockOrBurn(&_MockLBTCTokenPool.TransactOpts, lockOrBurnIn) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolTransactor) ReleaseOrMint(opts *bind.TransactOpts, releaseOrMintIn PoolReleaseOrMintInV1) (*types.Transaction, error) { + return _MockLBTCTokenPool.contract.Transact(opts, "releaseOrMint", releaseOrMintIn) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolSession) ReleaseOrMint(releaseOrMintIn PoolReleaseOrMintInV1) (*types.Transaction, error) { + return _MockLBTCTokenPool.Contract.ReleaseOrMint(&_MockLBTCTokenPool.TransactOpts, releaseOrMintIn) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolTransactorSession) ReleaseOrMint(releaseOrMintIn PoolReleaseOrMintInV1) (*types.Transaction, error) { + return _MockLBTCTokenPool.Contract.ReleaseOrMint(&_MockLBTCTokenPool.TransactOpts, releaseOrMintIn) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolTransactor) RemoveRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _MockLBTCTokenPool.contract.Transact(opts, "removeRemotePool", remoteChainSelector, remotePoolAddress) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolSession) RemoveRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _MockLBTCTokenPool.Contract.RemoveRemotePool(&_MockLBTCTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolTransactorSession) RemoveRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _MockLBTCTokenPool.Contract.RemoveRemotePool(&_MockLBTCTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolTransactor) SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) { + return _MockLBTCTokenPool.contract.Transact(opts, "setChainRateLimiterConfig", remoteChainSelector, outboundConfig, inboundConfig) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolSession) SetChainRateLimiterConfig(remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) { + return _MockLBTCTokenPool.Contract.SetChainRateLimiterConfig(&_MockLBTCTokenPool.TransactOpts, remoteChainSelector, outboundConfig, inboundConfig) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolTransactorSession) SetChainRateLimiterConfig(remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) { + return _MockLBTCTokenPool.Contract.SetChainRateLimiterConfig(&_MockLBTCTokenPool.TransactOpts, remoteChainSelector, outboundConfig, inboundConfig) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolTransactor) SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) { + return _MockLBTCTokenPool.contract.Transact(opts, "setRateLimitAdmin", rateLimitAdmin) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolSession) SetRateLimitAdmin(rateLimitAdmin common.Address) (*types.Transaction, error) { + return _MockLBTCTokenPool.Contract.SetRateLimitAdmin(&_MockLBTCTokenPool.TransactOpts, rateLimitAdmin) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolTransactorSession) SetRateLimitAdmin(rateLimitAdmin common.Address) (*types.Transaction, error) { + return _MockLBTCTokenPool.Contract.SetRateLimitAdmin(&_MockLBTCTokenPool.TransactOpts, rateLimitAdmin) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolTransactor) SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) { + return _MockLBTCTokenPool.contract.Transact(opts, "setRouter", newRouter) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolSession) SetRouter(newRouter common.Address) (*types.Transaction, error) { + return _MockLBTCTokenPool.Contract.SetRouter(&_MockLBTCTokenPool.TransactOpts, newRouter) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolTransactorSession) SetRouter(newRouter common.Address) (*types.Transaction, error) { + return _MockLBTCTokenPool.Contract.SetRouter(&_MockLBTCTokenPool.TransactOpts, newRouter) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _MockLBTCTokenPool.contract.Transact(opts, "transferOwnership", to) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _MockLBTCTokenPool.Contract.TransferOwnership(&_MockLBTCTokenPool.TransactOpts, to) +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _MockLBTCTokenPool.Contract.TransferOwnership(&_MockLBTCTokenPool.TransactOpts, to) +} + +type MockLBTCTokenPoolAllowListAddIterator struct { + Event *MockLBTCTokenPoolAllowListAdd + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *MockLBTCTokenPoolAllowListAddIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(MockLBTCTokenPoolAllowListAdd) + 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(MockLBTCTokenPoolAllowListAdd) + 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 *MockLBTCTokenPoolAllowListAddIterator) Error() error { + return it.fail +} + +func (it *MockLBTCTokenPoolAllowListAddIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type MockLBTCTokenPoolAllowListAdd struct { + Sender common.Address + Raw types.Log +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) FilterAllowListAdd(opts *bind.FilterOpts) (*MockLBTCTokenPoolAllowListAddIterator, error) { + + logs, sub, err := _MockLBTCTokenPool.contract.FilterLogs(opts, "AllowListAdd") + if err != nil { + return nil, err + } + return &MockLBTCTokenPoolAllowListAddIterator{contract: _MockLBTCTokenPool.contract, event: "AllowListAdd", logs: logs, sub: sub}, nil +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) WatchAllowListAdd(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolAllowListAdd) (event.Subscription, error) { + + logs, sub, err := _MockLBTCTokenPool.contract.WatchLogs(opts, "AllowListAdd") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(MockLBTCTokenPoolAllowListAdd) + if err := _MockLBTCTokenPool.contract.UnpackLog(event, "AllowListAdd", 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 (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) ParseAllowListAdd(log types.Log) (*MockLBTCTokenPoolAllowListAdd, error) { + event := new(MockLBTCTokenPoolAllowListAdd) + if err := _MockLBTCTokenPool.contract.UnpackLog(event, "AllowListAdd", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type MockLBTCTokenPoolAllowListRemoveIterator struct { + Event *MockLBTCTokenPoolAllowListRemove + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *MockLBTCTokenPoolAllowListRemoveIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(MockLBTCTokenPoolAllowListRemove) + 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(MockLBTCTokenPoolAllowListRemove) + 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 *MockLBTCTokenPoolAllowListRemoveIterator) Error() error { + return it.fail +} + +func (it *MockLBTCTokenPoolAllowListRemoveIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type MockLBTCTokenPoolAllowListRemove struct { + Sender common.Address + Raw types.Log +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) FilterAllowListRemove(opts *bind.FilterOpts) (*MockLBTCTokenPoolAllowListRemoveIterator, error) { + + logs, sub, err := _MockLBTCTokenPool.contract.FilterLogs(opts, "AllowListRemove") + if err != nil { + return nil, err + } + return &MockLBTCTokenPoolAllowListRemoveIterator{contract: _MockLBTCTokenPool.contract, event: "AllowListRemove", logs: logs, sub: sub}, nil +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) WatchAllowListRemove(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolAllowListRemove) (event.Subscription, error) { + + logs, sub, err := _MockLBTCTokenPool.contract.WatchLogs(opts, "AllowListRemove") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(MockLBTCTokenPoolAllowListRemove) + if err := _MockLBTCTokenPool.contract.UnpackLog(event, "AllowListRemove", 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 (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) ParseAllowListRemove(log types.Log) (*MockLBTCTokenPoolAllowListRemove, error) { + event := new(MockLBTCTokenPoolAllowListRemove) + if err := _MockLBTCTokenPool.contract.UnpackLog(event, "AllowListRemove", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type MockLBTCTokenPoolBurnedIterator struct { + Event *MockLBTCTokenPoolBurned + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *MockLBTCTokenPoolBurnedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(MockLBTCTokenPoolBurned) + 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(MockLBTCTokenPoolBurned) + 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 *MockLBTCTokenPoolBurnedIterator) Error() error { + return it.fail +} + +func (it *MockLBTCTokenPoolBurnedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type MockLBTCTokenPoolBurned struct { + Sender common.Address + Amount *big.Int + Raw types.Log +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) FilterBurned(opts *bind.FilterOpts, sender []common.Address) (*MockLBTCTokenPoolBurnedIterator, error) { + + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _MockLBTCTokenPool.contract.FilterLogs(opts, "Burned", senderRule) + if err != nil { + return nil, err + } + return &MockLBTCTokenPoolBurnedIterator{contract: _MockLBTCTokenPool.contract, event: "Burned", logs: logs, sub: sub}, nil +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) WatchBurned(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolBurned, sender []common.Address) (event.Subscription, error) { + + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _MockLBTCTokenPool.contract.WatchLogs(opts, "Burned", 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(MockLBTCTokenPoolBurned) + if err := _MockLBTCTokenPool.contract.UnpackLog(event, "Burned", 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 (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) ParseBurned(log types.Log) (*MockLBTCTokenPoolBurned, error) { + event := new(MockLBTCTokenPoolBurned) + if err := _MockLBTCTokenPool.contract.UnpackLog(event, "Burned", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type MockLBTCTokenPoolChainAddedIterator struct { + Event *MockLBTCTokenPoolChainAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *MockLBTCTokenPoolChainAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(MockLBTCTokenPoolChainAdded) + 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(MockLBTCTokenPoolChainAdded) + 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 *MockLBTCTokenPoolChainAddedIterator) Error() error { + return it.fail +} + +func (it *MockLBTCTokenPoolChainAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type MockLBTCTokenPoolChainAdded struct { + RemoteChainSelector uint64 + RemoteToken []byte + OutboundRateLimiterConfig RateLimiterConfig + InboundRateLimiterConfig RateLimiterConfig + Raw types.Log +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) FilterChainAdded(opts *bind.FilterOpts) (*MockLBTCTokenPoolChainAddedIterator, error) { + + logs, sub, err := _MockLBTCTokenPool.contract.FilterLogs(opts, "ChainAdded") + if err != nil { + return nil, err + } + return &MockLBTCTokenPoolChainAddedIterator{contract: _MockLBTCTokenPool.contract, event: "ChainAdded", logs: logs, sub: sub}, nil +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) WatchChainAdded(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolChainAdded) (event.Subscription, error) { + + logs, sub, err := _MockLBTCTokenPool.contract.WatchLogs(opts, "ChainAdded") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(MockLBTCTokenPoolChainAdded) + if err := _MockLBTCTokenPool.contract.UnpackLog(event, "ChainAdded", 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 (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) ParseChainAdded(log types.Log) (*MockLBTCTokenPoolChainAdded, error) { + event := new(MockLBTCTokenPoolChainAdded) + if err := _MockLBTCTokenPool.contract.UnpackLog(event, "ChainAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type MockLBTCTokenPoolChainConfiguredIterator struct { + Event *MockLBTCTokenPoolChainConfigured + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *MockLBTCTokenPoolChainConfiguredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(MockLBTCTokenPoolChainConfigured) + 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(MockLBTCTokenPoolChainConfigured) + 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 *MockLBTCTokenPoolChainConfiguredIterator) Error() error { + return it.fail +} + +func (it *MockLBTCTokenPoolChainConfiguredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type MockLBTCTokenPoolChainConfigured struct { + RemoteChainSelector uint64 + OutboundRateLimiterConfig RateLimiterConfig + InboundRateLimiterConfig RateLimiterConfig + Raw types.Log +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) FilterChainConfigured(opts *bind.FilterOpts) (*MockLBTCTokenPoolChainConfiguredIterator, error) { + + logs, sub, err := _MockLBTCTokenPool.contract.FilterLogs(opts, "ChainConfigured") + if err != nil { + return nil, err + } + return &MockLBTCTokenPoolChainConfiguredIterator{contract: _MockLBTCTokenPool.contract, event: "ChainConfigured", logs: logs, sub: sub}, nil +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) WatchChainConfigured(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolChainConfigured) (event.Subscription, error) { + + logs, sub, err := _MockLBTCTokenPool.contract.WatchLogs(opts, "ChainConfigured") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(MockLBTCTokenPoolChainConfigured) + if err := _MockLBTCTokenPool.contract.UnpackLog(event, "ChainConfigured", 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 (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) ParseChainConfigured(log types.Log) (*MockLBTCTokenPoolChainConfigured, error) { + event := new(MockLBTCTokenPoolChainConfigured) + if err := _MockLBTCTokenPool.contract.UnpackLog(event, "ChainConfigured", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type MockLBTCTokenPoolChainRemovedIterator struct { + Event *MockLBTCTokenPoolChainRemoved + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *MockLBTCTokenPoolChainRemovedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(MockLBTCTokenPoolChainRemoved) + 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(MockLBTCTokenPoolChainRemoved) + 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 *MockLBTCTokenPoolChainRemovedIterator) Error() error { + return it.fail +} + +func (it *MockLBTCTokenPoolChainRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type MockLBTCTokenPoolChainRemoved struct { + RemoteChainSelector uint64 + Raw types.Log +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) FilterChainRemoved(opts *bind.FilterOpts) (*MockLBTCTokenPoolChainRemovedIterator, error) { + + logs, sub, err := _MockLBTCTokenPool.contract.FilterLogs(opts, "ChainRemoved") + if err != nil { + return nil, err + } + return &MockLBTCTokenPoolChainRemovedIterator{contract: _MockLBTCTokenPool.contract, event: "ChainRemoved", logs: logs, sub: sub}, nil +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) WatchChainRemoved(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolChainRemoved) (event.Subscription, error) { + + logs, sub, err := _MockLBTCTokenPool.contract.WatchLogs(opts, "ChainRemoved") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(MockLBTCTokenPoolChainRemoved) + if err := _MockLBTCTokenPool.contract.UnpackLog(event, "ChainRemoved", 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 (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) ParseChainRemoved(log types.Log) (*MockLBTCTokenPoolChainRemoved, error) { + event := new(MockLBTCTokenPoolChainRemoved) + if err := _MockLBTCTokenPool.contract.UnpackLog(event, "ChainRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type MockLBTCTokenPoolConfigChangedIterator struct { + Event *MockLBTCTokenPoolConfigChanged + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *MockLBTCTokenPoolConfigChangedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(MockLBTCTokenPoolConfigChanged) + 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(MockLBTCTokenPoolConfigChanged) + 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 *MockLBTCTokenPoolConfigChangedIterator) Error() error { + return it.fail +} + +func (it *MockLBTCTokenPoolConfigChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type MockLBTCTokenPoolConfigChanged struct { + Config RateLimiterConfig + Raw types.Log +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) FilterConfigChanged(opts *bind.FilterOpts) (*MockLBTCTokenPoolConfigChangedIterator, error) { + + logs, sub, err := _MockLBTCTokenPool.contract.FilterLogs(opts, "ConfigChanged") + if err != nil { + return nil, err + } + return &MockLBTCTokenPoolConfigChangedIterator{contract: _MockLBTCTokenPool.contract, event: "ConfigChanged", logs: logs, sub: sub}, nil +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) WatchConfigChanged(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolConfigChanged) (event.Subscription, error) { + + logs, sub, err := _MockLBTCTokenPool.contract.WatchLogs(opts, "ConfigChanged") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(MockLBTCTokenPoolConfigChanged) + if err := _MockLBTCTokenPool.contract.UnpackLog(event, "ConfigChanged", 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 (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) ParseConfigChanged(log types.Log) (*MockLBTCTokenPoolConfigChanged, error) { + event := new(MockLBTCTokenPoolConfigChanged) + if err := _MockLBTCTokenPool.contract.UnpackLog(event, "ConfigChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type MockLBTCTokenPoolLockedIterator struct { + Event *MockLBTCTokenPoolLocked + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *MockLBTCTokenPoolLockedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(MockLBTCTokenPoolLocked) + 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(MockLBTCTokenPoolLocked) + 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 *MockLBTCTokenPoolLockedIterator) Error() error { + return it.fail +} + +func (it *MockLBTCTokenPoolLockedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type MockLBTCTokenPoolLocked struct { + Sender common.Address + Amount *big.Int + Raw types.Log +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) FilterLocked(opts *bind.FilterOpts, sender []common.Address) (*MockLBTCTokenPoolLockedIterator, error) { + + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _MockLBTCTokenPool.contract.FilterLogs(opts, "Locked", senderRule) + if err != nil { + return nil, err + } + return &MockLBTCTokenPoolLockedIterator{contract: _MockLBTCTokenPool.contract, event: "Locked", logs: logs, sub: sub}, nil +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) WatchLocked(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolLocked, sender []common.Address) (event.Subscription, error) { + + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _MockLBTCTokenPool.contract.WatchLogs(opts, "Locked", 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(MockLBTCTokenPoolLocked) + if err := _MockLBTCTokenPool.contract.UnpackLog(event, "Locked", 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 (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) ParseLocked(log types.Log) (*MockLBTCTokenPoolLocked, error) { + event := new(MockLBTCTokenPoolLocked) + if err := _MockLBTCTokenPool.contract.UnpackLog(event, "Locked", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type MockLBTCTokenPoolMintedIterator struct { + Event *MockLBTCTokenPoolMinted + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *MockLBTCTokenPoolMintedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(MockLBTCTokenPoolMinted) + 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(MockLBTCTokenPoolMinted) + 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 *MockLBTCTokenPoolMintedIterator) Error() error { + return it.fail +} + +func (it *MockLBTCTokenPoolMintedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type MockLBTCTokenPoolMinted struct { + Sender common.Address + Recipient common.Address + Amount *big.Int + Raw types.Log +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) FilterMinted(opts *bind.FilterOpts, sender []common.Address, recipient []common.Address) (*MockLBTCTokenPoolMintedIterator, error) { + + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + var recipientRule []interface{} + for _, recipientItem := range recipient { + recipientRule = append(recipientRule, recipientItem) + } + + logs, sub, err := _MockLBTCTokenPool.contract.FilterLogs(opts, "Minted", senderRule, recipientRule) + if err != nil { + return nil, err + } + return &MockLBTCTokenPoolMintedIterator{contract: _MockLBTCTokenPool.contract, event: "Minted", logs: logs, sub: sub}, nil +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) WatchMinted(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolMinted, sender []common.Address, recipient []common.Address) (event.Subscription, error) { + + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + var recipientRule []interface{} + for _, recipientItem := range recipient { + recipientRule = append(recipientRule, recipientItem) + } + + logs, sub, err := _MockLBTCTokenPool.contract.WatchLogs(opts, "Minted", senderRule, recipientRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(MockLBTCTokenPoolMinted) + if err := _MockLBTCTokenPool.contract.UnpackLog(event, "Minted", 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 (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) ParseMinted(log types.Log) (*MockLBTCTokenPoolMinted, error) { + event := new(MockLBTCTokenPoolMinted) + if err := _MockLBTCTokenPool.contract.UnpackLog(event, "Minted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type MockLBTCTokenPoolOwnershipTransferRequestedIterator struct { + Event *MockLBTCTokenPoolOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *MockLBTCTokenPoolOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(MockLBTCTokenPoolOwnershipTransferRequested) + 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(MockLBTCTokenPoolOwnershipTransferRequested) + 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 *MockLBTCTokenPoolOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *MockLBTCTokenPoolOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type MockLBTCTokenPoolOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*MockLBTCTokenPoolOwnershipTransferRequestedIterator, 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 := _MockLBTCTokenPool.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &MockLBTCTokenPoolOwnershipTransferRequestedIterator{contract: _MockLBTCTokenPool.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolOwnershipTransferRequested, 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 := _MockLBTCTokenPool.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(MockLBTCTokenPoolOwnershipTransferRequested) + if err := _MockLBTCTokenPool.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 (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) ParseOwnershipTransferRequested(log types.Log) (*MockLBTCTokenPoolOwnershipTransferRequested, error) { + event := new(MockLBTCTokenPoolOwnershipTransferRequested) + if err := _MockLBTCTokenPool.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type MockLBTCTokenPoolOwnershipTransferredIterator struct { + Event *MockLBTCTokenPoolOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *MockLBTCTokenPoolOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(MockLBTCTokenPoolOwnershipTransferred) + 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(MockLBTCTokenPoolOwnershipTransferred) + 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 *MockLBTCTokenPoolOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *MockLBTCTokenPoolOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type MockLBTCTokenPoolOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*MockLBTCTokenPoolOwnershipTransferredIterator, 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 := _MockLBTCTokenPool.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &MockLBTCTokenPoolOwnershipTransferredIterator{contract: _MockLBTCTokenPool.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolOwnershipTransferred, 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 := _MockLBTCTokenPool.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(MockLBTCTokenPoolOwnershipTransferred) + if err := _MockLBTCTokenPool.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 (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) ParseOwnershipTransferred(log types.Log) (*MockLBTCTokenPoolOwnershipTransferred, error) { + event := new(MockLBTCTokenPoolOwnershipTransferred) + if err := _MockLBTCTokenPool.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type MockLBTCTokenPoolRateLimitAdminSetIterator struct { + Event *MockLBTCTokenPoolRateLimitAdminSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *MockLBTCTokenPoolRateLimitAdminSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(MockLBTCTokenPoolRateLimitAdminSet) + 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(MockLBTCTokenPoolRateLimitAdminSet) + 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 *MockLBTCTokenPoolRateLimitAdminSetIterator) Error() error { + return it.fail +} + +func (it *MockLBTCTokenPoolRateLimitAdminSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type MockLBTCTokenPoolRateLimitAdminSet struct { + RateLimitAdmin common.Address + Raw types.Log +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) FilterRateLimitAdminSet(opts *bind.FilterOpts) (*MockLBTCTokenPoolRateLimitAdminSetIterator, error) { + + logs, sub, err := _MockLBTCTokenPool.contract.FilterLogs(opts, "RateLimitAdminSet") + if err != nil { + return nil, err + } + return &MockLBTCTokenPoolRateLimitAdminSetIterator{contract: _MockLBTCTokenPool.contract, event: "RateLimitAdminSet", logs: logs, sub: sub}, nil +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) WatchRateLimitAdminSet(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolRateLimitAdminSet) (event.Subscription, error) { + + logs, sub, err := _MockLBTCTokenPool.contract.WatchLogs(opts, "RateLimitAdminSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(MockLBTCTokenPoolRateLimitAdminSet) + if err := _MockLBTCTokenPool.contract.UnpackLog(event, "RateLimitAdminSet", 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 (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) ParseRateLimitAdminSet(log types.Log) (*MockLBTCTokenPoolRateLimitAdminSet, error) { + event := new(MockLBTCTokenPoolRateLimitAdminSet) + if err := _MockLBTCTokenPool.contract.UnpackLog(event, "RateLimitAdminSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type MockLBTCTokenPoolReleasedIterator struct { + Event *MockLBTCTokenPoolReleased + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *MockLBTCTokenPoolReleasedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(MockLBTCTokenPoolReleased) + 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(MockLBTCTokenPoolReleased) + 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 *MockLBTCTokenPoolReleasedIterator) Error() error { + return it.fail +} + +func (it *MockLBTCTokenPoolReleasedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type MockLBTCTokenPoolReleased struct { + Sender common.Address + Recipient common.Address + Amount *big.Int + Raw types.Log +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) FilterReleased(opts *bind.FilterOpts, sender []common.Address, recipient []common.Address) (*MockLBTCTokenPoolReleasedIterator, error) { + + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + var recipientRule []interface{} + for _, recipientItem := range recipient { + recipientRule = append(recipientRule, recipientItem) + } + + logs, sub, err := _MockLBTCTokenPool.contract.FilterLogs(opts, "Released", senderRule, recipientRule) + if err != nil { + return nil, err + } + return &MockLBTCTokenPoolReleasedIterator{contract: _MockLBTCTokenPool.contract, event: "Released", logs: logs, sub: sub}, nil +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) WatchReleased(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolReleased, sender []common.Address, recipient []common.Address) (event.Subscription, error) { + + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + var recipientRule []interface{} + for _, recipientItem := range recipient { + recipientRule = append(recipientRule, recipientItem) + } + + logs, sub, err := _MockLBTCTokenPool.contract.WatchLogs(opts, "Released", senderRule, recipientRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(MockLBTCTokenPoolReleased) + if err := _MockLBTCTokenPool.contract.UnpackLog(event, "Released", 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 (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) ParseReleased(log types.Log) (*MockLBTCTokenPoolReleased, error) { + event := new(MockLBTCTokenPoolReleased) + if err := _MockLBTCTokenPool.contract.UnpackLog(event, "Released", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type MockLBTCTokenPoolRemotePoolAddedIterator struct { + Event *MockLBTCTokenPoolRemotePoolAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *MockLBTCTokenPoolRemotePoolAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(MockLBTCTokenPoolRemotePoolAdded) + 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(MockLBTCTokenPoolRemotePoolAdded) + 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 *MockLBTCTokenPoolRemotePoolAddedIterator) Error() error { + return it.fail +} + +func (it *MockLBTCTokenPoolRemotePoolAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type MockLBTCTokenPoolRemotePoolAdded struct { + RemoteChainSelector uint64 + RemotePoolAddress []byte + Raw types.Log +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) FilterRemotePoolAdded(opts *bind.FilterOpts, remoteChainSelector []uint64) (*MockLBTCTokenPoolRemotePoolAddedIterator, error) { + + var remoteChainSelectorRule []interface{} + for _, remoteChainSelectorItem := range remoteChainSelector { + remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) + } + + logs, sub, err := _MockLBTCTokenPool.contract.FilterLogs(opts, "RemotePoolAdded", remoteChainSelectorRule) + if err != nil { + return nil, err + } + return &MockLBTCTokenPoolRemotePoolAddedIterator{contract: _MockLBTCTokenPool.contract, event: "RemotePoolAdded", logs: logs, sub: sub}, nil +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) WatchRemotePoolAdded(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolRemotePoolAdded, remoteChainSelector []uint64) (event.Subscription, error) { + + var remoteChainSelectorRule []interface{} + for _, remoteChainSelectorItem := range remoteChainSelector { + remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) + } + + logs, sub, err := _MockLBTCTokenPool.contract.WatchLogs(opts, "RemotePoolAdded", remoteChainSelectorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(MockLBTCTokenPoolRemotePoolAdded) + if err := _MockLBTCTokenPool.contract.UnpackLog(event, "RemotePoolAdded", 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 (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) ParseRemotePoolAdded(log types.Log) (*MockLBTCTokenPoolRemotePoolAdded, error) { + event := new(MockLBTCTokenPoolRemotePoolAdded) + if err := _MockLBTCTokenPool.contract.UnpackLog(event, "RemotePoolAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type MockLBTCTokenPoolRemotePoolRemovedIterator struct { + Event *MockLBTCTokenPoolRemotePoolRemoved + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *MockLBTCTokenPoolRemotePoolRemovedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(MockLBTCTokenPoolRemotePoolRemoved) + 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(MockLBTCTokenPoolRemotePoolRemoved) + 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 *MockLBTCTokenPoolRemotePoolRemovedIterator) Error() error { + return it.fail +} + +func (it *MockLBTCTokenPoolRemotePoolRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type MockLBTCTokenPoolRemotePoolRemoved struct { + RemoteChainSelector uint64 + RemotePoolAddress []byte + Raw types.Log +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) FilterRemotePoolRemoved(opts *bind.FilterOpts, remoteChainSelector []uint64) (*MockLBTCTokenPoolRemotePoolRemovedIterator, error) { + + var remoteChainSelectorRule []interface{} + for _, remoteChainSelectorItem := range remoteChainSelector { + remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) + } + + logs, sub, err := _MockLBTCTokenPool.contract.FilterLogs(opts, "RemotePoolRemoved", remoteChainSelectorRule) + if err != nil { + return nil, err + } + return &MockLBTCTokenPoolRemotePoolRemovedIterator{contract: _MockLBTCTokenPool.contract, event: "RemotePoolRemoved", logs: logs, sub: sub}, nil +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) WatchRemotePoolRemoved(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolRemotePoolRemoved, remoteChainSelector []uint64) (event.Subscription, error) { + + var remoteChainSelectorRule []interface{} + for _, remoteChainSelectorItem := range remoteChainSelector { + remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) + } + + logs, sub, err := _MockLBTCTokenPool.contract.WatchLogs(opts, "RemotePoolRemoved", remoteChainSelectorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(MockLBTCTokenPoolRemotePoolRemoved) + if err := _MockLBTCTokenPool.contract.UnpackLog(event, "RemotePoolRemoved", 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 (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) ParseRemotePoolRemoved(log types.Log) (*MockLBTCTokenPoolRemotePoolRemoved, error) { + event := new(MockLBTCTokenPoolRemotePoolRemoved) + if err := _MockLBTCTokenPool.contract.UnpackLog(event, "RemotePoolRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type MockLBTCTokenPoolRouterUpdatedIterator struct { + Event *MockLBTCTokenPoolRouterUpdated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *MockLBTCTokenPoolRouterUpdatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(MockLBTCTokenPoolRouterUpdated) + 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(MockLBTCTokenPoolRouterUpdated) + 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 *MockLBTCTokenPoolRouterUpdatedIterator) Error() error { + return it.fail +} + +func (it *MockLBTCTokenPoolRouterUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type MockLBTCTokenPoolRouterUpdated struct { + OldRouter common.Address + NewRouter common.Address + Raw types.Log +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) FilterRouterUpdated(opts *bind.FilterOpts) (*MockLBTCTokenPoolRouterUpdatedIterator, error) { + + logs, sub, err := _MockLBTCTokenPool.contract.FilterLogs(opts, "RouterUpdated") + if err != nil { + return nil, err + } + return &MockLBTCTokenPoolRouterUpdatedIterator{contract: _MockLBTCTokenPool.contract, event: "RouterUpdated", logs: logs, sub: sub}, nil +} + +func (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) WatchRouterUpdated(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolRouterUpdated) (event.Subscription, error) { + + logs, sub, err := _MockLBTCTokenPool.contract.WatchLogs(opts, "RouterUpdated") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(MockLBTCTokenPoolRouterUpdated) + if err := _MockLBTCTokenPool.contract.UnpackLog(event, "RouterUpdated", 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 (_MockLBTCTokenPool *MockLBTCTokenPoolFilterer) ParseRouterUpdated(log types.Log) (*MockLBTCTokenPoolRouterUpdated, error) { + event := new(MockLBTCTokenPoolRouterUpdated) + if err := _MockLBTCTokenPool.contract.UnpackLog(event, "RouterUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_MockLBTCTokenPool *MockLBTCTokenPool) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _MockLBTCTokenPool.abi.Events["AllowListAdd"].ID: + return _MockLBTCTokenPool.ParseAllowListAdd(log) + case _MockLBTCTokenPool.abi.Events["AllowListRemove"].ID: + return _MockLBTCTokenPool.ParseAllowListRemove(log) + case _MockLBTCTokenPool.abi.Events["Burned"].ID: + return _MockLBTCTokenPool.ParseBurned(log) + case _MockLBTCTokenPool.abi.Events["ChainAdded"].ID: + return _MockLBTCTokenPool.ParseChainAdded(log) + case _MockLBTCTokenPool.abi.Events["ChainConfigured"].ID: + return _MockLBTCTokenPool.ParseChainConfigured(log) + case _MockLBTCTokenPool.abi.Events["ChainRemoved"].ID: + return _MockLBTCTokenPool.ParseChainRemoved(log) + case _MockLBTCTokenPool.abi.Events["ConfigChanged"].ID: + return _MockLBTCTokenPool.ParseConfigChanged(log) + case _MockLBTCTokenPool.abi.Events["Locked"].ID: + return _MockLBTCTokenPool.ParseLocked(log) + case _MockLBTCTokenPool.abi.Events["Minted"].ID: + return _MockLBTCTokenPool.ParseMinted(log) + case _MockLBTCTokenPool.abi.Events["OwnershipTransferRequested"].ID: + return _MockLBTCTokenPool.ParseOwnershipTransferRequested(log) + case _MockLBTCTokenPool.abi.Events["OwnershipTransferred"].ID: + return _MockLBTCTokenPool.ParseOwnershipTransferred(log) + case _MockLBTCTokenPool.abi.Events["RateLimitAdminSet"].ID: + return _MockLBTCTokenPool.ParseRateLimitAdminSet(log) + case _MockLBTCTokenPool.abi.Events["Released"].ID: + return _MockLBTCTokenPool.ParseReleased(log) + case _MockLBTCTokenPool.abi.Events["RemotePoolAdded"].ID: + return _MockLBTCTokenPool.ParseRemotePoolAdded(log) + case _MockLBTCTokenPool.abi.Events["RemotePoolRemoved"].ID: + return _MockLBTCTokenPool.ParseRemotePoolRemoved(log) + case _MockLBTCTokenPool.abi.Events["RouterUpdated"].ID: + return _MockLBTCTokenPool.ParseRouterUpdated(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (MockLBTCTokenPoolAllowListAdd) Topic() common.Hash { + return common.HexToHash("0x2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d8") +} + +func (MockLBTCTokenPoolAllowListRemove) Topic() common.Hash { + return common.HexToHash("0x800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf7566") +} + +func (MockLBTCTokenPoolBurned) Topic() common.Hash { + return common.HexToHash("0x696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df7") +} + +func (MockLBTCTokenPoolChainAdded) Topic() common.Hash { + return common.HexToHash("0x8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c2") +} + +func (MockLBTCTokenPoolChainConfigured) Topic() common.Hash { + return common.HexToHash("0x0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b") +} + +func (MockLBTCTokenPoolChainRemoved) Topic() common.Hash { + return common.HexToHash("0x5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d859916") +} + +func (MockLBTCTokenPoolConfigChanged) Topic() common.Hash { + return common.HexToHash("0x9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19") +} + +func (MockLBTCTokenPoolLocked) Topic() common.Hash { + return common.HexToHash("0x9f1ec8c880f76798e7b793325d625e9b60e4082a553c98f42b6cda368dd60008") +} + +func (MockLBTCTokenPoolMinted) Topic() common.Hash { + return common.HexToHash("0x9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f0") +} + +func (MockLBTCTokenPoolOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (MockLBTCTokenPoolOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (MockLBTCTokenPoolRateLimitAdminSet) Topic() common.Hash { + return common.HexToHash("0x44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d09174") +} + +func (MockLBTCTokenPoolReleased) Topic() common.Hash { + return common.HexToHash("0x2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f52") +} + +func (MockLBTCTokenPoolRemotePoolAdded) Topic() common.Hash { + return common.HexToHash("0x7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea") +} + +func (MockLBTCTokenPoolRemotePoolRemoved) Topic() common.Hash { + return common.HexToHash("0x52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d76") +} + +func (MockLBTCTokenPoolRouterUpdated) Topic() common.Hash { + return common.HexToHash("0x02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684") +} + +func (_MockLBTCTokenPool *MockLBTCTokenPool) Address() common.Address { + return _MockLBTCTokenPool.address +} + +type MockLBTCTokenPoolInterface interface { + GetAllowList(opts *bind.CallOpts) ([]common.Address, error) + + GetAllowListEnabled(opts *bind.CallOpts) (bool, error) + + GetCurrentInboundRateLimiterState(opts *bind.CallOpts, remoteChainSelector uint64) (RateLimiterTokenBucket, error) + + GetCurrentOutboundRateLimiterState(opts *bind.CallOpts, remoteChainSelector uint64) (RateLimiterTokenBucket, error) + + GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error) + + GetRemotePools(opts *bind.CallOpts, remoteChainSelector uint64) ([][]byte, error) + + GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) + + GetRmnProxy(opts *bind.CallOpts) (common.Address, error) + + GetRouter(opts *bind.CallOpts) (common.Address, error) + + GetSupportedChains(opts *bind.CallOpts) ([]uint64, error) + + GetToken(opts *bind.CallOpts) (common.Address, error) + + GetTokenDecimals(opts *bind.CallOpts) (uint8, error) + + IDestPoolData(opts *bind.CallOpts) ([]byte, error) + + IsRemotePool(opts *bind.CallOpts, remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) + + IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error) + + IsSupportedToken(opts *bind.CallOpts, token common.Address) (bool, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) + + TypeAndVersion(opts *bind.CallOpts) (string, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + AddRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) + + ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) + + ApplyChainUpdates(opts *bind.TransactOpts, remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) + + LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) + + ReleaseOrMint(opts *bind.TransactOpts, releaseOrMintIn PoolReleaseOrMintInV1) (*types.Transaction, error) + + RemoveRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) + + SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) + + SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) + + SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + FilterAllowListAdd(opts *bind.FilterOpts) (*MockLBTCTokenPoolAllowListAddIterator, error) + + WatchAllowListAdd(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolAllowListAdd) (event.Subscription, error) + + ParseAllowListAdd(log types.Log) (*MockLBTCTokenPoolAllowListAdd, error) + + FilterAllowListRemove(opts *bind.FilterOpts) (*MockLBTCTokenPoolAllowListRemoveIterator, error) + + WatchAllowListRemove(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolAllowListRemove) (event.Subscription, error) + + ParseAllowListRemove(log types.Log) (*MockLBTCTokenPoolAllowListRemove, error) + + FilterBurned(opts *bind.FilterOpts, sender []common.Address) (*MockLBTCTokenPoolBurnedIterator, error) + + WatchBurned(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolBurned, sender []common.Address) (event.Subscription, error) + + ParseBurned(log types.Log) (*MockLBTCTokenPoolBurned, error) + + FilterChainAdded(opts *bind.FilterOpts) (*MockLBTCTokenPoolChainAddedIterator, error) + + WatchChainAdded(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolChainAdded) (event.Subscription, error) + + ParseChainAdded(log types.Log) (*MockLBTCTokenPoolChainAdded, error) + + FilterChainConfigured(opts *bind.FilterOpts) (*MockLBTCTokenPoolChainConfiguredIterator, error) + + WatchChainConfigured(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolChainConfigured) (event.Subscription, error) + + ParseChainConfigured(log types.Log) (*MockLBTCTokenPoolChainConfigured, error) + + FilterChainRemoved(opts *bind.FilterOpts) (*MockLBTCTokenPoolChainRemovedIterator, error) + + WatchChainRemoved(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolChainRemoved) (event.Subscription, error) + + ParseChainRemoved(log types.Log) (*MockLBTCTokenPoolChainRemoved, error) + + FilterConfigChanged(opts *bind.FilterOpts) (*MockLBTCTokenPoolConfigChangedIterator, error) + + WatchConfigChanged(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolConfigChanged) (event.Subscription, error) + + ParseConfigChanged(log types.Log) (*MockLBTCTokenPoolConfigChanged, error) + + FilterLocked(opts *bind.FilterOpts, sender []common.Address) (*MockLBTCTokenPoolLockedIterator, error) + + WatchLocked(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolLocked, sender []common.Address) (event.Subscription, error) + + ParseLocked(log types.Log) (*MockLBTCTokenPoolLocked, error) + + FilterMinted(opts *bind.FilterOpts, sender []common.Address, recipient []common.Address) (*MockLBTCTokenPoolMintedIterator, error) + + WatchMinted(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolMinted, sender []common.Address, recipient []common.Address) (event.Subscription, error) + + ParseMinted(log types.Log) (*MockLBTCTokenPoolMinted, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*MockLBTCTokenPoolOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*MockLBTCTokenPoolOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*MockLBTCTokenPoolOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*MockLBTCTokenPoolOwnershipTransferred, error) + + FilterRateLimitAdminSet(opts *bind.FilterOpts) (*MockLBTCTokenPoolRateLimitAdminSetIterator, error) + + WatchRateLimitAdminSet(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolRateLimitAdminSet) (event.Subscription, error) + + ParseRateLimitAdminSet(log types.Log) (*MockLBTCTokenPoolRateLimitAdminSet, error) + + FilterReleased(opts *bind.FilterOpts, sender []common.Address, recipient []common.Address) (*MockLBTCTokenPoolReleasedIterator, error) + + WatchReleased(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolReleased, sender []common.Address, recipient []common.Address) (event.Subscription, error) + + ParseReleased(log types.Log) (*MockLBTCTokenPoolReleased, error) + + FilterRemotePoolAdded(opts *bind.FilterOpts, remoteChainSelector []uint64) (*MockLBTCTokenPoolRemotePoolAddedIterator, error) + + WatchRemotePoolAdded(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolRemotePoolAdded, remoteChainSelector []uint64) (event.Subscription, error) + + ParseRemotePoolAdded(log types.Log) (*MockLBTCTokenPoolRemotePoolAdded, error) + + FilterRemotePoolRemoved(opts *bind.FilterOpts, remoteChainSelector []uint64) (*MockLBTCTokenPoolRemotePoolRemovedIterator, error) + + WatchRemotePoolRemoved(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolRemotePoolRemoved, remoteChainSelector []uint64) (event.Subscription, error) + + ParseRemotePoolRemoved(log types.Log) (*MockLBTCTokenPoolRemotePoolRemoved, error) + + FilterRouterUpdated(opts *bind.FilterOpts) (*MockLBTCTokenPoolRouterUpdatedIterator, error) + + WatchRouterUpdated(opts *bind.WatchOpts, sink chan<- *MockLBTCTokenPoolRouterUpdated) (event.Subscription, error) + + ParseRouterUpdated(log types.Log) (*MockLBTCTokenPoolRouterUpdated, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/ccip/generated/mock_usdc_token_messenger/mock_usdc_token_messenger.go b/core/gethwrappers/ccip/generated/mock_usdc_token_messenger/mock_usdc_token_messenger.go index 4d095a97da2..981b0b731fd 100644 --- a/core/gethwrappers/ccip/generated/mock_usdc_token_messenger/mock_usdc_token_messenger.go +++ b/core/gethwrappers/ccip/generated/mock_usdc_token_messenger/mock_usdc_token_messenger.go @@ -31,8 +31,8 @@ var ( ) var MockE2EUSDCTokenMessengerMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"burnToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"depositor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"mintRecipient\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"destinationDomain\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"destinationTokenMessenger\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"destinationCaller\",\"type\":\"bytes32\"}],\"name\":\"DepositForBurn\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DESTINATION_TOKEN_MESSENGER\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"destinationDomain\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"mintRecipient\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"burnToken\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"destinationCaller\",\"type\":\"bytes32\"}],\"name\":\"depositForBurnWithCaller\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"localMessageTransmitter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"localMessageTransmitterWithRelay\",\"outputs\":[{\"internalType\":\"contractIMessageTransmitterWithRelay\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"messageBodyVersion\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_nonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60e060405234801561001057600080fd5b5060405161082d38038061082d83398101604081905261002f91610063565b63ffffffff909116608052600080546001600160401b03191660011790556001600160a01b031660a081905260c0526100b2565b6000806040838503121561007657600080fd5b825163ffffffff8116811461008a57600080fd5b60208401519092506001600160a01b03811681146100a757600080fd5b809150509250929050565b60805160a05160c0516107396100f4600039600081816101290152818161049b015261055b01526000607901526000818160fa01526102b801526107396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c8063a250c66a11610050578063a250c66a14610124578063f856ddb61461014b578063fb8406a91461015e57600080fd5b80632c121921146100775780637eccf63e146100c35780639cdbb181146100f0575b600080fd5b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6000546100d79067ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016100ba565b60405163ffffffff7f00000000000000000000000000000000000000000000000000000000000000001681526020016100ba565b6100997f000000000000000000000000000000000000000000000000000000000000000081565b6100d761015936600461059e565b610193565b6101857f17c71eed51b181d8ae1908b4743526c6dbf099c201f158a1acd5f6718e82e8f681565b6040519081526020016100ba565b6040517f23b872dd0000000000000000000000000000000000000000000000000000000081523360048201523060248201526044810186905260009073ffffffffffffffffffffffffffffffffffffffff8416906323b872dd906064016020604051808303816000875af115801561020f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102339190610612565b506040517f42966c680000000000000000000000000000000000000000000000000000000081526004810187905273ffffffffffffffffffffffffffffffffffffffff8416906342966c6890602401600060405180830381600087803b15801561029c57600080fd5b505af11580156102b0573d6000803e3d6000fd5b5050604080517f000000000000000000000000000000000000000000000000000000000000000060e01b7fffffffff0000000000000000000000000000000000000000000000000000000016602082015273ffffffffffffffffffffffffffffffffffffffff8716602482015260448101889052606481018a9052336084808301919091528251808303909101815260a490910190915291506103779050867f17c71eed51b181d8ae1908b4743526c6dbf099c201f158a1acd5f6718e82e8f68584610457565b600080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff929092169182179055604080518981526020810188905263ffffffff8916918101919091527f17c71eed51b181d8ae1908b4743526c6dbf099c201f158a1acd5f6718e82e8f6606082015260808101859052339173ffffffffffffffffffffffffffffffffffffffff8716917f2fa9ca894982930190727e75500a97d8dc500233a5065e0f3126c48fbe0343c09060a00160405180910390a4505060005467ffffffffffffffff1695945050505050565b60008261051e576040517f0ba469bc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690630ba469bc906104d49088908890879060040161069f565b6020604051808303816000875af11580156104f3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061051791906106cd565b9050610596565b6040517ff7259a7500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063f7259a75906104d49088908890889088906004016106f7565b949350505050565b600080600080600060a086880312156105b657600080fd5b85359450602086013563ffffffff811681146105d157600080fd5b935060408601359250606086013573ffffffffffffffffffffffffffffffffffffffff8116811461060157600080fd5b949793965091946080013592915050565b60006020828403121561062457600080fd5b8151801515811461063457600080fd5b9392505050565b6000815180845260005b8181101561066157602081850181015186830182015201610645565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b63ffffffff841681528260208201526060604082015260006106c4606083018461063b565b95945050505050565b6000602082840312156106df57600080fd5b815167ffffffffffffffff8116811461063457600080fd5b63ffffffff85168152836020820152826040820152608060608201526000610722608083018461063b565b969550505050505056fea164736f6c6343000818000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"transmitter\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"DESTINATION_TOKEN_MESSENGER\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"depositForBurnWithCaller\",\"inputs\":[{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"destinationDomain\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"mintRecipient\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"burnToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"destinationCaller\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"localMessageTransmitter\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"localMessageTransmitterWithRelay\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIMessageTransmitterWithRelay\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"messageBodyVersion\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"s_nonce\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"DepositForBurn\",\"inputs\":[{\"name\":\"nonce\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"burnToken\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"depositor\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"mintRecipient\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"},{\"name\":\"destinationDomain\",\"type\":\"uint32\",\"indexed\":false,\"internalType\":\"uint32\"},{\"name\":\"destinationTokenMessenger\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"},{\"name\":\"destinationCaller\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"}],\"anonymous\":false}]", + Bin: "0x60e0346100b757601f61082538819003918201601f19168301916001600160401b038311848410176100bc5780849260409485528339810103126100b75780519063ffffffff821682036100b757602001516001600160a01b038116918282036100b757608052600080546001600160401b031916600117905560a05260c05260405161075290816100d382396080518181816101fc01526103fb015260a051816104ae015260c05181818161039c015261065f0152f35b600080fd5b634e487b7160e01b600052604160045260246000fdfe608080604052600436101561001357600080fd5b600090813560e01c9081632c12192114610464575080637eccf63e1461041f5780639cdbb181146103c0578063a250c66a14610351578063f856ddb6146100be5763fb8406a91461006357600080fd5b346100bb57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100bb5760206040517f17c71eed51b181d8ae1908b4743526c6dbf099c201f158a1acd5f6718e82e8f68152f35b80fd5b50346100bb5760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100bb576024359060043563ffffffff831680840361034d576044356064359173ffffffffffffffffffffffffffffffffffffffff831680930361034957608435916040517f23b872dd0000000000000000000000000000000000000000000000000000000081523360048201523060248201528560448201526020816064818a895af1801561030257610311575b50833b1561030d57604051967f42966c68000000000000000000000000000000000000000000000000000000008852856004890152868860248183895af1978815610302576020986102e2575b5061024f67ffffffffffffffff9185604051917fffffffff000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000060e01b168c8401528860248401528560448401528960648401523360848401526084835261024a60a4846104d6565b6105ca565b1695867fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008254161790556040519485528685015260408401527f17c71eed51b181d8ae1908b4743526c6dbf099c201f158a1acd5f6718e82e8f660608401526080830152827f2fa9ca894982930190727e75500a97d8dc500233a5065e0f3126c48fbe0343c060a03394a4604051908152f35b876102fa67ffffffffffffffff939961024f936104d6565b9791506101c6565b6040513d89823e3d90fd5b8580fd5b6020813d602011610341575b8161032a602093836104d6565b8101031261033d57518015158114610179575b8680fd5b3d915061031d565b8480fd5b8280fd5b50346100bb57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100bb57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346100bb57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100bb57602060405163ffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346100bb57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100bb5767ffffffffffffffff6020915416604051908152f35b9050346104d257817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104d25760209073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b5080fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761051757604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90816020910312610566575167ffffffffffffffff811681036105665790565b600080fd5b919082519283825260005b8481106105b55750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b80602080928401015182828601015201610576565b90806106cb575063ffffffff60209161064460405194859384937f0ba469bc0000000000000000000000000000000000000000000000000000000085521660048401527f17c71eed51b181d8ae1908b4743526c6dbf099c201f158a1acd5f6718e82e8f6602484015260606044840152606483019061056b565b0381600073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165af19081156106bf57600091610693575090565b6106b5915060203d6020116106b8575b6106ad81836104d6565b810190610546565b90565b503d6106a3565b6040513d6000823e3d90fd5b9160209161064463ffffffff9260405195869485947ff7259a750000000000000000000000000000000000000000000000000000000086521660048501527f17c71eed51b181d8ae1908b4743526c6dbf099c201f158a1acd5f6718e82e8f66024850152604484015260806064840152608483019061056b56fea164736f6c634300081a000a", } var MockE2EUSDCTokenMessengerABI = MockE2EUSDCTokenMessengerMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/mock_usdc_token_transmitter/mock_usdc_token_transmitter.go b/core/gethwrappers/ccip/generated/mock_usdc_token_transmitter/mock_usdc_token_transmitter.go index c3f12bab371..3a1620df2e8 100644 --- a/core/gethwrappers/ccip/generated/mock_usdc_token_transmitter/mock_usdc_token_transmitter.go +++ b/core/gethwrappers/ccip/generated/mock_usdc_token_transmitter/mock_usdc_token_transmitter.go @@ -31,8 +31,8 @@ var ( ) var MockE2EUSDCTransmitterMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_version\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"_localDomain\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"MessageSent\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"localDomain\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nextAvailableNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"receiveMessage\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_shouldSucceed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"destinationDomain\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"recipient\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"messageBody\",\"type\":\"bytes\"}],\"name\":\"sendMessage\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"destinationDomain\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"recipient\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"destinationCaller\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"messageBody\",\"type\":\"bytes\"}],\"name\":\"sendMessageWithCaller\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"shouldSucceed\",\"type\":\"bool\"}],\"name\":\"setShouldSucceed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60e060405234801561001057600080fd5b5060405161097338038061097383398101604081905261002f91610076565b63ffffffff928316608052911660a0526000805460ff191660011790556001600160a01b031660c0526100ca565b805163ffffffff8116811461007157600080fd5b919050565b60008060006060848603121561008b57600080fd5b6100948461005d565b92506100a26020850161005d565b60408501519092506001600160a01b03811681146100bf57600080fd5b809150509250925092565b60805160a05160c05161086d610106600039600061024e015260008181610140015261045801526000818160c00152610437015261086d6000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80638371744e1161005b5780638371744e146101255780638d3638f41461013e5780639e31ddb614610164578063f7259a75146101a557600080fd5b80630ba469bc1461008d57806354fd4d50146100be57806357ecfd28146100f55780637a64293514610118575b600080fd5b6100a061009b36600461054a565b6101b8565b60405167ffffffffffffffff90911681526020015b60405180910390f35b7f00000000000000000000000000000000000000000000000000000000000000005b60405163ffffffff90911681526020016100b5565b6101086101033660046105a4565b6101e1565b60405190151581526020016100b5565b6000546101089060ff1681565b6000546100a090610100900467ffffffffffffffff1681565b7f00000000000000000000000000000000000000000000000000000000000000006100e0565b6101a3610172366004610604565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b005b6100a06101b336600461062d565b6102ba565b600080806101c461036a565b9050336101d688888584868b8b6103cc565b509695505050505050565b6000806101f260b860a48789610695565b6101fb916106bf565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815260609190911c6004820181905260016024830152915073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906340c10f1990604401600060405180830381600087803b15801561029257600080fd5b505af11580156102a6573d6000803e3d6000fd5b505060005460ff1698975050505050505050565b60008361034e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f44657374696e6174696f6e2063616c6c6572206d757374206265206e6f6e7a6560448201527f726f00000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b600061035861036a565b9050336101d688888884868a8a6103cc565b60008054610100900467ffffffffffffffff16610388816001610707565b6000805467ffffffffffffffff92909216610100027fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff909216919091179055919050565b85610433576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f526563697069656e74206d757374206265206e6f6e7a65726f000000000000006044820152606401610345565b60007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008986888b8b898960405160200161049699989796959493929190610756565b60405160208183030381529060405290507f8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b036816040516104d691906107f3565b60405180910390a15050505050505050565b803563ffffffff811681146104fc57600080fd5b919050565b60008083601f84011261051357600080fd5b50813567ffffffffffffffff81111561052b57600080fd5b60208301915083602082850101111561054357600080fd5b9250929050565b6000806000806060858703121561056057600080fd5b610569856104e8565b935060208501359250604085013567ffffffffffffffff81111561058c57600080fd5b61059887828801610501565b95989497509550505050565b600080600080604085870312156105ba57600080fd5b843567ffffffffffffffff808211156105d257600080fd5b6105de88838901610501565b909650945060208701359150808211156105f757600080fd5b5061059887828801610501565b60006020828403121561061657600080fd5b8135801515811461062657600080fd5b9392505050565b60008060008060006080868803121561064557600080fd5b61064e866104e8565b94506020860135935060408601359250606086013567ffffffffffffffff81111561067857600080fd5b61068488828901610501565b969995985093965092949392505050565b600080858511156106a557600080fd5b838611156106b257600080fd5b5050820193919092039150565b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000081358181169160148510156106ff5780818660140360031b1b83161692505b505092915050565b67ffffffffffffffff81811683821601908082111561074f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5092915050565b60007fffffffff00000000000000000000000000000000000000000000000000000000808c60e01b168352808b60e01b166004840152808a60e01b166008840152507fffffffffffffffff0000000000000000000000000000000000000000000000008860c01b16600c83015286601483015285603483015284605483015282846074840137506000910160740190815298975050505050505050565b60006020808352835180602085015260005b8181101561082157858101830151858201604001528201610805565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116850101925050509291505056fea164736f6c6343000818000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_version\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"_localDomain\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"localDomain\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"nextAvailableNonce\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"receiveMessage\",\"inputs\":[{\"name\":\"message\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"success\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"s_shouldSucceed\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"sendMessage\",\"inputs\":[{\"name\":\"destinationDomain\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"recipient\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"messageBody\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"sendMessageWithCaller\",\"inputs\":[{\"name\":\"destinationDomain\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"recipient\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"destinationCaller\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"messageBody\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setShouldSucceed\",\"inputs\":[{\"name\":\"shouldSucceed\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"version\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"MessageSent\",\"inputs\":[{\"name\":\"message\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false}]", + Bin: "0x60e0346100c857601f610ab038819003918201601f19168301916001600160401b038311848410176100cd578084926060946040528339810103126100c857610047816100e3565b906040610056602083016100e3565b9101516001600160a01b03811692908390036100c85760805260a052600160ff19600054161760005560c0526040516109bb90816100f5823960805181818161011f0152818161063c0152610704015260a05181818161014901528181610418015261072e015260c051816105550152f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b519063ffffffff821682036100c85756fe6080604052600436101561001257600080fd5b6000803560e01c80630ba469bc1461066057806354fd4d501461060157806357ecfd28146104c45780637a642935146104845780638371744e1461043c5780638d3638f4146103dd5780639e31ddb61461036e5763f7259a751461007557600080fd5b3461036b5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261036b576100ac61086b565b6044359160243560643567ffffffffffffffff8111610367576100d3903690600401610883565b9480156102e3576100e2610921565b94831561028557866020976101ed946094947fffffffff0000000000000000000000000000000000000000000000000000000097604051988996817f000000000000000000000000000000000000000000000000000000000000000060e01b168e890152817f000000000000000000000000000000000000000000000000000000000000000060e01b16602489015260e01b1660288701527fffffffffffffffff0000000000000000000000000000000000000000000000008b60c01b16602c87015233603487015260548601526074850152848401378101858382015203017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018352826108b1565b604051918483528151918286850152815b838110610271575050827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f846040948585977f8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b0369901015201168101030190a167ffffffffffffffff60405191168152f35b8181018701518582016040015286016101fe565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f526563697069656e74206d757374206265206e6f6e7a65726f000000000000006044820152fd5b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f44657374696e6174696f6e2063616c6c6572206d757374206265206e6f6e7a6560448201527f726f0000000000000000000000000000000000000000000000000000000000006064820152fd5b8280fd5b80fd5b503461036b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261036b576004358015158091036103d95760ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00835416911617815580f35b5080fd5b503461036b57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261036b57602060405163ffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b503461036b57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261036b5767ffffffffffffffff6020915460081c16604051908152f35b503461036b57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261036b5760ff60209154166040519015158152f35b503461036b5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261036b5760043567ffffffffffffffff81116103d957610514903690600401610883565b60243567ffffffffffffffff81116105fd57610534903690600401610883565b505060b8116103d9578173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691823b156103d957604460a4918360405195869485937f40c10f19000000000000000000000000000000000000000000000000000000008552013560601c6004840152600160248401525af180156105f2579160ff91816020946105e2575b505054166040519015158152f35b6105eb916108b1565b38816105d4565b6040513d84823e3d90fd5b8380fd5b503461036b57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261036b57602060405163ffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b503461036b5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261036b5761069861086b565b906024359060443567ffffffffffffffff81116103d9576106bd903690600401610883565b90926106c7610921565b93811561028557602095837fffffffff00000000000000000000000000000000000000000000000000000000946094936107d395604051978895817f000000000000000000000000000000000000000000000000000000000000000060e01b168d880152817f000000000000000000000000000000000000000000000000000000000000000060e01b16602488015260e01b1660288601527fffffffffffffffff0000000000000000000000000000000000000000000000008a60c01b16602c8601523360348601526054850152876074850152848401378101858382015203017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018352826108b1565b604051918483528151918286850152815b838110610857575050827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f846040948585977f8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b0369901015201168101030190a167ffffffffffffffff60405191168152f35b8181018701518582016040015286016107e4565b6004359063ffffffff8216820361087e57565b600080fd5b9181601f8401121561087e5782359167ffffffffffffffff831161087e576020838186019501011161087e57565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176108f257604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60005467ffffffffffffffff8160081c16906001820167ffffffffffffffff811161097f5768ffffffffffffffff007fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff9160081b1691161760005590565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea164736f6c634300081a000a", } var MockE2EUSDCTransmitterABI = MockE2EUSDCTransmitterMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/multi_aggregate_rate_limiter/multi_aggregate_rate_limiter.go b/core/gethwrappers/ccip/generated/multi_aggregate_rate_limiter/multi_aggregate_rate_limiter.go index 7c2e2319b95..c4e5d8e11e0 100644 --- a/core/gethwrappers/ccip/generated/multi_aggregate_rate_limiter/multi_aggregate_rate_limiter.go +++ b/core/gethwrappers/ccip/generated/multi_aggregate_rate_limiter/multi_aggregate_rate_limiter.go @@ -87,8 +87,8 @@ type RateLimiterTokenBucket struct { } var MultiAggregateRateLimiterMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"authorizedCallers\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"PriceNotFoundForToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newFeeQuoter\",\"type\":\"address\"}],\"name\":\"FeeQuoterSet\",\"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\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isOutboundLane\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"RateLimiterConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"name\":\"TokenAggregateRateLimitAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"name\":\"TokenAggregateRateLimitRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address[]\",\"name\":\"addedCallers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedCallers\",\"type\":\"address[]\"}],\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\"}],\"name\":\"applyAuthorizedCallerUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isOutboundLane\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structMultiAggregateRateLimiter.RateLimiterConfigArgs[]\",\"name\":\"rateLimiterUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applyRateLimiterConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isOutboundLane\",\"type\":\"bool\"}],\"name\":\"currentRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedCallers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getAllRateLimitTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"localTokens\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"remoteTokens\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFeeQuoter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"onInboundMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"onOutboundMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newFeeQuoter\",\"type\":\"address\"}],\"name\":\"setFeeQuoter\",\"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\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structMultiAggregateRateLimiter.LocalRateLimitToken[]\",\"name\":\"removes\",\"type\":\"tuple[]\"},{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structMultiAggregateRateLimiter.LocalRateLimitToken\",\"name\":\"localTokenArgs\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"}],\"internalType\":\"structMultiAggregateRateLimiter.RateLimitTokenArgs[]\",\"name\":\"adds\",\"type\":\"tuple[]\"}],\"name\":\"updateRateLimitTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60806040523480156200001157600080fd5b50604051620032f2380380620032f28339810160408190526200003491620004d1565b80336000816200005757604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008a576200008a81620000cc565b5050604080518082018252828152815160008152602080820190935291810191909152620000b89062000146565b50620000c48262000295565b505062000608565b336001600160a01b03821603620000f657604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b8151811015620001d65760008282815181106200016f576200016f620005ba565b602090810291909101015190506200018960028262000311565b15620001cc576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b506001016200014e565b50815160005b81518110156200028f576000828281518110620001fd57620001fd620005ba565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200023b576040516342bcdf7f60e11b815260040160405180910390fd5b6200024860028262000331565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101620001dc565b50505050565b6001600160a01b038116620002bd576040516342bcdf7f60e11b815260040160405180910390fd5b600580546001600160a01b0319166001600160a01b0383169081179091556040519081527f7c737a8eddf62436489aa3600ed26e75e0a58b0f8c0d266bbcee64358c39fdac9060200160405180910390a150565b600062000328836001600160a01b03841662000348565b90505b92915050565b600062000328836001600160a01b0384166200044c565b60008181526001830160205260408120548015620004415760006200036f600183620005d0565b85549091506000906200038590600190620005d0565b9050818114620003f1576000866000018281548110620003a957620003a9620005ba565b9060005260206000200154905080876000018481548110620003cf57620003cf620005ba565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620004055762000405620005f2565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506200032b565b60009150506200032b565b600081815260018301602052604081205462000495575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556200032b565b5060006200032b565b80516001600160a01b0381168114620004b657600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060408385031215620004e557600080fd5b620004f0836200049e565b602084810151919350906001600160401b03808211156200051057600080fd5b818601915086601f8301126200052557600080fd5b8151818111156200053a576200053a620004bb565b8060051b604051601f19603f83011681018181108582111715620005625762000562620004bb565b6040529182528482019250838101850191898311156200058157600080fd5b938501935b82851015620005aa576200059a856200049e565b8452938501939285019262000586565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b818103818111156200032b57634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b612cda80620006186000396000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c80638da5cb5b1161008c578063e145291611610066578063e145291614610247578063e835232b14610265578063f2fde38b14610278578063fe843cd01461028b57600080fd5b80638da5cb5b146101e257806391a2749a14610221578063e0a0e5061461023457600080fd5b80631af18b7b116100c85780631af18b7b146101915780632451a627146101a4578063537e304e146101b957806379ba5097146101da57600080fd5b806308d450a1146100ef5780630a35bcc414610104578063181f5a771461017c575b600080fd5b6101026100fd3660046120e9565b61029e565b005b6101176101123660046121c9565b6102bd565b604051610173919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60405180910390f35b610184610382565b6040516101739190612260565b61010261019f36600461239a565b61039e565b6101ac6105fc565b60405161017391906124b7565b6101cc6101c73660046124ca565b61060d565b6040516101739291906124e5565b61010261077a565b60015473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610173565b61010261022f3660046125db565b610848565b61010261024236600461266c565b610859565b60055473ffffffffffffffffffffffffffffffffffffffff166101fc565b6101026102733660046126c1565b6108ce565b6101026102863660046126c1565b6108df565b6101026102993660046126fc565b6108f0565b6102a6610c3a565b6102ba816020015182608001516000610c84565b50565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526103796102f58484610d5b565b6040805160a08101825282546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff1660208501527401000000000000000000000000000000000000000090920460ff16151593830193909352600190930154808316606083015292909204166080820152610d8b565b90505b92915050565b604051806060016040528060238152602001612cab6023913981565b6103a6610e3d565b60005b82518110156104845760008382815181106103c6576103c6612830565b602002602001015160200151905060008483815181106103e8576103e8612830565b6020908102919091018101515167ffffffffffffffff811660009081526004909252604090912090915061041c9083610e8e565b1561047a576040805167ffffffffffffffff8316815273ffffffffffffffffffffffffffffffffffffffff841660208201527f530cabd30786b7235e124a6c0db77e0b685ef22813b1fe87554247f404eb8ed6910160405180910390a15b50506001016103a9565b5060005b81518110156105f75760008282815181106104a5576104a5612830565b602002602001015160000151905060008383815181106104c7576104c7612830565b6020026020010151602001519050600082602001519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16148061051857508151155b8061054a5750604080516000602082015201604051602081830303815290604052805190602001208280519060200120145b15610581576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b825167ffffffffffffffff811660009081526004602052604090206105a7908385610eb0565b156105e8577fad72a792d2a307f400c278be7deaeec6964276783304580cdc4e905436b8d5c58184846040516105df9392919061285f565b60405180910390a15b50505050806001019050610488565b505050565b60606106086002610edd565b905090565b67ffffffffffffffff81166000908152600460205260408120606091829161063490610eea565b90508067ffffffffffffffff81111561064f5761064f611e5a565b604051908082528060200260200182016040528015610678578160200160208202803683370190505b5092508067ffffffffffffffff81111561069457610694611e5a565b6040519080825280602002602001820160405280156106c757816020015b60608152602001906001900390816106b25790505b50915060005b818110156107735767ffffffffffffffff8516600090815260046020526040812081906106fa9084610ef5565b915091508186848151811061071157610711612830565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508085848151811061075e5761075e612830565b602090810291909101015250506001016106cd565b5050915091565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107cb576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610850610e3d565b6102ba81610f14565b610861610c3a565b6108ca8261087260408401846128a8565b808060200260200160405190810160405280939291908181526020016000905b828210156108be576108af60408302860136819003810190612910565b81526020019060010190610892565b50505050506001610c84565b5050565b6108d6610e3d565b6102ba816110a0565b6108e7610e3d565b6102ba81611166565b6108f8610e3d565b60005b81518110156108ca57600082828151811061091857610918612830565b6020908102919091010151604081015181519192509067ffffffffffffffff8116600003610972576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602083015160006109838383610d5b565b8054909150700100000000000000000000000000000000900463ffffffff16600003610bdc576109b484600061122a565b6040805160a081018252602080870180516fffffffffffffffffffffffffffffffff908116845263ffffffff421692840192909252875115158385015251811660608301529186015190911660808201528215610af55767ffffffffffffffff8416600090815260066020908152604091829020835160028201805493860151948601516fffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff00000000000000000000000000000000000000009095169490941770010000000000000000000000000000000063ffffffff9096168602177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000941515949094029390931790925560608401516080850151908316921690920217600390910155610bd6565b67ffffffffffffffff84166000908152600660209081526040918290208351815492850151938501516fffffffffffffffffffffffffffffffff9182167fffffffffffffffffffffffff00000000000000000000000000000000000000009094169390931770010000000000000000000000000000000063ffffffff9095168502177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000093151593909302929092178155606084015160808501519083169216909202176001909101555b50610be6565b610be68185611363565b8267ffffffffffffffff167ff14a5415ce6988a9e870a85fff0b9d7b7dd79bbc228cb63cad610daf6f7b6b978386604051610c2292919061292c565b60405180910390a250505050508060010190506108fb565b610c45600233611512565b610c82576040517fd86ad9cf0000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b565b6000610c908483610d5b565b805490915074010000000000000000000000000000000000000000900460ff1615610d55576000805b8451811015610d4057610d04858281518110610cd757610cd7612830565b6020908102919091018101515167ffffffffffffffff891660009081526004909252604090912090611541565b15610d3857610d2b858281518110610d1e57610d1e612830565b6020026020010151611563565b610d35908361299f565b91505b600101610cb9565b508015610d5357610d538282600061169f565b505b50505050565b67ffffffffffffffff821660009081526006602052604081208215610d8457600201905061037c565b905061037c565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152610e1982606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff1642610dfd91906129b2565b85608001516fffffffffffffffffffffffffffffffff16611a22565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b60015473ffffffffffffffffffffffffffffffffffffffff163314610c82576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103798373ffffffffffffffffffffffffffffffffffffffff8416611a4a565b6000610ed38473ffffffffffffffffffffffffffffffffffffffff851684611a6e565b90505b9392505050565b60606000610ed683611a93565b600061037c82611aef565b600060608180610f058686611afa565b909450925050505b9250929050565b602081015160005b8151811015610faf576000828281518110610f3957610f39612830565b60200260200101519050610f57816002611bb790919063ffffffff16565b15610fa65760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101610f1c565b50815160005b8151811015610d55576000828281518110610fd257610fd2612830565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611042576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61104d600282611bd9565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101610fb5565b73ffffffffffffffffffffffffffffffffffffffff81166110ed576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f7c737a8eddf62436489aa3600ed26e75e0a58b0f8c0d266bbcee64358c39fdac9060200160405180910390a150565b3373ffffffffffffffffffffffffffffffffffffffff8216036111b5576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b8151156112f15781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580611280575060408201516fffffffffffffffffffffffffffffffff16155b156112b957816040517f8020d124000000000000000000000000000000000000000000000000000000008152600401610c7991906129c5565b80156108ca576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516fffffffffffffffffffffffffffffffff1615158061132a575060208201516fffffffffffffffffffffffffffffffff1615155b156108ca57816040517fd68af9cc000000000000000000000000000000000000000000000000000000008152600401610c7991906129c5565b815460009061138c90700100000000000000000000000000000000900463ffffffff16426129b2565b9050801561142e57600183015483546113d4916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416611a22565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354611454916fffffffffffffffffffffffffffffffff9081169116611bfb565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19906115059084906129c5565b60405180910390a1505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610379565b60006103798373ffffffffffffffffffffffffffffffffffffffff8416611c11565b60055481516040517fd02641a000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821660048201526000928392169063d02641a0906024016040805180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb9190612a01565b5190507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff81166000036116715782516040517f9a655f7b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610c79565b6020830151610ed6907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff831690611c1d565b825474010000000000000000000000000000000000000000900460ff1615806116c6575081155b156116d057505050565b825460018401546fffffffffffffffffffffffffffffffff8083169291169060009061171690700100000000000000000000000000000000900463ffffffff16426129b2565b905080156117d65781831115611758576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546117929083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16611a22565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b8482101561188d5773ffffffffffffffffffffffffffffffffffffffff8416611835576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610c79565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610c79565b848310156119a05760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906118d190826129b2565b6118db878a6129b2565b6118e5919061299f565b6118ef9190612a6c565b905073ffffffffffffffffffffffffffffffffffffffff8616611948576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610c79565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610c79565b6119aa85846129b2565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b6000611a4185611a328486612aa7565b611a3c908761299f565b611bfb565b95945050505050565b60008181526002830160205260408120611a649082611e0c565b6103798383611c5a565b60008281526002840160205260408120611a888382612b61565b50610ed38484611c66565b606081600001805480602002602001604051908101604052809291908181526020018280548015611ae357602002820191906000526020600020905b815481526020019060010190808311611acf575b50505050509050919050565b600061037c82611c72565b6000606081611b098585611c7c565b60008181526002870160205260409020805491925082918190611b2b90612abe565b80601f0160208091040260200160405190810160405280929190818152602001828054611b5790612abe565b8015611ba45780601f10611b7957610100808354040283529160200191611ba4565b820191906000526020600020905b815481529060010190602001808311611b8757829003601f168201915b5050505050905092509250509250929050565b60006103798373ffffffffffffffffffffffffffffffffffffffff8416611c88565b60006103798373ffffffffffffffffffffffffffffffffffffffff8416611d7b565b6000818310611c0a5781610379565b5090919050565b60006103798383611dca565b6000670de0b6b3a7640000611c50837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8616612aa7565b6103799190612a6c565b60006103798383611c88565b60006103798383611d7b565b600061037c825490565b60006103798383611de2565b60008181526001830160205260408120548015611d71576000611cac6001836129b2565b8554909150600090611cc0906001906129b2565b9050818114611d25576000866000018281548110611ce057611ce0612830565b9060005260206000200154905080876000018481548110611d0357611d03612830565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611d3657611d36612c7b565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061037c565b600091505061037c565b6000818152600183016020526040812054611dc25750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561037c565b50600061037c565b60008181526001830160205260408120541515610379565b6000826000018281548110611df957611df9612830565b9060005260206000200154905092915050565b508054611e1890612abe565b6000825580601f10611e28575050565b601f0160209004906000526020600020908101906102ba91905b80821115611e565760008155600101611e42565b5090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611eac57611eac611e5a565b60405290565b60405160a0810167ffffffffffffffff81118282101715611eac57611eac611e5a565b6040516060810167ffffffffffffffff81118282101715611eac57611eac611e5a565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611f3f57611f3f611e5a565b604052919050565b803567ffffffffffffffff81168114611f5f57600080fd5b919050565b600082601f830112611f7557600080fd5b813567ffffffffffffffff811115611f8f57611f8f611e5a565b611fc060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611ef8565b818152846020838601011115611fd557600080fd5b816020850160208301376000918101602001919091529392505050565b600067ffffffffffffffff82111561200c5761200c611e5a565b5060051b60200190565b803573ffffffffffffffffffffffffffffffffffffffff81168114611f5f57600080fd5b60006040828403121561204c57600080fd5b612054611e89565b905061205f82612016565b81526020820135602082015292915050565b600082601f83011261208257600080fd5b8135602061209761209283611ff2565b611ef8565b8083825260208201915060208460061b8701019350868411156120b957600080fd5b602086015b848110156120de576120d0888261203a565b8352918301916040016120be565b509695505050505050565b6000602082840312156120fb57600080fd5b813567ffffffffffffffff8082111561211357600080fd5b9083019060a0828603121561212757600080fd5b61212f611eb2565b8235815261213f60208401611f47565b602082015260408301358281111561215657600080fd5b61216287828601611f64565b60408301525060608301358281111561217a57600080fd5b61218687828601611f64565b60608301525060808301358281111561219e57600080fd5b6121aa87828601612071565b60808301525095945050505050565b80358015158114611f5f57600080fd5b600080604083850312156121dc57600080fd5b6121e583611f47565b91506121f3602084016121b9565b90509250929050565b6000815180845260005b8181101561222257602081850181015186830182015201612206565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061037960208301846121fc565b60006040828403121561228557600080fd5b61228d611e89565b905061229882611f47565b81526122a660208301612016565b602082015292915050565b600082601f8301126122c257600080fd5b813560206122d261209283611ff2565b82815260059290921b840181019181810190868411156122f157600080fd5b8286015b848110156120de57803567ffffffffffffffff808211156123165760008081fd5b81890191506060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d0301121561234f5760008081fd5b612357611e89565b6123638c898601612273565b81529083013590828211156123785760008081fd5b6123868c8984870101611f64565b8189015286525050509183019183016122f5565b60008060408084860312156123ae57600080fd5b833567ffffffffffffffff808211156123c657600080fd5b818601915086601f8301126123da57600080fd5b813560206123ea61209283611ff2565b8083825260208201915060208460061b87010193508a84111561240c57600080fd5b6020860195505b83861015612434576124258b87612273565b82529486019490820190612413565b9750505050602086013592508083111561244d57600080fd5b505061245b858286016122b1565b9150509250929050565b60008151808452602080850194506020840160005b838110156124ac57815173ffffffffffffffffffffffffffffffffffffffff168752958201959082019060010161247a565b509495945050505050565b6020815260006103796020830184612465565b6000602082840312156124dc57600080fd5b61037982611f47565b6040815260006124f86040830185612465565b6020838203818501528185518084528284019150828160051b85010183880160005b83811015612566577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08784030185526125548383516121fc565b9486019492509085019060010161251a565b50909998505050505050505050565b600082601f83011261258657600080fd5b8135602061259661209283611ff2565b8083825260208201915060208460051b8701019350868411156125b857600080fd5b602086015b848110156120de576125ce81612016565b83529183019183016125bd565b6000602082840312156125ed57600080fd5b813567ffffffffffffffff8082111561260557600080fd5b908301906040828603121561261957600080fd5b612621611e89565b82358281111561263057600080fd5b61263c87828601612575565b82525060208301358281111561265157600080fd5b61265d87828601612575565b60208301525095945050505050565b6000806040838503121561267f57600080fd5b61268883611f47565b9150602083013567ffffffffffffffff8111156126a457600080fd5b830160a081860312156126b657600080fd5b809150509250929050565b6000602082840312156126d357600080fd5b61037982612016565b80356fffffffffffffffffffffffffffffffff81168114611f5f57600080fd5b6000602080838503121561270f57600080fd5b823567ffffffffffffffff81111561272657600080fd5b8301601f8101851361273757600080fd5b803561274561209282611ff2565b81815260a0918202830184019184820191908884111561276457600080fd5b938501935b8385101561282457848903818112156127825760008081fd5b61278a611ed5565b61279387611f47565b81526127a08888016121b9565b8882015260406060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0850112156127d85760008081fd5b6127e0611ed5565b93506127ed828a016121b9565b84526127fa818a016126dc565b8a8501525061280b608089016126dc565b8382015281019190915283529384019391850191612769565b50979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b67ffffffffffffffff8416815260606020820152600061288260608301856121fc565b905073ffffffffffffffffffffffffffffffffffffffff83166040830152949350505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126128dd57600080fd5b83018035915067ffffffffffffffff8211156128f857600080fd5b6020019150600681901b3603821315610f0d57600080fd5b60006040828403121561292257600080fd5b610379838361203a565b821515815260808101610ed660208301848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561037c5761037c612970565b8181038181111561037c5761037c612970565b6060810161037c82848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b600060408284031215612a1357600080fd5b612a1b611e89565b82517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff81168114612a4757600080fd5b8152602083015163ffffffff81168114612a6057600080fd5b60208201529392505050565b600082612aa2577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808202811582820484141761037c5761037c612970565b600181811c90821680612ad257607f821691505b602082108103612b0b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f8211156105f7576000816000526020600020601f850160051c81016020861015612b3a5750805b601f850160051c820191505b81811015612b5957828155600101612b46565b505050505050565b815167ffffffffffffffff811115612b7b57612b7b611e5a565b612b8f81612b898454612abe565b84612b11565b602080601f831160018114612be25760008415612bac5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612b59565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015612c2f57888601518255948401946001909101908401612c10565b5085821015612c6b57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfe4d756c7469416767726567617465526174654c696d6974657220312e362e302d646576a164736f6c6343000818000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"feeQuoter\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"authorizedCallers\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"acceptOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyAuthorizedCallerUpdates\",\"inputs\":[{\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\",\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"components\":[{\"name\":\"addedCallers\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"removedCallers\",\"type\":\"address[]\",\"internalType\":\"address[]\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyRateLimiterConfigUpdates\",\"inputs\":[{\"name\":\"rateLimiterUpdates\",\"type\":\"tuple[]\",\"internalType\":\"structMultiAggregateRateLimiter.RateLimiterConfigArgs[]\",\"components\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"isOutboundLane\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"rateLimiterConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"currentRateLimiterState\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"isOutboundLane\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.TokenBucket\",\"components\":[{\"name\":\"tokens\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"lastUpdated\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getAllAuthorizedCallers\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getAllRateLimitTokens\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"localTokens\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"remoteTokens\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getFeeQuoter\",\"inputs\":[],\"outputs\":[{\"name\":\"feeQuoter\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"onInboundMessage\",\"inputs\":[{\"name\":\"message\",\"type\":\"tuple\",\"internalType\":\"structClient.Any2EVMMessage\",\"components\":[{\"name\":\"messageId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sender\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\",\"internalType\":\"structClient.EVMTokenAmount[]\",\"components\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"onOutboundMessage\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"message\",\"type\":\"tuple\",\"internalType\":\"structClient.EVM2AnyMessage\",\"components\":[{\"name\":\"receiver\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"tokenAmounts\",\"type\":\"tuple[]\",\"internalType\":\"structClient.EVMTokenAmount[]\",\"components\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"feeToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"extraArgs\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"setFeeQuoter\",\"inputs\":[{\"name\":\"newFeeQuoter\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"typeAndVersion\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"updateRateLimitTokens\",\"inputs\":[{\"name\":\"removes\",\"type\":\"tuple[]\",\"internalType\":\"structMultiAggregateRateLimiter.LocalRateLimitToken[]\",\"components\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"localToken\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"name\":\"adds\",\"type\":\"tuple[]\",\"internalType\":\"structMultiAggregateRateLimiter.RateLimitTokenArgs[]\",\"components\":[{\"name\":\"localTokenArgs\",\"type\":\"tuple\",\"internalType\":\"structMultiAggregateRateLimiter.LocalRateLimitToken\",\"components\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"localToken\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"name\":\"remoteToken\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"AuthorizedCallerAdded\",\"inputs\":[{\"name\":\"caller\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"AuthorizedCallerRemoved\",\"inputs\":[{\"name\":\"caller\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ConfigChanged\",\"inputs\":[{\"name\":\"config\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"FeeQuoterSet\",\"inputs\":[{\"name\":\"newFeeQuoter\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferRequested\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RateLimiterConfigUpdated\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"isOutboundLane\",\"type\":\"bool\",\"indexed\":false,\"internalType\":\"bool\"},{\"name\":\"config\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TokenAggregateRateLimitAdded\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"remoteToken\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"},{\"name\":\"localToken\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TokenAggregateRateLimitRemoved\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"localToken\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TokensConsumed\",\"inputs\":[{\"name\":\"tokens\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AggregateValueMaxCapacityExceeded\",\"inputs\":[{\"name\":\"capacity\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"requested\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"AggregateValueRateLimitReached\",\"inputs\":[{\"name\":\"minWaitInSeconds\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"available\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"BucketOverfilled\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CannotTransferToSelf\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"DisabledNonZeroRateLimit\",\"inputs\":[{\"name\":\"config\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}]},{\"type\":\"error\",\"name\":\"InvalidRateLimitRate\",\"inputs\":[{\"name\":\"rateLimiterConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}]},{\"type\":\"error\",\"name\":\"MessageValidationError\",\"inputs\":[{\"name\":\"errorReason\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"MustBeProposedOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OnlyCallableByOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OwnerCannotBeZero\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PriceNotFoundForToken\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"RateLimitMustBeDisabled\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TokenMaxCapacityExceeded\",\"inputs\":[{\"name\":\"capacity\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"requested\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"tokenAddress\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"TokenRateLimitReached\",\"inputs\":[{\"name\":\"minWaitInSeconds\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"available\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"tokenAddress\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"UnauthorizedCaller\",\"inputs\":[{\"name\":\"caller\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ZeroAddressNotAllowed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ZeroChainSelectorNotAllowed\",\"inputs\":[]}]", + Bin: "0x60806040523461026457612f548038038061001981610269565b928339810190604081830312610264576100328161028e565b602082015190916001600160401b03821161026457019180601f84011215610264578251926001600160401b038411610225578360051b90602080610078818501610269565b80978152019282010192831161026457602001905b82821061024c57505050331561023b57600180546001600160a01b0319163317905560206100ba81610269565b60008152600036813760408051949085016001600160401b03811186821017610225576040528452808285015260005b8151811015610151576001906001600160a01b0361010882856102a2565b511684610114826102e4565b610121575b5050016100ea565b7fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda7758091604051908152a13884610119565b5050915160005b81518110156101c9576001600160a01b0361017382846102a2565b51169081156101b8577feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef85836101aa6001956103e2565b50604051908152a101610158565b6342bcdf7f60e11b60005260046000fd5b50506001600160a01b03169081156101b857600580546001600160a01b031916831790556040519182527f7c737a8eddf62436489aa3600ed26e75e0a58b0f8c0d266bbcee64358c39fdac91a1604051612b1190816104438239f35b634e487b7160e01b600052604160045260246000fd5b639b15e16f60e01b60005260046000fd5b602080916102598461028e565b81520191019061008d565b600080fd5b6040519190601f01601f191682016001600160401b0381118382101761022557604052565b51906001600160a01b038216820361026457565b80518210156102b65760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b80548210156102b65760005260206000200190600090565b60008181526003602052604090205480156103db5760001981018181116103c5576002546000198101919082116103c557808203610374575b505050600254801561035e57600019016103388160026102cc565b8154906000199060031b1b19169055600255600052600360205260006040812055600190565b634e487b7160e01b600052603160045260246000fd5b6103ad6103856103969360026102cc565b90549060031b1c92839260026102cc565b819391549060031b91821b91600019901b19161790565b9055600052600360205260406000205538808061031d565b634e487b7160e01b600052601160045260246000fd5b5050600090565b8060005260036020526040600020541560001461043c57600254680100000000000000008110156102255761042361039682600185940160025560026102cc565b9055600254906000526003602052604060002055600190565b5060009056fe608080604052600436101561001357600080fd5b60003560e01c90816308d450a114611ca3575080630a35bcc414611b72578063181f5a7714611ace5780631af18b7b1461156c5780632451a627146114bf578063537e304e146111f557806379ba50971461110c5780638da5cb5b146110ba57806391a2749a14610efc578063e0a0e50614610bbb578063e145291614610b69578063e835232b14610a8d578063f2fde38b1461099d5763fe843cd0146100b957600080fd5b346109985760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126109985760043567ffffffffffffffff81116109985736602382011215610998578060040135610113816120da565b916101216040519384611ff8565b818352602460a06020850193028201019036821161099857602401915b8183106108ea578361014e61243d565b6000905b80518210156108e8576101658282612345565b519160408301519267ffffffffffffffff8151169081156108be576020015115156101908183612408565b805463ffffffff8160801c16801560001461066757505085516000915015610592576fffffffffffffffffffffffffffffffff6040870151166fffffffffffffffffffffffffffffffff602088015116811090811591610589575b50610526577ff14a5415ce6988a9e870a85fff0b9d7b7dd79bbc228cb63cad610daf6f7b6b979161042960019697608093505b6fffffffffffffffffffffffffffffffff6040820151166fffffffffffffffffffffffffffffffff602083015116825115159160405161025d81611fa4565b828152602081019363ffffffff4216855260408201908152606082019384528882019283528a886000146104315760036103ef966103816fffffffffffffffffffffffffffffffff969587958695600052600660205261033a63ffffffff604060002095888060028901965116167fffffffffffffffffffffffffffffffff00000000000000000000000000000000865416178555511683907fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff73ffffffff0000000000000000000000000000000083549260801b169116179055565b5181547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690151560a01b74ff000000000000000000000000000000000000000016179055565b01945116167fffffffffffffffffffffffffffffffff0000000000000000000000000000000084541617835551166fffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffff0000000000000000000000000000000083549260801b169116179055565b60405192835260208301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565ba20190610152565b8d6fffffffffffffffffffffffffffffffff949361038186946104da63ffffffff6105219b8897600052600660205287806040600020975116167fffffffffffffffffffffffffffffffff00000000000000000000000000000000875416178655511684907fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff73ffffffff0000000000000000000000000000000083549260801b169116179055565b5182547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690151560a01b74ff000000000000000000000000000000000000000016178255565b6103ef565b606486610587604051917f8020d12400000000000000000000000000000000000000000000000000000000835260048301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565bfd5b905015876101eb565b506fffffffffffffffffffffffffffffffff60408601511615801590610648575b6105e75760807ff14a5415ce6988a9e870a85fff0b9d7b7dd79bbc228cb63cad610daf6f7b6b97916104296001969761021e565b606485610587604051917fd68af9cc00000000000000000000000000000000000000000000000000000000835260048301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b506fffffffffffffffffffffffffffffffff60208601511615156105b3565b6001969761079c6080947ff14a5415ce6988a9e870a85fff0b9d7b7dd79bbc228cb63cad610daf6f7b6b9796946106a16104299542612430565b9081610804575b50506fffffffffffffffffffffffffffffffff8a8160208601511692828154168085106000146107fc57508280855b16167fffffffffffffffffffffffffffffffff000000000000000000000000000000008254161781556107508651151582907fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff74ff0000000000000000000000000000000000000000835492151560a01b169116179055565b60408601517fffffffffffffffffffffffffffffffff0000000000000000000000000000000060809190911b16939092166fffffffffffffffffffffffffffffffff1692909217910155565b7f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1960606040516107f681856fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565ba16103ef565b8380916106d7565b6fffffffffffffffffffffffffffffffff916108388392838f6108319088015494828616958e1c906126f0565b91166123cc565b808210156108b757505b83547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff9290911692909216167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116174260801b73ffffffff00000000000000000000000000000000161781558b806106a8565b9050610842565b7fc65608950000000000000000000000000000000000000000000000000000000060005260046000fd5b005b82360360a081126109985760607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc06040519261092584611fdc565b61092e87612050565b845261093c602088016121ac565b602085015201126109985760a09160209160405161095981611fdc565b610965604088016121ac565b8152610973606088016122fd565b84820152610983608088016122fd565b6040820152604082015281520192019161013e565b600080fd5b346109985760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126109985773ffffffffffffffffffffffffffffffffffffffff6109e96120f2565b6109f161243d565b16338114610a6357807fffffffffffffffffffffffff0000000000000000000000000000000000000000600054161760005573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b7fdad89dca0000000000000000000000000000000000000000000000000000000060005260046000fd5b346109985760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126109985773ffffffffffffffffffffffffffffffffffffffff610ad96120f2565b610ae161243d565b168015610b3f576020817f7c737a8eddf62436489aa3600ed26e75e0a58b0f8c0d266bbcee64358c39fdac927fffffffffffffffffffffffff00000000000000000000000000000000000000006005541617600555604051908152a1005b7f8579befe0000000000000000000000000000000000000000000000000000000060005260046000fd5b346109985760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261099857602073ffffffffffffffffffffffffffffffffffffffff60055416604051908152f35b346109985760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261099857610bf2612039565b60243567ffffffffffffffff8111610998578036039060a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc83011261099857610c3a612388565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdd60448201359201821215610998570160048101359067ffffffffffffffff8211610998576024018160061b3603811361099857610c99913691612136565b90610ca5600182612408565b9160ff835460a01c16610cb457005b6000929167ffffffffffffffff16835b8251811015610ee857816000526004602052610d16604060002073ffffffffffffffffffffffffffffffffffffffff610cfd8487612345565b5151169060019160005201602052604060002054151590565b610d23575b600101610cc4565b93610d2e8584612345565b5173ffffffffffffffffffffffffffffffffffffffff60055416604073ffffffffffffffffffffffffffffffffffffffff83511660248251809481937fd02641a000000000000000000000000000000000000000000000000000000000835260048301525afa8015610edc57600090610e3c575b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff91505116908115610df75791670de0b6b3a7640000610de8610def9360206001960151906126f0565b04906123cc565b949050610d1b565b73ffffffffffffffffffffffffffffffffffffffff9051167f9a655f7b0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b6040823d8211610ed4575b81610e5460409383611ff8565b81010312610ecd5760405191610e6983611fc0565b80517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff81168103610ed0578352602001519063ffffffff82168203610ecd575060208201527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90610da2565b80fd5b8280fd5b3d9150610e47565b6040513d6000823e3d90fd5b5050509080610ef357005b6108e891612488565b346109985760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126109985760043567ffffffffffffffff81116109985760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82360301126109985760405190610f7682611fc0565b806004013567ffffffffffffffff811161099857610f9a9060043691840101612298565b825260248101359067ffffffffffffffff8211610998576004610fc09236920101612298565b60208201908152610fcf61243d565b519060005b8251811015611047578073ffffffffffffffffffffffffffffffffffffffff610fff60019386612345565b511661100a81612785565b611016575b5001610fd4565b60207fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda7758091604051908152a18461100f565b505160005b81518110156108e85773ffffffffffffffffffffffffffffffffffffffff6110748284612345565b5116908115610b3f577feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef6020836110ac600195612a4f565b50604051908152a10161104c565b346109985760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261099857602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b346109985760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126109985760005473ffffffffffffffffffffffffffffffffffffffff811633036111cb577fffffffffffffffffffffffff00000000000000000000000000000000000000006001549133828416176001551660005573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b7f02b543c60000000000000000000000000000000000000000000000000000000060005260046000fd5b346109985760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126109985767ffffffffffffffff611235612039565b168060005260046020526040600020549061124f826120da565b9161125d6040519384611ff8565b8083527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061128a826120da565b0136602085013761129a816120da565b916112a86040519384611ff8565b8183527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06112d5836120da565b0160005b8181106114ae57505060005b82811061138457611305858560405192839260408452604084019061224e565b8281036020840152815180825260208201916020808360051b8301019401926000915b8383106113355786860387f35b919395509193602080611372837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0866001960301875289516121b9565b97019301930190928695949293611328565b8160005260046020526040600020600261139e838361276d565b90549060031b1c918260005201602052604060002090604051916000908054906113c782612703565b8086529160018116908115611469575060011461142f575b505082916114076001959473ffffffffffffffffffffffffffffffffffffffff930384611ff8565b166114128389612345565b5261141d8287612345565b526114288186612345565b50016112e5565b6000908152602081209092505b8183106114535750508201602001816114076113df565b600181602092548386890101520192019161143c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660208088019190915292151560051b8601909201925083915061140790506113df565b8060606020809388010152016112d9565b346109985760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126109985760405180602060025491828152019060026000527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace9060005b818110611556576115528561153e81870382611ff8565b60405191829160208352602083019061224e565b0390f35b8254845260209093019260019283019201611527565b346109985760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126109985760043567ffffffffffffffff81116109985736602382011215610998578060040135906115c7826120da565b916115d56040519384611ff8565b8083526024602084019160061b8301019136831161099857602401905b828210611ab4576024358467ffffffffffffffff82116109985736602383011215610998578160040135611625816120da565b926116336040519485611ff8565b8184526024602085019260051b820101903682116109985760248101925b828410611a2157858561166261243d565b60005b815181101561176d578073ffffffffffffffffffffffffffffffffffffffff602061169260019486612345565b5101511667ffffffffffffffff6116a98386612345565b515116908160005260046020526116e7816040600020816000526002810160205260406000206116d98154612703565b908161172b575b505061291b565b6116f4575b505001611665565b7f530cabd30786b7235e124a6c0db77e0b685ef22813b1fe87554247f404eb8ed69160409182519182526020820152a184806116ec565b81601f600093118a146117425750555b89806116e0565b8183526020832061175d91601f0160051c8101908b01612756565b808252816020812091555561173b565b8260005b81518110156108e8576117848183612345565b515160206117928385612345565b51015173ffffffffffffffffffffffffffffffffffffffff6020830151169182158015611a18575b80156119ec575b610b3f5767ffffffffffffffff905116806000526004602052604060002083600052600281016020526040600020835167ffffffffffffffff81116119bd5761180a8254612703565b601f8111611980575b506020601f82116001146118d5579261186d9282889796959360019a99946000916118ca575b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff828c1b9260031b1c1916179055612aaf565b61187b575b50505001611771565b7fad72a792d2a307f400c278be7deaeec6964276783304580cdc4e905436b8d5c5926118b960405193849384526060602085015260608401906121b9565b9060408301520390a1838080611872565b90508701518c611839565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082169083600052806000209160005b818110611968575083899897969361186d969360019c9b968d9410611931575b5050811b019055612aaf565b8901517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690558c80611925565b9192602060018192868c015181550194019201611905565b6119ad90836000526020600020601f840160051c810191602085106119b3575b601f0160051c0190612756565b88611813565b90915081906119a0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b508151602083012060405160208101906000825260208152611a0f604082611ff8565b519020146117c1565b508151156117ba565b833567ffffffffffffffff811161099857820160607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc82360301126109985760405191611a6d83611fc0565b611a7a3660248401612218565b835260648201359267ffffffffffffffff841161099857611aa5602094936024869536920101612065565b83820152815201930192611651565b6020604091611ac33685612218565b8152019101906115f2565b346109985760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261099857611552604051611b0e606082611ff8565b602381527f4d756c7469416767726567617465526174654c696d6974657220312e362e302d60208201527f646576000000000000000000000000000000000000000000000000000000000060408201526040519182916020835260208301906121b9565b346109985760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261099857611ba9612039565b6024359081151582036109985760a091611bcb91611bc561231a565b50612408565b6fffffffffffffffffffffffffffffffff60405191611be983611fa4565b8181549181831685526001602086019163ffffffff8560801c16835260ff6040880195891c161515855201549263ffffffff60608701928486168452608088019560801c8652611c3761231a565b508480855116611c64828b5116611c5e611c548787511642612430565b858c5116906126f0565b906123cc565b80821015611c9c57505b1680985281421681526040519788525116602087015251151560408601525116606084015251166080820152f35b9050611c6e565b346109985760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126109985760043567ffffffffffffffff81116109985760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc823603011261099857611d1982611fa4565b80600401358252611d2c60248201612050565b9060208301918252604481013567ffffffffffffffff811161099857611d589060043691840101612065565b6040840152606481013567ffffffffffffffff811161099857611d819060043691840101612065565b606084015260848101359067ffffffffffffffff821161099857019036602383011215610998576080611dc767ffffffffffffffff933690602460048201359101612136565b9301928352611dd4612388565b51169051611de3600083612408565b9060ff825460a01c16611df257005b60009260005b8251811015610ee857816000526004602052611e31604060002073ffffffffffffffffffffffffffffffffffffffff610cfd8487612345565b611e3e575b600101611df8565b93611e498584612345565b5173ffffffffffffffffffffffffffffffffffffffff60055416604073ffffffffffffffffffffffffffffffffffffffff83511660248251809481937fd02641a000000000000000000000000000000000000000000000000000000000835260048301525afa8015610edc57600090611f0b575b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff91505116908115610df75791670de0b6b3a7640000610de8611f039360206001960151906126f0565b949050611e36565b6040823d8211611f9c575b81611f2360409383611ff8565b81010312610ecd5760405191611f3883611fc0565b80517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff81168103610ed0578352602001519063ffffffff82168203610ecd575060208201527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90611ebd565b3d9150611f16565b60a0810190811067ffffffffffffffff8211176119bd57604052565b6040810190811067ffffffffffffffff8211176119bd57604052565b6060810190811067ffffffffffffffff8211176119bd57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176119bd57604052565b6004359067ffffffffffffffff8216820361099857565b359067ffffffffffffffff8216820361099857565b81601f820112156109985780359067ffffffffffffffff82116119bd57604051926120b8601f84017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200185611ff8565b8284526020838301011161099857816000926020809301838601378301015290565b67ffffffffffffffff81116119bd5760051b60200190565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361099857565b359073ffffffffffffffffffffffffffffffffffffffff8216820361099857565b929192612142826120da565b936121506040519586611ff8565b602085848152019260061b82019181831161099857925b8284106121745750505050565b604084830312610998576020604091825161218e81611fc0565b61219787612115565b81528287013583820152815201930192612167565b3590811515820361099857565b919082519283825260005b8481106122035750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b806020809284010151828286010152016121c4565b91908260409103126109985760405161223081611fc0565b602061224981839561224181612050565b855201612115565b910152565b906020808351928381520192019060005b81811061226c5750505090565b825173ffffffffffffffffffffffffffffffffffffffff1684526020938401939092019160010161225f565b9080601f830112156109985781356122af816120da565b926122bd6040519485611ff8565b81845260208085019260051b82010192831161099857602001905b8282106122e55750505090565b602080916122f284612115565b8152019101906122d8565b35906fffffffffffffffffffffffffffffffff8216820361099857565b6040519061232782611fa4565b60006080838281528260208201528260408201528260608201520152565b80518210156123595760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b3360005260036020526040600020541561239e57565b7fd86ad9cf000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b919082018092116123d957565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff16600052600660205260406000209060001461242d5760020190565b90565b919082039182116123d957565b73ffffffffffffffffffffffffffffffffffffffff60015416330361245e57565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b805460ff8160a01c161580156126e8575b6126e3576fffffffffffffffffffffffffffffffff811690600183019081546124de63ffffffff6fffffffffffffffffffffffffffffffff83169360801c1642612430565b9081612645575b5050848110612613575083821061256a5750916020916fffffffffffffffffffffffffffffffff80612538847f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a97612430565b16167fffffffffffffffffffffffffffffffff00000000000000000000000000000000825416179055604051908152a1565b5460801c6125788285612430565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82018281116123d9576125ab916123cc565b9080156125e45790047f15279c080000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b84907ff94ebcd10000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b8285929395116126b95761266092611c5e9160801c906126f0565b808310156126b45750815b83547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff164260801b73ffffffff00000000000000000000000000000000161784559138806124e5565b61266b565b7f9725942a0000000000000000000000000000000000000000000000000000000060005260046000fd5b505050565b508215612499565b818102929181159184041417156123d957565b90600182811c9216801561274c575b602083101461271d57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f1691612712565b818110612761575050565b60008155600101612756565b80548210156123595760005260206000200190600090565b6000818152600360205260409020548015612914577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81018181116123d957600254907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82019182116123d9578082036128a5575b5050506002548015612876577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0161283381600261276d565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600255600052600360205260006040812055600190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6128fc6128b66128c793600261276d565b90549060031b1c928392600261276d565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b905560005260036020526040600020553880806127fa565b5050600090565b9060018201918160005282602052604060002054801515600014612a46577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81018181116123d9578254907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82019182116123d957808203612a0f575b50505080548015612876577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01906129d0828261276d565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b191690555560005260205260006040812055600190565b612a2f612a1f6128c7938661276d565b90549060031b1c9283928661276d565b905560005283602052604060002055388080612998565b50505050600090565b80600052600360205260406000205415600014612aa957600254680100000000000000008110156119bd57612a906128c7826001859401600255600261276d565b9055600254906000526003602052604060002055600190565b50600090565b600082815260018201602052604090205461291457805490680100000000000000008210156119bd5782612aed6128c784600180960185558461276d565b90558054926000520160205260406000205560019056fea164736f6c634300081a000a", } var MultiAggregateRateLimiterABI = MultiAggregateRateLimiterMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/multi_ocr3_helper/multi_ocr3_helper.go b/core/gethwrappers/ccip/generated/multi_ocr3_helper/multi_ocr3_helper.go index 3d43d16d520..3b0b885126a 100644 --- a/core/gethwrappers/ccip/generated/multi_ocr3_helper/multi_ocr3_helper.go +++ b/core/gethwrappers/ccip/generated/multi_ocr3_helper/multi_ocr3_helper.go @@ -58,8 +58,8 @@ type MultiOCR3BaseOracle struct { } var MultiOCR3HelperMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"AfterConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"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\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"oracleAddress\",\"type\":\"address\"}],\"name\":\"getOracle\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"},{\"internalType\":\"enumMultiOCR3Base.Role\",\"name\":\"role\",\"type\":\"uint8\"}],\"internalType\":\"structMultiOCR3Base.Oracle\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"setTransmitOcrPluginType\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[2]\",\"name\":\"reportContext\",\"type\":\"bytes32[2]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"transmitWithSignatures\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[2]\",\"name\":\"reportContext\",\"type\":\"bytes32[2]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"transmitWithoutSignatures\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x60a060405234801561001057600080fd5b503360008161003257604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0384811691909117909155811615610062576100628161006d565b5050466080526100e6565b336001600160a01b0382160361009657604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b608051611d256200010960003960008181610edd0152610f290152611d256000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c80637ac0aa1a11610076578063c673e5841161005b578063c673e584146101c5578063f2fde38b146101e5578063f716f99f146101f857600080fd5b80637ac0aa1a1461015b5780638da5cb5b1461019d57600080fd5b806334a9c92e116100a757806334a9c92e146101205780633ecdb95b1461014057806379ba50971461015357600080fd5b806310061068146100c3578063181f5a77146100d8575b600080fd5b6100d66100d1366004611524565b61020b565b005b604080518082018252601981527f4d756c74694f4352334261736548656c70657220312e302e3000000000000000602082015290516101179190611578565b60405180910390f35b61013361012e36600461161f565b61023a565b6040516101179190611681565b6100d661014e3660046116f4565b6102ca565b6100d661034d565b6100d66101693660046117a7565b600480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff92909216919091179055565b60015460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610117565b6101d86101d33660046117a7565b61041b565b604051610117919061181b565b6100d66101f33660046118ae565b610593565b6100d6610206366004611a1a565b6105a7565b604080516000808252602082019092526004549091506102349060ff16858585858060006105e9565b50505050565b6040805180820182526000808252602080830182905260ff86811683526003825284832073ffffffffffffffffffffffffffffffffffffffff871684528252918490208451808601909552805480841686529394939092918401916101009091041660028111156102ad576102ad611652565b60028111156102be576102be611652565b90525090505b92915050565b60045460408051602080880282810182019093528782526103439360ff16928c928c928c928c918c91829185019084908082843760009201919091525050604080516020808d0282810182019093528c82529093508c92508b9182918501908490808284376000920191909152508a92506105e9915050565b5050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461039e576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61045e6040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561051457602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116104e9575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561058357602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610558575b5050505050815250509050919050565b61059b610972565b6105a4816109c5565b50565b6105af610972565b60005b81518110156105e5576105dd8282815181106105d0576105d0611b83565b6020026020010151610a89565b6001016105b2565b5050565b60ff87811660009081526002602090815260408083208151608081018352815481526001909101548086169382019390935261010083048516918101919091526201000090910490921615156060830152873590610648876084611be1565b9050826060015115610690578451610661906020611bf4565b865161066e906020611bf4565b6106799060a0611be1565b6106839190611be1565b61068d9082611be1565b90505b3681146106d7576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044015b60405180910390fd5b508151811461071f5781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016106ce565b610727610eda565b60ff808a166000908152600360209081526040808320338452825280832081518083019092528054808616835293949193909284019161010090910416600281111561077557610775611652565b600281111561078657610786611652565b90525090506002816020015160028111156107a3576107a3611652565b1480156108045750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff16815481106107df576107df611b83565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b61083a576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5081606001511561091c576020820151610855906001611c0b565b60ff16855114610891576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83518551146108cc576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600087876040516108de929190611c24565b6040519081900381206108f5918b90602001611c34565b60405160208183030381529060405280519060200120905061091a8a82888888610f5b565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146109c3576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b3373ffffffffffffffffffffffffffffffffffffffff821603610a14576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff16600003610acd5760006040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b60208082015160ff80821660009081526002909352604083206001810154929390928392169003610b3a57606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055610b8f565b6060840151600182015460ff6201000090910416151590151514610b8f576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016106ce565b60a084015180516101001015610bd45760016040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b8051600003610c125760056040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b610c858484600301805480602002602001604051908101604052809291908181526020018280548015610c7b57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610c50575b505050505061116b565b846060015115610e2a57610d008484600201805480602002602001604051908101604052809291908181526020018280548015610c7b5760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610c5057505050505061116b565b608085015180516101001015610d455760026040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b6040860151610d55906003611c62565b60ff16815111610d945760036040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b815181511015610dd35760016040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b80516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff841602179055610e1b906002860190602084019061142b565b50610e2885826001611203565b505b610e3684826002611203565b8051610e4b906003850190602084019061142b565b506040858101516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f54793610ec29389939260028a01929190611c85565b60405180910390a1610ed3846113f2565b5050505050565b467f0000000000000000000000000000000000000000000000000000000000000000146109c3576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016106ce565b8251600090815b81811015610343576000600188868460208110610f8157610f81611b83565b610f8e91901a601b611c0b565b898581518110610fa057610fa0611b83565b6020026020010151898681518110610fba57610fba611b83565b602002602001015160405160008152602001604052604051610ff8949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa15801561101a573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015160ff808e1660009081526003602090815285822073ffffffffffffffffffffffffffffffffffffffff8516835281528582208587019096528554808416865293975090955092939284019161010090041660028111156110a6576110a6611652565b60028111156110b7576110b7611652565b90525090506001816020015160028111156110d4576110d4611652565b1461110b576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600160ff9091161b85161561114e576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050610f62565b60005b81518110156111fe5760ff8316600090815260036020526040812083519091908490849081106111a0576111a0611b83565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016905560010161116e565b505050565b60005b825181101561023457600083828151811061122357611223611b83565b602002602001015190506000600281111561124057611240611652565b60ff808716600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152902054610100900416600281111561128c5761128c611652565b146112c65760046040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b73ffffffffffffffffffffffffffffffffffffffff8116611313576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff16815260200184600281111561133957611339611652565b905260ff808716600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845282529091208351815493167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00841681178255918401519092909183917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016176101008360028111156113de576113de611652565b021790555090505050806001019050611206565b60405160ff821681527f897ac1b2c12867721b284f3eb147bd4ab046d4eef1cf31c1d8988bfcfb962b539060200160405180910390a150565b8280548282559060005260206000209081019282156114a5579160200282015b828111156114a557825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90911617825560209092019160019091019061144b565b506114b19291506114b5565b5090565b5b808211156114b157600081556001016114b6565b80604081018310156102c457600080fd5b60008083601f8401126114ed57600080fd5b50813567ffffffffffffffff81111561150557600080fd5b60208301915083602082850101111561151d57600080fd5b9250929050565b60008060006060848603121561153957600080fd5b61154385856114ca565b9250604084013567ffffffffffffffff81111561155f57600080fd5b61156b868287016114db565b9497909650939450505050565b60006020808352835180602085015260005b818110156115a65785810183015185820160400152820161158a565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803560ff811681146115f657600080fd5b919050565b803573ffffffffffffffffffffffffffffffffffffffff811681146115f657600080fd5b6000806040838503121561163257600080fd5b61163b836115e5565b9150611649602084016115fb565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b815160ff16815260208201516040820190600381106116a2576116a2611652565b8060208401525092915050565b60008083601f8401126116c157600080fd5b50813567ffffffffffffffff8111156116d957600080fd5b6020830191508360208260051b850101111561151d57600080fd5b60008060008060008060008060c0898b03121561171057600080fd5b61171a8a8a6114ca565b9750604089013567ffffffffffffffff8082111561173757600080fd5b6117438c838d016114db565b909950975060608b013591508082111561175c57600080fd5b6117688c838d016116af565b909750955060808b013591508082111561178157600080fd5b5061178e8b828c016116af565b999c989b50969995989497949560a00135949350505050565b6000602082840312156117b957600080fd5b6117c2826115e5565b9392505050565b60008151808452602080850194506020840160005b8381101561181057815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016117de565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a084015261186a60e08401826117c9565b905060408401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160c08501526118a582826117c9565b95945050505050565b6000602082840312156118c057600080fd5b6117c2826115fb565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff8111828210171561191b5761191b6118c9565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611968576119686118c9565b604052919050565b600067ffffffffffffffff82111561198a5761198a6118c9565b5060051b60200190565b803580151581146115f657600080fd5b600082601f8301126119b557600080fd5b813560206119ca6119c583611970565b611921565b8083825260208201915060208460051b8701019350868411156119ec57600080fd5b602086015b84811015611a0f57611a02816115fb565b83529183019183016119f1565b509695505050505050565b60006020808385031215611a2d57600080fd5b823567ffffffffffffffff80821115611a4557600080fd5b818501915085601f830112611a5957600080fd5b8135611a676119c582611970565b81815260059190911b83018401908481019088831115611a8657600080fd5b8585015b83811015611b7657803585811115611aa157600080fd5b860160c0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215611ad65760008081fd5b611ade6118f8565b8882013581526040611af18184016115e5565b8a8301526060611b028185016115e5565b8284015260809150611b15828501611994565b9083015260a08381013589811115611b2d5760008081fd5b611b3b8f8d838801016119a4565b838501525060c0840135915088821115611b555760008081fd5b611b638e8c848701016119a4565b9083015250845250918601918601611a8a565b5098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156102c4576102c4611bb2565b80820281158282048414176102c4576102c4611bb2565b60ff81811683821601908111156102c4576102c4611bb2565b8183823760009101908152919050565b828152604082602083013760600192915050565b6020810160068310611c5c57611c5c611652565b91905290565b60ff8181168382160290811690818114611c7e57611c7e611bb2565b5092915050565b600060a0820160ff88168352602087602085015260a0604085015281875480845260c086019150886000526020600020935060005b81811015611cec57845473ffffffffffffffffffffffffffffffffffffffff1683526001948501949284019201611cba565b50508481036060860152611d0081886117c9565b935050505060ff83166080830152969550505050505056fea164736f6c6343000818000a", + ABI: "[{\"type\":\"function\",\"name\":\"acceptOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getOracle\",\"inputs\":[{\"name\":\"ocrPluginType\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"oracleAddress\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structMultiOCR3Base.Oracle\",\"components\":[{\"name\":\"index\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"role\",\"type\":\"uint8\",\"internalType\":\"enumMultiOCR3Base.Role\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"latestConfigDetails\",\"inputs\":[{\"name\":\"ocrPluginType\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"outputs\":[{\"name\":\"ocrConfig\",\"type\":\"tuple\",\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"components\":[{\"name\":\"configInfo\",\"type\":\"tuple\",\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"components\":[{\"name\":\"configDigest\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"F\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"n\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"}]},{\"name\":\"signers\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"transmitters\",\"type\":\"address[]\",\"internalType\":\"address[]\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"setOCR3Configs\",\"inputs\":[{\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\",\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"components\":[{\"name\":\"configDigest\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"ocrPluginType\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"F\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"signers\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"transmitters\",\"type\":\"address[]\",\"internalType\":\"address[]\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setTransmitOcrPluginType\",\"inputs\":[{\"name\":\"ocrPluginType\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transmitWithSignatures\",\"inputs\":[{\"name\":\"reportContext\",\"type\":\"bytes32[2]\",\"internalType\":\"bytes32[2]\"},{\"name\":\"report\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"rs\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"ss\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"rawVs\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transmitWithoutSignatures\",\"inputs\":[{\"name\":\"reportContext\",\"type\":\"bytes32[2]\",\"internalType\":\"bytes32[2]\"},{\"name\":\"report\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"typeAndVersion\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"pure\"},{\"type\":\"event\",\"name\":\"AfterConfigSet\",\"inputs\":[{\"name\":\"ocrPluginType\",\"type\":\"uint8\",\"indexed\":false,\"internalType\":\"uint8\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ConfigSet\",\"inputs\":[{\"name\":\"ocrPluginType\",\"type\":\"uint8\",\"indexed\":false,\"internalType\":\"uint8\"},{\"name\":\"configDigest\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"},{\"name\":\"signers\",\"type\":\"address[]\",\"indexed\":false,\"internalType\":\"address[]\"},{\"name\":\"transmitters\",\"type\":\"address[]\",\"indexed\":false,\"internalType\":\"address[]\"},{\"name\":\"F\",\"type\":\"uint8\",\"indexed\":false,\"internalType\":\"uint8\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferRequested\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Transmitted\",\"inputs\":[{\"name\":\"ocrPluginType\",\"type\":\"uint8\",\"indexed\":true,\"internalType\":\"uint8\"},{\"name\":\"configDigest\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"},{\"name\":\"sequenceNumber\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"CannotTransferToSelf\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ConfigDigestMismatch\",\"inputs\":[{\"name\":\"expected\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"actual\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"ForkedChain\",\"inputs\":[{\"name\":\"expected\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"actual\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"InsufficientGasForCallWithExact\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidConfig\",\"inputs\":[{\"name\":\"errorType\",\"type\":\"uint8\",\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\"}]},{\"type\":\"error\",\"name\":\"MustBeProposedOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NonUniqueSignatures\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OnlyCallableByOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OracleCannotBeZeroAddress\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OwnerCannotBeZero\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"SignaturesOutOfRegistration\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"StaticConfigCannotBeChanged\",\"inputs\":[{\"name\":\"ocrPluginType\",\"type\":\"uint8\",\"internalType\":\"uint8\"}]},{\"type\":\"error\",\"name\":\"UnauthorizedSigner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnauthorizedTransmitter\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"WrongMessageLength\",\"inputs\":[{\"name\":\"expected\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"actual\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"WrongNumberOfSignatures\",\"inputs\":[]}]", + Bin: "0x60a080604052346051573315604057600180546001600160a01b0319163317905546608052611f5890816100578239608051818181610f2f01526116b70152f35b639b15e16f60e01b60005260046000fd5b600080fdfe6080604052600436101561001257600080fd5b60003560e01c806310061068146115fb578063181f5a771461152b57806334a9c92e146114445780633ecdb95b14610e2d57806379ba509714610d445780637ac0aa1a14610cdc5780638da5cb5b14610c8a578063c673e58414610b2e578063f2fde38b14610a3b5763f716f99f1461008a57600080fd5b34610a365760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610a365760043567ffffffffffffffff8111610a365736602382011215610a365780600401356100e481611c52565b916100f26040519384611c11565b8183526024602084019260051b82010190368211610a365760248101925b82841061093b5784610120611e90565b6002906000805b82518110156109395761013a8184611e00565b5190604082019060ff8251161561090a5760ff60208401511692836000528660205260406000206001810190815460ff8116156000146108c6577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff62ff00006060860151151560101b1691161782555b60a08301928351956101008751116107dc578651156108975760038301996101eb6101de6101e58d60405192838092611db0565b0382611c11565b8a611edb565b6060830151610566575b60005b88518110156103b55773ffffffffffffffffffffffffffffffffffffffff610220828b611e00565b5116908a600052600360205260ff60408060002060009073ffffffffffffffffffffffffffffffffffffffff86168252602052205460081c16600381101561032e5761038757811561035d578b6040519261027a84611bbd565b60ff83168452602084019161032e578f604060ff928f8493865260005260036020528160002073ffffffffffffffffffffffffffffffffffffffff60009216825260205220945116167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008454161783555191600383101561032e576001927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff61ff0083549260081b169116179055016101f8565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7fd6c62c9b0000000000000000000000000000000000000000000000000000000060005260046000fd5b7f367f56a2000000000000000000000000000000000000000000000000000000006000526004805260246000fd5b509997969091929394959781519167ffffffffffffffff83116105375768010000000000000000831161053757815483835580841061050e575b509060208d989796959493920190600052602060002060005b8381106104e157505050509360019796936104cb7fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547946104bd7f897ac1b2c12867721b284f3eb147bd4ab046d4eef1cf31c1d8988bfcfb962b53999560ff60209a51169460ff86167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055519485835551916040519687968a88528b88015260a0604088015260a087019101611db0565b908482036060860152611b73565b9060808301520390a1604051908152a101610127565b825173ffffffffffffffffffffffffffffffffffffffff16818301558e9950602090920191600101610408565b8260005283602060002091820191015b81811061052b57506103ef565b6000815560010161051e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8b840161058360405161057d816101de8186611db0565b8b611edb565b60808401519061010082511161086957815160ff8551166003029060ff821691820361083a57111561080b5781518a51116107dc5781519087547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff61ff008460081b16911617885567ffffffffffffffff8211610537576801000000000000000082116105375780548282558083106107b3575b506020830190600052602060002060005b8381106107895750600193600093508392509050835b61064c575b505050506101f5565b80518310156107845773ffffffffffffffffffffffffffffffffffffffff6106748483611e00565b5116928d600052600360205260ff60408060002060009073ffffffffffffffffffffffffffffffffffffffff88168252602052205460081c16600381101561032e5761038757831561035d5782604051946106ce86611bbd565b60ff83168652602086019161032e578f604060ff9283928a865260005260036020528160002073ffffffffffffffffffffffffffffffffffffffff60009216825260205220965116167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008654161785555190600382101561032e57859485927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff61ff0083549260081b169116179055019261063e565b610643565b600190602073ffffffffffffffffffffffffffffffffffffffff8551169401938184015501610628565b8160005282602060002091820191015b8181106107d05750610617565b600081556001016107c3565b7f367f56a200000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b7f367f56a200000000000000000000000000000000000000000000000000000000600052600360045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8d7f367f56a20000000000000000000000000000000000000000000000000000000060005260045260246000fd5b7f367f56a200000000000000000000000000000000000000000000000000000000600052600560045260246000fd5b60ff606085015115159160101c16151503156101aa57857f87f6037c0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b7f367f56a200000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b005b833567ffffffffffffffff8111610a3657820160c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc8236030112610a36576040519160c0830183811067ffffffffffffffff82111761053757604052602482013583526109ab60448301611b34565b60208401526109bc60648301611b34565b604084015260848201358015158103610a3657606084015260a482013567ffffffffffffffff8111610a36576109f89060243691850101611c6a565b608084015260c48201359267ffffffffffffffff8411610a3657610a26602094936024869536920101611c6a565b60a0820152815201930192610110565b600080fd5b34610a365760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610a365760043573ffffffffffffffffffffffffffffffffffffffff8116809103610a3657610a93611e90565b338114610b0457807fffffffffffffffffffffffff0000000000000000000000000000000000000000600054161760005573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b7fdad89dca0000000000000000000000000000000000000000000000000000000060005260046000fd5b34610a365760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610a365760ff610b67611b24565b606060408051610b7681611bd9565b8151610b8181611bf5565b60008152600060208201526000838201526000848201528152826020820152015216600052600260205260606040600020610c866003610c5560405193610bc785611bd9565b610bd081611d77565b8552610c0860405191610bf183610bea8160028501611db0565b0384611c11565b60208701928352610bea6040518096819301611db0565b6040850192835260405195869560208752518051602088015260ff602082015116604088015260ff604082015116828801520151151560808601525160c060a086015260e0850190611b73565b90517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160c0850152611b73565b0390f35b34610a365760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610a3657602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b34610a365760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610a365760ff610d15611b24565b167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff006004541617600455600080f35b34610a365760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610a365760005473ffffffffffffffffffffffffffffffffffffffff81163303610e03577fffffffffffffffffffffffff00000000000000000000000000000000000000006001549133828416176001551660005573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b7f02b543c60000000000000000000000000000000000000000000000000000000060005260046000fd5b34610a365760c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610a365736604411610a365760443567ffffffffffffffff8111610a3657610e84903690600401611af6565b9060643567ffffffffffffffff8111610a3657610ea5903690600401611b42565b919060843567ffffffffffffffff8111610a3657610eca610ee9913690600401611b42565b9190610ee160a4359460ff60045416973691611d2b565b923691611d2b565b90846000526002602052610f006040600020611d77565b9560043594610f0e82611e43565b97606081019889516113f7575b8036036113c65750805187810361139457507f00000000000000000000000000000000000000000000000000000000000000004681036113635750876000526003602052604060002073ffffffffffffffffffffffffffffffffffffffff331660005260205260406000209860405199610f948b611bbd565b5460ff81168b52610faf60ff60208d019260081c1682611d1f565b519960038b101561032e57600260009b1490816112ee575b50156112ab575b51611015575b88887f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef060408a815190815267ffffffffffffffff602435166020820152a280f35b60ff611028816020875194015116611e6c565b160361128357825184510361125b578761104183611ce5565b9161104f6040519384611c11565b8383526020830193368183011161125757806020928637830101525190206040516020810191825260406004818301376060815261108e608082611c11565b51902090869281519488945b8686106110a75750610fd4565b602086101561122a5760208a60806110c0858a1a611e7e565b6110ca8a89611e00565b516110d58b89611e00565b519060ff604051938c855216868401526040830152606082015282805260015afa1561121f578951898b52600360205273ffffffffffffffffffffffffffffffffffffffff60408c2091168b5260205260408a206040519061113682611bbd565b5460ff8116825261115160ff602084019260081c1682611d1f565b5160038110156111f2577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff016111ca57600160ff8251161b82166111a25790600160ff819351161b1795019461109a565b60048b7ff67bc7c4000000000000000000000000000000000000000000000000000000008152fd5b60048b7fca31867a000000000000000000000000000000000000000000000000000000008152fd5b60248c7f4e487b710000000000000000000000000000000000000000000000000000000081526021600452fd5b6040513d8b823e3d90fd5b60248a7f4e487b710000000000000000000000000000000000000000000000000000000081526032600452fd5b8280fd5b6004887fa75d88af000000000000000000000000000000000000000000000000000000008152fd5b6004887f71253a25000000000000000000000000000000000000000000000000000000008152fd5b72c11c11c11c11c11c11c11c11c11c11c11c11c1330315610fce5760048a7fda0f08e8000000000000000000000000000000000000000000000000000000008152fd5b9050898b52600260205260ff600360408d2001915116908054821015611336579073ffffffffffffffffffffffffffffffffffffffff918c5260208c2001541633148b610fc7565b60248c7f4e487b710000000000000000000000000000000000000000000000000000000081526032600452fd5b7f0f01ce85000000000000000000000000000000000000000000000000000000006000526004524660245260446000fd5b87907f93df584c0000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b7f8e1192e1000000000000000000000000000000000000000000000000000000006000526004523660245260446000fd5b84518060051b908082046020149015171561083a5761141590611e51565b908651918260051b928084046020149015171561083a5761143f9261143991611e5f565b90611e5f565b610f1b565b34610a365760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610a365761147b611b24565b6024359073ffffffffffffffffffffffffffffffffffffffff82168203610a365760ff90600060206040516114af81611bbd565b828152015216600052600360205273ffffffffffffffffffffffffffffffffffffffff604060002091166000526020526040600020604051906114f182611bbd565b5460ff8116825261150c60ff602084019260081c1682611d1f565b60ff60405192511682525190600382101561032e576040916020820152f35b34610a365760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610a365760408051906115698183611c11565b601982527f4d756c74694f4352334261736548656c70657220312e302e30000000000000006020830152805180926020825280519081602084015260005b8281106115e45750506000828201840152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168101030190f35b6020828201810151878301870152869450016115a7565b34610a365760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610a365736604411610a365760443567ffffffffffffffff8111610a3657611652903690600401611af6565b604051602092916116638483611c11565b60008252600036813760ff600454169182600052600285526116886040600020611d77565b936004359261169681611e43565b9560608101968751611ab1575b8036036113c657508051858103611a7f57507f000000000000000000000000000000000000000000000000000000000000000046810361136357508560005260038852604060002073ffffffffffffffffffffffffffffffffffffffff331660005288526040600020966040519761171a89611bbd565b5460ff8116895261173460ff8b8b019260081c1682611d1f565b5197600389101561032e576002600099149081611a39575b50156119f6575b5161179a575b86867f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef06040888c825191825267ffffffffffffffff6024351690820152a280f35b60ff6117ac818a875194015116611e6c565b16036119ce576117bb81611ce5565b906117c96040519283611c11565b8082528782019236828201116119ca578188928a92863783010152519020604051868101918252604060048183013760608152611807608082611c11565b519020849082519286925b84841061181f5750611759565b8884101561199d578888608061183682881a611e7e565b6118408887611e00565b5161184b8988611e00565b519060ff604051938a855216868401526040830152606082015282805260015afa1561199257875187895260038a5273ffffffffffffffffffffffffffffffffffffffff60408a2091168952895260408820604051906118aa82611bbd565b5460ff811682526118c460ff8c84019260081c1682611d1f565b516003811015611965577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0161193d57600160ff8251161b82166119155790600160ff819351161b17930192611812565b6004897ff67bc7c4000000000000000000000000000000000000000000000000000000008152fd5b6004897fca31867a000000000000000000000000000000000000000000000000000000008152fd5b60248a7f4e487b710000000000000000000000000000000000000000000000000000000081526021600452fd5b6040513d89823e3d90fd5b6024887f4e487b710000000000000000000000000000000000000000000000000000000081526032600452fd5b8780fd5b6004867f71253a25000000000000000000000000000000000000000000000000000000008152fd5b72c11c11c11c11c11c11c11c11c11c11c11c11c1330315611753576004887fda0f08e8000000000000000000000000000000000000000000000000000000008152fd5b905087895260028a5260ff600360408b200191511690805482101561122a579073ffffffffffffffffffffffffffffffffffffffff918a528a8a2001541633148a61174c565b85907f93df584c0000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b84518060051b908082048b149015171561083a57611ace90611e51565b908551918260051b928084048c149015171561083a57611af19261143991611e5f565b6116a3565b9181601f84011215610a365782359167ffffffffffffffff8311610a365760208381860195010111610a3657565b6004359060ff82168203610a3657565b359060ff82168203610a3657565b9181601f84011215610a365782359167ffffffffffffffff8311610a36576020808501948460051b010111610a3657565b906020808351928381520192019060005b818110611b915750505090565b825173ffffffffffffffffffffffffffffffffffffffff16845260209384019390920191600101611b84565b6040810190811067ffffffffffffffff82111761053757604052565b6060810190811067ffffffffffffffff82111761053757604052565b6080810190811067ffffffffffffffff82111761053757604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761053757604052565b67ffffffffffffffff81116105375760051b60200190565b9080601f83011215610a3657813590611c8282611c52565b92611c906040519485611c11565b82845260208085019360051b820101918211610a3657602001915b818310611cb85750505090565b823573ffffffffffffffffffffffffffffffffffffffff81168103610a3657815260209283019201611cab565b67ffffffffffffffff811161053757601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600382101561032e5752565b929190611d3781611c52565b93611d456040519586611c11565b602085838152019160051b8101928311610a3657905b828210611d6757505050565b8135815260209182019101611d5b565b90604051611d8481611bf5565b606060ff600183958054855201548181166020850152818160081c16604085015260101c161515910152565b906020825491828152019160005260206000209060005b818110611dd45750505090565b825473ffffffffffffffffffffffffffffffffffffffff16845260209093019260019283019201611dc7565b8051821015611e145760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b608401908160841161083a57565b60a001908160a01161083a57565b9190820180921161083a57565b60ff60019116019060ff821161083a57565b60ff601b9116019060ff821161083a57565b73ffffffffffffffffffffffffffffffffffffffff600154163303611eb157565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b91909160005b8351811015611f455760019060ff831660005260036020526000604080822073ffffffffffffffffffffffffffffffffffffffff611f1f858a611e00565b511673ffffffffffffffffffffffffffffffffffffffff16835260205281205501611ee1565b5050905056fea164736f6c634300081a000a", } var MultiOCR3HelperABI = MultiOCR3HelperMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/nonce_manager/nonce_manager.go b/core/gethwrappers/ccip/generated/nonce_manager/nonce_manager.go index ccd28cdd6ce..5593b55e827 100644 --- a/core/gethwrappers/ccip/generated/nonce_manager/nonce_manager.go +++ b/core/gethwrappers/ccip/generated/nonce_manager/nonce_manager.go @@ -47,8 +47,8 @@ type NonceManagerPreviousRampsArgs struct { } var NonceManagerMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"authorizedCallers\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PreviousRampAlreadySet\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerRemoved\",\"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\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"prevOnRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structNonceManager.PreviousRamps\",\"name\":\"prevRamp\",\"type\":\"tuple\"}],\"name\":\"PreviousRampsUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"}],\"name\":\"SkippedIncorrectNonce\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address[]\",\"name\":\"addedCallers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedCallers\",\"type\":\"address[]\"}],\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\"}],\"name\":\"applyAuthorizedCallerUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"overrideExistingRamps\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"prevOnRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"}],\"internalType\":\"structNonceManager.PreviousRamps\",\"name\":\"prevRamps\",\"type\":\"tuple\"}],\"internalType\":\"structNonceManager.PreviousRampsArgs[]\",\"name\":\"previousRampsArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyPreviousRampsUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedCallers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"}],\"name\":\"getInboundNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"getIncrementedOutboundNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"getOutboundNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"getPreviousRamps\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"prevOnRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"}],\"internalType\":\"structNonceManager.PreviousRamps\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"expectedNonce\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"}],\"name\":\"incrementInboundNonce\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"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\"}]", - Bin: "0x60806040523480156200001157600080fd5b5060405162001ad438038062001ad4833981016040819052620000349162000449565b80336000816200005757604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008a576200008a81620000c0565b5050604080518082018252828152815160008152602080820190935291810191909152620000b8906200013a565b505062000569565b336001600160a01b03821603620000ea57604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b8151811015620001ca5760008282815181106200016357620001636200051b565b602090810291909101015190506200017d60028262000289565b15620001c0576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b5060010162000142565b50815160005b815181101562000283576000828281518110620001f157620001f16200051b565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200022f576040516342bcdf7f60e11b815260040160405180910390fd5b6200023c600282620002a9565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101620001d0565b50505050565b6000620002a0836001600160a01b038416620002c0565b90505b92915050565b6000620002a0836001600160a01b038416620003c4565b60008181526001830160205260408120548015620003b9576000620002e760018362000531565b8554909150600090620002fd9060019062000531565b9050818114620003695760008660000182815481106200032157620003216200051b565b90600052602060002001549050808760000184815481106200034757620003476200051b565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806200037d576200037d62000553565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620002a3565b6000915050620002a3565b60008181526001830160205260408120546200040d57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620002a3565b506000620002a3565b634e487b7160e01b600052604160045260246000fd5b80516001600160a01b03811681146200044457600080fd5b919050565b600060208083850312156200045d57600080fd5b82516001600160401b03808211156200047557600080fd5b818501915085601f8301126200048a57600080fd5b8151818111156200049f576200049f62000416565b8060051b604051601f19603f83011681018181108582111715620004c757620004c762000416565b604052918252848201925083810185019188831115620004e657600080fd5b938501935b828510156200050f57620004ff856200042c565b84529385019392850192620004eb565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b81810381811115620002a357634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b61155b80620005796000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c806391a2749a11610081578063e0e03cae1161005b578063e0e03cae1461027c578063ea458c0c1461029f578063f2fde38b146102b257600080fd5b806391a2749a1461022a578063bf18402a1461023d578063c92236251461026957600080fd5b806379ba5097116100b257806379ba5097146101e55780637a75a094146101ef5780638da5cb5b1461020257600080fd5b8063181f5a77146100d95780632451a6271461012b578063294b563014610140575b600080fd5b6101156040518060400160405280601681526020017f4e6f6e63654d616e6167657220312e362e302d6465760000000000000000000081525081565b6040516101229190610f05565b60405180910390f35b6101336102c5565b6040516101229190610f72565b6101b161014e366004610fe2565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600460209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff9081168452600190910154169082015290565b60408051825173ffffffffffffffffffffffffffffffffffffffff9081168252602093840151169281019290925201610122565b6101ed6102d6565b005b6101ed6101fd366004610fff565b6103a4565b60015460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610122565b6101ed61023836600461118a565b610594565b61025061024b366004611231565b6105a8565b60405167ffffffffffffffff9091168152602001610122565b6102506102773660046112b3565b6105bd565b61028f61028a366004611308565b6105d4565b6040519015158152602001610122565b6102506102ad366004611231565b6106dd565b6101ed6102c036600461136d565b610771565b60606102d16002610782565b905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314610327576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6103ac61078f565b60005b8181101561058f57368383838181106103ca576103ca61138a565b608002919091019150600090506004816103e76020850185610fe2565b67ffffffffffffffff1681526020810191909152604001600020805490915073ffffffffffffffffffffffffffffffffffffffff161515806104425750600181015473ffffffffffffffffffffffffffffffffffffffff1615155b1561048d5761045760408301602084016113b9565b61048d576040517fc6117ae200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61049d606083016040840161136d565b81547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff919091161781556104ed608083016060840161136d565b6001820180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff929092169190911790556105416020830183610fe2565b67ffffffffffffffff167fa2e43edcbc4fd175ae4bebbe3fd6139871ed1f1783cd4a1ace59b90d302c33198360400160405161057d91906113db565b60405180910390a250506001016103af565b505050565b61059c61078f565b6105a5816107e2565b50565b60006105b48383610974565b90505b92915050565b60006105ca848484610a91565b90505b9392505050565b60006105de610be2565b60006105eb868585610a91565b6105f6906001611452565b90508467ffffffffffffffff168167ffffffffffffffff161461065a577f606ff8179e5e3c059b82df931acc496b7b6053e8879042f8267f930e0595f69f868686866040516106489493929190611473565b60405180910390a160009150506106d5565b67ffffffffffffffff861660009081526006602052604090819020905182919061068790879087906114df565b908152604051908190036020019020805467ffffffffffffffff929092167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090921691909117905550600190505b949350505050565b60006106e7610be2565b60006106f38484610974565b6106fe906001611452565b67ffffffffffffffff808616600090815260056020908152604080832073ffffffffffffffffffffffffffffffffffffffff89168452909152902080549183167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090921691909117905591505092915050565b61077961078f565b6105a581610c29565b606060006105cd83610ced565b60015473ffffffffffffffffffffffffffffffffffffffff1633146107e0576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b602081015160005b815181101561087d5760008282815181106108075761080761138a565b60200260200101519050610825816002610d4990919063ffffffff16565b156108745760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b506001016107ea565b50815160005b815181101561096e5760008282815181106108a0576108a061138a565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610910576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61091b600282610d6b565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101610883565b50505050565b67ffffffffffffffff808316600090815260056020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091528120549091168082036105b45767ffffffffffffffff841660009081526004602052604090205473ffffffffffffffffffffffffffffffffffffffff168015610a89576040517f856c824700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015282169063856c824790602401602060405180830381865afa158015610a5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8091906114ef565b925050506105b7565b509392505050565b67ffffffffffffffff83166000908152600660205260408082209051829190610abd90869086906114df565b9081526040519081900360200190205467ffffffffffffffff16905060008190036105ca5767ffffffffffffffff851660009081526004602052604090206001015473ffffffffffffffffffffffffffffffffffffffff168015610bd95773ffffffffffffffffffffffffffffffffffffffff811663856c8247610b438688018861136d565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401602060405180830381865afa158015610bac573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bd091906114ef565b925050506105cd565b50949350505050565b610bed600233610d8d565b6107e0576040517fd86ad9cf00000000000000000000000000000000000000000000000000000000815233600482015260240160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821603610c78576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b606081600001805480602002602001604051908101604052809291908181526020018280548015610d3d57602002820191906000526020600020905b815481526020019060010190808311610d29575b50505050509050919050565b60006105b48373ffffffffffffffffffffffffffffffffffffffff8416610dbc565b60006105b48373ffffffffffffffffffffffffffffffffffffffff8416610eb6565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260018301602052604081205415156105b4565b60008181526001830160205260408120548015610ea5576000610de060018361150c565b8554909150600090610df49060019061150c565b9050818114610e59576000866000018281548110610e1457610e1461138a565b9060005260206000200154905080876000018481548110610e3757610e3761138a565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080610e6a57610e6a61151f565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105b7565b60009150506105b7565b5092915050565b6000818152600183016020526040812054610efd575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105b7565b5060006105b7565b60006020808352835180602085015260005b81811015610f3357858101830151858201604001528201610f17565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b6020808252825182820181905260009190848201906040850190845b81811015610fc057835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101610f8e565b50909695505050505050565b67ffffffffffffffff811681146105a557600080fd5b600060208284031215610ff457600080fd5b81356105b481610fcc565b6000806020838503121561101257600080fd5b823567ffffffffffffffff8082111561102a57600080fd5b818501915085601f83011261103e57600080fd5b81358181111561104d57600080fd5b8660208260071b850101111561106257600080fd5b60209290920196919550909350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff811681146105a557600080fd5b600082601f8301126110d657600080fd5b8135602067ffffffffffffffff808311156110f3576110f3611074565b8260051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f8301168101818110848211171561113657611136611074565b604052938452602081870181019490810192508785111561115657600080fd5b6020870191505b8482101561117f578135611170816110a3565b8352918301919083019061115d565b979650505050505050565b60006020828403121561119c57600080fd5b813567ffffffffffffffff808211156111b457600080fd5b90830190604082860312156111c857600080fd5b6040516040810181811083821117156111e3576111e3611074565b6040528235828111156111f557600080fd5b611201878286016110c5565b82525060208301358281111561121657600080fd5b611222878286016110c5565b60208301525095945050505050565b6000806040838503121561124457600080fd5b823561124f81610fcc565b9150602083013561125f816110a3565b809150509250929050565b60008083601f84011261127c57600080fd5b50813567ffffffffffffffff81111561129457600080fd5b6020830191508360208285010111156112ac57600080fd5b9250929050565b6000806000604084860312156112c857600080fd5b83356112d381610fcc565b9250602084013567ffffffffffffffff8111156112ef57600080fd5b6112fb8682870161126a565b9497909650939450505050565b6000806000806060858703121561131e57600080fd5b843561132981610fcc565b9350602085013561133981610fcc565b9250604085013567ffffffffffffffff81111561135557600080fd5b6113618782880161126a565b95989497509550505050565b60006020828403121561137f57600080fd5b81356105b4816110a3565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156113cb57600080fd5b813580151581146105b457600080fd5b6040810182356113ea816110a3565b73ffffffffffffffffffffffffffffffffffffffff9081168352602084013590611413826110a3565b8082166020850152505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff818116838216019080821115610eaf57610eaf611423565b600067ffffffffffffffff8087168352808616602084015250606060408301528260608301528284608084013760006080848401015260807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f850116830101905095945050505050565b8183823760009101908152919050565b60006020828403121561150157600080fd5b81516105b481610fcc565b818103818111156105b7576105b7611423565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"authorizedCallers\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"acceptOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyAuthorizedCallerUpdates\",\"inputs\":[{\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\",\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"components\":[{\"name\":\"addedCallers\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"removedCallers\",\"type\":\"address[]\",\"internalType\":\"address[]\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyPreviousRampsUpdates\",\"inputs\":[{\"name\":\"previousRampsArgs\",\"type\":\"tuple[]\",\"internalType\":\"structNonceManager.PreviousRampsArgs[]\",\"components\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"overrideExistingRamps\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"prevRamps\",\"type\":\"tuple\",\"internalType\":\"structNonceManager.PreviousRamps\",\"components\":[{\"name\":\"prevOnRamp\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"prevOffRamp\",\"type\":\"address\",\"internalType\":\"address\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getAllAuthorizedCallers\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getInboundNonce\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sender\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getIncrementedOutboundNonce\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getOutboundNonce\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getPreviousRamps\",\"inputs\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structNonceManager.PreviousRamps\",\"components\":[{\"name\":\"prevOnRamp\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"prevOffRamp\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"incrementInboundNonce\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"expectedNonce\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sender\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"typeAndVersion\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"AuthorizedCallerAdded\",\"inputs\":[{\"name\":\"caller\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"AuthorizedCallerRemoved\",\"inputs\":[{\"name\":\"caller\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferRequested\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"PreviousRampsUpdated\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"prevRamp\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structNonceManager.PreviousRamps\",\"components\":[{\"name\":\"prevOnRamp\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"prevOffRamp\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SkippedIncorrectNonce\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"sender\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"CannotTransferToSelf\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MustBeProposedOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OnlyCallableByOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OwnerCannotBeZero\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PreviousRampAlreadySet\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnauthorizedCaller\",\"inputs\":[{\"name\":\"caller\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ZeroAddressNotAllowed\",\"inputs\":[]}]", + Bin: "0x60806040523461020f576117738038038061001981610214565b92833981019060208183031261020f578051906001600160401b03821161020f570181601f8201121561020f578051916001600160401b0383116101c8578260051b9160208061006a818601610214565b80968152019382010191821161020f57602001915b8183106101ef578333156101de57600180546001600160a01b031916331790556020906100ab82610214565b60008152600036813760408051929083016001600160401b038111848210176101c8576040528252808383015260005b8151811015610142576001906001600160a01b036100f98285610239565b5116856101058261027b565b610112575b5050016100db565b7fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda7758091604051908152a1858561010a565b50505160005b81518110156101b9576001600160a01b036101638284610239565b51169081156101a8577feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef848361019a600195610379565b50604051908152a101610148565b6342bcdf7f60e11b60005260046000fd5b60405161139990816103da8239f35b634e487b7160e01b600052604160045260246000fd5b639b15e16f60e01b60005260046000fd5b82516001600160a01b038116810361020f5781526020928301920161007f565b600080fd5b6040519190601f01601f191682016001600160401b038111838210176101c857604052565b805182101561024d5760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b805482101561024d5760005260206000200190600090565b600081815260036020526040902054801561037257600019810181811161035c5760025460001981019190821161035c5780820361030b575b50505060025480156102f557600019016102cf816002610263565b8154906000199060031b1b19169055600255600052600360205260006040812055600190565b634e487b7160e01b600052603160045260246000fd5b61034461031c61032d936002610263565b90549060031b1c9283926002610263565b819391549060031b91821b91600019901b19161790565b905560005260036020526040600020553880806102b4565b634e487b7160e01b600052601160045260246000fd5b5050600090565b806000526003602052604060002054156000146103d357600254680100000000000000008110156101c8576103ba61032d8260018594016002556002610263565b9055600254906000526003602052604060002055600190565b5060009056fe608080604052600436101561001357600080fd5b60003560e01c908163181f5a7714610a94575080632451a627146109a6578063294b5630146108ff57806379ba5097146108165780637a75a094146105f95780638da5cb5b146105a757806391a2749a146103bd578063bf18402a14610373578063c9223625146102fe578063e0e03cae14610272578063ea458c0c1461019b5763f2fde38b146100a357600080fd5b346101965760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101965760043573ffffffffffffffffffffffffffffffffffffffff8116809103610196576100fb610e81565b33811461016c57807fffffffffffffffffffffffff0000000000000000000000000000000000000000600054161760005573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b7fdad89dca0000000000000000000000000000000000000000000000000000000060005260046000fd5b600080fd5b346101965760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101965760206101d4610bef565b6101dc610c06565b6101e461113a565b67ffffffffffffffff6101ff6101fa8385610f2f565b610d1e565b92166000526005835273ffffffffffffffffffffffffffffffffffffffff604060002091166000528252604060002067ffffffffffffffff82167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000082541617905567ffffffffffffffff60405191168152f35b346101965760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610196576102a9610bef565b60243567ffffffffffffffff81168103610196576044359067ffffffffffffffff8211610196576020926102e46102f4933690600401610cba565b9290916102ef61113a565b610d6d565b6040519015158152f35b346101965760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019657610335610bef565b60243567ffffffffffffffff81116101965760209161035b610361923690600401610cba565b9161104a565b67ffffffffffffffff60405191168152f35b346101965760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101965760206103616103af610bef565b6103b7610c06565b90610f2f565b346101965760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101965760043567ffffffffffffffff81116101965760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8236030112610196576040519061043782610b63565b806004013567ffffffffffffffff81116101965761045b9060043691840101610c4a565b825260248101359067ffffffffffffffff82116101965760046104819236920101610c4a565b60208201908152610490610e81565b519060005b8251811015610508578073ffffffffffffffffffffffffffffffffffffffff6104c060019386610ecc565b51166104cb81611196565b6104d7575b5001610495565b60207fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda7758091604051908152a1846104d0565b505160005b81518110156105a55773ffffffffffffffffffffffffffffffffffffffff6105358284610ecc565b511690811561057b577feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef60208361056d60019561132c565b50604051908152a10161050d565b7f8579befe0000000000000000000000000000000000000000000000000000000060005260046000fd5b005b346101965760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019657602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b346101965760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101965760043567ffffffffffffffff8111610196573660238201121561019657806004013567ffffffffffffffff8111610196573660248260071b8401011161019657610670610e81565b60005b818110156105a55760008160071b84016024810167ffffffffffffffff61069982610ce8565b1683526004602052604083209273ffffffffffffffffffffffffffffffffffffffff845416158015906107f3575b6107b3575b5060408273ffffffffffffffffffffffffffffffffffffffff6107a667ffffffffffffffff6107907fa2e43edcbc4fd175ae4bebbe3fd6139871ed1f1783cd4a1ace59b90d302c3319966084606460019c9b9a01968661072b89610cfd565b167fffffffffffffffffffffffff00000000000000000000000000000000000000008c5416178b550198858c6107608c610cfd565b920191167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055610ce8565b16958261079e865195610c29565b168452610c29565b166020820152a201610673565b60448301358015908115036107ef57156106cc57807fc6117ae20000000000000000000000000000000000000000000000000000000060049252fd5b5080fd5b5073ffffffffffffffffffffffffffffffffffffffff60018501541615156106c7565b346101965760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101965760005473ffffffffffffffffffffffffffffffffffffffff811633036108d5577fffffffffffffffffffffffff00000000000000000000000000000000000000006001549133828416176001551660005573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b7f02b543c60000000000000000000000000000000000000000000000000000000060005260046000fd5b346101965760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101965767ffffffffffffffff61093f610bef565b6000602060405161094f81610b63565b828152015216600052600460205260408060002073ffffffffffffffffffffffffffffffffffffffff825161098381610b63565b602082600181865416958685520154169101908152835192835251166020820152f35b346101965760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610196576040518060206002549283815201809260026000527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace9060005b818110610a7e5750505081610a25910382610bae565b6040519182916020830190602084525180915260408301919060005b818110610a4f575050500390f35b825173ffffffffffffffffffffffffffffffffffffffff16845285945060209384019390920191600101610a41565b8254845260209093019260019283019201610a0f565b346101965760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019657610acc81610b63565b601681527f4e6f6e63654d616e6167657220312e362e302d64657600000000000000000000602082015260405190602082528181519182602083015260005b838110610b4b5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f836000604080968601015201168101030190f35b60208282018101516040878401015285935001610b0b565b6040810190811067ffffffffffffffff821117610b7f57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610b7f57604052565b6004359067ffffffffffffffff8216820361019657565b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361019657565b359073ffffffffffffffffffffffffffffffffffffffff8216820361019657565b9080601f830112156101965781359167ffffffffffffffff8311610b7f578260051b9060405193610c7e6020840186610bae565b845260208085019282010192831161019657602001905b828210610ca25750505090565b60208091610caf84610c29565b815201910190610c95565b9181601f840112156101965782359167ffffffffffffffff8311610196576020838186019501011161019657565b3567ffffffffffffffff811681036101965790565b3573ffffffffffffffffffffffffffffffffffffffff811681036101965790565b67ffffffffffffffff60019116019067ffffffffffffffff8211610d3e57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9291909267ffffffffffffffff610d886101fa85858561104a565b94168067ffffffffffffffff861603610df8575067ffffffffffffffff9291836020921660005260068252604060002083604051948593843782019081520301902091167fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000825416179055600190565b7f606ff8179e5e3c059b82df931acc496b7b6053e8879042f8267f930e0595f69f9450601f8467ffffffffffffffff956080957fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09460405198899716875260208701526060604087015281606087015286860137600085828601015201168101030190a1600090565b73ffffffffffffffffffffffffffffffffffffffff600154163303610ea257565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b8051821015610ee05760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90816020910312610196575167ffffffffffffffff811681036101965790565b67ffffffffffffffff1690816000526005602052604060002073ffffffffffffffffffffffffffffffffffffffff821660005260205267ffffffffffffffff60406000205416918215610f8157505090565b600052600460205273ffffffffffffffffffffffffffffffffffffffff604060002054169081610fb057505090565b6020919250602473ffffffffffffffffffffffffffffffffffffffff9160405194859384927f856c82470000000000000000000000000000000000000000000000000000000084521660048301525afa90811561103e57600091611012575090565b611034915060203d602011611037575b61102c8183610bae565b810190610f0f565b90565b503d611022565b6040513d6000823e3d90fd5b67ffffffffffffffff90929192169182600052600660205267ffffffffffffffff60406000206020604051809286868337868201908152030190205416928315611095575b50505090565b600052600460205273ffffffffffffffffffffffffffffffffffffffff6001604060002001541691821561108f57819293509060209181010312610196573573ffffffffffffffffffffffffffffffffffffffff8116809103610196576020906024604051809481937f856c824700000000000000000000000000000000000000000000000000000000835260048301525afa90811561103e57600091611012575090565b3360005260036020526040600020541561115057565b7fd86ad9cf000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b8054821015610ee05760005260206000200190600090565b6000818152600360205260409020548015611325577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101818111610d3e57600254907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8201918211610d3e578082036112b6575b5050506002548015611287577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0161124481600261117e565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600255600052600360205260006040812055600190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b61130d6112c76112d893600261117e565b90549060031b1c928392600261117e565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b9055600052600360205260406000205538808061120b565b5050600090565b806000526003602052604060002054156000146113865760025468010000000000000000811015610b7f5761136d6112d8826001859401600255600261117e565b9055600254906000526003602052604060002055600190565b5060009056fea164736f6c634300081a000a", } var NonceManagerABI = NonceManagerMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/offramp/offramp.go b/core/gethwrappers/ccip/generated/offramp/offramp.go index 830dcaf7bf4..08a10e52878 100644 --- a/core/gethwrappers/ccip/generated/offramp/offramp.go +++ b/core/gethwrappers/ccip/generated/offramp/offramp.go @@ -156,8 +156,8 @@ type OffRampStaticConfig struct { } var OffRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint16\",\"name\":\"gasForCallExactCheck\",\"type\":\"uint16\"},{\"internalType\":\"contractIRMNRemote\",\"name\":\"rmnRemote\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reportOnRamp\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"configOnRamp\",\"type\":\"bytes\"}],\"name\":\"CommitOnRampMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyBatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"tokenIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"oldLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenGasOverride\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionTokenGasOverride\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidOnRampUpdate\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionGasAmountCountMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignatureVerificationNotAllowedInExecutionPlugin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignatureVerificationRequiredInCommitPlugin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"reportSourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"messageSourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"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\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SkippedReportExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint16\",\"name\":\"gasForCallExactCheck\",\"type\":\"uint16\"},{\"internalType\":\"contractIRMNRemote\",\"name\":\"rmnRemote\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[2]\",\"name\":\"reportContext\",\"type\":\"bytes32[2]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[2]\",\"name\":\"reportContext\",\"type\":\"bytes32[2]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllSourceChainConfigs\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint16\",\"name\":\"gasForCallExactCheck\",\"type\":\"uint16\"},{\"internalType\":\"contractIRMNRemote\",\"name\":\"rmnRemote\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReport[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"receiverExecutionGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"internalType\":\"structOffRamp.GasLimitOverride[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"tuple[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"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\"}]", - Bin: "0x6101406040523480156200001257600080fd5b5060405162006d0638038062006d06833981016040819052620000359162000936565b336000816200005757604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008a576200008a81620001dc565b50504660805260408301516001600160a01b03161580620000b6575060608301516001600160a01b0316155b80620000cd575060808301516001600160a01b0316155b15620000ec576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b0316600003620001185760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a0908152604080860180516001600160a01b0390811660c05260608089018051831660e0526080808b0180518516610100526020808d01805161ffff9081166101205289518f51909c168c52905116908a0152945184169588019590955251821690860152905116908301527fb0fa1fb01508c5097c502ad056fd77018870c9be9a86d9e56b6b471862d7c5b7910160405180910390a1620001c88262000256565b620001d38162000344565b50505062000cde565b336001600160a01b038216036200020657604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b03166200027f576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516001600160a01b039889166001600160c01b03199097168717600160a01b63ffffffff958616021760ff60c01b1916600160c01b911515919091021790965560608089018051600580546001600160a01b031916918b169190911790558251968752935190921693850193909352935115159183019190915251909216908201527fcbb53bda7106a610de67df506ac86b65c44d5afac0fd2b11070dc2d61a6f2dee9060800160405180910390a150565b60005b8151811015620005d957600082828151811062000368576200036862000a16565b60200260200101519050600081602001519050806001600160401b0316600003620003a65760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b0316620003cf576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b03811660009081526008602052604090206060830151600182018054620003fd9062000a2c565b905060000362000460578154600160a81b600160e81b031916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620004d1565b8154600160a81b90046001600160401b0316600114801590620004a35750805160208201206040516200049890600185019062000a68565b604051809103902014155b15620004d157604051632105803760e11b81526001600160401b038416600482015260240160405180910390fd5b80511580620005075750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b1562000526576040516342bcdf7f60e11b815260040160405180910390fd5b6001820162000536828262000b3b565b506040840151825485516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b0319909116171782556200058560066001600160401b038516620005dd565b50826001600160401b03167f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b83604051620005c1919062000c07565b60405180910390a25050505080600101905062000347565b5050565b6000620005eb8383620005f4565b90505b92915050565b60008181526001830160205260408120546200063d57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620005ee565b506000620005ee565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b038111828210171562000681576200068162000646565b60405290565b60405160a081016001600160401b038111828210171562000681576200068162000646565b604051601f8201601f191681016001600160401b0381118282101715620006d757620006d762000646565b604052919050565b80516001600160401b0381168114620006f757600080fd5b919050565b6001600160a01b03811681146200071257600080fd5b50565b80518015158114620006f757600080fd5b6000608082840312156200073957600080fd5b620007436200065c565b905081516200075281620006fc565b8152602082015163ffffffff811681146200076c57600080fd5b60208201526200077f6040830162000715565b604082015260608201516200079481620006fc565b606082015292915050565b6000601f83601f840112620007b357600080fd5b825160206001600160401b0380831115620007d257620007d262000646565b8260051b620007e3838201620006ac565b9384528681018301938381019089861115620007fe57600080fd5b84890192505b8583101562000929578251848111156200081e5760008081fd5b89016080601f19828d038101821315620008385760008081fd5b620008426200065c565b888401516200085181620006fc565b8152604062000862858201620006df565b8a83015260606200087581870162000715565b838301529385015193898511156200088d5760008081fd5b84860195508f603f870112620008a557600094508485fd5b8a860151945089851115620008be57620008be62000646565b620008cf8b858f88011601620006ac565b93508484528f82868801011115620008e75760008081fd5b60005b8581101562000907578681018301518582018d01528b01620008ea565b5060009484018b01949094525091820152835250918401919084019062000804565b9998505050505050505050565b60008060008385036101408112156200094e57600080fd5b60a08112156200095d57600080fd5b506200096862000687565b6200097385620006df565b8152602085015161ffff811681146200098b57600080fd5b60208201526040850151620009a081620006fc565b60408201526060850151620009b581620006fc565b60608201526080850151620009ca81620006fc565b60808201529250620009e08560a0860162000726565b6101208501519092506001600160401b03811115620009fe57600080fd5b62000a0c868287016200079f565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168062000a4157607f821691505b60208210810362000a6257634e487b7160e01b600052602260045260246000fd5b50919050565b600080835462000a788162000a2c565b6001828116801562000a93576001811462000aa95762000ada565b60ff198416875282151583028701945062000ada565b8760005260208060002060005b8581101562000ad15781548a82015290840190820162000ab6565b50505082870194505b50929695505050505050565b601f82111562000b36576000816000526020600020601f850160051c8101602086101562000b115750805b601f850160051c820191505b8181101562000b325782815560010162000b1d565b5050505b505050565b81516001600160401b0381111562000b575762000b5762000646565b62000b6f8162000b68845462000a2c565b8462000ae6565b602080601f83116001811462000ba7576000841562000b8e5750858301515b600019600386901b1c1916600185901b17855562000b32565b600085815260208120601f198616915b8281101562000bd85788860151825594840194600190910190840162000bb7565b508582101562000bf75787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000c5c8162000a2c565b8060a089015260c0600183166000811462000c80576001811462000c9d5762000ccf565b60ff19841660c08b015260c083151560051b8b0101945062000ccf565b85600052602060002060005b8481101562000cc65781548c820185015290880190890162000ca9565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e0516101005161012051615f8b62000d7b600039600081816101b001528181610ce801528181612ed1015261380b0152600081816102380152612aa10152600081816102090152612d490152600081816101da01528181610fcc0152818161117c01526124a10152600081816101810152818161264c015261270301526000818161195b015261198e0152615f8b6000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c80637edf52f4116100ad578063de5e0b9a11610071578063de5e0b9a146104eb578063e9d68a8e146104fe578063f2fde38b1461051e578063f58e03fc14610531578063f716f99f1461054457600080fd5b80637edf52f41461044b57806385572ffb1461045e5780638da5cb5b1461046c578063c673e58414610487578063ccd37ba3146104a757600080fd5b80635e36480c116100f45780635e36480c146103405780635e7bb0081461036057806360987c20146103735780637437ff9f1461038657806379ba50971461044357600080fd5b806304666f9c1461013157806306285c6914610146578063181f5a77146102c65780633f4b04aa1461030f5780635215505b1461032a575b600080fd5b61014461013f366004613eaf565b610557565b005b6102686040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526040518060a001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160401b031681526020017f000000000000000000000000000000000000000000000000000000000000000061ffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040805182516001600160401b0316815260208084015161ffff1690820152828201516001600160a01b03908116928201929092526060808401518316908201526080928301519091169181019190915260a0015b60405180910390f35b6103026040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102bd919061401d565b600b546040516001600160401b0390911681526020016102bd565b61033261056b565b6040516102bd929190614077565b61035361034e366004614118565b6107c6565b6040516102bd9190614175565b61014461036e3660046146de565b61081b565b61014461038136600461496d565b610aaf565b6103fc60408051608081018252600080825260208201819052918101829052606081019190915250604080516080810182526004546001600160a01b038082168352600160a01b820463ffffffff166020840152600160c01b90910460ff16151592820192909252600554909116606082015290565b6040516102bd919081516001600160a01b03908116825260208084015163ffffffff1690830152604080840151151590830152606092830151169181019190915260800190565b610144610d8a565b610144610459366004614a01565b610e0d565b61014461012c366004614a66565b6001546040516001600160a01b0390911681526020016102bd565b61049a610495366004614ab1565b610e1e565b6040516102bd9190614b11565b6104dd6104b5366004614b86565b6001600160401b03919091166000908152600a60209081526040808320938352929052205490565b6040519081526020016102bd565b6101446104f9366004614c02565b610f7c565b61051161050c366004614cb4565b61147f565b6040516102bd9190614ccf565b61014461052c366004614ce2565b61158b565b61014461053f366004614cff565b61159c565b610144610552366004614dba565b611605565b61055f611647565b61056881611674565b50565b606080600061057a60066118fd565b6001600160401b0381111561059157610591613ccf565b6040519080825280602002602001820160405280156105e257816020015b60408051608081018252600080825260208083018290529282015260608082015282526000199092019101816105af5790505b50905060006105f160066118fd565b6001600160401b0381111561060857610608613ccf565b604051908082528060200260200182016040528015610631578160200160208202803683370190505b50905060005b61064160066118fd565b8110156107bd57610653600682611907565b82828151811061066557610665614ef7565b60200260200101906001600160401b031690816001600160401b0316815250506008600083838151811061069b5761069b614ef7565b6020908102919091018101516001600160401b039081168352828201939093526040918201600020825160808101845281546001600160a01b038116825260ff600160a01b820416151593820193909352600160a81b9092049093169181019190915260018201805491929160608401919061071690614f0d565b80601f016020809104026020016040519081016040528092919081815260200182805461074290614f0d565b801561078f5780601f106107645761010080835404028352916020019161078f565b820191906000526020600020905b81548152906001019060200180831161077257829003601f168201915b5050505050815250508382815181106107aa576107aa614ef7565b6020908102919091010152600101610637565b50939092509050565b60006107d460016004614f5d565b60026107e1608085614f86565b6001600160401b03166107f49190614fac565b6107fe8585611913565b901c1660038111156108125761081261414b565b90505b92915050565b610823611958565b815181518114610846576040516320f8fd5960e21b815260040160405180910390fd5b60005b81811015610a9f57600084828151811061086557610865614ef7565b6020026020010151905060008160200151519050600085848151811061088d5761088d614ef7565b60200260200101519050805182146108b8576040516320f8fd5960e21b815260040160405180910390fd5b60005b82811015610a905760008282815181106108d7576108d7614ef7565b60200260200101516000015190506000856020015183815181106108fd576108fd614ef7565b6020026020010151905081600014610956578060800151821015610956578551815151604051633a98d46360e11b81526001600160401b0390921660048301526024820152604481018390526064015b60405180910390fd5b83838151811061096857610968614ef7565b602002602001015160200151518160a0015151146109b557805180516060909101516040516370a193fd60e01b815260048101929092526001600160401b0316602482015260440161094d565b60005b8160a0015151811015610a825760008585815181106109d9576109d9614ef7565b60200260200101516020015182815181106109f6576109f6614ef7565b602002602001015163ffffffff16905080600014610a795760008360a001518381518110610a2657610a26614ef7565b60200260200101516040015163ffffffff16905080821015610a77578351516040516348e617b360e01b8152600481019190915260248101849052604481018290526064810183905260840161094d565b505b506001016109b8565b5050508060010190506108bb565b50505050806001019050610849565b50610aaa83836119c0565b505050565b333014610acf576040516306e34e6560e31b815260040160405180910390fd5b6040805160008082526020820190925281610b0c565b6040805180820190915260008082526020820152815260200190600190039081610ae55790505b5060a08701515190915015610b4257610b3f8660a001518760200151886060015189600001516020015189898989611a83565b90505b6040805160a081018252875151815287516020908101516001600160401b03168183015288015181830152908701516060820152608081018290526005546001600160a01b03168015610c35576040516308d450a160e01b81526001600160a01b038216906308d450a190610bbb908590600401615070565b600060405180830381600087803b158015610bd557600080fd5b505af1925050508015610be6575060015b610c35573d808015610c14576040519150601f19603f3d011682016040523d82523d6000602084013e610c19565b606091505b50806040516309c2532560e01b815260040161094d919061401d565b604088015151158015610c4a57506080880151155b80610c61575060608801516001600160a01b03163b155b80610c8857506060880151610c86906001600160a01b03166385572ffb60e01b611c34565b155b15610c9557505050610d83565b87516020908101516001600160401b03166000908152600890915260408082205460808b015160608c01519251633cf9798360e01b815284936001600160a01b0390931692633cf9798392610d119289927f00000000000000000000000000000000000000000000000000000000000000009291600401615083565b6000604051808303816000875af1158015610d30573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d5891908101906150bf565b509150915081610d7d57806040516302a35ba360e21b815260040161094d919061401d565b50505050505b5050505050565b6000546001600160a01b03163314610db55760405163015aa1e360e11b815260040160405180910390fd5b600180546001600160a01b0319808216339081179093556000805490911681556040516001600160a01b03909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610e15611647565b61056881611c50565b610e616040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c082015294855291820180548451818402810184019095528085529293858301939092830182828015610f0a57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610eec575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020018280548015610f6c57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610f4e575b5050505050815250509050919050565b6000610f8a8789018961536c565b6004805491925090600160c01b900460ff1661103457602082015151156110345760208201516040808401519051633854844f60e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016926370a9089e926110039230929190600401615594565b60006040518083038186803b15801561101b57600080fd5b505afa15801561102f573d6000803e3d6000fd5b505050505b8151515115158061104a57508151602001515115155b1561111557600b5460208b0135906001600160401b03808316911610156110ed57600b805467ffffffffffffffff19166001600160401b03831617905581548351604051633937306f60e01b81526001600160a01b0390921691633937306f916110b6916004016156a7565b600060405180830381600087803b1580156110d057600080fd5b505af11580156110e4573d6000803e3d6000fd5b50505050611113565b82602001515160000361111357604051632261116760e01b815260040160405180910390fd5b505b60005b8260200151518110156113cb5760008360200151828151811061113d5761113d614ef7565b60209081029190910101518051604051632cbc26bb60e01b815267ffffffffffffffff60801b608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa1580156111c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e791906156ba565b1561121057604051637edeb53960e11b81526001600160401b038216600482015260240161094d565b600061121b82611d55565b90508060010160405161122e91906156d7565b60405180910390208360200151805190602001201461126b5782602001518160010160405163b80d8fa960e01b815260040161094d9291906157ca565b60408301518154600160a81b90046001600160401b0390811691161415806112ac575082606001516001600160401b031683604001516001600160401b0316115b156112f157825160408085015160608601519151636af0786b60e11b81526001600160401b03938416600482015290831660248201529116604482015260640161094d565b6080830151806113145760405163504570e360e01b815260040160405180910390fd5b83516001600160401b03166000908152600a602090815260408083208484529091529020541561136c5783516040516332cf0cbf60e01b81526001600160401b0390911660048201526024810182905260440161094d565b606084015161137c9060016157ef565b825467ffffffffffffffff60a81b1916600160a81b6001600160401b0392831602179092559251166000908152600a602090815260408083209483529390529190912042905550600101611118565b50602082015182516040517f35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e492611403929091615816565b60405180910390a1610d7d60008b8b8b8b8b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808f0282810182019093528e82529093508e92508d9182918501908490808284376000920191909152508c9250611da1915050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b03878116845260088352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b90920490921694830194909452600184018054939492939184019161150b90614f0d565b80601f016020809104026020016040519081016040528092919081815260200182805461153790614f0d565b8015610f6c5780601f1061155957610100808354040283529160200191610f6c565b820191906000526020600020905b81548152906001019060200180831161156757505050919092525091949350505050565b611593611647565b6105688161209a565b6115dc6115ab8284018461583b565b60408051600080825260208201909252906115d6565b60608152602001906001900390816115c15790505b506119c0565b6040805160008082526020820190925290506115ff600185858585866000611da1565b50505050565b61160d611647565b60005b81518110156116435761163b82828151811061162e5761162e614ef7565b6020026020010151612113565b600101611610565b5050565b6001546001600160a01b03163314611672576040516315ae3a6f60e11b815260040160405180910390fd5b565b60005b815181101561164357600082828151811061169457611694614ef7565b60200260200101519050600081602001519050806001600160401b03166000036116d15760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166116f9576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b0381166000908152600860205260409020606083015160018201805461172590614f0d565b905060000361178757815467ffffffffffffffff60a81b1916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a16117f0565b8154600160a81b90046001600160401b03166001148015906117c75750805160208201206040516117bc9060018501906156d7565b604051809103902014155b156117f057604051632105803760e11b81526001600160401b038416600482015260240161094d565b805115806118255750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b15611843576040516342bcdf7f60e11b815260040160405180910390fd5b6001820161185182826158bf565b506040840151825485516001600160a01b03166001600160a01b0319921515600160a01b029290921674ffffffffffffffffffffffffffffffffffffffffff19909116171782556118ac60066001600160401b03851661243d565b50826001600160401b03167f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b836040516118e6919061597e565b60405180910390a250505050806001019050611677565b6000610815825490565b60006108128383612449565b6001600160401b0382166000908152600960205260408120816119376080856159cc565b6001600160401b031681526020810191909152604001600020549392505050565b467f00000000000000000000000000000000000000000000000000000000000000001461167257604051630f01ce8560e01b81527f0000000000000000000000000000000000000000000000000000000000000000600482015246602482015260440161094d565b81516000036119e25760405163c2e5347d60e01b815260040160405180910390fd5b80516040805160008082526020820190925291159181611a25565b6040805180820190915260008152606060208201528152602001906001900390816119fd5790505b50905060005b8451811015610d8357611a7b858281518110611a4957611a49614ef7565b602002602001015184611a7557858381518110611a6857611a68614ef7565b6020026020010151612473565b83612473565b600101611a2b565b606088516001600160401b03811115611a9e57611a9e613ccf565b604051908082528060200260200182016040528015611ae357816020015b6040805180820190915260008082526020820152815260200190600190039081611abc5790505b509050811560005b8a51811015611c265781611b8357848482818110611b0b57611b0b614ef7565b9050602002016020810190611b2091906159f2565b63ffffffff1615611b8357848482818110611b3d57611b3d614ef7565b9050602002016020810190611b5291906159f2565b8b8281518110611b6457611b64614ef7565b60200260200101516040019063ffffffff16908163ffffffff16815250505b611c018b8281518110611b9857611b98614ef7565b60200260200101518b8b8b8b8b87818110611bb557611bb5614ef7565b9050602002810190611bc79190615a0d565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612d0e92505050565b838281518110611c1357611c13614ef7565b6020908102919091010152600101611aeb565b505098975050505050505050565b6000611c3f8361300e565b801561081257506108128383613041565b80516001600160a01b0316611c78576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516001600160a01b039889167fffffffffffffffff0000000000000000000000000000000000000000000000009097168717600160a01b63ffffffff958616021760ff60c01b1916600160c01b911515919091021790965560608089018051600580546001600160a01b031916918b169190911790558251968752935190921693850193909352935115159183019190915251909216908201527fcbb53bda7106a610de67df506ac86b65c44d5afac0fd2b11070dc2d61a6f2dee9060800160405180910390a150565b6001600160401b03811660009081526008602052604081208054600160a01b900460ff166108155760405163ed053c5960e01b81526001600160401b038416600482015260240161094d565b60ff87811660009081526002602090815260408083208151608081018352815481526001909101548086169382019390935261010083048516918101919091526201000090910490921615156060830152873590611e00876084615a53565b9050826060015115611e48578451611e19906020614fac565b8651611e26906020614fac565b611e319060a0615a53565b611e3b9190615a53565b611e459082615a53565b90505b368114611e7157604051638e1192e160e01b81526004810182905236602482015260440161094d565b5081518114611ea05781516040516324f7d61360e21b815260048101919091526024810182905260440161094d565b611ea8611958565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611ef657611ef661414b565b6002811115611f0757611f0761414b565b9052509050600281602001516002811115611f2457611f2461414b565b148015611f785750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611f6057611f60614ef7565b6000918252602090912001546001600160a01b031633145b611f9557604051631b41e11d60e31b815260040160405180910390fd5b50816060015115612045576020820151611fb0906001615a66565b60ff16855114611fd3576040516371253a2560e01b815260040160405180910390fd5b8351855114611ff55760405163a75d88af60e01b815260040160405180910390fd5b60008787604051612007929190615a7f565b60405190819003812061201e918b90602001615a8f565b6040516020818303038152906040528051906020012090506120438a828888886130cb565b505b6040805182815260208a8101356001600160401b03169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b336001600160a01b038216036120c357604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff1660000361213e576000604051631b3fab5160e11b815260040161094d9190615aa3565b60208082015160ff8082166000908152600290935260408320600181015492939092839216900361218f576060840151600182018054911515620100000262ff0000199092169190911790556121cb565b6060840151600182015460ff62010000909104161515901515146121cb576040516321fd80df60e21b815260ff8416600482015260240161094d565b60a0840151805161010010156121f7576001604051631b3fab5160e11b815260040161094d9190615aa3565b805160000361221c576005604051631b3fab5160e11b815260040161094d9190615aa3565b612282848460030180548060200260200160405190810160405280929190818152602001828054801561227857602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161225a575b505050505061327e565b8460600151156123b2576122f08484600201805480602002602001604051908101604052809291908181526020018280548015612278576020028201919060005260206000209081546001600160a01b0316815260019091019060200180831161225a57505050505061327e565b60808501518051610100101561231c576002604051631b3fab5160e11b815260040161094d9190615aa3565b604086015161232c906003615abd565b60ff16815111612352576003604051631b3fab5160e11b815260040161094d9190615aa3565b815181511015612378576001604051631b3fab5160e11b815260040161094d9190615aa3565b805160018401805461ff00191661010060ff8416021790556123a39060028601906020840190613c55565b506123b0858260016132e7565b505b6123be848260026132e7565b80516123d39060038501906020840190613c55565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f5479361242c9389939260028a01929190615ad9565b60405180910390a1610d8384613442565b600061081283836134c5565b600082600001828154811061246057612460614ef7565b9060005260206000200154905092915050565b81518151604051632cbc26bb60e01b8152608083901b67ffffffffffffffff60801b166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa1580156124f0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061251491906156ba565b1561258557801561254357604051637edeb53960e11b81526001600160401b038316600482015260240161094d565b6040516001600160401b03831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b60208401515160008190036125bb57845160405163676cf24b60e11b81526001600160401b03909116600482015260240161094d565b84604001515181146125e0576040516357e0e08360e01b815260040160405180910390fd5b6000816001600160401b038111156125fa576125fa613ccf565b604051908082528060200260200182016040528015612623578160200160208202803683370190505b50905060007f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f857f000000000000000000000000000000000000000000000000000000000000000061267488611d55565b60010160405161268491906156d7565b6040519081900381206126bc949392916020019384526001600160401b03928316602085015291166040830152606082015260800190565b60405160208183030381529060405280519060200120905060005b838110156127f2576000886020015182815181106126f7576126f7614ef7565b602002602001015190507f00000000000000000000000000000000000000000000000000000000000000006001600160401b03168160000151604001516001600160401b03161461276e5780516040908101519051631c21951160e11b81526001600160401b03909116600482015260240161094d565b866001600160401b03168160000151602001516001600160401b0316146127c257805160200151604051636c95f1eb60e01b81526001600160401b03808a166004830152909116602482015260440161094d565b6127cc8184613514565b8483815181106127de576127de614ef7565b6020908102919091010152506001016126d7565b5050600061280a858389606001518a6080015161361c565b90508060000361283857604051633ee8bd3f60e11b81526001600160401b038616600482015260240161094d565b60005b83811015612d045760005a905060008960200151838151811061286057612860614ef7565b60200260200101519050600061287e898360000151606001516107c6565b905060008160038111156128945761289461414b565b14806128b1575060038160038111156128af576128af61414b565b145b61290757815160600151604080516001600160401b03808d16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a1505050612cfc565b606088156129e6578a858151811061292157612921614ef7565b6020908102919091018101510151600454909150600090600160a01b900463ffffffff1661294f8842614f5d565b119050808061296f5750600383600381111561296d5761296d61414b565b145b612997576040516354e7e43160e11b81526001600160401b038c16600482015260240161094d565b8b86815181106129a9576129a9614ef7565b6020026020010151600001516000146129e0578b86815181106129ce576129ce614ef7565b60209081029190910101515160808501525b50612a52565b60008260038111156129fa576129fa61414b565b14612a5257825160600151604080516001600160401b03808e16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe65120910160405180910390a150505050612cfc565b8251608001516001600160401b031615612b28576000826003811115612a7a57612a7a61414b565b03612b285782516080015160208401516040516370701e5760e11b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612ad8928f929190600401615b8b565b6020604051808303816000875af1158015612af7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b1b91906156ba565b612b285750505050612cfc565b60008c604001518681518110612b4057612b40614ef7565b6020026020010151905080518460a001515114612b8a57835160600151604051631cfe6d8b60e01b81526001600160401b03808e166004830152909116602482015260440161094d565b612b9e8b8560000151606001516001613659565b600080612bac8684866136fe565b91509150612bc38d87600001516060015184613659565b8b15612c1a576003826003811115612bdd57612bdd61414b565b03612c1a576000856003811115612bf657612bf661414b565b14612c1a57855151604051632b11b8d960e01b815261094d91908390600401615bb7565b6002826003811115612c2e57612c2e61414b565b14612c6f576003826003811115612c4757612c4761414b565b14612c6f578551606001516040516349362d1f60e11b815261094d918f918590600401615bd0565b8560000151600001518660000151606001516001600160401b03168e6001600160401b03167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8d8c81518110612cc757612cc7614ef7565b602002602001015186865a612cdc908f614f5d565b604051612cec9493929190615bf5565b60405180910390a4505050505050505b60010161283b565b5050505050505050565b6040805180820190915260008082526020820152602086015160405163bbe4f6db60e01b81526001600160a01b0380831660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015612d92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612db69190615c2c565b90506001600160a01b0381161580612de55750612de36001600160a01b03821663aff2afbf60e01b611c34565b155b15612e0e5760405163ae9b4ce960e01b81526001600160a01b038216600482015260240161094d565b600080612e2688858c6040015163ffffffff166137b2565b915091506000806000612ef76040518061010001604052808e81526020018c6001600160401b031681526020018d6001600160a01b031681526020018f608001518152602001896001600160a01b031681526020018f6000015181526020018f6060015181526020018b815250604051602401612ea39190615c49565b60408051601f198184030181529190526020810180516001600160e01b0316633907753760e01b17905287867f000000000000000000000000000000000000000000000000000000000000000060846138b5565b92509250925082612f1f578582604051634ff17cad60e11b815260040161094d929190615d15565b8151602014612f4e578151604051631e3be00960e21b815260206004820152602481019190915260440161094d565b600082806020019051810190612f649190615d37565b9050866001600160a01b03168c6001600160a01b031614612fe0576000612f958d8a612f90868a614f5d565b6137b2565b50905086811080612faf575081612fac8883614f5d565b14155b15612fde5760405163a966e21f60e01b815260048101839052602481018890526044810182905260640161094d565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b6000613021826301ffc9a760e01b613041565b8015610815575061303a826001600160e01b0319613041565b1592915050565b6040516001600160e01b031982166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b178152825192935060009283928392909183918a617530fa92503d915060005190508280156130b4575060208210155b80156130c05750600081115b979650505050505050565b8251600090815b81811015612d045760006001888684602081106130f1576130f1614ef7565b6130fe91901a601b615a66565b89858151811061311057613110614ef7565b602002602001015189868151811061312a5761312a614ef7565b602002602001015160405160008152602001604052604051613168949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa15801561318a573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b038516835281528582208587019096528554808416865293975090955092939284019161010090041660028111156131eb576131eb61414b565b60028111156131fc576131fc61414b565b90525090506001816020015160028111156132195761321961414b565b1461323757604051636518c33d60e11b815260040160405180910390fd5b8051600160ff9091161b85161561326157604051633d9ef1f160e21b815260040160405180910390fd5b806000015160ff166001901b8517945050508060010190506130d2565b60005b8151811015610aaa5760ff8316600090815260036020526040812083519091908490849081106132b3576132b3614ef7565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff19169055600101613281565b60005b82518110156115ff57600083828151811061330757613307614ef7565b60200260200101519050600060028111156133245761332461414b565b60ff80871660009081526003602090815260408083206001600160a01b038716845290915290205461010090041660028111156133635761336361414b565b14613384576004604051631b3fab5160e11b815260040161094d9190615aa3565b6001600160a01b0381166133ab5760405163d6c62c9b60e01b815260040160405180910390fd5b60405180604001604052808360ff1681526020018460028111156133d1576133d161414b565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff19161761010083600281111561342e5761342e61414b565b0217905550905050508060010190506132ea565b60ff8181166000818152600260205260409020600101546201000090049091169061349a5780613485576040516317bd8dd160e11b815260040160405180910390fd5b600b805467ffffffffffffffff191690555050565b60001960ff831601611643578015611643576040516307b8c74d60e51b815260040160405180910390fd5b600081815260018301602052604081205461350c57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610815565b506000610815565b81518051606080850151908301516080808701519401516040516000958695889561357895919490939192916020019485526001600160a01b039390931660208501526001600160401b039182166040850152606084015216608082015260a00190565b604051602081830303815290604052805190602001208560200151805190602001208660400151805190602001208760a001516040516020016135bb9190615df1565b60408051601f198184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e0015b60405160208183030381529060405280519060200120905092915050565b60008061362a85858561398f565b6001600160401b0387166000908152600a6020908152604080832093835292905220549150505b949350505050565b60006002613668608085614f86565b6001600160401b031661367b9190614fac565b905060006136898585611913565b90508161369860016004614f5d565b901b1916818360038111156136af576136af61414b565b6001600160401b03871660009081526009602052604081209190921b929092179182916136dd6080886159cc565b6001600160401b031681526020810191909152604001600020555050505050565b604051630304c3e160e51b815260009060609030906360987c209061372b90889088908890600401615e88565b600060405180830381600087803b15801561374557600080fd5b505af1925050508015613756575060015b613795573d808015613784576040519150601f19603f3d011682016040523d82523d6000602084013e613789565b606091505b506003925090506137aa565b50506040805160208101909152600081526002905b935093915050565b6000806000806000613831886040516024016137dd91906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166370a0823160e01b17905288887f000000000000000000000000000000000000000000000000000000000000000060846138b5565b92509250925082613859578682604051634ff17cad60e11b815260040161094d929190615d15565b6020825114613888578151604051631e3be00960e21b815260206004820152602481019190915260440161094d565b8180602001905181019061389c9190615d37565b6138a68288614f5d565b94509450505050935093915050565b6000606060008361ffff166001600160401b038111156138d7576138d7613ccf565b6040519080825280601f01601f191660200182016040528015613901576020820181803683370190505b509150863b61391b5763030ed58f60e21b60005260046000fd5b5a8581101561393557632be8ca8b60e21b60005260046000fd5b8590036040810481038710613955576337c3be2960e01b60005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d848111156139785750835b808352806000602085013e50955095509592505050565b82518251600091908183036139b757604051630469ac9960e21b815260040160405180910390fd5b61010182118015906139cb57506101018111155b6139e8576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613a12576040516309bde33960e01b815260040160405180910390fd5b80600003613a3f5786600081518110613a2d57613a2d614ef7565b60200260200101519350505050613c0d565b6000816001600160401b03811115613a5957613a59613ccf565b604051908082528060200260200182016040528015613a82578160200160208202803683370190505b50905060008080805b85811015613bac5760006001821b8b811603613ae65788851015613acf578c5160018601958e918110613ac057613ac0614ef7565b60200260200101519050613b08565b8551600185019487918110613ac057613ac0614ef7565b8b5160018401938d918110613afd57613afd614ef7565b602002602001015190505b600089861015613b38578d5160018701968f918110613b2957613b29614ef7565b60200260200101519050613b5a565b8651600186019588918110613b4f57613b4f614ef7565b602002602001015190505b82851115613b7b576040516309bde33960e01b815260040160405180910390fd5b613b858282613c14565b878481518110613b9757613b97614ef7565b60209081029190910101525050600101613a8b565b506001850382148015613bbe57508683145b8015613bc957508581145b613be6576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613bfb57613bfb614ef7565b60200260200101519750505050505050505b9392505050565b6000818310613c2c57613c278284613c32565b610812565b61081283835b6040805160016020820152908101839052606081018290526000906080016135fe565b828054828255906000526020600020908101928215613caa579160200282015b82811115613caa57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190613c75565b50613cb6929150613cba565b5090565b5b80821115613cb65760008155600101613cbb565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715613d0757613d07613ccf565b60405290565b60405160a081016001600160401b0381118282101715613d0757613d07613ccf565b60405160c081016001600160401b0381118282101715613d0757613d07613ccf565b604080519081016001600160401b0381118282101715613d0757613d07613ccf565b604051606081016001600160401b0381118282101715613d0757613d07613ccf565b604051601f8201601f191681016001600160401b0381118282101715613dbd57613dbd613ccf565b604052919050565b60006001600160401b03821115613dde57613dde613ccf565b5060051b60200190565b6001600160a01b038116811461056857600080fd5b80356001600160401b0381168114613e1457600080fd5b919050565b801515811461056857600080fd5b8035613e1481613e19565b60006001600160401b03821115613e4b57613e4b613ccf565b50601f01601f191660200190565b600082601f830112613e6a57600080fd5b8135613e7d613e7882613e32565b613d95565b818152846020838601011115613e9257600080fd5b816020850160208301376000918101602001919091529392505050565b60006020808385031215613ec257600080fd5b82356001600160401b0380821115613ed957600080fd5b818501915085601f830112613eed57600080fd5b8135613efb613e7882613dc5565b81815260059190911b83018401908481019088831115613f1a57600080fd5b8585015b83811015613fc057803585811115613f365760008081fd5b86016080818c03601f1901811315613f4e5760008081fd5b613f56613ce5565b89830135613f6381613de8565b81526040613f72848201613dfd565b8b830152606080850135613f8581613e19565b83830152928401359289841115613f9e57600091508182fd5b613fac8f8d86880101613e59565b908301525085525050918601918601613f1e565b5098975050505050505050565b60005b83811015613fe8578181015183820152602001613fd0565b50506000910152565b60008151808452614009816020860160208601613fcd565b601f01601f19169290920160200192915050565b6020815260006108126020830184613ff1565b6001600160a01b0381511682526020810151151560208301526001600160401b03604082015116604083015260006060820151608060608501526136516080850182613ff1565b604080825283519082018190526000906020906060840190828701845b828110156140b95781516001600160401b031684529284019290840190600101614094565b50505083810382850152845180825282820190600581901b8301840187850160005b8381101561410957601f198684030185526140f7838351614030565b948701949250908601906001016140db565b50909998505050505050505050565b6000806040838503121561412b57600080fd5b61413483613dfd565b915061414260208401613dfd565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b600481106141715761417161414b565b9052565b602081016108158284614161565b600060a0828403121561419557600080fd5b61419d613d0d565b9050813581526141af60208301613dfd565b60208201526141c060408301613dfd565b60408201526141d160608301613dfd565b60608201526141e260808301613dfd565b608082015292915050565b8035613e1481613de8565b803563ffffffff81168114613e1457600080fd5b600082601f83011261421d57600080fd5b8135602061422d613e7883613dc5565b82815260059290921b8401810191818101908684111561424c57600080fd5b8286015b8481101561431c5780356001600160401b03808211156142705760008081fd5b9088019060a0828b03601f190181131561428a5760008081fd5b614292613d0d565b87840135838111156142a45760008081fd5b6142b28d8a83880101613e59565b8252506040808501356142c481613de8565b828a015260606142d58682016141f8565b828401526080915081860135858111156142ef5760008081fd5b6142fd8f8c838a0101613e59565b9184019190915250919093013590830152508352918301918301614250565b509695505050505050565b6000610140828403121561433a57600080fd5b614342613d2f565b905061434e8383614183565b815260a08201356001600160401b038082111561436a57600080fd5b61437685838601613e59565b602084015260c084013591508082111561438f57600080fd5b61439b85838601613e59565b60408401526143ac60e085016141ed565b606084015261010084013560808401526101208401359150808211156143d157600080fd5b506143de8482850161420c565b60a08301525092915050565b600082601f8301126143fb57600080fd5b8135602061440b613e7883613dc5565b82815260059290921b8401810191818101908684111561442a57600080fd5b8286015b8481101561431c5780356001600160401b0381111561444d5760008081fd5b61445b8986838b0101614327565b84525091830191830161442e565b600082601f83011261447a57600080fd5b8135602061448a613e7883613dc5565b82815260059290921b840181019181810190868411156144a957600080fd5b8286015b8481101561431c5780356001600160401b03808211156144cc57600080fd5b818901915089603f8301126144e057600080fd5b858201356144f0613e7882613dc5565b81815260059190911b830160400190878101908c83111561451057600080fd5b604085015b838110156145495780358581111561452c57600080fd5b61453b8f6040838a0101613e59565b845250918901918901614515565b508752505050928401925083016144ad565b600082601f83011261456c57600080fd5b8135602061457c613e7883613dc5565b8083825260208201915060208460051b87010193508684111561459e57600080fd5b602086015b8481101561431c57803583529183019183016145a3565b600082601f8301126145cb57600080fd5b813560206145db613e7883613dc5565b82815260059290921b840181019181810190868411156145fa57600080fd5b8286015b8481101561431c5780356001600160401b038082111561461e5760008081fd5b9088019060a0828b03601f19018113156146385760008081fd5b614640613d0d565b61464b888501613dfd565b8152604080850135848111156146615760008081fd5b61466f8e8b838901016143ea565b8a84015250606080860135858111156146885760008081fd5b6146968f8c838a0101614469565b83850152506080915081860135858111156146b15760008081fd5b6146bf8f8c838a010161455b565b91840191909152509190930135908301525083529183019183016145fe565b600080604083850312156146f157600080fd5b6001600160401b038335111561470657600080fd5b61471384843585016145ba565b91506001600160401b036020840135111561472d57600080fd5b6020830135830184601f82011261474357600080fd5b614750613e788235613dc5565b81358082526020808301929160051b84010187101561476e57600080fd5b602083015b6020843560051b850101811015614914576001600160401b038135111561479957600080fd5b87603f8235860101126147ab57600080fd5b6147be613e786020833587010135613dc5565b81358501602081810135808452908301929160059190911b016040018a10156147e657600080fd5b604083358701015b83358701602081013560051b01604001811015614904576001600160401b038135111561481a57600080fd5b833587018135016040818d03603f1901121561483557600080fd5b61483d613d51565b604082013581526001600160401b036060830135111561485c57600080fd5b8c605f60608401358401011261487157600080fd5b6040606083013583010135614888613e7882613dc5565b808282526020820191508f60608460051b60608801358801010111156148ad57600080fd5b6060808601358601015b60608460051b6060880135880101018110156148e4576148d6816141f8565b8352602092830192016148b7565b5080602085015250505080855250506020830192506020810190506147ee565b5084525060209283019201614773565b508093505050509250929050565b60008083601f84011261493457600080fd5b5081356001600160401b0381111561494b57600080fd5b6020830191508360208260051b850101111561496657600080fd5b9250929050565b60008060008060006060868803121561498557600080fd5b85356001600160401b038082111561499c57600080fd5b6149a889838a01614327565b965060208801359150808211156149be57600080fd5b6149ca89838a01614922565b909650945060408801359150808211156149e357600080fd5b506149f088828901614922565b969995985093965092949392505050565b600060808284031215614a1357600080fd5b614a1b613ce5565b8235614a2681613de8565b8152614a34602084016141f8565b60208201526040830135614a4781613e19565b60408201526060830135614a5a81613de8565b60608201529392505050565b600060208284031215614a7857600080fd5b81356001600160401b03811115614a8e57600080fd5b820160a08185031215613c0d57600080fd5b803560ff81168114613e1457600080fd5b600060208284031215614ac357600080fd5b61081282614aa0565b60008151808452602080850194506020840160005b83811015614b065781516001600160a01b031687529582019590820190600101614ae1565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614b6060e0840182614acc565b90506040840151601f198483030160c0850152614b7d8282614acc565b95945050505050565b60008060408385031215614b9957600080fd5b614ba283613dfd565b946020939093013593505050565b806040810183101561081557600080fd5b60008083601f840112614bd357600080fd5b5081356001600160401b03811115614bea57600080fd5b60208301915083602082850101111561496657600080fd5b60008060008060008060008060c0898b031215614c1e57600080fd5b614c288a8a614bb0565b975060408901356001600160401b0380821115614c4457600080fd5b614c508c838d01614bc1565b909950975060608b0135915080821115614c6957600080fd5b614c758c838d01614922565b909750955060808b0135915080821115614c8e57600080fd5b50614c9b8b828c01614922565b999c989b50969995989497949560a00135949350505050565b600060208284031215614cc657600080fd5b61081282613dfd565b6020815260006108126020830184614030565b600060208284031215614cf457600080fd5b8135613c0d81613de8565b600080600060608486031215614d1457600080fd5b614d1e8585614bb0565b925060408401356001600160401b03811115614d3957600080fd5b614d4586828701614bc1565b9497909650939450505050565b600082601f830112614d6357600080fd5b81356020614d73613e7883613dc5565b8083825260208201915060208460051b870101935086841115614d9557600080fd5b602086015b8481101561431c578035614dad81613de8565b8352918301918301614d9a565b60006020808385031215614dcd57600080fd5b82356001600160401b0380821115614de457600080fd5b818501915085601f830112614df857600080fd5b8135614e06613e7882613dc5565b81815260059190911b83018401908481019088831115614e2557600080fd5b8585015b83811015613fc057803585811115614e4057600080fd5b860160c0818c03601f19011215614e575760008081fd5b614e5f613d2f565b8882013581526040614e72818401614aa0565b8a8301526060614e83818501614aa0565b8284015260809150614e96828501613e27565b9083015260a08381013589811115614eae5760008081fd5b614ebc8f8d83880101614d52565b838501525060c0840135915088821115614ed65760008081fd5b614ee48e8c84870101614d52565b9083015250845250918601918601614e29565b634e487b7160e01b600052603260045260246000fd5b600181811c90821680614f2157607f821691505b602082108103614f4157634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561081557610815614f47565b634e487b7160e01b600052601260045260246000fd5b60006001600160401b0380841680614fa057614fa0614f70565b92169190910692915050565b808202811582820484141761081557610815614f47565b80518252600060206001600160401b0381840151168185015260408084015160a06040870152614ff660a0870182613ff1565b90506060850151868203606088015261500f8282613ff1565b608087810151898303918a01919091528051808352908601935060009250908501905b8083101561506457835180516001600160a01b0316835286015186830152928501926001929092019190840190615032565b50979650505050505050565b6020815260006108126020830184614fc3565b6080815260006150966080830187614fc3565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b6000806000606084860312156150d457600080fd5b83516150df81613e19565b60208501519093506001600160401b038111156150fb57600080fd5b8401601f8101861361510c57600080fd5b805161511a613e7882613e32565b81815287602083850101111561512f57600080fd5b615140826020830160208601613fcd565b809450505050604084015190509250925092565b80356001600160e01b0381168114613e1457600080fd5b600082601f83011261517c57600080fd5b8135602061518c613e7883613dc5565b82815260069290921b840181019181810190868411156151ab57600080fd5b8286015b8481101561431c57604081890312156151c85760008081fd5b6151d0613d51565b6151d982613dfd565b81526151e6858301615154565b818601528352918301916040016151af565b600082601f83011261520957600080fd5b81356020615219613e7883613dc5565b82815260059290921b8401810191818101908684111561523857600080fd5b8286015b8481101561431c5780356001600160401b038082111561525c5760008081fd5b9088019060a0828b03601f19018113156152765760008081fd5b61527e613d0d565b615289888501613dfd565b81526040808501358481111561529f5760008081fd5b6152ad8e8b83890101613e59565b8a84015250606093506152c1848601613dfd565b9082015260806152d2858201613dfd565b9382019390935292013590820152835291830191830161523c565b600082601f8301126152fe57600080fd5b8135602061530e613e7883613dc5565b82815260069290921b8401810191818101908684111561532d57600080fd5b8286015b8481101561431c576040818903121561534a5760008081fd5b615352613d51565b813581528482013585820152835291830191604001615331565b6000602080838503121561537f57600080fd5b82356001600160401b038082111561539657600080fd5b90840190606082870312156153aa57600080fd5b6153b2613d73565b8235828111156153c157600080fd5b830160408189038113156153d457600080fd5b6153dc613d51565b8235858111156153eb57600080fd5b8301601f81018b136153fc57600080fd5b803561540a613e7882613dc5565b81815260069190911b8201890190898101908d83111561542957600080fd5b928a01925b828410156154795785848f0312156154465760008081fd5b61544e613d51565b843561545981613de8565b8152615466858d01615154565b818d0152825292850192908a019061542e565b84525050508287013591508482111561549157600080fd5b61549d8a83850161516b565b818801528352505082840135828111156154b657600080fd5b6154c2888286016151f8565b858301525060408301359350818411156154db57600080fd5b6154e7878585016152ed565b60408201529695505050505050565b600082825180855260208086019550808260051b84010181860160005b8481101561558757601f19868403018952815160a06001600160401b0380835116865286830151828888015261554b83880182613ff1565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101615513565b5090979650505050505050565b6001600160a01b0384168152600060206060818401526155b760608401866154f6565b83810360408581019190915285518083528387019284019060005b81811015614109578451805184528601518684015293850193918301916001016155d2565b805160408084528151848201819052600092602091908201906060870190855b8181101561564e57835180516001600160a01b031684528501516001600160e01b0316858401529284019291850191600101615617565b50508583015187820388850152805180835290840192506000918401905b8083101561506457835180516001600160401b031683528501516001600160e01b03168583015292840192600192909201919085019061566c565b60208152600061081260208301846155f7565b6000602082840312156156cc57600080fd5b8151613c0d81613e19565b60008083546156e581614f0d565b600182811680156156fd576001811461571257615741565b60ff1984168752821515830287019450615741565b8760005260208060002060005b858110156157385781548a82015290840190820161571f565b50505082870194505b50929695505050505050565b6000815461575a81614f0d565b8085526020600183811680156157775760018114615791576157bf565b60ff1985168884015283151560051b8801830195506157bf565b866000528260002060005b858110156157b75781548a820186015290830190840161579c565b890184019650505b505050505092915050565b6040815260006157dd6040830185613ff1565b8281036020840152614b7d818561574d565b6001600160401b0381811683821601908082111561580f5761580f614f47565b5092915050565b60408152600061582960408301856154f6565b8281036020840152614b7d81856155f7565b60006020828403121561584d57600080fd5b81356001600160401b0381111561586357600080fd5b613651848285016145ba565b601f821115610aaa576000816000526020600020601f850160051c810160208610156158985750805b601f850160051c820191505b818110156158b7578281556001016158a4565b505050505050565b81516001600160401b038111156158d8576158d8613ccf565b6158ec816158e68454614f0d565b8461586f565b602080601f83116001811461592157600084156159095750858301515b600019600386901b1c1916600185901b1785556158b7565b600085815260208120601f198616915b8281101561595057888601518255948401946001909101908401615931565b508582101561596e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60208152600082546001600160a01b038116602084015260ff8160a01c16151560408401526001600160401b038160a81c1660608401525060808083015261081260a083016001850161574d565b60006001600160401b03808416806159e6576159e6614f70565b92169190910492915050565b600060208284031215615a0457600080fd5b610812826141f8565b6000808335601e19843603018112615a2457600080fd5b8301803591506001600160401b03821115615a3e57600080fd5b60200191503681900382131561496657600080fd5b8082018082111561081557610815614f47565b60ff818116838216019081111561081557610815614f47565b8183823760009101908152919050565b828152604082602083013760600192915050565b6020810160068310615ab757615ab761414b565b91905290565b60ff818116838216029081169081811461580f5761580f614f47565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015615b315784546001600160a01b031683526001948501949284019201615b0c565b50508481036060860152865180825290820192508187019060005b81811015615b715782516001600160a01b031685529383019391830191600101615b4c565b50505060ff851660808501525090505b9695505050505050565b60006001600160401b03808616835280851660208401525060606040830152614b7d6060830184613ff1565b8281526040602082015260006136516040830184613ff1565b6001600160401b03848116825283166020820152606081016136516040830184614161565b848152615c056020820185614161565b608060408201526000615c1b6080830185613ff1565b905082606083015295945050505050565b600060208284031215615c3e57600080fd5b8151613c0d81613de8565b6020815260008251610100806020850152615c68610120850183613ff1565b91506020850151615c8460408601826001600160401b03169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615cbe60a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615cdb8483613ff1565b935060c08701519150808685030160e0870152615cf88483613ff1565b935060e0870151915080868503018387015250615b818382613ff1565b6001600160a01b03831681526040602082015260006136516040830184613ff1565b600060208284031215615d4957600080fd5b5051919050565b600082825180855260208086019550808260051b84010181860160005b8481101561558757601f19868403018952815160a08151818652615d9382870182613ff1565b9150506001600160a01b03868301511686860152604063ffffffff8184015116818701525060608083015186830382880152615dcf8382613ff1565b6080948501519790940196909652505098840198925090830190600101615d6d565b6020815260006108126020830184615d50565b60008282518085526020808601955060208260051b8401016020860160005b8481101561558757601f19868403018952615e3f838351613ff1565b98840198925090830190600101615e23565b60008151808452602080850194506020840160005b83811015614b0657815163ffffffff1687529582019590820190600101615e66565b60608152600084518051606084015260208101516001600160401b0380821660808601528060408401511660a08601528060608401511660c08601528060808401511660e0860152505050602085015161014080610100850152615ef06101a0850183613ff1565b91506040870151605f198086850301610120870152615f0f8483613ff1565b935060608901519150615f2c838701836001600160a01b03169052565b608089015161016087015260a0890151925080868503016101808701525050615f558282615d50565b9150508281036020840152615f6a8186615e04565b90508281036040840152615b818185615e5156fea164736f6c6343000818000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"staticConfig\",\"type\":\"tuple\",\"internalType\":\"structOffRamp.StaticConfig\",\"components\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"gasForCallExactCheck\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"rmnRemote\",\"type\":\"address\",\"internalType\":\"contractIRMNRemote\"},{\"name\":\"tokenAdminRegistry\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"nonceManager\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"name\":\"dynamicConfig\",\"type\":\"tuple\",\"internalType\":\"structOffRamp.DynamicConfig\",\"components\":[{\"name\":\"feeQuoter\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"messageInterceptor\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\",\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"components\":[{\"name\":\"router\",\"type\":\"address\",\"internalType\":\"contractIRouter\"},{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"onRamp\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"acceptOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applySourceChainConfigUpdates\",\"inputs\":[{\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\",\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"components\":[{\"name\":\"router\",\"type\":\"address\",\"internalType\":\"contractIRouter\"},{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"onRamp\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"ccipReceive\",\"inputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structClient.Any2EVMMessage\",\"components\":[{\"name\":\"messageId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sender\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\",\"internalType\":\"structClient.EVMTokenAmount[]\",\"components\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}]}],\"outputs\":[],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"commit\",\"inputs\":[{\"name\":\"reportContext\",\"type\":\"bytes32[2]\",\"internalType\":\"bytes32[2]\"},{\"name\":\"report\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"rs\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"ss\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"rawVs\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"execute\",\"inputs\":[{\"name\":\"reportContext\",\"type\":\"bytes32[2]\",\"internalType\":\"bytes32[2]\"},{\"name\":\"report\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"executeSingleMessage\",\"inputs\":[{\"name\":\"message\",\"type\":\"tuple\",\"internalType\":\"structInternal.Any2EVMRampMessage\",\"components\":[{\"name\":\"header\",\"type\":\"tuple\",\"internalType\":\"structInternal.RampMessageHeader\",\"components\":[{\"name\":\"messageId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sequenceNumber\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"sender\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"receiver\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"gasLimit\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"tokenAmounts\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"components\":[{\"name\":\"sourcePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"destTokenAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"destGasAmount\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"extraData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}]},{\"name\":\"offchainTokenData\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"},{\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\",\"internalType\":\"uint32[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getAllSourceChainConfigs\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"},{\"name\":\"\",\"type\":\"tuple[]\",\"internalType\":\"structOffRamp.SourceChainConfig[]\",\"components\":[{\"name\":\"router\",\"type\":\"address\",\"internalType\":\"contractIRouter\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"minSeqNr\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"onRamp\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getDynamicConfig\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structOffRamp.DynamicConfig\",\"components\":[{\"name\":\"feeQuoter\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"messageInterceptor\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getExecutionState\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sequenceNumber\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"enumInternal.MessageExecutionState\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getLatestPriceSequenceNumber\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getMerkleRoot\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getSourceChainConfig\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structOffRamp.SourceChainConfig\",\"components\":[{\"name\":\"router\",\"type\":\"address\",\"internalType\":\"contractIRouter\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"minSeqNr\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"onRamp\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getStaticConfig\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structOffRamp.StaticConfig\",\"components\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"gasForCallExactCheck\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"rmnRemote\",\"type\":\"address\",\"internalType\":\"contractIRMNRemote\"},{\"name\":\"tokenAdminRegistry\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"nonceManager\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"latestConfigDetails\",\"inputs\":[{\"name\":\"ocrPluginType\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"outputs\":[{\"name\":\"ocrConfig\",\"type\":\"tuple\",\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"components\":[{\"name\":\"configInfo\",\"type\":\"tuple\",\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"components\":[{\"name\":\"configDigest\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"F\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"n\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"}]},{\"name\":\"signers\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"transmitters\",\"type\":\"address[]\",\"internalType\":\"address[]\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"manuallyExecute\",\"inputs\":[{\"name\":\"reports\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.ExecutionReport[]\",\"components\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"messages\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"components\":[{\"name\":\"header\",\"type\":\"tuple\",\"internalType\":\"structInternal.RampMessageHeader\",\"components\":[{\"name\":\"messageId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sequenceNumber\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"sender\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"receiver\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"gasLimit\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"tokenAmounts\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"components\":[{\"name\":\"sourcePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"destTokenAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"destGasAmount\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"extraData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}]},{\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\",\"internalType\":\"bytes[][]\"},{\"name\":\"proofs\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"proofFlagBits\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"gasLimitOverrides\",\"type\":\"tuple[][]\",\"internalType\":\"structOffRamp.GasLimitOverride[][]\",\"components\":[{\"name\":\"receiverExecutionGasLimit\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\",\"internalType\":\"uint32[]\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"setDynamicConfig\",\"inputs\":[{\"name\":\"dynamicConfig\",\"type\":\"tuple\",\"internalType\":\"structOffRamp.DynamicConfig\",\"components\":[{\"name\":\"feeQuoter\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"messageInterceptor\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setOCR3Configs\",\"inputs\":[{\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\",\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"components\":[{\"name\":\"configDigest\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"ocrPluginType\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"F\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"signers\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"transmitters\",\"type\":\"address[]\",\"internalType\":\"address[]\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"typeAndVersion\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"AlreadyAttempted\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"sequenceNumber\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"CommitReportAccepted\",\"inputs\":[{\"name\":\"merkleRoots\",\"type\":\"tuple[]\",\"indexed\":false,\"internalType\":\"structInternal.MerkleRoot[]\",\"components\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"onRampAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"minSeqNr\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"maxSeqNr\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"merkleRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"priceUpdates\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structInternal.PriceUpdates\",\"components\":[{\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"components\":[{\"name\":\"sourceToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"usdPerToken\",\"type\":\"uint224\",\"internalType\":\"uint224\"}]},{\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.GasPriceUpdate[]\",\"components\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"usdPerUnitGas\",\"type\":\"uint224\",\"internalType\":\"uint224\"}]}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ConfigSet\",\"inputs\":[{\"name\":\"ocrPluginType\",\"type\":\"uint8\",\"indexed\":false,\"internalType\":\"uint8\"},{\"name\":\"configDigest\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"},{\"name\":\"signers\",\"type\":\"address[]\",\"indexed\":false,\"internalType\":\"address[]\"},{\"name\":\"transmitters\",\"type\":\"address[]\",\"indexed\":false,\"internalType\":\"address[]\"},{\"name\":\"F\",\"type\":\"uint8\",\"indexed\":false,\"internalType\":\"uint8\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DynamicConfigSet\",\"inputs\":[{\"name\":\"dynamicConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"components\":[{\"name\":\"feeQuoter\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"messageInterceptor\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ExecutionStateChanged\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"sequenceNumber\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"messageId\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"messageHash\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"},{\"name\":\"state\",\"type\":\"uint8\",\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\"},{\"name\":\"returnData\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"},{\"name\":\"gasUsed\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferRequested\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RootRemoved\",\"inputs\":[{\"name\":\"root\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SkippedAlreadyExecutedMessage\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"sequenceNumber\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SkippedReportExecution\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SourceChainConfigSet\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"sourceConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"components\":[{\"name\":\"router\",\"type\":\"address\",\"internalType\":\"contractIRouter\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"minSeqNr\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"onRamp\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SourceChainSelectorAdded\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"StaticConfigSet\",\"inputs\":[{\"name\":\"staticConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"components\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"gasForCallExactCheck\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"rmnRemote\",\"type\":\"address\",\"internalType\":\"contractIRMNRemote\"},{\"name\":\"tokenAdminRegistry\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"nonceManager\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Transmitted\",\"inputs\":[{\"name\":\"ocrPluginType\",\"type\":\"uint8\",\"indexed\":true,\"internalType\":\"uint8\"},{\"name\":\"configDigest\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"},{\"name\":\"sequenceNumber\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"CanOnlySelfCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CannotTransferToSelf\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CommitOnRampMismatch\",\"inputs\":[{\"name\":\"reportOnRamp\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"configOnRamp\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"ConfigDigestMismatch\",\"inputs\":[{\"name\":\"expected\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"actual\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"CursedByRMN\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"EmptyBatch\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"EmptyReport\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"ExecutionError\",\"inputs\":[{\"name\":\"messageId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"err\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"ForkedChain\",\"inputs\":[{\"name\":\"expected\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"actual\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"InsufficientGasForCallWithExact\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidConfig\",\"inputs\":[{\"name\":\"errorType\",\"type\":\"uint8\",\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\"}]},{\"type\":\"error\",\"name\":\"InvalidDataLength\",\"inputs\":[{\"name\":\"expected\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"got\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"InvalidInterval\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"min\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"max\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"InvalidManualExecutionGasLimit\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"messageId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"newLimit\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"InvalidManualExecutionTokenGasOverride\",\"inputs\":[{\"name\":\"messageId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"tokenIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"oldLimit\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"tokenGasOverride\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"InvalidMessageDestChainSelector\",\"inputs\":[{\"name\":\"messageDestChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"InvalidNewState\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sequenceNumber\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"newState\",\"type\":\"uint8\",\"internalType\":\"enumInternal.MessageExecutionState\"}]},{\"type\":\"error\",\"name\":\"InvalidOnRampUpdate\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"InvalidProof\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidRoot\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"LeavesCannotBeEmpty\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ManualExecutionGasAmountCountMismatch\",\"inputs\":[{\"name\":\"messageId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"sequenceNumber\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"ManualExecutionGasLimitMismatch\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ManualExecutionNotYetEnabled\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"MessageValidationError\",\"inputs\":[{\"name\":\"errorReason\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"MustBeProposedOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NonUniqueSignatures\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotACompatiblePool\",\"inputs\":[{\"name\":\"notPool\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"OnlyCallableByOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OracleCannotBeZeroAddress\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OwnerCannotBeZero\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ReceiverError\",\"inputs\":[{\"name\":\"err\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"ReleaseOrMintBalanceMismatch\",\"inputs\":[{\"name\":\"amountReleased\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"balancePre\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"balancePost\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"RootAlreadyCommitted\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"merkleRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"RootNotCommitted\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"SignatureVerificationNotAllowedInExecutionPlugin\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"SignatureVerificationRequiredInCommitPlugin\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"SignaturesOutOfRegistration\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"SourceChainNotEnabled\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"SourceChainSelectorMismatch\",\"inputs\":[{\"name\":\"reportSourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"messageSourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"StaleCommitReport\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"StaticConfigCannotBeChanged\",\"inputs\":[{\"name\":\"ocrPluginType\",\"type\":\"uint8\",\"internalType\":\"uint8\"}]},{\"type\":\"error\",\"name\":\"TokenDataMismatch\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sequenceNumber\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"TokenHandlingError\",\"inputs\":[{\"name\":\"target\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"err\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"UnauthorizedSigner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnauthorizedTransmitter\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnexpectedTokenData\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"WrongMessageLength\",\"inputs\":[{\"name\":\"expected\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"actual\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"WrongNumberOfSignatures\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ZeroAddressNotAllowed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ZeroChainSelectorNotAllowed\",\"inputs\":[]}]", + Bin: "0x6101408060405234610848576163ea803803809161001d828561087e565b833981019080820361014081126108485760a08112610848576040519060a082016001600160401b0381118382101761084d5760405261005c836108a1565b825260208301519261ffff84168403610848576020830193845260408101516001600160a01b0381168103610848576040840190815261009e606083016108b5565b946060850195865260806100b38185016108b5565b86820190815294609f19011261084857604051946100d086610863565b6100dc60a085016108b5565b865260c08401519463ffffffff86168603610848576020870195865261010460e086016108c9565b976040880198895261011961010087016108b5565b6060890190815261012087015190966001600160401b03821161084857018a601f820112156108485780519a6001600160401b038c1161084d578b60051b916020806040519e8f9061016d8388018361087e565b81520193820101908282116108485760208101935b828510610748575050505050331561073757600180546001600160a01b031916331790554660805284516001600160a01b0316158015610725575b8015610713575b6106f15782516001600160401b0316156107025782516001600160401b0390811660a090815286516001600160a01b0390811660c0528351811660e0528451811661010052865161ffff90811661012052604080519751909416875296519096166020860152955185169084015251831660608301525190911660808201527fb0fa1fb01508c5097c502ad056fd77018870c9be9a86d9e56b6b471862d7c5b79190a182516001600160a01b0316156106f1579151600480548351865160ff60c01b90151560c01b1663ffffffff60a01b60a09290921b919091166001600160a01b039485166001600160c81b0319909316831717179091558351600580549184166001600160a01b031990921691909117905560408051918252925163ffffffff166020820152935115159184019190915290511660608201527fcbb53bda7106a610de67df506ac86b65c44d5afac0fd2b11070dc2d61a6f2dee90608090a160005b815181101561066b576020600582901b8301810151908101516001600160401b031690600090821561065c5780516001600160a01b03161561064d57828252600860205260408220906060810151600183019361038585546108d6565b6105ee578354600160a81b600160e81b031916600160a81b1784556040518681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb990602090a15b815180159081156105c3575b506105b4578151916001600160401b0383116105a0576103f986546108d6565b601f811161055b575b50602091601f84116001146104e257926001989796949281926000805160206163ca8339815191529795926104d7575b5050600019600383901b1c191690881b1783555b60408101518254915160a089811b8a9003801960ff60a01b1990951693151590911b60ff60a01b169290921792909216911617815561048484610993565b506104ce6040519283926020845254888060a01b038116602085015260ff8160a01c1615156040850152888060401b039060a81c16606084015260808084015260a0830190610910565b0390a201610328565b015190503880610432565b9190601f198416878452828420935b818110610543575092600199989795939285926000805160206163ca83398151915298968c951061052a575b505050811b018355610446565b015160001960f88460031b161c1916905538808061051d565b929360206001819287860151815501950193016104f1565b86835260208320601f850160051c81019160208610610596575b601f0160051c01905b81811061058b5750610402565b83815560010161057e565b9091508190610575565b634e487b7160e01b82526041600452602482fd5b6342bcdf7f60e11b8152600490fd5b905060208301206040516020810190838252602081526105e460408261087e565b51902014386103d9565b835460a81c6001600160401b0316600114158061061f575b156103cd57632105803760e11b81526004869052602490fd5b50604051610638816106318189610910565b038261087e565b60208151910120825160208401201415610606565b6342bcdf7f60e11b8252600482fd5b63c656089560e01b8252600482fd5b6040516159a39081610a2782396080518161368c015260a05181818161048e01526141ea015260c0518181816104e401528181612cba0152818161310e0152614184015260e05181818161051301526149c701526101005181818161054201526145ad0152610120518181816104b50152818161243401528181614aba01526156d80152f35b6342bcdf7f60e11b60005260046000fd5b63c656089560e01b60005260046000fd5b5081516001600160a01b0316156101c4565b5080516001600160a01b0316156101bd565b639b15e16f60e01b60005260046000fd5b84516001600160401b0381116108485782016080818603601f190112610848576040519061077582610863565b60208101516001600160a01b0381168103610848578252610798604082016108a1565b60208301526107a9606082016108c9565b604083015260808101516001600160401b03811161084857602091010185601f820112156108485780516001600160401b03811161084d57604051916107f9601f8301601f19166020018461087e565b81835287602083830101116108485760005b8281106108335750509181600060208096949581960101526060820152815201940193610182565b8060208092840101518282870101520161080b565b600080fd5b634e487b7160e01b600052604160045260246000fd5b608081019081106001600160401b0382111761084d57604052565b601f909101601f19168101906001600160401b0382119082101761084d57604052565b51906001600160401b038216820361084857565b51906001600160a01b038216820361084857565b5190811515820361084857565b90600182811c92168015610906575b60208310146108f057565b634e487b7160e01b600052602260045260246000fd5b91607f16916108e5565b60009291815491610920836108d6565b8083529260018116908115610976575060011461093c57505050565b60009081526020812093945091925b83831061095c575060209250010190565b60018160209294939454838587010152019101919061094b565b915050602093945060ff929192191683830152151560051b010190565b80600052600760205260406000205415600014610a20576006546801000000000000000081101561084d576001810180600655811015610a0a577ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f0181905560065460009182526007602052604090912055600190565b634e487b7160e01b600052603260045260246000fd5b5060009056fe6080604052600436101561001257600080fd5b60003560e01c806304666f9c1461015757806306285c6914610152578063181f5a771461014d5780633f4b04aa146101485780635215505b146101435780635e36480c1461013e5780635e7bb0081461013957806360987c20146101345780637437ff9f1461012f57806379ba50971461012a5780637edf52f41461012557806385572ffb146101205780638da5cb5b1461011b578063c673e58414610116578063ccd37ba314610111578063de5e0b9a1461010c578063e9d68a8e14610107578063f2fde38b14610102578063f58e03fc146100fd5763f716f99f146100f857600080fd5b6118d4565b6117b7565b61172c565b611691565b6115f5565b611571565b6114c6565b6113de565b6113a8565b6111e2565b611162565b6110b9565b61103e565b610e39565b6108ce565b610789565b61067c565b61061d565b61043d565b61031f565b634e487b7160e01b600052604160045260246000fd5b608081019081106001600160401b0382111761018d57604052565b61015c565b60a081019081106001600160401b0382111761018d57604052565b604081019081106001600160401b0382111761018d57604052565b606081019081106001600160401b0382111761018d57604052565b90601f801991011681019081106001600160401b0382111761018d57604052565b6040519061021360c0836101e3565b565b6040519061021360a0836101e3565b60405190610213610100836101e3565b604051906102136040836101e3565b6001600160401b03811161018d5760051b60200190565b6001600160a01b0381160361026b57565b600080fd5b600435906001600160401b038216820361026b57565b35906001600160401b038216820361026b57565b8015150361026b57565b35906102138261029a565b6001600160401b03811161018d57601f01601f191660200190565b9291926102d6826102af565b916102e460405193846101e3565b82948184528183011161026b578281602093846000960137010152565b9080601f8301121561026b5781602061031c933591016102ca565b90565b3461026b57602036600319011261026b576004356001600160401b03811161026b573660238201121561026b5780600401359061035b82610243565b9061036960405192836101e3565b8282526024602083019360051b8201019036821161026b5760248101935b8285106103995761039784611a0f565b005b84356001600160401b03811161026b5782016080602319823603011261026b57604051916103c683610172565b60248201356103d48161025a565b83526103e260448301610286565b602084015260648201356103f58161029a565b60408401526084820135926001600160401b03841161026b57610422602094936024869536920101610301565b6060820152815201940193610387565b600091031261026b57565b3461026b57600036600319011261026b576000608060405161045e81610192565b82815282602082015282604082015282606082015201526105bc60405161048481610192565b6001600160401b037f000000000000000000000000000000000000000000000000000000000000000016815261ffff7f00000000000000000000000000000000000000000000000000000000000000001660208201526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660408201526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660608201526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660808201526040519182918291909160806001600160a01b038160a08401956001600160401b03815116855261ffff6020820151166020860152826040820151166040860152826060820151166060860152015116910152565b0390f35b604051906105cf6020836101e3565b60008252565b60005b8381106105e85750506000910152565b81810151838201526020016105d8565b90602091610611815180928185528580860191016105d5565b601f01601f1916010190565b3461026b57600036600319011261026b576105bc604080519061064081836101e3565b601182527f4f666652616d7020312e362e302d6465760000000000000000000000000000006020830152519182916020835260208301906105f8565b3461026b57600036600319011261026b5760206001600160401b03600b5416604051908152f35b906080606061031c936001600160a01b0381511684526020810151151560208501526001600160401b03604082015116604085015201519181606082015201906105f8565b6040810160408252825180915260206060830193019060005b81811061076a575050506020818303910152815180825260208201916020808360051b8301019401926000915b83831061073d57505050505090565b909192939460208061075b600193601f1986820301875289516106a3565b9701930193019193929061072e565b82516001600160401b0316855260209485019490920191600101610701565b3461026b57600036600319011261026b576006546107a681610243565b906107b460405192836101e3565b808252601f196107c382610243565b0160005b8181106108855750506107d981611ce2565b9060005b8181106107f55750506105bc604051928392836106e8565b8061082b61081361080760019461406b565b6001600160401b031690565b61081d8387611d3c565b906001600160401b03169052565b61086961086461084b61083e8488611d3c565b516001600160401b031690565b6001600160401b03166000526008602052604060002090565b611e28565b6108738287611d3c565b5261087e8186611d3c565b50016107dd565b602090610890611cbb565b828287010152016107c7565b634e487b7160e01b600052602160045260246000fd5b600411156108bc57565b61089c565b9060048210156108bc5752565b3461026b57604036600319011261026b576108e7610270565b602435906001600160401b038216820361026b5760209161090791611ec4565b61091460405180926108c1565bf35b91908260a091031261026b5760405161092e81610192565b60806109738183958035855261094660208201610286565b602086015261095760408201610286565b604086015261096860608201610286565b606086015201610286565b910152565b35906102138261025a565b63ffffffff81160361026b57565b359061021382610983565b81601f8201121561026b578035906109b382610243565b926109c160405194856101e3565b82845260208085019360051b8301019181831161026b5760208101935b8385106109ed57505050505090565b84356001600160401b03811161026b57820160a0818503601f19011261026b5760405191610a1a83610192565b60208201356001600160401b03811161026b57856020610a3c92850101610301565b83526040820135610a4c8161025a565b6020840152610a5d60608301610991565b60408401526080820135926001600160401b03841161026b5760a083610a8a886020809881980101610301565b6060840152013560808201528152019401936109de565b9190916101408184031261026b57610ab7610204565b92610ac28183610916565b845260a08201356001600160401b03811161026b5781610ae3918401610301565b602085015260c08201356001600160401b03811161026b5781610b07918401610301565b6040850152610b1860e08301610978565b606085015261010082013560808501526101208201356001600160401b03811161026b57610b46920161099c565b60a0830152565b9080601f8301121561026b578135610b6481610243565b92610b7260405194856101e3565b81845260208085019260051b8201019183831161026b5760208201905b838210610b9e57505050505090565b81356001600160401b03811161026b57602091610bc087848094880101610aa1565b815201910190610b8f565b81601f8201121561026b57803590610be282610243565b92610bf060405194856101e3565b82845260208085019360051b8301019181831161026b5760208101935b838510610c1c57505050505090565b84356001600160401b03811161026b57820183603f8201121561026b576020810135610c4781610243565b91610c5560405193846101e3565b8183526020808085019360051b830101019186831161026b5760408201905b838210610c8e575050509082525060209485019401610c0d565b81356001600160401b03811161026b57602091610cb28a8480809589010101610301565b815201910190610c74565b929190610cc981610243565b93610cd760405195866101e3565b602085838152019160051b810192831161026b57905b828210610cf957505050565b8135815260209182019101610ced565b9080601f8301121561026b5781602061031c93359101610cbd565b81601f8201121561026b57803590610d3b82610243565b92610d4960405194856101e3565b82845260208085019360051b8301019181831161026b5760208101935b838510610d7557505050505090565b84356001600160401b03811161026b57820160a0818503601f19011261026b57610d9d610215565b91610daa60208301610286565b835260408201356001600160401b03811161026b57856020610dce92850101610b4d565b602084015260608201356001600160401b03811161026b57856020610df592850101610bcb565b60408401526080820135926001600160401b03841161026b5760a083610e22886020809881980101610d09565b606084015201356080820152815201940193610d66565b3461026b57604036600319011261026b576004356001600160401b03811161026b57610e69903690600401610d24565b6024356001600160401b03811161026b573660238201121561026b57806004013591610e9483610243565b91610ea260405193846101e3565b8383526024602084019460051b8201019036821161026b5760248101945b828610610ed1576103978585611f0c565b85356001600160401b03811161026b5782013660438201121561026b576024810135610efc81610243565b91610f0a60405193846101e3565b818352602060248185019360051b830101019036821161026b5760448101925b828410610f44575050509082525060209586019501610ec0565b83356001600160401b03811161026b576024908301016040601f19823603011261026b5760405190610f75826101ad565b6020810135825260408101356001600160401b03811161026b57602091010136601f8201121561026b57803590610fab82610243565b91610fb960405193846101e3565b80835260208084019160051b8301019136831161026b57602001905b828210610ff45750505091816020938480940152815201930192610f2a565b60208091833561100381610983565b815201910190610fd5565b9181601f8401121561026b578235916001600160401b03831161026b576020808501948460051b01011161026b57565b3461026b57606036600319011261026b576004356001600160401b03811161026b5761106e903690600401610aa1565b6024356001600160401b03811161026b5761108d90369060040161100e565b91604435926001600160401b03841161026b576110b161039794369060040161100e565b939092612318565b3461026b57600036600319011261026b576110d26125e5565b506105bc6040516110e281610172565b60ff6004546001600160a01b038116835263ffffffff8160a01c16602084015260c01c16151560408201526001600160a01b036005541660608201526040519182918291909160606001600160a01b0381608084019582815116855263ffffffff6020820151166020860152604081015115156040860152015116910152565b3461026b57600036600319011261026b576000546001600160a01b03811633036111d1576001600160a01b0319600154913382841617600155166000556001600160a01b033391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b63015aa1e360e11b60005260046000fd5b3461026b57608036600319011261026b57600060405161120181610172565b60043561120d8161025a565b815260243561121b81610983565b602082015260443561122c8161029a565b604082015260643561123d8161025a565b606082015261124a613489565b6001600160a01b038151161561139957611393816112a96001600160a01b037fcbb53bda7106a610de67df506ac86b65c44d5afac0fd2b11070dc2d61a6f2dee9451166001600160a01b03166001600160a01b03196004541617600455565b60208101516004547fffffffffffffff0000000000ffffffffffffffffffffffffffffffffffffffff77ffffffff000000000000000000000000000000000000000078ff0000000000000000000000000000000000000000000000006040860151151560c01b169360a01b169116171760045561134f61133360608301516001600160a01b031690565b6001600160a01b03166001600160a01b03196005541617600555565b6040519182918291909160606001600160a01b0381608084019582815116855263ffffffff6020820151166020860152604081015115156040860152015116910152565b0390a180f35b6342bcdf7f60e11b8252600482fd5b3461026b57602036600319011261026b576004356001600160401b03811161026b5760a090600319903603011261026b57600080fd5b3461026b57600036600319011261026b5760206001600160a01b0360015416604051908152f35b6004359060ff8216820361026b57565b359060ff8216820361026b57565b906020808351928381520192019060005b8181106114415750505090565b82516001600160a01b0316845260209384019390920191600101611434565b9061031c9160208152606082518051602084015260ff602082015116604084015260ff6040820151168284015201511515608082015260406114b1602084015160c060a085015260e0840190611423565b9201519060c0601f1982850301910152611423565b3461026b57602036600319011261026b5760ff6114e1611405565b6060604080516114f0816101c8565b6114f86125e5565b815282602082015201521660005260026020526105bc6040600020600361156060405192611525846101c8565b61152e8161260a565b845260405161154b816115448160028601612643565b03826101e3565b60208501526115446040518094819301612643565b604082015260405191829182611460565b3461026b57604036600319011261026b5761158a610270565b6001600160401b036024359116600052600a6020526040600020906000526020526020604060002054604051908152f35b9060049160441161026b57565b9181601f8401121561026b578235916001600160401b03831161026b576020838186019501011161026b57565b3461026b5760c036600319011261026b5761160f366115bb565b6044356001600160401b03811161026b5761162e9036906004016115c8565b6064929192356001600160401b03811161026b5761165090369060040161100e565b60843594916001600160401b03861161026b5761167461039796369060040161100e565b94909360a43596612c75565b90602061031c9281815201906106a3565b3461026b57602036600319011261026b576001600160401b036116b2610270565b6116ba611cbb565b501660005260086020526105bc6040600020600161171b604051926116de84610172565b6001600160401b0381546001600160a01b038116865260ff8160a01c161515602087015260a81c1660408501526115446040518094819301611d8a565b606082015260405191829182611680565b3461026b57602036600319011261026b576001600160a01b036004356117518161025a565b611759613489565b163381146117a657806001600160a01b031960005416176000556001600160a01b03600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b636d6c4ee560e11b60005260046000fd5b3461026b57606036600319011261026b576117d1366115bb565b6044356001600160401b03811161026b576117f09036906004016115c8565b9182820160208382031261026b578235906001600160401b03821161026b5761181a918401610d24565b60405190602061182a81846101e3565b60008352601f19810160005b81811061185e57505050610397949161184e916136cd565b611856613184565b928392613a33565b60608582018401528201611836565b9080601f8301121561026b57813561188481610243565b9261189260405194856101e3565b81845260208085019260051b82010192831161026b57602001905b8282106118ba5750505090565b6020809183356118c98161025a565b8152019101906118ad565b3461026b57602036600319011261026b576004356001600160401b03811161026b573660238201121561026b5780600401359061191082610243565b9061191e60405192836101e3565b8282526024602083019360051b8201019036821161026b5760248101935b82851061194c57610397846131a0565b84356001600160401b03811161026b57820160c0602319823603011261026b57611974610204565b916024820135835261198860448301611415565b602084015261199960648301611415565b60408401526119aa608483016102a4565b606084015260a48201356001600160401b03811161026b576119d2906024369185010161186d565b608084015260c4820135926001600160401b03841161026b576119ff60209493602486953692010161186d565b60a082015281520194019361193c565b611a17613489565b60005b8151811015611cb757611a2d8183611d3c565b5190611a4360208301516001600160401b031690565b916001600160401b038316908115611ca657611a78611a6c611a6c83516001600160a01b031690565b6001600160a01b031690565b15611c0d57611a9a846001600160401b03166000526008602052604060002090565b906060810151916001810195611ab08754611d50565b611c3457611b237ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb991611b0984750100000000000000000000000000000000000000000067ffffffffffffffff60a81b19825416179055565b6040516001600160401b0390911681529081906020820190565b0390a15b82518015908115611c1e575b50611c0d57611bee611bd2611c0493611b6f7f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b9660019a61352b565b611bc5611b7f6040830151151590565b85547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690151560a01b74ff000000000000000000000000000000000000000016178555565b516001600160a01b031690565b82906001600160a01b03166001600160a01b0319825416179055565b611bf784615093565b50604051918291826135fc565b0390a201611a1a565b6342bcdf7f60e11b60005260046000fd5b90506020840120611c2d6134ae565b1438611b33565b60016001600160401b03611c5384546001600160401b039060a81c1690565b16141580611c87575b611c665750611b27565b632105803760e11b6000526001600160401b031660045260246000fd5b6000fd5b50611c9187611e0d565b60208151910120845160208601201415611c5c565b63c656089560e01b60005260046000fd5b5050565b60405190611cc882610172565b606080836000815260006020820152600060408201520152565b90611cec82610243565b611cf960405191826101e3565b8281528092611d0a601f1991610243565b0190602036910137565b634e487b7160e01b600052603260045260246000fd5b805115611d375760200190565b611d14565b8051821015611d375760209160051b010190565b90600182811c92168015611d80575b6020831014611d6a57565b634e487b7160e01b600052602260045260246000fd5b91607f1691611d5f565b60009291815491611d9a83611d50565b8083529260018116908115611df05750600114611db657505050565b60009081526020812093945091925b838310611dd6575060209250010190565b600181602092949394548385870101520191019190611dc5565b915050602093945060ff929192191683830152151560051b010190565b90610213611e219260405193848092611d8a565b03836101e3565b9060016060604051611e3981610172565b611e8281956001600160401b0381546001600160a01b038116855260ff8160a01c161515602086015260a81c166040840152611e7b6040518096819301611d8a565b03846101e3565b0152565b634e487b7160e01b600052601160045260246000fd5b908160051b9180830460201490151715611eb257565b611e86565b91908203918211611eb257565b611ed082607f92613646565b9116906801fffffffffffffffe6001600160401b0383169260011b169180830460021490151715611eb2576003911c1660048110156108bc5790565b611f1461368a565b80518251810361210b5760005b818110611f3457505090610213916136cd565b611f3e8184611d3c565b516020810190815151611f518488611d3c565b51928351820361210b5790916000925b808410611f75575050505050600101611f21565b91949398611f87848b98939598611d3c565b515198611f95888851611d3c565b5199806120c2575b5060a08a01988b6020611fb38b8d515193611d3c565b51015151036120855760005b8a515181101561207057611ffb611ff2611fe88f6020611fe08f8793611d3c565b510151611d3c565b5163ffffffff1690565b63ffffffff1690565b8b8161200c575b5050600101611fbf565b611ff2604061201f8561202b9451611d3c565b51015163ffffffff1690565b9081811061203a57508b612002565b8d51516040516348e617b360e01b81526004810191909152602481019390935260448301919091526064820152608490fd5b0390fd5b50985098509893949095600101929091611f61565b611c838b516120a0606082519201516001600160401b031690565b6370a193fd60e01b6000526004919091526001600160401b0316602452604490565b60808b0151811015611f9d57611c83908b6120e488516001600160401b031690565b905151633a98d46360e11b6000526001600160401b03909116600452602452604452606490565b6320f8fd5960e21b60005260046000fd5b60405190612129826101ad565b60006020838281520152565b604051906121446020836101e3565b600080835282815b82811061215857505050565b60209061216361211c565b8282850101520161214c565b805182526001600160401b03602082015116602083015260806121b66121a4604084015160a0604087015260a08601906105f8565b606084015185820360608701526105f8565b9101519160808183039101526020808351928381520192019060005b8181106121df5750505090565b825180516001600160a01b0316855260209081015181860152604090940193909201916001016121d2565b90602061031c92818152019061216f565b6040513d6000823e3d90fd5b3d15612252573d90612238826102af565b9161224660405193846101e3565b82523d6000602084013e565b606090565b90602061031c9281815201906105f8565b909160608284031261026b57815161227f8161029a565b9260208301516001600160401b03811161026b5783019080601f8301121561026b578151916122ad836102af565b916122bb60405193846101e3565b8383526020848301011161026b576040926122dc91602080850191016105d5565b92015190565b9293606092959461ffff6123066001600160a01b039460808852608088019061216f565b97166020860152604085015216910152565b929093913033036125d45761232b612135565b9460a0850151805161258d575b5050505050805191612356602084519401516001600160401b031690565b906020830151916040840192612383845192612370610215565b9788526001600160401b03166020880152565b6040860152606085015260808401526001600160a01b036123ac6005546001600160a01b031690565b1680612510575b5051511580612504575b80156124ee575b80156124c5575b611cb75761245d9181612402611a6c6123f561084b602060009751016001600160401b0390511690565b546001600160a01b031690565b908361241d606060808401519301516001600160a01b031690565b604051633cf9798360e01b815296879586948593917f000000000000000000000000000000000000000000000000000000000000000090600486016122e2565b03925af19081156124c057600090600092612499575b501561247c5750565b6040516302a35ba360e21b815290819061206c9060048301612257565b90506124b891503d806000833e6124b081836101e3565b810190612268565b509038612473565b61221b565b506124e96124e56124e060608401516001600160a01b031690565b6138f4565b1590565b6123cb565b5060608101516001600160a01b03163b156123c4565b506080810151156123bd565b803b1561026b57600060405180926308d450a160e01b82528183816125388a6004830161220a565b03925af19081612572575b5061256c5761206c612553612227565b6040516309c2532560e01b815291829160048301612257565b386123b3565b806125816000612587936101e3565b80610432565b38612543565b85965060206125c99601516125ac60608901516001600160a01b031690565b906125c360208a51016001600160401b0390511690565b926137db565b903880808080612338565b6306e34e6560e31b60005260046000fd5b604051906125f282610172565b60006060838281528260208201528260408201520152565b9060405161261781610172565b606060ff600183958054855201548181166020850152818160081c16604085015260101c161515910152565b906020825491828152019160005260206000209060005b8181106126675750505090565b82546001600160a01b031684526020909301926001928301920161265a565b90610213611e219260405193848092612643565b35906001600160e01b038216820361026b57565b81601f8201121561026b578035906126c582610243565b926126d360405194856101e3565b82845260208085019360061b8301019181831161026b57602001925b8284106126fd575050505090565b60408483031261026b5760206040918251612717816101ad565b61272087610286565b815261272d83880161269a565b838201528152019301926126ef565b81601f8201121561026b5780359061275382610243565b9261276160405194856101e3565b82845260208085019360051b8301019181831161026b5760208101935b83851061278d57505050505090565b84356001600160401b03811161026b57820160a0818503601f19011261026b57604051916127ba83610192565b6127c660208301610286565b83526040820135926001600160401b03841161026b5760a0836127f0886020809881980101610301565b8584015261280060608201610286565b604084015261281160808201610286565b60608401520135608082015281520194019361277e565b81601f8201121561026b5780359061283f82610243565b9261284d60405194856101e3565b82845260208085019360061b8301019181831161026b57602001925b828410612877575050505090565b60408483031261026b5760206040918251612891816101ad565b863581528287013583820152815201930192612869565b60208183031261026b578035906001600160401b03821161026b570160608183031261026b57604051916128db836101c8565b81356001600160401b03811161026b57820160408183031261026b5760405190612904826101ad565b80356001600160401b03811161026b57810183601f8201121561026b57803561292c81610243565b9161293a60405193846101e3565b81835260208084019260061b8201019086821161026b57602001915b8183106129d25750505082526020810135906001600160401b03821161026b57612982918491016126ae565b6020820152835260208201356001600160401b03811161026b57816129a891840161273c565b602084015260408201356001600160401b03811161026b576129ca9201612828565b604082015290565b60408388031261026b57602060409182516129ec816101ad565b85356129f78161025a565b8152612a0483870161269a565b83820152815201920191612956565b9080602083519182815201916020808360051b8301019401926000915b838310612a3f57505050505090565b9091929394602080600192601f198582030186528851906001600160401b038251168152608080612a7d8585015160a08786015260a08501906105f8565b936001600160401b0360408201511660408501526001600160401b036060820151166060850152015191015297019301930191939290612a30565b916001600160a01b03612ad992168352606060208401526060830190612a13565b9060408183039101526020808351928381520192019060005b818110612aff5750505090565b8251805185526020908101518186015260409094019390920191600101612af2565b906020808351928381520192019060005b818110612b3f5750505090565b825180516001600160401b031685526020908101516001600160e01b03168186015260409094019390920191600101612b32565b9190604081019083519160408252825180915260206060830193019060005b818110612bb357505050602061031c93940151906020818403910152612b21565b825180516001600160a01b031686526020908101516001600160e01b03168187015260409095019490920191600101612b92565b90602061031c928181520190612b73565b9081602091031261026b575161031c8161029a565b9091612c2461031c936040845260408401906105f8565b916020818403910152611d8a565b6001600160401b036001911601906001600160401b038211611eb257565b9091612c6761031c93604084526040840190612a13565b916020818403910152612b73565b929693959190979497612c8a828201826128a8565b98612c9e6124e560045460ff9060c01c1690565b6130f2575b895180515115908115916130e3575b5061300a575b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316999860208a019860005b8a518051821015612fa85781612d0191611d3c565b518d612d1482516001600160401b031690565b604051632cbc26bb60e01b815267ffffffffffffffff60801b608083901b1660048201529091602090829060249082905afa9081156124c057600091612f7a575b50612f5d57612d6390613942565b60208201805160208151910120906001830191612d7f83611e0d565b6020815191012003612f40575050805460408301516001600160401b039081169160a81c168114801590612f18575b612ec657506080820151908115612eb557612dff82612df0612dd786516001600160401b031690565b6001600160401b0316600052600a602052604060002090565b90600052602052604060002090565b54612e81578291612e65612e7a92612e2c612e2760606001999801516001600160401b031690565b612c32565b67ffffffffffffffff60a81b197cffffffffffffffff00000000000000000000000000000000000000000083549260a81b169116179055565b612df0612dd74294516001600160401b031690565b5501612cec565b50612e96611c8392516001600160401b031690565b6332cf0cbf60e01b6000526001600160401b0316600452602452604490565b63504570e360e01b60005260046000fd5b82611c8391612ef06060612ee184516001600160401b031690565b9301516001600160401b031690565b636af0786b60e11b6000526001600160401b0392831660045290821660245216604452606490565b50612f3061080760608501516001600160401b031690565b6001600160401b03821611612dae565b5161206c60405192839263b80d8fa960e01b845260048401612c0d565b637edeb53960e11b6000526001600160401b031660045260246000fd5b612f9b915060203d8111612fa1575b612f9381836101e3565b810190612bf8565b38612d55565b503d612f89565b50506130049496989b507f35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e46102139b612ffc949597999b51905190612ff260405192839283612c50565b0390a13691610cbd565b943691610cbd565b93613d2d565b61301f602086015b356001600160401b031690565b600b546001600160401b03828116911610156130c757613055906001600160401b03166001600160401b0319600b541617600b55565b61306d611a6c611a6c6004546001600160a01b031690565b8a5190803b1561026b57604051633937306f60e01b815291600091839182908490829061309d9060048301612be7565b03925af180156124c0576130b2575b50612cb8565b8061258160006130c1936101e3565b386130ac565b5060208a015151612cb857632261116760e01b60005260046000fd5b60209150015151151538612cb2565b60208a01518051613104575b50612ca3565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169060408c0151823b1561026b57604051633854844f60e11b815292600092849283918291613160913060048501612ab8565b03915afa80156124c057156130fe5780612581600061317e936101e3565b386130fe565b604051906131936020836101e3565b6000808352366020840137565b6131a8613489565b60005b8151811015611cb7576131be8183611d3c565b51906040820160ff6131d1825160ff1690565b161561347357602083015160ff16926131f78460ff166000526002602052604060002090565b916001830191825461321261320c8260ff1690565b60ff1690565b613438575061323f6132276060830151151590565b845462ff0000191690151560101b62ff000016178455565b60a081019182516101008151116133e057805115613422576003860161326d61326782612686565b8a614e41565b60608401516132fd575b947fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547946002946132d96132c96132f79a966132c28760019f9c6132bd6132ef9a8f614fa2565b613f6e565b5160ff1690565b845460ff191660ff821617909455565b5190818555519060405195869501908886613ff4565b0390a1615024565b016131ab565b9794600287939597019661331961331389612686565b88614e41565b60808501519461010086511161340c57855161334161320c61333c8a5160ff1690565b613f5a565b10156133f65785518451116133e0576132d96132c97fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547986132c28760019f6132bd6132f79f9a8f6133c860029f6133c26132ef9f8f906132bd84926133a7845160ff1690565b908054909161ff001990911660089190911b61ff0016179055565b82614ed5565b505050979c9f50975050969a50505094509450613277565b631b3fab5160e11b600052600160045260246000fd5b631b3fab5160e11b600052600360045260246000fd5b631b3fab5160e11b600052600260045260246000fd5b631b3fab5160e11b600052600560045260246000fd5b60101c60ff1661345361344e6060840151151590565b151590565b9015151461323f576321fd80df60e21b60005260ff861660045260246000fd5b631b3fab5160e11b600090815260045260246000fd5b6001600160a01b0360015416330361349d57565b6315ae3a6f60e11b60005260046000fd5b604051602081019060008252602081526134c96040826101e3565b51902090565b8181106134da575050565b600081556001016134cf565b9190601f81116134f557505050565b610213926000526020600020906020601f840160051c83019310613521575b601f0160051c01906134cf565b9091508190613514565b91909182516001600160401b03811161018d576135528161354c8454611d50565b846134e6565b6020601f8211600114613593578190613584939495600092613588575b50508160011b916000199060031b1c19161790565b9055565b01519050388061356f565b601f198216906135a884600052602060002090565b9160005b8181106135e4575095836001959697106135cb575b505050811b019055565b015160001960f88460031b161c191690553880806135c1565b9192602060018192868b0151815501940192016135ac565b90600160a061031c93602081526001600160401b0384546001600160a01b038116602084015260ff81851c161515604084015260a81c166060820152608080820152019101611d8a565b906001600160401b03613686921660005260096020526701ffffffffffffff60406000209160071c166001600160401b0316600052602052604060002090565b5490565b7f00000000000000000000000000000000000000000000000000000000000000004681036136b55750565b630f01ce8560e01b6000526004524660245260446000fd5b91909180511561376f5782511592602091604051926136ec81856101e3565b60008452601f19810160005b81811061374b5750505060005b8151811015613743578061372c61371e60019385611d3c565b518815613732578690614133565b01613705565b61373c8387611d3c565b5190614133565b505050509050565b8290604051613759816101ad565b60008152606083820152828289010152016136f8565b63c2e5347d60e01b60005260046000fd5b9190811015611d375760051b0190565b3561031c81610983565b9190811015611d375760051b81013590601e198136030182121561026b5701908135916001600160401b03831161026b57602001823603811361026b579190565b909294919397968151966137ee88610243565b976137fc604051998a6101e3565b80895261380b601f1991610243565b0160005b8181106138dd57505060005b83518110156138d057806138628c8a8a8a61385c613855878d61384e828f8f9d8f9e60019f8161387e575b505050611d3c565b519761379a565b36916102ca565b93614978565b61386c828c611d3c565b52613877818b611d3c565b500161381b565b63ffffffff613896613891858585613780565b613790565b1615613846576138c6926138ad9261389192613780565b60406138b98585611d3c565b51019063ffffffff169052565b8f8f908391613846565b5096985050505050505050565b6020906138e861211c565b82828d0101520161380f565b6139056385572ffb60e01b82614cdb565b908161391f575b81613915575090565b61031c9150614cad565b905061392a81614c32565b159061390c565b61390563aff2afbf60e01b82614cdb565b6001600160401b031680600052600860205260406000209060ff825460a01c161561396b575090565b63ed053c5960e01b60005260045260246000fd5b6084019081608411611eb257565b60a001908160a011611eb257565b91908201809211611eb257565b600311156108bc57565b60038210156108bc5752565b906102136040516139ce816101ad565b602060ff829554818116845260081c1691016139b2565b8054821015611d375760005260206000200190600090565b60ff60019116019060ff8211611eb257565b60ff601b9116019060ff8211611eb257565b90606092604091835260208301370190565b6001600052600260205293613a677fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e061260a565b93853594613a748561397f565b6060820190613a838251151590565b613cff575b803603613ce757508151878103613cce5750613aa261368a565b60016000526003602052613af1613aec7fa15bc60c955c405d20d9149c709e2460f1c2d9a497496a7f46004d1772c3054c5b336001600160a01b0316600052602052604060002090565b6139be565b60026020820151613b01816139a8565b613b0a816139a8565b149081613c66575b5015613c3a575b51613b71575b50505050507f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef090613b5561301260019460200190565b604080519283526001600160401b0391909116602083015290a2565b613b9261320c613b8d602085969799989a955194015160ff1690565b6139fd565b03613c29578151835103613c1857613c106000613b559461301294613bdc7f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef09960019b36916102ca565b60208151910120604051613c0781613bf989602083019586613a21565b03601f1981018352826101e3565b5190208a614d0b565b948394613b1f565b63a75d88af60e01b60005260046000fd5b6371253a2560e01b60005260046000fd5b72c11c11c11c11c11c11c11c11c11c11c11c11c1330315613b1957631b41e11d60e31b60005260046000fd5b60016000526002602052613cc69150611a6c90613cb390613cad60037fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e05b01915160ff1690565b906139e5565b90546001600160a01b039160031b1c1690565b331438613b12565b6324f7d61360e21b600052600452602487905260446000fd5b638e1192e160e01b6000526004523660245260446000fd5b613d2890613d22613d18613d138751611e9c565b61398d565b613d228851611e9c565b9061399b565b613a88565b60008052600260205294909390929091613d667fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b61260a565b94863595613d738361397f565b6060820190613d828251151590565b613f37575b803603613ce757508151888103613f1e5750613da161368a565b600080526003602052613dd6613aec7f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92eff613ad4565b60026020820151613de6816139a8565b613def816139a8565b149081613ed5575b5015613ea9575b51613e3b575b5050505050507f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef090613b5561301260009460200190565b613e5761320c613b8d602087989a999b96975194015160ff1690565b03613c29578351865103613c18576000967f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef096613b5595613bdc613ea0946130129736916102ca565b94839438613e04565b72c11c11c11c11c11c11c11c11c11c11c11c11c1330315613dfe57631b41e11d60e31b60005260046000fd5b600080526002602052613f169150611a6c90613cb390613cad60037fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b613ca4565b331438613df7565b6324f7d61360e21b600052600452602488905260446000fd5b613f5590613d22613f4b613d138951611e9c565b613d228a51611e9c565b613d87565b60ff166003029060ff8216918203611eb257565b8151916001600160401b03831161018d5768010000000000000000831161018d576020908254848455808510613fd7575b500190600052602060002060005b838110613fba5750505050565b60019060206001600160a01b038551169401938184015501613fad565b613fee9084600052858460002091820191016134cf565b38613f9f565b95949392909160ff61401993168752602087015260a0604087015260a0860190612643565b84810360608601526020808351928381520192019060005b81811061404c575050509060806102139294019060ff169052565b82516001600160a01b0316845260209384019390920191600101614031565b600654811015611d375760066000527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f015490565b6001600160401b0361031c94938160609416835216602082015281604082015201906105f8565b60409061031c9392815281602082015201906105f8565b9291906001600160401b039081606495166004521660245260048110156108bc57604452565b94939261411d60609361412e93885260208801906108c1565b6080604087015260808601906105f8565b930152565b9061414582516001600160401b031690565b8151604051632cbc26bb60e01b815267ffffffffffffffff60801b608084901b1660048201529015159391906001600160401b038216906020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156124c057600091614861575b5061481f5760208301918251519485156147ef576040850180515187036147de576141e787611ce2565b957f000000000000000000000000000000000000000000000000000000000000000061421d600161421787613942565b01611e0d565b6020815191012060405161427d81613bf96020820194868b876001600160401b036060929594938160808401977f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f85521660208401521660408201520152565b519020906001600160401b031660005b8a81106147465750505080608060606142ad9301519101519088866152d4565b9788156147285760005b8881106142ca5750505050505050505050565b5a6142d6828951611d3c565b518051606001516142f0906001600160401b031688611ec4565b6142f9816108b2565b8015908d8283159384614715575b156146d25760608815614655575061432e6020614324898d611d3c565b5101519242611eb7565b6004546143439060a01c63ffffffff16611ff2565b108015614642575b156146245761435a878b611d3c565b515161460e575b845160800151614379906001600160401b0316610807565b614556575b5061438a868951611d3c565b5160a08501515181510361451a57936143ef9695938c938f966143cf8e958c926143c96143c360608951016001600160401b0390511690565b89615306565b866155c1565b9a9080966143e960608851016001600160401b0390511690565b9061538e565b6144c8575b50506143ff826108b2565b60028203614480575b6001966144767f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b936001600160401b0393519261446761445e8b61445660608801516001600160401b031690565b96519b611d3c565b51985a90611eb7565b91604051958695169885614104565b0390a45b016142b7565b91509193949250614490826108b2565b600382036144a4578b929493918a91614408565b51606001516349362d1f60e11b600052611c8391906001600160401b0316896140de565b6144d1846108b2565b600384036143f45790929495506144e99193506108b2565b6144f9578b92918a9138806143f4565b5151604051632b11b8d960e01b815290819061206c908790600484016140c7565b611c838b61453460608851016001600160401b0390511690565b631cfe6d8b60e01b6000526001600160401b0391821660045216602452604490565b61455f836108b2565b61456a575b3861437e565b8351608001516001600160401b0316602080860151918c61459f60405194859384936370701e5760e11b8552600485016140a0565b038160006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165af19081156124c0576000916145f0575b5061456457505050505060019061447a565b614608915060203d8111612fa157612f9381836101e3565b386145de565b614618878b611d3c565b51516080860152614361565b6354e7e43160e11b6000526001600160401b038b1660045260246000fd5b5061464c836108b2565b6003831461434b565b915083614661846108b2565b15614361575060019594506146ca92506146a891507f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe651209351016001600160401b0390511690565b604080516001600160401b03808c168252909216602083015290918291820190565b0390a161447a565b5050505060019291506146ca6146a860607f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c9351016001600160401b0390511690565b5061471f836108b2565b60038314614307565b633ee8bd3f60e11b6000526001600160401b03841660045260246000fd5b614751818a51611d3c565b518051604001516001600160401b03168381036147c157508051602001516001600160401b031689810361479e57509061478d846001936151cc565b614797828d611d3c565b520161428d565b636c95f1eb60e01b6000526001600160401b03808a166004521660245260446000fd5b631c21951160e11b6000526001600160401b031660045260246000fd5b6357e0e08360e01b60005260046000fd5b611c8361480386516001600160401b031690565b63676cf24b60e11b6000526001600160401b0316600452602490565b5092915050612f5d576040516001600160401b039190911681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d89493390602090a1565b61487a915060203d602011612fa157612f9381836101e3565b386141bd565b9081602091031261026b575161031c8161025a565b9061031c916020815260e061493361491e6148be855161010060208701526101208601906105f8565b60208601516001600160401b0316604086015260408601516001600160a01b0316606086015260608601516080860152614908608087015160a08701906001600160a01b03169052565b60a0860151858203601f190160c08701526105f8565b60c0850151848203601f1901848601526105f8565b92015190610100601f19828503019101526105f8565b6040906001600160a01b0361031c949316815281602082015201906105f8565b9081602091031261026b575190565b9193929361498461211c565b5060208301516001600160a01b031660405163bbe4f6db60e01b81526001600160a01b038216600482015290959092602084806024810103816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa9384156124c057600094614c01575b506001600160a01b0384169586158015614bef575b614bd157614ab6614adf92613bf992614a3a614a33611ff260408c015163ffffffff1690565b8c896156a0565b9690996080810151614a686060835193015193614a55610224565b9687526001600160401b03166020870152565b6001600160a01b038a16604086015260608501526001600160a01b038d16608085015260a084015260c083015260e0820152604051633907753760e01b602082015292839160248301614895565b82857f00000000000000000000000000000000000000000000000000000000000000009261572e565b94909115614bb55750805160208103614b9c575090614b08826020808a95518301019101614969565b956001600160a01b03841603614b40575b5050505050614b38614b29610234565b6001600160a01b039093168352565b602082015290565b614b5393614b4d91611eb7565b916156a0565b50908082108015614b89575b614b6b57808481614b19565b63a966e21f60e01b6000908152600493909352602452604452606490fd5b5082614b958284611eb7565b1415614b5f565b631e3be00960e21b600052602060045260245260446000fd5b61206c604051928392634ff17cad60e11b845260048401614949565b63ae9b4ce960e01b6000526001600160a01b03851660045260246000fd5b50614bfc6124e586613931565b614a0d565b614c2491945060203d602011614c2b575b614c1c81836101e3565b810190614880565b92386149f8565b503d614c12565b60405160208101916301ffc9a760e01b835263ffffffff60e01b602483015260248252614c606044836101e3565b6179185a10614c9c576020926000925191617530fa6000513d82614c90575b5081614c89575090565b9050151590565b60201115915038614c7f565b63753fa58960e11b60005260046000fd5b60405160208101916301ffc9a760e01b83526301ffc9a760e01b602483015260248252614c606044836101e3565b6040519060208201926301ffc9a760e01b845263ffffffff60e01b16602483015260248252614c606044836101e3565b919390926000948051946000965b868810614d2a575050505050505050565b6020881015611d375760206000614d42878b1a613a0f565b614d4c8b87611d3c565b5190614d83614d5b8d8a611d3c565b5160405193849389859094939260ff6060936080840197845216602083015260408201520152565b838052039060015afa156124c057614dc9613aec600051614db18960ff166000526003602052604060002090565b906001600160a01b0316600052602052604060002090565b9060016020830151614dda816139a8565b614de3816139a8565b03614e3057614e00614df6835160ff1690565b60ff600191161b90565b8116614e1f57614e16614df66001935160ff1690565b17970196614d19565b633d9ef1f160e21b60005260046000fd5b636518c33d60e11b60005260046000fd5b91909160005b8351811015614e9a5760019060ff831660005260036020526000614e93604082206001600160a01b03614e7a858a611d3c565b51166001600160a01b0316600052602052604060002090565b5501614e47565b50509050565b8151815460ff191660ff91909116178155906020015160038110156108bc57815461ff00191660089190911b61ff0016179055565b919060005b8151811015614e9a57614ef0611bc58284611d3c565b90614f19614f0f83614db18860ff166000526003602052604060002090565b5460081c60ff1690565b614f22816139a8565b614f8d576001600160a01b03821615614f7c57614f76600192614f71614f46610234565b60ff8516815291614f5a86602085016139b2565b614db18960ff166000526003602052604060002090565b614ea0565b01614eda565b63d6c62c9b60e01b60005260046000fd5b631b3fab5160e11b6000526004805260246000fd5b919060005b8151811015614e9a57614fbd611bc58284611d3c565b90614fdc614f0f83614db18860ff166000526003602052604060002090565b614fe5816139a8565b614f8d576001600160a01b03821615614f7c5761501e600192614f71615009610234565b60ff8516815291614f5a6002602085016139b2565b01614fa7565b60ff1680600052600260205260ff60016040600020015460101c16908015600014615072575015615061576001600160401b0319600b5416600b55565b6317bd8dd160e11b60005260046000fd5b60011461507c5750565b61508257565b6307b8c74d60e51b60005260046000fd5b80600052600760205260406000205415600014615111576006546801000000000000000081101561018d57600181016006556000600654821015611d3757600690527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f01819055600654906000526007602052604060002055600190565b50600090565b9080602083519182815201916020808360051b8301019401926000915b83831061514357505050505090565b9091929394602080600192601f198582030186528851906080806151a6615173855160a0865260a08601906105f8565b6001600160a01b0387870151168786015263ffffffff6040870151166040860152606086015185820360608701526105f8565b93015191015297019301930191939290615134565b90602061031c928181520190615117565b6134c981518051906152606151eb60608601516001600160a01b031690565b613bf961520260608501516001600160401b031690565b9361521b6080808a01519201516001600160401b031690565b90604051958694602086019889936001600160401b036080946001600160a01b0382959998949960a089019a8952166020880152166040860152606085015216910152565b519020613bf96020840151602081519101209360a060408201516020815191012091015160405161529981613bf96020820194856151bb565b51902090604051958694602086019889919260a093969594919660c08401976000855260208501526040840152606083015260808201520152565b926001600160401b03926152e7926157eb565b9116600052600a60205260406000209060005260205260406000205490565b607f8216906801fffffffffffffffe6001600160401b0383169260011b169180830460021490151715611eb25761538b916001600160401b036153498584613646565b921660005260096020526701ffffffffffffff60406000209460071c169160036001831b921b19161792906001600160401b0316600052602052604060002090565b55565b9091607f83166801fffffffffffffffe6001600160401b0382169160011b169080820460021490151715611eb2576153c68484613646565b60048310156108bc576001600160401b0361538b9416600052600960205260036701ffffffffffffff60406000209660071c1693831b921b19161792906001600160401b0316600052602052604060002090565b9080602083519182815201916020808360051b8301019401926000915b83831061544657505050505090565b9091929394602080615464600193601f1986820301875289516105f8565b97019301930191939290615437565b906020808351928381520192019060005b8181106154915750505090565b825163ffffffff16845260209384019390920191600101615484565b916155769061556861031c9593606086526001600160401b0360808251805160608a015282602082015116828a01528260408201511660a08a01528260608201511660c08a015201511660e087015260a061553461551d60208401516101406101008b01526101a08a01906105f8565b6040840151898203605f19016101208b01526105f8565b60608301516001600160a01b03166101408901529160808101516101608901520151868203605f1901610180880152615117565b90848203602086015261541a565b916040818403910152615473565b80516020909101516001600160e01b03198116929190600482106155a6575050565b6001600160e01b031960049290920360031b82901b16169150565b90303b1561026b576000916155ea6040519485938493630304c3e160e51b8552600485016154ad565b038183305af1908161568b575b5061568057615604612227565b9072c11c11c11c11c11c11c11c11c11c11c11c11c13314615626575b60039190565b61563f61563283615584565b6001600160e01b03191690565b6337c3be2960e01b148015615665575b1561562057631d1ccf9f60e01b60005260046000fd5b5061567261563283615584565b632be8ca8b60e21b1461564f565b60029061031c6105c0565b80612581600061569a936101e3565b386155f7565b6040516370a0823160e01b60208201526001600160a01b0390911660248201529192916156fd906156d48160448101613bf9565b84837f00000000000000000000000000000000000000000000000000000000000000009261572e565b92909115614bb55750805160208103614b9c5750906157288260208061031c95518301019101614969565b93611eb7565b93919361573b60846102af565b9461574960405196876101e3565b6084865261575760846102af565b602087019590601f1901368737833b156157da575a908082106157c9578291038060061c900311156157b8576000918291825a9560208451940192f1905a9003923d90608482116157af575b6000908287523e929190565b608491506157a3565b6337c3be2960e01b60005260046000fd5b632be8ca8b60e21b60005260046000fd5b63030ed58f60e21b60005260046000fd5b8051928251908415615947576101018511158061593b575b1561586a5781850194600019860195610100871161586a57861561592b5761582a87611ce2565b9660009586978795885b84811061588f575050505050600119018095149384615885575b50508261587b575b50501561586a5761586691611d3c565b5190565b6309bde33960e01b60005260046000fd5b1490503880615856565b149250388061584e565b6001811b8281160361591d57868a1015615908576158b160018b019a85611d3c565b51905b8c888c10156158f457506158cc60018c019b86611d3c565b515b818d1161586a576158ed828f926158e790600196615958565b92611d3c565b5201615834565b60018d019c61590291611d3c565b516158ce565b61591660018c019b8d611d3c565b51906158b4565b615916600189019884611d3c565b5050505090506158669150611d2a565b50610101821115615803565b630469ac9960e21b60005260046000fd5b8181101561596a579061031c9161596f565b61031c915b906040519060208201926001845260408301526060820152606081526134c96080826101e356fea164736f6c634300081a000a49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b", } var OffRampABI = OffRampMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/onramp/onramp.go b/core/gethwrappers/ccip/generated/onramp/onramp.go index f6f61ebc976..9e00fb7a88b 100644 --- a/core/gethwrappers/ccip/generated/onramp/onramp.go +++ b/core/gethwrappers/ccip/generated/onramp/onramp.go @@ -100,8 +100,8 @@ type OnRampStaticConfig struct { } var OnRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNRemote\",\"name\":\"rmnRemote\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowlistAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"allowlistEnabled\",\"type\":\"bool\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidAllowListRequest\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAllowlistAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyGuardReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"allowlistAdmin\",\"type\":\"address\"}],\"name\":\"AllowListAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPMessageSent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNRemote\",\"name\":\"rmnRemote\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowlistAdmin\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowlistEnabled\",\"type\":\"bool\"}],\"name\":\"DestChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeeTokenWithdrawn\",\"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\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowlistEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"addedAllowlistedSenders\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedAllowlistedSenders\",\"type\":\"address[]\"}],\"internalType\":\"structOnRamp.AllowlistConfigArgs[]\",\"name\":\"allowlistConfigArgsItems\",\"type\":\"tuple[]\"}],\"name\":\"applyAllowlistUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"allowlistEnabled\",\"type\":\"bool\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"}],\"name\":\"forwardFromRouter\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getAllowedSendersList\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"configuredAddresses\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowlistEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowlistAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"contractIERC20\",\"name\":\"sourceToken\",\"type\":\"address\"}],\"name\":\"getPoolBySourceToken\",\"outputs\":[{\"internalType\":\"contractIPoolV1\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNRemote\",\"name\":\"rmnRemote\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"getSupportedTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowlistAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"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\":\"feeTokens\",\"type\":\"address[]\"}],\"name\":\"withdrawFeeTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101006040523480156200001257600080fd5b506040516200409f3803806200409f833981016040819052620000359162000709565b336000816200005757604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008a576200008a816200014f565b505082516001600160401b03161580620000af575060208301516001600160a01b0316155b80620000c6575060408301516001600160a01b0316155b80620000dd575060608301516001600160a01b0316155b15620000fc576040516306b7c75960e31b815260040160405180910390fd5b82516001600160401b031660805260208301516001600160a01b0390811660a0526040840151811660c05260608401511660e0526200013b82620001c9565b620001468162000378565b5050506200080a565b336001600160a01b038216036200017957604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b03161580620001ec575060608101516001600160a01b0316155b80620001f9575080602001515b1562000218576040516306b7c75960e31b815260040160405180910390fd5b8051600280546020808501511515600160a01b026001600160a81b03199092166001600160a01b039485161791909117909155604080840151600380549185166001600160a01b0319928316179055606080860151600480549187169184169190911790556080808701516005805491881691909416179092558251808301845291516001600160401b0316825260a05185169382019390935260c05184168183015260e05190931691830191909152517fc7372d2d886367d7bb1b0e0708a5436f2c91d6963de210eb2dc1ec2ecd6d21f1916200036d91849082516001600160401b031681526020808401516001600160a01b03908116828401526040858101518216818501526060958601518216868501528451821660808086019190915292850151151560a0850152840151811660c084015293830151841660e0830152909101519091166101008201526101200190565b60405180910390a150565b60005b8151811015620004cb5760008282815181106200039c576200039c620007f4565b602002602001015190506000838381518110620003bd57620003bd620007f4565b6020026020010151600001519050806001600160401b0316600003620004055760405163c35aa79d60e01b81526001600160401b038216600482015260240160405180910390fd5b6001600160401b0381811660008181526006602090815260409182902086820151815488850151600160401b600160e81b031990911669010000000000000000006001600160a01b0390931692830260ff60401b19161768010000000000000000911515820217808455855197811688529387019190915260ff920491909116151591840191909152917fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a25050508060010190506200037b565b5050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b03811182821017156200050a576200050a620004cf565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200053b576200053b620004cf565b604052919050565b80516001600160401b03811681146200055b57600080fd5b919050565b6001600160a01b03811681146200057657600080fd5b50565b805180151581146200055b57600080fd5b600060a082840312156200059d57600080fd5b60405160a081016001600160401b0381118282101715620005c257620005c2620004cf565b80604052508091508251620005d78162000560565b8152620005e76020840162000579565b60208201526040830151620005fc8162000560565b60408201526060830151620006118162000560565b60608201526080830151620006268162000560565b6080919091015292915050565b600082601f8301126200064557600080fd5b815160206001600160401b03821115620006635762000663620004cf565b62000673818360051b0162000510565b828152606092830285018201928282019190878511156200069357600080fd5b8387015b85811015620006fc5781818a031215620006b15760008081fd5b620006bb620004e5565b620006c68262000543565b815285820151620006d78162000560565b818701526040620006ea83820162000579565b90820152845292840192810162000697565b5090979650505050505050565b60008060008385036101408112156200072157600080fd5b60808112156200073057600080fd5b50604051608081016001600160401b038082118383101715620007575762000757620004cf565b81604052620007668762000543565b8352602087015191506200077a8262000560565b81602084015260408701519150620007928262000560565b81604084015260608701519150620007aa8262000560565b816060840152829550620007c288608089016200058a565b9450610120870151925080831115620007da57600080fd5b5050620007ea8682870162000633565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e05161381c62000883600039600081816101fc015281816107670152611ac40152600081816101c0015281816114b90152611a9d015260008181610184015281816105a50152611a7301526000818161015401528181611040015281816115d60152611a4f015261381c6000f3fe608060405234801561001057600080fd5b506004361061011b5760003560e01c80637437ff9f116100b2578063972b461211610081578063df0aa9e911610066578063df0aa9e9146104fb578063f2fde38b1461050e578063fbca3b741461052157600080fd5b8063972b4612146104c7578063c9b146b3146104e857600080fd5b80637437ff9f146103cb57806379ba5097146104755780638da5cb5b1461047d5780639041be3d1461049b57600080fd5b806327e936f1116100ee57806327e936f1146102ce57806348a98aa4146102e15780635cb80c5d146103195780636def4ce71461032c57600080fd5b806306285c6914610120578063181f5a771461024f57806320487ded146102985780632716072b146102b9575b600080fd5b61023960408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b6040516102469190612589565b60405180910390f35b61028b6040518060400160405280601081526020017f4f6e52616d7020312e362e302d6465760000000000000000000000000000000081525081565b604051610246919061264e565b6102ab6102a636600461268f565b610541565b604051908152602001610246565b6102cc6102c73660046127fd565b6106fa565b005b6102cc6102dc3660046128eb565b61070e565b6102f46102ef366004612983565b61071f565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610246565b6102cc610327366004612a08565b6107d4565b61038f61033a366004612a4a565b67ffffffffffffffff9081166000908152600660205260409020549081169168010000000000000000820460ff16916901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6040805167ffffffffffffffff9094168452911515602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610246565b6104686040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a08101825260025473ffffffffffffffffffffffffffffffffffffffff80821683527401000000000000000000000000000000000000000090910460ff161515602083015260035481169282019290925260045482166060820152600554909116608082015290565b6040516102469190612a67565b6102cc610956565b60015473ffffffffffffffffffffffffffffffffffffffff166102f4565b6104ae6104a9366004612a4a565b610a24565b60405167ffffffffffffffff9091168152602001610246565b6104da6104d5366004612a4a565b610a4d565b604051610246929190612b12565b6102cc6104f6366004612a08565b610a91565b6102ab610509366004612b2d565b610dad565b6102cc61051c366004612b99565b6116bb565b61053461052f366004612a4a565b6116cc565b6040516102469190612bb6565b6040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608084901b16600482015260009073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa1580156105ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106109190612bc9565b15610658576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6002546040517fd8694ccd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063d8694ccd906106b09086908690600401612ce8565b602060405180830381865afa1580156106cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f19190612e31565b90505b92915050565b610702611700565b61070b81611753565b50565b610716611700565b61070b816118f6565b6040517fbbe4f6db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa1580156107b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f19190612e4a565b60045473ffffffffffffffffffffffffffffffffffffffff1660005b8281101561095057600084848381811061080c5761080c612e67565b90506020020160208101906108219190612b99565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610891573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b59190612e31565b90508015610946576108de73ffffffffffffffffffffffffffffffffffffffff83168583611b26565b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e8360405161093d91815260200190565b60405180910390a35b50506001016107f0565b50505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146109a7576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff80821660009081526006602052604081205490916106f491166001612ec5565b67ffffffffffffffff8116600090815260066020526040812080546060916801000000000000000090910460ff1690610a8890600101611bb3565b91509150915091565b60015473ffffffffffffffffffffffffffffffffffffffff163314610b015760055473ffffffffffffffffffffffffffffffffffffffff163314610b01576040517f905d7d9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610da8576000838383818110610b2057610b20612e67565b9050602002810190610b329190612ee6565b610b3b90612f97565b805167ffffffffffffffff1660009081526006602090815260409182902090830151815490151568010000000000000000027fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff90911617815590820151519192509015610cfb57816020015115610cba5760005b826040015151811015610c6a57600083604001518281518110610bd457610bd4612e67565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610c535783516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161064f565b610c606001840182611bc7565b5050600101610baf565b50816000015167ffffffffffffffff167f330939f6eafe8bb516716892fe962ff19770570838686e6579dbc1cc51fc32818360400151604051610cad9190612bb6565b60405180910390a2610cfb565b81516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161064f565b60005b826060015151811015610d4757610d3e83606001518281518110610d2457610d24612e67565b602002602001015183600101611be990919063ffffffff16565b50600101610cfe565b5060608201515115610d9e57816000015167ffffffffffffffff167fc237ec1921f855ccd5e9a5af9733f2d58943a5a8501ec5988e305d7a4d4215868360600151604051610d959190612bb6565b60405180910390a25b5050600101610b04565b505050565b60025460009074010000000000000000000000000000000000000000900460ff1615610e05576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905567ffffffffffffffff8516600090815260066020526040902073ffffffffffffffffffffffffffffffffffffffff8316610eaa576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805468010000000000000000900460ff1615610f1b57610ecd6001820184611c0b565b610f1b576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260240161064f565b80546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314610f78576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035473ffffffffffffffffffffffffffffffffffffffff16801561101e576040517fe0a0e50600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e0a0e50690610feb908a908a90600401612ce8565b600060405180830381600087803b15801561100557600080fd5b505af1158015611019573d6000803e3d6000fd5b505050505b50604080516101c081019091526000610120820181815267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811661014085015289811661016085015284549293928392916101808401918791879161108c9116613048565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff168152602001600067ffffffffffffffff1681525081526020018573ffffffffffffffffffffffffffffffffffffffff168152602001878060200190611100919061306f565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250602001611144888061306f565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250938552505060408051602081810183529381529284019290925250016111a06080890160608a01612b99565b73ffffffffffffffffffffffffffffffffffffffff168152602001868152602001600081526020018780604001906111d891906130d4565b905067ffffffffffffffff8111156111f2576111f26126df565b60405190808252806020026020018201604052801561126b57816020015b6112586040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001606081526020016060815260200160008152602001606081525090565b8152602001906001900390816112105790505b5090529050600061127f60408801886130d4565b808060200260200160405190810160405280939291908181526020016000905b828210156112cb576112bc6040830286013681900381019061313c565b8152602001906001019061129f565b5050505050905060005b6112e260408901896130d4565b905081101561137c5761135282828151811061130057611300612e67565b60209081029190910101518a6113168b8061306f565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508c9250611c3a915050565b836101000151828151811061136957611369612e67565b60209081029190910101526001016112d5565b50600254600090606090819073ffffffffffffffffffffffffffffffffffffffff1663430d138c8c6113b360808e018e8601612b99565b8c8e80608001906113c4919061306f565b8b61010001518b6040518863ffffffff1660e01b81526004016113ed9796959493929190613259565b600060405180830381865afa15801561140a573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611450919081019061338b565b60e0890193909352909450925090508261152b576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8c16600482015273ffffffffffffffffffffffffffffffffffffffff89811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af1158015611502573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611526919061347e565b61152e565b60005b855167ffffffffffffffff909116608091820152850182905260005b856101000151518110156115a05781818151811061156a5761156a612e67565b6020026020010151866101000151828151811061158957611589612e67565b60209081029190910101516080015260010161154a565b50604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908c16606082015230608082015261163090869060a00160405160208183030381529060405280519060200120611f51565b85515284516060015160405167ffffffffffffffff918216918d16907f192442a2b2adb6a7948f097023cb6b57d29d3a7a5dd33e6666d33c39cc456f329061167990899061349b565b60405180910390a35050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055505051519150505b949350505050565b6116c3611700565b61070b816120a3565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60015473ffffffffffffffffffffffffffffffffffffffff163314611751576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b60005b81518110156118f257600082828151811061177357611773612e67565b60200260200101519050600083838151811061179157611791612e67565b60200260200101516000015190508067ffffffffffffffff166000036117ef576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161064f565b67ffffffffffffffff818116600081815260066020908152604091829020868201518154888501517fffffff000000000000000000000000000000000000000000ffffffffffffffff909116690100000000000000000073ffffffffffffffffffffffffffffffffffffffff9093169283027fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff161768010000000000000000911515820217808455855197811688529387019190915260ff920491909116151591840191909152917fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a2505050806001019050611756565b5050565b805173ffffffffffffffffffffffffffffffffffffffff1615806119325750606081015173ffffffffffffffffffffffffffffffffffffffff16155b8061193e575080602001515b15611975576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160028054602080850151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00000000000000000000000000000000000000000090921673ffffffffffffffffffffffffffffffffffffffff9485161791909117909155604080840151600380549185167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179055606080860151600480549187169184169190911790556080808701516005805491881691909416179092558251918201835267ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001682527f00000000000000000000000000000000000000000000000000000000000000008516938201939093527f00000000000000000000000000000000000000000000000000000000000000008416818301527f000000000000000000000000000000000000000000000000000000000000000090931691830191909152517fc7372d2d886367d7bb1b0e0708a5436f2c91d6963de210eb2dc1ec2ecd6d21f191611b1b9184906135f3565b60405180910390a150565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610da8908490612167565b60606000611bc083612273565b9392505050565b60006106f18373ffffffffffffffffffffffffffffffffffffffff84166122cf565b60006106f18373ffffffffffffffffffffffffffffffffffffffff841661231e565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260018301602052604081205415156106f1565b611c826040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001606081526020016060815260200160008152602001606081525090565b8460200151600003611cc0576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611cd085876000015161071f565b905073ffffffffffffffffffffffffffffffffffffffff81161580611da057506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015611d7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d9e9190612bc9565b155b15611df25785516040517fbf16aab600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161064f565b60008173ffffffffffffffffffffffffffffffffffffffff16639a4575b96040518060a001604052808881526020018967ffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018a6020015181526020018a6000015173ffffffffffffffffffffffffffffffffffffffff168152506040518263ffffffff1660e01b8152600401611e9191906136a1565b6000604051808303816000875af1158015611eb0573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611ef69190810190613717565b6040805160a08101825273ffffffffffffffffffffffffffffffffffffffff90941684528151602080860191909152918201518482015288820151606085015280519182019052600081526080830152509050949350505050565b60008060001b8284602001518560000151606001518660000151608001518760a001518860c00151604051602001611fcf95949392919073ffffffffffffffffffffffffffffffffffffffff958616815267ffffffffffffffff94851660208201529290931660408301529092166060830152608082015260a00190565b6040516020818303038152906040528051906020012085606001518051906020012086604001518051906020012087610100015160405160200161201391906137a8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206080808d0151805190840120928501999099529183019690965260608201949094529485019190915260a084015260c083015260e08201526101000160405160208183030381529060405280519060200120905092915050565b3373ffffffffffffffffffffffffffffffffffffffff8216036120f2576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60006121c9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166124189092919063ffffffff16565b805190915015610da857808060200190518101906121e79190612bc9565b610da8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161064f565b6060816000018054806020026020016040519081016040528092919081815260200182805480156122c357602002820191906000526020600020905b8154815260200190600101908083116122af575b50505050509050919050565b6000818152600183016020526040812054612316575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556106f4565b5060006106f4565b600081815260018301602052604081205480156124075760006123426001836137bb565b8554909150600090612356906001906137bb565b90508082146123bb57600086600001828154811061237657612376612e67565b906000526020600020015490508087600001848154811061239957612399612e67565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806123cc576123cc6137ce565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506106f4565b60009150506106f4565b5092915050565b60606116b38484600085856000808673ffffffffffffffffffffffffffffffffffffffff16858760405161244c91906137fd565b60006040518083038185875af1925050503d8060008114612489576040519150601f19603f3d011682016040523d82523d6000602084013e61248e565b606091505b509150915061249f878383876124aa565b979650505050505050565b606083156125405782516000036125395773ffffffffffffffffffffffffffffffffffffffff85163b612539576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161064f565b50816116b3565b6116b383838151156125555781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161064f919061264e565b608081016106f4828467ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b60005b838110156125fb5781810151838201526020016125e3565b50506000910152565b6000815180845261261c8160208601602086016125e0565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006106f16020830184612604565b67ffffffffffffffff8116811461070b57600080fd5b600060a0828403121561268957600080fd5b50919050565b600080604083850312156126a257600080fd5b82356126ad81612661565b9150602083013567ffffffffffffffff8111156126c957600080fd5b6126d585828601612677565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516060810167ffffffffffffffff81118282101715612731576127316126df565b60405290565b6040805190810167ffffffffffffffff81118282101715612731576127316126df565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156127a1576127a16126df565b604052919050565b600067ffffffffffffffff8211156127c3576127c36126df565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff8116811461070b57600080fd5b801515811461070b57600080fd5b6000602080838503121561281057600080fd5b823567ffffffffffffffff81111561282757600080fd5b8301601f8101851361283857600080fd5b803561284b612846826127a9565b61275a565b8181526060918202830184019184820191908884111561286a57600080fd5b938501935b838510156128cf5780858a0312156128875760008081fd5b61288f61270e565b853561289a81612661565b8152858701356128a9816127cd565b818801526040868101356128bc816127ef565b908201528352938401939185019161286f565b50979650505050505050565b80356128e6816127cd565b919050565b600060a082840312156128fd57600080fd5b60405160a0810181811067ffffffffffffffff82111715612920576129206126df565b604052823561292e816127cd565b8152602083013561293e816127ef565b60208201526040830135612951816127cd565b60408201526060830135612964816127cd565b60608201526080830135612977816127cd565b60808201529392505050565b6000806040838503121561299657600080fd5b82356129a181612661565b915060208301356129b1816127cd565b809150509250929050565b60008083601f8401126129ce57600080fd5b50813567ffffffffffffffff8111156129e657600080fd5b6020830191508360208260051b8501011115612a0157600080fd5b9250929050565b60008060208385031215612a1b57600080fd5b823567ffffffffffffffff811115612a3257600080fd5b612a3e858286016129bc565b90969095509350505050565b600060208284031215612a5c57600080fd5b8135611bc081612661565b60a081016106f4828473ffffffffffffffffffffffffffffffffffffffff808251168352602082015115156020840152806040830151166040840152806060830151166060840152806080830151166080840152505050565b60008151808452602080850194506020840160005b83811015612b0757815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101612ad5565b509495945050505050565b82151581526040602082015260006116b36040830184612ac0565b60008060008060808587031215612b4357600080fd5b8435612b4e81612661565b9350602085013567ffffffffffffffff811115612b6a57600080fd5b612b7687828801612677565b935050604085013591506060850135612b8e816127cd565b939692955090935050565b600060208284031215612bab57600080fd5b8135611bc0816127cd565b6020815260006106f16020830184612ac0565b600060208284031215612bdb57600080fd5b8151611bc0816127ef565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612c1b57600080fd5b830160208101925035905067ffffffffffffffff811115612c3b57600080fd5b803603821315612a0157600080fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8183526000602080850194508260005b85811015612b07578135612cb6816127cd565b73ffffffffffffffffffffffffffffffffffffffff168752818301358388015260409687019690910190600101612ca3565b600067ffffffffffffffff808516835260406020840152612d098485612be6565b60a06040860152612d1e60e086018284612c4a565b915050612d2e6020860186612be6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc080878503016060880152612d64848385612c4a565b9350604088013592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1883603018312612d9d57600080fd5b60209288019283019235915084821115612db657600080fd5b8160061b3603831315612dc857600080fd5b80878503016080880152612ddd848385612c93565b9450612deb606089016128db565b73ffffffffffffffffffffffffffffffffffffffff811660a08901529350612e166080890189612be6565b94509250808786030160c0880152505061249f838383612c4a565b600060208284031215612e4357600080fd5b5051919050565b600060208284031215612e5c57600080fd5b8151611bc0816127cd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff81811683821601908082111561241157612411612e96565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112612f1a57600080fd5b9190910192915050565b600082601f830112612f3557600080fd5b81356020612f45612846836127a9565b8083825260208201915060208460051b870101935086841115612f6757600080fd5b602086015b84811015612f8c578035612f7f816127cd565b8352918301918301612f6c565b509695505050505050565b600060808236031215612fa957600080fd5b6040516080810167ffffffffffffffff8282108183111715612fcd57612fcd6126df565b8160405284359150612fde82612661565b908252602084013590612ff0826127ef565b816020840152604085013591508082111561300a57600080fd5b61301636838701612f24565b6040840152606085013591508082111561302f57600080fd5b5061303c36828601612f24565b60608301525092915050565b600067ffffffffffffffff80831681810361306557613065612e96565b6001019392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126130a457600080fd5b83018035915067ffffffffffffffff8211156130bf57600080fd5b602001915036819003821315612a0157600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261310957600080fd5b83018035915067ffffffffffffffff82111561312457600080fd5b6020019150600681901b3603821315612a0157600080fd5b60006040828403121561314e57600080fd5b613156612737565b8235613161816127cd565b81526020928301359281019290925250919050565b600082825180855260208086019550808260051b84010181860160005b8481101561324c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a073ffffffffffffffffffffffffffffffffffffffff82511685528582015181878701526131f582870182612604565b9150506040808301518683038288015261320f8382612604565b925050506060808301518187015250608080830151925085820381870152506132388183612604565b9a86019a9450505090830190600101613193565b5090979650505050505050565b67ffffffffffffffff881681526000602073ffffffffffffffffffffffffffffffffffffffff808a1682850152604089604086015260c060608601526132a360c08601898b612c4a565b85810360808701526132b58189613176565b86810360a0880152875180825285890192509085019060005b818110156132f55783518051871684528701518784015292860192918401916001016132ce565b50909e9d5050505050505050505050505050565b600082601f83011261331a57600080fd5b815167ffffffffffffffff811115613334576133346126df565b61336560207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161275a565b81815284602083860101111561337a57600080fd5b6116b38260208301602087016125e0565b600080600080608085870312156133a157600080fd5b845193506020808601516133b4816127ef565b604087015190945067ffffffffffffffff808211156133d257600080fd5b6133de89838a01613309565b945060608801519150808211156133f457600080fd5b818801915088601f83011261340857600080fd5b8151613416612846826127a9565b81815260059190911b8301840190848101908b83111561343557600080fd5b8585015b8381101561346d578051858111156134515760008081fd5b61345f8e89838a0101613309565b845250918601918601613439565b50989b979a50959850505050505050565b60006020828403121561349057600080fd5b8151611bc081612661565b602081526134ec60208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b6000602083015161351560c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408301516101a08060e08501526135326101c0850183612604565b915060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06101008187860301818801526135708584612604565b945060808801519250818786030161012088015261358e8584612604565b945060a088015192506135ba61014088018473ffffffffffffffffffffffffffffffffffffffff169052565b60c088015161016088015260e08801516101808801528701518685039091018387015290506135e98382613176565b9695505050505050565b610120810161364b828567ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b825173ffffffffffffffffffffffffffffffffffffffff9081166080848101919091526020850151151560a08501526040850151821660c08501526060850151821660e085015284015116610100830152611bc0565b602081526000825160a060208401526136bd60c0840182612604565b905067ffffffffffffffff6020850151166040840152604084015173ffffffffffffffffffffffffffffffffffffffff8082166060860152606086015160808601528060808701511660a086015250508091505092915050565b60006020828403121561372957600080fd5b815167ffffffffffffffff8082111561374157600080fd5b908301906040828603121561375557600080fd5b61375d612737565b82518281111561376c57600080fd5b61377887828601613309565b82525060208301518281111561378d57600080fd5b61379987828601613309565b60208301525095945050505050565b6020815260006106f16020830184613176565b818103818111156106f4576106f4612e96565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612f1a8184602087016125e056fea164736f6c6343000818000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"staticConfig\",\"type\":\"tuple\",\"internalType\":\"structOnRamp.StaticConfig\",\"components\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"rmnRemote\",\"type\":\"address\",\"internalType\":\"contractIRMNRemote\"},{\"name\":\"nonceManager\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenAdminRegistry\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"name\":\"dynamicConfig\",\"type\":\"tuple\",\"internalType\":\"structOnRamp.DynamicConfig\",\"components\":[{\"name\":\"feeQuoter\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"messageInterceptor\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"feeAggregator\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"allowlistAdmin\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\",\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"components\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"router\",\"type\":\"address\",\"internalType\":\"contractIRouter\"},{\"name\":\"allowlistEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"}]}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"acceptOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyAllowlistUpdates\",\"inputs\":[{\"name\":\"allowlistConfigArgsItems\",\"type\":\"tuple[]\",\"internalType\":\"structOnRamp.AllowlistConfigArgs[]\",\"components\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"allowlistEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"addedAllowlistedSenders\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"removedAllowlistedSenders\",\"type\":\"address[]\",\"internalType\":\"address[]\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyDestChainConfigUpdates\",\"inputs\":[{\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\",\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"components\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"router\",\"type\":\"address\",\"internalType\":\"contractIRouter\"},{\"name\":\"allowlistEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"forwardFromRouter\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"message\",\"type\":\"tuple\",\"internalType\":\"structClient.EVM2AnyMessage\",\"components\":[{\"name\":\"receiver\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"tokenAmounts\",\"type\":\"tuple[]\",\"internalType\":\"structClient.EVMTokenAmount[]\",\"components\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"feeToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"extraArgs\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"feeTokenAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"originalSender\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getAllowedSendersList\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"configuredAddresses\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getDestChainConfig\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"sequenceNumber\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"allowlistEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"router\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getDynamicConfig\",\"inputs\":[],\"outputs\":[{\"name\":\"dynamicConfig\",\"type\":\"tuple\",\"internalType\":\"structOnRamp.DynamicConfig\",\"components\":[{\"name\":\"feeQuoter\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"messageInterceptor\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"feeAggregator\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"allowlistAdmin\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getExpectedNextSequenceNumber\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getFee\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"message\",\"type\":\"tuple\",\"internalType\":\"structClient.EVM2AnyMessage\",\"components\":[{\"name\":\"receiver\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"tokenAmounts\",\"type\":\"tuple[]\",\"internalType\":\"structClient.EVMTokenAmount[]\",\"components\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"feeToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"extraArgs\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"feeTokenAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getPoolBySourceToken\",\"inputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sourceToken\",\"type\":\"address\",\"internalType\":\"contractIERC20\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIPoolV1\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getStaticConfig\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structOnRamp.StaticConfig\",\"components\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"rmnRemote\",\"type\":\"address\",\"internalType\":\"contractIRMNRemote\"},{\"name\":\"nonceManager\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenAdminRegistry\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getSupportedTokens\",\"inputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"setDynamicConfig\",\"inputs\":[{\"name\":\"dynamicConfig\",\"type\":\"tuple\",\"internalType\":\"structOnRamp.DynamicConfig\",\"components\":[{\"name\":\"feeQuoter\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"messageInterceptor\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"feeAggregator\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"allowlistAdmin\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"typeAndVersion\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"withdrawFeeTokens\",\"inputs\":[{\"name\":\"feeTokens\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"AllowListAdminSet\",\"inputs\":[{\"name\":\"allowlistAdmin\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"AllowListSendersAdded\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"senders\",\"type\":\"address[]\",\"indexed\":false,\"internalType\":\"address[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"AllowListSendersRemoved\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"senders\",\"type\":\"address[]\",\"indexed\":false,\"internalType\":\"address[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"CCIPMessageSent\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"sequenceNumber\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"message\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"components\":[{\"name\":\"header\",\"type\":\"tuple\",\"internalType\":\"structInternal.RampMessageHeader\",\"components\":[{\"name\":\"messageId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sequenceNumber\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"receiver\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"extraArgs\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"feeToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"feeTokenAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"feeValueJuels\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"tokenAmounts\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"components\":[{\"name\":\"sourcePoolAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"destTokenAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"extraData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"destExecData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ConfigSet\",\"inputs\":[{\"name\":\"staticConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structOnRamp.StaticConfig\",\"components\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"rmnRemote\",\"type\":\"address\",\"internalType\":\"contractIRMNRemote\"},{\"name\":\"nonceManager\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenAdminRegistry\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"name\":\"dynamicConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structOnRamp.DynamicConfig\",\"components\":[{\"name\":\"feeQuoter\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"messageInterceptor\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"feeAggregator\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"allowlistAdmin\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DestChainConfigSet\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"sequenceNumber\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"router\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"contractIRouter\"},{\"name\":\"allowlistEnabled\",\"type\":\"bool\",\"indexed\":false,\"internalType\":\"bool\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"FeeTokenWithdrawn\",\"inputs\":[{\"name\":\"feeAggregator\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"feeToken\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferRequested\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"CannotSendZeroTokens\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CannotTransferToSelf\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CursedByRMN\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidAllowListRequest\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"InvalidConfig\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidDestChainConfig\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"MustBeCalledByRouter\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MustBeProposedOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OnlyCallableByOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OnlyCallableByOwnerOrAllowlistAdmin\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OwnerCannotBeZero\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ReentrancyGuardReentrantCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"RouterMustSetOriginalSender\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"SenderNotAllowed\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"UnsupportedToken\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]}]", + Bin: "0x6101006040523461055f57613c018038038061001a81610599565b92833981019080820390610140821261055f576080821261055f5761003d61057a565b90610047816105be565b82526020810151906001600160a01b038216820361055f5760208301918252610072604082016105d2565b926040810193845260a0610088606084016105d2565b6060830190815295607f19011261055f5760405160a081016001600160401b03811182821017610564576040526100c1608084016105d2565b81526100cf60a084016105e6565b602082019081526100e260c085016105d2565b91604081019283526100f660e086016105d2565b936060820194855261010b61010087016105d2565b6080830190815261012087015190966001600160401b03821161055f57018a601f8201121561055f578051906001600160401b0382116105645760209b8c6060610159828660051b01610599565b9e8f8681520194028301019181831161055f57602001925b8284106104f1575050505033156104e057600180546001600160a01b0319163317905580516001600160401b03161580156104ce575b80156104bc575b80156104aa575b61047d57516001600160401b0316608081905295516001600160a01b0390811660a08190529751811660c08190529851811660e08190528251909116158015610498575b801561048e575b61047d57815160028054855160ff60a01b90151560a01b166001600160a01b039384166001600160a81b0319909216919091171790558451600380549183166001600160a01b03199283161790558651600480549184169183169190911790558751600580549190931691161790557fc7372d2d886367d7bb1b0e0708a5436f2c91d6963de210eb2dc1ec2ecd6d21f19861012098606061029f61057a565b8a8152602080820193845260408083019586529290910194855281519a8b5291516001600160a01b03908116928b019290925291518116918901919091529051811660608801529051811660808701529051151560a08601529051811660c08501529051811660e0840152905116610100820152a16000905b805182101561040b5761032b82826105f3565b51916001600160401b0361033f82846105f3565b5151169283156103f65760008481526006602090815260409182902081840151815494840151600160401b600160e81b03198616604883901b600160481b600160e81b031617901515851b68ff000000000000000016179182905583516001600160401b0390951685526001600160a01b031691840191909152811c60ff1615159082015291926001927fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef590606090a20190610318565b8363c35aa79d60e01b60005260045260246000fd5b6040516135e3908161061e82396080518181816103e301528181610b39015281816120c8015261286b015260a0518181816121010152818161261e01526128a4015260c051818181610efc0152818161213d01526128e0015260e0518181816121790152818161291c0152612edd0152f35b6306b7c75960e31b60005260046000fd5b5082511515610200565b5084516001600160a01b0316156101f9565b5088516001600160a01b0316156101b5565b5087516001600160a01b0316156101ae565b5086516001600160a01b0316156101a7565b639b15e16f60e01b60005260046000fd5b60608483031261055f5760405190606082016001600160401b0381118382101761056457604052610521856105be565b82526020850151906001600160a01b038216820361055f578260209283606095015261054f604088016105e6565b6040820152815201930192610171565b600080fd5b634e487b7160e01b600052604160045260246000fd5b60405190608082016001600160401b0381118382101761056457604052565b6040519190601f01601f191682016001600160401b0381118382101761056457604052565b51906001600160401b038216820361055f57565b51906001600160a01b038216820361055f57565b5190811515820361055f57565b80518210156106075760209160051b010190565b634e487b7160e01b600052603260045260246000fdfe608080604052600436101561001357600080fd5b600090813560e01c90816306285c691461280557508063181f5a771461278657806320487ded146125425780632716072b1461229257806327e936f114611e8c57806348a98aa414611e095780635cb80c5d14611b215780636def4ce714611a925780637437ff9f1461195957806379ba5097146118745780638da5cb5b146118225780639041be3d14611775578063972b4612146116a7578063c9b146b3146112da578063df0aa9e91461022c578063f2fde38b1461013f5763fbca3b74146100dc57600080fd5b3461013c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c57600490610116612af4565b507f9e7177c8000000000000000000000000000000000000000000000000000000008152fd5b80fd5b503461013c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c5773ffffffffffffffffffffffffffffffffffffffff61018c612b4a565b610194613280565b1633811461020457807fffffffffffffffffffffffff000000000000000000000000000000000000000083541617825573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12788380a380f35b6004827fdad89dca000000000000000000000000000000000000000000000000000000008152fd5b503461013c5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c57610264612af4565b67ffffffffffffffff602435116112d65760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc602435360301126112d6576102ab612b6d565b60025460ff8160a01c166112ae577fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001760025567ffffffffffffffff8216835260066020526040832073ffffffffffffffffffffffffffffffffffffffff82161561128657805460ff8160401c16611218575b60481c73ffffffffffffffffffffffffffffffffffffffff1633036111f05773ffffffffffffffffffffffffffffffffffffffff6003541680611183575b50805467ffffffffffffffff811667ffffffffffffffff8114611156579067ffffffffffffffff60017fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009493011692839116179055604051906103d5826129db565b84825267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016602083015267ffffffffffffffff8416604083015260608201528360808201526104366024803501602435600401613060565b61044560046024350180613060565b610453606460243501612f97565b936104686044602435016024356004016130b1565b9490507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06104ae61049887612b25565b966104a66040519889612a13565b808852612b25565b018a5b81811061113f575050604051968761012081011067ffffffffffffffff6101208a011117611112576101208801604052875273ffffffffffffffffffffffffffffffffffffffff8816602088015261051c939291610510913691613131565b60408701523691613131565b606084015273ffffffffffffffffffffffffffffffffffffffff6020926040516105468582612a13565b88815260808601521660a084015260443560c08401528560e084015261010083015261057c6044602435016024356004016130b1565b61058881969296612b25565b906105966040519283612a13565b8082528382018097368360061b8201116110895780915b8360061b820183106110d75750505050865b6105d36044602435016024356004016130b1565b9050811015610959576105e6818361301d565b516106006105f960046024350180613060565b3691613131565b90610609613105565b5085810151156109315773ffffffffffffffffffffffffffffffffffffffff61063481835116612e7e565b169182158015610887575b61084457908a6106ee949392888873ffffffffffffffffffffffffffffffffffffffff8d838701518280895116926040519761067a896129db565b885267ffffffffffffffff87890196168652816040890191168152606088019283526080880193845267ffffffffffffffff6040519d8e998a997f9a4575b9000000000000000000000000000000000000000000000000000000008b5260048b01525160a060248b015260c48a0190612ab1565b965116604488015251166064860152516084850152511660a4830152038183865af1938415610839578b94610783575b5061077c918484928980600198519301519101519160405193610740856129db565b84528a8401526040830152606082015260405161075d8982612a13565b8c8152608082015261010089015190610776838361301d565b5261301d565b50016105bf565b93503d91828c863e6107958386612a13565b878584810103126108355784519167ffffffffffffffff83116108315760408387018588010312610831576040516107cc816129f7565b8387015167ffffffffffffffff811161082d576107f09086890190868a0101613168565b81528984880101519467ffffffffffffffff861161082d578761077c96889661081f9360019b01920101613168565b8a820152955091509161071e565b8e80fd5b8c80fd5b8b80fd5b6040513d8d823e3d90fd5b60248b73ffffffffffffffffffffffffffffffffffffffff8451167fbf16aab6000000000000000000000000000000000000000000000000000000008252600452fd5b506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf0000000000000000000000000000000000000000000000000000000060048201528781602481875afa908115610926578c916108f1575b501561063f565b90508781813d831161091f575b6109088183612a13565b810103126108355761091990612c2c565b386108ea565b503d6108fe565b6040513d8e823e3d90fd5b60048a7f5cf04449000000000000000000000000000000000000000000000000000000008152fd5b50867f430d138c00000000000000000000000000000000000000000000000000000000839282979873ffffffffffffffffffffffffffffffffffffffff600254169187610a496109ad606460243501612f97565b610a198c61010073ffffffffffffffffffffffffffffffffffffffff6109dd608460243501602435600401613060565b92909301519467ffffffffffffffff6040519e8f9d8e521660048d01521660248b015260443560448b015260c060648b015260c48a0191612c89565b907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8883030160848901526131aa565b917ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8684030160a48701525191828152019190855b8982821061109c575050505082809103915afa9586156110915785869087938899610f7f575b5060e087015215610e8d5750845b67ffffffffffffffff6080865101911690526080840152835b61010084015151811015610b015780610ae66001928861301d565b516080610af88361010089015161301d565b51015201610acb565b509092604051848101907f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321825267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016604082015267ffffffffffffffff8416606082015230608082015260808152610b8360a082612a13565b51902073ffffffffffffffffffffffffffffffffffffffff602085015116845167ffffffffffffffff6080816060840151169201511673ffffffffffffffffffffffffffffffffffffffff60a08801511660c088015191604051938a850195865260408501526060840152608083015260a082015260a08152610c0760c082612a13565b51902060608501518681519101206040860151878151910120610100870151604051610c6d81610c418c8201948d865260408301906131aa565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282612a13565b51902091608088015189815191012093604051958a870197885260408701526060860152608085015260a084015260c083015260e082015260e08152610cb561010082612a13565b51902082515267ffffffffffffffff60608351015116907f192442a2b2adb6a7948f097023cb6b57d29d3a7a5dd33e6666d33c39cc456f3260405185815267ffffffffffffffff608086518051898501528289820151166040850152826040820151166060850152826060820151168285015201511660a082015273ffffffffffffffffffffffffffffffffffffffff60208601511660c082015280610e58610ddf610daa610d7560408a01516101a060e08701526101c0860190612ab1565b60608a01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086830301610100870152612ab1565b60808901517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe085830301610120860152612ab1565b73ffffffffffffffffffffffffffffffffffffffff60a08901511661014084015260c088015161016084015260e088015161018084015267ffffffffffffffff610100890151967fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0858403016101a086015216956131aa565b0390a37fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff600254166002555151604051908152f35b73ffffffffffffffffffffffffffffffffffffffff604051917fea458c0c00000000000000000000000000000000000000000000000000000000835267ffffffffffffffff8516600484015216602482015283816044818973ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165af1908115610f74578691610f32575b50610ab2565b90508381813d8311610f6d575b610f498183612a13565b81010312610f69575167ffffffffffffffff81168103610f695787610f2c565b8580fd5b503d610f3f565b6040513d88823e3d90fd5b9850505090503d908186883e610f958288612a13565b6080878381010312610f6957865196610faf858201612c2c565b97604082015167ffffffffffffffff811161108d57610fd390858401908401613168565b9160608101519467ffffffffffffffff861161108957808201601f87840101121561108957858201519161100683612b25565b966110146040519889612a13565b838852898801928083018b8660051b848601010111610831578a82840101935b8b8660051b84860101018510611054575050505050509790929789610aa4565b845167ffffffffffffffff811161082d578c809261107c829383878a0191898b010101613168565b8152019501949050611034565b8980fd5b8880fd5b6040513d87823e3d90fd5b8351805173ffffffffffffffffffffffffffffffffffffffff168652810151818601528c975088965060409094019390920191600101610a7e565b60408336031261110e578660409182516110f0816129f7565b6110f986612b90565b815282860135838201528152019201916105ad565b8a80fd5b60248b7f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b60209061114a613105565b82828a010152016104b1565b6024867f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b803b156111ec578460405180927fe0a0e5060000000000000000000000000000000000000000000000000000000082528183816111c96024356004018b60048401612cc8565b03925af18015611091571561037357846111e591959295612a13565b9238610373565b8480fd5b6004847f1c0a3529000000000000000000000000000000000000000000000000000000008152fd5b73ffffffffffffffffffffffffffffffffffffffff831660009081526002830160205260409020546103355760248573ffffffffffffffffffffffffffffffffffffffff857fd0d2597600000000000000000000000000000000000000000000000000000000835216600452fd5b6004847fa4ec7479000000000000000000000000000000000000000000000000000000008152fd5b6004847f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b5080fd5b503461013c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c5760043567ffffffffffffffff81116112d65761132a903690600401612bb1565b73ffffffffffffffffffffffffffffffffffffffff60015416330361165f575b919081907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8181360301915b8481101561165b578060051b820135838112156111ec578201916080833603126111ec57604051946113a686612990565b6113af84612b10565b86526113bd60208501612b3d565b9660208701978852604085013567ffffffffffffffff8111611657576113e69036908701612fb8565b9460408801958652606081013567ffffffffffffffff81116116535761140e91369101612fb8565b60608801908152875167ffffffffffffffff1683526006602052604080842099518a547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff169015159182901b68ff000000000000000016178a5590959081515161152b575b5095976001019550815b855180518210156114bc57906114b573ffffffffffffffffffffffffffffffffffffffff6114ad8360019561301d565b511689613374565b500161147d565b505095909694506001929193519081516114dc575b505001939293611375565b61152167ffffffffffffffff7fc237ec1921f855ccd5e9a5af9733f2d58943a5a8501ec5988e305d7a4d42158692511692604051918291602083526020830190612be2565b0390a238806114d1565b9893959296919094979860001461161c57600184019591875b865180518210156115c15761156e8273ffffffffffffffffffffffffffffffffffffffff9261301d565b5116801561158a57906115836001928a6132e3565b5001611544565b60248a67ffffffffffffffff8e51167f463258ff000000000000000000000000000000000000000000000000000000008252600452fd5b50509692955090929796937f330939f6eafe8bb516716892fe962ff19770570838686e6579dbc1cc51fc328161161267ffffffffffffffff8a51169251604051918291602083526020830190612be2565b0390a23880611473565b60248767ffffffffffffffff8b51167f463258ff000000000000000000000000000000000000000000000000000000008252600452fd5b8380fd5b8280fd5b8380f35b73ffffffffffffffffffffffffffffffffffffffff6005541633031561134a576004837f905d7d9b000000000000000000000000000000000000000000000000000000008152fd5b503461013c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c5767ffffffffffffffff6116e8612af4565b16808252600660205260ff604083205460401c16908252600660205260016040832001916040518093849160208254918281520191845260208420935b81811061175c57505061173a92500383612a13565b61175860405192839215158352604060208401526040830190612be2565b0390f35b8454835260019485019487945060209093019201611725565b503461013c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c5767ffffffffffffffff6117b6612af4565b1681526006602052600167ffffffffffffffff604083205416019067ffffffffffffffff82116117f55760208267ffffffffffffffff60405191168152f35b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526011600452fd5b503461013c57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c57602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b503461013c57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c57805473ffffffffffffffffffffffffffffffffffffffff81163303611931577fffffffffffffffffffffffff000000000000000000000000000000000000000060015491338284161760015516825573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b6004827f02b543c6000000000000000000000000000000000000000000000000000000008152fd5b503461013c57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c576080604051611996816129db565b828152826020820152826040820152826060820152015260a06040516119bb816129db565b60ff60025473ffffffffffffffffffffffffffffffffffffffff81168352831c161515602082015273ffffffffffffffffffffffffffffffffffffffff60035416604082015273ffffffffffffffffffffffffffffffffffffffff60045416606082015273ffffffffffffffffffffffffffffffffffffffff600554166080820152611a90604051809273ffffffffffffffffffffffffffffffffffffffff60808092828151168552602081015115156020860152826040820151166040860152826060820151166060860152015116910152565bf35b503461013c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c57604060609167ffffffffffffffff611ad8612af4565b1681526006602052205473ffffffffffffffffffffffffffffffffffffffff6040519167ffffffffffffffff8116835260ff8160401c161515602084015260481c166040820152f35b503461013c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c5760043567ffffffffffffffff81116112d657611b71903690600401612bb1565b9073ffffffffffffffffffffffffffffffffffffffff6004541690835b83811015611e055773ffffffffffffffffffffffffffffffffffffffff611bb98260051b8401612f97565b1690604051917f70a08231000000000000000000000000000000000000000000000000000000008352306004840152602083602481845afa928315611dfa578793611dc3575b5082611c11575b506001915001611b8e565b8460405193611ccc60208601957fa9059cbb00000000000000000000000000000000000000000000000000000000875283602482015282604482015260448152611c5c606482612a13565b8a80604098895193611c6e8b86612a13565b602085527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65646020860152519082895af13d15611dbb573d90611caf82612a54565b91611cbc8a519384612a13565b82523d8d602084013e5b86613506565b805180611d08575b505060207f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e9160019651908152a338611c06565b81929495969350906020918101031261108d576020611d279101612c2c565b15611d385792919085903880611cd4565b608490517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152fd5b606090611cc6565b9092506020813d8211611df2575b81611dde60209383612a13565b81010312611dee57519138611bff565b8680fd5b3d9150611dd1565b6040513d89823e3d90fd5b8480f35b503461013c5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c57611e41612af4565b506024359073ffffffffffffffffffffffffffffffffffffffff8216820361013c576020611e6e83612e7e565b73ffffffffffffffffffffffffffffffffffffffff60405191168152f35b503461013c5760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c57604051611ec8816129db565b611ed0612b4a565b81526024358015158103611657576020820190815260443573ffffffffffffffffffffffffffffffffffffffff811681036116535760408301908152611f14612b6d565b90606084019182526084359273ffffffffffffffffffffffffffffffffffffffff84168403610f695760808501938452611f4c613280565b73ffffffffffffffffffffffffffffffffffffffff855116158015612273575b8015612269575b612241579273ffffffffffffffffffffffffffffffffffffffff859381809461012097827fc7372d2d886367d7bb1b0e0708a5436f2c91d6963de210eb2dc1ec2ecd6d21f19a51167fffffffffffffffffffffffff000000000000000000000000000000000000000060025416176002555115157fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff74ff00000000000000000000000000000000000000006002549260a01b1691161760025551167fffffffffffffffffffffffff0000000000000000000000000000000000000000600354161760035551167fffffffffffffffffffffffff0000000000000000000000000000000000000000600454161760045551167fffffffffffffffffffffffff0000000000000000000000000000000000000000600554161760055561223d604051916120bd83612990565b67ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016835273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016602084015273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016604084015273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660608401526121ed604051809473ffffffffffffffffffffffffffffffffffffffff6060809267ffffffffffffffff8151168552826020820151166020860152826040820151166040860152015116910152565b608083019073ffffffffffffffffffffffffffffffffffffffff60808092828151168552602081015115156020860152826040820151166040860152826060820151166060860152015116910152565ba180f35b6004867f35be3ac8000000000000000000000000000000000000000000000000000000008152fd5b5080511515611f73565b5073ffffffffffffffffffffffffffffffffffffffff83511615611f6c565b503461013c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c576004359067ffffffffffffffff821161013c573660238301121561013c5781600401356122ee81612b25565b926122fc6040519485612a13565b818452602460606020860193028201019036821161165357602401915b81831061249a5750505061232b613280565b805b825181101561249657612340818461301d565b5167ffffffffffffffff612354838661301d565b51511690811561246a57907fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef5606060019493838752600660205260ff6040882061242b604060208501519483547fffffff0000000000000000000000000000000000000000ffffffffffffffffff7cffffffffffffffffffffffffffffffffffffffff0000000000000000008860481b1691161784550151151582907fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff68ff0000000000000000835492151560401b169116179055565b5473ffffffffffffffffffffffffffffffffffffffff6040519367ffffffffffffffff8316855216602084015260401c1615156040820152a20161232d565b602484837fc35aa79d000000000000000000000000000000000000000000000000000000008252600452fd5b5080f35b606083360312611653576040516060810181811067ffffffffffffffff821117612515576040526124ca84612b10565b8152602084013573ffffffffffffffffffffffffffffffffffffffff81168103610f6957918160609360208094015261250560408701612b3d565b6040820152815201920191612319565b6024867f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b503461013c5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c5761257a612af4565b60243567ffffffffffffffff81116116575760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8236030112611657576040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff000000000000000000000000000000008360801b16600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa90811561277b578491612741575b5061270b576126ad9160209173ffffffffffffffffffffffffffffffffffffffff60025416906040518095819482937fd8694ccd0000000000000000000000000000000000000000000000000000000084526004019060048401612cc8565b03915afa9081156127005782916126ca575b602082604051908152f35b90506020813d6020116126f8575b816126e560209383612a13565b810103126112d6576020915051386126bf565b3d91506126d8565b6040513d84823e3d90fd5b60248367ffffffffffffffff847ffdbd6a7200000000000000000000000000000000000000000000000000000000835216600452fd5b90506020813d602011612773575b8161275c60209383612a13565b810103126116535761276d90612c2c565b3861264e565b3d915061274f565b6040513d86823e3d90fd5b503461013c57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c57506117586040516127c7604082612a13565b601081527f4f6e52616d7020312e362e302d646576000000000000000000000000000000006020820152604051918291602083526020830190612ab1565b9050346112d657817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126112d65780612841606092612990565b8281528260208201528260408201520152608060405161286081612990565b67ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016602082015273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016604082015273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166060820152611a90604051809273ffffffffffffffffffffffffffffffffffffffff6060809267ffffffffffffffff8151168552826020820151166020860152826040820151166040860152015116910152565b6080810190811067ffffffffffffffff8211176129ac57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60a0810190811067ffffffffffffffff8211176129ac57604052565b6040810190811067ffffffffffffffff8211176129ac57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176129ac57604052565b67ffffffffffffffff81116129ac57601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60005b838110612aa15750506000910152565b8181015183820152602001612a91565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602093612aed81518092818752878088019101612a8e565b0116010190565b6004359067ffffffffffffffff82168203612b0b57565b600080fd5b359067ffffffffffffffff82168203612b0b57565b67ffffffffffffffff81116129ac5760051b60200190565b35908115158203612b0b57565b6004359073ffffffffffffffffffffffffffffffffffffffff82168203612b0b57565b6064359073ffffffffffffffffffffffffffffffffffffffff82168203612b0b57565b359073ffffffffffffffffffffffffffffffffffffffff82168203612b0b57565b9181601f84011215612b0b5782359167ffffffffffffffff8311612b0b576020808501948460051b010111612b0b57565b906020808351928381520192019060005b818110612c005750505090565b825173ffffffffffffffffffffffffffffffffffffffff16845260209384019390920191600101612bf3565b51908115158203612b0b57565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe182360301811215612b0b57016020813591019167ffffffffffffffff8211612b0b578136038313612b0b57565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b9067ffffffffffffffff9093929316815260406020820152612d3e612d01612cf08580612c39565b60a0604086015260e0850191612c89565b612d0e6020860186612c39565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0858403016060860152612c89565b9060408401357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe185360301811215612b0b5784016020813591019267ffffffffffffffff8211612b0b578160061b36038413612b0b578281037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0016080840152818152602001929060005b818110612e3f57505050612e0c8473ffffffffffffffffffffffffffffffffffffffff612dfc6060612e3c979801612b90565b1660a08401526080810190612c39565b9160c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc082860301910152612c89565b90565b90919360408060019273ffffffffffffffffffffffffffffffffffffffff612e6689612b90565b16815260208881013590820152019501929101612dc9565b73ffffffffffffffffffffffffffffffffffffffff604051917fbbe4f6db00000000000000000000000000000000000000000000000000000000835216600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa908115612f8b57600091612f28575b5073ffffffffffffffffffffffffffffffffffffffff1690565b6020813d602011612f83575b81612f4160209383612a13565b810103126112d657519073ffffffffffffffffffffffffffffffffffffffff8216820361013c575073ffffffffffffffffffffffffffffffffffffffff612f0e565b3d9150612f34565b6040513d6000823e3d90fd5b3573ffffffffffffffffffffffffffffffffffffffff81168103612b0b5790565b9080601f83011215612b0b578135612fcf81612b25565b92612fdd6040519485612a13565b81845260208085019260051b820101928311612b0b57602001905b8282106130055750505090565b6020809161301284612b90565b815201910190612ff8565b80518210156130315760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215612b0b570180359067ffffffffffffffff8211612b0b57602001918136038313612b0b57565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215612b0b570180359067ffffffffffffffff8211612b0b57602001918160061b36038313612b0b57565b60405190613112826129db565b6060608083600081528260208201528260408201526000838201520152565b92919261313d82612a54565b9161314b6040519384612a13565b829481845281830111612b0b578281602093846000960137010152565b81601f82011215612b0b57805161317e81612a54565b9261318c6040519485612a13565b81845260208284010111612b0b57612e3c9160208085019101612a8e565b9080602083519182815201916020808360051b8301019401926000915b8383106131d657505050505090565b9091929394602080613271837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0866001960301875289519073ffffffffffffffffffffffffffffffffffffffff825116815260806132566132448685015160a08886015260a0850190612ab1565b60408501518482036040860152612ab1565b92606081015160608401520151906080818403910152612ab1565b970193019301919392906131c7565b73ffffffffffffffffffffffffffffffffffffffff6001541633036132a157565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b80548210156130315760005260206000200190600090565b600082815260018201602052604090205461336d57805490680100000000000000008210156129ac57826133566133218460018096018555846132cb565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b905580549260005201602052604060002055600190565b5050600090565b90600182019181600052826020526040600020548015156000146134fd577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81018181116134ce578254907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82019182116134ce57818103613497575b50505080548015613468577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019061342982826132cb565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b191690555560005260205260006040812055600190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6134b76134a761332193866132cb565b90549060031b1c928392866132cb565b9055600052836020526040600020553880806133f1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50505050600090565b91929015613581575081511561351a575090565b3b156135235790565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152fd5b8251909150156135945750805190602001fd5b6135d2906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352602060048401526024830190612ab1565b0390fdfea164736f6c634300081a000a", } var OnRampABI = OnRampMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/ping_pong_demo/ping_pong_demo.go b/core/gethwrappers/ccip/generated/ping_pong_demo/ping_pong_demo.go index 2184e5926d0..090d7d4cd11 100644 --- a/core/gethwrappers/ccip/generated/ping_pong_demo/ping_pong_demo.go +++ b/core/gethwrappers/ccip/generated/ping_pong_demo/ping_pong_demo.go @@ -44,8 +44,8 @@ type ClientEVMTokenAmount struct { } var PingPongDemoMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"contractIERC20\",\"name\":\"feeToken\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"name\":\"InvalidRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isOutOfOrder\",\"type\":\"bool\"}],\"name\":\"OutOfOrderExecutionChange\",\"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\":\"uint256\",\"name\":\"pingPongCount\",\"type\":\"uint256\"}],\"name\":\"Ping\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"pingPongCount\",\"type\":\"uint256\"}],\"name\":\"Pong\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCounterpartAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCounterpartChainSelector\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFeeToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getOutOfOrderExecution\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isPaused\",\"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\":\"uint64\",\"name\":\"counterpartChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"counterpartAddress\",\"type\":\"address\"}],\"name\":\"setCounterpart\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"setCounterpartAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"setCounterpartChainSelector\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"outOfOrderExecution\",\"type\":\"bool\"}],\"name\":\"setOutOfOrderExecution\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"pause\",\"type\":\"bool\"}],\"name\":\"setPaused\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startPingPong\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"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\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x60a06040523480156200001157600080fd5b50604051620014a8380380620014a88339810160408190526200003491620001ff565b336000836001600160a01b03811662000067576040516335fdcccd60e21b81526000600482015260240160405180910390fd5b6001600160a01b0390811660805282166200009557604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0384811691909117909155811615620000c857620000c8816200016c565b50506002805460ff60a01b19169055600380546001600160a01b0319166001600160a01b0383811691821790925560405163095ea7b360e01b8152918416600483015260001960248301529063095ea7b3906044016020604051808303816000875af11580156200013d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016391906200023e565b50505062000269565b336001600160a01b038216036200019657604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b0381168114620001fc57600080fd5b50565b600080604083850312156200021357600080fd5b82516200022081620001e6565b60208401519092506200023381620001e6565b809150509250929050565b6000602082840312156200025157600080fd5b815180151581146200026257600080fd5b9392505050565b6080516112156200029360003960008181610295015281816106520152610a5901526112156000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c80638da5cb5b116100b2578063b187bd2611610081578063bee518a411610066578063bee518a4146102ef578063ca709a251461032d578063f2fde38b1461034b57600080fd5b8063b187bd26146102b9578063b5a11011146102dc57600080fd5b80638da5cb5b1461023f5780639d2aede51461025d578063ae90de5514610270578063b0f479a11461029357600080fd5b80632874d8bf11610109578063665ed537116100ee578063665ed5371461021157806379ba50971461022457806385572ffb1461022c57600080fd5b80632874d8bf146101ca5780632b6e5d63146101d257600080fd5b806301ffc9a71461013b57806316c38b3c14610163578063181f5a77146101785780631892b906146101b7575b600080fd5b61014e610149366004610c29565b61035e565b60405190151581526020015b60405180910390f35b610176610171366004610c72565b6103f7565b005b604080518082018252601281527f50696e67506f6e6744656d6f20312e352e3000000000000000000000000000006020820152905161015a9190610cf8565b6101766101c5366004610d28565b610449565b6101766104a4565b60025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161015a565b61017661021f366004610c72565b6104e0565b61017661056c565b61017661023a366004610d43565b61063a565b60015473ffffffffffffffffffffffffffffffffffffffff166101ec565b61017661026b366004610da2565b6106c3565b60035474010000000000000000000000000000000000000000900460ff1661014e565b7f00000000000000000000000000000000000000000000000000000000000000006101ec565b60025474010000000000000000000000000000000000000000900460ff1661014e565b6101766102ea366004610dbd565b610712565b60015474010000000000000000000000000000000000000000900467ffffffffffffffff1660405167ffffffffffffffff909116815260200161015a565b60035473ffffffffffffffffffffffffffffffffffffffff166101ec565b610176610359366004610da2565b6107b4565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f85572ffb0000000000000000000000000000000000000000000000000000000014806103f157507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b6103ff6107c5565b6002805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b6104516107c5565b6001805467ffffffffffffffff90921674010000000000000000000000000000000000000000027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909216919091179055565b6104ac6107c5565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556104de6001610816565b565b6104e86107c5565b6003805482151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091161790556040517f05a3fef9935c9013a24c6193df2240d34fcf6b0ebf8786b85efe8401d696cdd99061056190831515815260200190565b60405180910390a150565b60005473ffffffffffffffffffffffffffffffffffffffff1633146105bd576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106af576040517fd7f7333400000000000000000000000000000000000000000000000000000000815233600482015260240160405180910390fd5b6106c06106bb82610ff3565b610b0f565b50565b6106cb6107c5565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b61071a6107c5565b6001805467ffffffffffffffff90931674010000000000000000000000000000000000000000027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909316929092179091556002805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216919091179055565b6107bc6107c5565b6106c081610b65565b60015473ffffffffffffffffffffffffffffffffffffffff1633146104de576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600116600103610859576040518181527f48257dc961b6f792c2b78a080dacfed693b660960a702de21cee364e20270e2f9060200160405180910390a161088d565b6040518181527f58b69f57828e6962d216502094c54f6562f3bf082ba758966c3454f9e37b15259060200160405180910390a15b6040805160a0810190915260025473ffffffffffffffffffffffffffffffffffffffff1660c08201526000908060e081016040516020818303038152906040528152602001836040516020016108e591815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190528152602001600060405190808252806020026020018201604052801561095f57816020015b60408051808201909152600080825260208201528152602001906001900390816109385790505b50815260035473ffffffffffffffffffffffffffffffffffffffff811660208084019190915260408051808201825262030d408082527401000000000000000000000000000000000000000090940460ff16151590830190815281516024810194909452511515604480850191909152815180850390910181526064909301815290820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f181dcf1000000000000000000000000000000000000000000000000000000000179052909101526001546040517f96f4e9f90000000000000000000000000000000000000000000000000000000081529192507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16916396f4e9f991610ac7917401000000000000000000000000000000000000000090910467ffffffffffffffff169085906004016110a0565b6020604051808303816000875af1158015610ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0a91906111b5565b505050565b60008160600151806020019051810190610b2991906111b5565b60025490915074010000000000000000000000000000000000000000900460ff16610b6157610b61610b5c8260016111ce565b610816565b5050565b3373ffffffffffffffffffffffffffffffffffffffff821603610bb4576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215610c3b57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610c6b57600080fd5b9392505050565b600060208284031215610c8457600080fd5b81358015158114610c6b57600080fd5b6000815180845260005b81811015610cba57602081850181015186830182015201610c9e565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610c6b6020830184610c94565b803567ffffffffffffffff81168114610d2357600080fd5b919050565b600060208284031215610d3a57600080fd5b610c6b82610d0b565b600060208284031215610d5557600080fd5b813567ffffffffffffffff811115610d6c57600080fd5b820160a08185031215610c6b57600080fd5b803573ffffffffffffffffffffffffffffffffffffffff81168114610d2357600080fd5b600060208284031215610db457600080fd5b610c6b82610d7e565b60008060408385031215610dd057600080fd5b610dd983610d0b565b9150610de760208401610d7e565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610e4257610e42610df0565b60405290565b60405160a0810167ffffffffffffffff81118282101715610e4257610e42610df0565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610eb257610eb2610df0565b604052919050565b600082601f830112610ecb57600080fd5b813567ffffffffffffffff811115610ee557610ee5610df0565b610f1660207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610e6b565b818152846020838601011115610f2b57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f830112610f5957600080fd5b8135602067ffffffffffffffff821115610f7557610f75610df0565b610f83818360051b01610e6b565b82815260069290921b84018101918181019086841115610fa257600080fd5b8286015b84811015610fe85760408189031215610fbf5760008081fd5b610fc7610e1f565b610fd082610d7e565b81528185013585820152835291830191604001610fa6565b509695505050505050565b600060a0823603121561100557600080fd5b61100d610e48565b8235815261101d60208401610d0b565b6020820152604083013567ffffffffffffffff8082111561103d57600080fd5b61104936838701610eba565b6040840152606085013591508082111561106257600080fd5b61106e36838701610eba565b6060840152608085013591508082111561108757600080fd5b5061109436828601610f48565b60808301525092915050565b6000604067ffffffffffffffff851683526020604081850152845160a060408601526110cf60e0860182610c94565b9050818601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08087840301606088015261110a8383610c94565b6040890151888203830160808a01528051808352908601945060009350908501905b8084101561116b578451805173ffffffffffffffffffffffffffffffffffffffff1683528601518683015293850193600193909301929086019061112c565b50606089015173ffffffffffffffffffffffffffffffffffffffff1660a08901526080890151888203830160c08a015295506111a78187610c94565b9a9950505050505050505050565b6000602082840312156111c757600080fd5b5051919050565b808201808211156103f1577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea164736f6c6343000818000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"router\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"feeToken\",\"type\":\"address\",\"internalType\":\"contractIERC20\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"acceptOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"ccipReceive\",\"inputs\":[{\"name\":\"message\",\"type\":\"tuple\",\"internalType\":\"structClient.Any2EVMMessage\",\"components\":[{\"name\":\"messageId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sender\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\",\"internalType\":\"structClient.EVMTokenAmount[]\",\"components\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getCounterpartAddress\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCounterpartChainSelector\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getFeeToken\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIERC20\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getOutOfOrderExecution\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRouter\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isPaused\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"setCounterpart\",\"inputs\":[{\"name\":\"counterpartChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"counterpartAddress\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setCounterpartAddress\",\"inputs\":[{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setCounterpartChainSelector\",\"inputs\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setOutOfOrderExecution\",\"inputs\":[{\"name\":\"outOfOrderExecution\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setPaused\",\"inputs\":[{\"name\":\"pause\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"startPingPong\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"typeAndVersion\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"pure\"},{\"type\":\"event\",\"name\":\"OutOfOrderExecutionChange\",\"inputs\":[{\"name\":\"isOutOfOrder\",\"type\":\"bool\",\"indexed\":false,\"internalType\":\"bool\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferRequested\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Ping\",\"inputs\":[{\"name\":\"pingPongCount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Pong\",\"inputs\":[{\"name\":\"pingPongCount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"CannotTransferToSelf\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidRouter\",\"inputs\":[{\"name\":\"router\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"MustBeProposedOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OnlyCallableByOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OwnerCannotBeZero\",\"inputs\":[]}]", + Bin: "0x60a0806040523461011f57604081611643803803809161001f828561015f565b83398101031261011f578051906001600160a01b0382169081830361011f57602001516001600160a01b038116929083900361011f57811561014957608052331561013857600180546001600160a01b031990811633179091556002805460ff60a01b19169055600380549091168317905560405163095ea7b360e01b81526004810191909152600019602482015290602090829060449082906000905af1801561012c576100ef575b6040516114aa908161019982396080518181816103df015281816105a00152610fd20152f35b6020813d602011610124575b816101086020938361015f565b8101031261011f57518015150361011f57386100c9565b600080fd5b3d91506100fb565b6040513d6000823e3d90fd5b639b15e16f60e01b60005260046000fd5b6335fdcccd60e21b600052600060045260246000fd5b601f909101601f19168101906001600160401b0382119082101761018257604052565b634e487b7160e01b600052604160045260246000fdfe608080604052600436101561001357600080fd5b60003560e01c90816301ffc9a7146111e05750806316c38b3c14611152578063181f5a77146110d15780631892b906146110415780632874d8bf14610cf25780632b6e5d6314610ca0578063665ed53714610bea57806379ba509714610b0157806385572ffb1461051c5780638da5cb5b146104ca5780639d2aede514610447578063ae90de5514610403578063b0f479a114610394578063b187bd2614610350578063b5a1101114610275578063bee518a41461022c578063ca709a25146101da5763f2fde38b146100e557600080fd5b346101d55760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d55773ffffffffffffffffffffffffffffffffffffffff610131611312565b610139611452565b163381146101ab57807fffffffffffffffffffffffff0000000000000000000000000000000000000000600054161760005573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b7fdad89dca0000000000000000000000000000000000000000000000000000000060005260046000fd5b600080fd5b346101d55760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d557602073ffffffffffffffffffffffffffffffffffffffff60035416604051908152f35b346101d55760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d557602067ffffffffffffffff60015460a01c16604051908152f35b346101d55760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d5576102ac6112fb565b6024359073ffffffffffffffffffffffffffffffffffffffff82168092036101d5576102d6611452565b7fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff7bffffffffffffffff00000000000000000000000000000000000000006001549260a01b169116176001557fffffffffffffffffffffffff00000000000000000000000000000000000000006002541617600255600080f35b346101d55760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d557602060ff60025460a01c166040519015158152f35b346101d55760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d557602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346101d55760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d557602060ff60035460a01c166040519015158152f35b346101d55760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d55773ffffffffffffffffffffffffffffffffffffffff610493611312565b61049b611452565b167fffffffffffffffffffffffff00000000000000000000000000000000000000006002541617600255600080f35b346101d55760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d557602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b346101d55760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d55760043567ffffffffffffffff81116101d55760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82360301126101d55773ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016803303610ad3576000916040516105d681611335565b81600401358152602482013567ffffffffffffffff81168103610acb576020820152604482013567ffffffffffffffff8111610acb5761061c90600436918501016113dd565b6040820152606482013567ffffffffffffffff8111610acb5761064590600436918501016113dd565b916060820192835260848101359067ffffffffffffffff8211610acf57019036602383011215610acb57600482013567ffffffffffffffff8111610a9e5760208160051b0192610698604051948561139c565b818452602060048186019360061b8301010190368211610a9a57602401915b818310610a44575050506080015251602081805181010312610a4057602001519060ff60025460a01c16156106ea578280f35b60018201809211610a13576001828116036109e4577f48257dc961b6f792c2b78a080dacfed693b660960a702de21cee364e20270e2f6020604051848152a15b73ffffffffffffffffffffffffffffffffffffffff60025416906040519160208301526020825261075c60408361139c565b6040519260208401526020835261077460408461139c565b604051602093610784858361139c565b85825290918585936003546040519061079c82611380565b62030d40825286820160ff8260a01c1615158152604051927f181dcf1000000000000000000000000000000000000000000000000000000000898501525160248401525115156044830152604482526107f660648361139c565b6040519761080389611335565b88528688019586526040880192835273ffffffffffffffffffffffffffffffffffffffff6060890191168152608088019182526108c567ffffffffffffffff60015460a01c16966108946040519a8b997f96f4e9f9000000000000000000000000000000000000000000000000000000008b5260048b0152604060248b01525160a060448b015260e48a019061129c565b90517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc8983030160648a015261129c565b9251927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc878203016084880152878085519283815201940190855b8181106109a757505050859392849273ffffffffffffffffffffffffffffffffffffffff61095f93511660a4850152517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc8483030160c485015261129c565b03925af1801561099c57610971578280f35b813d8311610995575b610984818361139c565b810103126109925781808280f35b80fd5b503d61097a565b6040513d85823e3d90fd5b8251805173ffffffffffffffffffffffffffffffffffffffff1687528a01518a8701528b998b99508d975060409096019590920191600101610900565b7f58b69f57828e6962d216502094c54f6562f3bf082ba758966c3454f9e37b15256020604051848152a161072a565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b8280fd5b604083360312610a9a5760405190610a5b82611380565b83359073ffffffffffffffffffffffffffffffffffffffff82168203610a9657826020926040945282860135838201528152019201916106b7565b8980fd5b8780fd5b6024867f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b8480fd5b8580fd5b7fd7f73334000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b346101d55760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d55760005473ffffffffffffffffffffffffffffffffffffffff81163303610bc0577fffffffffffffffffffffffff00000000000000000000000000000000000000006001549133828416176001551660005573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b7f02b543c60000000000000000000000000000000000000000000000000000000060005260046000fd5b346101d55760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d5576004358015158091036101d55760207f05a3fef9935c9013a24c6193df2240d34fcf6b0ebf8786b85efe8401d696cdd991610c52611452565b6003547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff74ff00000000000000000000000000000000000000008360a01b16911617600355604051908152a1005b346101d55760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d557602073ffffffffffffffffffffffffffffffffffffffff60025416604051908152f35b346101d55760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d557610d29611452565b7fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff600254166002557f48257dc961b6f792c2b78a080dacfed693b660960a702de21cee364e20270e2f602060405160018152a1600173ffffffffffffffffffffffffffffffffffffffff6002541660405190602082015260208152610daf60408261139c565b6040519082602083015260208252610dc860408361139c565b604051602092610dd8848361139c565b6000825260009461103c575b839060035460405190610df682611380565b62030d40825283820160ff8260a01c1615158152604051927f181dcf100000000000000000000000000000000000000000000000000000000086850152516024840152511515604483015260448252610e5060648361139c565b60405195610e5d87611335565b86528386019283526040860194855273ffffffffffffffffffffffffffffffffffffffff606087019116815260808601918252610f1f67ffffffffffffffff60015460a01c1693610eee6040519889967f96f4e9f90000000000000000000000000000000000000000000000000000000088526004880152604060248801525160a0604488015260e487019061129c565b90517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc86830301606487015261129c565b9451947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc848203016084850152848087519283815201960190895b8181106110025750505093610fb89173ffffffffffffffffffffffffffffffffffffffff849596511660a4850152517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc8483030160c485015261129c565b03818673ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165af1801561099c57610971578280f35b8251805173ffffffffffffffffffffffffffffffffffffffff16895287015187890152604090970196899689965090920191600101610f5a565b610de4565b346101d55760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d5576110786112fb565b611080611452565b7fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff7bffffffffffffffff00000000000000000000000000000000000000006001549260a01b16911617600155600080f35b346101d55760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d55761114e6040805190611112818361139c565b601282527f50696e67506f6e6744656d6f20312e352e30000000000000000000000000000060208301525191829160208352602083019061129c565b0390f35b346101d55760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d5576004358015158091036101d557611196611452565b7fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff74ff00000000000000000000000000000000000000006002549260a01b16911617600255600080f35b346101d55760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d557600435907fffffffff0000000000000000000000000000000000000000000000000000000082168092036101d557817f85572ffb0000000000000000000000000000000000000000000000000000000060209314908115611272575b5015158152f35b7f01ffc9a7000000000000000000000000000000000000000000000000000000009150148361126b565b919082519283825260005b8481106112e65750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b806020809284010151828286010152016112a7565b6004359067ffffffffffffffff821682036101d557565b6004359073ffffffffffffffffffffffffffffffffffffffff821682036101d557565b60a0810190811067ffffffffffffffff82111761135157604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040810190811067ffffffffffffffff82111761135157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761135157604052565b81601f820112156101d55780359067ffffffffffffffff82116113515760405192611430601f84017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0166020018561139c565b828452602083830101116101d557816000926020809301838601378301015290565b73ffffffffffffffffffffffffffffffffffffffff60015416330361147357565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fdfea164736f6c634300081a000a", } var PingPongDemoABI = PingPongDemoMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/registry_module_owner_custom/registry_module_owner_custom.go b/core/gethwrappers/ccip/generated/registry_module_owner_custom/registry_module_owner_custom.go index 315d75121b1..a93cb3b7ded 100644 --- a/core/gethwrappers/ccip/generated/registry_module_owner_custom/registry_module_owner_custom.go +++ b/core/gethwrappers/ccip/generated/registry_module_owner_custom/registry_module_owner_custom.go @@ -31,8 +31,8 @@ var ( ) var RegistryModuleOwnerCustomMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AddressZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"CanOnlySelfRegister\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"msgSender\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"RequiredRoleNotFound\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"administrator\",\"type\":\"address\"}],\"name\":\"AdministratorRegistered\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"registerAccessControlDefaultAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"registerAdminViaGetCCIPAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"registerAdminViaOwner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60a060405234801561001057600080fd5b5060405161064a38038061064a83398101604081905261002f91610067565b6001600160a01b03811661005657604051639fabe1c160e01b815260040160405180910390fd5b6001600160a01b0316608052610097565b60006020828403121561007957600080fd5b81516001600160a01b038116811461009057600080fd5b9392505050565b6080516105986100b260003960006103db01526105986000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c8063181f5a771461005157806369c0081e146100a357806396ea2f7a146100b8578063ff12c354146100cb575b600080fd5b61008d6040518060400160405280601f81526020017f52656769737472794d6f64756c654f776e6572437573746f6d20312e362e300081525081565b60405161009a9190610480565b60405180910390f35b6100b66100b136600461050f565b6100de565b005b6100b66100c636600461050f565b610255565b6100b66100d936600461050f565b6102d0565b60008173ffffffffffffffffffffffffffffffffffffffff1663a217fddf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561012b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061014f9190610533565b6040517f91d148540000000000000000000000000000000000000000000000000000000081526004810182905233602482015290915073ffffffffffffffffffffffffffffffffffffffff8316906391d1485490604401602060405180830381865afa1580156101c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101e7919061054c565b610247576040517f86e0b3440000000000000000000000000000000000000000000000000000000081523360048201526024810182905273ffffffffffffffffffffffffffffffffffffffff831660448201526064015b60405180910390fd5b610251823361031f565b5050565b6102cd818273ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102c8919061056e565b61031f565b50565b6102cd818273ffffffffffffffffffffffffffffffffffffffff16638fd6a6ac6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102a4573d6000803e3d6000fd5b73ffffffffffffffffffffffffffffffffffffffff8116331461038e576040517fc454d18200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301528316602482015260440161023e565b6040517fe677ae3700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff838116600483015282811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063e677ae3790604401600060405180830381600087803b15801561041f57600080fd5b505af1158015610433573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff8085169350851691507f09590fb70af4b833346363965e043a9339e8c7d378b8a2b903c75c277faec4f990600090a35050565b60006020808352835180602085015260005b818110156104ae57858101830151858201604001528201610492565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b73ffffffffffffffffffffffffffffffffffffffff811681146102cd57600080fd5b60006020828403121561052157600080fd5b813561052c816104ed565b9392505050565b60006020828403121561054557600080fd5b5051919050565b60006020828403121561055e57600080fd5b8151801515811461052c57600080fd5b60006020828403121561058057600080fd5b815161052c816104ed56fea164736f6c6343000818000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"tokenAdminRegistry\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"registerAccessControlDefaultAdmin\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"registerAdminViaGetCCIPAdmin\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"registerAdminViaOwner\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"typeAndVersion\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"AdministratorRegistered\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"administrator\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AddressZero\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CanOnlySelfRegister\",\"inputs\":[{\"name\":\"admin\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"RequiredRoleNotFound\",\"inputs\":[{\"name\":\"msgSender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]}]", + Bin: "0x60a034607e57601f6106e938819003918201601f19168301916001600160401b03831184841017608357808492602094604052833981010312607e57516001600160a01b03811690819003607e578015606d5760805260405161064f908161009a82396080518161052b0152f35b639fabe1c160e01b60005260046000fd5b600080fd5b634e487b7160e01b600052604160045260246000fdfe608080604052600436101561001357600080fd5b60003560e01c908163181f5a77146103795750806369c0081e146101e557806396ea2f7a1461012a5763ff12c3541461004b57600080fd5b346101255760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101255760043573ffffffffffffffffffffffffffffffffffffffff811690818103610125576020600492604051938480927f8fd6a6ac0000000000000000000000000000000000000000000000000000000082525afa908115610119576100e6926000926100e8575b506104f5565b005b61010b91925060203d602011610112575b6101038183610488565b8101906104c9565b90386100e0565b503d6100f9565b6040513d6000823e3d90fd5b600080fd5b346101255760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101255760043573ffffffffffffffffffffffffffffffffffffffff811690818103610125576020600492604051938480927f8da5cb5b0000000000000000000000000000000000000000000000000000000082525afa908115610119576100e6926000926101c457506104f5565b6101de91925060203d602011610112576101038183610488565b90836100e0565b346101255760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101255760043573ffffffffffffffffffffffffffffffffffffffff811690818103610125576040517fa217fddf000000000000000000000000000000000000000000000000000000008152602081600481865afa90811561011957600091610347575b506040517f91d14854000000000000000000000000000000000000000000000000000000008152816004820152336024820152602081604481875afa90811561011957600091610305575b50156102cf576100e633836104f5565b90507f86e0b344000000000000000000000000000000000000000000000000000000006000523360045260245260445260646000fd5b6020813d60201161033f575b8161031e60209383610488565b8101031261033b57519081151582036103385750846102bf565b80fd5b5080fd5b3d9150610311565b90506020813d602011610371575b8161036260209383610488565b81010312610125575183610274565b3d9150610355565b346101255760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610125576040810181811067ffffffffffffffff82111761045957604052601f81527f52656769737472794d6f64756c654f776e6572437573746f6d20312e362e3000602082015260405190602082528181519182602083015260005b8381106104415750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f836000604080968601015201168101030190f35b60208282018101516040878401015285935001610401565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761045957604052565b90816020910312610125575173ffffffffffffffffffffffffffffffffffffffff811681036101255790565b9073ffffffffffffffffffffffffffffffffffffffff16903382036105fb5773ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690813b156101255773ffffffffffffffffffffffffffffffffffffffff906040519182917fe677ae3700000000000000000000000000000000000000000000000000000000835216928360048301528460248301528160446000948580945af180156105f05790827f09590fb70af4b833346363965e043a9339e8c7d378b8a2b903c75c277faec4f993926105e0575b9050a3565b6105e991610488565b38816105db565b6040513d84823e3d90fd5b73ffffffffffffffffffffffffffffffffffffffff917fc454d182000000000000000000000000000000000000000000000000000000006000526004521660245260446000fdfea164736f6c634300081a000a", } var RegistryModuleOwnerCustomABI = RegistryModuleOwnerCustomMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/report_codec/report_codec.go b/core/gethwrappers/ccip/generated/report_codec/report_codec.go index 0a58d0a6b93..b3c7dfa61ee 100644 --- a/core/gethwrappers/ccip/generated/report_codec/report_codec.go +++ b/core/gethwrappers/ccip/generated/report_codec/report_codec.go @@ -98,8 +98,8 @@ type OffRampCommitReport struct { } var ReportCodecMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNRemote.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportDecoded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"structInternal.ExecutionReport[]\",\"name\":\"report\",\"type\":\"tuple[]\"}],\"name\":\"ExecuteReportDecoded\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"decodeCommitReport\",\"outputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNRemote.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"decodeExecuteReport\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReport[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b506113c3806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80636fb349561461003b578063f816ec6014610064575b600080fd5b61004e610049366004610231565b610084565b60405161005b91906104ee565b60405180910390f35b610077610072366004610231565b6100a0565b60405161005b9190610833565b60608180602001905181019061009a9190610e6d565b92915050565b6040805160a08101825260608082018181526080830182905282526020808301829052928201528251909161009a918401810190840161122d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561012d5761012d6100db565b60405290565b60405160c0810167ffffffffffffffff8111828210171561012d5761012d6100db565b6040805190810167ffffffffffffffff8111828210171561012d5761012d6100db565b6040516060810167ffffffffffffffff8111828210171561012d5761012d6100db565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156101e3576101e36100db565b604052919050565b600067ffffffffffffffff821115610205576102056100db565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60006020828403121561024357600080fd5b813567ffffffffffffffff81111561025a57600080fd5b8201601f8101841361026b57600080fd5b803561027e610279826101eb565b61019c565b81815285602083850101111561029357600080fd5b81602084016020830137600091810160200191909152949350505050565b60005b838110156102cc5781810151838201526020016102b4565b50506000910152565b600081518084526102ed8160208601602086016102b1565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082825180855260208086019550808260051b84010181860160005b848110156103eb577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a08151818652610380828701826102d5565b91505073ffffffffffffffffffffffffffffffffffffffff868301511686860152604063ffffffff81840151168187015250606080830151868303828801526103c983826102d5565b608094850151979094019690965250509884019892509083019060010161033c565b5090979650505050505050565b6000828251808552602080860195506005818360051b8501018287016000805b868110156104a3577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe088850381018c5283518051808752908801908887019080891b88018a01865b8281101561048c57858a830301845261047a8286516102d5565b948c0194938c01939150600101610460565b509e8a019e97505050938701935050600101610418565b50919998505050505050505050565b60008151808452602080850194506020840160005b838110156104e3578151875295820195908201906001016104c7565b509495945050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156106d6577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452815160a0860167ffffffffffffffff8083511688528883015160a08a8a015282815180855260c08b01915060c08160051b8c010194508b8301925060005b8181101561067f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408c87030183528351805180518852868f820151168f890152866040820151166040890152866060820151166060890152866080820151166080890152508d81015161014060a08901526106026101408901826102d5565b9050604082015188820360c08a015261061b82826102d5565b915050606082015161064560e08a018273ffffffffffffffffffffffffffffffffffffffff169052565b50608082015161010089015260a0820151915087810361012089015261066b818361031f565b97505050928c0192918c0191600101610582565b50505050506040820151878203604089015261069b82826103f8565b915050606082015187820360608901526106b582826104b2565b60809384015198909301979097525094509285019290850190600101610515565b5092979650505050505050565b60008151808452602080850194506020840160005b838110156104e3578151805167ffffffffffffffff1688528301517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1683880152604090960195908201906001016106f8565b600082825180855260208086019550808260051b84010181860160005b848110156103eb577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a067ffffffffffffffff8083511686528683015182888801526107bb838801826102d5565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101610764565b60008151808452602080850194506020840160005b838110156104e357815180518852830151838801526040909601959082019060010161080c565b602080825282516060838301528051604060808501819052815160c086018190526000949392840191859160e08801905b808410156108c1578451805173ffffffffffffffffffffffffffffffffffffffff1683528701517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1687830152938601936001939093019290820190610864565b50938501518785037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800160a0890152936108fb81866106e3565b9450505050508185015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08085830301604086015261093c8284610747565b925060408601519150808584030160608601525061095a82826107f7565b95945050505050565b600067ffffffffffffffff82111561097d5761097d6100db565b5060051b60200190565b805167ffffffffffffffff8116811461099f57600080fd5b919050565b600060a082840312156109b657600080fd5b6109be61010a565b9050815181526109d060208301610987565b60208201526109e160408301610987565b60408201526109f260608301610987565b6060820152610a0360808301610987565b608082015292915050565b600082601f830112610a1f57600080fd5b8151610a2d610279826101eb565b818152846020838601011115610a4257600080fd5b610a538260208301602087016102b1565b949350505050565b805173ffffffffffffffffffffffffffffffffffffffff8116811461099f57600080fd5b600082601f830112610a9057600080fd5b81516020610aa061027983610963565b82815260059290921b84018101918181019086841115610abf57600080fd5b8286015b84811015610bbb57805167ffffffffffffffff80821115610ae45760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610b1d5760008081fd5b610b2561010a565b8784015183811115610b375760008081fd5b610b458d8a83880101610a0e565b8252506040610b55818601610a5b565b8983015260608086015163ffffffff81168114610b725760008081fd5b808385015250608091508186015185811115610b8e5760008081fd5b610b9c8f8c838a0101610a0e565b9184019190915250919093015190830152508352918301918301610ac3565b509695505050505050565b600082601f830112610bd757600080fd5b81516020610be761027983610963565b82815260059290921b84018101918181019086841115610c0657600080fd5b8286015b84811015610bbb57805167ffffffffffffffff80821115610c2b5760008081fd5b8189019150610140807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610c655760008081fd5b610c6d610133565b610c798c8986016109a4565b815260c084015183811115610c8e5760008081fd5b610c9c8d8a83880101610a0e565b898301525060e084015183811115610cb45760008081fd5b610cc28d8a83880101610a0e565b604083015250610cd56101008501610a5b565b60608201526101208401516080820152908301519082821115610cf85760008081fd5b610d068c8984870101610a7f565b60a08201528652505050918301918301610c0a565b600082601f830112610d2c57600080fd5b81516020610d3c61027983610963565b82815260059290921b84018101918181019086841115610d5b57600080fd5b8286015b84811015610bbb57805167ffffffffffffffff80821115610d7f57600080fd5b818901915089603f830112610d9357600080fd5b85820151610da361027982610963565b81815260059190911b830160400190878101908c831115610dc357600080fd5b604085015b83811015610dfc57805185811115610ddf57600080fd5b610dee8f6040838a0101610a0e565b845250918901918901610dc8565b50875250505092840192508301610d5f565b600082601f830112610e1f57600080fd5b81516020610e2f61027983610963565b8083825260208201915060208460051b870101935086841115610e5157600080fd5b602086015b84811015610bbb5780518352918301918301610e56565b60006020808385031215610e8057600080fd5b825167ffffffffffffffff80821115610e9857600080fd5b818501915085601f830112610eac57600080fd5b8151610eba61027982610963565b81815260059190911b83018401908481019088831115610ed957600080fd5b8585015b83811015610fd357805185811115610ef457600080fd5b860160a0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215610f295760008081fd5b610f3161010a565b610f3c898301610987565b815260408083015188811115610f525760008081fd5b610f608e8c83870101610bc6565b8b8401525060608084015189811115610f795760008081fd5b610f878f8d83880101610d1b565b8385015250608091508184015189811115610fa25760008081fd5b610fb08f8d83880101610e0e565b918401919091525060a09290920151918101919091528352918601918601610edd565b5098975050505050505050565b80517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461099f57600080fd5b600082601f83011261101d57600080fd5b8151602061102d61027983610963565b82815260069290921b8401810191818101908684111561104c57600080fd5b8286015b84811015610bbb57604081890312156110695760008081fd5b611071610156565b61107a82610987565b8152611087858301610fe0565b81860152835291830191604001611050565b600082601f8301126110aa57600080fd5b815160206110ba61027983610963565b82815260059290921b840181019181810190868411156110d957600080fd5b8286015b84811015610bbb57805167ffffffffffffffff808211156110fe5760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d030112156111375760008081fd5b61113f61010a565b61114a888501610987565b8152604080850151848111156111605760008081fd5b61116e8e8b83890101610a0e565b8a8401525060609350611182848601610987565b908201526080611193858201610987565b938201939093529201519082015283529183019183016110dd565b600082601f8301126111bf57600080fd5b815160206111cf61027983610963565b82815260069290921b840181019181810190868411156111ee57600080fd5b8286015b84811015610bbb576040818903121561120b5760008081fd5b611213610156565b8151815284820151858201528352918301916040016111f2565b6000602080838503121561124057600080fd5b825167ffffffffffffffff8082111561125857600080fd5b908401906060828703121561126c57600080fd5b611274610179565b82518281111561128357600080fd5b8301604081890381131561129657600080fd5b61129e610156565b8251858111156112ad57600080fd5b8301601f81018b136112be57600080fd5b80516112cc61027982610963565b81815260069190911b8201890190898101908d8311156112eb57600080fd5b928a01925b828410156113395785848f0312156113085760008081fd5b611310610156565b61131985610a5b565b81526113268c8601610fe0565b818d0152825292850192908a01906112f0565b84525050508287015191508482111561135157600080fd5b61135d8a83850161100c565b8188015283525050828401518281111561137657600080fd5b61138288828601611099565b8583015250604083015193508184111561139b57600080fd5b6113a7878585016111ae565b6040820152969550505050505056fea164736f6c6343000818000a", + ABI: "[{\"type\":\"function\",\"name\":\"decodeCommitReport\",\"inputs\":[{\"name\":\"report\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structOffRamp.CommitReport\",\"components\":[{\"name\":\"priceUpdates\",\"type\":\"tuple\",\"internalType\":\"structInternal.PriceUpdates\",\"components\":[{\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"components\":[{\"name\":\"sourceToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"usdPerToken\",\"type\":\"uint224\",\"internalType\":\"uint224\"}]},{\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.GasPriceUpdate[]\",\"components\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"usdPerUnitGas\",\"type\":\"uint224\",\"internalType\":\"uint224\"}]}]},{\"name\":\"merkleRoots\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.MerkleRoot[]\",\"components\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"onRampAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"minSeqNr\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"maxSeqNr\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"merkleRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"rmnSignatures\",\"type\":\"tuple[]\",\"internalType\":\"structIRMNRemote.Signature[]\",\"components\":[{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]}]}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"decodeExecuteReport\",\"inputs\":[{\"name\":\"report\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.ExecutionReport[]\",\"components\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"messages\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"components\":[{\"name\":\"header\",\"type\":\"tuple\",\"internalType\":\"structInternal.RampMessageHeader\",\"components\":[{\"name\":\"messageId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sequenceNumber\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"sender\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"receiver\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"gasLimit\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"tokenAmounts\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"components\":[{\"name\":\"sourcePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"destTokenAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"destGasAmount\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"extraData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}]},{\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\",\"internalType\":\"bytes[][]\"},{\"name\":\"proofs\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"proofFlagBits\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"stateMutability\":\"pure\"},{\"type\":\"event\",\"name\":\"CommitReportDecoded\",\"inputs\":[{\"name\":\"report\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"components\":[{\"name\":\"priceUpdates\",\"type\":\"tuple\",\"internalType\":\"structInternal.PriceUpdates\",\"components\":[{\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"components\":[{\"name\":\"sourceToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"usdPerToken\",\"type\":\"uint224\",\"internalType\":\"uint224\"}]},{\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.GasPriceUpdate[]\",\"components\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"usdPerUnitGas\",\"type\":\"uint224\",\"internalType\":\"uint224\"}]}]},{\"name\":\"merkleRoots\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.MerkleRoot[]\",\"components\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"onRampAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"minSeqNr\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"maxSeqNr\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"merkleRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"rmnSignatures\",\"type\":\"tuple[]\",\"internalType\":\"structIRMNRemote.Signature[]\",\"components\":[{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ExecuteReportDecoded\",\"inputs\":[{\"name\":\"report\",\"type\":\"tuple[]\",\"indexed\":false,\"internalType\":\"structInternal.ExecutionReport[]\",\"components\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"messages\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"components\":[{\"name\":\"header\",\"type\":\"tuple\",\"internalType\":\"structInternal.RampMessageHeader\",\"components\":[{\"name\":\"messageId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sequenceNumber\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"sender\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"receiver\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"gasLimit\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"tokenAmounts\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"components\":[{\"name\":\"sourcePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"destTokenAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"destGasAmount\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"extraData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}]},{\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\",\"internalType\":\"bytes[][]\"},{\"name\":\"proofs\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"proofFlagBits\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"anonymous\":false}]", + Bin: "0x60808060405234601557611604908161001b8239f35b600080fdfe6101c0604052600436101561001357600080fd5b60003560e01c80636fb34956146106355763f816ec601461003357600080fd5b3461051d5761004136611462565b6060604061004d6113a4565b6100556113c4565b838152836020820152815282602082015201528051810190602082019060208184031261051d5760208101519067ffffffffffffffff821161051d57019060608284031261051d576100a56113a4565b92602083015167ffffffffffffffff811161051d578301602081019060409083031261051d576100d36113c4565b90805167ffffffffffffffff811161051d57810184601f8201121561051d57805161010561010082611545565b6113e4565b9160208084848152019260061b8201019087821161051d57602001915b8183106105f657505050825260208101519067ffffffffffffffff821161051d570183601f8201121561051d57805161015d61010082611545565b9160208084848152019260061b8201019086821161051d57602001915b8183106105b75750505060208201528452604083015167ffffffffffffffff811161051d576020908401019282601f8501121561051d578351936101c061010086611545565b9460208087838152019160051b8301019185831161051d5760208101915b838310610522575050505060208501938452606081015167ffffffffffffffff811161051d5760209101019180601f8401121561051d5782519161022461010084611545565b9360208086868152019460061b82010192831161051d5793959493602001925b8284106104e45750505050604082019283526040519283926020845251916060602085015260c0840192805193604060808701528451809152602060e0870195019060005b81811061048b5750505060200151927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808582030160a08601526020808551928381520194019060005b81811061043e5750505051917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848203016040850152825180825260208201916020808360051b8301019501926000915b83831061039e57505050505051907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08382030160608401526020808351928381520192019060005b818110610379575050500390f35b825180518552602090810151818601528695506040909401939092019160010161036b565b91939650919394602080827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0856001950301865289519067ffffffffffffffff82511681526080806103fd8585015160a08786015260a0850190611502565b9367ffffffffffffffff604082015116604085015267ffffffffffffffff606082015116606085015201519101529801930193019092879695949293610323565b8251805167ffffffffffffffff1687526020908101517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681880152889750604090960195909201916001016102d2565b8251805173ffffffffffffffffffffffffffffffffffffffff1688526020908101517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168189015289985060409097019690920191600101610289565b6040602085849997989903011261051d5760206040916105026113c4565b86518152828701518382015281520193019295949395610244565b600080fd5b825167ffffffffffffffff811161051d57820160a08188031261051d57610547611384565b916105546020830161155d565b835260408201519267ffffffffffffffff841161051d5760a08361057f8c6020809881980101611572565b8584015261058f6060820161155d565b60408401526105a06080820161155d565b6060840152015160808201528152019201916101de565b60406020848803011261051d5760206040916105d16113c4565b6105da8661155d565b81526105e78387016115ce565b8382015281520192019161017a565b60406020848903011261051d5760206040916106106113c4565b610619866115ad565b81526106268387016115ce565b83820152815201920191610122565b3461051d5761064336611462565b61010052610100515161010051016101a0526020610100516101a051031261051d5760206101005101516101405267ffffffffffffffff610140511161051d5760206101a05101603f61014051610100510101121561051d5760206101405161010051010151610120526106bc61010061012051611545565b60c05260c051610180526101205160c05152602060c0510160c05260c0516101605260206101a051016020806101205160051b6101405161010051010101011161051d5760406101405161010051010160e0525b6020806101205160051b61014051610100510101010160e05110610adc5760405180602081016020825261018051518091526040820160408260051b8401019161016051916000905b82821061076857505050500390f35b91939092947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc090820301825284519060a081019167ffffffffffffffff815116825260208101519260a06020840152835180915260c08301602060c08360051b86010195019160005b81811061092c57505050506040810151928281036040840152835180825260208201906020808260051b85010196019260005b8281106108715750505050506060810151928281036060840152602080855192838152019401906000905b80821061085957505050600192602092608080859401519101529601920192018594939192610759565b9091946020806001928851815201960192019061082f565b90919293967fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe083829e9d9e0301855287519081519081815260208101906020808460051b8301019401926000915b8183106108e35750505050506020806001929e9d9e99019501910192919092610804565b909192939460208061091f837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086600196030189528951611502565b97019501930191906108bf565b909192957fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff40868203018452865167ffffffffffffffff6080825180518552826020820151166020860152826040820151166040860152826060820151166060860152015116608083015260a06109c76109b5602084015161014084870152610140860190611502565b604084015185820360c0870152611502565b9173ffffffffffffffffffffffffffffffffffffffff60608201511660e0850152608081015161010085015201519161012081830391015281519081815260208101906020808460051b8301019401926000915b818310610a3b5750505050506020806001929801940191019190916107d1565b9091929394602080827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08560019503018852885190608080610ac9610a89855160a0865260a0860190611502565b73ffffffffffffffffffffffffffffffffffffffff87870151168786015263ffffffff604087015116604086015260608601518582036060870152611502565b9301519101529701950193019190610a1b565b60e0515160a05267ffffffffffffffff60a0511161051d5760a060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081835161014051610100510101016101a0510301011261051d57610b3b611384565b610b5560208060a05161014051610100510101010161155d565b81526040602060a0516101405161010051010101015160805267ffffffffffffffff6080511161051d5760206101a05101601f60206080518160a0516101405161010051010101010101121561051d5760206080518160a0516101405161010051010101010151610bc861010082611545565b90602082828152019060206101a0510160208260051b816080518160a0516101405161010051010101010101011161051d576020806080518160a0516101405161010051010101010101915b60208260051b816080518160a0516101405161010051010101010101018310610eff5750505060208201526060602060a0516101405161010051010101015167ffffffffffffffff811161051d5760206101a05101601f6020838160a0516101405161010051010101010101121561051d576020818160a051610140516101005101010101015190610ca861010083611545565b91602083828152019160206101a0510160208360051b81848160a0516101405161010051010101010101011161051d5760a051610140516101005101018101606001925b60208360051b81848160a0516101405161010051010101010101018410610dde5750505050604082015260a0805161014051610100510101015167ffffffffffffffff811161051d576020908160a0516101405161010051010101010160206101a05101601f8201121561051d57805190610d6961010083611545565b9160208084838152019160051b8301019160206101a05101831161051d57602001905b828210610dce57505050606082015260a06020815161014051610100510101010151608082015260c05152602060c0510160c052602060e0510160e052610710565b8151815260209182019101610d8c565b835167ffffffffffffffff811161051d5760206101a05101603f826020868160a051610140516101005101010101010101121561051d5760a051610140516101005101018301810160600151610e3661010082611545565b916020838381520160206101a051016020808560051b85828b8160a05161014051610100510101010101010101011161051d5760a0516101405161010051010186018201608001905b60a05161014051610100516080910190910188018401600586901b01018210610eb5575050509082525060209384019301610cec565b815167ffffffffffffffff811161051d576101a05160a051610140516101005160209586959094610ef4949087019360809301018d0189010101611572565b815201910190610e7f565b825167ffffffffffffffff811161051d5760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082826080518160a05161014051610100510101010101016101a05103010190610140821261051d576040519160c083019083821067ffffffffffffffff8311176113555760a0916040521261051d57610f8a611384565b602082816080518160a051610140516101005101010101010101518152610fca60408360206080518160a05161014051610100510101010101010161155d565b6020820152610ff260608360206080518160a05161014051610100510101010101010161155d565b6040820152611019608083602082518160a05161014051610100510101010101010161155d565b606082015261104060a083602060805181845161014051610100510101010101010161155d565b6080820152825260c08160206080518160a0516101405161010051010101010101015167ffffffffffffffff811161051d5761109d906020806101a051019184826080518160a05161014051610100510101010101010101611572565b602083015260e08160206080518160a0516101405161010051010101010101015167ffffffffffffffff811161051d576110f8906020806101a051019184826080518160a05161014051610100510101010101010101611572565b604083015261111f6101008260206080518160a051610140518651010101010101016115ad565b60608301526101208160206080518160a0516101405161010051010101010101015160808301526101408160206080518160a05185516101005101010101010101519067ffffffffffffffff821161051d5760206101a05101601f60208484826080518160a0516101405161010051010101010101010101121561051d5760208282826080518160a05161014051610100510101010101010101516111c661010082611545565b92602084838152019260206101a0510160208460051b818585826080518160a0516101405161010051010101010101010101011161051d576080805160a05161014051610100510101018201830101935b6080805160a051610140516101005101010183018401600586901b0101851061125257505050505060a0820152815260209283019201610c14565b845167ffffffffffffffff811161051d5760208484826080518160a051610140516101005101010101010101010160a060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0836101a0510301011261051d576112ba611384565b91602082015167ffffffffffffffff811161051d576112e4906020806101a0510191850101611572565b83526112f2604083016115ad565b6020840152606082015163ffffffff8116810361051d57604084015260808201519267ffffffffffffffff841161051d5760a06020949361133e869586806101a0510191840101611572565b606084015201516080820152815201940193611217565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519060a0820182811067ffffffffffffffff82111761135557604052565b604051906060820182811067ffffffffffffffff82111761135557604052565b604051906040820182811067ffffffffffffffff82111761135557604052565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f604051930116820182811067ffffffffffffffff82111761135557604052565b67ffffffffffffffff811161135557601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82011261051d5760043567ffffffffffffffff811161051d578160238201121561051d578060040135906114bb61010083611428565b928284526024838301011161051d5781600092602460209301838601378301015290565b60005b8381106114f25750506000910152565b81810151838201526020016114e2565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209361153e815180928187528780880191016114df565b0116010190565b67ffffffffffffffff81116113555760051b60200190565b519067ffffffffffffffff8216820361051d57565b81601f8201121561051d57805161158b61010082611428565b928184526020828401011161051d576115aa91602080850191016114df565b90565b519073ffffffffffffffffffffffffffffffffffffffff8216820361051d57565b51907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8216820361051d5756fea164736f6c634300081a000a", } var ReportCodecABI = ReportCodecMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/rmn_home/rmn_home.go b/core/gethwrappers/ccip/generated/rmn_home/rmn_home.go index 268b49b4f96..2f479d2968e 100644 --- a/core/gethwrappers/ccip/generated/rmn_home/rmn_home.go +++ b/core/gethwrappers/ccip/generated/rmn_home/rmn_home.go @@ -42,7 +42,7 @@ type RMNHomeNode struct { type RMNHomeSourceChain struct { ChainSelector uint64 - F uint64 + FObserve uint64 ObserverNodesBitmap *big.Int } @@ -59,8 +59,8 @@ type RMNHomeVersionedConfig struct { } var RMNHomeMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expectedConfigDigest\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"gotConfigDigest\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"DigestNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateOffchainPublicKey\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicatePeerId\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateSourceChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoOpStateTransitionNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotEnoughObservers\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OutOfBoundsNodesLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OutOfBoundsObserverNodeIndex\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RevokingZeroDigestNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"ActiveConfigRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"CandidateConfigRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"ConfigPromoted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"peerId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"offchainPublicKey\",\"type\":\"bytes32\"}],\"internalType\":\"structRMNHome.Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structRMNHome.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"f\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"observerNodesBitmap\",\"type\":\"uint256\"}],\"internalType\":\"structRMNHome.SourceChain[]\",\"name\":\"sourceChains\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structRMNHome.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"f\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"observerNodesBitmap\",\"type\":\"uint256\"}],\"internalType\":\"structRMNHome.SourceChain[]\",\"name\":\"sourceChains\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structRMNHome.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"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\":[],\"name\":\"getActiveDigest\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllConfigs\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"peerId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"offchainPublicKey\",\"type\":\"bytes32\"}],\"internalType\":\"structRMNHome.Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structRMNHome.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"f\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"observerNodesBitmap\",\"type\":\"uint256\"}],\"internalType\":\"structRMNHome.SourceChain[]\",\"name\":\"sourceChains\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structRMNHome.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"internalType\":\"structRMNHome.VersionedConfig\",\"name\":\"activeConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"peerId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"offchainPublicKey\",\"type\":\"bytes32\"}],\"internalType\":\"structRMNHome.Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structRMNHome.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"f\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"observerNodesBitmap\",\"type\":\"uint256\"}],\"internalType\":\"structRMNHome.SourceChain[]\",\"name\":\"sourceChains\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structRMNHome.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"internalType\":\"structRMNHome.VersionedConfig\",\"name\":\"candidateConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCandidateDigest\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"getConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"peerId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"offchainPublicKey\",\"type\":\"bytes32\"}],\"internalType\":\"structRMNHome.Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structRMNHome.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"f\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"observerNodesBitmap\",\"type\":\"uint256\"}],\"internalType\":\"structRMNHome.SourceChain[]\",\"name\":\"sourceChains\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structRMNHome.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"internalType\":\"structRMNHome.VersionedConfig\",\"name\":\"versionedConfig\",\"type\":\"tuple\"},{\"internalType\":\"bool\",\"name\":\"ok\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConfigDigests\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"activeConfigDigest\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"candidateConfigDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"digestToPromote\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"digestToRevoke\",\"type\":\"bytes32\"}],\"name\":\"promoteCandidateAndRevokeActive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"revokeCandidate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"peerId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"offchainPublicKey\",\"type\":\"bytes32\"}],\"internalType\":\"structRMNHome.Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structRMNHome.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"f\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"observerNodesBitmap\",\"type\":\"uint256\"}],\"internalType\":\"structRMNHome.SourceChain[]\",\"name\":\"sourceChains\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structRMNHome.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"digestToOverwrite\",\"type\":\"bytes32\"}],\"name\":\"setCandidate\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"newConfigDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"f\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"observerNodesBitmap\",\"type\":\"uint256\"}],\"internalType\":\"structRMNHome.SourceChain[]\",\"name\":\"sourceChains\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structRMNHome.DynamicConfig\",\"name\":\"newDynamicConfig\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"currentDigest\",\"type\":\"bytes32\"}],\"name\":\"setDynamicConfig\",\"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\"}]", - Bin: "0x6080604052600e80546001600160401b03191690553480156200002157600080fd5b50336000816200004457604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0384811691909117909155811615620000775762000077816200007f565b5050620000f9565b336001600160a01b03821603620000a957604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6128cb80620001096000396000f3fe608060405234801561001057600080fd5b50600436106100df5760003560e01c80636dd5b69d1161008c5780638c76967f116100665780638c76967f146101d45780638da5cb5b146101e7578063f2fde38b1461020f578063fb4022d41461022257600080fd5b80636dd5b69d14610196578063736be802146101b757806379ba5097146101cc57600080fd5b80633567e6b4116100bd5780633567e6b41461015b57806338354c5c14610178578063635079561461018057600080fd5b8063118dbac5146100e4578063123e65db1461010a578063181f5a7714610112575b600080fd5b6100f76100f236600461186a565b610235565b6040519081526020015b60405180910390f35b6100f7610418565b61014e6040518060400160405280601181526020017f524d4e486f6d6520312e362e302d64657600000000000000000000000000000081525081565b6040516101019190611945565b610163610457565b60408051928352602083019190915201610101565b6100f76104d8565b6101886104f7565b604051610101929190611ab0565b6101a96101a4366004611ad5565b610a79565b604051610101929190611aee565b6101ca6101c5366004611b12565b610d5d565b005b6101ca610e79565b6101ca6101e2366004611b57565b610f47565b60015460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610101565b6101ca61021d366004611b79565b61115a565b6101ca610230366004611ad5565b61116e565b600061023f61128a565b61025961024b85611d2b565b61025485611e2c565b6112dd565b60006102636104d8565b90508281146102ad576040517f93df584c00000000000000000000000000000000000000000000000000000000815260048101829052602481018490526044015b60405180910390fd5b80156102df5760405183907f53f5d9228f0a4173bea6e5931c9b3afe6eeb6692ede1d182952970f152534e3b90600090a25b600e80546000919082906102f89063ffffffff16611f41565b91906101000a81548163ffffffff021916908363ffffffff160217905590506103408660405160200161032b91906120ec565b60405160208183030381529060405282611455565b600e54909350600090600290640100000000900463ffffffff1660011863ffffffff1660028110610373576103736120ff565b600602016001810185905580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff8416178155905086600282016103bd828261234c565b50869050600482016103cf828261254b565b905050837ff6c6d1be15ba0acc8ee645c1ec613c360ef786d2d3200eb8e695b6dec757dbf08389896040516104069392919061278f565b60405180910390a25050509392505050565b60006002610434600e5463ffffffff6401000000009091041690565b63ffffffff166002811061044a5761044a6120ff565b6006020160010154905090565b6000806002610474600e5463ffffffff6401000000009091041690565b63ffffffff166002811061048a5761048a6120ff565b600602016001015460026104b2600e54600163ffffffff640100000000909204919091161890565b63ffffffff16600281106104c8576104c86120ff565b6006020160010154915091509091565b600e54600090600290640100000000900463ffffffff16600118610434565b6104ff6117ec565b6105076117ec565b60006002610523600e5463ffffffff6401000000009091041690565b63ffffffff1660028110610539576105396120ff565b6040805160808101825260069290920292909201805463ffffffff16825260018101546020808401919091528351600283018054606093810283018401875282870181815295969495948701949293919284929091849160009085015b828210156105dc57838290600052602060002090600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190610596565b5050505081526020016001820180546105f490612193565b80601f016020809104026020016040519081016040528092919081815260200182805461062090612193565b801561066d5780601f106106425761010080835404028352916020019161066d565b820191906000526020600020905b81548152906001019060200180831161065057829003601f168201915b50505050508152505081526020016004820160405180604001604052908160008201805480602002602001604051908101604052809291908181526020016000905b8282101561070f5760008481526020908190206040805160608101825260028602909201805467ffffffffffffffff80821685526801000000000000000090910416838501526001908101549183019190915290835290920191016106af565b50505050815260200160018201805461072790612193565b80601f016020809104026020016040519081016040528092919081815260200182805461075390612193565b80156107a05780601f10610775576101008083540402835291602001916107a0565b820191906000526020600020905b81548152906001019060200180831161078357829003601f168201915b505050919092525050509052506020810151909150156107be578092505b600e54600090600290640100000000900463ffffffff1660011863ffffffff16600281106107ee576107ee6120ff565b6040805160808101825260069290920292909201805463ffffffff16825260018101546020808401919091528351600283018054606093810283018401875282870181815295969495948701949293919284929091849160009085015b828210156108915783829060005260206000209060020201604051806040016040529081600082015481526020016001820154815250508152602001906001019061084b565b5050505081526020016001820180546108a990612193565b80601f01602080910402602001604051908101604052809291908181526020018280546108d590612193565b80156109225780601f106108f757610100808354040283529160200191610922565b820191906000526020600020905b81548152906001019060200180831161090557829003601f168201915b50505050508152505081526020016004820160405180604001604052908160008201805480602002602001604051908101604052809291908181526020016000905b828210156109c45760008481526020908190206040805160608101825260028602909201805467ffffffffffffffff8082168552680100000000000000009091041683850152600190810154918301919091529083529092019101610964565b5050505081526020016001820180546109dc90612193565b80601f0160208091040260200160405190810160405280929190818152602001828054610a0890612193565b8015610a555780601f10610a2a57610100808354040283529160200191610a55565b820191906000526020600020905b815481529060010190602001808311610a3857829003601f168201915b50505091909252505050905250602081015190915015610a73578092505b50509091565b610a816117ec565b6000805b6002811015610d52578360028260028110610aa257610aa26120ff565b6006020160010154148015610ab657508315155b15610d4a5760028160028110610ace57610ace6120ff565b6040805160808101825260069290920292909201805463ffffffff16825260018082015460208085019190915284516002840180546060938102830184018852828801818152959794969588958701948492849160009085015b82821015610b6e57838290600052602060002090600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190610b28565b505050508152602001600182018054610b8690612193565b80601f0160208091040260200160405190810160405280929190818152602001828054610bb290612193565b8015610bff5780601f10610bd457610100808354040283529160200191610bff565b820191906000526020600020905b815481529060010190602001808311610be257829003601f168201915b50505050508152505081526020016004820160405180604001604052908160008201805480602002602001604051908101604052809291908181526020016000905b82821015610ca15760008481526020908190206040805160608101825260028602909201805467ffffffffffffffff8082168552680100000000000000009091041683850152600190810154918301919091529083529092019101610c41565b505050508152602001600182018054610cb990612193565b80601f0160208091040260200160405190810160405280929190818152602001828054610ce590612193565b8015610d325780601f10610d0757610100808354040283529160200191610d32565b820191906000526020600020905b815481529060010190602001808311610d1557829003601f168201915b50505091909252505050905250969095509350505050565b600101610a85565b509092600092509050565b610d6561128a565b60005b6002811015610e3f578160028260028110610d8557610d856120ff565b6006020160010154148015610d9957508115155b15610e3757610dd0610daa84611e2c565b60028360028110610dbd57610dbd6120ff565b600602016002016000018054905061155d565b8260028260028110610de457610de46120ff565b600602016004018181610df7919061254b565b905050817f1f69d1a2edb327babc986b3deb80091f101b9105d42a6c30db4d99c31d7e629484604051610e2a91906127ca565b60405180910390a2505050565b600101610d68565b506040517fd0b2c031000000000000000000000000000000000000000000000000000000008152600481018290526024016102a4565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610eca576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610f4f61128a565b81158015610f5b575080155b15610f92576040517f7b4d1e4f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e54600163ffffffff6401000000009092048216181682600282818110610fbc57610fbc6120ff565b6006020160010154146110225760028160028110610fdc57610fdc6120ff565b6006020160010154836040517f93df584c0000000000000000000000000000000000000000000000000000000081526004016102a4929190918252602082015260400190565b6000600261103e600e5463ffffffff6401000000009091041690565b63ffffffff1660028110611054576110546120ff565b600602019050828160010154146110a75760018101546040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018490526044016102a4565b6000600180830191909155600e805463ffffffff6401000000008083048216909418169092027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff90921691909117905582156111295760405183907f0b31c0055e2d464bef7781994b98c4ff9ef4ae0d05f59feb6a68c42de5e201b890600090a25b60405184907ffc3e98dbbd47c3fa7c1c05b6ec711caeaf70eca4554192b9ada8fc11a37f298e90600090a250505050565b61116261128a565b61116b81611728565b50565b61117661128a565b806111ad576040517f0849d8cc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e54600163ffffffff64010000000090920482161816816002828181106111d7576111d76120ff565b60060201600101541461123d57600281600281106111f7576111f76120ff565b6006020160010154826040517f93df584c0000000000000000000000000000000000000000000000000000000081526004016102a4929190918252602082015260400190565b60405182907f53f5d9228f0a4173bea6e5931c9b3afe6eeb6692ede1d182952970f152534e3b90600090a26002816002811061127b5761127b6120ff565b60060201600101600090555050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146112db576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b815151610100101561131b576040517faf26d5e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251518110156114455760006113358260016127dd565b90505b83515181101561143c578351805182908110611356576113566120ff565b60200260200101516000015184600001518381518110611378576113786120ff565b602002602001015160000151036113bb576040517f221a8ae800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83518051829081106113cf576113cf6120ff565b602002602001015160200151846000015183815181106113f1576113f16120ff565b60200260200101516020015103611434576040517fae00651d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600101611338565b5060010161131e565b50610e758183600001515161155d565b604080517f45564d00000000000000000000000000000000000000000000000000000000006020820152469181019190915230606082015263ffffffff821660808201526000907dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060a001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526114fc9186906020016127f0565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00181529190528051602090910120167e0b0000000000000000000000000000000000000000000000000000000000001790505b92915050565b81515160005b8181101561172257600084600001518281518110611583576115836120ff565b60200260200101519050600082600161159c91906127dd565b90505b8381101561161f5785518051829081106115bb576115bb6120ff565b60200260200101516000015167ffffffffffffffff16826000015167ffffffffffffffff1603611617576040517f3857f84d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60010161159f565b506040810151806116328661010061281f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff901c82161461168e576040517f2847b60600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81156116b6576116a260018361281f565b909116906116af81612832565b9050611691565b60208301516116c690600261286a565b6116d1906001612896565b67ffffffffffffffff16811015611714576040517fa804bcb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050806001019050611563565b50505050565b3373ffffffffffffffffffffffffffffffffffffffff821603611777576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6040518060800160405280600063ffffffff1681526020016000801916815260200161182b604051806040016040528060608152602001606081525090565b815260200161184d604051806040016040528060608152602001606081525090565b905290565b60006040828403121561186457600080fd5b50919050565b60008060006060848603121561187f57600080fd5b833567ffffffffffffffff8082111561189757600080fd5b6118a387838801611852565b945060208601359150808211156118b957600080fd5b506118c686828701611852565b925050604084013590509250925092565b60005b838110156118f25781810151838201526020016118da565b50506000910152565b600081518084526119138160208601602086016118d7565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061195860208301846118fb565b9392505050565b8051604080845281518482018190526000926060916020918201918388019190865b828110156119bb578451805167ffffffffffffffff9081168652838201511683860152870151878501529381019392850192600101611981565b50808801519550888303818a015250506119d581856118fb565b979650505050505050565b63ffffffff81511682526000602080830151818501526040808401516080604087015260c0860181516040608089015281815180845260e08a0191508683019350600092505b80831015611a4f5783518051835287015187830152928601926001929092019190850190611a26565b50948301518886037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800160a08a015294611a8981876118fb565b9550505050505060608301518482036060860152611aa7828261195f565b95945050505050565b604081526000611ac360408301856119e0565b8281036020840152611aa781856119e0565b600060208284031215611ae757600080fd5b5035919050565b604081526000611b0160408301856119e0565b905082151560208301529392505050565b60008060408385031215611b2557600080fd5b823567ffffffffffffffff811115611b3c57600080fd5b611b4885828601611852565b95602094909401359450505050565b60008060408385031215611b6a57600080fd5b50508035926020909101359150565b600060208284031215611b8b57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461195857600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611c0157611c01611baf565b60405290565b6040516060810167ffffffffffffffff81118282101715611c0157611c01611baf565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611c7157611c71611baf565b604052919050565b600067ffffffffffffffff821115611c9357611c93611baf565b5060051b60200190565b600082601f830112611cae57600080fd5b813567ffffffffffffffff811115611cc857611cc8611baf565b611cf960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611c2a565b818152846020838601011115611d0e57600080fd5b816020850160208301376000918101602001919091529392505050565b60006040808336031215611d3e57600080fd5b611d46611bde565b833567ffffffffffffffff80821115611d5e57600080fd5b9085019036601f830112611d7157600080fd5b81356020611d86611d8183611c79565b611c2a565b82815260069290921b84018101918181019036841115611da557600080fd5b948201945b83861015611de557878636031215611dc25760008081fd5b611dca611bde565b86358152838701358482015282529487019490820190611daa565b86525087810135955082861115611dfb57600080fd5b611e0736878a01611c9d565b90850152509195945050505050565b67ffffffffffffffff8116811461116b57600080fd5b60006040808336031215611e3f57600080fd5b611e47611bde565b833567ffffffffffffffff80821115611e5f57600080fd5b9085019036601f830112611e7257600080fd5b81356020611e82611d8183611c79565b82815260609283028501820192828201919036851115611ea157600080fd5b958301955b84871015611efb57808736031215611ebe5760008081fd5b611ec6611c07565b8735611ed181611e16565b815287850135611ee081611e16565b81860152878a01358a82015283529586019591830191611ea6565b5086525087810135955082861115611dfb57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600063ffffffff808316818103611f5a57611f5a611f12565b6001019392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611f9957600080fd5b830160208101925035905067ffffffffffffffff811115611fb957600080fd5b803603821315611fc857600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b6000604080840183357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe185360301811261205157600080fd5b8401602081810191359067ffffffffffffffff82111561207057600080fd5b8160061b360383131561208257600080fd5b6040885292819052909160009190606088015b828410156120bb5784358152818501358282015293850193600193909301928501612095565b6120c86020890189611f64565b9650945088810360208a01526120df818787611fcf565b9998505050505050505050565b6020815260006119586020830184612018565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261216357600080fd5b83018035915067ffffffffffffffff82111561217e57600080fd5b602001915036819003821315611fc857600080fd5b600181811c908216806121a757607f821691505b602082108103611864577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b601f82111561222c576000816000526020600020601f850160051c810160208610156122095750805b601f850160051c820191505b8181101561222857828155600101612215565b5050505b505050565b67ffffffffffffffff83111561224957612249611baf565b61225d836122578354612193565b836121e0565b6000601f8411600181146122af57600085156122795750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355612345565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b828110156122fe57868501358255602094850194600190920191016122de565b5086821015612339577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b81357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe183360301811261237e57600080fd5b8201803567ffffffffffffffff81111561239757600080fd5b6020820191508060061b36038213156123af57600080fd5b680100000000000000008111156123c8576123c8611baf565b8254818455808210156124555760017f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808316831461240957612409611f12565b808416841461241a5761241a611f12565b5060008560005260206000208360011b81018560011b820191505b80821015612450578282558284830155600282019150612435565b505050505b5060008381526020902060005b8281101561248e5783358255602084013560018301556040939093019260029190910190600101612462565b5050505061249f602083018361212e565b611722818360018601612231565b81356124b881611e16565b67ffffffffffffffff811690508154817fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000821617835560208401356124fc81611e16565b6fffffffffffffffff00000000000000008160401b16837fffffffffffffffffffffffffffffffff00000000000000000000000000000000841617178455505050604082013560018201555050565b81357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe183360301811261257d57600080fd5b8201803567ffffffffffffffff81111561259657600080fd5b602082019150606080820236038313156125af57600080fd5b680100000000000000008211156125c8576125c8611baf565b8354828555808310156126555760017f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808316831461260957612609611f12565b808516851461261a5761261a611f12565b5060008660005260206000208360011b81018660011b820191505b80821015612650578282558284830155600282019150612635565b505050505b5060008481526020902060005b838110156126875761267485836124ad565b9382019360029190910190600101612662565b505050505061249f602083018361212e565b6000604080840183357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18536030181126126d257600080fd5b8401602081810191359067ffffffffffffffff808311156126f257600080fd5b6060808402360385131561270557600080fd5b60408a529483905292936000939060608a015b8486101561275c57863561272b81611e16565b831681528684013561273c81611e16565b831681850152868801358882015295810195600195909501948101612718565b61276960208b018b611f64565b985096508a810360208c0152612780818989611fcf565b9b9a5050505050505050505050565b63ffffffff841681526060602082015260006127ae6060830185612018565b82810360408401526127c08185612699565b9695505050505050565b6020815260006119586020830184612699565b8082018082111561155757611557611f12565b600083516128028184602088016118d7565b8351908301906128168183602088016118d7565b01949350505050565b8181038181111561155757611557611f12565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361286357612863611f12565b5060010190565b67ffffffffffffffff81811683821602808216919082811461288e5761288e611f12565b505092915050565b67ffffffffffffffff8181168382160190808211156128b7576128b7611f12565b509291505056fea164736f6c6343000818000a", + ABI: "[{\"type\":\"function\",\"name\":\"acceptOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getActiveDigest\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getAllConfigs\",\"inputs\":[],\"outputs\":[{\"name\":\"activeConfig\",\"type\":\"tuple\",\"internalType\":\"structRMNHome.VersionedConfig\",\"components\":[{\"name\":\"version\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"configDigest\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"staticConfig\",\"type\":\"tuple\",\"internalType\":\"structRMNHome.StaticConfig\",\"components\":[{\"name\":\"nodes\",\"type\":\"tuple[]\",\"internalType\":\"structRMNHome.Node[]\",\"components\":[{\"name\":\"peerId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"offchainPublicKey\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"offchainConfig\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"dynamicConfig\",\"type\":\"tuple\",\"internalType\":\"structRMNHome.DynamicConfig\",\"components\":[{\"name\":\"sourceChains\",\"type\":\"tuple[]\",\"internalType\":\"structRMNHome.SourceChain[]\",\"components\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"fObserve\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"observerNodesBitmap\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"offchainConfig\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"candidateConfig\",\"type\":\"tuple\",\"internalType\":\"structRMNHome.VersionedConfig\",\"components\":[{\"name\":\"version\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"configDigest\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"staticConfig\",\"type\":\"tuple\",\"internalType\":\"structRMNHome.StaticConfig\",\"components\":[{\"name\":\"nodes\",\"type\":\"tuple[]\",\"internalType\":\"structRMNHome.Node[]\",\"components\":[{\"name\":\"peerId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"offchainPublicKey\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"offchainConfig\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"dynamicConfig\",\"type\":\"tuple\",\"internalType\":\"structRMNHome.DynamicConfig\",\"components\":[{\"name\":\"sourceChains\",\"type\":\"tuple[]\",\"internalType\":\"structRMNHome.SourceChain[]\",\"components\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"fObserve\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"observerNodesBitmap\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"offchainConfig\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCandidateDigest\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getConfig\",\"inputs\":[{\"name\":\"configDigest\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"versionedConfig\",\"type\":\"tuple\",\"internalType\":\"structRMNHome.VersionedConfig\",\"components\":[{\"name\":\"version\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"configDigest\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"staticConfig\",\"type\":\"tuple\",\"internalType\":\"structRMNHome.StaticConfig\",\"components\":[{\"name\":\"nodes\",\"type\":\"tuple[]\",\"internalType\":\"structRMNHome.Node[]\",\"components\":[{\"name\":\"peerId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"offchainPublicKey\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"offchainConfig\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"dynamicConfig\",\"type\":\"tuple\",\"internalType\":\"structRMNHome.DynamicConfig\",\"components\":[{\"name\":\"sourceChains\",\"type\":\"tuple[]\",\"internalType\":\"structRMNHome.SourceChain[]\",\"components\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"fObserve\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"observerNodesBitmap\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"offchainConfig\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"ok\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getConfigDigests\",\"inputs\":[],\"outputs\":[{\"name\":\"activeConfigDigest\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"candidateConfigDigest\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"promoteCandidateAndRevokeActive\",\"inputs\":[{\"name\":\"digestToPromote\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"digestToRevoke\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"revokeCandidate\",\"inputs\":[{\"name\":\"configDigest\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setCandidate\",\"inputs\":[{\"name\":\"staticConfig\",\"type\":\"tuple\",\"internalType\":\"structRMNHome.StaticConfig\",\"components\":[{\"name\":\"nodes\",\"type\":\"tuple[]\",\"internalType\":\"structRMNHome.Node[]\",\"components\":[{\"name\":\"peerId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"offchainPublicKey\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"offchainConfig\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"dynamicConfig\",\"type\":\"tuple\",\"internalType\":\"structRMNHome.DynamicConfig\",\"components\":[{\"name\":\"sourceChains\",\"type\":\"tuple[]\",\"internalType\":\"structRMNHome.SourceChain[]\",\"components\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"fObserve\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"observerNodesBitmap\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"offchainConfig\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"digestToOverwrite\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"newConfigDigest\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setDynamicConfig\",\"inputs\":[{\"name\":\"newDynamicConfig\",\"type\":\"tuple\",\"internalType\":\"structRMNHome.DynamicConfig\",\"components\":[{\"name\":\"sourceChains\",\"type\":\"tuple[]\",\"internalType\":\"structRMNHome.SourceChain[]\",\"components\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"fObserve\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"observerNodesBitmap\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"offchainConfig\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"currentDigest\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"typeAndVersion\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"ActiveConfigRevoked\",\"inputs\":[{\"name\":\"configDigest\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"CandidateConfigRevoked\",\"inputs\":[{\"name\":\"configDigest\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ConfigPromoted\",\"inputs\":[{\"name\":\"configDigest\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ConfigSet\",\"inputs\":[{\"name\":\"configDigest\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"version\",\"type\":\"uint32\",\"indexed\":false,\"internalType\":\"uint32\"},{\"name\":\"staticConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRMNHome.StaticConfig\",\"components\":[{\"name\":\"nodes\",\"type\":\"tuple[]\",\"internalType\":\"structRMNHome.Node[]\",\"components\":[{\"name\":\"peerId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"offchainPublicKey\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"offchainConfig\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"dynamicConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRMNHome.DynamicConfig\",\"components\":[{\"name\":\"sourceChains\",\"type\":\"tuple[]\",\"internalType\":\"structRMNHome.SourceChain[]\",\"components\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"fObserve\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"observerNodesBitmap\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"offchainConfig\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DynamicConfigSet\",\"inputs\":[{\"name\":\"configDigest\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"dynamicConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRMNHome.DynamicConfig\",\"components\":[{\"name\":\"sourceChains\",\"type\":\"tuple[]\",\"internalType\":\"structRMNHome.SourceChain[]\",\"components\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"fObserve\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"observerNodesBitmap\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"offchainConfig\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferRequested\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"CannotTransferToSelf\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ConfigDigestMismatch\",\"inputs\":[{\"name\":\"expectedConfigDigest\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"gotConfigDigest\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"DigestNotFound\",\"inputs\":[{\"name\":\"configDigest\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"DuplicateOffchainPublicKey\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"DuplicatePeerId\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"DuplicateSourceChain\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MustBeProposedOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NoOpStateTransitionNotAllowed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotEnoughObservers\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OnlyCallableByOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OutOfBoundsNodesLength\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OutOfBoundsObserverNodeIndex\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OwnerCannotBeZero\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"RevokingZeroDigestNotAllowed\",\"inputs\":[]}]", + Bin: "0x60808060405234604d573315603c57600180546001600160a01b03191633179055600e80546001600160401b031916905561262690816100538239f35b639b15e16f60e01b60005260046000fd5b600080fdfe6080604052600436101561001257600080fd5b60003560e01c8063118dbac514610904578063123e65db146108ae578063181f5a77146108315780633567e6b4146107b757806338354c5c1461077657806363507956146106985780636dd5b69d1461063b578063736be802146105b457806379ba5097146104cb5780638c76967f146103255780638da5cb5b146102d3578063f2fde38b146101e05763fb4022d4146100ab57600080fd5b346101db5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101db576004356100e56123b4565b80156101b15763ffffffff610105600163ffffffff600e5460201c161890565b1660028110159081610152576006600391020191825481810361018157507f53f5d9228f0a4173bea6e5931c9b3afe6eeb6692ede1d182952970f152534e3b600080a26101525760009055005b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f93df584c0000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b7f0849d8cc0000000000000000000000000000000000000000000000000000000060005260046000fd5b600080fd5b346101db5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101db5760043573ffffffffffffffffffffffffffffffffffffffff81168091036101db576102386123b4565b3381146102a957807fffffffffffffffffffffffff0000000000000000000000000000000000000000600054161760005573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b7fdad89dca0000000000000000000000000000000000000000000000000000000060005260046000fd5b346101db5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101db57602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b346101db5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101db576004356024356103626123b4565b8115806104c3575b6104995763ffffffff610388600163ffffffff600e5460201c161890565b1660028110156101525760060260030154828103610467575063ffffffff600e5460201c166002811015610152576006026003018054828103610467575060009055600e547fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff67ffffffff00000000600163ffffffff8460201c161860201b16911617600e558061043c575b507ffc3e98dbbd47c3fa7c1c05b6ec711caeaf70eca4554192b9ada8fc11a37f298e600080a2005b7f0b31c0055e2d464bef7781994b98c4ff9ef4ae0d05f59feb6a68c42de5e201b8600080a281610414565b90507f93df584c0000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b7f7b4d1e4f0000000000000000000000000000000000000000000000000000000060005260046000fd5b50801561036a565b346101db5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101db5760005473ffffffffffffffffffffffffffffffffffffffff8116330361058a577fffffffffffffffffffffffff00000000000000000000000000000000000000006001549133828416176001551660005573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b7f02b543c60000000000000000000000000000000000000000000000000000000060005260046000fd5b346101db5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101db5760043567ffffffffffffffff81116101db5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82360301126101db576106399061062d6123b4565b60243590600401611f4a565b005b346101db5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101db5761068c610678600435611eea565b6040519283926040845260408401906116d2565b90151560208301520390f35b346101db5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101db576106cf611ca0565b6106d7611ca0565b9063ffffffff600e5460201c1660028110156101525760066106fc9102600201611d92565b602081015161076e575b50600e5460201c63ffffffff166001186002811015610152576107549261073560066107629302600201611d92565b6020810151610766575b506040519384936040855260408501906116d2565b9083820360208501526116d2565b0390f35b90508461073f565b905082610706565b346101db5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101db5760206107af611c65565b604051908152f35b346101db5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101db5763ffffffff600e5460201c1660028110156101525760060260030154600e5460201c63ffffffff16600118906002821015610152576003600660409302015482519182526020820152f35b346101db5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101db576107626040805190610872818361162b565b601182527f524d4e486f6d6520312e362e302d64657600000000000000000000000000000060208301525191829160208352602083019061168f565b346101db5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101db5763ffffffff600e5460201c1660028110156101525760036006602092020154604051908152f35b346101db5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101db5760043567ffffffffffffffff81116101db5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82360301126101db5767ffffffffffffffff602435116101db57602435360360407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8201126101db576109b96123b4565b6040516000916109c8826115a8565b67ffffffffffffffff8460040135116115a4578360040135840190366023830112156115a0576109fb600483013561180a565b610a08604051918261162b565b6004830135808252602082019060061b84016024013681116112ad5760248501915b81831061156f575050508352602485013567ffffffffffffffff811161156b57610a5a9060043691880101611822565b6020840152610a6e366024356004016118ac565b94610100845151116115435790919484955b845151871015610b765760018701808811610b49575b85518051821015610b3c5788610aab916123ff565b5151610ab88288516123ff565b515114610b14576020610acc8988516123ff565b5101516020610adc8389516123ff565b51015114610aec57600101610a96565b6004877fae00651d000000000000000000000000000000000000000000000000000000008152fd5b6004877f221a8ae8000000000000000000000000000000000000000000000000000000008152fd5b5050600190960195610a80565b6024877f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b949390610b8591515190612413565b610b8d611c65565b6044358103611513576114e7575b600e549363ffffffff85169463ffffffff86146114ba5763ffffffff60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000095969701169384911617600e557dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff604051610ccc610cfa6020830160208152610c5784610c2b604082018a600401611a26565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810186528561162b565b602060405191818301957f45564d000000000000000000000000000000000000000000000000000000000087524660408501523060608501528a608085015260808452610ca560a08561162b565b604051958694610cbd858701998a925192839161166c565b8501915180938584019061166c565b0101037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810183528261162b565b519020167e0b0000000000000000000000000000000000000000000000000000000000001793610d35600163ffffffff600e5460201c161890565b600281101561148d576006029182600201866003850155857fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000825416179055600483017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdd85360301856004013512156112a95767ffffffffffffffff6004830135116112a957600482013560061b360360248301136112a9576801000000000000000060048301351161127c578054600483013580835581116113ff575b508752602087208790602483015b600484013583106113db575050505060058201610e246024850185600401611ad9565b9067ffffffffffffffff82116113ae578190610e408454611b2a565b601f811161135e575b508990601f83116001146112bc578a926112b1575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790555b60068201907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdd6024356004013591018112156112ad57602435019060048201359167ffffffffffffffff83116112a95760240160608302360381136112a95768010000000000000000831161127c5781548383558084106111ca575b509087526020872087915b838310611150575050505060070191610f396024803501602435600401611ad9565b67ffffffffffffffff819592951161112357610f558254611b2a565b601f81116110de575b5090859392918760209890601f831160011461101a57907ff6c6d1be15ba0acc8ee645c1ec613c360ef786d2d3200eb8e695b6dec757dbf096978361100f575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790555b611004610ff160405193849384526060898501526060840190600401611a26565b8281036040840152602435600401611b92565b0390a2604051908152f35b013590508980610f9e565b96907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe083168489528a8920985b8181106110c45750917ff6c6d1be15ba0acc8ee645c1ec613c360ef786d2d3200eb8e695b6dec757dbf097989184600195941061108c575b505050811b019055610fd0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88560031b161c1991013516905589808061107f565b828401358a556001909901988a9850918b01918b01611047565b82885260208820601f830160051c81019160208410611119575b601f0160051c01905b81811061110e5750610f5e565b888155600101611101565b90915081906110f8565b6024877f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b600260608267ffffffffffffffff611169600195611b7d565b168554907fffffffffffffffffffffffffffffffff000000000000000000000000000000006fffffffffffffffff00000000000000006111ab60208601611b7d565b60401b1692161717855560408101358486015501920192019190610f17565b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116810361124f577f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8416840361124f57828952602089209060011b8101908460011b015b81811061123d5750610f0c565b808a600292558a600182015501611230565b6024897f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6024887f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b8780fd5b8680fd5b013590508980610e5e565b90917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01691848b5260208b20928b5b818110611346575090846001959493921061130e575b505050811b019055610e90565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88560031b161c19910135169055898080611301565b919360206001819287870135815501950192016112eb565b909150838a5260208a20601f840160051c810191602085106113a4575b90601f859493920160051c01905b8181106113965750610e49565b8b8155849350600101611389565b909150819061137b565b6024897f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b60016002604083600494358655602081013584870155019301930192919050610e01565b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116810361124f5760048301357f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116900361124f57818952602089209060011b810190600484013560011b015b81811061147b5750610df3565b6002908a81558a60018201550161146e565b6024877f4e487b710000000000000000000000000000000000000000000000000000000081526032600452fd5b6024857f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6044357f53f5d9228f0a4173bea6e5931c9b3afe6eeb6692ede1d182952970f152534e3b8480a2610b9b565b7f93df584c0000000000000000000000000000000000000000000000000000000084526004526044803560245283fd5b6004857faf26d5e3000000000000000000000000000000000000000000000000000000008152fd5b8480fd5b6040833603126112a95760206040918251611589816115a8565b853581528286013583820152815201920191610a2a565b8380fd5b8280fd5b6040810190811067ffffffffffffffff8211176115c457604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6060810190811067ffffffffffffffff8211176115c457604052565b6080810190811067ffffffffffffffff8211176115c457604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176115c457604052565b60005b83811061167f5750506000910152565b818101518382015260200161166f565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6020936116cb8151809281875287808801910161166c565b0116010190565b91909163ffffffff81511683526020810151602084015260408101516080604085015260c0840190805191604060808701528251809152602060e0870193019060005b8181106117e85750505060609160206117599201517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808783030160a088015261168f565b910151926060818303910152604081019083519160408252825180915260206060830193019060005b8181106117a65750505060206117a39394015190602081840391015261168f565b90565b909193602060606001926040885167ffffffffffffffff815116835267ffffffffffffffff858201511685840152015160408201520195019101919091611782565b8251805186526020908101518187015260409095019490920191600101611715565b67ffffffffffffffff81116115c45760051b60200190565b81601f820112156101db5780359067ffffffffffffffff82116115c45760405192611875601f84017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0166020018561162b565b828452602083830101116101db57816000926020809301838601378301015290565b359067ffffffffffffffff821682036101db57565b91906040838203126101db57604051906118c5826115a8565b8193803567ffffffffffffffff81116101db57810182601f820112156101db5780356118f08161180a565b916118fe604051938461162b565b818352602060608185019302820101908582116101db57602001915b81831061194d57505050835260208101359167ffffffffffffffff83116101db576020926119489201611822565b910152565b6060838703126101db576020606091604051611968816115f3565b61197186611897565b815261197e838701611897565b838201526040860135604082015281520192019161191a565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1823603018112156101db57016020813591019167ffffffffffffffff82116101db5781360383136101db57565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b9190604081019083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1853603018112156101db5784016020813591019267ffffffffffffffff82116101db578160061b360384136101db578190604084525260608201929060005b818110611ab957505050611aab8460206117a395960190611997565b9160208185039101526119e7565b823585526020808401359086015260409485019490920191600101611a8f565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156101db570180359067ffffffffffffffff82116101db576020019181360383136101db57565b90600182811c92168015611b73575b6020831014611b4457565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f1691611b39565b3567ffffffffffffffff811681036101db5790565b9190604081019083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1853603018112156101db5784016020813591019267ffffffffffffffff82116101db5760608202360384136101db578190604084525260608201929060005b818110611c1757505050611aab8460206117a395960190611997565b90919360608060019267ffffffffffffffff611c3289611897565b16815267ffffffffffffffff611c4a60208a01611897565b16602082015260408881013590820152019501929101611bfb565b600e5460201c63ffffffff166001186002811015610152576006026003015490565b60405190611c94826115a8565b60606020838281520152565b60405190611cad8261160f565b816000815260006020820152611cc1611c87565b60408201526060611948611c87565b9060405191826000825492611ce484611b2a565b8084529360018116908115611d525750600114611d0b575b50611d099250038361162b565b565b90506000929192526020600020906000915b818310611d36575050906020611d099282010138611cfc565b6020919350806001915483858901015201910190918492611d1d565b60209350611d099592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b82010138611cfc565b9060405191611da08361160f565b8263ffffffff8254168152600182015460208201526002820160405190611dc6826115a8565b8054611dd18161180a565b91611ddf604051938461162b565b818352602083019060005260206000206000915b838310611ebd57505050508152611e0c60038401611cd0565b60208201526040820152600482019160405192611e28846115a8565b8054611e338161180a565b91611e41604051938461162b565b818352602083019060005260206000206000915b838310611e7b5750505050600560609392611e7292865201611cd0565b60208401520152565b60026020600192604051611e8e816115f3565b67ffffffffffffffff8654818116835260401c1683820152848601546040820152815201920192019190611e55565b60026020600192604051611ed0816115a8565b855481528486015483820152815201920192019190611df3565b611ef2611ca0565b9060005b6002811015611f4257600060068202908360038301541480611f39575b611f21575050600101611ef6565b91509150611f33925050600201611d92565b90600190565b50831515611f13565b505090600090565b9060005b60028110156123865760006006820290836003830154148061237d575b611f79575050600101611f4e565b90915092919250611f976004820154611f9236856118ac565b612413565b6000906006810183357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1853603018112156115a05784019081359167ffffffffffffffff831161156b57602001606083023603811361156b5768010000000000000000831161235057815483835580841061229e575b509084526020842084915b8383106122245750505050600701906120346020840184611ad9565b919067ffffffffffffffff83116121f75761204f8454611b2a565b601f81116121b2575b5081601f84116001146120ec57926120dc949281927f1f69d1a2edb327babc986b3deb80091f101b9105d42a6c30db4d99c31d7e62949795926120e1575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790555b604051918291602083526020830190611b92565b0390a2565b013590503880612096565b917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0841685845260208420935b81811061219a57509260019285927f1f69d1a2edb327babc986b3deb80091f101b9105d42a6c30db4d99c31d7e629498966120dc989610612162575b505050811b0190556120c8565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88560031b161c19910135169055388080612155565b91936020600181928787013581550195019201612119565b84835260208320601f850160051c810191602086106121ed575b601f0160051c01905b8181106121e25750612058565b8381556001016121d5565b90915081906121cc565b6024827f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b600260608267ffffffffffffffff61223d600195611b7d565b168554907fffffffffffffffffffffffffffffffff000000000000000000000000000000006fffffffffffffffff000000000000000061227f60208601611b7d565b60401b1692161717855560408101358486015501920192019190612018565b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81168103612323577f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8416840361232357828652602086209060011b8101908460011b015b818110612311575061200d565b80876002925587600182015501612304565b6024867f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6024857f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b50831515611f6b565b507fd0b2c0310000000000000000000000000000000000000000000000000000000060005260045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff6001541633036123d557565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b80518210156101525760209160051b010190565b908151519160005b8381106124285750505050565b6124338183516123ff565b5160018201808311612508575b8581106125bf575060408101519084610100036101008111612508577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83911c81160361259557816000925b61253757506020015160011b6801fffffffffffffffe67fffffffffffffffe8216911681036125085760010167ffffffffffffffff81116125085767ffffffffffffffff16116124de5760010161241b565b7fa804bcb30000000000000000000000000000000000000000000000000000000060005260046000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101908082116125085716917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461250857600101918061248c565b7f2847b6060000000000000000000000000000000000000000000000000000000060005260046000fd5b67ffffffffffffffff82511667ffffffffffffffff6125df8387516123ff565b515116146125ef57600101612440565b7f3857f84d0000000000000000000000000000000000000000000000000000000060005260046000fdfea164736f6c634300081a000a", } var RMNHomeABI = RMNHomeMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/rmn_proxy_contract/rmn_proxy_contract.go b/core/gethwrappers/ccip/generated/rmn_proxy_contract/rmn_proxy_contract.go index 18fd9898d81..6bf174bfef1 100644 --- a/core/gethwrappers/ccip/generated/rmn_proxy_contract/rmn_proxy_contract.go +++ b/core/gethwrappers/ccip/generated/rmn_proxy_contract/rmn_proxy_contract.go @@ -30,17 +30,17 @@ var ( _ = abi.ConvertType ) -var RMNProxyContractMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"arm\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"arm\",\"type\":\"address\"}],\"name\":\"ARMSet\",\"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\"},{\"stateMutability\":\"nonpayable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getARM\",\"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\":\"address\",\"name\":\"arm\",\"type\":\"address\"}],\"name\":\"setARM\",\"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\"}]", - Bin: "0x608060405234801561001057600080fd5b5060405161084138038061084183398101604081905261002f91610255565b33806000816100855760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156100b5576100b5816100cd565b5050506100c78161017660201b60201c565b50610285565b336001600160a01b038216036101255760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161007c565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61017e6101f9565b6001600160a01b0381166101a5576040516342bcdf7f60e11b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fef31f568d741a833c6a9dc85a6e1c65e06fa772740d5dc94d1da21827a4e0cab9060200160405180910390a150565b6000546001600160a01b031633146102535760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161007c565b565b60006020828403121561026757600080fd5b81516001600160a01b038116811461027e57600080fd5b9392505050565b6105ad806102946000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806379ba50971161005057806379ba5097146101615780638da5cb5b14610169578063f2fde38b1461018757610072565b8063181f5a77146100bb5780632e90aa211461010d578063458fec3b1461014c575b60025473ffffffffffffffffffffffffffffffffffffffff16803b61009657600080fd5b366000803760008036600080855af13d6000803e80156100b5573d6000f35b503d6000fd5b6100f76040518060400160405280600e81526020017f41524d50726f787920312e302e3000000000000000000000000000000000000081525081565b60405161010491906104f6565b60405180910390f35b60025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610104565b61015f61015a366004610563565b61019a565b005b61015f610268565b60005473ffffffffffffffffffffffffffffffffffffffff16610127565b61015f610195366004610563565b61036a565b6101a261037e565b73ffffffffffffffffffffffffffffffffffffffff81166101ef576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fef31f568d741a833c6a9dc85a6e1c65e06fa772740d5dc94d1da21827a4e0cab9060200160405180910390a150565b60015473ffffffffffffffffffffffffffffffffffffffff1633146102ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61037261037e565b61037b81610401565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146103ff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016102e5565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016102e5565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60006020808352835180602085015260005b8181101561052457858101830151858201604001528201610508565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b60006020828403121561057557600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461059957600080fd5b939250505056fea164736f6c6343000818000a", +var RMNProxyMetaData = &bind.MetaData{ + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"arm\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"fallback\",\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"acceptOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getARM\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"setARM\",\"inputs\":[{\"name\":\"arm\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"typeAndVersion\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"ARMSet\",\"inputs\":[{\"name\":\"arm\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferRequested\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"ZeroAddressNotAllowed\",\"inputs\":[]}]", + Bin: "0x60803461012f5760009061079a3881900390601f8201601f191683016001600160401b0381118482101761011b579180849260209460405283398101031261011757516001600160a01b03811691908290036101145733156100cf5780546001600160a01b0319163317905580156100be57600280546001600160a01b031916821790556040519081527fef31f568d741a833c6a9dc85a6e1c65e06fa772740d5dc94d1da21827a4e0cab90602090a160405161066590816101358239f35b6342bcdf7f60e11b60005260046000fd5b60405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f00000000000000006044820152606490fd5b80fd5b5080fd5b634e487b7160e01b85526041600452602485fd5b600080fdfe6080604052600436101561001a575b3415610598575b600080fd5b60003560e01c8063181f5a771461007a5780632e90aa2114610075578063458fec3b1461007057806379ba50971461006b5780638da5cb5b146100665763f2fde38b0361000e5761049b565b610449565b6102ee565b61023b565b61019c565b346100155760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261001557604051604081019080821067ffffffffffffffff8311176101055761010191604052600e81527f41524d50726f787920312e302e30000000000000000000000000000000000000602082015260405191829182610134565b0390f35b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b9190916020815282519283602083015260005b8481106101865750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006040809697860101520116010190565b8060208092840101516040828601015201610147565b346100155760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261001557602073ffffffffffffffffffffffffffffffffffffffff60025416604051908152f35b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60209101126100155760043573ffffffffffffffffffffffffffffffffffffffff811681036100155790565b346100155773ffffffffffffffffffffffffffffffffffffffff61025e366101ee565b6102666105d9565b1680156102c4576020817fef31f568d741a833c6a9dc85a6e1c65e06fa772740d5dc94d1da21827a4e0cab927fffffffffffffffffffffffff00000000000000000000000000000000000000006002541617600255604051908152a1005b7f8579befe0000000000000000000000000000000000000000000000000000000060005260046000fd5b346100155760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100155773ffffffffffffffffffffffffffffffffffffffff6001541633036103eb5760005473ffffffffffffffffffffffffffffffffffffffff16600080547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790556103ac7fffffffffffffffffffffffff000000000000000000000000000000000000000060015416600155565b73ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152fd5b346100155760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261001557602073ffffffffffffffffffffffffffffffffffffffff60005416604051908152f35b346100155773ffffffffffffffffffffffffffffffffffffffff6104be366101ee565b6104c66105d9565b1633811461053a57807fffffffffffffffffffffffff0000000000000000000000000000000000000000600154161760015573ffffffffffffffffffffffffffffffffffffffff8060005416167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152fd5b73ffffffffffffffffffffffffffffffffffffffff60025416803b15610015576000809136828037818036925af13d6000803e6105d4573d6000fd5b3d6000f35b73ffffffffffffffffffffffffffffffffffffffff6000541633036105fa57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152fdfea164736f6c634300081a000a", } -var RMNProxyContractABI = RMNProxyContractMetaData.ABI +var RMNProxyABI = RMNProxyMetaData.ABI -var RMNProxyContractBin = RMNProxyContractMetaData.Bin +var RMNProxyBin = RMNProxyMetaData.Bin -func DeployRMNProxyContract(auth *bind.TransactOpts, backend bind.ContractBackend, arm common.Address) (common.Address, *types.Transaction, *RMNProxyContract, error) { - parsed, err := RMNProxyContractMetaData.GetAbi() +func DeployRMNProxy(auth *bind.TransactOpts, backend bind.ContractBackend, arm common.Address) (common.Address, *types.Transaction, *RMNProxy, error) { + parsed, err := RMNProxyMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err } @@ -48,132 +48,132 @@ func DeployRMNProxyContract(auth *bind.TransactOpts, backend bind.ContractBacken return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(RMNProxyContractBin), backend, arm) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(RMNProxyBin), backend, arm) if err != nil { return common.Address{}, nil, nil, err } - return address, tx, &RMNProxyContract{address: address, abi: *parsed, RMNProxyContractCaller: RMNProxyContractCaller{contract: contract}, RMNProxyContractTransactor: RMNProxyContractTransactor{contract: contract}, RMNProxyContractFilterer: RMNProxyContractFilterer{contract: contract}}, nil + return address, tx, &RMNProxy{address: address, abi: *parsed, RMNProxyCaller: RMNProxyCaller{contract: contract}, RMNProxyTransactor: RMNProxyTransactor{contract: contract}, RMNProxyFilterer: RMNProxyFilterer{contract: contract}}, nil } -type RMNProxyContract struct { +type RMNProxy struct { address common.Address abi abi.ABI - RMNProxyContractCaller - RMNProxyContractTransactor - RMNProxyContractFilterer + RMNProxyCaller + RMNProxyTransactor + RMNProxyFilterer } -type RMNProxyContractCaller struct { +type RMNProxyCaller struct { contract *bind.BoundContract } -type RMNProxyContractTransactor struct { +type RMNProxyTransactor struct { contract *bind.BoundContract } -type RMNProxyContractFilterer struct { +type RMNProxyFilterer struct { contract *bind.BoundContract } -type RMNProxyContractSession struct { - Contract *RMNProxyContract +type RMNProxySession struct { + Contract *RMNProxy CallOpts bind.CallOpts TransactOpts bind.TransactOpts } -type RMNProxyContractCallerSession struct { - Contract *RMNProxyContractCaller +type RMNProxyCallerSession struct { + Contract *RMNProxyCaller CallOpts bind.CallOpts } -type RMNProxyContractTransactorSession struct { - Contract *RMNProxyContractTransactor +type RMNProxyTransactorSession struct { + Contract *RMNProxyTransactor TransactOpts bind.TransactOpts } -type RMNProxyContractRaw struct { - Contract *RMNProxyContract +type RMNProxyRaw struct { + Contract *RMNProxy } -type RMNProxyContractCallerRaw struct { - Contract *RMNProxyContractCaller +type RMNProxyCallerRaw struct { + Contract *RMNProxyCaller } -type RMNProxyContractTransactorRaw struct { - Contract *RMNProxyContractTransactor +type RMNProxyTransactorRaw struct { + Contract *RMNProxyTransactor } -func NewRMNProxyContract(address common.Address, backend bind.ContractBackend) (*RMNProxyContract, error) { - abi, err := abi.JSON(strings.NewReader(RMNProxyContractABI)) +func NewRMNProxy(address common.Address, backend bind.ContractBackend) (*RMNProxy, error) { + abi, err := abi.JSON(strings.NewReader(RMNProxyABI)) if err != nil { return nil, err } - contract, err := bindRMNProxyContract(address, backend, backend, backend) + contract, err := bindRMNProxy(address, backend, backend, backend) if err != nil { return nil, err } - return &RMNProxyContract{address: address, abi: abi, RMNProxyContractCaller: RMNProxyContractCaller{contract: contract}, RMNProxyContractTransactor: RMNProxyContractTransactor{contract: contract}, RMNProxyContractFilterer: RMNProxyContractFilterer{contract: contract}}, nil + return &RMNProxy{address: address, abi: abi, RMNProxyCaller: RMNProxyCaller{contract: contract}, RMNProxyTransactor: RMNProxyTransactor{contract: contract}, RMNProxyFilterer: RMNProxyFilterer{contract: contract}}, nil } -func NewRMNProxyContractCaller(address common.Address, caller bind.ContractCaller) (*RMNProxyContractCaller, error) { - contract, err := bindRMNProxyContract(address, caller, nil, nil) +func NewRMNProxyCaller(address common.Address, caller bind.ContractCaller) (*RMNProxyCaller, error) { + contract, err := bindRMNProxy(address, caller, nil, nil) if err != nil { return nil, err } - return &RMNProxyContractCaller{contract: contract}, nil + return &RMNProxyCaller{contract: contract}, nil } -func NewRMNProxyContractTransactor(address common.Address, transactor bind.ContractTransactor) (*RMNProxyContractTransactor, error) { - contract, err := bindRMNProxyContract(address, nil, transactor, nil) +func NewRMNProxyTransactor(address common.Address, transactor bind.ContractTransactor) (*RMNProxyTransactor, error) { + contract, err := bindRMNProxy(address, nil, transactor, nil) if err != nil { return nil, err } - return &RMNProxyContractTransactor{contract: contract}, nil + return &RMNProxyTransactor{contract: contract}, nil } -func NewRMNProxyContractFilterer(address common.Address, filterer bind.ContractFilterer) (*RMNProxyContractFilterer, error) { - contract, err := bindRMNProxyContract(address, nil, nil, filterer) +func NewRMNProxyFilterer(address common.Address, filterer bind.ContractFilterer) (*RMNProxyFilterer, error) { + contract, err := bindRMNProxy(address, nil, nil, filterer) if err != nil { return nil, err } - return &RMNProxyContractFilterer{contract: contract}, nil + return &RMNProxyFilterer{contract: contract}, nil } -func bindRMNProxyContract(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := RMNProxyContractMetaData.GetAbi() +func bindRMNProxy(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := RMNProxyMetaData.GetAbi() if err != nil { return nil, err } return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } -func (_RMNProxyContract *RMNProxyContractRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _RMNProxyContract.Contract.RMNProxyContractCaller.contract.Call(opts, result, method, params...) +func (_RMNProxy *RMNProxyRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _RMNProxy.Contract.RMNProxyCaller.contract.Call(opts, result, method, params...) } -func (_RMNProxyContract *RMNProxyContractRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _RMNProxyContract.Contract.RMNProxyContractTransactor.contract.Transfer(opts) +func (_RMNProxy *RMNProxyRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _RMNProxy.Contract.RMNProxyTransactor.contract.Transfer(opts) } -func (_RMNProxyContract *RMNProxyContractRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _RMNProxyContract.Contract.RMNProxyContractTransactor.contract.Transact(opts, method, params...) +func (_RMNProxy *RMNProxyRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _RMNProxy.Contract.RMNProxyTransactor.contract.Transact(opts, method, params...) } -func (_RMNProxyContract *RMNProxyContractCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _RMNProxyContract.Contract.contract.Call(opts, result, method, params...) +func (_RMNProxy *RMNProxyCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _RMNProxy.Contract.contract.Call(opts, result, method, params...) } -func (_RMNProxyContract *RMNProxyContractTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _RMNProxyContract.Contract.contract.Transfer(opts) +func (_RMNProxy *RMNProxyTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _RMNProxy.Contract.contract.Transfer(opts) } -func (_RMNProxyContract *RMNProxyContractTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _RMNProxyContract.Contract.contract.Transact(opts, method, params...) +func (_RMNProxy *RMNProxyTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _RMNProxy.Contract.contract.Transact(opts, method, params...) } -func (_RMNProxyContract *RMNProxyContractCaller) GetARM(opts *bind.CallOpts) (common.Address, error) { +func (_RMNProxy *RMNProxyCaller) GetARM(opts *bind.CallOpts) (common.Address, error) { var out []interface{} - err := _RMNProxyContract.contract.Call(opts, &out, "getARM") + err := _RMNProxy.contract.Call(opts, &out, "getARM") if err != nil { return *new(common.Address), err @@ -185,17 +185,17 @@ func (_RMNProxyContract *RMNProxyContractCaller) GetARM(opts *bind.CallOpts) (co } -func (_RMNProxyContract *RMNProxyContractSession) GetARM() (common.Address, error) { - return _RMNProxyContract.Contract.GetARM(&_RMNProxyContract.CallOpts) +func (_RMNProxy *RMNProxySession) GetARM() (common.Address, error) { + return _RMNProxy.Contract.GetARM(&_RMNProxy.CallOpts) } -func (_RMNProxyContract *RMNProxyContractCallerSession) GetARM() (common.Address, error) { - return _RMNProxyContract.Contract.GetARM(&_RMNProxyContract.CallOpts) +func (_RMNProxy *RMNProxyCallerSession) GetARM() (common.Address, error) { + return _RMNProxy.Contract.GetARM(&_RMNProxy.CallOpts) } -func (_RMNProxyContract *RMNProxyContractCaller) Owner(opts *bind.CallOpts) (common.Address, error) { +func (_RMNProxy *RMNProxyCaller) Owner(opts *bind.CallOpts) (common.Address, error) { var out []interface{} - err := _RMNProxyContract.contract.Call(opts, &out, "owner") + err := _RMNProxy.contract.Call(opts, &out, "owner") if err != nil { return *new(common.Address), err @@ -207,17 +207,17 @@ func (_RMNProxyContract *RMNProxyContractCaller) Owner(opts *bind.CallOpts) (com } -func (_RMNProxyContract *RMNProxyContractSession) Owner() (common.Address, error) { - return _RMNProxyContract.Contract.Owner(&_RMNProxyContract.CallOpts) +func (_RMNProxy *RMNProxySession) Owner() (common.Address, error) { + return _RMNProxy.Contract.Owner(&_RMNProxy.CallOpts) } -func (_RMNProxyContract *RMNProxyContractCallerSession) Owner() (common.Address, error) { - return _RMNProxyContract.Contract.Owner(&_RMNProxyContract.CallOpts) +func (_RMNProxy *RMNProxyCallerSession) Owner() (common.Address, error) { + return _RMNProxy.Contract.Owner(&_RMNProxy.CallOpts) } -func (_RMNProxyContract *RMNProxyContractCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { +func (_RMNProxy *RMNProxyCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { var out []interface{} - err := _RMNProxyContract.contract.Call(opts, &out, "typeAndVersion") + err := _RMNProxy.contract.Call(opts, &out, "typeAndVersion") if err != nil { return *new(string), err @@ -229,64 +229,64 @@ func (_RMNProxyContract *RMNProxyContractCaller) TypeAndVersion(opts *bind.CallO } -func (_RMNProxyContract *RMNProxyContractSession) TypeAndVersion() (string, error) { - return _RMNProxyContract.Contract.TypeAndVersion(&_RMNProxyContract.CallOpts) +func (_RMNProxy *RMNProxySession) TypeAndVersion() (string, error) { + return _RMNProxy.Contract.TypeAndVersion(&_RMNProxy.CallOpts) } -func (_RMNProxyContract *RMNProxyContractCallerSession) TypeAndVersion() (string, error) { - return _RMNProxyContract.Contract.TypeAndVersion(&_RMNProxyContract.CallOpts) +func (_RMNProxy *RMNProxyCallerSession) TypeAndVersion() (string, error) { + return _RMNProxy.Contract.TypeAndVersion(&_RMNProxy.CallOpts) } -func (_RMNProxyContract *RMNProxyContractTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - return _RMNProxyContract.contract.Transact(opts, "acceptOwnership") +func (_RMNProxy *RMNProxyTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _RMNProxy.contract.Transact(opts, "acceptOwnership") } -func (_RMNProxyContract *RMNProxyContractSession) AcceptOwnership() (*types.Transaction, error) { - return _RMNProxyContract.Contract.AcceptOwnership(&_RMNProxyContract.TransactOpts) +func (_RMNProxy *RMNProxySession) AcceptOwnership() (*types.Transaction, error) { + return _RMNProxy.Contract.AcceptOwnership(&_RMNProxy.TransactOpts) } -func (_RMNProxyContract *RMNProxyContractTransactorSession) AcceptOwnership() (*types.Transaction, error) { - return _RMNProxyContract.Contract.AcceptOwnership(&_RMNProxyContract.TransactOpts) +func (_RMNProxy *RMNProxyTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _RMNProxy.Contract.AcceptOwnership(&_RMNProxy.TransactOpts) } -func (_RMNProxyContract *RMNProxyContractTransactor) SetARM(opts *bind.TransactOpts, arm common.Address) (*types.Transaction, error) { - return _RMNProxyContract.contract.Transact(opts, "setARM", arm) +func (_RMNProxy *RMNProxyTransactor) SetARM(opts *bind.TransactOpts, arm common.Address) (*types.Transaction, error) { + return _RMNProxy.contract.Transact(opts, "setARM", arm) } -func (_RMNProxyContract *RMNProxyContractSession) SetARM(arm common.Address) (*types.Transaction, error) { - return _RMNProxyContract.Contract.SetARM(&_RMNProxyContract.TransactOpts, arm) +func (_RMNProxy *RMNProxySession) SetARM(arm common.Address) (*types.Transaction, error) { + return _RMNProxy.Contract.SetARM(&_RMNProxy.TransactOpts, arm) } -func (_RMNProxyContract *RMNProxyContractTransactorSession) SetARM(arm common.Address) (*types.Transaction, error) { - return _RMNProxyContract.Contract.SetARM(&_RMNProxyContract.TransactOpts, arm) +func (_RMNProxy *RMNProxyTransactorSession) SetARM(arm common.Address) (*types.Transaction, error) { + return _RMNProxy.Contract.SetARM(&_RMNProxy.TransactOpts, arm) } -func (_RMNProxyContract *RMNProxyContractTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { - return _RMNProxyContract.contract.Transact(opts, "transferOwnership", to) +func (_RMNProxy *RMNProxyTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _RMNProxy.contract.Transact(opts, "transferOwnership", to) } -func (_RMNProxyContract *RMNProxyContractSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _RMNProxyContract.Contract.TransferOwnership(&_RMNProxyContract.TransactOpts, to) +func (_RMNProxy *RMNProxySession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _RMNProxy.Contract.TransferOwnership(&_RMNProxy.TransactOpts, to) } -func (_RMNProxyContract *RMNProxyContractTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _RMNProxyContract.Contract.TransferOwnership(&_RMNProxyContract.TransactOpts, to) +func (_RMNProxy *RMNProxyTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _RMNProxy.Contract.TransferOwnership(&_RMNProxy.TransactOpts, to) } -func (_RMNProxyContract *RMNProxyContractTransactor) Fallback(opts *bind.TransactOpts, calldata []byte) (*types.Transaction, error) { - return _RMNProxyContract.contract.RawTransact(opts, calldata) +func (_RMNProxy *RMNProxyTransactor) Fallback(opts *bind.TransactOpts, calldata []byte) (*types.Transaction, error) { + return _RMNProxy.contract.RawTransact(opts, calldata) } -func (_RMNProxyContract *RMNProxyContractSession) Fallback(calldata []byte) (*types.Transaction, error) { - return _RMNProxyContract.Contract.Fallback(&_RMNProxyContract.TransactOpts, calldata) +func (_RMNProxy *RMNProxySession) Fallback(calldata []byte) (*types.Transaction, error) { + return _RMNProxy.Contract.Fallback(&_RMNProxy.TransactOpts, calldata) } -func (_RMNProxyContract *RMNProxyContractTransactorSession) Fallback(calldata []byte) (*types.Transaction, error) { - return _RMNProxyContract.Contract.Fallback(&_RMNProxyContract.TransactOpts, calldata) +func (_RMNProxy *RMNProxyTransactorSession) Fallback(calldata []byte) (*types.Transaction, error) { + return _RMNProxy.Contract.Fallback(&_RMNProxy.TransactOpts, calldata) } -type RMNProxyContractARMSetIterator struct { - Event *RMNProxyContractARMSet +type RMNProxyARMSetIterator struct { + Event *RMNProxyARMSet contract *bind.BoundContract event string @@ -297,7 +297,7 @@ type RMNProxyContractARMSetIterator struct { fail error } -func (it *RMNProxyContractARMSetIterator) Next() bool { +func (it *RMNProxyARMSetIterator) Next() bool { if it.fail != nil { return false @@ -306,7 +306,7 @@ func (it *RMNProxyContractARMSetIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(RMNProxyContractARMSet) + it.Event = new(RMNProxyARMSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -321,7 +321,7 @@ func (it *RMNProxyContractARMSetIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(RMNProxyContractARMSet) + it.Event = new(RMNProxyARMSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -336,32 +336,32 @@ func (it *RMNProxyContractARMSetIterator) Next() bool { } } -func (it *RMNProxyContractARMSetIterator) Error() error { +func (it *RMNProxyARMSetIterator) Error() error { return it.fail } -func (it *RMNProxyContractARMSetIterator) Close() error { +func (it *RMNProxyARMSetIterator) Close() error { it.sub.Unsubscribe() return nil } -type RMNProxyContractARMSet struct { +type RMNProxyARMSet struct { Arm common.Address Raw types.Log } -func (_RMNProxyContract *RMNProxyContractFilterer) FilterARMSet(opts *bind.FilterOpts) (*RMNProxyContractARMSetIterator, error) { +func (_RMNProxy *RMNProxyFilterer) FilterARMSet(opts *bind.FilterOpts) (*RMNProxyARMSetIterator, error) { - logs, sub, err := _RMNProxyContract.contract.FilterLogs(opts, "ARMSet") + logs, sub, err := _RMNProxy.contract.FilterLogs(opts, "ARMSet") if err != nil { return nil, err } - return &RMNProxyContractARMSetIterator{contract: _RMNProxyContract.contract, event: "ARMSet", logs: logs, sub: sub}, nil + return &RMNProxyARMSetIterator{contract: _RMNProxy.contract, event: "ARMSet", logs: logs, sub: sub}, nil } -func (_RMNProxyContract *RMNProxyContractFilterer) WatchARMSet(opts *bind.WatchOpts, sink chan<- *RMNProxyContractARMSet) (event.Subscription, error) { +func (_RMNProxy *RMNProxyFilterer) WatchARMSet(opts *bind.WatchOpts, sink chan<- *RMNProxyARMSet) (event.Subscription, error) { - logs, sub, err := _RMNProxyContract.contract.WatchLogs(opts, "ARMSet") + logs, sub, err := _RMNProxy.contract.WatchLogs(opts, "ARMSet") if err != nil { return nil, err } @@ -371,8 +371,8 @@ func (_RMNProxyContract *RMNProxyContractFilterer) WatchARMSet(opts *bind.WatchO select { case log := <-logs: - event := new(RMNProxyContractARMSet) - if err := _RMNProxyContract.contract.UnpackLog(event, "ARMSet", log); err != nil { + event := new(RMNProxyARMSet) + if err := _RMNProxy.contract.UnpackLog(event, "ARMSet", log); err != nil { return err } event.Raw = log @@ -393,17 +393,17 @@ func (_RMNProxyContract *RMNProxyContractFilterer) WatchARMSet(opts *bind.WatchO }), nil } -func (_RMNProxyContract *RMNProxyContractFilterer) ParseARMSet(log types.Log) (*RMNProxyContractARMSet, error) { - event := new(RMNProxyContractARMSet) - if err := _RMNProxyContract.contract.UnpackLog(event, "ARMSet", log); err != nil { +func (_RMNProxy *RMNProxyFilterer) ParseARMSet(log types.Log) (*RMNProxyARMSet, error) { + event := new(RMNProxyARMSet) + if err := _RMNProxy.contract.UnpackLog(event, "ARMSet", log); err != nil { return nil, err } event.Raw = log return event, nil } -type RMNProxyContractOwnershipTransferRequestedIterator struct { - Event *RMNProxyContractOwnershipTransferRequested +type RMNProxyOwnershipTransferRequestedIterator struct { + Event *RMNProxyOwnershipTransferRequested contract *bind.BoundContract event string @@ -414,7 +414,7 @@ type RMNProxyContractOwnershipTransferRequestedIterator struct { fail error } -func (it *RMNProxyContractOwnershipTransferRequestedIterator) Next() bool { +func (it *RMNProxyOwnershipTransferRequestedIterator) Next() bool { if it.fail != nil { return false @@ -423,7 +423,7 @@ func (it *RMNProxyContractOwnershipTransferRequestedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(RMNProxyContractOwnershipTransferRequested) + it.Event = new(RMNProxyOwnershipTransferRequested) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -438,7 +438,7 @@ func (it *RMNProxyContractOwnershipTransferRequestedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(RMNProxyContractOwnershipTransferRequested) + it.Event = new(RMNProxyOwnershipTransferRequested) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -453,22 +453,22 @@ func (it *RMNProxyContractOwnershipTransferRequestedIterator) Next() bool { } } -func (it *RMNProxyContractOwnershipTransferRequestedIterator) Error() error { +func (it *RMNProxyOwnershipTransferRequestedIterator) Error() error { return it.fail } -func (it *RMNProxyContractOwnershipTransferRequestedIterator) Close() error { +func (it *RMNProxyOwnershipTransferRequestedIterator) Close() error { it.sub.Unsubscribe() return nil } -type RMNProxyContractOwnershipTransferRequested struct { +type RMNProxyOwnershipTransferRequested struct { From common.Address To common.Address Raw types.Log } -func (_RMNProxyContract *RMNProxyContractFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RMNProxyContractOwnershipTransferRequestedIterator, error) { +func (_RMNProxy *RMNProxyFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RMNProxyOwnershipTransferRequestedIterator, error) { var fromRule []interface{} for _, fromItem := range from { @@ -479,14 +479,14 @@ func (_RMNProxyContract *RMNProxyContractFilterer) FilterOwnershipTransferReques toRule = append(toRule, toItem) } - logs, sub, err := _RMNProxyContract.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + logs, sub, err := _RMNProxy.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) if err != nil { return nil, err } - return &RMNProxyContractOwnershipTransferRequestedIterator{contract: _RMNProxyContract.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil + return &RMNProxyOwnershipTransferRequestedIterator{contract: _RMNProxy.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil } -func (_RMNProxyContract *RMNProxyContractFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *RMNProxyContractOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { +func (_RMNProxy *RMNProxyFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *RMNProxyOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { var fromRule []interface{} for _, fromItem := range from { @@ -497,7 +497,7 @@ func (_RMNProxyContract *RMNProxyContractFilterer) WatchOwnershipTransferRequest toRule = append(toRule, toItem) } - logs, sub, err := _RMNProxyContract.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + logs, sub, err := _RMNProxy.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) if err != nil { return nil, err } @@ -507,8 +507,8 @@ func (_RMNProxyContract *RMNProxyContractFilterer) WatchOwnershipTransferRequest select { case log := <-logs: - event := new(RMNProxyContractOwnershipTransferRequested) - if err := _RMNProxyContract.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + event := new(RMNProxyOwnershipTransferRequested) + if err := _RMNProxy.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { return err } event.Raw = log @@ -529,17 +529,17 @@ func (_RMNProxyContract *RMNProxyContractFilterer) WatchOwnershipTransferRequest }), nil } -func (_RMNProxyContract *RMNProxyContractFilterer) ParseOwnershipTransferRequested(log types.Log) (*RMNProxyContractOwnershipTransferRequested, error) { - event := new(RMNProxyContractOwnershipTransferRequested) - if err := _RMNProxyContract.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { +func (_RMNProxy *RMNProxyFilterer) ParseOwnershipTransferRequested(log types.Log) (*RMNProxyOwnershipTransferRequested, error) { + event := new(RMNProxyOwnershipTransferRequested) + if err := _RMNProxy.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { return nil, err } event.Raw = log return event, nil } -type RMNProxyContractOwnershipTransferredIterator struct { - Event *RMNProxyContractOwnershipTransferred +type RMNProxyOwnershipTransferredIterator struct { + Event *RMNProxyOwnershipTransferred contract *bind.BoundContract event string @@ -550,7 +550,7 @@ type RMNProxyContractOwnershipTransferredIterator struct { fail error } -func (it *RMNProxyContractOwnershipTransferredIterator) Next() bool { +func (it *RMNProxyOwnershipTransferredIterator) Next() bool { if it.fail != nil { return false @@ -559,7 +559,7 @@ func (it *RMNProxyContractOwnershipTransferredIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(RMNProxyContractOwnershipTransferred) + it.Event = new(RMNProxyOwnershipTransferred) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -574,7 +574,7 @@ func (it *RMNProxyContractOwnershipTransferredIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(RMNProxyContractOwnershipTransferred) + it.Event = new(RMNProxyOwnershipTransferred) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -589,22 +589,22 @@ func (it *RMNProxyContractOwnershipTransferredIterator) Next() bool { } } -func (it *RMNProxyContractOwnershipTransferredIterator) Error() error { +func (it *RMNProxyOwnershipTransferredIterator) Error() error { return it.fail } -func (it *RMNProxyContractOwnershipTransferredIterator) Close() error { +func (it *RMNProxyOwnershipTransferredIterator) Close() error { it.sub.Unsubscribe() return nil } -type RMNProxyContractOwnershipTransferred struct { +type RMNProxyOwnershipTransferred struct { From common.Address To common.Address Raw types.Log } -func (_RMNProxyContract *RMNProxyContractFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RMNProxyContractOwnershipTransferredIterator, error) { +func (_RMNProxy *RMNProxyFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RMNProxyOwnershipTransferredIterator, error) { var fromRule []interface{} for _, fromItem := range from { @@ -615,14 +615,14 @@ func (_RMNProxyContract *RMNProxyContractFilterer) FilterOwnershipTransferred(op toRule = append(toRule, toItem) } - logs, sub, err := _RMNProxyContract.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + logs, sub, err := _RMNProxy.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) if err != nil { return nil, err } - return &RMNProxyContractOwnershipTransferredIterator{contract: _RMNProxyContract.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil + return &RMNProxyOwnershipTransferredIterator{contract: _RMNProxy.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil } -func (_RMNProxyContract *RMNProxyContractFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *RMNProxyContractOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { +func (_RMNProxy *RMNProxyFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *RMNProxyOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { var fromRule []interface{} for _, fromItem := range from { @@ -633,7 +633,7 @@ func (_RMNProxyContract *RMNProxyContractFilterer) WatchOwnershipTransferred(opt toRule = append(toRule, toItem) } - logs, sub, err := _RMNProxyContract.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) + logs, sub, err := _RMNProxy.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) if err != nil { return nil, err } @@ -643,8 +643,8 @@ func (_RMNProxyContract *RMNProxyContractFilterer) WatchOwnershipTransferred(opt select { case log := <-logs: - event := new(RMNProxyContractOwnershipTransferred) - if err := _RMNProxyContract.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + event := new(RMNProxyOwnershipTransferred) + if err := _RMNProxy.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { return err } event.Raw = log @@ -665,46 +665,46 @@ func (_RMNProxyContract *RMNProxyContractFilterer) WatchOwnershipTransferred(opt }), nil } -func (_RMNProxyContract *RMNProxyContractFilterer) ParseOwnershipTransferred(log types.Log) (*RMNProxyContractOwnershipTransferred, error) { - event := new(RMNProxyContractOwnershipTransferred) - if err := _RMNProxyContract.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { +func (_RMNProxy *RMNProxyFilterer) ParseOwnershipTransferred(log types.Log) (*RMNProxyOwnershipTransferred, error) { + event := new(RMNProxyOwnershipTransferred) + if err := _RMNProxy.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { return nil, err } event.Raw = log return event, nil } -func (_RMNProxyContract *RMNProxyContract) ParseLog(log types.Log) (generated.AbigenLog, error) { +func (_RMNProxy *RMNProxy) ParseLog(log types.Log) (generated.AbigenLog, error) { switch log.Topics[0] { - case _RMNProxyContract.abi.Events["ARMSet"].ID: - return _RMNProxyContract.ParseARMSet(log) - case _RMNProxyContract.abi.Events["OwnershipTransferRequested"].ID: - return _RMNProxyContract.ParseOwnershipTransferRequested(log) - case _RMNProxyContract.abi.Events["OwnershipTransferred"].ID: - return _RMNProxyContract.ParseOwnershipTransferred(log) + case _RMNProxy.abi.Events["ARMSet"].ID: + return _RMNProxy.ParseARMSet(log) + case _RMNProxy.abi.Events["OwnershipTransferRequested"].ID: + return _RMNProxy.ParseOwnershipTransferRequested(log) + case _RMNProxy.abi.Events["OwnershipTransferred"].ID: + return _RMNProxy.ParseOwnershipTransferred(log) default: return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) } } -func (RMNProxyContractARMSet) Topic() common.Hash { +func (RMNProxyARMSet) Topic() common.Hash { return common.HexToHash("0xef31f568d741a833c6a9dc85a6e1c65e06fa772740d5dc94d1da21827a4e0cab") } -func (RMNProxyContractOwnershipTransferRequested) Topic() common.Hash { +func (RMNProxyOwnershipTransferRequested) Topic() common.Hash { return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") } -func (RMNProxyContractOwnershipTransferred) Topic() common.Hash { +func (RMNProxyOwnershipTransferred) Topic() common.Hash { return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") } -func (_RMNProxyContract *RMNProxyContract) Address() common.Address { - return _RMNProxyContract.address +func (_RMNProxy *RMNProxy) Address() common.Address { + return _RMNProxy.address } -type RMNProxyContractInterface interface { +type RMNProxyInterface interface { GetARM(opts *bind.CallOpts) (common.Address, error) Owner(opts *bind.CallOpts) (common.Address, error) @@ -719,23 +719,23 @@ type RMNProxyContractInterface interface { Fallback(opts *bind.TransactOpts, calldata []byte) (*types.Transaction, error) - FilterARMSet(opts *bind.FilterOpts) (*RMNProxyContractARMSetIterator, error) + FilterARMSet(opts *bind.FilterOpts) (*RMNProxyARMSetIterator, error) - WatchARMSet(opts *bind.WatchOpts, sink chan<- *RMNProxyContractARMSet) (event.Subscription, error) + WatchARMSet(opts *bind.WatchOpts, sink chan<- *RMNProxyARMSet) (event.Subscription, error) - ParseARMSet(log types.Log) (*RMNProxyContractARMSet, error) + ParseARMSet(log types.Log) (*RMNProxyARMSet, error) - FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RMNProxyContractOwnershipTransferRequestedIterator, error) + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RMNProxyOwnershipTransferRequestedIterator, error) - WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *RMNProxyContractOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *RMNProxyOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) - ParseOwnershipTransferRequested(log types.Log) (*RMNProxyContractOwnershipTransferRequested, error) + ParseOwnershipTransferRequested(log types.Log) (*RMNProxyOwnershipTransferRequested, error) - FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RMNProxyContractOwnershipTransferredIterator, error) + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RMNProxyOwnershipTransferredIterator, error) - WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *RMNProxyContractOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *RMNProxyOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) - ParseOwnershipTransferred(log types.Log) (*RMNProxyContractOwnershipTransferred, error) + ParseOwnershipTransferred(log types.Log) (*RMNProxyOwnershipTransferred, error) ParseLog(log types.Log) (generated.AbigenLog, error) diff --git a/core/gethwrappers/ccip/generated/rmn_remote/rmn_remote.go b/core/gethwrappers/ccip/generated/rmn_remote/rmn_remote.go index 2c7c367ab1f..301f508b3b6 100644 --- a/core/gethwrappers/ccip/generated/rmn_remote/rmn_remote.go +++ b/core/gethwrappers/ccip/generated/rmn_remote/rmn_remote.go @@ -51,7 +51,7 @@ type InternalMerkleRoot struct { type RMNRemoteConfig struct { RmnHomeContractConfigDigest [32]byte Signers []RMNRemoteSigner - F uint64 + FSign uint64 } type RMNRemoteSigner struct { @@ -60,8 +60,8 @@ type RMNRemoteSigner struct { } var RMNRemoteMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"localChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMN\",\"name\":\"legacyRMN\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"AlreadyCursed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateOnchainPublicKey\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignerOrder\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IsBlessedNotAvailable\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"NotCursed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotEnoughSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OutOfOrderSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ThresholdNotMet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroValueNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"f\",\"type\":\"uint64\"}],\"indexed\":false,\"internalType\":\"structRMNRemote.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"Cursed\",\"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\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"Uncursed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"curse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"curse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCursedSubjects\",\"outputs\":[{\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLocalChainSelector\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"localChainSelector\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReportDigestHeader\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"digestHeader\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getVersionedConfig\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"f\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"commitStore\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMN.TaggedRoot\",\"name\":\"taggedRoot\",\"type\":\"tuple\"}],\"name\":\"isBlessed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"isCursed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isCursed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"f\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Config\",\"name\":\"newConfig\",\"type\":\"tuple\"}],\"name\":\"setConfig\",\"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\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"uncurse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"uncurse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"offrampAddress\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNRemote.Signature[]\",\"name\":\"signatures\",\"type\":\"tuple[]\"}],\"name\":\"verify\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60c06040523480156200001157600080fd5b506040516200230438038062002304833981016040819052620000349162000150565b336000816200005657604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b038481169190911790915581161562000089576200008981620000d6565b5050816001600160401b0316600003620000b65760405163273e150360e21b815260040160405180910390fd5b6001600160401b039091166080526001600160a01b031660a052620001a5565b336001600160a01b038216036200010057604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600080604083850312156200016457600080fd5b82516001600160401b03811681146200017c57600080fd5b60208401519092506001600160a01b03811681146200019a57600080fd5b809150509250929050565b60805160a05161212b620001d9600039600081816108c5015261096d0152600081816102a80152610b7c015261212b6000f3fe608060405234801561001057600080fd5b506004361061011b5760003560e01c80636d2d3993116100b25780639a19b32911610081578063eaa83ddd11610066578063eaa83ddd1461029a578063f2fde38b146102d2578063f8bb876e146102e557600080fd5b80639a19b32914610272578063d881e0921461028557600080fd5b80636d2d39931461021c57806370a9089e1461022f57806379ba5097146102425780638da5cb5b1461024a57600080fd5b8063397796f7116100ee578063397796f7146101c05780634d616771146101c857806362eed415146101db5780636509a954146101ee57600080fd5b8063181f5a7714610120578063198f0f77146101725780631add205f146101875780632cbc26bb1461019d575b600080fd5b61015c6040518060400160405280601381526020017f524d4e52656d6f746520312e362e302d6465760000000000000000000000000081525081565b60405161016991906114d9565b60405180910390f35b6101856101803660046114ec565b6102f8565b005b61018f6106f2565b604051610169929190611527565b6101b06101ab366004611605565b6107ea565b6040519015158152602001610169565b6101b0610847565b6101b06101d6366004611620565b6108c1565b6101856101e9366004611605565b6109e3565b6040517f9651943783dbf81935a60e98f218a9d9b5b28823fb2228bbd91320d632facf538152602001610169565b61018561022a366004611605565b610a57565b61018561023d3660046116a6565b610ac7565b610185610e22565b60015460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610169565b610185610280366004611825565b610ef0565b61028d610ff6565b60405161016991906118c2565b60405167ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610169565b6101856102e0366004611928565b611002565b6101856102f3366004611825565b611016565b610300611108565b8035610338576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60015b6103486020830183611945565b90508110156104185761035e6020830183611945565b8281811061036e5761036e6119ad565b905060400201602001602081019061038691906119fd565b67ffffffffffffffff1661039d6020840184611945565b6103a8600185611a49565b8181106103b7576103b76119ad565b90506040020160200160208101906103cf91906119fd565b67ffffffffffffffff1610610410576040517f4485151700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60010161033b565b5061042960608201604083016119fd565b610434906002611a5c565b61043f906001611a88565b67ffffffffffffffff166104566020830183611945565b90501015610490576040517f014c502000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003545b8015610522576008600060036104ab600185611a49565b815481106104bb576104bb6119ad565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905561051b81611aa9565b9050610494565b5060005b6105336020830183611945565b9050811015610668576008600061054d6020850185611945565b8481811061055d5761055d6119ad565b6105739260206040909202019081019150611928565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040016000205460ff16156105d4576040517f28cae27d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600860006105e76020860186611945565b858181106105f7576105f76119ad565b61060d9260206040909202019081019150611928565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055600101610526565b508060026106768282611b97565b5050600580546000919082906106919063ffffffff16611cd2565b91906101000a81548163ffffffff021916908363ffffffff160217905590508063ffffffff167f7f22bf988149dbe8de8fb879c6b97a4e56e68b2bd57421ce1a4e79d4ef6b496c836040516106e69190611cf5565b60405180910390a25050565b6040805160608082018352600080835260208301919091529181018290526005546040805160608101825260028054825260038054845160208281028201810190965281815263ffffffff9096169592948593818601939092909160009084015b828210156107c1576000848152602090819020604080518082019091529084015473ffffffffffffffffffffffffffffffffffffffff8116825274010000000000000000000000000000000000000000900467ffffffffffffffff1681830152825260019092019101610753565b505050908252506002919091015467ffffffffffffffff16602090910152919491935090915050565b60006107f6600661115b565b60000361080557506000919050565b610810600683611165565b80610841575061084160067f0100000000000000000000000000000100000000000000000000000000000000611165565b92915050565b6000610853600661115b565b6000036108605750600090565b61088b60067f0100000000000000000000000000000000000000000000000000000000000000611165565b806108bc57506108bc60067f0100000000000000000000000000000100000000000000000000000000000000611165565b905090565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16610930576040517f0a7c4edd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f4d61677100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690634d616771906109a2908590600401611dff565b602060405180830381865afa1580156109bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108419190611e38565b604080516001808252818301909252600091602080830190803683370190505090508181600081518110610a1957610a196119ad565b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921660209283029190910190910152610a5381611016565b5050565b604080516001808252818301909252600091602080830190803683370190505090508181600081518110610a8d57610a8d6119ad565b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921660209283029190910190910152610a5381610ef0565b60055463ffffffff16600003610b09576040517face124bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600454610b219067ffffffffffffffff166001611a88565b67ffffffffffffffff16811015610b64576040517f59fa4a9300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160c08101825246815267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166020820152309181019190915273ffffffffffffffffffffffffffffffffffffffff8616606082015260025460808201526000907f9651943783dbf81935a60e98f218a9d9b5b28823fb2228bbd91320d632facf539060a08101610c008789611e5a565b9052604051610c13929190602001611fba565b60405160208183030381529060405280519060200120905060008060005b84811015610e1757600184601b888885818110610c5057610c506119ad565b90506040020160000135898986818110610c6c57610c6c6119ad565b9050604002016020013560405160008152602001604052604051610cac949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015610cce573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015192505073ffffffffffffffffffffffffffffffffffffffff8216610d46576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1610610dab576040517fbbe15e7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821660009081526008602052604090205460ff16610e0a576040517faaaa914100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9091508190600101610c31565b505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610e73576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610ef8611108565b60005b8151811015610fbb57610f31828281518110610f1957610f196119ad565b602002602001015160066111a390919063ffffffff16565b610fb357818181518110610f4757610f476119ad565b60200260200101516040517f73281fa1000000000000000000000000000000000000000000000000000000008152600401610faa91907fffffffffffffffffffffffffffffffff0000000000000000000000000000000091909116815260200190565b60405180910390fd5b600101610efb565b507f0676e709c9cc74fa0519fd78f7c33be0f1b2b0bae0507c724aef7229379c6ba181604051610feb91906118c2565b60405180910390a150565b60606108bc60066111d1565b61100a611108565b611013816111de565b50565b61101e611108565b60005b81518110156110d85761105782828151811061103f5761103f6119ad565b602002602001015160066112a290919063ffffffff16565b6110d05781818151811061106d5761106d6119ad565b60200260200101516040517f19d5c79b000000000000000000000000000000000000000000000000000000008152600401610faa91907fffffffffffffffffffffffffffffffff0000000000000000000000000000000091909116815260200190565b600101611021565b507f1716e663a90a76d3b6c7e5f680673d1b051454c19c627e184c8daf28f3104f7481604051610feb91906118c2565b60015473ffffffffffffffffffffffffffffffffffffffff163314611159576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6000610841825490565b7fffffffffffffffffffffffffffffffff000000000000000000000000000000008116600090815260018301602052604081205415155b9392505050565b600061119c837fffffffffffffffffffffffffffffffff0000000000000000000000000000000084166112d0565b6060600061119c836113ca565b3373ffffffffffffffffffffffffffffffffffffffff82160361122d576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600061119c837fffffffffffffffffffffffffffffffff000000000000000000000000000000008416611426565b600081815260018301602052604081205480156113b95760006112f4600183611a49565b855490915060009061130890600190611a49565b905080821461136d576000866000018281548110611328576113286119ad565b906000526020600020015490508087600001848154811061134b5761134b6119ad565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061137e5761137e6120ef565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610841565b6000915050610841565b5092915050565b60608160000180548060200260200160405190810160405280929190818152602001828054801561141a57602002820191906000526020600020905b815481526020019060010190808311611406575b50505050509050919050565b600081815260018301602052604081205461146d57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610841565b506000610841565b6000815180845260005b8181101561149b5760208185018101518683018201520161147f565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061119c6020830184611475565b6000602082840312156114fe57600080fd5b813567ffffffffffffffff81111561151557600080fd5b82016060818503121561119c57600080fd5b63ffffffff831681526040602080830182905283518383015283810151606080850152805160a085018190526000939291820190849060c08701905b808310156115ac578351805173ffffffffffffffffffffffffffffffffffffffff16835285015167ffffffffffffffff1685830152928401926001929092019190850190611563565b50604088015167ffffffffffffffff81166080890152945098975050505050505050565b80357fffffffffffffffffffffffffffffffff000000000000000000000000000000008116811461160057600080fd5b919050565b60006020828403121561161757600080fd5b61119c826115d0565b60006040828403121561163257600080fd5b50919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461101357600080fd5b60008083601f84011261166c57600080fd5b50813567ffffffffffffffff81111561168457600080fd5b6020830191508360208260061b850101111561169f57600080fd5b9250929050565b6000806000806000606086880312156116be57600080fd5b85356116c981611638565b9450602086013567ffffffffffffffff808211156116e657600080fd5b818801915088601f8301126116fa57600080fd5b81358181111561170957600080fd5b8960208260051b850101111561171e57600080fd5b60208301965080955050604088013591508082111561173c57600080fd5b506117498882890161165a565b969995985093965092949392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff811182821017156117ac576117ac61175a565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156117f9576117f961175a565b604052919050565b600067ffffffffffffffff82111561181b5761181b61175a565b5060051b60200190565b6000602080838503121561183857600080fd5b823567ffffffffffffffff81111561184f57600080fd5b8301601f8101851361186057600080fd5b803561187361186e82611801565b6117b2565b81815260059190911b8201830190838101908783111561189257600080fd5b928401925b828410156118b7576118a8846115d0565b82529284019290840190611897565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561191c5783517fffffffffffffffffffffffffffffffff0000000000000000000000000000000016835292840192918401916001016118de565b50909695505050505050565b60006020828403121561193a57600080fd5b813561119c81611638565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261197a57600080fd5b83018035915067ffffffffffffffff82111561199557600080fd5b6020019150600681901b360382131561169f57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b67ffffffffffffffff8116811461101357600080fd5b8035611600816119dc565b600060208284031215611a0f57600080fd5b813561119c816119dc565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561084157610841611a1a565b67ffffffffffffffff818116838216028082169190828114611a8057611a80611a1a565b505092915050565b67ffffffffffffffff8181168382160190808211156113c3576113c3611a1a565b600081611ab857611ab8611a1a565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b60008135610841816119dc565b8135611af681611638565b73ffffffffffffffffffffffffffffffffffffffff811690508154817fffffffffffffffffffffffff000000000000000000000000000000000000000082161783556020840135611b46816119dc565b7bffffffffffffffff00000000000000000000000000000000000000008160a01b16837fffffffff000000000000000000000000000000000000000000000000000000008416171784555050505050565b81358155600180820160208401357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1853603018112611bd557600080fd5b8401803567ffffffffffffffff811115611bee57600080fd5b6020820191508060061b3603821315611c0657600080fd5b68010000000000000000811115611c1f57611c1f61175a565b825481845580821015611c54576000848152602081208381019083015b80821015611c505782825590870190611c3c565b5050505b50600092835260208320925b81811015611c8457611c728385611aeb565b92840192604092909201918401611c60565b5050505050610a53611c9860408401611ade565b6002830167ffffffffffffffff82167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008254161781555050565b600063ffffffff808316818103611ceb57611ceb611a1a565b6001019392505050565b6000602080835260808301843582850152818501357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1863603018112611d3a57600080fd5b8501828101903567ffffffffffffffff80821115611d5757600080fd5b8160061b3603831315611d6957600080fd5b6040606060408901528483865260a089019050849550600094505b83851015611dd4578535611d9781611638565b73ffffffffffffffffffffffffffffffffffffffff16815285870135611dbc816119dc565b83168188015294810194600194909401938101611d84565b611de060408b016119f2565b67ffffffffffffffff811660608b015296509998505050505050505050565b604081018235611e0e81611638565b73ffffffffffffffffffffffffffffffffffffffff81168352506020830135602083015292915050565b600060208284031215611e4a57600080fd5b8151801515811461119c57600080fd5b6000611e6861186e84611801565b80848252602080830192508560051b850136811115611e8657600080fd5b855b81811015611fae57803567ffffffffffffffff80821115611ea95760008081fd5b818901915060a08236031215611ebf5760008081fd5b611ec7611789565b8235611ed2816119dc565b81528286013582811115611ee65760008081fd5b8301601f3681830112611ef95760008081fd5b813584811115611f0b57611f0b61175a565b611f3a897fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084840116016117b2565b94508085523689828501011115611f5357600091508182fd5b808984018a8701376000898287010152505050818682015260409150611f7a8284016119f2565b8282015260609150611f8d8284016119f2565b91810191909152608091820135918101919091528552938201938201611e88565b50919695505050505050565b60006040848352602060408185015261010084018551604086015281860151606067ffffffffffffffff808316606089015260408901519250608073ffffffffffffffffffffffffffffffffffffffff80851660808b015260608b0151945060a081861660a08c015260808c015160c08c015260a08c0151955060c060e08c015286915085518088526101209750878c019250878160051b8d01019750888701965060005b818110156120dc577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee08d8a030184528751868151168a528a810151848c8c01526120ab858c0182611475565b828e015189168c8f01528983015189168a8d0152918701519a87019a909a529850968901969289019260010161205f565b50969d9c50505050505050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"localChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"legacyRMN\",\"type\":\"address\",\"internalType\":\"contractIRMN\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"acceptOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"curse\",\"inputs\":[{\"name\":\"subject\",\"type\":\"bytes16\",\"internalType\":\"bytes16\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"curse\",\"inputs\":[{\"name\":\"subjects\",\"type\":\"bytes16[]\",\"internalType\":\"bytes16[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getCursedSubjects\",\"inputs\":[],\"outputs\":[{\"name\":\"subjects\",\"type\":\"bytes16[]\",\"internalType\":\"bytes16[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getLocalChainSelector\",\"inputs\":[],\"outputs\":[{\"name\":\"localChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getReportDigestHeader\",\"inputs\":[],\"outputs\":[{\"name\":\"digestHeader\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"getVersionedConfig\",\"inputs\":[],\"outputs\":[{\"name\":\"version\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"config\",\"type\":\"tuple\",\"internalType\":\"structRMNRemote.Config\",\"components\":[{\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"signers\",\"type\":\"tuple[]\",\"internalType\":\"structRMNRemote.Signer[]\",\"components\":[{\"name\":\"onchainPublicKey\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"nodeIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"fSign\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isBlessed\",\"inputs\":[{\"name\":\"taggedRoot\",\"type\":\"tuple\",\"internalType\":\"structIRMN.TaggedRoot\",\"components\":[{\"name\":\"commitStore\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isCursed\",\"inputs\":[{\"name\":\"subject\",\"type\":\"bytes16\",\"internalType\":\"bytes16\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isCursed\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"setConfig\",\"inputs\":[{\"name\":\"newConfig\",\"type\":\"tuple\",\"internalType\":\"structRMNRemote.Config\",\"components\":[{\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"signers\",\"type\":\"tuple[]\",\"internalType\":\"structRMNRemote.Signer[]\",\"components\":[{\"name\":\"onchainPublicKey\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"nodeIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"fSign\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"typeAndVersion\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"uncurse\",\"inputs\":[{\"name\":\"subject\",\"type\":\"bytes16\",\"internalType\":\"bytes16\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"uncurse\",\"inputs\":[{\"name\":\"subjects\",\"type\":\"bytes16[]\",\"internalType\":\"bytes16[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"verify\",\"inputs\":[{\"name\":\"offRampAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"merkleRoots\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.MerkleRoot[]\",\"components\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"onRampAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"minSeqNr\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"maxSeqNr\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"merkleRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"signatures\",\"type\":\"tuple[]\",\"internalType\":\"structIRMNRemote.Signature[]\",\"components\":[{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]}],\"outputs\":[],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"ConfigSet\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint32\",\"indexed\":true,\"internalType\":\"uint32\"},{\"name\":\"config\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRMNRemote.Config\",\"components\":[{\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"signers\",\"type\":\"tuple[]\",\"internalType\":\"structRMNRemote.Signer[]\",\"components\":[{\"name\":\"onchainPublicKey\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"nodeIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"fSign\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Cursed\",\"inputs\":[{\"name\":\"subjects\",\"type\":\"bytes16[]\",\"indexed\":false,\"internalType\":\"bytes16[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferRequested\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Uncursed\",\"inputs\":[{\"name\":\"subjects\",\"type\":\"bytes16[]\",\"indexed\":false,\"internalType\":\"bytes16[]\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AlreadyCursed\",\"inputs\":[{\"name\":\"subject\",\"type\":\"bytes16\",\"internalType\":\"bytes16\"}]},{\"type\":\"error\",\"name\":\"CannotTransferToSelf\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ConfigNotSet\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"DuplicateOnchainPublicKey\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidSignature\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidSignerOrder\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"IsBlessedNotAvailable\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MustBeProposedOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotCursed\",\"inputs\":[{\"name\":\"subject\",\"type\":\"bytes16\",\"internalType\":\"bytes16\"}]},{\"type\":\"error\",\"name\":\"NotEnoughSigners\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OnlyCallableByOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OutOfOrderSignatures\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OwnerCannotBeZero\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ThresholdNotMet\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnexpectedSigner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ZeroValueNotAllowed\",\"inputs\":[]}]", + Bin: "0x60c0346100d357601f6121f938819003918201601f19168301916001600160401b038311848410176100d85780849260409485528339810103126100d35780516001600160401b038116918282036100d35760200151916001600160a01b03831683036100d35733156100c257600180546001600160a01b03191633179055156100b15760805260a05260405161210a90816100ef82396080518181816102fe0152610712015260a05181610f7d0152f35b63273e150360e21b60005260046000fd5b639b15e16f60e01b60005260046000fd5b600080fd5b634e487b7160e01b600052604160045260246000fdfe6080604052600436101561001257600080fd5b60003560e01c8063181f5a77146119ce578063198f0f77146112df5780631add205f146111145780632cbc26bb146110d3578063397796f7146110905780634d61677114610f3557806362eed41514610e155780636509a95414610dbc5780636d2d399314610c9c57806370a9089e146105f057806379ba5097146105075780638da5cb5b146104b55780639a19b329146103c7578063d881e09214610322578063eaa83ddd146102bf578063f2fde38b146101cf5763f8bb876e146100d757600080fd5b346101ca576100e536611b71565b6100ed611ec2565b60005b81518110156101955761012e7fffffffffffffffffffffffffffffffff000000000000000000000000000000006101278385611eae565b51166120a3565b1561013b576001016100f0565b610166907fffffffffffffffffffffffffffffffff0000000000000000000000000000000092611eae565b51167f19d5c79b0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b6040517f1716e663a90a76d3b6c7e5f680673d1b051454c19c627e184c8daf28f3104f7490806101c58582611c38565b0390a1005b600080fd5b346101ca5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5773ffffffffffffffffffffffffffffffffffffffff61021b611b36565b610223611ec2565b1633811461029557807fffffffffffffffffffffffff0000000000000000000000000000000000000000600054161760005573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b7fdad89dca0000000000000000000000000000000000000000000000000000000060005260046000fd5b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca57602060405167ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5760405180602060065491828152019060066000527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f9060005b8181106103b1576103ad856103a181870382611a67565b60405191829182611c38565b0390f35b825484526020909301926001928301920161038a565b346101ca576103d536611b71565b6103dd611ec2565b60005b81518110156104855761041e7fffffffffffffffffffffffffffffffff000000000000000000000000000000006104178385611eae565b5116611f0d565b1561042b576001016103e0565b610456907fffffffffffffffffffffffffffffffff0000000000000000000000000000000092611eae565b51167f73281fa10000000000000000000000000000000000000000000000000000000060005260045260246000fd5b6040517f0676e709c9cc74fa0519fd78f7c33be0f1b2b0bae0507c724aef7229379c6ba190806101c58582611c38565b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca57602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5760005473ffffffffffffffffffffffffffffffffffffffff811633036105c6577fffffffffffffffffffffffff00000000000000000000000000000000000000006001549133828416176001551660005573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b7f02b543c60000000000000000000000000000000000000000000000000000000060005260046000fd5b346101ca5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca57610627611b36565b67ffffffffffffffff602435116101ca573660236024350112156101ca57602435600401359067ffffffffffffffff82116101ca573660248360051b81350101116101ca576044359067ffffffffffffffff82116101ca57366023830112156101ca5767ffffffffffffffff8260040135116101ca57366024836004013560061b840101116101ca5763ffffffff6005541615610c725767ffffffffffffffff6106d48160045416611d3c565b16826004013510610c485760025460405160c0810181811067ffffffffffffffff821117610c1957604052468152602081019267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168452604082019230845273ffffffffffffffffffffffffffffffffffffffff60608401921682526080830190815261076987611b59565b916107776040519384611a67565b8783526000976024803501602085015b60248360051b813501018210610a61575050509073ffffffffffffffffffffffffffffffffffffffff8095939260a0860193845260405196879567ffffffffffffffff602088019a7f9651943783dbf81935a60e98f218a9d9b5b28823fb2228bbd91320d632facf538c526040808a01526101208901995160608a015251166080880152511660a0860152511660c08401525160e08301525160c0610100830152805180935261014082019260206101408260051b85010192019388905b8282106109c8575050506108809250037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282611a67565b5190208290815b83600401358310610896578480f35b60208560806108ad86886004013560248a01611ce8565b35836108c1888a6004013560248c01611ce8565b013560405191878352601b868401526040830152606082015282805260015afa156109bd5784519073ffffffffffffffffffffffffffffffffffffffff82169081156109955773ffffffffffffffffffffffffffffffffffffffff829116101561096d578552600860205260ff604086205416156109455760019290920191610887565b6004857faaaa9141000000000000000000000000000000000000000000000000000000008152fd5b6004867fbbe15e7f000000000000000000000000000000000000000000000000000000008152fd5b6004877f8baa579f000000000000000000000000000000000000000000000000000000008152fd5b6040513d86823e3d90fd5b91936020847ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec08293600195970301855287519067ffffffffffffffff8251168152608080610a238585015160a08786015260a0850190611aa8565b9367ffffffffffffffff604082015116604085015267ffffffffffffffff606082015116606085015201519101529601920192018593919492610845565b81359067ffffffffffffffff8211610c155760a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc836024350136030112610c15576040519060a0820182811067ffffffffffffffff821117610be457604052610ad060248481350101611d95565b82526044836024350101359167ffffffffffffffff8311610c115736604360243586018501011215610c115767ffffffffffffffff6024848682350101013511610be457908d9160207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6024878982350101013501160193610b576040519586611a67565b60248035870182019081013580875236910160440111610be057602495602095869560a49387908a90813586018101808301359060440186850137858235010101358301015285840152610bb060648289350101611d95565b6040840152610bc460848289350101611d95565b6060840152863501013560808201528152019201919050610787565b8380fd5b60248e7f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b8d80fd5b8b80fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f59fa4a930000000000000000000000000000000000000000000000000000000060005260046000fd5b7face124bc0000000000000000000000000000000000000000000000000000000060005260046000fd5b346101ca5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca57610cd3611b07565b604090815190610ce38383611a67565b600182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe083013660208401377fffffffffffffffffffffffffffffffff00000000000000000000000000000000610d3a83611ea1565b91169052610d46611ec2565b60005b8151811015610d8d57610d807fffffffffffffffffffffffffffffffff000000000000000000000000000000006104178385611eae565b1561042b57600101610d49565b82517f0676e709c9cc74fa0519fd78f7c33be0f1b2b0bae0507c724aef7229379c6ba190806101c58582611c38565b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5760206040517f9651943783dbf81935a60e98f218a9d9b5b28823fb2228bbd91320d632facf538152f35b346101ca5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca57610e4c611b07565b604090815190610e5c8383611a67565b600182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe083013660208401377fffffffffffffffffffffffffffffffff00000000000000000000000000000000610eb383611ea1565b91169052610ebf611ec2565b60005b8151811015610f0657610ef97fffffffffffffffffffffffffffffffff000000000000000000000000000000006101278385611eae565b1561013b57600101610ec2565b82517f1716e663a90a76d3b6c7e5f680673d1b051454c19c627e184c8daf28f3104f7490806101c58582611c38565b346101ca5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca57600073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168015611068576020604491604051928380927f4d61677100000000000000000000000000000000000000000000000000000000825273ffffffffffffffffffffffffffffffffffffffff610fef611b36565b16600483015260243560248301525afa90811561105d57829161101a575b6020826040519015158152f35b90506020813d602011611055575b8161103560209383611a67565b810103126110515751801515810361105157602091508261100d565b5080fd5b3d9150611028565b6040513d84823e3d90fd5b6004827f0a7c4edd000000000000000000000000000000000000000000000000000000008152fd5b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5760206110c9611e44565b6040519015158152f35b346101ca5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5760206110c961110f611b07565b611daa565b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5760006040805161115281611a4b565b82815260606020820152015263ffffffff600554166040519061117482611a4b565b60025482526003549161118683611b59565b926111946040519485611a67565b808452600360009081527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b9190602086015b82821061128057505050506020810192835267ffffffffffffffff6004541692604082019384526040519283526040602084015260a083019151604084015251906060808401528151809152602060c0840192019060005b81811061123e5750505067ffffffffffffffff8293511660808301520390f35b8251805173ffffffffffffffffffffffffffffffffffffffff16855260209081015167ffffffffffffffff16818601526040909401939092019160010161121e565b6040516040810181811067ffffffffffffffff821117610c1957600192839260209260405267ffffffffffffffff885473ffffffffffffffffffffffffffffffffffffffff8116835260a01c16838201528152019401910190926111c6565b346101ca5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5760043567ffffffffffffffff81116101ca57806004018136039160607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8401126101ca5761135a611ec2565b81359081156119a457909260248201919060015b6113788486611c94565b90508110156114595761138b8486611c94565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83019183831161142a576113cc926020926113c692611ce8565b01611d27565b67ffffffffffffffff806113ef60206113c6866113e98b8d611c94565b90611ce8565b16911610156114005760010161136e565b7f448515170000000000000000000000000000000000000000000000000000000060005260046000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b508390856114678584611c94565b60448601915061147682611d27565b60011b6801fffffffffffffffe67fffffffffffffffe82169116810361142a576114a867ffffffffffffffff91611d3c565b161161197a57600354805b611877575060005b6114c58786611c94565b905081101561159e5773ffffffffffffffffffffffffffffffffffffffff6114f96114f4836113e98b8a611c94565b611d74565b16600052600860205260ff60406000205416611574578073ffffffffffffffffffffffffffffffffffffffff6115386114f46001946113e98c8b611c94565b1660005260086020526040600020827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055016114bb565b7f28cae27d0000000000000000000000000000000000000000000000000000000060005260046000fd5b50846115b08780959685600255611c94565b90680100000000000000008211610c195760035482600355808310611831575b50600360005260206000206000915b838310611783575050505067ffffffffffffffff6115fc83611d27565b167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000060045416176004556005549463ffffffff86169563ffffffff871461142a5763ffffffff60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000098011696879116176005557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdd6040519560208752608087019560208801523591018112156101ca57016024600482013591019267ffffffffffffffff82116101ca578160061b360384136101ca578190606060408701525260a0840192906000905b80821061173057867f7f22bf988149dbe8de8fb879c6b97a4e56e68b2bd57421ce1a4e79d4ef6b496c87808867ffffffffffffffff6117258a611d95565b1660608301520390a2005b90919384359073ffffffffffffffffffffffffffffffffffffffff82168092036101ca5760408160019382935267ffffffffffffffff61177260208a01611d95565b1660208201520195019201906116e7565b600160408273ffffffffffffffffffffffffffffffffffffffff6117a78495611d74565b167fffffffffffffffffffffffff00000000000000000000000000000000000000008654161785556117db60208201611d27565b7fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff7bffffffffffffffff000000000000000000000000000000000000000087549260a01b169116178555019201920191906115df565b60036000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b9081019083015b81811061186b57506115d0565b6000815560010161185e565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811161142a57600090600354111561194d57600390527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85a81015473ffffffffffffffffffffffffffffffffffffffff16600090815260086020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055801561142a577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01806114b3565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526032600452fd5b7f014c50200000000000000000000000000000000000000000000000000000000060005260046000fd5b7f9cf8540c0000000000000000000000000000000000000000000000000000000060005260046000fd5b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca576103ad6040805190611a0f8183611a67565b601382527f524d4e52656d6f746520312e362e302d64657600000000000000000000000000602083015251918291602083526020830190611aa8565b6060810190811067ffffffffffffffff821117610c1957604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610c1957604052565b919082519283825260005b848110611af25750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b80602080928401015182828601015201611ab3565b600435907fffffffffffffffffffffffffffffffff00000000000000000000000000000000821682036101ca57565b6004359073ffffffffffffffffffffffffffffffffffffffff821682036101ca57565b67ffffffffffffffff8111610c195760051b60200190565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8201126101ca576004359067ffffffffffffffff82116101ca57806023830112156101ca57816004013590611bc882611b59565b92611bd66040519485611a67565b8284526024602085019360051b8201019182116101ca57602401915b818310611bff5750505090565b82357fffffffffffffffffffffffffffffffff00000000000000000000000000000000811681036101ca57815260209283019201611bf2565b602060408183019282815284518094520192019060005b818110611c5c5750505090565b82517fffffffffffffffffffffffffffffffff0000000000000000000000000000000016845260209384019390920191600101611c4f565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156101ca570180359067ffffffffffffffff82116101ca57602001918160061b360383136101ca57565b9190811015611cf85760061b0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b3567ffffffffffffffff811681036101ca5790565b67ffffffffffffffff60019116019067ffffffffffffffff821161142a57565b8054821015611cf85760005260206000200190600090565b3573ffffffffffffffffffffffffffffffffffffffff811681036101ca5790565b359067ffffffffffffffff821682036101ca57565b60065415611e3e577fffffffffffffffffffffffffffffffff0000000000000000000000000000000016600052600760205260406000205415801590611ded5790565b507f010000000000000000000000000000010000000000000000000000000000000060005260076020527f70b766b11586b6b505ed3893938b0cc6c6c98bd6f65e969ac311168d34e4f9e254151590565b50600090565b60065415611e9c577f010000000000000000000000000000010000000000000000000000000000000060005260076020527f70b766b11586b6b505ed3893938b0cc6c6c98bd6f65e969ac311168d34e4f9e254151590565b600090565b805115611cf85760200190565b8051821015611cf85760209160051b010190565b73ffffffffffffffffffffffffffffffffffffffff600154163303611ee357565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b600081815260076020526040902054801561209c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811161142a57600654907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820191821161142a5781810361202d575b5050506006548015611ffe577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01611fbb816006611d5c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600655600052600760205260006040812055600190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b61208461203e61204f936006611d5c565b90549060031b1c9283926006611d5c565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b90556000526007602052604060002055388080611f82565b5050600090565b80600052600760205260406000205415600014611e3e5760065468010000000000000000811015610c19576120e461204f8260018594016006556006611d5c565b905560065490600052600760205260406000205560019056fea164736f6c634300081a000a", } var RMNRemoteABI = RMNRemoteMetaData.ABI @@ -406,9 +406,9 @@ func (_RMNRemote *RMNRemoteCallerSession) TypeAndVersion() (string, error) { return _RMNRemote.Contract.TypeAndVersion(&_RMNRemote.CallOpts) } -func (_RMNRemote *RMNRemoteCaller) Verify(opts *bind.CallOpts, offrampAddress common.Address, merkleRoots []InternalMerkleRoot, signatures []IRMNRemoteSignature) error { +func (_RMNRemote *RMNRemoteCaller) Verify(opts *bind.CallOpts, offRampAddress common.Address, merkleRoots []InternalMerkleRoot, signatures []IRMNRemoteSignature) error { var out []interface{} - err := _RMNRemote.contract.Call(opts, &out, "verify", offrampAddress, merkleRoots, signatures) + err := _RMNRemote.contract.Call(opts, &out, "verify", offRampAddress, merkleRoots, signatures) if err != nil { return err @@ -418,12 +418,12 @@ func (_RMNRemote *RMNRemoteCaller) Verify(opts *bind.CallOpts, offrampAddress co } -func (_RMNRemote *RMNRemoteSession) Verify(offrampAddress common.Address, merkleRoots []InternalMerkleRoot, signatures []IRMNRemoteSignature) error { - return _RMNRemote.Contract.Verify(&_RMNRemote.CallOpts, offrampAddress, merkleRoots, signatures) +func (_RMNRemote *RMNRemoteSession) Verify(offRampAddress common.Address, merkleRoots []InternalMerkleRoot, signatures []IRMNRemoteSignature) error { + return _RMNRemote.Contract.Verify(&_RMNRemote.CallOpts, offRampAddress, merkleRoots, signatures) } -func (_RMNRemote *RMNRemoteCallerSession) Verify(offrampAddress common.Address, merkleRoots []InternalMerkleRoot, signatures []IRMNRemoteSignature) error { - return _RMNRemote.Contract.Verify(&_RMNRemote.CallOpts, offrampAddress, merkleRoots, signatures) +func (_RMNRemote *RMNRemoteCallerSession) Verify(offRampAddress common.Address, merkleRoots []InternalMerkleRoot, signatures []IRMNRemoteSignature) error { + return _RMNRemote.Contract.Verify(&_RMNRemote.CallOpts, offRampAddress, merkleRoots, signatures) } func (_RMNRemote *RMNRemoteTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { @@ -1212,7 +1212,7 @@ type RMNRemoteInterface interface { TypeAndVersion(opts *bind.CallOpts) (string, error) - Verify(opts *bind.CallOpts, offrampAddress common.Address, merkleRoots []InternalMerkleRoot, signatures []IRMNRemoteSignature) error + Verify(opts *bind.CallOpts, offRampAddress common.Address, merkleRoots []InternalMerkleRoot, signatures []IRMNRemoteSignature) error AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) diff --git a/core/gethwrappers/ccip/generated/router/router.go b/core/gethwrappers/ccip/generated/router/router.go index 9a0d4a40559..24f65d1796e 100644 --- a/core/gethwrappers/ccip/generated/router/router.go +++ b/core/gethwrappers/ccip/generated/router/router.go @@ -62,8 +62,8 @@ type RouterOnRamp struct { } var RouterMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"wrappedNative\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"armProxy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"BadARMSignal\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToSendValue\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientFeeTokenAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidMsgValue\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"InvalidRecipientAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"offRamp\",\"type\":\"address\"}],\"name\":\"OffRampMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyOffRamp\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"UnsupportedDestinationChain\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"offRamp\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"calldataHash\",\"type\":\"bytes32\"}],\"name\":\"MessageExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"offRamp\",\"type\":\"address\"}],\"name\":\"OffRampAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"offRamp\",\"type\":\"address\"}],\"name\":\"OffRampRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"}],\"name\":\"OnRampSet\",\"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\":\"MAX_RET_BYTES\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"}],\"internalType\":\"structRouter.OnRamp[]\",\"name\":\"onRampUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"offRamp\",\"type\":\"address\"}],\"internalType\":\"structRouter.OffRamp[]\",\"name\":\"offRampRemoves\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"offRamp\",\"type\":\"address\"}],\"internalType\":\"structRouter.OffRamp[]\",\"name\":\"offRampAdds\",\"type\":\"tuple[]\"}],\"name\":\"applyRampUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destinationChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"ccipSend\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getArmProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destinationChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getOffRamps\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"offRamp\",\"type\":\"address\"}],\"internalType\":\"structRouter.OffRamp[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getOnRamp\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"getSupportedTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWrappedNative\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"isChainSupported\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"offRamp\",\"type\":\"address\"}],\"name\":\"isOffRamp\",\"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\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"recoverTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"uint16\",\"name\":\"gasForCallExactCheck\",\"type\":\"uint16\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"routeMessage\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"retData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"wrappedNative\",\"type\":\"address\"}],\"name\":\"setWrappedNative\",\"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\"}]", - Bin: "0x60a06040523480156200001157600080fd5b5060405162002d2838038062002d288339810160408190526200003491620001af565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000e7565b5050600280546001600160a01b0319166001600160a01b039485161790555016608052620001e7565b336001600160a01b03821603620001415760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0381168114620001aa57600080fd5b919050565b60008060408385031215620001c357600080fd5b620001ce8362000192565b9150620001de6020840162000192565b90509250929050565b608051612b1762000211600039600081816101f9015281816105e10152610af20152612b176000f3fe6080604052600436106101295760003560e01c80638da5cb5b116100a5578063a8d87a3b11610074578063e861e90711610059578063e861e90714610409578063f2fde38b14610434578063fbca3b741461045457600080fd5b8063a8d87a3b1461039c578063da5fcac8146103e957600080fd5b80638da5cb5b146102ed57806396f4e9f914610318578063a40e69c71461032b578063a48a90581461034d57600080fd5b806352cb60ca116100fc578063787350e3116100e1578063787350e31461028057806379ba5097146102a857806383826b2b146102bd57600080fd5b806352cb60ca1461023e5780635f3e849f1461026057600080fd5b8063181f5a771461012e57806320487ded1461018d5780633cf97983146101bb5780635246492f146101ea575b600080fd5b34801561013a57600080fd5b506101776040518060400160405280600c81526020017f526f7574657220312e322e30000000000000000000000000000000000000000081525081565b6040516101849190611f3c565b60405180910390f35b34801561019957600080fd5b506101ad6101a83660046121ad565b610481565b604051908152602001610184565b3480156101c757600080fd5b506101db6101d63660046122aa565b6105d9565b60405161018493929190612322565b3480156101f657600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610184565b34801561024a57600080fd5b5061025e61025936600461234d565b610836565b005b34801561026c57600080fd5b5061025e61027b36600461236a565b610885565b34801561028c57600080fd5b50610295608481565b60405161ffff9091168152602001610184565b3480156102b457600080fd5b5061025e6109d3565b3480156102c957600080fd5b506102dd6102d83660046123ab565b610ad0565b6040519015158152602001610184565b3480156102f957600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610219565b6101ad6103263660046121ad565b610aee565b34801561033757600080fd5b50610340611087565b60405161018491906123e2565b34801561035957600080fd5b506102dd610368366004612451565b67ffffffffffffffff1660009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff16151590565b3480156103a857600080fd5b506102196103b7366004612451565b67ffffffffffffffff1660009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b3480156103f557600080fd5b5061025e6104043660046124b8565b61118b565b34801561041557600080fd5b5060025473ffffffffffffffffffffffffffffffffffffffff16610219565b34801561044057600080fd5b5061025e61044f36600461234d565b611490565b34801561046057600080fd5b5061047461046f366004612451565b6114a4565b6040516101849190612552565b606081015160009073ffffffffffffffffffffffffffffffffffffffff166104c25760025473ffffffffffffffffffffffffffffffffffffffff1660608301525b67ffffffffffffffff831660009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff168061053a576040517fae236d9c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024015b60405180910390fd5b6040517f20487ded00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216906320487ded9061058e9087908790600401612689565b602060405180830381865afa1580156105ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105cf91906126ac565b9150505b92915050565b6000606060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663397796f76040518163ffffffff1660e01b8152600401602060405180830381865afa15801561064a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066e91906126c5565b156106a5576040517fc148371500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6106be6106b86040890160208a01612451565b33610ad0565b6106f4576040517fd2316ede00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006385572ffb60e01b8860405160240161070f91906127f4565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152905061079c8186888a60846115c4565b919550935091507f9b877de93ea9895756e337442c657f95a34fc68e7eb988bdfa693d5be83016b688356107d660408b0160208c01612451565b83516020850120604051610823939291339193845267ffffffffffffffff92909216602084015273ffffffffffffffffffffffffffffffffffffffff166040830152606082015260800190565b60405180910390a1509450945094915050565b61083e6116ea565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b61088d6116ea565b73ffffffffffffffffffffffffffffffffffffffff82166108f2576040517f26a78f8f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401610531565b73ffffffffffffffffffffffffffffffffffffffff83166109ad5760008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114610967576040519150601f19603f3d011682016040523d82523d6000602084013e61096c565b606091505b50509050806109a7576040517fe417b80b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b6109ce73ffffffffffffffffffffffffffffffffffffffff8416838361176d565b505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610a54576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610531565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6000610ae7610adf8484611841565b600490611885565b9392505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663397796f76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7f91906126c5565b15610bb6576040517fc148371500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff831660009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff1680610c29576040517fae236d9c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610531565b606083015160009073ffffffffffffffffffffffffffffffffffffffff16610dbb5760025473ffffffffffffffffffffffffffffffffffffffff90811660608601526040517f20487ded000000000000000000000000000000000000000000000000000000008152908316906320487ded90610cab9088908890600401612689565b602060405180830381865afa158015610cc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cec91906126ac565b905080341015610d28576040517f07da6ee600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b349050836060015173ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015610d7757600080fd5b505af1158015610d8b573d6000803e3d6000fd5b505050506060850151610db6915073ffffffffffffffffffffffffffffffffffffffff16838361176d565b610eb2565b3415610df3576040517f1841b4e100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f20487ded00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316906320487ded90610e479088908890600401612689565b602060405180830381865afa158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906126ac565b6060850151909150610eb29073ffffffffffffffffffffffffffffffffffffffff1633848461189d565b60005b846040015151811015610fe257600085604001518281518110610eda57610eda612900565b6020908102919091010151516040517f48a98aa400000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8916600482015273ffffffffffffffffffffffffffffffffffffffff8083166024830152919250610fd9913391908716906348a98aa490604401602060405180830381865afa158015610f6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f90919061292f565b88604001518581518110610fa657610fa6612900565b6020026020010151602001518473ffffffffffffffffffffffffffffffffffffffff1661189d909392919063ffffffff16565b50600101610eb5565b506040517fdf0aa9e900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063df0aa9e99061103b90889088908690339060040161294c565b6020604051808303816000875af115801561105a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061107e91906126ac565b95945050505050565b6060600061109560046118fb565b90506000815167ffffffffffffffff8111156110b3576110b3611f6c565b6040519080825280602002602001820160405280156110f857816020015b60408051808201909152600080825260208201528152602001906001900390816110d15790505b50905060005b825181101561118457600083828151811061111b5761111b612900565b60200260200101519050604051806040016040528060a083901c67ffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681525083838151811061117057611170612900565b6020908102919091010152506001016110fe565b5092915050565b6111936116ea565b60005b8581101561126f5760008787838181106111b2576111b2612900565b9050604002018036038101906111c8919061299c565b60208181018051835167ffffffffffffffff90811660009081526003855260409081902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff948516179055855193519051921682529394509216917f1f7d0ec248b80e5c0dde0ee531c4fc8fdb6ce9a2b3d90f560c74acd6a7202f23910160405180910390a250600101611196565b5060005b838110156113a757600085858381811061128f5761128f612900565b6112a59260206040909202019081019150612451565b905060008686848181106112bb576112bb612900565b90506040020160200160208101906112d3919061234d565b90506112ea6112e28383611841565b600490611908565b611348576040517f4964779000000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8316600482015273ffffffffffffffffffffffffffffffffffffffff82166024820152604401610531565b60405173ffffffffffffffffffffffffffffffffffffffff8216815267ffffffffffffffff8316907fa823809efda3ba66c873364eec120fa0923d9fabda73bc97dd5663341e2d9bcb9060200160405180910390a25050600101611273565b5060005b818110156114875760008383838181106113c7576113c7612900565b6113dd9260206040909202019081019150612451565b905060008484848181106113f3576113f3612900565b905060400201602001602081019061140b919061234d565b905061142261141a8383611841565b600490611914565b1561147d5760405173ffffffffffffffffffffffffffffffffffffffff8216815267ffffffffffffffff8316907fa4bdf64ebdf3316320601a081916a75aa144bcef6c4beeb0e9fb1982cacc6b949060200160405180910390a25b50506001016113ab565b50505050505050565b6114986116ea565b6114a181611920565b50565b60606114de8267ffffffffffffffff1660009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff16151590565b6114f8576040805160008082526020820190925290611184565b67ffffffffffffffff8216600081815260036020526040908190205490517ffbca3b74000000000000000000000000000000000000000000000000000000008152600481019290925273ffffffffffffffffffffffffffffffffffffffff169063fbca3b7490602401600060405180830381865afa15801561157e573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526105d391908101906129db565b6000606060008361ffff1667ffffffffffffffff8111156115e7576115e7611f6c565b6040519080825280601f01601f191660200182016040528015611611576020820181803683370190505b509150863b611644577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015611677577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b85900360408104810387106116b0577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d848111156116d35750835b808352806000602085013e50955095509592505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461176b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610531565b565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109ce9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611a15565b6000610ae773ffffffffffffffffffffffffffffffffffffffff83167bffffffffffffffff000000000000000000000000000000000000000060a086901b16612a99565b60008181526001830160205260408120541515610ae7565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526109a79085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016117bf565b60606000610ae783611b21565b6000610ae78383611b7d565b6000610ae78383611c70565b3373ffffffffffffffffffffffffffffffffffffffff82160361199f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610531565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000611a77826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611cbf9092919063ffffffff16565b8051909150156109ce5780806020019051810190611a9591906126c5565b6109ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610531565b606081600001805480602002602001604051908101604052809291908181526020018280548015611b7157602002820191906000526020600020905b815481526020019060010190808311611b5d575b50505050509050919050565b60008181526001830160205260408120548015611c66576000611ba1600183612aac565b8554909150600090611bb590600190612aac565b9050808214611c1a576000866000018281548110611bd557611bd5612900565b9060005260206000200154905080876000018481548110611bf857611bf8612900565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611c2b57611c2b612abf565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105d3565b60009150506105d3565b6000818152600183016020526040812054611cb7575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105d3565b5060006105d3565b6060611cce8484600085611cd6565b949350505050565b606082471015611d68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610531565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051611d919190612aee565b60006040518083038185875af1925050503d8060008114611dce576040519150601f19603f3d011682016040523d82523d6000602084013e611dd3565b606091505b5091509150611de487838387611def565b979650505050505050565b60608315611e85578251600003611e7e5773ffffffffffffffffffffffffffffffffffffffff85163b611e7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610531565b5081611cce565b611cce8383815115611e9a5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105319190611f3c565b60005b83811015611ee9578181015183820152602001611ed1565b50506000910152565b60008151808452611f0a816020860160208601611ece565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610ae76020830184611ef2565b803567ffffffffffffffff81168114611f6757600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611fbe57611fbe611f6c565b60405290565b60405160a0810167ffffffffffffffff81118282101715611fbe57611fbe611f6c565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561202e5761202e611f6c565b604052919050565b600082601f83011261204757600080fd5b813567ffffffffffffffff81111561206157612061611f6c565b61209260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611fe7565b8181528460208386010111156120a757600080fd5b816020850160208301376000918101602001919091529392505050565b600067ffffffffffffffff8211156120de576120de611f6c565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff811681146114a157600080fd5b8035611f67816120e8565b600082601f83011261212657600080fd5b8135602061213b612136836120c4565b611fe7565b82815260069290921b8401810191818101908684111561215a57600080fd5b8286015b848110156121a257604081890312156121775760008081fd5b61217f611f9b565b813561218a816120e8565b8152818501358582015283529183019160400161215e565b509695505050505050565b600080604083850312156121c057600080fd5b6121c983611f4f565b9150602083013567ffffffffffffffff808211156121e657600080fd5b9084019060a082870312156121fa57600080fd5b612202611fc4565b82358281111561221157600080fd5b61221d88828601612036565b82525060208301358281111561223257600080fd5b61223e88828601612036565b60208301525060408301358281111561225657600080fd5b61226288828601612115565b6040830152506122746060840161210a565b606082015260808301358281111561228b57600080fd5b61229788828601612036565b6080830152508093505050509250929050565b600080600080608085870312156122c057600080fd5b843567ffffffffffffffff8111156122d757600080fd5b850160a081880312156122e957600080fd5b9350602085013561ffff8116811461230057600080fd5b9250604085013591506060850135612317816120e8565b939692955090935050565b831515815260606020820152600061233d6060830185611ef2565b9050826040830152949350505050565b60006020828403121561235f57600080fd5b8135610ae7816120e8565b60008060006060848603121561237f57600080fd5b833561238a816120e8565b9250602084013561239a816120e8565b929592945050506040919091013590565b600080604083850312156123be57600080fd5b6123c783611f4f565b915060208301356123d7816120e8565b809150509250929050565b602080825282518282018190526000919060409081850190868401855b82811015612444578151805167ffffffffffffffff16855286015173ffffffffffffffffffffffffffffffffffffffff168685015292840192908501906001016123ff565b5091979650505050505050565b60006020828403121561246357600080fd5b610ae782611f4f565b60008083601f84011261247e57600080fd5b50813567ffffffffffffffff81111561249657600080fd5b6020830191508360208260061b85010111156124b157600080fd5b9250929050565b600080600080600080606087890312156124d157600080fd5b863567ffffffffffffffff808211156124e957600080fd5b6124f58a838b0161246c565b9098509650602089013591508082111561250e57600080fd5b61251a8a838b0161246c565b9096509450604089013591508082111561253357600080fd5b5061254089828a0161246c565b979a9699509497509295939492505050565b6020808252825182820181905260009190848201906040850190845b818110156125a057835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161256e565b50909695505050505050565b6000815160a084526125c160a0850182611ef2565b9050602080840151858303828701526125da8382611ef2565b60408681015188830389830152805180845290850195509092506000918401905b8083101561263a578551805173ffffffffffffffffffffffffffffffffffffffff168352850151858301529484019460019290920191908301906125fb565b5060608701519450612664606089018673ffffffffffffffffffffffffffffffffffffffff169052565b60808701519450878103608089015261267d8186611ef2565b98975050505050505050565b67ffffffffffffffff83168152604060208201526000611cce60408301846125ac565b6000602082840312156126be57600080fd5b5051919050565b6000602082840312156126d757600080fd5b81518015158114610ae757600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261271c57600080fd5b830160208101925035905067ffffffffffffffff81111561273c57600080fd5b8036038213156124b157600080fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8183526000602080850194508260005b858110156127e95781356127b7816120e8565b73ffffffffffffffffffffffffffffffffffffffff1687528183013583880152604096870196909101906001016127a4565b509495945050505050565b6020815281356020820152600061280d60208401611f4f565b67ffffffffffffffff808216604085015261282b60408601866126e7565b925060a0606086015261284260c08601848361274b565b92505061285260608601866126e7565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08087860301608088015261288885838561274b565b9450608088013592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18836030183126128c157600080fd5b602092880192830192359150838211156128da57600080fd5b8160061b36038313156128ec57600080fd5b8685030160a0870152611de4848284612794565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561294157600080fd5b8151610ae7816120e8565b67ffffffffffffffff8516815260806020820152600061296f60808301866125ac565b905083604083015273ffffffffffffffffffffffffffffffffffffffff8316606083015295945050505050565b6000604082840312156129ae57600080fd5b6129b6611f9b565b6129bf83611f4f565b815260208301356129cf816120e8565b60208201529392505050565b600060208083850312156129ee57600080fd5b825167ffffffffffffffff811115612a0557600080fd5b8301601f81018513612a1657600080fd5b8051612a24612136826120c4565b81815260059190911b82018301908381019087831115612a4357600080fd5b928401925b82841015611de4578351612a5b816120e8565b82529284019290840190612a48565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156105d3576105d3612a6a565b818103818111156105d3576105d3612a6a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612b00818460208701611ece565b919091019291505056fea164736f6c6343000818000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"wrappedNative\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"armProxy\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"MAX_RET_BYTES\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint16\",\"internalType\":\"uint16\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"acceptOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyRampUpdates\",\"inputs\":[{\"name\":\"onRampUpdates\",\"type\":\"tuple[]\",\"internalType\":\"structRouter.OnRamp[]\",\"components\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"onRamp\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"name\":\"offRampRemoves\",\"type\":\"tuple[]\",\"internalType\":\"structRouter.OffRamp[]\",\"components\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"offRamp\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"name\":\"offRampAdds\",\"type\":\"tuple[]\",\"internalType\":\"structRouter.OffRamp[]\",\"components\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"offRamp\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"ccipSend\",\"inputs\":[{\"name\":\"destinationChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"message\",\"type\":\"tuple\",\"internalType\":\"structClient.EVM2AnyMessage\",\"components\":[{\"name\":\"receiver\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"tokenAmounts\",\"type\":\"tuple[]\",\"internalType\":\"structClient.EVMTokenAmount[]\",\"components\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"feeToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"extraArgs\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"getArmProxy\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getFee\",\"inputs\":[{\"name\":\"destinationChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"message\",\"type\":\"tuple\",\"internalType\":\"structClient.EVM2AnyMessage\",\"components\":[{\"name\":\"receiver\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"tokenAmounts\",\"type\":\"tuple[]\",\"internalType\":\"structClient.EVMTokenAmount[]\",\"components\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"feeToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"extraArgs\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"fee\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getOffRamps\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"tuple[]\",\"internalType\":\"structRouter.OffRamp[]\",\"components\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"offRamp\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getOnRamp\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getSupportedTokens\",\"inputs\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getWrappedNative\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isChainSupported\",\"inputs\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isOffRamp\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"offRamp\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"recoverTokens\",\"inputs\":[{\"name\":\"tokenAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"routeMessage\",\"inputs\":[{\"name\":\"message\",\"type\":\"tuple\",\"internalType\":\"structClient.Any2EVMMessage\",\"components\":[{\"name\":\"messageId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sender\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\",\"internalType\":\"structClient.EVMTokenAmount[]\",\"components\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}]},{\"name\":\"gasForCallExactCheck\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"gasLimit\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"receiver\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"success\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"retData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"gasUsed\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setWrappedNative\",\"inputs\":[{\"name\":\"wrappedNative\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"typeAndVersion\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"MessageExecuted\",\"inputs\":[{\"name\":\"messageId\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"},{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"offRamp\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"calldataHash\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OffRampAdded\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"offRamp\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OffRampRemoved\",\"inputs\":[{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"offRamp\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OnRampSet\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"onRamp\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferRequested\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"BadARMSignal\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"FailedToSendValue\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InsufficientFeeTokenAmount\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidMsgValue\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidRecipientAddress\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"OffRampMismatch\",\"inputs\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"offRamp\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"OnlyOffRamp\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnsupportedDestinationChain\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]}]", + Bin: "0x60a0346100f557601f612b2e38819003918201601f19168301916001600160401b038311848410176100fa5780849260409485528339810103126100f557610052602061004b83610110565b9201610110565b9033156100b057600080546001600160a01b03199081163317909155600280549091166001600160a01b0392909216919091179055608052604051612a099081610125823960805181818161084e01528181610bfb0152611d290152f35b60405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f00000000000000006044820152606490fd5b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b03821682036100f55756fe6080604052600436101561001257600080fd5b60003560e01c8063181f5a771461013757806320487ded146101325780633cf979831461012d5780635246492f1461012857806352cb60ca146101235780635f3e849f1461011e578063787350e31461011957806379ba50971461011457806383826b2b1461010f5780638da5cb5b1461010a57806396f4e9f914610105578063a40e69c714610100578063a48a9058146100fb578063a8d87a3b146100f6578063da5fcac8146100f1578063e861e907146100ec578063f2fde38b146100e75763fbca3b74146100e257600080fd5b611922565b6117de565b61178c565b611413565b61136f565b6112fc565b6111ab565b610baf565b610b5d565b610aeb565b610990565b610956565b6108f9565b610872565b610803565b610758565b61057d565b6102aa565b600091031261014757565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040810190811067ffffffffffffffff82111761019757604052565b61014c565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761019757604052565b604051906101ec60a08361019c565b565b604051906101ec60408361019c565b67ffffffffffffffff811161019757601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b919082519283825260005b8481106102815750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b80602080928401015182828601015201610242565b9060206102a7928181520190610237565b90565b346101475760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101475761032760408051906102eb818361019c565b600c82527f526f7574657220312e322e300000000000000000000000000000000000000000602083015251918291602083526020830190610237565b0390f35b67ffffffffffffffff81160361014757565b81601f8201121561014757803590610354826101fd565b92610362604051948561019c565b8284526020838301011161014757816000926020809301838601378301015290565b67ffffffffffffffff81116101975760051b60200190565b73ffffffffffffffffffffffffffffffffffffffff81160361014757565b35906101ec8261039c565b81601f82011215610147578035906103dc82610384565b926103ea604051948561019c565b82845260208085019360061b8301019181831161014757602001925b828410610414575050505090565b604084830312610147576020604091825161042e8161017b565b86356104398161039c565b81528287013583820152815201930192610406565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc830112610147576004356104858161032b565b9160243567ffffffffffffffff81116101475760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8284030112610147576104cc6101dd565b91816004013567ffffffffffffffff8111610147578160046104f09285010161033d565b8352602482013567ffffffffffffffff8111610147578160046105159285010161033d565b6020840152604482013567ffffffffffffffff81116101475781600461053d928501016103c5565b604084015261054e606483016103ba565b606084015260848201359167ffffffffffffffff831161014757610575920160040161033d565b608082015290565b346101475761058b3661044e565b6060810173ffffffffffffffffffffffffffffffffffffffff6105c2825173ffffffffffffffffffffffffffffffffffffffff1690565b16156106f1575b5073ffffffffffffffffffffffffffffffffffffffff61061a6106008467ffffffffffffffff166000526003602052604060002090565b5473ffffffffffffffffffffffffffffffffffffffff1690565b1680156106b9579060209161065e936040518095819482937f20487ded00000000000000000000000000000000000000000000000000000000845260048401611a98565b03915afa80156106b45761032791600091610685575b506040519081529081906020820190565b6106a7915060203d6020116106ad575b61069f818361019c565b8101906119c0565b38610674565b503d610695565b611ab9565b7fae236d9c0000000000000000000000000000000000000000000000000000000060005267ffffffffffffffff831660045260246000fd5b61072e9061071460025473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff169052565b386105c9565b9392916107539060409215158652606060208701526060860190610237565b930152565b346101475760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101475760043567ffffffffffffffff81116101475760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82360301126101475760243561ffff8116810361014757610327916107f49160443590606435926107ec8461039c565b600401611ce2565b60409391935193849384610734565b346101475760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346101475760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101475773ffffffffffffffffffffffffffffffffffffffff6004356108c28161039c565b6108ca6123fe565b167fffffffffffffffffffffffff00000000000000000000000000000000000000006002541617600255600080f35b346101475760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610147576109546004356109378161039c565b6024356109438161039c565b6044359161094f6123fe565b611ef4565b005b346101475760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014757602060405160848152f35b346101475760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101475773ffffffffffffffffffffffffffffffffffffffff600154163303610a8d5760005473ffffffffffffffffffffffffffffffffffffffff16600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001633179055610a4e7fffffffffffffffffffffffff000000000000000000000000000000000000000060015416600155565b73ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152fd5b346101475760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610147576020610b53610b40600435610b2e8161032b565b60243590610b3b8261039c565b61250e565b6000526005602052604060002054151590565b6040519015158152f35b346101475760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014757602073ffffffffffffffffffffffffffffffffffffffff60005416604051908152f35b610bb83661044e565b6040517f397796f700000000000000000000000000000000000000000000000000000000815260208160048173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9081156106b457600091611116575b506110ec57610c526106008367ffffffffffffffff166000526003602052604060002090565b73ffffffffffffffffffffffffffffffffffffffff811680156110b4576060830191610cae610c95845173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1690565b610fe157610cee610cd460025473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff168452565b6040517f20487ded00000000000000000000000000000000000000000000000000000000815260208180610d26888a60048401611a98565b0381865afa9081156106b457600091610fc2575b503410610f98573492610d67610c95610c95835173ffffffffffffffffffffffffffffffffffffffff1690565b91823b15610147576000600493604051948580927fd0e30db000000000000000000000000000000000000000000000000000000000825234905af19283156106b457610dda93610f7d575b50610dd5610c9534935173ffffffffffffffffffffffffffffffffffffffff1690565b61247d565b9190915b604082019160005b83518051821015610ef557610c95610e0183610e1c93611fdc565b515173ffffffffffffffffffffffffffffffffffffffff1690565b6040517f48a98aa400000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8816600482015273ffffffffffffffffffffffffffffffffffffffff82166024820152909190602081604481885afa80156106b457600193610ebf92600092610ec5575b5073ffffffffffffffffffffffffffffffffffffffff6020610eb2868b51611fdc565b5101519216903390612558565b01610de6565b610ee791925060203d8111610eee575b610edf818361019c565b810190611ff5565b9038610e8f565b503d610ed5565b610f386020888689600088604051968795869485937fdf0aa9e900000000000000000000000000000000000000000000000000000000855233926004860161200a565b03925af180156106b45761032791600091610f5e57506040519081529081906020820190565b610f77915060203d6020116106ad5761069f818361019c565b82610674565b80610f8c6000610f929361019c565b8061013c565b38610db2565b7f07da6ee60000000000000000000000000000000000000000000000000000000060005260046000fd5b610fdb915060203d6020116106ad5761069f818361019c565b38610d3a565b3461108a57604051907f20487ded0000000000000000000000000000000000000000000000000000000082526020828061101f888a60048401611a98565b0381865afa9081156106b45761106192600092611069575b5061105a610c9583965173ffffffffffffffffffffffffffffffffffffffff1690565b3390612558565b919091610dde565b61108391925060203d6020116106ad5761069f818361019c565b9038611037565b7f1841b4e10000000000000000000000000000000000000000000000000000000060005260046000fd5b7fae236d9c0000000000000000000000000000000000000000000000000000000060005267ffffffffffffffff841660045260246000fd5b7fc14837150000000000000000000000000000000000000000000000000000000060005260046000fd5b611138915060203d60201161113e575b611130818361019c565b810190611ac5565b38610c2c565b503d611126565b602060408183019282815284518094520192019060005b8181106111695750505090565b8251805167ffffffffffffffff16855260209081015173ffffffffffffffffffffffffffffffffffffffff16818601526040909401939092019160010161115c565b346101475760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101475760405180816020600454928381520160046000527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b9260005b8181106112e35750506112289250038261019c565b6112328151612052565b9060005b81518110156112d5578061124c60019284611fdc565b516112b973ffffffffffffffffffffffffffffffffffffffff61127f6112728460a01c90565b67ffffffffffffffff1690565b9261129b61128b6101ee565b67ffffffffffffffff9095168552565b1673ffffffffffffffffffffffffffffffffffffffff166020830152565b6112c38286611fdc565b526112ce8185611fdc565b5001611236565b604051806103278582611145565b8454835260019485019486945060209093019201611213565b346101475760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610147576020610b5360043561133c8161032b565b67ffffffffffffffff16600052600360205273ffffffffffffffffffffffffffffffffffffffff60406000205416151590565b346101475760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101475767ffffffffffffffff6004356113b38161032b565b166000526003602052602073ffffffffffffffffffffffffffffffffffffffff60406000205416604051908152f35b9181601f840112156101475782359167ffffffffffffffff8311610147576020808501948460061b01011161014757565b346101475760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101475760043567ffffffffffffffff8111610147576114629036906004016113e2565b60243567ffffffffffffffff8111610147576114829036906004016113e2565b60443567ffffffffffffffff8111610147576114a29036906004016113e2565b9490936114ad6123fe565b60005b81811061165d5750505060005b8181106115755750505060005b8281106114d357005b806114e96114e460019386866120cd565b611add565b6114ff60206114f98488886120cd565b01612116565b9061151261150d838361250e565b6128a3565b61151f575b5050016114ca565b60405173ffffffffffffffffffffffffffffffffffffffff92909216825267ffffffffffffffff16907fa4bdf64ebdf3316320601a081916a75aa144bcef6c4beeb0e9fb1982cacc6b9490602090a23880611517565b6115836114e48284866120cd565b61159360206114f98486886120cd565b906115ad6115a96115a4848461250e565b6127bf565b1590565b61160d5760405173ffffffffffffffffffffffffffffffffffffffff9290921682526001929167ffffffffffffffff91909116907fa823809efda3ba66c873364eec120fa0923d9fabda73bc97dd5663341e2d9bcb90602090a2016114bd565b7f496477900000000000000000000000000000000000000000000000000000000060005267ffffffffffffffff1660045273ffffffffffffffffffffffffffffffffffffffff1660245260446000fd5b8061167361166e60019385876120cd565b6120dd565b7f1f7d0ec248b80e5c0dde0ee531c4fc8fdb6ce9a2b3d90f560c74acd6a7202f2367ffffffffffffffff61176161174660208501946117386116c9875173ffffffffffffffffffffffffffffffffffffffff1690565b6116f86116de845167ffffffffffffffff1690565b67ffffffffffffffff166000526003602052604060002090565b9073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055565b5167ffffffffffffffff1690565b935173ffffffffffffffffffffffffffffffffffffffff1690565b60405173ffffffffffffffffffffffffffffffffffffffff919091168152921691602090a2016114b0565b346101475760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014757602073ffffffffffffffffffffffffffffffffffffffff60025416604051908152f35b346101475760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101475773ffffffffffffffffffffffffffffffffffffffff60043561182e8161039c565b6118366123fe565b163381146118c457807fffffffffffffffffffffffff0000000000000000000000000000000000000000600154161760015573ffffffffffffffffffffffffffffffffffffffff61189c60005473ffffffffffffffffffffffffffffffffffffffff1690565b167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152fd5b346101475760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610147576119656004356119608161032b565b6121a4565b60405180916020820160208352815180915260206040840192019060005b818110611991575050500390f35b825173ffffffffffffffffffffffffffffffffffffffff16845285945060209384019390920191600101611983565b90816020910312610147575190565b91906119f96119e7845160a0845260a0840190610237565b60208501518382036020850152610237565b9060408401519181810360408301526020808451928381520193019060005b818110611a6057505050608084611a5060606102a796970151606085019073ffffffffffffffffffffffffffffffffffffffff169052565b0151906080818403910152610237565b8251805173ffffffffffffffffffffffffffffffffffffffff1686526020908101518187015260409095019490920191600101611a18565b60409067ffffffffffffffff6102a7949316815281602082015201906119cf565b6040513d6000823e3d90fd5b90816020910312610147575180151581036101475790565b356102a78161032b565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561014757016020813591019167ffffffffffffffff821161014757813603831361014757565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b9160209082815201919060005b818110611b905750505090565b90919260408060019273ffffffffffffffffffffffffffffffffffffffff8735611bb98161039c565b16815260208781013590820152019401929101611b83565b90602082528035602083015267ffffffffffffffff6020820135611bf48161032b565b166040830152611c5b611c1e611c0d6040840184611ae7565b60a0606087015260c0860191611b37565b611c2b6060840184611ae7565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403016080870152611b37565b9060808101357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe182360301811215610147570160208135910167ffffffffffffffff8211610147578160061b36038113610147578360a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06102a796860301910152611b76565b939190926040517f397796f700000000000000000000000000000000000000000000000000000000815260208160048173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9081156106b457600091611ea5575b506110ec5760208501611d7b610b408235611d748161032b565b339061250e565b15611e7b57611deb611e73611e1d7f85572ffb0000000000000000000000000000000000000000000000000000000097611e29967f9b877de93ea9895756e337442c657f95a34fc68e7eb988bdfa693d5be83016b696611e178c604051978891602083019e8f5260248301611bd1565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810188528761019c565b856122d8565b98919690993594611add565b925190206040519384933391859094939273ffffffffffffffffffffffffffffffffffffffff9067ffffffffffffffff606094608085019885521660208401521660408201520152565b0390a1929190565b7fd2316ede0000000000000000000000000000000000000000000000000000000060005260046000fd5b611ebe915060203d60201161113e57611130818361019c565b38611d5a565b3d15611eef573d90611ed5826101fd565b91611ee3604051938461019c565b82523d6000602084013e565b606090565b91909173ffffffffffffffffffffffffffffffffffffffff83168015611f80575073ffffffffffffffffffffffffffffffffffffffff16918215611f3b576101ec9261247d565b6000809350809281925af1611f4e611ec4565b5015611f5657565b7fe417b80b0000000000000000000000000000000000000000000000000000000060005260046000fd5b7f26a78f8f0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8051821015611ff05760209160051b010190565b611fad565b9081602091031261014757516102a78161039c565b92949361204660609367ffffffffffffffff73ffffffffffffffffffffffffffffffffffffffff941686526080602087015260808601906119cf565b95604085015216910152565b9061205c82610384565b612069604051918261019c565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06120978294610384565b019060005b8281106120a857505050565b6020906040516120b78161017b565b600081526000838201528282850101520161209c565b9190811015611ff05760061b0190565b604081360312610147576020604051916120f68361017b565b80356121018161032b565b8352013561210e8161039c565b602082015290565b356102a78161039c565b6020818303126101475780519067ffffffffffffffff821161014757019080601f8301121561014757815161215481610384565b92612162604051948561019c565b81845260208085019260051b82010192831161014757602001905b82821061218a5750505090565b6020809183516121998161039c565b81520191019061217d565b6121db8167ffffffffffffffff16600052600360205273ffffffffffffffffffffffffffffffffffffffff60406000205416151590565b156122985760006122659167ffffffffffffffff811682526003602052612220610c95610c956040852073ffffffffffffffffffffffffffffffffffffffff90541690565b60405180809581947ffbca3b740000000000000000000000000000000000000000000000000000000083526004830191909167ffffffffffffffff6020820193169052565b03915afa9081156106b45760009161227b575090565b6102a791503d806000833e612290818361019c565b810190612120565b5060405160206122a8818361019c565b600082527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810190369083013790565b9391936122e560846101fd565b946122f3604051968761019c565b6084865261230160846101fd565b947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0602088019601368737833b156123d4575a908082106123aa578291038060061c90031115612380576000918291825a9560208451940192f1905a9003923d9060848211612377575b6000908287523e929190565b6084915061236b565b7f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b7fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b7f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b73ffffffffffffffffffffffffffffffffffffffff60005416330361241f57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152fd5b6101ec9273ffffffffffffffffffffffffffffffffffffffff604051937fa9059cbb0000000000000000000000000000000000000000000000000000000060208601521660248401526044830152604482526124da60648361019c565b6125bf565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7bffffffffffffffff000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9160a01b16911681018091116125535790565b6124df565b90919273ffffffffffffffffffffffffffffffffffffffff6101ec9481604051957f23b872dd0000000000000000000000000000000000000000000000000000000060208801521660248601521660448401526064830152606482526124da60848361019c565b73ffffffffffffffffffffffffffffffffffffffff61262f9116916040926000808551936125ed878661019c565b602085527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564602086015260208151910182855af1612629611ec4565b91612934565b8051908161263c57505050565b60208061264d938301019101611ac5565b156126555750565b608490517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152fd5b8054821015611ff05760005260206000200190600090565b91612728918354907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b9055565b80548015612790577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019061276182826126d8565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b1916905555565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008181526005602052604090205490811561289c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82019082821161255357600454927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff840193841161255357838360009561285b9503612861575b50505061284a600461272c565b600590600052602052604060002090565b55600190565b61284a61288d916128836128796128939560046126d8565b90549060031b1c90565b92839160046126d8565b906126f0565b5538808061283d565b5050600090565b60008181526005602052604090205461292e5760045468010000000000000000811015610197576129156128e082600185940160045560046126d8565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b9055600454906000526005602052604060002055600190565b50600090565b919290156129af5750815115612948575090565b3b156129515790565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152fd5b8251909150156129c25750805190602001fd5b6129f8906040519182917f08c379a000000000000000000000000000000000000000000000000000000000835260048301610296565b0390fdfea164736f6c634300081a000a", } var RouterABI = RouterMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/token_admin_registry/token_admin_registry.go b/core/gethwrappers/ccip/generated/token_admin_registry/token_admin_registry.go index 4e1a15ce60f..d9883e72250 100644 --- a/core/gethwrappers/ccip/generated/token_admin_registry/token_admin_registry.go +++ b/core/gethwrappers/ccip/generated/token_admin_registry/token_admin_registry.go @@ -37,8 +37,8 @@ type TokenAdminRegistryTokenConfig struct { } var TokenAdminRegistryMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"AlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidTokenPoolToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"OnlyAdministrator\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"OnlyPendingAdministrator\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"OnlyRegistryModuleOrOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddress\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"currentAdmin\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdministratorTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdministratorTransferred\",\"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\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousPool\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newPool\",\"type\":\"address\"}],\"name\":\"PoolSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"module\",\"type\":\"address\"}],\"name\":\"RegistryModuleAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"module\",\"type\":\"address\"}],\"name\":\"RegistryModuleRemoved\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"name\":\"acceptAdminRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"module\",\"type\":\"address\"}],\"name\":\"addRegistryModule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"startIndex\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxCount\",\"type\":\"uint64\"}],\"name\":\"getAllConfiguredTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getPool\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getPools\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"administrator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"pendingAdministrator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenPool\",\"type\":\"address\"}],\"internalType\":\"structTokenAdminRegistry.TokenConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"administrator\",\"type\":\"address\"}],\"name\":\"isAdministrator\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"module\",\"type\":\"address\"}],\"name\":\"isRegistryModule\",\"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\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"administrator\",\"type\":\"address\"}],\"name\":\"proposeAdministrator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"module\",\"type\":\"address\"}],\"name\":\"removeRegistryModule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"name\":\"setPool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"transferAdminRole\",\"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\"}]", - Bin: "0x608060405234801561001057600080fd5b503360008161003257604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156100625761006281610069565b50506100e2565b336001600160a01b0382160361009257604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6113b9806100f16000396000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c80637d3f255211610097578063cb67e3b111610066578063cb67e3b1146102bc578063ddadfa8e14610374578063e677ae3714610387578063f2fde38b1461039a57600080fd5b80637d3f2552146101e05780638da5cb5b14610203578063bbe4f6db14610242578063c1af6e031461027f57600080fd5b80634e847fc7116100d35780634e847fc7146101925780635e63547a146101a557806372d64a81146101c557806379ba5097146101d857600080fd5b806310cbcf1814610105578063156194da1461011a578063181f5a771461012d5780633dc457721461017f575b600080fd5b6101186101133660046110dc565b6103ad565b005b6101186101283660046110dc565b61040a565b6101696040518060400160405280601881526020017f546f6b656e41646d696e526567697374727920312e352e30000000000000000081525081565b60405161017691906110f7565b60405180910390f35b61011861018d3660046110dc565b61050f565b6101186101a0366004611164565b610573565b6101b86101b3366004611197565b6107d3565b604051610176919061120c565b6101b86101d336600461127e565b6108cc565b6101186109e2565b6101f36101ee3660046110dc565b610ab0565b6040519015158152602001610176565b60015473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610176565b61021d6102503660046110dc565b73ffffffffffffffffffffffffffffffffffffffff908116600090815260026020819052604090912001541690565b6101f361028d366004611164565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260026020526040902054821691161490565b6103356102ca3660046110dc565b60408051606080820183526000808352602080840182905292840181905273ffffffffffffffffffffffffffffffffffffffff948516815260028084529084902084519283018552805486168352600181015486169383019390935291909101549092169082015290565b60408051825173ffffffffffffffffffffffffffffffffffffffff90811682526020808501518216908301529282015190921690820152606001610176565b610118610382366004611164565b610abd565b610118610395366004611164565b610bc7565b6101186103a83660046110dc565b610d8f565b6103b5610da0565b6103c0600582610df3565b156104075760405173ffffffffffffffffffffffffffffffffffffffff8216907f93eaa26dcb9275e56bacb1d33fdbf402262da6f0f4baf2a6e2cd154b73f387f890600090a25b50565b73ffffffffffffffffffffffffffffffffffffffff808216600090815260026020526040902060018101549091163314610493576040517f3edffe7500000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff831660248201526044015b60405180910390fd5b8054337fffffffffffffffffffffffff00000000000000000000000000000000000000009182168117835560018301805490921690915560405173ffffffffffffffffffffffffffffffffffffffff8416907f399b55200f7f639a63d76efe3dcfa9156ce367058d6b673041b84a628885f5a790600090a35050565b610517610da0565b610522600582610e1c565b156104075760405173ffffffffffffffffffffffffffffffffffffffff821681527f3cabf004338366bfeaeb610ad827cb58d16b588017c509501f2c97c83caae7b29060200160405180910390a150565b73ffffffffffffffffffffffffffffffffffffffff80831660009081526002602052604090205483911633146105f3576040517fed5d85b500000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff8216602482015260440161048a565b73ffffffffffffffffffffffffffffffffffffffff8216158015906106a557506040517f240028e800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff848116600483015283169063240028e890602401602060405180830381865afa15801561067f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106a391906112a8565b155b156106f4576040517f962b60e600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260240161048a565b73ffffffffffffffffffffffffffffffffffffffff808416600090815260026020819052604090912090810180548584167fffffffffffffffffffffffff0000000000000000000000000000000000000000821681179092559192919091169081146107cc578373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f754449ec3aff3bd528bfce43ae9319c4a381b67fcd1d20097b3b24dacaecc35d60405160405180910390a45b5050505050565b606060008267ffffffffffffffff8111156107f0576107f06112ca565b604051908082528060200260200182016040528015610819578160200160208202803683370190505b50905060005b838110156108c2576002600086868481811061083d5761083d6112f9565b905060200201602081019061085291906110dc565b73ffffffffffffffffffffffffffffffffffffffff90811682526020820192909252604001600020600201548351911690839083908110610895576108956112f9565b73ffffffffffffffffffffffffffffffffffffffff9092166020928302919091019091015260010161081f565b5090505b92915050565b606060006108da6003610e3e565b9050808467ffffffffffffffff16106108f357506108c6565b67ffffffffffffffff80841690829061090e90871683611357565b111561092b5761092867ffffffffffffffff86168361136a565b90505b8067ffffffffffffffff811115610944576109446112ca565b60405190808252806020026020018201604052801561096d578160200160208202803683370190505b50925060005b818110156109d95761099a6109928267ffffffffffffffff8916611357565b600390610e48565b8482815181106109ac576109ac6112f9565b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152600101610973565b50505092915050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a33576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60006108c6600583610e54565b73ffffffffffffffffffffffffffffffffffffffff8083166000908152600260205260409020548391163314610b3d576040517fed5d85b500000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff8216602482015260440161048a565b73ffffffffffffffffffffffffffffffffffffffff8381166000818152600260205260408082206001810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001695881695861790559051909392339290917fc54c3051ff16e63bb9203214432372aca006c589e3653619b577a3265675b7169190a450505050565b610bd033610ab0565b158015610bf5575060015473ffffffffffffffffffffffffffffffffffffffff163314155b15610c2e576040517f51ca1ec300000000000000000000000000000000000000000000000000000000815233600482015260240161048a565b73ffffffffffffffffffffffffffffffffffffffff8116610c7b576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8083166000908152600260205260409020805490911615610cf5576040517f45ed80e900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260240161048a565b6001810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416179055610d42600384610e1c565b5060405173ffffffffffffffffffffffffffffffffffffffff808416916000918616907fc54c3051ff16e63bb9203214432372aca006c589e3653619b577a3265675b716908390a4505050565b610d97610da0565b61040781610e83565b60015473ffffffffffffffffffffffffffffffffffffffff163314610df1576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6000610e158373ffffffffffffffffffffffffffffffffffffffff8416610f47565b9392505050565b6000610e158373ffffffffffffffffffffffffffffffffffffffff841661103a565b60006108c6825490565b6000610e158383611089565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610e15565b3373ffffffffffffffffffffffffffffffffffffffff821603610ed2576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120548015611030576000610f6b60018361136a565b8554909150600090610f7f9060019061136a565b9050808214610fe4576000866000018281548110610f9f57610f9f6112f9565b9060005260206000200154905080876000018481548110610fc257610fc26112f9565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080610ff557610ff561137d565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506108c6565b60009150506108c6565b6000818152600183016020526040812054611081575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556108c6565b5060006108c6565b60008260000182815481106110a0576110a06112f9565b9060005260206000200154905092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146110d757600080fd5b919050565b6000602082840312156110ee57600080fd5b610e15826110b3565b60006020808352835180602085015260005b8181101561112557858101830151858201604001528201611109565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b6000806040838503121561117757600080fd5b611180836110b3565b915061118e602084016110b3565b90509250929050565b600080602083850312156111aa57600080fd5b823567ffffffffffffffff808211156111c257600080fd5b818501915085601f8301126111d657600080fd5b8135818111156111e557600080fd5b8660208260051b85010111156111fa57600080fd5b60209290920196919550909350505050565b6020808252825182820181905260009190848201906040850190845b8181101561125a57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101611228565b50909695505050505050565b803567ffffffffffffffff811681146110d757600080fd5b6000806040838503121561129157600080fd5b61129a83611266565b915061118e60208401611266565b6000602082840312156112ba57600080fd5b81518015158114610e1557600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156108c6576108c6611328565b818103818111156108c6576108c6611328565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", + ABI: "[{\"type\":\"function\",\"name\":\"acceptAdminRole\",\"inputs\":[{\"name\":\"localToken\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"acceptOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"addRegistryModule\",\"inputs\":[{\"name\":\"module\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getAllConfiguredTokens\",\"inputs\":[{\"name\":\"startIndex\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"maxCount\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"tokens\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getPool\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getPools\",\"inputs\":[{\"name\":\"tokens\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTokenConfig\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structTokenAdminRegistry.TokenConfig\",\"components\":[{\"name\":\"administrator\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"pendingAdministrator\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenPool\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isAdministrator\",\"inputs\":[{\"name\":\"localToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"administrator\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isRegistryModule\",\"inputs\":[{\"name\":\"module\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposeAdministrator\",\"inputs\":[{\"name\":\"localToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"administrator\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"removeRegistryModule\",\"inputs\":[{\"name\":\"module\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setPool\",\"inputs\":[{\"name\":\"localToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"pool\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferAdminRole\",\"inputs\":[{\"name\":\"localToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"newAdmin\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"typeAndVersion\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"AdministratorTransferRequested\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"currentAdmin\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newAdmin\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"AdministratorTransferred\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newAdmin\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferRequested\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"PoolSet\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"previousPool\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newPool\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RegistryModuleAdded\",\"inputs\":[{\"name\":\"module\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RegistryModuleRemoved\",\"inputs\":[{\"name\":\"module\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AlreadyRegistered\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"CannotTransferToSelf\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidTokenPoolToken\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"MustBeProposedOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OnlyAdministrator\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"OnlyCallableByOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OnlyPendingAdministrator\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"OnlyRegistryModuleOrOwner\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"OwnerCannotBeZero\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ZeroAddress\",\"inputs\":[]}]", + Bin: "0x60808060405234603d573315602c57600180546001600160a01b031916331790556114a790816100438239f35b639b15e16f60e01b60005260046000fd5b600080fdfe6080604052600436101561001257600080fd5b60003560e01c806310cbcf1814610e82578063156194da14610d45578063181f5a7714610c335780633dc4577214610ba25780634e847fc7146109b65780635e63547a146108be57806372d64a811461084957806379ba5097146107605780637d3f2552146106f15780638da5cb5b1461069f578063bbe4f6db14610621578063c1af6e0314610587578063cb67e3b1146104b5578063ddadfa8e14610385578063e677ae37146101c15763f2fde38b146100cc57600080fd5b346101bc5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc5773ffffffffffffffffffffffffffffffffffffffff610118610f0d565b6101206111e7565b1633811461019257807fffffffffffffffffffffffff0000000000000000000000000000000000000000600054161760005573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b7fdad89dca0000000000000000000000000000000000000000000000000000000060005260046000fd5b600080fd5b346101bc5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc576101f8610f0d565b610200610f30565b610217336000526006602052604060002054151590565b1580610363575b6103355773ffffffffffffffffffffffffffffffffffffffff1690811561030b5773ffffffffffffffffffffffffffffffffffffffff16806000526002602052604060002073ffffffffffffffffffffffffffffffffffffffff8154166102dd5760010180547fffffffffffffffffffffffff000000000000000000000000000000000000000016831790556000906102b681611440565b507fc54c3051ff16e63bb9203214432372aca006c589e3653619b577a3265675b7168280a4005b507f45ed80e90000000000000000000000000000000000000000000000000000000060005260045260246000fd5b7fd92e233d0000000000000000000000000000000000000000000000000000000060005260046000fd5b7f51ca1ec3000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b5073ffffffffffffffffffffffffffffffffffffffff6001541633141561021e565b346101bc5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc576103bc610f0d565b73ffffffffffffffffffffffffffffffffffffffff6103d9610f30565b91169081600052600260205273ffffffffffffffffffffffffffffffffffffffff6040600020541633036104835773ffffffffffffffffffffffffffffffffffffffff9082600052600260205260016040600020018282167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055169033907fc54c3051ff16e63bb9203214432372aca006c589e3653619b577a3265675b716600080a4005b507fed5d85b5000000000000000000000000000000000000000000000000000000006000523360045260245260446000fd5b346101bc5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc5773ffffffffffffffffffffffffffffffffffffffff610501610f0d565b60006040805161051081610f53565b82815282602082015201521660005260026020526060604060002073ffffffffffffffffffffffffffffffffffffffff60405161054c81610f53565b818084541693848352604082600281600185015416936020870194855201541693019283526040519485525116602084015251166040820152f35b346101bc5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc5760206105c0610f0d565b73ffffffffffffffffffffffffffffffffffffffff6105dd610f30565b91166000526002825273ffffffffffffffffffffffffffffffffffffffff6040600020541673ffffffffffffffffffffffffffffffffffffffff6040519216148152f35b346101bc5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc5773ffffffffffffffffffffffffffffffffffffffff61066d610f0d565b166000526002602052602073ffffffffffffffffffffffffffffffffffffffff60026040600020015416604051908152f35b346101bc5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc57602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b346101bc5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc57602061075673ffffffffffffffffffffffffffffffffffffffff610742610f0d565b166000526006602052604060002054151590565b6040519015158152f35b346101bc5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc5760005473ffffffffffffffffffffffffffffffffffffffff8116330361081f577fffffffffffffffffffffffff00000000000000000000000000000000000000006001549133828416176001551660005573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b7f02b543c60000000000000000000000000000000000000000000000000000000060005260046000fd5b346101bc5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc5760043567ffffffffffffffff811681036101bc576024359067ffffffffffffffff821682036101bc576108ba916108ae916110e6565b60405191829182610fb0565b0390f35b346101bc5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc5760043567ffffffffffffffff81116101bc57366023820112156101bc57806004013567ffffffffffffffff81116101bc573660248260051b840101116101bc5761093681611018565b60005b828110156109a857600060248260051b8601013573ffffffffffffffffffffffffffffffffffffffff81168091036109a457600260408373ffffffffffffffffffffffffffffffffffffffff936001969552826020522001541661099d8285611067565b5201610939565b5080fd5b604051806108ba8482610fb0565b346101bc5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc576109ed610f0d565b73ffffffffffffffffffffffffffffffffffffffff610a0a610f30565b91169081600052600260205273ffffffffffffffffffffffffffffffffffffffff6040600020541633036104835773ffffffffffffffffffffffffffffffffffffffff169081151580610b0c575b610adf5780600052600260205260026040600020019073ffffffffffffffffffffffffffffffffffffffff82541691837fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055828203610ab857005b7f754449ec3aff3bd528bfce43ae9319c4a381b67fcd1d20097b3b24dacaecc35d600080a4005b7f962b60e60000000000000000000000000000000000000000000000000000000060005260045260246000fd5b506040517f240028e8000000000000000000000000000000000000000000000000000000008152816004820152602081602481865afa908115610b9657600091610b58575b5015610a58565b6020813d602011610b8e575b81610b7160209383610f6f565b810103126109a45751908115158203610b8b575083610b51565b80fd5b3d9150610b64565b6040513d6000823e3d90fd5b346101bc5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc5773ffffffffffffffffffffffffffffffffffffffff610bee610f0d565b610bf66111e7565b16610c00816113e0565b610c0657005b60207f3cabf004338366bfeaeb610ad827cb58d16b588017c509501f2c97c83caae7b291604051908152a1005b346101bc5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc576040516040810181811067ffffffffffffffff821117610d1657604052601881527f546f6b656e41646d696e526567697374727920312e352e300000000000000000602082015260405190602082528181519182602083015260005b838110610cfe5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f836000604080968601015201168101030190f35b60208282018101516040878401015285935001610cbe565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b346101bc5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc5773ffffffffffffffffffffffffffffffffffffffff610d91610f0d565b168060005260026020526040600020600181019073ffffffffffffffffffffffffffffffffffffffff8254163303610e505773ffffffffffffffffffffffffffffffffffffffff33167fffffffffffffffffffffffff00000000000000000000000000000000000000008254161790557fffffffffffffffffffffffff0000000000000000000000000000000000000000815416905533907f399b55200f7f639a63d76efe3dcfa9156ce367058d6b673041b84a628885f5a7600080a3005b827f3edffe75000000000000000000000000000000000000000000000000000000006000523360045260245260446000fd5b346101bc5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc5773ffffffffffffffffffffffffffffffffffffffff610ece610f0d565b610ed66111e7565b16610ee08161124a565b610ee657005b7f93eaa26dcb9275e56bacb1d33fdbf402262da6f0f4baf2a6e2cd154b73f387f8600080a2005b6004359073ffffffffffffffffffffffffffffffffffffffff821682036101bc57565b6024359073ffffffffffffffffffffffffffffffffffffffff821682036101bc57565b6060810190811067ffffffffffffffff821117610d1657604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610d1657604052565b602060408183019282815284518094520192019060005b818110610fd45750505090565b825173ffffffffffffffffffffffffffffffffffffffff16845260209384019390920191600101610fc7565b67ffffffffffffffff8111610d165760051b60200190565b9061102282611000565b61102f6040519182610f6f565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061105d8294611000565b0190602036910137565b805182101561107b5760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b919082018092116110b757565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff600354911691818310156111df5767ffffffffffffffff16908061111384846110aa565b116111ce575b509061112482611018565b91600091600354925b82811061113b575050505090565b61114581836110aa565b6000858210156111a157600390527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b01546001919073ffffffffffffffffffffffffffffffffffffffff1661119a8288611067565b520161112d565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526032600452fd5b828103915081116110b75738611119565b505050606090565b73ffffffffffffffffffffffffffffffffffffffff60015416330361120857565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b805482101561107b5760005260206000200190600090565b60008181526006602052604090205480156113d9577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81018181116110b757600554907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82019182116110b75781810361136a575b505050600554801561133b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff016112f8816005611232565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600555600052600660205260006040812055600190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6113c161137b61138c936005611232565b90549060031b1c9283926005611232565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b905560005260066020526040600020553880806112bf565b5050600090565b8060005260066020526040600020541560001461143a5760055468010000000000000000811015610d165761142161138c8260018594016005556005611232565b9055600554906000526006602052604060002055600190565b50600090565b8060005260046020526040600020541560001461143a5760035468010000000000000000811015610d165761148161138c8260018594016003556003611232565b905560035490600052600460205260406000205560019056fea164736f6c634300081a000a", } var TokenAdminRegistryABI = TokenAdminRegistryMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/token_pool/token_pool.go b/core/gethwrappers/ccip/generated/token_pool/token_pool.go index c7c947d8636..587f4ebb84b 100644 --- a/core/gethwrappers/ccip/generated/token_pool/token_pool.go +++ b/core/gethwrappers/ccip/generated/token_pool/token_pool.go @@ -81,7 +81,7 @@ type TokenPoolChainUpdate struct { } var TokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MismatchedArrayLengths\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"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\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"lockOrBurnOut\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectors\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"outboundConfigs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"inboundConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setChainRateLimiterConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"type\":\"function\",\"name\":\"acceptOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"addRemotePool\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyAllowListUpdates\",\"inputs\":[{\"name\":\"removes\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"adds\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyChainUpdates\",\"inputs\":[{\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"},{\"name\":\"chainsToAdd\",\"type\":\"tuple[]\",\"internalType\":\"structTokenPool.ChainUpdate[]\",\"components\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"},{\"name\":\"remoteTokenAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getAllowList\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getAllowListEnabled\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCurrentInboundRateLimiterState\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.TokenBucket\",\"components\":[{\"name\":\"tokens\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"lastUpdated\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCurrentOutboundRateLimiterState\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.TokenBucket\",\"components\":[{\"name\":\"tokens\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"lastUpdated\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRateLimitAdmin\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRemotePools\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRemoteToken\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRmnProxy\",\"inputs\":[],\"outputs\":[{\"name\":\"rmnProxy\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRouter\",\"inputs\":[],\"outputs\":[{\"name\":\"router\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getSupportedChains\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getToken\",\"inputs\":[],\"outputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"contractIERC20\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTokenDecimals\",\"inputs\":[],\"outputs\":[{\"name\":\"decimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isRemotePool\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isSupportedChain\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isSupportedToken\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"lockOrBurn\",\"inputs\":[{\"name\":\"lockOrBurnIn\",\"type\":\"tuple\",\"internalType\":\"structPool.LockOrBurnInV1\",\"components\":[{\"name\":\"receiver\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"originalSender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"localToken\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"outputs\":[{\"name\":\"lockOrBurnOut\",\"type\":\"tuple\",\"internalType\":\"structPool.LockOrBurnOutV1\",\"components\":[{\"name\":\"destTokenAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"destPoolData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"releaseOrMint\",\"inputs\":[{\"name\":\"releaseOrMintIn\",\"type\":\"tuple\",\"internalType\":\"structPool.ReleaseOrMintInV1\",\"components\":[{\"name\":\"originalSender\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"receiver\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"localToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"sourcePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"sourcePoolData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"offchainTokenData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"components\":[{\"name\":\"destinationAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"removeRemotePool\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setChainRateLimiterConfig\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"outboundConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setChainRateLimiterConfigs\",\"inputs\":[{\"name\":\"remoteChainSelectors\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"},{\"name\":\"outboundConfigs\",\"type\":\"tuple[]\",\"internalType\":\"structRateLimiter.Config[]\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundConfigs\",\"type\":\"tuple[]\",\"internalType\":\"structRateLimiter.Config[]\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setRateLimitAdmin\",\"inputs\":[{\"name\":\"rateLimitAdmin\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setRouter\",\"inputs\":[{\"name\":\"newRouter\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"AllowListAdd\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"AllowListRemove\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Burned\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChainAdded\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"remoteToken\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"},{\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChainConfigured\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChainRemoved\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ConfigChanged\",\"inputs\":[{\"name\":\"config\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Locked\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Minted\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferRequested\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RateLimitAdminSet\",\"inputs\":[{\"name\":\"rateLimitAdmin\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Released\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RemotePoolAdded\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RemotePoolRemoved\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RouterUpdated\",\"inputs\":[{\"name\":\"oldRouter\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"newRouter\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AllowListNotEnabled\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CallerIsNotARampOnRouter\",\"inputs\":[{\"name\":\"caller\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"CannotTransferToSelf\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ChainAlreadyExists\",\"inputs\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"ChainNotAllowed\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"CursedByRMN\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"DisabledNonZeroRateLimit\",\"inputs\":[{\"name\":\"config\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}]},{\"type\":\"error\",\"name\":\"InvalidDecimalArgs\",\"inputs\":[{\"name\":\"expected\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"actual\",\"type\":\"uint8\",\"internalType\":\"uint8\"}]},{\"type\":\"error\",\"name\":\"InvalidRateLimitRate\",\"inputs\":[{\"name\":\"rateLimiterConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}]},{\"type\":\"error\",\"name\":\"InvalidRemoteChainDecimals\",\"inputs\":[{\"name\":\"sourcePoolData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidRemotePoolForChain\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidSourcePoolAddress\",\"inputs\":[{\"name\":\"sourcePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidToken\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"MismatchedArrayLengths\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MustBeProposedOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NonExistentChain\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"OnlyCallableByOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OverflowDetected\",\"inputs\":[{\"name\":\"remoteDecimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"localDecimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"remoteAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"OwnerCannotBeZero\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PoolAlreadyAdded\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"RateLimitMustBeDisabled\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"SenderNotAllowed\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"Unauthorized\",\"inputs\":[{\"name\":\"caller\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ZeroAddressNotAllowed\",\"inputs\":[]}]", } var TokenPoolABI = TokenPoolMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/usdc_reader_tester/usdc_reader_tester.go b/core/gethwrappers/ccip/generated/usdc_reader_tester/usdc_reader_tester.go index f9bd3b56efa..ab8002c05eb 100644 --- a/core/gethwrappers/ccip/generated/usdc_reader_tester/usdc_reader_tester.go +++ b/core/gethwrappers/ccip/generated/usdc_reader_tester/usdc_reader_tester.go @@ -31,8 +31,8 @@ var ( ) var USDCReaderTesterMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"MessageSent\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"sourceDomain\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destinationDomain\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"recipient\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"destinationCaller\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"sender\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"messageBody\",\"type\":\"bytes\"}],\"name\":\"emitMessageSent\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5061032c806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c806362826f1814610030575b600080fd5b61004361003e366004610129565b610045565b005b600061008d8a8a8a87898c8c8a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506100d292505050565b90507f8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b036816040516100be9190610228565b60405180910390a150505050505050505050565b606088888888888888886040516020016100f3989796959493929190610279565b604051602081830303815290604052905098975050505050505050565b803563ffffffff8116811461012457600080fd5b919050565b60008060008060008060008060006101008a8c03121561014857600080fd5b6101518a610110565b985061015f60208b01610110565b975061016d60408b01610110565b965060608a0135955060808a0135945060a08a0135935060c08a013567ffffffffffffffff80821682146101a057600080fd5b90935060e08b013590808211156101b657600080fd5b818c0191508c601f8301126101ca57600080fd5b8135818111156101d957600080fd5b8d60208285010111156101eb57600080fd5b6020830194508093505050509295985092959850929598565b60005b8381101561021f578181015183820152602001610207565b50506000910152565b6020815260008251806020840152610247816040850160208701610204565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60007fffffffff00000000000000000000000000000000000000000000000000000000808b60e01b168352808a60e01b166004840152808960e01b166008840152507fffffffffffffffff0000000000000000000000000000000000000000000000008760c01b16600c830152856014830152846034830152836054830152825161030b816074850160208701610204565b91909101607401999850505050505050505056fea164736f6c6343000818000a", + ABI: "[{\"type\":\"function\",\"name\":\"emitMessageSent\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"sourceDomain\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destinationDomain\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"recipient\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"destinationCaller\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"sender\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"messageBody\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"MessageSent\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false}]", + Bin: "0x6080806040523460155761034b908161001b8239f35b600080fdfe608080604052600436101561001357600080fd5b60003560e01c6362826f181461002857600080fd5b346102a6576101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102a65760043563ffffffff811681036102a65760243563ffffffff811681036102a6576044359063ffffffff821682036102a65760c4359367ffffffffffffffff851685036102a65760e4359067ffffffffffffffff82116102a657366023830112156102a65781600401359567ffffffffffffffff87116102a65736602488850101116102a657600087601f8299017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200161011490856102ab565b8084528060208501956024018637830160200152604051948594602086019760e01b7fffffffff0000000000000000000000000000000000000000000000000000000016885260e01b7fffffffff0000000000000000000000000000000000000000000000000000000016602486015260e01b7fffffffff0000000000000000000000000000000000000000000000000000000016602885015260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016602c84015260a435603484015260643560548401526084356074840152519081609484016102009261031b565b8101036094017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101825261023590826102ab565b60405191829160208352519081602084015281604084016102559261031b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168101036040017f8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b03691a180f35b600080fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176102ec57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60005b83811061032e5750506000910152565b818101518382015260200161031e56fea164736f6c634300081a000a", } var USDCReaderTesterABI = USDCReaderTesterMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/usdc_token_pool/usdc_token_pool.go b/core/gethwrappers/ccip/generated/usdc_token_pool/usdc_token_pool.go index fb9493b24ac..5e07dde287f 100644 --- a/core/gethwrappers/ccip/generated/usdc_token_pool/usdc_token_pool.go +++ b/core/gethwrappers/ccip/generated/usdc_token_pool/usdc_token_pool.go @@ -94,8 +94,8 @@ type USDCTokenPoolDomainUpdate struct { } var USDCTokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractITokenMessenger\",\"name\":\"tokenMessenger\",\"type\":\"address\"},{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"expected\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"got\",\"type\":\"uint32\"}],\"name\":\"InvalidDestinationDomain\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structUSDCTokenPool.DomainUpdate\",\"name\":\"domain\",\"type\":\"tuple\"}],\"name\":\"InvalidDomain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"}],\"name\":\"InvalidMessageVersion\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"expected\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"got\",\"type\":\"uint64\"}],\"name\":\"InvalidNonce\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"}],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"expected\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"got\",\"type\":\"uint32\"}],\"name\":\"InvalidSourceDomain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"}],\"name\":\"InvalidTokenMessengerVersion\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MismatchedArrayLengths\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"domain\",\"type\":\"uint64\"}],\"name\":\"UnknownDomain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnlockingUSDCFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenMessenger\",\"type\":\"address\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structUSDCTokenPool.DomainUpdate[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"name\":\"DomainsSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"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\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"SUPPORTED_USDC_VERSION\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"getDomain\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structUSDCTokenPool.Domain\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_localDomainIdentifier\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_messageTransmitter\",\"outputs\":[{\"internalType\":\"contractIMessageTransmitter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_tokenMessenger\",\"outputs\":[{\"internalType\":\"contractITokenMessenger\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectors\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"outboundConfigs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"inboundConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setChainRateLimiterConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structUSDCTokenPool.DomainUpdate[]\",\"name\":\"domains\",\"type\":\"tuple[]\"}],\"name\":\"setDomains\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"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\"}]", - Bin: "0x6101606040523480156200001257600080fd5b506040516200573a3803806200573a833981016040819052620000359162000b93565b836006848484336000816200005d57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200009057620000908162000493565b50506001600160a01b0385161580620000b057506001600160a01b038116155b80620000c357506001600160a01b038216155b15620000e2576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b03808616608081905290831660c0526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa92505050801562000152575060408051601f3d908101601f191682019092526200014f9181019062000cb9565b60015b1562000193578060ff168560ff161462000191576040516332ad3e0760e11b815260ff8087166004830152821660248201526044015b60405180910390fd5b505b60ff841660a052600480546001600160a01b0319166001600160a01b038316179055825115801560e052620001dd57604080516000815260208101909152620001dd90846200050d565b5050506001600160a01b03871691506200020c9050576040516306b7c75960e31b815260040160405180910390fd5b6000856001600160a01b0316632c1219216040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200024d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000273919062000ce5565b90506000816001600160a01b03166354fd4d506040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002b6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002dc919062000d05565b905063ffffffff8116156200030d576040516334697c6b60e11b815263ffffffff8216600482015260240162000188565b6000876001600160a01b0316639cdbb1816040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200034e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000374919062000d05565b905063ffffffff811615620003a5576040516316ba39c560e31b815263ffffffff8216600482015260240162000188565b6001600160a01b038089166101005283166101208190526040805163234d8e3d60e21b81529051638d3638f4916004808201926020929091908290030181865afa158015620003f8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200041e919062000d05565b63ffffffff16610140526101005160805162000449916001600160a01b03909116906000196200066a565b6040516001600160a01b03891681527f2e902d38f15b233cbb63711add0fca4545334d3a169d60c0a616494d7eea95449060200160405180910390a1505050505050505062000e52565b336001600160a01b03821603620004bd57604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e0516200052e576040516335f4a7b360e01b815260040160405180910390fd5b60005b8251811015620005b957600083828151811062000552576200055262000d2d565b602090810291909101015190506200056c60028262000750565b15620005af576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b5060010162000531565b5060005b815181101562000665576000828281518110620005de57620005de62000d2d565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200060a57506200065c565b6200061760028262000770565b156200065a576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101620005bd565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa158015620006bc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620006e2919062000d43565b620006ee919062000d73565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b179091529192506200074a918691906200078716565b50505050565b600062000767836001600160a01b03841662000858565b90505b92915050565b600062000767836001600160a01b0384166200095c565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656490820152600090620007d6906001600160a01b038516908490620009ae565b805190915015620006655780806020019051810190620007f7919062000d89565b620006655760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000188565b60008181526001830160205260408120548015620009515760006200087f60018362000dad565b8554909150600090620008959060019062000dad565b905080821462000901576000866000018281548110620008b957620008b962000d2d565b9060005260206000200154905080876000018481548110620008df57620008df62000d2d565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000915576200091562000dc3565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506200076a565b60009150506200076a565b6000818152600183016020526040812054620009a5575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556200076a565b5060006200076a565b6060620009bf8484600085620009c7565b949350505050565b60608247101562000a2a5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000188565b600080866001600160a01b0316858760405162000a48919062000dff565b60006040518083038185875af1925050503d806000811462000a87576040519150601f19603f3d011682016040523d82523d6000602084013e62000a8c565b606091505b50909250905062000aa08783838762000aab565b979650505050505050565b6060831562000b1f57825160000362000b17576001600160a01b0385163b62000b175760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000188565b5081620009bf565b620009bf838381511562000b365781518083602001fd5b8060405162461bcd60e51b815260040162000188919062000e1d565b6001600160a01b038116811462000b6857600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b805162000b8e8162000b52565b919050565b600080600080600060a0868803121562000bac57600080fd5b855162000bb98162000b52565b8095505060208087015162000bce8162000b52565b60408801519095506001600160401b038082111562000bec57600080fd5b818901915089601f83011262000c0157600080fd5b81518181111562000c165762000c1662000b6b565b8060051b604051601f19603f8301168101818110858211171562000c3e5762000c3e62000b6b565b60405291825284820192508381018501918c83111562000c5d57600080fd5b938501935b8285101562000c865762000c768562000b81565b8452938501939285019262000c62565b80985050505050505062000c9d6060870162000b81565b915062000cad6080870162000b81565b90509295509295909350565b60006020828403121562000ccc57600080fd5b815160ff8116811462000cde57600080fd5b9392505050565b60006020828403121562000cf857600080fd5b815162000cde8162000b52565b60006020828403121562000d1857600080fd5b815163ffffffff8116811462000cde57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121562000d5657600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b808201808211156200076a576200076a62000d5d565b60006020828403121562000d9c57600080fd5b8151801515811462000cde57600080fd5b818103818111156200076a576200076a62000d5d565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000df657818101518382015260200162000ddc565b50506000910152565b6000825162000e1381846020870162000dd9565b9190910192915050565b602081526000825180602084015262000e3e81604085016020870162000dd9565b601f01601f19169190910160400192915050565b60805160a05160c05160e05161010051610120516101405161483262000f0860003960008181610432015281816112c40152818161228f01526122ed0152600081816107590152610aa30152600081816103f801526111da01526000818161070a015281816123a50152612ef60152600081816106460152818161203c015261277b015260006103810152600081816102e80152818161033d015281816111a401528181612cea01526130e101526148326000f3fe608060405234801561001057600080fd5b506004361061025b5760003560e01c80639a4575b911610145578063c4bffe2b116100bd578063dfadfa351161008c578063e8a1da1711610071578063e8a1da171461072e578063f2fde38b14610741578063fbf84dd71461075457600080fd5b8063dfadfa351461066a578063e0351e131461070857600080fd5b8063c4bffe2b14610609578063c75eea9c1461061e578063cf7401f314610631578063dc0bd9711461064457600080fd5b8063acfecf9111610114578063b0f479a1116100f9578063b0f479a1146105c5578063b7946580146105e3578063c0d78655146105f657600080fd5b8063acfecf9114610543578063af58d59f1461055657600080fd5b80639a4575b9146104e65780639fdf13ff14610506578063a42a7b8b1461050e578063a7cd63b71461052e57600080fd5b80636155cda0116101d857806379ba5097116101a75780638926f54f1161018c5780638926f54f146104a25780638da5cb5b146104b5578063962d4020146104d357600080fd5b806379ba5097146104875780637d54534e1461048f57600080fd5b80636155cda0146103f357806362ddd3c41461041a5780636b716b0d1461042d5780636d3d1a581461046957600080fd5b8063240028e81161022f578063390775371161021457806339077537146103ab5780634c5ef0ed146103cd57806354c8a4f3146103e057600080fd5b8063240028e81461032d57806324f65ee71461037a57600080fd5b806241d3c11461026057806301ffc9a714610275578063181f5a771461029d57806321df0da7146102e6575b600080fd5b61027361026e3660046136ff565b61077b565b005b610288610283366004613774565b610918565b60405190151581526020015b60405180910390f35b6102d96040518060400160405280601381526020017f55534443546f6b656e506f6f6c20312e352e310000000000000000000000000081525081565b604051610294919061381a565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610294565b61028861033b36600461384f565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610294565b6103be6103b936600461386c565b6109fd565b60405190518152602001610294565b6102886103db3660046138be565b610be2565b6102736103ee36600461398f565b610c2c565b6103087f000000000000000000000000000000000000000000000000000000000000000081565b6102736104283660046138be565b610ca7565b6104547f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff9091168152602001610294565b60095473ffffffffffffffffffffffffffffffffffffffff16610308565b610273610d3f565b61027361049d36600461384f565b610e0d565b6102886104b03660046139fb565b610e8e565b60015473ffffffffffffffffffffffffffffffffffffffff16610308565b6102736104e1366004613a5d565b610ea5565b6104f96104f4366004613af7565b610fff565b6040516102949190613b32565b610454600081565b61052161051c3660046139fb565b61133f565b6040516102949190613b89565b6105366114aa565b6040516102949190613c0b565b6102736105513660046138be565b6114bb565b6105696105643660046139fb565b6115d3565b604051610294919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610308565b6102d96105f13660046139fb565b6116a8565b61027361060436600461384f565b611758565b61061161182c565b6040516102949190613c65565b61056961062c3660046139fb565b6118e4565b61027361063f366004613df2565b6119b6565b7f0000000000000000000000000000000000000000000000000000000000000000610308565b6106de6106783660046139fb565b60408051606080820183526000808352602080840182905292840181905267ffffffffffffffff949094168452600a82529282902082519384018352805484526001015463ffffffff811691840191909152640100000000900460ff1615159082015290565b604080518251815260208084015163ffffffff169082015291810151151590820152606001610294565b7f0000000000000000000000000000000000000000000000000000000000000000610288565b61027361073c36600461398f565b611a3a565b61027361074f36600461384f565b611f4c565b6103087f000000000000000000000000000000000000000000000000000000000000000081565b610783611f60565b60005b818110156108da5760008383838181106107a2576107a2613e39565b9050608002018036038101906107b89190613e7c565b805190915015806107d55750604081015167ffffffffffffffff16155b1561084457604080517fa087bd2900000000000000000000000000000000000000000000000000000000815282516004820152602083015163ffffffff1660248201529082015167ffffffffffffffff1660448201526060820151151560648201526084015b60405180910390fd5b60408051606080820183528351825260208085015163ffffffff9081168285019081529286015115158486019081529585015167ffffffffffffffff166000908152600a90925293902091518255516001918201805494511515640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000909516919093161792909217905501610786565b507f1889010d2535a0ab1643678d1da87fbbe8b87b2f585b47ddb72ec622aef9ee56828260405161090c929190613ef6565b60405180910390a15050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf0000000000000000000000000000000000000000000000000000000014806109ab57507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b806109f757507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b604080516020810190915260008152610a1582611fb3565b6000610a2460c0840184613f7d565b810190610a319190613fe2565b90506000610a4260e0850185613f7d565b810190610a4f91906140af565b9050610a5f8160000151836121d7565b805160208201516040517f57ecfd2800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016926357ecfd2892610ad692600401614140565b6020604051808303816000875af1158015610af5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b199190614165565b610b4f576040517fbf969f2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b5f606085016040860161384f565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f08660600135604051610bc191815260200190565b60405180910390a35050604080516020810190915260609092013582525090565b6000610c248383604051610bf7929190614182565b604080519182900390912067ffffffffffffffff8716600090815260076020529190912060050190612388565b949350505050565b610c34611f60565b610ca1848480806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250506040805160208088028281018201909352878252909350879250869182918501908490808284376000920191909152506123a392505050565b50505050565b610caf611f60565b610cb883610e8e565b610cfa576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161083b565b610d3a8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061255992505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d90576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610e15611f60565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b60006109f7600567ffffffffffffffff8416612388565b60095473ffffffffffffffffffffffffffffffffffffffff163314801590610ee5575060015473ffffffffffffffffffffffffffffffffffffffff163314155b15610f1e576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161083b565b8483141580610f2d5750848114155b15610f64576040517f568efce200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b85811015610ff657610fee878783818110610f8457610f84613e39565b9050602002016020810190610f9991906139fb565b868684818110610fab57610fab613e39565b905060600201803603810190610fc19190614192565b858585818110610fd357610fd3613e39565b905060600201803603810190610fe99190614192565b612653565b600101610f67565b50505050505050565b604080518082019091526060808252602082015261101c8261273d565b6000600a8161103160408601602087016139fb565b67ffffffffffffffff168152602080820192909252604090810160002081516060810183528154815260019091015463ffffffff81169382019390935264010000000090920460ff1615159082018190529091506110d85761109960408401602085016139fb565b6040517fd201c48a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161083b565b6110e28380613f7d565b9050602014611129576110f58380613f7d565b6040517fa3c8cf0900000000000000000000000000000000000000000000000000000000815260040161083b9291906141f7565b60006111358480613f7d565b810190611142919061420b565b602083015183516040517ff856ddb60000000000000000000000000000000000000000000000000000000081526060880135600482015263ffffffff90921660248301526044820183905273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116606484015260848301919091529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f856ddb69060a4016020604051808303816000875af1158015611223573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112479190614224565b6040516060870135815290915033907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a260405180604001604052806112a48760200160208101906105f191906139fb565b815260408051808201825267ffffffffffffffff851680825263ffffffff7f00000000000000000000000000000000000000000000000000000000000000008116602093840190815284518085019390935251169281019290925290910190606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905295945050505050565b67ffffffffffffffff8116600090815260076020526040812060609190611368906005016128c9565b90506000815167ffffffffffffffff81111561138657611386613ca7565b6040519080825280602002602001820160405280156113b957816020015b60608152602001906001900390816113a45790505b50905060005b82518110156114a257600860008483815181106113de576113de613e39565b6020026020010151815260200190815260200160002080546113ff90614241565b80601f016020809104026020016040519081016040528092919081815260200182805461142b90614241565b80156114785780601f1061144d57610100808354040283529160200191611478565b820191906000526020600020905b81548152906001019060200180831161145b57829003601f168201915b505050505082828151811061148f5761148f613e39565b60209081029190910101526001016113bf565b509392505050565b60606114b660026128c9565b905090565b6114c3611f60565b6114cc83610e8e565b61150e576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161083b565b61154e8282604051611521929190614182565b604080519182900390912067ffffffffffffffff86166000908152600760205291909120600501906128d6565b61158a578282826040517f74f23c7c00000000000000000000000000000000000000000000000000000000815260040161083b93929190614294565b8267ffffffffffffffff167f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d7683836040516115c69291906141f7565b60405180910390a2505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260039091015480841660608301529190910490911660808201526109f7906128e2565b67ffffffffffffffff811660009081526007602052604090206004018054606091906116d390614241565b80601f01602080910402602001604051908101604052809291908181526020018280546116ff90614241565b801561174c5780601f106117215761010080835404028352916020019161174c565b820191906000526020600020905b81548152906001019060200180831161172f57829003601f168201915b50505050509050919050565b611760611f60565b73ffffffffffffffffffffffffffffffffffffffff81166117ad576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910161090c565b6060600061183a60056128c9565b90506000815167ffffffffffffffff81111561185857611858613ca7565b604051908082528060200260200182016040528015611881578160200160208202803683370190505b50905060005b82518110156118dd578281815181106118a2576118a2613e39565b60200260200101518282815181106118bc576118bc613e39565b67ffffffffffffffff90921660209283029190910190910152600101611887565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260019091015480841660608301529190910490911660808201526109f7906128e2565b60095473ffffffffffffffffffffffffffffffffffffffff1633148015906119f6575060015473ffffffffffffffffffffffffffffffffffffffff163314155b15611a2f576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161083b565b610d3a838383612653565b611a42611f60565b60005b83811015611c2f576000858583818110611a6157611a61613e39565b9050602002016020810190611a7691906139fb565b9050611a8d600567ffffffffffffffff83166128d6565b611acf576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161083b565b67ffffffffffffffff81166000908152600760205260408120611af4906005016128c9565b905060005b8151811015611b6057611b57828281518110611b1757611b17613e39565b6020026020010151600760008667ffffffffffffffff1667ffffffffffffffff1681526020019081526020016000206005016128d690919063ffffffff16565b50600101611af9565b5067ffffffffffffffff8216600090815260076020526040812080547fffffffffffffffffffffff00000000000000000000000000000000000000000090811682556001820183905560028201805490911690556003810182905590611bc96004830182613692565b6005820160008181611bdb82826136cc565b505060405167ffffffffffffffff871681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d85991694506020019250611c1d915050565b60405180910390a15050600101611a45565b5060005b81811015611f45576000838383818110611c4f57611c4f613e39565b9050602002810190611c6191906142b8565b611c6a90614395565b9050611c7b81606001516000612994565b611c8a81608001516000612994565b806040015151600003611cc9576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051611ce19060059067ffffffffffffffff16612ad1565b611d265780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161083b565b805167ffffffffffffffff16600090815260076020908152604091829020825160a08082018552606080870180518601516fffffffffffffffffffffffffffffffff90811680865263ffffffff42168689018190528351511515878b0181905284518a0151841686890181905294518b0151841660809889018190528954740100000000000000000000000000000000000000009283027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7001000000000000000000000000000000008087027fffffffffffffffffffffffff000000000000000000000000000000000000000094851690981788178216929092178d5592810290971760018c01558c519889018d52898e0180518d01518716808b528a8e019590955280515115158a8f018190528151909d01518716988a01899052518d0151909516979098018790526002890180549a909102999093161717909416959095179092559092029091176003820155908201516004820190611ea9908261449d565b5060005b826020015151811015611eed57611ee5836000015184602001518381518110611ed857611ed8613e39565b6020026020010151612559565b600101611ead565b507f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c28260000151836040015184606001518560800151604051611f3394939291906145b7565b60405180910390a15050600101611c33565b5050505050565b611f54611f60565b611f5d81612add565b50565b60015473ffffffffffffffffffffffffffffffffffffffff163314611fb1576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b611fc661033b60a083016080840161384f565b61202557611fda60a082016080830161384f565b6040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161083b565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb61207160408401602085016139fb565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa1580156120e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121069190614165565b1561213d576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61215561215060408301602084016139fb565b612ba1565b61217561216860408301602084016139fb565b6103db60a0840184613f7d565b6121ba5761218660a0820182613f7d565b6040517f24eb47e500000000000000000000000000000000000000000000000000000000815260040161083b9291906141f7565b611f5d6121cd60408301602084016139fb565b8260600135612cc7565b600482015163ffffffff811615612222576040517f68d2f8d600000000000000000000000000000000000000000000000000000000815263ffffffff8216600482015260240161083b565b6008830151600c8401516014850151602085015163ffffffff80851691161461228d5760208501516040517fe366a11700000000000000000000000000000000000000000000000000000000815263ffffffff9182166004820152908416602482015260440161083b565b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff168263ffffffff1614612322576040517f77e4802600000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301528316602482015260440161083b565b845167ffffffffffffffff8281169116146123805784516040517ff917ffea00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9182166004820152908216602482015260440161083b565b505050505050565b600081815260018301602052604081205415155b9392505050565b7f00000000000000000000000000000000000000000000000000000000000000006123fa576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b825181101561249057600083828151811061241a5761241a613e39565b60200260200101519050612438816002612d0e90919063ffffffff16565b156124875760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b506001016123fd565b5060005b8151811015610d3a5760008282815181106124b1576124b1613e39565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036124f55750612551565b612500600282612d30565b1561254f5760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101612494565b8051600003612594576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160208083019190912067ffffffffffffffff84166000908152600790925260409091206125c69060050182612ad1565b6126005782826040517f393b8ad200000000000000000000000000000000000000000000000000000000815260040161083b929190614650565b6000818152600860205260409020612618838261449d565b508267ffffffffffffffff167f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea836040516115c6919061381a565b61265c83610e8e565b61269e576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161083b565b6126a9826000612994565b67ffffffffffffffff831660009081526007602052604090206126cc9083612d52565b6126d7816000612994565b67ffffffffffffffff831660009081526007602052604090206126fd9060020182612d52565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b83838360405161273093929190614673565b60405180910390a1505050565b61275061033b60a083016080840161384f565b61276457611fda60a082016080830161384f565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb6127b060408401602085016139fb565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015612821573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128459190614165565b1561287c576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61289461288f606083016040840161384f565b612ef4565b6128ac6128a760408301602084016139fb565b612f73565b611f5d6128bf60408301602084016139fb565b82606001356130c1565b6060600061239c83613105565b600061239c8383613160565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915261297082606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff16426129549190614725565b85608001516fffffffffffffffffffffffffffffffff16613253565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b815115612a5f5781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff161015806129ea575060408201516fffffffffffffffffffffffffffffffff16155b15612a2357816040517f8020d12400000000000000000000000000000000000000000000000000000000815260040161083b9190614738565b8015612a5b576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60408201516fffffffffffffffffffffffffffffffff16151580612a98575060208201516fffffffffffffffffffffffffffffffff1615155b15612a5b57816040517fd68af9cc00000000000000000000000000000000000000000000000000000000815260040161083b9190614738565b600061239c838361327b565b3373ffffffffffffffffffffffffffffffffffffffff821603612b2c576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b612baa81610e8e565b612bec576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161083b565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa158015612c6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c8f9190614165565b611f5d576040517f728fe07b00000000000000000000000000000000000000000000000000000000815233600482015260240161083b565b67ffffffffffffffff82166000908152600760205260409020612a5b90600201827f00000000000000000000000000000000000000000000000000000000000000006132ca565b600061239c8373ffffffffffffffffffffffffffffffffffffffff8416613160565b600061239c8373ffffffffffffffffffffffffffffffffffffffff841661327b565b8154600090612d7b90700100000000000000000000000000000000900463ffffffff1642614725565b90508015612e1d5760018301548354612dc3916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416613253565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612e43916fffffffffffffffffffffffffffffffff908116911661364d565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1990612730908490614738565b7f000000000000000000000000000000000000000000000000000000000000000015611f5d57612f25600282613663565b611f5d576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015260240161083b565b612f7c81610e8e565b612fbe576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161083b565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015613037573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061305b9190614774565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611f5d576040517f728fe07b00000000000000000000000000000000000000000000000000000000815233600482015260240161083b565b67ffffffffffffffff82166000908152600760205260409020612a5b90827f00000000000000000000000000000000000000000000000000000000000000006132ca565b60608160000180548060200260200160405190810160405280929190818152602001828054801561174c57602002820191906000526020600020905b8154815260200190600101908083116131415750505050509050919050565b60008181526001830160205260408120548015613249576000613184600183614725565b855490915060009061319890600190614725565b90508082146131fd5760008660000182815481106131b8576131b8613e39565b90600052602060002001549050808760000184815481106131db576131db613e39565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061320e5761320e614791565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506109f7565b60009150506109f7565b60006132728561326384866147c0565b61326d90876147d7565b61364d565b95945050505050565b60008181526001830160205260408120546132c2575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556109f7565b5060006109f7565b825474010000000000000000000000000000000000000000900460ff1615806132f1575081155b156132fb57505050565b825460018401546fffffffffffffffffffffffffffffffff8083169291169060009061334190700100000000000000000000000000000000900463ffffffff1642614725565b905080156134015781831115613383576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546133bd9083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16613253565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156134b85773ffffffffffffffffffffffffffffffffffffffff8416613460576040517ff94ebcd1000000000000000000000000000000000000000000000000000000008152600481018390526024810186905260440161083b565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff8516604482015260640161083b565b848310156135cb5760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906134fc9082614725565b613506878a614725565b61351091906147d7565b61351a91906147ea565b905073ffffffffffffffffffffffffffffffffffffffff8616613573576040517f15279c08000000000000000000000000000000000000000000000000000000008152600481018290526024810186905260440161083b565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff8716604482015260640161083b565b6135d58584614725565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b600081831061365c578161239c565b5090919050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151561239c565b50805461369e90614241565b6000825580601f106136ae575050565b601f016020900490600052602060002090810190611f5d91906136e6565b5080546000825590600052602060002090810190611f5d91905b5b808211156136fb57600081556001016136e7565b5090565b6000806020838503121561371257600080fd5b823567ffffffffffffffff8082111561372a57600080fd5b818501915085601f83011261373e57600080fd5b81358181111561374d57600080fd5b8660208260071b850101111561376257600080fd5b60209290920196919550909350505050565b60006020828403121561378657600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461239c57600080fd5b6000815180845260005b818110156137dc576020818501810151868301820152016137c0565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061239c60208301846137b6565b73ffffffffffffffffffffffffffffffffffffffff81168114611f5d57600080fd5b60006020828403121561386157600080fd5b813561239c8161382d565b60006020828403121561387e57600080fd5b813567ffffffffffffffff81111561389557600080fd5b8201610100818503121561239c57600080fd5b67ffffffffffffffff81168114611f5d57600080fd5b6000806000604084860312156138d357600080fd5b83356138de816138a8565b9250602084013567ffffffffffffffff808211156138fb57600080fd5b818601915086601f83011261390f57600080fd5b81358181111561391e57600080fd5b87602082850101111561393057600080fd5b6020830194508093505050509250925092565b60008083601f84011261395557600080fd5b50813567ffffffffffffffff81111561396d57600080fd5b6020830191508360208260051b850101111561398857600080fd5b9250929050565b600080600080604085870312156139a557600080fd5b843567ffffffffffffffff808211156139bd57600080fd5b6139c988838901613943565b909650945060208701359150808211156139e257600080fd5b506139ef87828801613943565b95989497509550505050565b600060208284031215613a0d57600080fd5b813561239c816138a8565b60008083601f840112613a2a57600080fd5b50813567ffffffffffffffff811115613a4257600080fd5b60208301915083602060608302850101111561398857600080fd5b60008060008060008060608789031215613a7657600080fd5b863567ffffffffffffffff80821115613a8e57600080fd5b613a9a8a838b01613943565b90985096506020890135915080821115613ab357600080fd5b613abf8a838b01613a18565b90965094506040890135915080821115613ad857600080fd5b50613ae589828a01613a18565b979a9699509497509295939492505050565b600060208284031215613b0957600080fd5b813567ffffffffffffffff811115613b2057600080fd5b820160a0818503121561239c57600080fd5b602081526000825160406020840152613b4e60608401826137b6565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084830301604085015261327282826137b6565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015613bfe577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452613bec8583516137b6565b94509285019290850190600101613bb2565b5092979650505050505050565b6020808252825182820181905260009190848201906040850190845b81811015613c5957835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101613c27565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015613c5957835167ffffffffffffffff1683529284019291840191600101613c81565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715613cf957613cf9613ca7565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613d4657613d46613ca7565b604052919050565b8015158114611f5d57600080fd5b80356fffffffffffffffffffffffffffffffff81168114613d7c57600080fd5b919050565b600060608284031215613d9357600080fd5b6040516060810181811067ffffffffffffffff82111715613db657613db6613ca7565b6040529050808235613dc781613d4e565b8152613dd560208401613d5c565b6020820152613de660408401613d5c565b60408201525092915050565b600080600060e08486031215613e0757600080fd5b8335613e12816138a8565b9250613e218560208601613d81565b9150613e308560808601613d81565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b803563ffffffff81168114613d7c57600080fd5b600060808284031215613e8e57600080fd5b6040516080810181811067ffffffffffffffff82111715613eb157613eb1613ca7565b60405282358152613ec460208401613e68565b60208201526040830135613ed7816138a8565b60408201526060830135613eea81613d4e565b60608201529392505050565b6020808252818101839052600090604080840186845b87811015613f70578135835263ffffffff613f28868401613e68565b168584015283820135613f3a816138a8565b67ffffffffffffffff1683850152606082810135613f5781613d4e565b1515908401526080928301929190910190600101613f0c565b5090979650505050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613fb257600080fd5b83018035915067ffffffffffffffff821115613fcd57600080fd5b60200191503681900382131561398857600080fd5b600060408284031215613ff457600080fd5b613ffc613cd6565b8235614007816138a8565b815261401560208401613e68565b60208201529392505050565b600082601f83011261403257600080fd5b813567ffffffffffffffff81111561404c5761404c613ca7565b61407d60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613cff565b81815284602083860101111561409257600080fd5b816020850160208301376000918101602001919091529392505050565b6000602082840312156140c157600080fd5b813567ffffffffffffffff808211156140d957600080fd5b90830190604082860312156140ed57600080fd5b6140f5613cd6565b82358281111561410457600080fd5b61411087828601614021565b82525060208301358281111561412557600080fd5b61413187828601614021565b60208301525095945050505050565b60408152600061415360408301856137b6565b828103602084015261327281856137b6565b60006020828403121561417757600080fd5b815161239c81613d4e565b8183823760009101908152919050565b6000606082840312156141a457600080fd5b61239c8383613d81565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526000610c246020830184866141ae565b60006020828403121561421d57600080fd5b5035919050565b60006020828403121561423657600080fd5b815161239c816138a8565b600181811c9082168061425557607f821691505b60208210810361428e577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b67ffffffffffffffff841681526040602082015260006132726040830184866141ae565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee18336030181126142ec57600080fd5b9190910192915050565b600082601f83011261430757600080fd5b8135602067ffffffffffffffff8083111561432457614324613ca7565b8260051b614333838201613cff565b938452858101830193838101908886111561434d57600080fd5b84880192505b858310156143895782358481111561436b5760008081fd5b6143798a87838c0101614021565b8352509184019190840190614353565b98975050505050505050565b600061012082360312156143a857600080fd5b60405160a0810167ffffffffffffffff82821081831117156143cc576143cc613ca7565b81604052843591506143dd826138a8565b908252602084013590808211156143f357600080fd5b6143ff368387016142f6565b6020840152604085013591508082111561441857600080fd5b5061442536828601614021565b6040830152506144383660608501613d81565b606082015261444a3660c08501613d81565b608082015292915050565b601f821115610d3a576000816000526020600020601f850160051c8101602086101561447e5750805b601f850160051c820191505b818110156123805782815560010161448a565b815167ffffffffffffffff8111156144b7576144b7613ca7565b6144cb816144c58454614241565b84614455565b602080601f83116001811461451e57600084156144e85750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612380565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561456b5788860151825594840194600190910190840161454c565b50858210156145a757878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff871683528060208401526145db818401876137b6565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff90811660608701529087015116608085015291506146199050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152613272565b67ffffffffffffffff83168152604060208201526000610c2460408301846137b6565b67ffffffffffffffff8416815260e081016146bf60208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c0830152610c24565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156109f7576109f76146f6565b606081016109f782848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561478657600080fd5b815161239c8161382d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b80820281158282048414176109f7576109f76146f6565b808201808211156109f7576109f76146f6565b600082614820577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea164736f6c6343000818000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"tokenMessenger\",\"type\":\"address\",\"internalType\":\"contractITokenMessenger\"},{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"contractIERC20\"},{\"name\":\"allowlist\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"rmnProxy\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"router\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"SUPPORTED_USDC_VERSION\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"acceptOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"addRemotePool\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyAllowListUpdates\",\"inputs\":[{\"name\":\"removes\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"adds\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyChainUpdates\",\"inputs\":[{\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"},{\"name\":\"chainsToAdd\",\"type\":\"tuple[]\",\"internalType\":\"structTokenPool.ChainUpdate[]\",\"components\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"},{\"name\":\"remoteTokenAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getAllowList\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getAllowListEnabled\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCurrentInboundRateLimiterState\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.TokenBucket\",\"components\":[{\"name\":\"tokens\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"lastUpdated\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCurrentOutboundRateLimiterState\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.TokenBucket\",\"components\":[{\"name\":\"tokens\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"lastUpdated\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getDomain\",\"inputs\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structUSDCTokenPool.Domain\",\"components\":[{\"name\":\"allowedCaller\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"domainIdentifier\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"enabled\",\"type\":\"bool\",\"internalType\":\"bool\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRateLimitAdmin\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRemotePools\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRemoteToken\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRmnProxy\",\"inputs\":[],\"outputs\":[{\"name\":\"rmnProxy\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRouter\",\"inputs\":[],\"outputs\":[{\"name\":\"router\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getSupportedChains\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getToken\",\"inputs\":[],\"outputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"contractIERC20\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTokenDecimals\",\"inputs\":[],\"outputs\":[{\"name\":\"decimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"i_localDomainIdentifier\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"i_messageTransmitter\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIMessageTransmitter\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"i_tokenMessenger\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractITokenMessenger\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isRemotePool\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isSupportedChain\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isSupportedToken\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"lockOrBurn\",\"inputs\":[{\"name\":\"lockOrBurnIn\",\"type\":\"tuple\",\"internalType\":\"structPool.LockOrBurnInV1\",\"components\":[{\"name\":\"receiver\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"originalSender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"localToken\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structPool.LockOrBurnOutV1\",\"components\":[{\"name\":\"destTokenAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"destPoolData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"releaseOrMint\",\"inputs\":[{\"name\":\"releaseOrMintIn\",\"type\":\"tuple\",\"internalType\":\"structPool.ReleaseOrMintInV1\",\"components\":[{\"name\":\"originalSender\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"receiver\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"localToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"sourcePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"sourcePoolData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"offchainTokenData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"components\":[{\"name\":\"destinationAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"removeRemotePool\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setChainRateLimiterConfig\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"outboundConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setChainRateLimiterConfigs\",\"inputs\":[{\"name\":\"remoteChainSelectors\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"},{\"name\":\"outboundConfigs\",\"type\":\"tuple[]\",\"internalType\":\"structRateLimiter.Config[]\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundConfigs\",\"type\":\"tuple[]\",\"internalType\":\"structRateLimiter.Config[]\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setDomains\",\"inputs\":[{\"name\":\"domains\",\"type\":\"tuple[]\",\"internalType\":\"structUSDCTokenPool.DomainUpdate[]\",\"components\":[{\"name\":\"allowedCaller\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"domainIdentifier\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"enabled\",\"type\":\"bool\",\"internalType\":\"bool\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setRateLimitAdmin\",\"inputs\":[{\"name\":\"rateLimitAdmin\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setRouter\",\"inputs\":[{\"name\":\"newRouter\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"typeAndVersion\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"AllowListAdd\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"AllowListRemove\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Burned\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChainAdded\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"remoteToken\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"},{\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChainConfigured\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChainRemoved\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ConfigChanged\",\"inputs\":[{\"name\":\"config\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ConfigSet\",\"inputs\":[{\"name\":\"tokenMessenger\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DomainsSet\",\"inputs\":[{\"name\":\"\",\"type\":\"tuple[]\",\"indexed\":false,\"internalType\":\"structUSDCTokenPool.DomainUpdate[]\",\"components\":[{\"name\":\"allowedCaller\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"domainIdentifier\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"enabled\",\"type\":\"bool\",\"internalType\":\"bool\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Locked\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Minted\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferRequested\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RateLimitAdminSet\",\"inputs\":[{\"name\":\"rateLimitAdmin\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Released\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RemotePoolAdded\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RemotePoolRemoved\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RouterUpdated\",\"inputs\":[{\"name\":\"oldRouter\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"newRouter\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TokensConsumed\",\"inputs\":[{\"name\":\"tokens\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AggregateValueMaxCapacityExceeded\",\"inputs\":[{\"name\":\"capacity\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"requested\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"AggregateValueRateLimitReached\",\"inputs\":[{\"name\":\"minWaitInSeconds\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"available\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"AllowListNotEnabled\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BucketOverfilled\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CallerIsNotARampOnRouter\",\"inputs\":[{\"name\":\"caller\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"CannotTransferToSelf\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ChainAlreadyExists\",\"inputs\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"ChainNotAllowed\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"CursedByRMN\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"DisabledNonZeroRateLimit\",\"inputs\":[{\"name\":\"config\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}]},{\"type\":\"error\",\"name\":\"InvalidConfig\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidDecimalArgs\",\"inputs\":[{\"name\":\"expected\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"actual\",\"type\":\"uint8\",\"internalType\":\"uint8\"}]},{\"type\":\"error\",\"name\":\"InvalidDestinationDomain\",\"inputs\":[{\"name\":\"expected\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"got\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]},{\"type\":\"error\",\"name\":\"InvalidDomain\",\"inputs\":[{\"name\":\"domain\",\"type\":\"tuple\",\"internalType\":\"structUSDCTokenPool.DomainUpdate\",\"components\":[{\"name\":\"allowedCaller\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"domainIdentifier\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"enabled\",\"type\":\"bool\",\"internalType\":\"bool\"}]}]},{\"type\":\"error\",\"name\":\"InvalidMessageVersion\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]},{\"type\":\"error\",\"name\":\"InvalidNonce\",\"inputs\":[{\"name\":\"expected\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"got\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"InvalidRateLimitRate\",\"inputs\":[{\"name\":\"rateLimiterConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}]},{\"type\":\"error\",\"name\":\"InvalidReceiver\",\"inputs\":[{\"name\":\"receiver\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidRemoteChainDecimals\",\"inputs\":[{\"name\":\"sourcePoolData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidRemotePoolForChain\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidSourceDomain\",\"inputs\":[{\"name\":\"expected\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"got\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]},{\"type\":\"error\",\"name\":\"InvalidSourcePoolAddress\",\"inputs\":[{\"name\":\"sourcePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidToken\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"InvalidTokenMessengerVersion\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]},{\"type\":\"error\",\"name\":\"MismatchedArrayLengths\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MustBeProposedOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NonExistentChain\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"OnlyCallableByOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OverflowDetected\",\"inputs\":[{\"name\":\"remoteDecimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"localDecimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"remoteAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"OwnerCannotBeZero\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PoolAlreadyAdded\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"RateLimitMustBeDisabled\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"SenderNotAllowed\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"TokenMaxCapacityExceeded\",\"inputs\":[{\"name\":\"capacity\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"requested\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"tokenAddress\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"TokenRateLimitReached\",\"inputs\":[{\"name\":\"minWaitInSeconds\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"available\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"tokenAddress\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"Unauthorized\",\"inputs\":[{\"name\":\"caller\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"UnknownDomain\",\"inputs\":[{\"name\":\"domain\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"UnlockingUSDCFailed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ZeroAddressNotAllowed\",\"inputs\":[]}]", + Bin: "0x610160806040523461049b5761582d803803809161001d82856107dc565b8339810160a08282031261049b5781516001600160a01b0381169290919083830361049b5760208101516001600160a01b038116919082810361049b5760408201516001600160401b03811161049b5782019380601f8601121561049b578451946001600160401b0386116104a0578560051b9060208201966100a360405198896107dc565b875260208088019282010192831161049b57602001905b8282106107c4575050506100dc60806100d5606085016107ff565b93016107ff565b9233156107b357600180546001600160a01b03191633179055801580156107a2575b8015610791575b6107805760049260209260805260c0526040519283809263313ce56760e01b82525afa809160009161073d575b5090610719575b50600660a052600480546001600160a01b0319166001600160a01b03929092169190911790558051151560e08190526105f7575b5081156105e657604051632c12192160e01b8152602081600481865afa90811561050b576000916105ac575b5060405163054fd4d560e41b81526001600160a01b03919091169190602081600481865afa801561050b5763ffffffff9160009161058d575b5016806105795750604051639cdbb18160e01b8152602081600481875afa801561050b5763ffffffff9160009161055a575b50168061054657506004916020916101005280610120526040519283809263234d8e3d60e21b82525afa90811561050b57600091610517575b506101405260805161010051604051636eb1769f60e11b81523060048201526001600160a01b0391821660248201819052939290911690602081604481855afa90811561050b576000916104d9575b5060001981018091116104c35760405190602082019463095ea7b360e01b865260248301526044820152604481526102c56064826107dc565b6000806040958651936102d888866107dc565b602085527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65646020860152519082865af13d156104b6573d906001600160401b0382116104a057855161034994909261033a601f8201601f1916602001856107dc565b83523d6000602085013e6109b9565b80518061041f575b837f2e902d38f15b233cbb63711add0fca4545334d3a169d60c0a616494d7eea95446020858351908152a151614da39081610a8a82396080518181816105fa0152818161069401528181611422015281816140080152614485015260a051816106fc015260c051818181612067015281816136710152613bb4015260e051818181610acd0152818161218d01526142de015261010051818181610ceb015261148501526101205181818161083c0152612710015261014051818181610dcd0152818161152e01526138140152f35b816020918101031261049b576020015180159081150361049b57610444573880610351565b815162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608490fd5b600080fd5b634e487b7160e01b600052604160045260246000fd5b91610349926060916109b9565b634e487b7160e01b600052601160045260246000fd5b90506020813d602011610503575b816104f4602093836107dc565b8101031261049b57513861028c565b3d91506104e7565b6040513d6000823e3d90fd5b610539915060203d60201161053f575b61053181836107dc565b810190610813565b3861023d565b503d610527565b6316ba39c560e31b60005260045260246000fd5b610573915060203d60201161053f5761053181836107dc565b38610204565b6334697c6b60e11b60005260045260246000fd5b6105a6915060203d60201161053f5761053181836107dc565b386101d2565b90506020813d6020116105de575b816105c7602093836107dc565b8101031261049b576105d8906107ff565b38610199565b3d91506105ba565b6306b7c75960e31b60005260046000fd5b906020906040519061060983836107dc565b60008252600036813760e051156107085760005b8251811015610684576001906001600160a01b0361063b828661082f565b51168561064782610871565b610654575b50500161061d565b7f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf756691604051908152a1388561064c565b5092905060005b81518110156106ff576001906001600160a01b036106a9828561082f565b511680156106f957846106bb82610959565b6106c9575b50505b0161068b565b7f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d891604051908152a138846106c0565b506106c3565b5050503861016d565b6335f4a7b360e01b60005260046000fd5b60ff1660068114610139576332ad3e0760e11b600052600660045260245260446000fd5b6020813d602011610778575b81610756602093836107dc565b8101031261077457519060ff82168203610771575038610132565b80fd5b5080fd5b3d9150610749565b6342bcdf7f60e11b60005260046000fd5b506001600160a01b03831615610105565b506001600160a01b038416156100fe565b639b15e16f60e01b60005260046000fd5b602080916107d1846107ff565b8152019101906100ba565b601f909101601f19168101906001600160401b038211908210176104a057604052565b51906001600160a01b038216820361049b57565b9081602091031261049b575163ffffffff8116810361049b5790565b80518210156108435760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b80548210156108435760005260206000200190600090565b60008181526003602052604090205480156109525760001981018181116104c3576002546000198101919082116104c357818103610901575b50505060025480156108eb57600019016108c5816002610859565b8154906000199060031b1b19169055600255600052600360205260006040812055600190565b634e487b7160e01b600052603160045260246000fd5b61093a610912610923936002610859565b90549060031b1c9283926002610859565b819391549060031b91821b91600019901b19161790565b905560005260036020526040600020553880806108aa565b5050600090565b806000526003602052604060002054156000146109b357600254680100000000000000008110156104a05761099a6109238260018594016002556002610859565b9055600254906000526003602052604060002055600190565b50600090565b91929015610a1b57508151156109cd575090565b3b156109d65790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b825190915015610a2e5750805190602001fd5b6040519062461bcd60e51b8252602060048301528181519182602483015260005b838110610a715750508160006044809484010152601f80199101168101030190fd5b60208282018101516044878401015285935001610a4f56fe6080604052600436101561001257600080fd5b60003560e01c806241d3c11461025657806301ffc9a714610251578063181f5a771461024c57806321df0da714610247578063240028e81461024257806324f65ee71461023d57806339077537146102385780634c5ef0ed1461023357806354c8a4f31461022e5780636155cda01461022957806362ddd3c4146102245780636b716b0d1461021f5780636d3d1a581461021a57806379ba5097146102155780637d54534e146102105780638926f54f1461020b5780638da5cb5b14610206578063962d4020146102015780639a4575b9146101fc5780639fdf13ff146101f7578063a42a7b8b146101f2578063a7cd63b7146101ed578063acfecf91146101e8578063af58d59f146101e3578063b0f479a1146101de578063b7946580146101d9578063c0d78655146101d4578063c4bffe2b146101cf578063c75eea9c146101ca578063cf7401f3146101c5578063dc0bd971146101c0578063dfadfa35146101bb578063e0351e13146101b6578063e8a1da17146101b1578063f2fde38b146101ac5763fbf84dd7146101a757600080fd5b6126c5565b6125d1565b6121b2565b612157565b61208b565b61201c565b611f00565b611d9d565b611cec565b611bac565b611b57565b611af4565b611a2a565b6118fe565b61186c565b61174c565b611694565b6112ce565b6110bb565b611038565b610fdb565b610f2c565b610e43565b610df1565b610d92565b610d0f565b610ca0565b610a9b565b6109e1565b610720565b6106c4565b61063c565b6105af565b61052e565b6102d8565b346102d35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d35760043567ffffffffffffffff81116102d357366023820112156102d357806004013567ffffffffffffffff81116102d3573660248260071b840101116102d35760246102d19201612734565b005b600080fd5b346102d35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d3576004357fffffffff0000000000000000000000000000000000000000000000000000000081168091036102d357807faff2afbf000000000000000000000000000000000000000000000000000000006020921490811561039e575b8115610374575b506040519015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501438610369565b7f0e64dd290000000000000000000000000000000000000000000000000000000081149150610362565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6060810190811067ffffffffffffffff82111761041357604052565b6103c8565b6040810190811067ffffffffffffffff82111761041357604052565b60a0810190811067ffffffffffffffff82111761041357604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761041357604052565b604051906104a0602083610450565b565b604051906104a0604083610450565b604051906104a060a083610450565b604051906104a0606083610450565b919082519283825260005b8481106105195750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b806020809284010151828286010152016104da565b346102d35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d3576105ab604080519061056f8183610450565b601382527f55534443546f6b656e506f6f6c20312e352e31000000000000000000000000006020830152519182916020835260208301906104cf565b0390f35b346102d35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d357602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b73ffffffffffffffffffffffffffffffffffffffff8116036102d357565b346102d35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d35760206106ba60043561067c8161061e565b73ffffffffffffffffffffffffffffffffffffffff807f00000000000000000000000000000000000000000000000000000000000000001691161490565b6040519015158152f35b346102d35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d357602060405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346102d35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d35760043567ffffffffffffffff81116102d357806004016101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc83360301126102d3576020610821916107a0612a20565b506107aa816135a3565b6107e66107de6107d66107cb6107c360c4890186612a44565b810190612a95565b9360e4880190612a44565b810190612b4d565b9182516137c9565b8181519101519060405193849283927f57ecfd2800000000000000000000000000000000000000000000000000000000845260048401612bd3565b0381600073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165af190811561094457600091610915575b50156108eb5780606461088560446105ab9401612c04565b60405191909201358082529173ffffffffffffffffffffffffffffffffffffffff169033907f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f090602090a36108d8610491565b8190526040519081529081906020820190565b7fbf969f220000000000000000000000000000000000000000000000000000000060005260046000fd5b610937915060203d60201161093d575b61092f8183610450565b810190612bbe565b3861086d565b503d610925565b612bf8565b67ffffffffffffffff8116036102d357565b35906104a082610949565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8201126102d35760043561099c81610949565b9160243567ffffffffffffffff81116102d357826023820112156102d35780600401359267ffffffffffffffff84116102d357602484830101116102d3576024019190565b346102d35760206106ba6109f436610966565b91612c0e565b9181601f840112156102d35782359167ffffffffffffffff83116102d3576020808501948460051b0101116102d357565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8201126102d35760043567ffffffffffffffff81116102d35781610a74916004016109fa565b929092916024359067ffffffffffffffff82116102d357610a97916004016109fa565b9091565b346102d357610ac3610acb610aaf36610a2b565b9491610abc939193613558565b3691612c6e565b923691612c6e565b7f000000000000000000000000000000000000000000000000000000000000000015610c765760005b8251811015610bb95780610b27610b0d60019386612dce565b5173ffffffffffffffffffffffffffffffffffffffff1690565b610b63610b5e73ffffffffffffffffffffffffffffffffffffffff83165b73ffffffffffffffffffffffffffffffffffffffff1690565b614637565b610b6f575b5001610af4565b60405173ffffffffffffffffffffffffffffffffffffffff9190911681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf756690602090a138610b68565b5060005b81518110156102d15780610bd6610b0d60019385612dce565b73ffffffffffffffffffffffffffffffffffffffff811615610c7057610c19610c1473ffffffffffffffffffffffffffffffffffffffff8316610b45565b6148ed565b610c26575b505b01610bbd565b60405173ffffffffffffffffffffffffffffffffffffffff9190911681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d890602090a183610c1e565b50610c20565b7f35f4a7b30000000000000000000000000000000000000000000000000000000060005260046000fd5b346102d35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d357602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346102d357610d1d36610966565b610d28929192613558565b67ffffffffffffffff8216610d4a816000526006602052604060002054151590565b15610d6557506102d192610d5f913691612acd565b90613975565b7f1e670e4b0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b346102d35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d357602060405163ffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346102d35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d357602073ffffffffffffffffffffffffffffffffffffffff60095416604051908152f35b346102d35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d35760005473ffffffffffffffffffffffffffffffffffffffff81163303610f02577fffffffffffffffffffffffff00000000000000000000000000000000000000006001549133828416176001551660005573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b7f02b543c60000000000000000000000000000000000000000000000000000000060005260046000fd5b346102d35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d3577f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d09174602073ffffffffffffffffffffffffffffffffffffffff600435610f9f8161061e565b610fa7613558565b16807fffffffffffffffffffffffff00000000000000000000000000000000000000006009541617600955604051908152a1005b346102d35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d35760206106ba67ffffffffffffffff60043561102481610949565b166000526006602052604060002054151590565b346102d35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d357602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b9181601f840112156102d35782359167ffffffffffffffff83116102d357602080850194606085020101116102d357565b346102d35760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d35760043567ffffffffffffffff81116102d35761110a9036906004016109fa565b9060243567ffffffffffffffff81116102d35761112b90369060040161108a565b9060443567ffffffffffffffff81116102d35761114c90369060040161108a565b61116e610b4560095473ffffffffffffffffffffffffffffffffffffffff1690565b3314158061124d575b61121b57838614801590611211575b6111e75760005b86811061119657005b806111e16111af6111aa6001948b8b612ce5565b612cf5565b6111ba838989612cff565b6111db6111d36111cb86898b612cff565b923690611eb7565b913690611eb7565b91613a3a565b0161118d565b7f568efce20000000000000000000000000000000000000000000000000000000060005260046000fd5b5080861415611186565b7f8e4a23d6000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b6000fd5b50611270610b4560015473ffffffffffffffffffffffffffffffffffffffff1690565b331415611177565b906112cb91602081526020611298835160408385015260608401906104cf565b9201519060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828503019101526104cf565b90565b346102d35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d35760043567ffffffffffffffff81116102d3578060040160a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc83360301126102d357611347612d0f565b5061135181613b6a565b6024820161138361137e61136483612cf5565b67ffffffffffffffff16600052600a602052604060002090565b612d28565b916113986113946040850151151590565b1590565b6116525760206113a88280612a44565b90500361160e5760646113c86113c083602094612a44565b810190612daa565b940135926113dc8282015163ffffffff1690565b90516040517ff856ddb60000000000000000000000000000000000000000000000000000000081526004810186905263ffffffff909216602483015260448201959095527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1660648201526084810194909452838060a481010381600073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165af1918215610944576105ab936000936115cb575b5061150b611506611583936115af937f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df7604051806114fe3394829190602083019252565b0390a2612cf5565b612f9b565b926115276115176104a2565b67ffffffffffffffff9092168252565b63ffffffff7f000000000000000000000000000000000000000000000000000000000000000016602082015260405192839160208301919091602063ffffffff81604084019567ffffffffffffffff8151168552015116910152565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282610450565b6115b76104a2565b918252602082015260405191829182611278565b6115af919350611506611583936115fc61150b9360203d602011611607575b6115f48183610450565b810190612db9565b9593509350506114ba565b503d6115ea565b8061161891612a44565b9061164e6040519283927fa3c8cf0900000000000000000000000000000000000000000000000000000000845260048401612d99565b0390fd5b61124961165e83612cf5565b7fd201c48a0000000000000000000000000000000000000000000000000000000060005267ffffffffffffffff16600452602490565b346102d35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d357602060405160008152f35b602081016020825282518091526040820191602060408360051b8301019401926000915b83831061170157505050505090565b909192939460208061173d837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0866001960301875289516104cf565b970193019301919392906116f2565b346102d35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d35767ffffffffffffffff60043561179081610949565b1660005260076020526117a96005604060002001614541565b8051907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06117ef6117d984612c56565b936117e76040519586610450565b808552612c56565b0160005b81811061185b57505060005b815181101561184d578061183161182c61181b60019486612dce565b516000526008602052604060002090565b612e35565b61183b8286612dce565b526118468185612dce565b50016117ff565b604051806105ab85826116ce565b8060606020809387010152016117f3565b346102d35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d3576118a36144ab565b60405180916020820160208352815180915260206040840192019060005b8181106118cf575050500390f35b825173ffffffffffffffffffffffffffffffffffffffff168452859450602093840193909201916001016118c1565b346102d35761190c36610966565b611917929192613558565b67ffffffffffffffff82169161193d611394846000526006602052604060002054151590565b6119f35761198061139460056119678467ffffffffffffffff166000526007602052604060002090565b01611973368689612acd565b60208151910120906147e2565b6119bc57507f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d7691926119b760405192839283612d99565b0390a2005b61164e84926040519384937f74f23c7c00000000000000000000000000000000000000000000000000000000855260048501612ef5565b7f1e670e4b0000000000000000000000000000000000000000000000000000000060005267ffffffffffffffff1660045260246000fd5b346102d35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d35767ffffffffffffffff600435611a6e81610949565b611a76612f16565b501660005260076020526105ab611a9b611a966002604060002001612f41565b613c7a565b6040519182918291909160806fffffffffffffffffffffffffffffffff8160a084019582815116855263ffffffff6020820151166020860152604081015115156040860152826060820151166060860152015116910152565b346102d35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d357602073ffffffffffffffffffffffffffffffffffffffff60045416604051908152f35b9060206112cb9281815201906104cf565b346102d35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d3576105ab611b9860043561150681610949565b6040519182916020835260208301906104cf565b346102d35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d35773ffffffffffffffffffffffffffffffffffffffff600435611bfc8161061e565b611c04613558565b168015611c7e5760407f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f16849160045490807fffffffffffffffffffffffff000000000000000000000000000000000000000083161760045573ffffffffffffffffffffffffffffffffffffffff8351921682526020820152a1005b7f8579befe0000000000000000000000000000000000000000000000000000000060005260046000fd5b602060408183019282815284518094520192019060005b818110611ccc5750505090565b825167ffffffffffffffff16845260209384019390920191600101611cbf565b346102d35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d357611d236144f6565b8051907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611d536117d984612c56565b0136602084013760005b8151811015611d8f578067ffffffffffffffff611d7c60019385612dce565b5116611d888286612dce565b5201611d5d565b604051806105ab8582611ca8565b346102d35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d35767ffffffffffffffff600435611de181610949565b611de9612f16565b501660005260076020526105ab611a9b611a966040600020612f41565b801515036102d357565b35906fffffffffffffffffffffffffffffffff821682036102d357565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7c60609101126102d35760405190611e64826103f7565b81608435611e7181611e06565b815260a4356fffffffffffffffffffffffffffffffff811681036102d357602082015260c435906fffffffffffffffffffffffffffffffff821682036102d35760400152565b91908260609103126102d357604051611ecf816103f7565b6040611efb8183958035611ee281611e06565b8552611ef060208201611e10565b602086015201611e10565b910152565b346102d35760e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d357600435611f3b81610949565b60607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc3601126102d357604051611f71816103f7565b602435611f7d81611e06565b81526044356fffffffffffffffffffffffffffffffff811681036102d35760208201526064356fffffffffffffffffffffffffffffffff811681036102d3576040820152611fca36611e2d565b9073ffffffffffffffffffffffffffffffffffffffff6009541633141580611ffa575b61121b576102d192613a3a565b5073ffffffffffffffffffffffffffffffffffffffff60015416331415611fed565b346102d35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d357602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346102d35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d35767ffffffffffffffff6004356120cf81610949565b6000604080516120de816103f7565b828152826020820152015216600052600a6020526105ab604060002060ff60016040519261210b846103f7565b80548452015463ffffffff8116602084015260201c16151560408201526040519182918291909160408060608301948051845263ffffffff602082015116602085015201511515910152565b346102d35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d35760206040517f000000000000000000000000000000000000000000000000000000000000000015158152f35b346102d3576121c036610a2b565b9190926121cb613558565b6000915b80831061247d5750505060009163ffffffff4216925b8281106121ee57005b6122016121fc82858561313a565b6131f9565b90606082016122108151613d57565b608083019361221f8551613d57565b604084019081515115611c7e57612259611394612254612247885167ffffffffffffffff1690565b67ffffffffffffffff1690565b61497e565b61243257612392612292612278879a999a5167ffffffffffffffff1690565b67ffffffffffffffff166000526007602052604060002090565b6123558961234f87516123366122bb60408301516fffffffffffffffffffffffffffffffff1690565b9161231d6122e66122df60208401516fffffffffffffffffffffffffffffffff1690565b9251151590565b6123146122f16104b1565b6fffffffffffffffffffffffffffffffff851681529763ffffffff166020890152565b15156040870152565b6fffffffffffffffffffffffffffffffff166060850152565b6fffffffffffffffffffffffffffffffff166080830152565b82613290565b6123878961237e8a516123366122bb60408301516fffffffffffffffffffffffffffffffff1690565b60028301613290565b60048451910161339c565b602085019660005b885180518210156123d557906123cf6001926123c8836123c28c5167ffffffffffffffff1690565b92612dce565b5190613975565b0161239a565b505097965094906124297f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c293926124166001975167ffffffffffffffff1690565b92519351905190604051948594856134c3565b0390a1016121e5565b611249612447865167ffffffffffffffff1690565b7f1d5ad3c50000000000000000000000000000000000000000000000000000000060005267ffffffffffffffff16600452602490565b90919261248e6111aa858486612ce5565b946124a561139467ffffffffffffffff881661471b565b612599576124d260056124cc8867ffffffffffffffff166000526007602052604060002090565b01614541565b9360005b855181101561251e5760019061251760056125058b67ffffffffffffffff166000526007602052604060002090565b01612510838a612dce565b51906147e2565b50016124d6565b509350937f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d85991661258b6001939761257061256b8267ffffffffffffffff166000526007602052604060002090565b61308b565b60405167ffffffffffffffff90911681529081906020820190565b0390a10191909392936121cf565b7f1e670e4b0000000000000000000000000000000000000000000000000000000060005267ffffffffffffffff861660045260246000fd5b346102d35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d35773ffffffffffffffffffffffffffffffffffffffff6004356126218161061e565b612629613558565b1633811461269b57807fffffffffffffffffffffffff0000000000000000000000000000000000000000600054161760005573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b7fdad89dca0000000000000000000000000000000000000000000000000000000060005260046000fd5b346102d35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d357602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b61273c613558565b60005b82811061277e5750907f1889010d2535a0ab1643678d1da87fbbe8b87b2f585b47ddb72ec622aef9ee5691612779604051928392836129a1565b0390a1565b61279161278c828585612914565b61293a565b80511580156128bf575b61285c57906128568261280661136460406127bf6020600198015163ffffffff1690565b936127f78151956127ef6127d66060850151151590565b916127df6104c0565b98895263ffffffff166020890152565b151586840152565b015167ffffffffffffffff1690565b60019082518155019063ffffffff6020820151167fffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000064ff0000000060408554940151151560201b16921617179055565b0161273f565b604080517fa087bd2900000000000000000000000000000000000000000000000000000000815282516004820152602083015163ffffffff1660248201529082015167ffffffffffffffff16604482015260609091015115156064820152608490fd5b5067ffffffffffffffff6128de604083015167ffffffffffffffff1690565b161561279b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b91908110156129245760071b0190565b6128e5565b359063ffffffff821682036102d357565b6080813603126102d35760405190608082019082821067ffffffffffffffff831117610413576060916040528035835261297660208201612929565b6020840152604081013561298981610949565b6040840152013561299981611e06565b606082015290565b602080825281018390526040019160005b8181106129bf5750505090565b9091926080806001928635815263ffffffff6129dd60208901612929565b16602082015267ffffffffffffffff60408801356129fa81610949565b1660408201526060870135612a0e81611e06565b151560608201520194019291016129b2565b604051906020820182811067ffffffffffffffff8211176104135760405260008252565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156102d3570180359067ffffffffffffffff82116102d3576020019181360383136102d357565b908160409103126102d357612ac5602060405192612ab284610418565b8035612abd81610949565b845201612929565b602082015290565b92919267ffffffffffffffff82116104135760405191612b15601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200184610450565b8294818452818301116102d3578281602093846000960137010152565b9080601f830112156102d3578160206112cb93359101612acd565b6020818303126102d35780359067ffffffffffffffff82116102d357016040818303126102d35760405191612b8183610418565b813567ffffffffffffffff81116102d35781612b9e918401612b32565b8352602082013567ffffffffffffffff81116102d357612ac59201612b32565b908160209103126102d357516112cb81611e06565b9091612bea6112cb936040845260408401906104cf565b9160208184039101526104cf565b6040513d6000823e3d90fd5b356112cb8161061e565b6112cb929167ffffffffffffffff612c39921660005260076020526005604060002001923691612acd565b602081519101209060019160005201602052604060002054151590565b67ffffffffffffffff81116104135760051b60200190565b929190612c7a81612c56565b93612c886040519586610450565b602085838152019160051b81019283116102d357905b828210612caa57505050565b602080918335612cb98161061e565b815201910190612c9e565b67ffffffffffffffff6112cb91166000526006602052604060002054151590565b91908110156129245760051b0190565b356112cb81610949565b9190811015612924576060020190565b60405190612d1c82610418565b60606020838281520152565b90604051612d35816103f7565b604060ff6001839580548552015463ffffffff8116602085015260201c161515910152565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b9160206112cb938181520191612d5a565b908160209103126102d3573590565b908160209103126102d357516112cb81610949565b80518210156129245760209160051b010190565b90600182811c92168015612e2b575b6020831014612dfc57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f1691612df1565b9060405191826000825492612e4984612de2565b8084529360018116908115612eb55750600114612e6e575b506104a092500383610450565b90506000929192526020600020906000915b818310612e995750509060206104a09282010138612e61565b6020919350806001915483858901015201910190918492612e80565b602093506104a09592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b82010138612e61565b60409067ffffffffffffffff6112cb95931681528160208201520191612d5a565b60405190612f2382610434565b60006080838281528260208201528260408201528260608201520152565b90604051612f4e81610434565b60806fffffffffffffffffffffffffffffffff6001839560ff8154848116875263ffffffff81871c16602088015260a01c1615156040860152015481808216166060850152821c16910152565b67ffffffffffffffff1660005260076020526112cb6004604060002001612e35565b91612ff5918354907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b9055565b818110613004575050565b60008155600101612ff9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181029291811591840414171561305257565b613010565b8054906000815581613067575050565b6000526020600020908101905b81811061307f575050565b60008155600101613074565b60056104a09160008155600060018201556000600282015560006003820155600481016130b88154612de2565b90816130c7575b505001613057565b81601f600093116001146130df5750555b38806130bf565b818352602083206130fa91601f01861c810190600101612ff9565b808252602082209081548360011b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8560031b1c1916179055556130d8565b91908110156129245760051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee1813603018212156102d3570190565b9080601f830112156102d357813561319181612c56565b9261319f6040519485610450565b81845260208085019260051b820101918383116102d35760208201905b8382106131cb57505050505090565b813567ffffffffffffffff81116102d3576020916131ee87848094880101612b32565b8152019101906131bc565b610120813603126102d3576040519061321182610434565b61321a8161095b565b8252602081013567ffffffffffffffff81116102d35761323d903690830161317a565b602083015260408101359067ffffffffffffffff82116102d3576132676132889236908301612b32565b60408401526132793660608301611eb7565b606084015260c0369101611eb7565b608082015290565b8151815460208401516040850151608091821b73ffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff9485167fffffffffffffffffffffff000000000000000000000000000000000000000000909416939093179290921791151560a01b74ff000000000000000000000000000000000000000016919091178355606084015193810151901b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000016921691909117600190910155565b9190601f811161336657505050565b6104a0926000526020600020906020601f840160051c83019310613392575b601f0160051c0190612ff9565b9091508190613385565b919091825167ffffffffffffffff8111610413576133c4816133be8454612de2565b84613357565b6020601f821160011461341e578190612ff5939495600092613413575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b0151905038806133e1565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082169061345184600052602060002090565b9160005b8181106134ab57509583600195969710613474575b505050811b019055565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c1916905538808061346a565b9192602060018192868b015181550194019201613455565b6135276134f26104a09597969467ffffffffffffffff60a09516845261010060208501526101008401906104cf565b9660408301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b01906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b73ffffffffffffffffffffffffffffffffffffffff60015416330361357957565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b90608082016135b761139461067c83612c04565b61377b5750602082019161365860206135fd6135d561224787612cf5565b60801b7fffffffffffffffffffffffffffffffff000000000000000000000000000000001690565b6040517f2cbc26bb0000000000000000000000000000000000000000000000000000000081527fffffffffffffffffffffffffffffffff00000000000000000000000000000000909116600482015291829081906024820190565b038173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9081156109445760009161375c575b50613732576136b86136b384612cf5565b613ead565b6136c183612cf5565b6136d661139460a08401926109f48486612a44565b6136f3575060606136ea6104a09394612cf5565b91013590613fd1565b6136fc91612a44565b9061164e6040519283927f24eb47e500000000000000000000000000000000000000000000000000000000845260048401612d99565b7f53ad11d80000000000000000000000000000000000000000000000000000000060005260046000fd5b613775915060203d60201161093d5761092f8183610450565b386136a2565b61378761124991612c04565b7f961c9a4f0000000000000000000000000000000000000000000000000000000060005273ffffffffffffffffffffffffffffffffffffffff16600452602490565b90600482015163ffffffff811661392157506008820151916014600c820151910151926137fd602084015163ffffffff1690565b63ffffffff811663ffffffff8316036138e85750507f000000000000000000000000000000000000000000000000000000000000000063ffffffff811663ffffffff8316036138af5750505167ffffffffffffffff1667ffffffffffffffff811667ffffffffffffffff831603613872575050565b7ff917ffea0000000000000000000000000000000000000000000000000000000060005267ffffffffffffffff9081166004521660245260446000fd5b7f77e480260000000000000000000000000000000000000000000000000000000060005263ffffffff9081166004521660245260446000fd5b7fe366a1170000000000000000000000000000000000000000000000000000000060005263ffffffff9081166004521660245260446000fd5b7f68d2f8d60000000000000000000000000000000000000000000000000000000060005263ffffffff1660045260246000fd5b60409067ffffffffffffffff6112cb949316815281602082015201906104cf565b90805115611c7e578051602082012067ffffffffffffffff8316928360005260076020526139aa8260056040600020016149d4565b15613a035750816139f27f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea936139ed6139fe946000526008602052604060002090565b61339c565b60405191829182611b46565b0390a2565b905061164e6040519283927f393b8ad200000000000000000000000000000000000000000000000000000000845260048401613954565b67ffffffffffffffff166000818152600660205260409020549092919015613b3c5791613b3960e092613b0585613a917f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b97613d57565b846000526007602052613aa881604060002061402e565b613ab183613d57565b846000526007602052613acb83600260406000200161402e565b60405194855260208501906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b60808301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565ba1565b827f1e670e4b0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b60808101613b7d61139461067c83612c04565b61377b57506020810190613b9b60206135fd6135d561224786612cf5565b038173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa90811561094457600091613c21575b50613732576060613c186104a093613c07613c0260408601612c04565b6142dc565b6111aa613c1382612cf5565b614373565b91013590614451565b613c3a915060203d60201161093d5761092f8183610450565b38613be5565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820191821161305257565b9190820391821161305257565b613c82612f16565b506fffffffffffffffffffffffffffffffff6060820151166fffffffffffffffffffffffffffffffff82511690602083019163ffffffff835116420342811161305257613ce6906fffffffffffffffffffffffffffffffff6080870151169061303f565b810180911161305257613d0c6fffffffffffffffffffffffffffffffff92918392614d84565b161682524263ffffffff16905290565b6104a09092919260608101936fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b805115613e105760408101516fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff613dbb613da660208501516fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff1690565b911690811090811591613e07575b50613dd15750565b61164e906040519182917f8020d12400000000000000000000000000000000000000000000000000000000835260048301613d1c565b90501538613dc9565b6fffffffffffffffffffffffffffffffff613e3e60408301516fffffffffffffffffffffffffffffffff1690565b1615801590613e85575b613e4f5750565b61164e906040519182917fd68af9cc00000000000000000000000000000000000000000000000000000000835260048301613d1c565b50613ea6613da660208301516fffffffffffffffffffffffffffffffff1690565b1515613e48565b613eb961139482612cc4565b613f9a576020613f3291613ee5610b4560045473ffffffffffffffffffffffffffffffffffffffff1690565b6040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90921660048301523360248301529092839190829081906044820190565b03915afa90811561094457600091613f7b575b5015613f4d57565b7f728fe07b000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b613f94915060203d60201161093d5761092f8183610450565b38613f45565b7fa9902c7e0000000000000000000000000000000000000000000000000000000060005267ffffffffffffffff1660045260246000fd5b9067ffffffffffffffff6104a09216600052600760205260026040600020019073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691614a62565b7f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c199161420d61277992805461407f6140796140708363ffffffff9060801c1690565b63ffffffff1690565b42613c6d565b9081614219575b50506141c760016140aa60208601516fffffffffffffffffffffffffffffffff1690565b926141356140f8613da66fffffffffffffffffffffffffffffffff6140df85546fffffffffffffffffffffffffffffffff1690565b166fffffffffffffffffffffffffffffffff8816614d84565b82906fffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffff00000000000000000000000000000000825416179055565b6141886141428751151590565b82547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690151560a01b74ff000000000000000000000000000000000000000016178255565b019182906fffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffff00000000000000000000000000000000825416179055565b604083015181546fffffffffffffffffffffffffffffffff1660809190911b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000016179055565b60405191829182613d1c565b613da66140f8916fffffffffffffffffffffffffffffffff61428d614294958261428660018a0154928261427f614278614262876fffffffffffffffffffffffffffffffff1690565b996fffffffffffffffffffffffffffffffff1690565b9560801c90565b169061303f565b91166148c3565b9116614d84565b80547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff164260801b73ffffffff00000000000000000000000000000000161781553880614086565b7f00000000000000000000000000000000000000000000000000000000000000006143045750565b73ffffffffffffffffffffffffffffffffffffffff16806000526003602052604060002054156143315750565b7fd0d259760000000000000000000000000000000000000000000000000000000060005260045260246000fd5b908160209103126102d357516112cb8161061e565b61437f61139482612cc4565b613f9a5760206143f0916143ab610b4560045473ffffffffffffffffffffffffffffffffffffffff1690565b60405180809581947fa8d87a3b0000000000000000000000000000000000000000000000000000000083526004830191909167ffffffffffffffff6020820193169052565b03915afa80156109445773ffffffffffffffffffffffffffffffffffffffff91600091614422575b50163303613f4d57565b614444915060203d60201161444a575b61443c8183610450565b81019061435e565b38614418565b503d614432565b9067ffffffffffffffff6104a09216600052600760205260406000209073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691614a62565b604051906002548083528260208101600260005260206000209260005b8181106144dd5750506104a092500383610450565b84548352600194850194879450602090930192016144c8565b604051906005548083528260208101600560005260206000209260005b8181106145285750506104a092500383610450565b8454835260019485019487945060209093019201614513565b906040519182815491828252602082019060005260206000209260005b8181106145735750506104a092500383610450565b845483526001948501948794506020909301920161455e565b80548210156129245760005260206000200190600090565b80548015614608577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01906145d9828261458c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b1916905555565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600081815260036020526040902054908115614714577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82019082821161305257600254927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84019384116130525783836000956146d395036146d9575b5050506146c260026145a4565b600390600052602052604060002090565b55600190565b6146c2614705916146fb6146f161470b95600261458c565b90549060031b1c90565b928391600261458c565b90612fbd565b553880806146b5565b5050600090565b600081815260066020526040902054908115614714577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82019082821161305257600554927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84019384116130525783836000956146d395036147b7575b5050506147a660056145a4565b600690600052602052604060002090565b6147a6614705916147cf6146f16147d995600561458c565b928391600561458c565b55388080614799565b60018101918060005282602052604060002054928315156000146148ba577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8401848111613052578354937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85019485116130525760009585836146d3976148729503614881575b5050506145a4565b90600052602052604060002090565b6148a1614705916148986146f16148b1958861458c565b9283918761458c565b8590600052602052604060002090565b5538808061486a565b50505050600090565b9190820180921161305257565b926148db919261303f565b8101809111613052576112cb91614d84565b60008181526003602052604090205461497857600254680100000000000000008110156104135761495f61492a826001859401600255600261458c565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b9055600254906000526003602052604060002055600190565b50600090565b6000818152600660205260409020546149785760055468010000000000000000811015610413576149bb61492a826001859401600555600561458c565b9055600554906000526006602052604060002055600190565b600082815260018201602052604090205461471457805490680100000000000000008210156104135782614a1261492a84600180960185558461458c565b905580549260005201602052604060002055600190565b8115614a33570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b9091815490614a786113948360ff9060a01c1690565b8015614d7c575b614d7657614a9e6fffffffffffffffffffffffffffffffff8316613da6565b9160018401908154614ad8614079614070614acb613da6856fffffffffffffffffffffffffffffffff1690565b9460801c63ffffffff1690565b80614ce2575b5050858110614c435750848310614b7257505091614b6261277992614b27613da6847f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a97613c6d565b6fffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffff00000000000000000000000000000000825416179055565b6040519081529081906020820190565b84614ba0614b9185614b8b613da6614ba5965460801c90565b93613c6d565b614b9a83613c40565b906148c3565b614a29565b9173ffffffffffffffffffffffffffffffffffffffff821615614c1157611249927fd0c8d23a00000000000000000000000000000000000000000000000000000000600052929173ffffffffffffffffffffffffffffffffffffffff9160649460045260245216604452565b7f15279c0800000000000000000000000000000000000000000000000000000000600052600483905260245260446000fd5b828673ffffffffffffffffffffffffffffffffffffffff821615614cb057611249927f1a76572a00000000000000000000000000000000000000000000000000000000600052929173ffffffffffffffffffffffffffffffffffffffff9160649460045260245216604452565b7ff94ebcd100000000000000000000000000000000000000000000000000000000600052600483905260245260446000fd5b828692939611614d4c57614cfc613da6614d039460801c90565b91866148d0565b84547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff164260801b73ffffffff0000000000000000000000000000000016178555923880614ade565b7f9725942a0000000000000000000000000000000000000000000000000000000060005260046000fd5b50505050565b508315614a7f565b9080821015614d91575090565b90509056fea164736f6c634300081a000a", } var USDCTokenPoolABI = USDCTokenPoolMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/weth9/weth9.go b/core/gethwrappers/ccip/generated/weth9/weth9.go index 50d0aa23f73..34c1fd7fb8b 100644 --- a/core/gethwrappers/ccip/generated/weth9/weth9.go +++ b/core/gethwrappers/ccip/generated/weth9/weth9.go @@ -31,8 +31,8 @@ var ( ) var WETH9MetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"guy\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"Withdrawal\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"guy\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", - Bin: "0x60c0604052600d60809081526c2bb930b83832b21022ba3432b960991b60a05260009061002c9082610116565b506040805180820190915260048152630ae8aa8960e31b60208201526001906100559082610116565b506002805460ff1916601217905534801561006f57600080fd5b506101d5565b634e487b7160e01b600052604160045260246000fd5b600181811c9082168061009f57607f821691505b6020821081036100bf57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610111576000816000526020600020601f850160051c810160208610156100ee5750805b601f850160051c820191505b8181101561010d578281556001016100fa565b5050505b505050565b81516001600160401b0381111561012f5761012f610075565b6101438161013d845461008b565b846100c5565b602080601f83116001811461017857600084156101605750858301515b600019600386901b1c1916600185901b17855561010d565b600085815260208120601f198616915b828110156101a757888601518255948401946001909101908401610188565b50858210156101c55787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6108ad806101e46000396000f3fe6080604052600436106100c05760003560e01c8063313ce56711610074578063a9059cbb1161004e578063a9059cbb146101fa578063d0e30db01461021a578063dd62ed3e1461022257600080fd5b8063313ce5671461018c57806370a08231146101b857806395d89b41146101e557600080fd5b806318160ddd116100a557806318160ddd1461012f57806323b872dd1461014c5780632e1a7d4d1461016c57600080fd5b806306fdde03146100d4578063095ea7b3146100ff57600080fd5b366100cf576100cd61025a565b005b600080fd5b3480156100e057600080fd5b506100e96102b5565b6040516100f69190610695565b60405180910390f35b34801561010b57600080fd5b5061011f61011a36600461072b565b610343565b60405190151581526020016100f6565b34801561013b57600080fd5b50475b6040519081526020016100f6565b34801561015857600080fd5b5061011f610167366004610755565b6103bd565b34801561017857600080fd5b506100cd610187366004610791565b6105c4565b34801561019857600080fd5b506002546101a69060ff1681565b60405160ff90911681526020016100f6565b3480156101c457600080fd5b5061013e6101d33660046107aa565b60036020526000908152604090205481565b3480156101f157600080fd5b506100e961066a565b34801561020657600080fd5b5061011f61021536600461072b565b610677565b6100cd61068b565b34801561022e57600080fd5b5061013e61023d3660046107c5565b600460209081526000928352604080842090915290825290205481565b3360009081526003602052604081208054349290610279908490610827565b909155505060405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a2565b600080546102c29061083a565b80601f01602080910402602001604051908101604052809291908181526020018280546102ee9061083a565b801561033b5780601f106103105761010080835404028352916020019161033b565b820191906000526020600020905b81548152906001019060200180831161031e57829003601f168201915b505050505081565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103ab9086815260200190565b60405180910390a35060015b92915050565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600360205260408120548211156103ef57600080fd5b73ffffffffffffffffffffffffffffffffffffffff84163314801590610455575073ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020546fffffffffffffffffffffffffffffffff14155b156104dd5773ffffffffffffffffffffffffffffffffffffffff8416600090815260046020908152604080832033845290915290205482111561049757600080fd5b73ffffffffffffffffffffffffffffffffffffffff84166000908152600460209081526040808320338452909152812080548492906104d790849061088d565b90915550505b73ffffffffffffffffffffffffffffffffffffffff84166000908152600360205260408120805484929061051290849061088d565b909155505073ffffffffffffffffffffffffffffffffffffffff83166000908152600360205260408120805484929061054c908490610827565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516105b291815260200190565b60405180910390a35060019392505050565b336000908152600360205260409020548111156105e057600080fd5b33600090815260036020526040812080548392906105ff90849061088d565b9091555050604051339082156108fc029083906000818181858888f19350505050158015610631573d6000803e3d6000fd5b5060405181815233907f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b659060200160405180910390a250565b600180546102c29061083a565b60006106843384846103bd565b9392505050565b61069361025a565b565b60006020808352835180602085015260005b818110156106c3578581018301518582016040015282016106a7565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461072657600080fd5b919050565b6000806040838503121561073e57600080fd5b61074783610702565b946020939093013593505050565b60008060006060848603121561076a57600080fd5b61077384610702565b925061078160208501610702565b9150604084013590509250925092565b6000602082840312156107a357600080fd5b5035919050565b6000602082840312156107bc57600080fd5b61068482610702565b600080604083850312156107d857600080fd5b6107e183610702565b91506107ef60208401610702565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156103b7576103b76107f8565b600181811c9082168061084e57607f821691505b602082108103610887577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b818103818111156103b7576103b76107f856fea164736f6c6343000818000a", + ABI: "[{\"type\":\"receive\",\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"allowance\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"approve\",\"inputs\":[{\"name\":\"guy\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"balanceOf\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"decimals\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"deposit\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"name\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"symbol\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"totalSupply\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transfer\",\"inputs\":[{\"name\":\"dst\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferFrom\",\"inputs\":[{\"name\":\"src\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"dst\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"withdraw\",\"inputs\":[{\"name\":\"wad\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"Approval\",\"inputs\":[{\"name\":\"src\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"guy\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Deposit\",\"inputs\":[{\"name\":\"dst\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Transfer\",\"inputs\":[{\"name\":\"src\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"dst\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Withdrawal\",\"inputs\":[{\"name\":\"src\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false}]", + Bin: "0x60806040523461011457610014600054610119565b601f81116100cb575b507f577261707065642045746865720000000000000000000000000000000000001a60005560015461004e90610119565b601f8111610081575b6008630ae8aa8960e31b016001556002805460ff19166012179055604051610a5a90816101548239f35b6001600052601f0160051c7fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6908101905b8181106100bf5750610057565b600081556001016100b2565b60008052601f0160051c7f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563908101905b818110610108575061001d565b600081556001016100fb565b600080fd5b90600182811c92168015610149575b602083101461013357565b634e487b7160e01b600052602260045260246000fd5b91607f169161012856fe60806040526004361015610062575b361561001957600080fd5b33600052600360205260406000206100323482546108a0565b90556040513481527fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c60203392a2005b60003560e01c806306fdde0314610696578063095ea7b3146105ef57806318160ddd146105b557806323b872dd146105685780632e1a7d4d146104aa578063313ce5671461046b57806370a082311461040657806395d89b4114610208578063a9059cbb146101b8578063d0e30db0146101755763dd62ed3e0361000e57346101705760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101705761011761081e565b73ffffffffffffffffffffffffffffffffffffffff610134610841565b9116600052600460205273ffffffffffffffffffffffffffffffffffffffff604060002091166000526020526020604060002054604051908152f35b600080fd5b60007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101705733600052600360205260406000206100323482546108a0565b346101705760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101705760206101fe6101f461081e565b60243590336108ad565b6040519015158152f35b346101705760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610170576000604051908091600154928360011c600185169485156103fc575b6020821086146103cf57839495828552908160001461036f57506001146102f6575b5003601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210176102c9576102c59250604052604051918291826107b6565b0390f35b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b600185528491507fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65b81831061035357505081016020017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0610275565b602091935080600191548385880101520191019091839261031f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660208581019190915291151560051b840190910191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09050610275565b6024857f4e487b710000000000000000000000000000000000000000000000000000000081526022600452fd5b90607f1690610253565b346101705760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101705773ffffffffffffffffffffffffffffffffffffffff61045261081e565b1660005260036020526020604060002054604051908152f35b346101705760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261017057602060ff60025416604051908152f35b346101705760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261017057600435336000526003602052806040600020541061017057336000526003602052604060002061050a828254610864565b9055806000811561055f575b600080809381933390f115610553576040519081527f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b6560203392a2005b6040513d6000823e3d90fd5b506108fc610516565b346101705760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101705760206101fe6105a461081e565b6105ac610841565b604435916108ad565b346101705760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261017057602047604051908152f35b346101705760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101705761062661081e565b73ffffffffffffffffffffffffffffffffffffffff6024359133600052600460205260406000208282166000526020528260406000205560405192835216907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b346101705760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101705760006040519080918154928360011c600185169485156107ac575b6020821086146103cf57839495828552908160001461036f5750600114610751575003601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210176102c9576102c59250604052604051918291826107b6565b848052602085208592505b81831061079057505081016020017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0610275565b602091935080600191548385880101520191019091839261075c565b90607f16906106e0565b9190916020815282519283602083015260005b8481106108085750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006040809697860101520116010190565b80602080928401015160408286010152016107c9565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361017057565b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361017057565b9190820391821161087157565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9190820180921161087157565b73ffffffffffffffffffffffffffffffffffffffff16908160005260036020528260406000205410610170573382141580610a03575b610963575b602073ffffffffffffffffffffffffffffffffffffffff7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9284600052600383526040600020610939878254610864565b90551693846000526003825260406000206109558282546108a0565b9055604051908152a3600190565b816000526004602052604060002073ffffffffffffffffffffffffffffffffffffffff3316600052602052826040600020541061017057602073ffffffffffffffffffffffffffffffffffffffff7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9284600052600483526040600020823316600052835260406000206109f8878254610864565b9055925050506108e8565b50816000526004602052604060002073ffffffffffffffffffffffffffffffffffffffff33166000526020526fffffffffffffffffffffffffffffffff60406000205414156108e356fea164736f6c634300081a000a", } var WETH9ABI = WETH9MetaData.ABI diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index f35104e20df..c063c5709f6 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,32 +1,31 @@ GETH_VERSION: 1.14.11 -burn_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnFromMintTokenPool/BurnFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnFromMintTokenPool/BurnFromMintTokenPool.bin 76c31f52fe1df85528c08b2e772e37dcf99ca1ec492d83a221abc1d5ec833694 -burn_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMintTokenPool.bin 1c78cd3118b3c9ca82f8cb77ffc1137619ea4e8e503c460f2dafb659d0dd766b -burn_with_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.bin eab9c19ef27b245e5ef0216ab1080c9dd89c96013b7dc978bf610288d5e82b00 -ccip_encoding_utils: ../../../contracts/solc/v0.8.24/ICCIPEncodingUtils/ICCIPEncodingUtils.abi ../../../contracts/solc/v0.8.24/ICCIPEncodingUtils/ICCIPEncodingUtils.bin 9971fc93c34442a0989570d3dab90a125de31e6e60754ad972807ce6ad4dfba0 -ccip_home: ../../../contracts/solc/v0.8.24/CCIPHome/CCIPHome.abi ../../../contracts/solc/v0.8.24/CCIPHome/CCIPHome.bin 865bc25c54cf346e5f519dc3fb625260a12c80983b5ba2dcea63519a7befc660 -ccip_reader_tester: ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin b368699ae7dbee7c21d049a641642837f18ce2cc8d4ece69509f205de673108e -ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin 09510a3f773f108a3c231e8d202835c845ded862d071ec54c4f89c12d868b8de -fee_quoter: ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.abi ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.bin aee49c9246d5903e68b175516b3cdfdec5df23e25d53d604cd382b6bc0bf34f7 -lock_release_token_pool: ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.bin 04b40584830294fb603cc2a250af7d831d05a04650a8c2fc9e3af5a78c471be6 -maybe_revert_message_receiver: ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.abi ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.bin d73956c26232ebcc4a5444429fa99cbefed960e323be9b5a24925885c2e477d5 -message_hasher: ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.abi ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.bin ec2d3a92348d8e7b8f0d359b62a45157b9d2c750c01fbcf991826c4392f6e218 -mock_usdc_token_messenger: ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.bin d976651d36b33ac2196b32b9d2f4fa6690c6a18d41b621365659fce1c1d1e737 -mock_usdc_token_transmitter: ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.bin be0dbc3e475741ea0b7a54ec2b935a321b428baa9f4ce18180a87fb38bb87de2 -mock_v3_aggregator_contract: ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.abi ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.bin 518e19efa2ff52b0fefd8e597b05765317ee7638189bfe34ca43de2f6599faf4 -multi_aggregate_rate_limiter: ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.abi ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.bin c3cac2010c2815b484055bf981363a2bd04e7fbe7bb502dc8fd29a16165d221c -multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin a523e11ea4c069d7d61b309c156951cc6834aff0f352bd1ac37c3a838ff2588f -nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin e6008490d916826cefd1903612db39621d51617300fc9bb42b68c6c117958198 -offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin 067fdfbf7cae1557fc03ca16d9c38737ee4595655792a1b8bc4846c45caa0c74 -onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin 2bf74188a997218502031f177cb2df505b272d66b25fd341a741289e77380c59 -ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin 24b4415a883a470d65c484be0fa20714a46b1c9262db205f1c958017820307b2 -registry_module_owner_custom: ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.abi ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.bin 0fc277a0b512db4e20b5a32a775b94ed2c0d342d8237511de78c94f7dacad428 -report_codec: ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.abi ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.bin 6c943b39f003aa67c3cefa19a8ff99e846236a058e1ceae77569c3a065ffd5c7 -rmn_home: ../../../contracts/solc/v0.8.24/RMNHome/RMNHome.abi ../../../contracts/solc/v0.8.24/RMNHome/RMNHome.bin 84ca84b3d0c00949905a3d10a91255f877cf32b2a0d7f7f7ce3121ced34a8cb7 -rmn_proxy_contract: ../../../contracts/solc/v0.8.24/ARMProxy/ARMProxy.abi ../../../contracts/solc/v0.8.24/ARMProxy/ARMProxy.bin b048d8e752e3c41113ebb305c1efa06737ad36b4907b93e627fb0a3113023454 -rmn_remote: ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.abi ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.bin 941118dfdc6bb042c339cfe8d8e0c7a0b486afb731a785d58a64994e7a13c459 -router: ../../../contracts/solc/v0.8.24/Router/Router.abi ../../../contracts/solc/v0.8.24/Router/Router.bin 2e4f0a7826c8abb49d882bb49fc5ff20a186dbd3137624b9097ffed903ae4888 -token_admin_registry: ../../../contracts/solc/v0.8.24/TokenAdminRegistry/TokenAdminRegistry.abi ../../../contracts/solc/v0.8.24/TokenAdminRegistry/TokenAdminRegistry.bin 397bc7be08c2848c0f4715f90b16206d6367f78ffb7cd48e2b1dfc0ccc5aea26 -token_pool: ../../../contracts/solc/v0.8.24/TokenPool/TokenPool.abi ../../../contracts/solc/v0.8.24/TokenPool/TokenPool.bin 793d65f336929becdcf8bc3f2208a5b6de93774215fe2e863bef64df419cfdb0 -usdc_reader_tester: ../../../contracts/solc/v0.8.24/USDCReaderTester/USDCReaderTester.abi ../../../contracts/solc/v0.8.24/USDCReaderTester/USDCReaderTester.bin 672a07c9218fd6ad7c04dde583088b0f5ffc8d55a46f4be1714008dd3409438b -usdc_token_pool: ../../../contracts/solc/v0.8.24/USDCTokenPool/USDCTokenPool.abi ../../../contracts/solc/v0.8.24/USDCTokenPool/USDCTokenPool.bin a9fef4db2c901302c0293b139eb77017b18da8543b7623e17f2932efbb8e3011 -weth9: ../../../contracts/solc/v0.8.24/WETH9/WETH9.abi ../../../contracts/solc/v0.8.24/WETH9/WETH9.bin 2970d79a0ca6dd6279cde130de45e56c8790ed695eae477fb5ba4c1bb75b720d +burn_from_mint_token_pool: ../../../contracts/solc/ccip/BurnFromMintTokenPool/BurnFromMintTokenPool.sol/BurnFromMintTokenPool.abi.json ../../../contracts/solc/ccip/BurnFromMintTokenPool/BurnFromMintTokenPool.sol/BurnFromMintTokenPool.bin ae4e15dc926517092d46e108cd5e24863d58e689444ce310bb00c1390f711ba9 +burn_mint_token_pool: ../../../contracts/solc/ccip/BurnMintTokenPool/BurnMintTokenPool.sol/BurnMintTokenPool.abi.json ../../../contracts/solc/ccip/BurnMintTokenPool/BurnMintTokenPool.sol/BurnMintTokenPool.bin 7360dc05306d51b247abdf9a3aa8704847b1f4fb91fdb822a2dfc54e1d86cda1 +burn_with_from_mint_token_pool: ../../../contracts/solc/ccip/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.sol/BurnWithFromMintTokenPool.abi.json ../../../contracts/solc/ccip/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.sol/BurnWithFromMintTokenPool.bin 66715c303bb2da2b49bba100a788f6471b0f94d255d40f92306e279b909ae33b +ccip_encoding_utils: ../../../contracts/solc/ccip/EncodingUtils/EncodingUtils.sol/EncodingUtils.abi.json ../../../contracts/solc/ccip/EncodingUtils/EncodingUtils.sol/EncodingUtils.bin abd960015cec3e4d94a5948d2d66ee915770fe4a744c28a5ff46d23e870baaea +ccip_home: ../../../contracts/solc/ccip/CCIPHome/CCIPHome.sol/CCIPHome.abi.json ../../../contracts/solc/ccip/CCIPHome/CCIPHome.sol/CCIPHome.bin 39de1fbc907a2b573e9358e716803bf5ac3b0a2e622d5bc0069ab60daf38949b +ccip_reader_tester: ../../../contracts/solc/ccip/CCIPReaderTester/CCIPReaderTester.sol/CCIPReaderTester.abi.json ../../../contracts/solc/ccip/CCIPReaderTester/CCIPReaderTester.sol/CCIPReaderTester.bin b8e597d175ec5ff4990d98b4e3b8a8cf06c6ae22977dd6f0e58c0f4107639e8f +ether_sender_receiver: ../../../contracts/solc/ccip/EtherSenderReceiver/EtherSenderReceiver.sol/EtherSenderReceiver.abi.json ../../../contracts/solc/ccip/EtherSenderReceiver/EtherSenderReceiver.sol/EtherSenderReceiver.bin 88973abc1bfbca23a23704e20087ef46f2e20581a13477806308c8f2e664844e +fee_quoter: ../../../contracts/solc/ccip/FeeQuoter/FeeQuoter.sol/FeeQuoter.abi.json ../../../contracts/solc/ccip/FeeQuoter/FeeQuoter.sol/FeeQuoter.bin 7be986f71fb72d1790b05033ba39531679284ff6a1b8f4978aea11763d932e73 +lock_release_token_pool: ../../../contracts/solc/ccip/LockReleaseTokenPool/LockReleaseTokenPool.sol/LockReleaseTokenPool.abi.json ../../../contracts/solc/ccip/LockReleaseTokenPool/LockReleaseTokenPool.sol/LockReleaseTokenPool.bin 2e73ee0da6f9a9a5722294289b969e4202476706e5d7cdb623e728831c79c28b +maybe_revert_message_receiver: ../../../contracts/solc/ccip/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.sol/MaybeRevertMessageReceiver.abi.json ../../../contracts/solc/ccip/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.sol/MaybeRevertMessageReceiver.bin d1eb951af1027ca20cbee2c34df80fddbfd861e1695989aeebd29327cfe56584 +message_hasher: ../../../contracts/solc/ccip/MessageHasher/MessageHasher.sol/MessageHasher.abi.json ../../../contracts/solc/ccip/MessageHasher/MessageHasher.sol/MessageHasher.bin 9d503e62f007cfa7bf411ec845c3537b272709001d25ec738820ca83991c299c +mock_usdc_token_messenger: ../../../contracts/solc/ccip/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.sol/MockE2EUSDCTokenMessenger.abi.json ../../../contracts/solc/ccip/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.sol/MockE2EUSDCTokenMessenger.bin ad7902d63667e582b93b2fad139aa53111f9fddcedf92b1d6d122d1ab7ec4bab +mock_usdc_token_transmitter: ../../../contracts/solc/ccip/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.sol/MockE2EUSDCTransmitter.abi.json ../../../contracts/solc/ccip/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.sol/MockE2EUSDCTransmitter.bin ae0d090105bc248f4eccd337836ec1db760c506d6f5578e662305abbbc520fcd +multi_aggregate_rate_limiter: ../../../contracts/solc/ccip/MultiAggregateRateLimiter/MultiAggregateRateLimiter.sol/MultiAggregateRateLimiter.abi.json ../../../contracts/solc/ccip/MultiAggregateRateLimiter/MultiAggregateRateLimiter.sol/MultiAggregateRateLimiter.bin d462b10c87ad74b73502c3c97a7fc53771b915adb9a0fbee781e744f3827d179 +multi_ocr3_helper: ../../../contracts/solc/ccip/MultiOCR3Helper/MultiOCR3Helper.sol/MultiOCR3Helper.abi.json ../../../contracts/solc/ccip/MultiOCR3Helper/MultiOCR3Helper.sol/MultiOCR3Helper.bin 71514db63a2ac5e3bebe0e6b393061ee1b414c9405084f4bbd890cfc76c21b0f +nonce_manager: ../../../contracts/solc/ccip/NonceManager/NonceManager.sol/NonceManager.abi.json ../../../contracts/solc/ccip/NonceManager/NonceManager.sol/NonceManager.bin ac76c64749ce07dd2ec1b9346d3401dcc5538253e516aecc4767c4308817ea59 +offramp: ../../../contracts/solc/ccip/OffRamp/OffRamp.sol/OffRamp.abi.json ../../../contracts/solc/ccip/OffRamp/OffRamp.sol/OffRamp.bin 61002b1524baea33d1d6a71d007511ccebc4cf8c3105385774cc27e9c00f046e +onramp: ../../../contracts/solc/ccip/OnRamp/OnRamp.sol/OnRamp.abi.json ../../../contracts/solc/ccip/OnRamp/OnRamp.sol/OnRamp.bin a829e4efe4d8f600dc20589505701fbce872b09bc763b1a5abded28ef4a3afc9 +ping_pong_demo: ../../../contracts/solc/ccip/PingPongDemo/PingPongDemo.sol/PingPongDemo.abi.json ../../../contracts/solc/ccip/PingPongDemo/PingPongDemo.sol/PingPongDemo.bin c87b6e1a8961a9dd2fab1eced0df12d0c1ef47bb1b2511f372b7e33443a20683 +registry_module_owner_custom: ../../../contracts/solc/ccip/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.sol/RegistryModuleOwnerCustom.abi.json ../../../contracts/solc/ccip/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.sol/RegistryModuleOwnerCustom.bin ce04722cdea2e96d791e48c6a99f64559125d34cd24e19cfd5281892d2ed8ef0 +report_codec: ../../../contracts/solc/ccip/ReportCodec/ReportCodec.sol/ReportCodec.abi.json ../../../contracts/solc/ccip/ReportCodec/ReportCodec.sol/ReportCodec.bin 5e66322fdcd40d601e1a55cfccfb9abe066b90297084d2db4f55dfe3ae7d0af2 +rmn_home: ../../../contracts/solc/ccip/RMNHome/RMNHome.sol/RMNHome.abi.json ../../../contracts/solc/ccip/RMNHome/RMNHome.sol/RMNHome.bin f13285ef924c4675710e3055b0ecc028a1e0cf4ea3c0e83b31ffe8a76fc6c420 +rmn_proxy_contract: ../../../contracts/solc/ccip/RMNProxy/RMNProxy.sol/RMNProxy.abi.json ../../../contracts/solc/ccip/RMNProxy/RMNProxy.sol/RMNProxy.bin 4d06f9e5c6f72daef745e6114faed3bae57ad29758d75de5a4eefcd5f0172328 +rmn_remote: ../../../contracts/solc/ccip/RMNRemote/RMNRemote.sol/RMNRemote.abi.json ../../../contracts/solc/ccip/RMNRemote/RMNRemote.sol/RMNRemote.bin 32173df61397fc104bc6bcd9d8e929165ee3911518350dc7f2bb5d1d94875a94 +router: ../../../contracts/solc/ccip/Router/Router.sol/Router.abi.json ../../../contracts/solc/ccip/Router/Router.sol/Router.bin 0103ab2fd344179d49f0320d0a47ec8255fe8a401a2f2c8973e8314dc49d2413 +token_admin_registry: ../../../contracts/solc/ccip/TokenAdminRegistry/TokenAdminRegistry.sol/TokenAdminRegistry.abi.json ../../../contracts/solc/ccip/TokenAdminRegistry/TokenAdminRegistry.sol/TokenAdminRegistry.bin 086268b9df56e089a69a96ce3e4fd03a07a00a1c8812ba9504e31930a5c3ff1d +token_pool: ../../../contracts/solc/ccip/TokenPool/TokenPool.sol/TokenPool.abi.json ../../../contracts/solc/ccip/TokenPool/TokenPool.sol/TokenPool.bin 6c00ce7b2082f40d5f9b4808eb692a90e81c312b4f5d70d62e4b1ef69a164a9f +usdc_reader_tester: ../../../contracts/solc/ccip/USDCReaderTester/USDCReaderTester.sol/USDCReaderTester.abi.json ../../../contracts/solc/ccip/USDCReaderTester/USDCReaderTester.sol/USDCReaderTester.bin 7622b1e42bc9c3933c51607d765d8463796c615155596929e554a58ed68b263d +usdc_token_pool: ../../../contracts/solc/ccip/USDCTokenPool/USDCTokenPool.sol/USDCTokenPool.abi.json ../../../contracts/solc/ccip/USDCTokenPool/USDCTokenPool.sol/USDCTokenPool.bin 8a44f8d2d193fc1332e5e80a5e05172dc15680e0921d7cc945ea321746f764fc +weth9: ../../../contracts/solc/ccip/WETH9/WETH9.sol/WETH9.abi.json ../../../contracts/solc/ccip/WETH9/WETH9.sol/WETH9.bin 89ee9892414b4d9abfb18046504aa7771c88c52a0831479ca4152f120e647d49 diff --git a/core/gethwrappers/ccip/go_generate.go b/core/gethwrappers/ccip/go_generate.go index 9d6fa7c4645..e1fa0e9150d 100644 --- a/core/gethwrappers/ccip/go_generate.go +++ b/core/gethwrappers/ccip/go_generate.go @@ -1,76 +1,38 @@ -// Package gethwrappers_ccip provides tools for wrapping solidity contracts with -// golang packages, using abigen. package ccip -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/ARMProxy/ARMProxy.abi ../../../contracts/solc/v0.8.24/ARMProxy/ARMProxy.bin RMNProxyContract rmn_proxy_contract -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/TokenAdminRegistry/TokenAdminRegistry.abi ../../../contracts/solc/v0.8.24/TokenAdminRegistry/TokenAdminRegistry.bin TokenAdminRegistry token_admin_registry -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.abi ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.bin RegistryModuleOwnerCustom registry_module_owner_custom -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin OnRamp onramp -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin OffRamp offramp -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.abi ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.bin RMNRemote rmn_remote -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/RMNHome/RMNHome.abi ../../../contracts/solc/v0.8.24/RMNHome/RMNHome.bin RMNHome rmn_home -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.abi ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.bin MultiAggregateRateLimiter multi_aggregate_rate_limiter -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/Router/Router.abi ../../../contracts/solc/v0.8.24/Router/Router.bin Router router -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.abi ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.bin FeeQuoter fee_quoter -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/CCIPHome/CCIPHome.abi ../../../contracts/solc/v0.8.24/CCIPHome/CCIPHome.bin CCIPHome ccip_home -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin NonceManager nonce_manager +//go:generate go run ../generation/wrap.go ccip Router router +//go:generate go run ../generation/wrap.go ccip CCIPHome ccip_home +//go:generate go run ../generation/wrap.go ccip OnRamp onramp +//go:generate go run ../generation/wrap.go ccip OffRamp offramp +//go:generate go run ../generation/wrap.go ccip FeeQuoter fee_quoter +//go:generate go run ../generation/wrap.go ccip NonceManager nonce_manager +//go:generate go run ../generation/wrap.go ccip MultiAggregateRateLimiter multi_aggregate_rate_limiter +//go:generate go run ../generation/wrap.go ccip TokenAdminRegistry token_admin_registry +//go:generate go run ../generation/wrap.go ccip RegistryModuleOwnerCustom registry_module_owner_custom +//go:generate go run ../generation/wrap.go ccip RMNProxy rmn_proxy_contract +//go:generate go run ../generation/wrap.go ccip RMNRemote rmn_remote +//go:generate go run ../generation/wrap.go ccip RMNHome rmn_home // Pools -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMintTokenPool.bin BurnMintTokenPool burn_mint_token_pool -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/BurnFromMintTokenPool/BurnFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnFromMintTokenPool/BurnFromMintTokenPool.bin BurnFromMintTokenPool burn_from_mint_token_pool -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.bin BurnWithFromMintTokenPool burn_with_from_mint_token_pool -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.bin LockReleaseTokenPool lock_release_token_pool -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/TokenPool/TokenPool.abi ../../../contracts/solc/v0.8.24/TokenPool/TokenPool.bin TokenPool token_pool -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/USDCTokenPool/USDCTokenPool.abi ../../../contracts/solc/v0.8.24/USDCTokenPool/USDCTokenPool.bin USDCTokenPool usdc_token_pool +//go:generate go run ../generation/wrap.go ccip BurnMintTokenPool burn_mint_token_pool +//go:generate go run ../generation/wrap.go ccip BurnFromMintTokenPool burn_from_mint_token_pool +//go:generate go run ../generation/wrap.go ccip BurnWithFromMintTokenPool burn_with_from_mint_token_pool +//go:generate go run ../generation/wrap.go ccip LockReleaseTokenPool lock_release_token_pool +//go:generate go run ../generation/wrap.go ccip TokenPool token_pool +//go:generate go run ../generation/wrap.go ccip USDCTokenPool usdc_token_pool // Helpers -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.abi ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.bin MockV3Aggregator mock_v3_aggregator_contract -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.abi ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.bin MaybeRevertMessageReceiver maybe_revert_message_receiver -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin PingPongDemo ping_pong_demo -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.abi ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.bin MessageHasher message_hasher -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin MultiOCR3Helper multi_ocr3_helper -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/USDCReaderTester/USDCReaderTester.abi ../../../contracts/solc/v0.8.24/USDCReaderTester/USDCReaderTester.bin USDCReaderTester usdc_reader_tester -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.abi ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.bin ReportCodec report_codec -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin EtherSenderReceiver ether_sender_receiver -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/WETH9/WETH9.abi ../../../contracts/solc/v0.8.24/WETH9/WETH9.bin WETH9 weth9 -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.bin MockE2EUSDCTokenMessenger mock_usdc_token_messenger -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.bin MockE2EUSDCTransmitter mock_usdc_token_transmitter -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin CCIPReaderTester ccip_reader_tester +//go:generate go run ../generation/wrap.go ccip MaybeRevertMessageReceiver maybe_revert_message_receiver +//go:generate go run ../generation/wrap.go ccip PingPongDemo ping_pong_demo +//go:generate go run ../generation/wrap.go ccip MessageHasher message_hasher +//go:generate go run ../generation/wrap.go ccip MultiOCR3Helper multi_ocr3_helper +//go:generate go run ../generation/wrap.go ccip USDCReaderTester usdc_reader_tester +//go:generate go run ../generation/wrap.go ccip ReportCodec report_codec +//go:generate go run ../generation/wrap.go ccip EtherSenderReceiver ether_sender_receiver +//go:generate go run ../generation/wrap.go ccip WETH9 weth9 +//go:generate go run ../generation/wrap.go ccip MockE2EUSDCTokenMessenger mock_usdc_token_messenger +//go:generate go run ../generation/wrap.go ccip MockE2EUSDCTransmitter mock_usdc_token_transmitter +//go:generate go run ../generation/wrap.go ccip CCIPReaderTester ccip_reader_tester // EncodingUtils -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/ICCIPEncodingUtils/ICCIPEncodingUtils.abi ../../../contracts/solc/v0.8.24/ICCIPEncodingUtils/ICCIPEncodingUtils.bin EncodingUtils ccip_encoding_utils - -// To run these commands, you must either install docker, or the correct version -// of abigen. The latter can be installed with these commands, at least on linux: -// -// git clone https://github.com/ethereum/go-ethereum -// cd go-ethereum/cmd/abigen -// git checkout v -// go install -// -// Here, is the version of go-ethereum specified in chainlink's -// go.mod. This will install abigen in "$GOPATH/bin", which you should add to -// your $PATH. -// -// To reduce explicit dependencies, and in case the system does not have the -// correct version of abigen installed , the above commands spin up docker -// containers. In my hands, total running time including compilation is about -// 13s. If you're modifying solidity code and testing against go code a lot, it -// might be worthwhile to generate the the wrappers using a static container -// with abigen and solc, which will complete much faster. E.g. -// -// abigen -sol ../../contracts/src/v0.6/VRFAll.sol -pkg vrf -out solidity_interfaces.go -// -// where VRFAll.sol simply contains `import "contract_path";` instructions for -// all the contracts you wish to target. This runs in about 0.25 seconds in my -// hands. -// -// If you're on linux, you can copy the correct version of solc out of the -// appropriate docker container. At least, the following works on ubuntu: -// -// $ docker run --name solc ethereum/solc:0.6.2 -// $ sudo docker cp solc:/usr/bin/solc /usr/bin -// $ docker rm solc -// -// If you need to point abigen at your solc executable, you can specify the path -// with the abigen --solc option. +//go:generate go run ../generation/wrap.go ccip EncodingUtils ccip_encoding_utils diff --git a/core/gethwrappers/ccip/mocks/commit_store_interface.go b/core/gethwrappers/ccip/mocks/commit_store_interface.go index 0cadfd036a8..f1ff6c610a1 100644 --- a/core/gethwrappers/ccip/mocks/commit_store_interface.go +++ b/core/gethwrappers/ccip/mocks/commit_store_interface.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mock_contracts @@ -89,7 +89,7 @@ func (_c *CommitStoreInterface_AcceptOwnership_Call) RunAndReturn(run func(*bind return _c } -// Address provides a mock function with given fields: +// Address provides a mock function with no fields func (_m *CommitStoreInterface) Address() common.Address { ret := _m.Called() diff --git a/core/gethwrappers/ccip/mocks/evm2_evm_off_ramp_interface.go b/core/gethwrappers/ccip/mocks/evm2_evm_off_ramp_interface.go index e9e635d8711..73ee46418c9 100644 --- a/core/gethwrappers/ccip/mocks/evm2_evm_off_ramp_interface.go +++ b/core/gethwrappers/ccip/mocks/evm2_evm_off_ramp_interface.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mock_contracts @@ -88,7 +88,7 @@ func (_c *EVM2EVMOffRampInterface_AcceptOwnership_Call) RunAndReturn(run func(*b return _c } -// Address provides a mock function with given fields: +// Address provides a mock function with no fields func (_m *EVM2EVMOffRampInterface) Address() common.Address { ret := _m.Called() diff --git a/core/gethwrappers/ccip/mocks/evm2_evm_on_ramp_interface.go b/core/gethwrappers/ccip/mocks/evm2_evm_on_ramp_interface.go index 3c65e2c5627..428c71ba393 100644 --- a/core/gethwrappers/ccip/mocks/evm2_evm_on_ramp_interface.go +++ b/core/gethwrappers/ccip/mocks/evm2_evm_on_ramp_interface.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mock_contracts @@ -90,7 +90,7 @@ func (_c *EVM2EVMOnRampInterface_AcceptOwnership_Call) RunAndReturn(run func(*bi return _c } -// Address provides a mock function with given fields: +// Address provides a mock function with no fields func (_m *EVM2EVMOnRampInterface) Address() common.Address { ret := _m.Called() diff --git a/core/gethwrappers/ccip/mocks/fee_quoter_interface.go b/core/gethwrappers/ccip/mocks/fee_quoter_interface.go index 8fadeb40e08..b254eae565b 100644 --- a/core/gethwrappers/ccip/mocks/fee_quoter_interface.go +++ b/core/gethwrappers/ccip/mocks/fee_quoter_interface.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mock_contracts @@ -90,7 +90,7 @@ func (_c *FeeQuoterInterface_AcceptOwnership_Call) RunAndReturn(run func(*bind.T return _c } -// Address provides a mock function with given fields: +// Address provides a mock function with no fields func (_m *FeeQuoterInterface) Address() common.Address { ret := _m.Called() diff --git a/core/gethwrappers/ccip/mocks/link_token_interface.go b/core/gethwrappers/ccip/mocks/link_token_interface.go index 59e9d7c8543..dcf0c1cadbc 100644 --- a/core/gethwrappers/ccip/mocks/link_token_interface.go +++ b/core/gethwrappers/ccip/mocks/link_token_interface.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mock_contracts @@ -32,7 +32,7 @@ func (_m *LinkTokenInterface) EXPECT() *LinkTokenInterface_Expecter { return &LinkTokenInterface_Expecter{mock: &_m.Mock} } -// Address provides a mock function with given fields: +// Address provides a mock function with no fields func (_m *LinkTokenInterface) Address() common.Address { ret := _m.Called() diff --git a/core/gethwrappers/ccip/mocks/v1_2_0/evm2_evm_off_ramp_interface.go b/core/gethwrappers/ccip/mocks/v1_2_0/evm2_evm_off_ramp_interface.go index a7de44f93ea..7a20a3bd068 100644 --- a/core/gethwrappers/ccip/mocks/v1_2_0/evm2_evm_off_ramp_interface.go +++ b/core/gethwrappers/ccip/mocks/v1_2_0/evm2_evm_off_ramp_interface.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mock_contracts @@ -90,7 +90,7 @@ func (_c *EVM2EVMOffRampInterface_AcceptOwnership_Call) RunAndReturn(run func(*b return _c } -// Address provides a mock function with given fields: +// Address provides a mock function with no fields func (_m *EVM2EVMOffRampInterface) Address() common.Address { ret := _m.Called() diff --git a/core/gethwrappers/generated/automation_registry_wrapper_2_3/automation_registry_wrapper_2_3.go b/core/gethwrappers/generated/automation_registry_wrapper_2_3/automation_registry_wrapper_2_3.go index 97f0cfb113a..17cbd9a95a8 100644 --- a/core/gethwrappers/generated/automation_registry_wrapper_2_3/automation_registry_wrapper_2_3.go +++ b/core/gethwrappers/generated/automation_registry_wrapper_2_3/automation_registry_wrapper_2_3.go @@ -76,7 +76,7 @@ type AutomationRegistryBase23PaymentReceipt struct { var AutomationRegistryMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"contractAutomationRegistryLogicA2_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\":\"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\":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\"},{\"components\":[{\"internalType\":\"uint96\",\"name\":\"gasChargeInBillingToken\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"premiumInBillingToken\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"gasReimbursementInJuels\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"premiumInJuels\",\"type\":\"uint96\"},{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"linkUSD\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"nativeUSD\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"billingUSD\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.PaymentReceipt\",\"name\":\"receipt\",\"type\":\"tuple\"}],\"name\":\"UpkeepCharged\",\"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\":[],\"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\":\"contractIChainModule\",\"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\":\"contractIERC20Metadata[]\",\"name\":\"billingTokens\",\"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\"}],\"internalType\":\"structAutomationRegistryBase2_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\"}]", - Bin: "0x6101806040523480156200001257600080fd5b50604051620065423803806200654283398101604081905262000035916200062f565b80816001600160a01b031663ca30e6036040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b91906200062f565b826001600160a01b031663226cf83c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062f565b836001600160a01b031663614486af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016591906200062f565b846001600160a01b0316636709d0e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ca91906200062f565b856001600160a01b0316635425d8ac6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f91906200062f565b866001600160a01b031663a08714c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029491906200062f565b876001600160a01b031663c5b964e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f9919062000656565b886001600160a01b031663ac4dc59a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000338573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035e91906200062f565b3380600081620003b55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620003e857620003e8816200056b565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff19166001838181111562000439576200043962000679565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200049a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c091906200068f565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000504573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200052a91906200068f565b60ff16146200054c576040516301f86e1760e41b815260040160405180910390fd5b5050506001600160a01b039095166101605250620006b4945050505050565b336001600160a01b03821603620005c55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620003ac565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200062c57600080fd5b50565b6000602082840312156200064257600080fd5b81516200064f8162000616565b9392505050565b6000602082840312156200066957600080fd5b8151600281106200064f57600080fd5b634e487b7160e01b600052602160045260246000fd5b600060208284031215620006a257600080fd5b815160ff811681146200064f57600080fd5b60805160a05160c05160e05161010051610120516101405161016051615e2a620007186000396000818160b3015261018601526000505060005050600050506000505060006137bd015260005050600081816113710152612de60152615e2a6000f3fe6080604052600436106100b15760003560e01c80638da5cb5b11610069578063b1dc65a41161004e578063b1dc65a4146102cb578063e3d0e712146102eb578063f2fde38b1461030b576100b1565b80638da5cb5b1461025a578063afcb95d714610285576100b1565b8063349e8cca1161009a578063349e8cca1461017757806379ba5097146101cb57806381ff7048146101e0576100b1565b80630870d3a1146100f8578063181f5a7714610118575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e8080156100f1573d6000f35b3d6000fd5b005b34801561010457600080fd5b506100f6610113366004614b9e565b61032b565b34801561012457600080fd5b506101616040518060400160405280601881526020017f4175746f6d6174696f6e526567697374727920322e332e30000000000000000081525081565b60405161016e9190614d1a565b60405180910390f35b34801561018357600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161016e565b3480156101d757600080fd5b506100f6610c0f565b3480156101ec57600080fd5b5061023760175460135463ffffffff74010000000000000000000000000000000000000000830481169378010000000000000000000000000000000000000000000000009093041691565b6040805163ffffffff94851681529390921660208401529082015260600161016e565b34801561026657600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101a6565b34801561029157600080fd5b50601354601454604080516000815260208101939093526c0100000000000000000000000090910463ffffffff169082015260600161016e565b3480156102d757600080fd5b506100f66102e6366004614d79565b610d11565b3480156102f757600080fd5b506100f6610306366004614e5e565b611051565b34801561031757600080fd5b506100f6610326366004614f2b565b61108b565b61033361109f565b601f8851111561036f576040517f25d0209c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8560ff166000036103ac576040517fe77dba5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b865188511415806103cb57506103c3866003614f77565b60ff16885111155b15610402576040517f1d2d1c5800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805182511461043d576040517fcf54c06a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104478282611122565b610451888861175a565b604051806101200160405280601460000160009054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff168152602001600063ffffffff1681526020018660a0015162ffffff16815260200186610120015161ffff1681526020018760ff168152602001601460000160169054906101000a900460ff1615158152602001601460000160179054906101000a900460ff1615158152602001866080015115158152602001866101e0015173ffffffffffffffffffffffffffffffffffffffff16815250601460008201518160000160006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550602082015181600001600c6101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160106101000a81548162ffffff021916908362ffffff16021790555060608201518160000160136101000a81548161ffff021916908361ffff16021790555060808201518160000160156101000a81548160ff021916908360ff16021790555060a08201518160000160166101000a81548160ff02191690831515021790555060c08201518160000160176101000a81548160ff02191690831515021790555060e08201518160000160186101000a81548160ff0219169083151502179055506101008201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050506000601660010160189054906101000a900463ffffffff1690506000866101e0015173ffffffffffffffffffffffffffffffffffffffff166357e871e76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610701573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107259190614f93565b6017549091506000906107579074010000000000000000000000000000000000000000900463ffffffff166001614fac565b9050604051806101600160405280896060015173ffffffffffffffffffffffffffffffffffffffff168152602001896000015163ffffffff168152602001896020015163ffffffff1681526020016016600001601c9054906101000a900463ffffffff1663ffffffff16815260200189610100015173ffffffffffffffffffffffffffffffffffffffff1681526020018263ffffffff1681526020018363ffffffff168152602001896040015163ffffffff16815260200189610140015173ffffffffffffffffffffffffffffffffffffffff1681526020018960c0015163ffffffff1681526020018960e0015163ffffffff16815250601660008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160186101000a81548163ffffffff021916908363ffffffff160217905550606082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a08201518160010160146101000a81548163ffffffff021916908363ffffffff16021790555060c08201518160010160186101000a81548163ffffffff021916908363ffffffff16021790555060e082015181600101601c6101000a81548163ffffffff021916908363ffffffff1602179055506101008201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101208201518160020160146101000a81548163ffffffff021916908363ffffffff1602179055506101408201518160020160186101000a81548163ffffffff021916908363ffffffff160217905550905050876101600151601981905550876101800151601a81905550876101a00151601b81905550600088604051602001610a9a919061501a565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152919052601754909150610aff904690309074010000000000000000000000000000000000000000900463ffffffff168f8f8f878f8f611e19565b6013556000610b0e6009611ec3565b90505b8015610b4b57610b38610b30610b286001846151a0565b600990611ed3565b600990611ee6565b5080610b43816151b3565b915050610b11565b5060005b896101c0015151811015610ba257610b8f8a6101c001518281518110610b7757610b776151e8565b60200260200101516009611f0890919063ffffffff16565b5080610b9a81615217565b915050610b4f565b507f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0584601354601660010160149054906101000a900463ffffffff168f8f8f878f8f604051610bf99998979695949392919061524f565b60405180910390a1505050505050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610c95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60005a90506000610d238660406152e5565b610d2f896101446152fc565b610d3991906152fc565b9050368114610d74576040517fdfe9309000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051610120810182526014546bffffffffffffffffffffffff8116825263ffffffff6c01000000000000000000000000820416602083015262ffffff7001000000000000000000000000000000008204169282019290925261ffff730100000000000000000000000000000000000000830416606082015260ff75010000000000000000000000000000000000000000008304811660808301527601000000000000000000000000000000000000000000008304811615801560a08401527701000000000000000000000000000000000000000000000084048216151560c0840152780100000000000000000000000000000000000000000000000090930416151560e082015260155473ffffffffffffffffffffffffffffffffffffffff1661010082015290610ed3576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600b602052604090205460ff16610f1c576040517f1099ed7500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6013548b3514610f58576040517fdfdcf8e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6080810151610f6890600161530f565b60ff1687141580610f795750868514155b15610fb0576040517f0244f71a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610fc08b8b8b8b8b8b8b8b611f2a565b6000610fcc8b8b612193565b905060208c0135600881901c63ffffffff16610fe984848861224c565b836020015163ffffffff168163ffffffff16111561104157601480547fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff166c0100000000000000000000000063ffffffff8416021790555b5050505050505050505050505050565b60008060008580602001905181019061106a9190615495565b925092509250611080898989868989888861032b565b505050505050505050565b61109361109f565b61109c81612e5c565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314611120576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610c8c565b565b60005b6024548110156111e0576022600060248381548110611146576111466151e8565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001812080547fffffffff00000000000000000000000000000000000000000000000000000000168155600181019190915560020180547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000169055806111d881615217565b915050611125565b506111ed602460006145f2565b60255460ff1660005b8351811015611754576000848281518110611213576112136151e8565b602002602001015190506000848381518110611231576112316151e8565b602002602001015190508173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611286573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112aa9190615640565b60ff16816060015160ff161415806113385750806040015173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561130c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113309190615640565b60ff16600814155b1561136f576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161480156113db575060018460018111156113d9576113d961565d565b145b15611412576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216158061144d5750604081015173ffffffffffffffffffffffffffffffffffffffff16155b15611484576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff828116600090815260226020526040902054670100000000000000900416156114ee576040517f357d0cc400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6024805460018181019092557f7cd332d19b93bcabe3cce7ca0c18a052f57e5fd03b4758a09f30f5ddc4b22ec401805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216821790925560008181526022602090815260409182902086518154928801518489015160608a015160ff167b01000000000000000000000000000000000000000000000000000000027fffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffff9190981667010000000000000002167fffffffff000000000000000000000000000000000000000000ffffffffffffff62ffffff909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000090951663ffffffff9093169290921793909317929092169190911793909317835560808501519383019390935560a0840151600290920180546bffffffffffffffffffffffff9093167fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009093169290921790915590517fca93cbe727c73163ec538f71be6c0a64877d7f1f6dd35d5ca7cbaef3a3e34ba390611737908490600060c08201905063ffffffff835116825262ffffff602084015116602083015273ffffffffffffffffffffffffffffffffffffffff604084015116604083015260ff6060840151166060830152608083015160808301526bffffffffffffffffffffffff60a08401511660a083015292915050565b60405180910390a25050808061174c90615217565b9150506111f6565b50505050565b600e546014546bffffffffffffffffffffffff1660005b600e548110156117cd576117ba600e8281548110611791576117916151e8565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff168385612f51565b50806117c581615217565b915050611771565b5060255460009060ff16815b600e5481101561193e57600e81815481106117f6576117f66151e8565b6000918252602082200154600d805473ffffffffffffffffffffffffffffffffffffffff9092169550600c929184908110611833576118336151e8565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff9081168452838201949094526040928301822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690559286168152600b909252902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905560018260018111156118d5576118d561565d565b14801561191a575073ffffffffffffffffffffffffffffffffffffffff83166000908152600b60205260409020546201000090046bffffffffffffffffffffffff1615155b1561192c5761192a600f84611f08565b505b8061193681615217565b9150506117d9565b5061194b600d60006145f2565b611957600e60006145f2565b6040805160808101825260008082526020820181905291810182905260608101829052905b8751811015611de757600c600089838151811061199b5761199b6151e8565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528101919091526040016000205460ff1615611a06576040517f77cea0fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16888281518110611a3057611a306151e8565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603611a85576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052806001151581526020018260ff16815250600c60008a8481518110611ab657611ab66151e8565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528181019290925260400160002082518154939092015160ff16610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909316929092171790558651879082908110611b5e57611b5e6151e8565b60200260200101519350600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611bce576040517f58a70a0a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff84166000908152600b60209081526040918290208251608081018452905460ff80821615801584526101008304909116938301939093526bffffffffffffffffffffffff6201000082048116948301949094526e01000000000000000000000000000090049092166060830152909250611c89576040517f6a7281ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180835260ff80831660208086019182526014546bffffffffffffffffffffffff9081166060880190815273ffffffffffffffffffffffffffffffffffffffff8a166000908152600b909352604092839020885181549551948a0151925184166e010000000000000000000000000000027fffffffffffff000000000000000000000000ffffffffffffffffffffffffffff939094166201000002929092167fffffffffffff000000000000000000000000000000000000000000000000ffff94909616610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090951694909417179190911692909217919091179055836001811115611dc357611dc361565d565b03611dd557611dd3600f85611ee6565b505b80611ddf81615217565b91505061197c565b508651611dfb90600d9060208a0190614610565b508551611e0f90600e906020890190614610565b5050505050505050565b6000808a8a8a8a8a8a8a8a8a604051602001611e3d9998979695949392919061568c565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179b9a5050505050505050505050565b6000611ecd825490565b92915050565b6000611edf8383613159565b9392505050565b6000611edf8373ffffffffffffffffffffffffffffffffffffffff8416613183565b6000611edf8373ffffffffffffffffffffffffffffffffffffffff841661327d565b60008787604051611f3c929190615721565b604051908190038120611f53918b90602001615731565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201208383019092526000808452908301819052909250906000805b8881101561212a57600185878360208110611fbf57611fbf6151e8565b611fcc91901a601b61530f565b8c8c85818110611fde57611fde6151e8565b905060200201358b8b86818110611ff757611ff76151e8565b9050602002013560405160008152602001604052604051612034949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612056573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff81166000908152600c602090815290849020838501909452925460ff8082161515808552610100909204169383019390935290955093509050612104576040517f0f4c073700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826020015160080260ff166001901b84019350808061212290615217565b915050611fa2565b50827e01010101010101010101010101010101010101010101010101010101010101841614612185576040517fc103be2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050505050505050565b6121cc6040518060c001604052806000815260200160008152602001606081526020016060815260200160608152602001606081525090565b60006121da83850185615822565b60408101515160608201515191925090811415806121fd57508082608001515114155b8061220d5750808260a001515114155b15612244576040517fb55ac75400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b509392505050565b600082604001515167ffffffffffffffff81111561226c5761226c6146a7565b60405190808252806020026020018201604052801561233857816020015b6040805161020081018252600060e08201818152610100830182905261012083018290526101408301829052610160830182905261018083018290526101a083018290526101c083018290526101e0830182905282526020808301829052928201819052606082018190526080820181905260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161228a5790505b50905060006040518060800160405280600061ffff16815260200160006bffffffffffffffffffffffff16815260200160006bffffffffffffffffffffffff16815260200160008152509050600085610100015173ffffffffffffffffffffffffffffffffffffffff166357e871e76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123fa9190614f93565b6101008701516040517f7810d12a00000000000000000000000000000000000000000000000000000000815236600482015291925060009173ffffffffffffffffffffffffffffffffffffffff90911690637810d12a90602401602060405180830381865afa158015612471573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124959190614f93565b905060005b8660400151518110156129255760046000886040015183815181106124c1576124c16151e8565b6020908102919091018101518252818101929092526040908101600020815161012081018352815460ff8082161515835261010080830490911615159583019590955263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490931660e08201526002909101549091169181019190915285518690839081106125e4576125e46151e8565b6020026020010151600001819052506126198760400151828151811061260c5761260c6151e8565b60200260200101516132cc565b85828151811061262b5761262b6151e8565b60200260200101516060019060018111156126485761264861565d565b9081600181111561265b5761265b61565d565b815250506126bf87604001518281518110612678576126786151e8565b60200260200101518489608001518481518110612697576126976151e8565b60200260200101518885815181106126b1576126b16151e8565b60200260200101518c613377565b8683815181106126d1576126d16151e8565b60200260200101516020018784815181106126ee576126ee6151e8565b602002602001015160c0018281525082151515158152505050848181518110612719576127196151e8565b602002602001015160200151156127495760018460000181815161273d919061590f565b61ffff1690525061274e565b612913565b6127b4858281518110612763576127636151e8565b6020026020010151600001516080015188606001518381518110612789576127896151e8565b60200260200101518960a0015184815181106127a7576127a76151e8565b6020026020010151613496565b8683815181106127c6576127c66151e8565b60200260200101516040018784815181106127e3576127e36151e8565b602002602001015160800182815250821515151581525050508760800151600161280d919061530f565b61281b9060ff1660406152e5565b6103a48860a001518381518110612834576128346151e8565b60200260200101515161284791906152fc565b61285191906152fc565b858281518110612863576128636151e8565b602002602001015160a0018181525050848181518110612885576128856151e8565b602002602001015160a00151846060018181516128a291906152fc565b90525084518590829081106128b9576128b96151e8565b602002602001015160800151866128d091906151a0565b9550612913876040015182815181106128eb576128eb6151e8565b602002602001015184878481518110612906576129066151e8565b60200260200101516136b1565b8061291d81615217565b91505061249a565b50825161ffff1660000361293c5750505050505050565b61c80061294a3660106152e5565b5a61295590886151a0565b61295f91906152fc565b61296991906152fc565b8351909550613778906129809061ffff1687615959565b61298a91906152fc565b60408051608081018252600080825260208201819052918101829052606081018290529196506129b9896137b6565b905060005b886040015151811015612cf5578681815181106129dd576129dd6151e8565b60200260200101516020015115612ce357801580612a75575086612a026001836151a0565b81518110612a1257612a126151e8565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff16878281518110612a4b57612a4b6151e8565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff1614155b15612aa957612aa68a888381518110612a9057612a906151e8565b60200260200101516000015161010001516138a0565b92505b6000612bc78b6040518061012001604052808b8681518110612acd57612acd6151e8565b60200260200101516080015181526020018c81526020018a606001518c8781518110612afb57612afb6151e8565b602002602001015160a001518a612b1291906152e5565b612b1c9190615959565b81526020018d6000015181526020018d6020015181526020018681526020018b8681518110612b4d57612b4d6151e8565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff168152602001878152602001600115158152508c604001518581518110612b9c57612b9c6151e8565b60200260200101518b8681518110612bb657612bb66151e8565b602002602001015160000151613a1c565b9050806060015187604001818151612bdf919061596d565b6bffffffffffffffffffffffff169052506040810151602088018051612c0690839061596d565b6bffffffffffffffffffffffff169052508751889083908110612c2b57612c2b6151e8565b60200260200101516040015115158a604001518381518110612c4f57612c4f6151e8565b60200260200101517fad8cc9579b21dfe2c2f6ea35ba15b656e46b4f5b0cb424f52739b8ce5cac9c5b83602001518460000151612c8c919061596d565b8b8681518110612c9e57612c9e6151e8565b6020026020010151608001518d8f608001518881518110612cc157612cc16151e8565b6020026020010151604051612cd99493929190615992565b60405180910390a3505b80612ced81615217565b9150506129be565b505050602083810151336000908152600b90925260409091208054600290612d329084906201000090046bffffffffffffffffffffffff1661596d565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508260400151601460000160008282829054906101000a90046bffffffffffffffffffffffff16612d90919061596d565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff16021790555082604001518360200151612dd2919061596d565b6bffffffffffffffffffffffff16602160007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254612e4e91906152fc565b909155505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603612edb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610c8c565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600b602090815260408083208151608081018352905460ff80821615801584526101008304909116948301949094526bffffffffffffffffffffffff6201000082048116938301939093526e010000000000000000000000000000900490911660608201529061314d576000816060015185612fe991906159cf565b90506000612ff785836159f4565b9050808360400181815161300b919061596d565b6bffffffffffffffffffffffff169052506130268582615a1f565b83606001818151613037919061596d565b6bffffffffffffffffffffffff90811690915273ffffffffffffffffffffffffffffffffffffffff89166000908152600b602090815260409182902087518154928901519389015160608a015186166e010000000000000000000000000000027fffffffffffff000000000000000000000000ffffffffffffffffffffffffffff919096166201000002167fffffffffffff000000000000000000000000000000000000000000000000ffff60ff95909516610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909416939093171792909216179190911790555050505b60400151949350505050565b6000826000018281548110613170576131706151e8565b9060005260206000200154905092915050565b6000818152600183016020526040812054801561326c5760006131a76001836151a0565b85549091506000906131bb906001906151a0565b90508181146132205760008660000182815481106131db576131db6151e8565b90600052602060002001549050808760000184815481106131fe576131fe6151e8565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061323157613231615a4f565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050611ecd565b6000915050611ecd565b5092915050565b60008181526001830160205260408120546132c457508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611ecd565b506000611ecd565b6000818160045b600f811015613359577fff000000000000000000000000000000000000000000000000000000000000008216838260208110613311576133116151e8565b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461334757506000949350505050565b8061335181615217565b9150506132d3565b5081600f1a600181111561336f5761336f61565d565b949350505050565b6000808080856060015160018111156133925761339261565d565b036133b8576133a48888888888613e8b565b6133b35760009250905061348c565b613430565b6001856060015160018111156133d0576133d061565d565b036133fe5760006133e389898988614015565b92509050806133f8575060009250905061348c565b50613430565b6040517ff2b2d41200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516060015163ffffffff16871061348557877fc3237c8807c467c1b39b8d0395eff077313e691bf0a7388106792564ebfd5636876040516134729190614d1a565b60405180910390a260009250905061348c565b6001925090505b9550959350505050565b601454600090819077010000000000000000000000000000000000000000000000900460ff16156134f3576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16770100000000000000000000000000000000000000000000001790556040517f4585e33b0000000000000000000000000000000000000000000000000000000090613568908590602401614d1a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290517f79188d1600000000000000000000000000000000000000000000000000000000815290935073ffffffffffffffffffffffffffffffffffffffff8616906379188d169061363b9087908790600401615a7e565b60408051808303816000875af1158015613659573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061367d9190615a97565b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16905590969095509350505050565b6000816060015160018111156136c9576136c961565d565b0361372d57600083815260046020526040902060010180547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167c010000000000000000000000000000000000000000000000000000000063ffffffff851602179055505050565b6001816060015160018111156137455761374561565d565b036137b15760c08101805160009081526008602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055915191517fa4a4e334c0e330143f9437484fe516c13bc560b86b5b0daf58e7084aaac228f29190a25b505050565b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613826573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061384a9190615adf565b5093505092505060008213158061386057508042105b8061389057506000846040015162ffffff16118015613890575061388481426151a0565b846040015162ffffff16105b15613276575050601b5492915050565b60408051608081018252600080825260208083018281528385018381526060850184905273ffffffffffffffffffffffffffffffffffffffff878116855260229093528584208054640100000000810462ffffff1690925263ffffffff82169092527b01000000000000000000000000000000000000000000000000000000810460ff16855285517ffeaf968c00000000000000000000000000000000000000000000000000000000815295519495919484936701000000000000009092049091169163feaf968c9160048083019260a09291908290030181865afa15801561398d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139b19190615adf565b509350509250506000821315806139c757508042105b806139f757506000866040015162ffffff161180156139f757506139eb81426151a0565b866040015162ffffff16105b15613a0b5760018301546060850152613a13565b606084018290525b50505092915050565b604080516101008101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e08201529082015115613ab25760008381526023602090815260409182902082518084018452905463ffffffff811680835262ffffff640100000000909204821692840192835260e089018051909401529051915191169101525b6000613abe8686614222565b60c0840151602082015182519293509091600091613adb9161596d565b60e08801515190915060ff16600060128210613af8576001613b0e565b613b038260126151a0565b613b0e90600a615c4f565b9050600060128311613b21576001613b37565b613b2c6012846151a0565b613b3790600a615c4f565b905085600001516bffffffffffffffffffffffff16856bffffffffffffffffffffffff161015613bdf57849350613bb3818b60800151613b7791906152e5565b838c60e0015160600151886bffffffffffffffffffffffff16613b9a91906152e5565b613ba491906152e5565b613bae9190615959565b614550565b6bffffffffffffffffffffffff9081166040880152600060608801819052602088015285168652613d05565b836bffffffffffffffffffffffff16856bffffffffffffffffffffffff161015613d0557849350613c6d86604001516bffffffffffffffffffffffff16828c60800151613c2c91906152e5565b848d60e0015160600151896bffffffffffffffffffffffff16613c4f91906152e5565b613c5991906152e5565b613c639190615959565b613bae91906151a0565b6bffffffffffffffffffffffff1660608088019190915260e08b01510151613cf190613c9a9084906152e5565b6001848d60e0015160600151613cb091906152e5565b613cba91906151a0565b838d608001518a606001516bffffffffffffffffffffffff16613cdd91906152e5565b613ce791906152e5565b613ba491906152fc565b6bffffffffffffffffffffffff1660208701525b60008981526004602052604090206001018054859190601090613d4b90849070010000000000000000000000000000000090046bffffffffffffffffffffffff166159cf565b82546101009290920a6bffffffffffffffffffffffff81810219909316918316021790915560008b81526004602052604081206001018054928816935091613da69084906fffffffffffffffffffffffffffffffff16615c5b565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550836bffffffffffffffffffffffff16602160008c60c0015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254613e3d91906151a0565b92505081905550887f801ba6ed51146ffe3e99d1dbd9dd0f4de6292e78a9a34c39c0183de17b3f40fc87604051613e749190615c84565b60405180910390a250939998505050505050505050565b60008084806020019051810190613ea29190615d44565b845160e00151815191925063ffffffff90811691161015613eff57867f405288ea7be309e16cfdf481367f90a413e1d4634fcdaf8966546db9b93012e886604051613eed9190614d1a565b60405180910390a2600091505061400c565b8260e001518015613fbf5750602081015115801590613fbf5750602081015161010084015182516040517f85df51fd00000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff909116906385df51fd90602401602060405180830381865afa158015613f98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fbc9190614f93565b14155b80613fd15750805163ffffffff168611155b1561400657867f6aa7f60c176da7af894b384daea2249497448137f5943c1237ada8bc92bdc30186604051613eed9190614d1a565b60019150505b95945050505050565b60008060008480602001905181019061402e9190615d9c565b905060008782600001518360200151846040015160405160200161409094939291909384526020840192909252604083015260e01b7fffffffff0000000000000000000000000000000000000000000000000000000016606082015260640190565b6040516020818303038152906040528051906020012090508460e00151801561416b575060808201511580159061416b5750608082015161010086015160608401516040517f85df51fd00000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff909116906385df51fd90602401602060405180830381865afa158015614144573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141689190614f93565b14155b80614180575086826060015163ffffffff1610155b156141ca57877f6aa7f60c176da7af894b384daea2249497448137f5943c1237ada8bc92bdc301876040516141b59190614d1a565b60405180910390a26000935091506142199050565b60008181526008602052604090205460ff161561421157877f405288ea7be309e16cfdf481367f90a413e1d4634fcdaf8966546db9b93012e8876040516141b59190614d1a565b600193509150505b94509492505050565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915260008260e001516000015160ff1690506000846060015161ffff16846060015161428d91906152e5565b905083610100015180156142a05750803a105b156142a857503a5b6000601283116142b95760016142cf565b6142c46012846151a0565b6142cf90600a615c4f565b90506000601284106142e25760016142f8565b6142ed8460126151a0565b6142f890600a615c4f565b905060008660a0015187604001518860200151896000015161431a91906152fc565b61432490876152e5565b61432e91906152fc565b61433891906152e5565b905061437b828860e001516060015161435191906152e5565b6001848a60e001516060015161436791906152e5565b61437191906151a0565b613ce786856152e5565b6bffffffffffffffffffffffff168652608087015161439e90613bae9083615959565b6bffffffffffffffffffffffff1660408088019190915260e088015101516000906143d79062ffffff16683635c9adc5dea000006152e5565b9050600081633b9aca008a60a001518b60e001516020015163ffffffff168c604001518d600001518b61440a91906152e5565b61441491906152fc565b61441e91906152e5565b61442891906152e5565b6144329190615959565b61443c91906152fc565b905061447f848a60e001516060015161445591906152e5565b6001868c60e001516060015161446b91906152e5565b61447591906151a0565b613ce788856152e5565b6bffffffffffffffffffffffff16602089015260808901516144a590613bae9083615959565b6bffffffffffffffffffffffff16606089015260c089015173ffffffffffffffffffffffffffffffffffffffff166080808a01919091528901516144e890614550565b6bffffffffffffffffffffffff1660a0808a019190915289015161450b90614550565b6bffffffffffffffffffffffff1660c089015260e08901516060015161453090614550565b6bffffffffffffffffffffffff1660e08901525050505050505092915050565b60006bffffffffffffffffffffffff8211156145ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610c8c565b5090565b508054600082559060005260206000209081019061109c9190614692565b82805482825590600052602060002090810192821561468a579160200282015b8281111561468a57825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190614630565b506145ee9291505b5b808211156145ee5760008155600101614693565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610200810167ffffffffffffffff811182821017156146fa576146fa6146a7565b60405290565b60405160c0810167ffffffffffffffff811182821017156146fa576146fa6146a7565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561476a5761476a6146a7565b604052919050565b600067ffffffffffffffff82111561478c5761478c6146a7565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff8116811461109c57600080fd5b80356147c381614796565b919050565b600082601f8301126147d957600080fd5b813560206147ee6147e983614772565b614723565b82815260059290921b8401810191818101908684111561480d57600080fd5b8286015b8481101561483157803561482481614796565b8352918301918301614811565b509695505050505050565b60ff8116811461109c57600080fd5b80356147c38161483c565b63ffffffff8116811461109c57600080fd5b80356147c381614856565b801515811461109c57600080fd5b80356147c381614873565b62ffffff8116811461109c57600080fd5b80356147c38161488c565b61ffff8116811461109c57600080fd5b80356147c3816148a8565b600061020082840312156148d657600080fd5b6148de6146d6565b90506148e982614868565b81526148f760208301614868565b602082015261490860408301614868565b6040820152614919606083016147b8565b606082015261492a60808301614881565b608082015261493b60a0830161489d565b60a082015261494c60c08301614868565b60c082015261495d60e08301614868565b60e08201526101006149708184016147b8565b908201526101206149828382016148b8565b908201526101406149948382016147b8565b90820152610160828101359082015261018080830135908201526101a080830135908201526101c08083013567ffffffffffffffff8111156149d557600080fd5b6149e1858286016147c8565b8284015250506101e06149f58184016147b8565b9082015292915050565b803567ffffffffffffffff811681146147c357600080fd5b600082601f830112614a2857600080fd5b813567ffffffffffffffff811115614a4257614a426146a7565b614a7360207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614723565b818152846020838601011115614a8857600080fd5b816020850160208301376000918101602001919091529392505050565b6bffffffffffffffffffffffff8116811461109c57600080fd5b600082601f830112614ad057600080fd5b81356020614ae06147e983614772565b82815260c09283028501820192828201919087851115614aff57600080fd5b8387015b85811015614b915781818a031215614b1b5760008081fd5b614b23614700565b8135614b2e81614856565b815281860135614b3d8161488c565b81870152604082810135614b5081614796565b90820152606082810135614b638161483c565b908201526080828101359082015260a080830135614b8081614aa5565b908201528452928401928101614b03565b5090979650505050505050565b600080600080600080600080610100898b031215614bbb57600080fd5b883567ffffffffffffffff80821115614bd357600080fd5b614bdf8c838d016147c8565b995060208b0135915080821115614bf557600080fd5b614c018c838d016147c8565b9850614c0f60408c0161484b565b975060608b0135915080821115614c2557600080fd5b614c318c838d016148c3565b9650614c3f60808c016149ff565b955060a08b0135915080821115614c5557600080fd5b614c618c838d01614a17565b945060c08b0135915080821115614c7757600080fd5b614c838c838d016147c8565b935060e08b0135915080821115614c9957600080fd5b50614ca68b828c01614abf565b9150509295985092959890939650565b6000815180845260005b81811015614cdc57602081850181015186830182015201614cc0565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611edf6020830184614cb6565b60008083601f840112614d3f57600080fd5b50813567ffffffffffffffff811115614d5757600080fd5b6020830191508360208260051b8501011115614d7257600080fd5b9250929050565b60008060008060008060008060e0898b031215614d9557600080fd5b606089018a811115614da657600080fd5b8998503567ffffffffffffffff80821115614dc057600080fd5b818b0191508b601f830112614dd457600080fd5b813581811115614de357600080fd5b8c6020828501011115614df557600080fd5b6020830199508098505060808b0135915080821115614e1357600080fd5b614e1f8c838d01614d2d565b909750955060a08b0135915080821115614e3857600080fd5b50614e458b828c01614d2d565b999c989b50969995989497949560c00135949350505050565b60008060008060008060c08789031215614e7757600080fd5b863567ffffffffffffffff80821115614e8f57600080fd5b614e9b8a838b016147c8565b97506020890135915080821115614eb157600080fd5b614ebd8a838b016147c8565b9650614ecb60408a0161484b565b95506060890135915080821115614ee157600080fd5b614eed8a838b01614a17565b9450614efb60808a016149ff565b935060a0890135915080821115614f1157600080fd5b50614f1e89828a01614a17565b9150509295509295509295565b600060208284031215614f3d57600080fd5b8135611edf81614796565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff818116838216029081169081811461327657613276614f48565b600060208284031215614fa557600080fd5b5051919050565b63ffffffff81811683821601908082111561327657613276614f48565b600081518084526020808501945080840160005b8381101561500f57815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101614fdd565b509495945050505050565b6020815261503160208201835163ffffffff169052565b6000602083015161504a604084018263ffffffff169052565b50604083015163ffffffff8116606084015250606083015173ffffffffffffffffffffffffffffffffffffffff8116608084015250608083015180151560a08401525060a083015162ffffff811660c08401525060c083015163ffffffff811660e08401525060e08301516101006150c98185018363ffffffff169052565b84015190506101206150f28482018373ffffffffffffffffffffffffffffffffffffffff169052565b84015190506101406151098482018361ffff169052565b84015190506101606151328482018373ffffffffffffffffffffffffffffffffffffffff169052565b840151610180848101919091528401516101a0808501919091528401516101c0808501919091528401516102006101e08086018290529192509061517a610220860184614fc9565b95015173ffffffffffffffffffffffffffffffffffffffff169301929092525090919050565b81810381811115611ecd57611ecd614f48565b6000816151c2576151c2614f48565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361524857615248614f48565b5060010190565b600061012063ffffffff808d1684528b6020850152808b1660408501525080606084015261527f8184018a614fc9565b905082810360808401526152938189614fc9565b905060ff871660a084015282810360c08401526152b08187614cb6565b905067ffffffffffffffff851660e08401528281036101008401526152d58185614cb6565b9c9b505050505050505050505050565b8082028115828204841417611ecd57611ecd614f48565b80820180821115611ecd57611ecd614f48565b60ff8181168382160190811115611ecd57611ecd614f48565b80516147c381614856565b80516147c381614796565b80516147c381614873565b80516147c38161488c565b80516147c3816148a8565b600082601f83011261537057600080fd5b815160206153806147e983614772565b82815260059290921b8401810191818101908684111561539f57600080fd5b8286015b848110156148315780516153b681614796565b83529183019183016153a3565b600082601f8301126153d457600080fd5b815160206153e46147e983614772565b82815260c0928302850182019282820191908785111561540357600080fd5b8387015b85811015614b915781818a03121561541f5760008081fd5b615427614700565b815161543281614856565b8152818601516154418161488c565b8187015260408281015161545481614796565b908201526060828101516154678161483c565b908201526080828101519082015260a08083015161548481614aa5565b908201528452928401928101615407565b6000806000606084860312156154aa57600080fd5b835167ffffffffffffffff808211156154c257600080fd5b9085019061020082880312156154d757600080fd5b6154df6146d6565b6154e883615328565b81526154f660208401615328565b602082015261550760408401615328565b604082015261551860608401615333565b60608201526155296080840161533e565b608082015261553a60a08401615349565b60a082015261554b60c08401615328565b60c082015261555c60e08401615328565b60e082015261010061556f818501615333565b90820152610120615581848201615354565b90820152610140615593848201615333565b90820152610160838101519082015261018080840151908201526101a080840151908201526101c080840151838111156155cc57600080fd5b6155d88a82870161535f565b8284015250506101e06155ec818501615333565b90820152602087015190955091508082111561560757600080fd5b6156138783880161535f565b9350604086015191508082111561562957600080fd5b50615636868287016153c3565b9150509250925092565b60006020828403121561565257600080fd5b8151611edf8161483c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b1660408501528160608501526156d38285018b614fc9565b915083820360808501526156e7828a614fc9565b915060ff881660a085015283820360c08501526157048288614cb6565b90861660e085015283810361010085015290506152d58185614cb6565b8183823760009101908152919050565b8281526080810160608360208401379392505050565b600082601f83011261575857600080fd5b813560206157686147e983614772565b82815260059290921b8401810191818101908684111561578757600080fd5b8286015b84811015614831578035835291830191830161578b565b600082601f8301126157b357600080fd5b813560206157c36147e983614772565b82815260059290921b840181019181810190868411156157e257600080fd5b8286015b8481101561483157803567ffffffffffffffff8111156158065760008081fd5b6158148986838b0101614a17565b8452509183019183016157e6565b60006020828403121561583457600080fd5b813567ffffffffffffffff8082111561584c57600080fd5b9083019060c0828603121561586057600080fd5b615868614700565b823581526020830135602082015260408301358281111561588857600080fd5b61589487828601615747565b6040830152506060830135828111156158ac57600080fd5b6158b887828601615747565b6060830152506080830135828111156158d057600080fd5b6158dc878286016157a2565b60808301525060a0830135828111156158f457600080fd5b615900878286016157a2565b60a08301525095945050505050565b61ffff81811683821601908082111561327657613276614f48565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826159685761596861592a565b500490565b6bffffffffffffffffffffffff81811683821601908082111561327657613276614f48565b6bffffffffffffffffffffffff851681528360208201528260408201526080606082015260006159c56080830184614cb6565b9695505050505050565b6bffffffffffffffffffffffff82811682821603908082111561327657613276614f48565b60006bffffffffffffffffffffffff80841680615a1357615a1361592a565b92169190910492915050565b6bffffffffffffffffffffffff818116838216028082169190828114615a4757615a47614f48565b505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b82815260406020820152600061336f6040830184614cb6565b60008060408385031215615aaa57600080fd5b8251615ab581614873565b6020939093015192949293505050565b805169ffffffffffffffffffff811681146147c357600080fd5b600080600080600060a08688031215615af757600080fd5b615b0086615ac5565b9450602086015193506040860151925060608601519150615b2360808701615ac5565b90509295509295909350565b600181815b80851115615b8857817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615b6e57615b6e614f48565b80851615615b7b57918102915b93841c9390800290615b34565b509250929050565b600082615b9f57506001611ecd565b81615bac57506000611ecd565b8160018114615bc25760028114615bcc57615be8565b6001915050611ecd565b60ff841115615bdd57615bdd614f48565b50506001821b611ecd565b5060208310610133831016604e8410600b8410161715615c0b575081810a611ecd565b615c158383615b2f565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615c4757615c47614f48565b029392505050565b6000611edf8383615b90565b6fffffffffffffffffffffffffffffffff81811683821601908082111561327657613276614f48565b6000610100820190506bffffffffffffffffffffffff8084511683528060208501511660208401528060408501511660408401528060608501511660608401525073ffffffffffffffffffffffffffffffffffffffff608084015116608083015260a0830151615d0460a08401826bffffffffffffffffffffffff169052565b5060c0830151615d2460c08401826bffffffffffffffffffffffff169052565b5060e083015161327660e08401826bffffffffffffffffffffffff169052565b600060408284031215615d5657600080fd5b6040516040810181811067ffffffffffffffff82111715615d7957615d796146a7565b6040528251615d8781614856565b81526020928301519281019290925250919050565b600060a08284031215615dae57600080fd5b60405160a0810181811067ffffffffffffffff82111715615dd157615dd16146a7565b806040525082518152602083015160208201526040830151615df281614856565b60408201526060830151615e0581614856565b6060820152608092830151928101929092525091905056fea164736f6c6343000813000a", + Bin: "0x6101806040523480156200001257600080fd5b50604051620064b5380380620064b583398101604081905262000035916200062f565b80816001600160a01b031663ca30e6036040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b91906200062f565b826001600160a01b031663226cf83c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062f565b836001600160a01b031663614486af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016591906200062f565b846001600160a01b0316636709d0e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ca91906200062f565b856001600160a01b0316635425d8ac6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f91906200062f565b866001600160a01b031663a08714c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029491906200062f565b876001600160a01b031663c5b964e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f9919062000656565b886001600160a01b031663ac4dc59a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000338573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035e91906200062f565b3380600081620003b55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620003e857620003e8816200056b565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff19166001838181111562000439576200043962000679565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200049a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c091906200068f565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000504573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200052a91906200068f565b60ff16146200054c576040516301f86e1760e41b815260040160405180910390fd5b5050506001600160a01b039095166101605250620006b4945050505050565b336001600160a01b03821603620005c55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620003ac565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200062c57600080fd5b50565b6000602082840312156200064257600080fd5b81516200064f8162000616565b9392505050565b6000602082840312156200066957600080fd5b8151600281106200064f57600080fd5b634e487b7160e01b600052602160045260246000fd5b600060208284031215620006a257600080fd5b815160ff811681146200064f57600080fd5b60805160a05160c05160e05161010051610120516101405161016051615d9d620007186000396000818160b301526101860152600050506000505060005050600050506000613730015260005050600081816113710152612d590152615d9d6000f3fe6080604052600436106100b15760003560e01c80638da5cb5b11610069578063b1dc65a41161004e578063b1dc65a4146102cb578063e3d0e712146102eb578063f2fde38b1461030b576100b1565b80638da5cb5b1461025a578063afcb95d714610285576100b1565b8063349e8cca1161009a578063349e8cca1461017757806379ba5097146101cb57806381ff7048146101e0576100b1565b80630870d3a1146100f8578063181f5a7714610118575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e8080156100f1573d6000f35b3d6000fd5b005b34801561010457600080fd5b506100f6610113366004614b11565b61032b565b34801561012457600080fd5b506101616040518060400160405280601881526020017f4175746f6d6174696f6e526567697374727920322e332e30000000000000000081525081565b60405161016e9190614c8d565b60405180910390f35b34801561018357600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161016e565b3480156101d757600080fd5b506100f6610c0f565b3480156101ec57600080fd5b5061023760175460135463ffffffff74010000000000000000000000000000000000000000830481169378010000000000000000000000000000000000000000000000009093041691565b6040805163ffffffff94851681529390921660208401529082015260600161016e565b34801561026657600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101a6565b34801561029157600080fd5b50601354601454604080516000815260208101939093526c0100000000000000000000000090910463ffffffff169082015260600161016e565b3480156102d757600080fd5b506100f66102e6366004614cec565b610d11565b3480156102f757600080fd5b506100f6610306366004614dd1565b611051565b34801561031757600080fd5b506100f6610326366004614e9e565b61108b565b61033361109f565b601f8851111561036f576040517f25d0209c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8560ff166000036103ac576040517fe77dba5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b865188511415806103cb57506103c3866003614eea565b60ff16885111155b15610402576040517f1d2d1c5800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805182511461043d576040517fcf54c06a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104478282611122565b610451888861175a565b604051806101200160405280601460000160009054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff168152602001600063ffffffff1681526020018660a0015162ffffff16815260200186610120015161ffff1681526020018760ff168152602001601460000160169054906101000a900460ff1615158152602001601460000160179054906101000a900460ff1615158152602001866080015115158152602001866101e0015173ffffffffffffffffffffffffffffffffffffffff16815250601460008201518160000160006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550602082015181600001600c6101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160106101000a81548162ffffff021916908362ffffff16021790555060608201518160000160136101000a81548161ffff021916908361ffff16021790555060808201518160000160156101000a81548160ff021916908360ff16021790555060a08201518160000160166101000a81548160ff02191690831515021790555060c08201518160000160176101000a81548160ff02191690831515021790555060e08201518160000160186101000a81548160ff0219169083151502179055506101008201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050506000601660010160189054906101000a900463ffffffff1690506000866101e0015173ffffffffffffffffffffffffffffffffffffffff166357e871e76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610701573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107259190614f06565b6017549091506000906107579074010000000000000000000000000000000000000000900463ffffffff166001614f1f565b9050604051806101600160405280896060015173ffffffffffffffffffffffffffffffffffffffff168152602001896000015163ffffffff168152602001896020015163ffffffff1681526020016016600001601c9054906101000a900463ffffffff1663ffffffff16815260200189610100015173ffffffffffffffffffffffffffffffffffffffff1681526020018263ffffffff1681526020018363ffffffff168152602001896040015163ffffffff16815260200189610140015173ffffffffffffffffffffffffffffffffffffffff1681526020018960c0015163ffffffff1681526020018960e0015163ffffffff16815250601660008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160186101000a81548163ffffffff021916908363ffffffff160217905550606082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a08201518160010160146101000a81548163ffffffff021916908363ffffffff16021790555060c08201518160010160186101000a81548163ffffffff021916908363ffffffff16021790555060e082015181600101601c6101000a81548163ffffffff021916908363ffffffff1602179055506101008201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101208201518160020160146101000a81548163ffffffff021916908363ffffffff1602179055506101408201518160020160186101000a81548163ffffffff021916908363ffffffff160217905550905050876101600151601981905550876101800151601a81905550876101a00151601b81905550600088604051602001610a9a9190614f8d565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152919052601754909150610aff904690309074010000000000000000000000000000000000000000900463ffffffff168f8f8f878f8f611e19565b6013556000610b0e6009611ec3565b90505b8015610b4b57610b38610b30610b28600184615113565b600990611ed3565b600990611ee6565b5080610b4381615126565b915050610b11565b5060005b896101c0015151811015610ba257610b8f8a6101c001518281518110610b7757610b7761515b565b60200260200101516009611f0890919063ffffffff16565b5080610b9a8161518a565b915050610b4f565b507f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0584601354601660010160149054906101000a900463ffffffff168f8f8f878f8f604051610bf9999897969594939291906151c2565b60405180910390a1505050505050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610c95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60005a90506000610d23866040615258565b610d2f8961014461526f565b610d39919061526f565b9050368114610d74576040517fdfe9309000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051610120810182526014546bffffffffffffffffffffffff8116825263ffffffff6c01000000000000000000000000820416602083015262ffffff7001000000000000000000000000000000008204169282019290925261ffff730100000000000000000000000000000000000000830416606082015260ff75010000000000000000000000000000000000000000008304811660808301527601000000000000000000000000000000000000000000008304811615801560a08401527701000000000000000000000000000000000000000000000084048216151560c0840152780100000000000000000000000000000000000000000000000090930416151560e082015260155473ffffffffffffffffffffffffffffffffffffffff1661010082015290610ed3576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600b602052604090205460ff16610f1c576040517f1099ed7500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6013548b3514610f58576040517fdfdcf8e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6080810151610f68906001615282565b60ff1687141580610f795750868514155b15610fb0576040517f0244f71a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610fc08b8b8b8b8b8b8b8b611f2a565b6000610fcc8b8b612193565b905060208c0135600881901c63ffffffff16610fe984848861224c565b836020015163ffffffff168163ffffffff16111561104157601480547fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff166c0100000000000000000000000063ffffffff8416021790555b5050505050505050505050505050565b60008060008580602001905181019061106a9190615408565b925092509250611080898989868989888861032b565b505050505050505050565b61109361109f565b61109c81612dcf565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314611120576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610c8c565b565b60005b6024548110156111e05760226000602483815481106111465761114661515b565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001812080547fffffffff00000000000000000000000000000000000000000000000000000000168155600181019190915560020180547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000169055806111d88161518a565b915050611125565b506111ed60246000614565565b60255460ff1660005b83518110156117545760008482815181106112135761121361515b565b6020026020010151905060008483815181106112315761123161515b565b602002602001015190508173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611286573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112aa91906155b3565b60ff16816060015160ff161415806113385750806040015173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561130c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061133091906155b3565b60ff16600814155b1561136f576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161480156113db575060018460018111156113d9576113d96155d0565b145b15611412576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216158061144d5750604081015173ffffffffffffffffffffffffffffffffffffffff16155b15611484576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff828116600090815260226020526040902054670100000000000000900416156114ee576040517f357d0cc400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6024805460018181019092557f7cd332d19b93bcabe3cce7ca0c18a052f57e5fd03b4758a09f30f5ddc4b22ec401805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216821790925560008181526022602090815260409182902086518154928801518489015160608a015160ff167b01000000000000000000000000000000000000000000000000000000027fffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffff9190981667010000000000000002167fffffffff000000000000000000000000000000000000000000ffffffffffffff62ffffff909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000090951663ffffffff9093169290921793909317929092169190911793909317835560808501519383019390935560a0840151600290920180546bffffffffffffffffffffffff9093167fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009093169290921790915590517fca93cbe727c73163ec538f71be6c0a64877d7f1f6dd35d5ca7cbaef3a3e34ba390611737908490600060c08201905063ffffffff835116825262ffffff602084015116602083015273ffffffffffffffffffffffffffffffffffffffff604084015116604083015260ff6060840151166060830152608083015160808301526bffffffffffffffffffffffff60a08401511660a083015292915050565b60405180910390a25050808061174c9061518a565b9150506111f6565b50505050565b600e546014546bffffffffffffffffffffffff1660005b600e548110156117cd576117ba600e82815481106117915761179161515b565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff168385612ec4565b50806117c58161518a565b915050611771565b5060255460009060ff16815b600e5481101561193e57600e81815481106117f6576117f661515b565b6000918252602082200154600d805473ffffffffffffffffffffffffffffffffffffffff9092169550600c9291849081106118335761183361515b565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff9081168452838201949094526040928301822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690559286168152600b909252902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905560018260018111156118d5576118d56155d0565b14801561191a575073ffffffffffffffffffffffffffffffffffffffff83166000908152600b60205260409020546201000090046bffffffffffffffffffffffff1615155b1561192c5761192a600f84611f08565b505b806119368161518a565b9150506117d9565b5061194b600d6000614565565b611957600e6000614565565b6040805160808101825260008082526020820181905291810182905260608101829052905b8751811015611de757600c600089838151811061199b5761199b61515b565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528101919091526040016000205460ff1615611a06576040517f77cea0fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16888281518110611a3057611a3061515b565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603611a85576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052806001151581526020018260ff16815250600c60008a8481518110611ab657611ab661515b565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528181019290925260400160002082518154939092015160ff16610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909316929092171790558651879082908110611b5e57611b5e61515b565b60200260200101519350600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611bce576040517f58a70a0a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff84166000908152600b60209081526040918290208251608081018452905460ff80821615801584526101008304909116938301939093526bffffffffffffffffffffffff6201000082048116948301949094526e01000000000000000000000000000090049092166060830152909250611c89576040517f6a7281ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180835260ff80831660208086019182526014546bffffffffffffffffffffffff9081166060880190815273ffffffffffffffffffffffffffffffffffffffff8a166000908152600b909352604092839020885181549551948a0151925184166e010000000000000000000000000000027fffffffffffff000000000000000000000000ffffffffffffffffffffffffffff939094166201000002929092167fffffffffffff000000000000000000000000000000000000000000000000ffff94909616610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090951694909417179190911692909217919091179055836001811115611dc357611dc36155d0565b03611dd557611dd3600f85611ee6565b505b80611ddf8161518a565b91505061197c565b508651611dfb90600d9060208a0190614583565b508551611e0f90600e906020890190614583565b5050505050505050565b6000808a8a8a8a8a8a8a8a8a604051602001611e3d999897969594939291906155ff565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179b9a5050505050505050505050565b6000611ecd825490565b92915050565b6000611edf83836130cc565b9392505050565b6000611edf8373ffffffffffffffffffffffffffffffffffffffff84166130f6565b6000611edf8373ffffffffffffffffffffffffffffffffffffffff84166131f0565b60008787604051611f3c929190615694565b604051908190038120611f53918b906020016156a4565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201208383019092526000808452908301819052909250906000805b8881101561212a57600185878360208110611fbf57611fbf61515b565b611fcc91901a601b615282565b8c8c85818110611fde57611fde61515b565b905060200201358b8b86818110611ff757611ff761515b565b9050602002013560405160008152602001604052604051612034949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612056573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff81166000908152600c602090815290849020838501909452925460ff8082161515808552610100909204169383019390935290955093509050612104576040517f0f4c073700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826020015160080260ff166001901b8401935080806121229061518a565b915050611fa2565b50827e01010101010101010101010101010101010101010101010101010101010101841614612185576040517fc103be2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050505050505050565b6121cc6040518060c001604052806000815260200160008152602001606081526020016060815260200160608152602001606081525090565b60006121da83850185615795565b60408101515160608201515191925090811415806121fd57508082608001515114155b8061220d5750808260a001515114155b15612244576040517fb55ac75400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b509392505050565b600082604001515167ffffffffffffffff81111561226c5761226c61461a565b60405190808252806020026020018201604052801561233857816020015b6040805161020081018252600060e08201818152610100830182905261012083018290526101408301829052610160830182905261018083018290526101a083018290526101c083018290526101e0830182905282526020808301829052928201819052606082018190526080820181905260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161228a5790505b50905060006040518060800160405280600061ffff16815260200160006bffffffffffffffffffffffff16815260200160006bffffffffffffffffffffffff16815260200160008152509050600085610100015173ffffffffffffffffffffffffffffffffffffffff166357e871e76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123fa9190614f06565b6101008701516040517f7810d12a00000000000000000000000000000000000000000000000000000000815236600482015291925060009173ffffffffffffffffffffffffffffffffffffffff90911690637810d12a90602401602060405180830381865afa158015612471573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124959190614f06565b905060005b8660400151518110156129255760046000886040015183815181106124c1576124c161515b565b6020908102919091018101518252818101929092526040908101600020815161012081018352815460ff8082161515835261010080830490911615159583019590955263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490931660e08201526002909101549091169181019190915285518690839081106125e4576125e461515b565b6020026020010151600001819052506126198760400151828151811061260c5761260c61515b565b602002602001015161323f565b85828151811061262b5761262b61515b565b6020026020010151606001906001811115612648576126486155d0565b9081600181111561265b5761265b6155d0565b815250506126bf876040015182815181106126785761267861515b565b602002602001015184896080015184815181106126975761269761515b565b60200260200101518885815181106126b1576126b161515b565b60200260200101518c6132ea565b8683815181106126d1576126d161515b565b60200260200101516020018784815181106126ee576126ee61515b565b602002602001015160c00182815250821515151581525050508481815181106127195761271961515b565b602002602001015160200151156127495760018460000181815161273d9190615882565b61ffff1690525061274e565b612913565b6127b48582815181106127635761276361515b565b60200260200101516000015160800151886060015183815181106127895761278961515b565b60200260200101518960a0015184815181106127a7576127a761515b565b6020026020010151613409565b8683815181106127c6576127c661515b565b60200260200101516040018784815181106127e3576127e361515b565b602002602001015160800182815250821515151581525050508760800151600161280d9190615282565b61281b9060ff166040615258565b6103a48860a0015183815181106128345761283461515b565b602002602001015151612847919061526f565b612851919061526f565b8582815181106128635761286361515b565b602002602001015160a00181815250508481815181106128855761288561515b565b602002602001015160a00151846060018181516128a2919061526f565b90525084518590829081106128b9576128b961515b565b602002602001015160800151866128d09190615113565b9550612913876040015182815181106128eb576128eb61515b565b6020026020010151848784815181106129065761290661515b565b6020026020010151613624565b8061291d8161518a565b91505061249a565b50825161ffff1660000361293c5750505050505050565b61c73861294a366010615258565b5a6129559088615113565b61295f919061526f565b612969919061526f565b8351909550613a34906129809061ffff16876158cc565b61298a919061526f565b60408051608081018252600080825260208201819052918101829052606081018290529196506129b989613729565b905060005b886040015151811015612c68578681815181106129dd576129dd61515b565b60200260200101516020015115612c5657612a1a8a888381518110612a0457612a0461515b565b6020026020010151600001516101000151613813565b92506000612b3a8b6040518061012001604052808b8681518110612a4057612a4061515b565b60200260200101516080015181526020018c81526020018a606001518c8781518110612a6e57612a6e61515b565b602002602001015160a001518a612a859190615258565b612a8f91906158cc565b81526020018d6000015181526020018d6020015181526020018681526020018b8681518110612ac057612ac061515b565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff168152602001878152602001600115158152508c604001518581518110612b0f57612b0f61515b565b60200260200101518b8681518110612b2957612b2961515b565b60200260200101516000015161398f565b9050806060015187604001818151612b5291906158e0565b6bffffffffffffffffffffffff169052506040810151602088018051612b799083906158e0565b6bffffffffffffffffffffffff169052508751889083908110612b9e57612b9e61515b565b60200260200101516040015115158a604001518381518110612bc257612bc261515b565b60200260200101517fad8cc9579b21dfe2c2f6ea35ba15b656e46b4f5b0cb424f52739b8ce5cac9c5b83602001518460000151612bff91906158e0565b8b8681518110612c1157612c1161515b565b6020026020010151608001518d8f608001518881518110612c3457612c3461515b565b6020026020010151604051612c4c9493929190615905565b60405180910390a3505b80612c608161518a565b9150506129be565b505050602083810151336000908152600b90925260409091208054600290612ca59084906201000090046bffffffffffffffffffffffff166158e0565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508260400151601460000160008282829054906101000a90046bffffffffffffffffffffffff16612d0391906158e0565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff16021790555082604001518360200151612d4591906158e0565b6bffffffffffffffffffffffff16602160007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254612dc1919061526f565b909155505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603612e4e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610c8c565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600b602090815260408083208151608081018352905460ff80821615801584526101008304909116948301949094526bffffffffffffffffffffffff6201000082048116938301939093526e01000000000000000000000000000090049091166060820152906130c0576000816060015185612f5c9190615942565b90506000612f6a8583615967565b90508083604001818151612f7e91906158e0565b6bffffffffffffffffffffffff16905250612f998582615992565b83606001818151612faa91906158e0565b6bffffffffffffffffffffffff90811690915273ffffffffffffffffffffffffffffffffffffffff89166000908152600b602090815260409182902087518154928901519389015160608a015186166e010000000000000000000000000000027fffffffffffff000000000000000000000000ffffffffffffffffffffffffffff919096166201000002167fffffffffffff000000000000000000000000000000000000000000000000ffff60ff95909516610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909416939093171792909216179190911790555050505b60400151949350505050565b60008260000182815481106130e3576130e361515b565b9060005260206000200154905092915050565b600081815260018301602052604081205480156131df57600061311a600183615113565b855490915060009061312e90600190615113565b905081811461319357600086600001828154811061314e5761314e61515b565b90600052602060002001549050808760000184815481106131715761317161515b565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806131a4576131a46159c2565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050611ecd565b6000915050611ecd565b5092915050565b600081815260018301602052604081205461323757508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611ecd565b506000611ecd565b6000818160045b600f8110156132cc577fff0000000000000000000000000000000000000000000000000000000000000082168382602081106132845761328461515b565b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916146132ba57506000949350505050565b806132c48161518a565b915050613246565b5081600f1a60018111156132e2576132e26155d0565b949350505050565b600080808085606001516001811115613305576133056155d0565b0361332b576133178888888888613dfe565b613326576000925090506133ff565b6133a3565b600185606001516001811115613343576133436155d0565b0361337157600061335689898988613f88565b925090508061336b57506000925090506133ff565b506133a3565b6040517ff2b2d41200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516060015163ffffffff1687106133f857877fc3237c8807c467c1b39b8d0395eff077313e691bf0a7388106792564ebfd5636876040516133e59190614c8d565b60405180910390a26000925090506133ff565b6001925090505b9550959350505050565b601454600090819077010000000000000000000000000000000000000000000000900460ff1615613466576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16770100000000000000000000000000000000000000000000001790556040517f4585e33b00000000000000000000000000000000000000000000000000000000906134db908590602401614c8d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290517f79188d1600000000000000000000000000000000000000000000000000000000815290935073ffffffffffffffffffffffffffffffffffffffff8616906379188d16906135ae90879087906004016159f1565b60408051808303816000875af11580156135cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135f09190615a0a565b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16905590969095509350505050565b60008160600151600181111561363c5761363c6155d0565b036136a057600083815260046020526040902060010180547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167c010000000000000000000000000000000000000000000000000000000063ffffffff851602179055505050565b6001816060015160018111156136b8576136b86155d0565b036137245760c08101805160009081526008602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055915191517fa4a4e334c0e330143f9437484fe516c13bc560b86b5b0daf58e7084aaac228f29190a25b505050565b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613799573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137bd9190615a52565b509350509250506000821315806137d357508042105b8061380357506000846040015162ffffff1611801561380357506137f78142615113565b846040015162ffffff16105b156131e9575050601b5492915050565b60408051608081018252600080825260208083018281528385018381526060850184905273ffffffffffffffffffffffffffffffffffffffff878116855260229093528584208054640100000000810462ffffff1690925263ffffffff82169092527b01000000000000000000000000000000000000000000000000000000810460ff16855285517ffeaf968c00000000000000000000000000000000000000000000000000000000815295519495919484936701000000000000009092049091169163feaf968c9160048083019260a09291908290030181865afa158015613900573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139249190615a52565b5093505092505060008213158061393a57508042105b8061396a57506000866040015162ffffff1611801561396a575061395e8142615113565b866040015162ffffff16105b1561397e5760018301546060850152613986565b606084018290525b50505092915050565b604080516101008101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e08201529082015115613a255760008381526023602090815260409182902082518084018452905463ffffffff811680835262ffffff640100000000909204821692840192835260e089018051909401529051915191169101525b6000613a318686614195565b60c0840151602082015182519293509091600091613a4e916158e0565b60e08801515190915060ff16600060128210613a6b576001613a81565b613a76826012615113565b613a8190600a615bc2565b9050600060128311613a94576001613aaa565b613a9f601284615113565b613aaa90600a615bc2565b905085600001516bffffffffffffffffffffffff16856bffffffffffffffffffffffff161015613b5257849350613b26818b60800151613aea9190615258565b838c60e0015160600151886bffffffffffffffffffffffff16613b0d9190615258565b613b179190615258565b613b2191906158cc565b6144c3565b6bffffffffffffffffffffffff9081166040880152600060608801819052602088015285168652613c78565b836bffffffffffffffffffffffff16856bffffffffffffffffffffffff161015613c7857849350613be086604001516bffffffffffffffffffffffff16828c60800151613b9f9190615258565b848d60e0015160600151896bffffffffffffffffffffffff16613bc29190615258565b613bcc9190615258565b613bd691906158cc565b613b219190615113565b6bffffffffffffffffffffffff1660608088019190915260e08b01510151613c6490613c0d908490615258565b6001848d60e0015160600151613c239190615258565b613c2d9190615113565b838d608001518a606001516bffffffffffffffffffffffff16613c509190615258565b613c5a9190615258565b613b17919061526f565b6bffffffffffffffffffffffff1660208701525b60008981526004602052604090206001018054859190601090613cbe90849070010000000000000000000000000000000090046bffffffffffffffffffffffff16615942565b82546101009290920a6bffffffffffffffffffffffff81810219909316918316021790915560008b81526004602052604081206001018054928816935091613d199084906fffffffffffffffffffffffffffffffff16615bce565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550836bffffffffffffffffffffffff16602160008c60c0015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254613db09190615113565b92505081905550887f801ba6ed51146ffe3e99d1dbd9dd0f4de6292e78a9a34c39c0183de17b3f40fc87604051613de79190615bf7565b60405180910390a250939998505050505050505050565b60008084806020019051810190613e159190615cb7565b845160e00151815191925063ffffffff90811691161015613e7257867f405288ea7be309e16cfdf481367f90a413e1d4634fcdaf8966546db9b93012e886604051613e609190614c8d565b60405180910390a26000915050613f7f565b8260e001518015613f325750602081015115801590613f325750602081015161010084015182516040517f85df51fd00000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff909116906385df51fd90602401602060405180830381865afa158015613f0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f2f9190614f06565b14155b80613f445750805163ffffffff168611155b15613f7957867f6aa7f60c176da7af894b384daea2249497448137f5943c1237ada8bc92bdc30186604051613e609190614c8d565b60019150505b95945050505050565b600080600084806020019051810190613fa19190615d0f565b905060008782600001518360200151846040015160405160200161400394939291909384526020840192909252604083015260e01b7fffffffff0000000000000000000000000000000000000000000000000000000016606082015260640190565b6040516020818303038152906040528051906020012090508460e0015180156140de57506080820151158015906140de5750608082015161010086015160608401516040517f85df51fd00000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff909116906385df51fd90602401602060405180830381865afa1580156140b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140db9190614f06565b14155b806140f3575086826060015163ffffffff1610155b1561413d57877f6aa7f60c176da7af894b384daea2249497448137f5943c1237ada8bc92bdc301876040516141289190614c8d565b60405180910390a260009350915061418c9050565b60008181526008602052604090205460ff161561418457877f405288ea7be309e16cfdf481367f90a413e1d4634fcdaf8966546db9b93012e8876040516141289190614c8d565b600193509150505b94509492505050565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915260008260e001516000015160ff1690506000846060015161ffff1684606001516142009190615258565b905083610100015180156142135750803a105b1561421b57503a5b60006012831161422c576001614242565b614237601284615113565b61424290600a615bc2565b905060006012841061425557600161426b565b614260846012615113565b61426b90600a615bc2565b905060008660a0015187604001518860200151896000015161428d919061526f565b6142979087615258565b6142a1919061526f565b6142ab9190615258565b90506142ee828860e00151606001516142c49190615258565b6001848a60e00151606001516142da9190615258565b6142e49190615113565b613c5a8685615258565b6bffffffffffffffffffffffff168652608087015161431190613b2190836158cc565b6bffffffffffffffffffffffff1660408088019190915260e0880151015160009061434a9062ffffff16683635c9adc5dea00000615258565b9050600081633b9aca008a60a001518b60e001516020015163ffffffff168c604001518d600001518b61437d9190615258565b614387919061526f565b6143919190615258565b61439b9190615258565b6143a591906158cc565b6143af919061526f565b90506143f2848a60e00151606001516143c89190615258565b6001868c60e00151606001516143de9190615258565b6143e89190615113565b613c5a8885615258565b6bffffffffffffffffffffffff166020890152608089015161441890613b2190836158cc565b6bffffffffffffffffffffffff16606089015260c089015173ffffffffffffffffffffffffffffffffffffffff166080808a019190915289015161445b906144c3565b6bffffffffffffffffffffffff1660a0808a019190915289015161447e906144c3565b6bffffffffffffffffffffffff1660c089015260e0890151606001516144a3906144c3565b6bffffffffffffffffffffffff1660e08901525050505050505092915050565b60006bffffffffffffffffffffffff821115614561576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610c8c565b5090565b508054600082559060005260206000209081019061109c9190614605565b8280548282559060005260206000209081019282156145fd579160200282015b828111156145fd57825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9091161782556020909201916001909101906145a3565b506145619291505b5b808211156145615760008155600101614606565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610200810167ffffffffffffffff8111828210171561466d5761466d61461a565b60405290565b60405160c0810167ffffffffffffffff8111828210171561466d5761466d61461a565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156146dd576146dd61461a565b604052919050565b600067ffffffffffffffff8211156146ff576146ff61461a565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff8116811461109c57600080fd5b803561473681614709565b919050565b600082601f83011261474c57600080fd5b8135602061476161475c836146e5565b614696565b82815260059290921b8401810191818101908684111561478057600080fd5b8286015b848110156147a457803561479781614709565b8352918301918301614784565b509695505050505050565b60ff8116811461109c57600080fd5b8035614736816147af565b63ffffffff8116811461109c57600080fd5b8035614736816147c9565b801515811461109c57600080fd5b8035614736816147e6565b62ffffff8116811461109c57600080fd5b8035614736816147ff565b61ffff8116811461109c57600080fd5b80356147368161481b565b6000610200828403121561484957600080fd5b614851614649565b905061485c826147db565b815261486a602083016147db565b602082015261487b604083016147db565b604082015261488c6060830161472b565b606082015261489d608083016147f4565b60808201526148ae60a08301614810565b60a08201526148bf60c083016147db565b60c08201526148d060e083016147db565b60e08201526101006148e381840161472b565b908201526101206148f583820161482b565b9082015261014061490783820161472b565b90820152610160828101359082015261018080830135908201526101a080830135908201526101c08083013567ffffffffffffffff81111561494857600080fd5b6149548582860161473b565b8284015250506101e061496881840161472b565b9082015292915050565b803567ffffffffffffffff8116811461473657600080fd5b600082601f83011261499b57600080fd5b813567ffffffffffffffff8111156149b5576149b561461a565b6149e660207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614696565b8181528460208386010111156149fb57600080fd5b816020850160208301376000918101602001919091529392505050565b6bffffffffffffffffffffffff8116811461109c57600080fd5b600082601f830112614a4357600080fd5b81356020614a5361475c836146e5565b82815260c09283028501820192828201919087851115614a7257600080fd5b8387015b85811015614b045781818a031215614a8e5760008081fd5b614a96614673565b8135614aa1816147c9565b815281860135614ab0816147ff565b81870152604082810135614ac381614709565b90820152606082810135614ad6816147af565b908201526080828101359082015260a080830135614af381614a18565b908201528452928401928101614a76565b5090979650505050505050565b600080600080600080600080610100898b031215614b2e57600080fd5b883567ffffffffffffffff80821115614b4657600080fd5b614b528c838d0161473b565b995060208b0135915080821115614b6857600080fd5b614b748c838d0161473b565b9850614b8260408c016147be565b975060608b0135915080821115614b9857600080fd5b614ba48c838d01614836565b9650614bb260808c01614972565b955060a08b0135915080821115614bc857600080fd5b614bd48c838d0161498a565b945060c08b0135915080821115614bea57600080fd5b614bf68c838d0161473b565b935060e08b0135915080821115614c0c57600080fd5b50614c198b828c01614a32565b9150509295985092959890939650565b6000815180845260005b81811015614c4f57602081850181015186830182015201614c33565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611edf6020830184614c29565b60008083601f840112614cb257600080fd5b50813567ffffffffffffffff811115614cca57600080fd5b6020830191508360208260051b8501011115614ce557600080fd5b9250929050565b60008060008060008060008060e0898b031215614d0857600080fd5b606089018a811115614d1957600080fd5b8998503567ffffffffffffffff80821115614d3357600080fd5b818b0191508b601f830112614d4757600080fd5b813581811115614d5657600080fd5b8c6020828501011115614d6857600080fd5b6020830199508098505060808b0135915080821115614d8657600080fd5b614d928c838d01614ca0565b909750955060a08b0135915080821115614dab57600080fd5b50614db88b828c01614ca0565b999c989b50969995989497949560c00135949350505050565b60008060008060008060c08789031215614dea57600080fd5b863567ffffffffffffffff80821115614e0257600080fd5b614e0e8a838b0161473b565b97506020890135915080821115614e2457600080fd5b614e308a838b0161473b565b9650614e3e60408a016147be565b95506060890135915080821115614e5457600080fd5b614e608a838b0161498a565b9450614e6e60808a01614972565b935060a0890135915080821115614e8457600080fd5b50614e9189828a0161498a565b9150509295509295509295565b600060208284031215614eb057600080fd5b8135611edf81614709565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff81811683821602908116908181146131e9576131e9614ebb565b600060208284031215614f1857600080fd5b5051919050565b63ffffffff8181168382160190808211156131e9576131e9614ebb565b600081518084526020808501945080840160005b83811015614f8257815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101614f50565b509495945050505050565b60208152614fa460208201835163ffffffff169052565b60006020830151614fbd604084018263ffffffff169052565b50604083015163ffffffff8116606084015250606083015173ffffffffffffffffffffffffffffffffffffffff8116608084015250608083015180151560a08401525060a083015162ffffff811660c08401525060c083015163ffffffff811660e08401525060e083015161010061503c8185018363ffffffff169052565b84015190506101206150658482018373ffffffffffffffffffffffffffffffffffffffff169052565b840151905061014061507c8482018361ffff169052565b84015190506101606150a58482018373ffffffffffffffffffffffffffffffffffffffff169052565b840151610180848101919091528401516101a0808501919091528401516101c0808501919091528401516102006101e0808601829052919250906150ed610220860184614f3c565b95015173ffffffffffffffffffffffffffffffffffffffff169301929092525090919050565b81810381811115611ecd57611ecd614ebb565b60008161513557615135614ebb565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036151bb576151bb614ebb565b5060010190565b600061012063ffffffff808d1684528b6020850152808b166040850152508060608401526151f28184018a614f3c565b905082810360808401526152068189614f3c565b905060ff871660a084015282810360c08401526152238187614c29565b905067ffffffffffffffff851660e08401528281036101008401526152488185614c29565b9c9b505050505050505050505050565b8082028115828204841417611ecd57611ecd614ebb565b80820180821115611ecd57611ecd614ebb565b60ff8181168382160190811115611ecd57611ecd614ebb565b8051614736816147c9565b805161473681614709565b8051614736816147e6565b8051614736816147ff565b80516147368161481b565b600082601f8301126152e357600080fd5b815160206152f361475c836146e5565b82815260059290921b8401810191818101908684111561531257600080fd5b8286015b848110156147a457805161532981614709565b8352918301918301615316565b600082601f83011261534757600080fd5b8151602061535761475c836146e5565b82815260c0928302850182019282820191908785111561537657600080fd5b8387015b85811015614b045781818a0312156153925760008081fd5b61539a614673565b81516153a5816147c9565b8152818601516153b4816147ff565b818701526040828101516153c781614709565b908201526060828101516153da816147af565b908201526080828101519082015260a0808301516153f781614a18565b90820152845292840192810161537a565b60008060006060848603121561541d57600080fd5b835167ffffffffffffffff8082111561543557600080fd5b90850190610200828803121561544a57600080fd5b615452614649565b61545b8361529b565b81526154696020840161529b565b602082015261547a6040840161529b565b604082015261548b606084016152a6565b606082015261549c608084016152b1565b60808201526154ad60a084016152bc565b60a08201526154be60c0840161529b565b60c08201526154cf60e0840161529b565b60e08201526101006154e28185016152a6565b908201526101206154f48482016152c7565b908201526101406155068482016152a6565b90820152610160838101519082015261018080840151908201526101a080840151908201526101c0808401518381111561553f57600080fd5b61554b8a8287016152d2565b8284015250506101e061555f8185016152a6565b90820152602087015190955091508082111561557a57600080fd5b615586878388016152d2565b9350604086015191508082111561559c57600080fd5b506155a986828701615336565b9150509250925092565b6000602082840312156155c557600080fd5b8151611edf816147af565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b1660408501528160608501526156468285018b614f3c565b9150838203608085015261565a828a614f3c565b915060ff881660a085015283820360c08501526156778288614c29565b90861660e085015283810361010085015290506152488185614c29565b8183823760009101908152919050565b8281526080810160608360208401379392505050565b600082601f8301126156cb57600080fd5b813560206156db61475c836146e5565b82815260059290921b840181019181810190868411156156fa57600080fd5b8286015b848110156147a457803583529183019183016156fe565b600082601f83011261572657600080fd5b8135602061573661475c836146e5565b82815260059290921b8401810191818101908684111561575557600080fd5b8286015b848110156147a457803567ffffffffffffffff8111156157795760008081fd5b6157878986838b010161498a565b845250918301918301615759565b6000602082840312156157a757600080fd5b813567ffffffffffffffff808211156157bf57600080fd5b9083019060c082860312156157d357600080fd5b6157db614673565b82358152602083013560208201526040830135828111156157fb57600080fd5b615807878286016156ba565b60408301525060608301358281111561581f57600080fd5b61582b878286016156ba565b60608301525060808301358281111561584357600080fd5b61584f87828601615715565b60808301525060a08301358281111561586757600080fd5b61587387828601615715565b60a08301525095945050505050565b61ffff8181168382160190808211156131e9576131e9614ebb565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826158db576158db61589d565b500490565b6bffffffffffffffffffffffff8181168382160190808211156131e9576131e9614ebb565b6bffffffffffffffffffffffff851681528360208201528260408201526080606082015260006159386080830184614c29565b9695505050505050565b6bffffffffffffffffffffffff8281168282160390808211156131e9576131e9614ebb565b60006bffffffffffffffffffffffff808416806159865761598661589d565b92169190910492915050565b6bffffffffffffffffffffffff8181168382160280821691908281146159ba576159ba614ebb565b505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8281526040602082015260006132e26040830184614c29565b60008060408385031215615a1d57600080fd5b8251615a28816147e6565b6020939093015192949293505050565b805169ffffffffffffffffffff8116811461473657600080fd5b600080600080600060a08688031215615a6a57600080fd5b615a7386615a38565b9450602086015193506040860151925060608601519150615a9660808701615a38565b90509295509295909350565b600181815b80851115615afb57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615ae157615ae1614ebb565b80851615615aee57918102915b93841c9390800290615aa7565b509250929050565b600082615b1257506001611ecd565b81615b1f57506000611ecd565b8160018114615b355760028114615b3f57615b5b565b6001915050611ecd565b60ff841115615b5057615b50614ebb565b50506001821b611ecd565b5060208310610133831016604e8410600b8410161715615b7e575081810a611ecd565b615b888383615aa2565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615bba57615bba614ebb565b029392505050565b6000611edf8383615b03565b6fffffffffffffffffffffffffffffffff8181168382160190808211156131e9576131e9614ebb565b6000610100820190506bffffffffffffffffffffffff8084511683528060208501511660208401528060408501511660408401528060608501511660608401525073ffffffffffffffffffffffffffffffffffffffff608084015116608083015260a0830151615c7760a08401826bffffffffffffffffffffffff169052565b5060c0830151615c9760c08401826bffffffffffffffffffffffff169052565b5060e08301516131e960e08401826bffffffffffffffffffffffff169052565b600060408284031215615cc957600080fd5b6040516040810181811067ffffffffffffffff82111715615cec57615cec61461a565b6040528251615cfa816147c9565b81526020928301519281019290925250919050565b600060a08284031215615d2157600080fd5b60405160a0810181811067ffffffffffffffff82111715615d4457615d4461461a565b806040525082518152602083015160208201526040830151615d65816147c9565b60408201526060830151615d78816147c9565b6060820152608092830151928101929092525091905056fea164736f6c6343000813000a", } var AutomationRegistryABI = AutomationRegistryMetaData.ABI diff --git a/core/gethwrappers/generated/type_and_version_interface_wrapper/type_and_version_interface_wrapper.go b/core/gethwrappers/generated/type_and_version_interface_wrapper/type_and_version_interface_wrapper.go deleted file mode 100644 index bf907b0354b..00000000000 --- a/core/gethwrappers/generated/type_and_version_interface_wrapper/type_and_version_interface_wrapper.go +++ /dev/null @@ -1,183 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package type_and_version_interface_wrapper - -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 TypeAndVersionInterfaceMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", -} - -var TypeAndVersionInterfaceABI = TypeAndVersionInterfaceMetaData.ABI - -type TypeAndVersionInterface struct { - address common.Address - abi abi.ABI - TypeAndVersionInterfaceCaller - TypeAndVersionInterfaceTransactor - TypeAndVersionInterfaceFilterer -} - -type TypeAndVersionInterfaceCaller struct { - contract *bind.BoundContract -} - -type TypeAndVersionInterfaceTransactor struct { - contract *bind.BoundContract -} - -type TypeAndVersionInterfaceFilterer struct { - contract *bind.BoundContract -} - -type TypeAndVersionInterfaceSession struct { - Contract *TypeAndVersionInterface - CallOpts bind.CallOpts - TransactOpts bind.TransactOpts -} - -type TypeAndVersionInterfaceCallerSession struct { - Contract *TypeAndVersionInterfaceCaller - CallOpts bind.CallOpts -} - -type TypeAndVersionInterfaceTransactorSession struct { - Contract *TypeAndVersionInterfaceTransactor - TransactOpts bind.TransactOpts -} - -type TypeAndVersionInterfaceRaw struct { - Contract *TypeAndVersionInterface -} - -type TypeAndVersionInterfaceCallerRaw struct { - Contract *TypeAndVersionInterfaceCaller -} - -type TypeAndVersionInterfaceTransactorRaw struct { - Contract *TypeAndVersionInterfaceTransactor -} - -func NewTypeAndVersionInterface(address common.Address, backend bind.ContractBackend) (*TypeAndVersionInterface, error) { - abi, err := abi.JSON(strings.NewReader(TypeAndVersionInterfaceABI)) - if err != nil { - return nil, err - } - contract, err := bindTypeAndVersionInterface(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &TypeAndVersionInterface{address: address, abi: abi, TypeAndVersionInterfaceCaller: TypeAndVersionInterfaceCaller{contract: contract}, TypeAndVersionInterfaceTransactor: TypeAndVersionInterfaceTransactor{contract: contract}, TypeAndVersionInterfaceFilterer: TypeAndVersionInterfaceFilterer{contract: contract}}, nil -} - -func NewTypeAndVersionInterfaceCaller(address common.Address, caller bind.ContractCaller) (*TypeAndVersionInterfaceCaller, error) { - contract, err := bindTypeAndVersionInterface(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &TypeAndVersionInterfaceCaller{contract: contract}, nil -} - -func NewTypeAndVersionInterfaceTransactor(address common.Address, transactor bind.ContractTransactor) (*TypeAndVersionInterfaceTransactor, error) { - contract, err := bindTypeAndVersionInterface(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &TypeAndVersionInterfaceTransactor{contract: contract}, nil -} - -func NewTypeAndVersionInterfaceFilterer(address common.Address, filterer bind.ContractFilterer) (*TypeAndVersionInterfaceFilterer, error) { - contract, err := bindTypeAndVersionInterface(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &TypeAndVersionInterfaceFilterer{contract: contract}, nil -} - -func bindTypeAndVersionInterface(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := TypeAndVersionInterfaceMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -func (_TypeAndVersionInterface *TypeAndVersionInterfaceRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _TypeAndVersionInterface.Contract.TypeAndVersionInterfaceCaller.contract.Call(opts, result, method, params...) -} - -func (_TypeAndVersionInterface *TypeAndVersionInterfaceRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _TypeAndVersionInterface.Contract.TypeAndVersionInterfaceTransactor.contract.Transfer(opts) -} - -func (_TypeAndVersionInterface *TypeAndVersionInterfaceRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _TypeAndVersionInterface.Contract.TypeAndVersionInterfaceTransactor.contract.Transact(opts, method, params...) -} - -func (_TypeAndVersionInterface *TypeAndVersionInterfaceCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _TypeAndVersionInterface.Contract.contract.Call(opts, result, method, params...) -} - -func (_TypeAndVersionInterface *TypeAndVersionInterfaceTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _TypeAndVersionInterface.Contract.contract.Transfer(opts) -} - -func (_TypeAndVersionInterface *TypeAndVersionInterfaceTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _TypeAndVersionInterface.Contract.contract.Transact(opts, method, params...) -} - -func (_TypeAndVersionInterface *TypeAndVersionInterfaceCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { - var out []interface{} - err := _TypeAndVersionInterface.contract.Call(opts, &out, "typeAndVersion") - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - -} - -func (_TypeAndVersionInterface *TypeAndVersionInterfaceSession) TypeAndVersion() (string, error) { - return _TypeAndVersionInterface.Contract.TypeAndVersion(&_TypeAndVersionInterface.CallOpts) -} - -func (_TypeAndVersionInterface *TypeAndVersionInterfaceCallerSession) TypeAndVersion() (string, error) { - return _TypeAndVersionInterface.Contract.TypeAndVersion(&_TypeAndVersionInterface.CallOpts) -} - -func (_TypeAndVersionInterface *TypeAndVersionInterface) Address() common.Address { - return _TypeAndVersionInterface.address -} - -type TypeAndVersionInterfaceInterface interface { - TypeAndVersion(opts *bind.CallOpts) (string, error) - - Address() common.Address -} diff --git a/core/gethwrappers/generation/generate/genwrapper/genwrapper.go b/core/gethwrappers/generation/generate/genwrapper/genwrapper.go new file mode 100644 index 00000000000..380d6827553 --- /dev/null +++ b/core/gethwrappers/generation/generate/genwrapper/genwrapper.go @@ -0,0 +1,44 @@ +package genwrapper + +import ( + "fmt" + "os" + "path/filepath" + + gethParams "github.com/ethereum/go-ethereum/params" + + gethwrappers2 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers" +) + +func GenWrapper(abiPath string, binPath string, className string, pkgName string) { + fmt.Println("Generating", pkgName, "contract wrapper") + + cwd, err := os.Getwd() // gethwrappers directory + if err != nil { + gethwrappers2.Exit("could not get working directory", err) + } + outDir := filepath.Join(cwd, "generated", pkgName) + if mkdErr := os.MkdirAll(outDir, 0700); err != nil { + gethwrappers2.Exit("failed to create wrapper dir", mkdErr) + } + outPath := filepath.Join(outDir, pkgName+".go") + + gethwrappers2.Abigen(gethwrappers2.AbigenArgs{ + Bin: binPath, ABI: abiPath, Out: outPath, Type: className, Pkg: pkgName, + }) + + // Build succeeded, so update the versions db with the new contract data + versions, err := gethwrappers2.ReadVersionsDB() + if err != nil { + gethwrappers2.Exit("could not read current versions database", err) + } + versions.GethVersion = gethParams.Version + versions.ContractVersions[pkgName] = gethwrappers2.ContractVersion{ + Hash: gethwrappers2.VersionHash(abiPath, binPath), + AbiPath: abiPath, + BinaryPath: binPath, + } + if err := gethwrappers2.WriteVersionsDB(versions); err != nil { + gethwrappers2.Exit("could not save versions db", err) + } +} diff --git a/core/gethwrappers/generation/generate/wrap.go b/core/gethwrappers/generation/generate/wrap.go index 967e703d393..db251101cc3 100644 --- a/core/gethwrappers/generation/generate/wrap.go +++ b/core/gethwrappers/generation/generate/wrap.go @@ -1,13 +1,9 @@ package main import ( - "fmt" "os" - "path/filepath" - gethParams "github.com/ethereum/go-ethereum/params" - - gethwrappers2 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generation/generate/genwrapper" ) func main() { @@ -15,34 +11,6 @@ func main() { binPath := os.Args[2] className := os.Args[3] pkgName := os.Args[4] - fmt.Println("Generating", pkgName, "contract wrapper") - - cwd, err := os.Getwd() // gethwrappers directory - if err != nil { - gethwrappers2.Exit("could not get working directory", err) - } - outDir := filepath.Join(cwd, "generated", pkgName) - if mkdErr := os.MkdirAll(outDir, 0700); err != nil { - gethwrappers2.Exit("failed to create wrapper dir", mkdErr) - } - outPath := filepath.Join(outDir, pkgName+".go") - - gethwrappers2.Abigen(gethwrappers2.AbigenArgs{ - Bin: binPath, ABI: abiPath, Out: outPath, Type: className, Pkg: pkgName, - }) - // Build succeeded, so update the versions db with the new contract data - versions, err := gethwrappers2.ReadVersionsDB() - if err != nil { - gethwrappers2.Exit("could not read current versions database", err) - } - versions.GethVersion = gethParams.Version - versions.ContractVersions[pkgName] = gethwrappers2.ContractVersion{ - Hash: gethwrappers2.VersionHash(abiPath, binPath), - AbiPath: abiPath, - BinaryPath: binPath, - } - if err := gethwrappers2.WriteVersionsDB(versions); err != nil { - gethwrappers2.Exit("could not save versions db", err) - } + genwrapper.GenWrapper(abiPath, binPath, className, pkgName) } 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 514c2596ff2..7080ec31b26 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 @@ -1,6 +1,5 @@ GETH_VERSION: 1.14.11 aggregator_v2v3_interface: ../../contracts/solc/v0.8.6/AggregatorV2V3Interface/AggregatorV2V3Interface.abi ../../contracts/solc/v0.8.6/AggregatorV2V3Interface/AggregatorV2V3Interface.bin 95e8814b408bb05bf21742ef580d98698b7db6a9bac6a35c3de12b23aec4ee28 -aggregator_v3_interface: ../../contracts/solc/v0.8.6/AggregatorV2V3Interface/AggregatorV3Interface.abi ../../contracts/solc/v0.8.6/AggregatorV2V3Interface/AggregatorV3Interface.bin 351b55d3b0f04af67db6dfb5c92f1c64479400ca1fec77afc20bc0ce65cb49ab arbitrum_module: ../../contracts/solc/v0.8.19/ArbitrumModule/ArbitrumModule.abi ../../contracts/solc/v0.8.19/ArbitrumModule/ArbitrumModule.bin 12a7bad1f887d832d101a73ae279a91a90c93fd72befea9983e85eff493f62f4 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 @@ -15,7 +14,7 @@ automation_registry_logic_b_wrapper_2_2: ../../contracts/solc/v0.8.19/Automation 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 e628b4ba1ca8bf45c2b08c6b80f0b14efbd2dff13b85e5a9ebf643df32335ed2 automation_registry_logic_c_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistryLogicC2_3/AutomationRegistryLogicC2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicC2_3/AutomationRegistryLogicC2_3.bin 19d59318e42f28777756eff60d5c5e52563a2fffb8e3f0f0b07b6d36d82b2c55 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 7072ba90159d84572f427ec816e78aa032cf907b39bf228185e0c446842f7c11 -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 b6163402434b84e3b66bc078f6efac121c1e1240dca0e8ea89c43db46b4e308b +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 77ed34165d8623c4998dfdfb2ee74dcb395bbaa916e011a78ed1cbc98b24819e 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 automation_utils_2_2: ../../contracts/solc/v0.8.19/AutomationUtils2_2/AutomationUtils2_2.abi ../../contracts/solc/v0.8.19/AutomationUtils2_2/AutomationUtils2_2.bin 8743f6231aaefa3f2a0b2d484258070d506e2d0860690e66890dccc3949edb2e automation_utils_2_3: ../../contracts/solc/v0.8.19/AutomationUtils2_3/AutomationUtils2_3.abi ../../contracts/solc/v0.8.19/AutomationUtils2_3/AutomationUtils2_3.bin 11e2b481dc9a4d936e3443345d45d2cc571164459d214917b42a8054b295393b @@ -24,7 +23,6 @@ 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 f13715b38b5b9084b08bffa571fb1c8ef686001535902e1255052f074b31ad4e 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 7a82cc28014761090185c2650239ad01a0901181f1b2b899b42ca293bcda3741 -chain_reader_tester: ../../contracts/solc/v0.8.19/ChainReaderTester/ChainReaderTester.abi ../../contracts/solc/v0.8.19/ChainReaderTester/ChainReaderTester.bin ee9839cc26b615d168d5dbc8ef4f31d8d8b1ef8d276d8ee50625476f87ef1508 chain_specific_util_helper: ../../contracts/solc/v0.8.6/ChainSpecificUtilHelper/ChainSpecificUtilHelper.abi ../../contracts/solc/v0.8.6/ChainSpecificUtilHelper/ChainSpecificUtilHelper.bin 66eb30b0717fefe05672df5ec863c0b9a5a654623c4757307a2726d8f31e26b1 counter: ../../contracts/solc/v0.8.6/Counter/Counter.abi ../../contracts/solc/v0.8.6/Counter/Counter.bin 6ca06e000e8423573ffa0bdfda749d88236ab3da2a4cbb4a868c706da90488c9 cron_upkeep_factory_wrapper: ../../contracts/solc/v0.8.6/CronUpkeepFactory/CronUpkeepFactory.abi - dacb0f8cdf54ae9d2781c5e720fc314b32ed5e58eddccff512c75d6067292cd7 @@ -52,7 +50,6 @@ keeper_registry_wrapper1_3: ../../contracts/solc/v0.8.6/KeeperRegistry1_3/Keeper keeper_registry_wrapper2_0: ../../contracts/solc/v0.8.6/KeeperRegistry2_0/KeeperRegistry2_0.abi ../../contracts/solc/v0.8.6/KeeperRegistry2_0/KeeperRegistry2_0.bin c32dea7d5ef66b7c58ddc84ddf69aa44df1b3ae8601fbc271c95be4ff5853056 keeper_registry_wrapper_2_1: ../../contracts/solc/v0.8.16/KeeperRegistry2_1/KeeperRegistry2_1.abi ../../contracts/solc/v0.8.16/KeeperRegistry2_1/KeeperRegistry2_1.bin 11d36cb9eab0e136a2c3224709f7df17711756a126127e8c82326ce0a2e2b4f4 keepers_vrf_consumer: ../../contracts/solc/v0.8.6/KeepersVRFConsumer/KeepersVRFConsumer.abi ../../contracts/solc/v0.8.6/KeepersVRFConsumer/KeepersVRFConsumer.bin fa75572e689c9e84705c63e8dbe1b7b8aa1a8fe82d66356c4873d024bb9166e8 -log_emitter: ../../contracts/solc/v0.8.19/LogEmitter/LogEmitter.abi ../../contracts/solc/v0.8.19/LogEmitter/LogEmitter.bin 4b129ab93432c95ff9143f0631323e189887668889e0b36ccccf18a571e41ccf log_triggered_streams_lookup_wrapper: ../../contracts/solc/v0.8.16/LogTriggeredStreamsLookup/LogTriggeredStreamsLookup.abi ../../contracts/solc/v0.8.16/LogTriggeredStreamsLookup/LogTriggeredStreamsLookup.bin 920fff3b662909f12ed11b47d168036ffa74ad52070a94e2fa26cdad5e428b4e log_upkeep_counter_wrapper: ../../contracts/solc/v0.8.6/LogUpkeepCounter/LogUpkeepCounter.abi ../../contracts/solc/v0.8.6/LogUpkeepCounter/LogUpkeepCounter.bin 5482033d55eddb653bf580de0cc950db89a329091e085ac4122583df4a9777cd mock_aggregator_proxy: ../../contracts/solc/v0.8.6/MockAggregatorProxy/MockAggregatorProxy.abi ../../contracts/solc/v0.8.6/MockAggregatorProxy/MockAggregatorProxy.bin b16c108f3dd384c342ddff5e94da7c0a8d39d1be5e3d8f2cf61ecc7f0e50ff42 @@ -70,7 +67,6 @@ solidity_vrf_v08_verifier_wrapper: ../../contracts/solc/v0.8.6/VRFTestHelper/VRF streams_lookup_compatible_interface: ../../contracts/solc/v0.8.16/StreamsLookupCompatibleInterface/StreamsLookupCompatibleInterface.abi ../../contracts/solc/v0.8.16/StreamsLookupCompatibleInterface/StreamsLookupCompatibleInterface.bin 2861f553fb4731e89126b13319462df674727005a51982d1e617e2c2e44fa422 streams_lookup_upkeep_wrapper: ../../contracts/solc/v0.8.16/StreamsLookupUpkeep/StreamsLookupUpkeep.abi ../../contracts/solc/v0.8.16/StreamsLookupUpkeep/StreamsLookupUpkeep.bin 37e3a61091cc2a156539dd4aaff987e07577118aa02e97931a647df55705465e trusted_blockhash_store: ../../contracts/solc/v0.8.19/TrustedBlockhashStore/TrustedBlockhashStore.abi ../../contracts/solc/v0.8.19/TrustedBlockhashStore/TrustedBlockhashStore.bin 1570663ef6feabf8660a93e85d2427ad8e7dabcfa5b418d308c62132451c5662 -type_and_version_interface_wrapper: ../../contracts/solc/v0.8.6/KeeperRegistry1_2/TypeAndVersionInterface.abi ../../contracts/solc/v0.8.6/KeeperRegistry1_2/TypeAndVersionInterface.bin bc9c3a6e73e3ebd5b58754df0deeb3b33f4bb404d5709bb904aed51d32f4b45e upkeep_counter_wrapper: ../../contracts/solc/v0.8.16/UpkeepCounter/UpkeepCounter.abi ../../contracts/solc/v0.8.16/UpkeepCounter/UpkeepCounter.bin cef953186d12ac802e54d17c897d01605b60bbe0ce2df3b4cf2c31c5c3168b35 upkeep_perform_counter_restrictive_wrapper: ../../contracts/solc/v0.8.16/UpkeepPerformCounterRestrictive/UpkeepPerformCounterRestrictive.abi ../../contracts/solc/v0.8.16/UpkeepPerformCounterRestrictive/UpkeepPerformCounterRestrictive.bin 20955b21acceb58355fa287b29194a73edf5937067ba7140667301017cb2b24c upkeep_transcoder: ../../contracts/solc/v0.8.6/UpkeepTranscoder/UpkeepTranscoder.abi ../../contracts/solc/v0.8.6/UpkeepTranscoder/UpkeepTranscoder.bin 336c92a981597be26508455f81a908a0784a817b129a59686c5b2c4afcba730a @@ -93,7 +89,6 @@ vrf_external_sub_owner_example: ../../contracts/solc/v0.8.6/VRFExternalSubOwnerE vrf_load_test_external_sub_owner: ../../contracts/solc/v0.8.6/VRFLoadTestExternalSubOwner/VRFLoadTestExternalSubOwner.abi ../../contracts/solc/v0.8.6/VRFLoadTestExternalSubOwner/VRFLoadTestExternalSubOwner.bin 2097faa70265e420036cc8a3efb1f1e0836ad2d7323b295b9a26a125dbbe6c7d vrf_load_test_ownerless_consumer: ../../contracts/solc/v0.8.6/VRFLoadTestOwnerlessConsumer/VRFLoadTestOwnerlessConsumer.abi ../../contracts/solc/v0.8.6/VRFLoadTestOwnerlessConsumer/VRFLoadTestOwnerlessConsumer.bin 74f914843cbc70b9c3079c3e1c709382ce415225e8bb40113e7ac018bfcb0f5c vrf_load_test_with_metrics: ../../contracts/solc/v0.8.6/VRFV2LoadTestWithMetrics/VRFV2LoadTestWithMetrics.abi ../../contracts/solc/v0.8.6/VRFV2LoadTestWithMetrics/VRFV2LoadTestWithMetrics.bin c9621c52d216a090ff6bbe942f1b75d2bce8658a27323c3789e5e14b523277ee -vrf_log_emitter: ../../contracts/solc/v0.8.19/VRFLogEmitter/VRFLogEmitter.abi ../../contracts/solc/v0.8.19/VRFLogEmitter/VRFLogEmitter.bin 15f491d445ac4d0c712d1cbe4e5054c759b080bf20de7d54bfe2a82cde4dcf06 vrf_malicious_consumer_v2: ../../contracts/solc/v0.8.6/VRFMaliciousConsumerV2/VRFMaliciousConsumerV2.abi ../../contracts/solc/v0.8.6/VRFMaliciousConsumerV2/VRFMaliciousConsumerV2.bin 9755fa8ffc7f5f0b337d5d413d77b0c9f6cd6f68c31727d49acdf9d4a51bc522 vrf_malicious_consumer_v2_plus: ../../contracts/solc/v0.8.19/VRFMaliciousConsumerV2Plus/VRFMaliciousConsumerV2Plus.abi ../../contracts/solc/v0.8.19/VRFMaliciousConsumerV2Plus/VRFMaliciousConsumerV2Plus.bin f6bf81658d3472bb705d28dc4a837097ec93d78c3f786efaa9cd040ada9d3319 vrf_mock_ethlink_aggregator: ../../contracts/solc/v0.8.6/VRFMockETHLINKAggregator/VRFMockETHLINKAggregator.abi ../../contracts/solc/v0.8.6/VRFMockETHLINKAggregator/VRFMockETHLINKAggregator.bin 3657f8c552147eb55d7538fa7d8012c1a983d8c5184610de60600834a72e006b diff --git a/core/gethwrappers/generation/wrap.go b/core/gethwrappers/generation/wrap.go new file mode 100644 index 00000000000..8bbdf61483c --- /dev/null +++ b/core/gethwrappers/generation/wrap.go @@ -0,0 +1,22 @@ +package main + +import ( + "os" + + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generation/generate/genwrapper" +) + +const ( + rootDir = "../../../contracts/solc/" +) + +func main() { + project := os.Args[1] + className := os.Args[2] + pkgName := os.Args[3] + + abiPath := rootDir + project + "/" + className + "/" + className + ".sol/" + className + ".abi.json" + binPath := rootDir + project + "/" + className + "/" + className + ".sol/" + className + ".bin" + + genwrapper.GenWrapper(abiPath, binPath, className, pkgName) +} diff --git a/core/gethwrappers/go_generate.go b/core/gethwrappers/go_generate.go index 25001027a59..7f1d3f02e91 100644 --- a/core/gethwrappers/go_generate.go +++ b/core/gethwrappers/go_generate.go @@ -17,7 +17,6 @@ package gethwrappers //go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/KeeperRegistrar1_2/KeeperRegistrar.abi ../../contracts/solc/v0.8.6/KeeperRegistrar1_2/KeeperRegistrar.bin KeeperRegistrar keeper_registrar_wrapper1_2 //go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/KeeperRegistrar1_2Mock/KeeperRegistrar1_2Mock.abi ../../contracts/solc/v0.8.6/KeeperRegistrar1_2Mock/KeeperRegistrar1_2Mock.bin KeeperRegistrarMock keeper_registrar_wrapper1_2_mock //go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/KeeperRegistry1_2/KeeperRegistry1_2.abi ../../contracts/solc/v0.8.6/KeeperRegistry1_2/KeeperRegistry1_2.bin KeeperRegistry keeper_registry_wrapper1_2 -//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/KeeperRegistry1_2/TypeAndVersionInterface.abi ../../contracts/solc/v0.8.6/KeeperRegistry1_2/TypeAndVersionInterface.bin TypeAndVersionInterface type_and_version_interface_wrapper //go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.abi ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.bin KeeperRegistryCheckUpkeepGasUsageWrapper gas_wrapper //go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.abi ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.bin KeeperRegistryCheckUpkeepGasUsageWrapperMock gas_wrapper_mock //go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/KeeperRegistry1_3/KeeperRegistry1_3.abi ../../contracts/solc/v0.8.6/KeeperRegistry1_3/KeeperRegistry1_3.bin KeeperRegistry keeper_registry_wrapper1_3 @@ -147,20 +146,13 @@ package gethwrappers // Aggregators //go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/AggregatorV2V3Interface/AggregatorV2V3Interface.abi ../../contracts/solc/v0.8.6/AggregatorV2V3Interface/AggregatorV2V3Interface.bin AggregatorV2V3Interface aggregator_v2v3_interface -//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/AggregatorV2V3Interface/AggregatorV3Interface.abi ../../contracts/solc/v0.8.6/AggregatorV2V3Interface/AggregatorV3Interface.bin AggregatorV3Interface aggregator_v3_interface //go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/MockAggregatorProxy/MockAggregatorProxy.abi ../../contracts/solc/v0.8.6/MockAggregatorProxy/MockAggregatorProxy.bin MockAggregatorProxy mock_aggregator_proxy -// Log tester - -// ChainReader test contract -//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 - //go:generate go generate ./functions //go:generate go generate ./keystone //go:generate go generate ./llo-feeds //go:generate go generate ./operatorforwarder //go:generate go generate ./shared -//go:generate go generate ./transmission //go:generate go generate ./ccip //go:generate go generate ./liquiditymanager //go:generate go generate ./workflow diff --git a/core/gethwrappers/go_generate_logpoller.go b/core/gethwrappers/go_generate_logpoller.go deleted file mode 100644 index b28b8205830..00000000000 --- a/core/gethwrappers/go_generate_logpoller.go +++ /dev/null @@ -1,7 +0,0 @@ -// Package gethwrappers provides tools for wrapping solidity contracts with -// golang packages, using abigen. -package gethwrappers - -// Log tester -//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/LogEmitter/LogEmitter.abi ../../contracts/solc/v0.8.19/LogEmitter/LogEmitter.bin LogEmitter log_emitter -//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/VRFLogEmitter/VRFLogEmitter.abi ../../contracts/solc/v0.8.19/VRFLogEmitter/VRFLogEmitter.bin VRFLogEmitter vrf_log_emitter diff --git a/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0/capabilities_registry.go b/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0/capabilities_registry.go new file mode 100644 index 00000000000..2a21f64da56 --- /dev/null +++ b/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0/capabilities_registry.go @@ -0,0 +1,2352 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package capabilities_registry + +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 +) + +type CapabilitiesRegistryCapability struct { + LabelledName string + Version string + CapabilityType uint8 + ResponseType uint8 + ConfigurationContract common.Address +} + +type CapabilitiesRegistryCapabilityConfiguration struct { + CapabilityId [32]byte + Config []byte +} + +type CapabilitiesRegistryCapabilityInfo struct { + HashedId [32]byte + LabelledName string + Version string + CapabilityType uint8 + ResponseType uint8 + ConfigurationContract common.Address + IsDeprecated bool +} + +type CapabilitiesRegistryDONInfo struct { + Id uint32 + ConfigCount uint32 + F uint8 + IsPublic bool + AcceptsWorkflows bool + NodeP2PIds [][32]byte + CapabilityConfigurations []CapabilitiesRegistryCapabilityConfiguration +} + +type CapabilitiesRegistryNodeOperator struct { + Admin common.Address + Name string +} + +type CapabilitiesRegistryNodeParams struct { + NodeOperatorId uint32 + Signer [32]byte + P2pId [32]byte + EncryptionPublicKey [32]byte + HashedCapabilityIds [][32]byte +} + +type INodeInfoProviderNodeInfo struct { + NodeOperatorId uint32 + ConfigCount uint32 + WorkflowDONId uint32 + Signer [32]byte + P2pId [32]byte + EncryptionPublicKey [32]byte + HashedCapabilityIds [][32]byte + CapabilitiesDONIds []*big.Int +} + +var CapabilitiesRegistryMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AccessForbidden\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityIsDeprecated\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"CapabilityRequiredByDON\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"DONDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"DuplicateDONCapability\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"}],\"name\":\"DuplicateDONNode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedConfigurationContract\",\"type\":\"address\"}],\"name\":\"InvalidCapabilityConfigurationContractInterface\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"nodeCount\",\"type\":\"uint256\"}],\"name\":\"InvalidFaultTolerance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"name\":\"InvalidNodeCapabilities\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"encryptionPublicKey\",\"type\":\"bytes32\"}],\"name\":\"InvalidNodeEncryptionPublicKey\",\"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\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"}],\"name\":\"NodeAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"}],\"name\":\"NodeDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"NodeDoesNotSupportCapability\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"}],\"name\":\"NodeOperatorDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"}],\"name\":\"NodePartOfCapabilitiesDON\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"}],\"name\":\"NodePartOfWorkflowDON\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDeprecated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"}],\"name\":\"NodeAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"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\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"}],\"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\":\"string\",\"name\":\"labelledName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"},{\"internalType\":\"enumCapabilitiesRegistry.CapabilityType\",\"name\":\"capabilityType\",\"type\":\"uint8\"},{\"internalType\":\"enumCapabilitiesRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilitiesRegistry.Capability[]\",\"name\":\"capabilities\",\"type\":\"tuple[]\"}],\"name\":\"addCapabilities\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"nodes\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCapabilitiesRegistry.CapabilityConfiguration[]\",\"name\":\"capabilityConfigurations\",\"type\":\"tuple[]\"},{\"internalType\":\"bool\",\"name\":\"isPublic\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"acceptsWorkflows\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"}],\"name\":\"addDON\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilitiesRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"encryptionPublicKey\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilitiesRegistry.NodeParams[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"}],\"name\":\"addNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"name\":\"deprecateCapabilities\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilities\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"hashedId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"labelledName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"},{\"internalType\":\"enumCapabilitiesRegistry.CapabilityType\",\"name\":\"capabilityType\",\"type\":\"uint8\"},{\"internalType\":\"enumCapabilitiesRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isDeprecated\",\"type\":\"bool\"}],\"internalType\":\"structCapabilitiesRegistry.CapabilityInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedId\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"hashedId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"labelledName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"},{\"internalType\":\"enumCapabilitiesRegistry.CapabilityType\",\"name\":\"capabilityType\",\"type\":\"uint8\"},{\"internalType\":\"enumCapabilitiesRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isDeprecated\",\"type\":\"bool\"}],\"internalType\":\"structCapabilitiesRegistry.CapabilityInfo\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"getCapabilityConfigs\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"getDON\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"id\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isPublic\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"acceptsWorkflows\",\"type\":\"bool\"},{\"internalType\":\"bytes32[]\",\"name\":\"nodeP2PIds\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCapabilitiesRegistry.CapabilityConfiguration[]\",\"name\":\"capabilityConfigurations\",\"type\":\"tuple[]\"}],\"internalType\":\"structCapabilitiesRegistry.DONInfo\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDONs\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"id\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isPublic\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"acceptsWorkflows\",\"type\":\"bool\"},{\"internalType\":\"bytes32[]\",\"name\":\"nodeP2PIds\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCapabilitiesRegistry.CapabilityConfiguration[]\",\"name\":\"capabilityConfigurations\",\"type\":\"tuple[]\"}],\"internalType\":\"structCapabilitiesRegistry.DONInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"labelledName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"}],\"name\":\"getHashedCapabilityId\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNextDONId\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"getNode\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"workflowDONId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"encryptionPublicKey\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256[]\",\"name\":\"capabilitiesDONIds\",\"type\":\"uint256[]\"}],\"internalType\":\"structINodeInfoProvider.NodeInfo\",\"name\":\"nodeInfo\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilitiesRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNodeOperators\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilitiesRegistry.NodeOperator[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNodes\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"workflowDONId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"encryptionPublicKey\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256[]\",\"name\":\"capabilitiesDONIds\",\"type\":\"uint256[]\"}],\"internalType\":\"structINodeInfoProvider.NodeInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"p2pIds\",\"type\":\"bytes32[]\"}],\"name\":\"getNodesByP2PIds\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"workflowDONId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"encryptionPublicKey\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256[]\",\"name\":\"capabilitiesDONIds\",\"type\":\"uint256[]\"}],\"internalType\":\"structINodeInfoProvider.NodeInfo[]\",\"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\":\"uint32[]\",\"name\":\"donIds\",\"type\":\"uint32[]\"}],\"name\":\"removeDONs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint32[]\"}],\"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\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32[]\",\"name\":\"nodes\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCapabilitiesRegistry.CapabilityConfiguration[]\",\"name\":\"capabilityConfigurations\",\"type\":\"tuple[]\"},{\"internalType\":\"bool\",\"name\":\"isPublic\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"}],\"name\":\"updateDON\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint32[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilitiesRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"updateNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"encryptionPublicKey\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilitiesRegistry.NodeParams[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"}],\"name\":\"updateNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x6080604052600e80546001600160401b0319166401000000011790553480156200002857600080fd5b503380600081620000805760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000b357620000b381620000bc565b50505062000167565b336001600160a01b03821603620001165760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000077565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61536d80620001776000396000f3fe608060405234801561001057600080fd5b50600436106101c45760003560e01c806350c946fe116100f95780638da5cb5b11610097578063ddbe4f8211610071578063ddbe4f821461044d578063e29581aa14610462578063f2fde38b1461046a578063fcdc8efe1461047d57600080fd5b80638da5cb5b146103f25780639cb7c5f41461041a578063d8bc7b681461043a57600080fd5b8063715f5295116100d3578063715f5295146103b157806379ba5097146103c457806384f5ed8a146103cc57806386fa4246146103df57600080fd5b806350c946fe146103695780635d83d9671461038957806366acaa331461039c57600080fd5b806323537405116101665780632c01a1e8116101405780632c01a1e81461030f578063358039f414610322578063398f3773146103355780633f2a13c91461034857600080fd5b806323537405146102c9578063275459f2146102e95780632a852933146102fc57600080fd5b8063181f5a77116101a2578063181f5a77146102365780631d05394c1461027f578063214502431461029457806322bdbcbc146102a957600080fd5b806305a51966146101c95780630fe5800a146101f25780631257001114610213575b600080fd5b6101dc6101d73660046140ab565b6104a3565b6040516101e991906141aa565b60405180910390f35b61020561020036600461436f565b61062c565b6040519081526020016101e9565b6102266102213660046143d3565b61065f565b60405190151581526020016101e9565b6102726040518060400160405280601a81526020017f4361706162696c6974696573526567697374727920312e312e3000000000000081525081565b6040516101e9919061445a565b61029261028d3660046140ab565b61066c565b005b61029c610874565b6040516101e99190614568565b6102bc6102b73660046145f6565b6109d1565b6040516101e9919061464e565b6102dc6102d73660046145f6565b610abe565b6040516101e99190614661565b6102926102f73660046140ab565b610b02565b61029261030a366004614695565b610bd9565b61029261031d3660046140ab565b610cb9565b6102926103303660046140ab565b610f5c565b6102926103433660046140ab565b6116d1565b61035b610356366004614737565b611890565b6040516101e9929190614761565b61037c6103773660046143d3565b611a7c565b6040516101e99190614786565b6102926103973660046140ab565b611b69565b6103a4611c5e565b6040516101e99190614799565b6102926103bf3660046140ab565b611e41565b610292611ef3565b6102926103da3660046140ab565b611ff0565b6102926103ed36600461480e565b61250b565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101e9565b61042d6104283660046143d3565b61284b565b6040516101e99190614955565b610292610448366004614968565b612a86565b610455612b50565b6040516101e991906149ee565b6101dc612c44565b610292610478366004614a87565b612d55565b600e54640100000000900463ffffffff1660405163ffffffff90911681526020016101e9565b606060008267ffffffffffffffff8111156104c0576104c061422c565b60405190808252806020026020018201604052801561054f57816020015b60408051610100810182526000808252602080830182905292820181905260608083018290526080830182905260a083019190915260c0820181905260e082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816104de5790505b50905060005b838110156106225761057e85858381811061057257610572614aa2565b90506020020135611a7c565b82828151811061059057610590614aa2565b602002602001018190525060008019168282815181106105b2576105b2614aa2565b6020026020010151608001510361061a578484828181106105d5576105d5614aa2565b905060200201356040517fd82f6adb00000000000000000000000000000000000000000000000000000000815260040161061191815260200190565b60405180910390fd5b600101610555565b5090505b92915050565b60008282604051602001610641929190614761565b60405160208183030381529060405280519060200120905092915050565b6000610626600583612d69565b610674612d84565b60005b8181101561086f57600083838381811061069357610693614aa2565b90506020020160208101906106a891906145f6565b63ffffffff8181166000908152600d60209081526040808320805464010000000081049095168085526001820190935290832094955093909290916a010000000000000000000090910460ff16905b61070083612e07565b8110156107a057811561075657600c600061071b8584612e11565b8152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff169055610798565b6107968663ffffffff16600c60006107778588612e1190919063ffffffff16565b8152602001908152602001600020600501612e1d90919063ffffffff16565b505b6001016106f7565b508354640100000000900463ffffffff166000036107f2576040517f2b62be9b00000000000000000000000000000000000000000000000000000000815263ffffffff86166004820152602401610611565b63ffffffff85166000818152600d6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffff0000000000000000000000169055519182527ff264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c1581703651910160405180910390a25050505050806001019050610677565b505050565b600e54606090640100000000900463ffffffff166000610895600183614b00565b63ffffffff1667ffffffffffffffff8111156108b3576108b361422c565b60405190808252806020026020018201604052801561093a57816020015b6040805160e081018252600080825260208083018290529282018190526060808301829052608083019190915260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816108d15790505b509050600060015b8363ffffffff168163ffffffff1610156109ae5763ffffffff8082166000908152600d602052604090205416156109a65761097c81612e29565b83838151811061098e5761098e614aa2565b6020026020010181905250816109a390614b1d565b91505b600101610942565b506109ba600184614b00565b63ffffffff1681146109ca578082525b5092915050565b60408051808201909152600081526060602082015263ffffffff82166000908152600b60209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191610a3590614b55565b80601f0160208091040260200160405190810160405280929190818152602001828054610a6190614b55565b8015610aae5780601f10610a8357610100808354040283529160200191610aae565b820191906000526020600020905b815481529060010190602001808311610a9157829003601f168201915b5050505050815250509050919050565b6040805160e0810182526000808252602082018190529181018290526060808201839052608082019290925260a0810182905260c081019190915261062682612e29565b610b0a612d84565b60005b63ffffffff811682111561086f57600083838363ffffffff16818110610b3557610b35614aa2565b9050602002016020810190610b4a91906145f6565b63ffffffff81166000908152600b6020526040812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155919250610b956001830182613ff9565b505060405163ffffffff8216907fa59268ca81d40429e65ccea5385b59cf2d3fc6519371dee92f8eb1dae5107a7a90600090a250610bd281614ba8565b9050610b0d565b610be1612d84565b63ffffffff8088166000908152600d60205260408120805490926401000000009091041690819003610c47576040517f2b62be9b00000000000000000000000000000000000000000000000000000000815263ffffffff8a166004820152602401610611565b610cae888888886040518060a001604052808f63ffffffff16815260200187610c6f90614ba8565b63ffffffff811682528b15156020830152895460ff6a01000000000000000000009091048116151560408401528b1660609092019190915296506130f4565b505050505050505050565b6000805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610f56576000848483818110610cf357610cf3614aa2565b602090810292909201356000818152600c90935260409092206001810154929350919050610d50576040517fd82f6adb00000000000000000000000000000000000000000000000000000000815260048101839052602401610611565b6000610d5e82600501612e07565b1115610db357610d716005820184612e11565b6040517f60a6d89800000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101839052604401610611565b805468010000000000000000900463ffffffff1615610e1b5780546040517f60b9df730000000000000000000000000000000000000000000000000000000081526801000000000000000090910463ffffffff16600482015260248101839052604401610611565b83158015610e555750805463ffffffff166000908152600b602052604090205473ffffffffffffffffffffffffffffffffffffffff163314155b15610e8e576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610611565b6001810154610e9f90600790612e1d565b506002810154610eb190600990612e1d565b506000828152600c6020526040812080547fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001681556001810182905560028101829055600381018290559060058201818181610f0d8282614033565b5050505050507f5254e609a97bab37b7cc79fe128f85c097bd6015c6e1624ae0ba392eb975320582604051610f4491815260200190565b60405180910390a15050600101610cd7565b50505050565b6000805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610f56576000848483818110610f9657610f96614aa2565b9050602002810190610fa89190614bcb565b610fb190614c09565b6040808201516000908152600c6020908152828220805463ffffffff168352600b82528383208451808601909552805473ffffffffffffffffffffffffffffffffffffffff168552600181018054969750919593949390928401919061101690614b55565b80601f016020809104026020016040519081016040528092919081815260200182805461104290614b55565b801561108f5780601f106110645761010080835404028352916020019161108f565b820191906000526020600020905b81548152906001019060200180831161107257829003601f168201915b5050509190925250505060018301549091506110df5782604001516040517fd82f6adb00000000000000000000000000000000000000000000000000000000815260040161061191815260200190565b841580156111045750805173ffffffffffffffffffffffffffffffffffffffff163314155b1561113d576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610611565b6020830151611178576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001820154602084015181146111f957602084015161119990600790612d69565b156111d0576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602084015160018401556111e5600782612e1d565b5060208401516111f79060079061390b565b505b606084015161123c5783606001516040517f37d8976500000000000000000000000000000000000000000000000000000000815260040161061191815260200190565b6080840151805160000361127e57806040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106119190614ce6565b8354600090859060049061129f90640100000000900463ffffffff16614ba8565b91906101000a81548163ffffffff021916908363ffffffff1602179055905060005b8251811015611384576112f78382815181106112df576112df614aa2565b60200260200101516003612d6990919063ffffffff16565b61132f57826040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106119190614ce6565b61137b83828151811061134457611344614aa2565b60200260200101518760040160008563ffffffff1663ffffffff16815260200190815260200160002061390b90919063ffffffff16565b506001016112c1565b50845468010000000000000000900463ffffffff1680156114e55763ffffffff8082166000908152600d60209081526040808320805464010000000090049094168352600190930181528282206002018054845181840281018401909552808552929392909183018282801561141957602002820191906000526020600020905b815481526020019060010190808311611405575b5050505050905060005b81518110156114e25761147882828151811061144157611441614aa2565b60200260200101518960040160008763ffffffff1663ffffffff168152602001908152602001600020612d6990919063ffffffff16565b6114da5781818151811061148e5761148e614aa2565b6020026020010151836040517f03dcd86200000000000000000000000000000000000000000000000000000000815260040161061192919091825263ffffffff16602082015260400190565b600101611423565b50505b60006114f387600501613917565b905060005b81518163ffffffff161015611639576000828263ffffffff168151811061152157611521614aa2565b60209081029190910181015163ffffffff8082166000908152600d845260408082208054640100000000900490931682526001909201845281812060020180548351818702810187019094528084529395509093919290918301828280156115a857602002820191906000526020600020905b815481526020019060010190808311611594575b5050505050905060005b8151811015611625576116078282815181106115d0576115d0614aa2565b60200260200101518c60040160008a63ffffffff1663ffffffff168152602001908152602001600020612d6990919063ffffffff16565b61161d5781818151811061148e5761148e614aa2565b6001016115b2565b5050508061163290614ba8565b90506114f8565b50875187547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff90911690811788556040808a015160028a0181905560608b015160038b01556020808c01518351928352908201527f4b5b465e22eea0c3d40c30e936643245b80d19b2dcf75788c0699fe8d8db645b910160405180910390a25050505050505050806001019050610f7a565b6116d9612d84565b60005b8181101561086f5760008383838181106116f8576116f8614aa2565b905060200281019061170a9190614d2a565b61171390614d5e565b805190915073ffffffffffffffffffffffffffffffffffffffff16611764576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e54604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815263ffffffff9095166000818152600b909252939020825181547fffffffffffffffffffffffff000000000000000000000000000000000000000016921691909117815592519192909160018201906117f09082614e18565b5050600e805490915060009061180b9063ffffffff16614ba8565b91906101000a81548163ffffffff021916908363ffffffff160217905550816000015173ffffffffffffffffffffffffffffffffffffffff168163ffffffff167f78e94ca80be2c30abc061b99e7eb8583b1254781734b1e3ce339abb57da2fe8e846020015160405161187e919061445a565b60405180910390a350506001016116dc565b63ffffffff8083166000908152600d602090815260408083208054640100000000900490941680845260019094018252808320858452600301909152812080546060938493909290916118e290614b55565b80601f016020809104026020016040519081016040528092919081815260200182805461190e90614b55565b801561195b5780601f106119305761010080835404028352916020019161195b565b820191906000526020600020905b81548152906001019060200180831161193e57829003601f168201915b5050506000888152600260208190526040909120015492935060609262010000900473ffffffffffffffffffffffffffffffffffffffff16159150611a6e905057600086815260026020819052604091829020015490517f8318ed5d00000000000000000000000000000000000000000000000000000000815263ffffffff891660048201526201000090910473ffffffffffffffffffffffffffffffffffffffff1690638318ed5d90602401600060405180830381865afa158015611a25573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611a6b9190810190614f32565b90505b9093509150505b9250929050565b604080516101008101825260008082526020820181905291810182905260608082018390526080820183905260a082019290925260c0810182905260e081019190915260408051610100810182526000848152600c6020908152838220805463ffffffff8082168652640100000000820481168487018190526801000000000000000090920416858701526001820154606086015260028201546080860152600382015460a0860152835260040190529190912060c0820190611b3e90613917565b8152602001611b61600c6000868152602001908152602001600020600501613917565b905292915050565b611b71612d84565b60005b8181101561086f576000838383818110611b9057611b90614aa2565b905060200201359050611bad816003612d6990919063ffffffff16565b611be6576040517fe181733f00000000000000000000000000000000000000000000000000000000815260048101829052602401610611565b611bf160058261390b565b611c2a576040517ff7d7a29400000000000000000000000000000000000000000000000000000000815260048101829052602401610611565b60405181907fdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf2190600090a250600101611b74565b600e5460609063ffffffff166000611c77600183614b00565b63ffffffff1667ffffffffffffffff811115611c9557611c9561422c565b604051908082528060200260200182016040528015611cdb57816020015b604080518082019091526000815260606020820152815260200190600190039081611cb35790505b509050600060015b8363ffffffff168163ffffffff161015611e2b5763ffffffff81166000908152600b602052604090205473ffffffffffffffffffffffffffffffffffffffff1615611e235763ffffffff81166000908152600b60209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191611d7790614b55565b80601f0160208091040260200160405190810160405280929190818152602001828054611da390614b55565b8015611df05780601f10611dc557610100808354040283529160200191611df0565b820191906000526020600020905b815481529060010190602001808311611dd357829003601f168201915b505050505081525050838381518110611e0b57611e0b614aa2565b602002602001018190525081611e2090614b1d565b91505b600101611ce3565b50600e546109ba9060019063ffffffff16614b00565b611e49612d84565b60005b8181101561086f576000838383818110611e6857611e68614aa2565b9050602002810190611e7a9190614bcb565b611e8390614faf565b90506000611e998260000151836020015161062c565b9050611ea660038261390b565b611edf576040517febf5255100000000000000000000000000000000000000000000000000000000815260048101829052602401610611565b611ee98183613924565b5050600101611e4c565b60015473ffffffffffffffffffffffffffffffffffffffff163314611f74576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610611565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6000805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610f5657600084848381811061202a5761202a614aa2565b905060200281019061203c9190614bcb565b61204590614c09565b805163ffffffff166000908152600b602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff16825260018101805495965093949193909284019161209b90614b55565b80601f01602080910402602001604051908101604052809291908181526020018280546120c790614b55565b80156121145780601f106120e957610100808354040283529160200191612114565b820191906000526020600020905b8154815290600101906020018083116120f757829003601f168201915b50505091909252505081519192505073ffffffffffffffffffffffffffffffffffffffff1661217a5781516040517fadd9ae1e00000000000000000000000000000000000000000000000000000000815263ffffffff9091166004820152602401610611565b8315801561219f5750805173ffffffffffffffffffffffffffffffffffffffff163314155b156121d8576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610611565b6040808301516000908152600c6020522060018101541561222d5782604001516040517f5461848300000000000000000000000000000000000000000000000000000000815260040161061191815260200190565b60408301516122705782604001516040517f64e2ee9200000000000000000000000000000000000000000000000000000000815260040161061191815260200190565b6020830151158061228d5750602083015161228d90600790612d69565b156122c4576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608301516123075782606001516040517f37d8976500000000000000000000000000000000000000000000000000000000815260040161061191815260200190565b6080830151805160000361234957806040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106119190614ce6565b8154829060049061236790640100000000900463ffffffff16614ba8565b82546101009290920a63ffffffff818102199093169183160217909155825464010000000090041660005b825181101561243d576123b08382815181106112df576112df614aa2565b6123e857826040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106119190614ce6565b6124348382815181106123fd576123fd614aa2565b60200260200101518560040160008563ffffffff1663ffffffff16815260200190815260200160002061390b90919063ffffffff16565b50600101612392565b5060608501516003840155845183547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff9182161784556040860151600285015560208601516001850181905561249d916007919061390b16565b5060408501516124af9060099061390b565b50845160408087015160208089015183519283529082015263ffffffff909216917f74becb12a5e8fd0e98077d02dfba8f647c9670c9df177e42c2418cf17a636f05910160405180910390a2505050505080600101905061200e565b82811461254e576040517fab8b67c60000000000000000000000000000000000000000000000000000000081526004810184905260248101829052604401610611565b6000805473ffffffffffffffffffffffffffffffffffffffff16905b8481101561284357600086868381811061258657612586614aa2565b905060200201602081019061259b91906145f6565b63ffffffff81166000908152600b6020526040902080549192509073ffffffffffffffffffffffffffffffffffffffff1661260a576040517fadd9ae1e00000000000000000000000000000000000000000000000000000000815263ffffffff83166004820152602401610611565b600086868581811061261e5761261e614aa2565b90506020028101906126309190614d2a565b61263990614d5e565b805190915073ffffffffffffffffffffffffffffffffffffffff1661268a576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815473ffffffffffffffffffffffffffffffffffffffff1633148015906126c757503373ffffffffffffffffffffffffffffffffffffffff861614155b15612700576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610611565b8051825473ffffffffffffffffffffffffffffffffffffffff908116911614158061277c5750602080820151604051612739920161445a565b60405160208183030381529060405280519060200120826001016040516020016127639190615055565b6040516020818303038152906040528051906020012014155b1561283557805182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602081015160018301906127d69082614e18565b50806000015173ffffffffffffffffffffffffffffffffffffffff168363ffffffff167f86f41145bde5dd7f523305452e4aad3685508c181432ec733d5f345009358a28836020015160405161282c919061445a565b60405180910390a35b50505080600101905061256a565b505050505050565b61288c6040805160e0810182526000808252606060208301819052928201839052909182019081526020016000815260006020820181905260409091015290565b6040805160e081018252838152600084815260026020908152929020805491928301916128b890614b55565b80601f01602080910402602001604051908101604052809291908181526020018280546128e490614b55565b80156129315780601f1061290657610100808354040283529160200191612931565b820191906000526020600020905b81548152906001019060200180831161291457829003601f168201915b5050505050815260200160026000858152602001908152602001600020600101805461295c90614b55565b80601f016020809104026020016040519081016040528092919081815260200182805461298890614b55565b80156129d55780601f106129aa576101008083540402835291602001916129d5565b820191906000526020600020905b8154815290600101906020018083116129b857829003601f168201915b50505091835250506000848152600260208181526040909220015491019060ff166003811115612a0757612a0761487a565b815260008481526002602081815260409092200154910190610100900460ff166001811115612a3857612a3861487a565b81526000848152600260208181526040928390209091015462010000900473ffffffffffffffffffffffffffffffffffffffff169083015201612a7c600585612d69565b1515905292915050565b612a8e612d84565b600e805460009164010000000090910463ffffffff16906004612ab083614ba8565b82546101009290920a63ffffffff81810219909316918316021790915581166000818152600d602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001684179055815160a08101835292835260019083015286151590820152841515606082015260ff84166080820152909150612b469089908990899089906130f4565b5050505050505050565b60606000612b5e6003613917565b90506000815167ffffffffffffffff811115612b7c57612b7c61422c565b604051908082528060200260200182016040528015612bee57816020015b612bdb6040805160e0810182526000808252606060208301819052928201839052909182019081526020016000815260006020820181905260409091015290565b815260200190600190039081612b9a5790505b50905060005b82518110156109ca57612c1f838281518110612c1257612c12614aa2565b602002602001015161284b565b828281518110612c3157612c31614aa2565b6020908102919091010152600101612bf4565b60606000612c526009613917565b90506000815167ffffffffffffffff811115612c7057612c7061422c565b604051908082528060200260200182016040528015612cff57816020015b60408051610100810182526000808252602080830182905292820181905260608083018290526080830182905260a083019190915260c0820181905260e082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181612c8e5790505b50905060005b82518110156109ca57612d30838281518110612d2357612d23614aa2565b6020026020010151611a7c565b828281518110612d4257612d42614aa2565b6020908102919091010152600101612d05565b612d5d612d84565b612d6681613b0c565b50565b600081815260018301602052604081205415155b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612e05576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610611565b565b6000610626825490565b6000612d7d8383613c01565b6000612d7d8383613c2b565b6040805160e0810182526000808252602080830182905282840182905260608084018390526080840183905260a0840181905260c084015263ffffffff8581168352600d8252848320805464010000000090049091168084526001909101825284832060028101805487518186028101860190985280885295969295919493909190830182828015612eda57602002820191906000526020600020905b815481526020019060010190808311612ec6575b505050505090506000815167ffffffffffffffff811115612efd57612efd61422c565b604051908082528060200260200182016040528015612f4357816020015b604080518082019091526000815260606020820152815260200190600190039081612f1b5790505b50905060005b815181101561305b576040518060400160405280848381518110612f6f57612f6f614aa2565b60200260200101518152602001856003016000868581518110612f9457612f94614aa2565b602002602001015181526020019081526020016000208054612fb590614b55565b80601f0160208091040260200160405190810160405280929190818152602001828054612fe190614b55565b801561302e5780601f106130035761010080835404028352916020019161302e565b820191906000526020600020905b81548152906001019060200180831161301157829003601f168201915b505050505081525082828151811061304857613048614aa2565b6020908102919091010152600101612f49565b506040805160e08101825263ffffffff8089166000818152600d6020818152868320548086168752948b168187015260ff680100000000000000008604811697870197909752690100000000000000000085048716151560608701529290915290526a010000000000000000000090049091161515608082015260a081016130e285613917565b81526020019190915295945050505050565b805163ffffffff9081166000908152600d602090815260408083208286015190941683526001909301905220608082015160ff161580613146575060808201518590613141906001615103565b60ff16115b1561318f5760808201516040517f25b4d61800000000000000000000000000000000000000000000000000000000815260ff909116600482015260248101869052604401610611565b6001826020015163ffffffff16111561327757815163ffffffff166000908152600d6020908152604082209084015160019182019183916131d09190614b00565b63ffffffff1663ffffffff168152602001908152602001600020905060005b6131f882612e07565b81101561327457613227846000015163ffffffff16600c60006107778587600001612e1190919063ffffffff16565b50600c60006132368484612e11565b8152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff1690556001016131ef565b50505b60005b858110156134b1576132a787878381811061329757613297614aa2565b859260209091020135905061390b565b6133085782518787838181106132bf576132bf614aa2565b6040517f636e405700000000000000000000000000000000000000000000000000000000815263ffffffff90941660048501526020029190910135602483015250604401610611565b82606001511561345f57825163ffffffff16600c600089898581811061333057613330614aa2565b602090810292909201358352508101919091526040016000205468010000000000000000900463ffffffff16148015906133aa5750600c600088888481811061337b5761337b614aa2565b602090810292909201358352508101919091526040016000205468010000000000000000900463ffffffff1615155b1561340c5782518787838181106133c3576133c3614aa2565b6040517f60b9df7300000000000000000000000000000000000000000000000000000000815263ffffffff90941660048501526020029190910135602483015250604401610611565b8251600c600089898581811061342457613424614aa2565b90506020020135815260200190815260200160002060000160086101000a81548163ffffffff021916908363ffffffff1602179055506134a9565b82516134a79063ffffffff16600c60008a8a8681811061348157613481614aa2565b90506020020135815260200190815260200160002060050161390b90919063ffffffff16565b505b60010161327a565b5060005b838110156138bf57368585838181106134d0576134d0614aa2565b90506020028101906134e29190614d2a565b90506134f060038235612d69565b613529576040517fe181733f00000000000000000000000000000000000000000000000000000000815281356004820152602401610611565b61353560058235612d69565b1561356f576040517ff7d7a29400000000000000000000000000000000000000000000000000000000815281356004820152602401610611565b803560009081526003840160205260408120805461358c90614b55565b905011156135d85783516040517f3927d08000000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015281356024820152604401610611565b60005b878110156136e25761367f8235600c60008c8c868181106135fe576135fe614aa2565b9050602002013581526020019081526020016000206004016000600c60008e8e8881811061362e5761362e614aa2565b90506020020135815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff1663ffffffff168152602001908152602001600020612d6990919063ffffffff16565b6136da5788888281811061369557613695614aa2565b6040517fa7e792500000000000000000000000000000000000000000000000000000000081526020909102929092013560048301525082356024820152604401610611565b6001016135db565b506002830180546001810182556000918252602091829020833591015561370b9082018261511c565b82356000908152600386016020526040902091613729919083615181565b50604080850151855163ffffffff9081166000908152600d602090815284822080549415156901000000000000000000027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff90951694909417909355606088015188518316825284822080549115156a0100000000000000000000027fffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffff9092169190911790556080880151885183168252848220805460ff9290921668010000000000000000027fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff909216919091179055828801805189518416835294909120805494909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff909416939093179055855191516138b692918435908c908c9061387c9088018861511c565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613d1e92505050565b506001016134b5565b50815160208084015160405163ffffffff91821681529216917ff264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c1581703651910160405180910390a2505050505050565b6000612d7d8383613dff565b60606000612d7d83613e4e565b608081015173ffffffffffffffffffffffffffffffffffffffff16156139c65761397281608001517f78bea72100000000000000000000000000000000000000000000000000000000613eaa565b6139c65760808101516040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610611565b6000828152600260205260409020815182919081906139e59082614e18565b50602082015160018201906139fa9082614e18565b5060408201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001836003811115613a3c57613a3c61487a565b021790555060608201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100836001811115613a8357613a8361487a565b0217905550608091909101516002909101805473ffffffffffffffffffffffffffffffffffffffff90921662010000027fffffffffffffffffffff0000000000000000000000000000000000000000ffff90921691909117905560405182907f04f0a9bcf3f3a3b42a4d7ca081119755f82ebe43e0d30c8f7292c4fe0dc4a2ae90600090a25050565b3373ffffffffffffffffffffffffffffffffffffffff821603613b8b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610611565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000826000018281548110613c1857613c18614aa2565b9060005260206000200154905092915050565b60008181526001830160205260408120548015613d14576000613c4f60018361529c565b8554909150600090613c639060019061529c565b9050818114613cc8576000866000018281548110613c8357613c83614aa2565b9060005260206000200154905080876000018481548110613ca657613ca6614aa2565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613cd957613cd96152af565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610626565b6000915050610626565b6000848152600260208190526040909120015462010000900473ffffffffffffffffffffffffffffffffffffffff161561284357600084815260026020819052604091829020015490517ffba64a7c0000000000000000000000000000000000000000000000000000000081526201000090910473ffffffffffffffffffffffffffffffffffffffff169063fba64a7c90613dc5908690869086908b908d906004016152de565b600060405180830381600087803b158015613ddf57600080fd5b505af1158015613df3573d6000803e3d6000fd5b50505050505050505050565b6000818152600183016020526040812054613e4657508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610626565b506000610626565b606081600001805480602002602001604051908101604052809291908181526020018280548015613e9e57602002820191906000526020600020905b815481526020019060010190808311613e8a575b50505050509050919050565b6000613eb583613ec6565b8015612d7d5750612d7d8383613f2a565b6000613ef2827f01ffc9a700000000000000000000000000000000000000000000000000000000613f2a565b80156106265750613f23827fffffffff00000000000000000000000000000000000000000000000000000000613f2a565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015613fe2575060208210155b8015613fee5750600081115b979650505050505050565b50805461400590614b55565b6000825580601f10614015575050565b601f016020900490600052602060002090810190612d66919061404d565b5080546000825590600052602060002090810190612d6691905b5b80821115614062576000815560010161404e565b5090565b60008083601f84011261407857600080fd5b50813567ffffffffffffffff81111561409057600080fd5b6020830191508360208260051b8501011115611a7557600080fd5b600080602083850312156140be57600080fd5b823567ffffffffffffffff8111156140d557600080fd5b6140e185828601614066565b90969095509350505050565b60008151808452602080850194506020840160005b8381101561411e57815187529582019590820190600101614102565b509495945050505050565b600061010063ffffffff80845116855280602085015116602086015280604085015116604086015250606083015160608501526080830151608085015260a083015160a085015260c08301518160c0860152614187828601826140ed565b91505060e083015184820360e08601526141a182826140ed565b95945050505050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561421f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261420d858351614129565b945092850192908501906001016141d3565b5092979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561427e5761427e61422c565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156142cb576142cb61422c565b604052919050565b600067ffffffffffffffff8211156142ed576142ed61422c565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261432a57600080fd5b813561433d614338826142d3565b614284565b81815284602083860101111561435257600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561438257600080fd5b823567ffffffffffffffff8082111561439a57600080fd5b6143a686838701614319565b935060208501359150808211156143bc57600080fd5b506143c985828601614319565b9150509250929050565b6000602082840312156143e557600080fd5b5035919050565b60005b838110156144075781810151838201526020016143ef565b50506000910152565b600081518084526144288160208601602086016143ec565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000612d7d6020830184614410565b600082825180855260208086019550808260051b84010181860160005b848110156144ea578583037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001895281518051845284015160408585018190526144d681860183614410565b9a86019a945050509083019060010161448a565b5090979650505050505050565b600063ffffffff8083511684528060208401511660208501525060ff604083015116604084015260608201511515606084015260808201511515608084015260a082015160e060a085015261454f60e08501826140ed565b905060c083015184820360c08601526141a1828261446d565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561421f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526145cb8583516144f7565b94509285019290850190600101614591565b803563ffffffff811681146145f157600080fd5b919050565b60006020828403121561460857600080fd5b612d7d826145dd565b73ffffffffffffffffffffffffffffffffffffffff815116825260006020820151604060208501526146466040850182614410565b949350505050565b602081526000612d7d6020830184614611565b602081526000612d7d60208301846144f7565b803580151581146145f157600080fd5b803560ff811681146145f157600080fd5b600080600080600080600060a0888a0312156146b057600080fd5b6146b9886145dd565b9650602088013567ffffffffffffffff808211156146d657600080fd5b6146e28b838c01614066565b909850965060408a01359150808211156146fb57600080fd5b506147088a828b01614066565b909550935061471b905060608901614674565b915061472960808901614684565b905092959891949750929550565b6000806040838503121561474a57600080fd5b614753836145dd565b946020939093013593505050565b6040815260006147746040830185614410565b82810360208401526141a18185614410565b602081526000612d7d6020830184614129565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561421f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526147fc858351614611565b945092850192908501906001016147c2565b6000806000806040858703121561482457600080fd5b843567ffffffffffffffff8082111561483c57600080fd5b61484888838901614066565b9096509450602087013591508082111561486157600080fd5b5061486e87828801614066565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b805182526000602082015160e060208501526148c860e0850182614410565b9050604083015184820360408601526148e18282614410565b9150506060830151600481106148f9576148f961487a565b60608501526080830151600281106149135761491361487a565b8060808601525060a083015161494160a086018273ffffffffffffffffffffffffffffffffffffffff169052565b5060c083015161062260c086018215159052565b602081526000612d7d60208301846148a9565b600080600080600080600060a0888a03121561498357600080fd5b873567ffffffffffffffff8082111561499b57600080fd5b6149a78b838c01614066565b909950975060208a01359150808211156149c057600080fd5b506149cd8a828b01614066565b90965094506149e0905060408901614674565b925061471b60608901614674565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561421f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452614a518583516148a9565b94509285019290850190600101614a17565b803573ffffffffffffffffffffffffffffffffffffffff811681146145f157600080fd5b600060208284031215614a9957600080fd5b612d7d82614a63565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b63ffffffff8281168282160390808211156109ca576109ca614ad1565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614b4e57614b4e614ad1565b5060010190565b600181811c90821680614b6957607f821691505b602082108103614ba2577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600063ffffffff808316818103614bc157614bc1614ad1565b6001019392505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61833603018112614bff57600080fd5b9190910192915050565b600060a08236031215614c1b57600080fd5b614c2361425b565b614c2c836145dd565b8152602080840135818301526040840135604083015260608401356060830152608084013567ffffffffffffffff80821115614c6757600080fd5b9085019036601f830112614c7a57600080fd5b813581811115614c8c57614c8c61422c565b8060051b9150614c9d848301614284565b8181529183018401918481019036841115614cb757600080fd5b938501935b83851015614cd557843582529385019390850190614cbc565b608087015250939695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015614d1e57835183529284019291840191600101614d02565b50909695505050505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112614bff57600080fd5b600060408236031215614d7057600080fd5b6040516040810167ffffffffffffffff8282108183111715614d9457614d9461422c565b81604052614da185614a63565b83526020850135915080821115614db757600080fd5b50614dc436828601614319565b60208301525092915050565b601f82111561086f576000816000526020600020601f850160051c81016020861015614df95750805b601f850160051c820191505b8181101561284357828155600101614e05565b815167ffffffffffffffff811115614e3257614e3261422c565b614e4681614e408454614b55565b84614dd0565b602080601f831160018114614e995760008415614e635750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612843565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015614ee657888601518255948401946001909101908401614ec7565b5085821015614f2257878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600060208284031215614f4457600080fd5b815167ffffffffffffffff811115614f5b57600080fd5b8201601f81018413614f6c57600080fd5b8051614f7a614338826142d3565b818152856020838501011115614f8f57600080fd5b6141a18260208301602086016143ec565b8035600281106145f157600080fd5b600060a08236031215614fc157600080fd5b614fc961425b565b823567ffffffffffffffff80821115614fe157600080fd5b614fed36838701614319565b8352602085013591508082111561500357600080fd5b5061501036828601614319565b60208301525060408301356004811061502857600080fd5b604082015261503960608401614fa0565b606082015261504a60808401614a63565b608082015292915050565b600060208083526000845461506981614b55565b806020870152604060018084166000811461508b57600181146150c5576150f5565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00851660408a0152604084151560051b8a010195506150f5565b89600052602060002060005b858110156150ec5781548b82018601529083019088016150d1565b8a016040019650505b509398975050505050505050565b60ff818116838216019081111561062657610626614ad1565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261515157600080fd5b83018035915067ffffffffffffffff82111561516c57600080fd5b602001915036819003821315611a7557600080fd5b67ffffffffffffffff8311156151995761519961422c565b6151ad836151a78354614b55565b83614dd0565b6000601f8411600181146151ff57600085156151c95750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355615295565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b8281101561524e578685013582556020948501946001909201910161522e565b5086821015615289577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b8181038181111561062657610626614ad1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6080815284608082015260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86111561531757600080fd5b8560051b808860a0850137820182810360a0908101602085015261533d90820187614410565b91505063ffffffff8085166040840152808416606084015250969550505050505056fea164736f6c6343000818000a", +} + +var CapabilitiesRegistryABI = CapabilitiesRegistryMetaData.ABI + +var CapabilitiesRegistryBin = CapabilitiesRegistryMetaData.Bin + +func DeployCapabilitiesRegistry(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *CapabilitiesRegistry, error) { + parsed, err := CapabilitiesRegistryMetaData.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(CapabilitiesRegistryBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &CapabilitiesRegistry{address: address, abi: *parsed, CapabilitiesRegistryCaller: CapabilitiesRegistryCaller{contract: contract}, CapabilitiesRegistryTransactor: CapabilitiesRegistryTransactor{contract: contract}, CapabilitiesRegistryFilterer: CapabilitiesRegistryFilterer{contract: contract}}, nil +} + +type CapabilitiesRegistry struct { + address common.Address + abi abi.ABI + CapabilitiesRegistryCaller + CapabilitiesRegistryTransactor + CapabilitiesRegistryFilterer +} + +type CapabilitiesRegistryCaller struct { + contract *bind.BoundContract +} + +type CapabilitiesRegistryTransactor struct { + contract *bind.BoundContract +} + +type CapabilitiesRegistryFilterer struct { + contract *bind.BoundContract +} + +type CapabilitiesRegistrySession struct { + Contract *CapabilitiesRegistry + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type CapabilitiesRegistryCallerSession struct { + Contract *CapabilitiesRegistryCaller + CallOpts bind.CallOpts +} + +type CapabilitiesRegistryTransactorSession struct { + Contract *CapabilitiesRegistryTransactor + TransactOpts bind.TransactOpts +} + +type CapabilitiesRegistryRaw struct { + Contract *CapabilitiesRegistry +} + +type CapabilitiesRegistryCallerRaw struct { + Contract *CapabilitiesRegistryCaller +} + +type CapabilitiesRegistryTransactorRaw struct { + Contract *CapabilitiesRegistryTransactor +} + +func NewCapabilitiesRegistry(address common.Address, backend bind.ContractBackend) (*CapabilitiesRegistry, error) { + abi, err := abi.JSON(strings.NewReader(CapabilitiesRegistryABI)) + if err != nil { + return nil, err + } + contract, err := bindCapabilitiesRegistry(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &CapabilitiesRegistry{address: address, abi: abi, CapabilitiesRegistryCaller: CapabilitiesRegistryCaller{contract: contract}, CapabilitiesRegistryTransactor: CapabilitiesRegistryTransactor{contract: contract}, CapabilitiesRegistryFilterer: CapabilitiesRegistryFilterer{contract: contract}}, nil +} + +func NewCapabilitiesRegistryCaller(address common.Address, caller bind.ContractCaller) (*CapabilitiesRegistryCaller, error) { + contract, err := bindCapabilitiesRegistry(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &CapabilitiesRegistryCaller{contract: contract}, nil +} + +func NewCapabilitiesRegistryTransactor(address common.Address, transactor bind.ContractTransactor) (*CapabilitiesRegistryTransactor, error) { + contract, err := bindCapabilitiesRegistry(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &CapabilitiesRegistryTransactor{contract: contract}, nil +} + +func NewCapabilitiesRegistryFilterer(address common.Address, filterer bind.ContractFilterer) (*CapabilitiesRegistryFilterer, error) { + contract, err := bindCapabilitiesRegistry(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &CapabilitiesRegistryFilterer{contract: contract}, nil +} + +func bindCapabilitiesRegistry(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := CapabilitiesRegistryMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _CapabilitiesRegistry.Contract.CapabilitiesRegistryCaller.contract.Call(opts, result, method, params...) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.CapabilitiesRegistryTransactor.contract.Transfer(opts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.CapabilitiesRegistryTransactor.contract.Transact(opts, method, params...) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _CapabilitiesRegistry.Contract.contract.Call(opts, result, method, params...) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.contract.Transfer(opts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.contract.Transact(opts, method, params...) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetCapabilities(opts *bind.CallOpts) ([]CapabilitiesRegistryCapabilityInfo, error) { + var out []interface{} + err := _CapabilitiesRegistry.contract.Call(opts, &out, "getCapabilities") + + if err != nil { + return *new([]CapabilitiesRegistryCapabilityInfo), err + } + + out0 := *abi.ConvertType(out[0], new([]CapabilitiesRegistryCapabilityInfo)).(*[]CapabilitiesRegistryCapabilityInfo) + + return out0, err + +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetCapabilities() ([]CapabilitiesRegistryCapabilityInfo, error) { + return _CapabilitiesRegistry.Contract.GetCapabilities(&_CapabilitiesRegistry.CallOpts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetCapabilities() ([]CapabilitiesRegistryCapabilityInfo, error) { + return _CapabilitiesRegistry.Contract.GetCapabilities(&_CapabilitiesRegistry.CallOpts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetCapability(opts *bind.CallOpts, hashedId [32]byte) (CapabilitiesRegistryCapabilityInfo, error) { + var out []interface{} + err := _CapabilitiesRegistry.contract.Call(opts, &out, "getCapability", hashedId) + + if err != nil { + return *new(CapabilitiesRegistryCapabilityInfo), err + } + + out0 := *abi.ConvertType(out[0], new(CapabilitiesRegistryCapabilityInfo)).(*CapabilitiesRegistryCapabilityInfo) + + return out0, err + +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetCapability(hashedId [32]byte) (CapabilitiesRegistryCapabilityInfo, error) { + return _CapabilitiesRegistry.Contract.GetCapability(&_CapabilitiesRegistry.CallOpts, hashedId) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetCapability(hashedId [32]byte) (CapabilitiesRegistryCapabilityInfo, error) { + return _CapabilitiesRegistry.Contract.GetCapability(&_CapabilitiesRegistry.CallOpts, hashedId) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetCapabilityConfigs(opts *bind.CallOpts, donId uint32, capabilityId [32]byte) ([]byte, []byte, error) { + var out []interface{} + err := _CapabilitiesRegistry.contract.Call(opts, &out, "getCapabilityConfigs", donId, capabilityId) + + if err != nil { + return *new([]byte), *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + out1 := *abi.ConvertType(out[1], new([]byte)).(*[]byte) + + return out0, out1, err + +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetCapabilityConfigs(donId uint32, capabilityId [32]byte) ([]byte, []byte, error) { + return _CapabilitiesRegistry.Contract.GetCapabilityConfigs(&_CapabilitiesRegistry.CallOpts, donId, capabilityId) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetCapabilityConfigs(donId uint32, capabilityId [32]byte) ([]byte, []byte, error) { + return _CapabilitiesRegistry.Contract.GetCapabilityConfigs(&_CapabilitiesRegistry.CallOpts, donId, capabilityId) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetDON(opts *bind.CallOpts, donId uint32) (CapabilitiesRegistryDONInfo, error) { + var out []interface{} + err := _CapabilitiesRegistry.contract.Call(opts, &out, "getDON", donId) + + if err != nil { + return *new(CapabilitiesRegistryDONInfo), err + } + + out0 := *abi.ConvertType(out[0], new(CapabilitiesRegistryDONInfo)).(*CapabilitiesRegistryDONInfo) + + return out0, err + +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetDON(donId uint32) (CapabilitiesRegistryDONInfo, error) { + return _CapabilitiesRegistry.Contract.GetDON(&_CapabilitiesRegistry.CallOpts, donId) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetDON(donId uint32) (CapabilitiesRegistryDONInfo, error) { + return _CapabilitiesRegistry.Contract.GetDON(&_CapabilitiesRegistry.CallOpts, donId) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetDONs(opts *bind.CallOpts) ([]CapabilitiesRegistryDONInfo, error) { + var out []interface{} + err := _CapabilitiesRegistry.contract.Call(opts, &out, "getDONs") + + if err != nil { + return *new([]CapabilitiesRegistryDONInfo), err + } + + out0 := *abi.ConvertType(out[0], new([]CapabilitiesRegistryDONInfo)).(*[]CapabilitiesRegistryDONInfo) + + return out0, err + +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetDONs() ([]CapabilitiesRegistryDONInfo, error) { + return _CapabilitiesRegistry.Contract.GetDONs(&_CapabilitiesRegistry.CallOpts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetDONs() ([]CapabilitiesRegistryDONInfo, error) { + return _CapabilitiesRegistry.Contract.GetDONs(&_CapabilitiesRegistry.CallOpts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetHashedCapabilityId(opts *bind.CallOpts, labelledName string, version string) ([32]byte, error) { + var out []interface{} + err := _CapabilitiesRegistry.contract.Call(opts, &out, "getHashedCapabilityId", labelledName, version) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetHashedCapabilityId(labelledName string, version string) ([32]byte, error) { + return _CapabilitiesRegistry.Contract.GetHashedCapabilityId(&_CapabilitiesRegistry.CallOpts, labelledName, version) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetHashedCapabilityId(labelledName string, version string) ([32]byte, error) { + return _CapabilitiesRegistry.Contract.GetHashedCapabilityId(&_CapabilitiesRegistry.CallOpts, labelledName, version) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetNextDONId(opts *bind.CallOpts) (uint32, error) { + var out []interface{} + err := _CapabilitiesRegistry.contract.Call(opts, &out, "getNextDONId") + + if err != nil { + return *new(uint32), err + } + + out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32) + + return out0, err + +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetNextDONId() (uint32, error) { + return _CapabilitiesRegistry.Contract.GetNextDONId(&_CapabilitiesRegistry.CallOpts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetNextDONId() (uint32, error) { + return _CapabilitiesRegistry.Contract.GetNextDONId(&_CapabilitiesRegistry.CallOpts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetNode(opts *bind.CallOpts, p2pId [32]byte) (INodeInfoProviderNodeInfo, error) { + var out []interface{} + err := _CapabilitiesRegistry.contract.Call(opts, &out, "getNode", p2pId) + + if err != nil { + return *new(INodeInfoProviderNodeInfo), err + } + + out0 := *abi.ConvertType(out[0], new(INodeInfoProviderNodeInfo)).(*INodeInfoProviderNodeInfo) + + return out0, err + +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetNode(p2pId [32]byte) (INodeInfoProviderNodeInfo, error) { + return _CapabilitiesRegistry.Contract.GetNode(&_CapabilitiesRegistry.CallOpts, p2pId) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetNode(p2pId [32]byte) (INodeInfoProviderNodeInfo, error) { + return _CapabilitiesRegistry.Contract.GetNode(&_CapabilitiesRegistry.CallOpts, p2pId) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetNodeOperator(opts *bind.CallOpts, nodeOperatorId uint32) (CapabilitiesRegistryNodeOperator, error) { + var out []interface{} + err := _CapabilitiesRegistry.contract.Call(opts, &out, "getNodeOperator", nodeOperatorId) + + if err != nil { + return *new(CapabilitiesRegistryNodeOperator), err + } + + out0 := *abi.ConvertType(out[0], new(CapabilitiesRegistryNodeOperator)).(*CapabilitiesRegistryNodeOperator) + + return out0, err + +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetNodeOperator(nodeOperatorId uint32) (CapabilitiesRegistryNodeOperator, error) { + return _CapabilitiesRegistry.Contract.GetNodeOperator(&_CapabilitiesRegistry.CallOpts, nodeOperatorId) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetNodeOperator(nodeOperatorId uint32) (CapabilitiesRegistryNodeOperator, error) { + return _CapabilitiesRegistry.Contract.GetNodeOperator(&_CapabilitiesRegistry.CallOpts, nodeOperatorId) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetNodeOperators(opts *bind.CallOpts) ([]CapabilitiesRegistryNodeOperator, error) { + var out []interface{} + err := _CapabilitiesRegistry.contract.Call(opts, &out, "getNodeOperators") + + if err != nil { + return *new([]CapabilitiesRegistryNodeOperator), err + } + + out0 := *abi.ConvertType(out[0], new([]CapabilitiesRegistryNodeOperator)).(*[]CapabilitiesRegistryNodeOperator) + + return out0, err + +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetNodeOperators() ([]CapabilitiesRegistryNodeOperator, error) { + return _CapabilitiesRegistry.Contract.GetNodeOperators(&_CapabilitiesRegistry.CallOpts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetNodeOperators() ([]CapabilitiesRegistryNodeOperator, error) { + return _CapabilitiesRegistry.Contract.GetNodeOperators(&_CapabilitiesRegistry.CallOpts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetNodes(opts *bind.CallOpts) ([]INodeInfoProviderNodeInfo, error) { + var out []interface{} + err := _CapabilitiesRegistry.contract.Call(opts, &out, "getNodes") + + if err != nil { + return *new([]INodeInfoProviderNodeInfo), err + } + + out0 := *abi.ConvertType(out[0], new([]INodeInfoProviderNodeInfo)).(*[]INodeInfoProviderNodeInfo) + + return out0, err + +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetNodes() ([]INodeInfoProviderNodeInfo, error) { + return _CapabilitiesRegistry.Contract.GetNodes(&_CapabilitiesRegistry.CallOpts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetNodes() ([]INodeInfoProviderNodeInfo, error) { + return _CapabilitiesRegistry.Contract.GetNodes(&_CapabilitiesRegistry.CallOpts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetNodesByP2PIds(opts *bind.CallOpts, p2pIds [][32]byte) ([]INodeInfoProviderNodeInfo, error) { + var out []interface{} + err := _CapabilitiesRegistry.contract.Call(opts, &out, "getNodesByP2PIds", p2pIds) + + if err != nil { + return *new([]INodeInfoProviderNodeInfo), err + } + + out0 := *abi.ConvertType(out[0], new([]INodeInfoProviderNodeInfo)).(*[]INodeInfoProviderNodeInfo) + + return out0, err + +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetNodesByP2PIds(p2pIds [][32]byte) ([]INodeInfoProviderNodeInfo, error) { + return _CapabilitiesRegistry.Contract.GetNodesByP2PIds(&_CapabilitiesRegistry.CallOpts, p2pIds) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetNodesByP2PIds(p2pIds [][32]byte) ([]INodeInfoProviderNodeInfo, error) { + return _CapabilitiesRegistry.Contract.GetNodesByP2PIds(&_CapabilitiesRegistry.CallOpts, p2pIds) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) IsCapabilityDeprecated(opts *bind.CallOpts, hashedCapabilityId [32]byte) (bool, error) { + var out []interface{} + err := _CapabilitiesRegistry.contract.Call(opts, &out, "isCapabilityDeprecated", hashedCapabilityId) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) IsCapabilityDeprecated(hashedCapabilityId [32]byte) (bool, error) { + return _CapabilitiesRegistry.Contract.IsCapabilityDeprecated(&_CapabilitiesRegistry.CallOpts, hashedCapabilityId) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) IsCapabilityDeprecated(hashedCapabilityId [32]byte) (bool, error) { + return _CapabilitiesRegistry.Contract.IsCapabilityDeprecated(&_CapabilitiesRegistry.CallOpts, hashedCapabilityId) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _CapabilitiesRegistry.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 (_CapabilitiesRegistry *CapabilitiesRegistrySession) Owner() (common.Address, error) { + return _CapabilitiesRegistry.Contract.Owner(&_CapabilitiesRegistry.CallOpts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) Owner() (common.Address, error) { + return _CapabilitiesRegistry.Contract.Owner(&_CapabilitiesRegistry.CallOpts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _CapabilitiesRegistry.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) TypeAndVersion() (string, error) { + return _CapabilitiesRegistry.Contract.TypeAndVersion(&_CapabilitiesRegistry.CallOpts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) TypeAndVersion() (string, error) { + return _CapabilitiesRegistry.Contract.TypeAndVersion(&_CapabilitiesRegistry.CallOpts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CapabilitiesRegistry.contract.Transact(opts, "acceptOwnership") +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) AcceptOwnership() (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.AcceptOwnership(&_CapabilitiesRegistry.TransactOpts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.AcceptOwnership(&_CapabilitiesRegistry.TransactOpts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) AddCapabilities(opts *bind.TransactOpts, capabilities []CapabilitiesRegistryCapability) (*types.Transaction, error) { + return _CapabilitiesRegistry.contract.Transact(opts, "addCapabilities", capabilities) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) AddCapabilities(capabilities []CapabilitiesRegistryCapability) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.AddCapabilities(&_CapabilitiesRegistry.TransactOpts, capabilities) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) AddCapabilities(capabilities []CapabilitiesRegistryCapability) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.AddCapabilities(&_CapabilitiesRegistry.TransactOpts, capabilities) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) AddDON(opts *bind.TransactOpts, nodes [][32]byte, capabilityConfigurations []CapabilitiesRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint8) (*types.Transaction, error) { + return _CapabilitiesRegistry.contract.Transact(opts, "addDON", nodes, capabilityConfigurations, isPublic, acceptsWorkflows, f) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) AddDON(nodes [][32]byte, capabilityConfigurations []CapabilitiesRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint8) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.AddDON(&_CapabilitiesRegistry.TransactOpts, nodes, capabilityConfigurations, isPublic, acceptsWorkflows, f) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) AddDON(nodes [][32]byte, capabilityConfigurations []CapabilitiesRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint8) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.AddDON(&_CapabilitiesRegistry.TransactOpts, nodes, capabilityConfigurations, isPublic, acceptsWorkflows, f) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) AddNodeOperators(opts *bind.TransactOpts, nodeOperators []CapabilitiesRegistryNodeOperator) (*types.Transaction, error) { + return _CapabilitiesRegistry.contract.Transact(opts, "addNodeOperators", nodeOperators) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) AddNodeOperators(nodeOperators []CapabilitiesRegistryNodeOperator) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.AddNodeOperators(&_CapabilitiesRegistry.TransactOpts, nodeOperators) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) AddNodeOperators(nodeOperators []CapabilitiesRegistryNodeOperator) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.AddNodeOperators(&_CapabilitiesRegistry.TransactOpts, nodeOperators) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) AddNodes(opts *bind.TransactOpts, nodes []CapabilitiesRegistryNodeParams) (*types.Transaction, error) { + return _CapabilitiesRegistry.contract.Transact(opts, "addNodes", nodes) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) AddNodes(nodes []CapabilitiesRegistryNodeParams) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.AddNodes(&_CapabilitiesRegistry.TransactOpts, nodes) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) AddNodes(nodes []CapabilitiesRegistryNodeParams) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.AddNodes(&_CapabilitiesRegistry.TransactOpts, nodes) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) DeprecateCapabilities(opts *bind.TransactOpts, hashedCapabilityIds [][32]byte) (*types.Transaction, error) { + return _CapabilitiesRegistry.contract.Transact(opts, "deprecateCapabilities", hashedCapabilityIds) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) DeprecateCapabilities(hashedCapabilityIds [][32]byte) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.DeprecateCapabilities(&_CapabilitiesRegistry.TransactOpts, hashedCapabilityIds) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) DeprecateCapabilities(hashedCapabilityIds [][32]byte) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.DeprecateCapabilities(&_CapabilitiesRegistry.TransactOpts, hashedCapabilityIds) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) RemoveDONs(opts *bind.TransactOpts, donIds []uint32) (*types.Transaction, error) { + return _CapabilitiesRegistry.contract.Transact(opts, "removeDONs", donIds) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) RemoveDONs(donIds []uint32) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.RemoveDONs(&_CapabilitiesRegistry.TransactOpts, donIds) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) RemoveDONs(donIds []uint32) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.RemoveDONs(&_CapabilitiesRegistry.TransactOpts, donIds) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) RemoveNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []uint32) (*types.Transaction, error) { + return _CapabilitiesRegistry.contract.Transact(opts, "removeNodeOperators", nodeOperatorIds) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) RemoveNodeOperators(nodeOperatorIds []uint32) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.RemoveNodeOperators(&_CapabilitiesRegistry.TransactOpts, nodeOperatorIds) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) RemoveNodeOperators(nodeOperatorIds []uint32) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.RemoveNodeOperators(&_CapabilitiesRegistry.TransactOpts, nodeOperatorIds) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) RemoveNodes(opts *bind.TransactOpts, removedNodeP2PIds [][32]byte) (*types.Transaction, error) { + return _CapabilitiesRegistry.contract.Transact(opts, "removeNodes", removedNodeP2PIds) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) RemoveNodes(removedNodeP2PIds [][32]byte) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.RemoveNodes(&_CapabilitiesRegistry.TransactOpts, removedNodeP2PIds) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) RemoveNodes(removedNodeP2PIds [][32]byte) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.RemoveNodes(&_CapabilitiesRegistry.TransactOpts, removedNodeP2PIds) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _CapabilitiesRegistry.contract.Transact(opts, "transferOwnership", to) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.TransferOwnership(&_CapabilitiesRegistry.TransactOpts, to) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.TransferOwnership(&_CapabilitiesRegistry.TransactOpts, to) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) UpdateDON(opts *bind.TransactOpts, donId uint32, nodes [][32]byte, capabilityConfigurations []CapabilitiesRegistryCapabilityConfiguration, isPublic bool, f uint8) (*types.Transaction, error) { + return _CapabilitiesRegistry.contract.Transact(opts, "updateDON", donId, nodes, capabilityConfigurations, isPublic, f) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) UpdateDON(donId uint32, nodes [][32]byte, capabilityConfigurations []CapabilitiesRegistryCapabilityConfiguration, isPublic bool, f uint8) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.UpdateDON(&_CapabilitiesRegistry.TransactOpts, donId, nodes, capabilityConfigurations, isPublic, f) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) UpdateDON(donId uint32, nodes [][32]byte, capabilityConfigurations []CapabilitiesRegistryCapabilityConfiguration, isPublic bool, f uint8) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.UpdateDON(&_CapabilitiesRegistry.TransactOpts, donId, nodes, capabilityConfigurations, isPublic, f) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) UpdateNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []uint32, nodeOperators []CapabilitiesRegistryNodeOperator) (*types.Transaction, error) { + return _CapabilitiesRegistry.contract.Transact(opts, "updateNodeOperators", nodeOperatorIds, nodeOperators) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) UpdateNodeOperators(nodeOperatorIds []uint32, nodeOperators []CapabilitiesRegistryNodeOperator) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.UpdateNodeOperators(&_CapabilitiesRegistry.TransactOpts, nodeOperatorIds, nodeOperators) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) UpdateNodeOperators(nodeOperatorIds []uint32, nodeOperators []CapabilitiesRegistryNodeOperator) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.UpdateNodeOperators(&_CapabilitiesRegistry.TransactOpts, nodeOperatorIds, nodeOperators) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) UpdateNodes(opts *bind.TransactOpts, nodes []CapabilitiesRegistryNodeParams) (*types.Transaction, error) { + return _CapabilitiesRegistry.contract.Transact(opts, "updateNodes", nodes) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) UpdateNodes(nodes []CapabilitiesRegistryNodeParams) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.UpdateNodes(&_CapabilitiesRegistry.TransactOpts, nodes) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) UpdateNodes(nodes []CapabilitiesRegistryNodeParams) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.UpdateNodes(&_CapabilitiesRegistry.TransactOpts, nodes) +} + +type CapabilitiesRegistryCapabilityConfiguredIterator struct { + Event *CapabilitiesRegistryCapabilityConfigured + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilitiesRegistryCapabilityConfiguredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryCapabilityConfigured) + 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(CapabilitiesRegistryCapabilityConfigured) + 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 *CapabilitiesRegistryCapabilityConfiguredIterator) Error() error { + return it.fail +} + +func (it *CapabilitiesRegistryCapabilityConfiguredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilitiesRegistryCapabilityConfigured struct { + HashedCapabilityId [32]byte + Raw types.Log +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterCapabilityConfigured(opts *bind.FilterOpts, hashedCapabilityId [][32]byte) (*CapabilitiesRegistryCapabilityConfiguredIterator, error) { + + var hashedCapabilityIdRule []interface{} + for _, hashedCapabilityIdItem := range hashedCapabilityId { + hashedCapabilityIdRule = append(hashedCapabilityIdRule, hashedCapabilityIdItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "CapabilityConfigured", hashedCapabilityIdRule) + if err != nil { + return nil, err + } + return &CapabilitiesRegistryCapabilityConfiguredIterator{contract: _CapabilitiesRegistry.contract, event: "CapabilityConfigured", logs: logs, sub: sub}, nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchCapabilityConfigured(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryCapabilityConfigured, hashedCapabilityId [][32]byte) (event.Subscription, error) { + + var hashedCapabilityIdRule []interface{} + for _, hashedCapabilityIdItem := range hashedCapabilityId { + hashedCapabilityIdRule = append(hashedCapabilityIdRule, hashedCapabilityIdItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.WatchLogs(opts, "CapabilityConfigured", hashedCapabilityIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilitiesRegistryCapabilityConfigured) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "CapabilityConfigured", 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 (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseCapabilityConfigured(log types.Log) (*CapabilitiesRegistryCapabilityConfigured, error) { + event := new(CapabilitiesRegistryCapabilityConfigured) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "CapabilityConfigured", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CapabilitiesRegistryCapabilityDeprecatedIterator struct { + Event *CapabilitiesRegistryCapabilityDeprecated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilitiesRegistryCapabilityDeprecatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryCapabilityDeprecated) + 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(CapabilitiesRegistryCapabilityDeprecated) + 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 *CapabilitiesRegistryCapabilityDeprecatedIterator) Error() error { + return it.fail +} + +func (it *CapabilitiesRegistryCapabilityDeprecatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilitiesRegistryCapabilityDeprecated struct { + HashedCapabilityId [32]byte + Raw types.Log +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterCapabilityDeprecated(opts *bind.FilterOpts, hashedCapabilityId [][32]byte) (*CapabilitiesRegistryCapabilityDeprecatedIterator, error) { + + var hashedCapabilityIdRule []interface{} + for _, hashedCapabilityIdItem := range hashedCapabilityId { + hashedCapabilityIdRule = append(hashedCapabilityIdRule, hashedCapabilityIdItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "CapabilityDeprecated", hashedCapabilityIdRule) + if err != nil { + return nil, err + } + return &CapabilitiesRegistryCapabilityDeprecatedIterator{contract: _CapabilitiesRegistry.contract, event: "CapabilityDeprecated", logs: logs, sub: sub}, nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchCapabilityDeprecated(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryCapabilityDeprecated, hashedCapabilityId [][32]byte) (event.Subscription, error) { + + var hashedCapabilityIdRule []interface{} + for _, hashedCapabilityIdItem := range hashedCapabilityId { + hashedCapabilityIdRule = append(hashedCapabilityIdRule, hashedCapabilityIdItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.WatchLogs(opts, "CapabilityDeprecated", hashedCapabilityIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilitiesRegistryCapabilityDeprecated) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "CapabilityDeprecated", 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 (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseCapabilityDeprecated(log types.Log) (*CapabilitiesRegistryCapabilityDeprecated, error) { + event := new(CapabilitiesRegistryCapabilityDeprecated) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "CapabilityDeprecated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CapabilitiesRegistryConfigSetIterator struct { + Event *CapabilitiesRegistryConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilitiesRegistryConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryConfigSet) + 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(CapabilitiesRegistryConfigSet) + 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 *CapabilitiesRegistryConfigSetIterator) Error() error { + return it.fail +} + +func (it *CapabilitiesRegistryConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilitiesRegistryConfigSet struct { + DonId uint32 + ConfigCount uint32 + Raw types.Log +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterConfigSet(opts *bind.FilterOpts, donId []uint32) (*CapabilitiesRegistryConfigSetIterator, error) { + + var donIdRule []interface{} + for _, donIdItem := range donId { + donIdRule = append(donIdRule, donIdItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "ConfigSet", donIdRule) + if err != nil { + return nil, err + } + return &CapabilitiesRegistryConfigSetIterator{contract: _CapabilitiesRegistry.contract, event: "ConfigSet", logs: logs, sub: sub}, nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryConfigSet, donId []uint32) (event.Subscription, error) { + + var donIdRule []interface{} + for _, donIdItem := range donId { + donIdRule = append(donIdRule, donIdItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.WatchLogs(opts, "ConfigSet", donIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilitiesRegistryConfigSet) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "ConfigSet", 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 (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseConfigSet(log types.Log) (*CapabilitiesRegistryConfigSet, error) { + event := new(CapabilitiesRegistryConfigSet) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "ConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CapabilitiesRegistryNodeAddedIterator struct { + Event *CapabilitiesRegistryNodeAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilitiesRegistryNodeAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryNodeAdded) + 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(CapabilitiesRegistryNodeAdded) + 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 *CapabilitiesRegistryNodeAddedIterator) Error() error { + return it.fail +} + +func (it *CapabilitiesRegistryNodeAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilitiesRegistryNodeAdded struct { + P2pId [32]byte + NodeOperatorId uint32 + Signer [32]byte + Raw types.Log +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterNodeAdded(opts *bind.FilterOpts, nodeOperatorId []uint32) (*CapabilitiesRegistryNodeAddedIterator, error) { + + var nodeOperatorIdRule []interface{} + for _, nodeOperatorIdItem := range nodeOperatorId { + nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "NodeAdded", nodeOperatorIdRule) + if err != nil { + return nil, err + } + return &CapabilitiesRegistryNodeAddedIterator{contract: _CapabilitiesRegistry.contract, event: "NodeAdded", logs: logs, sub: sub}, nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchNodeAdded(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeAdded, nodeOperatorId []uint32) (event.Subscription, error) { + + var nodeOperatorIdRule []interface{} + for _, nodeOperatorIdItem := range nodeOperatorId { + nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.WatchLogs(opts, "NodeAdded", nodeOperatorIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilitiesRegistryNodeAdded) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeAdded", 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 (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseNodeAdded(log types.Log) (*CapabilitiesRegistryNodeAdded, error) { + event := new(CapabilitiesRegistryNodeAdded) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CapabilitiesRegistryNodeOperatorAddedIterator struct { + Event *CapabilitiesRegistryNodeOperatorAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilitiesRegistryNodeOperatorAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryNodeOperatorAdded) + 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(CapabilitiesRegistryNodeOperatorAdded) + 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 *CapabilitiesRegistryNodeOperatorAddedIterator) Error() error { + return it.fail +} + +func (it *CapabilitiesRegistryNodeOperatorAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilitiesRegistryNodeOperatorAdded struct { + NodeOperatorId uint32 + Admin common.Address + Name string + Raw types.Log +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterNodeOperatorAdded(opts *bind.FilterOpts, nodeOperatorId []uint32, admin []common.Address) (*CapabilitiesRegistryNodeOperatorAddedIterator, error) { + + var nodeOperatorIdRule []interface{} + for _, nodeOperatorIdItem := range nodeOperatorId { + nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) + } + var adminRule []interface{} + for _, adminItem := range admin { + adminRule = append(adminRule, adminItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "NodeOperatorAdded", nodeOperatorIdRule, adminRule) + if err != nil { + return nil, err + } + return &CapabilitiesRegistryNodeOperatorAddedIterator{contract: _CapabilitiesRegistry.contract, event: "NodeOperatorAdded", logs: logs, sub: sub}, nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchNodeOperatorAdded(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeOperatorAdded, nodeOperatorId []uint32, admin []common.Address) (event.Subscription, error) { + + var nodeOperatorIdRule []interface{} + for _, nodeOperatorIdItem := range nodeOperatorId { + nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) + } + var adminRule []interface{} + for _, adminItem := range admin { + adminRule = append(adminRule, adminItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.WatchLogs(opts, "NodeOperatorAdded", nodeOperatorIdRule, adminRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilitiesRegistryNodeOperatorAdded) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeOperatorAdded", 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 (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseNodeOperatorAdded(log types.Log) (*CapabilitiesRegistryNodeOperatorAdded, error) { + event := new(CapabilitiesRegistryNodeOperatorAdded) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeOperatorAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CapabilitiesRegistryNodeOperatorRemovedIterator struct { + Event *CapabilitiesRegistryNodeOperatorRemoved + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilitiesRegistryNodeOperatorRemovedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryNodeOperatorRemoved) + 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(CapabilitiesRegistryNodeOperatorRemoved) + 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 *CapabilitiesRegistryNodeOperatorRemovedIterator) Error() error { + return it.fail +} + +func (it *CapabilitiesRegistryNodeOperatorRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilitiesRegistryNodeOperatorRemoved struct { + NodeOperatorId uint32 + Raw types.Log +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterNodeOperatorRemoved(opts *bind.FilterOpts, nodeOperatorId []uint32) (*CapabilitiesRegistryNodeOperatorRemovedIterator, error) { + + var nodeOperatorIdRule []interface{} + for _, nodeOperatorIdItem := range nodeOperatorId { + nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "NodeOperatorRemoved", nodeOperatorIdRule) + if err != nil { + return nil, err + } + return &CapabilitiesRegistryNodeOperatorRemovedIterator{contract: _CapabilitiesRegistry.contract, event: "NodeOperatorRemoved", logs: logs, sub: sub}, nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchNodeOperatorRemoved(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeOperatorRemoved, nodeOperatorId []uint32) (event.Subscription, error) { + + var nodeOperatorIdRule []interface{} + for _, nodeOperatorIdItem := range nodeOperatorId { + nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.WatchLogs(opts, "NodeOperatorRemoved", nodeOperatorIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilitiesRegistryNodeOperatorRemoved) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeOperatorRemoved", 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 (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseNodeOperatorRemoved(log types.Log) (*CapabilitiesRegistryNodeOperatorRemoved, error) { + event := new(CapabilitiesRegistryNodeOperatorRemoved) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeOperatorRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CapabilitiesRegistryNodeOperatorUpdatedIterator struct { + Event *CapabilitiesRegistryNodeOperatorUpdated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilitiesRegistryNodeOperatorUpdatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryNodeOperatorUpdated) + 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(CapabilitiesRegistryNodeOperatorUpdated) + 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 *CapabilitiesRegistryNodeOperatorUpdatedIterator) Error() error { + return it.fail +} + +func (it *CapabilitiesRegistryNodeOperatorUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilitiesRegistryNodeOperatorUpdated struct { + NodeOperatorId uint32 + Admin common.Address + Name string + Raw types.Log +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterNodeOperatorUpdated(opts *bind.FilterOpts, nodeOperatorId []uint32, admin []common.Address) (*CapabilitiesRegistryNodeOperatorUpdatedIterator, error) { + + var nodeOperatorIdRule []interface{} + for _, nodeOperatorIdItem := range nodeOperatorId { + nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) + } + var adminRule []interface{} + for _, adminItem := range admin { + adminRule = append(adminRule, adminItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "NodeOperatorUpdated", nodeOperatorIdRule, adminRule) + if err != nil { + return nil, err + } + return &CapabilitiesRegistryNodeOperatorUpdatedIterator{contract: _CapabilitiesRegistry.contract, event: "NodeOperatorUpdated", logs: logs, sub: sub}, nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchNodeOperatorUpdated(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeOperatorUpdated, nodeOperatorId []uint32, admin []common.Address) (event.Subscription, error) { + + var nodeOperatorIdRule []interface{} + for _, nodeOperatorIdItem := range nodeOperatorId { + nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) + } + var adminRule []interface{} + for _, adminItem := range admin { + adminRule = append(adminRule, adminItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.WatchLogs(opts, "NodeOperatorUpdated", nodeOperatorIdRule, adminRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilitiesRegistryNodeOperatorUpdated) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeOperatorUpdated", 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 (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseNodeOperatorUpdated(log types.Log) (*CapabilitiesRegistryNodeOperatorUpdated, error) { + event := new(CapabilitiesRegistryNodeOperatorUpdated) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeOperatorUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CapabilitiesRegistryNodeRemovedIterator struct { + Event *CapabilitiesRegistryNodeRemoved + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilitiesRegistryNodeRemovedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryNodeRemoved) + 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(CapabilitiesRegistryNodeRemoved) + 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 *CapabilitiesRegistryNodeRemovedIterator) Error() error { + return it.fail +} + +func (it *CapabilitiesRegistryNodeRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilitiesRegistryNodeRemoved struct { + P2pId [32]byte + Raw types.Log +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterNodeRemoved(opts *bind.FilterOpts) (*CapabilitiesRegistryNodeRemovedIterator, error) { + + logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "NodeRemoved") + if err != nil { + return nil, err + } + return &CapabilitiesRegistryNodeRemovedIterator{contract: _CapabilitiesRegistry.contract, event: "NodeRemoved", logs: logs, sub: sub}, nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchNodeRemoved(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeRemoved) (event.Subscription, error) { + + logs, sub, err := _CapabilitiesRegistry.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(CapabilitiesRegistryNodeRemoved) + if err := _CapabilitiesRegistry.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 (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseNodeRemoved(log types.Log) (*CapabilitiesRegistryNodeRemoved, error) { + event := new(CapabilitiesRegistryNodeRemoved) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CapabilitiesRegistryNodeUpdatedIterator struct { + Event *CapabilitiesRegistryNodeUpdated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilitiesRegistryNodeUpdatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryNodeUpdated) + 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(CapabilitiesRegistryNodeUpdated) + 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 *CapabilitiesRegistryNodeUpdatedIterator) Error() error { + return it.fail +} + +func (it *CapabilitiesRegistryNodeUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilitiesRegistryNodeUpdated struct { + P2pId [32]byte + NodeOperatorId uint32 + Signer [32]byte + Raw types.Log +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterNodeUpdated(opts *bind.FilterOpts, nodeOperatorId []uint32) (*CapabilitiesRegistryNodeUpdatedIterator, error) { + + var nodeOperatorIdRule []interface{} + for _, nodeOperatorIdItem := range nodeOperatorId { + nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "NodeUpdated", nodeOperatorIdRule) + if err != nil { + return nil, err + } + return &CapabilitiesRegistryNodeUpdatedIterator{contract: _CapabilitiesRegistry.contract, event: "NodeUpdated", logs: logs, sub: sub}, nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchNodeUpdated(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeUpdated, nodeOperatorId []uint32) (event.Subscription, error) { + + var nodeOperatorIdRule []interface{} + for _, nodeOperatorIdItem := range nodeOperatorId { + nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.WatchLogs(opts, "NodeUpdated", nodeOperatorIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilitiesRegistryNodeUpdated) + if err := _CapabilitiesRegistry.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 (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseNodeUpdated(log types.Log) (*CapabilitiesRegistryNodeUpdated, error) { + event := new(CapabilitiesRegistryNodeUpdated) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CapabilitiesRegistryOwnershipTransferRequestedIterator struct { + Event *CapabilitiesRegistryOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilitiesRegistryOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryOwnershipTransferRequested) + 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(CapabilitiesRegistryOwnershipTransferRequested) + 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 *CapabilitiesRegistryOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *CapabilitiesRegistryOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilitiesRegistryOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CapabilitiesRegistryOwnershipTransferRequestedIterator, 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 := _CapabilitiesRegistry.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &CapabilitiesRegistryOwnershipTransferRequestedIterator{contract: _CapabilitiesRegistry.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryOwnershipTransferRequested, 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 := _CapabilitiesRegistry.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(CapabilitiesRegistryOwnershipTransferRequested) + if err := _CapabilitiesRegistry.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 (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseOwnershipTransferRequested(log types.Log) (*CapabilitiesRegistryOwnershipTransferRequested, error) { + event := new(CapabilitiesRegistryOwnershipTransferRequested) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CapabilitiesRegistryOwnershipTransferredIterator struct { + Event *CapabilitiesRegistryOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilitiesRegistryOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryOwnershipTransferred) + 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(CapabilitiesRegistryOwnershipTransferred) + 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 *CapabilitiesRegistryOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *CapabilitiesRegistryOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilitiesRegistryOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CapabilitiesRegistryOwnershipTransferredIterator, 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 := _CapabilitiesRegistry.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &CapabilitiesRegistryOwnershipTransferredIterator{contract: _CapabilitiesRegistry.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryOwnershipTransferred, 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 := _CapabilitiesRegistry.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(CapabilitiesRegistryOwnershipTransferred) + if err := _CapabilitiesRegistry.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 (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseOwnershipTransferred(log types.Log) (*CapabilitiesRegistryOwnershipTransferred, error) { + event := new(CapabilitiesRegistryOwnershipTransferred) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistry) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _CapabilitiesRegistry.abi.Events["CapabilityConfigured"].ID: + return _CapabilitiesRegistry.ParseCapabilityConfigured(log) + case _CapabilitiesRegistry.abi.Events["CapabilityDeprecated"].ID: + return _CapabilitiesRegistry.ParseCapabilityDeprecated(log) + case _CapabilitiesRegistry.abi.Events["ConfigSet"].ID: + return _CapabilitiesRegistry.ParseConfigSet(log) + case _CapabilitiesRegistry.abi.Events["NodeAdded"].ID: + return _CapabilitiesRegistry.ParseNodeAdded(log) + case _CapabilitiesRegistry.abi.Events["NodeOperatorAdded"].ID: + return _CapabilitiesRegistry.ParseNodeOperatorAdded(log) + case _CapabilitiesRegistry.abi.Events["NodeOperatorRemoved"].ID: + return _CapabilitiesRegistry.ParseNodeOperatorRemoved(log) + case _CapabilitiesRegistry.abi.Events["NodeOperatorUpdated"].ID: + return _CapabilitiesRegistry.ParseNodeOperatorUpdated(log) + case _CapabilitiesRegistry.abi.Events["NodeRemoved"].ID: + return _CapabilitiesRegistry.ParseNodeRemoved(log) + case _CapabilitiesRegistry.abi.Events["NodeUpdated"].ID: + return _CapabilitiesRegistry.ParseNodeUpdated(log) + case _CapabilitiesRegistry.abi.Events["OwnershipTransferRequested"].ID: + return _CapabilitiesRegistry.ParseOwnershipTransferRequested(log) + case _CapabilitiesRegistry.abi.Events["OwnershipTransferred"].ID: + return _CapabilitiesRegistry.ParseOwnershipTransferred(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (CapabilitiesRegistryCapabilityConfigured) Topic() common.Hash { + return common.HexToHash("0x04f0a9bcf3f3a3b42a4d7ca081119755f82ebe43e0d30c8f7292c4fe0dc4a2ae") +} + +func (CapabilitiesRegistryCapabilityDeprecated) Topic() common.Hash { + return common.HexToHash("0xdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf21") +} + +func (CapabilitiesRegistryConfigSet) Topic() common.Hash { + return common.HexToHash("0xf264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c1581703651") +} + +func (CapabilitiesRegistryNodeAdded) Topic() common.Hash { + return common.HexToHash("0x74becb12a5e8fd0e98077d02dfba8f647c9670c9df177e42c2418cf17a636f05") +} + +func (CapabilitiesRegistryNodeOperatorAdded) Topic() common.Hash { + return common.HexToHash("0x78e94ca80be2c30abc061b99e7eb8583b1254781734b1e3ce339abb57da2fe8e") +} + +func (CapabilitiesRegistryNodeOperatorRemoved) Topic() common.Hash { + return common.HexToHash("0xa59268ca81d40429e65ccea5385b59cf2d3fc6519371dee92f8eb1dae5107a7a") +} + +func (CapabilitiesRegistryNodeOperatorUpdated) Topic() common.Hash { + return common.HexToHash("0x86f41145bde5dd7f523305452e4aad3685508c181432ec733d5f345009358a28") +} + +func (CapabilitiesRegistryNodeRemoved) Topic() common.Hash { + return common.HexToHash("0x5254e609a97bab37b7cc79fe128f85c097bd6015c6e1624ae0ba392eb9753205") +} + +func (CapabilitiesRegistryNodeUpdated) Topic() common.Hash { + return common.HexToHash("0x4b5b465e22eea0c3d40c30e936643245b80d19b2dcf75788c0699fe8d8db645b") +} + +func (CapabilitiesRegistryOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (CapabilitiesRegistryOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (_CapabilitiesRegistry *CapabilitiesRegistry) Address() common.Address { + return _CapabilitiesRegistry.address +} + +type CapabilitiesRegistryInterface interface { + GetCapabilities(opts *bind.CallOpts) ([]CapabilitiesRegistryCapabilityInfo, error) + + GetCapability(opts *bind.CallOpts, hashedId [32]byte) (CapabilitiesRegistryCapabilityInfo, error) + + GetCapabilityConfigs(opts *bind.CallOpts, donId uint32, capabilityId [32]byte) ([]byte, []byte, error) + + GetDON(opts *bind.CallOpts, donId uint32) (CapabilitiesRegistryDONInfo, error) + + GetDONs(opts *bind.CallOpts) ([]CapabilitiesRegistryDONInfo, error) + + GetHashedCapabilityId(opts *bind.CallOpts, labelledName string, version string) ([32]byte, error) + + GetNextDONId(opts *bind.CallOpts) (uint32, error) + + GetNode(opts *bind.CallOpts, p2pId [32]byte) (INodeInfoProviderNodeInfo, error) + + GetNodeOperator(opts *bind.CallOpts, nodeOperatorId uint32) (CapabilitiesRegistryNodeOperator, error) + + GetNodeOperators(opts *bind.CallOpts) ([]CapabilitiesRegistryNodeOperator, error) + + GetNodes(opts *bind.CallOpts) ([]INodeInfoProviderNodeInfo, error) + + GetNodesByP2PIds(opts *bind.CallOpts, p2pIds [][32]byte) ([]INodeInfoProviderNodeInfo, error) + + IsCapabilityDeprecated(opts *bind.CallOpts, hashedCapabilityId [32]byte) (bool, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + TypeAndVersion(opts *bind.CallOpts) (string, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + AddCapabilities(opts *bind.TransactOpts, capabilities []CapabilitiesRegistryCapability) (*types.Transaction, error) + + AddDON(opts *bind.TransactOpts, nodes [][32]byte, capabilityConfigurations []CapabilitiesRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint8) (*types.Transaction, error) + + AddNodeOperators(opts *bind.TransactOpts, nodeOperators []CapabilitiesRegistryNodeOperator) (*types.Transaction, error) + + AddNodes(opts *bind.TransactOpts, nodes []CapabilitiesRegistryNodeParams) (*types.Transaction, error) + + DeprecateCapabilities(opts *bind.TransactOpts, hashedCapabilityIds [][32]byte) (*types.Transaction, error) + + RemoveDONs(opts *bind.TransactOpts, donIds []uint32) (*types.Transaction, error) + + RemoveNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []uint32) (*types.Transaction, error) + + RemoveNodes(opts *bind.TransactOpts, removedNodeP2PIds [][32]byte) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + UpdateDON(opts *bind.TransactOpts, donId uint32, nodes [][32]byte, capabilityConfigurations []CapabilitiesRegistryCapabilityConfiguration, isPublic bool, f uint8) (*types.Transaction, error) + + UpdateNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []uint32, nodeOperators []CapabilitiesRegistryNodeOperator) (*types.Transaction, error) + + UpdateNodes(opts *bind.TransactOpts, nodes []CapabilitiesRegistryNodeParams) (*types.Transaction, error) + + FilterCapabilityConfigured(opts *bind.FilterOpts, hashedCapabilityId [][32]byte) (*CapabilitiesRegistryCapabilityConfiguredIterator, error) + + WatchCapabilityConfigured(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryCapabilityConfigured, hashedCapabilityId [][32]byte) (event.Subscription, error) + + ParseCapabilityConfigured(log types.Log) (*CapabilitiesRegistryCapabilityConfigured, error) + + FilterCapabilityDeprecated(opts *bind.FilterOpts, hashedCapabilityId [][32]byte) (*CapabilitiesRegistryCapabilityDeprecatedIterator, error) + + WatchCapabilityDeprecated(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryCapabilityDeprecated, hashedCapabilityId [][32]byte) (event.Subscription, error) + + ParseCapabilityDeprecated(log types.Log) (*CapabilitiesRegistryCapabilityDeprecated, error) + + FilterConfigSet(opts *bind.FilterOpts, donId []uint32) (*CapabilitiesRegistryConfigSetIterator, error) + + WatchConfigSet(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryConfigSet, donId []uint32) (event.Subscription, error) + + ParseConfigSet(log types.Log) (*CapabilitiesRegistryConfigSet, error) + + FilterNodeAdded(opts *bind.FilterOpts, nodeOperatorId []uint32) (*CapabilitiesRegistryNodeAddedIterator, error) + + WatchNodeAdded(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeAdded, nodeOperatorId []uint32) (event.Subscription, error) + + ParseNodeAdded(log types.Log) (*CapabilitiesRegistryNodeAdded, error) + + FilterNodeOperatorAdded(opts *bind.FilterOpts, nodeOperatorId []uint32, admin []common.Address) (*CapabilitiesRegistryNodeOperatorAddedIterator, error) + + WatchNodeOperatorAdded(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeOperatorAdded, nodeOperatorId []uint32, admin []common.Address) (event.Subscription, error) + + ParseNodeOperatorAdded(log types.Log) (*CapabilitiesRegistryNodeOperatorAdded, error) + + FilterNodeOperatorRemoved(opts *bind.FilterOpts, nodeOperatorId []uint32) (*CapabilitiesRegistryNodeOperatorRemovedIterator, error) + + WatchNodeOperatorRemoved(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeOperatorRemoved, nodeOperatorId []uint32) (event.Subscription, error) + + ParseNodeOperatorRemoved(log types.Log) (*CapabilitiesRegistryNodeOperatorRemoved, error) + + FilterNodeOperatorUpdated(opts *bind.FilterOpts, nodeOperatorId []uint32, admin []common.Address) (*CapabilitiesRegistryNodeOperatorUpdatedIterator, error) + + WatchNodeOperatorUpdated(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeOperatorUpdated, nodeOperatorId []uint32, admin []common.Address) (event.Subscription, error) + + ParseNodeOperatorUpdated(log types.Log) (*CapabilitiesRegistryNodeOperatorUpdated, error) + + FilterNodeRemoved(opts *bind.FilterOpts) (*CapabilitiesRegistryNodeRemovedIterator, error) + + WatchNodeRemoved(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeRemoved) (event.Subscription, error) + + ParseNodeRemoved(log types.Log) (*CapabilitiesRegistryNodeRemoved, error) + + FilterNodeUpdated(opts *bind.FilterOpts, nodeOperatorId []uint32) (*CapabilitiesRegistryNodeUpdatedIterator, error) + + WatchNodeUpdated(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeUpdated, nodeOperatorId []uint32) (event.Subscription, error) + + ParseNodeUpdated(log types.Log) (*CapabilitiesRegistryNodeUpdated, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CapabilitiesRegistryOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*CapabilitiesRegistryOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CapabilitiesRegistryOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*CapabilitiesRegistryOwnershipTransferred, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/keystone/generated/feeds_consumer_1_0_0/feeds_consumer.go b/core/gethwrappers/keystone/generated/feeds_consumer_1_0_0/feeds_consumer.go new file mode 100644 index 00000000000..8b618fbddb5 --- /dev/null +++ b/core/gethwrappers/keystone/generated/feeds_consumer_1_0_0/feeds_consumer.go @@ -0,0 +1,756 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package feeds_consumer + +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 KeystoneFeedsConsumerMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"UnauthorizedSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"}],\"name\":\"UnauthorizedWorkflowName\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"}],\"name\":\"UnauthorizedWorkflowOwner\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"feedId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint224\",\"name\":\"price\",\"type\":\"uint224\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"name\":\"FeedReceived\",\"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\":[{\"internalType\":\"bytes32\",\"name\":\"feedId\",\"type\":\"bytes32\"}],\"name\":\"getPrice\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"rawReport\",\"type\":\"bytes\"}],\"name\":\"onReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_allowedSendersList\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"_allowedWorkflowOwnersList\",\"type\":\"address[]\"},{\"internalType\":\"bytes10[]\",\"name\":\"_allowedWorkflowNamesList\",\"type\":\"bytes10[]\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6112d8806101576000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063805f21321161005b578063805f2132146101695780638da5cb5b1461017c578063e3401711146101a4578063f2fde38b146101b757600080fd5b806301ffc9a71461008257806331d98b3f146100aa57806379ba50971461015f575b600080fd5b610095610090366004610e2b565b6101ca565b60405190151581526020015b60405180910390f35b6101266100b8366004610e74565b6000908152600260209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff81168084527c010000000000000000000000000000000000000000000000000000000090910463ffffffff169290910182905291565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909316835263ffffffff9091166020830152016100a1565b610167610263565b005b610167610177366004610ed6565b610365565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100a1565b6101676101b2366004610f87565b6106e4565b6101676101c5366004611021565b610b24565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f805f213200000000000000000000000000000000000000000000000000000000148061025d57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146102e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3360009081526004602052604090205460ff166103b0576040517f3fcc3f170000000000000000000000000000000000000000000000000000000081523360048201526024016102e0565b6000806103f286868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610b3892505050565b7fffffffffffffffffffff000000000000000000000000000000000000000000008216600090815260086020526040902054919350915060ff16610486576040517f4b942f800000000000000000000000000000000000000000000000000000000081527fffffffffffffffffffff00000000000000000000000000000000000000000000831660048201526024016102e0565b73ffffffffffffffffffffffffffffffffffffffff811660009081526006602052604090205460ff166104fd576040517fbf24162300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016102e0565b600061050b848601866110fe565b905060005b81518110156106da57604051806040016040528083838151811061053657610536611210565b6020026020010151602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260200183838151811061057757610577611210565b60200260200101516040015163ffffffff16815250600260008484815181106105a2576105a2611210565b602090810291909101810151518252818101929092526040016000208251929091015163ffffffff167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909216919091179055815182908290811061062457610624611210565b6020026020010151600001517f2c30f5cb3caf4239d0f994ce539d7ef24817fa550169c388e3a110f02e40197d83838151811061066357610663611210565b60200260200101516020015184848151811061068157610681611210565b6020026020010151604001516040516106ca9291907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216825263ffffffff16602082015260400190565b60405180910390a2600101610510565b5050505050505050565b6106ec610b4e565b60005b60035463ffffffff8216101561078d5760006004600060038463ffffffff168154811061071e5761071e611210565b60009182526020808320919091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790556107868161123f565b90506106ef565b5060005b63ffffffff81168611156108355760016004600089898563ffffffff168181106107bd576107bd611210565b90506020020160208101906107d29190611021565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905561082e8161123f565b9050610791565b5061084260038787610cc6565b5060005b60055463ffffffff821610156108e45760006006600060058463ffffffff168154811061087557610875611210565b60009182526020808320919091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790556108dd8161123f565b9050610846565b5060005b63ffffffff811684111561098c5760016006600087878563ffffffff1681811061091457610914611210565b90506020020160208101906109299190611021565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790556109858161123f565b90506108e8565b5061099960058585610cc6565b5060005b60075463ffffffff82161015610a5a5760006008600060078463ffffffff16815481106109cc576109cc611210565b600091825260208083206003808404909101549206600a026101000a90910460b01b7fffffffffffffffffffff00000000000000000000000000000000000000000000168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055610a538161123f565b905061099d565b5060005b63ffffffff8116821115610b0e5760016008600085858563ffffffff16818110610a8a57610a8a611210565b9050602002016020810190610a9f9190611289565b7fffffffffffffffffffff00000000000000000000000000000000000000000000168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055610b078161123f565b9050610a5e565b50610b1b60078383610d4e565b50505050505050565b610b2c610b4e565b610b3581610bd1565b50565b6040810151604a90910151909160609190911c90565b60005473ffffffffffffffffffffffffffffffffffffffff163314610bcf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016102e0565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610c50576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016102e0565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b828054828255906000526020600020908101928215610d3e579160200282015b82811115610d3e5781547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff843516178255602090920191600190910190610ce6565b50610d4a929150610e16565b5090565b82805482825590600052602060002090600201600390048101928215610d3e5791602002820160005b83821115610dd757833575ffffffffffffffffffffffffffffffffffffffffffff191683826101000a81548169ffffffffffffffffffff021916908360b01c02179055509260200192600a01602081600901049283019260010302610d77565b8015610e0d5782816101000a81549069ffffffffffffffffffff0219169055600a01602081600901049283019260010302610dd7565b5050610d4a9291505b5b80821115610d4a5760008155600101610e17565b600060208284031215610e3d57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610e6d57600080fd5b9392505050565b600060208284031215610e8657600080fd5b5035919050565b60008083601f840112610e9f57600080fd5b50813567ffffffffffffffff811115610eb757600080fd5b602083019150836020828501011115610ecf57600080fd5b9250929050565b60008060008060408587031215610eec57600080fd5b843567ffffffffffffffff80821115610f0457600080fd5b610f1088838901610e8d565b90965094506020870135915080821115610f2957600080fd5b50610f3687828801610e8d565b95989497509550505050565b60008083601f840112610f5457600080fd5b50813567ffffffffffffffff811115610f6c57600080fd5b6020830191508360208260051b8501011115610ecf57600080fd5b60008060008060008060608789031215610fa057600080fd5b863567ffffffffffffffff80821115610fb857600080fd5b610fc48a838b01610f42565b90985096506020890135915080821115610fdd57600080fd5b610fe98a838b01610f42565b9096509450604089013591508082111561100257600080fd5b5061100f89828a01610f42565b979a9699509497509295939492505050565b60006020828403121561103357600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610e6d57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516060810167ffffffffffffffff811182821017156110a9576110a9611057565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156110f6576110f6611057565b604052919050565b6000602080838503121561111157600080fd5b823567ffffffffffffffff8082111561112957600080fd5b818501915085601f83011261113d57600080fd5b81358181111561114f5761114f611057565b61115d848260051b016110af565b8181528481019250606091820284018501918883111561117c57600080fd5b938501935b828510156112045780858a0312156111995760008081fd5b6111a1611086565b85358152868601357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146111d45760008081fd5b8188015260408681013563ffffffff811681146111f15760008081fd5b9082015284529384019392850192611181565b50979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600063ffffffff80831681810361127f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6001019392505050565b60006020828403121561129b57600080fd5b81357fffffffffffffffffffff0000000000000000000000000000000000000000000081168114610e6d57600080fdfea164736f6c6343000818000a", +} + +var KeystoneFeedsConsumerABI = KeystoneFeedsConsumerMetaData.ABI + +var KeystoneFeedsConsumerBin = KeystoneFeedsConsumerMetaData.Bin + +func DeployKeystoneFeedsConsumer(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *KeystoneFeedsConsumer, error) { + parsed, err := KeystoneFeedsConsumerMetaData.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(KeystoneFeedsConsumerBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &KeystoneFeedsConsumer{address: address, abi: *parsed, KeystoneFeedsConsumerCaller: KeystoneFeedsConsumerCaller{contract: contract}, KeystoneFeedsConsumerTransactor: KeystoneFeedsConsumerTransactor{contract: contract}, KeystoneFeedsConsumerFilterer: KeystoneFeedsConsumerFilterer{contract: contract}}, nil +} + +type KeystoneFeedsConsumer struct { + address common.Address + abi abi.ABI + KeystoneFeedsConsumerCaller + KeystoneFeedsConsumerTransactor + KeystoneFeedsConsumerFilterer +} + +type KeystoneFeedsConsumerCaller struct { + contract *bind.BoundContract +} + +type KeystoneFeedsConsumerTransactor struct { + contract *bind.BoundContract +} + +type KeystoneFeedsConsumerFilterer struct { + contract *bind.BoundContract +} + +type KeystoneFeedsConsumerSession struct { + Contract *KeystoneFeedsConsumer + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type KeystoneFeedsConsumerCallerSession struct { + Contract *KeystoneFeedsConsumerCaller + CallOpts bind.CallOpts +} + +type KeystoneFeedsConsumerTransactorSession struct { + Contract *KeystoneFeedsConsumerTransactor + TransactOpts bind.TransactOpts +} + +type KeystoneFeedsConsumerRaw struct { + Contract *KeystoneFeedsConsumer +} + +type KeystoneFeedsConsumerCallerRaw struct { + Contract *KeystoneFeedsConsumerCaller +} + +type KeystoneFeedsConsumerTransactorRaw struct { + Contract *KeystoneFeedsConsumerTransactor +} + +func NewKeystoneFeedsConsumer(address common.Address, backend bind.ContractBackend) (*KeystoneFeedsConsumer, error) { + abi, err := abi.JSON(strings.NewReader(KeystoneFeedsConsumerABI)) + if err != nil { + return nil, err + } + contract, err := bindKeystoneFeedsConsumer(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &KeystoneFeedsConsumer{address: address, abi: abi, KeystoneFeedsConsumerCaller: KeystoneFeedsConsumerCaller{contract: contract}, KeystoneFeedsConsumerTransactor: KeystoneFeedsConsumerTransactor{contract: contract}, KeystoneFeedsConsumerFilterer: KeystoneFeedsConsumerFilterer{contract: contract}}, nil +} + +func NewKeystoneFeedsConsumerCaller(address common.Address, caller bind.ContractCaller) (*KeystoneFeedsConsumerCaller, error) { + contract, err := bindKeystoneFeedsConsumer(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &KeystoneFeedsConsumerCaller{contract: contract}, nil +} + +func NewKeystoneFeedsConsumerTransactor(address common.Address, transactor bind.ContractTransactor) (*KeystoneFeedsConsumerTransactor, error) { + contract, err := bindKeystoneFeedsConsumer(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &KeystoneFeedsConsumerTransactor{contract: contract}, nil +} + +func NewKeystoneFeedsConsumerFilterer(address common.Address, filterer bind.ContractFilterer) (*KeystoneFeedsConsumerFilterer, error) { + contract, err := bindKeystoneFeedsConsumer(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &KeystoneFeedsConsumerFilterer{contract: contract}, nil +} + +func bindKeystoneFeedsConsumer(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := KeystoneFeedsConsumerMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _KeystoneFeedsConsumer.Contract.KeystoneFeedsConsumerCaller.contract.Call(opts, result, method, params...) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _KeystoneFeedsConsumer.Contract.KeystoneFeedsConsumerTransactor.contract.Transfer(opts) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _KeystoneFeedsConsumer.Contract.KeystoneFeedsConsumerTransactor.contract.Transact(opts, method, params...) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _KeystoneFeedsConsumer.Contract.contract.Call(opts, result, method, params...) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _KeystoneFeedsConsumer.Contract.contract.Transfer(opts) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _KeystoneFeedsConsumer.Contract.contract.Transact(opts, method, params...) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerCaller) GetPrice(opts *bind.CallOpts, feedId [32]byte) (*big.Int, uint32, error) { + var out []interface{} + err := _KeystoneFeedsConsumer.contract.Call(opts, &out, "getPrice", feedId) + + if err != nil { + return *new(*big.Int), *new(uint32), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + out1 := *abi.ConvertType(out[1], new(uint32)).(*uint32) + + return out0, out1, err + +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerSession) GetPrice(feedId [32]byte) (*big.Int, uint32, error) { + return _KeystoneFeedsConsumer.Contract.GetPrice(&_KeystoneFeedsConsumer.CallOpts, feedId) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerCallerSession) GetPrice(feedId [32]byte) (*big.Int, uint32, error) { + return _KeystoneFeedsConsumer.Contract.GetPrice(&_KeystoneFeedsConsumer.CallOpts, feedId) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _KeystoneFeedsConsumer.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 (_KeystoneFeedsConsumer *KeystoneFeedsConsumerSession) Owner() (common.Address, error) { + return _KeystoneFeedsConsumer.Contract.Owner(&_KeystoneFeedsConsumer.CallOpts) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerCallerSession) Owner() (common.Address, error) { + return _KeystoneFeedsConsumer.Contract.Owner(&_KeystoneFeedsConsumer.CallOpts) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + var out []interface{} + err := _KeystoneFeedsConsumer.contract.Call(opts, &out, "supportsInterface", interfaceId) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _KeystoneFeedsConsumer.Contract.SupportsInterface(&_KeystoneFeedsConsumer.CallOpts, interfaceId) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _KeystoneFeedsConsumer.Contract.SupportsInterface(&_KeystoneFeedsConsumer.CallOpts, interfaceId) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _KeystoneFeedsConsumer.contract.Transact(opts, "acceptOwnership") +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerSession) AcceptOwnership() (*types.Transaction, error) { + return _KeystoneFeedsConsumer.Contract.AcceptOwnership(&_KeystoneFeedsConsumer.TransactOpts) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _KeystoneFeedsConsumer.Contract.AcceptOwnership(&_KeystoneFeedsConsumer.TransactOpts) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerTransactor) OnReport(opts *bind.TransactOpts, metadata []byte, rawReport []byte) (*types.Transaction, error) { + return _KeystoneFeedsConsumer.contract.Transact(opts, "onReport", metadata, rawReport) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerSession) OnReport(metadata []byte, rawReport []byte) (*types.Transaction, error) { + return _KeystoneFeedsConsumer.Contract.OnReport(&_KeystoneFeedsConsumer.TransactOpts, metadata, rawReport) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerTransactorSession) OnReport(metadata []byte, rawReport []byte) (*types.Transaction, error) { + return _KeystoneFeedsConsumer.Contract.OnReport(&_KeystoneFeedsConsumer.TransactOpts, metadata, rawReport) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerTransactor) SetConfig(opts *bind.TransactOpts, _allowedSendersList []common.Address, _allowedWorkflowOwnersList []common.Address, _allowedWorkflowNamesList [][10]byte) (*types.Transaction, error) { + return _KeystoneFeedsConsumer.contract.Transact(opts, "setConfig", _allowedSendersList, _allowedWorkflowOwnersList, _allowedWorkflowNamesList) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerSession) SetConfig(_allowedSendersList []common.Address, _allowedWorkflowOwnersList []common.Address, _allowedWorkflowNamesList [][10]byte) (*types.Transaction, error) { + return _KeystoneFeedsConsumer.Contract.SetConfig(&_KeystoneFeedsConsumer.TransactOpts, _allowedSendersList, _allowedWorkflowOwnersList, _allowedWorkflowNamesList) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerTransactorSession) SetConfig(_allowedSendersList []common.Address, _allowedWorkflowOwnersList []common.Address, _allowedWorkflowNamesList [][10]byte) (*types.Transaction, error) { + return _KeystoneFeedsConsumer.Contract.SetConfig(&_KeystoneFeedsConsumer.TransactOpts, _allowedSendersList, _allowedWorkflowOwnersList, _allowedWorkflowNamesList) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _KeystoneFeedsConsumer.contract.Transact(opts, "transferOwnership", to) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _KeystoneFeedsConsumer.Contract.TransferOwnership(&_KeystoneFeedsConsumer.TransactOpts, to) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _KeystoneFeedsConsumer.Contract.TransferOwnership(&_KeystoneFeedsConsumer.TransactOpts, to) +} + +type KeystoneFeedsConsumerFeedReceivedIterator struct { + Event *KeystoneFeedsConsumerFeedReceived + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *KeystoneFeedsConsumerFeedReceivedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(KeystoneFeedsConsumerFeedReceived) + 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(KeystoneFeedsConsumerFeedReceived) + 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 *KeystoneFeedsConsumerFeedReceivedIterator) Error() error { + return it.fail +} + +func (it *KeystoneFeedsConsumerFeedReceivedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type KeystoneFeedsConsumerFeedReceived struct { + FeedId [32]byte + Price *big.Int + Timestamp uint32 + Raw types.Log +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerFilterer) FilterFeedReceived(opts *bind.FilterOpts, feedId [][32]byte) (*KeystoneFeedsConsumerFeedReceivedIterator, error) { + + var feedIdRule []interface{} + for _, feedIdItem := range feedId { + feedIdRule = append(feedIdRule, feedIdItem) + } + + logs, sub, err := _KeystoneFeedsConsumer.contract.FilterLogs(opts, "FeedReceived", feedIdRule) + if err != nil { + return nil, err + } + return &KeystoneFeedsConsumerFeedReceivedIterator{contract: _KeystoneFeedsConsumer.contract, event: "FeedReceived", logs: logs, sub: sub}, nil +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerFilterer) WatchFeedReceived(opts *bind.WatchOpts, sink chan<- *KeystoneFeedsConsumerFeedReceived, feedId [][32]byte) (event.Subscription, error) { + + var feedIdRule []interface{} + for _, feedIdItem := range feedId { + feedIdRule = append(feedIdRule, feedIdItem) + } + + logs, sub, err := _KeystoneFeedsConsumer.contract.WatchLogs(opts, "FeedReceived", feedIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(KeystoneFeedsConsumerFeedReceived) + if err := _KeystoneFeedsConsumer.contract.UnpackLog(event, "FeedReceived", 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 (_KeystoneFeedsConsumer *KeystoneFeedsConsumerFilterer) ParseFeedReceived(log types.Log) (*KeystoneFeedsConsumerFeedReceived, error) { + event := new(KeystoneFeedsConsumerFeedReceived) + if err := _KeystoneFeedsConsumer.contract.UnpackLog(event, "FeedReceived", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type KeystoneFeedsConsumerOwnershipTransferRequestedIterator struct { + Event *KeystoneFeedsConsumerOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *KeystoneFeedsConsumerOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(KeystoneFeedsConsumerOwnershipTransferRequested) + 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(KeystoneFeedsConsumerOwnershipTransferRequested) + 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 *KeystoneFeedsConsumerOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *KeystoneFeedsConsumerOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type KeystoneFeedsConsumerOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*KeystoneFeedsConsumerOwnershipTransferRequestedIterator, 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 := _KeystoneFeedsConsumer.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &KeystoneFeedsConsumerOwnershipTransferRequestedIterator{contract: _KeystoneFeedsConsumer.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *KeystoneFeedsConsumerOwnershipTransferRequested, 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 := _KeystoneFeedsConsumer.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(KeystoneFeedsConsumerOwnershipTransferRequested) + if err := _KeystoneFeedsConsumer.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 (_KeystoneFeedsConsumer *KeystoneFeedsConsumerFilterer) ParseOwnershipTransferRequested(log types.Log) (*KeystoneFeedsConsumerOwnershipTransferRequested, error) { + event := new(KeystoneFeedsConsumerOwnershipTransferRequested) + if err := _KeystoneFeedsConsumer.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type KeystoneFeedsConsumerOwnershipTransferredIterator struct { + Event *KeystoneFeedsConsumerOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *KeystoneFeedsConsumerOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(KeystoneFeedsConsumerOwnershipTransferred) + 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(KeystoneFeedsConsumerOwnershipTransferred) + 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 *KeystoneFeedsConsumerOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *KeystoneFeedsConsumerOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type KeystoneFeedsConsumerOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*KeystoneFeedsConsumerOwnershipTransferredIterator, 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 := _KeystoneFeedsConsumer.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &KeystoneFeedsConsumerOwnershipTransferredIterator{contract: _KeystoneFeedsConsumer.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *KeystoneFeedsConsumerOwnershipTransferred, 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 := _KeystoneFeedsConsumer.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(KeystoneFeedsConsumerOwnershipTransferred) + if err := _KeystoneFeedsConsumer.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 (_KeystoneFeedsConsumer *KeystoneFeedsConsumerFilterer) ParseOwnershipTransferred(log types.Log) (*KeystoneFeedsConsumerOwnershipTransferred, error) { + event := new(KeystoneFeedsConsumerOwnershipTransferred) + if err := _KeystoneFeedsConsumer.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumer) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _KeystoneFeedsConsumer.abi.Events["FeedReceived"].ID: + return _KeystoneFeedsConsumer.ParseFeedReceived(log) + case _KeystoneFeedsConsumer.abi.Events["OwnershipTransferRequested"].ID: + return _KeystoneFeedsConsumer.ParseOwnershipTransferRequested(log) + case _KeystoneFeedsConsumer.abi.Events["OwnershipTransferred"].ID: + return _KeystoneFeedsConsumer.ParseOwnershipTransferred(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (KeystoneFeedsConsumerFeedReceived) Topic() common.Hash { + return common.HexToHash("0x2c30f5cb3caf4239d0f994ce539d7ef24817fa550169c388e3a110f02e40197d") +} + +func (KeystoneFeedsConsumerOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (KeystoneFeedsConsumerOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumer) Address() common.Address { + return _KeystoneFeedsConsumer.address +} + +type KeystoneFeedsConsumerInterface interface { + GetPrice(opts *bind.CallOpts, feedId [32]byte) (*big.Int, uint32, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + OnReport(opts *bind.TransactOpts, metadata []byte, rawReport []byte) (*types.Transaction, error) + + SetConfig(opts *bind.TransactOpts, _allowedSendersList []common.Address, _allowedWorkflowOwnersList []common.Address, _allowedWorkflowNamesList [][10]byte) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + FilterFeedReceived(opts *bind.FilterOpts, feedId [][32]byte) (*KeystoneFeedsConsumerFeedReceivedIterator, error) + + WatchFeedReceived(opts *bind.WatchOpts, sink chan<- *KeystoneFeedsConsumerFeedReceived, feedId [][32]byte) (event.Subscription, error) + + ParseFeedReceived(log types.Log) (*KeystoneFeedsConsumerFeedReceived, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*KeystoneFeedsConsumerOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *KeystoneFeedsConsumerOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*KeystoneFeedsConsumerOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*KeystoneFeedsConsumerOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *KeystoneFeedsConsumerOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*KeystoneFeedsConsumerOwnershipTransferred, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/keystone/generated/forwarder_1_0_0/forwarder.go b/core/gethwrappers/keystone/generated/forwarder_1_0_0/forwarder.go new file mode 100644 index 00000000000..c62e4904deb --- /dev/null +++ b/core/gethwrappers/keystone/generated/forwarder_1_0_0/forwarder.go @@ -0,0 +1,1337 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package 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 +) + +type IRouterTransmissionInfo struct { + TransmissionId [32]byte + State uint8 + Transmitter common.Address + InvalidReceiver bool + Success bool + GasLimit *big.Int +} + +var KeystoneForwarderMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transmissionId\",\"type\":\"bytes32\"}],\"name\":\"AlreadyAttempted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"}],\"name\":\"DuplicateSigner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numSigners\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxSigners\",\"type\":\"uint256\"}],\"name\":\"ExcessSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FaultToleranceMustBePositive\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transmissionId\",\"type\":\"bytes32\"}],\"name\":\"InsufficientGasForRouting\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numSigners\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minSigners\",\"type\":\"uint256\"}],\"name\":\"InsufficientSigners\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"configId\",\"type\":\"uint64\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"received\",\"type\":\"uint256\"}],\"name\":\"InvalidSignatureCount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"}],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedForwarder\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"configVersion\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"}],\"name\":\"ForwarderAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"}],\"name\":\"ForwarderRemoved\",\"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\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"workflowExecutionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes2\",\"name\":\"reportId\",\"type\":\"bytes2\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"result\",\"type\":\"bool\"}],\"name\":\"ReportProcessed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"}],\"name\":\"addForwarder\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configVersion\",\"type\":\"uint32\"}],\"name\":\"clearConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"workflowExecutionId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes2\",\"name\":\"reportId\",\"type\":\"bytes2\"}],\"name\":\"getTransmissionId\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"workflowExecutionId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes2\",\"name\":\"reportId\",\"type\":\"bytes2\"}],\"name\":\"getTransmissionInfo\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transmissionId\",\"type\":\"bytes32\"},{\"internalType\":\"enumIRouter.TransmissionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"invalidReceiver\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"uint80\",\"name\":\"gasLimit\",\"type\":\"uint80\"}],\"internalType\":\"structIRouter.TransmissionInfo\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"workflowExecutionId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes2\",\"name\":\"reportId\",\"type\":\"bytes2\"}],\"name\":\"getTransmitter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"}],\"name\":\"isForwarder\",\"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\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"}],\"name\":\"removeForwarder\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"rawReport\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"reportContext\",\"type\":\"bytes\"},{\"internalType\":\"bytes[]\",\"name\":\"signatures\",\"type\":\"bytes[]\"}],\"name\":\"report\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transmissionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"validatedReport\",\"type\":\"bytes\"}],\"name\":\"route\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configVersion\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"}],\"name\":\"setConfig\",\"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\"}]", + Bin: "0x60806040523480156200001157600080fd5b503380600081620000695760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156200009c576200009c81620000bf565b5050306000908152600360205260409020805460ff19166001179055506200016a565b336001600160a01b03821603620001195760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000060565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61218f806200017a6000396000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c806379ba50971161008c578063abcef55411610066578063abcef5541461035d578063ee59d26c14610396578063ef6e17a0146103a9578063f2fde38b146103bc57600080fd5b806379ba50971461025e5780638864b864146102665780638da5cb5b1461033f57600080fd5b8063272cbd93116100c8578063272cbd9314610179578063354bdd66146101995780634d93172d146102385780635c41d2fe1461024b57600080fd5b806311289565146100ef578063181f5a7714610104578063233fd52d14610156575b600080fd5b6101026100fd366004611a33565b6103cf565b005b6101406040518060400160405280601781526020017f4b657973746f6e65466f7277617264657220312e302e3000000000000000000081525081565b60405161014d9190611ade565b60405180910390f35b610169610164366004611b4b565b610989565b604051901515815260200161014d565b61018c610187366004611bd3565b610d4a565b60405161014d9190611c67565b61022a6101a7366004611bd3565b6040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606085901b166020820152603481018390527fffff000000000000000000000000000000000000000000000000000000000000821660548201526000906056016040516020818303038152906040528051906020012090509392505050565b60405190815260200161014d565b610102610246366004611d0f565b610f50565b610102610259366004611d0f565b610fcc565b61010261104b565b61031a610274366004611bd3565b6040805160609490941b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660208086019190915260348501939093527fffff000000000000000000000000000000000000000000000000000000000000919091166054840152805160368185030181526056909301815282519282019290922060009081526004909152205473ffffffffffffffffffffffffffffffffffffffff1690565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014d565b60005473ffffffffffffffffffffffffffffffffffffffff1661031a565b61016961036b366004611d0f565b73ffffffffffffffffffffffffffffffffffffffff1660009081526003602052604090205460ff1690565b6101026103a4366004611d3e565b611148565b6101026103b7366004611dbc565b611525565b6101026103ca366004611d0f565b6115c5565b606d85101561040a576040517fb55ac75400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600061044e89898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115d992505050565b67ffffffffffffffff8216600090815260026020526040812080549497509195509193509160ff16908190036104c1576040517fdf3b81ea00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b856104cd826001611e1e565b60ff161461051f576104e0816001611e1e565b6040517fd6022e8e00000000000000000000000000000000000000000000000000000000815260ff9091166004820152602481018790526044016104b8565b60008b8b604051610531929190611e37565b60405190819003812061054a918c908c90602001611e47565b60405160208183030381529060405280519060200120905061056a6118c0565b60005b888110156107ec573660008b8b8481811061058a5761058a611e61565b905060200281019061059c9190611e90565b9092509050604181146105df5781816040517f2adfdc300000000000000000000000000000000000000000000000000000000081526004016104b8929190611f3e565b6000600186848460408181106105f7576105f7611e61565b61060992013560f81c9050601b611e1e565b610617602060008789611f5a565b61062091611f84565b61062e60406020888a611f5a565b61063791611f84565b6040805160008152602081018083529590955260ff909316928401929092526060830152608082015260a0016020604051602081039080840390855afa158015610685573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015173ffffffffffffffffffffffffffffffffffffffff8116600090815260028c0160205291822054909350915081900361072b576040517fbf18af4300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024016104b8565b600086826020811061073f5761073f611e61565b602002015173ffffffffffffffffffffffffffffffffffffffff16146107a9576040517fe021c4f200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024016104b8565b818682602081106107bc576107bc611e61565b73ffffffffffffffffffffffffffffffffffffffff909216602092909202015250506001909201915061056d9050565b50506040805160608f901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602080830191909152603482018990527fffff0000000000000000000000000000000000000000000000000000000000008816605483015282516036818403018152605690920190925280519101206000945030935063233fd52d92509050338d8d8d602d90606d9261088e93929190611f5a565b8f8f606d9080926108a193929190611f5a565b6040518863ffffffff1660e01b81526004016108c39796959493929190611fc0565b6020604051808303816000875af11580156108e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109069190612021565b9050817dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916838b73ffffffffffffffffffffffffffffffffffffffff167f3617b009e9785c42daebadb6d3fb553243a4bf586d07ea72d65d80013ce116b584604051610975911515815260200190565b60405180910390a450505050505050505050565b3360009081526003602052604081205460ff166109d2576040517fd79e123d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006109e26113886161a861204a565b5a6109ed919061205d565b90506109fd6113886161a861204a565b610a0a9062015f9061204a565b610a169061271061204a565b811015610a52576040517f0bfecd63000000000000000000000000000000000000000000000000000000008152600481018a90526024016104b8565b6000898152600460209081526040918290208251608081018452905473ffffffffffffffffffffffffffffffffffffffff8116825274010000000000000000000000000000000000000000810460ff90811615159383019390935275010000000000000000000000000000000000000000008104909216151592810183905276010000000000000000000000000000000000000000000090910469ffffffffffffffffffff1660608201529080610b0a575080602001515b15610b44576040517fa53dc8ca000000000000000000000000000000000000000000000000000000008152600481018b90526024016104b8565b60008a8152600460205260409020805469ffffffffffffffffffff84167601000000000000000000000000000000000000000000000275ffff000000000000000000000000000000000000000090911673ffffffffffffffffffffffffffffffffffffffff8c1617179055610bd9887f805f2132000000000000000000000000000000000000000000000000000000006115f4565b610c3057505050600087815260046020526040812080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055610d3f565b60008088888888604051602401610c4a9493929190612070565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f805f213200000000000000000000000000000000000000000000000000000000179052905060006113885a610cd2919061205d565b905060008083516020850160008f86f192508215610d375760008d815260046020526040902080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b509093505050505b979650505050505050565b6040805160c0810182526000808252602080830182905282840182905260608084018390526080840183905260a0840183905284519088901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001681830152603481018790527fffff000000000000000000000000000000000000000000000000000000000000861660548201528451603681830301815260568201808752815191840191909120808552600490935285842060d68301909652945473ffffffffffffffffffffffffffffffffffffffff811680875274010000000000000000000000000000000000000000820460ff9081161515607685015275010000000000000000000000000000000000000000008304161515609684015276010000000000000000000000000000000000000000000090910469ffffffffffffffffffff1660b69092019190915292939092909190610ea857506000610ed0565b816020015115610eba57506002610ed0565b8160400151610eca576003610ecd565b60015b90505b6040518060c00160405280848152602001826003811115610ef357610ef3611c38565b8152602001836000015173ffffffffffffffffffffffffffffffffffffffff168152602001836020015115158152602001836040015115158152602001836060015169ffffffffffffffffffff1681525093505050509392505050565b610f58611619565b73ffffffffffffffffffffffffffffffffffffffff811660008181526003602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517fb96d15bf9258c7b8df062753a6a262864611fc7b060a5ee2e57e79b85f898d389190a250565b610fd4611619565b73ffffffffffffffffffffffffffffffffffffffff811660008181526003602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f0ea0ce2c048ff45a4a95f2947879de3fb94abec2f152190400cab2d1272a68e79190a250565b60015473ffffffffffffffffffffffffffffffffffffffff1633146110cc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016104b8565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b611150611619565b8260ff1660000361118d576040517f0743bae600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601f8111156111d2576040517f61750f4000000000000000000000000000000000000000000000000000000000815260048101829052601f60248201526044016104b8565b6111dd836003612097565b60ff16811161123b57806111f2846003612097565b6111fd906001611e1e565b6040517f9dd9e6d8000000000000000000000000000000000000000000000000000000008152600481019290925260ff1660248201526044016104b8565b67ffffffff00000000602086901b1663ffffffff85161760005b67ffffffffffffffff82166000908152600260205260409020600101548110156112eb5767ffffffffffffffff82166000908152600260208190526040822060018101805491909201929190849081106112b1576112b1611e61565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001812055600101611255565b5060005b8281101561146757600084848381811061130b5761130b611e61565b90506020020160208101906113209190611d0f565b905073ffffffffffffffffffffffffffffffffffffffff8116611387576040517fbf18af4300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016104b8565b67ffffffffffffffff8316600090815260026020818152604080842073ffffffffffffffffffffffffffffffffffffffff86168552909201905290205415611413576040517fe021c4f200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016104b8565b61141e82600161204a565b67ffffffffffffffff8416600090815260026020818152604080842073ffffffffffffffffffffffffffffffffffffffff909616845294909101905291909120556001016112ef565b5067ffffffffffffffff8116600090815260026020526040902061148f9060010184846118df565b5067ffffffffffffffff81166000908152600260205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff87161790555163ffffffff86811691908816907f4120bd3b23957dd423555817d55654d4481b438aa15485c21b4180c784f1a45590611515908890889088906120b3565b60405180910390a3505050505050565b61152d611619565b63ffffffff818116602084811b67ffffffff00000000168217600090815260028252604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690558051828152928301905291928516917f4120bd3b23957dd423555817d55654d4481b438aa15485c21b4180c784f1a455916040516115b9929190612119565b60405180910390a35050565b6115cd611619565b6115d68161169c565b50565b60218101516045820151608b90920151909260c09290921c91565b60006115ff83611791565b8015611610575061161083836117f5565b90505b92915050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461169a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016104b8565b565b3373ffffffffffffffffffffffffffffffffffffffff82160361171b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016104b8565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60006117bd827f01ffc9a7000000000000000000000000000000000000000000000000000000006117f5565b801561161357506117ee827fffffffff000000000000000000000000000000000000000000000000000000006117f5565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156118ad575060208210155b8015610d3f575015159695505050505050565b6040518061040001604052806020906020820280368337509192915050565b828054828255906000526020600020908101928215611957579160200282015b828111156119575781547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8435161782556020909201916001909101906118ff565b50611963929150611967565b5090565b5b808211156119635760008155600101611968565b803573ffffffffffffffffffffffffffffffffffffffff811681146119a057600080fd5b919050565b60008083601f8401126119b757600080fd5b50813567ffffffffffffffff8111156119cf57600080fd5b6020830191508360208285010111156119e757600080fd5b9250929050565b60008083601f840112611a0057600080fd5b50813567ffffffffffffffff811115611a1857600080fd5b6020830191508360208260051b85010111156119e757600080fd5b60008060008060008060006080888a031215611a4e57600080fd5b611a578861197c565b9650602088013567ffffffffffffffff80821115611a7457600080fd5b611a808b838c016119a5565b909850965060408a0135915080821115611a9957600080fd5b611aa58b838c016119a5565b909650945060608a0135915080821115611abe57600080fd5b50611acb8a828b016119ee565b989b979a50959850939692959293505050565b60006020808352835180602085015260005b81811015611b0c57858101830151858201604001528201611af0565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b600080600080600080600060a0888a031215611b6657600080fd5b87359650611b766020890161197c565b9550611b846040890161197c565b9450606088013567ffffffffffffffff80821115611ba157600080fd5b611bad8b838c016119a5565b909650945060808a0135915080821115611bc657600080fd5b50611acb8a828b016119a5565b600080600060608486031215611be857600080fd5b611bf18461197c565b92506020840135915060408401357fffff00000000000000000000000000000000000000000000000000000000000081168114611c2d57600080fd5b809150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b81518152602082015160c082019060048110611cac577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8060208401525073ffffffffffffffffffffffffffffffffffffffff604084015116604083015260608301511515606083015260808301511515608083015260a0830151611d0860a084018269ffffffffffffffffffff169052565b5092915050565b600060208284031215611d2157600080fd5b6116108261197c565b803563ffffffff811681146119a057600080fd5b600080600080600060808688031215611d5657600080fd5b611d5f86611d2a565b9450611d6d60208701611d2a565b9350604086013560ff81168114611d8357600080fd5b9250606086013567ffffffffffffffff811115611d9f57600080fd5b611dab888289016119ee565b969995985093965092949392505050565b60008060408385031215611dcf57600080fd5b611dd883611d2a565b9150611de660208401611d2a565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff818116838216019081111561161357611613611def565b8183823760009101908152919050565b838152818360208301376000910160200190815292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611ec557600080fd5b83018035915067ffffffffffffffff821115611ee057600080fd5b6020019150368190038213156119e757600080fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526000611f52602083018486611ef5565b949350505050565b60008085851115611f6a57600080fd5b83861115611f7757600080fd5b5050820193919092039150565b80356020831015611613577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525060a0606083015261200060a083018688611ef5565b8281036080840152612013818587611ef5565b9a9950505050505050505050565b60006020828403121561203357600080fd5b8151801515811461204357600080fd5b9392505050565b8082018082111561161357611613611def565b8181038181111561161357611613611def565b604081526000612084604083018688611ef5565b8281036020840152610d3f818587611ef5565b60ff8181168382160290811690818114611d0857611d08611def565b60ff8416815260406020808301829052908201839052600090849060608401835b8681101561210d5773ffffffffffffffffffffffffffffffffffffffff6120fa8561197c565b16825292820192908201906001016120d4565b50979650505050505050565b60006040820160ff8516835260206040602085015281855180845260608601915060208701935060005b8181101561217557845173ffffffffffffffffffffffffffffffffffffffff1683529383019391830191600101612143565b509097965050505050505056fea164736f6c6343000818000a", +} + +var KeystoneForwarderABI = KeystoneForwarderMetaData.ABI + +var KeystoneForwarderBin = KeystoneForwarderMetaData.Bin + +func DeployKeystoneForwarder(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *KeystoneForwarder, error) { + parsed, err := KeystoneForwarderMetaData.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(KeystoneForwarderBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &KeystoneForwarder{address: address, abi: *parsed, KeystoneForwarderCaller: KeystoneForwarderCaller{contract: contract}, KeystoneForwarderTransactor: KeystoneForwarderTransactor{contract: contract}, KeystoneForwarderFilterer: KeystoneForwarderFilterer{contract: contract}}, nil +} + +type KeystoneForwarder struct { + address common.Address + abi abi.ABI + KeystoneForwarderCaller + KeystoneForwarderTransactor + KeystoneForwarderFilterer +} + +type KeystoneForwarderCaller struct { + contract *bind.BoundContract +} + +type KeystoneForwarderTransactor struct { + contract *bind.BoundContract +} + +type KeystoneForwarderFilterer struct { + contract *bind.BoundContract +} + +type KeystoneForwarderSession struct { + Contract *KeystoneForwarder + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type KeystoneForwarderCallerSession struct { + Contract *KeystoneForwarderCaller + CallOpts bind.CallOpts +} + +type KeystoneForwarderTransactorSession struct { + Contract *KeystoneForwarderTransactor + TransactOpts bind.TransactOpts +} + +type KeystoneForwarderRaw struct { + Contract *KeystoneForwarder +} + +type KeystoneForwarderCallerRaw struct { + Contract *KeystoneForwarderCaller +} + +type KeystoneForwarderTransactorRaw struct { + Contract *KeystoneForwarderTransactor +} + +func NewKeystoneForwarder(address common.Address, backend bind.ContractBackend) (*KeystoneForwarder, error) { + abi, err := abi.JSON(strings.NewReader(KeystoneForwarderABI)) + if err != nil { + return nil, err + } + contract, err := bindKeystoneForwarder(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &KeystoneForwarder{address: address, abi: abi, KeystoneForwarderCaller: KeystoneForwarderCaller{contract: contract}, KeystoneForwarderTransactor: KeystoneForwarderTransactor{contract: contract}, KeystoneForwarderFilterer: KeystoneForwarderFilterer{contract: contract}}, nil +} + +func NewKeystoneForwarderCaller(address common.Address, caller bind.ContractCaller) (*KeystoneForwarderCaller, error) { + contract, err := bindKeystoneForwarder(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &KeystoneForwarderCaller{contract: contract}, nil +} + +func NewKeystoneForwarderTransactor(address common.Address, transactor bind.ContractTransactor) (*KeystoneForwarderTransactor, error) { + contract, err := bindKeystoneForwarder(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &KeystoneForwarderTransactor{contract: contract}, nil +} + +func NewKeystoneForwarderFilterer(address common.Address, filterer bind.ContractFilterer) (*KeystoneForwarderFilterer, error) { + contract, err := bindKeystoneForwarder(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &KeystoneForwarderFilterer{contract: contract}, nil +} + +func bindKeystoneForwarder(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := KeystoneForwarderMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_KeystoneForwarder *KeystoneForwarderRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _KeystoneForwarder.Contract.KeystoneForwarderCaller.contract.Call(opts, result, method, params...) +} + +func (_KeystoneForwarder *KeystoneForwarderRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _KeystoneForwarder.Contract.KeystoneForwarderTransactor.contract.Transfer(opts) +} + +func (_KeystoneForwarder *KeystoneForwarderRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _KeystoneForwarder.Contract.KeystoneForwarderTransactor.contract.Transact(opts, method, params...) +} + +func (_KeystoneForwarder *KeystoneForwarderCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _KeystoneForwarder.Contract.contract.Call(opts, result, method, params...) +} + +func (_KeystoneForwarder *KeystoneForwarderTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _KeystoneForwarder.Contract.contract.Transfer(opts) +} + +func (_KeystoneForwarder *KeystoneForwarderTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _KeystoneForwarder.Contract.contract.Transact(opts, method, params...) +} + +func (_KeystoneForwarder *KeystoneForwarderCaller) GetTransmissionId(opts *bind.CallOpts, receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) ([32]byte, error) { + var out []interface{} + err := _KeystoneForwarder.contract.Call(opts, &out, "getTransmissionId", receiver, workflowExecutionId, reportId) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +func (_KeystoneForwarder *KeystoneForwarderSession) GetTransmissionId(receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) ([32]byte, error) { + return _KeystoneForwarder.Contract.GetTransmissionId(&_KeystoneForwarder.CallOpts, receiver, workflowExecutionId, reportId) +} + +func (_KeystoneForwarder *KeystoneForwarderCallerSession) GetTransmissionId(receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) ([32]byte, error) { + return _KeystoneForwarder.Contract.GetTransmissionId(&_KeystoneForwarder.CallOpts, receiver, workflowExecutionId, reportId) +} + +func (_KeystoneForwarder *KeystoneForwarderCaller) GetTransmissionInfo(opts *bind.CallOpts, receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) (IRouterTransmissionInfo, error) { + var out []interface{} + err := _KeystoneForwarder.contract.Call(opts, &out, "getTransmissionInfo", receiver, workflowExecutionId, reportId) + + if err != nil { + return *new(IRouterTransmissionInfo), err + } + + out0 := *abi.ConvertType(out[0], new(IRouterTransmissionInfo)).(*IRouterTransmissionInfo) + + return out0, err + +} + +func (_KeystoneForwarder *KeystoneForwarderSession) GetTransmissionInfo(receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) (IRouterTransmissionInfo, error) { + return _KeystoneForwarder.Contract.GetTransmissionInfo(&_KeystoneForwarder.CallOpts, receiver, workflowExecutionId, reportId) +} + +func (_KeystoneForwarder *KeystoneForwarderCallerSession) GetTransmissionInfo(receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) (IRouterTransmissionInfo, error) { + return _KeystoneForwarder.Contract.GetTransmissionInfo(&_KeystoneForwarder.CallOpts, receiver, workflowExecutionId, reportId) +} + +func (_KeystoneForwarder *KeystoneForwarderCaller) GetTransmitter(opts *bind.CallOpts, receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) (common.Address, error) { + var out []interface{} + err := _KeystoneForwarder.contract.Call(opts, &out, "getTransmitter", receiver, workflowExecutionId, reportId) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_KeystoneForwarder *KeystoneForwarderSession) GetTransmitter(receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) (common.Address, error) { + return _KeystoneForwarder.Contract.GetTransmitter(&_KeystoneForwarder.CallOpts, receiver, workflowExecutionId, reportId) +} + +func (_KeystoneForwarder *KeystoneForwarderCallerSession) GetTransmitter(receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) (common.Address, error) { + return _KeystoneForwarder.Contract.GetTransmitter(&_KeystoneForwarder.CallOpts, receiver, workflowExecutionId, reportId) +} + +func (_KeystoneForwarder *KeystoneForwarderCaller) IsForwarder(opts *bind.CallOpts, forwarder common.Address) (bool, error) { + var out []interface{} + err := _KeystoneForwarder.contract.Call(opts, &out, "isForwarder", forwarder) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_KeystoneForwarder *KeystoneForwarderSession) IsForwarder(forwarder common.Address) (bool, error) { + return _KeystoneForwarder.Contract.IsForwarder(&_KeystoneForwarder.CallOpts, forwarder) +} + +func (_KeystoneForwarder *KeystoneForwarderCallerSession) IsForwarder(forwarder common.Address) (bool, error) { + return _KeystoneForwarder.Contract.IsForwarder(&_KeystoneForwarder.CallOpts, forwarder) +} + +func (_KeystoneForwarder *KeystoneForwarderCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _KeystoneForwarder.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 (_KeystoneForwarder *KeystoneForwarderSession) Owner() (common.Address, error) { + return _KeystoneForwarder.Contract.Owner(&_KeystoneForwarder.CallOpts) +} + +func (_KeystoneForwarder *KeystoneForwarderCallerSession) Owner() (common.Address, error) { + return _KeystoneForwarder.Contract.Owner(&_KeystoneForwarder.CallOpts) +} + +func (_KeystoneForwarder *KeystoneForwarderCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _KeystoneForwarder.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_KeystoneForwarder *KeystoneForwarderSession) TypeAndVersion() (string, error) { + return _KeystoneForwarder.Contract.TypeAndVersion(&_KeystoneForwarder.CallOpts) +} + +func (_KeystoneForwarder *KeystoneForwarderCallerSession) TypeAndVersion() (string, error) { + return _KeystoneForwarder.Contract.TypeAndVersion(&_KeystoneForwarder.CallOpts) +} + +func (_KeystoneForwarder *KeystoneForwarderTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _KeystoneForwarder.contract.Transact(opts, "acceptOwnership") +} + +func (_KeystoneForwarder *KeystoneForwarderSession) AcceptOwnership() (*types.Transaction, error) { + return _KeystoneForwarder.Contract.AcceptOwnership(&_KeystoneForwarder.TransactOpts) +} + +func (_KeystoneForwarder *KeystoneForwarderTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _KeystoneForwarder.Contract.AcceptOwnership(&_KeystoneForwarder.TransactOpts) +} + +func (_KeystoneForwarder *KeystoneForwarderTransactor) AddForwarder(opts *bind.TransactOpts, forwarder common.Address) (*types.Transaction, error) { + return _KeystoneForwarder.contract.Transact(opts, "addForwarder", forwarder) +} + +func (_KeystoneForwarder *KeystoneForwarderSession) AddForwarder(forwarder common.Address) (*types.Transaction, error) { + return _KeystoneForwarder.Contract.AddForwarder(&_KeystoneForwarder.TransactOpts, forwarder) +} + +func (_KeystoneForwarder *KeystoneForwarderTransactorSession) AddForwarder(forwarder common.Address) (*types.Transaction, error) { + return _KeystoneForwarder.Contract.AddForwarder(&_KeystoneForwarder.TransactOpts, forwarder) +} + +func (_KeystoneForwarder *KeystoneForwarderTransactor) ClearConfig(opts *bind.TransactOpts, donId uint32, configVersion uint32) (*types.Transaction, error) { + return _KeystoneForwarder.contract.Transact(opts, "clearConfig", donId, configVersion) +} + +func (_KeystoneForwarder *KeystoneForwarderSession) ClearConfig(donId uint32, configVersion uint32) (*types.Transaction, error) { + return _KeystoneForwarder.Contract.ClearConfig(&_KeystoneForwarder.TransactOpts, donId, configVersion) +} + +func (_KeystoneForwarder *KeystoneForwarderTransactorSession) ClearConfig(donId uint32, configVersion uint32) (*types.Transaction, error) { + return _KeystoneForwarder.Contract.ClearConfig(&_KeystoneForwarder.TransactOpts, donId, configVersion) +} + +func (_KeystoneForwarder *KeystoneForwarderTransactor) RemoveForwarder(opts *bind.TransactOpts, forwarder common.Address) (*types.Transaction, error) { + return _KeystoneForwarder.contract.Transact(opts, "removeForwarder", forwarder) +} + +func (_KeystoneForwarder *KeystoneForwarderSession) RemoveForwarder(forwarder common.Address) (*types.Transaction, error) { + return _KeystoneForwarder.Contract.RemoveForwarder(&_KeystoneForwarder.TransactOpts, forwarder) +} + +func (_KeystoneForwarder *KeystoneForwarderTransactorSession) RemoveForwarder(forwarder common.Address) (*types.Transaction, error) { + return _KeystoneForwarder.Contract.RemoveForwarder(&_KeystoneForwarder.TransactOpts, forwarder) +} + +func (_KeystoneForwarder *KeystoneForwarderTransactor) Report(opts *bind.TransactOpts, receiver common.Address, rawReport []byte, reportContext []byte, signatures [][]byte) (*types.Transaction, error) { + return _KeystoneForwarder.contract.Transact(opts, "report", receiver, rawReport, reportContext, signatures) +} + +func (_KeystoneForwarder *KeystoneForwarderSession) Report(receiver common.Address, rawReport []byte, reportContext []byte, signatures [][]byte) (*types.Transaction, error) { + return _KeystoneForwarder.Contract.Report(&_KeystoneForwarder.TransactOpts, receiver, rawReport, reportContext, signatures) +} + +func (_KeystoneForwarder *KeystoneForwarderTransactorSession) Report(receiver common.Address, rawReport []byte, reportContext []byte, signatures [][]byte) (*types.Transaction, error) { + return _KeystoneForwarder.Contract.Report(&_KeystoneForwarder.TransactOpts, receiver, rawReport, reportContext, signatures) +} + +func (_KeystoneForwarder *KeystoneForwarderTransactor) Route(opts *bind.TransactOpts, transmissionId [32]byte, transmitter common.Address, receiver common.Address, metadata []byte, validatedReport []byte) (*types.Transaction, error) { + return _KeystoneForwarder.contract.Transact(opts, "route", transmissionId, transmitter, receiver, metadata, validatedReport) +} + +func (_KeystoneForwarder *KeystoneForwarderSession) Route(transmissionId [32]byte, transmitter common.Address, receiver common.Address, metadata []byte, validatedReport []byte) (*types.Transaction, error) { + return _KeystoneForwarder.Contract.Route(&_KeystoneForwarder.TransactOpts, transmissionId, transmitter, receiver, metadata, validatedReport) +} + +func (_KeystoneForwarder *KeystoneForwarderTransactorSession) Route(transmissionId [32]byte, transmitter common.Address, receiver common.Address, metadata []byte, validatedReport []byte) (*types.Transaction, error) { + return _KeystoneForwarder.Contract.Route(&_KeystoneForwarder.TransactOpts, transmissionId, transmitter, receiver, metadata, validatedReport) +} + +func (_KeystoneForwarder *KeystoneForwarderTransactor) SetConfig(opts *bind.TransactOpts, donId uint32, configVersion uint32, f uint8, signers []common.Address) (*types.Transaction, error) { + return _KeystoneForwarder.contract.Transact(opts, "setConfig", donId, configVersion, f, signers) +} + +func (_KeystoneForwarder *KeystoneForwarderSession) SetConfig(donId uint32, configVersion uint32, f uint8, signers []common.Address) (*types.Transaction, error) { + return _KeystoneForwarder.Contract.SetConfig(&_KeystoneForwarder.TransactOpts, donId, configVersion, f, signers) +} + +func (_KeystoneForwarder *KeystoneForwarderTransactorSession) SetConfig(donId uint32, configVersion uint32, f uint8, signers []common.Address) (*types.Transaction, error) { + return _KeystoneForwarder.Contract.SetConfig(&_KeystoneForwarder.TransactOpts, donId, configVersion, f, signers) +} + +func (_KeystoneForwarder *KeystoneForwarderTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _KeystoneForwarder.contract.Transact(opts, "transferOwnership", to) +} + +func (_KeystoneForwarder *KeystoneForwarderSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _KeystoneForwarder.Contract.TransferOwnership(&_KeystoneForwarder.TransactOpts, to) +} + +func (_KeystoneForwarder *KeystoneForwarderTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _KeystoneForwarder.Contract.TransferOwnership(&_KeystoneForwarder.TransactOpts, to) +} + +type KeystoneForwarderConfigSetIterator struct { + Event *KeystoneForwarderConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *KeystoneForwarderConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(KeystoneForwarderConfigSet) + 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(KeystoneForwarderConfigSet) + 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 *KeystoneForwarderConfigSetIterator) Error() error { + return it.fail +} + +func (it *KeystoneForwarderConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type KeystoneForwarderConfigSet struct { + DonId uint32 + ConfigVersion uint32 + F uint8 + Signers []common.Address + Raw types.Log +} + +func (_KeystoneForwarder *KeystoneForwarderFilterer) FilterConfigSet(opts *bind.FilterOpts, donId []uint32, configVersion []uint32) (*KeystoneForwarderConfigSetIterator, error) { + + var donIdRule []interface{} + for _, donIdItem := range donId { + donIdRule = append(donIdRule, donIdItem) + } + var configVersionRule []interface{} + for _, configVersionItem := range configVersion { + configVersionRule = append(configVersionRule, configVersionItem) + } + + logs, sub, err := _KeystoneForwarder.contract.FilterLogs(opts, "ConfigSet", donIdRule, configVersionRule) + if err != nil { + return nil, err + } + return &KeystoneForwarderConfigSetIterator{contract: _KeystoneForwarder.contract, event: "ConfigSet", logs: logs, sub: sub}, nil +} + +func (_KeystoneForwarder *KeystoneForwarderFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderConfigSet, donId []uint32, configVersion []uint32) (event.Subscription, error) { + + var donIdRule []interface{} + for _, donIdItem := range donId { + donIdRule = append(donIdRule, donIdItem) + } + var configVersionRule []interface{} + for _, configVersionItem := range configVersion { + configVersionRule = append(configVersionRule, configVersionItem) + } + + logs, sub, err := _KeystoneForwarder.contract.WatchLogs(opts, "ConfigSet", donIdRule, configVersionRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(KeystoneForwarderConfigSet) + if err := _KeystoneForwarder.contract.UnpackLog(event, "ConfigSet", 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 (_KeystoneForwarder *KeystoneForwarderFilterer) ParseConfigSet(log types.Log) (*KeystoneForwarderConfigSet, error) { + event := new(KeystoneForwarderConfigSet) + if err := _KeystoneForwarder.contract.UnpackLog(event, "ConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type KeystoneForwarderForwarderAddedIterator struct { + Event *KeystoneForwarderForwarderAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *KeystoneForwarderForwarderAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(KeystoneForwarderForwarderAdded) + 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(KeystoneForwarderForwarderAdded) + 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 *KeystoneForwarderForwarderAddedIterator) Error() error { + return it.fail +} + +func (it *KeystoneForwarderForwarderAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type KeystoneForwarderForwarderAdded struct { + Forwarder common.Address + Raw types.Log +} + +func (_KeystoneForwarder *KeystoneForwarderFilterer) FilterForwarderAdded(opts *bind.FilterOpts, forwarder []common.Address) (*KeystoneForwarderForwarderAddedIterator, error) { + + var forwarderRule []interface{} + for _, forwarderItem := range forwarder { + forwarderRule = append(forwarderRule, forwarderItem) + } + + logs, sub, err := _KeystoneForwarder.contract.FilterLogs(opts, "ForwarderAdded", forwarderRule) + if err != nil { + return nil, err + } + return &KeystoneForwarderForwarderAddedIterator{contract: _KeystoneForwarder.contract, event: "ForwarderAdded", logs: logs, sub: sub}, nil +} + +func (_KeystoneForwarder *KeystoneForwarderFilterer) WatchForwarderAdded(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderForwarderAdded, forwarder []common.Address) (event.Subscription, error) { + + var forwarderRule []interface{} + for _, forwarderItem := range forwarder { + forwarderRule = append(forwarderRule, forwarderItem) + } + + logs, sub, err := _KeystoneForwarder.contract.WatchLogs(opts, "ForwarderAdded", forwarderRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(KeystoneForwarderForwarderAdded) + if err := _KeystoneForwarder.contract.UnpackLog(event, "ForwarderAdded", 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 (_KeystoneForwarder *KeystoneForwarderFilterer) ParseForwarderAdded(log types.Log) (*KeystoneForwarderForwarderAdded, error) { + event := new(KeystoneForwarderForwarderAdded) + if err := _KeystoneForwarder.contract.UnpackLog(event, "ForwarderAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type KeystoneForwarderForwarderRemovedIterator struct { + Event *KeystoneForwarderForwarderRemoved + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *KeystoneForwarderForwarderRemovedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(KeystoneForwarderForwarderRemoved) + 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(KeystoneForwarderForwarderRemoved) + 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 *KeystoneForwarderForwarderRemovedIterator) Error() error { + return it.fail +} + +func (it *KeystoneForwarderForwarderRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type KeystoneForwarderForwarderRemoved struct { + Forwarder common.Address + Raw types.Log +} + +func (_KeystoneForwarder *KeystoneForwarderFilterer) FilterForwarderRemoved(opts *bind.FilterOpts, forwarder []common.Address) (*KeystoneForwarderForwarderRemovedIterator, error) { + + var forwarderRule []interface{} + for _, forwarderItem := range forwarder { + forwarderRule = append(forwarderRule, forwarderItem) + } + + logs, sub, err := _KeystoneForwarder.contract.FilterLogs(opts, "ForwarderRemoved", forwarderRule) + if err != nil { + return nil, err + } + return &KeystoneForwarderForwarderRemovedIterator{contract: _KeystoneForwarder.contract, event: "ForwarderRemoved", logs: logs, sub: sub}, nil +} + +func (_KeystoneForwarder *KeystoneForwarderFilterer) WatchForwarderRemoved(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderForwarderRemoved, forwarder []common.Address) (event.Subscription, error) { + + var forwarderRule []interface{} + for _, forwarderItem := range forwarder { + forwarderRule = append(forwarderRule, forwarderItem) + } + + logs, sub, err := _KeystoneForwarder.contract.WatchLogs(opts, "ForwarderRemoved", forwarderRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(KeystoneForwarderForwarderRemoved) + if err := _KeystoneForwarder.contract.UnpackLog(event, "ForwarderRemoved", 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 (_KeystoneForwarder *KeystoneForwarderFilterer) ParseForwarderRemoved(log types.Log) (*KeystoneForwarderForwarderRemoved, error) { + event := new(KeystoneForwarderForwarderRemoved) + if err := _KeystoneForwarder.contract.UnpackLog(event, "ForwarderRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type KeystoneForwarderOwnershipTransferRequestedIterator struct { + Event *KeystoneForwarderOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *KeystoneForwarderOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(KeystoneForwarderOwnershipTransferRequested) + 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(KeystoneForwarderOwnershipTransferRequested) + 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 *KeystoneForwarderOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *KeystoneForwarderOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type KeystoneForwarderOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_KeystoneForwarder *KeystoneForwarderFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*KeystoneForwarderOwnershipTransferRequestedIterator, 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 := _KeystoneForwarder.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &KeystoneForwarderOwnershipTransferRequestedIterator{contract: _KeystoneForwarder.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_KeystoneForwarder *KeystoneForwarderFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderOwnershipTransferRequested, 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 := _KeystoneForwarder.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(KeystoneForwarderOwnershipTransferRequested) + if err := _KeystoneForwarder.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 (_KeystoneForwarder *KeystoneForwarderFilterer) ParseOwnershipTransferRequested(log types.Log) (*KeystoneForwarderOwnershipTransferRequested, error) { + event := new(KeystoneForwarderOwnershipTransferRequested) + if err := _KeystoneForwarder.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type KeystoneForwarderOwnershipTransferredIterator struct { + Event *KeystoneForwarderOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *KeystoneForwarderOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(KeystoneForwarderOwnershipTransferred) + 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(KeystoneForwarderOwnershipTransferred) + 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 *KeystoneForwarderOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *KeystoneForwarderOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type KeystoneForwarderOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_KeystoneForwarder *KeystoneForwarderFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*KeystoneForwarderOwnershipTransferredIterator, 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 := _KeystoneForwarder.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &KeystoneForwarderOwnershipTransferredIterator{contract: _KeystoneForwarder.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_KeystoneForwarder *KeystoneForwarderFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderOwnershipTransferred, 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 := _KeystoneForwarder.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(KeystoneForwarderOwnershipTransferred) + if err := _KeystoneForwarder.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 (_KeystoneForwarder *KeystoneForwarderFilterer) ParseOwnershipTransferred(log types.Log) (*KeystoneForwarderOwnershipTransferred, error) { + event := new(KeystoneForwarderOwnershipTransferred) + if err := _KeystoneForwarder.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type KeystoneForwarderReportProcessedIterator struct { + Event *KeystoneForwarderReportProcessed + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *KeystoneForwarderReportProcessedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(KeystoneForwarderReportProcessed) + 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(KeystoneForwarderReportProcessed) + 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 *KeystoneForwarderReportProcessedIterator) Error() error { + return it.fail +} + +func (it *KeystoneForwarderReportProcessedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type KeystoneForwarderReportProcessed struct { + Receiver common.Address + WorkflowExecutionId [32]byte + ReportId [2]byte + Result bool + Raw types.Log +} + +func (_KeystoneForwarder *KeystoneForwarderFilterer) FilterReportProcessed(opts *bind.FilterOpts, receiver []common.Address, workflowExecutionId [][32]byte, reportId [][2]byte) (*KeystoneForwarderReportProcessedIterator, error) { + + var receiverRule []interface{} + for _, receiverItem := range receiver { + receiverRule = append(receiverRule, receiverItem) + } + var workflowExecutionIdRule []interface{} + for _, workflowExecutionIdItem := range workflowExecutionId { + workflowExecutionIdRule = append(workflowExecutionIdRule, workflowExecutionIdItem) + } + var reportIdRule []interface{} + for _, reportIdItem := range reportId { + reportIdRule = append(reportIdRule, reportIdItem) + } + + logs, sub, err := _KeystoneForwarder.contract.FilterLogs(opts, "ReportProcessed", receiverRule, workflowExecutionIdRule, reportIdRule) + if err != nil { + return nil, err + } + return &KeystoneForwarderReportProcessedIterator{contract: _KeystoneForwarder.contract, event: "ReportProcessed", logs: logs, sub: sub}, nil +} + +func (_KeystoneForwarder *KeystoneForwarderFilterer) WatchReportProcessed(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderReportProcessed, receiver []common.Address, workflowExecutionId [][32]byte, reportId [][2]byte) (event.Subscription, error) { + + var receiverRule []interface{} + for _, receiverItem := range receiver { + receiverRule = append(receiverRule, receiverItem) + } + var workflowExecutionIdRule []interface{} + for _, workflowExecutionIdItem := range workflowExecutionId { + workflowExecutionIdRule = append(workflowExecutionIdRule, workflowExecutionIdItem) + } + var reportIdRule []interface{} + for _, reportIdItem := range reportId { + reportIdRule = append(reportIdRule, reportIdItem) + } + + logs, sub, err := _KeystoneForwarder.contract.WatchLogs(opts, "ReportProcessed", receiverRule, workflowExecutionIdRule, reportIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(KeystoneForwarderReportProcessed) + if err := _KeystoneForwarder.contract.UnpackLog(event, "ReportProcessed", 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 (_KeystoneForwarder *KeystoneForwarderFilterer) ParseReportProcessed(log types.Log) (*KeystoneForwarderReportProcessed, error) { + event := new(KeystoneForwarderReportProcessed) + if err := _KeystoneForwarder.contract.UnpackLog(event, "ReportProcessed", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_KeystoneForwarder *KeystoneForwarder) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _KeystoneForwarder.abi.Events["ConfigSet"].ID: + return _KeystoneForwarder.ParseConfigSet(log) + case _KeystoneForwarder.abi.Events["ForwarderAdded"].ID: + return _KeystoneForwarder.ParseForwarderAdded(log) + case _KeystoneForwarder.abi.Events["ForwarderRemoved"].ID: + return _KeystoneForwarder.ParseForwarderRemoved(log) + case _KeystoneForwarder.abi.Events["OwnershipTransferRequested"].ID: + return _KeystoneForwarder.ParseOwnershipTransferRequested(log) + case _KeystoneForwarder.abi.Events["OwnershipTransferred"].ID: + return _KeystoneForwarder.ParseOwnershipTransferred(log) + case _KeystoneForwarder.abi.Events["ReportProcessed"].ID: + return _KeystoneForwarder.ParseReportProcessed(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (KeystoneForwarderConfigSet) Topic() common.Hash { + return common.HexToHash("0x4120bd3b23957dd423555817d55654d4481b438aa15485c21b4180c784f1a455") +} + +func (KeystoneForwarderForwarderAdded) Topic() common.Hash { + return common.HexToHash("0x0ea0ce2c048ff45a4a95f2947879de3fb94abec2f152190400cab2d1272a68e7") +} + +func (KeystoneForwarderForwarderRemoved) Topic() common.Hash { + return common.HexToHash("0xb96d15bf9258c7b8df062753a6a262864611fc7b060a5ee2e57e79b85f898d38") +} + +func (KeystoneForwarderOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (KeystoneForwarderOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (KeystoneForwarderReportProcessed) Topic() common.Hash { + return common.HexToHash("0x3617b009e9785c42daebadb6d3fb553243a4bf586d07ea72d65d80013ce116b5") +} + +func (_KeystoneForwarder *KeystoneForwarder) Address() common.Address { + return _KeystoneForwarder.address +} + +type KeystoneForwarderInterface interface { + GetTransmissionId(opts *bind.CallOpts, receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) ([32]byte, error) + + GetTransmissionInfo(opts *bind.CallOpts, receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) (IRouterTransmissionInfo, error) + + GetTransmitter(opts *bind.CallOpts, receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) (common.Address, error) + + IsForwarder(opts *bind.CallOpts, forwarder common.Address) (bool, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + TypeAndVersion(opts *bind.CallOpts) (string, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + AddForwarder(opts *bind.TransactOpts, forwarder common.Address) (*types.Transaction, error) + + ClearConfig(opts *bind.TransactOpts, donId uint32, configVersion uint32) (*types.Transaction, error) + + RemoveForwarder(opts *bind.TransactOpts, forwarder common.Address) (*types.Transaction, error) + + Report(opts *bind.TransactOpts, receiver common.Address, rawReport []byte, reportContext []byte, signatures [][]byte) (*types.Transaction, error) + + Route(opts *bind.TransactOpts, transmissionId [32]byte, transmitter common.Address, receiver common.Address, metadata []byte, validatedReport []byte) (*types.Transaction, error) + + SetConfig(opts *bind.TransactOpts, donId uint32, configVersion uint32, f uint8, signers []common.Address) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + FilterConfigSet(opts *bind.FilterOpts, donId []uint32, configVersion []uint32) (*KeystoneForwarderConfigSetIterator, error) + + WatchConfigSet(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderConfigSet, donId []uint32, configVersion []uint32) (event.Subscription, error) + + ParseConfigSet(log types.Log) (*KeystoneForwarderConfigSet, error) + + FilterForwarderAdded(opts *bind.FilterOpts, forwarder []common.Address) (*KeystoneForwarderForwarderAddedIterator, error) + + WatchForwarderAdded(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderForwarderAdded, forwarder []common.Address) (event.Subscription, error) + + ParseForwarderAdded(log types.Log) (*KeystoneForwarderForwarderAdded, error) + + FilterForwarderRemoved(opts *bind.FilterOpts, forwarder []common.Address) (*KeystoneForwarderForwarderRemovedIterator, error) + + WatchForwarderRemoved(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderForwarderRemoved, forwarder []common.Address) (event.Subscription, error) + + ParseForwarderRemoved(log types.Log) (*KeystoneForwarderForwarderRemoved, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*KeystoneForwarderOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*KeystoneForwarderOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*KeystoneForwarderOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*KeystoneForwarderOwnershipTransferred, error) + + FilterReportProcessed(opts *bind.FilterOpts, receiver []common.Address, workflowExecutionId [][32]byte, reportId [][2]byte) (*KeystoneForwarderReportProcessedIterator, error) + + WatchReportProcessed(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderReportProcessed, receiver []common.Address, workflowExecutionId [][32]byte, reportId [][2]byte) (event.Subscription, error) + + ParseReportProcessed(log types.Log) (*KeystoneForwarderReportProcessed, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/keystone/generated/ocr3_capability_1_0_0/ocr3_capability.go b/core/gethwrappers/keystone/generated/ocr3_capability_1_0_0/ocr3_capability.go new file mode 100644 index 00000000000..b4292c44125 --- /dev/null +++ b/core/gethwrappers/keystone/generated/ocr3_capability_1_0_0/ocr3_capability.go @@ -0,0 +1,946 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package ocr3_capability + +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 OCR3CapabilityMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"message\",\"type\":\"string\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReportingUnsupported\",\"type\":\"error\"},{\"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\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"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\":\"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\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"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\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"_signers\",\"type\":\"bytes[]\"},{\"internalType\":\"address[]\",\"name\":\"_transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"_f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"_onchainConfig\",\"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\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"transmit\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6112bc806101576000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80638da5cb5b1161005b5780638da5cb5b14610169578063afcb95d714610191578063b1dc65a4146101b1578063f2fde38b146101c457600080fd5b8063181f5a771461008d57806379ba5097146100df5780637f3c87d3146100e957806381ff7048146100fc575b600080fd5b6100c96040518060400160405280601481526020017f4f4352334361706162696c69747920312e302e3000000000000000000000000081525081565b6040516100d69190610b8a565b60405180910390f35b6100e76101d7565b005b6100e76100f7366004610cf8565b6102d9565b61014660015460025463ffffffff74010000000000000000000000000000000000000000830481169378010000000000000000000000000000000000000000000000009093041691565b6040805163ffffffff9485168152939092166020840152908201526060016100d6565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100d6565b6040805160018152600060208201819052918101919091526060016100d6565b6100e76101bf366004610dd4565b6108b7565b6100e76101d2366004610edd565b6108e9565b60015473ffffffffffffffffffffffffffffffffffffffff16331461025d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b868560ff8616601f83111561034a576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f746f6f206d616e79207369676e657273000000000000000000000000000000006044820152606401610254565b806000036103b4576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f66206d75737420626520706f73697469766500000000000000000000000000006044820152606401610254565b818314610442576040517f89a61989000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f6f7261636c6520616464726573736573206f7574206f6620726567697374726160448201527f74696f6e000000000000000000000000000000000000000000000000000000006064820152608401610254565b61044d816003610f27565b83116104b5576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661756c74792d6f7261636c65206620746f6f206869676800000000000000006044820152606401610254565b6104bd6108fd565b60005b8a8110156107255760008a8a838181106104dc576104dc610f44565b90506020020160208101906104f19190610edd565b73ffffffffffffffffffffffffffffffffffffffff160361056e576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f7472616e736d6974746572206d757374206e6f7420626520656d7074790000006044820152606401610254565b3660008d8d8481811061058357610583610f44565b90506020028101906105959190610f73565b9092509050600061ffff82165b8082101561071657806105b6836003610fd8565b111561061e576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f696e76616c6964207369676e6572207075624b657920656e636f64696e6700006044820152606401610254565b60006008858561062f866002610fd8565b81811061063e5761063e610f44565b919091013560f81c90911b90508585610658866001610fd8565b81811061066757610667610f44565b6106789392013560f81c9050610fd8565b90508181610687856003610fd8565b6106919190610fd8565b11156106f9576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f696e76616c6964207369676e6572207075624b657920656e636f64696e6700006044820152606401610254565b610704816003610fd8565b61070e9084610fd8565b9250506105a2565b505050508060010190506104c0565b50600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff8916179055600180547fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff8116780100000000000000000000000000000000000000000000000063ffffffff43811682029290921780855592048116929182916014916107d491849174010000000000000000000000000000000000000000900416610feb565b92506101000a81548163ffffffff021916908363ffffffff16021790555061081d4630600160149054906101000a900463ffffffff1663ffffffff168f8f8f8f8f8f8f8f610980565b6002600001819055508b8b9050600260010160016101000a81548160ff021916908360ff1602179055507f36257c6e8d535293ad661e377c0baac536289be6707b8a488ac175ddaa4055c881600260000154600160149054906101000a900463ffffffff168f8f8f8f8f8f8f8f6040516108a19b9a9998979695949392919061117e565b60405180910390a1505050505050505050505050565b6040517f0750181900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108f16108fd565b6108fa81610a31565b50565b60005473ffffffffffffffffffffffffffffffffffffffff16331461097e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610254565b565b6000808c8c8c8c8c8c8c8c8c8c8c6040516020016109a89b9a99989796959493929190611218565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e0e000000000000000000000000000000000000000000000000000000000000179150509b9a5050505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603610ab0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610254565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000815180845260005b81811015610b4c57602081850181015186830182015201610b30565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610b9d6020830184610b26565b9392505050565b60008083601f840112610bb657600080fd5b50813567ffffffffffffffff811115610bce57600080fd5b6020830191508360208260051b8501011115610be957600080fd5b9250929050565b803560ff81168114610c0157600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112610c4657600080fd5b813567ffffffffffffffff80821115610c6157610c61610c06565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610ca757610ca7610c06565b81604052838152866020858801011115610cc057600080fd5b836020870160208301376000602085830101528094505050505092915050565b803567ffffffffffffffff81168114610c0157600080fd5b60008060008060008060008060c0898b031215610d1457600080fd5b883567ffffffffffffffff80821115610d2c57600080fd5b610d388c838d01610ba4565b909a50985060208b0135915080821115610d5157600080fd5b610d5d8c838d01610ba4565b9098509650869150610d7160408c01610bf0565b955060608b0135915080821115610d8757600080fd5b610d938c838d01610c35565b9450610da160808c01610ce0565b935060a08b0135915080821115610db757600080fd5b50610dc48b828c01610c35565b9150509295985092959890939650565b60008060008060008060008060e0898b031215610df057600080fd5b606089018a811115610e0157600080fd5b8998503567ffffffffffffffff80821115610e1b57600080fd5b818b0191508b601f830112610e2f57600080fd5b813581811115610e3e57600080fd5b8c6020828501011115610e5057600080fd5b6020830199508098505060808b0135915080821115610e6e57600080fd5b610e7a8c838d01610ba4565b909750955060a08b0135915080821115610e9357600080fd5b50610ea08b828c01610ba4565b999c989b50969995989497949560c00135949350505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610c0157600080fd5b600060208284031215610eef57600080fd5b610b9d82610eb9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610f3e57610f3e610ef8565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610fa857600080fd5b83018035915067ffffffffffffffff821115610fc357600080fd5b602001915036819003821315610be957600080fd5b80820180821115610f3e57610f3e610ef8565b63ffffffff81811683821601908082111561100857611008610ef8565b5092915050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b6000838385526020808601955060208560051b8301018460005b8781101561111d577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe085840301895281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18836030181126110d357600080fd5b8701848101903567ffffffffffffffff8111156110ef57600080fd5b8036038213156110fe57600080fd5b61110985828461100f565b9a86019a9450505090830190600101611072565b5090979650505050505050565b8183526000602080850194508260005b858110156111735773ffffffffffffffffffffffffffffffffffffffff61116083610eb9565b168752958201959082019060010161113a565b509495945050505050565b600061012063ffffffff808f1684528d6020850152808d166040850152508060608401526111af8184018b8d611058565b905082810360808401526111c481898b61112a565b905060ff871660a084015282810360c08401526111e18187610b26565b905067ffffffffffffffff851660e08401528281036101008401526112068185610b26565b9e9d5050505050505050505050505050565b60006101208d835273ffffffffffffffffffffffffffffffffffffffff8d16602084015267ffffffffffffffff808d1660408501528160608501526112608285018c8e611058565b91508382036080850152611275828a8c61112a565b915060ff881660a085015283820360c08501526112928288610b26565b90861660e085015283810361010085015290506112068185610b2656fea164736f6c6343000818000a", +} + +var OCR3CapabilityABI = OCR3CapabilityMetaData.ABI + +var OCR3CapabilityBin = OCR3CapabilityMetaData.Bin + +func DeployOCR3Capability(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *OCR3Capability, error) { + parsed, err := OCR3CapabilityMetaData.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(OCR3CapabilityBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &OCR3Capability{address: address, abi: *parsed, OCR3CapabilityCaller: OCR3CapabilityCaller{contract: contract}, OCR3CapabilityTransactor: OCR3CapabilityTransactor{contract: contract}, OCR3CapabilityFilterer: OCR3CapabilityFilterer{contract: contract}}, nil +} + +type OCR3Capability struct { + address common.Address + abi abi.ABI + OCR3CapabilityCaller + OCR3CapabilityTransactor + OCR3CapabilityFilterer +} + +type OCR3CapabilityCaller struct { + contract *bind.BoundContract +} + +type OCR3CapabilityTransactor struct { + contract *bind.BoundContract +} + +type OCR3CapabilityFilterer struct { + contract *bind.BoundContract +} + +type OCR3CapabilitySession struct { + Contract *OCR3Capability + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type OCR3CapabilityCallerSession struct { + Contract *OCR3CapabilityCaller + CallOpts bind.CallOpts +} + +type OCR3CapabilityTransactorSession struct { + Contract *OCR3CapabilityTransactor + TransactOpts bind.TransactOpts +} + +type OCR3CapabilityRaw struct { + Contract *OCR3Capability +} + +type OCR3CapabilityCallerRaw struct { + Contract *OCR3CapabilityCaller +} + +type OCR3CapabilityTransactorRaw struct { + Contract *OCR3CapabilityTransactor +} + +func NewOCR3Capability(address common.Address, backend bind.ContractBackend) (*OCR3Capability, error) { + abi, err := abi.JSON(strings.NewReader(OCR3CapabilityABI)) + if err != nil { + return nil, err + } + contract, err := bindOCR3Capability(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &OCR3Capability{address: address, abi: abi, OCR3CapabilityCaller: OCR3CapabilityCaller{contract: contract}, OCR3CapabilityTransactor: OCR3CapabilityTransactor{contract: contract}, OCR3CapabilityFilterer: OCR3CapabilityFilterer{contract: contract}}, nil +} + +func NewOCR3CapabilityCaller(address common.Address, caller bind.ContractCaller) (*OCR3CapabilityCaller, error) { + contract, err := bindOCR3Capability(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &OCR3CapabilityCaller{contract: contract}, nil +} + +func NewOCR3CapabilityTransactor(address common.Address, transactor bind.ContractTransactor) (*OCR3CapabilityTransactor, error) { + contract, err := bindOCR3Capability(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &OCR3CapabilityTransactor{contract: contract}, nil +} + +func NewOCR3CapabilityFilterer(address common.Address, filterer bind.ContractFilterer) (*OCR3CapabilityFilterer, error) { + contract, err := bindOCR3Capability(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &OCR3CapabilityFilterer{contract: contract}, nil +} + +func bindOCR3Capability(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := OCR3CapabilityMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_OCR3Capability *OCR3CapabilityRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _OCR3Capability.Contract.OCR3CapabilityCaller.contract.Call(opts, result, method, params...) +} + +func (_OCR3Capability *OCR3CapabilityRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OCR3Capability.Contract.OCR3CapabilityTransactor.contract.Transfer(opts) +} + +func (_OCR3Capability *OCR3CapabilityRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _OCR3Capability.Contract.OCR3CapabilityTransactor.contract.Transact(opts, method, params...) +} + +func (_OCR3Capability *OCR3CapabilityCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _OCR3Capability.Contract.contract.Call(opts, result, method, params...) +} + +func (_OCR3Capability *OCR3CapabilityTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OCR3Capability.Contract.contract.Transfer(opts) +} + +func (_OCR3Capability *OCR3CapabilityTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _OCR3Capability.Contract.contract.Transact(opts, method, params...) +} + +func (_OCR3Capability *OCR3CapabilityCaller) LatestConfigDetails(opts *bind.CallOpts) (LatestConfigDetails, + + error) { + var out []interface{} + err := _OCR3Capability.contract.Call(opts, &out, "latestConfigDetails") + + outstruct := new(LatestConfigDetails) + if err != nil { + return *outstruct, err + } + + outstruct.ConfigCount = *abi.ConvertType(out[0], new(uint32)).(*uint32) + outstruct.BlockNumber = *abi.ConvertType(out[1], new(uint32)).(*uint32) + outstruct.ConfigDigest = *abi.ConvertType(out[2], new([32]byte)).(*[32]byte) + + return *outstruct, err + +} + +func (_OCR3Capability *OCR3CapabilitySession) LatestConfigDetails() (LatestConfigDetails, + + error) { + return _OCR3Capability.Contract.LatestConfigDetails(&_OCR3Capability.CallOpts) +} + +func (_OCR3Capability *OCR3CapabilityCallerSession) LatestConfigDetails() (LatestConfigDetails, + + error) { + return _OCR3Capability.Contract.LatestConfigDetails(&_OCR3Capability.CallOpts) +} + +func (_OCR3Capability *OCR3CapabilityCaller) LatestConfigDigestAndEpoch(opts *bind.CallOpts) (LatestConfigDigestAndEpoch, + + error) { + var out []interface{} + err := _OCR3Capability.contract.Call(opts, &out, "latestConfigDigestAndEpoch") + + outstruct := new(LatestConfigDigestAndEpoch) + if err != nil { + return *outstruct, err + } + + outstruct.ScanLogs = *abi.ConvertType(out[0], new(bool)).(*bool) + outstruct.ConfigDigest = *abi.ConvertType(out[1], new([32]byte)).(*[32]byte) + outstruct.Epoch = *abi.ConvertType(out[2], new(uint32)).(*uint32) + + return *outstruct, err + +} + +func (_OCR3Capability *OCR3CapabilitySession) LatestConfigDigestAndEpoch() (LatestConfigDigestAndEpoch, + + error) { + return _OCR3Capability.Contract.LatestConfigDigestAndEpoch(&_OCR3Capability.CallOpts) +} + +func (_OCR3Capability *OCR3CapabilityCallerSession) LatestConfigDigestAndEpoch() (LatestConfigDigestAndEpoch, + + error) { + return _OCR3Capability.Contract.LatestConfigDigestAndEpoch(&_OCR3Capability.CallOpts) +} + +func (_OCR3Capability *OCR3CapabilityCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _OCR3Capability.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 (_OCR3Capability *OCR3CapabilitySession) Owner() (common.Address, error) { + return _OCR3Capability.Contract.Owner(&_OCR3Capability.CallOpts) +} + +func (_OCR3Capability *OCR3CapabilityCallerSession) Owner() (common.Address, error) { + return _OCR3Capability.Contract.Owner(&_OCR3Capability.CallOpts) +} + +func (_OCR3Capability *OCR3CapabilityCaller) Transmit(opts *bind.CallOpts, arg0 [3][32]byte, arg1 []byte, arg2 [][32]byte, arg3 [][32]byte, arg4 [32]byte) error { + var out []interface{} + err := _OCR3Capability.contract.Call(opts, &out, "transmit", arg0, arg1, arg2, arg3, arg4) + + if err != nil { + return err + } + + return err + +} + +func (_OCR3Capability *OCR3CapabilitySession) Transmit(arg0 [3][32]byte, arg1 []byte, arg2 [][32]byte, arg3 [][32]byte, arg4 [32]byte) error { + return _OCR3Capability.Contract.Transmit(&_OCR3Capability.CallOpts, arg0, arg1, arg2, arg3, arg4) +} + +func (_OCR3Capability *OCR3CapabilityCallerSession) Transmit(arg0 [3][32]byte, arg1 []byte, arg2 [][32]byte, arg3 [][32]byte, arg4 [32]byte) error { + return _OCR3Capability.Contract.Transmit(&_OCR3Capability.CallOpts, arg0, arg1, arg2, arg3, arg4) +} + +func (_OCR3Capability *OCR3CapabilityCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _OCR3Capability.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_OCR3Capability *OCR3CapabilitySession) TypeAndVersion() (string, error) { + return _OCR3Capability.Contract.TypeAndVersion(&_OCR3Capability.CallOpts) +} + +func (_OCR3Capability *OCR3CapabilityCallerSession) TypeAndVersion() (string, error) { + return _OCR3Capability.Contract.TypeAndVersion(&_OCR3Capability.CallOpts) +} + +func (_OCR3Capability *OCR3CapabilityTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OCR3Capability.contract.Transact(opts, "acceptOwnership") +} + +func (_OCR3Capability *OCR3CapabilitySession) AcceptOwnership() (*types.Transaction, error) { + return _OCR3Capability.Contract.AcceptOwnership(&_OCR3Capability.TransactOpts) +} + +func (_OCR3Capability *OCR3CapabilityTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _OCR3Capability.Contract.AcceptOwnership(&_OCR3Capability.TransactOpts) +} + +func (_OCR3Capability *OCR3CapabilityTransactor) SetConfig(opts *bind.TransactOpts, _signers [][]byte, _transmitters []common.Address, _f uint8, _onchainConfig []byte, _offchainConfigVersion uint64, _offchainConfig []byte) (*types.Transaction, error) { + return _OCR3Capability.contract.Transact(opts, "setConfig", _signers, _transmitters, _f, _onchainConfig, _offchainConfigVersion, _offchainConfig) +} + +func (_OCR3Capability *OCR3CapabilitySession) SetConfig(_signers [][]byte, _transmitters []common.Address, _f uint8, _onchainConfig []byte, _offchainConfigVersion uint64, _offchainConfig []byte) (*types.Transaction, error) { + return _OCR3Capability.Contract.SetConfig(&_OCR3Capability.TransactOpts, _signers, _transmitters, _f, _onchainConfig, _offchainConfigVersion, _offchainConfig) +} + +func (_OCR3Capability *OCR3CapabilityTransactorSession) SetConfig(_signers [][]byte, _transmitters []common.Address, _f uint8, _onchainConfig []byte, _offchainConfigVersion uint64, _offchainConfig []byte) (*types.Transaction, error) { + return _OCR3Capability.Contract.SetConfig(&_OCR3Capability.TransactOpts, _signers, _transmitters, _f, _onchainConfig, _offchainConfigVersion, _offchainConfig) +} + +func (_OCR3Capability *OCR3CapabilityTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _OCR3Capability.contract.Transact(opts, "transferOwnership", to) +} + +func (_OCR3Capability *OCR3CapabilitySession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _OCR3Capability.Contract.TransferOwnership(&_OCR3Capability.TransactOpts, to) +} + +func (_OCR3Capability *OCR3CapabilityTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _OCR3Capability.Contract.TransferOwnership(&_OCR3Capability.TransactOpts, to) +} + +type OCR3CapabilityConfigSetIterator struct { + Event *OCR3CapabilityConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OCR3CapabilityConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OCR3CapabilityConfigSet) + 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(OCR3CapabilityConfigSet) + 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 *OCR3CapabilityConfigSetIterator) Error() error { + return it.fail +} + +func (it *OCR3CapabilityConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OCR3CapabilityConfigSet struct { + PreviousConfigBlockNumber uint32 + ConfigDigest [32]byte + ConfigCount uint64 + Signers [][]byte + Transmitters []common.Address + F uint8 + OnchainConfig []byte + OffchainConfigVersion uint64 + OffchainConfig []byte + Raw types.Log +} + +func (_OCR3Capability *OCR3CapabilityFilterer) FilterConfigSet(opts *bind.FilterOpts) (*OCR3CapabilityConfigSetIterator, error) { + + logs, sub, err := _OCR3Capability.contract.FilterLogs(opts, "ConfigSet") + if err != nil { + return nil, err + } + return &OCR3CapabilityConfigSetIterator{contract: _OCR3Capability.contract, event: "ConfigSet", logs: logs, sub: sub}, nil +} + +func (_OCR3Capability *OCR3CapabilityFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *OCR3CapabilityConfigSet) (event.Subscription, error) { + + logs, sub, err := _OCR3Capability.contract.WatchLogs(opts, "ConfigSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OCR3CapabilityConfigSet) + if err := _OCR3Capability.contract.UnpackLog(event, "ConfigSet", 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 (_OCR3Capability *OCR3CapabilityFilterer) ParseConfigSet(log types.Log) (*OCR3CapabilityConfigSet, error) { + event := new(OCR3CapabilityConfigSet) + if err := _OCR3Capability.contract.UnpackLog(event, "ConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OCR3CapabilityOwnershipTransferRequestedIterator struct { + Event *OCR3CapabilityOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OCR3CapabilityOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OCR3CapabilityOwnershipTransferRequested) + 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(OCR3CapabilityOwnershipTransferRequested) + 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 *OCR3CapabilityOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *OCR3CapabilityOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OCR3CapabilityOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_OCR3Capability *OCR3CapabilityFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OCR3CapabilityOwnershipTransferRequestedIterator, 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 := _OCR3Capability.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &OCR3CapabilityOwnershipTransferRequestedIterator{contract: _OCR3Capability.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_OCR3Capability *OCR3CapabilityFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *OCR3CapabilityOwnershipTransferRequested, 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 := _OCR3Capability.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(OCR3CapabilityOwnershipTransferRequested) + if err := _OCR3Capability.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 (_OCR3Capability *OCR3CapabilityFilterer) ParseOwnershipTransferRequested(log types.Log) (*OCR3CapabilityOwnershipTransferRequested, error) { + event := new(OCR3CapabilityOwnershipTransferRequested) + if err := _OCR3Capability.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OCR3CapabilityOwnershipTransferredIterator struct { + Event *OCR3CapabilityOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OCR3CapabilityOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OCR3CapabilityOwnershipTransferred) + 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(OCR3CapabilityOwnershipTransferred) + 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 *OCR3CapabilityOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *OCR3CapabilityOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OCR3CapabilityOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_OCR3Capability *OCR3CapabilityFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OCR3CapabilityOwnershipTransferredIterator, 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 := _OCR3Capability.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &OCR3CapabilityOwnershipTransferredIterator{contract: _OCR3Capability.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_OCR3Capability *OCR3CapabilityFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *OCR3CapabilityOwnershipTransferred, 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 := _OCR3Capability.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(OCR3CapabilityOwnershipTransferred) + if err := _OCR3Capability.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 (_OCR3Capability *OCR3CapabilityFilterer) ParseOwnershipTransferred(log types.Log) (*OCR3CapabilityOwnershipTransferred, error) { + event := new(OCR3CapabilityOwnershipTransferred) + if err := _OCR3Capability.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OCR3CapabilityTransmittedIterator struct { + Event *OCR3CapabilityTransmitted + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OCR3CapabilityTransmittedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OCR3CapabilityTransmitted) + 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(OCR3CapabilityTransmitted) + 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 *OCR3CapabilityTransmittedIterator) Error() error { + return it.fail +} + +func (it *OCR3CapabilityTransmittedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OCR3CapabilityTransmitted struct { + ConfigDigest [32]byte + Epoch uint32 + Raw types.Log +} + +func (_OCR3Capability *OCR3CapabilityFilterer) FilterTransmitted(opts *bind.FilterOpts) (*OCR3CapabilityTransmittedIterator, error) { + + logs, sub, err := _OCR3Capability.contract.FilterLogs(opts, "Transmitted") + if err != nil { + return nil, err + } + return &OCR3CapabilityTransmittedIterator{contract: _OCR3Capability.contract, event: "Transmitted", logs: logs, sub: sub}, nil +} + +func (_OCR3Capability *OCR3CapabilityFilterer) WatchTransmitted(opts *bind.WatchOpts, sink chan<- *OCR3CapabilityTransmitted) (event.Subscription, error) { + + logs, sub, err := _OCR3Capability.contract.WatchLogs(opts, "Transmitted") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OCR3CapabilityTransmitted) + if err := _OCR3Capability.contract.UnpackLog(event, "Transmitted", 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 (_OCR3Capability *OCR3CapabilityFilterer) ParseTransmitted(log types.Log) (*OCR3CapabilityTransmitted, error) { + event := new(OCR3CapabilityTransmitted) + if err := _OCR3Capability.contract.UnpackLog(event, "Transmitted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type LatestConfigDetails struct { + ConfigCount uint32 + BlockNumber uint32 + ConfigDigest [32]byte +} +type LatestConfigDigestAndEpoch struct { + ScanLogs bool + ConfigDigest [32]byte + Epoch uint32 +} + +func (_OCR3Capability *OCR3Capability) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _OCR3Capability.abi.Events["ConfigSet"].ID: + return _OCR3Capability.ParseConfigSet(log) + case _OCR3Capability.abi.Events["OwnershipTransferRequested"].ID: + return _OCR3Capability.ParseOwnershipTransferRequested(log) + case _OCR3Capability.abi.Events["OwnershipTransferred"].ID: + return _OCR3Capability.ParseOwnershipTransferred(log) + case _OCR3Capability.abi.Events["Transmitted"].ID: + return _OCR3Capability.ParseTransmitted(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (OCR3CapabilityConfigSet) Topic() common.Hash { + return common.HexToHash("0x36257c6e8d535293ad661e377c0baac536289be6707b8a488ac175ddaa4055c8") +} + +func (OCR3CapabilityOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (OCR3CapabilityOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (OCR3CapabilityTransmitted) Topic() common.Hash { + return common.HexToHash("0xb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62") +} + +func (_OCR3Capability *OCR3Capability) Address() common.Address { + return _OCR3Capability.address +} + +type OCR3CapabilityInterface interface { + LatestConfigDetails(opts *bind.CallOpts) (LatestConfigDetails, + + error) + + LatestConfigDigestAndEpoch(opts *bind.CallOpts) (LatestConfigDigestAndEpoch, + + error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + Transmit(opts *bind.CallOpts, arg0 [3][32]byte, arg1 []byte, arg2 [][32]byte, arg3 [][32]byte, arg4 [32]byte) error + + TypeAndVersion(opts *bind.CallOpts) (string, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + SetConfig(opts *bind.TransactOpts, _signers [][]byte, _transmitters []common.Address, _f uint8, _onchainConfig []byte, _offchainConfigVersion uint64, _offchainConfig []byte) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + FilterConfigSet(opts *bind.FilterOpts) (*OCR3CapabilityConfigSetIterator, error) + + WatchConfigSet(opts *bind.WatchOpts, sink chan<- *OCR3CapabilityConfigSet) (event.Subscription, error) + + ParseConfigSet(log types.Log) (*OCR3CapabilityConfigSet, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OCR3CapabilityOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *OCR3CapabilityOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*OCR3CapabilityOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OCR3CapabilityOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *OCR3CapabilityOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*OCR3CapabilityOwnershipTransferred, error) + + FilterTransmitted(opts *bind.FilterOpts) (*OCR3CapabilityTransmittedIterator, error) + + WatchTransmitted(opts *bind.WatchOpts, sink chan<- *OCR3CapabilityTransmitted) (event.Subscription, error) + + ParseTransmitted(log types.Log) (*OCR3CapabilityTransmitted, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/liquiditymanager/mocks/mock_arbitrum_gateway_router/arbitrum_gateway_router_interface.go b/core/gethwrappers/liquiditymanager/mocks/mock_arbitrum_gateway_router/arbitrum_gateway_router_interface.go index eac55ff03a3..d7b88a8f27b 100644 --- a/core/gethwrappers/liquiditymanager/mocks/mock_arbitrum_gateway_router/arbitrum_gateway_router_interface.go +++ b/core/gethwrappers/liquiditymanager/mocks/mock_arbitrum_gateway_router/arbitrum_gateway_router_interface.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mock_arbitrum_gateway_router @@ -33,7 +33,7 @@ func (_m *ArbitrumGatewayRouterInterface) EXPECT() *ArbitrumGatewayRouterInterfa return &ArbitrumGatewayRouterInterface_Expecter{mock: &_m.Mock} } -// Address provides a mock function with given fields: +// Address provides a mock function with no fields func (_m *ArbitrumGatewayRouterInterface) Address() common.Address { ret := _m.Called() diff --git a/core/gethwrappers/liquiditymanager/mocks/mock_arbitrum_inbox/arbitrum_inbox_interface.go b/core/gethwrappers/liquiditymanager/mocks/mock_arbitrum_inbox/arbitrum_inbox_interface.go index 7e9939b8023..934613e32fc 100644 --- a/core/gethwrappers/liquiditymanager/mocks/mock_arbitrum_inbox/arbitrum_inbox_interface.go +++ b/core/gethwrappers/liquiditymanager/mocks/mock_arbitrum_inbox/arbitrum_inbox_interface.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mock_arbitrum_inbox @@ -33,7 +33,7 @@ func (_m *ArbitrumInboxInterface) EXPECT() *ArbitrumInboxInterface_Expecter { return &ArbitrumInboxInterface_Expecter{mock: &_m.Mock} } -// Address provides a mock function with given fields: +// Address provides a mock function with no fields func (_m *ArbitrumInboxInterface) Address() common.Address { ret := _m.Called() diff --git a/core/gethwrappers/liquiditymanager/mocks/mock_arbitrum_l1_bridge_adapter/arbitrum_l1_bridge_adapter_interface.go b/core/gethwrappers/liquiditymanager/mocks/mock_arbitrum_l1_bridge_adapter/arbitrum_l1_bridge_adapter_interface.go index 65ddb6e398d..d1728d94e92 100644 --- a/core/gethwrappers/liquiditymanager/mocks/mock_arbitrum_l1_bridge_adapter/arbitrum_l1_bridge_adapter_interface.go +++ b/core/gethwrappers/liquiditymanager/mocks/mock_arbitrum_l1_bridge_adapter/arbitrum_l1_bridge_adapter_interface.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mock_arbitrum_l1_bridge_adapter @@ -29,7 +29,7 @@ func (_m *ArbitrumL1BridgeAdapterInterface) EXPECT() *ArbitrumL1BridgeAdapterInt return &ArbitrumL1BridgeAdapterInterface_Expecter{mock: &_m.Mock} } -// Address provides a mock function with given fields: +// Address provides a mock function with no fields func (_m *ArbitrumL1BridgeAdapterInterface) Address() common.Address { ret := _m.Called() diff --git a/core/gethwrappers/liquiditymanager/mocks/mock_arbitrum_l2_bridge_adapter/arbitrum_l2_bridge_adapter_interface.go b/core/gethwrappers/liquiditymanager/mocks/mock_arbitrum_l2_bridge_adapter/arbitrum_l2_bridge_adapter_interface.go index 873879f7d06..dc176879aa4 100644 --- a/core/gethwrappers/liquiditymanager/mocks/mock_arbitrum_l2_bridge_adapter/arbitrum_l2_bridge_adapter_interface.go +++ b/core/gethwrappers/liquiditymanager/mocks/mock_arbitrum_l2_bridge_adapter/arbitrum_l2_bridge_adapter_interface.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mock_arbitrum_l2_bridge_adapter @@ -26,7 +26,7 @@ func (_m *ArbitrumL2BridgeAdapterInterface) EXPECT() *ArbitrumL2BridgeAdapterInt return &ArbitrumL2BridgeAdapterInterface_Expecter{mock: &_m.Mock} } -// Address provides a mock function with given fields: +// Address provides a mock function with no fields func (_m *ArbitrumL2BridgeAdapterInterface) Address() common.Address { ret := _m.Called() diff --git a/core/gethwrappers/liquiditymanager/mocks/mock_arbitrum_rollup_core/arb_rollup_core_interface.go b/core/gethwrappers/liquiditymanager/mocks/mock_arbitrum_rollup_core/arb_rollup_core_interface.go index a41ee15a254..8dead9cf8b1 100644 --- a/core/gethwrappers/liquiditymanager/mocks/mock_arbitrum_rollup_core/arb_rollup_core_interface.go +++ b/core/gethwrappers/liquiditymanager/mocks/mock_arbitrum_rollup_core/arb_rollup_core_interface.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mock_arbitrum_rollup_core @@ -33,7 +33,7 @@ func (_m *ArbRollupCoreInterface) EXPECT() *ArbRollupCoreInterface_Expecter { return &ArbRollupCoreInterface_Expecter{mock: &_m.Mock} } -// Address provides a mock function with given fields: +// Address provides a mock function with no fields func (_m *ArbRollupCoreInterface) Address() common.Address { ret := _m.Called() diff --git a/core/gethwrappers/liquiditymanager/mocks/mock_arbsys/arb_sys_interface.go b/core/gethwrappers/liquiditymanager/mocks/mock_arbsys/arb_sys_interface.go index d07eef5b579..6e1af68b03d 100644 --- a/core/gethwrappers/liquiditymanager/mocks/mock_arbsys/arb_sys_interface.go +++ b/core/gethwrappers/liquiditymanager/mocks/mock_arbsys/arb_sys_interface.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mock_arbsys @@ -33,7 +33,7 @@ func (_m *ArbSysInterface) EXPECT() *ArbSysInterface_Expecter { return &ArbSysInterface_Expecter{mock: &_m.Mock} } -// Address provides a mock function with given fields: +// Address provides a mock function with no fields func (_m *ArbSysInterface) Address() common.Address { ret := _m.Called() diff --git a/core/gethwrappers/liquiditymanager/mocks/mock_l2_arbitrum_gateway/l2_arbitrum_gateway_interface.go b/core/gethwrappers/liquiditymanager/mocks/mock_l2_arbitrum_gateway/l2_arbitrum_gateway_interface.go index 5e8f4037eaf..d1b85f5a26b 100644 --- a/core/gethwrappers/liquiditymanager/mocks/mock_l2_arbitrum_gateway/l2_arbitrum_gateway_interface.go +++ b/core/gethwrappers/liquiditymanager/mocks/mock_l2_arbitrum_gateway/l2_arbitrum_gateway_interface.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mock_l2_arbitrum_gateway @@ -32,7 +32,7 @@ func (_m *L2ArbitrumGatewayInterface) EXPECT() *L2ArbitrumGatewayInterface_Expec return &L2ArbitrumGatewayInterface_Expecter{mock: &_m.Mock} } -// Address provides a mock function with given fields: +// Address provides a mock function with no fields func (_m *L2ArbitrumGatewayInterface) Address() common.Address { ret := _m.Called() diff --git a/core/gethwrappers/liquiditymanager/mocks/mock_l2_arbitrum_messenger/l2_arbitrum_messenger_interface.go b/core/gethwrappers/liquiditymanager/mocks/mock_l2_arbitrum_messenger/l2_arbitrum_messenger_interface.go index 1ee3fb075c4..576c15dbeef 100644 --- a/core/gethwrappers/liquiditymanager/mocks/mock_l2_arbitrum_messenger/l2_arbitrum_messenger_interface.go +++ b/core/gethwrappers/liquiditymanager/mocks/mock_l2_arbitrum_messenger/l2_arbitrum_messenger_interface.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mock_l2_arbitrum_messenger @@ -32,7 +32,7 @@ func (_m *L2ArbitrumMessengerInterface) EXPECT() *L2ArbitrumMessengerInterface_E return &L2ArbitrumMessengerInterface_Expecter{mock: &_m.Mock} } -// Address provides a mock function with given fields: +// Address provides a mock function with no fields func (_m *L2ArbitrumMessengerInterface) Address() common.Address { ret := _m.Called() diff --git a/core/gethwrappers/liquiditymanager/mocks/mock_node_interface/node_interface_interface.go b/core/gethwrappers/liquiditymanager/mocks/mock_node_interface/node_interface_interface.go index 6950201b8c8..0f85d52cb23 100644 --- a/core/gethwrappers/liquiditymanager/mocks/mock_node_interface/node_interface_interface.go +++ b/core/gethwrappers/liquiditymanager/mocks/mock_node_interface/node_interface_interface.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mock_node_interface @@ -29,7 +29,7 @@ func (_m *NodeInterfaceInterface) EXPECT() *NodeInterfaceInterface_Expecter { return &NodeInterfaceInterface_Expecter{mock: &_m.Mock} } -// Address provides a mock function with given fields: +// Address provides a mock function with no fields func (_m *NodeInterfaceInterface) Address() common.Address { ret := _m.Called() diff --git a/core/gethwrappers/liquiditymanager/mocks/mock_optimism_dispute_game_factory/optimism_dispute_game_factory_interface.go b/core/gethwrappers/liquiditymanager/mocks/mock_optimism_dispute_game_factory/optimism_dispute_game_factory_interface.go index 1ffa9426638..0e47f57a1f3 100644 --- a/core/gethwrappers/liquiditymanager/mocks/mock_optimism_dispute_game_factory/optimism_dispute_game_factory_interface.go +++ b/core/gethwrappers/liquiditymanager/mocks/mock_optimism_dispute_game_factory/optimism_dispute_game_factory_interface.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mock_optimism_dispute_game_factory @@ -26,7 +26,7 @@ func (_m *OptimismDisputeGameFactoryInterface) EXPECT() *OptimismDisputeGameFact return &OptimismDisputeGameFactoryInterface_Expecter{mock: &_m.Mock} } -// Address provides a mock function with given fields: +// Address provides a mock function with no fields func (_m *OptimismDisputeGameFactoryInterface) Address() common.Address { ret := _m.Called() diff --git a/core/gethwrappers/liquiditymanager/mocks/mock_optimism_l2_output_oracle/optimism_l2_output_oracle_interface.go b/core/gethwrappers/liquiditymanager/mocks/mock_optimism_l2_output_oracle/optimism_l2_output_oracle_interface.go index 2736d2a5ed3..bffece06092 100644 --- a/core/gethwrappers/liquiditymanager/mocks/mock_optimism_l2_output_oracle/optimism_l2_output_oracle_interface.go +++ b/core/gethwrappers/liquiditymanager/mocks/mock_optimism_l2_output_oracle/optimism_l2_output_oracle_interface.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mock_optimism_l2_output_oracle @@ -26,7 +26,7 @@ func (_m *OptimismL2OutputOracleInterface) EXPECT() *OptimismL2OutputOracleInter return &OptimismL2OutputOracleInterface_Expecter{mock: &_m.Mock} } -// Address provides a mock function with given fields: +// Address provides a mock function with no fields func (_m *OptimismL2OutputOracleInterface) Address() common.Address { ret := _m.Called() diff --git a/core/gethwrappers/liquiditymanager/mocks/mock_optimism_portal/optimism_portal_interface.go b/core/gethwrappers/liquiditymanager/mocks/mock_optimism_portal/optimism_portal_interface.go index dcfc2758406..cdfd585df4d 100644 --- a/core/gethwrappers/liquiditymanager/mocks/mock_optimism_portal/optimism_portal_interface.go +++ b/core/gethwrappers/liquiditymanager/mocks/mock_optimism_portal/optimism_portal_interface.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mock_optimism_portal @@ -28,7 +28,7 @@ func (_m *OptimismPortalInterface) EXPECT() *OptimismPortalInterface_Expecter { return &OptimismPortalInterface_Expecter{mock: &_m.Mock} } -// Address provides a mock function with given fields: +// Address provides a mock function with no fields func (_m *OptimismPortalInterface) Address() common.Address { ret := _m.Called() diff --git a/core/gethwrappers/liquiditymanager/mocks/mock_optimism_portal_2/optimism_portal2_interface.go b/core/gethwrappers/liquiditymanager/mocks/mock_optimism_portal_2/optimism_portal2_interface.go index d693ff317bc..bb820a7f415 100644 --- a/core/gethwrappers/liquiditymanager/mocks/mock_optimism_portal_2/optimism_portal2_interface.go +++ b/core/gethwrappers/liquiditymanager/mocks/mock_optimism_portal_2/optimism_portal2_interface.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mock_optimism_portal_2 @@ -22,7 +22,7 @@ func (_m *OptimismPortal2Interface) EXPECT() *OptimismPortal2Interface_Expecter return &OptimismPortal2Interface_Expecter{mock: &_m.Mock} } -// Address provides a mock function with given fields: +// Address provides a mock function with no fields func (_m *OptimismPortal2Interface) Address() common.Address { ret := _m.Called() diff --git a/core/gethwrappers/llo-feeds/generated/fee_manager_v0_5_0/fee_manager_v0_5_0.go b/core/gethwrappers/llo-feeds/generated/fee_manager_v0_5_0/fee_manager_v0_5_0.go new file mode 100644 index 00000000000..64b70873b0a --- /dev/null +++ b/core/gethwrappers/llo-feeds/generated/fee_manager_v0_5_0/fee_manager_v0_5_0.go @@ -0,0 +1,1786 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package fee_manager_v0_5_0 + +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 +) + +type CommonAddressAndWeight struct { + Addr common.Address + Weight uint64 +} + +type CommonAsset struct { + AssetAddress common.Address + Amount *big.Int +} + +type IRewardManagerFeePayment struct { + PoolId [32]byte + Amount *big.Int +} + +var FeeManagerMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_linkAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_nativeAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_proxyAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_rewardManagerAddress\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ExpiredReport\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDeposit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDiscount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidQuote\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReceivingAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSurcharge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroDeficit\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"subscriber\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"structCommon.Asset\",\"name\":\"fee\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"structCommon.Asset\",\"name\":\"reward\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"appliedDiscount\",\"type\":\"uint256\"}],\"name\":\"DiscountApplied\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"poolId\",\"type\":\"bytes32\"},{\"internalType\":\"uint192\",\"name\":\"amount\",\"type\":\"uint192\"}],\"indexed\":false,\"internalType\":\"structIRewardManager.FeePayment[]\",\"name\":\"rewards\",\"type\":\"tuple[]\"}],\"name\":\"InsufficientLink\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"linkQuantity\",\"type\":\"uint256\"}],\"name\":\"LinkDeficitCleared\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"newSurcharge\",\"type\":\"uint64\"}],\"name\":\"NativeSurchargeUpdated\",\"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\":true,\"internalType\":\"address\",\"name\":\"subscriber\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"feedId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"discount\",\"type\":\"uint64\"}],\"name\":\"SubscriberDiscountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"adminAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint192\",\"name\":\"quantity\",\"type\":\"uint192\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"subscriber\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"quoteAddress\",\"type\":\"address\"}],\"name\":\"getFeeAndReward\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structCommon.Asset\",\"name\":\"\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structCommon.Asset\",\"name\":\"\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_linkAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_nativeAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_proxyAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_rewardManager\",\"outputs\":[{\"internalType\":\"contractIRewardManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"linkAvailableForPayment\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"payLinkDeficit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"parameterPayload\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"subscriber\",\"type\":\"address\"}],\"name\":\"processFee\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"payloads\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"parameterPayload\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"subscriber\",\"type\":\"address\"}],\"name\":\"processFeeBulk\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"s_globalDiscounts\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"s_linkDeficit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_nativeSurcharge\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"s_subscriberDiscounts\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"weight\",\"type\":\"uint64\"}],\"internalType\":\"structCommon.AddressAndWeight[]\",\"name\":\"rewardRecipientAndWeights\",\"type\":\"tuple[]\"}],\"name\":\"setFeeRecipients\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"surcharge\",\"type\":\"uint64\"}],\"name\":\"setNativeSurcharge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"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\":\"address\",\"name\":\"subscriber\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"feedId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"discount\",\"type\":\"uint64\"}],\"name\":\"updateSubscriberDiscount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"subscriber\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"discount\",\"type\":\"uint64\"}],\"name\":\"updateSubscriberGlobalDiscount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint192\",\"name\":\"quantity\",\"type\":\"uint192\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x6101006040523480156200001257600080fd5b506040516200374038038062003740833981016040819052620000359162000288565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001c0565b5050506001600160a01b0384161580620000e057506001600160a01b038316155b80620000f357506001600160a01b038216155b806200010657506001600160a01b038116155b15620001255760405163e6c4247b60e01b815260040160405180910390fd5b6001600160a01b03848116608081905284821660a05283821660c05290821660e081905260405163095ea7b360e01b81526004810191909152600019602482015263095ea7b3906044016020604051808303816000875af11580156200018f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001b59190620002e5565b505050505062000310565b336001600160a01b038216036200021a5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b03811681146200028357600080fd5b919050565b600080600080608085870312156200029f57600080fd5b620002aa856200026b565b9350620002ba602086016200026b565b9250620002ca604086016200026b565b9150620002da606086016200026b565b905092959194509250565b600060208284031215620002f857600080fd5b815180151581146200030957600080fd5b9392505050565b60805160a05160c05160e05161334062000400600039600081816102c301528181611644015281816117d20152818161209101526122df015260008181610383015281816107d701528181610f47015261171801526000818161033c01528181610ab301528181610d6a01528181611164015281816111bb015281816114b901528181611fb701526120600152600081816105280152818161095201528181610a5c01528181610d1301528181610eaa015281816110530152818161118901528181611212015281816113aa015281816114150152818161145501528181611c32015261215201526133406000f3fe6080604052600436106101805760003560e01c806376cf3187116100d6578063dba45fe01161007f578063ea4b861b11610059578063ea4b861b14610516578063f2fde38b1461054a578063f65df9621461056a57600080fd5b8063dba45fe014610478578063e03dab1a1461048b578063e389d9a4146104f657600080fd5b80638da5cb5b116100b05780638da5cb5b14610418578063ce7817d114610443578063d09dc3391461046357600080fd5b806376cf3187146103a557806379ba5097146103c557806387d6d843146103da57600080fd5b806332f5f746116101385780636387866811610112578063638786681461032a5780636c2f1a171461035e5780636d1342cb1461037157600080fd5b806332f5f7461461029b5780633aa5ac07146102b1578063505380941461030a57600080fd5b8063181f5a7711610169578063181f5a77146101f55780631cc7f2d8146102415780631d4d84a21461027957600080fd5b8063013f542b1461018557806301ffc9a7146101c5575b600080fd5b34801561019157600080fd5b506101b26101a036600461289a565b60046020526000908152604090205481565b6040519081526020015b60405180910390f35b3480156101d157600080fd5b506101e56101e03660046128b3565b61058a565b60405190151581526020016101bc565b34801561020157600080fd5b50604080518082018252601081527f4665654d616e6167657220322e312e3000000000000000000000000000000000602082015290516101bc9190612919565b34801561024d57600080fd5b506101b261025c36600461299c565b600360209081526000928352604080842090915290825290205481565b34801561028557600080fd5b506102996102943660046129fb565b610623565b005b3480156102a757600080fd5b506101b260055481565b3480156102bd57600080fd5b506102e57f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101bc565b34801561031657600080fd5b50610299610325366004612a5e565b610725565b34801561033657600080fd5b506102e57f000000000000000000000000000000000000000000000000000000000000000081565b61029961036c366004612ac2565b6107bf565b34801561037d57600080fd5b506102e57f000000000000000000000000000000000000000000000000000000000000000081565b3480156103b157600080fd5b506102996103c0366004612b71565b610a06565b3480156103d157600080fd5b50610299610bbb565b3480156103e657600080fd5b506101b26103f5366004612bb8565b600260209081526000938452604080852082529284528284209052825290205481565b34801561042457600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166102e5565b34801561044f57600080fd5b5061029961045e366004612bef565b610cbd565b34801561046f57600080fd5b506101b2610e79565b610299610486366004612c40565b610f2f565b34801561049757600080fd5b506104ab6104a6366004612d9e565b6110cb565b60408051845173ffffffffffffffffffffffffffffffffffffffff9081168252602095860151868301528451169181019190915292909101516060830152608082015260a0016101bc565b34801561050257600080fd5b5061029961051136600461289a565b61151b565b34801561052257600080fd5b506102e57f000000000000000000000000000000000000000000000000000000000000000081565b34801561055657600080fd5b50610299610565366004612df7565b6116ec565b34801561057657600080fd5b50610299610585366004612e14565b611700565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fdba45fe000000000000000000000000000000000000000000000000000000000148061061d57507fffffffff0000000000000000000000000000000000000000000000000000000082167f6c2f1a1700000000000000000000000000000000000000000000000000000000145b92915050565b61062b611842565b73ffffffffffffffffffffffffffffffffffffffff831661066f5761066a828277ffffffffffffffffffffffffffffffffffffffffffffffff166118c5565b505050565b6106aa73ffffffffffffffffffffffffffffffffffffffff84168377ffffffffffffffffffffffffffffffffffffffffffffffff8416611969565b6040805133815273ffffffffffffffffffffffffffffffffffffffff848116602083015285168183015277ffffffffffffffffffffffffffffffffffffffffffffffff8316606082015290517f7ff78a71698bdb18dcca96f52ab25e0a1b146fb6a49adf8e6845299e49021f299181900360800190a1505050565b61072d611842565b670de0b6b3a764000067ffffffffffffffff82161115610779576040517f05e8ac2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff811660058190556040519081527f08f7c0d17932ddb8523bc06754d42ff19ebc77d76a8b9bfde02c28ab1ed3d6399060200160405180910390a150565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461082e576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008467ffffffffffffffff81111561084957610849612cc4565b60405190808252806020026020018201604052801561088257816020015b61086f61280d565b8152602001906001900390816108675790505b5090506000806000805b888110156109cd5760008060006108c88d8d868181106108ae576108ae612e93565b90506020028101906108c09190612ec2565b8d8d8d611a3d565b92509250925082602001516000146109b95760405180608001604052808e8e878181106108f7576108f7612e93565b90506020028101906109099190612ec2565b61091291612f27565b81526020018481526020018381526020018281525088868061093390612f92565b97508151811061094557610945612e93565b60200260200101819052507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16836000015173ffffffffffffffffffffffffffffffffffffffff16036109b2578660010196506109b9565b8560010195505b505050806109c690612f92565b905061088c565b50821515806109db57508115155b156109f1576109ec85858585611b4d565b6109fb565b6109fb85346118c5565b505050505050505050565b610a0e611842565b670de0b6b3a764000067ffffffffffffffff82161115610a5a576040517f997ea36000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614158015610b0257507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b15610b39576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff838116600081815260036020908152604080832094871680845294825280832067ffffffffffffffff87169081905581519586529185019190915290927f5eba5a8afa39780f0f99b6cbeb95f3da6a7040ca00abd46bdc91a0a060134139910160405180910390a3505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610c41576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610cc5611842565b670de0b6b3a764000067ffffffffffffffff82161115610d11576040517f997ea36000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614158015610db957507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b15610df0576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff848116600081815260026020908152604080832088845282528083209487168084529482529182902067ffffffffffffffff86169081905582519485529084015285927f5eba5a8afa39780f0f99b6cbeb95f3da6a7040ca00abd46bdc91a0a060134139910160405180910390a350505050565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015610f06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2a9190612fca565b905090565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610f9e576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000806000610fb08888888888611a3d565b9250925092508260200151600003610fd457610fcc84346118c5565b5050506110c4565b604080516001808252818301909252600091816020015b610ff361280d565b815260200190600190039081610feb57505060408051608081019091529091508061101e8a8c612f27565b8152602001858152602001848152602001838152508160008151811061104657611046612e93565b60200260200101819052507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff16036110b6576109ec858260016000611b4d565b6109fb858260006001611b4d565b5050505050565b604080518082018252600080825260208083018290528351808501855282815280820183905284518086018652838152808301849052855180870190965283865291850183905292938261111e88612fe3565b90507fffff0000000000000000000000000000000000000000000000000000000000008082169081016111b957505073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811683527f0000000000000000000000000000000000000000000000000000000000000000168152909350915060009050611512565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161415801561126157507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614155b15611298576040517ff861803000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008b8060200190518101906112b1919061303c565b77ffffffffffffffffffffffffffffffffffffffffffffffff91821698509116955063ffffffff1693505050428210159050611319576040517fb6c405f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff808e1660009081526002602090815260408083208984528252808320938f1683529290529081205490819003611393575073ffffffffffffffffffffffffffffffffffffffff808e166000908152600360209081526040808320938f16835292905220545b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001687526113f96113e182670de0b6b3a76400006130ae565b6113eb90866130c1565b670de0b6b3a7640000612361565b602088015273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116908d16036114865773ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016885260208088015190890152611503565b6005546000906114a2906113e190670de0b6b3a76400006130d8565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168a5290506114fc6114f283670de0b6b3a76400006130ae565b6113eb90836130c1565b60208a0152505b96995094975094955050505050505b93509350939050565b611523611842565b6000818152600460205260408120549081900361156c576040517f03aad31200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600460205260408082208290558051600180825281830190925290816020015b604080518082019091526000808252602082015281526020019060019003908161159157905050905060405180604001604052808481526020018377ffffffffffffffffffffffffffffffffffffffffffffffff16815250816000815181106115fc576115fc612e93565b60209081029190910101526040517fb0d9fa1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063b0d9fa199061167b908490309060040161314b565b600060405180830381600087803b15801561169557600080fd5b505af11580156116a9573d6000803e3d6000fd5b50505050827f843f0b103e50b42b08f9d30f12f961845a6d02623730872e24644899c0dd9895836040516116df91815260200190565b60405180910390a2505050565b6116f4611842565b6116fd81612399565b50565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480159061175e575060005473ffffffffffffffffffffffffffffffffffffffff163314155b15611795576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f14060f2300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906314060f239061180b90869086908690600401613183565b600060405180830381600087803b15801561182557600080fd5b505af1158015611839573d6000803e3d6000fd5b50505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146118c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610c38565b565b80156119655760008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611925576040519150601f19603f3d011682016040523d82523d6000602084013e61192a565b606091505b505090508061066a576040517fef2af20100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905261066a9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261248e565b6040805180820190915260008082526020820152604080518082019091526000808252602082015260003073ffffffffffffffffffffffffffffffffffffffff851603611ab6576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611ac4888a018a613203565b915050600081611ad390612fe3565b905060007e010000000000000000000000000000000000000000000000000000000000007fffff000000000000000000000000000000000000000000000000000000000000831614611b2e57611b2b888a018a612df7565b90505b611b398784836110cb565b955095509550505050955095509592505050565b60008267ffffffffffffffff811115611b6857611b68612cc4565b604051908082528060200260200182016040528015611bad57816020015b6040805180820190915260008082526020820152815260200190600190039081611b865790505b50905060008267ffffffffffffffff811115611bcb57611bcb612cc4565b604051908082528060200260200182016040528015611c1057816020015b6040805180820190915260008082526020820152815260200190600190039081611be95790505b509050600080808080611c23888a6130d8565b905060005b81811015611f72577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168b8281518110611c7957611c79612e93565b6020026020010151602001516000015173ffffffffffffffffffffffffffffffffffffffff1603611d3f5760405180604001604052808c8381518110611cc157611cc1612e93565b60200260200101516000015181526020018c8381518110611ce457611ce4612e93565b6020026020010151604001516020015177ffffffffffffffffffffffffffffffffffffffffffffffff16815250888580611d1d90612f92565b965081518110611d2f57611d2f612e93565b6020026020010181905250611e34565b60405180604001604052808c8381518110611d5c57611d5c612e93565b60200260200101516000015181526020018c8381518110611d7f57611d7f612e93565b6020026020010151604001516020015177ffffffffffffffffffffffffffffffffffffffffffffffff16815250878480611db890612f92565b955081518110611dca57611dca612e93565b60200260200101819052508a8181518110611de757611de7612e93565b6020026020010151602001516020015186611e0291906130d8565b95508a8181518110611e1657611e16612e93565b6020026020010151604001516020015185611e3191906130d8565b94505b8a8181518110611e4657611e46612e93565b602002602001015160600151600014611f62578b73ffffffffffffffffffffffffffffffffffffffff168b8281518110611e8257611e82612e93565b6020026020010151600001517f88b15eb682210089cddf967648e2cb2a4535aeadc8f8f36050922e33c04e71258d8481518110611ec157611ec1612e93565b6020026020010151602001518e8581518110611edf57611edf612e93565b6020026020010151604001518f8681518110611efd57611efd612e93565b602002602001015160600151604051611f5993929190835173ffffffffffffffffffffffffffffffffffffffff908116825260209485015185830152835116604082015291909201516060820152608081019190915260a00190565b60405180910390a35b611f6b81612f92565b9050611c28565b50600034156120405734861115611fb5576040517fb2e532de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0876040518263ffffffff1660e01b81526004016000604051808303818588803b15801561201d57600080fd5b505af1158015612031573d6000803e3d6000fd5b50505050508534039050612088565b85156120885761208873ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168d308961259a565b87511561211d577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663b0d9fa19898e6040518363ffffffff1660e01b81526004016120ea92919061314b565b600060405180830381600087803b15801561210457600080fd5b505af1158015612118573d6000803e3d6000fd5b505050505b865115612349576040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa1580156121ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121d29190612fca565b8511156122a25760005b8751811015612265578781815181106121f7576121f7612e93565b60200260200101516020015177ffffffffffffffffffffffffffffffffffffffffffffffff16600460008a848151811061223357612233612e93565b6020908102919091018101515182528101919091526040016000208054909101905561225e81612f92565b90506121dc565b507ff52e5907b69d97c33392936c12d78b494463b78c5b72df50b4c497eee5720b678760405161229591906132a7565b60405180910390a1612349565b6040517fb0d9fa1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063b0d9fa1990612316908a90309060040161314b565b600060405180830381600087803b15801561233057600080fd5b505af1158015612344573d6000803e3d6000fd5b505050505b6123538c826118c5565b505050505050505050505050565b6000821561238f57816123756001856130ae565b61237f91906132ba565b61238a9060016130d8565b612392565b60005b9392505050565b3373ffffffffffffffffffffffffffffffffffffffff821603612418576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610c38565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60006124f0826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166125fe9092919063ffffffff16565b80519091501561066a578080602001905181019061250e91906132f5565b61066a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610c38565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526125f89085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016119bb565b50505050565b606061260d8484600085612615565b949350505050565b6060824710156126a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610c38565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516126d09190613317565b60006040518083038185875af1925050503d806000811461270d576040519150601f19603f3d011682016040523d82523d6000602084013e612712565b606091505b50915091506127238783838761272e565b979650505050505050565b606083156127c45782516000036127bd5773ffffffffffffffffffffffffffffffffffffffff85163b6127bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610c38565b508161260d565b61260d83838151156127d95781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c389190612919565b6040518060800160405280600080191681526020016128556040518060400160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600081525090565b815260200161288d6040518060400160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600081525090565b8152602001600081525090565b6000602082840312156128ac57600080fd5b5035919050565b6000602082840312156128c557600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461239257600080fd5b60005b838110156129105781810151838201526020016128f8565b50506000910152565b60208152600082518060208401526129388160408501602087016128f5565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b73ffffffffffffffffffffffffffffffffffffffff811681146116fd57600080fd5b80356129978161296a565b919050565b600080604083850312156129af57600080fd5b82356129ba8161296a565b915060208301356129ca8161296a565b809150509250929050565b77ffffffffffffffffffffffffffffffffffffffffffffffff811681146116fd57600080fd5b600080600060608486031215612a1057600080fd5b8335612a1b8161296a565b92506020840135612a2b8161296a565b91506040840135612a3b816129d5565b809150509250925092565b803567ffffffffffffffff8116811461299757600080fd5b600060208284031215612a7057600080fd5b61239282612a46565b60008083601f840112612a8b57600080fd5b50813567ffffffffffffffff811115612aa357600080fd5b602083019150836020828501011115612abb57600080fd5b9250929050565b600080600080600060608688031215612ada57600080fd5b853567ffffffffffffffff80821115612af257600080fd5b818801915088601f830112612b0657600080fd5b813581811115612b1557600080fd5b8960208260051b8501011115612b2a57600080fd5b602092830197509550908701359080821115612b4557600080fd5b50612b5288828901612a79565b9094509250612b6590506040870161298c565b90509295509295909350565b600080600060608486031215612b8657600080fd5b8335612b918161296a565b92506020840135612ba18161296a565b9150612baf60408501612a46565b90509250925092565b600080600060608486031215612bcd57600080fd5b8335612bd88161296a565b9250602084013591506040840135612a3b8161296a565b60008060008060808587031215612c0557600080fd5b8435612c108161296a565b9350602085013592506040850135612c278161296a565b9150612c3560608601612a46565b905092959194509250565b600080600080600060608688031215612c5857600080fd5b853567ffffffffffffffff80821115612c7057600080fd5b612c7c89838a01612a79565b90975095506020880135915080821115612c9557600080fd5b50612ca288828901612a79565b9094509250506040860135612cb68161296a565b809150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112612d0457600080fd5b813567ffffffffffffffff80821115612d1f57612d1f612cc4565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715612d6557612d65612cc4565b81604052838152866020858801011115612d7e57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600060608486031215612db357600080fd5b8335612dbe8161296a565b9250602084013567ffffffffffffffff811115612dda57600080fd5b612de686828701612cf3565b9250506040840135612a3b8161296a565b600060208284031215612e0957600080fd5b81356123928161296a565b600080600060408486031215612e2957600080fd5b83359250602084013567ffffffffffffffff80821115612e4857600080fd5b818601915086601f830112612e5c57600080fd5b813581811115612e6b57600080fd5b8760208260061b8501011115612e8057600080fd5b6020830194508093505050509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612ef757600080fd5b83018035915067ffffffffffffffff821115612f1257600080fd5b602001915036819003821315612abb57600080fd5b8035602083101561061d577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612fc357612fc3612f63565b5060010190565b600060208284031215612fdc57600080fd5b5051919050565b80516020808301519190811015613022577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8160200360031b1b821691505b50919050565b805163ffffffff8116811461299757600080fd5b60008060008060008060c0878903121561305557600080fd5b8651955061306560208801613028565b945061307360408801613028565b93506060870151613083816129d5565b6080880151909350613094816129d5565b91506130a260a08801613028565b90509295509295509295565b8181038181111561061d5761061d612f63565b808202811582820484141761061d5761061d612f63565b8082018082111561061d5761061d612f63565b600081518084526020808501945080840160005b838110156131405781518051885283015177ffffffffffffffffffffffffffffffffffffffffffffffff1683880152604090960195908201906001016130ff565b509495945050505050565b60408152600061315e60408301856130eb565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b8381526040602080830182905282820184905260009190859060608501845b878110156131f65783356131b58161296a565b73ffffffffffffffffffffffffffffffffffffffff16825267ffffffffffffffff6131e1858501612a46565b168284015292840192908401906001016131a2565b5098975050505050505050565b6000806080838503121561321657600080fd5b83601f84011261322557600080fd5b6040516060810167ffffffffffffffff828210818311171561324957613249612cc4565b81604052829150606086018781111561326157600080fd5b865b8181101561327b578035845260209384019301613263565b509294509135918083111561328f57600080fd5b505061329d85828601612cf3565b9150509250929050565b60208152600061239260208301846130eb565b6000826132f0577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60006020828403121561330757600080fd5b8151801515811461239257600080fd5b600082516133298184602087016128f5565b919091019291505056fea164736f6c6343000813000a", +} + +var FeeManagerABI = FeeManagerMetaData.ABI + +var FeeManagerBin = FeeManagerMetaData.Bin + +func DeployFeeManager(auth *bind.TransactOpts, backend bind.ContractBackend, _linkAddress common.Address, _nativeAddress common.Address, _proxyAddress common.Address, _rewardManagerAddress common.Address) (common.Address, *types.Transaction, *FeeManager, error) { + parsed, err := FeeManagerMetaData.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(FeeManagerBin), backend, _linkAddress, _nativeAddress, _proxyAddress, _rewardManagerAddress) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &FeeManager{address: address, abi: *parsed, FeeManagerCaller: FeeManagerCaller{contract: contract}, FeeManagerTransactor: FeeManagerTransactor{contract: contract}, FeeManagerFilterer: FeeManagerFilterer{contract: contract}}, nil +} + +type FeeManager struct { + address common.Address + abi abi.ABI + FeeManagerCaller + FeeManagerTransactor + FeeManagerFilterer +} + +type FeeManagerCaller struct { + contract *bind.BoundContract +} + +type FeeManagerTransactor struct { + contract *bind.BoundContract +} + +type FeeManagerFilterer struct { + contract *bind.BoundContract +} + +type FeeManagerSession struct { + Contract *FeeManager + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type FeeManagerCallerSession struct { + Contract *FeeManagerCaller + CallOpts bind.CallOpts +} + +type FeeManagerTransactorSession struct { + Contract *FeeManagerTransactor + TransactOpts bind.TransactOpts +} + +type FeeManagerRaw struct { + Contract *FeeManager +} + +type FeeManagerCallerRaw struct { + Contract *FeeManagerCaller +} + +type FeeManagerTransactorRaw struct { + Contract *FeeManagerTransactor +} + +func NewFeeManager(address common.Address, backend bind.ContractBackend) (*FeeManager, error) { + abi, err := abi.JSON(strings.NewReader(FeeManagerABI)) + if err != nil { + return nil, err + } + contract, err := bindFeeManager(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &FeeManager{address: address, abi: abi, FeeManagerCaller: FeeManagerCaller{contract: contract}, FeeManagerTransactor: FeeManagerTransactor{contract: contract}, FeeManagerFilterer: FeeManagerFilterer{contract: contract}}, nil +} + +func NewFeeManagerCaller(address common.Address, caller bind.ContractCaller) (*FeeManagerCaller, error) { + contract, err := bindFeeManager(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &FeeManagerCaller{contract: contract}, nil +} + +func NewFeeManagerTransactor(address common.Address, transactor bind.ContractTransactor) (*FeeManagerTransactor, error) { + contract, err := bindFeeManager(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &FeeManagerTransactor{contract: contract}, nil +} + +func NewFeeManagerFilterer(address common.Address, filterer bind.ContractFilterer) (*FeeManagerFilterer, error) { + contract, err := bindFeeManager(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &FeeManagerFilterer{contract: contract}, nil +} + +func bindFeeManager(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := FeeManagerMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_FeeManager *FeeManagerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _FeeManager.Contract.FeeManagerCaller.contract.Call(opts, result, method, params...) +} + +func (_FeeManager *FeeManagerRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _FeeManager.Contract.FeeManagerTransactor.contract.Transfer(opts) +} + +func (_FeeManager *FeeManagerRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _FeeManager.Contract.FeeManagerTransactor.contract.Transact(opts, method, params...) +} + +func (_FeeManager *FeeManagerCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _FeeManager.Contract.contract.Call(opts, result, method, params...) +} + +func (_FeeManager *FeeManagerTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _FeeManager.Contract.contract.Transfer(opts) +} + +func (_FeeManager *FeeManagerTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _FeeManager.Contract.contract.Transact(opts, method, params...) +} + +func (_FeeManager *FeeManagerCaller) GetFeeAndReward(opts *bind.CallOpts, subscriber common.Address, report []byte, quoteAddress common.Address) (CommonAsset, CommonAsset, *big.Int, error) { + var out []interface{} + err := _FeeManager.contract.Call(opts, &out, "getFeeAndReward", subscriber, report, quoteAddress) + + if err != nil { + return *new(CommonAsset), *new(CommonAsset), *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(CommonAsset)).(*CommonAsset) + out1 := *abi.ConvertType(out[1], new(CommonAsset)).(*CommonAsset) + out2 := *abi.ConvertType(out[2], new(*big.Int)).(**big.Int) + + return out0, out1, out2, err + +} + +func (_FeeManager *FeeManagerSession) GetFeeAndReward(subscriber common.Address, report []byte, quoteAddress common.Address) (CommonAsset, CommonAsset, *big.Int, error) { + return _FeeManager.Contract.GetFeeAndReward(&_FeeManager.CallOpts, subscriber, report, quoteAddress) +} + +func (_FeeManager *FeeManagerCallerSession) GetFeeAndReward(subscriber common.Address, report []byte, quoteAddress common.Address) (CommonAsset, CommonAsset, *big.Int, error) { + return _FeeManager.Contract.GetFeeAndReward(&_FeeManager.CallOpts, subscriber, report, quoteAddress) +} + +func (_FeeManager *FeeManagerCaller) ILinkAddress(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _FeeManager.contract.Call(opts, &out, "i_linkAddress") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_FeeManager *FeeManagerSession) ILinkAddress() (common.Address, error) { + return _FeeManager.Contract.ILinkAddress(&_FeeManager.CallOpts) +} + +func (_FeeManager *FeeManagerCallerSession) ILinkAddress() (common.Address, error) { + return _FeeManager.Contract.ILinkAddress(&_FeeManager.CallOpts) +} + +func (_FeeManager *FeeManagerCaller) INativeAddress(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _FeeManager.contract.Call(opts, &out, "i_nativeAddress") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_FeeManager *FeeManagerSession) INativeAddress() (common.Address, error) { + return _FeeManager.Contract.INativeAddress(&_FeeManager.CallOpts) +} + +func (_FeeManager *FeeManagerCallerSession) INativeAddress() (common.Address, error) { + return _FeeManager.Contract.INativeAddress(&_FeeManager.CallOpts) +} + +func (_FeeManager *FeeManagerCaller) IProxyAddress(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _FeeManager.contract.Call(opts, &out, "i_proxyAddress") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_FeeManager *FeeManagerSession) IProxyAddress() (common.Address, error) { + return _FeeManager.Contract.IProxyAddress(&_FeeManager.CallOpts) +} + +func (_FeeManager *FeeManagerCallerSession) IProxyAddress() (common.Address, error) { + return _FeeManager.Contract.IProxyAddress(&_FeeManager.CallOpts) +} + +func (_FeeManager *FeeManagerCaller) IRewardManager(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _FeeManager.contract.Call(opts, &out, "i_rewardManager") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_FeeManager *FeeManagerSession) IRewardManager() (common.Address, error) { + return _FeeManager.Contract.IRewardManager(&_FeeManager.CallOpts) +} + +func (_FeeManager *FeeManagerCallerSession) IRewardManager() (common.Address, error) { + return _FeeManager.Contract.IRewardManager(&_FeeManager.CallOpts) +} + +func (_FeeManager *FeeManagerCaller) LinkAvailableForPayment(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _FeeManager.contract.Call(opts, &out, "linkAvailableForPayment") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_FeeManager *FeeManagerSession) LinkAvailableForPayment() (*big.Int, error) { + return _FeeManager.Contract.LinkAvailableForPayment(&_FeeManager.CallOpts) +} + +func (_FeeManager *FeeManagerCallerSession) LinkAvailableForPayment() (*big.Int, error) { + return _FeeManager.Contract.LinkAvailableForPayment(&_FeeManager.CallOpts) +} + +func (_FeeManager *FeeManagerCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _FeeManager.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 (_FeeManager *FeeManagerSession) Owner() (common.Address, error) { + return _FeeManager.Contract.Owner(&_FeeManager.CallOpts) +} + +func (_FeeManager *FeeManagerCallerSession) Owner() (common.Address, error) { + return _FeeManager.Contract.Owner(&_FeeManager.CallOpts) +} + +func (_FeeManager *FeeManagerCaller) SGlobalDiscounts(opts *bind.CallOpts, arg0 common.Address, arg1 common.Address) (*big.Int, error) { + var out []interface{} + err := _FeeManager.contract.Call(opts, &out, "s_globalDiscounts", arg0, arg1) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_FeeManager *FeeManagerSession) SGlobalDiscounts(arg0 common.Address, arg1 common.Address) (*big.Int, error) { + return _FeeManager.Contract.SGlobalDiscounts(&_FeeManager.CallOpts, arg0, arg1) +} + +func (_FeeManager *FeeManagerCallerSession) SGlobalDiscounts(arg0 common.Address, arg1 common.Address) (*big.Int, error) { + return _FeeManager.Contract.SGlobalDiscounts(&_FeeManager.CallOpts, arg0, arg1) +} + +func (_FeeManager *FeeManagerCaller) SLinkDeficit(opts *bind.CallOpts, arg0 [32]byte) (*big.Int, error) { + var out []interface{} + err := _FeeManager.contract.Call(opts, &out, "s_linkDeficit", arg0) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_FeeManager *FeeManagerSession) SLinkDeficit(arg0 [32]byte) (*big.Int, error) { + return _FeeManager.Contract.SLinkDeficit(&_FeeManager.CallOpts, arg0) +} + +func (_FeeManager *FeeManagerCallerSession) SLinkDeficit(arg0 [32]byte) (*big.Int, error) { + return _FeeManager.Contract.SLinkDeficit(&_FeeManager.CallOpts, arg0) +} + +func (_FeeManager *FeeManagerCaller) SNativeSurcharge(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _FeeManager.contract.Call(opts, &out, "s_nativeSurcharge") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_FeeManager *FeeManagerSession) SNativeSurcharge() (*big.Int, error) { + return _FeeManager.Contract.SNativeSurcharge(&_FeeManager.CallOpts) +} + +func (_FeeManager *FeeManagerCallerSession) SNativeSurcharge() (*big.Int, error) { + return _FeeManager.Contract.SNativeSurcharge(&_FeeManager.CallOpts) +} + +func (_FeeManager *FeeManagerCaller) SSubscriberDiscounts(opts *bind.CallOpts, arg0 common.Address, arg1 [32]byte, arg2 common.Address) (*big.Int, error) { + var out []interface{} + err := _FeeManager.contract.Call(opts, &out, "s_subscriberDiscounts", arg0, arg1, arg2) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_FeeManager *FeeManagerSession) SSubscriberDiscounts(arg0 common.Address, arg1 [32]byte, arg2 common.Address) (*big.Int, error) { + return _FeeManager.Contract.SSubscriberDiscounts(&_FeeManager.CallOpts, arg0, arg1, arg2) +} + +func (_FeeManager *FeeManagerCallerSession) SSubscriberDiscounts(arg0 common.Address, arg1 [32]byte, arg2 common.Address) (*big.Int, error) { + return _FeeManager.Contract.SSubscriberDiscounts(&_FeeManager.CallOpts, arg0, arg1, arg2) +} + +func (_FeeManager *FeeManagerCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + var out []interface{} + err := _FeeManager.contract.Call(opts, &out, "supportsInterface", interfaceId) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_FeeManager *FeeManagerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _FeeManager.Contract.SupportsInterface(&_FeeManager.CallOpts, interfaceId) +} + +func (_FeeManager *FeeManagerCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _FeeManager.Contract.SupportsInterface(&_FeeManager.CallOpts, interfaceId) +} + +func (_FeeManager *FeeManagerCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _FeeManager.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_FeeManager *FeeManagerSession) TypeAndVersion() (string, error) { + return _FeeManager.Contract.TypeAndVersion(&_FeeManager.CallOpts) +} + +func (_FeeManager *FeeManagerCallerSession) TypeAndVersion() (string, error) { + return _FeeManager.Contract.TypeAndVersion(&_FeeManager.CallOpts) +} + +func (_FeeManager *FeeManagerTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _FeeManager.contract.Transact(opts, "acceptOwnership") +} + +func (_FeeManager *FeeManagerSession) AcceptOwnership() (*types.Transaction, error) { + return _FeeManager.Contract.AcceptOwnership(&_FeeManager.TransactOpts) +} + +func (_FeeManager *FeeManagerTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _FeeManager.Contract.AcceptOwnership(&_FeeManager.TransactOpts) +} + +func (_FeeManager *FeeManagerTransactor) PayLinkDeficit(opts *bind.TransactOpts, configDigest [32]byte) (*types.Transaction, error) { + return _FeeManager.contract.Transact(opts, "payLinkDeficit", configDigest) +} + +func (_FeeManager *FeeManagerSession) PayLinkDeficit(configDigest [32]byte) (*types.Transaction, error) { + return _FeeManager.Contract.PayLinkDeficit(&_FeeManager.TransactOpts, configDigest) +} + +func (_FeeManager *FeeManagerTransactorSession) PayLinkDeficit(configDigest [32]byte) (*types.Transaction, error) { + return _FeeManager.Contract.PayLinkDeficit(&_FeeManager.TransactOpts, configDigest) +} + +func (_FeeManager *FeeManagerTransactor) ProcessFee(opts *bind.TransactOpts, payload []byte, parameterPayload []byte, subscriber common.Address) (*types.Transaction, error) { + return _FeeManager.contract.Transact(opts, "processFee", payload, parameterPayload, subscriber) +} + +func (_FeeManager *FeeManagerSession) ProcessFee(payload []byte, parameterPayload []byte, subscriber common.Address) (*types.Transaction, error) { + return _FeeManager.Contract.ProcessFee(&_FeeManager.TransactOpts, payload, parameterPayload, subscriber) +} + +func (_FeeManager *FeeManagerTransactorSession) ProcessFee(payload []byte, parameterPayload []byte, subscriber common.Address) (*types.Transaction, error) { + return _FeeManager.Contract.ProcessFee(&_FeeManager.TransactOpts, payload, parameterPayload, subscriber) +} + +func (_FeeManager *FeeManagerTransactor) ProcessFeeBulk(opts *bind.TransactOpts, payloads [][]byte, parameterPayload []byte, subscriber common.Address) (*types.Transaction, error) { + return _FeeManager.contract.Transact(opts, "processFeeBulk", payloads, parameterPayload, subscriber) +} + +func (_FeeManager *FeeManagerSession) ProcessFeeBulk(payloads [][]byte, parameterPayload []byte, subscriber common.Address) (*types.Transaction, error) { + return _FeeManager.Contract.ProcessFeeBulk(&_FeeManager.TransactOpts, payloads, parameterPayload, subscriber) +} + +func (_FeeManager *FeeManagerTransactorSession) ProcessFeeBulk(payloads [][]byte, parameterPayload []byte, subscriber common.Address) (*types.Transaction, error) { + return _FeeManager.Contract.ProcessFeeBulk(&_FeeManager.TransactOpts, payloads, parameterPayload, subscriber) +} + +func (_FeeManager *FeeManagerTransactor) SetFeeRecipients(opts *bind.TransactOpts, configDigest [32]byte, rewardRecipientAndWeights []CommonAddressAndWeight) (*types.Transaction, error) { + return _FeeManager.contract.Transact(opts, "setFeeRecipients", configDigest, rewardRecipientAndWeights) +} + +func (_FeeManager *FeeManagerSession) SetFeeRecipients(configDigest [32]byte, rewardRecipientAndWeights []CommonAddressAndWeight) (*types.Transaction, error) { + return _FeeManager.Contract.SetFeeRecipients(&_FeeManager.TransactOpts, configDigest, rewardRecipientAndWeights) +} + +func (_FeeManager *FeeManagerTransactorSession) SetFeeRecipients(configDigest [32]byte, rewardRecipientAndWeights []CommonAddressAndWeight) (*types.Transaction, error) { + return _FeeManager.Contract.SetFeeRecipients(&_FeeManager.TransactOpts, configDigest, rewardRecipientAndWeights) +} + +func (_FeeManager *FeeManagerTransactor) SetNativeSurcharge(opts *bind.TransactOpts, surcharge uint64) (*types.Transaction, error) { + return _FeeManager.contract.Transact(opts, "setNativeSurcharge", surcharge) +} + +func (_FeeManager *FeeManagerSession) SetNativeSurcharge(surcharge uint64) (*types.Transaction, error) { + return _FeeManager.Contract.SetNativeSurcharge(&_FeeManager.TransactOpts, surcharge) +} + +func (_FeeManager *FeeManagerTransactorSession) SetNativeSurcharge(surcharge uint64) (*types.Transaction, error) { + return _FeeManager.Contract.SetNativeSurcharge(&_FeeManager.TransactOpts, surcharge) +} + +func (_FeeManager *FeeManagerTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _FeeManager.contract.Transact(opts, "transferOwnership", to) +} + +func (_FeeManager *FeeManagerSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _FeeManager.Contract.TransferOwnership(&_FeeManager.TransactOpts, to) +} + +func (_FeeManager *FeeManagerTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _FeeManager.Contract.TransferOwnership(&_FeeManager.TransactOpts, to) +} + +func (_FeeManager *FeeManagerTransactor) UpdateSubscriberDiscount(opts *bind.TransactOpts, subscriber common.Address, feedId [32]byte, token common.Address, discount uint64) (*types.Transaction, error) { + return _FeeManager.contract.Transact(opts, "updateSubscriberDiscount", subscriber, feedId, token, discount) +} + +func (_FeeManager *FeeManagerSession) UpdateSubscriberDiscount(subscriber common.Address, feedId [32]byte, token common.Address, discount uint64) (*types.Transaction, error) { + return _FeeManager.Contract.UpdateSubscriberDiscount(&_FeeManager.TransactOpts, subscriber, feedId, token, discount) +} + +func (_FeeManager *FeeManagerTransactorSession) UpdateSubscriberDiscount(subscriber common.Address, feedId [32]byte, token common.Address, discount uint64) (*types.Transaction, error) { + return _FeeManager.Contract.UpdateSubscriberDiscount(&_FeeManager.TransactOpts, subscriber, feedId, token, discount) +} + +func (_FeeManager *FeeManagerTransactor) UpdateSubscriberGlobalDiscount(opts *bind.TransactOpts, subscriber common.Address, token common.Address, discount uint64) (*types.Transaction, error) { + return _FeeManager.contract.Transact(opts, "updateSubscriberGlobalDiscount", subscriber, token, discount) +} + +func (_FeeManager *FeeManagerSession) UpdateSubscriberGlobalDiscount(subscriber common.Address, token common.Address, discount uint64) (*types.Transaction, error) { + return _FeeManager.Contract.UpdateSubscriberGlobalDiscount(&_FeeManager.TransactOpts, subscriber, token, discount) +} + +func (_FeeManager *FeeManagerTransactorSession) UpdateSubscriberGlobalDiscount(subscriber common.Address, token common.Address, discount uint64) (*types.Transaction, error) { + return _FeeManager.Contract.UpdateSubscriberGlobalDiscount(&_FeeManager.TransactOpts, subscriber, token, discount) +} + +func (_FeeManager *FeeManagerTransactor) Withdraw(opts *bind.TransactOpts, assetAddress common.Address, recipient common.Address, quantity *big.Int) (*types.Transaction, error) { + return _FeeManager.contract.Transact(opts, "withdraw", assetAddress, recipient, quantity) +} + +func (_FeeManager *FeeManagerSession) Withdraw(assetAddress common.Address, recipient common.Address, quantity *big.Int) (*types.Transaction, error) { + return _FeeManager.Contract.Withdraw(&_FeeManager.TransactOpts, assetAddress, recipient, quantity) +} + +func (_FeeManager *FeeManagerTransactorSession) Withdraw(assetAddress common.Address, recipient common.Address, quantity *big.Int) (*types.Transaction, error) { + return _FeeManager.Contract.Withdraw(&_FeeManager.TransactOpts, assetAddress, recipient, quantity) +} + +type FeeManagerDiscountAppliedIterator struct { + Event *FeeManagerDiscountApplied + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *FeeManagerDiscountAppliedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(FeeManagerDiscountApplied) + 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(FeeManagerDiscountApplied) + 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 *FeeManagerDiscountAppliedIterator) Error() error { + return it.fail +} + +func (it *FeeManagerDiscountAppliedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type FeeManagerDiscountApplied struct { + ConfigDigest [32]byte + Subscriber common.Address + Fee CommonAsset + Reward CommonAsset + AppliedDiscount *big.Int + Raw types.Log +} + +func (_FeeManager *FeeManagerFilterer) FilterDiscountApplied(opts *bind.FilterOpts, configDigest [][32]byte, subscriber []common.Address) (*FeeManagerDiscountAppliedIterator, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + var subscriberRule []interface{} + for _, subscriberItem := range subscriber { + subscriberRule = append(subscriberRule, subscriberItem) + } + + logs, sub, err := _FeeManager.contract.FilterLogs(opts, "DiscountApplied", configDigestRule, subscriberRule) + if err != nil { + return nil, err + } + return &FeeManagerDiscountAppliedIterator{contract: _FeeManager.contract, event: "DiscountApplied", logs: logs, sub: sub}, nil +} + +func (_FeeManager *FeeManagerFilterer) WatchDiscountApplied(opts *bind.WatchOpts, sink chan<- *FeeManagerDiscountApplied, configDigest [][32]byte, subscriber []common.Address) (event.Subscription, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + var subscriberRule []interface{} + for _, subscriberItem := range subscriber { + subscriberRule = append(subscriberRule, subscriberItem) + } + + logs, sub, err := _FeeManager.contract.WatchLogs(opts, "DiscountApplied", configDigestRule, subscriberRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(FeeManagerDiscountApplied) + if err := _FeeManager.contract.UnpackLog(event, "DiscountApplied", 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 (_FeeManager *FeeManagerFilterer) ParseDiscountApplied(log types.Log) (*FeeManagerDiscountApplied, error) { + event := new(FeeManagerDiscountApplied) + if err := _FeeManager.contract.UnpackLog(event, "DiscountApplied", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type FeeManagerInsufficientLinkIterator struct { + Event *FeeManagerInsufficientLink + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *FeeManagerInsufficientLinkIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(FeeManagerInsufficientLink) + 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(FeeManagerInsufficientLink) + 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 *FeeManagerInsufficientLinkIterator) Error() error { + return it.fail +} + +func (it *FeeManagerInsufficientLinkIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type FeeManagerInsufficientLink struct { + Rewards []IRewardManagerFeePayment + Raw types.Log +} + +func (_FeeManager *FeeManagerFilterer) FilterInsufficientLink(opts *bind.FilterOpts) (*FeeManagerInsufficientLinkIterator, error) { + + logs, sub, err := _FeeManager.contract.FilterLogs(opts, "InsufficientLink") + if err != nil { + return nil, err + } + return &FeeManagerInsufficientLinkIterator{contract: _FeeManager.contract, event: "InsufficientLink", logs: logs, sub: sub}, nil +} + +func (_FeeManager *FeeManagerFilterer) WatchInsufficientLink(opts *bind.WatchOpts, sink chan<- *FeeManagerInsufficientLink) (event.Subscription, error) { + + logs, sub, err := _FeeManager.contract.WatchLogs(opts, "InsufficientLink") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(FeeManagerInsufficientLink) + if err := _FeeManager.contract.UnpackLog(event, "InsufficientLink", 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 (_FeeManager *FeeManagerFilterer) ParseInsufficientLink(log types.Log) (*FeeManagerInsufficientLink, error) { + event := new(FeeManagerInsufficientLink) + if err := _FeeManager.contract.UnpackLog(event, "InsufficientLink", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type FeeManagerLinkDeficitClearedIterator struct { + Event *FeeManagerLinkDeficitCleared + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *FeeManagerLinkDeficitClearedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(FeeManagerLinkDeficitCleared) + 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(FeeManagerLinkDeficitCleared) + 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 *FeeManagerLinkDeficitClearedIterator) Error() error { + return it.fail +} + +func (it *FeeManagerLinkDeficitClearedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type FeeManagerLinkDeficitCleared struct { + ConfigDigest [32]byte + LinkQuantity *big.Int + Raw types.Log +} + +func (_FeeManager *FeeManagerFilterer) FilterLinkDeficitCleared(opts *bind.FilterOpts, configDigest [][32]byte) (*FeeManagerLinkDeficitClearedIterator, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + + logs, sub, err := _FeeManager.contract.FilterLogs(opts, "LinkDeficitCleared", configDigestRule) + if err != nil { + return nil, err + } + return &FeeManagerLinkDeficitClearedIterator{contract: _FeeManager.contract, event: "LinkDeficitCleared", logs: logs, sub: sub}, nil +} + +func (_FeeManager *FeeManagerFilterer) WatchLinkDeficitCleared(opts *bind.WatchOpts, sink chan<- *FeeManagerLinkDeficitCleared, configDigest [][32]byte) (event.Subscription, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + + logs, sub, err := _FeeManager.contract.WatchLogs(opts, "LinkDeficitCleared", configDigestRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(FeeManagerLinkDeficitCleared) + if err := _FeeManager.contract.UnpackLog(event, "LinkDeficitCleared", 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 (_FeeManager *FeeManagerFilterer) ParseLinkDeficitCleared(log types.Log) (*FeeManagerLinkDeficitCleared, error) { + event := new(FeeManagerLinkDeficitCleared) + if err := _FeeManager.contract.UnpackLog(event, "LinkDeficitCleared", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type FeeManagerNativeSurchargeUpdatedIterator struct { + Event *FeeManagerNativeSurchargeUpdated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *FeeManagerNativeSurchargeUpdatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(FeeManagerNativeSurchargeUpdated) + 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(FeeManagerNativeSurchargeUpdated) + 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 *FeeManagerNativeSurchargeUpdatedIterator) Error() error { + return it.fail +} + +func (it *FeeManagerNativeSurchargeUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type FeeManagerNativeSurchargeUpdated struct { + NewSurcharge uint64 + Raw types.Log +} + +func (_FeeManager *FeeManagerFilterer) FilterNativeSurchargeUpdated(opts *bind.FilterOpts) (*FeeManagerNativeSurchargeUpdatedIterator, error) { + + logs, sub, err := _FeeManager.contract.FilterLogs(opts, "NativeSurchargeUpdated") + if err != nil { + return nil, err + } + return &FeeManagerNativeSurchargeUpdatedIterator{contract: _FeeManager.contract, event: "NativeSurchargeUpdated", logs: logs, sub: sub}, nil +} + +func (_FeeManager *FeeManagerFilterer) WatchNativeSurchargeUpdated(opts *bind.WatchOpts, sink chan<- *FeeManagerNativeSurchargeUpdated) (event.Subscription, error) { + + logs, sub, err := _FeeManager.contract.WatchLogs(opts, "NativeSurchargeUpdated") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(FeeManagerNativeSurchargeUpdated) + if err := _FeeManager.contract.UnpackLog(event, "NativeSurchargeUpdated", 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 (_FeeManager *FeeManagerFilterer) ParseNativeSurchargeUpdated(log types.Log) (*FeeManagerNativeSurchargeUpdated, error) { + event := new(FeeManagerNativeSurchargeUpdated) + if err := _FeeManager.contract.UnpackLog(event, "NativeSurchargeUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type FeeManagerOwnershipTransferRequestedIterator struct { + Event *FeeManagerOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *FeeManagerOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(FeeManagerOwnershipTransferRequested) + 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(FeeManagerOwnershipTransferRequested) + 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 *FeeManagerOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *FeeManagerOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type FeeManagerOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_FeeManager *FeeManagerFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*FeeManagerOwnershipTransferRequestedIterator, 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 := _FeeManager.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &FeeManagerOwnershipTransferRequestedIterator{contract: _FeeManager.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_FeeManager *FeeManagerFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *FeeManagerOwnershipTransferRequested, 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 := _FeeManager.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(FeeManagerOwnershipTransferRequested) + if err := _FeeManager.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 (_FeeManager *FeeManagerFilterer) ParseOwnershipTransferRequested(log types.Log) (*FeeManagerOwnershipTransferRequested, error) { + event := new(FeeManagerOwnershipTransferRequested) + if err := _FeeManager.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type FeeManagerOwnershipTransferredIterator struct { + Event *FeeManagerOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *FeeManagerOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(FeeManagerOwnershipTransferred) + 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(FeeManagerOwnershipTransferred) + 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 *FeeManagerOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *FeeManagerOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type FeeManagerOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_FeeManager *FeeManagerFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*FeeManagerOwnershipTransferredIterator, 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 := _FeeManager.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &FeeManagerOwnershipTransferredIterator{contract: _FeeManager.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_FeeManager *FeeManagerFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *FeeManagerOwnershipTransferred, 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 := _FeeManager.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(FeeManagerOwnershipTransferred) + if err := _FeeManager.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 (_FeeManager *FeeManagerFilterer) ParseOwnershipTransferred(log types.Log) (*FeeManagerOwnershipTransferred, error) { + event := new(FeeManagerOwnershipTransferred) + if err := _FeeManager.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type FeeManagerSubscriberDiscountUpdatedIterator struct { + Event *FeeManagerSubscriberDiscountUpdated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *FeeManagerSubscriberDiscountUpdatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(FeeManagerSubscriberDiscountUpdated) + 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(FeeManagerSubscriberDiscountUpdated) + 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 *FeeManagerSubscriberDiscountUpdatedIterator) Error() error { + return it.fail +} + +func (it *FeeManagerSubscriberDiscountUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type FeeManagerSubscriberDiscountUpdated struct { + Subscriber common.Address + FeedId [32]byte + Token common.Address + Discount uint64 + Raw types.Log +} + +func (_FeeManager *FeeManagerFilterer) FilterSubscriberDiscountUpdated(opts *bind.FilterOpts, subscriber []common.Address, feedId [][32]byte) (*FeeManagerSubscriberDiscountUpdatedIterator, error) { + + var subscriberRule []interface{} + for _, subscriberItem := range subscriber { + subscriberRule = append(subscriberRule, subscriberItem) + } + var feedIdRule []interface{} + for _, feedIdItem := range feedId { + feedIdRule = append(feedIdRule, feedIdItem) + } + + logs, sub, err := _FeeManager.contract.FilterLogs(opts, "SubscriberDiscountUpdated", subscriberRule, feedIdRule) + if err != nil { + return nil, err + } + return &FeeManagerSubscriberDiscountUpdatedIterator{contract: _FeeManager.contract, event: "SubscriberDiscountUpdated", logs: logs, sub: sub}, nil +} + +func (_FeeManager *FeeManagerFilterer) WatchSubscriberDiscountUpdated(opts *bind.WatchOpts, sink chan<- *FeeManagerSubscriberDiscountUpdated, subscriber []common.Address, feedId [][32]byte) (event.Subscription, error) { + + var subscriberRule []interface{} + for _, subscriberItem := range subscriber { + subscriberRule = append(subscriberRule, subscriberItem) + } + var feedIdRule []interface{} + for _, feedIdItem := range feedId { + feedIdRule = append(feedIdRule, feedIdItem) + } + + logs, sub, err := _FeeManager.contract.WatchLogs(opts, "SubscriberDiscountUpdated", subscriberRule, feedIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(FeeManagerSubscriberDiscountUpdated) + if err := _FeeManager.contract.UnpackLog(event, "SubscriberDiscountUpdated", 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 (_FeeManager *FeeManagerFilterer) ParseSubscriberDiscountUpdated(log types.Log) (*FeeManagerSubscriberDiscountUpdated, error) { + event := new(FeeManagerSubscriberDiscountUpdated) + if err := _FeeManager.contract.UnpackLog(event, "SubscriberDiscountUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type FeeManagerWithdrawIterator struct { + Event *FeeManagerWithdraw + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *FeeManagerWithdrawIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(FeeManagerWithdraw) + 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(FeeManagerWithdraw) + 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 *FeeManagerWithdrawIterator) Error() error { + return it.fail +} + +func (it *FeeManagerWithdrawIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type FeeManagerWithdraw struct { + AdminAddress common.Address + Recipient common.Address + AssetAddress common.Address + Quantity *big.Int + Raw types.Log +} + +func (_FeeManager *FeeManagerFilterer) FilterWithdraw(opts *bind.FilterOpts) (*FeeManagerWithdrawIterator, error) { + + logs, sub, err := _FeeManager.contract.FilterLogs(opts, "Withdraw") + if err != nil { + return nil, err + } + return &FeeManagerWithdrawIterator{contract: _FeeManager.contract, event: "Withdraw", logs: logs, sub: sub}, nil +} + +func (_FeeManager *FeeManagerFilterer) WatchWithdraw(opts *bind.WatchOpts, sink chan<- *FeeManagerWithdraw) (event.Subscription, error) { + + logs, sub, err := _FeeManager.contract.WatchLogs(opts, "Withdraw") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(FeeManagerWithdraw) + if err := _FeeManager.contract.UnpackLog(event, "Withdraw", 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 (_FeeManager *FeeManagerFilterer) ParseWithdraw(log types.Log) (*FeeManagerWithdraw, error) { + event := new(FeeManagerWithdraw) + if err := _FeeManager.contract.UnpackLog(event, "Withdraw", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_FeeManager *FeeManager) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _FeeManager.abi.Events["DiscountApplied"].ID: + return _FeeManager.ParseDiscountApplied(log) + case _FeeManager.abi.Events["InsufficientLink"].ID: + return _FeeManager.ParseInsufficientLink(log) + case _FeeManager.abi.Events["LinkDeficitCleared"].ID: + return _FeeManager.ParseLinkDeficitCleared(log) + case _FeeManager.abi.Events["NativeSurchargeUpdated"].ID: + return _FeeManager.ParseNativeSurchargeUpdated(log) + case _FeeManager.abi.Events["OwnershipTransferRequested"].ID: + return _FeeManager.ParseOwnershipTransferRequested(log) + case _FeeManager.abi.Events["OwnershipTransferred"].ID: + return _FeeManager.ParseOwnershipTransferred(log) + case _FeeManager.abi.Events["SubscriberDiscountUpdated"].ID: + return _FeeManager.ParseSubscriberDiscountUpdated(log) + case _FeeManager.abi.Events["Withdraw"].ID: + return _FeeManager.ParseWithdraw(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (FeeManagerDiscountApplied) Topic() common.Hash { + return common.HexToHash("0x88b15eb682210089cddf967648e2cb2a4535aeadc8f8f36050922e33c04e7125") +} + +func (FeeManagerInsufficientLink) Topic() common.Hash { + return common.HexToHash("0xf52e5907b69d97c33392936c12d78b494463b78c5b72df50b4c497eee5720b67") +} + +func (FeeManagerLinkDeficitCleared) Topic() common.Hash { + return common.HexToHash("0x843f0b103e50b42b08f9d30f12f961845a6d02623730872e24644899c0dd9895") +} + +func (FeeManagerNativeSurchargeUpdated) Topic() common.Hash { + return common.HexToHash("0x08f7c0d17932ddb8523bc06754d42ff19ebc77d76a8b9bfde02c28ab1ed3d639") +} + +func (FeeManagerOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (FeeManagerOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (FeeManagerSubscriberDiscountUpdated) Topic() common.Hash { + return common.HexToHash("0x5eba5a8afa39780f0f99b6cbeb95f3da6a7040ca00abd46bdc91a0a060134139") +} + +func (FeeManagerWithdraw) Topic() common.Hash { + return common.HexToHash("0x7ff78a71698bdb18dcca96f52ab25e0a1b146fb6a49adf8e6845299e49021f29") +} + +func (_FeeManager *FeeManager) Address() common.Address { + return _FeeManager.address +} + +type FeeManagerInterface interface { + GetFeeAndReward(opts *bind.CallOpts, subscriber common.Address, report []byte, quoteAddress common.Address) (CommonAsset, CommonAsset, *big.Int, error) + + ILinkAddress(opts *bind.CallOpts) (common.Address, error) + + INativeAddress(opts *bind.CallOpts) (common.Address, error) + + IProxyAddress(opts *bind.CallOpts) (common.Address, error) + + IRewardManager(opts *bind.CallOpts) (common.Address, error) + + LinkAvailableForPayment(opts *bind.CallOpts) (*big.Int, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + SGlobalDiscounts(opts *bind.CallOpts, arg0 common.Address, arg1 common.Address) (*big.Int, error) + + SLinkDeficit(opts *bind.CallOpts, arg0 [32]byte) (*big.Int, error) + + SNativeSurcharge(opts *bind.CallOpts) (*big.Int, error) + + SSubscriberDiscounts(opts *bind.CallOpts, arg0 common.Address, arg1 [32]byte, arg2 common.Address) (*big.Int, error) + + SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) + + TypeAndVersion(opts *bind.CallOpts) (string, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + PayLinkDeficit(opts *bind.TransactOpts, configDigest [32]byte) (*types.Transaction, error) + + ProcessFee(opts *bind.TransactOpts, payload []byte, parameterPayload []byte, subscriber common.Address) (*types.Transaction, error) + + ProcessFeeBulk(opts *bind.TransactOpts, payloads [][]byte, parameterPayload []byte, subscriber common.Address) (*types.Transaction, error) + + SetFeeRecipients(opts *bind.TransactOpts, configDigest [32]byte, rewardRecipientAndWeights []CommonAddressAndWeight) (*types.Transaction, error) + + SetNativeSurcharge(opts *bind.TransactOpts, surcharge uint64) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + UpdateSubscriberDiscount(opts *bind.TransactOpts, subscriber common.Address, feedId [32]byte, token common.Address, discount uint64) (*types.Transaction, error) + + UpdateSubscriberGlobalDiscount(opts *bind.TransactOpts, subscriber common.Address, token common.Address, discount uint64) (*types.Transaction, error) + + Withdraw(opts *bind.TransactOpts, assetAddress common.Address, recipient common.Address, quantity *big.Int) (*types.Transaction, error) + + FilterDiscountApplied(opts *bind.FilterOpts, configDigest [][32]byte, subscriber []common.Address) (*FeeManagerDiscountAppliedIterator, error) + + WatchDiscountApplied(opts *bind.WatchOpts, sink chan<- *FeeManagerDiscountApplied, configDigest [][32]byte, subscriber []common.Address) (event.Subscription, error) + + ParseDiscountApplied(log types.Log) (*FeeManagerDiscountApplied, error) + + FilterInsufficientLink(opts *bind.FilterOpts) (*FeeManagerInsufficientLinkIterator, error) + + WatchInsufficientLink(opts *bind.WatchOpts, sink chan<- *FeeManagerInsufficientLink) (event.Subscription, error) + + ParseInsufficientLink(log types.Log) (*FeeManagerInsufficientLink, error) + + FilterLinkDeficitCleared(opts *bind.FilterOpts, configDigest [][32]byte) (*FeeManagerLinkDeficitClearedIterator, error) + + WatchLinkDeficitCleared(opts *bind.WatchOpts, sink chan<- *FeeManagerLinkDeficitCleared, configDigest [][32]byte) (event.Subscription, error) + + ParseLinkDeficitCleared(log types.Log) (*FeeManagerLinkDeficitCleared, error) + + FilterNativeSurchargeUpdated(opts *bind.FilterOpts) (*FeeManagerNativeSurchargeUpdatedIterator, error) + + WatchNativeSurchargeUpdated(opts *bind.WatchOpts, sink chan<- *FeeManagerNativeSurchargeUpdated) (event.Subscription, error) + + ParseNativeSurchargeUpdated(log types.Log) (*FeeManagerNativeSurchargeUpdated, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*FeeManagerOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *FeeManagerOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*FeeManagerOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*FeeManagerOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *FeeManagerOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*FeeManagerOwnershipTransferred, error) + + FilterSubscriberDiscountUpdated(opts *bind.FilterOpts, subscriber []common.Address, feedId [][32]byte) (*FeeManagerSubscriberDiscountUpdatedIterator, error) + + WatchSubscriberDiscountUpdated(opts *bind.WatchOpts, sink chan<- *FeeManagerSubscriberDiscountUpdated, subscriber []common.Address, feedId [][32]byte) (event.Subscription, error) + + ParseSubscriberDiscountUpdated(log types.Log) (*FeeManagerSubscriberDiscountUpdated, error) + + FilterWithdraw(opts *bind.FilterOpts) (*FeeManagerWithdrawIterator, error) + + WatchWithdraw(opts *bind.WatchOpts, sink chan<- *FeeManagerWithdraw) (event.Subscription, error) + + ParseWithdraw(log types.Log) (*FeeManagerWithdraw, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/llo-feeds/generated/llo_feeds/llo_feeds.go b/core/gethwrappers/llo-feeds/generated/llo_feeds/llo_feeds.go deleted file mode 100644 index 0cf53356440..00000000000 --- a/core/gethwrappers/llo-feeds/generated/llo_feeds/llo_feeds.go +++ /dev/null @@ -1,1318 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package llo_feeds - -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 -) - -type CommonAddressAndWeight struct { - Addr common.Address - Weight *big.Int -} - -type CommonAsset struct { - AssetAddress common.Address - Amount *big.Int -} - -type IFeeManagerQuote struct { - QuoteAddress common.Address -} - -var LLOFeeManagerMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_linkAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_nativeAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_proxyAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_rewardManagerAddress\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ExpiredReport\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDeposit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDiscount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidQuote\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSurcharge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"linkQuantity\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nativeQuantity\",\"type\":\"uint256\"}],\"name\":\"InsufficientLink\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSurcharge\",\"type\":\"uint256\"}],\"name\":\"NativeSurchargeSet\",\"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\":true,\"internalType\":\"address\",\"name\":\"subscriber\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"feedId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"discount\",\"type\":\"uint256\"}],\"name\":\"SubscriberDiscountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"adminAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"quantity\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"subscriber\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"quoteAddress\",\"type\":\"address\"}],\"internalType\":\"structIFeeManager.Quote\",\"name\":\"quote\",\"type\":\"tuple\"}],\"name\":\"getFeeAndReward\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structCommon.Asset\",\"name\":\"\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structCommon.Asset\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"linkAvailableForPayment\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nativeSurcharge\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"subscriber\",\"type\":\"address\"}],\"name\":\"processFee\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"}],\"internalType\":\"structCommon.AddressAndWeight[]\",\"name\":\"rewardRecipientAndWeights\",\"type\":\"tuple[]\"}],\"name\":\"setFeeRecipients\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"surcharge\",\"type\":\"uint256\"}],\"name\":\"setNativeSurcharge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"subscriberDiscounts\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"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\":\"address\",\"name\":\"subscriber\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"feedId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"discount\",\"type\":\"uint256\"}],\"name\":\"updateSubscriberDiscount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"quantity\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101006040523480156200001257600080fd5b50604051620024d4380380620024d4833981016040819052620000359162000288565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001c0565b5050506001600160a01b0384161580620000e057506001600160a01b038316155b80620000f357506001600160a01b038216155b806200010657506001600160a01b038116155b15620001255760405163e6c4247b60e01b815260040160405180910390fd5b6001600160a01b03848116608081905284821660a05283821660c05290821660e081905260405163095ea7b360e01b81526004810191909152600019602482015263095ea7b3906044016020604051808303816000875af11580156200018f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001b59190620002e5565b505050505062000310565b336001600160a01b038216036200021a5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b03811681146200028357600080fd5b919050565b600080600080608085870312156200029f57600080fd5b620002aa856200026b565b9350620002ba602086016200026b565b9250620002ca604086016200026b565b9150620002da606086016200026b565b905092959194509250565b600060208284031215620002f857600080fd5b815180151581146200030957600080fd5b9392505050565b60805160a05160c05160e051612128620003ac6000396000818161044c01528181610e5401526110b20152600081816103820152610b1b0152600081816106af015281816107020152818161090f01528181610c6901528181610d3001526112170152600081816106d40152818161075d0152818161089a01528181610a5d01528181610def01528181610fa301526111c001526121286000f3fe6080604052600436106100dd5760003560e01c806393798be71161007f578063f1387e1611610059578063f1387e16146102d6578063f237f1a8146102e9578063f2fde38b14610309578063f3fef3a31461032957600080fd5b806393798be714610255578063c541cbde14610293578063d09dc339146102c157600080fd5b80636b54d8a6116100bb5780636b54d8a6146101c757806379ba5097146101e75780637d75cc49146101fc5780638da5cb5b1461022057600080fd5b806301ffc9a7146100e2578063181f5a771461015957806369fd2b34146101a5575b600080fd5b3480156100ee57600080fd5b506101446100fd36600461167b565b7fffffffff00000000000000000000000000000000000000000000000000000000167ff1387e16000000000000000000000000000000000000000000000000000000001490565b60405190151581526020015b60405180910390f35b34801561016557600080fd5b50604080518082018252601081527f4665654d616e6167657220302e302e31000000000000000000000000000000006020820152905161015091906116c4565b3480156101b157600080fd5b506101c56101c0366004611730565b610349565b005b3480156101d357600080fd5b506101c56101e23660046117af565b6104bc565b3480156101f357600080fd5b506101c5610541565b34801561020857600080fd5b5061021260035481565b604051908152602001610150565b34801561022c57600080fd5b5060005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610150565b34801561026157600080fd5b506102126102703660046117ea565b600260209081526000938452604080852082529284528284209052825290205481565b34801561029f57600080fd5b506102b36102ae366004611961565b61063e565b604051610150929190611a02565b3480156102cd57600080fd5b50610212610a2c565b6101c56102e4366004611a56565b610ae2565b3480156102f557600080fd5b506101c5610304366004611ace565b611174565b34801561031557600080fd5b506101c5610324366004611b16565b61131b565b34801561033557600080fd5b506101c5610344366004611b33565b61132f565b60005473ffffffffffffffffffffffffffffffffffffffff163314806103a457503373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016145b61040f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4f6e6c79206f776e6572206f722070726f78790000000000000000000000000060448201526064015b60405180910390fd5b6040517f633b5f6e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063633b5f6e9061048590869086908690600401611b5f565b600060405180830381600087803b15801561049f57600080fd5b505af11580156104b3573d6000803e3d6000fd5b50505050505050565b6104c46114c9565b670de0b6b3a7640000811115610506576040517f05e8ac2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60038190556040518181527f4fbcc2b7f4cb5518be923bd7c7c887e29e07b001e2a4a0fdd47c494696d8a1479060200160405180910390a150565b60015473ffffffffffffffffffffffffffffffffffffffff1633146105c2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610406565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60408051808201909152600080825260208201526040805180820190915260008082526020820152604080518082019091526000808252602082015260408051808201909152600080825260208201528551610120106107005773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811683527f00000000000000000000000000000000000000000000000000000000000000001681529092509050610a24565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16856000015173ffffffffffffffffffffffffffffffffffffffff16141580156107b057507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16856000015173ffffffffffffffffffffffffffffffffffffffff1614155b156107e7576040517ff861803000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000806000888060200190518101906108009190611c39565b63ffffffff169b5077ffffffffffffffffffffffffffffffffffffffffffffffff169b5077ffffffffffffffffffffffffffffffffffffffffffffffff169b5050505050505050505042811015610883576040517fb6c405f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116808652602086018590528951909116036108f857835173ffffffffffffffffffffffffffffffffffffffff16855260208085015190860152610968565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001685526003546109629061094a90670de0b6b3a7640000611d36565b6109549084611d49565b670de0b6b3a764000061154c565b60208601525b60006109738a611d86565b73ffffffffffffffffffffffffffffffffffffffff808d16600090815260026020908152604080832085845282528083208e519094168352928152919020549088015191925090670de0b6b3a7640000906109cf908390611d49565b6109d99190611dcb565b87602001516109e89190611e06565b876020018181525050610a048187602001516109549190611d49565b8660200151610a139190611e06565b602087015250949650929450505050505b935093915050565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015610ab9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610add9190611e19565b905090565b60005473ffffffffffffffffffffffffffffffffffffffff16331480610b3d57503373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016145b610ba3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4f6e6c79206f776e6572206f722070726f7879000000000000000000000000006044820152606401610406565b3073ffffffffffffffffffffffffffffffffffffffff821603610bf2576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610c0083850185611ea0565b604080516020810190915260008152909250905081516101201015610c4c576000610c2d85870187611f6f565b9550505050505080806020019051810190610c489190612037565b9150505b600080610c5a33858561063e565b909250905060003415610dbd577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16836000015173ffffffffffffffffffffffffffffffffffffffff1614610cf0576040517fb2e532de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3483602001511115610d2e576040517fb2e532de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db084602001516040518263ffffffff1660e01b81526004016000604051808303818588803b158015610d9a57600080fd5b505af1158015610dae573d6000803e3d6000fd5b50505050508260200151340390505b6000610dc9888a612065565b60208501519091501561111e57835173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116911603610ec4576040517f84afb76e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906384afb76e90610e8d9084908b9088906004016120a1565b600060405180830381600087803b158015610ea757600080fd5b505af1158015610ebb573d6000803e3d6000fd5b5050505061111e565b34600003610f7557835160208501516040517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a8116600483015230602483015260448201929092529116906323b872dd906064016020604051808303816000875af1158015610f4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7391906120f9565b505b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015610fff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110239190611e19565b836020015111156110755760208084015185820151604080519283529282015282917feb6f22018570d97db6df12dc94f202b4e2b2888a6a5d4bd179422c91b29dcdf7910160405180910390a261111e565b6040517f84afb76e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906384afb76e906110eb908490309088906004016120a1565b600060405180830381600087803b15801561110557600080fd5b505af1158015611119573d6000803e3d6000fd5b505050505b81156111695760405173ffffffffffffffffffffffffffffffffffffffff88169083156108fc029084906000818181858888f19350505050158015611167573d6000803e3d6000fd5b505b505050505050505050565b61117c6114c9565b670de0b6b3a76400008111156111be576040517f997ea36000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415801561126657507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b1561129d576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff84811660008181526002602090815260408083208884528252808320948716808452948252918290208590558151938452830184905285927f41eb9ccd292d5906dc1f0ec108bed3e2b966e3071e033df938f7215f6d30ca84910160405180910390a350505050565b6113236114c9565b61132c81611586565b50565b6113376114c9565b73ffffffffffffffffffffffffffffffffffffffff821661139d576000805460405173ffffffffffffffffffffffffffffffffffffffff9091169183156108fc02918491818181858888f19350505050158015611398573d6000803e3d6000fd5b505050565b8173ffffffffffffffffffffffffffffffffffffffff1663a9059cbb6113d860005473ffffffffffffffffffffffffffffffffffffffff1690565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602481018490526044016020604051808303816000875af115801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e91906120f9565b506040805133815273ffffffffffffffffffffffffffffffffffffffff841660208201529081018290527f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb9060600160405180910390a15050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461154a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610406565b565b6000821561157a5781611560600185611e06565b61156a9190611dcb565b611575906001611d36565b61157d565b60005b90505b92915050565b3373ffffffffffffffffffffffffffffffffffffffff821603611605576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610406565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60006020828403121561168d57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146116bd57600080fd5b9392505050565b600060208083528351808285015260005b818110156116f1578581018301518582016040015282016116d5565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b60008060006040848603121561174557600080fd5b83359250602084013567ffffffffffffffff8082111561176457600080fd5b818601915086601f83011261177857600080fd5b81358181111561178757600080fd5b8760208260061b850101111561179c57600080fd5b6020830194508093505050509250925092565b6000602082840312156117c157600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461132c57600080fd5b6000806000606084860312156117ff57600080fd5b833561180a816117c8565b9250602084013591506040840135611821816117c8565b809150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516020810167ffffffffffffffff8111828210171561187e5761187e61182c565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156118cb576118cb61182c565b604052919050565b600082601f8301126118e457600080fd5b813567ffffffffffffffff8111156118fe576118fe61182c565b61192f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611884565b81815284602083860101111561194457600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000838503606081121561197757600080fd5b8435611982816117c8565b9350602085013567ffffffffffffffff81111561199e57600080fd5b6119aa878288016118d3565b93505060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0820112156119dd57600080fd5b506119e661185b565b60408501356119f4816117c8565b815292959194509192509050565b825173ffffffffffffffffffffffffffffffffffffffff1681526020808401519082015260808101825173ffffffffffffffffffffffffffffffffffffffff166040830152602083015160608301526116bd565b600080600060408486031215611a6b57600080fd5b833567ffffffffffffffff80821115611a8357600080fd5b818601915086601f830112611a9757600080fd5b813581811115611aa657600080fd5b876020828501011115611ab857600080fd5b60209283019550935050840135611821816117c8565b60008060008060808587031215611ae457600080fd5b8435611aef816117c8565b9350602085013592506040850135611b06816117c8565b9396929550929360600135925050565b600060208284031215611b2857600080fd5b81356116bd816117c8565b60008060408385031215611b4657600080fd5b8235611b51816117c8565b946020939093013593505050565b8381526040602080830182905282820184905260009190859060608501845b87811015611bc1578335611b91816117c8565b73ffffffffffffffffffffffffffffffffffffffff16825283830135838301529284019290840190600101611b7e565b5098975050505050505050565b805163ffffffff81168114611be257600080fd5b919050565b8051601781900b8114611be257600080fd5b805167ffffffffffffffff81168114611be257600080fd5b805177ffffffffffffffffffffffffffffffffffffffffffffffff81168114611be257600080fd5b6000806000806000806000806000806000806101808d8f031215611c5c57600080fd5b8c519b50611c6c60208e01611bce565b9a50611c7a60408e01611be7565b9950611c8860608e01611be7565b9850611c9660808e01611be7565b9750611ca460a08e01611bf9565b965060c08d01519550611cb960e08e01611bf9565b9450611cc86101008e01611bf9565b9350611cd76101208e01611c11565b9250611ce66101408e01611c11565b9150611cf56101608e01611bce565b90509295989b509295989b509295989b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561158057611580611d07565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615611d8157611d81611d07565b500290565b80516020808301519190811015611dc5577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8160200360031b1b821691505b50919050565b600082611e01577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b8181038181111561158057611580611d07565b600060208284031215611e2b57600080fd5b5051919050565b600082601f830112611e4357600080fd5b6040516060810181811067ffffffffffffffff82111715611e6657611e6661182c565b604052806060840185811115611e7b57600080fd5b845b81811015611e95578035835260209283019201611e7d565b509195945050505050565b60008060808385031215611eb357600080fd5b611ebd8484611e32565b9150606083013567ffffffffffffffff811115611ed957600080fd5b611ee5858286016118d3565b9150509250929050565b600082601f830112611f0057600080fd5b8135602067ffffffffffffffff821115611f1c57611f1c61182c565b8160051b611f2b828201611884565b9283528481018201928281019087851115611f4557600080fd5b83870192505b84831015611f6457823582529183019190830190611f4b565b979650505050505050565b6000806000806000806101008789031215611f8957600080fd5b611f938888611e32565b9550606087013567ffffffffffffffff80821115611fb057600080fd5b611fbc8a838b016118d3565b96506080890135915080821115611fd257600080fd5b611fde8a838b01611eef565b955060a0890135915080821115611ff457600080fd5b6120008a838b01611eef565b945060c0890135935060e089013591508082111561201d57600080fd5b5061202a89828a016118d3565b9150509295509295509295565b60006020828403121561204957600080fd5b61205161185b565b825161205c816117c8565b81529392505050565b80356020831015611580577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b83815273ffffffffffffffffffffffffffffffffffffffff83166020820152608081016120f16040830184805173ffffffffffffffffffffffffffffffffffffffff168252602090810151910152565b949350505050565b60006020828403121561210b57600080fd5b815180151581146116bd57600080fdfea164736f6c6343000810000a", -} - -var LLOFeeManagerABI = LLOFeeManagerMetaData.ABI - -var LLOFeeManagerBin = LLOFeeManagerMetaData.Bin - -func DeployLLOFeeManager(auth *bind.TransactOpts, backend bind.ContractBackend, _linkAddress common.Address, _nativeAddress common.Address, _proxyAddress common.Address, _rewardManagerAddress common.Address) (common.Address, *types.Transaction, *LLOFeeManager, error) { - parsed, err := LLOFeeManagerMetaData.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(LLOFeeManagerBin), backend, _linkAddress, _nativeAddress, _proxyAddress, _rewardManagerAddress) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &LLOFeeManager{LLOFeeManagerCaller: LLOFeeManagerCaller{contract: contract}, LLOFeeManagerTransactor: LLOFeeManagerTransactor{contract: contract}, LLOFeeManagerFilterer: LLOFeeManagerFilterer{contract: contract}}, nil -} - -type LLOFeeManager struct { - address common.Address - abi abi.ABI - LLOFeeManagerCaller - LLOFeeManagerTransactor - LLOFeeManagerFilterer -} - -type LLOFeeManagerCaller struct { - contract *bind.BoundContract -} - -type LLOFeeManagerTransactor struct { - contract *bind.BoundContract -} - -type LLOFeeManagerFilterer struct { - contract *bind.BoundContract -} - -type LLOFeeManagerSession struct { - Contract *LLOFeeManager - CallOpts bind.CallOpts - TransactOpts bind.TransactOpts -} - -type LLOFeeManagerCallerSession struct { - Contract *LLOFeeManagerCaller - CallOpts bind.CallOpts -} - -type LLOFeeManagerTransactorSession struct { - Contract *LLOFeeManagerTransactor - TransactOpts bind.TransactOpts -} - -type LLOFeeManagerRaw struct { - Contract *LLOFeeManager -} - -type LLOFeeManagerCallerRaw struct { - Contract *LLOFeeManagerCaller -} - -type LLOFeeManagerTransactorRaw struct { - Contract *LLOFeeManagerTransactor -} - -func NewLLOFeeManager(address common.Address, backend bind.ContractBackend) (*LLOFeeManager, error) { - abi, err := abi.JSON(strings.NewReader(LLOFeeManagerABI)) - if err != nil { - return nil, err - } - contract, err := bindLLOFeeManager(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &LLOFeeManager{address: address, abi: abi, LLOFeeManagerCaller: LLOFeeManagerCaller{contract: contract}, LLOFeeManagerTransactor: LLOFeeManagerTransactor{contract: contract}, LLOFeeManagerFilterer: LLOFeeManagerFilterer{contract: contract}}, nil -} - -func NewLLOFeeManagerCaller(address common.Address, caller bind.ContractCaller) (*LLOFeeManagerCaller, error) { - contract, err := bindLLOFeeManager(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &LLOFeeManagerCaller{contract: contract}, nil -} - -func NewLLOFeeManagerTransactor(address common.Address, transactor bind.ContractTransactor) (*LLOFeeManagerTransactor, error) { - contract, err := bindLLOFeeManager(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &LLOFeeManagerTransactor{contract: contract}, nil -} - -func NewLLOFeeManagerFilterer(address common.Address, filterer bind.ContractFilterer) (*LLOFeeManagerFilterer, error) { - contract, err := bindLLOFeeManager(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &LLOFeeManagerFilterer{contract: contract}, nil -} - -func bindLLOFeeManager(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := LLOFeeManagerMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -func (_LLOFeeManager *LLOFeeManagerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _LLOFeeManager.Contract.LLOFeeManagerCaller.contract.Call(opts, result, method, params...) -} - -func (_LLOFeeManager *LLOFeeManagerRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _LLOFeeManager.Contract.LLOFeeManagerTransactor.contract.Transfer(opts) -} - -func (_LLOFeeManager *LLOFeeManagerRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _LLOFeeManager.Contract.LLOFeeManagerTransactor.contract.Transact(opts, method, params...) -} - -func (_LLOFeeManager *LLOFeeManagerCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _LLOFeeManager.Contract.contract.Call(opts, result, method, params...) -} - -func (_LLOFeeManager *LLOFeeManagerTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _LLOFeeManager.Contract.contract.Transfer(opts) -} - -func (_LLOFeeManager *LLOFeeManagerTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _LLOFeeManager.Contract.contract.Transact(opts, method, params...) -} - -func (_LLOFeeManager *LLOFeeManagerCaller) GetFeeAndReward(opts *bind.CallOpts, subscriber common.Address, report []byte, quote IFeeManagerQuote) (CommonAsset, CommonAsset, error) { - var out []interface{} - err := _LLOFeeManager.contract.Call(opts, &out, "getFeeAndReward", subscriber, report, quote) - - if err != nil { - return *new(CommonAsset), *new(CommonAsset), err - } - - out0 := *abi.ConvertType(out[0], new(CommonAsset)).(*CommonAsset) - out1 := *abi.ConvertType(out[1], new(CommonAsset)).(*CommonAsset) - - return out0, out1, err - -} - -func (_LLOFeeManager *LLOFeeManagerSession) GetFeeAndReward(subscriber common.Address, report []byte, quote IFeeManagerQuote) (CommonAsset, CommonAsset, error) { - return _LLOFeeManager.Contract.GetFeeAndReward(&_LLOFeeManager.CallOpts, subscriber, report, quote) -} - -func (_LLOFeeManager *LLOFeeManagerCallerSession) GetFeeAndReward(subscriber common.Address, report []byte, quote IFeeManagerQuote) (CommonAsset, CommonAsset, error) { - return _LLOFeeManager.Contract.GetFeeAndReward(&_LLOFeeManager.CallOpts, subscriber, report, quote) -} - -func (_LLOFeeManager *LLOFeeManagerCaller) LinkAvailableForPayment(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _LLOFeeManager.contract.Call(opts, &out, "linkAvailableForPayment") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_LLOFeeManager *LLOFeeManagerSession) LinkAvailableForPayment() (*big.Int, error) { - return _LLOFeeManager.Contract.LinkAvailableForPayment(&_LLOFeeManager.CallOpts) -} - -func (_LLOFeeManager *LLOFeeManagerCallerSession) LinkAvailableForPayment() (*big.Int, error) { - return _LLOFeeManager.Contract.LinkAvailableForPayment(&_LLOFeeManager.CallOpts) -} - -func (_LLOFeeManager *LLOFeeManagerCaller) NativeSurcharge(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _LLOFeeManager.contract.Call(opts, &out, "nativeSurcharge") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_LLOFeeManager *LLOFeeManagerSession) NativeSurcharge() (*big.Int, error) { - return _LLOFeeManager.Contract.NativeSurcharge(&_LLOFeeManager.CallOpts) -} - -func (_LLOFeeManager *LLOFeeManagerCallerSession) NativeSurcharge() (*big.Int, error) { - return _LLOFeeManager.Contract.NativeSurcharge(&_LLOFeeManager.CallOpts) -} - -func (_LLOFeeManager *LLOFeeManagerCaller) Owner(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _LLOFeeManager.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 (_LLOFeeManager *LLOFeeManagerSession) Owner() (common.Address, error) { - return _LLOFeeManager.Contract.Owner(&_LLOFeeManager.CallOpts) -} - -func (_LLOFeeManager *LLOFeeManagerCallerSession) Owner() (common.Address, error) { - return _LLOFeeManager.Contract.Owner(&_LLOFeeManager.CallOpts) -} - -func (_LLOFeeManager *LLOFeeManagerCaller) SubscriberDiscounts(opts *bind.CallOpts, arg0 common.Address, arg1 [32]byte, arg2 common.Address) (*big.Int, error) { - var out []interface{} - err := _LLOFeeManager.contract.Call(opts, &out, "subscriberDiscounts", arg0, arg1, arg2) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_LLOFeeManager *LLOFeeManagerSession) SubscriberDiscounts(arg0 common.Address, arg1 [32]byte, arg2 common.Address) (*big.Int, error) { - return _LLOFeeManager.Contract.SubscriberDiscounts(&_LLOFeeManager.CallOpts, arg0, arg1, arg2) -} - -func (_LLOFeeManager *LLOFeeManagerCallerSession) SubscriberDiscounts(arg0 common.Address, arg1 [32]byte, arg2 common.Address) (*big.Int, error) { - return _LLOFeeManager.Contract.SubscriberDiscounts(&_LLOFeeManager.CallOpts, arg0, arg1, arg2) -} - -func (_LLOFeeManager *LLOFeeManagerCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { - var out []interface{} - err := _LLOFeeManager.contract.Call(opts, &out, "supportsInterface", interfaceId) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -func (_LLOFeeManager *LLOFeeManagerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _LLOFeeManager.Contract.SupportsInterface(&_LLOFeeManager.CallOpts, interfaceId) -} - -func (_LLOFeeManager *LLOFeeManagerCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _LLOFeeManager.Contract.SupportsInterface(&_LLOFeeManager.CallOpts, interfaceId) -} - -func (_LLOFeeManager *LLOFeeManagerCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { - var out []interface{} - err := _LLOFeeManager.contract.Call(opts, &out, "typeAndVersion") - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - -} - -func (_LLOFeeManager *LLOFeeManagerSession) TypeAndVersion() (string, error) { - return _LLOFeeManager.Contract.TypeAndVersion(&_LLOFeeManager.CallOpts) -} - -func (_LLOFeeManager *LLOFeeManagerCallerSession) TypeAndVersion() (string, error) { - return _LLOFeeManager.Contract.TypeAndVersion(&_LLOFeeManager.CallOpts) -} - -func (_LLOFeeManager *LLOFeeManagerTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - return _LLOFeeManager.contract.Transact(opts, "acceptOwnership") -} - -func (_LLOFeeManager *LLOFeeManagerSession) AcceptOwnership() (*types.Transaction, error) { - return _LLOFeeManager.Contract.AcceptOwnership(&_LLOFeeManager.TransactOpts) -} - -func (_LLOFeeManager *LLOFeeManagerTransactorSession) AcceptOwnership() (*types.Transaction, error) { - return _LLOFeeManager.Contract.AcceptOwnership(&_LLOFeeManager.TransactOpts) -} - -func (_LLOFeeManager *LLOFeeManagerTransactor) ProcessFee(opts *bind.TransactOpts, payload []byte, subscriber common.Address) (*types.Transaction, error) { - return _LLOFeeManager.contract.Transact(opts, "processFee", payload, subscriber) -} - -func (_LLOFeeManager *LLOFeeManagerSession) ProcessFee(payload []byte, subscriber common.Address) (*types.Transaction, error) { - return _LLOFeeManager.Contract.ProcessFee(&_LLOFeeManager.TransactOpts, payload, subscriber) -} - -func (_LLOFeeManager *LLOFeeManagerTransactorSession) ProcessFee(payload []byte, subscriber common.Address) (*types.Transaction, error) { - return _LLOFeeManager.Contract.ProcessFee(&_LLOFeeManager.TransactOpts, payload, subscriber) -} - -func (_LLOFeeManager *LLOFeeManagerTransactor) SetFeeRecipients(opts *bind.TransactOpts, configDigest [32]byte, rewardRecipientAndWeights []CommonAddressAndWeight) (*types.Transaction, error) { - return _LLOFeeManager.contract.Transact(opts, "setFeeRecipients", configDigest, rewardRecipientAndWeights) -} - -func (_LLOFeeManager *LLOFeeManagerSession) SetFeeRecipients(configDigest [32]byte, rewardRecipientAndWeights []CommonAddressAndWeight) (*types.Transaction, error) { - return _LLOFeeManager.Contract.SetFeeRecipients(&_LLOFeeManager.TransactOpts, configDigest, rewardRecipientAndWeights) -} - -func (_LLOFeeManager *LLOFeeManagerTransactorSession) SetFeeRecipients(configDigest [32]byte, rewardRecipientAndWeights []CommonAddressAndWeight) (*types.Transaction, error) { - return _LLOFeeManager.Contract.SetFeeRecipients(&_LLOFeeManager.TransactOpts, configDigest, rewardRecipientAndWeights) -} - -func (_LLOFeeManager *LLOFeeManagerTransactor) SetNativeSurcharge(opts *bind.TransactOpts, surcharge *big.Int) (*types.Transaction, error) { - return _LLOFeeManager.contract.Transact(opts, "setNativeSurcharge", surcharge) -} - -func (_LLOFeeManager *LLOFeeManagerSession) SetNativeSurcharge(surcharge *big.Int) (*types.Transaction, error) { - return _LLOFeeManager.Contract.SetNativeSurcharge(&_LLOFeeManager.TransactOpts, surcharge) -} - -func (_LLOFeeManager *LLOFeeManagerTransactorSession) SetNativeSurcharge(surcharge *big.Int) (*types.Transaction, error) { - return _LLOFeeManager.Contract.SetNativeSurcharge(&_LLOFeeManager.TransactOpts, surcharge) -} - -func (_LLOFeeManager *LLOFeeManagerTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { - return _LLOFeeManager.contract.Transact(opts, "transferOwnership", to) -} - -func (_LLOFeeManager *LLOFeeManagerSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _LLOFeeManager.Contract.TransferOwnership(&_LLOFeeManager.TransactOpts, to) -} - -func (_LLOFeeManager *LLOFeeManagerTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _LLOFeeManager.Contract.TransferOwnership(&_LLOFeeManager.TransactOpts, to) -} - -func (_LLOFeeManager *LLOFeeManagerTransactor) UpdateSubscriberDiscount(opts *bind.TransactOpts, subscriber common.Address, feedId [32]byte, token common.Address, discount *big.Int) (*types.Transaction, error) { - return _LLOFeeManager.contract.Transact(opts, "updateSubscriberDiscount", subscriber, feedId, token, discount) -} - -func (_LLOFeeManager *LLOFeeManagerSession) UpdateSubscriberDiscount(subscriber common.Address, feedId [32]byte, token common.Address, discount *big.Int) (*types.Transaction, error) { - return _LLOFeeManager.Contract.UpdateSubscriberDiscount(&_LLOFeeManager.TransactOpts, subscriber, feedId, token, discount) -} - -func (_LLOFeeManager *LLOFeeManagerTransactorSession) UpdateSubscriberDiscount(subscriber common.Address, feedId [32]byte, token common.Address, discount *big.Int) (*types.Transaction, error) { - return _LLOFeeManager.Contract.UpdateSubscriberDiscount(&_LLOFeeManager.TransactOpts, subscriber, feedId, token, discount) -} - -func (_LLOFeeManager *LLOFeeManagerTransactor) Withdraw(opts *bind.TransactOpts, assetAddress common.Address, quantity *big.Int) (*types.Transaction, error) { - return _LLOFeeManager.contract.Transact(opts, "withdraw", assetAddress, quantity) -} - -func (_LLOFeeManager *LLOFeeManagerSession) Withdraw(assetAddress common.Address, quantity *big.Int) (*types.Transaction, error) { - return _LLOFeeManager.Contract.Withdraw(&_LLOFeeManager.TransactOpts, assetAddress, quantity) -} - -func (_LLOFeeManager *LLOFeeManagerTransactorSession) Withdraw(assetAddress common.Address, quantity *big.Int) (*types.Transaction, error) { - return _LLOFeeManager.Contract.Withdraw(&_LLOFeeManager.TransactOpts, assetAddress, quantity) -} - -type LLOFeeManagerInsufficientLinkIterator struct { - Event *LLOFeeManagerInsufficientLink - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *LLOFeeManagerInsufficientLinkIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(LLOFeeManagerInsufficientLink) - 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(LLOFeeManagerInsufficientLink) - 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 *LLOFeeManagerInsufficientLinkIterator) Error() error { - return it.fail -} - -func (it *LLOFeeManagerInsufficientLinkIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type LLOFeeManagerInsufficientLink struct { - ConfigDigest [32]byte - LinkQuantity *big.Int - NativeQuantity *big.Int - Raw types.Log -} - -func (_LLOFeeManager *LLOFeeManagerFilterer) FilterInsufficientLink(opts *bind.FilterOpts, configDigest [][32]byte) (*LLOFeeManagerInsufficientLinkIterator, error) { - - var configDigestRule []interface{} - for _, configDigestItem := range configDigest { - configDigestRule = append(configDigestRule, configDigestItem) - } - - logs, sub, err := _LLOFeeManager.contract.FilterLogs(opts, "InsufficientLink", configDigestRule) - if err != nil { - return nil, err - } - return &LLOFeeManagerInsufficientLinkIterator{contract: _LLOFeeManager.contract, event: "InsufficientLink", logs: logs, sub: sub}, nil -} - -func (_LLOFeeManager *LLOFeeManagerFilterer) WatchInsufficientLink(opts *bind.WatchOpts, sink chan<- *LLOFeeManagerInsufficientLink, configDigest [][32]byte) (event.Subscription, error) { - - var configDigestRule []interface{} - for _, configDigestItem := range configDigest { - configDigestRule = append(configDigestRule, configDigestItem) - } - - logs, sub, err := _LLOFeeManager.contract.WatchLogs(opts, "InsufficientLink", configDigestRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(LLOFeeManagerInsufficientLink) - if err := _LLOFeeManager.contract.UnpackLog(event, "InsufficientLink", 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 (_LLOFeeManager *LLOFeeManagerFilterer) ParseInsufficientLink(log types.Log) (*LLOFeeManagerInsufficientLink, error) { - event := new(LLOFeeManagerInsufficientLink) - if err := _LLOFeeManager.contract.UnpackLog(event, "InsufficientLink", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type LLOFeeManagerNativeSurchargeSetIterator struct { - Event *LLOFeeManagerNativeSurchargeSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *LLOFeeManagerNativeSurchargeSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(LLOFeeManagerNativeSurchargeSet) - 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(LLOFeeManagerNativeSurchargeSet) - 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 *LLOFeeManagerNativeSurchargeSetIterator) Error() error { - return it.fail -} - -func (it *LLOFeeManagerNativeSurchargeSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type LLOFeeManagerNativeSurchargeSet struct { - NewSurcharge *big.Int - Raw types.Log -} - -func (_LLOFeeManager *LLOFeeManagerFilterer) FilterNativeSurchargeSet(opts *bind.FilterOpts) (*LLOFeeManagerNativeSurchargeSetIterator, error) { - - logs, sub, err := _LLOFeeManager.contract.FilterLogs(opts, "NativeSurchargeSet") - if err != nil { - return nil, err - } - return &LLOFeeManagerNativeSurchargeSetIterator{contract: _LLOFeeManager.contract, event: "NativeSurchargeSet", logs: logs, sub: sub}, nil -} - -func (_LLOFeeManager *LLOFeeManagerFilterer) WatchNativeSurchargeSet(opts *bind.WatchOpts, sink chan<- *LLOFeeManagerNativeSurchargeSet) (event.Subscription, error) { - - logs, sub, err := _LLOFeeManager.contract.WatchLogs(opts, "NativeSurchargeSet") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(LLOFeeManagerNativeSurchargeSet) - if err := _LLOFeeManager.contract.UnpackLog(event, "NativeSurchargeSet", 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 (_LLOFeeManager *LLOFeeManagerFilterer) ParseNativeSurchargeSet(log types.Log) (*LLOFeeManagerNativeSurchargeSet, error) { - event := new(LLOFeeManagerNativeSurchargeSet) - if err := _LLOFeeManager.contract.UnpackLog(event, "NativeSurchargeSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type LLOFeeManagerOwnershipTransferRequestedIterator struct { - Event *LLOFeeManagerOwnershipTransferRequested - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *LLOFeeManagerOwnershipTransferRequestedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(LLOFeeManagerOwnershipTransferRequested) - 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(LLOFeeManagerOwnershipTransferRequested) - 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 *LLOFeeManagerOwnershipTransferRequestedIterator) Error() error { - return it.fail -} - -func (it *LLOFeeManagerOwnershipTransferRequestedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type LLOFeeManagerOwnershipTransferRequested struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_LLOFeeManager *LLOFeeManagerFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*LLOFeeManagerOwnershipTransferRequestedIterator, 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 := _LLOFeeManager.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) - if err != nil { - return nil, err - } - return &LLOFeeManagerOwnershipTransferRequestedIterator{contract: _LLOFeeManager.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil -} - -func (_LLOFeeManager *LLOFeeManagerFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *LLOFeeManagerOwnershipTransferRequested, 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 := _LLOFeeManager.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(LLOFeeManagerOwnershipTransferRequested) - if err := _LLOFeeManager.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 (_LLOFeeManager *LLOFeeManagerFilterer) ParseOwnershipTransferRequested(log types.Log) (*LLOFeeManagerOwnershipTransferRequested, error) { - event := new(LLOFeeManagerOwnershipTransferRequested) - if err := _LLOFeeManager.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type LLOFeeManagerOwnershipTransferredIterator struct { - Event *LLOFeeManagerOwnershipTransferred - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *LLOFeeManagerOwnershipTransferredIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(LLOFeeManagerOwnershipTransferred) - 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(LLOFeeManagerOwnershipTransferred) - 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 *LLOFeeManagerOwnershipTransferredIterator) Error() error { - return it.fail -} - -func (it *LLOFeeManagerOwnershipTransferredIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type LLOFeeManagerOwnershipTransferred struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_LLOFeeManager *LLOFeeManagerFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*LLOFeeManagerOwnershipTransferredIterator, 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 := _LLOFeeManager.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) - if err != nil { - return nil, err - } - return &LLOFeeManagerOwnershipTransferredIterator{contract: _LLOFeeManager.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil -} - -func (_LLOFeeManager *LLOFeeManagerFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *LLOFeeManagerOwnershipTransferred, 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 := _LLOFeeManager.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(LLOFeeManagerOwnershipTransferred) - if err := _LLOFeeManager.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 (_LLOFeeManager *LLOFeeManagerFilterer) ParseOwnershipTransferred(log types.Log) (*LLOFeeManagerOwnershipTransferred, error) { - event := new(LLOFeeManagerOwnershipTransferred) - if err := _LLOFeeManager.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type LLOFeeManagerSubscriberDiscountUpdatedIterator struct { - Event *LLOFeeManagerSubscriberDiscountUpdated - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *LLOFeeManagerSubscriberDiscountUpdatedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(LLOFeeManagerSubscriberDiscountUpdated) - 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(LLOFeeManagerSubscriberDiscountUpdated) - 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 *LLOFeeManagerSubscriberDiscountUpdatedIterator) Error() error { - return it.fail -} - -func (it *LLOFeeManagerSubscriberDiscountUpdatedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type LLOFeeManagerSubscriberDiscountUpdated struct { - Subscriber common.Address - FeedId [32]byte - Token common.Address - Discount *big.Int - Raw types.Log -} - -func (_LLOFeeManager *LLOFeeManagerFilterer) FilterSubscriberDiscountUpdated(opts *bind.FilterOpts, subscriber []common.Address, feedId [][32]byte) (*LLOFeeManagerSubscriberDiscountUpdatedIterator, error) { - - var subscriberRule []interface{} - for _, subscriberItem := range subscriber { - subscriberRule = append(subscriberRule, subscriberItem) - } - var feedIdRule []interface{} - for _, feedIdItem := range feedId { - feedIdRule = append(feedIdRule, feedIdItem) - } - - logs, sub, err := _LLOFeeManager.contract.FilterLogs(opts, "SubscriberDiscountUpdated", subscriberRule, feedIdRule) - if err != nil { - return nil, err - } - return &LLOFeeManagerSubscriberDiscountUpdatedIterator{contract: _LLOFeeManager.contract, event: "SubscriberDiscountUpdated", logs: logs, sub: sub}, nil -} - -func (_LLOFeeManager *LLOFeeManagerFilterer) WatchSubscriberDiscountUpdated(opts *bind.WatchOpts, sink chan<- *LLOFeeManagerSubscriberDiscountUpdated, subscriber []common.Address, feedId [][32]byte) (event.Subscription, error) { - - var subscriberRule []interface{} - for _, subscriberItem := range subscriber { - subscriberRule = append(subscriberRule, subscriberItem) - } - var feedIdRule []interface{} - for _, feedIdItem := range feedId { - feedIdRule = append(feedIdRule, feedIdItem) - } - - logs, sub, err := _LLOFeeManager.contract.WatchLogs(opts, "SubscriberDiscountUpdated", subscriberRule, feedIdRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(LLOFeeManagerSubscriberDiscountUpdated) - if err := _LLOFeeManager.contract.UnpackLog(event, "SubscriberDiscountUpdated", 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 (_LLOFeeManager *LLOFeeManagerFilterer) ParseSubscriberDiscountUpdated(log types.Log) (*LLOFeeManagerSubscriberDiscountUpdated, error) { - event := new(LLOFeeManagerSubscriberDiscountUpdated) - if err := _LLOFeeManager.contract.UnpackLog(event, "SubscriberDiscountUpdated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type LLOFeeManagerWithdrawIterator struct { - Event *LLOFeeManagerWithdraw - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *LLOFeeManagerWithdrawIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(LLOFeeManagerWithdraw) - 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(LLOFeeManagerWithdraw) - 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 *LLOFeeManagerWithdrawIterator) Error() error { - return it.fail -} - -func (it *LLOFeeManagerWithdrawIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type LLOFeeManagerWithdraw struct { - AdminAddress common.Address - AssetAddress common.Address - Quantity *big.Int - Raw types.Log -} - -func (_LLOFeeManager *LLOFeeManagerFilterer) FilterWithdraw(opts *bind.FilterOpts) (*LLOFeeManagerWithdrawIterator, error) { - - logs, sub, err := _LLOFeeManager.contract.FilterLogs(opts, "Withdraw") - if err != nil { - return nil, err - } - return &LLOFeeManagerWithdrawIterator{contract: _LLOFeeManager.contract, event: "Withdraw", logs: logs, sub: sub}, nil -} - -func (_LLOFeeManager *LLOFeeManagerFilterer) WatchWithdraw(opts *bind.WatchOpts, sink chan<- *LLOFeeManagerWithdraw) (event.Subscription, error) { - - logs, sub, err := _LLOFeeManager.contract.WatchLogs(opts, "Withdraw") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(LLOFeeManagerWithdraw) - if err := _LLOFeeManager.contract.UnpackLog(event, "Withdraw", 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 (_LLOFeeManager *LLOFeeManagerFilterer) ParseWithdraw(log types.Log) (*LLOFeeManagerWithdraw, error) { - event := new(LLOFeeManagerWithdraw) - if err := _LLOFeeManager.contract.UnpackLog(event, "Withdraw", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -func (_LLOFeeManager *LLOFeeManager) ParseLog(log types.Log) (generated.AbigenLog, error) { - switch log.Topics[0] { - case _LLOFeeManager.abi.Events["InsufficientLink"].ID: - return _LLOFeeManager.ParseInsufficientLink(log) - case _LLOFeeManager.abi.Events["NativeSurchargeSet"].ID: - return _LLOFeeManager.ParseNativeSurchargeSet(log) - case _LLOFeeManager.abi.Events["OwnershipTransferRequested"].ID: - return _LLOFeeManager.ParseOwnershipTransferRequested(log) - case _LLOFeeManager.abi.Events["OwnershipTransferred"].ID: - return _LLOFeeManager.ParseOwnershipTransferred(log) - case _LLOFeeManager.abi.Events["SubscriberDiscountUpdated"].ID: - return _LLOFeeManager.ParseSubscriberDiscountUpdated(log) - case _LLOFeeManager.abi.Events["Withdraw"].ID: - return _LLOFeeManager.ParseWithdraw(log) - - default: - return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) - } -} - -func (LLOFeeManagerInsufficientLink) Topic() common.Hash { - return common.HexToHash("0xeb6f22018570d97db6df12dc94f202b4e2b2888a6a5d4bd179422c91b29dcdf7") -} - -func (LLOFeeManagerNativeSurchargeSet) Topic() common.Hash { - return common.HexToHash("0x4fbcc2b7f4cb5518be923bd7c7c887e29e07b001e2a4a0fdd47c494696d8a147") -} - -func (LLOFeeManagerOwnershipTransferRequested) Topic() common.Hash { - return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") -} - -func (LLOFeeManagerOwnershipTransferred) Topic() common.Hash { - return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") -} - -func (LLOFeeManagerSubscriberDiscountUpdated) Topic() common.Hash { - return common.HexToHash("0x41eb9ccd292d5906dc1f0ec108bed3e2b966e3071e033df938f7215f6d30ca84") -} - -func (LLOFeeManagerWithdraw) Topic() common.Hash { - return common.HexToHash("0x9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb") -} - -func (_LLOFeeManager *LLOFeeManager) Address() common.Address { - return _LLOFeeManager.address -} - -type LLOFeeManagerInterface interface { - GetFeeAndReward(opts *bind.CallOpts, subscriber common.Address, report []byte, quote IFeeManagerQuote) (CommonAsset, CommonAsset, error) - - LinkAvailableForPayment(opts *bind.CallOpts) (*big.Int, error) - - NativeSurcharge(opts *bind.CallOpts) (*big.Int, error) - - Owner(opts *bind.CallOpts) (common.Address, error) - - SubscriberDiscounts(opts *bind.CallOpts, arg0 common.Address, arg1 [32]byte, arg2 common.Address) (*big.Int, error) - - SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) - - TypeAndVersion(opts *bind.CallOpts) (string, error) - - AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) - - ProcessFee(opts *bind.TransactOpts, payload []byte, subscriber common.Address) (*types.Transaction, error) - - SetFeeRecipients(opts *bind.TransactOpts, configDigest [32]byte, rewardRecipientAndWeights []CommonAddressAndWeight) (*types.Transaction, error) - - SetNativeSurcharge(opts *bind.TransactOpts, surcharge *big.Int) (*types.Transaction, error) - - TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) - - UpdateSubscriberDiscount(opts *bind.TransactOpts, subscriber common.Address, feedId [32]byte, token common.Address, discount *big.Int) (*types.Transaction, error) - - Withdraw(opts *bind.TransactOpts, assetAddress common.Address, quantity *big.Int) (*types.Transaction, error) - - FilterInsufficientLink(opts *bind.FilterOpts, configDigest [][32]byte) (*LLOFeeManagerInsufficientLinkIterator, error) - - WatchInsufficientLink(opts *bind.WatchOpts, sink chan<- *LLOFeeManagerInsufficientLink, configDigest [][32]byte) (event.Subscription, error) - - ParseInsufficientLink(log types.Log) (*LLOFeeManagerInsufficientLink, error) - - FilterNativeSurchargeSet(opts *bind.FilterOpts) (*LLOFeeManagerNativeSurchargeSetIterator, error) - - WatchNativeSurchargeSet(opts *bind.WatchOpts, sink chan<- *LLOFeeManagerNativeSurchargeSet) (event.Subscription, error) - - ParseNativeSurchargeSet(log types.Log) (*LLOFeeManagerNativeSurchargeSet, error) - - FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*LLOFeeManagerOwnershipTransferRequestedIterator, error) - - WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *LLOFeeManagerOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferRequested(log types.Log) (*LLOFeeManagerOwnershipTransferRequested, error) - - FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*LLOFeeManagerOwnershipTransferredIterator, error) - - WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *LLOFeeManagerOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferred(log types.Log) (*LLOFeeManagerOwnershipTransferred, error) - - FilterSubscriberDiscountUpdated(opts *bind.FilterOpts, subscriber []common.Address, feedId [][32]byte) (*LLOFeeManagerSubscriberDiscountUpdatedIterator, error) - - WatchSubscriberDiscountUpdated(opts *bind.WatchOpts, sink chan<- *LLOFeeManagerSubscriberDiscountUpdated, subscriber []common.Address, feedId [][32]byte) (event.Subscription, error) - - ParseSubscriberDiscountUpdated(log types.Log) (*LLOFeeManagerSubscriberDiscountUpdated, error) - - FilterWithdraw(opts *bind.FilterOpts) (*LLOFeeManagerWithdrawIterator, error) - - WatchWithdraw(opts *bind.WatchOpts, sink chan<- *LLOFeeManagerWithdraw) (event.Subscription, error) - - ParseWithdraw(log types.Log) (*LLOFeeManagerWithdraw, error) - - ParseLog(log types.Log) (generated.AbigenLog, error) - - Address() common.Address -} diff --git a/core/gethwrappers/llo-feeds/generated/llo_feeds_test/llo_feeds_test.go b/core/gethwrappers/llo-feeds/generated/llo_feeds_test/llo_feeds_test.go deleted file mode 100644 index 51f0f6e462e..00000000000 --- a/core/gethwrappers/llo-feeds/generated/llo_feeds_test/llo_feeds_test.go +++ /dev/null @@ -1,202 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package llo_feeds_test - -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 LLOExposedVerifierMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_feedId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_chainId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_contractAddress\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"_configCount\",\"type\":\"uint64\"},{\"internalType\":\"address[]\",\"name\":\"_signers\",\"type\":\"address[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"_offchainTransmitters\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"_f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"_onchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"_encodedConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"_encodedConfig\",\"type\":\"bytes\"}],\"name\":\"exposedConfigDigestFromConfigData\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b50610696806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80630ebd702314610030575b600080fd5b61004361003e3660046103f7565b610055565b60405190815260200160405180910390f35b60006100a18c8c8c8c8c8c8c8c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508e92508d91506100b19050565b9c9b505050505050505050505050565b6000808b8b8b8b8b8b8b8b8b8b6040516020016100d79a999897969594939291906105a7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e06000000000000000000000000000000000000000000000000000000000000179150509a9950505050505050505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461018357600080fd5b919050565b803567ffffffffffffffff8116811461018357600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610216576102166101a0565b604052919050565b600067ffffffffffffffff821115610238576102386101a0565b5060051b60200190565b600082601f83011261025357600080fd5b813560206102686102638361021e565b6101cf565b82815260059290921b8401810191818101908684111561028757600080fd5b8286015b848110156102a95761029c8161015f565b835291830191830161028b565b509695505050505050565b600082601f8301126102c557600080fd5b813560206102d56102638361021e565b82815260059290921b840181019181810190868411156102f457600080fd5b8286015b848110156102a957803583529183019183016102f8565b803560ff8116811461018357600080fd5b60008083601f84011261033257600080fd5b50813567ffffffffffffffff81111561034a57600080fd5b60208301915083602082850101111561036257600080fd5b9250929050565b600082601f83011261037a57600080fd5b813567ffffffffffffffff811115610394576103946101a0565b6103c560207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016101cf565b8181528460208386010111156103da57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060008060008060006101408c8e03121561041957600080fd5b8b359a5060208c0135995061043060408d0161015f565b985061043e60608d01610188565b975067ffffffffffffffff8060808e0135111561045a57600080fd5b61046a8e60808f01358f01610242565b97508060a08e0135111561047d57600080fd5b61048d8e60a08f01358f016102b4565b965061049b60c08e0161030f565b95508060e08e013511156104ae57600080fd5b6104be8e60e08f01358f01610320565b90955093506104d06101008e01610188565b9250806101208e013511156104e457600080fd5b506104f68d6101208e01358e01610369565b90509295989b509295989b9093969950565b600081518084526020808501945080840160005b838110156105385781518752958201959082019060010161051c565b509495945050505050565b6000815180845260005b818110156105695760208185018101518683018201520161054d565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b8a815260208082018b905273ffffffffffffffffffffffffffffffffffffffff8a8116604084015267ffffffffffffffff8a1660608401526101406080840181905289519084018190526000926101608501928b820192855b8181101561061e578451831686529483019493830193600101610600565b505050505082810360a08401526106358189610508565b60ff881660c0850152905082810360e08401526106528187610543565b67ffffffffffffffff861661010085015290508281036101208401526106788185610543565b9d9c5050505050505050505050505056fea164736f6c6343000810000a", -} - -var LLOExposedVerifierABI = LLOExposedVerifierMetaData.ABI - -var LLOExposedVerifierBin = LLOExposedVerifierMetaData.Bin - -func DeployLLOExposedVerifier(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *LLOExposedVerifier, error) { - parsed, err := LLOExposedVerifierMetaData.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(LLOExposedVerifierBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &LLOExposedVerifier{LLOExposedVerifierCaller: LLOExposedVerifierCaller{contract: contract}, LLOExposedVerifierTransactor: LLOExposedVerifierTransactor{contract: contract}, LLOExposedVerifierFilterer: LLOExposedVerifierFilterer{contract: contract}}, nil -} - -type LLOExposedVerifier struct { - address common.Address - abi abi.ABI - LLOExposedVerifierCaller - LLOExposedVerifierTransactor - LLOExposedVerifierFilterer -} - -type LLOExposedVerifierCaller struct { - contract *bind.BoundContract -} - -type LLOExposedVerifierTransactor struct { - contract *bind.BoundContract -} - -type LLOExposedVerifierFilterer struct { - contract *bind.BoundContract -} - -type LLOExposedVerifierSession struct { - Contract *LLOExposedVerifier - CallOpts bind.CallOpts - TransactOpts bind.TransactOpts -} - -type LLOExposedVerifierCallerSession struct { - Contract *LLOExposedVerifierCaller - CallOpts bind.CallOpts -} - -type LLOExposedVerifierTransactorSession struct { - Contract *LLOExposedVerifierTransactor - TransactOpts bind.TransactOpts -} - -type LLOExposedVerifierRaw struct { - Contract *LLOExposedVerifier -} - -type LLOExposedVerifierCallerRaw struct { - Contract *LLOExposedVerifierCaller -} - -type LLOExposedVerifierTransactorRaw struct { - Contract *LLOExposedVerifierTransactor -} - -func NewLLOExposedVerifier(address common.Address, backend bind.ContractBackend) (*LLOExposedVerifier, error) { - abi, err := abi.JSON(strings.NewReader(LLOExposedVerifierABI)) - if err != nil { - return nil, err - } - contract, err := bindLLOExposedVerifier(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &LLOExposedVerifier{address: address, abi: abi, LLOExposedVerifierCaller: LLOExposedVerifierCaller{contract: contract}, LLOExposedVerifierTransactor: LLOExposedVerifierTransactor{contract: contract}, LLOExposedVerifierFilterer: LLOExposedVerifierFilterer{contract: contract}}, nil -} - -func NewLLOExposedVerifierCaller(address common.Address, caller bind.ContractCaller) (*LLOExposedVerifierCaller, error) { - contract, err := bindLLOExposedVerifier(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &LLOExposedVerifierCaller{contract: contract}, nil -} - -func NewLLOExposedVerifierTransactor(address common.Address, transactor bind.ContractTransactor) (*LLOExposedVerifierTransactor, error) { - contract, err := bindLLOExposedVerifier(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &LLOExposedVerifierTransactor{contract: contract}, nil -} - -func NewLLOExposedVerifierFilterer(address common.Address, filterer bind.ContractFilterer) (*LLOExposedVerifierFilterer, error) { - contract, err := bindLLOExposedVerifier(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &LLOExposedVerifierFilterer{contract: contract}, nil -} - -func bindLLOExposedVerifier(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := LLOExposedVerifierMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -func (_LLOExposedVerifier *LLOExposedVerifierRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _LLOExposedVerifier.Contract.LLOExposedVerifierCaller.contract.Call(opts, result, method, params...) -} - -func (_LLOExposedVerifier *LLOExposedVerifierRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _LLOExposedVerifier.Contract.LLOExposedVerifierTransactor.contract.Transfer(opts) -} - -func (_LLOExposedVerifier *LLOExposedVerifierRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _LLOExposedVerifier.Contract.LLOExposedVerifierTransactor.contract.Transact(opts, method, params...) -} - -func (_LLOExposedVerifier *LLOExposedVerifierCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _LLOExposedVerifier.Contract.contract.Call(opts, result, method, params...) -} - -func (_LLOExposedVerifier *LLOExposedVerifierTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _LLOExposedVerifier.Contract.contract.Transfer(opts) -} - -func (_LLOExposedVerifier *LLOExposedVerifierTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _LLOExposedVerifier.Contract.contract.Transact(opts, method, params...) -} - -func (_LLOExposedVerifier *LLOExposedVerifierCaller) ExposedConfigDigestFromConfigData(opts *bind.CallOpts, _feedId [32]byte, _chainId *big.Int, _contractAddress common.Address, _configCount uint64, _signers []common.Address, _offchainTransmitters [][32]byte, _f uint8, _onchainConfig []byte, _encodedConfigVersion uint64, _encodedConfig []byte) ([32]byte, error) { - var out []interface{} - err := _LLOExposedVerifier.contract.Call(opts, &out, "exposedConfigDigestFromConfigData", _feedId, _chainId, _contractAddress, _configCount, _signers, _offchainTransmitters, _f, _onchainConfig, _encodedConfigVersion, _encodedConfig) - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -func (_LLOExposedVerifier *LLOExposedVerifierSession) ExposedConfigDigestFromConfigData(_feedId [32]byte, _chainId *big.Int, _contractAddress common.Address, _configCount uint64, _signers []common.Address, _offchainTransmitters [][32]byte, _f uint8, _onchainConfig []byte, _encodedConfigVersion uint64, _encodedConfig []byte) ([32]byte, error) { - return _LLOExposedVerifier.Contract.ExposedConfigDigestFromConfigData(&_LLOExposedVerifier.CallOpts, _feedId, _chainId, _contractAddress, _configCount, _signers, _offchainTransmitters, _f, _onchainConfig, _encodedConfigVersion, _encodedConfig) -} - -func (_LLOExposedVerifier *LLOExposedVerifierCallerSession) ExposedConfigDigestFromConfigData(_feedId [32]byte, _chainId *big.Int, _contractAddress common.Address, _configCount uint64, _signers []common.Address, _offchainTransmitters [][32]byte, _f uint8, _onchainConfig []byte, _encodedConfigVersion uint64, _encodedConfig []byte) ([32]byte, error) { - return _LLOExposedVerifier.Contract.ExposedConfigDigestFromConfigData(&_LLOExposedVerifier.CallOpts, _feedId, _chainId, _contractAddress, _configCount, _signers, _offchainTransmitters, _f, _onchainConfig, _encodedConfigVersion, _encodedConfig) -} - -func (_LLOExposedVerifier *LLOExposedVerifier) Address() common.Address { - return _LLOExposedVerifier.address -} - -type LLOExposedVerifierInterface interface { - ExposedConfigDigestFromConfigData(opts *bind.CallOpts, _feedId [32]byte, _chainId *big.Int, _contractAddress common.Address, _configCount uint64, _signers []common.Address, _offchainTransmitters [][32]byte, _f uint8, _onchainConfig []byte, _encodedConfigVersion uint64, _encodedConfig []byte) ([32]byte, error) - - Address() common.Address -} diff --git a/core/gethwrappers/llo-feeds/generated/reward_manager_v0_5_0/reward_manager_v0_5_0.go b/core/gethwrappers/llo-feeds/generated/reward_manager_v0_5_0/reward_manager_v0_5_0.go new file mode 100644 index 00000000000..f7221195282 --- /dev/null +++ b/core/gethwrappers/llo-feeds/generated/reward_manager_v0_5_0/reward_manager_v0_5_0.go @@ -0,0 +1,1420 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package reward_manager_v0_5_0 + +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 +) + +type CommonAddressAndWeight struct { + Addr common.Address + Weight uint64 +} + +type IRewardManagerFeePayment struct { + PoolId [32]byte + Amount *big.Int +} + +var RewardManagerMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"linkAddress\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPoolId\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPoolLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidWeights\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newFeeManagerAddress\",\"type\":\"address\"}],\"name\":\"FeeManagerUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"poolId\",\"type\":\"bytes32\"},{\"internalType\":\"uint192\",\"name\":\"amount\",\"type\":\"uint192\"}],\"indexed\":false,\"internalType\":\"structIRewardManager.FeePayment[]\",\"name\":\"payments\",\"type\":\"tuple[]\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"}],\"name\":\"FeePaid\",\"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\":true,\"internalType\":\"bytes32\",\"name\":\"poolId\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"weight\",\"type\":\"uint64\"}],\"indexed\":false,\"internalType\":\"structCommon.AddressAndWeight[]\",\"name\":\"newRewardRecipients\",\"type\":\"tuple[]\"}],\"name\":\"RewardRecipientsUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"poolId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint192\",\"name\":\"quantity\",\"type\":\"uint192\"}],\"name\":\"RewardsClaimed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"poolIds\",\"type\":\"bytes32[]\"}],\"name\":\"claimRewards\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"startIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"endIndex\",\"type\":\"uint256\"}],\"name\":\"getAvailableRewardPoolIds\",\"outputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_linkAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"poolId\",\"type\":\"bytes32\"},{\"internalType\":\"uint192\",\"name\":\"amount\",\"type\":\"uint192\"}],\"internalType\":\"structIRewardManager.FeePayment[]\",\"name\":\"payments\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"}],\"name\":\"onFeePaid\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"poolId\",\"type\":\"bytes32\"},{\"internalType\":\"address[]\",\"name\":\"recipients\",\"type\":\"address[]\"}],\"name\":\"payRecipients\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_feeManagerAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_registeredPoolIds\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"s_rewardRecipientWeights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"s_rewardRecipientWeightsSet\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"s_totalRewardRecipientFees\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"s_totalRewardRecipientFeesLastClaimedAmounts\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newFeeManagerAddress\",\"type\":\"address\"}],\"name\":\"setFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"poolId\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"weight\",\"type\":\"uint64\"}],\"internalType\":\"structCommon.AddressAndWeight[]\",\"name\":\"rewardRecipientAndWeights\",\"type\":\"tuple[]\"}],\"name\":\"setRewardRecipients\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"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\":\"bytes32\",\"name\":\"poolId\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"weight\",\"type\":\"uint64\"}],\"internalType\":\"structCommon.AddressAndWeight[]\",\"name\":\"newRewardRecipients\",\"type\":\"tuple[]\"}],\"name\":\"updateRewardRecipients\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60a06040523480156200001157600080fd5b50604051620020c2380380620020c28339810160408190526200003491620001a6565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000fb565b5050506001600160a01b038116620000e95760405163e6c4247b60e01b815260040160405180910390fd5b6001600160a01b0316608052620001d8565b336001600160a01b03821603620001555760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215620001b957600080fd5b81516001600160a01b0381168114620001d157600080fd5b9392505050565b608051611ec062000202600039600081816103bd01528181610ce30152610f1e0152611ec06000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c80634d322084116100cd5780638da5cb5b11610081578063cd5f729211610066578063cd5f7292146103a5578063ea4b861b146103b8578063f2fde38b146103df57600080fd5b80638da5cb5b14610374578063b0d9fa191461039257600080fd5b806360122608116100b2578063601226081461031657806379ba5097146103415780638ac85a5c1461034957600080fd5b80634d322084146102e057806359256201146102f357600080fd5b8063276e7660116101245780634722647511610109578063472264751461029a578063472d35b9146102ba5780634944832f146102cd57600080fd5b8063276e76601461022757806339ee81e11461026c57600080fd5b806301ffc9a7146101565780630f3c34d1146101c057806314060f23146101d5578063181f5a77146101e8575b600080fd5b6101ab6101643660046117ac565b7fffffffff00000000000000000000000000000000000000000000000000000000167fb0d9fa19000000000000000000000000000000000000000000000000000000001490565b60405190151581526020015b60405180910390f35b6101d36101ce36600461186c565b6103f2565b005b6101d36101e336600461195e565b610400565b604080518082018252601381527f5265776172644d616e6167657220312e312e3000000000000000000000000000602082015290516101b791906119ce565b6007546102479073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101b7565b61028c61027a366004611a1f565b60026020526000908152604090205481565b6040519081526020016101b7565b6102ad6102a8366004611a61565b6105b6565b6040516101b79190611a94565b6101d36102c8366004611ad8565b610740565b6101d36102db36600461195e565b61080e565b6101d36102ee366004611afa565b610957565b6101ab610301366004611a1f565b60056020526000908152604090205460ff1681565b61028c610324366004611b79565b600360209081526000928352604080842090915290825290205481565b6101d3610a96565b61028c610357366004611b79565b600460209081526000928352604080842090915290825290205481565b60005473ffffffffffffffffffffffffffffffffffffffff16610247565b6101d36103a0366004611ba5565b610b98565b61028c6103b3366004611a1f565b610d4c565b6102477f000000000000000000000000000000000000000000000000000000000000000081565b6101d36103ed366004611ad8565b610d6d565b6103fc3382610d81565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314801590610440575060075473ffffffffffffffffffffffffffffffffffffffff163314155b15610477576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008190036104b2576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526005602052604090205460ff16156104fb576040517f0afa7ee800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6006805460018181019092557ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f01849055600084815260056020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169091179055610577838383670de0b6b3a7640000610f4e565b827f8f668d6090683f98b3373a8b83d214da45737f7486cb7de554cc07b54e61cfe683836040516105a9929190611c11565b60405180910390a2505050565b60065460609060008184116105cb57836105cd565b815b905080851115610609576040517fa22caccc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006106158683611ca8565b67ffffffffffffffff81111561062d5761062d6117ee565b604051908082528060200260200182016040528015610656578160200160208202803683370190505b5090506000865b838110156107335760006006828154811061067a5761067a611cbb565b600091825260208083209091015480835260048252604080842073ffffffffffffffffffffffffffffffffffffffff8f16855290925291205490915015610722576000818152600260209081526040808320546003835281842073ffffffffffffffffffffffffffffffffffffffff8f168552909252909120548114610720578185858060010196508151811061071357610713611cbb565b6020026020010181815250505b505b5061072c81611cea565b905061065d565b5090979650505050505050565b610748611125565b73ffffffffffffffffffffffffffffffffffffffff8116610795576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fe45f5e140399b0a7e12971ab020724b828fbed8ac408c420884dc7d1bbe506b49060200160405180910390a150565b610816611125565b60408051600180825281830190925260009160208083019080368337019050509050838160008151811061084c5761084c611cbb565b6020026020010181815250506000805b8381101561090957600085858381811061087857610878611cbb565b61088e9260206040909202019081019150611ad8565b600088815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff851684529091529020549091506108f28787858181106108d6576108d6611cbb565b6108ec9260206040909202019081019150611ad8565b86610d81565b5092909201915061090281611cea565b905061085c565b5061091685858584610f4e565b847f8f668d6090683f98b3373a8b83d214da45737f7486cb7de554cc07b54e61cfe68585604051610948929190611c11565b60405180910390a25050505050565b8261097760005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156109c957506000818152600460209081526040808320338452909152902054155b15610a00576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001808252818301909252600091602080830190803683370190505090508481600081518110610a3657610a36611cbb565b60200260200101818152505060005b83811015610a8e57610a7d858583818110610a6257610a62611cbb565b9050602002016020810190610a779190611ad8565b83610d81565b50610a8781611cea565b9050610a45565b505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610b1c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60075473ffffffffffffffffffffffffffffffffffffffff163314610be9576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805b83811015610cc857848482818110610c0757610c07611cbb565b9050604002016020016020810190610c1f9190611d4a565b77ffffffffffffffffffffffffffffffffffffffffffffffff1660026000878785818110610c4f57610c4f611cbb565b6040908102929092013583525060208201929092520160002080549091019055848482818110610c8157610c81611cbb565b9050604002016020016020810190610c999190611d4a565b77ffffffffffffffffffffffffffffffffffffffffffffffff168201915080610cc190611cea565b9050610bed565b50610d0b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168330846111a8565b7fa1cc025ea76bacce5d740ee4bc331899375dc2c5f2ab33933aaacbd9ba001b66848484604051610d3e93929190611d65565b60405180910390a150505050565b60068181548110610d5c57600080fd5b600091825260209091200154905081565b610d75611125565b610d7e8161128a565b50565b60008060005b8351811015610efd576000848281518110610da457610da4611cbb565b6020026020010151905060006002600083815260200190815260200160002054905080600003610dd5575050610eed565b600082815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8b16808552908352818420548685526004845282852091855292528220549083039190670de0b6b3a764000090830204905080600003610e3e5750505050610eed565b600084815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8d168085529252909120849055885196820196899087908110610e8957610e89611cbb565b60200260200101517f989969655bc1d593922527fe85d71347bb8e12fa423cc71f362dd8ef7cb10ef283604051610ee0919077ffffffffffffffffffffffffffffffffffffffffffffffff91909116815260200190565b60405180910390a3505050505b610ef681611cea565b9050610d87565b508015610f4557610f4573ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016858361137f565b90505b92915050565b610fa98383808060200260200160405190810160405280939291908181526020016000905b82821015610f9f57610f9060408302860136819003810190611dec565b81526020019060010190610f73565b50505050506113da565b15610fe0576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805b838110156110e457600085858381811061100057611000611cbb565b90506040020160200160208101906110189190611e47565b67ffffffffffffffff169050600086868481811061103857611038611cbb565b61104e9260206040909202019081019150611ad8565b905073ffffffffffffffffffffffffffffffffffffffff811661109d576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600088815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff90941683529290522081905591909101906110dd81611cea565b9050610fe4565b5081811461111e576040517f84677ce800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146111a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610b13565b565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526112849085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611491565b50505050565b3373ffffffffffffffffffffffffffffffffffffffff821603611309576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610b13565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526113d59084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401611202565b505050565b6000805b82518110156114885760006113f4826001611e62565b90505b835181101561147f5783818151811061141257611412611cbb565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1684838151811061144657611446611cbb565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1603611477575060019392505050565b6001016113f7565b506001016113de565b50600092915050565b60006114f3826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661159d9092919063ffffffff16565b8051909150156113d557808060200190518101906115119190611e75565b6113d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610b13565b60606115ac84846000856115b4565b949350505050565b606082471015611646576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610b13565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161166f9190611e97565b60006040518083038185875af1925050503d80600081146116ac576040519150601f19603f3d011682016040523d82523d6000602084013e6116b1565b606091505b50915091506116c2878383876116cd565b979650505050505050565b6060831561176357825160000361175c5773ffffffffffffffffffffffffffffffffffffffff85163b61175c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610b13565b50816115ac565b6115ac83838151156117785781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b1391906119ce565b6000602082840312156117be57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610f4557600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611864576118646117ee565b604052919050565b6000602080838503121561187f57600080fd5b823567ffffffffffffffff8082111561189757600080fd5b818501915085601f8301126118ab57600080fd5b8135818111156118bd576118bd6117ee565b8060051b91506118ce84830161181d565b81815291830184019184810190888411156118e857600080fd5b938501935b83851015611906578435825293850193908501906118ed565b98975050505050505050565b60008083601f84011261192457600080fd5b50813567ffffffffffffffff81111561193c57600080fd5b6020830191508360208260061b850101111561195757600080fd5b9250929050565b60008060006040848603121561197357600080fd5b83359250602084013567ffffffffffffffff81111561199157600080fd5b61199d86828701611912565b9497909650939450505050565b60005b838110156119c55781810151838201526020016119ad565b50506000910152565b60208152600082518060208401526119ed8160408501602087016119aa565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b600060208284031215611a3157600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611a5c57600080fd5b919050565b600080600060608486031215611a7657600080fd5b611a7f84611a38565b95602085013595506040909401359392505050565b6020808252825182820181905260009190848201906040850190845b81811015611acc57835183529284019291840191600101611ab0565b50909695505050505050565b600060208284031215611aea57600080fd5b611af382611a38565b9392505050565b600080600060408486031215611b0f57600080fd5b83359250602084013567ffffffffffffffff80821115611b2e57600080fd5b818601915086601f830112611b4257600080fd5b813581811115611b5157600080fd5b8760208260051b8501011115611b6657600080fd5b6020830194508093505050509250925092565b60008060408385031215611b8c57600080fd5b82359150611b9c60208401611a38565b90509250929050565b600080600060408486031215611bba57600080fd5b833567ffffffffffffffff811115611bd157600080fd5b611bdd86828701611912565b9094509250611bf0905060208501611a38565b90509250925092565b803567ffffffffffffffff81168114611a5c57600080fd5b6020808252818101839052600090604080840186845b878110156107335773ffffffffffffffffffffffffffffffffffffffff611c4d83611a38565b16835267ffffffffffffffff611c64868401611bf9565b16838601529183019190830190600101611c27565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115610f4857610f48611c79565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611d1b57611d1b611c79565b5060010190565b803577ffffffffffffffffffffffffffffffffffffffffffffffff81168114611a5c57600080fd5b600060208284031215611d5c57600080fd5b611af382611d22565b60408082528181018490526000908560608401835b87811015611dc15782358252602077ffffffffffffffffffffffffffffffffffffffffffffffff611dac828601611d22565b16908301529183019190830190600101611d7a565b5080935050505073ffffffffffffffffffffffffffffffffffffffff83166020830152949350505050565b600060408284031215611dfe57600080fd5b6040516040810181811067ffffffffffffffff82111715611e2157611e216117ee565b604052611e2d83611a38565b8152611e3b60208401611bf9565b60208201529392505050565b600060208284031215611e5957600080fd5b611af382611bf9565b80820180821115610f4857610f48611c79565b600060208284031215611e8757600080fd5b81518015158114610f4557600080fd5b60008251611ea98184602087016119aa565b919091019291505056fea164736f6c6343000813000a", +} + +var RewardManagerABI = RewardManagerMetaData.ABI + +var RewardManagerBin = RewardManagerMetaData.Bin + +func DeployRewardManager(auth *bind.TransactOpts, backend bind.ContractBackend, linkAddress common.Address) (common.Address, *types.Transaction, *RewardManager, error) { + parsed, err := RewardManagerMetaData.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(RewardManagerBin), backend, linkAddress) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &RewardManager{address: address, abi: *parsed, RewardManagerCaller: RewardManagerCaller{contract: contract}, RewardManagerTransactor: RewardManagerTransactor{contract: contract}, RewardManagerFilterer: RewardManagerFilterer{contract: contract}}, nil +} + +type RewardManager struct { + address common.Address + abi abi.ABI + RewardManagerCaller + RewardManagerTransactor + RewardManagerFilterer +} + +type RewardManagerCaller struct { + contract *bind.BoundContract +} + +type RewardManagerTransactor struct { + contract *bind.BoundContract +} + +type RewardManagerFilterer struct { + contract *bind.BoundContract +} + +type RewardManagerSession struct { + Contract *RewardManager + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type RewardManagerCallerSession struct { + Contract *RewardManagerCaller + CallOpts bind.CallOpts +} + +type RewardManagerTransactorSession struct { + Contract *RewardManagerTransactor + TransactOpts bind.TransactOpts +} + +type RewardManagerRaw struct { + Contract *RewardManager +} + +type RewardManagerCallerRaw struct { + Contract *RewardManagerCaller +} + +type RewardManagerTransactorRaw struct { + Contract *RewardManagerTransactor +} + +func NewRewardManager(address common.Address, backend bind.ContractBackend) (*RewardManager, error) { + abi, err := abi.JSON(strings.NewReader(RewardManagerABI)) + if err != nil { + return nil, err + } + contract, err := bindRewardManager(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &RewardManager{address: address, abi: abi, RewardManagerCaller: RewardManagerCaller{contract: contract}, RewardManagerTransactor: RewardManagerTransactor{contract: contract}, RewardManagerFilterer: RewardManagerFilterer{contract: contract}}, nil +} + +func NewRewardManagerCaller(address common.Address, caller bind.ContractCaller) (*RewardManagerCaller, error) { + contract, err := bindRewardManager(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &RewardManagerCaller{contract: contract}, nil +} + +func NewRewardManagerTransactor(address common.Address, transactor bind.ContractTransactor) (*RewardManagerTransactor, error) { + contract, err := bindRewardManager(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &RewardManagerTransactor{contract: contract}, nil +} + +func NewRewardManagerFilterer(address common.Address, filterer bind.ContractFilterer) (*RewardManagerFilterer, error) { + contract, err := bindRewardManager(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &RewardManagerFilterer{contract: contract}, nil +} + +func bindRewardManager(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := RewardManagerMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_RewardManager *RewardManagerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _RewardManager.Contract.RewardManagerCaller.contract.Call(opts, result, method, params...) +} + +func (_RewardManager *RewardManagerRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _RewardManager.Contract.RewardManagerTransactor.contract.Transfer(opts) +} + +func (_RewardManager *RewardManagerRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _RewardManager.Contract.RewardManagerTransactor.contract.Transact(opts, method, params...) +} + +func (_RewardManager *RewardManagerCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _RewardManager.Contract.contract.Call(opts, result, method, params...) +} + +func (_RewardManager *RewardManagerTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _RewardManager.Contract.contract.Transfer(opts) +} + +func (_RewardManager *RewardManagerTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _RewardManager.Contract.contract.Transact(opts, method, params...) +} + +func (_RewardManager *RewardManagerCaller) GetAvailableRewardPoolIds(opts *bind.CallOpts, recipient common.Address, startIndex *big.Int, endIndex *big.Int) ([][32]byte, error) { + var out []interface{} + err := _RewardManager.contract.Call(opts, &out, "getAvailableRewardPoolIds", recipient, startIndex, endIndex) + + if err != nil { + return *new([][32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([][32]byte)).(*[][32]byte) + + return out0, err + +} + +func (_RewardManager *RewardManagerSession) GetAvailableRewardPoolIds(recipient common.Address, startIndex *big.Int, endIndex *big.Int) ([][32]byte, error) { + return _RewardManager.Contract.GetAvailableRewardPoolIds(&_RewardManager.CallOpts, recipient, startIndex, endIndex) +} + +func (_RewardManager *RewardManagerCallerSession) GetAvailableRewardPoolIds(recipient common.Address, startIndex *big.Int, endIndex *big.Int) ([][32]byte, error) { + return _RewardManager.Contract.GetAvailableRewardPoolIds(&_RewardManager.CallOpts, recipient, startIndex, endIndex) +} + +func (_RewardManager *RewardManagerCaller) ILinkAddress(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _RewardManager.contract.Call(opts, &out, "i_linkAddress") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_RewardManager *RewardManagerSession) ILinkAddress() (common.Address, error) { + return _RewardManager.Contract.ILinkAddress(&_RewardManager.CallOpts) +} + +func (_RewardManager *RewardManagerCallerSession) ILinkAddress() (common.Address, error) { + return _RewardManager.Contract.ILinkAddress(&_RewardManager.CallOpts) +} + +func (_RewardManager *RewardManagerCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _RewardManager.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 (_RewardManager *RewardManagerSession) Owner() (common.Address, error) { + return _RewardManager.Contract.Owner(&_RewardManager.CallOpts) +} + +func (_RewardManager *RewardManagerCallerSession) Owner() (common.Address, error) { + return _RewardManager.Contract.Owner(&_RewardManager.CallOpts) +} + +func (_RewardManager *RewardManagerCaller) SFeeManagerAddress(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _RewardManager.contract.Call(opts, &out, "s_feeManagerAddress") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_RewardManager *RewardManagerSession) SFeeManagerAddress() (common.Address, error) { + return _RewardManager.Contract.SFeeManagerAddress(&_RewardManager.CallOpts) +} + +func (_RewardManager *RewardManagerCallerSession) SFeeManagerAddress() (common.Address, error) { + return _RewardManager.Contract.SFeeManagerAddress(&_RewardManager.CallOpts) +} + +func (_RewardManager *RewardManagerCaller) SRegisteredPoolIds(opts *bind.CallOpts, arg0 *big.Int) ([32]byte, error) { + var out []interface{} + err := _RewardManager.contract.Call(opts, &out, "s_registeredPoolIds", arg0) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +func (_RewardManager *RewardManagerSession) SRegisteredPoolIds(arg0 *big.Int) ([32]byte, error) { + return _RewardManager.Contract.SRegisteredPoolIds(&_RewardManager.CallOpts, arg0) +} + +func (_RewardManager *RewardManagerCallerSession) SRegisteredPoolIds(arg0 *big.Int) ([32]byte, error) { + return _RewardManager.Contract.SRegisteredPoolIds(&_RewardManager.CallOpts, arg0) +} + +func (_RewardManager *RewardManagerCaller) SRewardRecipientWeights(opts *bind.CallOpts, arg0 [32]byte, arg1 common.Address) (*big.Int, error) { + var out []interface{} + err := _RewardManager.contract.Call(opts, &out, "s_rewardRecipientWeights", arg0, arg1) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_RewardManager *RewardManagerSession) SRewardRecipientWeights(arg0 [32]byte, arg1 common.Address) (*big.Int, error) { + return _RewardManager.Contract.SRewardRecipientWeights(&_RewardManager.CallOpts, arg0, arg1) +} + +func (_RewardManager *RewardManagerCallerSession) SRewardRecipientWeights(arg0 [32]byte, arg1 common.Address) (*big.Int, error) { + return _RewardManager.Contract.SRewardRecipientWeights(&_RewardManager.CallOpts, arg0, arg1) +} + +func (_RewardManager *RewardManagerCaller) SRewardRecipientWeightsSet(opts *bind.CallOpts, arg0 [32]byte) (bool, error) { + var out []interface{} + err := _RewardManager.contract.Call(opts, &out, "s_rewardRecipientWeightsSet", arg0) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_RewardManager *RewardManagerSession) SRewardRecipientWeightsSet(arg0 [32]byte) (bool, error) { + return _RewardManager.Contract.SRewardRecipientWeightsSet(&_RewardManager.CallOpts, arg0) +} + +func (_RewardManager *RewardManagerCallerSession) SRewardRecipientWeightsSet(arg0 [32]byte) (bool, error) { + return _RewardManager.Contract.SRewardRecipientWeightsSet(&_RewardManager.CallOpts, arg0) +} + +func (_RewardManager *RewardManagerCaller) STotalRewardRecipientFees(opts *bind.CallOpts, arg0 [32]byte) (*big.Int, error) { + var out []interface{} + err := _RewardManager.contract.Call(opts, &out, "s_totalRewardRecipientFees", arg0) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_RewardManager *RewardManagerSession) STotalRewardRecipientFees(arg0 [32]byte) (*big.Int, error) { + return _RewardManager.Contract.STotalRewardRecipientFees(&_RewardManager.CallOpts, arg0) +} + +func (_RewardManager *RewardManagerCallerSession) STotalRewardRecipientFees(arg0 [32]byte) (*big.Int, error) { + return _RewardManager.Contract.STotalRewardRecipientFees(&_RewardManager.CallOpts, arg0) +} + +func (_RewardManager *RewardManagerCaller) STotalRewardRecipientFeesLastClaimedAmounts(opts *bind.CallOpts, arg0 [32]byte, arg1 common.Address) (*big.Int, error) { + var out []interface{} + err := _RewardManager.contract.Call(opts, &out, "s_totalRewardRecipientFeesLastClaimedAmounts", arg0, arg1) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_RewardManager *RewardManagerSession) STotalRewardRecipientFeesLastClaimedAmounts(arg0 [32]byte, arg1 common.Address) (*big.Int, error) { + return _RewardManager.Contract.STotalRewardRecipientFeesLastClaimedAmounts(&_RewardManager.CallOpts, arg0, arg1) +} + +func (_RewardManager *RewardManagerCallerSession) STotalRewardRecipientFeesLastClaimedAmounts(arg0 [32]byte, arg1 common.Address) (*big.Int, error) { + return _RewardManager.Contract.STotalRewardRecipientFeesLastClaimedAmounts(&_RewardManager.CallOpts, arg0, arg1) +} + +func (_RewardManager *RewardManagerCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + var out []interface{} + err := _RewardManager.contract.Call(opts, &out, "supportsInterface", interfaceId) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_RewardManager *RewardManagerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _RewardManager.Contract.SupportsInterface(&_RewardManager.CallOpts, interfaceId) +} + +func (_RewardManager *RewardManagerCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _RewardManager.Contract.SupportsInterface(&_RewardManager.CallOpts, interfaceId) +} + +func (_RewardManager *RewardManagerCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _RewardManager.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_RewardManager *RewardManagerSession) TypeAndVersion() (string, error) { + return _RewardManager.Contract.TypeAndVersion(&_RewardManager.CallOpts) +} + +func (_RewardManager *RewardManagerCallerSession) TypeAndVersion() (string, error) { + return _RewardManager.Contract.TypeAndVersion(&_RewardManager.CallOpts) +} + +func (_RewardManager *RewardManagerTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _RewardManager.contract.Transact(opts, "acceptOwnership") +} + +func (_RewardManager *RewardManagerSession) AcceptOwnership() (*types.Transaction, error) { + return _RewardManager.Contract.AcceptOwnership(&_RewardManager.TransactOpts) +} + +func (_RewardManager *RewardManagerTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _RewardManager.Contract.AcceptOwnership(&_RewardManager.TransactOpts) +} + +func (_RewardManager *RewardManagerTransactor) ClaimRewards(opts *bind.TransactOpts, poolIds [][32]byte) (*types.Transaction, error) { + return _RewardManager.contract.Transact(opts, "claimRewards", poolIds) +} + +func (_RewardManager *RewardManagerSession) ClaimRewards(poolIds [][32]byte) (*types.Transaction, error) { + return _RewardManager.Contract.ClaimRewards(&_RewardManager.TransactOpts, poolIds) +} + +func (_RewardManager *RewardManagerTransactorSession) ClaimRewards(poolIds [][32]byte) (*types.Transaction, error) { + return _RewardManager.Contract.ClaimRewards(&_RewardManager.TransactOpts, poolIds) +} + +func (_RewardManager *RewardManagerTransactor) OnFeePaid(opts *bind.TransactOpts, payments []IRewardManagerFeePayment, payer common.Address) (*types.Transaction, error) { + return _RewardManager.contract.Transact(opts, "onFeePaid", payments, payer) +} + +func (_RewardManager *RewardManagerSession) OnFeePaid(payments []IRewardManagerFeePayment, payer common.Address) (*types.Transaction, error) { + return _RewardManager.Contract.OnFeePaid(&_RewardManager.TransactOpts, payments, payer) +} + +func (_RewardManager *RewardManagerTransactorSession) OnFeePaid(payments []IRewardManagerFeePayment, payer common.Address) (*types.Transaction, error) { + return _RewardManager.Contract.OnFeePaid(&_RewardManager.TransactOpts, payments, payer) +} + +func (_RewardManager *RewardManagerTransactor) PayRecipients(opts *bind.TransactOpts, poolId [32]byte, recipients []common.Address) (*types.Transaction, error) { + return _RewardManager.contract.Transact(opts, "payRecipients", poolId, recipients) +} + +func (_RewardManager *RewardManagerSession) PayRecipients(poolId [32]byte, recipients []common.Address) (*types.Transaction, error) { + return _RewardManager.Contract.PayRecipients(&_RewardManager.TransactOpts, poolId, recipients) +} + +func (_RewardManager *RewardManagerTransactorSession) PayRecipients(poolId [32]byte, recipients []common.Address) (*types.Transaction, error) { + return _RewardManager.Contract.PayRecipients(&_RewardManager.TransactOpts, poolId, recipients) +} + +func (_RewardManager *RewardManagerTransactor) SetFeeManager(opts *bind.TransactOpts, newFeeManagerAddress common.Address) (*types.Transaction, error) { + return _RewardManager.contract.Transact(opts, "setFeeManager", newFeeManagerAddress) +} + +func (_RewardManager *RewardManagerSession) SetFeeManager(newFeeManagerAddress common.Address) (*types.Transaction, error) { + return _RewardManager.Contract.SetFeeManager(&_RewardManager.TransactOpts, newFeeManagerAddress) +} + +func (_RewardManager *RewardManagerTransactorSession) SetFeeManager(newFeeManagerAddress common.Address) (*types.Transaction, error) { + return _RewardManager.Contract.SetFeeManager(&_RewardManager.TransactOpts, newFeeManagerAddress) +} + +func (_RewardManager *RewardManagerTransactor) SetRewardRecipients(opts *bind.TransactOpts, poolId [32]byte, rewardRecipientAndWeights []CommonAddressAndWeight) (*types.Transaction, error) { + return _RewardManager.contract.Transact(opts, "setRewardRecipients", poolId, rewardRecipientAndWeights) +} + +func (_RewardManager *RewardManagerSession) SetRewardRecipients(poolId [32]byte, rewardRecipientAndWeights []CommonAddressAndWeight) (*types.Transaction, error) { + return _RewardManager.Contract.SetRewardRecipients(&_RewardManager.TransactOpts, poolId, rewardRecipientAndWeights) +} + +func (_RewardManager *RewardManagerTransactorSession) SetRewardRecipients(poolId [32]byte, rewardRecipientAndWeights []CommonAddressAndWeight) (*types.Transaction, error) { + return _RewardManager.Contract.SetRewardRecipients(&_RewardManager.TransactOpts, poolId, rewardRecipientAndWeights) +} + +func (_RewardManager *RewardManagerTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _RewardManager.contract.Transact(opts, "transferOwnership", to) +} + +func (_RewardManager *RewardManagerSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _RewardManager.Contract.TransferOwnership(&_RewardManager.TransactOpts, to) +} + +func (_RewardManager *RewardManagerTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _RewardManager.Contract.TransferOwnership(&_RewardManager.TransactOpts, to) +} + +func (_RewardManager *RewardManagerTransactor) UpdateRewardRecipients(opts *bind.TransactOpts, poolId [32]byte, newRewardRecipients []CommonAddressAndWeight) (*types.Transaction, error) { + return _RewardManager.contract.Transact(opts, "updateRewardRecipients", poolId, newRewardRecipients) +} + +func (_RewardManager *RewardManagerSession) UpdateRewardRecipients(poolId [32]byte, newRewardRecipients []CommonAddressAndWeight) (*types.Transaction, error) { + return _RewardManager.Contract.UpdateRewardRecipients(&_RewardManager.TransactOpts, poolId, newRewardRecipients) +} + +func (_RewardManager *RewardManagerTransactorSession) UpdateRewardRecipients(poolId [32]byte, newRewardRecipients []CommonAddressAndWeight) (*types.Transaction, error) { + return _RewardManager.Contract.UpdateRewardRecipients(&_RewardManager.TransactOpts, poolId, newRewardRecipients) +} + +type RewardManagerFeeManagerUpdatedIterator struct { + Event *RewardManagerFeeManagerUpdated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *RewardManagerFeeManagerUpdatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(RewardManagerFeeManagerUpdated) + 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(RewardManagerFeeManagerUpdated) + 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 *RewardManagerFeeManagerUpdatedIterator) Error() error { + return it.fail +} + +func (it *RewardManagerFeeManagerUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type RewardManagerFeeManagerUpdated struct { + NewFeeManagerAddress common.Address + Raw types.Log +} + +func (_RewardManager *RewardManagerFilterer) FilterFeeManagerUpdated(opts *bind.FilterOpts) (*RewardManagerFeeManagerUpdatedIterator, error) { + + logs, sub, err := _RewardManager.contract.FilterLogs(opts, "FeeManagerUpdated") + if err != nil { + return nil, err + } + return &RewardManagerFeeManagerUpdatedIterator{contract: _RewardManager.contract, event: "FeeManagerUpdated", logs: logs, sub: sub}, nil +} + +func (_RewardManager *RewardManagerFilterer) WatchFeeManagerUpdated(opts *bind.WatchOpts, sink chan<- *RewardManagerFeeManagerUpdated) (event.Subscription, error) { + + logs, sub, err := _RewardManager.contract.WatchLogs(opts, "FeeManagerUpdated") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(RewardManagerFeeManagerUpdated) + if err := _RewardManager.contract.UnpackLog(event, "FeeManagerUpdated", 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 (_RewardManager *RewardManagerFilterer) ParseFeeManagerUpdated(log types.Log) (*RewardManagerFeeManagerUpdated, error) { + event := new(RewardManagerFeeManagerUpdated) + if err := _RewardManager.contract.UnpackLog(event, "FeeManagerUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type RewardManagerFeePaidIterator struct { + Event *RewardManagerFeePaid + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *RewardManagerFeePaidIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(RewardManagerFeePaid) + 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(RewardManagerFeePaid) + 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 *RewardManagerFeePaidIterator) Error() error { + return it.fail +} + +func (it *RewardManagerFeePaidIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type RewardManagerFeePaid struct { + Payments []IRewardManagerFeePayment + Payer common.Address + Raw types.Log +} + +func (_RewardManager *RewardManagerFilterer) FilterFeePaid(opts *bind.FilterOpts) (*RewardManagerFeePaidIterator, error) { + + logs, sub, err := _RewardManager.contract.FilterLogs(opts, "FeePaid") + if err != nil { + return nil, err + } + return &RewardManagerFeePaidIterator{contract: _RewardManager.contract, event: "FeePaid", logs: logs, sub: sub}, nil +} + +func (_RewardManager *RewardManagerFilterer) WatchFeePaid(opts *bind.WatchOpts, sink chan<- *RewardManagerFeePaid) (event.Subscription, error) { + + logs, sub, err := _RewardManager.contract.WatchLogs(opts, "FeePaid") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(RewardManagerFeePaid) + if err := _RewardManager.contract.UnpackLog(event, "FeePaid", 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 (_RewardManager *RewardManagerFilterer) ParseFeePaid(log types.Log) (*RewardManagerFeePaid, error) { + event := new(RewardManagerFeePaid) + if err := _RewardManager.contract.UnpackLog(event, "FeePaid", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type RewardManagerOwnershipTransferRequestedIterator struct { + Event *RewardManagerOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *RewardManagerOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(RewardManagerOwnershipTransferRequested) + 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(RewardManagerOwnershipTransferRequested) + 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 *RewardManagerOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *RewardManagerOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type RewardManagerOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_RewardManager *RewardManagerFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RewardManagerOwnershipTransferRequestedIterator, 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 := _RewardManager.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &RewardManagerOwnershipTransferRequestedIterator{contract: _RewardManager.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_RewardManager *RewardManagerFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *RewardManagerOwnershipTransferRequested, 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 := _RewardManager.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(RewardManagerOwnershipTransferRequested) + if err := _RewardManager.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 (_RewardManager *RewardManagerFilterer) ParseOwnershipTransferRequested(log types.Log) (*RewardManagerOwnershipTransferRequested, error) { + event := new(RewardManagerOwnershipTransferRequested) + if err := _RewardManager.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type RewardManagerOwnershipTransferredIterator struct { + Event *RewardManagerOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *RewardManagerOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(RewardManagerOwnershipTransferred) + 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(RewardManagerOwnershipTransferred) + 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 *RewardManagerOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *RewardManagerOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type RewardManagerOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_RewardManager *RewardManagerFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RewardManagerOwnershipTransferredIterator, 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 := _RewardManager.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &RewardManagerOwnershipTransferredIterator{contract: _RewardManager.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_RewardManager *RewardManagerFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *RewardManagerOwnershipTransferred, 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 := _RewardManager.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(RewardManagerOwnershipTransferred) + if err := _RewardManager.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 (_RewardManager *RewardManagerFilterer) ParseOwnershipTransferred(log types.Log) (*RewardManagerOwnershipTransferred, error) { + event := new(RewardManagerOwnershipTransferred) + if err := _RewardManager.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type RewardManagerRewardRecipientsUpdatedIterator struct { + Event *RewardManagerRewardRecipientsUpdated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *RewardManagerRewardRecipientsUpdatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(RewardManagerRewardRecipientsUpdated) + 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(RewardManagerRewardRecipientsUpdated) + 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 *RewardManagerRewardRecipientsUpdatedIterator) Error() error { + return it.fail +} + +func (it *RewardManagerRewardRecipientsUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type RewardManagerRewardRecipientsUpdated struct { + PoolId [32]byte + NewRewardRecipients []CommonAddressAndWeight + Raw types.Log +} + +func (_RewardManager *RewardManagerFilterer) FilterRewardRecipientsUpdated(opts *bind.FilterOpts, poolId [][32]byte) (*RewardManagerRewardRecipientsUpdatedIterator, error) { + + var poolIdRule []interface{} + for _, poolIdItem := range poolId { + poolIdRule = append(poolIdRule, poolIdItem) + } + + logs, sub, err := _RewardManager.contract.FilterLogs(opts, "RewardRecipientsUpdated", poolIdRule) + if err != nil { + return nil, err + } + return &RewardManagerRewardRecipientsUpdatedIterator{contract: _RewardManager.contract, event: "RewardRecipientsUpdated", logs: logs, sub: sub}, nil +} + +func (_RewardManager *RewardManagerFilterer) WatchRewardRecipientsUpdated(opts *bind.WatchOpts, sink chan<- *RewardManagerRewardRecipientsUpdated, poolId [][32]byte) (event.Subscription, error) { + + var poolIdRule []interface{} + for _, poolIdItem := range poolId { + poolIdRule = append(poolIdRule, poolIdItem) + } + + logs, sub, err := _RewardManager.contract.WatchLogs(opts, "RewardRecipientsUpdated", poolIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(RewardManagerRewardRecipientsUpdated) + if err := _RewardManager.contract.UnpackLog(event, "RewardRecipientsUpdated", 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 (_RewardManager *RewardManagerFilterer) ParseRewardRecipientsUpdated(log types.Log) (*RewardManagerRewardRecipientsUpdated, error) { + event := new(RewardManagerRewardRecipientsUpdated) + if err := _RewardManager.contract.UnpackLog(event, "RewardRecipientsUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type RewardManagerRewardsClaimedIterator struct { + Event *RewardManagerRewardsClaimed + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *RewardManagerRewardsClaimedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(RewardManagerRewardsClaimed) + 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(RewardManagerRewardsClaimed) + 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 *RewardManagerRewardsClaimedIterator) Error() error { + return it.fail +} + +func (it *RewardManagerRewardsClaimedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type RewardManagerRewardsClaimed struct { + PoolId [32]byte + Recipient common.Address + Quantity *big.Int + Raw types.Log +} + +func (_RewardManager *RewardManagerFilterer) FilterRewardsClaimed(opts *bind.FilterOpts, poolId [][32]byte, recipient []common.Address) (*RewardManagerRewardsClaimedIterator, error) { + + var poolIdRule []interface{} + for _, poolIdItem := range poolId { + poolIdRule = append(poolIdRule, poolIdItem) + } + var recipientRule []interface{} + for _, recipientItem := range recipient { + recipientRule = append(recipientRule, recipientItem) + } + + logs, sub, err := _RewardManager.contract.FilterLogs(opts, "RewardsClaimed", poolIdRule, recipientRule) + if err != nil { + return nil, err + } + return &RewardManagerRewardsClaimedIterator{contract: _RewardManager.contract, event: "RewardsClaimed", logs: logs, sub: sub}, nil +} + +func (_RewardManager *RewardManagerFilterer) WatchRewardsClaimed(opts *bind.WatchOpts, sink chan<- *RewardManagerRewardsClaimed, poolId [][32]byte, recipient []common.Address) (event.Subscription, error) { + + var poolIdRule []interface{} + for _, poolIdItem := range poolId { + poolIdRule = append(poolIdRule, poolIdItem) + } + var recipientRule []interface{} + for _, recipientItem := range recipient { + recipientRule = append(recipientRule, recipientItem) + } + + logs, sub, err := _RewardManager.contract.WatchLogs(opts, "RewardsClaimed", poolIdRule, recipientRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(RewardManagerRewardsClaimed) + if err := _RewardManager.contract.UnpackLog(event, "RewardsClaimed", 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 (_RewardManager *RewardManagerFilterer) ParseRewardsClaimed(log types.Log) (*RewardManagerRewardsClaimed, error) { + event := new(RewardManagerRewardsClaimed) + if err := _RewardManager.contract.UnpackLog(event, "RewardsClaimed", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_RewardManager *RewardManager) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _RewardManager.abi.Events["FeeManagerUpdated"].ID: + return _RewardManager.ParseFeeManagerUpdated(log) + case _RewardManager.abi.Events["FeePaid"].ID: + return _RewardManager.ParseFeePaid(log) + case _RewardManager.abi.Events["OwnershipTransferRequested"].ID: + return _RewardManager.ParseOwnershipTransferRequested(log) + case _RewardManager.abi.Events["OwnershipTransferred"].ID: + return _RewardManager.ParseOwnershipTransferred(log) + case _RewardManager.abi.Events["RewardRecipientsUpdated"].ID: + return _RewardManager.ParseRewardRecipientsUpdated(log) + case _RewardManager.abi.Events["RewardsClaimed"].ID: + return _RewardManager.ParseRewardsClaimed(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (RewardManagerFeeManagerUpdated) Topic() common.Hash { + return common.HexToHash("0xe45f5e140399b0a7e12971ab020724b828fbed8ac408c420884dc7d1bbe506b4") +} + +func (RewardManagerFeePaid) Topic() common.Hash { + return common.HexToHash("0xa1cc025ea76bacce5d740ee4bc331899375dc2c5f2ab33933aaacbd9ba001b66") +} + +func (RewardManagerOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (RewardManagerOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (RewardManagerRewardRecipientsUpdated) Topic() common.Hash { + return common.HexToHash("0x8f668d6090683f98b3373a8b83d214da45737f7486cb7de554cc07b54e61cfe6") +} + +func (RewardManagerRewardsClaimed) Topic() common.Hash { + return common.HexToHash("0x989969655bc1d593922527fe85d71347bb8e12fa423cc71f362dd8ef7cb10ef2") +} + +func (_RewardManager *RewardManager) Address() common.Address { + return _RewardManager.address +} + +type RewardManagerInterface interface { + GetAvailableRewardPoolIds(opts *bind.CallOpts, recipient common.Address, startIndex *big.Int, endIndex *big.Int) ([][32]byte, error) + + ILinkAddress(opts *bind.CallOpts) (common.Address, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + SFeeManagerAddress(opts *bind.CallOpts) (common.Address, error) + + SRegisteredPoolIds(opts *bind.CallOpts, arg0 *big.Int) ([32]byte, error) + + SRewardRecipientWeights(opts *bind.CallOpts, arg0 [32]byte, arg1 common.Address) (*big.Int, error) + + SRewardRecipientWeightsSet(opts *bind.CallOpts, arg0 [32]byte) (bool, error) + + STotalRewardRecipientFees(opts *bind.CallOpts, arg0 [32]byte) (*big.Int, error) + + STotalRewardRecipientFeesLastClaimedAmounts(opts *bind.CallOpts, arg0 [32]byte, arg1 common.Address) (*big.Int, error) + + SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) + + TypeAndVersion(opts *bind.CallOpts) (string, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + ClaimRewards(opts *bind.TransactOpts, poolIds [][32]byte) (*types.Transaction, error) + + OnFeePaid(opts *bind.TransactOpts, payments []IRewardManagerFeePayment, payer common.Address) (*types.Transaction, error) + + PayRecipients(opts *bind.TransactOpts, poolId [32]byte, recipients []common.Address) (*types.Transaction, error) + + SetFeeManager(opts *bind.TransactOpts, newFeeManagerAddress common.Address) (*types.Transaction, error) + + SetRewardRecipients(opts *bind.TransactOpts, poolId [32]byte, rewardRecipientAndWeights []CommonAddressAndWeight) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + UpdateRewardRecipients(opts *bind.TransactOpts, poolId [32]byte, newRewardRecipients []CommonAddressAndWeight) (*types.Transaction, error) + + FilterFeeManagerUpdated(opts *bind.FilterOpts) (*RewardManagerFeeManagerUpdatedIterator, error) + + WatchFeeManagerUpdated(opts *bind.WatchOpts, sink chan<- *RewardManagerFeeManagerUpdated) (event.Subscription, error) + + ParseFeeManagerUpdated(log types.Log) (*RewardManagerFeeManagerUpdated, error) + + FilterFeePaid(opts *bind.FilterOpts) (*RewardManagerFeePaidIterator, error) + + WatchFeePaid(opts *bind.WatchOpts, sink chan<- *RewardManagerFeePaid) (event.Subscription, error) + + ParseFeePaid(log types.Log) (*RewardManagerFeePaid, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RewardManagerOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *RewardManagerOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*RewardManagerOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RewardManagerOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *RewardManagerOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*RewardManagerOwnershipTransferred, error) + + FilterRewardRecipientsUpdated(opts *bind.FilterOpts, poolId [][32]byte) (*RewardManagerRewardRecipientsUpdatedIterator, error) + + WatchRewardRecipientsUpdated(opts *bind.WatchOpts, sink chan<- *RewardManagerRewardRecipientsUpdated, poolId [][32]byte) (event.Subscription, error) + + ParseRewardRecipientsUpdated(log types.Log) (*RewardManagerRewardRecipientsUpdated, error) + + FilterRewardsClaimed(opts *bind.FilterOpts, poolId [][32]byte, recipient []common.Address) (*RewardManagerRewardsClaimedIterator, error) + + WatchRewardsClaimed(opts *bind.WatchOpts, sink chan<- *RewardManagerRewardsClaimed, poolId [][32]byte, recipient []common.Address) (event.Subscription, error) + + ParseRewardsClaimed(log types.Log) (*RewardManagerRewardsClaimed, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/llo-feeds/generated/verifier_proxy_v0_5_0/verifier_proxy_v0_5_0.go b/core/gethwrappers/llo-feeds/generated/verifier_proxy_v0_5_0/verifier_proxy_v0_5_0.go new file mode 100644 index 00000000000..606c30017dd --- /dev/null +++ b/core/gethwrappers/llo-feeds/generated/verifier_proxy_v0_5_0/verifier_proxy_v0_5_0.go @@ -0,0 +1,1387 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package verifier_proxy_v0_5_0 + +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 +) + +type CommonAddressAndWeight struct { + Addr common.Address + Weight uint64 +} + +var VerifierProxyMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"contractAccessControllerInterface\",\"name\":\"accessController\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AccessForbidden\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BadVerification\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"verifier\",\"type\":\"address\"}],\"name\":\"ConfigDigestAlreadySet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FeeManagerInvalid\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"verifier\",\"type\":\"address\"}],\"name\":\"VerifierAlreadyInitialized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"VerifierInvalid\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"VerifierNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddress\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessController\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessController\",\"type\":\"address\"}],\"name\":\"AccessControllerSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldFeeManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newFeeManager\",\"type\":\"address\"}],\"name\":\"FeeManagerSet\",\"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\":\"verifierAddress\",\"type\":\"address\"}],\"name\":\"VerifierInitialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"oldConfigDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"newConfigDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"verifierAddress\",\"type\":\"address\"}],\"name\":\"VerifierSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"verifierAddress\",\"type\":\"address\"}],\"name\":\"VerifierUnset\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"getVerifier\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"verifierAddress\",\"type\":\"address\"}],\"name\":\"initializeVerifier\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_accessController\",\"outputs\":[{\"internalType\":\"contractAccessControllerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_feeManager\",\"outputs\":[{\"internalType\":\"contractIVerifierFeeManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractAccessControllerInterface\",\"name\":\"accessController\",\"type\":\"address\"}],\"name\":\"setAccessController\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIVerifierFeeManager\",\"name\":\"feeManager\",\"type\":\"address\"}],\"name\":\"setFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"currentConfigDigest\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"newConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"weight\",\"type\":\"uint64\"}],\"internalType\":\"structCommon.AddressAndWeight[]\",\"name\":\"addressesAndWeights\",\"type\":\"tuple[]\"}],\"name\":\"setVerifier\",\"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\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"unsetVerifier\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"parameterPayload\",\"type\":\"bytes\"}],\"name\":\"verify\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"payloads\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"parameterPayload\",\"type\":\"bytes\"}],\"name\":\"verifyBulk\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"verifiedReports\",\"type\":\"bytes[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + Bin: "0x60806040523480156200001157600080fd5b5060405162001d3638038062001d36833981016040819052620000349162000193565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000e8565b5050600480546001600160a01b0319166001600160a01b03939093169290921790915550620001c5565b336001600160a01b03821603620001425760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215620001a657600080fd5b81516001600160a01b0381168114620001be57600080fd5b9392505050565b611b6180620001d56000396000f3fe6080604052600436106100dd5760003560e01c806394ba28461161007f578063f08391d811610059578063f08391d8146102be578063f2fde38b146102de578063f7e83aee146102fe578063f873a61c1461031157600080fd5b806394ba28461461022e578063b011b2471461025b578063eeb7b2481461027b57600080fd5b80636e914094116100bb5780636e914094146101ae57806379ba5097146101ce5780638c2a4d53146101e35780638da5cb5b1461020357600080fd5b8063181f5a77146100e257806338416b5b1461013a578063472d35b91461018c575b600080fd5b3480156100ee57600080fd5b5060408051808201909152601381527f566572696669657250726f787920322e302e300000000000000000000000000060208201525b60405161013191906113c3565b60405180910390f35b34801561014657600080fd5b506005546101679073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610131565b34801561019857600080fd5b506101ac6101a73660046113ff565b610331565b005b3480156101ba57600080fd5b506101ac6101c936600461141c565b6105a9565b3480156101da57600080fd5b506101ac61069a565b3480156101ef57600080fd5b506101ac6101fe3660046113ff565b610797565b34801561020f57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610167565b34801561023a57600080fd5b506004546101679073ffffffffffffffffffffffffffffffffffffffff1681565b34801561026757600080fd5b506101ac610276366004611435565b6109c8565b34801561028757600080fd5b5061016761029636600461141c565b60009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b3480156102ca57600080fd5b506101ac6102d93660046113ff565b610bee565b3480156102ea57600080fd5b506101ac6102f93660046113ff565b610c75565b61012461030c366004611501565b610c89565b61032461031f36600461156d565b610e43565b60405161013191906115ee565b6103396110a7565b73ffffffffffffffffffffffffffffffffffffffff8116610386576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527fdba45fe000000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015610410573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610434919061166e565b15806104eb57506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f6c2f1a1700000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa1580156104c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104e9919061166e565b155b15610522576040517f8238941900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f04628abcaa6b1674651352125cb94b65b289145bc2bc4d67720bb7d966372f0391015b60405180910390a15050565b6105b16110a7565b60008181526003602052604090205473ffffffffffffffffffffffffffffffffffffffff1680610615576040517fb151802b000000000000000000000000000000000000000000000000000000008152600481018390526024015b60405180910390fd5b6000828152600360205260409081902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055517f11dc15c4b8ac2b183166cc8427e5385a5ece8308217a4217338c6a7614845c4c9061059d908490849091825273ffffffffffffffffffffffffffffffffffffffff16602082015260400190565b60015473ffffffffffffffffffffffffffffffffffffffff16331461071b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161060c565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61079f6110a7565b8073ffffffffffffffffffffffffffffffffffffffff81166107ed576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f3d3ac1b500000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015610877573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061089b919061166e565b6108d1576040517f75b0527a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821660009081526002602052604090205460ff1615610949576040517f4e01ccfd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015260240161060c565b73ffffffffffffffffffffffffffffffffffffffff821660008181526002602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590519182527f1f2cd7c97f4d801b5efe26cc409617c1fd6c5ef786e79aacb90af40923e4e8e9910161059d565b600083815260036020526040902054839073ffffffffffffffffffffffffffffffffffffffff168015610a46576040517f375d1fe60000000000000000000000000000000000000000000000000000000081526004810183905273ffffffffffffffffffffffffffffffffffffffff8216602482015260440161060c565b3360009081526002602052604090205460ff16610a8f576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600085815260036020526040902080547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790558215610ba75760055473ffffffffffffffffffffffffffffffffffffffff16610b1a576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005546040517ff65df96200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063f65df96290610b7490889088908890600401611690565b600060405180830381600087803b158015610b8e57600080fd5b505af1158015610ba2573d6000803e3d6000fd5b505050505b6040805187815260208101879052338183015290517fbeb513e532542a562ac35699e7cd9ae7d198dcd3eee15bada6c857d28ceaddcf9181900360600190a1505050505050565b610bf66110a7565b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f953e92b1a6442e9c3242531154a3f6f6eb00b4e9c719ba8118fa6235e4ce89b6910161059d565b610c7d6110a7565b610c868161112a565b50565b60045460609073ffffffffffffffffffffffffffffffffffffffff168015801590610d4957506040517f6b14daf800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821690636b14daf890610d069033906000903690600401611762565b602060405180830381865afa158015610d23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d47919061166e565b155b15610d80576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60055473ffffffffffffffffffffffffffffffffffffffff168015610e2e576040517fdba45fe000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063dba45fe0903490610dfb908b908b908b908b90339060040161179b565b6000604051808303818588803b158015610e1457600080fd5b505af1158015610e28573d6000803e3d6000fd5b50505050505b610e38878761121f565b979650505050505050565b60045460609073ffffffffffffffffffffffffffffffffffffffff168015801590610f0357506040517f6b14daf800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821690636b14daf890610ec09033906000903690600401611762565b602060405180830381865afa158015610edd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f01919061166e565b155b15610f3a576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60055473ffffffffffffffffffffffffffffffffffffffff168015610fe8576040517f6c2f1a1700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821690636c2f1a17903490610fb5908b908b908b908b9033906004016117eb565b6000604051808303818588803b158015610fce57600080fd5b505af1158015610fe2573d6000803e3d6000fd5b50505050505b8567ffffffffffffffff811115611001576110016118fc565b60405190808252806020026020018201604052801561103457816020015b606081526020019060019003908161101f5790505b50925060005b8681101561109c5761106e8888838181106110575761105761192b565b9050602002810190611069919061195a565b61121f565b8482815181106110805761108061192b565b602002602001018190525080611095906119bf565b905061103a565b505050949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611128576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161060c565b565b3373ffffffffffffffffffffffffffffffffffffffff8216036111a9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161060c565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6060600061122d8385611a1e565b60008181526003602052604090205490915073ffffffffffffffffffffffffffffffffffffffff168061128f576040517fb151802b0000000000000000000000000000000000000000000000000000000081526004810183905260240161060c565b6040517f3d3ac1b500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821690633d3ac1b5906112e590889088903390600401611a5a565b6000604051808303816000875af1158015611304573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261134a9190810190611a94565b925050505b92915050565b60005b83811015611370578181015183820152602001611358565b50506000910152565b60008151808452611391816020860160208601611355565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006113d66020830184611379565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610c8657600080fd5b60006020828403121561141157600080fd5b81356113d6816113dd565b60006020828403121561142e57600080fd5b5035919050565b6000806000806060858703121561144b57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561147157600080fd5b818701915087601f83011261148557600080fd5b81358181111561149457600080fd5b8860208260061b85010111156114a957600080fd5b95989497505060200194505050565b60008083601f8401126114ca57600080fd5b50813567ffffffffffffffff8111156114e257600080fd5b6020830191508360208285010111156114fa57600080fd5b9250929050565b6000806000806040858703121561151757600080fd5b843567ffffffffffffffff8082111561152f57600080fd5b61153b888389016114b8565b9096509450602087013591508082111561155457600080fd5b50611561878288016114b8565b95989497509550505050565b6000806000806040858703121561158357600080fd5b843567ffffffffffffffff8082111561159b57600080fd5b818701915087601f8301126115af57600080fd5b8135818111156115be57600080fd5b8860208260051b85010111156115d357600080fd5b60209283019650945090860135908082111561155457600080fd5b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015611661577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261164f858351611379565b94509285019290850190600101611615565b5092979650505050505050565b60006020828403121561168057600080fd5b815180151581146113d657600080fd5b838152604060208083018290528282018490526000919085906060850184805b8881101561170a5784356116c3816113dd565b73ffffffffffffffffffffffffffffffffffffffff1683528484013567ffffffffffffffff81168082146116f5578384fd5b848601525093850193918501916001016116b0565b50909998505050505050505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff84168152604060208201526000611792604083018486611719565b95945050505050565b6060815260006117af606083018789611719565b82810360208401526117c2818688611719565b91505073ffffffffffffffffffffffffffffffffffffffff831660408301529695505050505050565b6060808252810185905260006080600587901b8301810190830188835b898110156118b7577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8086850301835281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18c360301811261186957600080fd5b8b01602081810191359067ffffffffffffffff82111561188857600080fd5b81360383131561189757600080fd5b6118a2878385611719565b96509485019493909301925050600101611808565b50505082810360208401526118cd818688611719565b9150506118f2604083018473ffffffffffffffffffffffffffffffffffffffff169052565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261198f57600080fd5b83018035915067ffffffffffffffff8211156119aa57600080fd5b6020019150368190038213156114fa57600080fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611a17577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b8035602083101561134f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b604081526000611a6e604083018587611719565b905073ffffffffffffffffffffffffffffffffffffffff83166020830152949350505050565b600060208284031215611aa657600080fd5b815167ffffffffffffffff80821115611abe57600080fd5b818401915084601f830112611ad257600080fd5b815181811115611ae457611ae46118fc565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611b2a57611b2a6118fc565b81604052828152876020848701011115611b4357600080fd5b610e3883602083016020880161135556fea164736f6c6343000813000a", +} + +var VerifierProxyABI = VerifierProxyMetaData.ABI + +var VerifierProxyBin = VerifierProxyMetaData.Bin + +func DeployVerifierProxy(auth *bind.TransactOpts, backend bind.ContractBackend, accessController common.Address) (common.Address, *types.Transaction, *VerifierProxy, error) { + parsed, err := VerifierProxyMetaData.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(VerifierProxyBin), backend, accessController) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &VerifierProxy{address: address, abi: *parsed, VerifierProxyCaller: VerifierProxyCaller{contract: contract}, VerifierProxyTransactor: VerifierProxyTransactor{contract: contract}, VerifierProxyFilterer: VerifierProxyFilterer{contract: contract}}, nil +} + +type VerifierProxy struct { + address common.Address + abi abi.ABI + VerifierProxyCaller + VerifierProxyTransactor + VerifierProxyFilterer +} + +type VerifierProxyCaller struct { + contract *bind.BoundContract +} + +type VerifierProxyTransactor struct { + contract *bind.BoundContract +} + +type VerifierProxyFilterer struct { + contract *bind.BoundContract +} + +type VerifierProxySession struct { + Contract *VerifierProxy + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type VerifierProxyCallerSession struct { + Contract *VerifierProxyCaller + CallOpts bind.CallOpts +} + +type VerifierProxyTransactorSession struct { + Contract *VerifierProxyTransactor + TransactOpts bind.TransactOpts +} + +type VerifierProxyRaw struct { + Contract *VerifierProxy +} + +type VerifierProxyCallerRaw struct { + Contract *VerifierProxyCaller +} + +type VerifierProxyTransactorRaw struct { + Contract *VerifierProxyTransactor +} + +func NewVerifierProxy(address common.Address, backend bind.ContractBackend) (*VerifierProxy, error) { + abi, err := abi.JSON(strings.NewReader(VerifierProxyABI)) + if err != nil { + return nil, err + } + contract, err := bindVerifierProxy(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &VerifierProxy{address: address, abi: abi, VerifierProxyCaller: VerifierProxyCaller{contract: contract}, VerifierProxyTransactor: VerifierProxyTransactor{contract: contract}, VerifierProxyFilterer: VerifierProxyFilterer{contract: contract}}, nil +} + +func NewVerifierProxyCaller(address common.Address, caller bind.ContractCaller) (*VerifierProxyCaller, error) { + contract, err := bindVerifierProxy(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &VerifierProxyCaller{contract: contract}, nil +} + +func NewVerifierProxyTransactor(address common.Address, transactor bind.ContractTransactor) (*VerifierProxyTransactor, error) { + contract, err := bindVerifierProxy(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &VerifierProxyTransactor{contract: contract}, nil +} + +func NewVerifierProxyFilterer(address common.Address, filterer bind.ContractFilterer) (*VerifierProxyFilterer, error) { + contract, err := bindVerifierProxy(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &VerifierProxyFilterer{contract: contract}, nil +} + +func bindVerifierProxy(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := VerifierProxyMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_VerifierProxy *VerifierProxyRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _VerifierProxy.Contract.VerifierProxyCaller.contract.Call(opts, result, method, params...) +} + +func (_VerifierProxy *VerifierProxyRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _VerifierProxy.Contract.VerifierProxyTransactor.contract.Transfer(opts) +} + +func (_VerifierProxy *VerifierProxyRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _VerifierProxy.Contract.VerifierProxyTransactor.contract.Transact(opts, method, params...) +} + +func (_VerifierProxy *VerifierProxyCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _VerifierProxy.Contract.contract.Call(opts, result, method, params...) +} + +func (_VerifierProxy *VerifierProxyTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _VerifierProxy.Contract.contract.Transfer(opts) +} + +func (_VerifierProxy *VerifierProxyTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _VerifierProxy.Contract.contract.Transact(opts, method, params...) +} + +func (_VerifierProxy *VerifierProxyCaller) GetVerifier(opts *bind.CallOpts, configDigest [32]byte) (common.Address, error) { + var out []interface{} + err := _VerifierProxy.contract.Call(opts, &out, "getVerifier", configDigest) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_VerifierProxy *VerifierProxySession) GetVerifier(configDigest [32]byte) (common.Address, error) { + return _VerifierProxy.Contract.GetVerifier(&_VerifierProxy.CallOpts, configDigest) +} + +func (_VerifierProxy *VerifierProxyCallerSession) GetVerifier(configDigest [32]byte) (common.Address, error) { + return _VerifierProxy.Contract.GetVerifier(&_VerifierProxy.CallOpts, configDigest) +} + +func (_VerifierProxy *VerifierProxyCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _VerifierProxy.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 (_VerifierProxy *VerifierProxySession) Owner() (common.Address, error) { + return _VerifierProxy.Contract.Owner(&_VerifierProxy.CallOpts) +} + +func (_VerifierProxy *VerifierProxyCallerSession) Owner() (common.Address, error) { + return _VerifierProxy.Contract.Owner(&_VerifierProxy.CallOpts) +} + +func (_VerifierProxy *VerifierProxyCaller) SAccessController(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _VerifierProxy.contract.Call(opts, &out, "s_accessController") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_VerifierProxy *VerifierProxySession) SAccessController() (common.Address, error) { + return _VerifierProxy.Contract.SAccessController(&_VerifierProxy.CallOpts) +} + +func (_VerifierProxy *VerifierProxyCallerSession) SAccessController() (common.Address, error) { + return _VerifierProxy.Contract.SAccessController(&_VerifierProxy.CallOpts) +} + +func (_VerifierProxy *VerifierProxyCaller) SFeeManager(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _VerifierProxy.contract.Call(opts, &out, "s_feeManager") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_VerifierProxy *VerifierProxySession) SFeeManager() (common.Address, error) { + return _VerifierProxy.Contract.SFeeManager(&_VerifierProxy.CallOpts) +} + +func (_VerifierProxy *VerifierProxyCallerSession) SFeeManager() (common.Address, error) { + return _VerifierProxy.Contract.SFeeManager(&_VerifierProxy.CallOpts) +} + +func (_VerifierProxy *VerifierProxyCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _VerifierProxy.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_VerifierProxy *VerifierProxySession) TypeAndVersion() (string, error) { + return _VerifierProxy.Contract.TypeAndVersion(&_VerifierProxy.CallOpts) +} + +func (_VerifierProxy *VerifierProxyCallerSession) TypeAndVersion() (string, error) { + return _VerifierProxy.Contract.TypeAndVersion(&_VerifierProxy.CallOpts) +} + +func (_VerifierProxy *VerifierProxyTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _VerifierProxy.contract.Transact(opts, "acceptOwnership") +} + +func (_VerifierProxy *VerifierProxySession) AcceptOwnership() (*types.Transaction, error) { + return _VerifierProxy.Contract.AcceptOwnership(&_VerifierProxy.TransactOpts) +} + +func (_VerifierProxy *VerifierProxyTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _VerifierProxy.Contract.AcceptOwnership(&_VerifierProxy.TransactOpts) +} + +func (_VerifierProxy *VerifierProxyTransactor) InitializeVerifier(opts *bind.TransactOpts, verifierAddress common.Address) (*types.Transaction, error) { + return _VerifierProxy.contract.Transact(opts, "initializeVerifier", verifierAddress) +} + +func (_VerifierProxy *VerifierProxySession) InitializeVerifier(verifierAddress common.Address) (*types.Transaction, error) { + return _VerifierProxy.Contract.InitializeVerifier(&_VerifierProxy.TransactOpts, verifierAddress) +} + +func (_VerifierProxy *VerifierProxyTransactorSession) InitializeVerifier(verifierAddress common.Address) (*types.Transaction, error) { + return _VerifierProxy.Contract.InitializeVerifier(&_VerifierProxy.TransactOpts, verifierAddress) +} + +func (_VerifierProxy *VerifierProxyTransactor) SetAccessController(opts *bind.TransactOpts, accessController common.Address) (*types.Transaction, error) { + return _VerifierProxy.contract.Transact(opts, "setAccessController", accessController) +} + +func (_VerifierProxy *VerifierProxySession) SetAccessController(accessController common.Address) (*types.Transaction, error) { + return _VerifierProxy.Contract.SetAccessController(&_VerifierProxy.TransactOpts, accessController) +} + +func (_VerifierProxy *VerifierProxyTransactorSession) SetAccessController(accessController common.Address) (*types.Transaction, error) { + return _VerifierProxy.Contract.SetAccessController(&_VerifierProxy.TransactOpts, accessController) +} + +func (_VerifierProxy *VerifierProxyTransactor) SetFeeManager(opts *bind.TransactOpts, feeManager common.Address) (*types.Transaction, error) { + return _VerifierProxy.contract.Transact(opts, "setFeeManager", feeManager) +} + +func (_VerifierProxy *VerifierProxySession) SetFeeManager(feeManager common.Address) (*types.Transaction, error) { + return _VerifierProxy.Contract.SetFeeManager(&_VerifierProxy.TransactOpts, feeManager) +} + +func (_VerifierProxy *VerifierProxyTransactorSession) SetFeeManager(feeManager common.Address) (*types.Transaction, error) { + return _VerifierProxy.Contract.SetFeeManager(&_VerifierProxy.TransactOpts, feeManager) +} + +func (_VerifierProxy *VerifierProxyTransactor) SetVerifier(opts *bind.TransactOpts, currentConfigDigest [32]byte, newConfigDigest [32]byte, addressesAndWeights []CommonAddressAndWeight) (*types.Transaction, error) { + return _VerifierProxy.contract.Transact(opts, "setVerifier", currentConfigDigest, newConfigDigest, addressesAndWeights) +} + +func (_VerifierProxy *VerifierProxySession) SetVerifier(currentConfigDigest [32]byte, newConfigDigest [32]byte, addressesAndWeights []CommonAddressAndWeight) (*types.Transaction, error) { + return _VerifierProxy.Contract.SetVerifier(&_VerifierProxy.TransactOpts, currentConfigDigest, newConfigDigest, addressesAndWeights) +} + +func (_VerifierProxy *VerifierProxyTransactorSession) SetVerifier(currentConfigDigest [32]byte, newConfigDigest [32]byte, addressesAndWeights []CommonAddressAndWeight) (*types.Transaction, error) { + return _VerifierProxy.Contract.SetVerifier(&_VerifierProxy.TransactOpts, currentConfigDigest, newConfigDigest, addressesAndWeights) +} + +func (_VerifierProxy *VerifierProxyTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _VerifierProxy.contract.Transact(opts, "transferOwnership", to) +} + +func (_VerifierProxy *VerifierProxySession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _VerifierProxy.Contract.TransferOwnership(&_VerifierProxy.TransactOpts, to) +} + +func (_VerifierProxy *VerifierProxyTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _VerifierProxy.Contract.TransferOwnership(&_VerifierProxy.TransactOpts, to) +} + +func (_VerifierProxy *VerifierProxyTransactor) UnsetVerifier(opts *bind.TransactOpts, configDigest [32]byte) (*types.Transaction, error) { + return _VerifierProxy.contract.Transact(opts, "unsetVerifier", configDigest) +} + +func (_VerifierProxy *VerifierProxySession) UnsetVerifier(configDigest [32]byte) (*types.Transaction, error) { + return _VerifierProxy.Contract.UnsetVerifier(&_VerifierProxy.TransactOpts, configDigest) +} + +func (_VerifierProxy *VerifierProxyTransactorSession) UnsetVerifier(configDigest [32]byte) (*types.Transaction, error) { + return _VerifierProxy.Contract.UnsetVerifier(&_VerifierProxy.TransactOpts, configDigest) +} + +func (_VerifierProxy *VerifierProxyTransactor) Verify(opts *bind.TransactOpts, payload []byte, parameterPayload []byte) (*types.Transaction, error) { + return _VerifierProxy.contract.Transact(opts, "verify", payload, parameterPayload) +} + +func (_VerifierProxy *VerifierProxySession) Verify(payload []byte, parameterPayload []byte) (*types.Transaction, error) { + return _VerifierProxy.Contract.Verify(&_VerifierProxy.TransactOpts, payload, parameterPayload) +} + +func (_VerifierProxy *VerifierProxyTransactorSession) Verify(payload []byte, parameterPayload []byte) (*types.Transaction, error) { + return _VerifierProxy.Contract.Verify(&_VerifierProxy.TransactOpts, payload, parameterPayload) +} + +func (_VerifierProxy *VerifierProxyTransactor) VerifyBulk(opts *bind.TransactOpts, payloads [][]byte, parameterPayload []byte) (*types.Transaction, error) { + return _VerifierProxy.contract.Transact(opts, "verifyBulk", payloads, parameterPayload) +} + +func (_VerifierProxy *VerifierProxySession) VerifyBulk(payloads [][]byte, parameterPayload []byte) (*types.Transaction, error) { + return _VerifierProxy.Contract.VerifyBulk(&_VerifierProxy.TransactOpts, payloads, parameterPayload) +} + +func (_VerifierProxy *VerifierProxyTransactorSession) VerifyBulk(payloads [][]byte, parameterPayload []byte) (*types.Transaction, error) { + return _VerifierProxy.Contract.VerifyBulk(&_VerifierProxy.TransactOpts, payloads, parameterPayload) +} + +type VerifierProxyAccessControllerSetIterator struct { + Event *VerifierProxyAccessControllerSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VerifierProxyAccessControllerSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VerifierProxyAccessControllerSet) + 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(VerifierProxyAccessControllerSet) + 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 *VerifierProxyAccessControllerSetIterator) Error() error { + return it.fail +} + +func (it *VerifierProxyAccessControllerSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VerifierProxyAccessControllerSet struct { + OldAccessController common.Address + NewAccessController common.Address + Raw types.Log +} + +func (_VerifierProxy *VerifierProxyFilterer) FilterAccessControllerSet(opts *bind.FilterOpts) (*VerifierProxyAccessControllerSetIterator, error) { + + logs, sub, err := _VerifierProxy.contract.FilterLogs(opts, "AccessControllerSet") + if err != nil { + return nil, err + } + return &VerifierProxyAccessControllerSetIterator{contract: _VerifierProxy.contract, event: "AccessControllerSet", logs: logs, sub: sub}, nil +} + +func (_VerifierProxy *VerifierProxyFilterer) WatchAccessControllerSet(opts *bind.WatchOpts, sink chan<- *VerifierProxyAccessControllerSet) (event.Subscription, error) { + + logs, sub, err := _VerifierProxy.contract.WatchLogs(opts, "AccessControllerSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VerifierProxyAccessControllerSet) + if err := _VerifierProxy.contract.UnpackLog(event, "AccessControllerSet", 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 (_VerifierProxy *VerifierProxyFilterer) ParseAccessControllerSet(log types.Log) (*VerifierProxyAccessControllerSet, error) { + event := new(VerifierProxyAccessControllerSet) + if err := _VerifierProxy.contract.UnpackLog(event, "AccessControllerSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VerifierProxyFeeManagerSetIterator struct { + Event *VerifierProxyFeeManagerSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VerifierProxyFeeManagerSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VerifierProxyFeeManagerSet) + 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(VerifierProxyFeeManagerSet) + 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 *VerifierProxyFeeManagerSetIterator) Error() error { + return it.fail +} + +func (it *VerifierProxyFeeManagerSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VerifierProxyFeeManagerSet struct { + OldFeeManager common.Address + NewFeeManager common.Address + Raw types.Log +} + +func (_VerifierProxy *VerifierProxyFilterer) FilterFeeManagerSet(opts *bind.FilterOpts) (*VerifierProxyFeeManagerSetIterator, error) { + + logs, sub, err := _VerifierProxy.contract.FilterLogs(opts, "FeeManagerSet") + if err != nil { + return nil, err + } + return &VerifierProxyFeeManagerSetIterator{contract: _VerifierProxy.contract, event: "FeeManagerSet", logs: logs, sub: sub}, nil +} + +func (_VerifierProxy *VerifierProxyFilterer) WatchFeeManagerSet(opts *bind.WatchOpts, sink chan<- *VerifierProxyFeeManagerSet) (event.Subscription, error) { + + logs, sub, err := _VerifierProxy.contract.WatchLogs(opts, "FeeManagerSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VerifierProxyFeeManagerSet) + if err := _VerifierProxy.contract.UnpackLog(event, "FeeManagerSet", 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 (_VerifierProxy *VerifierProxyFilterer) ParseFeeManagerSet(log types.Log) (*VerifierProxyFeeManagerSet, error) { + event := new(VerifierProxyFeeManagerSet) + if err := _VerifierProxy.contract.UnpackLog(event, "FeeManagerSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VerifierProxyOwnershipTransferRequestedIterator struct { + Event *VerifierProxyOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VerifierProxyOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VerifierProxyOwnershipTransferRequested) + 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(VerifierProxyOwnershipTransferRequested) + 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 *VerifierProxyOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *VerifierProxyOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VerifierProxyOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_VerifierProxy *VerifierProxyFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*VerifierProxyOwnershipTransferRequestedIterator, 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 := _VerifierProxy.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &VerifierProxyOwnershipTransferRequestedIterator{contract: _VerifierProxy.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_VerifierProxy *VerifierProxyFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *VerifierProxyOwnershipTransferRequested, 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 := _VerifierProxy.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(VerifierProxyOwnershipTransferRequested) + if err := _VerifierProxy.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 (_VerifierProxy *VerifierProxyFilterer) ParseOwnershipTransferRequested(log types.Log) (*VerifierProxyOwnershipTransferRequested, error) { + event := new(VerifierProxyOwnershipTransferRequested) + if err := _VerifierProxy.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VerifierProxyOwnershipTransferredIterator struct { + Event *VerifierProxyOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VerifierProxyOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VerifierProxyOwnershipTransferred) + 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(VerifierProxyOwnershipTransferred) + 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 *VerifierProxyOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *VerifierProxyOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VerifierProxyOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_VerifierProxy *VerifierProxyFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*VerifierProxyOwnershipTransferredIterator, 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 := _VerifierProxy.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &VerifierProxyOwnershipTransferredIterator{contract: _VerifierProxy.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_VerifierProxy *VerifierProxyFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *VerifierProxyOwnershipTransferred, 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 := _VerifierProxy.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(VerifierProxyOwnershipTransferred) + if err := _VerifierProxy.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 (_VerifierProxy *VerifierProxyFilterer) ParseOwnershipTransferred(log types.Log) (*VerifierProxyOwnershipTransferred, error) { + event := new(VerifierProxyOwnershipTransferred) + if err := _VerifierProxy.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VerifierProxyVerifierInitializedIterator struct { + Event *VerifierProxyVerifierInitialized + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VerifierProxyVerifierInitializedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VerifierProxyVerifierInitialized) + 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(VerifierProxyVerifierInitialized) + 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 *VerifierProxyVerifierInitializedIterator) Error() error { + return it.fail +} + +func (it *VerifierProxyVerifierInitializedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VerifierProxyVerifierInitialized struct { + VerifierAddress common.Address + Raw types.Log +} + +func (_VerifierProxy *VerifierProxyFilterer) FilterVerifierInitialized(opts *bind.FilterOpts) (*VerifierProxyVerifierInitializedIterator, error) { + + logs, sub, err := _VerifierProxy.contract.FilterLogs(opts, "VerifierInitialized") + if err != nil { + return nil, err + } + return &VerifierProxyVerifierInitializedIterator{contract: _VerifierProxy.contract, event: "VerifierInitialized", logs: logs, sub: sub}, nil +} + +func (_VerifierProxy *VerifierProxyFilterer) WatchVerifierInitialized(opts *bind.WatchOpts, sink chan<- *VerifierProxyVerifierInitialized) (event.Subscription, error) { + + logs, sub, err := _VerifierProxy.contract.WatchLogs(opts, "VerifierInitialized") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VerifierProxyVerifierInitialized) + if err := _VerifierProxy.contract.UnpackLog(event, "VerifierInitialized", 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 (_VerifierProxy *VerifierProxyFilterer) ParseVerifierInitialized(log types.Log) (*VerifierProxyVerifierInitialized, error) { + event := new(VerifierProxyVerifierInitialized) + if err := _VerifierProxy.contract.UnpackLog(event, "VerifierInitialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VerifierProxyVerifierSetIterator struct { + Event *VerifierProxyVerifierSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VerifierProxyVerifierSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VerifierProxyVerifierSet) + 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(VerifierProxyVerifierSet) + 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 *VerifierProxyVerifierSetIterator) Error() error { + return it.fail +} + +func (it *VerifierProxyVerifierSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VerifierProxyVerifierSet struct { + OldConfigDigest [32]byte + NewConfigDigest [32]byte + VerifierAddress common.Address + Raw types.Log +} + +func (_VerifierProxy *VerifierProxyFilterer) FilterVerifierSet(opts *bind.FilterOpts) (*VerifierProxyVerifierSetIterator, error) { + + logs, sub, err := _VerifierProxy.contract.FilterLogs(opts, "VerifierSet") + if err != nil { + return nil, err + } + return &VerifierProxyVerifierSetIterator{contract: _VerifierProxy.contract, event: "VerifierSet", logs: logs, sub: sub}, nil +} + +func (_VerifierProxy *VerifierProxyFilterer) WatchVerifierSet(opts *bind.WatchOpts, sink chan<- *VerifierProxyVerifierSet) (event.Subscription, error) { + + logs, sub, err := _VerifierProxy.contract.WatchLogs(opts, "VerifierSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VerifierProxyVerifierSet) + if err := _VerifierProxy.contract.UnpackLog(event, "VerifierSet", 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 (_VerifierProxy *VerifierProxyFilterer) ParseVerifierSet(log types.Log) (*VerifierProxyVerifierSet, error) { + event := new(VerifierProxyVerifierSet) + if err := _VerifierProxy.contract.UnpackLog(event, "VerifierSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VerifierProxyVerifierUnsetIterator struct { + Event *VerifierProxyVerifierUnset + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VerifierProxyVerifierUnsetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VerifierProxyVerifierUnset) + 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(VerifierProxyVerifierUnset) + 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 *VerifierProxyVerifierUnsetIterator) Error() error { + return it.fail +} + +func (it *VerifierProxyVerifierUnsetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VerifierProxyVerifierUnset struct { + ConfigDigest [32]byte + VerifierAddress common.Address + Raw types.Log +} + +func (_VerifierProxy *VerifierProxyFilterer) FilterVerifierUnset(opts *bind.FilterOpts) (*VerifierProxyVerifierUnsetIterator, error) { + + logs, sub, err := _VerifierProxy.contract.FilterLogs(opts, "VerifierUnset") + if err != nil { + return nil, err + } + return &VerifierProxyVerifierUnsetIterator{contract: _VerifierProxy.contract, event: "VerifierUnset", logs: logs, sub: sub}, nil +} + +func (_VerifierProxy *VerifierProxyFilterer) WatchVerifierUnset(opts *bind.WatchOpts, sink chan<- *VerifierProxyVerifierUnset) (event.Subscription, error) { + + logs, sub, err := _VerifierProxy.contract.WatchLogs(opts, "VerifierUnset") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VerifierProxyVerifierUnset) + if err := _VerifierProxy.contract.UnpackLog(event, "VerifierUnset", 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 (_VerifierProxy *VerifierProxyFilterer) ParseVerifierUnset(log types.Log) (*VerifierProxyVerifierUnset, error) { + event := new(VerifierProxyVerifierUnset) + if err := _VerifierProxy.contract.UnpackLog(event, "VerifierUnset", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_VerifierProxy *VerifierProxy) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _VerifierProxy.abi.Events["AccessControllerSet"].ID: + return _VerifierProxy.ParseAccessControllerSet(log) + case _VerifierProxy.abi.Events["FeeManagerSet"].ID: + return _VerifierProxy.ParseFeeManagerSet(log) + case _VerifierProxy.abi.Events["OwnershipTransferRequested"].ID: + return _VerifierProxy.ParseOwnershipTransferRequested(log) + case _VerifierProxy.abi.Events["OwnershipTransferred"].ID: + return _VerifierProxy.ParseOwnershipTransferred(log) + case _VerifierProxy.abi.Events["VerifierInitialized"].ID: + return _VerifierProxy.ParseVerifierInitialized(log) + case _VerifierProxy.abi.Events["VerifierSet"].ID: + return _VerifierProxy.ParseVerifierSet(log) + case _VerifierProxy.abi.Events["VerifierUnset"].ID: + return _VerifierProxy.ParseVerifierUnset(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (VerifierProxyAccessControllerSet) Topic() common.Hash { + return common.HexToHash("0x953e92b1a6442e9c3242531154a3f6f6eb00b4e9c719ba8118fa6235e4ce89b6") +} + +func (VerifierProxyFeeManagerSet) Topic() common.Hash { + return common.HexToHash("0x04628abcaa6b1674651352125cb94b65b289145bc2bc4d67720bb7d966372f03") +} + +func (VerifierProxyOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (VerifierProxyOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (VerifierProxyVerifierInitialized) Topic() common.Hash { + return common.HexToHash("0x1f2cd7c97f4d801b5efe26cc409617c1fd6c5ef786e79aacb90af40923e4e8e9") +} + +func (VerifierProxyVerifierSet) Topic() common.Hash { + return common.HexToHash("0xbeb513e532542a562ac35699e7cd9ae7d198dcd3eee15bada6c857d28ceaddcf") +} + +func (VerifierProxyVerifierUnset) Topic() common.Hash { + return common.HexToHash("0x11dc15c4b8ac2b183166cc8427e5385a5ece8308217a4217338c6a7614845c4c") +} + +func (_VerifierProxy *VerifierProxy) Address() common.Address { + return _VerifierProxy.address +} + +type VerifierProxyInterface interface { + GetVerifier(opts *bind.CallOpts, configDigest [32]byte) (common.Address, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + SAccessController(opts *bind.CallOpts) (common.Address, error) + + SFeeManager(opts *bind.CallOpts) (common.Address, error) + + TypeAndVersion(opts *bind.CallOpts) (string, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + InitializeVerifier(opts *bind.TransactOpts, verifierAddress common.Address) (*types.Transaction, error) + + SetAccessController(opts *bind.TransactOpts, accessController common.Address) (*types.Transaction, error) + + SetFeeManager(opts *bind.TransactOpts, feeManager common.Address) (*types.Transaction, error) + + SetVerifier(opts *bind.TransactOpts, currentConfigDigest [32]byte, newConfigDigest [32]byte, addressesAndWeights []CommonAddressAndWeight) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + UnsetVerifier(opts *bind.TransactOpts, configDigest [32]byte) (*types.Transaction, error) + + Verify(opts *bind.TransactOpts, payload []byte, parameterPayload []byte) (*types.Transaction, error) + + VerifyBulk(opts *bind.TransactOpts, payloads [][]byte, parameterPayload []byte) (*types.Transaction, error) + + FilterAccessControllerSet(opts *bind.FilterOpts) (*VerifierProxyAccessControllerSetIterator, error) + + WatchAccessControllerSet(opts *bind.WatchOpts, sink chan<- *VerifierProxyAccessControllerSet) (event.Subscription, error) + + ParseAccessControllerSet(log types.Log) (*VerifierProxyAccessControllerSet, error) + + FilterFeeManagerSet(opts *bind.FilterOpts) (*VerifierProxyFeeManagerSetIterator, error) + + WatchFeeManagerSet(opts *bind.WatchOpts, sink chan<- *VerifierProxyFeeManagerSet) (event.Subscription, error) + + ParseFeeManagerSet(log types.Log) (*VerifierProxyFeeManagerSet, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*VerifierProxyOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *VerifierProxyOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*VerifierProxyOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*VerifierProxyOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *VerifierProxyOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*VerifierProxyOwnershipTransferred, error) + + FilterVerifierInitialized(opts *bind.FilterOpts) (*VerifierProxyVerifierInitializedIterator, error) + + WatchVerifierInitialized(opts *bind.WatchOpts, sink chan<- *VerifierProxyVerifierInitialized) (event.Subscription, error) + + ParseVerifierInitialized(log types.Log) (*VerifierProxyVerifierInitialized, error) + + FilterVerifierSet(opts *bind.FilterOpts) (*VerifierProxyVerifierSetIterator, error) + + WatchVerifierSet(opts *bind.WatchOpts, sink chan<- *VerifierProxyVerifierSet) (event.Subscription, error) + + ParseVerifierSet(log types.Log) (*VerifierProxyVerifierSet, error) + + FilterVerifierUnset(opts *bind.FilterOpts) (*VerifierProxyVerifierUnsetIterator, error) + + WatchVerifierUnset(opts *bind.WatchOpts, sink chan<- *VerifierProxyVerifierUnset) (event.Subscription, error) + + ParseVerifierUnset(log types.Log) (*VerifierProxyVerifierUnset, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/llo-feeds/generated/verifier_v0_5_0/verifier_v0_5_0.go b/core/gethwrappers/llo-feeds/generated/verifier_v0_5_0/verifier_v0_5_0.go new file mode 100644 index 00000000000..f6e45d02762 --- /dev/null +++ b/core/gethwrappers/llo-feeds/generated/verifier_v0_5_0/verifier_v0_5_0.go @@ -0,0 +1,1385 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package verifier_v0_5_0 + +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 +) + +type CommonAddressAndWeight struct { + Addr common.Address + Weight uint64 +} + +var VerifierMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"verifierProxyAddr\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AccessForbidden\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BadVerification\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigDigestAlreadySet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DigestEmpty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"DigestInactive\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"DigestNotSet\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numSigners\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxSigners\",\"type\":\"uint256\"}],\"name\":\"ExcessSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FaultToleranceMustBePositive\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numSigners\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expectedNumSigners\",\"type\":\"uint256\"}],\"name\":\"IncorrectSignatureCount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numSigners\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minSigners\",\"type\":\"uint256\"}],\"name\":\"InsufficientSigners\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"rsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"ssLength\",\"type\":\"uint256\"}],\"name\":\"MismatchedSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddress\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"ConfigActivated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"ConfigDeactivated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"prevSigners\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"newSigners\",\"type\":\"address[]\"}],\"name\":\"ConfigUpdated\",\"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\":true,\"internalType\":\"bytes32\",\"name\":\"feedId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"requester\",\"type\":\"address\"}],\"name\":\"ReportVerified\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"activateConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"deactivateConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"weight\",\"type\":\"uint64\"}],\"internalType\":\"structCommon.AddressAndWeight[]\",\"name\":\"recipientAddressesAndWeights\",\"type\":\"tuple[]\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isVerifier\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"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\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"address[]\",\"name\":\"prevSigners\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"newSigners\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"}],\"name\":\"updateConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"signedReport\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"verify\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"verifierResponse\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60a06040523480156200001157600080fd5b5060405162001e7038038062001e708339810160408190526200003491620001a6565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000fb565b5050506001600160a01b038116620000e95760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0316608052620001d8565b336001600160a01b03821603620001555760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215620001b957600080fd5b81516001600160a01b0381168114620001d157600080fd5b9392505050565b608051611c75620001fb600039600081816107c20152610e110152611c756000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c80633d3ac1b5116100815780638da5cb5b1161005b5780638da5cb5b146101e3578063e84f128e1461020b578063f2fde38b1461024657600080fd5b80633d3ac1b5146101b557806341e3df58146101c857806379ba5097146101db57600080fd5b80630e112e54116100b25780630e112e541461014d5780630f672ef414610160578063181f5a771461017357600080fd5b806301ffc9a7146100ce5780630d1d79af14610138575b600080fd5b6101236100dc366004611333565b7fffffffff00000000000000000000000000000000000000000000000000000000167f3d3ac1b5000000000000000000000000000000000000000000000000000000001490565b60405190151581526020015b60405180910390f35b61014b61014636600461137c565b610259565b005b61014b61015b3660046113f7565b610351565b61014b61016e36600461137c565b6106bc565b60408051808201909152600e81527f566572696669657220322e302e3000000000000000000000000000000000000060208201525b60405161012f91906114e4565b6101a86101c336600461151b565b6107a8565b61014b6101d636600461168a565b6108cc565b61014b61098e565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161012f565b61023161021936600461137c565b60009081526002602052604090205463ffffffff1690565b60405163ffffffff909116815260200161012f565b61014b6102543660046117a3565b610a8b565b610261610a9f565b6000818152600260205260409020816102a6576040517fe332262700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805465010000000000900460ff166000036102f5576040517f74eb4b93000000000000000000000000000000000000000000000000000000008152600481018390526024015b60405180910390fd5b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffff1664010000000017815560405182907fa543797a0501218bba8a3daf75a71c8df8d1a7f791f4e44d40e43b6450183cea90600090a25050565b8160ff82166000819003610391576040517f0743bae600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601f8211156103d6576040517f61750f4000000000000000000000000000000000000000000000000000000000815260048101839052601f60248201526044016102ec565b6103e18160036117ed565b821161043957816103f38260036117ed565b6103fe90600161180a565b6040517f9dd9e6d8000000000000000000000000000000000000000000000000000000008152600481019290925260248201526044016102ec565b610441610a9f565b6000888152600260205260408120805490916501000000000090910460ff16900361049b576040517f74eb4b93000000000000000000000000000000000000000000000000000000008152600481018a90526024016102ec565b80546601000000000000900460ff1687146104e2576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8781101561061c5760008260010160008b8b858181106105075761050761184c565b905060200201602081019061051c91906117a3565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002054610100900460ff16600181111561055c5761055c61181d565b03610593576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8160010160008a8a848181106105ab576105ab61184c565b90506020020160208101906105c091906117a3565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690556106158161187b565b90506104e5565b5061067389878787600060405190808252806020026020018201604052801561066b57816020015b60408051808201909152600080825260208201528152602001906001900390816106445790505b506001610b22565b887fb0b75a854fab801413da6202fc07e875c54eaf371a1e3909fb2645364ba58616898989896040516106a99493929190611907565b60405180910390a2505050505050505050565b6106c4610a9f565b600081815260026020526040902081610709576040517fe332262700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805465010000000000900460ff16600003610753576040517f74eb4b93000000000000000000000000000000000000000000000000000000008152600481018390526024016102ec565b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffff16815560405182907f5bfaab86edc1b932e3c334327a591c9ded067cb521abae19b95ca927d607657990600090a25050565b60603373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610819576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008080808061082b888a018a611a2d565b84516000818152600260205260409020959a50939850919650945092509061085582868684610ec2565b8551602087012061086a818988888887610fc2565b61087387611b08565b60405173ffffffffffffffffffffffffffffffffffffffff8c1681527f58ca9502e98a536e06e72d680fcc251e5d10b72291a281665a2c2dc0ac30fcc59060200160405180910390a250949a9950505050505050505050565b8260ff8316600081900361090c576040517f0743bae600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601f821115610951576040517f61750f4000000000000000000000000000000000000000000000000000000000815260048101839052601f60248201526044016102ec565b61095c8160036117ed565b821161096e57816103f38260036117ed565b610976610a9f565b61098587878787876000610b22565b50505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610a0f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016102ec565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610a93610a9f565b610a9c8161123e565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610b20576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016102ec565b565b6000868152600260205260409020805465010000000000900460ff1615801590610b4a575081155b15610b81576040517f961dba8800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805460ff8681166601000000000000027fffffffffffffffffffffffffffffffffffffffffffffffffff00ff00ffffffff91871665010000000000027fffffffffffffffffffffffffffffffffffffffffffffffffffff00ff0000000090931663ffffffff43161792909217161764010000000017815560005b60ff8116861115610dce57600087878360ff16818110610c1d57610c1d61184c565b9050602002016020810190610c3291906117a3565b905073ffffffffffffffffffffffffffffffffffffffff8116610c81576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008073ffffffffffffffffffffffffffffffffffffffff831660009081526001868101602052604090912054610100900460ff1690811115610cc657610cc661181d565b1480159150610d01576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051808201825260ff85811682526001602080840182815273ffffffffffffffffffffffffffffffffffffffff881660009081528a84019092529490208351815493167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008416811782559451939490939284927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090911690911790610100908490811115610db357610db361181d565b0217905550905050505080610dc790611b4d565b9050610bfb565b5081610985576040517fb011b24700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063b011b24790610e4b906000908b908890600401611b6c565b600060405180830381600087803b158015610e6557600080fd5b505af1158015610e79573d6000803e3d6000fd5b50505050867f5b1f376eb2bda670fa39339616d0a73f45b61bec8faeba8ca834f2ebb49676e0878787604051610eb193929190611bec565b60405180910390a250505050505050565b8054600090610ede9065010000000000900460ff166001611c13565b8254909150640100000000900460ff16610f27576040517fd990d621000000000000000000000000000000000000000000000000000000008152600481018690526024016102ec565b8060ff16845114610f735783516040517f5348a282000000000000000000000000000000000000000000000000000000008152600481019190915260ff821660248201526044016102ec565b8251845114610fbb57835183516040517ff0d31408000000000000000000000000000000000000000000000000000000008152600481019290925260248201526044016102ec565b5050505050565b60008686604051602001610fd7929190611c2c565b604051602081830303815290604052805190602001209050600061100b604080518082019091526000808252602082015290565b8651600090815b818110156111d65760018689836020811061102f5761102f61184c565b61103c91901a601b611c13565b8c848151811061104e5761104e61184c565b60200260200101518c85815181106110685761106861184c565b6020026020010151604051600081526020016040526040516110a6949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa1580156110c8573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff811660009081526001808d01602090815291859020848601909552845460ff80821686529399509395509085019261010090049091169081111561114d5761114d61181d565b600181111561115e5761115e61181d565b905250935060018460200151600181111561117b5761117b61181d565b146111b2576040517f4df18f0700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836000015160080260ff166001901b85019450806111cf9061187b565b9050611012565b50837e01010101010101010101010101010101010101010101010101010101010101851614611231576040517f4df18f0700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff8216036112bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016102ec565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60006020828403121561134557600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461137557600080fd5b9392505050565b60006020828403121561138e57600080fd5b5035919050565b60008083601f8401126113a757600080fd5b50813567ffffffffffffffff8111156113bf57600080fd5b6020830191508360208260051b85010111156113da57600080fd5b9250929050565b803560ff811681146113f257600080fd5b919050565b6000806000806000806080878903121561141057600080fd5b86359550602087013567ffffffffffffffff8082111561142f57600080fd5b61143b8a838b01611395565b9097509550604089013591508082111561145457600080fd5b5061146189828a01611395565b90945092506114749050606088016113e1565b90509295509295509295565b6000815180845260005b818110156114a65760208185018101518683018201520161148a565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006113756020830184611480565b803573ffffffffffffffffffffffffffffffffffffffff811681146113f257600080fd5b60008060006040848603121561153057600080fd5b833567ffffffffffffffff8082111561154857600080fd5b818601915086601f83011261155c57600080fd5b81358181111561156b57600080fd5b87602082850101111561157d57600080fd5b60209283019550935061159391860190506114f7565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156115ee576115ee61159c565b60405290565b6040516060810167ffffffffffffffff811182821017156115ee576115ee61159c565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561165e5761165e61159c565b604052919050565b600067ffffffffffffffff8211156116805761168061159c565b5060051b60200190565b6000806000806000608086880312156116a257600080fd5b8535945060208087013567ffffffffffffffff808211156116c257600080fd5b6116ce8a838b01611395565b9097509550604091506116e28983016113e1565b94506060890135818111156116f657600080fd5b8901601f81018b1361170757600080fd5b803561171a61171582611666565b611617565b81815260069190911b8201850190858101908d83111561173957600080fd5b928601925b8284101561178f5785848f0312156117565760008081fd5b61175e6115cb565b611767856114f7565b815287850135868116811461177c5760008081fd5b818901528252928501929086019061173e565b809750505050505050509295509295909350565b6000602082840312156117b557600080fd5b611375826114f7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417611804576118046117be565b92915050565b80820180821115611804576118046117be565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036118ac576118ac6117be565b5060010190565b8183526000602080850194508260005b858110156118fc5773ffffffffffffffffffffffffffffffffffffffff6118e9836114f7565b16875295820195908201906001016118c3565b509495945050505050565b60408152600061191b6040830186886118b3565b828103602084015261192e8185876118b3565b979650505050505050565b600082601f83011261194a57600080fd5b813567ffffffffffffffff8111156119645761196461159c565b61199560207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611617565b8181528460208386010111156119aa57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f8301126119d857600080fd5b813560206119e861171583611666565b82815260059290921b84018101918181019086841115611a0757600080fd5b8286015b84811015611a225780358352918301918301611a0b565b509695505050505050565b600080600080600060e08688031215611a4557600080fd5b86601f870112611a5457600080fd5b611a5c6115f4565b806060880189811115611a6e57600080fd5b885b81811015611a88578035845260209384019301611a70565b5090965035905067ffffffffffffffff80821115611aa557600080fd5b611ab189838a01611939565b95506080880135915080821115611ac757600080fd5b611ad389838a016119c7565b945060a0880135915080821115611ae957600080fd5b50611af6888289016119c7565b9598949750929560c001359392505050565b80516020808301519190811015611b47577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8160200360031b1b821691505b50919050565b600060ff821660ff8103611b6357611b636117be565b60010192915050565b600060608201858352602085818501526040606081860152828651808552608087019150838801945060005b81811015611bdd578551805173ffffffffffffffffffffffffffffffffffffffff16845285015167ffffffffffffffff16858401529484019491830191600101611b98565b50909998505050505050505050565b604081526000611c006040830185876118b3565b905060ff83166020830152949350505050565b60ff8181168382160190811115611804576118046117be565b828152600060208083018460005b6003811015611c5757815183529183019190830190600101611c3a565b50505050608082019050939250505056fea164736f6c6343000813000a", +} + +var VerifierABI = VerifierMetaData.ABI + +var VerifierBin = VerifierMetaData.Bin + +func DeployVerifier(auth *bind.TransactOpts, backend bind.ContractBackend, verifierProxyAddr common.Address) (common.Address, *types.Transaction, *Verifier, error) { + parsed, err := VerifierMetaData.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(VerifierBin), backend, verifierProxyAddr) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Verifier{address: address, abi: *parsed, VerifierCaller: VerifierCaller{contract: contract}, VerifierTransactor: VerifierTransactor{contract: contract}, VerifierFilterer: VerifierFilterer{contract: contract}}, nil +} + +type Verifier struct { + address common.Address + abi abi.ABI + VerifierCaller + VerifierTransactor + VerifierFilterer +} + +type VerifierCaller struct { + contract *bind.BoundContract +} + +type VerifierTransactor struct { + contract *bind.BoundContract +} + +type VerifierFilterer struct { + contract *bind.BoundContract +} + +type VerifierSession struct { + Contract *Verifier + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type VerifierCallerSession struct { + Contract *VerifierCaller + CallOpts bind.CallOpts +} + +type VerifierTransactorSession struct { + Contract *VerifierTransactor + TransactOpts bind.TransactOpts +} + +type VerifierRaw struct { + Contract *Verifier +} + +type VerifierCallerRaw struct { + Contract *VerifierCaller +} + +type VerifierTransactorRaw struct { + Contract *VerifierTransactor +} + +func NewVerifier(address common.Address, backend bind.ContractBackend) (*Verifier, error) { + abi, err := abi.JSON(strings.NewReader(VerifierABI)) + if err != nil { + return nil, err + } + contract, err := bindVerifier(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Verifier{address: address, abi: abi, VerifierCaller: VerifierCaller{contract: contract}, VerifierTransactor: VerifierTransactor{contract: contract}, VerifierFilterer: VerifierFilterer{contract: contract}}, nil +} + +func NewVerifierCaller(address common.Address, caller bind.ContractCaller) (*VerifierCaller, error) { + contract, err := bindVerifier(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &VerifierCaller{contract: contract}, nil +} + +func NewVerifierTransactor(address common.Address, transactor bind.ContractTransactor) (*VerifierTransactor, error) { + contract, err := bindVerifier(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &VerifierTransactor{contract: contract}, nil +} + +func NewVerifierFilterer(address common.Address, filterer bind.ContractFilterer) (*VerifierFilterer, error) { + contract, err := bindVerifier(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &VerifierFilterer{contract: contract}, nil +} + +func bindVerifier(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := VerifierMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_Verifier *VerifierRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Verifier.Contract.VerifierCaller.contract.Call(opts, result, method, params...) +} + +func (_Verifier *VerifierRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Verifier.Contract.VerifierTransactor.contract.Transfer(opts) +} + +func (_Verifier *VerifierRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Verifier.Contract.VerifierTransactor.contract.Transact(opts, method, params...) +} + +func (_Verifier *VerifierCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Verifier.Contract.contract.Call(opts, result, method, params...) +} + +func (_Verifier *VerifierTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Verifier.Contract.contract.Transfer(opts) +} + +func (_Verifier *VerifierTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Verifier.Contract.contract.Transact(opts, method, params...) +} + +func (_Verifier *VerifierCaller) LatestConfigDetails(opts *bind.CallOpts, configDigest [32]byte) (uint32, error) { + var out []interface{} + err := _Verifier.contract.Call(opts, &out, "latestConfigDetails", configDigest) + + if err != nil { + return *new(uint32), err + } + + out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32) + + return out0, err + +} + +func (_Verifier *VerifierSession) LatestConfigDetails(configDigest [32]byte) (uint32, error) { + return _Verifier.Contract.LatestConfigDetails(&_Verifier.CallOpts, configDigest) +} + +func (_Verifier *VerifierCallerSession) LatestConfigDetails(configDigest [32]byte) (uint32, error) { + return _Verifier.Contract.LatestConfigDetails(&_Verifier.CallOpts, configDigest) +} + +func (_Verifier *VerifierCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Verifier.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 (_Verifier *VerifierSession) Owner() (common.Address, error) { + return _Verifier.Contract.Owner(&_Verifier.CallOpts) +} + +func (_Verifier *VerifierCallerSession) Owner() (common.Address, error) { + return _Verifier.Contract.Owner(&_Verifier.CallOpts) +} + +func (_Verifier *VerifierCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + var out []interface{} + err := _Verifier.contract.Call(opts, &out, "supportsInterface", interfaceId) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_Verifier *VerifierSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _Verifier.Contract.SupportsInterface(&_Verifier.CallOpts, interfaceId) +} + +func (_Verifier *VerifierCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _Verifier.Contract.SupportsInterface(&_Verifier.CallOpts, interfaceId) +} + +func (_Verifier *VerifierCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _Verifier.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_Verifier *VerifierSession) TypeAndVersion() (string, error) { + return _Verifier.Contract.TypeAndVersion(&_Verifier.CallOpts) +} + +func (_Verifier *VerifierCallerSession) TypeAndVersion() (string, error) { + return _Verifier.Contract.TypeAndVersion(&_Verifier.CallOpts) +} + +func (_Verifier *VerifierTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Verifier.contract.Transact(opts, "acceptOwnership") +} + +func (_Verifier *VerifierSession) AcceptOwnership() (*types.Transaction, error) { + return _Verifier.Contract.AcceptOwnership(&_Verifier.TransactOpts) +} + +func (_Verifier *VerifierTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _Verifier.Contract.AcceptOwnership(&_Verifier.TransactOpts) +} + +func (_Verifier *VerifierTransactor) ActivateConfig(opts *bind.TransactOpts, configDigest [32]byte) (*types.Transaction, error) { + return _Verifier.contract.Transact(opts, "activateConfig", configDigest) +} + +func (_Verifier *VerifierSession) ActivateConfig(configDigest [32]byte) (*types.Transaction, error) { + return _Verifier.Contract.ActivateConfig(&_Verifier.TransactOpts, configDigest) +} + +func (_Verifier *VerifierTransactorSession) ActivateConfig(configDigest [32]byte) (*types.Transaction, error) { + return _Verifier.Contract.ActivateConfig(&_Verifier.TransactOpts, configDigest) +} + +func (_Verifier *VerifierTransactor) DeactivateConfig(opts *bind.TransactOpts, configDigest [32]byte) (*types.Transaction, error) { + return _Verifier.contract.Transact(opts, "deactivateConfig", configDigest) +} + +func (_Verifier *VerifierSession) DeactivateConfig(configDigest [32]byte) (*types.Transaction, error) { + return _Verifier.Contract.DeactivateConfig(&_Verifier.TransactOpts, configDigest) +} + +func (_Verifier *VerifierTransactorSession) DeactivateConfig(configDigest [32]byte) (*types.Transaction, error) { + return _Verifier.Contract.DeactivateConfig(&_Verifier.TransactOpts, configDigest) +} + +func (_Verifier *VerifierTransactor) SetConfig(opts *bind.TransactOpts, configDigest [32]byte, signers []common.Address, f uint8, recipientAddressesAndWeights []CommonAddressAndWeight) (*types.Transaction, error) { + return _Verifier.contract.Transact(opts, "setConfig", configDigest, signers, f, recipientAddressesAndWeights) +} + +func (_Verifier *VerifierSession) SetConfig(configDigest [32]byte, signers []common.Address, f uint8, recipientAddressesAndWeights []CommonAddressAndWeight) (*types.Transaction, error) { + return _Verifier.Contract.SetConfig(&_Verifier.TransactOpts, configDigest, signers, f, recipientAddressesAndWeights) +} + +func (_Verifier *VerifierTransactorSession) SetConfig(configDigest [32]byte, signers []common.Address, f uint8, recipientAddressesAndWeights []CommonAddressAndWeight) (*types.Transaction, error) { + return _Verifier.Contract.SetConfig(&_Verifier.TransactOpts, configDigest, signers, f, recipientAddressesAndWeights) +} + +func (_Verifier *VerifierTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _Verifier.contract.Transact(opts, "transferOwnership", to) +} + +func (_Verifier *VerifierSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _Verifier.Contract.TransferOwnership(&_Verifier.TransactOpts, to) +} + +func (_Verifier *VerifierTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _Verifier.Contract.TransferOwnership(&_Verifier.TransactOpts, to) +} + +func (_Verifier *VerifierTransactor) UpdateConfig(opts *bind.TransactOpts, configDigest [32]byte, prevSigners []common.Address, newSigners []common.Address, f uint8) (*types.Transaction, error) { + return _Verifier.contract.Transact(opts, "updateConfig", configDigest, prevSigners, newSigners, f) +} + +func (_Verifier *VerifierSession) UpdateConfig(configDigest [32]byte, prevSigners []common.Address, newSigners []common.Address, f uint8) (*types.Transaction, error) { + return _Verifier.Contract.UpdateConfig(&_Verifier.TransactOpts, configDigest, prevSigners, newSigners, f) +} + +func (_Verifier *VerifierTransactorSession) UpdateConfig(configDigest [32]byte, prevSigners []common.Address, newSigners []common.Address, f uint8) (*types.Transaction, error) { + return _Verifier.Contract.UpdateConfig(&_Verifier.TransactOpts, configDigest, prevSigners, newSigners, f) +} + +func (_Verifier *VerifierTransactor) Verify(opts *bind.TransactOpts, signedReport []byte, sender common.Address) (*types.Transaction, error) { + return _Verifier.contract.Transact(opts, "verify", signedReport, sender) +} + +func (_Verifier *VerifierSession) Verify(signedReport []byte, sender common.Address) (*types.Transaction, error) { + return _Verifier.Contract.Verify(&_Verifier.TransactOpts, signedReport, sender) +} + +func (_Verifier *VerifierTransactorSession) Verify(signedReport []byte, sender common.Address) (*types.Transaction, error) { + return _Verifier.Contract.Verify(&_Verifier.TransactOpts, signedReport, sender) +} + +type VerifierConfigActivatedIterator struct { + Event *VerifierConfigActivated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VerifierConfigActivatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VerifierConfigActivated) + 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(VerifierConfigActivated) + 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 *VerifierConfigActivatedIterator) Error() error { + return it.fail +} + +func (it *VerifierConfigActivatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VerifierConfigActivated struct { + ConfigDigest [32]byte + Raw types.Log +} + +func (_Verifier *VerifierFilterer) FilterConfigActivated(opts *bind.FilterOpts, configDigest [][32]byte) (*VerifierConfigActivatedIterator, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + + logs, sub, err := _Verifier.contract.FilterLogs(opts, "ConfigActivated", configDigestRule) + if err != nil { + return nil, err + } + return &VerifierConfigActivatedIterator{contract: _Verifier.contract, event: "ConfigActivated", logs: logs, sub: sub}, nil +} + +func (_Verifier *VerifierFilterer) WatchConfigActivated(opts *bind.WatchOpts, sink chan<- *VerifierConfigActivated, configDigest [][32]byte) (event.Subscription, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + + logs, sub, err := _Verifier.contract.WatchLogs(opts, "ConfigActivated", configDigestRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VerifierConfigActivated) + if err := _Verifier.contract.UnpackLog(event, "ConfigActivated", 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 (_Verifier *VerifierFilterer) ParseConfigActivated(log types.Log) (*VerifierConfigActivated, error) { + event := new(VerifierConfigActivated) + if err := _Verifier.contract.UnpackLog(event, "ConfigActivated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VerifierConfigDeactivatedIterator struct { + Event *VerifierConfigDeactivated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VerifierConfigDeactivatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VerifierConfigDeactivated) + 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(VerifierConfigDeactivated) + 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 *VerifierConfigDeactivatedIterator) Error() error { + return it.fail +} + +func (it *VerifierConfigDeactivatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VerifierConfigDeactivated struct { + ConfigDigest [32]byte + Raw types.Log +} + +func (_Verifier *VerifierFilterer) FilterConfigDeactivated(opts *bind.FilterOpts, configDigest [][32]byte) (*VerifierConfigDeactivatedIterator, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + + logs, sub, err := _Verifier.contract.FilterLogs(opts, "ConfigDeactivated", configDigestRule) + if err != nil { + return nil, err + } + return &VerifierConfigDeactivatedIterator{contract: _Verifier.contract, event: "ConfigDeactivated", logs: logs, sub: sub}, nil +} + +func (_Verifier *VerifierFilterer) WatchConfigDeactivated(opts *bind.WatchOpts, sink chan<- *VerifierConfigDeactivated, configDigest [][32]byte) (event.Subscription, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + + logs, sub, err := _Verifier.contract.WatchLogs(opts, "ConfigDeactivated", configDigestRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VerifierConfigDeactivated) + if err := _Verifier.contract.UnpackLog(event, "ConfigDeactivated", 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 (_Verifier *VerifierFilterer) ParseConfigDeactivated(log types.Log) (*VerifierConfigDeactivated, error) { + event := new(VerifierConfigDeactivated) + if err := _Verifier.contract.UnpackLog(event, "ConfigDeactivated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VerifierConfigSetIterator struct { + Event *VerifierConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VerifierConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VerifierConfigSet) + 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(VerifierConfigSet) + 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 *VerifierConfigSetIterator) Error() error { + return it.fail +} + +func (it *VerifierConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VerifierConfigSet struct { + ConfigDigest [32]byte + Signers []common.Address + F uint8 + Raw types.Log +} + +func (_Verifier *VerifierFilterer) FilterConfigSet(opts *bind.FilterOpts, configDigest [][32]byte) (*VerifierConfigSetIterator, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + + logs, sub, err := _Verifier.contract.FilterLogs(opts, "ConfigSet", configDigestRule) + if err != nil { + return nil, err + } + return &VerifierConfigSetIterator{contract: _Verifier.contract, event: "ConfigSet", logs: logs, sub: sub}, nil +} + +func (_Verifier *VerifierFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *VerifierConfigSet, configDigest [][32]byte) (event.Subscription, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + + logs, sub, err := _Verifier.contract.WatchLogs(opts, "ConfigSet", configDigestRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VerifierConfigSet) + if err := _Verifier.contract.UnpackLog(event, "ConfigSet", 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 (_Verifier *VerifierFilterer) ParseConfigSet(log types.Log) (*VerifierConfigSet, error) { + event := new(VerifierConfigSet) + if err := _Verifier.contract.UnpackLog(event, "ConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VerifierConfigUpdatedIterator struct { + Event *VerifierConfigUpdated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VerifierConfigUpdatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VerifierConfigUpdated) + 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(VerifierConfigUpdated) + 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 *VerifierConfigUpdatedIterator) Error() error { + return it.fail +} + +func (it *VerifierConfigUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VerifierConfigUpdated struct { + ConfigDigest [32]byte + PrevSigners []common.Address + NewSigners []common.Address + Raw types.Log +} + +func (_Verifier *VerifierFilterer) FilterConfigUpdated(opts *bind.FilterOpts, configDigest [][32]byte) (*VerifierConfigUpdatedIterator, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + + logs, sub, err := _Verifier.contract.FilterLogs(opts, "ConfigUpdated", configDigestRule) + if err != nil { + return nil, err + } + return &VerifierConfigUpdatedIterator{contract: _Verifier.contract, event: "ConfigUpdated", logs: logs, sub: sub}, nil +} + +func (_Verifier *VerifierFilterer) WatchConfigUpdated(opts *bind.WatchOpts, sink chan<- *VerifierConfigUpdated, configDigest [][32]byte) (event.Subscription, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + + logs, sub, err := _Verifier.contract.WatchLogs(opts, "ConfigUpdated", configDigestRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VerifierConfigUpdated) + if err := _Verifier.contract.UnpackLog(event, "ConfigUpdated", 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 (_Verifier *VerifierFilterer) ParseConfigUpdated(log types.Log) (*VerifierConfigUpdated, error) { + event := new(VerifierConfigUpdated) + if err := _Verifier.contract.UnpackLog(event, "ConfigUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VerifierOwnershipTransferRequestedIterator struct { + Event *VerifierOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VerifierOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VerifierOwnershipTransferRequested) + 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(VerifierOwnershipTransferRequested) + 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 *VerifierOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *VerifierOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VerifierOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_Verifier *VerifierFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*VerifierOwnershipTransferRequestedIterator, 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 := _Verifier.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &VerifierOwnershipTransferRequestedIterator{contract: _Verifier.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_Verifier *VerifierFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *VerifierOwnershipTransferRequested, 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 := _Verifier.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(VerifierOwnershipTransferRequested) + if err := _Verifier.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 (_Verifier *VerifierFilterer) ParseOwnershipTransferRequested(log types.Log) (*VerifierOwnershipTransferRequested, error) { + event := new(VerifierOwnershipTransferRequested) + if err := _Verifier.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VerifierOwnershipTransferredIterator struct { + Event *VerifierOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VerifierOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VerifierOwnershipTransferred) + 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(VerifierOwnershipTransferred) + 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 *VerifierOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *VerifierOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VerifierOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_Verifier *VerifierFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*VerifierOwnershipTransferredIterator, 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 := _Verifier.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &VerifierOwnershipTransferredIterator{contract: _Verifier.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_Verifier *VerifierFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *VerifierOwnershipTransferred, 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 := _Verifier.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(VerifierOwnershipTransferred) + if err := _Verifier.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 (_Verifier *VerifierFilterer) ParseOwnershipTransferred(log types.Log) (*VerifierOwnershipTransferred, error) { + event := new(VerifierOwnershipTransferred) + if err := _Verifier.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VerifierReportVerifiedIterator struct { + Event *VerifierReportVerified + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VerifierReportVerifiedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VerifierReportVerified) + 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(VerifierReportVerified) + 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 *VerifierReportVerifiedIterator) Error() error { + return it.fail +} + +func (it *VerifierReportVerifiedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VerifierReportVerified struct { + FeedId [32]byte + Requester common.Address + Raw types.Log +} + +func (_Verifier *VerifierFilterer) FilterReportVerified(opts *bind.FilterOpts, feedId [][32]byte) (*VerifierReportVerifiedIterator, error) { + + var feedIdRule []interface{} + for _, feedIdItem := range feedId { + feedIdRule = append(feedIdRule, feedIdItem) + } + + logs, sub, err := _Verifier.contract.FilterLogs(opts, "ReportVerified", feedIdRule) + if err != nil { + return nil, err + } + return &VerifierReportVerifiedIterator{contract: _Verifier.contract, event: "ReportVerified", logs: logs, sub: sub}, nil +} + +func (_Verifier *VerifierFilterer) WatchReportVerified(opts *bind.WatchOpts, sink chan<- *VerifierReportVerified, feedId [][32]byte) (event.Subscription, error) { + + var feedIdRule []interface{} + for _, feedIdItem := range feedId { + feedIdRule = append(feedIdRule, feedIdItem) + } + + logs, sub, err := _Verifier.contract.WatchLogs(opts, "ReportVerified", feedIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VerifierReportVerified) + if err := _Verifier.contract.UnpackLog(event, "ReportVerified", 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 (_Verifier *VerifierFilterer) ParseReportVerified(log types.Log) (*VerifierReportVerified, error) { + event := new(VerifierReportVerified) + if err := _Verifier.contract.UnpackLog(event, "ReportVerified", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_Verifier *Verifier) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _Verifier.abi.Events["ConfigActivated"].ID: + return _Verifier.ParseConfigActivated(log) + case _Verifier.abi.Events["ConfigDeactivated"].ID: + return _Verifier.ParseConfigDeactivated(log) + case _Verifier.abi.Events["ConfigSet"].ID: + return _Verifier.ParseConfigSet(log) + case _Verifier.abi.Events["ConfigUpdated"].ID: + return _Verifier.ParseConfigUpdated(log) + case _Verifier.abi.Events["OwnershipTransferRequested"].ID: + return _Verifier.ParseOwnershipTransferRequested(log) + case _Verifier.abi.Events["OwnershipTransferred"].ID: + return _Verifier.ParseOwnershipTransferred(log) + case _Verifier.abi.Events["ReportVerified"].ID: + return _Verifier.ParseReportVerified(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (VerifierConfigActivated) Topic() common.Hash { + return common.HexToHash("0xa543797a0501218bba8a3daf75a71c8df8d1a7f791f4e44d40e43b6450183cea") +} + +func (VerifierConfigDeactivated) Topic() common.Hash { + return common.HexToHash("0x5bfaab86edc1b932e3c334327a591c9ded067cb521abae19b95ca927d6076579") +} + +func (VerifierConfigSet) Topic() common.Hash { + return common.HexToHash("0x5b1f376eb2bda670fa39339616d0a73f45b61bec8faeba8ca834f2ebb49676e0") +} + +func (VerifierConfigUpdated) Topic() common.Hash { + return common.HexToHash("0xb0b75a854fab801413da6202fc07e875c54eaf371a1e3909fb2645364ba58616") +} + +func (VerifierOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (VerifierOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (VerifierReportVerified) Topic() common.Hash { + return common.HexToHash("0x58ca9502e98a536e06e72d680fcc251e5d10b72291a281665a2c2dc0ac30fcc5") +} + +func (_Verifier *Verifier) Address() common.Address { + return _Verifier.address +} + +type VerifierInterface interface { + LatestConfigDetails(opts *bind.CallOpts, configDigest [32]byte) (uint32, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) + + TypeAndVersion(opts *bind.CallOpts) (string, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + ActivateConfig(opts *bind.TransactOpts, configDigest [32]byte) (*types.Transaction, error) + + DeactivateConfig(opts *bind.TransactOpts, configDigest [32]byte) (*types.Transaction, error) + + SetConfig(opts *bind.TransactOpts, configDigest [32]byte, signers []common.Address, f uint8, recipientAddressesAndWeights []CommonAddressAndWeight) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + UpdateConfig(opts *bind.TransactOpts, configDigest [32]byte, prevSigners []common.Address, newSigners []common.Address, f uint8) (*types.Transaction, error) + + Verify(opts *bind.TransactOpts, signedReport []byte, sender common.Address) (*types.Transaction, error) + + FilterConfigActivated(opts *bind.FilterOpts, configDigest [][32]byte) (*VerifierConfigActivatedIterator, error) + + WatchConfigActivated(opts *bind.WatchOpts, sink chan<- *VerifierConfigActivated, configDigest [][32]byte) (event.Subscription, error) + + ParseConfigActivated(log types.Log) (*VerifierConfigActivated, error) + + FilterConfigDeactivated(opts *bind.FilterOpts, configDigest [][32]byte) (*VerifierConfigDeactivatedIterator, error) + + WatchConfigDeactivated(opts *bind.WatchOpts, sink chan<- *VerifierConfigDeactivated, configDigest [][32]byte) (event.Subscription, error) + + ParseConfigDeactivated(log types.Log) (*VerifierConfigDeactivated, error) + + FilterConfigSet(opts *bind.FilterOpts, configDigest [][32]byte) (*VerifierConfigSetIterator, error) + + WatchConfigSet(opts *bind.WatchOpts, sink chan<- *VerifierConfigSet, configDigest [][32]byte) (event.Subscription, error) + + ParseConfigSet(log types.Log) (*VerifierConfigSet, error) + + FilterConfigUpdated(opts *bind.FilterOpts, configDigest [][32]byte) (*VerifierConfigUpdatedIterator, error) + + WatchConfigUpdated(opts *bind.WatchOpts, sink chan<- *VerifierConfigUpdated, configDigest [][32]byte) (event.Subscription, error) + + ParseConfigUpdated(log types.Log) (*VerifierConfigUpdated, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*VerifierOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *VerifierOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*VerifierOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*VerifierOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *VerifierOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*VerifierOwnershipTransferred, error) + + FilterReportVerified(opts *bind.FilterOpts, feedId [][32]byte) (*VerifierReportVerifiedIterator, error) + + WatchReportVerified(opts *bind.WatchOpts, sink chan<- *VerifierReportVerified, feedId [][32]byte) (event.Subscription, error) + + ParseReportVerified(log types.Log) (*VerifierReportVerified, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/llo-feeds/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/llo-feeds/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 8498720be6b..2713dc81133 100644 --- a/core/gethwrappers/llo-feeds/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/llo-feeds/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,21 +1,28 @@ GETH_VERSION: 1.14.11 -channel_config_store: ../../../contracts/solc/v0.8.19/ChannelConfigStore/ChannelConfigStore.abi ../../../contracts/solc/v0.8.19/ChannelConfigStore/ChannelConfigStore.bin 3fafe83ea21d50488f5533962f62683988ffa6fd1476dccbbb9040be2369cb37 +channel_config_store: ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/configuration/ChannelConfigStore/ChannelConfigStore.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/configuration/ChannelConfigStore/ChannelConfigStore.bin 3fafe83ea21d50488f5533962f62683988ffa6fd1476dccbbb9040be2369cb37 +channel_config_store_v0_5_0: ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/configuration/ChannelConfigStore/ChannelConfigStore.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/configuration/ChannelConfigStore/ChannelConfigStore.bin 3fafe83ea21d50488f5533962f62683988ffa6fd1476dccbbb9040be2369cb37 channel_config_verifier_proxy: ../../../contracts/solc/v0.8.19/ChannelVerifierProxy/ChannelVerifierProxy.abi ../../../contracts/solc/v0.8.19/ChannelVerifierProxy/ChannelVerifierProxy.bin 655658e5f61dfadfe3268de04f948b7e690ad03ca45676e645d6cd6018154661 channel_verifier: ../../../contracts/solc/v0.8.19/ChannelVerifier/ChannelVerifier.abi ../../../contracts/solc/v0.8.19/ChannelVerifier/ChannelVerifier.bin e6020553bd8e3e6b250fcaffe7efd22aea955c8c1a0eb05d282fdeb0ab6550b7 -configurator: ../../../contracts/solc/v0.8.19/Configurator/Configurator.abi ../../../contracts/solc/v0.8.19/Configurator/Configurator.bin 7d1640ca82b55c743c7dea4040e4d353a85bcc4751f42c08e29f42742d81d704 -destination_fee_manager: ../../../contracts/solc/v0.8.19/DestinationFeeManager/DestinationFeeManager.abi ../../../contracts/solc/v0.8.19/DestinationFeeManager/DestinationFeeManager.bin a56ae53e35e6610269f086b1e915ca1e80f5d0bf5695d09156e82fccfc2d77b3 -destination_reward_manager: ../../../contracts/solc/v0.8.19/DestinationRewardManager/DestinationRewardManager.abi ../../../contracts/solc/v0.8.19/DestinationRewardManager/DestinationRewardManager.bin 77874e97a54ecbd9c61132964da5b053f0b584dc7b774d75dd51baedd2bc7c40 -destination_verifier: ../../../contracts/solc/v0.8.19/DestinationVerifier/DestinationVerifier.abi ../../../contracts/solc/v0.8.19/DestinationVerifier/DestinationVerifier.bin 369323ce520923b9eb31ed90885f5ebd0f46b6799288fbf4da5d6ede7d697aef -destination_verifier_proxy: ../../../contracts/solc/v0.8.19/DestinationVerifierProxy/DestinationVerifierProxy.abi ../../../contracts/solc/v0.8.19/DestinationVerifierProxy/DestinationVerifierProxy.bin 4e255301cf6657777e7292eccea3e4c0ce65281404341e9248e095703a9fe392 -errored_verifier: ../../../contracts/solc/v0.8.19/ErroredVerifier/ErroredVerifier.abi ../../../contracts/solc/v0.8.19/ErroredVerifier/ErroredVerifier.bin ad8ac8d6b99890081725e2304d79d1ba7dd5212b89d130aa9689f4269eed4691 +configurator: ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/configuration/Configurator/Configurator.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/configuration/Configurator/Configurator.bin 7d1640ca82b55c743c7dea4040e4d353a85bcc4751f42c08e29f42742d81d704 +configurator_v0_5_0: ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/configuration/Configurator/Configurator.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/configuration/Configurator/Configurator.bin ee5ed0cd4f42636b6e008a12a8952c0efe3381094974e97269928eb13329c636 +destination_fee_manager: ../../../contracts/solc/v0.8.19/llo-feeds/v0.4.0/DestinationFeeManager/DestinationFeeManager.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.4.0/DestinationFeeManager/DestinationFeeManager.bin a56ae53e35e6610269f086b1e915ca1e80f5d0bf5695d09156e82fccfc2d77b3 +destination_reward_manager: ../../../contracts/solc/v0.8.19/llo-feeds/v0.4.0/DestinationRewardManager/DestinationRewardManager.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.4.0/DestinationRewardManager/DestinationRewardManager.bin 77874e97a54ecbd9c61132964da5b053f0b584dc7b774d75dd51baedd2bc7c40 +destination_verifier: ../../../contracts/solc/v0.8.19/llo-feeds/v0.4.0/DestinationVerifier/DestinationVerifier.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.4.0/DestinationVerifier/DestinationVerifier.bin 369323ce520923b9eb31ed90885f5ebd0f46b6799288fbf4da5d6ede7d697aef +destination_verifier_proxy: ../../../contracts/solc/v0.8.19/llo-feeds/v0.4.0/DestinationVerifierProxy/DestinationVerifierProxy.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.4.0/DestinationVerifierProxy/DestinationVerifierProxy.bin 4e255301cf6657777e7292eccea3e4c0ce65281404341e9248e095703a9fe392 +errored_verifier: ../../../contracts/solc/v0.8.19/llo-feeds/v0.3.0/test/mocks/ErroredVerifier/ErroredVerifier.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.3.0/test/mocks/ErroredVerifier/ErroredVerifier.bin ad8ac8d6b99890081725e2304d79d1ba7dd5212b89d130aa9689f4269eed4691 exposed_channel_verifier: ../../../contracts/solc/v0.8.19/ExposedChannelVerifier/ExposedChannelVerifier.abi ../../../contracts/solc/v0.8.19/ExposedChannelVerifier/ExposedChannelVerifier.bin c21cde078900241c06de69e2bc5d906c5ef558b52db66caa68bed065940a2253 -exposed_configurator: ../../../contracts/solc/v0.8.19/ExposedConfigurator/ExposedConfigurator.abi ../../../contracts/solc/v0.8.19/ExposedConfigurator/ExposedConfigurator.bin f1d4d7b812df5676bf0fd2a94187a9e871c19ed59b68aebb70ce8ee9bb4de42d -exposed_verifier: ../../../contracts/solc/v0.8.19/ExposedVerifier/ExposedVerifier.abi ../../../contracts/solc/v0.8.19/ExposedVerifier/ExposedVerifier.bin 00816ab345f768e522c79abadeadf9155c2c688067e18f8f73e5d6ab71037663 -fee_manager: ../../../contracts/solc/v0.8.19/FeeManager/FeeManager.abi ../../../contracts/solc/v0.8.19/FeeManager/FeeManager.bin edc85f34294ae7c90d45c4c71eb5c105c60a4842dfbbf700c692870ffcc403a1 +exposed_configurator: ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/configuration/test/mocks/ExposedConfigurator/ExposedConfigurator.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/configuration/test/mocks/ExposedConfigurator/ExposedConfigurator.bin f1d4d7b812df5676bf0fd2a94187a9e871c19ed59b68aebb70ce8ee9bb4de42d +exposed_configurator_v0_5_0: ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/configuration/test/mocks/ExposedConfigurator/ExposedConfigurator.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/configuration/test/mocks/ExposedConfigurator/ExposedConfigurator.bin f43362e7ef7588ecbd4d7ebd45b750cc4308e89c3d9e54fba1383e792213bbef +exposed_verifier: ../../../contracts/solc/v0.8.19/llo-feeds/v0.3.0/test/mocks/ExposedVerifier/ExposedVerifier.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.3.0/test/mocks/ExposedVerifier/ExposedVerifier.bin 00816ab345f768e522c79abadeadf9155c2c688067e18f8f73e5d6ab71037663 +fee_manager: ../../../contracts/solc/v0.8.19/llo-feeds/v0.3.0/FeeManager/FeeManager.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.3.0/FeeManager/FeeManager.bin edc85f34294ae7c90d45c4c71eb5c105c60a4842dfbbf700c692870ffcc403a1 +fee_manager_v0_5_0: ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/FeeManager/FeeManager.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/FeeManager/FeeManager.bin b5dfb3ac5e985d6412faf0fd21e2f5b0a759c983b3f0516f9c26cc9e4bbaed01 llo_feeds: ../../../contracts/solc/v0.8.19/FeeManager.abi ../../../contracts/solc/v0.8.19/FeeManager.bin cb71e018f67e49d7bc0e194c822204dfd59f79ff42e4fc8fd8ab63f3acd71361 llo_feeds_test: ../../../contracts/solc/v0.8.19/ExposedVerifier.abi ../../../contracts/solc/v0.8.19/ExposedVerifier.bin 6932cea8f2738e874d3ec9e1a4231d2421704030c071d9e15dd2f7f08482c246 -reward_manager: ../../../contracts/solc/v0.8.19/RewardManager/RewardManager.abi ../../../contracts/solc/v0.8.19/RewardManager/RewardManager.bin 7996cbc89a7f9af85b1ca4079ecf782d7138626b3f4bdb3bfa996248c9ccb9f4 +reward_manager: ../../../contracts/solc/v0.8.19/llo-feeds/v0.3.0/RewardManager/RewardManager.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.3.0/RewardManager/RewardManager.bin 7996cbc89a7f9af85b1ca4079ecf782d7138626b3f4bdb3bfa996248c9ccb9f4 +reward_manager_v0_5_0: ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/RewardManager/RewardManager.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/RewardManager/RewardManager.bin 7996cbc89a7f9af85b1ca4079ecf782d7138626b3f4bdb3bfa996248c9ccb9f4 stream_config_store: ../../../contracts/solc/v0.8.19/StreamConfigStore/StreamConfigStore.abi ../../../contracts/solc/v0.8.19/StreamConfigStore/StreamConfigStore.bin 45ae1b0a45a90b3dee076023052aef73c212c8ef8825b829397f751f6b0a1598 -verifier: ../../../contracts/solc/v0.8.19/Verifier/Verifier.abi ../../../contracts/solc/v0.8.19/Verifier/Verifier.bin 413406be1578e9fb73e664ceb1967e6aedf5cf7c4701a2b81fe7c42b03f13573 -verifier_proxy: ../../../contracts/solc/v0.8.19/VerifierProxy/VerifierProxy.abi ../../../contracts/solc/v0.8.19/VerifierProxy/VerifierProxy.bin aca18e93b0129114f20c4c0fbaeb61c86bc0ca0724bc438ec7ae11c158038ea7 +verifier: ../../../contracts/solc/v0.8.19/llo-feeds/v0.3.0/Verifier/Verifier.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.3.0/Verifier/Verifier.bin 413406be1578e9fb73e664ceb1967e6aedf5cf7c4701a2b81fe7c42b03f13573 +verifier_proxy: ../../../contracts/solc/v0.8.19/llo-feeds/v0.3.0/VerifierProxy/VerifierProxy.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.3.0/VerifierProxy/VerifierProxy.bin aca18e93b0129114f20c4c0fbaeb61c86bc0ca0724bc438ec7ae11c158038ea7 +verifier_proxy_v0_5_0: ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/VerifierProxy/VerifierProxy.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/VerifierProxy/VerifierProxy.bin aca18e93b0129114f20c4c0fbaeb61c86bc0ca0724bc438ec7ae11c158038ea7 +verifier_v0_5_0: ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/Verifier/Verifier.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/Verifier/Verifier.bin 18d894dbbec00fc9d42dc8e61ee3c428e94d3c375552f1c5d1b39cfa5c9535ad werc20_mock: ../../../contracts/solc/v0.8.19/WERC20Mock.abi ../../../contracts/solc/v0.8.19/WERC20Mock.bin ff2ca3928b2aa9c412c892cb8226c4d754c73eeb291bb7481c32c48791b2aa94 diff --git a/core/gethwrappers/llo-feeds/go_generate.go b/core/gethwrappers/llo-feeds/go_generate.go index 5bc29f36dea..9a0fd295b98 100644 --- a/core/gethwrappers/llo-feeds/go_generate.go +++ b/core/gethwrappers/llo-feeds/go_generate.go @@ -2,19 +2,26 @@ // golang packages, using abigen. package gethwrappers -// Chainlink LLO -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/Verifier/Verifier.abi ../../../contracts/solc/v0.8.19/Verifier/Verifier.bin Verifier verifier -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/VerifierProxy/VerifierProxy.abi ../../../contracts/solc/v0.8.19/VerifierProxy/VerifierProxy.bin VerifierProxy verifier_proxy -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/ErroredVerifier/ErroredVerifier.abi ../../../contracts/solc/v0.8.19/ErroredVerifier/ErroredVerifier.bin ErroredVerifier errored_verifier -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/ExposedVerifier/ExposedVerifier.abi ../../../contracts/solc/v0.8.19/ExposedVerifier/ExposedVerifier.bin ExposedVerifier exposed_verifier -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/RewardManager/RewardManager.abi ../../../contracts/solc/v0.8.19/RewardManager/RewardManager.bin RewardManager reward_manager -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/FeeManager/FeeManager.abi ../../../contracts/solc/v0.8.19/FeeManager/FeeManager.bin FeeManager fee_manager -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/ChannelConfigStore/ChannelConfigStore.abi ../../../contracts/solc/v0.8.19/ChannelConfigStore/ChannelConfigStore.bin ChannelConfigStore channel_config_store +// Chainlink LLO V0.3.0 +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/llo-feeds/v0.3.0/Verifier/Verifier.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.3.0/Verifier/Verifier.bin Verifier verifier +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/llo-feeds/v0.3.0/VerifierProxy/VerifierProxy.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.3.0/VerifierProxy/VerifierProxy.bin VerifierProxy verifier_proxy +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/llo-feeds/v0.3.0/RewardManager/RewardManager.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.3.0/RewardManager/RewardManager.bin RewardManager reward_manager +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/llo-feeds/v0.3.0/FeeManager/FeeManager.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.3.0/FeeManager/FeeManager.bin FeeManager fee_manager +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/llo-feeds/v0.3.0/test/mocks/ErroredVerifier/ErroredVerifier.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.3.0/test/mocks/ErroredVerifier/ErroredVerifier.bin ErroredVerifier errored_verifier +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/llo-feeds/v0.3.0/test/mocks/ExposedVerifier/ExposedVerifier.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.3.0/test/mocks/ExposedVerifier/ExposedVerifier.bin ExposedVerifier exposed_verifier -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/DestinationVerifier/DestinationVerifier.abi ../../../contracts/solc/v0.8.19/DestinationVerifier/DestinationVerifier.bin DestinationVerifier destination_verifier -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/DestinationVerifierProxy/DestinationVerifierProxy.abi ../../../contracts/solc/v0.8.19/DestinationVerifierProxy/DestinationVerifierProxy.bin DestinationVerifierProxy destination_verifier_proxy -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/DestinationFeeManager/DestinationFeeManager.abi ../../../contracts/solc/v0.8.19/DestinationFeeManager/DestinationFeeManager.bin DestinationFeeManager destination_fee_manager -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/DestinationRewardManager/DestinationRewardManager.abi ../../../contracts/solc/v0.8.19/DestinationRewardManager/DestinationRewardManager.bin DestinationRewardManager destination_reward_manager -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/Configurator/Configurator.abi ../../../contracts/solc/v0.8.19/Configurator/Configurator.bin Configurator configurator +// Chainlink LLO V0.4.0 +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/llo-feeds/v0.4.0/DestinationVerifier/DestinationVerifier.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.4.0/DestinationVerifier/DestinationVerifier.bin DestinationVerifier destination_verifier +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/llo-feeds/v0.4.0/DestinationVerifierProxy/DestinationVerifierProxy.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.4.0/DestinationVerifierProxy/DestinationVerifierProxy.bin DestinationVerifierProxy destination_verifier_proxy +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/llo-feeds/v0.4.0/DestinationFeeManager/DestinationFeeManager.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.4.0/DestinationFeeManager/DestinationFeeManager.bin DestinationFeeManager destination_fee_manager +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/llo-feeds/v0.4.0/DestinationRewardManager/DestinationRewardManager.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.4.0/DestinationRewardManager/DestinationRewardManager.bin DestinationRewardManager destination_reward_manager -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/ExposedConfigurator/ExposedConfigurator.abi ../../../contracts/solc/v0.8.19/ExposedConfigurator/ExposedConfigurator.bin ExposedConfigurator exposed_configurator +// Chainlink LLO V0.5.0 +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/Verifier/Verifier.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/Verifier/Verifier.bin Verifier verifier_v0_5_0 +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/VerifierProxy/VerifierProxy.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/VerifierProxy/VerifierProxy.bin VerifierProxy verifier_proxy_v0_5_0 +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/FeeManager/FeeManager.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/FeeManager/FeeManager.bin FeeManager fee_manager_v0_5_0 +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/RewardManager/RewardManager.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/RewardManager/RewardManager.bin RewardManager reward_manager_v0_5_0 + +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/configuration/ChannelConfigStore/ChannelConfigStore.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/configuration/ChannelConfigStore/ChannelConfigStore.bin ChannelConfigStore channel_config_store +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/configuration/Configurator/Configurator.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/configuration/Configurator/Configurator.bin Configurator configurator +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/configuration/test/mocks/ExposedConfigurator/ExposedConfigurator.abi ../../../contracts/solc/v0.8.19/llo-feeds/v0.5.0/configuration/test/mocks/ExposedConfigurator/ExposedConfigurator.bin ExposedConfigurator exposed_configurator diff --git a/core/gethwrappers/generated/aggregator_v3_interface/aggregator_v3_interface.go b/core/gethwrappers/shared/generated/aggregator_v3_interface/aggregator_v3_interface.go similarity index 87% rename from core/gethwrappers/generated/aggregator_v3_interface/aggregator_v3_interface.go rename to core/gethwrappers/shared/generated/aggregator_v3_interface/aggregator_v3_interface.go index 5daccaf84b5..7c14c14ed2d 100644 --- a/core/gethwrappers/generated/aggregator_v3_interface/aggregator_v3_interface.go +++ b/core/gethwrappers/shared/generated/aggregator_v3_interface/aggregator_v3_interface.go @@ -29,7 +29,7 @@ var ( ) var AggregatorV3InterfaceMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"description\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint80\",\"name\":\"_roundId\",\"type\":\"uint80\"}],\"name\":\"getRoundData\",\"outputs\":[{\"internalType\":\"uint80\",\"name\":\"roundId\",\"type\":\"uint80\"},{\"internalType\":\"int256\",\"name\":\"answer\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"startedAt\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"updatedAt\",\"type\":\"uint256\"},{\"internalType\":\"uint80\",\"name\":\"answeredInRound\",\"type\":\"uint80\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestRoundData\",\"outputs\":[{\"internalType\":\"uint80\",\"name\":\"roundId\",\"type\":\"uint80\"},{\"internalType\":\"int256\",\"name\":\"answer\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"startedAt\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"updatedAt\",\"type\":\"uint256\"},{\"internalType\":\"uint80\",\"name\":\"answeredInRound\",\"type\":\"uint80\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + ABI: "[{\"type\":\"function\",\"name\":\"decimals\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"description\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRoundData\",\"inputs\":[{\"name\":\"_roundId\",\"type\":\"uint80\",\"internalType\":\"uint80\"}],\"outputs\":[{\"name\":\"roundId\",\"type\":\"uint80\",\"internalType\":\"uint80\"},{\"name\":\"answer\",\"type\":\"int256\",\"internalType\":\"int256\"},{\"name\":\"startedAt\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"updatedAt\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"answeredInRound\",\"type\":\"uint80\",\"internalType\":\"uint80\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"latestRoundData\",\"inputs\":[],\"outputs\":[{\"name\":\"roundId\",\"type\":\"uint80\",\"internalType\":\"uint80\"},{\"name\":\"answer\",\"type\":\"int256\",\"internalType\":\"int256\"},{\"name\":\"startedAt\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"updatedAt\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"answeredInRound\",\"type\":\"uint80\",\"internalType\":\"uint80\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"version\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"}]", } var AggregatorV3InterfaceABI = AggregatorV3InterfaceMetaData.ABI diff --git a/core/gethwrappers/shared/generated/burn_mint_erc20/burn_mint_erc20.go b/core/gethwrappers/shared/generated/burn_mint_erc20/burn_mint_erc20.go index 9780521156e..22072a87895 100644 --- a/core/gethwrappers/shared/generated/burn_mint_erc20/burn_mint_erc20.go +++ b/core/gethwrappers/shared/generated/burn_mint_erc20/burn_mint_erc20.go @@ -31,7 +31,7 @@ var ( ) var BurnMintERC20MetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"decimals_\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"maxSupply_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preMint\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"InvalidRecipient\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"supplyAfterMint\",\"type\":\"uint256\"}],\"name\":\"MaxSupplyExceeded\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"CCIPAdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BURNER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MINTER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burnFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCCIPAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"burnAndMinter\",\"type\":\"address\"}],\"name\":\"grantMintAndBurnRoles\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"setCCIPAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"name\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"symbol\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"decimals_\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"maxSupply_\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"preMint\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"BURNER_ROLE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"DEFAULT_ADMIN_ROLE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"MINTER_ROLE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"allowance\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"approve\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"balanceOf\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"burn\",\"inputs\":[{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"burn\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"burnFrom\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"decimals\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"decreaseAllowance\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"subtractedValue\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getCCIPAdmin\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRoleAdmin\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"grantMintAndBurnRoles\",\"inputs\":[{\"name\":\"burnAndMinter\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"grantRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"hasRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"increaseAllowance\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"addedValue\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"maxSupply\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"mint\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"name\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"renounceRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"revokeRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setCCIPAdmin\",\"inputs\":[{\"name\":\"newAdmin\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"symbol\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"totalSupply\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transfer\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferFrom\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"Approval\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"spender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"CCIPAdminTransferred\",\"inputs\":[{\"name\":\"previousAdmin\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newAdmin\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RoleAdminChanged\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"previousAdminRole\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"newAdminRole\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RoleGranted\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RoleRevoked\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Transfer\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"InvalidRecipient\",\"inputs\":[{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"MaxSupplyExceeded\",\"inputs\":[{\"name\":\"supplyAfterMint\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}]", Bin: "0x60c06040523480156200001157600080fd5b5060405162002260380380620022608339810160408190526200003491620002e7565b848460036200004483826200040b565b5060046200005382826200040b565b50505060ff831660805260a0829052600680546001600160a01b03191633179055801562000087576200008733826200009f565b6200009460003362000166565b5050505050620004f9565b6001600160a01b038216620000fa5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640160405180910390fd5b80600260008282546200010e9190620004d7565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35b5050565b620001728282620001f5565b620001625760008281526005602090815260408083206001600160a01b03851684529091529020805460ff19166001179055620001ac3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b505050565b60008281526005602090815260408083206001600160a01b038516845290915290205460ff165b92915050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200024a57600080fd5b81516001600160401b038082111562000267576200026762000222565b604051601f8301601f19908116603f0116810190828211818310171562000292576200029262000222565b81604052838152602092508683858801011115620002af57600080fd5b600091505b83821015620002d35785820183015181830184015290820190620002b4565b600093810190920192909252949350505050565b600080600080600060a086880312156200030057600080fd5b85516001600160401b03808211156200031857600080fd5b6200032689838a0162000238565b965060208801519150808211156200033d57600080fd5b506200034c8882890162000238565b945050604086015160ff811681146200036457600080fd5b6060870151608090970151959894975095949392505050565b600181811c908216806200039257607f821691505b602082108103620003b357634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620001f057600081815260208120601f850160051c81016020861015620003e25750805b601f850160051c820191505b818110156200040357828155600101620003ee565b505050505050565b81516001600160401b0381111562000427576200042762000222565b6200043f816200043884546200037d565b84620003b9565b602080601f8311600181146200047757600084156200045e5750858301515b600019600386901b1c1916600185901b17855562000403565b600085815260208120601f198616915b82811015620004a85788860151825594840194600190910190840162000487565b5085821015620004c75787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b808201808211156200021c57634e487b7160e01b600052601160045260246000fd5b60805160a051611d336200052d6000396000818161047c015281816108f2015261091c015260006102a40152611d336000f3fe608060405234801561001057600080fd5b50600436106101c45760003560e01c806379cc6790116100f9578063a8fa343c11610097578063d539139311610071578063d539139314610440578063d547741f14610467578063d5abeb011461047a578063dd62ed3e146104a057600080fd5b8063a8fa343c14610407578063a9059cbb1461041a578063c630948d1461042d57600080fd5b806395d89b41116100d357806395d89b41146103d15780639dc29fac146103d9578063a217fddf146103ec578063a457c2d7146103f457600080fd5b806379cc6790146103505780638fd6a6ac1461036357806391d148541461038b57600080fd5b80632f2ff15d11610166578063395093511161014057806339509351146102e157806340c10f19146102f457806342966c681461030757806370a082311461031a57600080fd5b80632f2ff15d14610288578063313ce5671461029d57806336568abe146102ce57600080fd5b806318160ddd116101a257806318160ddd1461021957806323b872dd1461022b578063248a9ca31461023e578063282c51f31461026157600080fd5b806301ffc9a7146101c957806306fdde03146101f1578063095ea7b314610206575b600080fd5b6101dc6101d7366004611996565b6104e6565b60405190151581526020015b60405180910390f35b6101f9610663565b6040516101e891906119fc565b6101dc610214366004611a76565b6106f5565b6002545b6040519081526020016101e8565b6101dc610239366004611aa0565b61070d565b61021d61024c366004611adc565b60009081526005602052604090206001015490565b61021d7f3c11d16cbaffd01df69ce1c404f6340ee057498f5f00246190ea54220576a84881565b61029b610296366004611af5565b610731565b005b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016101e8565b61029b6102dc366004611af5565b61075b565b6101dc6102ef366004611a76565b610813565b61029b610302366004611a76565b61085f565b61029b610315366004611adc565b6109a9565b61021d610328366004611b21565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b61029b61035e366004611a76565b6109dc565b60065460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101e8565b6101dc610399366004611af5565b600091825260056020908152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b6101f9610a10565b61029b6103e7366004611a76565b610a1f565b61021d600081565b6101dc610402366004611a76565b610a29565b61029b610415366004611b21565b610afa565b6101dc610428366004611a76565b610b7d565b61029b61043b366004611b21565b610b8b565b61021d7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b61029b610475366004611af5565b610be2565b7f000000000000000000000000000000000000000000000000000000000000000061021d565b61021d6104ae366004611b3c565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f36372b0700000000000000000000000000000000000000000000000000000000148061057957507fffffffff0000000000000000000000000000000000000000000000000000000082167fe6599b4d00000000000000000000000000000000000000000000000000000000145b806105c557507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b8061061157507fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000145b8061065d57507fffffffff0000000000000000000000000000000000000000000000000000000082167f8fd6a6ac00000000000000000000000000000000000000000000000000000000145b92915050565b60606003805461067290611b66565b80601f016020809104026020016040519081016040528092919081815260200182805461069e90611b66565b80156106eb5780601f106106c0576101008083540402835291602001916106eb565b820191906000526020600020905b8154815290600101906020018083116106ce57829003601f168201915b5050505050905090565b600033610703818585610c07565b5060019392505050565b60003361071b858285610c79565b610726858585610d50565b506001949350505050565b60008281526005602052604090206001015461074c81610dc2565b6107568383610dcc565b505050565b73ffffffffffffffffffffffffffffffffffffffff81163314610805576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084015b60405180910390fd5b61080f8282610ec0565b5050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152812054909190610703908290869061085a908790611be8565b610c07565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a661088981610dc2565b3073ffffffffffffffffffffffffffffffffffffffff8416036108f0576040517f17858bbe00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024016107fc565b7f00000000000000000000000000000000000000000000000000000000000000001580159061095157507f00000000000000000000000000000000000000000000000000000000000000008261094560025490565b61094f9190611be8565b115b1561099f578161096060025490565b61096a9190611be8565b6040517fcbbf11130000000000000000000000000000000000000000000000000000000081526004016107fc91815260200190565b6107568383610f7b565b7f3c11d16cbaffd01df69ce1c404f6340ee057498f5f00246190ea54220576a8486109d381610dc2565b61080f8261106e565b7f3c11d16cbaffd01df69ce1c404f6340ee057498f5f00246190ea54220576a848610a0681610dc2565b6107568383611078565b60606004805461067290611b66565b61080f82826109dc565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610aed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016107fc565b6107268286868403610c07565b6000610b0581610dc2565b6006805473ffffffffffffffffffffffffffffffffffffffff8481167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f9524c9e4b0b61eb018dd58a1cd856e3e74009528328ab4a613b434fa631d724290600090a3505050565b600033610703818585610d50565b610bb57f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a682610731565b610bdf7f3c11d16cbaffd01df69ce1c404f6340ee057498f5f00246190ea54220576a84882610731565b50565b600082815260056020526040902060010154610bfd81610dc2565b6107568383610ec0565b3073ffffffffffffffffffffffffffffffffffffffff831603610c6e576040517f17858bbe00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024016107fc565b61075683838361108d565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610d4a5781811015610d3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016107fc565b610d4a8484848403610c07565b50505050565b3073ffffffffffffffffffffffffffffffffffffffff831603610db7576040517f17858bbe00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024016107fc565b610756838383611240565b610bdf81336114af565b600082815260056020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff1661080f57600082815260056020908152604080832073ffffffffffffffffffffffffffffffffffffffff85168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055610e623390565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b600082815260056020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff161561080f57600082815260056020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b73ffffffffffffffffffffffffffffffffffffffff8216610ff8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016107fc565b806002600082825461100a9190611be8565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b610bdf3382611569565b611083823383610c79565b61080f8282611569565b73ffffffffffffffffffffffffffffffffffffffff831661112f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016107fc565b73ffffffffffffffffffffffffffffffffffffffff82166111d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016107fc565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff83166112e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016107fc565b73ffffffffffffffffffffffffffffffffffffffff8216611386576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016107fc565b73ffffffffffffffffffffffffffffffffffffffff83166000908152602081905260409020548181101561143c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016107fc565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610d4a565b600082815260056020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff1661080f576114ef8161172d565b6114fa83602061174c565b60405160200161150b929190611bfb565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a00000000000000000000000000000000000000000000000000000000082526107fc916004016119fc565b73ffffffffffffffffffffffffffffffffffffffff821661160c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016107fc565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054818110156116c2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016107fc565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b606061065d73ffffffffffffffffffffffffffffffffffffffff831660145b6060600061175b836002611c7c565b611766906002611be8565b67ffffffffffffffff81111561177e5761177e611c93565b6040519080825280601f01601f1916602001820160405280156117a8576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000816000815181106117df576117df611cc2565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061184257611842611cc2565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600061187e846002611c7c565b611889906001611be8565b90505b6001811115611926577f303132333435363738396162636465660000000000000000000000000000000085600f16601081106118ca576118ca611cc2565b1a60f81b8282815181106118e0576118e0611cc2565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c9361191f81611cf1565b905061188c565b50831561198f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016107fc565b9392505050565b6000602082840312156119a857600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461198f57600080fd5b60005b838110156119f35781810151838201526020016119db565b50506000910152565b6020815260008251806020840152611a1b8160408501602087016119d8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611a7157600080fd5b919050565b60008060408385031215611a8957600080fd5b611a9283611a4d565b946020939093013593505050565b600080600060608486031215611ab557600080fd5b611abe84611a4d565b9250611acc60208501611a4d565b9150604084013590509250925092565b600060208284031215611aee57600080fd5b5035919050565b60008060408385031215611b0857600080fd5b82359150611b1860208401611a4d565b90509250929050565b600060208284031215611b3357600080fd5b61198f82611a4d565b60008060408385031215611b4f57600080fd5b611b5883611a4d565b9150611b1860208401611a4d565b600181811c90821680611b7a57607f821691505b602082108103611bb3577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561065d5761065d611bb9565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351611c338160178501602088016119d8565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351611c708160288401602088016119d8565b01602801949350505050565b808202811582820484141761065d5761065d611bb9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081611d0057611d00611bb9565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea164736f6c6343000813000a", } diff --git a/core/gethwrappers/shared/generated/burn_mint_erc677/burn_mint_erc677.go b/core/gethwrappers/shared/generated/burn_mint_erc677/burn_mint_erc677.go index 1d5b1c4ab17..ca4edccfd25 100644 --- a/core/gethwrappers/shared/generated/burn_mint_erc677/burn_mint_erc677.go +++ b/core/gethwrappers/shared/generated/burn_mint_erc677/burn_mint_erc677.go @@ -31,7 +31,7 @@ var ( ) var BurnMintERC677MetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"decimals_\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"maxSupply_\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"supplyAfterMint\",\"type\":\"uint256\"}],\"name\":\"MaxSupplyExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotBurner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotMinter\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"burner\",\"type\":\"address\"}],\"name\":\"BurnAccessGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"burner\",\"type\":\"address\"}],\"name\":\"BurnAccessRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"}],\"name\":\"MintAccessGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"}],\"name\":\"MintAccessRevoked\",\"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\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burnFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseApproval\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBurners\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getMinters\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"burner\",\"type\":\"address\"}],\"name\":\"grantBurnRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"burnAndMinter\",\"type\":\"address\"}],\"name\":\"grantMintAndBurnRoles\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"}],\"name\":\"grantMintRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseApproval\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"burner\",\"type\":\"address\"}],\"name\":\"isBurner\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"}],\"name\":\"isMinter\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"burner\",\"type\":\"address\"}],\"name\":\"revokeBurnRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"}],\"name\":\"revokeMintRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"transferAndCall\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"name\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"symbol\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"decimals_\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"maxSupply_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"acceptOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"allowance\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"approve\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"balanceOf\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"burn\",\"inputs\":[{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"burn\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"burnFrom\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"decimals\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"decreaseAllowance\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"subtractedValue\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"decreaseApproval\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"subtractedValue\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"success\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getBurners\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getMinters\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"grantBurnRole\",\"inputs\":[{\"name\":\"burner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"grantMintAndBurnRoles\",\"inputs\":[{\"name\":\"burnAndMinter\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"grantMintRole\",\"inputs\":[{\"name\":\"minter\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"increaseAllowance\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"addedValue\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"increaseApproval\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"addedValue\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"isBurner\",\"inputs\":[{\"name\":\"burner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isMinter\",\"inputs\":[{\"name\":\"minter\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"maxSupply\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"mint\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"name\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"revokeBurnRole\",\"inputs\":[{\"name\":\"burner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"revokeMintRole\",\"inputs\":[{\"name\":\"minter\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"symbol\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"totalSupply\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transfer\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferAndCall\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"success\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferFrom\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"Approval\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"spender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"BurnAccessGranted\",\"inputs\":[{\"name\":\"burner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"BurnAccessRevoked\",\"inputs\":[{\"name\":\"burner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"MintAccessGranted\",\"inputs\":[{\"name\":\"minter\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"MintAccessRevoked\",\"inputs\":[{\"name\":\"minter\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferRequested\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Transfer\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Transfer\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"MaxSupplyExceeded\",\"inputs\":[{\"name\":\"supplyAfterMint\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"SenderNotBurner\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"SenderNotMinter\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"}]}]", Bin: "0x60c06040523480156200001157600080fd5b50604051620022dd380380620022dd833981016040819052620000349162000277565b338060008686818160036200004a838262000391565b50600462000059828262000391565b5050506001600160a01b0384169150620000bc90505760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0384811691909117909155811615620000ef57620000ef8162000106565b50505060ff90911660805260a052506200045d9050565b336001600160a01b03821603620001605760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620000b3565b600680546001600160a01b0319166001600160a01b03838116918217909255600554604051919216907fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae127890600090a350565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001da57600080fd5b81516001600160401b0380821115620001f757620001f7620001b2565b604051601f8301601f19908116603f01168101908282118183101715620002225762000222620001b2565b816040528381526020925086838588010111156200023f57600080fd5b600091505b8382101562000263578582018301518183018401529082019062000244565b600093810190920192909252949350505050565b600080600080608085870312156200028e57600080fd5b84516001600160401b0380821115620002a657600080fd5b620002b488838901620001c8565b95506020870151915080821115620002cb57600080fd5b50620002da87828801620001c8565b935050604085015160ff81168114620002f257600080fd5b6060959095015193969295505050565b600181811c908216806200031757607f821691505b6020821081036200033857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200038c57600081815260208120601f850160051c81016020861015620003675750805b601f850160051c820191505b81811015620003885782815560010162000373565b5050505b505050565b81516001600160401b03811115620003ad57620003ad620001b2565b620003c581620003be845462000302565b846200033e565b602080601f831160018114620003fd5760008415620003e45750858301515b600019600386901b1c1916600185901b17855562000388565b600085815260208120601f198616915b828110156200042e578886015182559484019460019091019084016200040d565b50858210156200044d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a051611e4c6200049160003960008181610447015281816108c301526108ed015260006102710152611e4c6000f3fe608060405234801561001057600080fd5b50600436106101f05760003560e01c806379cc67901161010f578063c2e3273d116100a2578063d73dd62311610071578063d73dd6231461046b578063dd62ed3e1461047e578063f2fde38b146104c4578063f81094f3146104d757600080fd5b8063c2e3273d1461040c578063c630948d1461041f578063c64d0ebc14610432578063d5abeb011461044557600080fd5b80639dc29fac116100de5780639dc29fac146103c0578063a457c2d7146103d3578063a9059cbb146103e6578063aa271e1a146103f957600080fd5b806379cc67901461037557806386fe8b43146103885780638da5cb5b1461039057806395d89b41146103b857600080fd5b806340c10f19116101875780636618846311610156578063661884631461030f5780636b32810b1461032257806370a082311461033757806379ba50971461036d57600080fd5b806340c10f19146102c157806342966c68146102d65780634334614a146102e95780634f5632f8146102fc57600080fd5b806323b872dd116101c357806323b872dd14610257578063313ce5671461026a578063395093511461029b5780634000aea0146102ae57600080fd5b806301ffc9a7146101f557806306fdde031461021d578063095ea7b31461023257806318160ddd14610245575b600080fd5b6102086102033660046119b9565b6104ea565b60405190151581526020015b60405180910390f35b61022561061b565b6040516102149190611a5f565b610208610240366004611a9b565b6106ad565b6002545b604051908152602001610214565b610208610265366004611ac5565b6106c5565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610214565b6102086102a9366004611a9b565b6106e9565b6102086102bc366004611b30565b610735565b6102d46102cf366004611a9b565b610858565b005b6102d46102e4366004611c19565b61097f565b6102086102f7366004611c32565b6109cc565b6102d461030a366004611c32565b6109d9565b61020861031d366004611a9b565b610a35565b61032a610a48565b6040516102149190611c4d565b610249610345366004611c32565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6102d4610a59565b6102d4610383366004611a9b565b610b5a565b61032a610ba9565b60055460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610214565b610225610bb5565b6102d46103ce366004611a9b565b610bc4565b6102086103e1366004611a9b565b610bce565b6102086103f4366004611a9b565b610c9f565b610208610407366004611c32565b610cad565b6102d461041a366004611c32565b610cba565b6102d461042d366004611c32565b610d16565b6102d4610440366004611c32565b610d24565b7f0000000000000000000000000000000000000000000000000000000000000000610249565b6102d4610479366004611a9b565b610d80565b61024961048c366004611ca7565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6102d46104d2366004611c32565b610d8a565b6102d46104e5366004611c32565b610d9b565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f36372b0700000000000000000000000000000000000000000000000000000000148061057d57507fffffffff0000000000000000000000000000000000000000000000000000000082167f4000aea000000000000000000000000000000000000000000000000000000000145b806105c957507fffffffff0000000000000000000000000000000000000000000000000000000082167fe6599b4d00000000000000000000000000000000000000000000000000000000145b8061061557507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b60606003805461062a90611cda565b80601f016020809104026020016040519081016040528092919081815260200182805461065690611cda565b80156106a35780601f10610678576101008083540402835291602001916106a3565b820191906000526020600020905b81548152906001019060200180831161068657829003601f168201915b5050505050905090565b6000336106bb818585610df7565b5060019392505050565b6000336106d3858285610e2b565b6106de858585610efc565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906106bb9082908690610730908790611d5c565b610df7565b60006107418484610c9f565b508373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fe19260aff97b920c7df27010903aeb9c8d2be5d310a2c67824cf3f15396e4c1685856040516107a1929190611d6f565b60405180910390a373ffffffffffffffffffffffffffffffffffffffff84163b156106bb576040517fa4c0ed3600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85169063a4c0ed369061081c90339087908790600401611d90565b600060405180830381600087803b15801561083657600080fd5b505af115801561084a573d6000803e3d6000fd5b505050505060019392505050565b61086133610cad565b61089e576040517fe2c8c9d50000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b813073ffffffffffffffffffffffffffffffffffffffff8216036108c157600080fd5b7f00000000000000000000000000000000000000000000000000000000000000001580159061092257507f00000000000000000000000000000000000000000000000000000000000000008261091660025490565b6109209190611d5c565b115b15610970578161093160025490565b61093b9190611d5c565b6040517fcbbf111300000000000000000000000000000000000000000000000000000000815260040161089591815260200190565b61097a8383610f2a565b505050565b610988336109cc565b6109c0576040517fc820b10b000000000000000000000000000000000000000000000000000000008152336004820152602401610895565b6109c98161101d565b50565b6000610615600983611027565b6109e1611056565b6109ec6009826110d9565b156109c95760405173ffffffffffffffffffffffffffffffffffffffff8216907f0a675452746933cefe3d74182e78db7afe57ba60eaa4234b5d85e9aa41b0610c90600090a250565b6000610a418383610bce565b9392505050565b6060610a5460076110fb565b905090565b60065473ffffffffffffffffffffffffffffffffffffffff163314610ada576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610895565b600580547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560068054909116905560405173ffffffffffffffffffffffffffffffffffffffff909116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a350565b610b63336109cc565b610b9b576040517fc820b10b000000000000000000000000000000000000000000000000000000008152336004820152602401610895565b610ba58282611108565b5050565b6060610a5460096110fb565b60606004805461062a90611cda565b610ba58282610b5a565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610c92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610895565b6106de8286868403610df7565b6000336106bb818585610efc565b6000610615600783611027565b610cc2611056565b610ccd60078261111d565b156109c95760405173ffffffffffffffffffffffffffffffffffffffff8216907fe46fef8bbff1389d9010703cf8ebb363fb3daf5bf56edc27080b67bc8d9251ea90600090a250565b610d1f81610cba565b6109c9815b610d2c611056565b610d3760098261111d565b156109c95760405173ffffffffffffffffffffffffffffffffffffffff8216907f92308bb7573b2a3d17ddb868b39d8ebec433f3194421abc22d084f89658c9bad90600090a250565b61097a82826106e9565b610d92611056565b6109c98161113f565b610da3611056565b610dae6007826110d9565b156109c95760405173ffffffffffffffffffffffffffffffffffffffff8216907fed998b960f6340d045f620c119730f7aa7995e7425c2401d3a5b64ff998a59e990600090a250565b813073ffffffffffffffffffffffffffffffffffffffff821603610e1a57600080fd5b610e25848484611235565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610e255781811015610eef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610895565b610e258484848403610df7565b813073ffffffffffffffffffffffffffffffffffffffff821603610f1f57600080fd5b610e258484846113e8565b73ffffffffffffffffffffffffffffffffffffffff8216610fa7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610895565b8060026000828254610fb99190611d5c565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b6109c93382611657565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610a41565b60055473ffffffffffffffffffffffffffffffffffffffff1633146110d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610895565b565b6000610a418373ffffffffffffffffffffffffffffffffffffffff841661181b565b60606000610a418361190e565b611113823383610e2b565b610ba58282611657565b6000610a418373ffffffffffffffffffffffffffffffffffffffff841661196a565b3373ffffffffffffffffffffffffffffffffffffffff8216036111be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610895565b600680547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217909255600554604051919216907fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae127890600090a350565b73ffffffffffffffffffffffffffffffffffffffff83166112d7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610895565b73ffffffffffffffffffffffffffffffffffffffff821661137a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610895565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff831661148b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610895565b73ffffffffffffffffffffffffffffffffffffffff821661152e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610895565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040902054818110156115e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610895565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610e25565b73ffffffffffffffffffffffffffffffffffffffff82166116fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610895565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054818110156117b0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610895565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b6000818152600183016020526040812054801561190457600061183f600183611dce565b855490915060009061185390600190611dce565b90508181146118b857600086600001828154811061187357611873611de1565b906000526020600020015490508087600001848154811061189657611896611de1565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806118c9576118c9611e10565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610615565b6000915050610615565b60608160000180548060200260200160405190810160405280929190818152602001828054801561195e57602002820191906000526020600020905b81548152602001906001019080831161194a575b50505050509050919050565b60008181526001830160205260408120546119b157508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610615565b506000610615565b6000602082840312156119cb57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610a4157600080fd5b6000815180845260005b81811015611a2157602081850181015186830182015201611a05565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610a4160208301846119fb565b803573ffffffffffffffffffffffffffffffffffffffff81168114611a9657600080fd5b919050565b60008060408385031215611aae57600080fd5b611ab783611a72565b946020939093013593505050565b600080600060608486031215611ada57600080fd5b611ae384611a72565b9250611af160208501611a72565b9150604084013590509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060608486031215611b4557600080fd5b611b4e84611a72565b925060208401359150604084013567ffffffffffffffff80821115611b7257600080fd5b818601915086601f830112611b8657600080fd5b813581811115611b9857611b98611b01565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611bde57611bde611b01565b81604052828152896020848701011115611bf757600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b600060208284031215611c2b57600080fd5b5035919050565b600060208284031215611c4457600080fd5b610a4182611a72565b6020808252825182820181905260009190848201906040850190845b81811015611c9b57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101611c69565b50909695505050505050565b60008060408385031215611cba57600080fd5b611cc383611a72565b9150611cd160208401611a72565b90509250929050565b600181811c90821680611cee57607f821691505b602082108103611d27577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561061557610615611d2d565b828152604060208201526000611d8860408301846119fb565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff84168152826020820152606060408201526000611dc560608301846119fb565b95945050505050565b8181038181111561061557610615611d2d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000813000a", } diff --git a/core/gethwrappers/generated/chain_reader_tester/chain_reader_tester.go b/core/gethwrappers/shared/generated/chain_reader_tester/chain_reader_tester.go similarity index 80% rename from core/gethwrappers/generated/chain_reader_tester/chain_reader_tester.go rename to core/gethwrappers/shared/generated/chain_reader_tester/chain_reader_tester.go index 407858373c9..b49f14c0a5c 100644 --- a/core/gethwrappers/generated/chain_reader_tester/chain_reader_tester.go +++ b/core/gethwrappers/shared/generated/chain_reader_tester/chain_reader_tester.go @@ -68,7 +68,7 @@ type TestStruct struct { } var ChainReaderTesterMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"StaticBytes\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"int32\",\"name\":\"field\",\"type\":\"int32\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"oracleId\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"string\",\"name\":\"S\",\"type\":\"string\"}],\"internalType\":\"structInnerDynamicTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"indexed\":false,\"internalType\":\"structMidLevelDynamicTestStruct\",\"name\":\"nestedDynamicStruct\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"address\",\"name\":\"A\",\"type\":\"address\"}],\"internalType\":\"structInnerStaticTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"indexed\":false,\"internalType\":\"structMidLevelStaticTestStruct\",\"name\":\"nestedStaticStruct\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint8[32]\",\"name\":\"oracleIds\",\"type\":\"uint8[32]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"AccountStr\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structAccountStruct\",\"name\":\"accountStruct\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"Accounts\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"differentField\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"int192\",\"name\":\"bigField\",\"type\":\"int192\"}],\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"string\",\"name\":\"field1\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint8[32]\",\"name\":\"field2\",\"type\":\"uint8[32]\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"field3\",\"type\":\"bytes32\"}],\"name\":\"TriggeredWithFourTopicsWithHashed\",\"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]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"AccountStr\",\"type\":\"address\"}],\"internalType\":\"structAccountStruct\",\"name\":\"accountStruct\",\"type\":\"tuple\"},{\"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\":\"structInnerDynamicTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelDynamicTestStruct\",\"name\":\"nestedDynamicStruct\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"address\",\"name\":\"A\",\"type\":\"address\"}],\"internalType\":\"structInnerStaticTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelStaticTestStruct\",\"name\":\"nestedStaticStruct\",\"type\":\"tuple\"}],\"name\":\"addTestStruct\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAlterablePrimitiveValue\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"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]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"AccountStr\",\"type\":\"address\"}],\"internalType\":\"structAccountStruct\",\"name\":\"AccountStruct\",\"type\":\"tuple\"},{\"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\":\"structInnerDynamicTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelDynamicTestStruct\",\"name\":\"NestedDynamicStruct\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"address\",\"name\":\"A\",\"type\":\"address\"}],\"internalType\":\"structInnerStaticTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelStaticTestStruct\",\"name\":\"NestedStaticStruct\",\"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]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"AccountStr\",\"type\":\"address\"}],\"internalType\":\"structAccountStruct\",\"name\":\"accountStruct\",\"type\":\"tuple\"},{\"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\":\"structInnerDynamicTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelDynamicTestStruct\",\"name\":\"nestedDynamicStruct\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"address\",\"name\":\"A\",\"type\":\"address\"}],\"internalType\":\"structInnerStaticTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelStaticTestStruct\",\"name\":\"nestedStaticStruct\",\"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]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"AccountStr\",\"type\":\"address\"}],\"internalType\":\"structAccountStruct\",\"name\":\"AccountStruct\",\"type\":\"tuple\"},{\"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\":\"structInnerDynamicTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelDynamicTestStruct\",\"name\":\"NestedDynamicStruct\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"address\",\"name\":\"A\",\"type\":\"address\"}],\"internalType\":\"structInnerStaticTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelStaticTestStruct\",\"name\":\"NestedStaticStruct\",\"type\":\"tuple\"}],\"internalType\":\"structTestStruct\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"value\",\"type\":\"uint64\"}],\"name\":\"setAlterablePrimitiveValue\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int32\",\"name\":\"field\",\"type\":\"int32\"},{\"internalType\":\"uint8\",\"name\":\"oracleId\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"string\",\"name\":\"S\",\"type\":\"string\"}],\"internalType\":\"structInnerDynamicTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelDynamicTestStruct\",\"name\":\"nestedDynamicStruct\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"address\",\"name\":\"A\",\"type\":\"address\"}],\"internalType\":\"structInnerStaticTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelStaticTestStruct\",\"name\":\"nestedStaticStruct\",\"type\":\"tuple\"},{\"internalType\":\"uint8[32]\",\"name\":\"oracleIds\",\"type\":\"uint8[32]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"AccountStr\",\"type\":\"address\"}],\"internalType\":\"structAccountStruct\",\"name\":\"accountStruct\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"string\",\"name\":\"differentField\",\"type\":\"string\"},{\"internalType\":\"int192\",\"name\":\"bigField\",\"type\":\"int192\"}],\"name\":\"triggerEvent\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"field\",\"type\":\"string\"}],\"name\":\"triggerEventWithDynamicTopic\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"val1\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"val2\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"val3\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"val4\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"val5\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"val6\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"val7\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"raw\",\"type\":\"bytes\"}],\"name\":\"triggerStaticBytes\",\"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\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"field1\",\"type\":\"string\"},{\"internalType\":\"uint8[32]\",\"name\":\"field2\",\"type\":\"uint8[32]\"},{\"internalType\":\"bytes32\",\"name\":\"field3\",\"type\":\"bytes32\"}],\"name\":\"triggerWithFourTopicsWithHashed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"type\":\"constructor\",\"inputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"addTestStruct\",\"inputs\":[{\"name\":\"field\",\"type\":\"int32\",\"internalType\":\"int32\"},{\"name\":\"differentField\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"oracleId\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"oracleIds\",\"type\":\"uint8[32]\",\"internalType\":\"uint8[32]\"},{\"name\":\"accountStruct\",\"type\":\"tuple\",\"internalType\":\"structAccountStruct\",\"components\":[{\"name\":\"Account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"AccountStr\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"name\":\"accounts\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"bigField\",\"type\":\"int192\",\"internalType\":\"int192\"},{\"name\":\"nestedDynamicStruct\",\"type\":\"tuple\",\"internalType\":\"structMidLevelDynamicTestStruct\",\"components\":[{\"name\":\"FixedBytes\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"Inner\",\"type\":\"tuple\",\"internalType\":\"structInnerDynamicTestStruct\",\"components\":[{\"name\":\"IntVal\",\"type\":\"int64\",\"internalType\":\"int64\"},{\"name\":\"S\",\"type\":\"string\",\"internalType\":\"string\"}]}]},{\"name\":\"nestedStaticStruct\",\"type\":\"tuple\",\"internalType\":\"structMidLevelStaticTestStruct\",\"components\":[{\"name\":\"FixedBytes\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"Inner\",\"type\":\"tuple\",\"internalType\":\"structInnerStaticTestStruct\",\"components\":[{\"name\":\"IntVal\",\"type\":\"int64\",\"internalType\":\"int64\"},{\"name\":\"A\",\"type\":\"address\",\"internalType\":\"address\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getAlterablePrimitiveValue\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getDifferentPrimitiveValue\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"getElementAtIndex\",\"inputs\":[{\"name\":\"i\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structTestStruct\",\"components\":[{\"name\":\"Field\",\"type\":\"int32\",\"internalType\":\"int32\"},{\"name\":\"DifferentField\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"OracleId\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"OracleIds\",\"type\":\"uint8[32]\",\"internalType\":\"uint8[32]\"},{\"name\":\"AccountStruct\",\"type\":\"tuple\",\"internalType\":\"structAccountStruct\",\"components\":[{\"name\":\"Account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"AccountStr\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"name\":\"Accounts\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"BigField\",\"type\":\"int192\",\"internalType\":\"int192\"},{\"name\":\"NestedDynamicStruct\",\"type\":\"tuple\",\"internalType\":\"structMidLevelDynamicTestStruct\",\"components\":[{\"name\":\"FixedBytes\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"Inner\",\"type\":\"tuple\",\"internalType\":\"structInnerDynamicTestStruct\",\"components\":[{\"name\":\"IntVal\",\"type\":\"int64\",\"internalType\":\"int64\"},{\"name\":\"S\",\"type\":\"string\",\"internalType\":\"string\"}]}]},{\"name\":\"NestedStaticStruct\",\"type\":\"tuple\",\"internalType\":\"structMidLevelStaticTestStruct\",\"components\":[{\"name\":\"FixedBytes\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"Inner\",\"type\":\"tuple\",\"internalType\":\"structInnerStaticTestStruct\",\"components\":[{\"name\":\"IntVal\",\"type\":\"int64\",\"internalType\":\"int64\"},{\"name\":\"A\",\"type\":\"address\",\"internalType\":\"address\"}]}]}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getPrimitiveValue\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"getSliceValue\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"returnSeen\",\"inputs\":[{\"name\":\"field\",\"type\":\"int32\",\"internalType\":\"int32\"},{\"name\":\"differentField\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"oracleId\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"oracleIds\",\"type\":\"uint8[32]\",\"internalType\":\"uint8[32]\"},{\"name\":\"accountStruct\",\"type\":\"tuple\",\"internalType\":\"structAccountStruct\",\"components\":[{\"name\":\"Account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"AccountStr\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"name\":\"accounts\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"bigField\",\"type\":\"int192\",\"internalType\":\"int192\"},{\"name\":\"nestedDynamicStruct\",\"type\":\"tuple\",\"internalType\":\"structMidLevelDynamicTestStruct\",\"components\":[{\"name\":\"FixedBytes\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"Inner\",\"type\":\"tuple\",\"internalType\":\"structInnerDynamicTestStruct\",\"components\":[{\"name\":\"IntVal\",\"type\":\"int64\",\"internalType\":\"int64\"},{\"name\":\"S\",\"type\":\"string\",\"internalType\":\"string\"}]}]},{\"name\":\"nestedStaticStruct\",\"type\":\"tuple\",\"internalType\":\"structMidLevelStaticTestStruct\",\"components\":[{\"name\":\"FixedBytes\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"Inner\",\"type\":\"tuple\",\"internalType\":\"structInnerStaticTestStruct\",\"components\":[{\"name\":\"IntVal\",\"type\":\"int64\",\"internalType\":\"int64\"},{\"name\":\"A\",\"type\":\"address\",\"internalType\":\"address\"}]}]}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structTestStruct\",\"components\":[{\"name\":\"Field\",\"type\":\"int32\",\"internalType\":\"int32\"},{\"name\":\"DifferentField\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"OracleId\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"OracleIds\",\"type\":\"uint8[32]\",\"internalType\":\"uint8[32]\"},{\"name\":\"AccountStruct\",\"type\":\"tuple\",\"internalType\":\"structAccountStruct\",\"components\":[{\"name\":\"Account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"AccountStr\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"name\":\"Accounts\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"BigField\",\"type\":\"int192\",\"internalType\":\"int192\"},{\"name\":\"NestedDynamicStruct\",\"type\":\"tuple\",\"internalType\":\"structMidLevelDynamicTestStruct\",\"components\":[{\"name\":\"FixedBytes\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"Inner\",\"type\":\"tuple\",\"internalType\":\"structInnerDynamicTestStruct\",\"components\":[{\"name\":\"IntVal\",\"type\":\"int64\",\"internalType\":\"int64\"},{\"name\":\"S\",\"type\":\"string\",\"internalType\":\"string\"}]}]},{\"name\":\"NestedStaticStruct\",\"type\":\"tuple\",\"internalType\":\"structMidLevelStaticTestStruct\",\"components\":[{\"name\":\"FixedBytes\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"Inner\",\"type\":\"tuple\",\"internalType\":\"structInnerStaticTestStruct\",\"components\":[{\"name\":\"IntVal\",\"type\":\"int64\",\"internalType\":\"int64\"},{\"name\":\"A\",\"type\":\"address\",\"internalType\":\"address\"}]}]}]}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"setAlterablePrimitiveValue\",\"inputs\":[{\"name\":\"value\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"triggerEvent\",\"inputs\":[{\"name\":\"field\",\"type\":\"int32\",\"internalType\":\"int32\"},{\"name\":\"oracleId\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"nestedDynamicStruct\",\"type\":\"tuple\",\"internalType\":\"structMidLevelDynamicTestStruct\",\"components\":[{\"name\":\"FixedBytes\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"Inner\",\"type\":\"tuple\",\"internalType\":\"structInnerDynamicTestStruct\",\"components\":[{\"name\":\"IntVal\",\"type\":\"int64\",\"internalType\":\"int64\"},{\"name\":\"S\",\"type\":\"string\",\"internalType\":\"string\"}]}]},{\"name\":\"nestedStaticStruct\",\"type\":\"tuple\",\"internalType\":\"structMidLevelStaticTestStruct\",\"components\":[{\"name\":\"FixedBytes\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"Inner\",\"type\":\"tuple\",\"internalType\":\"structInnerStaticTestStruct\",\"components\":[{\"name\":\"IntVal\",\"type\":\"int64\",\"internalType\":\"int64\"},{\"name\":\"A\",\"type\":\"address\",\"internalType\":\"address\"}]}]},{\"name\":\"oracleIds\",\"type\":\"uint8[32]\",\"internalType\":\"uint8[32]\"},{\"name\":\"accountStruct\",\"type\":\"tuple\",\"internalType\":\"structAccountStruct\",\"components\":[{\"name\":\"Account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"AccountStr\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"name\":\"accounts\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"differentField\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"bigField\",\"type\":\"int192\",\"internalType\":\"int192\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"triggerEventWithDynamicTopic\",\"inputs\":[{\"name\":\"field\",\"type\":\"string\",\"internalType\":\"string\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"triggerStaticBytes\",\"inputs\":[{\"name\":\"val1\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"val2\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"val3\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"val4\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"val5\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"val6\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"val7\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"raw\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"triggerWithFourTopics\",\"inputs\":[{\"name\":\"field1\",\"type\":\"int32\",\"internalType\":\"int32\"},{\"name\":\"field2\",\"type\":\"int32\",\"internalType\":\"int32\"},{\"name\":\"field3\",\"type\":\"int32\",\"internalType\":\"int32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"triggerWithFourTopicsWithHashed\",\"inputs\":[{\"name\":\"field1\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"field2\",\"type\":\"uint8[32]\",\"internalType\":\"uint8[32]\"},{\"name\":\"field3\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"StaticBytes\",\"inputs\":[{\"name\":\"message\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Triggered\",\"inputs\":[{\"name\":\"field\",\"type\":\"int32\",\"indexed\":true,\"internalType\":\"int32\"},{\"name\":\"oracleId\",\"type\":\"uint8\",\"indexed\":false,\"internalType\":\"uint8\"},{\"name\":\"nestedDynamicStruct\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structMidLevelDynamicTestStruct\",\"components\":[{\"name\":\"FixedBytes\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"Inner\",\"type\":\"tuple\",\"internalType\":\"structInnerDynamicTestStruct\",\"components\":[{\"name\":\"IntVal\",\"type\":\"int64\",\"internalType\":\"int64\"},{\"name\":\"S\",\"type\":\"string\",\"internalType\":\"string\"}]}]},{\"name\":\"nestedStaticStruct\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structMidLevelStaticTestStruct\",\"components\":[{\"name\":\"FixedBytes\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"Inner\",\"type\":\"tuple\",\"internalType\":\"structInnerStaticTestStruct\",\"components\":[{\"name\":\"IntVal\",\"type\":\"int64\",\"internalType\":\"int64\"},{\"name\":\"A\",\"type\":\"address\",\"internalType\":\"address\"}]}]},{\"name\":\"oracleIds\",\"type\":\"uint8[32]\",\"indexed\":false,\"internalType\":\"uint8[32]\"},{\"name\":\"accountStruct\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structAccountStruct\",\"components\":[{\"name\":\"Account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"AccountStr\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"name\":\"Accounts\",\"type\":\"address[]\",\"indexed\":false,\"internalType\":\"address[]\"},{\"name\":\"differentField\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"bigField\",\"type\":\"int192\",\"indexed\":false,\"internalType\":\"int192\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TriggeredEventWithDynamicTopic\",\"inputs\":[{\"name\":\"fieldHash\",\"type\":\"string\",\"indexed\":true,\"internalType\":\"string\"},{\"name\":\"field\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TriggeredWithFourTopics\",\"inputs\":[{\"name\":\"field1\",\"type\":\"int32\",\"indexed\":true,\"internalType\":\"int32\"},{\"name\":\"field2\",\"type\":\"int32\",\"indexed\":true,\"internalType\":\"int32\"},{\"name\":\"field3\",\"type\":\"int32\",\"indexed\":true,\"internalType\":\"int32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TriggeredWithFourTopicsWithHashed\",\"inputs\":[{\"name\":\"field1\",\"type\":\"string\",\"indexed\":true,\"internalType\":\"string\"},{\"name\":\"field2\",\"type\":\"uint8[32]\",\"indexed\":true,\"internalType\":\"uint8[32]\"},{\"name\":\"field3\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"}],\"anonymous\":false}]", Bin: "0x608060405234801561001057600080fd5b50600180548082018255600082905260048082047fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6908101805460086003958616810261010090810a8088026001600160401b0391820219909416939093179093558654808801909755848704909301805496909516909202900a91820291021990921691909117905561209a806100a96000396000f3fe608060405234801561001057600080fd5b50600436106100df5760003560e01c80636cf01bfc1161008c578063ab5e0b3811610066578063ab5e0b38146101df578063dbfd7332146101fc578063ef4e1ced1461020f578063fbe9fbf61461021657600080fd5b80636cf01bfc146101a657806380d77303146101b9578063a90e1998146101cc57600080fd5b8063660b5962116100bd578063660b596214610135578063679004a4146101485780636c9a43b61461015d57600080fd5b80632c45576f146100e45780633272b66c1461010d57806351f3f54d14610122575b600080fd5b6100f76100f2366004610f24565b610228565b604051610104919061108d565b60405180910390f35b61012061011b366004611240565b61059b565b005b61012061013036600461139f565b6105f0565b61012061014336600461150c565b610664565b610150610a33565b6040516101049190611612565b61012061016b366004611660565b600280547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff92909216919091179055565b6100f76101b436600461150c565b610abf565b6101206101c7366004611682565b610bd6565b6101206101da366004611795565b610c30565b6107c65b60405167ffffffffffffffff9091168152602001610104565b61012061020a36600461184a565b610c8a565b60036101e3565b60025467ffffffffffffffff166101e3565b610230610cc7565b600061023d60018461188d565b8154811061024d5761024d6118c7565b6000918252602091829020604080516101208101909152600d90920201805460030b82526001810180549293919291840191610288906118f6565b80601f01602080910402602001604051908101604052809291908181526020018280546102b4906118f6565b80156103015780601f106102d657610100808354040283529160200191610301565b820191906000526020600020905b8154815290600101906020018083116102e457829003601f168201915b5050509183525050600282015460ff166020808301919091526040805161040081018083529190930192916003850191826000855b825461010083900a900460ff168152602060019283018181049485019490930390920291018084116103365790505050509183525050604080518082018252600484015473ffffffffffffffffffffffffffffffffffffffff90811682526005850154166020828101919091528084019190915260068401805483518184028101840185528181529390940193909183018282801561040b57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116103e0575b505050918352505060078281015460170b60208084019190915260408051808201825260088601805460f01b7fffff0000000000000000000000000000000000000000000000000000000000001682528251808401845260098801805490960b8152600a880180549490970196929591948681019491939084019161048f906118f6565b80601f01602080910402602001604051908101604052809291908181526020018280546104bb906118f6565b80156105085780601f106104dd57610100808354040283529160200191610508565b820191906000526020600020905b8154815290600101906020018083116104eb57829003601f168201915b505050919092525050509052508152604080518082018252600b84015460f01b7fffff0000000000000000000000000000000000000000000000000000000000001681528151808301909252600c90930154600781900b825268010000000000000000900473ffffffffffffffffffffffffffffffffffffffff1660208083019190915280840191909152015292915050565b81816040516105ab929190611943565b60405180910390207f3d969732b1bbbb9f1d7eb9f3f14e4cb50a74d950b3ef916a397b85dfbab93c6783836040516105e492919061199c565b60405180910390a25050565b600088888888888888886040516020016106119897969594939291906119b0565b60405160208183030381529060405290507f1e40927ec0bdc7319f09a53452590433ec395dec3b70b982eba779c740685bfe816040516106519190611a56565b60405180910390a1505050505050505050565b60006040518061012001604052808d60030b81526020018c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060ff8b166020808301919091526040805161040081810183529190930192918c918390839080828437600092019190915250505081526020016106fc368a90038a018a611a8d565b8152602001878780806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250505090825250601786900b602082015260400161074d85611b0c565b815260200161076136859003850185611baa565b905281546001808201845560009384526020938490208351600d9093020180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff9093169290921782559282015191929091908201906107c79082611c89565b5060408201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff90921691909117905560608201516108159060038301906020610d90565b506080820151805160048301805473ffffffffffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560209283015160058501805491909316911617905560a0830151805161088f9260068501920190610e23565b5060c08201516007820180547fffffffffffffffff0000000000000000000000000000000000000000000000001677ffffffffffffffffffffffffffffffffffffffffffffffff90921691909117905560e082015180516008830180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660f09290921c91909117815560208083015180516009860180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff90921691909117815591810151909190600a8601906109729082611c89565b5050505061010092909201518051600b8301805460f09290921c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009092169190911790556020908101518051600c9093018054919092015173ffffffffffffffffffffffffffffffffffffffff1668010000000000000000027fffffffff0000000000000000000000000000000000000000000000000000000090911667ffffffffffffffff90931692909217919091179055505050505050505050505050565b60606001805480602002602001604051908101604052809291908181526020018280548015610ab557602002820191906000526020600020906000905b82829054906101000a900467ffffffffffffffff1667ffffffffffffffff1681526020019060080190602082600701049283019260010382029150808411610a705790505b5050505050905090565b610ac7610cc7565b6040518061012001604052808d60030b81526020018c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060ff8b166020808301919091526040805161040081810183529190930192918c91839083908082843760009201919091525050508152602001610b5d368a90038a018a611a8d565b8152602001878780806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250505090825250601786900b6020820152604001610bae85611b0c565b8152602001610bc236859003850185611baa565b905290505b9b9a5050505050505050505050565b8a60030b7f6a1c0d59d12839c1d2bd0a8cd5e73032dc60569f7f448b99b572b61c442b8add8b8b8b8b8b8b8b8b8b8b604051610c1b9a99989796959493929190611ec4565b60405180910390a25050505050505050505050565b8082604051610c3f9190612035565b604051809103902084604051610c559190612071565b604051908190038120907f7220e4dbe4e9d0ed5f71acd022bc89c26748ac6784f2c548bc17bb8e52af34b090600090a4505050565b8060030b8260030b8460030b7f91c80dc390f3d041b3a04b0099b19634499541ea26972250986ee4b24a12fac560405160405180910390a4505050565b6040805161012081018252600080825260606020830181905292820152908101610cef610e9d565b8152602001610d3d6040518060400160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681525090565b81526060602082018190526000604083015201610d58610ebc565b8152602001610d8b6040805180820182526000808252825180840190935280835260208381019190915290919082015290565b905290565b600183019183908215610e135791602002820160005b83821115610de457835183826101000a81548160ff021916908360ff1602179055509260200192600101602081600001049283019260010302610da6565b8015610e115782816101000a81549060ff0219169055600101602081600001049283019260010302610de4565b505b50610e1f929150610f0f565b5090565b828054828255906000526020600020908101928215610e13579160200282015b82811115610e1357825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190610e43565b6040518061040001604052806020906020820280368337509192915050565b604051806040016040528060007dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001610d8b6040518060400160405280600060070b8152602001606081525090565b5b80821115610e1f5760008155600101610f10565b600060208284031215610f3657600080fd5b5035919050565b60005b83811015610f58578181015183820152602001610f40565b50506000910152565b60008151808452610f79816020860160208601610f3d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b6020808210610fbe5750610fd5565b825160ff1685529384019390910190600101610faf565b50505050565b600081518084526020808501945080840160005b8381101561102157815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101610fef565b509495945050505050565b7fffff00000000000000000000000000000000000000000000000000000000000081511682526000602082015160406020850152805160070b604085015260208101519050604060608501526110856080850182610f61565b949350505050565b602081526110a160208201835160030b9052565b6000602083015161056060408401526110be610580840182610f61565b905060408401516110d4606085018260ff169052565b5060608401516110e76080850182610fab565b506080840151805173ffffffffffffffffffffffffffffffffffffffff9081166104808601526020820151166104a08501525060a08401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe080858403016104c08601526111558383610fdb565b925060c0860151915061116e6104e086018360170b9052565b60e0860151915080858403016105008601525061118b828261102c565b61010086015180517fffff00000000000000000000000000000000000000000000000000000000000016610520870152602080820151805160070b610540890152015173ffffffffffffffffffffffffffffffffffffffff166105608701529092509050509392505050565b60008083601f84011261120957600080fd5b50813567ffffffffffffffff81111561122157600080fd5b60208301915083602082850101111561123957600080fd5b9250929050565b6000806020838503121561125357600080fd5b823567ffffffffffffffff81111561126a57600080fd5b611276858286016111f7565b90969095509350505050565b803563ffffffff8116811461129657600080fd5b919050565b803567ffffffffffffffff8116811461129657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611305576113056112b3565b60405290565b600067ffffffffffffffff80841115611326576113266112b3565b604051601f85017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561136c5761136c6112b3565b8160405280935085815286868601111561138557600080fd5b858560208301376000602087830101525050509392505050565b600080600080600080600080610100898b0312156113bc57600080fd5b6113c589611282565b97506113d360208a01611282565b96506113e160408a01611282565b95506113ef60608a0161129b565b94506080890135935060a0890135925060c0890135915060e089013567ffffffffffffffff81111561142057600080fd5b8901601f81018b1361143157600080fd5b6114408b82356020840161130b565b9150509295985092959890939650565b8035600381900b811461129657600080fd5b803560ff8116811461129657600080fd5b80610400810183101561148557600080fd5b92915050565b60006040828403121561149d57600080fd5b50919050565b60008083601f8401126114b557600080fd5b50813567ffffffffffffffff8111156114cd57600080fd5b6020830191508360208260051b850101111561123957600080fd5b8035601781900b811461129657600080fd5b60006060828403121561149d57600080fd5b60008060008060008060008060008060006105608c8e03121561152e57600080fd5b6115378c611450565b9a5067ffffffffffffffff8060208e0135111561155357600080fd5b6115638e60208f01358f016111f7565b909b50995061157460408e01611462565b98506115838e60608f01611473565b97506115938e6104608f0161148b565b9650806104a08e013511156115a757600080fd5b6115b88e6104a08f01358f016114a3565b90965094506115ca6104c08e016114e8565b9350806104e08e013511156115de57600080fd5b506115f08d6104e08e01358e0161148b565b91506116008d6105008e016114fa565b90509295989b509295989b9093969950565b6020808252825182820181905260009190848201906040850190845b8181101561165457835167ffffffffffffffff168352928401929184019160010161162e565b50909695505050505050565b60006020828403121561167257600080fd5b61167b8261129b565b9392505050565b60008060008060008060008060008060006105608c8e0312156116a457600080fd5b6116ad8c611450565b9a506116bb60208d01611462565b995067ffffffffffffffff8060408e013511156116d757600080fd5b6116e78e60408f01358f0161148b565b99506116f68e60608f016114fa565b98506117058e60c08f01611473565b97506117158e6104c08f0161148b565b9650806105008e0135111561172957600080fd5b61173a8e6105008f01358f016114a3565b90965094506105208d013581101561175157600080fd5b506117638d6105208e01358e016111f7565b90935091506116006105408d016114e8565b600082601f83011261178657600080fd5b61167b8383356020850161130b565b600080600061044084860312156117ab57600080fd5b833567ffffffffffffffff808211156117c357600080fd5b6117cf87838801611775565b94506020915086603f8701126117e457600080fd5b60405161040081018181108382111715611800576118006112b3565b60405290508061042087018881111561181857600080fd5b8388015b8181101561183a5761182d81611462565b845292840192840161181c565b5095989097509435955050505050565b60008060006060848603121561185f57600080fd5b61186884611450565b925061187660208501611450565b915061188460408501611450565b90509250925092565b81810381811115611485577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181811c9082168061190a57607f821691505b60208210810361149d577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b8183823760009101908152919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526000611085602083018486611953565b60007fffffffff00000000000000000000000000000000000000000000000000000000808b60e01b168352808a60e01b166004840152808960e01b166008840152507fffffffffffffffff0000000000000000000000000000000000000000000000008760c01b16600c8301528560148301528460348301528360548301528251611a42816074850160208701610f3d565b919091016074019998505050505050505050565b60208152600061167b6020830184610f61565b803573ffffffffffffffffffffffffffffffffffffffff8116811461129657600080fd5b600060408284031215611a9f57600080fd5b611aa76112e2565b611ab083611a69565b8152611abe60208401611a69565b60208201529392505050565b80357fffff0000000000000000000000000000000000000000000000000000000000008116811461129657600080fd5b8035600781900b811461129657600080fd5b600060408236031215611b1e57600080fd5b611b266112e2565b611b2f83611aca565b8152602083013567ffffffffffffffff80821115611b4c57600080fd5b818501915060408236031215611b6157600080fd5b611b696112e2565b611b7283611afa565b8152602083013582811115611b8657600080fd5b611b9236828601611775565b60208301525080602085015250505080915050919050565b60008183036060811215611bbd57600080fd5b611bc56112e2565b611bce84611aca565b815260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe083011215611c0057600080fd5b611c086112e2565b9150611c1660208501611afa565b8252611c2460408501611a69565b6020830152816020820152809250505092915050565b601f821115611c8457600081815260208120601f850160051c81016020861015611c615750805b601f850160051c820191505b81811015611c8057828155600101611c6d565b5050505b505050565b815167ffffffffffffffff811115611ca357611ca36112b3565b611cb781611cb184546118f6565b84611c3a565b602080601f831160018114611d0a5760008415611cd45750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555611c80565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015611d5757888601518255948401946001909101908401611d38565b5085821015611d9357878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7fffff000000000000000000000000000000000000000000000000000000000000611dcd82611aca565b168252611ddc60208201611afa565b60070b602083015273ffffffffffffffffffffffffffffffffffffffff611e0560408301611a69565b1660408301525050565b8060005b6020808210611e225750610fd5565b60ff611e2d84611462565b168552938401939190910190600101611e13565b73ffffffffffffffffffffffffffffffffffffffff80611e6083611a69565b16835280611e7060208401611a69565b166020840152505050565b8183526000602080850194508260005b858110156110215773ffffffffffffffffffffffffffffffffffffffff611eb183611a69565b1687529582019590820190600101611e8b565b600061054060ff8d1683528060208401527fffff000000000000000000000000000000000000000000000000000000000000611eff8d611aca565b16818401525060208b01357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18c3603018112611f3a57600080fd5b60406105608401528b01611f4d81611afa565b60070b61058084015260208101357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1823603018112611f8b57600080fd5b0160208101903567ffffffffffffffff811115611fa757600080fd5b803603821315611fb657600080fd5b60406105a0850152611fcd6105c085018284611953565b915050611fdd604084018c611da3565b611fea60a084018b611e0f565b611ff86104a084018a611e41565b8281036104e084015261200c81888a611e7b565b9050828103610500840152612022818688611953565b915050610bc761052083018460170b9052565b60008183825b602080821061204a5750612061565b825160ff168452928301929091019060010161203b565b5050506104008201905092915050565b60008251612083818460208701610f3d565b919091019291505056fea164736f6c6343000813000a", } diff --git a/core/gethwrappers/shared/generated/erc20/erc20.go b/core/gethwrappers/shared/generated/erc20/erc20.go index 9fd43134b6d..10659ec6486 100644 --- a/core/gethwrappers/shared/generated/erc20/erc20.go +++ b/core/gethwrappers/shared/generated/erc20/erc20.go @@ -31,7 +31,7 @@ var ( ) var ERC20MetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name_\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol_\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"name_\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"symbol_\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"allowance\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"approve\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"balanceOf\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"decimals\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"decreaseAllowance\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"subtractedValue\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"increaseAllowance\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"addedValue\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"name\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"symbol\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"totalSupply\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transfer\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferFrom\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"Approval\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"spender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Transfer\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false}]", Bin: "0x60806040523480156200001157600080fd5b5060405162000de638038062000de683398101604081905262000034916200011f565b600362000042838262000218565b50600462000051828262000218565b505050620002e4565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200008257600080fd5b81516001600160401b03808211156200009f576200009f6200005a565b604051601f8301601f19908116603f01168101908282118183101715620000ca57620000ca6200005a565b81604052838152602092508683858801011115620000e757600080fd5b600091505b838210156200010b5785820183015181830184015290820190620000ec565b600093810190920192909252949350505050565b600080604083850312156200013357600080fd5b82516001600160401b03808211156200014b57600080fd5b620001598683870162000070565b935060208501519150808211156200017057600080fd5b506200017f8582860162000070565b9150509250929050565b600181811c908216806200019e57607f821691505b602082108103620001bf57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200021357600081815260208120601f850160051c81016020861015620001ee5750805b601f850160051c820191505b818110156200020f57828155600101620001fa565b5050505b505050565b81516001600160401b038111156200023457620002346200005a565b6200024c8162000245845462000189565b84620001c5565b602080601f8311600181146200028457600084156200026b5750858301515b600019600386901b1c1916600185901b1785556200020f565b600085815260208120601f198616915b82811015620002b55788860151825594840194600190910190840162000294565b5085821015620002d45787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b610af280620002f46000396000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c80633950935111610081578063a457c2d71161005b578063a457c2d714610194578063a9059cbb146101a7578063dd62ed3e146101ba57600080fd5b8063395093511461014357806370a082311461015657806395d89b411461018c57600080fd5b806318160ddd116100b257806318160ddd1461010f57806323b872dd14610121578063313ce5671461013457600080fd5b806306fdde03146100ce578063095ea7b3146100ec575b600080fd5b6100d6610200565b6040516100e39190610908565b60405180910390f35b6100ff6100fa36600461099d565b610292565b60405190151581526020016100e3565b6002545b6040519081526020016100e3565b6100ff61012f3660046109c7565b6102ac565b604051601281526020016100e3565b6100ff61015136600461099d565b6102d0565b610113610164366004610a03565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6100d661031c565b6100ff6101a236600461099d565b61032b565b6100ff6101b536600461099d565b610401565b6101136101c8366004610a25565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b60606003805461020f90610a58565b80601f016020809104026020016040519081016040528092919081815260200182805461023b90610a58565b80156102885780601f1061025d57610100808354040283529160200191610288565b820191906000526020600020905b81548152906001019060200180831161026b57829003601f168201915b5050505050905090565b6000336102a081858561040f565b60019150505b92915050565b6000336102ba8582856105c2565b6102c5858585610699565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906102a09082908690610317908790610aab565b61040f565b60606004805461020f90610a58565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152812054909190838110156103f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6102c5828686840361040f565b6000336102a0818585610699565b73ffffffffffffffffffffffffffffffffffffffff83166104b1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016103eb565b73ffffffffffffffffffffffffffffffffffffffff8216610554576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016103eb565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146106935781811015610686576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016103eb565b610693848484840361040f565b50505050565b73ffffffffffffffffffffffffffffffffffffffff831661073c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016103eb565b73ffffffffffffffffffffffffffffffffffffffff82166107df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016103eb565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610895576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016103eb565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610693565b600060208083528351808285015260005b8181101561093557858101830151858201604001528201610919565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461099857600080fd5b919050565b600080604083850312156109b057600080fd5b6109b983610974565b946020939093013593505050565b6000806000606084860312156109dc57600080fd5b6109e584610974565b92506109f360208501610974565b9150604084013590509250925092565b600060208284031215610a1557600080fd5b610a1e82610974565b9392505050565b60008060408385031215610a3857600080fd5b610a4183610974565b9150610a4f60208401610974565b90509250929050565b600181811c90821680610a6c57607f821691505b602082108103610aa5577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b808201808211156102a6577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea164736f6c6343000813000a", } diff --git a/core/gethwrappers/shared/generated/erc677/erc677.go b/core/gethwrappers/shared/generated/erc677/erc677.go new file mode 100644 index 00000000000..189687e123d --- /dev/null +++ b/core/gethwrappers/shared/generated/erc677/erc677.go @@ -0,0 +1,866 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package erc677 + +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 ERC677MetaData = &bind.MetaData{ + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"name\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"symbol\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"allowance\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"approve\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"balanceOf\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"decimals\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"decreaseAllowance\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"subtractedValue\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"increaseAllowance\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"addedValue\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"name\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"symbol\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"totalSupply\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transfer\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferAndCall\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"success\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferFrom\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"Approval\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"spender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Transfer\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Transfer\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false}]", + Bin: "0x60806040523480156200001157600080fd5b50604051620010ae380380620010ae833981016040819052620000349162000123565b818160036200004483826200021c565b5060046200005382826200021c565b5050505050620002e8565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200008657600080fd5b81516001600160401b0380821115620000a357620000a36200005e565b604051601f8301601f19908116603f01168101908282118183101715620000ce57620000ce6200005e565b81604052838152602092508683858801011115620000eb57600080fd5b600091505b838210156200010f5785820183015181830184015290820190620000f0565b600093810190920192909252949350505050565b600080604083850312156200013757600080fd5b82516001600160401b03808211156200014f57600080fd5b6200015d8683870162000074565b935060208501519150808211156200017457600080fd5b50620001838582860162000074565b9150509250929050565b600181811c90821680620001a257607f821691505b602082108103620001c357634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200021757600081815260208120601f850160051c81016020861015620001f25750805b601f850160051c820191505b818110156200021357828155600101620001fe565b5050505b505050565b81516001600160401b038111156200023857620002386200005e565b62000250816200024984546200018d565b84620001c9565b602080601f8311600181146200028857600084156200026f5750858301515b600019600386901b1c1916600185901b17855562000213565b600085815260208120601f198616915b82811015620002b95788860151825594840194600190910190840162000298565b5085821015620002d85787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b610db680620002f86000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c80634000aea011610081578063a457c2d71161005b578063a457c2d7146101b2578063a9059cbb146101c5578063dd62ed3e146101d857600080fd5b80634000aea01461016157806370a082311461017457806395d89b41146101aa57600080fd5b806323b872dd116100b257806323b872dd1461012c578063313ce5671461013f578063395093511461014e57600080fd5b806306fdde03146100d9578063095ea7b3146100f757806318160ddd1461011a575b600080fd5b6100e161021e565b6040516100ee9190610aae565b60405180910390f35b61010a610105366004610af1565b6102b0565b60405190151581526020016100ee565b6002545b6040519081526020016100ee565b61010a61013a366004610b1b565b6102ca565b604051601281526020016100ee565b61010a61015c366004610af1565b6102ee565b61010a61016f366004610b86565b61033a565b61011e610182366004610c6f565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6100e161045e565b61010a6101c0366004610af1565b61046d565b61010a6101d3366004610af1565b610543565b61011e6101e6366004610c8a565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b60606003805461022d90610cbd565b80601f016020809104026020016040519081016040528092919081815260200182805461025990610cbd565b80156102a65780601f1061027b576101008083540402835291602001916102a6565b820191906000526020600020905b81548152906001019060200180831161028957829003601f168201915b5050505050905090565b6000336102be818585610551565b60019150505b92915050565b6000336102d8858285610704565b6102e38585856107db565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906102be9082908690610335908790610d10565b610551565b60006103468484610543565b508373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fe19260aff97b920c7df27010903aeb9c8d2be5d310a2c67824cf3f15396e4c1685856040516103a6929190610d4a565b60405180910390a373ffffffffffffffffffffffffffffffffffffffff84163b15610454576040517fa4c0ed3600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85169063a4c0ed369061042190339087908790600401610d6b565b600060405180830381600087803b15801561043b57600080fd5b505af115801561044f573d6000803e3d6000fd5b505050505b5060019392505050565b60606004805461022d90610cbd565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610536576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6102e38286868403610551565b6000336102be8185856107db565b73ffffffffffffffffffffffffffffffffffffffff83166105f3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015260840161052d565b73ffffffffffffffffffffffffffffffffffffffff8216610696576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f7373000000000000000000000000000000000000000000000000000000000000606482015260840161052d565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146107d557818110156107c8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161052d565b6107d58484848403610551565b50505050565b73ffffffffffffffffffffffffffffffffffffffff831661087e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161052d565b73ffffffffffffffffffffffffffffffffffffffff8216610921576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015260840161052d565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040902054818110156109d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e63650000000000000000000000000000000000000000000000000000606482015260840161052d565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a36107d5565b6000815180845260005b81811015610a7057602081850181015186830182015201610a54565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610ac16020830184610a4a565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610aec57600080fd5b919050565b60008060408385031215610b0457600080fd5b610b0d83610ac8565b946020939093013593505050565b600080600060608486031215610b3057600080fd5b610b3984610ac8565b9250610b4760208501610ac8565b9150604084013590509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060608486031215610b9b57600080fd5b610ba484610ac8565b925060208401359150604084013567ffffffffffffffff80821115610bc857600080fd5b818601915086601f830112610bdc57600080fd5b813581811115610bee57610bee610b57565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715610c3457610c34610b57565b81604052828152896020848701011115610c4d57600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b600060208284031215610c8157600080fd5b610ac182610ac8565b60008060408385031215610c9d57600080fd5b610ca683610ac8565b9150610cb460208401610ac8565b90509250929050565b600181811c90821680610cd157607f821691505b602082108103610d0a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b808201808211156102c4577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b828152604060208201526000610d636040830184610a4a565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff84168152826020820152606060408201526000610da06060830184610a4a565b9594505050505056fea164736f6c6343000813000a", +} + +var ERC677ABI = ERC677MetaData.ABI + +var ERC677Bin = ERC677MetaData.Bin + +func DeployERC677(auth *bind.TransactOpts, backend bind.ContractBackend, name string, symbol string) (common.Address, *types.Transaction, *ERC677, error) { + parsed, err := ERC677MetaData.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(ERC677Bin), backend, name, symbol) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &ERC677{address: address, abi: *parsed, ERC677Caller: ERC677Caller{contract: contract}, ERC677Transactor: ERC677Transactor{contract: contract}, ERC677Filterer: ERC677Filterer{contract: contract}}, nil +} + +type ERC677 struct { + address common.Address + abi abi.ABI + ERC677Caller + ERC677Transactor + ERC677Filterer +} + +type ERC677Caller struct { + contract *bind.BoundContract +} + +type ERC677Transactor struct { + contract *bind.BoundContract +} + +type ERC677Filterer struct { + contract *bind.BoundContract +} + +type ERC677Session struct { + Contract *ERC677 + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type ERC677CallerSession struct { + Contract *ERC677Caller + CallOpts bind.CallOpts +} + +type ERC677TransactorSession struct { + Contract *ERC677Transactor + TransactOpts bind.TransactOpts +} + +type ERC677Raw struct { + Contract *ERC677 +} + +type ERC677CallerRaw struct { + Contract *ERC677Caller +} + +type ERC677TransactorRaw struct { + Contract *ERC677Transactor +} + +func NewERC677(address common.Address, backend bind.ContractBackend) (*ERC677, error) { + abi, err := abi.JSON(strings.NewReader(ERC677ABI)) + if err != nil { + return nil, err + } + contract, err := bindERC677(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &ERC677{address: address, abi: abi, ERC677Caller: ERC677Caller{contract: contract}, ERC677Transactor: ERC677Transactor{contract: contract}, ERC677Filterer: ERC677Filterer{contract: contract}}, nil +} + +func NewERC677Caller(address common.Address, caller bind.ContractCaller) (*ERC677Caller, error) { + contract, err := bindERC677(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ERC677Caller{contract: contract}, nil +} + +func NewERC677Transactor(address common.Address, transactor bind.ContractTransactor) (*ERC677Transactor, error) { + contract, err := bindERC677(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ERC677Transactor{contract: contract}, nil +} + +func NewERC677Filterer(address common.Address, filterer bind.ContractFilterer) (*ERC677Filterer, error) { + contract, err := bindERC677(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ERC677Filterer{contract: contract}, nil +} + +func bindERC677(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := ERC677MetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_ERC677 *ERC677Raw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ERC677.Contract.ERC677Caller.contract.Call(opts, result, method, params...) +} + +func (_ERC677 *ERC677Raw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ERC677.Contract.ERC677Transactor.contract.Transfer(opts) +} + +func (_ERC677 *ERC677Raw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ERC677.Contract.ERC677Transactor.contract.Transact(opts, method, params...) +} + +func (_ERC677 *ERC677CallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ERC677.Contract.contract.Call(opts, result, method, params...) +} + +func (_ERC677 *ERC677TransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ERC677.Contract.contract.Transfer(opts) +} + +func (_ERC677 *ERC677TransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ERC677.Contract.contract.Transact(opts, method, params...) +} + +func (_ERC677 *ERC677Caller) Allowance(opts *bind.CallOpts, owner common.Address, spender common.Address) (*big.Int, error) { + var out []interface{} + err := _ERC677.contract.Call(opts, &out, "allowance", owner, spender) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_ERC677 *ERC677Session) Allowance(owner common.Address, spender common.Address) (*big.Int, error) { + return _ERC677.Contract.Allowance(&_ERC677.CallOpts, owner, spender) +} + +func (_ERC677 *ERC677CallerSession) Allowance(owner common.Address, spender common.Address) (*big.Int, error) { + return _ERC677.Contract.Allowance(&_ERC677.CallOpts, owner, spender) +} + +func (_ERC677 *ERC677Caller) BalanceOf(opts *bind.CallOpts, account common.Address) (*big.Int, error) { + var out []interface{} + err := _ERC677.contract.Call(opts, &out, "balanceOf", account) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_ERC677 *ERC677Session) BalanceOf(account common.Address) (*big.Int, error) { + return _ERC677.Contract.BalanceOf(&_ERC677.CallOpts, account) +} + +func (_ERC677 *ERC677CallerSession) BalanceOf(account common.Address) (*big.Int, error) { + return _ERC677.Contract.BalanceOf(&_ERC677.CallOpts, account) +} + +func (_ERC677 *ERC677Caller) Decimals(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _ERC677.contract.Call(opts, &out, "decimals") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +func (_ERC677 *ERC677Session) Decimals() (uint8, error) { + return _ERC677.Contract.Decimals(&_ERC677.CallOpts) +} + +func (_ERC677 *ERC677CallerSession) Decimals() (uint8, error) { + return _ERC677.Contract.Decimals(&_ERC677.CallOpts) +} + +func (_ERC677 *ERC677Caller) Name(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _ERC677.contract.Call(opts, &out, "name") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_ERC677 *ERC677Session) Name() (string, error) { + return _ERC677.Contract.Name(&_ERC677.CallOpts) +} + +func (_ERC677 *ERC677CallerSession) Name() (string, error) { + return _ERC677.Contract.Name(&_ERC677.CallOpts) +} + +func (_ERC677 *ERC677Caller) Symbol(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _ERC677.contract.Call(opts, &out, "symbol") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_ERC677 *ERC677Session) Symbol() (string, error) { + return _ERC677.Contract.Symbol(&_ERC677.CallOpts) +} + +func (_ERC677 *ERC677CallerSession) Symbol() (string, error) { + return _ERC677.Contract.Symbol(&_ERC677.CallOpts) +} + +func (_ERC677 *ERC677Caller) TotalSupply(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _ERC677.contract.Call(opts, &out, "totalSupply") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_ERC677 *ERC677Session) TotalSupply() (*big.Int, error) { + return _ERC677.Contract.TotalSupply(&_ERC677.CallOpts) +} + +func (_ERC677 *ERC677CallerSession) TotalSupply() (*big.Int, error) { + return _ERC677.Contract.TotalSupply(&_ERC677.CallOpts) +} + +func (_ERC677 *ERC677Transactor) Approve(opts *bind.TransactOpts, spender common.Address, amount *big.Int) (*types.Transaction, error) { + return _ERC677.contract.Transact(opts, "approve", spender, amount) +} + +func (_ERC677 *ERC677Session) Approve(spender common.Address, amount *big.Int) (*types.Transaction, error) { + return _ERC677.Contract.Approve(&_ERC677.TransactOpts, spender, amount) +} + +func (_ERC677 *ERC677TransactorSession) Approve(spender common.Address, amount *big.Int) (*types.Transaction, error) { + return _ERC677.Contract.Approve(&_ERC677.TransactOpts, spender, amount) +} + +func (_ERC677 *ERC677Transactor) DecreaseAllowance(opts *bind.TransactOpts, spender common.Address, subtractedValue *big.Int) (*types.Transaction, error) { + return _ERC677.contract.Transact(opts, "decreaseAllowance", spender, subtractedValue) +} + +func (_ERC677 *ERC677Session) DecreaseAllowance(spender common.Address, subtractedValue *big.Int) (*types.Transaction, error) { + return _ERC677.Contract.DecreaseAllowance(&_ERC677.TransactOpts, spender, subtractedValue) +} + +func (_ERC677 *ERC677TransactorSession) DecreaseAllowance(spender common.Address, subtractedValue *big.Int) (*types.Transaction, error) { + return _ERC677.Contract.DecreaseAllowance(&_ERC677.TransactOpts, spender, subtractedValue) +} + +func (_ERC677 *ERC677Transactor) IncreaseAllowance(opts *bind.TransactOpts, spender common.Address, addedValue *big.Int) (*types.Transaction, error) { + return _ERC677.contract.Transact(opts, "increaseAllowance", spender, addedValue) +} + +func (_ERC677 *ERC677Session) IncreaseAllowance(spender common.Address, addedValue *big.Int) (*types.Transaction, error) { + return _ERC677.Contract.IncreaseAllowance(&_ERC677.TransactOpts, spender, addedValue) +} + +func (_ERC677 *ERC677TransactorSession) IncreaseAllowance(spender common.Address, addedValue *big.Int) (*types.Transaction, error) { + return _ERC677.Contract.IncreaseAllowance(&_ERC677.TransactOpts, spender, addedValue) +} + +func (_ERC677 *ERC677Transactor) Transfer(opts *bind.TransactOpts, to common.Address, amount *big.Int) (*types.Transaction, error) { + return _ERC677.contract.Transact(opts, "transfer", to, amount) +} + +func (_ERC677 *ERC677Session) Transfer(to common.Address, amount *big.Int) (*types.Transaction, error) { + return _ERC677.Contract.Transfer(&_ERC677.TransactOpts, to, amount) +} + +func (_ERC677 *ERC677TransactorSession) Transfer(to common.Address, amount *big.Int) (*types.Transaction, error) { + return _ERC677.Contract.Transfer(&_ERC677.TransactOpts, to, amount) +} + +func (_ERC677 *ERC677Transactor) TransferAndCall(opts *bind.TransactOpts, to common.Address, amount *big.Int, data []byte) (*types.Transaction, error) { + return _ERC677.contract.Transact(opts, "transferAndCall", to, amount, data) +} + +func (_ERC677 *ERC677Session) TransferAndCall(to common.Address, amount *big.Int, data []byte) (*types.Transaction, error) { + return _ERC677.Contract.TransferAndCall(&_ERC677.TransactOpts, to, amount, data) +} + +func (_ERC677 *ERC677TransactorSession) TransferAndCall(to common.Address, amount *big.Int, data []byte) (*types.Transaction, error) { + return _ERC677.Contract.TransferAndCall(&_ERC677.TransactOpts, to, amount, data) +} + +func (_ERC677 *ERC677Transactor) TransferFrom(opts *bind.TransactOpts, from common.Address, to common.Address, amount *big.Int) (*types.Transaction, error) { + return _ERC677.contract.Transact(opts, "transferFrom", from, to, amount) +} + +func (_ERC677 *ERC677Session) TransferFrom(from common.Address, to common.Address, amount *big.Int) (*types.Transaction, error) { + return _ERC677.Contract.TransferFrom(&_ERC677.TransactOpts, from, to, amount) +} + +func (_ERC677 *ERC677TransactorSession) TransferFrom(from common.Address, to common.Address, amount *big.Int) (*types.Transaction, error) { + return _ERC677.Contract.TransferFrom(&_ERC677.TransactOpts, from, to, amount) +} + +type ERC677ApprovalIterator struct { + Event *ERC677Approval + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *ERC677ApprovalIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(ERC677Approval) + 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(ERC677Approval) + 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 *ERC677ApprovalIterator) Error() error { + return it.fail +} + +func (it *ERC677ApprovalIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type ERC677Approval struct { + Owner common.Address + Spender common.Address + Value *big.Int + Raw types.Log +} + +func (_ERC677 *ERC677Filterer) FilterApproval(opts *bind.FilterOpts, owner []common.Address, spender []common.Address) (*ERC677ApprovalIterator, error) { + + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + var spenderRule []interface{} + for _, spenderItem := range spender { + spenderRule = append(spenderRule, spenderItem) + } + + logs, sub, err := _ERC677.contract.FilterLogs(opts, "Approval", ownerRule, spenderRule) + if err != nil { + return nil, err + } + return &ERC677ApprovalIterator{contract: _ERC677.contract, event: "Approval", logs: logs, sub: sub}, nil +} + +func (_ERC677 *ERC677Filterer) WatchApproval(opts *bind.WatchOpts, sink chan<- *ERC677Approval, owner []common.Address, spender []common.Address) (event.Subscription, error) { + + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + var spenderRule []interface{} + for _, spenderItem := range spender { + spenderRule = append(spenderRule, spenderItem) + } + + logs, sub, err := _ERC677.contract.WatchLogs(opts, "Approval", ownerRule, spenderRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(ERC677Approval) + if err := _ERC677.contract.UnpackLog(event, "Approval", 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 (_ERC677 *ERC677Filterer) ParseApproval(log types.Log) (*ERC677Approval, error) { + event := new(ERC677Approval) + if err := _ERC677.contract.UnpackLog(event, "Approval", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type ERC677TransferIterator struct { + Event *ERC677Transfer + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *ERC677TransferIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(ERC677Transfer) + 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(ERC677Transfer) + 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 *ERC677TransferIterator) Error() error { + return it.fail +} + +func (it *ERC677TransferIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type ERC677Transfer struct { + From common.Address + To common.Address + Value *big.Int + Raw types.Log +} + +func (_ERC677 *ERC677Filterer) FilterTransfer(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*ERC677TransferIterator, 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 := _ERC677.contract.FilterLogs(opts, "Transfer", fromRule, toRule) + if err != nil { + return nil, err + } + return &ERC677TransferIterator{contract: _ERC677.contract, event: "Transfer", logs: logs, sub: sub}, nil +} + +func (_ERC677 *ERC677Filterer) WatchTransfer(opts *bind.WatchOpts, sink chan<- *ERC677Transfer, 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 := _ERC677.contract.WatchLogs(opts, "Transfer", 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(ERC677Transfer) + if err := _ERC677.contract.UnpackLog(event, "Transfer", 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 (_ERC677 *ERC677Filterer) ParseTransfer(log types.Log) (*ERC677Transfer, error) { + event := new(ERC677Transfer) + if err := _ERC677.contract.UnpackLog(event, "Transfer", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type ERC677Transfer0Iterator struct { + Event *ERC677Transfer0 + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *ERC677Transfer0Iterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(ERC677Transfer0) + 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(ERC677Transfer0) + 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 *ERC677Transfer0Iterator) Error() error { + return it.fail +} + +func (it *ERC677Transfer0Iterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type ERC677Transfer0 struct { + From common.Address + To common.Address + Value *big.Int + Data []byte + Raw types.Log +} + +func (_ERC677 *ERC677Filterer) FilterTransfer0(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*ERC677Transfer0Iterator, 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 := _ERC677.contract.FilterLogs(opts, "Transfer0", fromRule, toRule) + if err != nil { + return nil, err + } + return &ERC677Transfer0Iterator{contract: _ERC677.contract, event: "Transfer0", logs: logs, sub: sub}, nil +} + +func (_ERC677 *ERC677Filterer) WatchTransfer0(opts *bind.WatchOpts, sink chan<- *ERC677Transfer0, 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 := _ERC677.contract.WatchLogs(opts, "Transfer0", 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(ERC677Transfer0) + if err := _ERC677.contract.UnpackLog(event, "Transfer0", 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 (_ERC677 *ERC677Filterer) ParseTransfer0(log types.Log) (*ERC677Transfer0, error) { + event := new(ERC677Transfer0) + if err := _ERC677.contract.UnpackLog(event, "Transfer0", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_ERC677 *ERC677) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _ERC677.abi.Events["Approval"].ID: + return _ERC677.ParseApproval(log) + case _ERC677.abi.Events["Transfer"].ID: + return _ERC677.ParseTransfer(log) + case _ERC677.abi.Events["Transfer0"].ID: + return _ERC677.ParseTransfer0(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (ERC677Approval) Topic() common.Hash { + return common.HexToHash("0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925") +} + +func (ERC677Transfer) Topic() common.Hash { + return common.HexToHash("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef") +} + +func (ERC677Transfer0) Topic() common.Hash { + return common.HexToHash("0xe19260aff97b920c7df27010903aeb9c8d2be5d310a2c67824cf3f15396e4c16") +} + +func (_ERC677 *ERC677) Address() common.Address { + return _ERC677.address +} + +type ERC677Interface interface { + Allowance(opts *bind.CallOpts, owner common.Address, spender common.Address) (*big.Int, error) + + BalanceOf(opts *bind.CallOpts, account common.Address) (*big.Int, error) + + Decimals(opts *bind.CallOpts) (uint8, error) + + Name(opts *bind.CallOpts) (string, error) + + Symbol(opts *bind.CallOpts) (string, error) + + TotalSupply(opts *bind.CallOpts) (*big.Int, error) + + Approve(opts *bind.TransactOpts, spender common.Address, amount *big.Int) (*types.Transaction, error) + + DecreaseAllowance(opts *bind.TransactOpts, spender common.Address, subtractedValue *big.Int) (*types.Transaction, error) + + IncreaseAllowance(opts *bind.TransactOpts, spender common.Address, addedValue *big.Int) (*types.Transaction, error) + + Transfer(opts *bind.TransactOpts, to common.Address, amount *big.Int) (*types.Transaction, error) + + TransferAndCall(opts *bind.TransactOpts, to common.Address, amount *big.Int, data []byte) (*types.Transaction, error) + + TransferFrom(opts *bind.TransactOpts, from common.Address, to common.Address, amount *big.Int) (*types.Transaction, error) + + FilterApproval(opts *bind.FilterOpts, owner []common.Address, spender []common.Address) (*ERC677ApprovalIterator, error) + + WatchApproval(opts *bind.WatchOpts, sink chan<- *ERC677Approval, owner []common.Address, spender []common.Address) (event.Subscription, error) + + ParseApproval(log types.Log) (*ERC677Approval, error) + + FilterTransfer(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*ERC677TransferIterator, error) + + WatchTransfer(opts *bind.WatchOpts, sink chan<- *ERC677Transfer, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseTransfer(log types.Log) (*ERC677Transfer, error) + + FilterTransfer0(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*ERC677Transfer0Iterator, error) + + WatchTransfer0(opts *bind.WatchOpts, sink chan<- *ERC677Transfer0, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseTransfer0(log types.Log) (*ERC677Transfer0, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/shared/generated/link_token/link_token.go b/core/gethwrappers/shared/generated/link_token/link_token.go index 14676806266..ff7d4dcec8b 100644 --- a/core/gethwrappers/shared/generated/link_token/link_token.go +++ b/core/gethwrappers/shared/generated/link_token/link_token.go @@ -31,7 +31,7 @@ var ( ) var LinkTokenMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"supplyAfterMint\",\"type\":\"uint256\"}],\"name\":\"MaxSupplyExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotBurner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotMinter\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"burner\",\"type\":\"address\"}],\"name\":\"BurnAccessGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"burner\",\"type\":\"address\"}],\"name\":\"BurnAccessRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"}],\"name\":\"MintAccessGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"}],\"name\":\"MintAccessRevoked\",\"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\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burnFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseApproval\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBurners\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getMinters\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"burner\",\"type\":\"address\"}],\"name\":\"grantBurnRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"burnAndMinter\",\"type\":\"address\"}],\"name\":\"grantMintAndBurnRoles\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"}],\"name\":\"grantMintRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseApproval\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"burner\",\"type\":\"address\"}],\"name\":\"isBurner\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"}],\"name\":\"isMinter\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"burner\",\"type\":\"address\"}],\"name\":\"revokeBurnRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"}],\"name\":\"revokeMintRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"transferAndCall\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"type\":\"constructor\",\"inputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"acceptOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"allowance\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"approve\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"balanceOf\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"burn\",\"inputs\":[{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"burn\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"burnFrom\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"decimals\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"decreaseAllowance\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"subtractedValue\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"decreaseApproval\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"subtractedValue\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"success\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getBurners\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getMinters\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"grantBurnRole\",\"inputs\":[{\"name\":\"burner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"grantMintAndBurnRoles\",\"inputs\":[{\"name\":\"burnAndMinter\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"grantMintRole\",\"inputs\":[{\"name\":\"minter\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"increaseAllowance\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"addedValue\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"increaseApproval\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"addedValue\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"isBurner\",\"inputs\":[{\"name\":\"burner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isMinter\",\"inputs\":[{\"name\":\"minter\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"maxSupply\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"mint\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"name\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"revokeBurnRole\",\"inputs\":[{\"name\":\"burner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"revokeMintRole\",\"inputs\":[{\"name\":\"minter\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"symbol\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"totalSupply\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transfer\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferAndCall\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"success\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferFrom\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"Approval\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"spender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"BurnAccessGranted\",\"inputs\":[{\"name\":\"burner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"BurnAccessRevoked\",\"inputs\":[{\"name\":\"burner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"MintAccessGranted\",\"inputs\":[{\"name\":\"minter\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"MintAccessRevoked\",\"inputs\":[{\"name\":\"minter\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferRequested\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Transfer\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Transfer\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"MaxSupplyExceeded\",\"inputs\":[{\"name\":\"supplyAfterMint\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"SenderNotBurner\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"SenderNotMinter\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"}]}]", Bin: "0x60c06040523480156200001157600080fd5b506040518060400160405280600f81526020016e21b430b4b72634b735902a37b5b2b760891b815250604051806040016040528060048152602001634c494e4b60e01b81525060126b033b2e3c9fd0803ce8000000338060008686818181600390816200007f91906200028c565b5060046200008e82826200028c565b5050506001600160a01b0384169150620000f190505760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600580546001600160a01b0319166001600160a01b0384811691909117909155811615620001245762000124816200013b565b50505060ff90911660805260a05250620003589050565b336001600160a01b03821603620001955760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620000e8565b600680546001600160a01b0319166001600160a01b03838116918217909255600554604051919216907fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae127890600090a350565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200021257607f821691505b6020821081036200023357634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200028757600081815260208120601f850160051c81016020861015620002625750805b601f850160051c820191505b8181101562000283578281556001016200026e565b5050505b505050565b81516001600160401b03811115620002a857620002a8620001e7565b620002c081620002b98454620001fd565b8462000239565b602080601f831160018114620002f85760008415620002df5750858301515b600019600386901b1c1916600185901b17855562000283565b600085815260208120601f198616915b82811015620003295788860151825594840194600190910190840162000308565b5085821015620003485787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a051611e4c6200038c60003960008181610447015281816108c301526108ed015260006102710152611e4c6000f3fe608060405234801561001057600080fd5b50600436106101f05760003560e01c806379cc67901161010f578063c2e3273d116100a2578063d73dd62311610071578063d73dd6231461046b578063dd62ed3e1461047e578063f2fde38b146104c4578063f81094f3146104d757600080fd5b8063c2e3273d1461040c578063c630948d1461041f578063c64d0ebc14610432578063d5abeb011461044557600080fd5b80639dc29fac116100de5780639dc29fac146103c0578063a457c2d7146103d3578063a9059cbb146103e6578063aa271e1a146103f957600080fd5b806379cc67901461037557806386fe8b43146103885780638da5cb5b1461039057806395d89b41146103b857600080fd5b806340c10f19116101875780636618846311610156578063661884631461030f5780636b32810b1461032257806370a082311461033757806379ba50971461036d57600080fd5b806340c10f19146102c157806342966c68146102d65780634334614a146102e95780634f5632f8146102fc57600080fd5b806323b872dd116101c357806323b872dd14610257578063313ce5671461026a578063395093511461029b5780634000aea0146102ae57600080fd5b806301ffc9a7146101f557806306fdde031461021d578063095ea7b31461023257806318160ddd14610245575b600080fd5b6102086102033660046119b9565b6104ea565b60405190151581526020015b60405180910390f35b61022561061b565b6040516102149190611a5f565b610208610240366004611a9b565b6106ad565b6002545b604051908152602001610214565b610208610265366004611ac5565b6106c5565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610214565b6102086102a9366004611a9b565b6106e9565b6102086102bc366004611b30565b610735565b6102d46102cf366004611a9b565b610858565b005b6102d46102e4366004611c19565b61097f565b6102086102f7366004611c32565b6109cc565b6102d461030a366004611c32565b6109d9565b61020861031d366004611a9b565b610a35565b61032a610a48565b6040516102149190611c4d565b610249610345366004611c32565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6102d4610a59565b6102d4610383366004611a9b565b610b5a565b61032a610ba9565b60055460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610214565b610225610bb5565b6102d46103ce366004611a9b565b610bc4565b6102086103e1366004611a9b565b610bce565b6102086103f4366004611a9b565b610c9f565b610208610407366004611c32565b610cad565b6102d461041a366004611c32565b610cba565b6102d461042d366004611c32565b610d16565b6102d4610440366004611c32565b610d24565b7f0000000000000000000000000000000000000000000000000000000000000000610249565b6102d4610479366004611a9b565b610d80565b61024961048c366004611ca7565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6102d46104d2366004611c32565b610d8a565b6102d46104e5366004611c32565b610d9b565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f36372b0700000000000000000000000000000000000000000000000000000000148061057d57507fffffffff0000000000000000000000000000000000000000000000000000000082167f4000aea000000000000000000000000000000000000000000000000000000000145b806105c957507fffffffff0000000000000000000000000000000000000000000000000000000082167fe6599b4d00000000000000000000000000000000000000000000000000000000145b8061061557507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b60606003805461062a90611cda565b80601f016020809104026020016040519081016040528092919081815260200182805461065690611cda565b80156106a35780601f10610678576101008083540402835291602001916106a3565b820191906000526020600020905b81548152906001019060200180831161068657829003601f168201915b5050505050905090565b6000336106bb818585610df7565b5060019392505050565b6000336106d3858285610e2b565b6106de858585610efc565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906106bb9082908690610730908790611d5c565b610df7565b60006107418484610c9f565b508373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fe19260aff97b920c7df27010903aeb9c8d2be5d310a2c67824cf3f15396e4c1685856040516107a1929190611d6f565b60405180910390a373ffffffffffffffffffffffffffffffffffffffff84163b156106bb576040517fa4c0ed3600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85169063a4c0ed369061081c90339087908790600401611d90565b600060405180830381600087803b15801561083657600080fd5b505af115801561084a573d6000803e3d6000fd5b505050505060019392505050565b61086133610cad565b61089e576040517fe2c8c9d50000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b813073ffffffffffffffffffffffffffffffffffffffff8216036108c157600080fd5b7f00000000000000000000000000000000000000000000000000000000000000001580159061092257507f00000000000000000000000000000000000000000000000000000000000000008261091660025490565b6109209190611d5c565b115b15610970578161093160025490565b61093b9190611d5c565b6040517fcbbf111300000000000000000000000000000000000000000000000000000000815260040161089591815260200190565b61097a8383610f2a565b505050565b610988336109cc565b6109c0576040517fc820b10b000000000000000000000000000000000000000000000000000000008152336004820152602401610895565b6109c98161101d565b50565b6000610615600983611027565b6109e1611056565b6109ec6009826110d9565b156109c95760405173ffffffffffffffffffffffffffffffffffffffff8216907f0a675452746933cefe3d74182e78db7afe57ba60eaa4234b5d85e9aa41b0610c90600090a250565b6000610a418383610bce565b9392505050565b6060610a5460076110fb565b905090565b60065473ffffffffffffffffffffffffffffffffffffffff163314610ada576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610895565b600580547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560068054909116905560405173ffffffffffffffffffffffffffffffffffffffff909116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a350565b610b63336109cc565b610b9b576040517fc820b10b000000000000000000000000000000000000000000000000000000008152336004820152602401610895565b610ba58282611108565b5050565b6060610a5460096110fb565b60606004805461062a90611cda565b610ba58282610b5a565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610c92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610895565b6106de8286868403610df7565b6000336106bb818585610efc565b6000610615600783611027565b610cc2611056565b610ccd60078261111d565b156109c95760405173ffffffffffffffffffffffffffffffffffffffff8216907fe46fef8bbff1389d9010703cf8ebb363fb3daf5bf56edc27080b67bc8d9251ea90600090a250565b610d1f81610cba565b6109c9815b610d2c611056565b610d3760098261111d565b156109c95760405173ffffffffffffffffffffffffffffffffffffffff8216907f92308bb7573b2a3d17ddb868b39d8ebec433f3194421abc22d084f89658c9bad90600090a250565b61097a82826106e9565b610d92611056565b6109c98161113f565b610da3611056565b610dae6007826110d9565b156109c95760405173ffffffffffffffffffffffffffffffffffffffff8216907fed998b960f6340d045f620c119730f7aa7995e7425c2401d3a5b64ff998a59e990600090a250565b813073ffffffffffffffffffffffffffffffffffffffff821603610e1a57600080fd5b610e25848484611235565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610e255781811015610eef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610895565b610e258484848403610df7565b813073ffffffffffffffffffffffffffffffffffffffff821603610f1f57600080fd5b610e258484846113e8565b73ffffffffffffffffffffffffffffffffffffffff8216610fa7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610895565b8060026000828254610fb99190611d5c565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b6109c93382611657565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610a41565b60055473ffffffffffffffffffffffffffffffffffffffff1633146110d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610895565b565b6000610a418373ffffffffffffffffffffffffffffffffffffffff841661181b565b60606000610a418361190e565b611113823383610e2b565b610ba58282611657565b6000610a418373ffffffffffffffffffffffffffffffffffffffff841661196a565b3373ffffffffffffffffffffffffffffffffffffffff8216036111be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610895565b600680547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217909255600554604051919216907fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae127890600090a350565b73ffffffffffffffffffffffffffffffffffffffff83166112d7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610895565b73ffffffffffffffffffffffffffffffffffffffff821661137a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610895565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff831661148b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610895565b73ffffffffffffffffffffffffffffffffffffffff821661152e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610895565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040902054818110156115e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610895565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610e25565b73ffffffffffffffffffffffffffffffffffffffff82166116fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610895565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054818110156117b0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610895565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b6000818152600183016020526040812054801561190457600061183f600183611dce565b855490915060009061185390600190611dce565b90508181146118b857600086600001828154811061187357611873611de1565b906000526020600020015490508087600001848154811061189657611896611de1565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806118c9576118c9611e10565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610615565b6000915050610615565b60608160000180548060200260200160405190810160405280929190818152602001828054801561195e57602002820191906000526020600020905b81548152602001906001019080831161194a575b50505050509050919050565b60008181526001830160205260408120546119b157508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610615565b506000610615565b6000602082840312156119cb57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610a4157600080fd5b6000815180845260005b81811015611a2157602081850181015186830182015201611a05565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610a4160208301846119fb565b803573ffffffffffffffffffffffffffffffffffffffff81168114611a9657600080fd5b919050565b60008060408385031215611aae57600080fd5b611ab783611a72565b946020939093013593505050565b600080600060608486031215611ada57600080fd5b611ae384611a72565b9250611af160208501611a72565b9150604084013590509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060608486031215611b4557600080fd5b611b4e84611a72565b925060208401359150604084013567ffffffffffffffff80821115611b7257600080fd5b818601915086601f830112611b8657600080fd5b813581811115611b9857611b98611b01565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611bde57611bde611b01565b81604052828152896020848701011115611bf757600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b600060208284031215611c2b57600080fd5b5035919050565b600060208284031215611c4457600080fd5b610a4182611a72565b6020808252825182820181905260009190848201906040850190845b81811015611c9b57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101611c69565b50909695505050505050565b60008060408385031215611cba57600080fd5b611cc383611a72565b9150611cd160208401611a72565b90509250929050565b600181811c90821680611cee57607f821691505b602082108103611d27577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561061557610615611d2d565b828152604060208201526000611d8860408301846119fb565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff84168152826020820152606060408201526000611dc560608301846119fb565b95945050505050565b8181038181111561061557610615611d2d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000813000a", } diff --git a/core/gethwrappers/generated/log_emitter/log_emitter.go b/core/gethwrappers/shared/generated/log_emitter/log_emitter.go similarity index 93% rename from core/gethwrappers/generated/log_emitter/log_emitter.go rename to core/gethwrappers/shared/generated/log_emitter/log_emitter.go index 24fef257af3..6ae06d7f08d 100644 --- a/core/gethwrappers/generated/log_emitter/log_emitter.go +++ b/core/gethwrappers/shared/generated/log_emitter/log_emitter.go @@ -31,7 +31,7 @@ var ( ) var LogEmitterMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"Log1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"Log2\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"Log3\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"Log4\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"v\",\"type\":\"uint256[]\"}],\"name\":\"EmitLog1\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"v\",\"type\":\"uint256[]\"}],\"name\":\"EmitLog2\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string[]\",\"name\":\"v\",\"type\":\"string[]\"}],\"name\":\"EmitLog3\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"v\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"w\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"c\",\"type\":\"uint256\"}],\"name\":\"EmitLog4\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"type\":\"function\",\"name\":\"EmitLog1\",\"inputs\":[{\"name\":\"v\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"EmitLog2\",\"inputs\":[{\"name\":\"v\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"EmitLog3\",\"inputs\":[{\"name\":\"v\",\"type\":\"string[]\",\"internalType\":\"string[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"EmitLog4\",\"inputs\":[{\"name\":\"v\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"w\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"c\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"Log1\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Log2\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Log3\",\"inputs\":[{\"name\":\"\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Log4\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"}],\"anonymous\":false}]", Bin: "0x608060405234801561001057600080fd5b506105c5806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c8063696933c914610051578063b4b12d9814610066578063bc253bc014610079578063d9c21f461461008c575b600080fd5b61006461005f3660046102d7565b61009f565b005b61006461007436600461036d565b610113565b6100646100873660046102d7565b610163565b61006461009a366004610399565b6101c7565b60005b815181101561010f577f46692c0e59ca9cd1ad8f984a9d11715ec83424398b7eed4e05c8ce84662415a88282815181106100de576100de6104be565b60200260200101516040516100f591815260200190565b60405180910390a180610107816104ed565b9150506100a2565b5050565b60005b8181101561015d57604051839085907fba21d5b63d64546cb4ab29e370a8972bf26f78cb0c395391b4f451699fdfdc5d90600090a380610155816104ed565b915050610116565b50505050565b60005b815181101561010f57818181518110610181576101816104be565b60200260200101517f624fb00c2ce79f34cb543884c3af64816dce0f4cec3d32661959e49d488a7a9360405160405180910390a2806101bf816104ed565b915050610166565b60005b815181101561010f577fb94ec34dfe32a8a7170992a093976368d1e63decf8f0bc0b38a8eb89cc9f95cf828281518110610206576102066104be565b602002602001015160405161021b919061054c565b60405180910390a18061022d816104ed565b9150506101ca565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156102ab576102ab610235565b604052919050565b600067ffffffffffffffff8211156102cd576102cd610235565b5060051b60200190565b600060208083850312156102ea57600080fd5b823567ffffffffffffffff81111561030157600080fd5b8301601f8101851361031257600080fd5b8035610325610320826102b3565b610264565b81815260059190911b8201830190838101908783111561034457600080fd5b928401925b8284101561036257833582529284019290840190610349565b979650505050505050565b60008060006060848603121561038257600080fd5b505081359360208301359350604090920135919050565b600060208083850312156103ac57600080fd5b823567ffffffffffffffff808211156103c457600080fd5b8185019150601f86818401126103d957600080fd5b82356103e7610320826102b3565b81815260059190911b8401850190858101908983111561040657600080fd5b8686015b838110156104b0578035868111156104225760008081fd5b8701603f81018c136104345760008081fd5b8881013560408882111561044a5761044a610235565b6104798b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08a85011601610264565b8281528e8284860101111561048e5760008081fd5b828285018d83013760009281018c01929092525084525091870191870161040a565b509998505050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610545577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b600060208083528351808285015260005b818110156105795785810183015185820160400152820161055d565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116850101925050509291505056fea164736f6c6343000813000a", } diff --git a/core/gethwrappers/ccip/generated/mock_v3_aggregator_contract/mock_v3_aggregator_contract.go b/core/gethwrappers/shared/generated/mock_v3_aggregator_contract/mock_v3_aggregator_contract.go similarity index 83% rename from core/gethwrappers/ccip/generated/mock_v3_aggregator_contract/mock_v3_aggregator_contract.go rename to core/gethwrappers/shared/generated/mock_v3_aggregator_contract/mock_v3_aggregator_contract.go index c3521d35151..616ffef18c3 100644 --- a/core/gethwrappers/ccip/generated/mock_v3_aggregator_contract/mock_v3_aggregator_contract.go +++ b/core/gethwrappers/shared/generated/mock_v3_aggregator_contract/mock_v3_aggregator_contract.go @@ -31,8 +31,8 @@ var ( ) var MockV3AggregatorMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"_decimals\",\"type\":\"uint8\"},{\"internalType\":\"int256\",\"name\":\"_initialAnswer\",\"type\":\"int256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"int256\",\"name\":\"current\",\"type\":\"int256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"roundId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"updatedAt\",\"type\":\"uint256\"}],\"name\":\"AnswerUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"roundId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"startedBy\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startedAt\",\"type\":\"uint256\"}],\"name\":\"NewRound\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"description\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"getAnswer\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint80\",\"name\":\"_roundId\",\"type\":\"uint80\"}],\"name\":\"getRoundData\",\"outputs\":[{\"internalType\":\"uint80\",\"name\":\"roundId\",\"type\":\"uint80\"},{\"internalType\":\"int256\",\"name\":\"answer\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"startedAt\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"updatedAt\",\"type\":\"uint256\"},{\"internalType\":\"uint80\",\"name\":\"answeredInRound\",\"type\":\"uint80\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"getTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestAnswer\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestRound\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestRoundData\",\"outputs\":[{\"internalType\":\"uint80\",\"name\":\"roundId\",\"type\":\"uint80\"},{\"internalType\":\"int256\",\"name\":\"answer\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"startedAt\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"updatedAt\",\"type\":\"uint256\"},{\"internalType\":\"uint80\",\"name\":\"answeredInRound\",\"type\":\"uint80\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"_answer\",\"type\":\"int256\"}],\"name\":\"updateAnswer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint80\",\"name\":\"_roundId\",\"type\":\"uint80\"},{\"internalType\":\"int256\",\"name\":\"_answer\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startedAt\",\"type\":\"uint256\"}],\"name\":\"updateRoundData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5060405161059638038061059683398101604081905261002f916100a4565b6000805460ff191660ff84161790556100478161004e565b50506100ff565b60018190554260025560038054906000610067836100d8565b9091555050600380546000908152600460209081526040808320949094558254825260058152838220429081905592548252600690529190912055565b600080604083850312156100b757600080fd5b825160ff811681146100c857600080fd5b6020939093015192949293505050565b6000600182016100f857634e487b7160e01b600052601160045260246000fd5b5060010190565b6104888061010e6000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c80638205bf6a11610081578063b5ab58dc1161005b578063b5ab58dc1461025b578063b633620c1461027b578063feaf968c1461029b57600080fd5b80638205bf6a146101c15780639a6fc8f5146101ca578063a87a20ce1461024857600080fd5b806354fd4d50116100b257806354fd4d5014610171578063668a0f02146101795780637284e4161461018257600080fd5b8063313ce567146100d95780634aa2011f146100fd57806350d25bcd1461015a575b600080fd5b6000546100e69060ff1681565b60405160ff90911681526020015b60405180910390f35b61015861010b36600461033b565b69ffffffffffffffffffff90931660038181556001849055600283905560009182526004602090815260408084209590955581548352600581528483209390935554815260069091522055565b005b61016360015481565b6040519081526020016100f4565b610163600081565b61016360035481565b604080518082018252601f81527f76302e382f74657374732f4d6f636b563341676772656761746f722e736f6c00602082015290516100f49190610374565b61016360025481565b6102116101d83660046103e1565b69ffffffffffffffffffff8116600090815260046020908152604080832054600683528184205460059093529220549293919290918490565b6040805169ffffffffffffffffffff968716815260208101959095528401929092526060830152909116608082015260a0016100f4565b610158610256366004610403565b6102c6565b610163610269366004610403565b60046020526000908152604090205481565b610163610289366004610403565b60056020526000908152604090205481565b6003546000818152600460209081526040808320546006835281842054600590935292205483610211565b600181905542600255600380549060006102df8361041c565b9091555050600380546000908152600460209081526040808320949094558254825260058152838220429081905592548252600690529190912055565b803569ffffffffffffffffffff8116811461033657600080fd5b919050565b6000806000806080858703121561035157600080fd5b61035a8561031c565b966020860135965060408601359560600135945092505050565b60006020808352835180602085015260005b818110156103a257858101830151858201604001528201610386565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b6000602082840312156103f357600080fd5b6103fc8261031c565b9392505050565b60006020828403121561041557600080fd5b5035919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610474577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b506001019056fea164736f6c6343000818000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_decimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"_initialAnswer\",\"type\":\"int256\",\"internalType\":\"int256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"decimals\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"description\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"getAnswer\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"int256\",\"internalType\":\"int256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRoundData\",\"inputs\":[{\"name\":\"_roundId\",\"type\":\"uint80\",\"internalType\":\"uint80\"}],\"outputs\":[{\"name\":\"roundId\",\"type\":\"uint80\",\"internalType\":\"uint80\"},{\"name\":\"answer\",\"type\":\"int256\",\"internalType\":\"int256\"},{\"name\":\"startedAt\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"updatedAt\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"answeredInRound\",\"type\":\"uint80\",\"internalType\":\"uint80\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTimestamp\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"latestAnswer\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"int256\",\"internalType\":\"int256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"latestRound\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"latestRoundData\",\"inputs\":[],\"outputs\":[{\"name\":\"roundId\",\"type\":\"uint80\",\"internalType\":\"uint80\"},{\"name\":\"answer\",\"type\":\"int256\",\"internalType\":\"int256\"},{\"name\":\"startedAt\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"updatedAt\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"answeredInRound\",\"type\":\"uint80\",\"internalType\":\"uint80\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"latestTimestamp\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"updateAnswer\",\"inputs\":[{\"name\":\"_answer\",\"type\":\"int256\",\"internalType\":\"int256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"updateRoundData\",\"inputs\":[{\"name\":\"_roundId\",\"type\":\"uint80\",\"internalType\":\"uint80\"},{\"name\":\"_answer\",\"type\":\"int256\",\"internalType\":\"int256\"},{\"name\":\"_timestamp\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_startedAt\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"version\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"AnswerUpdated\",\"inputs\":[{\"name\":\"current\",\"type\":\"int256\",\"indexed\":true,\"internalType\":\"int256\"},{\"name\":\"roundId\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"updatedAt\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"NewRound\",\"inputs\":[{\"name\":\"roundId\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"startedBy\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"startedAt\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false}]", + Bin: "0x608060405234801561001057600080fd5b5060405161059538038061059583398101604081905261002f916100a4565b6000805460ff191660ff84161790556100478161004e565b50506100ff565b60018190554260025560038054906000610067836100d8565b9091555050600380546000908152600460209081526040808320949094558254825260058152838220429081905592548252600690529190912055565b600080604083850312156100b757600080fd5b825160ff811681146100c857600080fd5b6020939093015192949293505050565b6000600182016100f857634e487b7160e01b600052601160045260246000fd5b5060010190565b6104878061010e6000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c80638205bf6a11610081578063b5ab58dc1161005b578063b5ab58dc1461025b578063b633620c1461027b578063feaf968c1461029b57600080fd5b80638205bf6a146101c15780639a6fc8f5146101ca578063a87a20ce1461024857600080fd5b806354fd4d50116100b257806354fd4d5014610171578063668a0f02146101795780637284e4161461018257600080fd5b8063313ce567146100d95780634aa2011f146100fd57806350d25bcd1461015a575b600080fd5b6000546100e69060ff1681565b60405160ff90911681526020015b60405180910390f35b61015861010b36600461033b565b69ffffffffffffffffffff90931660038181556001849055600283905560009182526004602090815260408084209590955581548352600581528483209390935554815260069091522055565b005b61016360015481565b6040519081526020016100f4565b610163600081565b61016360035481565b604080518082018252601f81527f76302e382f74657374732f4d6f636b563341676772656761746f722e736f6c00602082015290516100f49190610374565b61016360025481565b6102116101d83660046103e0565b69ffffffffffffffffffff8116600090815260046020908152604080832054600683528184205460059093529220549293919290918490565b6040805169ffffffffffffffffffff968716815260208101959095528401929092526060830152909116608082015260a0016100f4565b610158610256366004610402565b6102c6565b610163610269366004610402565b60046020526000908152604090205481565b610163610289366004610402565b60056020526000908152604090205481565b6003546000818152600460209081526040808320546006835281842054600590935292205483610211565b600181905542600255600380549060006102df8361041b565b9091555050600380546000908152600460209081526040808320949094558254825260058152838220429081905592548252600690529190912055565b803569ffffffffffffffffffff8116811461033657600080fd5b919050565b6000806000806080858703121561035157600080fd5b61035a8561031c565b966020860135965060408601359560600135945092505050565b600060208083528351808285015260005b818110156103a157858101830151858201604001528201610385565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b6000602082840312156103f257600080fd5b6103fb8261031c565b9392505050565b60006020828403121561041457600080fd5b5035919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610473577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b506001019056fea164736f6c6343000813000a", } var MockV3AggregatorABI = MockV3AggregatorMetaData.ABI diff --git a/core/gethwrappers/shared/generated/multicall3/multicall3.go b/core/gethwrappers/shared/generated/multicall3/multicall3.go index 91d612756b8..917d33f07f4 100644 --- a/core/gethwrappers/shared/generated/multicall3/multicall3.go +++ b/core/gethwrappers/shared/generated/multicall3/multicall3.go @@ -52,7 +52,7 @@ type Multicall3Result struct { } var Multicall3MetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"aggregate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"returnData\",\"type\":\"bytes[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"allowFailure\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Call3[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"aggregate3\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"allowFailure\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Call3Value[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"aggregate3Value\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"blockAndAggregate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBasefee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"basefee\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"name\":\"getBlockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getChainId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"chainid\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockCoinbase\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"coinbase\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockDifficulty\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"difficulty\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockGasLimit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"gaslimit\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"getEthBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLastBlockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"requireSuccess\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"tryAggregate\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"requireSuccess\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"tryBlockAndAggregate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + ABI: "[{\"type\":\"function\",\"name\":\"aggregate\",\"inputs\":[{\"name\":\"calls\",\"type\":\"tuple[]\",\"internalType\":\"structMulticall3.Call[]\",\"components\":[{\"name\":\"target\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"callData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"blockNumber\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"returnData\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"aggregate3\",\"inputs\":[{\"name\":\"calls\",\"type\":\"tuple[]\",\"internalType\":\"structMulticall3.Call3[]\",\"components\":[{\"name\":\"target\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"allowFailure\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"callData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"returnData\",\"type\":\"tuple[]\",\"internalType\":\"structMulticall3.Result[]\",\"components\":[{\"name\":\"success\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"returnData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"aggregate3Value\",\"inputs\":[{\"name\":\"calls\",\"type\":\"tuple[]\",\"internalType\":\"structMulticall3.Call3Value[]\",\"components\":[{\"name\":\"target\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"allowFailure\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"callData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"returnData\",\"type\":\"tuple[]\",\"internalType\":\"structMulticall3.Result[]\",\"components\":[{\"name\":\"success\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"returnData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"blockAndAggregate\",\"inputs\":[{\"name\":\"calls\",\"type\":\"tuple[]\",\"internalType\":\"structMulticall3.Call[]\",\"components\":[{\"name\":\"target\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"callData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"blockNumber\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"blockHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"returnData\",\"type\":\"tuple[]\",\"internalType\":\"structMulticall3.Result[]\",\"components\":[{\"name\":\"success\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"returnData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"getBasefee\",\"inputs\":[],\"outputs\":[{\"name\":\"basefee\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getBlockHash\",\"inputs\":[{\"name\":\"blockNumber\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"blockHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getBlockNumber\",\"inputs\":[],\"outputs\":[{\"name\":\"blockNumber\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getChainId\",\"inputs\":[],\"outputs\":[{\"name\":\"chainid\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCurrentBlockCoinbase\",\"inputs\":[],\"outputs\":[{\"name\":\"coinbase\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCurrentBlockDifficulty\",\"inputs\":[],\"outputs\":[{\"name\":\"difficulty\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCurrentBlockGasLimit\",\"inputs\":[],\"outputs\":[{\"name\":\"gaslimit\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCurrentBlockTimestamp\",\"inputs\":[],\"outputs\":[{\"name\":\"timestamp\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getEthBalance\",\"inputs\":[{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"balance\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getLastBlockHash\",\"inputs\":[],\"outputs\":[{\"name\":\"blockHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"tryAggregate\",\"inputs\":[{\"name\":\"requireSuccess\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"calls\",\"type\":\"tuple[]\",\"internalType\":\"structMulticall3.Call[]\",\"components\":[{\"name\":\"target\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"callData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"returnData\",\"type\":\"tuple[]\",\"internalType\":\"structMulticall3.Result[]\",\"components\":[{\"name\":\"success\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"returnData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"tryBlockAndAggregate\",\"inputs\":[{\"name\":\"requireSuccess\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"calls\",\"type\":\"tuple[]\",\"internalType\":\"structMulticall3.Call[]\",\"components\":[{\"name\":\"target\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"callData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"blockNumber\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"blockHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"returnData\",\"type\":\"tuple[]\",\"internalType\":\"structMulticall3.Result[]\",\"components\":[{\"name\":\"success\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"returnData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"stateMutability\":\"payable\"}]", Bin: "0x608060405234801561001057600080fd5b50610eb0806100206000396000f3fe6080604052600436106100f35760003560e01c80634d2301cc1161008a578063a8b0574e11610059578063a8b0574e1461025a578063bce38bd714610275578063c3077fa914610288578063ee82ac5e1461029b57600080fd5b80634d2301cc146101ec57806372425d9d1461022157806382ad56cb1461023457806386d516e81461024757600080fd5b80633408e470116100c65780633408e47014610191578063399542e9146101a45780633e64a696146101c657806342cbb15c146101d957600080fd5b80630f28c97d146100f8578063174dea711461011a578063252dba421461013a57806327e86d6e1461015b575b600080fd5b34801561010457600080fd5b50425b6040519081526020015b60405180910390f35b61012d610128366004610a85565b6102ba565b6040516101119190610bb7565b61014d610148366004610a85565b6104ef565b604051610111929190610bd1565b34801561016757600080fd5b50437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0140610107565b34801561019d57600080fd5b5046610107565b6101b76101b2366004610c59565b610690565b60405161011193929190610cb3565b3480156101d257600080fd5b5048610107565b3480156101e557600080fd5b5043610107565b3480156101f857600080fd5b50610107610207366004610cdb565b73ffffffffffffffffffffffffffffffffffffffff163190565b34801561022d57600080fd5b5044610107565b61012d610242366004610a85565b6106ab565b34801561025357600080fd5b5045610107565b34801561026657600080fd5b50604051418152602001610111565b61012d610283366004610c59565b61085a565b6101b7610296366004610a85565b610a1a565b3480156102a757600080fd5b506101076102b6366004610d11565b4090565b60606000828067ffffffffffffffff8111156102d8576102d8610d2a565b60405190808252806020026020018201604052801561031e57816020015b6040805180820190915260008152606060208201528152602001906001900390816102f65790505b5092503660005b8281101561047757600085828151811061034157610341610d59565b6020026020010151905087878381811061035d5761035d610d59565b905060200281019061036f9190610d88565b6040810135958601959093506103886020850185610cdb565b73ffffffffffffffffffffffffffffffffffffffff16816103ac6060870187610dc6565b6040516103ba929190610e2b565b60006040518083038185875af1925050503d80600081146103f7576040519150601f19603f3d011682016040523d82523d6000602084013e6103fc565b606091505b50602080850191909152901515808452908501351761046d577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260846000fd5b5050600101610325565b508234146104e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d756c746963616c6c333a2076616c7565206d69736d6174636800000000000060448201526064015b60405180910390fd5b50505092915050565b436060828067ffffffffffffffff81111561050c5761050c610d2a565b60405190808252806020026020018201604052801561053f57816020015b606081526020019060019003908161052a5790505b5091503660005b8281101561068657600087878381811061056257610562610d59565b90506020028101906105749190610e3b565b92506105836020840184610cdb565b73ffffffffffffffffffffffffffffffffffffffff166105a66020850185610dc6565b6040516105b4929190610e2b565b6000604051808303816000865af19150503d80600081146105f1576040519150601f19603f3d011682016040523d82523d6000602084013e6105f6565b606091505b5086848151811061060957610609610d59565b602090810291909101015290508061067d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b50600101610546565b5050509250929050565b43804060606106a086868661085a565b905093509350939050565b6060818067ffffffffffffffff8111156106c7576106c7610d2a565b60405190808252806020026020018201604052801561070d57816020015b6040805180820190915260008152606060208201528152602001906001900390816106e55790505b5091503660005b828110156104e657600084828151811061073057610730610d59565b6020026020010151905086868381811061074c5761074c610d59565b905060200281019061075e9190610e6f565b925061076d6020840184610cdb565b73ffffffffffffffffffffffffffffffffffffffff166107906040850185610dc6565b60405161079e929190610e2b565b6000604051808303816000865af19150503d80600081146107db576040519150601f19603f3d011682016040523d82523d6000602084013e6107e0565b606091505b506020808401919091529015158083529084013517610851577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260646000fd5b50600101610714565b6060818067ffffffffffffffff81111561087657610876610d2a565b6040519080825280602002602001820160405280156108bc57816020015b6040805180820190915260008152606060208201528152602001906001900390816108945790505b5091503660005b82811015610a105760008482815181106108df576108df610d59565b602002602001015190508686838181106108fb576108fb610d59565b905060200281019061090d9190610e3b565b925061091c6020840184610cdb565b73ffffffffffffffffffffffffffffffffffffffff1661093f6020850185610dc6565b60405161094d929190610e2b565b6000604051808303816000865af19150503d806000811461098a576040519150601f19603f3d011682016040523d82523d6000602084013e61098f565b606091505b506020830152151581528715610a07578051610a07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b506001016108c3565b5050509392505050565b6000806060610a2b60018686610690565b919790965090945092505050565b60008083601f840112610a4b57600080fd5b50813567ffffffffffffffff811115610a6357600080fd5b6020830191508360208260051b8501011115610a7e57600080fd5b9250929050565b60008060208385031215610a9857600080fd5b823567ffffffffffffffff811115610aaf57600080fd5b610abb85828601610a39565b90969095509350505050565b6000815180845260005b81811015610aed57602081850181015186830182015201610ad1565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b600082825180855260208086019550808260051b84010181860160005b84811015610baa578583037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001895281518051151584528401516040858501819052610b9681860183610ac7565b9a86019a9450505090830190600101610b48565b5090979650505050505050565b602081526000610bca6020830184610b2b565b9392505050565b600060408201848352602060408185015281855180845260608601915060608160051b870101935082870160005b82811015610c4b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018452610c39868351610ac7565b95509284019290840190600101610bff565b509398975050505050505050565b600080600060408486031215610c6e57600080fd5b83358015158114610c7e57600080fd5b9250602084013567ffffffffffffffff811115610c9a57600080fd5b610ca686828701610a39565b9497909650939450505050565b838152826020820152606060408201526000610cd26060830184610b2b565b95945050505050565b600060208284031215610ced57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610bca57600080fd5b600060208284031215610d2357600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112610dbc57600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610dfb57600080fd5b83018035915067ffffffffffffffff821115610e1657600080fd5b602001915036819003821315610a7e57600080fd5b8183823760009101908152919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112610dbc57600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1833603018112610dbc57600080fdfea164736f6c6343000813000a", } diff --git a/core/gethwrappers/shared/generated/type_and_version/type_and_version.go b/core/gethwrappers/shared/generated/type_and_version/type_and_version.go new file mode 100644 index 00000000000..a4a518d9ea2 --- /dev/null +++ b/core/gethwrappers/shared/generated/type_and_version/type_and_version.go @@ -0,0 +1,183 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package type_and_version + +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 ITypeAndVersionMetaData = &bind.MetaData{ + ABI: "[{\"type\":\"function\",\"name\":\"typeAndVersion\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"pure\"}]", +} + +var ITypeAndVersionABI = ITypeAndVersionMetaData.ABI + +type ITypeAndVersion struct { + address common.Address + abi abi.ABI + ITypeAndVersionCaller + ITypeAndVersionTransactor + ITypeAndVersionFilterer +} + +type ITypeAndVersionCaller struct { + contract *bind.BoundContract +} + +type ITypeAndVersionTransactor struct { + contract *bind.BoundContract +} + +type ITypeAndVersionFilterer struct { + contract *bind.BoundContract +} + +type ITypeAndVersionSession struct { + Contract *ITypeAndVersion + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type ITypeAndVersionCallerSession struct { + Contract *ITypeAndVersionCaller + CallOpts bind.CallOpts +} + +type ITypeAndVersionTransactorSession struct { + Contract *ITypeAndVersionTransactor + TransactOpts bind.TransactOpts +} + +type ITypeAndVersionRaw struct { + Contract *ITypeAndVersion +} + +type ITypeAndVersionCallerRaw struct { + Contract *ITypeAndVersionCaller +} + +type ITypeAndVersionTransactorRaw struct { + Contract *ITypeAndVersionTransactor +} + +func NewITypeAndVersion(address common.Address, backend bind.ContractBackend) (*ITypeAndVersion, error) { + abi, err := abi.JSON(strings.NewReader(ITypeAndVersionABI)) + if err != nil { + return nil, err + } + contract, err := bindITypeAndVersion(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &ITypeAndVersion{address: address, abi: abi, ITypeAndVersionCaller: ITypeAndVersionCaller{contract: contract}, ITypeAndVersionTransactor: ITypeAndVersionTransactor{contract: contract}, ITypeAndVersionFilterer: ITypeAndVersionFilterer{contract: contract}}, nil +} + +func NewITypeAndVersionCaller(address common.Address, caller bind.ContractCaller) (*ITypeAndVersionCaller, error) { + contract, err := bindITypeAndVersion(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ITypeAndVersionCaller{contract: contract}, nil +} + +func NewITypeAndVersionTransactor(address common.Address, transactor bind.ContractTransactor) (*ITypeAndVersionTransactor, error) { + contract, err := bindITypeAndVersion(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ITypeAndVersionTransactor{contract: contract}, nil +} + +func NewITypeAndVersionFilterer(address common.Address, filterer bind.ContractFilterer) (*ITypeAndVersionFilterer, error) { + contract, err := bindITypeAndVersion(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ITypeAndVersionFilterer{contract: contract}, nil +} + +func bindITypeAndVersion(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := ITypeAndVersionMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_ITypeAndVersion *ITypeAndVersionRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ITypeAndVersion.Contract.ITypeAndVersionCaller.contract.Call(opts, result, method, params...) +} + +func (_ITypeAndVersion *ITypeAndVersionRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ITypeAndVersion.Contract.ITypeAndVersionTransactor.contract.Transfer(opts) +} + +func (_ITypeAndVersion *ITypeAndVersionRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ITypeAndVersion.Contract.ITypeAndVersionTransactor.contract.Transact(opts, method, params...) +} + +func (_ITypeAndVersion *ITypeAndVersionCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ITypeAndVersion.Contract.contract.Call(opts, result, method, params...) +} + +func (_ITypeAndVersion *ITypeAndVersionTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ITypeAndVersion.Contract.contract.Transfer(opts) +} + +func (_ITypeAndVersion *ITypeAndVersionTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ITypeAndVersion.Contract.contract.Transact(opts, method, params...) +} + +func (_ITypeAndVersion *ITypeAndVersionCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _ITypeAndVersion.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_ITypeAndVersion *ITypeAndVersionSession) TypeAndVersion() (string, error) { + return _ITypeAndVersion.Contract.TypeAndVersion(&_ITypeAndVersion.CallOpts) +} + +func (_ITypeAndVersion *ITypeAndVersionCallerSession) TypeAndVersion() (string, error) { + return _ITypeAndVersion.Contract.TypeAndVersion(&_ITypeAndVersion.CallOpts) +} + +func (_ITypeAndVersion *ITypeAndVersion) Address() common.Address { + return _ITypeAndVersion.address +} + +type ITypeAndVersionInterface interface { + TypeAndVersion(opts *bind.CallOpts) (string, error) + + Address() common.Address +} diff --git a/core/gethwrappers/generated/vrf_log_emitter/vrf_log_emitter.go b/core/gethwrappers/shared/generated/vrf_log_emitter/vrf_log_emitter.go similarity index 88% rename from core/gethwrappers/generated/vrf_log_emitter/vrf_log_emitter.go rename to core/gethwrappers/shared/generated/vrf_log_emitter/vrf_log_emitter.go index 2cdeaa6c3a8..db6fae033a8 100644 --- a/core/gethwrappers/generated/vrf_log_emitter/vrf_log_emitter.go +++ b/core/gethwrappers/shared/generated/vrf_log_emitter/vrf_log_emitter.go @@ -31,7 +31,7 @@ var ( ) var VRFLogEmitterMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"outputSeed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"payment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"name\":\"RandomWordsFulfilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"preSeed\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"subId\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"minimumRequestConfirmations\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"numWords\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RandomWordsRequested\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"outputSeed\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"payment\",\"type\":\"uint96\"},{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"name\":\"emitRandomWordsFulfilled\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preSeed\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"subId\",\"type\":\"uint64\"},{\"internalType\":\"uint16\",\"name\":\"minimumRequestConfirmations\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"numWords\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"emitRandomWordsRequested\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"type\":\"function\",\"name\":\"emitRandomWordsFulfilled\",\"inputs\":[{\"name\":\"requestId\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"outputSeed\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"payment\",\"type\":\"uint96\",\"internalType\":\"uint96\"},{\"name\":\"success\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"emitRandomWordsRequested\",\"inputs\":[{\"name\":\"keyHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"requestId\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"preSeed\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"subId\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"minimumRequestConfirmations\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"callbackGasLimit\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"numWords\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"RandomWordsFulfilled\",\"inputs\":[{\"name\":\"requestId\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"outputSeed\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"payment\",\"type\":\"uint96\",\"indexed\":false,\"internalType\":\"uint96\"},{\"name\":\"success\",\"type\":\"bool\",\"indexed\":false,\"internalType\":\"bool\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RandomWordsRequested\",\"inputs\":[{\"name\":\"keyHash\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"requestId\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"preSeed\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"subId\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"minimumRequestConfirmations\",\"type\":\"uint16\",\"indexed\":false,\"internalType\":\"uint16\"},{\"name\":\"callbackGasLimit\",\"type\":\"uint32\",\"indexed\":false,\"internalType\":\"uint32\"},{\"name\":\"numWords\",\"type\":\"uint32\",\"indexed\":false,\"internalType\":\"uint32\"},{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false}]", Bin: "0x608060405234801561001057600080fd5b5061027f806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063ca920adb1461003b578063fe62d3e914610050575b600080fd5b61004e61004936600461015b565b610063565b005b61004e61005e366004610212565b6100eb565b604080518881526020810188905261ffff86168183015263ffffffff858116606083015284166080820152905173ffffffffffffffffffffffffffffffffffffffff83169167ffffffffffffffff8816918b917f63373d1c4696214b898952999c9aaec57dac1ee2723cec59bea6888f489a9772919081900360a00190a45050505050505050565b604080518481526bffffffffffffffffffffffff8416602082015282151581830152905185917f7dffc5ae5ee4e2e4df1651cf6ad329a73cebdb728f37ea0187b9b17e036756e4919081900360600190a250505050565b803563ffffffff8116811461015657600080fd5b919050565b600080600080600080600080610100898b03121561017857600080fd5b883597506020890135965060408901359550606089013567ffffffffffffffff811681146101a557600080fd5b9450608089013561ffff811681146101bc57600080fd5b93506101ca60a08a01610142565b92506101d860c08a01610142565b915060e089013573ffffffffffffffffffffffffffffffffffffffff8116811461020157600080fd5b809150509295985092959890939650565b6000806000806080858703121561022857600080fd5b843593506020850135925060408501356bffffffffffffffffffffffff8116811461025257600080fd5b91506060850135801515811461026757600080fd5b93969295509093505056fea164736f6c6343000813000a", } diff --git a/core/gethwrappers/shared/generated/werc20_mock/werc20_mock.go b/core/gethwrappers/shared/generated/werc20_mock/werc20_mock.go index c8ff3722755..64c227266b8 100644 --- a/core/gethwrappers/shared/generated/werc20_mock/werc20_mock.go +++ b/core/gethwrappers/shared/generated/werc20_mock/werc20_mock.go @@ -31,7 +31,7 @@ var ( ) var WERC20MockMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"Withdrawal\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", + ABI: "[{\"type\":\"constructor\",\"inputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"receive\",\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"allowance\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"approve\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"balanceOf\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"burn\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"decimals\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"decreaseAllowance\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"subtractedValue\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"deposit\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"increaseAllowance\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"addedValue\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"mint\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"name\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"symbol\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"totalSupply\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transfer\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferFrom\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"withdraw\",\"inputs\":[{\"name\":\"wad\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"Approval\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"spender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Deposit\",\"inputs\":[{\"name\":\"dst\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Transfer\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Withdrawal\",\"inputs\":[{\"name\":\"src\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false}]", Bin: "0x60806040523480156200001157600080fd5b506040518060400160405280600a8152602001695745524332304d6f636b60b01b815250604051806040016040528060048152602001635745524360e01b815250816003908162000063919062000120565b50600462000072828262000120565b505050620001ec565b634e487b7160e01b600052604160045260246000fd5b600181811c90821680620000a657607f821691505b602082108103620000c757634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200011b57600081815260208120601f850160051c81016020861015620000f65750805b601f850160051c820191505b81811015620001175782815560010162000102565b5050505b505050565b81516001600160401b038111156200013c576200013c6200007b565b62000154816200014d845462000091565b84620000cd565b602080601f8311600181146200018c5760008415620001735750858301515b600019600386901b1c1916600185901b17855562000117565b600085815260208120601f198616915b82811015620001bd578886015182559484019460019091019084016200019c565b5085821015620001dc5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b610fc980620001fc6000396000f3fe6080604052600436106100ec5760003560e01c806340c10f191161008a578063a457c2d711610059578063a457c2d71461028e578063a9059cbb146102ae578063d0e30db0146102ce578063dd62ed3e146102d657600080fd5b806340c10f19146101f657806370a082311461021657806395d89b41146102595780639dc29fac1461026e57600080fd5b806323b872dd116100c657806323b872dd1461017a5780632e1a7d4d1461019a578063313ce567146101ba57806339509351146101d657600080fd5b806306fdde0314610100578063095ea7b31461012b57806318160ddd1461015b57600080fd5b366100fb576100f9610329565b005b600080fd5b34801561010c57600080fd5b5061011561036a565b6040516101229190610dc6565b60405180910390f35b34801561013757600080fd5b5061014b610146366004610e5b565b6103fc565b6040519015158152602001610122565b34801561016757600080fd5b506002545b604051908152602001610122565b34801561018657600080fd5b5061014b610195366004610e85565b610416565b3480156101a657600080fd5b506100f96101b5366004610ec1565b61043a565b3480156101c657600080fd5b5060405160128152602001610122565b3480156101e257600080fd5b5061014b6101f1366004610e5b565b6104c6565b34801561020257600080fd5b506100f9610211366004610e5b565b610512565b34801561022257600080fd5b5061016c610231366004610eda565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b34801561026557600080fd5b50610115610520565b34801561027a57600080fd5b506100f9610289366004610e5b565b61052f565b34801561029a57600080fd5b5061014b6102a9366004610e5b565b610539565b3480156102ba57600080fd5b5061014b6102c9366004610e5b565b61060f565b6100f9610329565b3480156102e257600080fd5b5061016c6102f1366004610efc565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b610333333461061d565b60405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a2565b60606003805461037990610f2f565b80601f01602080910402602001604051908101604052809291908181526020018280546103a590610f2f565b80156103f25780601f106103c7576101008083540402835291602001916103f2565b820191906000526020600020905b8154815290600101906020018083116103d557829003601f168201915b5050505050905090565b60003361040a818585610710565b60019150505b92915050565b6000336104248582856108c4565b61042f85858561099b565b506001949350505050565b3360009081526020819052604090205481111561045657600080fd5b6104603382610c0a565b604051339082156108fc029083906000818181858888f1935050505015801561048d573d6000803e3d6000fd5b5060405181815233907f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b659060200160405180910390a250565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919061040a908290869061050d908790610f82565b610710565b61051c828261061d565b5050565b60606004805461037990610f2f565b61051c8282610c0a565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610602576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61042f8286868403610710565b60003361040a81858561099b565b73ffffffffffffffffffffffffffffffffffffffff821661069a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016105f9565b80600260008282546106ac9190610f82565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff83166107b2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016105f9565b73ffffffffffffffffffffffffffffffffffffffff8216610855576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016105f9565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146109955781811015610988576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016105f9565b6109958484848403610710565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610a3e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016105f9565b73ffffffffffffffffffffffffffffffffffffffff8216610ae1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016105f9565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610b97576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016105f9565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610995565b73ffffffffffffffffffffffffffffffffffffffff8216610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016105f9565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090205481811015610d63576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016105f9565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91016108b7565b600060208083528351808285015260005b81811015610df357858101830151858201604001528201610dd7565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610e5657600080fd5b919050565b60008060408385031215610e6e57600080fd5b610e7783610e32565b946020939093013593505050565b600080600060608486031215610e9a57600080fd5b610ea384610e32565b9250610eb160208501610e32565b9150604084013590509250925092565b600060208284031215610ed357600080fd5b5035919050565b600060208284031215610eec57600080fd5b610ef582610e32565b9392505050565b60008060408385031215610f0f57600080fd5b610f1883610e32565b9150610f2660208401610e32565b90509250929050565b600181811c90821680610f4357607f821691505b602082108103610f7c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b80820180821115610410577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea164736f6c6343000813000a", } diff --git a/core/gethwrappers/shared/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/shared/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 470cd477fe0..0e49e7b25e7 100644 --- a/core/gethwrappers/shared/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/shared/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,7 +1,14 @@ GETH_VERSION: 1.14.11 -burn_mint_erc20: ../../../contracts/solc/v0.8.19/BurnMintERC20/BurnMintERC20.abi ../../../contracts/solc/v0.8.19/BurnMintERC20/BurnMintERC20.bin 9faa5e698c31f771907d9e8404f95fa33b61ecc18ca02cb379836206566331a5 -burn_mint_erc677: ../../../contracts/solc/v0.8.19/BurnMintERC677/BurnMintERC677.abi ../../../contracts/solc/v0.8.19/BurnMintERC677/BurnMintERC677.bin 405c9016171e614b17e10588653ef8d33dcea21dd569c3fddc596a46fcff68a3 -erc20: ../../../contracts/solc/v0.8.19/ERC20/ERC20.abi ../../../contracts/solc/v0.8.19/ERC20/ERC20.bin 5b1a93d9b24f250e49a730c96335a8113c3f7010365cba578f313b483001d4fc -link_token: ../../../contracts/solc/v0.8.19/LinkToken/LinkToken.abi ../../../contracts/solc/v0.8.19/LinkToken/LinkToken.bin c0ef9b507103aae541ebc31d87d051c2764ba9d843076b30ec505d37cdfffaba -multicall3: ../../../contracts/solc/v0.8.19/Multicall3/Multicall3.abi ../../../contracts/solc/v0.8.19/Multicall3/Multicall3.bin 66fff7368bbd7dfe1cb20d31cf29efa917a24cf5344e2d79b34994b8c3b9530a -werc20_mock: ../../../contracts/solc/v0.8.19/WERC20Mock/WERC20Mock.abi ../../../contracts/solc/v0.8.19/WERC20Mock/WERC20Mock.bin ff2ca3928b2aa9c412c892cb8226c4d754c73eeb291bb7481c32c48791b2aa94 +aggregator_v3_interface: ../../../contracts/solc/shared/AggregatorV3Interface/AggregatorV3Interface.sol/AggregatorV3Interface.abi.json ../../../contracts/solc/shared/AggregatorV3Interface/AggregatorV3Interface.sol/AggregatorV3Interface.bin 0294226c10dd4b77239d85074fcf05c39c5cbf513b45bb07f966a8733457d2cb +burn_mint_erc20: ../../../contracts/solc/shared/BurnMintERC20/BurnMintERC20.sol/BurnMintERC20.abi.json ../../../contracts/solc/shared/BurnMintERC20/BurnMintERC20.sol/BurnMintERC20.bin 161d4fc00d3bd8759a82a11d2d0946653ed06853e67359049ac4176288090d22 +burn_mint_erc677: ../../../contracts/solc/shared/BurnMintERC677/BurnMintERC677.sol/BurnMintERC677.abi.json ../../../contracts/solc/shared/BurnMintERC677/BurnMintERC677.sol/BurnMintERC677.bin c510542f105686f93e6287a66a6466c10cd576781063fc787ef365b4a47f5cb8 +chain_reader_tester: ../../../contracts/solc/shared/ChainReaderTester/ChainReaderTester.sol/ChainReaderTester.abi.json ../../../contracts/solc/shared/ChainReaderTester/ChainReaderTester.sol/ChainReaderTester.bin 876c55e8d2556dc9cc953c786ae72b0430cb2c992f84573a2aae9680068f293d +erc20: ../../../contracts/solc/vendor/ERC20/ERC20.sol/ERC20.abi.json ../../../contracts/solc/vendor/ERC20/ERC20.sol/ERC20.bin 9a5e3f7ec9fea385eeba374d184d6b83784304f537a90f6b81827c732d0b37c4 +erc677: ../../../contracts/solc/shared/ERC677/ERC677.sol/ERC677.abi.json ../../../contracts/solc/shared/ERC677/ERC677.sol/ERC677.bin 0fba0204e8f677754b5dc4747c35d575abb20f33a2c15a3ca3650f314c8c5b6c +link_token: ../../../contracts/solc/shared/LinkToken/LinkToken.sol/LinkToken.abi.json ../../../contracts/solc/shared/LinkToken/LinkToken.sol/LinkToken.bin 9d1c648233822b70b03bf4fdb1af4cffaead8f1391dd149a79b3072defbd0c62 +log_emitter: ../../../contracts/solc/shared/LogEmitter/LogEmitter.sol/LogEmitter.abi.json ../../../contracts/solc/shared/LogEmitter/LogEmitter.sol/LogEmitter.bin f884ed34204f82dcd1ea8f20db1b24d410bf23ab2687d56968d2c670e98277dd +mock_v3_aggregator_contract: ../../../contracts/solc/shared/MockV3Aggregator/MockV3Aggregator.sol/MockV3Aggregator.abi.json ../../../contracts/solc/shared/MockV3Aggregator/MockV3Aggregator.sol/MockV3Aggregator.bin 76796e0faffb2981d49082d94f2f2c9ec87d8ad960b022993d0681f9c81a832d +multicall3: ../../../contracts/solc/vendor/Multicall3/Multicall3.sol/Multicall3.abi.json ../../../contracts/solc/vendor/Multicall3/Multicall3.sol/Multicall3.bin 175cd8790a4c714790c3761c50b0e93694c71bb7f8897eb92150847e6d8a94f4 +type_and_version: ../../../contracts/solc/shared/ITypeAndVersion/ITypeAndVersion.sol/ITypeAndVersion.abi.json ../../../contracts/solc/shared/ITypeAndVersion/ITypeAndVersion.sol/ITypeAndVersion.bin 21f6da4daa754971a4fdafea90ec64a77a5f03e62f9a9639802726b22eaa380a +vrf_log_emitter: ../../../contracts/solc/shared/VRFLogEmitter/VRFLogEmitter.sol/VRFLogEmitter.abi.json ../../../contracts/solc/shared/VRFLogEmitter/VRFLogEmitter.sol/VRFLogEmitter.bin 46788c9519425dd23befdea8e561ee454dcb559f6a8fe70f4a092805574218f6 +werc20_mock: ../../../contracts/solc/shared/WERC20Mock/WERC20Mock.sol/WERC20Mock.abi.json ../../../contracts/solc/shared/WERC20Mock/WERC20Mock.sol/WERC20Mock.bin f5ba13fc99c248354508e3bab6cd0fb66607d3b7377f59a1e80b930e96ed4f48 diff --git a/core/gethwrappers/shared/go_generate.go b/core/gethwrappers/shared/go_generate.go index 7fe9d6a8ef2..30ca631178d 100644 --- a/core/gethwrappers/shared/go_generate.go +++ b/core/gethwrappers/shared/go_generate.go @@ -2,9 +2,17 @@ // golang packages, using abigen. package gethwrappers -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/BurnMintERC677/BurnMintERC677.abi ../../../contracts/solc/v0.8.19/BurnMintERC677/BurnMintERC677.bin BurnMintERC677 burn_mint_erc677 -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/LinkToken/LinkToken.abi ../../../contracts/solc/v0.8.19/LinkToken/LinkToken.bin LinkToken link_token -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/BurnMintERC20/BurnMintERC20.abi ../../../contracts/solc/v0.8.19/BurnMintERC20/BurnMintERC20.bin BurnMintERC20 burn_mint_erc20 -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/ERC20/ERC20.abi ../../../contracts/solc/v0.8.19/ERC20/ERC20.bin ERC20 erc20 -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/WERC20Mock/WERC20Mock.abi ../../../contracts/solc/v0.8.19/WERC20Mock/WERC20Mock.bin WERC20Mock werc20_mock -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/Multicall3/Multicall3.abi ../../../contracts/solc/v0.8.19/Multicall3/Multicall3.bin Multicall3 multicall3 +//go:generate go run ../generation/wrap.go shared BurnMintERC677 burn_mint_erc677 +//go:generate go run ../generation/wrap.go shared ERC677 erc677 +//go:generate go run ../generation/wrap.go shared LinkToken link_token +//go:generate go run ../generation/wrap.go shared BurnMintERC20 burn_mint_erc20 +//go:generate go run ../generation/wrap.go shared WERC20Mock werc20_mock +//go:generate go run ../generation/wrap.go shared ChainReaderTester chain_reader_tester +//go:generate go run ../generation/wrap.go shared AggregatorV3Interface aggregator_v3_interface +//go:generate go run ../generation/wrap.go shared MockV3Aggregator mock_v3_aggregator_contract +//go:generate go run ../generation/wrap.go shared LogEmitter log_emitter +//go:generate go run ../generation/wrap.go shared VRFLogEmitter vrf_log_emitter +//go:generate go run ../generation/wrap.go shared ITypeAndVersion type_and_version + +//go:generate go run ../generation/wrap.go vendor ERC20 erc20 +//go:generate go run ../generation/wrap.go vendor Multicall3 multicall3 diff --git a/core/gethwrappers/transmission/generated/entry_point/entry_point.go b/core/gethwrappers/transmission/generated/entry_point/entry_point.go deleted file mode 100644 index 5a22214cb0e..00000000000 --- a/core/gethwrappers/transmission/generated/entry_point/entry_point.go +++ /dev/null @@ -1,1871 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package entry_point - -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 -) - -type EntryPointMemoryUserOp struct { - Sender common.Address - Nonce *big.Int - CallGasLimit *big.Int - VerificationGasLimit *big.Int - PreVerificationGas *big.Int - Paymaster common.Address - MaxFeePerGas *big.Int - MaxPriorityFeePerGas *big.Int -} - -type EntryPointUserOpInfo struct { - MUserOp EntryPointMemoryUserOp - UserOpHash [32]byte - Prefund *big.Int - ContextOffset *big.Int - PreOpGas *big.Int -} - -type IEntryPointUserOpsPerAggregator struct { - UserOps []UserOperation - Aggregator common.Address - Signature []byte -} - -type IStakeManagerDepositInfo struct { - Deposit *big.Int - Staked bool - Stake *big.Int - UnstakeDelaySec uint32 - WithdrawTime *big.Int -} - -type UserOperation struct { - Sender common.Address - Nonce *big.Int - InitCode []byte - CallData []byte - CallGasLimit *big.Int - VerificationGasLimit *big.Int - PreVerificationGas *big.Int - MaxFeePerGas *big.Int - MaxPriorityFeePerGas *big.Int - PaymasterAndData []byte - Signature []byte -} - -var EntryPointMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"paid\",\"type\":\"uint256\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bool\",\"name\":\"targetSuccess\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"targetResult\",\"type\":\"bytes\"}],\"name\":\"ExecutionResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"opIndex\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"FailedOp\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderAddressResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureValidationFailed\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"structIEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"structIStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"structIStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"structIStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResult\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"structIEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"structIStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"structIStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"structIStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"structIStakeManager.StakeInfo\",\"name\":\"stakeInfo\",\"type\":\"tuple\"}],\"internalType\":\"structIEntryPoint.AggregatorStakeInfo\",\"name\":\"aggregatorInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResultWithAggregation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"factory\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"}],\"name\":\"AccountDeployed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalDeposit\",\"type\":\"uint256\"}],\"name\":\"Deposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureAggregatorChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalStaked\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"name\":\"StakeLocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"withdrawTime\",\"type\":\"uint256\"}],\"name\":\"StakeUnlocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"StakeWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasUsed\",\"type\":\"uint256\"}],\"name\":\"UserOperationEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"revertReason\",\"type\":\"bytes\"}],\"name\":\"UserOperationRevertReason\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdrawn\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"SIG_VALIDATION_FAILED\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"}],\"name\":\"_validateSenderAndPaymaster\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"}],\"name\":\"addStake\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"depositTo\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getDepositInfo\",\"outputs\":[{\"components\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"internalType\":\"structIStakeManager.DepositInfo\",\"name\":\"info\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"}],\"name\":\"getSenderAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"structUserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"getUserOpHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"structUserOperation[]\",\"name\":\"userOps\",\"type\":\"tuple[]\"},{\"internalType\":\"contractIAggregator\",\"name\":\"aggregator\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"structIEntryPoint.UserOpsPerAggregator[]\",\"name\":\"opsPerAggregator\",\"type\":\"tuple[]\"},{\"internalType\":\"addresspayable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleAggregatedOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"structUserOperation[]\",\"name\":\"ops\",\"type\":\"tuple[]\"},{\"internalType\":\"addresspayable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"}],\"internalType\":\"structEntryPoint.MemoryUserOp\",\"name\":\"mUserOp\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"contextOffset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"}],\"internalType\":\"structEntryPoint.UserOpInfo\",\"name\":\"opInfo\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"}],\"name\":\"innerHandleOp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"structUserOperation\",\"name\":\"op\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"targetCallData\",\"type\":\"bytes\"}],\"name\":\"simulateHandleOp\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"structUserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"simulateValidation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unlockStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"addresspayable\",\"name\":\"withdrawAddress\",\"type\":\"address\"}],\"name\":\"withdrawStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"addresspayable\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"withdrawAmount\",\"type\":\"uint256\"}],\"name\":\"withdrawTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", - Bin: "0x60a0604052604051620000129062000050565b604051809103906000f0801580156200002f573d6000803e3d6000fd5b506001600160a01b03166080523480156200004957600080fd5b506200005e565b61020a8062004b0483390190565b608051614a83620000816000396000818161146e015261363e0152614a836000f3fe6080604052600436106101125760003560e01c8063957122ab116100a5578063bb9fe6bf11610074578063d6383f9411610059578063d6383f941461042c578063ee2194231461044c578063fc7e286d1461046c57600080fd5b8063bb9fe6bf146103f7578063c23a5cea1461040c57600080fd5b8063957122ab146103845780639b249f69146103a4578063a6193531146103c4578063b760faf9146103e457600080fd5b80634b1d7cf5116100e15780634b1d7cf5146101ad5780635287ce12146101cd57806370a082311461031c5780638f41ec5a1461036f57600080fd5b80630396cb60146101275780631d7327561461013a5780631fad948c1461016d578063205c28781461018d57600080fd5b366101225761012033610546565b005b600080fd5b6101206101353660046139b1565b6105c1565b34801561014657600080fd5b5061015a610155366004613c28565b610944565b6040519081526020015b60405180910390f35b34801561017957600080fd5b50610120610188366004613d33565b610af7565b34801561019957600080fd5b506101206101a8366004613d8a565b610c38565b3480156101b957600080fd5b506101206101c8366004613d33565b610e3a565b3480156101d957600080fd5b506102bd6101e8366004613db6565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091525073ffffffffffffffffffffffffffffffffffffffff1660009081526020818152604091829020825160a08101845281546dffffffffffffffffffffffffffff80821683526e010000000000000000000000000000820460ff161515948301949094526f0100000000000000000000000000000090049092169282019290925260019091015463ffffffff81166060830152640100000000900465ffffffffffff16608082015290565b6040805182516dffffffffffffffffffffffffffff908116825260208085015115159083015283830151169181019190915260608083015163ffffffff169082015260809182015165ffffffffffff169181019190915260a001610164565b34801561032857600080fd5b5061015a610337366004613db6565b73ffffffffffffffffffffffffffffffffffffffff166000908152602081905260409020546dffffffffffffffffffffffffffff1690565b34801561037b57600080fd5b5061015a600181565b34801561039057600080fd5b5061012061039f366004613dd3565b6112d9565b3480156103b057600080fd5b506101206103bf366004613e58565b611431565b3480156103d057600080fd5b5061015a6103df366004613eb3565b611533565b6101206103f2366004613db6565b610546565b34801561040357600080fd5b50610120611575565b34801561041857600080fd5b50610120610427366004613db6565b61172c565b34801561043857600080fd5b50610120610447366004613ee8565b611a2c565b34801561045857600080fd5b50610120610467366004613eb3565b611b5a565b34801561047857600080fd5b506104f9610487366004613db6565b600060208190529081526040902080546001909101546dffffffffffffffffffffffffffff808316926e010000000000000000000000000000810460ff16926f010000000000000000000000000000009091049091169063ffffffff811690640100000000900465ffffffffffff1685565b604080516dffffffffffffffffffffffffffff96871681529415156020860152929094169183019190915263ffffffff16606082015265ffffffffffff909116608082015260a001610164565b6105508134611ec2565b73ffffffffffffffffffffffffffffffffffffffff811660008181526020818152604091829020805492516dffffffffffffffffffffffffffff909316835292917f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c491015b60405180910390a25050565b33600090815260208190526040902063ffffffff8216610642576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c617900000000000060448201526064015b60405180910390fd5b600181015463ffffffff90811690831610156106ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152606401610639565b80546000906106ed9034906f0100000000000000000000000000000090046dffffffffffffffffffffffffffff16613f79565b905060008111610759576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152606401610639565b6dffffffffffffffffffffffffffff8111156107d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152606401610639565b6040805160a08101825283546dffffffffffffffffffffffffffff90811682526001602080840182815286841685870190815263ffffffff808b16606088019081526000608089018181523380835296829052908a9020985189549551945189166f01000000000000000000000000000000027fffffff0000000000000000000000000000ffffffffffffffffffffffffffffff9515156e010000000000000000000000000000027fffffffffffffffffffffffffffffffffff0000000000000000000000000000009097169190991617949094179290921695909517865551949092018054925165ffffffffffff16640100000000027fffffffffffffffffffffffffffffffffffffffffffff00000000000000000000909316949093169390931717905590517fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c0190610937908490879091825263ffffffff16602082015260400190565b60405180910390a2505050565b6000805a90503330146109b3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152606401610639565b8451604081015160608201518101611388015a10156109f6577fdeaddead0000000000000000000000000000000000000000000000000000000060005260206000fd5b875160009015610a97576000610a13846000015160008c86611fbf565b905080610a95576000610a27610800611fd7565b805190915015610a8f57846000015173ffffffffffffffffffffffffffffffffffffffff168a602001517f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a201876020015184604051610a86929190613ffa565b60405180910390a35b60019250505b505b600088608001515a8603019050610ae96000838b8b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250612003915050565b9a9950505050505050505050565b8160008167ffffffffffffffff811115610b1357610b136139d7565b604051908082528060200260200182016040528015610b4c57816020015b610b3961390d565b815260200190600190039081610b315790505b50905060005b82811015610bc5576000828281518110610b6e57610b6e614013565b60200260200101519050600080610ba9848a8a87818110610b9157610b91614013565b9050602002810190610ba39190614042565b856123e1565b91509150610bba84838360006125a3565b505050600101610b52565b506000805b83811015610c2557610c1981888884818110610be857610be8614013565b9050602002810190610bfa9190614042565b858481518110610c0c57610c0c614013565b60200260200101516127f8565b90910190600101610bca565b50610c30848261297d565b505050505050565b33600090815260208190526040902080546dffffffffffffffffffffffffffff16821115610cc2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152606401610639565b8054610cdf9083906dffffffffffffffffffffffffffff16614080565b81547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000166dffffffffffffffffffffffffffff919091161781556040805173ffffffffffffffffffffffffffffffffffffffff851681526020810184905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb910160405180910390a260008373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d8060008114610dc4576040519150601f19603f3d011682016040523d82523d6000602084013e610dc9565b606091505b5050905080610e34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152606401610639565b50505050565b816000805b828110156110335736868683818110610e5a57610e5a614013565b9050602002810190610e6c9190614093565b9050366000610e7b83806140c7565b90925090506000610e926040850160208601613db6565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff73ffffffffffffffffffffffffffffffffffffffff821601610f33576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152606401610639565b73ffffffffffffffffffffffffffffffffffffffff8116156110105773ffffffffffffffffffffffffffffffffffffffff811663e3563a4f8484610f7a604089018961412f565b6040518563ffffffff1660e01b8152600401610f999493929190614345565b60006040518083038186803b158015610fb157600080fd5b505afa925050508015610fc2575060015b611010576040517f86a9f75000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610639565b61101a8287613f79565b955050505050808061102b906143fc565b915050610e3f565b5060008167ffffffffffffffff81111561104f5761104f6139d7565b60405190808252806020026020018201604052801561108857816020015b61107561390d565b81526020019060019003908161106d5790505b5090506000805b8481101561117357368888838181106110aa576110aa614013565b90506020028101906110bc9190614093565b90503660006110cb83806140c7565b909250905060006110e26040850160208601613db6565b90508160005b8181101561115a57600089898151811061110457611104614013565b602002602001015190506000806111278b898987818110610b9157610b91614013565b91509150611137848383896125a3565b8a611141816143fc565b9b50505050508080611152906143fc565b9150506110e8565b505050505050808061116b906143fc565b91505061108f565b50600080915060005b85811015611299573689898381811061119757611197614013565b90506020028101906111a99190614093565b90506111bb6040820160208301613db6565b73ffffffffffffffffffffffffffffffffffffffff167f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d60405160405180910390a236600061120a83806140c7565b90925090508060005b81811015611281576112558885858481811061123157611231614013565b90506020028101906112439190614042565b8b8b81518110610c0c57610c0c614013565b61125f9088613f79565b96508761126b816143fc565b9850508080611279906143fc565b915050611213565b50505050508080611291906143fc565b91505061117c565b506040516000907f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d908290a26112cf868261297d565b5050505050505050565b831580156112fc575073ffffffffffffffffffffffffffffffffffffffff83163b155b15611363576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f41413230206163636f756e74206e6f74206465706c6f796564000000000000006044820152606401610639565b601481106113f557600061137a6014828486614434565b6113839161445e565b60601c9050803b6000036113f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f41413330207061796d6173746572206e6f74206465706c6f79656400000000006044820152606401610639565b505b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260006024820152604401610639565b6040517f570e1a3600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063570e1a36906114a590859085906004016144a6565b6020604051808303816000875af11580156114c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114e891906144ba565b6040517f6ca7b80600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610639565b600061153e82612ac9565b6040805160208101929092523090820152466060820152608001604051602081830303815290604052805190602001209050919050565b3360009081526020819052604081206001810154909163ffffffff90911690036115fb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152606401610639565b80546e010000000000000000000000000000900460ff16611678576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152606401610639565b60018101546000906116909063ffffffff16426144d7565b6001830180547fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff1664010000000065ffffffffffff84169081029190911790915583547fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff16845560405190815290915033907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a906020016105b5565b33600090815260208190526040902080546f0100000000000000000000000000000090046dffffffffffffffffffffffffffff16806117c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152606401610639565b6001820154640100000000900465ffffffffffff16611842576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152606401610639565b60018201544264010000000090910465ffffffffffff1611156118c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152606401610639565b6001820180547fffffffffffffffffffffffffffffffffffffffffffff0000000000000000000016905581547fffffff0000000000000000000000000000ffffffffffffffffffffffffffffff1682556040805173ffffffffffffffffffffffffffffffffffffffff851681526020810183905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda3910160405180910390a260008373ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d80600081146119bc576040519150601f19603f3d011682016040523d82523d6000602084013e6119c1565b606091505b5050905080610e34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152606401610639565b611a3461390d565b611a3d85612ae2565b600080611a4c600088856123e1565b915091506000611a5c8383612bd5565b9050611a6743600052565b6000611a7560008a876127f8565b9050611a8043600052565b6000606073ffffffffffffffffffffffffffffffffffffffff8a1615611b10578973ffffffffffffffffffffffffffffffffffffffff168989604051611ac79291906144fd565b6000604051808303816000865af19150503d8060008114611b04576040519150601f19603f3d011682016040523d82523d6000602084013e611b09565b606091505b5090925090505b8660800151838560200151866040015185856040517f8b7ac9800000000000000000000000000000000000000000000000000000000081526004016106399695949392919061450d565b611b6261390d565b611b6b82612ae2565b600080611b7a600085856123e1565b845160a001516040805180820182526000808252602080830182815273ffffffffffffffffffffffffffffffffffffffff958616835282825284832080546dffffffffffffffffffffffffffff6f01000000000000000000000000000000918290048116875260019283015463ffffffff9081169094528d51518851808a018a5287815280870188815291909a16875286865288872080549390930490911689529101549091169052835180850190945281845283015293955091935090366000611c4860408a018a61412f565b909250905060006014821015611c5f576000611c7a565b611c6d601460008486614434565b611c769161445e565b60601c5b6040805180820182526000808252602080830182815273ffffffffffffffffffffffffffffffffffffffff861683529082905292902080546f0100000000000000000000000000000090046dffffffffffffffffffffffffffff1682526001015463ffffffff1690915290915093505050506000611cf88686612bd5565b90506000816000015190506000600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614905060006040518060c001604052808b6080015181526020018b6040015181526020018315158152602001856020015165ffffffffffff168152602001856040015165ffffffffffff168152602001611d8f8c6060015190565b9052905073ffffffffffffffffffffffffffffffffffffffff831615801590611dcf575073ffffffffffffffffffffffffffffffffffffffff8316600114155b15611e885760408051808201825273ffffffffffffffffffffffffffffffffffffffff851680825282518084018452600080825260208083018281529382528181529085902080546f0100000000000000000000000000000090046dffffffffffffffffffffffffffff1683526001015463ffffffff169092529082015290517ffaecb4e4000000000000000000000000000000000000000000000000000000008152610639908390899089908c9086906004016145af565b808686896040517fe0cff05f000000000000000000000000000000000000000000000000000000008152600401610639949392919061463c565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054909190611f079084906dffffffffffffffffffffffffffff16613f79565b90506dffffffffffffffffffffffffffff811115611f81576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6465706f736974206f766572666c6f77000000000000000000000000000000006044820152606401610639565b81547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000166dffffffffffffffffffffffffffff919091161790555050565b6000806000845160208601878987f195945050505050565b60603d82811115611fe55750815b604051602082018101604052818152816000602083013e9392505050565b6000805a85519091506000908161201982612cbc565b60a083015190915073ffffffffffffffffffffffffffffffffffffffff81166120455782519350612293565b80935060008851111561229357868202955060028a600281111561206b5761206b614693565b146121035760608301516040517fa9a2340900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169163a9a23409916120cb908e908d908c906004016146c2565b600060405180830381600088803b1580156120e557600080fd5b5087f11580156120f9573d6000803e3d6000fd5b5050505050612293565b60608301516040517fa9a2340900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169163a9a234099161215e908e908d908c906004016146c2565b600060405180830381600088803b15801561217857600080fd5b5087f19350505050801561218a575060015b61229357612196614722565b806308c379a00361222657506121aa61473e565b806121b55750612228565b8b816040516020016121c791906147e6565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f220266b60000000000000000000000000000000000000000000000000000000082526106399291600401613ffa565b505b8a6040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526012908201527f4141353020706f73744f70207265766572740000000000000000000000000000606082015260800190565b5a85038701965081870295508589604001511015612315578a6040517f220266b600000000000000000000000000000000000000000000000000000000815260040161063991815260406020808301829052908201527f414135312070726566756e642062656c6f772061637475616c476173436f7374606082015260800190565b60408901518690036123278582611ec2565b6000808c600281111561233c5761233c614693565b1490508460a0015173ffffffffffffffffffffffffffffffffffffffff16856000015173ffffffffffffffffffffffffffffffffffffffff168c602001517f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f8860200151858d8f6040516123c9949392919093845291151560208401526040830152606082015260800190565b60405180910390a45050505050505095945050505050565b60008060005a84519091506123f68682612cec565b6123ff86611533565b6020860152604081015160608201516080830151171760e087013517610100870135176effffffffffffffffffffffffffffff81111561249b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152606401610639565b6000806124a784612e0c565b90506124b58a8a8a84612e66565b975091506124c243600052565b60a084015160609073ffffffffffffffffffffffffffffffffffffffff16156124f7576124f28b8b8b858761317c565b975090505b60005a87039050808b60a001351015612575578b6040517f220266b6000000000000000000000000000000000000000000000000000000008152600401610639918152604060208201819052601e908201527f41413430206f76657220766572696669636174696f6e4761734c696d69740000606082015260800190565b60408a018390528160608b015260c08b01355a8803018a608001818152505050505050505050935093915050565b6000806125af8561343f565b915091508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161461265157856040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526014908201527f41413234207369676e6174757265206572726f72000000000000000000000000606082015260800190565b80156126c257856040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526017908201527f414132322065787069726564206f72206e6f7420647565000000000000000000606082015260800190565b60006126cd8561343f565b9250905073ffffffffffffffffffffffffffffffffffffffff81161561275857866040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526014908201527f41413334207369676e6174757265206572726f72000000000000000000000000606082015260800190565b81156127ef57866040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526021908201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560608201527f6500000000000000000000000000000000000000000000000000000000000000608082015260a00190565b50505050505050565b6000805a9050600061280b846060015190565b905030631d732756612820606088018861412f565b87856040518563ffffffff1660e01b8152600401612841949392919061482b565b6020604051808303816000875af192505050801561289a575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252612897918101906148ec565b60015b61297157600060206000803e506000517f2152215300000000000000000000000000000000000000000000000000000000810161293c57866040517f220266b6000000000000000000000000000000000000000000000000000000008152600401610639918152604060208201819052600f908201527f41413935206f7574206f66206761730000000000000000000000000000000000606082015260800190565b600085608001515a61294e9086614080565b6129589190613f79565b9050612968886002888685612003565b94505050612974565b92505b50509392505050565b73ffffffffffffffffffffffffffffffffffffffff82166129fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152606401610639565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114612a54576040519150601f19603f3d011682016040523d82523d6000602084013e612a59565b606091505b5050905080612ac4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152606401610639565b505050565b6000612ad482613492565b805190602001209050919050565b3063957122ab612af5604084018461412f565b612b026020860186613db6565b612b1061012087018761412f565b6040518663ffffffff1660e01b8152600401612b30959493929190614905565b60006040518083038186803b158015612b4857600080fd5b505afa925050508015612b59575060015b612bd257612b65614722565b806308c379a003612bc65750612b7961473e565b80612b845750612bc8565b805115612bc2576000816040517f220266b6000000000000000000000000000000000000000000000000000000008152600401610639929190613ffa565b5050565b505b3d6000803e3d6000fd5b50565b6040805160608101825260008082526020820181905291810182905290612bfb846134d1565b90506000612c08846134d1565b825190915073ffffffffffffffffffffffffffffffffffffffff8116612c2c575080515b602080840151604080860151928501519085015191929165ffffffffffff8083169085161015612c5a578193505b8065ffffffffffff168365ffffffffffff161115612c76578092505b50506040805160608101825273ffffffffffffffffffffffffffffffffffffffff909416845265ffffffffffff9283166020850152911690820152925050505b92915050565b60c081015160e082015160009190808203612cd8575092915050565b612ce48248830161354f565b949350505050565b612cf96020830183613db6565b73ffffffffffffffffffffffffffffffffffffffff16815260208083013590820152608080830135604083015260a0830135606083015260c0808401359183019190915260e0808401359183019190915261010083013590820152366000612d6561012085018561412f565b90925090508015612dff576014811015612ddb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152606401610639565b612de9601460008385614434565b612df29161445e565b60601c60a0840152610e34565b600060a084015250505050565b60a0810151600090819073ffffffffffffffffffffffffffffffffffffffff16612e37576001612e3a565b60035b60ff16905060008360800151828560600151028560400151010190508360c00151810292505050919050565b60008060005a8551805191925090612e8b8988612e8660408c018c61412f565b613567565b60a0820151612e9943600052565b600073ffffffffffffffffffffffffffffffffffffffff8216612f025773ffffffffffffffffffffffffffffffffffffffff83166000908152602081905260409020546dffffffffffffffffffffffffffff16888111612efb57808903612efe565b60005b9150505b606084015160208a01516040517f3a871cdd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff861692633a871cdd929091612f62918f918790600401614948565b60206040518083038160008887f193505050508015612fbc575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252612fb9918101906148ec565b60015b61306657612fc8614722565b806308c379a003612ff95750612fdc61473e565b80612fe75750612ffb565b8b816040516020016121c7919061496d565b505b8a6040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526016908201527f4141323320726576657274656420286f72204f4f472900000000000000000000606082015260800190565b955073ffffffffffffffffffffffffffffffffffffffff82166131695773ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040902080546dffffffffffffffffffffffffffff16808a111561312d578c6040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526017908201527f41413231206469646e2774207061792070726566756e64000000000000000000606082015260800190565b81547fffffffffffffffffffffffffffffffffffff000000000000000000000000000016908a90036dffffffffffffffffffffffffffff161790555b5a85039650505050505094509492505050565b825160608181015190916000918481116131f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4141343120746f6f206c6974746c6520766572696669636174696f6e476173006044820152606401610639565b60a082015173ffffffffffffffffffffffffffffffffffffffff8116600090815260208190526040902080548784039291906dffffffffffffffffffffffffffff16898110156132a7578c6040517f220266b6000000000000000000000000000000000000000000000000000000008152600401610639918152604060208201819052601e908201527f41413331207061796d6173746572206465706f73697420746f6f206c6f770000606082015260800190565b8981038260000160006101000a8154816dffffffffffffffffffffffffffff02191690836dffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff1663f465c77e858e8e602001518e6040518563ffffffff1660e01b815260040161332293929190614948565b60006040518083038160008887f19350505050801561338157506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261337e91908101906149b2565b60015b61342b5761338d614722565b806308c379a0036133be57506133a161473e565b806133ac57506133c0565b8d816040516020016121c79190614a3e565b505b8c6040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526016908201527f4141333320726576657274656420286f72204f4f472900000000000000000000606082015260800190565b909e909d509b505050505050505050505050565b6000808260000361345557506000928392509050565b6000613460846134d1565b9050806040015165ffffffffffff164211806134875750806020015165ffffffffffff1642105b905194909350915050565b60603660006134a561014085018561412f565b915091508360208184030360405194506020810185016040528085528082602087013750505050919050565b60408051606081018252600080825260208201819052918101919091528160a081901c65ffffffffffff811660000361350d575065ffffffffffff5b6040805160608101825273ffffffffffffffffffffffffffffffffffffffff909316835260d09490941c602083015265ffffffffffff16928101929092525090565b600081831061355e5781613560565b825b9392505050565b8015610e345782515173ffffffffffffffffffffffffffffffffffffffff81163b156135f857846040517f220266b6000000000000000000000000000000000000000000000000000000008152600401610639918152604060208201819052601f908201527f414131302073656e64657220616c726561647920636f6e737472756374656400606082015260800190565b8351606001516040517f570e1a3600000000000000000000000000000000000000000000000000000000815260009173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169163570e1a36919061367690889088906004016144a6565b60206040518083038160008887f1158015613695573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906136ba91906144ba565b905073ffffffffffffffffffffffffffffffffffffffff811661374257856040517f220266b6000000000000000000000000000000000000000000000000000000008152600401610639918152604060208201819052601b908201527f4141313320696e6974436f6465206661696c6564206f72204f4f470000000000606082015260800190565b8173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146137df57856040517f220266b600000000000000000000000000000000000000000000000000000000815260040161063991815260406020808301829052908201527f4141313420696e6974436f6465206d7573742072657475726e2073656e646572606082015260800190565b8073ffffffffffffffffffffffffffffffffffffffff163b60000361386857856040517f220266b600000000000000000000000000000000000000000000000000000000815260040161063991815260406020808301829052908201527f4141313520696e6974436f6465206d757374206372656174652073656e646572606082015260800190565b60006138776014828688614434565b6138809161445e565b60601c90508273ffffffffffffffffffffffffffffffffffffffff1686602001517fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d83896000015160a001516040516138fc92919073ffffffffffffffffffffffffffffffffffffffff92831681529116602082015260400190565b60405180910390a350505050505050565b6040518060a0016040528061398c604051806101000160405280600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081525090565b8152602001600080191681526020016000815260200160008152602001600081525090565b6000602082840312156139c357600080fd5b813563ffffffff8116811461356057600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60a0810181811067ffffffffffffffff82111715613a2657613a266139d7565b60405250565b610100810181811067ffffffffffffffff82111715613a2657613a266139d7565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116810181811067ffffffffffffffff82111715613a9157613a916139d7565b6040525050565b600067ffffffffffffffff821115613ab257613ab26139d7565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b73ffffffffffffffffffffffffffffffffffffffff81168114612bd257600080fd5b8035613b0b81613ade565b919050565b6000818303610180811215613b2457600080fd5b604051613b3081613a06565b80925061010080831215613b4357600080fd5b6040519250613b5183613a2c565b613b5a85613b00565b835260208501356020840152604085013560408401526060850135606084015260808501356080840152613b9060a08601613b00565b60a084015260c085013560c084015260e085013560e084015282825280850135602083015250610120840135604082015261014084013560608201526101608401356080820152505092915050565b60008083601f840112613bf157600080fd5b50813567ffffffffffffffff811115613c0957600080fd5b602083019150836020828501011115613c2157600080fd5b9250929050565b6000806000806101c08587031215613c3f57600080fd5b843567ffffffffffffffff80821115613c5757600080fd5b818701915087601f830112613c6b57600080fd5b8135613c7681613a98565b604051613c838282613a4d565b8281528a6020848701011115613c9857600080fd5b82602086016020830137600060208483010152809850505050613cbe8860208901613b10565b94506101a0870135915080821115613cd557600080fd5b50613ce287828801613bdf565b95989497509550505050565b60008083601f840112613d0057600080fd5b50813567ffffffffffffffff811115613d1857600080fd5b6020830191508360208260051b8501011115613c2157600080fd5b600080600060408486031215613d4857600080fd5b833567ffffffffffffffff811115613d5f57600080fd5b613d6b86828701613cee565b9094509250506020840135613d7f81613ade565b809150509250925092565b60008060408385031215613d9d57600080fd5b8235613da881613ade565b946020939093013593505050565b600060208284031215613dc857600080fd5b813561356081613ade565b600080600080600060608688031215613deb57600080fd5b853567ffffffffffffffff80821115613e0357600080fd5b613e0f89838a01613bdf565b909750955060208801359150613e2482613ade565b90935060408701359080821115613e3a57600080fd5b50613e4788828901613bdf565b969995985093965092949392505050565b60008060208385031215613e6b57600080fd5b823567ffffffffffffffff811115613e8257600080fd5b613e8e85828601613bdf565b90969095509350505050565b60006101608284031215613ead57600080fd5b50919050565b600060208284031215613ec557600080fd5b813567ffffffffffffffff811115613edc57600080fd5b612ce484828501613e9a565b60008060008060608587031215613efe57600080fd5b843567ffffffffffffffff80821115613f1657600080fd5b613f2288838901613e9a565b955060208701359150613f3482613ade565b90935060408601359080821115613cd557600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820180821115612cb657612cb6613f4a565b60005b83811015613fa7578181015183820152602001613f8f565b50506000910152565b60008151808452613fc8816020860160208601613f8c565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b828152604060208201526000612ce46040830184613fb0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea183360301811261407657600080fd5b9190910192915050565b81810381811115612cb657612cb6613f4a565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811261407657600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126140fc57600080fd5b83018035915067ffffffffffffffff82111561411757600080fd5b6020019150600581901b3603821315613c2157600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261416457600080fd5b83018035915067ffffffffffffffff82111561417f57600080fd5b602001915036819003821315613c2157600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126141c957600080fd5b830160208101925035905067ffffffffffffffff8111156141e957600080fd5b803603821315613c2157600080fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b600061016061426d8461425385613b00565b73ffffffffffffffffffffffffffffffffffffffff169052565b602083013560208501526142846040840184614194565b82604087015261429783870182846141f8565b925050506142a86060840184614194565b85830360608701526142bb8382846141f8565b925050506080830135608085015260a083013560a085015260c083013560c085015260e083013560e085015261010080840135818601525061012061430281850185614194565b868403838801526143148482846141f8565b935050505061014061432881850185614194565b8684038388015261433a8482846141f8565b979650505050505050565b6040808252810184905260006060600586901b830181019083018783805b898110156143e5577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa087860301845282357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea18c36030181126143c3578283fd5b6143cf868d8301614241565b9550506020938401939290920191600101614363565b50505050828103602084015261433a8185876141f8565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361442d5761442d613f4a565b5060010190565b6000808585111561444457600080fd5b8386111561445157600080fd5b5050820193919092039150565b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000813581811691601485101561449e5780818660140360031b1b83161692505b505092915050565b602081526000612ce46020830184866141f8565b6000602082840312156144cc57600080fd5b815161356081613ade565b65ffffffffffff8181168382160190808211156144f6576144f6613f4a565b5092915050565b8183823760009101908152919050565b868152856020820152600065ffffffffffff8087166040840152808616606084015250831515608083015260c060a083015261454c60c0830184613fb0565b98975050505050505050565b80518252602081015160208301526040810151151560408301526000606082015165ffffffffffff8082166060860152806080850151166080860152505060a082015160c060a0850152612ce460c0850182613fb0565b60006101408083526145c381840189614558565b9150506145dd602083018780518252602090810151910152565b845160608301526020948501516080830152835160a08301529284015160c0820152815173ffffffffffffffffffffffffffffffffffffffff1660e0820152908301518051610100830152909201516101209092019190915292915050565b60e08152600061464f60e0830187614558565b9050614668602083018680518252602090810151910152565b8351606083015260208401516080830152825160a0830152602083015160c083015295945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6000600385106146fb577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b848252606060208301526147126060830185613fb0565b9050826040830152949350505050565b600060033d111561473b5760046000803e5060005160e01c5b90565b600060443d101561474c5790565b6040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc803d016004833e81513d67ffffffffffffffff816024840111818411171561479a57505050505090565b82850191508151818111156147b25750505050505090565b843d87010160208285010111156147cc5750505050505090565b6147db60208286010187613a4d565b509095945050505050565b7f4141353020706f73744f702072657665727465643a200000000000000000000081526000825161481e816016850160208701613f8c565b9190910160160192915050565b60006101c080835261484081840187896141f8565b9050845173ffffffffffffffffffffffffffffffffffffffff808251166020860152602082015160408601526040820151606086015260608201516080860152608082015160a08601528060a08301511660c08601525060c081015160e085015260e08101516101008501525060208501516101208401526040850151610140840152606085015161016084015260808501516101808401528281036101a084015261433a8185613fb0565b6000602082840312156148fe57600080fd5b5051919050565b6060815260006149196060830187896141f8565b73ffffffffffffffffffffffffffffffffffffffff86166020840152828103604084015261454c8185876141f8565b60608152600061495b6060830186614241565b60208301949094525060400152919050565b7f414132332072657665727465643a2000000000000000000000000000000000008152600082516149a581600f850160208701613f8c565b91909101600f0192915050565b600080604083850312156149c557600080fd5b825167ffffffffffffffff8111156149dc57600080fd5b8301601f810185136149ed57600080fd5b80516149f881613a98565b604051614a058282613a4d565b828152876020848601011115614a1a57600080fd5b614a2b836020830160208701613f8c565b6020969096015195979596505050505050565b7f414133332072657665727465643a2000000000000000000000000000000000008152600082516149a581600f850160208701613f8c56fea164736f6c6343000813000a608060405234801561001057600080fd5b506101ea806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063570e1a3614610030575b600080fd5b61004361003e3660046100f9565b61006c565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b60008061007c601482858761016b565b61008591610195565b60601c90506000610099846014818861016b565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525084519495509360209350849250905082850182875af190506000519350806100f057600093505b50505092915050565b6000806020838503121561010c57600080fd5b823567ffffffffffffffff8082111561012457600080fd5b818501915085601f83011261013857600080fd5b81358181111561014757600080fd5b86602082850101111561015957600080fd5b60209290920196919550909350505050565b6000808585111561017b57600080fd5b8386111561018857600080fd5b5050820193919092039150565b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000081358181169160148510156101d55780818660140360031b1b83161692505b50509291505056fea164736f6c6343000813000a", -} - -var EntryPointABI = EntryPointMetaData.ABI - -var EntryPointBin = EntryPointMetaData.Bin - -func DeployEntryPoint(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *EntryPoint, error) { - parsed, err := EntryPointMetaData.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(EntryPointBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &EntryPoint{address: address, abi: *parsed, EntryPointCaller: EntryPointCaller{contract: contract}, EntryPointTransactor: EntryPointTransactor{contract: contract}, EntryPointFilterer: EntryPointFilterer{contract: contract}}, nil -} - -type EntryPoint struct { - address common.Address - abi abi.ABI - EntryPointCaller - EntryPointTransactor - EntryPointFilterer -} - -type EntryPointCaller struct { - contract *bind.BoundContract -} - -type EntryPointTransactor struct { - contract *bind.BoundContract -} - -type EntryPointFilterer struct { - contract *bind.BoundContract -} - -type EntryPointSession struct { - Contract *EntryPoint - CallOpts bind.CallOpts - TransactOpts bind.TransactOpts -} - -type EntryPointCallerSession struct { - Contract *EntryPointCaller - CallOpts bind.CallOpts -} - -type EntryPointTransactorSession struct { - Contract *EntryPointTransactor - TransactOpts bind.TransactOpts -} - -type EntryPointRaw struct { - Contract *EntryPoint -} - -type EntryPointCallerRaw struct { - Contract *EntryPointCaller -} - -type EntryPointTransactorRaw struct { - Contract *EntryPointTransactor -} - -func NewEntryPoint(address common.Address, backend bind.ContractBackend) (*EntryPoint, error) { - abi, err := abi.JSON(strings.NewReader(EntryPointABI)) - if err != nil { - return nil, err - } - contract, err := bindEntryPoint(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &EntryPoint{address: address, abi: abi, EntryPointCaller: EntryPointCaller{contract: contract}, EntryPointTransactor: EntryPointTransactor{contract: contract}, EntryPointFilterer: EntryPointFilterer{contract: contract}}, nil -} - -func NewEntryPointCaller(address common.Address, caller bind.ContractCaller) (*EntryPointCaller, error) { - contract, err := bindEntryPoint(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &EntryPointCaller{contract: contract}, nil -} - -func NewEntryPointTransactor(address common.Address, transactor bind.ContractTransactor) (*EntryPointTransactor, error) { - contract, err := bindEntryPoint(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &EntryPointTransactor{contract: contract}, nil -} - -func NewEntryPointFilterer(address common.Address, filterer bind.ContractFilterer) (*EntryPointFilterer, error) { - contract, err := bindEntryPoint(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &EntryPointFilterer{contract: contract}, nil -} - -func bindEntryPoint(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := EntryPointMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -func (_EntryPoint *EntryPointRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _EntryPoint.Contract.EntryPointCaller.contract.Call(opts, result, method, params...) -} - -func (_EntryPoint *EntryPointRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _EntryPoint.Contract.EntryPointTransactor.contract.Transfer(opts) -} - -func (_EntryPoint *EntryPointRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _EntryPoint.Contract.EntryPointTransactor.contract.Transact(opts, method, params...) -} - -func (_EntryPoint *EntryPointCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _EntryPoint.Contract.contract.Call(opts, result, method, params...) -} - -func (_EntryPoint *EntryPointTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _EntryPoint.Contract.contract.Transfer(opts) -} - -func (_EntryPoint *EntryPointTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _EntryPoint.Contract.contract.Transact(opts, method, params...) -} - -func (_EntryPoint *EntryPointCaller) SIGVALIDATIONFAILED(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _EntryPoint.contract.Call(opts, &out, "SIG_VALIDATION_FAILED") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_EntryPoint *EntryPointSession) SIGVALIDATIONFAILED() (*big.Int, error) { - return _EntryPoint.Contract.SIGVALIDATIONFAILED(&_EntryPoint.CallOpts) -} - -func (_EntryPoint *EntryPointCallerSession) SIGVALIDATIONFAILED() (*big.Int, error) { - return _EntryPoint.Contract.SIGVALIDATIONFAILED(&_EntryPoint.CallOpts) -} - -func (_EntryPoint *EntryPointCaller) ValidateSenderAndPaymaster(opts *bind.CallOpts, initCode []byte, sender common.Address, paymasterAndData []byte) error { - var out []interface{} - err := _EntryPoint.contract.Call(opts, &out, "_validateSenderAndPaymaster", initCode, sender, paymasterAndData) - - if err != nil { - return err - } - - return err - -} - -func (_EntryPoint *EntryPointSession) ValidateSenderAndPaymaster(initCode []byte, sender common.Address, paymasterAndData []byte) error { - return _EntryPoint.Contract.ValidateSenderAndPaymaster(&_EntryPoint.CallOpts, initCode, sender, paymasterAndData) -} - -func (_EntryPoint *EntryPointCallerSession) ValidateSenderAndPaymaster(initCode []byte, sender common.Address, paymasterAndData []byte) error { - return _EntryPoint.Contract.ValidateSenderAndPaymaster(&_EntryPoint.CallOpts, initCode, sender, paymasterAndData) -} - -func (_EntryPoint *EntryPointCaller) BalanceOf(opts *bind.CallOpts, account common.Address) (*big.Int, error) { - var out []interface{} - err := _EntryPoint.contract.Call(opts, &out, "balanceOf", account) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_EntryPoint *EntryPointSession) BalanceOf(account common.Address) (*big.Int, error) { - return _EntryPoint.Contract.BalanceOf(&_EntryPoint.CallOpts, account) -} - -func (_EntryPoint *EntryPointCallerSession) BalanceOf(account common.Address) (*big.Int, error) { - return _EntryPoint.Contract.BalanceOf(&_EntryPoint.CallOpts, account) -} - -func (_EntryPoint *EntryPointCaller) Deposits(opts *bind.CallOpts, arg0 common.Address) (Deposits, - - error) { - var out []interface{} - err := _EntryPoint.contract.Call(opts, &out, "deposits", arg0) - - outstruct := new(Deposits) - if err != nil { - return *outstruct, err - } - - outstruct.Deposit = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - outstruct.Staked = *abi.ConvertType(out[1], new(bool)).(*bool) - outstruct.Stake = *abi.ConvertType(out[2], new(*big.Int)).(**big.Int) - outstruct.UnstakeDelaySec = *abi.ConvertType(out[3], new(uint32)).(*uint32) - outstruct.WithdrawTime = *abi.ConvertType(out[4], new(*big.Int)).(**big.Int) - - return *outstruct, err - -} - -func (_EntryPoint *EntryPointSession) Deposits(arg0 common.Address) (Deposits, - - error) { - return _EntryPoint.Contract.Deposits(&_EntryPoint.CallOpts, arg0) -} - -func (_EntryPoint *EntryPointCallerSession) Deposits(arg0 common.Address) (Deposits, - - error) { - return _EntryPoint.Contract.Deposits(&_EntryPoint.CallOpts, arg0) -} - -func (_EntryPoint *EntryPointCaller) GetDepositInfo(opts *bind.CallOpts, account common.Address) (IStakeManagerDepositInfo, error) { - var out []interface{} - err := _EntryPoint.contract.Call(opts, &out, "getDepositInfo", account) - - if err != nil { - return *new(IStakeManagerDepositInfo), err - } - - out0 := *abi.ConvertType(out[0], new(IStakeManagerDepositInfo)).(*IStakeManagerDepositInfo) - - return out0, err - -} - -func (_EntryPoint *EntryPointSession) GetDepositInfo(account common.Address) (IStakeManagerDepositInfo, error) { - return _EntryPoint.Contract.GetDepositInfo(&_EntryPoint.CallOpts, account) -} - -func (_EntryPoint *EntryPointCallerSession) GetDepositInfo(account common.Address) (IStakeManagerDepositInfo, error) { - return _EntryPoint.Contract.GetDepositInfo(&_EntryPoint.CallOpts, account) -} - -func (_EntryPoint *EntryPointCaller) GetUserOpHash(opts *bind.CallOpts, userOp UserOperation) ([32]byte, error) { - var out []interface{} - err := _EntryPoint.contract.Call(opts, &out, "getUserOpHash", userOp) - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -func (_EntryPoint *EntryPointSession) GetUserOpHash(userOp UserOperation) ([32]byte, error) { - return _EntryPoint.Contract.GetUserOpHash(&_EntryPoint.CallOpts, userOp) -} - -func (_EntryPoint *EntryPointCallerSession) GetUserOpHash(userOp UserOperation) ([32]byte, error) { - return _EntryPoint.Contract.GetUserOpHash(&_EntryPoint.CallOpts, userOp) -} - -func (_EntryPoint *EntryPointTransactor) AddStake(opts *bind.TransactOpts, unstakeDelaySec uint32) (*types.Transaction, error) { - return _EntryPoint.contract.Transact(opts, "addStake", unstakeDelaySec) -} - -func (_EntryPoint *EntryPointSession) AddStake(unstakeDelaySec uint32) (*types.Transaction, error) { - return _EntryPoint.Contract.AddStake(&_EntryPoint.TransactOpts, unstakeDelaySec) -} - -func (_EntryPoint *EntryPointTransactorSession) AddStake(unstakeDelaySec uint32) (*types.Transaction, error) { - return _EntryPoint.Contract.AddStake(&_EntryPoint.TransactOpts, unstakeDelaySec) -} - -func (_EntryPoint *EntryPointTransactor) DepositTo(opts *bind.TransactOpts, account common.Address) (*types.Transaction, error) { - return _EntryPoint.contract.Transact(opts, "depositTo", account) -} - -func (_EntryPoint *EntryPointSession) DepositTo(account common.Address) (*types.Transaction, error) { - return _EntryPoint.Contract.DepositTo(&_EntryPoint.TransactOpts, account) -} - -func (_EntryPoint *EntryPointTransactorSession) DepositTo(account common.Address) (*types.Transaction, error) { - return _EntryPoint.Contract.DepositTo(&_EntryPoint.TransactOpts, account) -} - -func (_EntryPoint *EntryPointTransactor) GetSenderAddress(opts *bind.TransactOpts, initCode []byte) (*types.Transaction, error) { - return _EntryPoint.contract.Transact(opts, "getSenderAddress", initCode) -} - -func (_EntryPoint *EntryPointSession) GetSenderAddress(initCode []byte) (*types.Transaction, error) { - return _EntryPoint.Contract.GetSenderAddress(&_EntryPoint.TransactOpts, initCode) -} - -func (_EntryPoint *EntryPointTransactorSession) GetSenderAddress(initCode []byte) (*types.Transaction, error) { - return _EntryPoint.Contract.GetSenderAddress(&_EntryPoint.TransactOpts, initCode) -} - -func (_EntryPoint *EntryPointTransactor) HandleAggregatedOps(opts *bind.TransactOpts, opsPerAggregator []IEntryPointUserOpsPerAggregator, beneficiary common.Address) (*types.Transaction, error) { - return _EntryPoint.contract.Transact(opts, "handleAggregatedOps", opsPerAggregator, beneficiary) -} - -func (_EntryPoint *EntryPointSession) HandleAggregatedOps(opsPerAggregator []IEntryPointUserOpsPerAggregator, beneficiary common.Address) (*types.Transaction, error) { - return _EntryPoint.Contract.HandleAggregatedOps(&_EntryPoint.TransactOpts, opsPerAggregator, beneficiary) -} - -func (_EntryPoint *EntryPointTransactorSession) HandleAggregatedOps(opsPerAggregator []IEntryPointUserOpsPerAggregator, beneficiary common.Address) (*types.Transaction, error) { - return _EntryPoint.Contract.HandleAggregatedOps(&_EntryPoint.TransactOpts, opsPerAggregator, beneficiary) -} - -func (_EntryPoint *EntryPointTransactor) HandleOps(opts *bind.TransactOpts, ops []UserOperation, beneficiary common.Address) (*types.Transaction, error) { - return _EntryPoint.contract.Transact(opts, "handleOps", ops, beneficiary) -} - -func (_EntryPoint *EntryPointSession) HandleOps(ops []UserOperation, beneficiary common.Address) (*types.Transaction, error) { - return _EntryPoint.Contract.HandleOps(&_EntryPoint.TransactOpts, ops, beneficiary) -} - -func (_EntryPoint *EntryPointTransactorSession) HandleOps(ops []UserOperation, beneficiary common.Address) (*types.Transaction, error) { - return _EntryPoint.Contract.HandleOps(&_EntryPoint.TransactOpts, ops, beneficiary) -} - -func (_EntryPoint *EntryPointTransactor) InnerHandleOp(opts *bind.TransactOpts, callData []byte, opInfo EntryPointUserOpInfo, context []byte) (*types.Transaction, error) { - return _EntryPoint.contract.Transact(opts, "innerHandleOp", callData, opInfo, context) -} - -func (_EntryPoint *EntryPointSession) InnerHandleOp(callData []byte, opInfo EntryPointUserOpInfo, context []byte) (*types.Transaction, error) { - return _EntryPoint.Contract.InnerHandleOp(&_EntryPoint.TransactOpts, callData, opInfo, context) -} - -func (_EntryPoint *EntryPointTransactorSession) InnerHandleOp(callData []byte, opInfo EntryPointUserOpInfo, context []byte) (*types.Transaction, error) { - return _EntryPoint.Contract.InnerHandleOp(&_EntryPoint.TransactOpts, callData, opInfo, context) -} - -func (_EntryPoint *EntryPointTransactor) SimulateHandleOp(opts *bind.TransactOpts, op UserOperation, target common.Address, targetCallData []byte) (*types.Transaction, error) { - return _EntryPoint.contract.Transact(opts, "simulateHandleOp", op, target, targetCallData) -} - -func (_EntryPoint *EntryPointSession) SimulateHandleOp(op UserOperation, target common.Address, targetCallData []byte) (*types.Transaction, error) { - return _EntryPoint.Contract.SimulateHandleOp(&_EntryPoint.TransactOpts, op, target, targetCallData) -} - -func (_EntryPoint *EntryPointTransactorSession) SimulateHandleOp(op UserOperation, target common.Address, targetCallData []byte) (*types.Transaction, error) { - return _EntryPoint.Contract.SimulateHandleOp(&_EntryPoint.TransactOpts, op, target, targetCallData) -} - -func (_EntryPoint *EntryPointTransactor) SimulateValidation(opts *bind.TransactOpts, userOp UserOperation) (*types.Transaction, error) { - return _EntryPoint.contract.Transact(opts, "simulateValidation", userOp) -} - -func (_EntryPoint *EntryPointSession) SimulateValidation(userOp UserOperation) (*types.Transaction, error) { - return _EntryPoint.Contract.SimulateValidation(&_EntryPoint.TransactOpts, userOp) -} - -func (_EntryPoint *EntryPointTransactorSession) SimulateValidation(userOp UserOperation) (*types.Transaction, error) { - return _EntryPoint.Contract.SimulateValidation(&_EntryPoint.TransactOpts, userOp) -} - -func (_EntryPoint *EntryPointTransactor) UnlockStake(opts *bind.TransactOpts) (*types.Transaction, error) { - return _EntryPoint.contract.Transact(opts, "unlockStake") -} - -func (_EntryPoint *EntryPointSession) UnlockStake() (*types.Transaction, error) { - return _EntryPoint.Contract.UnlockStake(&_EntryPoint.TransactOpts) -} - -func (_EntryPoint *EntryPointTransactorSession) UnlockStake() (*types.Transaction, error) { - return _EntryPoint.Contract.UnlockStake(&_EntryPoint.TransactOpts) -} - -func (_EntryPoint *EntryPointTransactor) WithdrawStake(opts *bind.TransactOpts, withdrawAddress common.Address) (*types.Transaction, error) { - return _EntryPoint.contract.Transact(opts, "withdrawStake", withdrawAddress) -} - -func (_EntryPoint *EntryPointSession) WithdrawStake(withdrawAddress common.Address) (*types.Transaction, error) { - return _EntryPoint.Contract.WithdrawStake(&_EntryPoint.TransactOpts, withdrawAddress) -} - -func (_EntryPoint *EntryPointTransactorSession) WithdrawStake(withdrawAddress common.Address) (*types.Transaction, error) { - return _EntryPoint.Contract.WithdrawStake(&_EntryPoint.TransactOpts, withdrawAddress) -} - -func (_EntryPoint *EntryPointTransactor) WithdrawTo(opts *bind.TransactOpts, withdrawAddress common.Address, withdrawAmount *big.Int) (*types.Transaction, error) { - return _EntryPoint.contract.Transact(opts, "withdrawTo", withdrawAddress, withdrawAmount) -} - -func (_EntryPoint *EntryPointSession) WithdrawTo(withdrawAddress common.Address, withdrawAmount *big.Int) (*types.Transaction, error) { - return _EntryPoint.Contract.WithdrawTo(&_EntryPoint.TransactOpts, withdrawAddress, withdrawAmount) -} - -func (_EntryPoint *EntryPointTransactorSession) WithdrawTo(withdrawAddress common.Address, withdrawAmount *big.Int) (*types.Transaction, error) { - return _EntryPoint.Contract.WithdrawTo(&_EntryPoint.TransactOpts, withdrawAddress, withdrawAmount) -} - -func (_EntryPoint *EntryPointTransactor) Receive(opts *bind.TransactOpts) (*types.Transaction, error) { - return _EntryPoint.contract.RawTransact(opts, nil) -} - -func (_EntryPoint *EntryPointSession) Receive() (*types.Transaction, error) { - return _EntryPoint.Contract.Receive(&_EntryPoint.TransactOpts) -} - -func (_EntryPoint *EntryPointTransactorSession) Receive() (*types.Transaction, error) { - return _EntryPoint.Contract.Receive(&_EntryPoint.TransactOpts) -} - -type EntryPointAccountDeployedIterator struct { - Event *EntryPointAccountDeployed - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EntryPointAccountDeployedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EntryPointAccountDeployed) - 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(EntryPointAccountDeployed) - 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 *EntryPointAccountDeployedIterator) Error() error { - return it.fail -} - -func (it *EntryPointAccountDeployedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EntryPointAccountDeployed struct { - UserOpHash [32]byte - Sender common.Address - Factory common.Address - Paymaster common.Address - Raw types.Log -} - -func (_EntryPoint *EntryPointFilterer) FilterAccountDeployed(opts *bind.FilterOpts, userOpHash [][32]byte, sender []common.Address) (*EntryPointAccountDeployedIterator, error) { - - var userOpHashRule []interface{} - for _, userOpHashItem := range userOpHash { - userOpHashRule = append(userOpHashRule, userOpHashItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } - - logs, sub, err := _EntryPoint.contract.FilterLogs(opts, "AccountDeployed", userOpHashRule, senderRule) - if err != nil { - return nil, err - } - return &EntryPointAccountDeployedIterator{contract: _EntryPoint.contract, event: "AccountDeployed", logs: logs, sub: sub}, nil -} - -func (_EntryPoint *EntryPointFilterer) WatchAccountDeployed(opts *bind.WatchOpts, sink chan<- *EntryPointAccountDeployed, userOpHash [][32]byte, sender []common.Address) (event.Subscription, error) { - - var userOpHashRule []interface{} - for _, userOpHashItem := range userOpHash { - userOpHashRule = append(userOpHashRule, userOpHashItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } - - logs, sub, err := _EntryPoint.contract.WatchLogs(opts, "AccountDeployed", userOpHashRule, 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(EntryPointAccountDeployed) - if err := _EntryPoint.contract.UnpackLog(event, "AccountDeployed", 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 (_EntryPoint *EntryPointFilterer) ParseAccountDeployed(log types.Log) (*EntryPointAccountDeployed, error) { - event := new(EntryPointAccountDeployed) - if err := _EntryPoint.contract.UnpackLog(event, "AccountDeployed", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EntryPointDepositedIterator struct { - Event *EntryPointDeposited - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EntryPointDepositedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EntryPointDeposited) - 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(EntryPointDeposited) - 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 *EntryPointDepositedIterator) Error() error { - return it.fail -} - -func (it *EntryPointDepositedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EntryPointDeposited struct { - Account common.Address - TotalDeposit *big.Int - Raw types.Log -} - -func (_EntryPoint *EntryPointFilterer) FilterDeposited(opts *bind.FilterOpts, account []common.Address) (*EntryPointDepositedIterator, error) { - - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - - logs, sub, err := _EntryPoint.contract.FilterLogs(opts, "Deposited", accountRule) - if err != nil { - return nil, err - } - return &EntryPointDepositedIterator{contract: _EntryPoint.contract, event: "Deposited", logs: logs, sub: sub}, nil -} - -func (_EntryPoint *EntryPointFilterer) WatchDeposited(opts *bind.WatchOpts, sink chan<- *EntryPointDeposited, account []common.Address) (event.Subscription, error) { - - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - - logs, sub, err := _EntryPoint.contract.WatchLogs(opts, "Deposited", accountRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EntryPointDeposited) - if err := _EntryPoint.contract.UnpackLog(event, "Deposited", 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 (_EntryPoint *EntryPointFilterer) ParseDeposited(log types.Log) (*EntryPointDeposited, error) { - event := new(EntryPointDeposited) - if err := _EntryPoint.contract.UnpackLog(event, "Deposited", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EntryPointSignatureAggregatorChangedIterator struct { - Event *EntryPointSignatureAggregatorChanged - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EntryPointSignatureAggregatorChangedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EntryPointSignatureAggregatorChanged) - 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(EntryPointSignatureAggregatorChanged) - 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 *EntryPointSignatureAggregatorChangedIterator) Error() error { - return it.fail -} - -func (it *EntryPointSignatureAggregatorChangedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EntryPointSignatureAggregatorChanged struct { - Aggregator common.Address - Raw types.Log -} - -func (_EntryPoint *EntryPointFilterer) FilterSignatureAggregatorChanged(opts *bind.FilterOpts, aggregator []common.Address) (*EntryPointSignatureAggregatorChangedIterator, error) { - - var aggregatorRule []interface{} - for _, aggregatorItem := range aggregator { - aggregatorRule = append(aggregatorRule, aggregatorItem) - } - - logs, sub, err := _EntryPoint.contract.FilterLogs(opts, "SignatureAggregatorChanged", aggregatorRule) - if err != nil { - return nil, err - } - return &EntryPointSignatureAggregatorChangedIterator{contract: _EntryPoint.contract, event: "SignatureAggregatorChanged", logs: logs, sub: sub}, nil -} - -func (_EntryPoint *EntryPointFilterer) WatchSignatureAggregatorChanged(opts *bind.WatchOpts, sink chan<- *EntryPointSignatureAggregatorChanged, aggregator []common.Address) (event.Subscription, error) { - - var aggregatorRule []interface{} - for _, aggregatorItem := range aggregator { - aggregatorRule = append(aggregatorRule, aggregatorItem) - } - - logs, sub, err := _EntryPoint.contract.WatchLogs(opts, "SignatureAggregatorChanged", aggregatorRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EntryPointSignatureAggregatorChanged) - if err := _EntryPoint.contract.UnpackLog(event, "SignatureAggregatorChanged", 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 (_EntryPoint *EntryPointFilterer) ParseSignatureAggregatorChanged(log types.Log) (*EntryPointSignatureAggregatorChanged, error) { - event := new(EntryPointSignatureAggregatorChanged) - if err := _EntryPoint.contract.UnpackLog(event, "SignatureAggregatorChanged", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EntryPointStakeLockedIterator struct { - Event *EntryPointStakeLocked - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EntryPointStakeLockedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EntryPointStakeLocked) - 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(EntryPointStakeLocked) - 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 *EntryPointStakeLockedIterator) Error() error { - return it.fail -} - -func (it *EntryPointStakeLockedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EntryPointStakeLocked struct { - Account common.Address - TotalStaked *big.Int - UnstakeDelaySec *big.Int - Raw types.Log -} - -func (_EntryPoint *EntryPointFilterer) FilterStakeLocked(opts *bind.FilterOpts, account []common.Address) (*EntryPointStakeLockedIterator, error) { - - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - - logs, sub, err := _EntryPoint.contract.FilterLogs(opts, "StakeLocked", accountRule) - if err != nil { - return nil, err - } - return &EntryPointStakeLockedIterator{contract: _EntryPoint.contract, event: "StakeLocked", logs: logs, sub: sub}, nil -} - -func (_EntryPoint *EntryPointFilterer) WatchStakeLocked(opts *bind.WatchOpts, sink chan<- *EntryPointStakeLocked, account []common.Address) (event.Subscription, error) { - - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - - logs, sub, err := _EntryPoint.contract.WatchLogs(opts, "StakeLocked", accountRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EntryPointStakeLocked) - if err := _EntryPoint.contract.UnpackLog(event, "StakeLocked", 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 (_EntryPoint *EntryPointFilterer) ParseStakeLocked(log types.Log) (*EntryPointStakeLocked, error) { - event := new(EntryPointStakeLocked) - if err := _EntryPoint.contract.UnpackLog(event, "StakeLocked", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EntryPointStakeUnlockedIterator struct { - Event *EntryPointStakeUnlocked - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EntryPointStakeUnlockedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EntryPointStakeUnlocked) - 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(EntryPointStakeUnlocked) - 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 *EntryPointStakeUnlockedIterator) Error() error { - return it.fail -} - -func (it *EntryPointStakeUnlockedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EntryPointStakeUnlocked struct { - Account common.Address - WithdrawTime *big.Int - Raw types.Log -} - -func (_EntryPoint *EntryPointFilterer) FilterStakeUnlocked(opts *bind.FilterOpts, account []common.Address) (*EntryPointStakeUnlockedIterator, error) { - - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - - logs, sub, err := _EntryPoint.contract.FilterLogs(opts, "StakeUnlocked", accountRule) - if err != nil { - return nil, err - } - return &EntryPointStakeUnlockedIterator{contract: _EntryPoint.contract, event: "StakeUnlocked", logs: logs, sub: sub}, nil -} - -func (_EntryPoint *EntryPointFilterer) WatchStakeUnlocked(opts *bind.WatchOpts, sink chan<- *EntryPointStakeUnlocked, account []common.Address) (event.Subscription, error) { - - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - - logs, sub, err := _EntryPoint.contract.WatchLogs(opts, "StakeUnlocked", accountRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EntryPointStakeUnlocked) - if err := _EntryPoint.contract.UnpackLog(event, "StakeUnlocked", 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 (_EntryPoint *EntryPointFilterer) ParseStakeUnlocked(log types.Log) (*EntryPointStakeUnlocked, error) { - event := new(EntryPointStakeUnlocked) - if err := _EntryPoint.contract.UnpackLog(event, "StakeUnlocked", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EntryPointStakeWithdrawnIterator struct { - Event *EntryPointStakeWithdrawn - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EntryPointStakeWithdrawnIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EntryPointStakeWithdrawn) - 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(EntryPointStakeWithdrawn) - 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 *EntryPointStakeWithdrawnIterator) Error() error { - return it.fail -} - -func (it *EntryPointStakeWithdrawnIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EntryPointStakeWithdrawn struct { - Account common.Address - WithdrawAddress common.Address - Amount *big.Int - Raw types.Log -} - -func (_EntryPoint *EntryPointFilterer) FilterStakeWithdrawn(opts *bind.FilterOpts, account []common.Address) (*EntryPointStakeWithdrawnIterator, error) { - - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - - logs, sub, err := _EntryPoint.contract.FilterLogs(opts, "StakeWithdrawn", accountRule) - if err != nil { - return nil, err - } - return &EntryPointStakeWithdrawnIterator{contract: _EntryPoint.contract, event: "StakeWithdrawn", logs: logs, sub: sub}, nil -} - -func (_EntryPoint *EntryPointFilterer) WatchStakeWithdrawn(opts *bind.WatchOpts, sink chan<- *EntryPointStakeWithdrawn, account []common.Address) (event.Subscription, error) { - - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - - logs, sub, err := _EntryPoint.contract.WatchLogs(opts, "StakeWithdrawn", accountRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EntryPointStakeWithdrawn) - if err := _EntryPoint.contract.UnpackLog(event, "StakeWithdrawn", 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 (_EntryPoint *EntryPointFilterer) ParseStakeWithdrawn(log types.Log) (*EntryPointStakeWithdrawn, error) { - event := new(EntryPointStakeWithdrawn) - if err := _EntryPoint.contract.UnpackLog(event, "StakeWithdrawn", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EntryPointUserOperationEventIterator struct { - Event *EntryPointUserOperationEvent - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EntryPointUserOperationEventIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EntryPointUserOperationEvent) - 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(EntryPointUserOperationEvent) - 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 *EntryPointUserOperationEventIterator) Error() error { - return it.fail -} - -func (it *EntryPointUserOperationEventIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EntryPointUserOperationEvent struct { - UserOpHash [32]byte - Sender common.Address - Paymaster common.Address - Nonce *big.Int - Success bool - ActualGasCost *big.Int - ActualGasUsed *big.Int - Raw types.Log -} - -func (_EntryPoint *EntryPointFilterer) FilterUserOperationEvent(opts *bind.FilterOpts, userOpHash [][32]byte, sender []common.Address, paymaster []common.Address) (*EntryPointUserOperationEventIterator, error) { - - var userOpHashRule []interface{} - for _, userOpHashItem := range userOpHash { - userOpHashRule = append(userOpHashRule, userOpHashItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } - var paymasterRule []interface{} - for _, paymasterItem := range paymaster { - paymasterRule = append(paymasterRule, paymasterItem) - } - - logs, sub, err := _EntryPoint.contract.FilterLogs(opts, "UserOperationEvent", userOpHashRule, senderRule, paymasterRule) - if err != nil { - return nil, err - } - return &EntryPointUserOperationEventIterator{contract: _EntryPoint.contract, event: "UserOperationEvent", logs: logs, sub: sub}, nil -} - -func (_EntryPoint *EntryPointFilterer) WatchUserOperationEvent(opts *bind.WatchOpts, sink chan<- *EntryPointUserOperationEvent, userOpHash [][32]byte, sender []common.Address, paymaster []common.Address) (event.Subscription, error) { - - var userOpHashRule []interface{} - for _, userOpHashItem := range userOpHash { - userOpHashRule = append(userOpHashRule, userOpHashItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } - var paymasterRule []interface{} - for _, paymasterItem := range paymaster { - paymasterRule = append(paymasterRule, paymasterItem) - } - - logs, sub, err := _EntryPoint.contract.WatchLogs(opts, "UserOperationEvent", userOpHashRule, senderRule, paymasterRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EntryPointUserOperationEvent) - if err := _EntryPoint.contract.UnpackLog(event, "UserOperationEvent", 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 (_EntryPoint *EntryPointFilterer) ParseUserOperationEvent(log types.Log) (*EntryPointUserOperationEvent, error) { - event := new(EntryPointUserOperationEvent) - if err := _EntryPoint.contract.UnpackLog(event, "UserOperationEvent", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EntryPointUserOperationRevertReasonIterator struct { - Event *EntryPointUserOperationRevertReason - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EntryPointUserOperationRevertReasonIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EntryPointUserOperationRevertReason) - 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(EntryPointUserOperationRevertReason) - 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 *EntryPointUserOperationRevertReasonIterator) Error() error { - return it.fail -} - -func (it *EntryPointUserOperationRevertReasonIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EntryPointUserOperationRevertReason struct { - UserOpHash [32]byte - Sender common.Address - Nonce *big.Int - RevertReason []byte - Raw types.Log -} - -func (_EntryPoint *EntryPointFilterer) FilterUserOperationRevertReason(opts *bind.FilterOpts, userOpHash [][32]byte, sender []common.Address) (*EntryPointUserOperationRevertReasonIterator, error) { - - var userOpHashRule []interface{} - for _, userOpHashItem := range userOpHash { - userOpHashRule = append(userOpHashRule, userOpHashItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } - - logs, sub, err := _EntryPoint.contract.FilterLogs(opts, "UserOperationRevertReason", userOpHashRule, senderRule) - if err != nil { - return nil, err - } - return &EntryPointUserOperationRevertReasonIterator{contract: _EntryPoint.contract, event: "UserOperationRevertReason", logs: logs, sub: sub}, nil -} - -func (_EntryPoint *EntryPointFilterer) WatchUserOperationRevertReason(opts *bind.WatchOpts, sink chan<- *EntryPointUserOperationRevertReason, userOpHash [][32]byte, sender []common.Address) (event.Subscription, error) { - - var userOpHashRule []interface{} - for _, userOpHashItem := range userOpHash { - userOpHashRule = append(userOpHashRule, userOpHashItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } - - logs, sub, err := _EntryPoint.contract.WatchLogs(opts, "UserOperationRevertReason", userOpHashRule, 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(EntryPointUserOperationRevertReason) - if err := _EntryPoint.contract.UnpackLog(event, "UserOperationRevertReason", 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 (_EntryPoint *EntryPointFilterer) ParseUserOperationRevertReason(log types.Log) (*EntryPointUserOperationRevertReason, error) { - event := new(EntryPointUserOperationRevertReason) - if err := _EntryPoint.contract.UnpackLog(event, "UserOperationRevertReason", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EntryPointWithdrawnIterator struct { - Event *EntryPointWithdrawn - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EntryPointWithdrawnIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EntryPointWithdrawn) - 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(EntryPointWithdrawn) - 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 *EntryPointWithdrawnIterator) Error() error { - return it.fail -} - -func (it *EntryPointWithdrawnIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EntryPointWithdrawn struct { - Account common.Address - WithdrawAddress common.Address - Amount *big.Int - Raw types.Log -} - -func (_EntryPoint *EntryPointFilterer) FilterWithdrawn(opts *bind.FilterOpts, account []common.Address) (*EntryPointWithdrawnIterator, error) { - - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - - logs, sub, err := _EntryPoint.contract.FilterLogs(opts, "Withdrawn", accountRule) - if err != nil { - return nil, err - } - return &EntryPointWithdrawnIterator{contract: _EntryPoint.contract, event: "Withdrawn", logs: logs, sub: sub}, nil -} - -func (_EntryPoint *EntryPointFilterer) WatchWithdrawn(opts *bind.WatchOpts, sink chan<- *EntryPointWithdrawn, account []common.Address) (event.Subscription, error) { - - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - - logs, sub, err := _EntryPoint.contract.WatchLogs(opts, "Withdrawn", accountRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EntryPointWithdrawn) - if err := _EntryPoint.contract.UnpackLog(event, "Withdrawn", 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 (_EntryPoint *EntryPointFilterer) ParseWithdrawn(log types.Log) (*EntryPointWithdrawn, error) { - event := new(EntryPointWithdrawn) - if err := _EntryPoint.contract.UnpackLog(event, "Withdrawn", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type Deposits struct { - Deposit *big.Int - Staked bool - Stake *big.Int - UnstakeDelaySec uint32 - WithdrawTime *big.Int -} - -func (_EntryPoint *EntryPoint) ParseLog(log types.Log) (generated.AbigenLog, error) { - switch log.Topics[0] { - case _EntryPoint.abi.Events["AccountDeployed"].ID: - return _EntryPoint.ParseAccountDeployed(log) - case _EntryPoint.abi.Events["Deposited"].ID: - return _EntryPoint.ParseDeposited(log) - case _EntryPoint.abi.Events["SignatureAggregatorChanged"].ID: - return _EntryPoint.ParseSignatureAggregatorChanged(log) - case _EntryPoint.abi.Events["StakeLocked"].ID: - return _EntryPoint.ParseStakeLocked(log) - case _EntryPoint.abi.Events["StakeUnlocked"].ID: - return _EntryPoint.ParseStakeUnlocked(log) - case _EntryPoint.abi.Events["StakeWithdrawn"].ID: - return _EntryPoint.ParseStakeWithdrawn(log) - case _EntryPoint.abi.Events["UserOperationEvent"].ID: - return _EntryPoint.ParseUserOperationEvent(log) - case _EntryPoint.abi.Events["UserOperationRevertReason"].ID: - return _EntryPoint.ParseUserOperationRevertReason(log) - case _EntryPoint.abi.Events["Withdrawn"].ID: - return _EntryPoint.ParseWithdrawn(log) - - default: - return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) - } -} - -func (EntryPointAccountDeployed) Topic() common.Hash { - return common.HexToHash("0xd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d") -} - -func (EntryPointDeposited) Topic() common.Hash { - return common.HexToHash("0x2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c4") -} - -func (EntryPointSignatureAggregatorChanged) Topic() common.Hash { - return common.HexToHash("0x575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d") -} - -func (EntryPointStakeLocked) Topic() common.Hash { - return common.HexToHash("0xa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01") -} - -func (EntryPointStakeUnlocked) Topic() common.Hash { - return common.HexToHash("0xfa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a") -} - -func (EntryPointStakeWithdrawn) Topic() common.Hash { - return common.HexToHash("0xb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda3") -} - -func (EntryPointUserOperationEvent) Topic() common.Hash { - return common.HexToHash("0x49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f") -} - -func (EntryPointUserOperationRevertReason) Topic() common.Hash { - return common.HexToHash("0x1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a201") -} - -func (EntryPointWithdrawn) Topic() common.Hash { - return common.HexToHash("0xd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb") -} - -func (_EntryPoint *EntryPoint) Address() common.Address { - return _EntryPoint.address -} - -type EntryPointInterface interface { - SIGVALIDATIONFAILED(opts *bind.CallOpts) (*big.Int, error) - - ValidateSenderAndPaymaster(opts *bind.CallOpts, initCode []byte, sender common.Address, paymasterAndData []byte) error - - BalanceOf(opts *bind.CallOpts, account common.Address) (*big.Int, error) - - Deposits(opts *bind.CallOpts, arg0 common.Address) (Deposits, - - error) - - GetDepositInfo(opts *bind.CallOpts, account common.Address) (IStakeManagerDepositInfo, error) - - GetUserOpHash(opts *bind.CallOpts, userOp UserOperation) ([32]byte, error) - - AddStake(opts *bind.TransactOpts, unstakeDelaySec uint32) (*types.Transaction, error) - - DepositTo(opts *bind.TransactOpts, account common.Address) (*types.Transaction, error) - - GetSenderAddress(opts *bind.TransactOpts, initCode []byte) (*types.Transaction, error) - - HandleAggregatedOps(opts *bind.TransactOpts, opsPerAggregator []IEntryPointUserOpsPerAggregator, beneficiary common.Address) (*types.Transaction, error) - - HandleOps(opts *bind.TransactOpts, ops []UserOperation, beneficiary common.Address) (*types.Transaction, error) - - InnerHandleOp(opts *bind.TransactOpts, callData []byte, opInfo EntryPointUserOpInfo, context []byte) (*types.Transaction, error) - - SimulateHandleOp(opts *bind.TransactOpts, op UserOperation, target common.Address, targetCallData []byte) (*types.Transaction, error) - - SimulateValidation(opts *bind.TransactOpts, userOp UserOperation) (*types.Transaction, error) - - UnlockStake(opts *bind.TransactOpts) (*types.Transaction, error) - - WithdrawStake(opts *bind.TransactOpts, withdrawAddress common.Address) (*types.Transaction, error) - - WithdrawTo(opts *bind.TransactOpts, withdrawAddress common.Address, withdrawAmount *big.Int) (*types.Transaction, error) - - Receive(opts *bind.TransactOpts) (*types.Transaction, error) - - FilterAccountDeployed(opts *bind.FilterOpts, userOpHash [][32]byte, sender []common.Address) (*EntryPointAccountDeployedIterator, error) - - WatchAccountDeployed(opts *bind.WatchOpts, sink chan<- *EntryPointAccountDeployed, userOpHash [][32]byte, sender []common.Address) (event.Subscription, error) - - ParseAccountDeployed(log types.Log) (*EntryPointAccountDeployed, error) - - FilterDeposited(opts *bind.FilterOpts, account []common.Address) (*EntryPointDepositedIterator, error) - - WatchDeposited(opts *bind.WatchOpts, sink chan<- *EntryPointDeposited, account []common.Address) (event.Subscription, error) - - ParseDeposited(log types.Log) (*EntryPointDeposited, error) - - FilterSignatureAggregatorChanged(opts *bind.FilterOpts, aggregator []common.Address) (*EntryPointSignatureAggregatorChangedIterator, error) - - WatchSignatureAggregatorChanged(opts *bind.WatchOpts, sink chan<- *EntryPointSignatureAggregatorChanged, aggregator []common.Address) (event.Subscription, error) - - ParseSignatureAggregatorChanged(log types.Log) (*EntryPointSignatureAggregatorChanged, error) - - FilterStakeLocked(opts *bind.FilterOpts, account []common.Address) (*EntryPointStakeLockedIterator, error) - - WatchStakeLocked(opts *bind.WatchOpts, sink chan<- *EntryPointStakeLocked, account []common.Address) (event.Subscription, error) - - ParseStakeLocked(log types.Log) (*EntryPointStakeLocked, error) - - FilterStakeUnlocked(opts *bind.FilterOpts, account []common.Address) (*EntryPointStakeUnlockedIterator, error) - - WatchStakeUnlocked(opts *bind.WatchOpts, sink chan<- *EntryPointStakeUnlocked, account []common.Address) (event.Subscription, error) - - ParseStakeUnlocked(log types.Log) (*EntryPointStakeUnlocked, error) - - FilterStakeWithdrawn(opts *bind.FilterOpts, account []common.Address) (*EntryPointStakeWithdrawnIterator, error) - - WatchStakeWithdrawn(opts *bind.WatchOpts, sink chan<- *EntryPointStakeWithdrawn, account []common.Address) (event.Subscription, error) - - ParseStakeWithdrawn(log types.Log) (*EntryPointStakeWithdrawn, error) - - FilterUserOperationEvent(opts *bind.FilterOpts, userOpHash [][32]byte, sender []common.Address, paymaster []common.Address) (*EntryPointUserOperationEventIterator, error) - - WatchUserOperationEvent(opts *bind.WatchOpts, sink chan<- *EntryPointUserOperationEvent, userOpHash [][32]byte, sender []common.Address, paymaster []common.Address) (event.Subscription, error) - - ParseUserOperationEvent(log types.Log) (*EntryPointUserOperationEvent, error) - - FilterUserOperationRevertReason(opts *bind.FilterOpts, userOpHash [][32]byte, sender []common.Address) (*EntryPointUserOperationRevertReasonIterator, error) - - WatchUserOperationRevertReason(opts *bind.WatchOpts, sink chan<- *EntryPointUserOperationRevertReason, userOpHash [][32]byte, sender []common.Address) (event.Subscription, error) - - ParseUserOperationRevertReason(log types.Log) (*EntryPointUserOperationRevertReason, error) - - FilterWithdrawn(opts *bind.FilterOpts, account []common.Address) (*EntryPointWithdrawnIterator, error) - - WatchWithdrawn(opts *bind.WatchOpts, sink chan<- *EntryPointWithdrawn, account []common.Address) (event.Subscription, error) - - ParseWithdrawn(log types.Log) (*EntryPointWithdrawn, error) - - ParseLog(log types.Log) (generated.AbigenLog, error) - - Address() common.Address -} diff --git a/core/gethwrappers/transmission/generated/greeter_wrapper/greeter_wrapper.go b/core/gethwrappers/transmission/generated/greeter_wrapper/greeter_wrapper.go deleted file mode 100644 index 0f9e4a7719d..00000000000 --- a/core/gethwrappers/transmission/generated/greeter_wrapper/greeter_wrapper.go +++ /dev/null @@ -1,216 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package greeter_wrapper - -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 GreeterMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"getGreeting\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"greeting\",\"type\":\"string\"}],\"name\":\"setGreeting\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b50610443806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063a41368621461003b578063fe50cc7214610050575b600080fd5b61004e61004936600461013f565b61006e565b005b61005861007e565b604051610065919061020e565b60405180910390f35b600061007a828261031c565b5050565b60606000805461008d9061027a565b80601f01602080910402602001604051908101604052809291908181526020018280546100b99061027a565b80156101065780601f106100db57610100808354040283529160200191610106565b820191906000526020600020905b8154815290600101906020018083116100e957829003601f168201915b5050505050905090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561015157600080fd5b813567ffffffffffffffff8082111561016957600080fd5b818401915084601f83011261017d57600080fd5b81358181111561018f5761018f610110565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156101d5576101d5610110565b816040528281528760208487010111156101ee57600080fd5b826020860160208301376000928101602001929092525095945050505050565b600060208083528351808285015260005b8181101561023b5785810183015185820160400152820161021f565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b600181811c9082168061028e57607f821691505b6020821081036102c7577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f82111561031757600081815260208120601f850160051c810160208610156102f45750805b601f850160051c820191505b8181101561031357828155600101610300565b5050505b505050565b815167ffffffffffffffff81111561033657610336610110565b61034a81610344845461027a565b846102cd565b602080601f83116001811461039d57600084156103675750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610313565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156103ea578886015182559484019460019091019084016103cb565b508582101561042657878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c6343000813000a", -} - -var GreeterABI = GreeterMetaData.ABI - -var GreeterBin = GreeterMetaData.Bin - -func DeployGreeter(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Greeter, error) { - parsed, err := GreeterMetaData.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(GreeterBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &Greeter{address: address, abi: *parsed, GreeterCaller: GreeterCaller{contract: contract}, GreeterTransactor: GreeterTransactor{contract: contract}, GreeterFilterer: GreeterFilterer{contract: contract}}, nil -} - -type Greeter struct { - address common.Address - abi abi.ABI - GreeterCaller - GreeterTransactor - GreeterFilterer -} - -type GreeterCaller struct { - contract *bind.BoundContract -} - -type GreeterTransactor struct { - contract *bind.BoundContract -} - -type GreeterFilterer struct { - contract *bind.BoundContract -} - -type GreeterSession struct { - Contract *Greeter - CallOpts bind.CallOpts - TransactOpts bind.TransactOpts -} - -type GreeterCallerSession struct { - Contract *GreeterCaller - CallOpts bind.CallOpts -} - -type GreeterTransactorSession struct { - Contract *GreeterTransactor - TransactOpts bind.TransactOpts -} - -type GreeterRaw struct { - Contract *Greeter -} - -type GreeterCallerRaw struct { - Contract *GreeterCaller -} - -type GreeterTransactorRaw struct { - Contract *GreeterTransactor -} - -func NewGreeter(address common.Address, backend bind.ContractBackend) (*Greeter, error) { - abi, err := abi.JSON(strings.NewReader(GreeterABI)) - if err != nil { - return nil, err - } - contract, err := bindGreeter(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &Greeter{address: address, abi: abi, GreeterCaller: GreeterCaller{contract: contract}, GreeterTransactor: GreeterTransactor{contract: contract}, GreeterFilterer: GreeterFilterer{contract: contract}}, nil -} - -func NewGreeterCaller(address common.Address, caller bind.ContractCaller) (*GreeterCaller, error) { - contract, err := bindGreeter(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &GreeterCaller{contract: contract}, nil -} - -func NewGreeterTransactor(address common.Address, transactor bind.ContractTransactor) (*GreeterTransactor, error) { - contract, err := bindGreeter(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &GreeterTransactor{contract: contract}, nil -} - -func NewGreeterFilterer(address common.Address, filterer bind.ContractFilterer) (*GreeterFilterer, error) { - contract, err := bindGreeter(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &GreeterFilterer{contract: contract}, nil -} - -func bindGreeter(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := GreeterMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -func (_Greeter *GreeterRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Greeter.Contract.GreeterCaller.contract.Call(opts, result, method, params...) -} - -func (_Greeter *GreeterRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Greeter.Contract.GreeterTransactor.contract.Transfer(opts) -} - -func (_Greeter *GreeterRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Greeter.Contract.GreeterTransactor.contract.Transact(opts, method, params...) -} - -func (_Greeter *GreeterCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Greeter.Contract.contract.Call(opts, result, method, params...) -} - -func (_Greeter *GreeterTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Greeter.Contract.contract.Transfer(opts) -} - -func (_Greeter *GreeterTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Greeter.Contract.contract.Transact(opts, method, params...) -} - -func (_Greeter *GreeterCaller) GetGreeting(opts *bind.CallOpts) (string, error) { - var out []interface{} - err := _Greeter.contract.Call(opts, &out, "getGreeting") - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - -} - -func (_Greeter *GreeterSession) GetGreeting() (string, error) { - return _Greeter.Contract.GetGreeting(&_Greeter.CallOpts) -} - -func (_Greeter *GreeterCallerSession) GetGreeting() (string, error) { - return _Greeter.Contract.GetGreeting(&_Greeter.CallOpts) -} - -func (_Greeter *GreeterTransactor) SetGreeting(opts *bind.TransactOpts, greeting string) (*types.Transaction, error) { - return _Greeter.contract.Transact(opts, "setGreeting", greeting) -} - -func (_Greeter *GreeterSession) SetGreeting(greeting string) (*types.Transaction, error) { - return _Greeter.Contract.SetGreeting(&_Greeter.TransactOpts, greeting) -} - -func (_Greeter *GreeterTransactorSession) SetGreeting(greeting string) (*types.Transaction, error) { - return _Greeter.Contract.SetGreeting(&_Greeter.TransactOpts, greeting) -} - -func (_Greeter *Greeter) Address() common.Address { - return _Greeter.address -} - -type GreeterInterface interface { - GetGreeting(opts *bind.CallOpts) (string, error) - - SetGreeting(opts *bind.TransactOpts, greeting string) (*types.Transaction, error) - - Address() common.Address -} diff --git a/core/gethwrappers/transmission/generated/paymaster_wrapper/paymaster_wrapper.go b/core/gethwrappers/transmission/generated/paymaster_wrapper/paymaster_wrapper.go deleted file mode 100644 index 63a2712ca3f..00000000000 --- a/core/gethwrappers/transmission/generated/paymaster_wrapper/paymaster_wrapper.go +++ /dev/null @@ -1,719 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package paymaster_wrapper - -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 -) - -type UserOperation struct { - Sender common.Address - Nonce *big.Int - InitCode []byte - CallData []byte - CallGasLimit *big.Int - VerificationGasLimit *big.Int - PreVerificationGas *big.Int - MaxFeePerGas *big.Int - MaxPriorityFeePerGas *big.Int - PaymasterAndData []byte - Signature []byte -} - -var PaymasterMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractLinkTokenInterface\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"linkEthFeed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"entryPoint\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"juelsNeeded\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"subscriptionBalance\",\"type\":\"uint256\"}],\"name\":\"InsufficientFunds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidCalldata\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableFromLink\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"validator\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"}],\"name\":\"UserOperationAlreadyTried\",\"type\":\"error\"},{\"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\":[],\"name\":\"i_entryPoint\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_linkEthFeed\",\"outputs\":[{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_linkToken\",\"outputs\":[{\"internalType\":\"contractLinkTokenInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"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\":\"enumIPaymaster.PostOpMode\",\"name\":\"\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"}],\"name\":\"postOp\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_config\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"int256\",\"name\":\"fallbackWeiPerUnitLink\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"int256\",\"name\":\"fallbackWeiPerUnitLink\",\"type\":\"int256\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"structUserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"maxCost\",\"type\":\"uint256\"}],\"name\":\"validatePaymasterUserOp\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"validationData\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60e06040523480156200001157600080fd5b50604051620014c4380380620014c48339810160408190526200003491620001a3565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000df565b5050506001600160a01b0392831660805290821660a0521660c052620001f7565b336001600160a01b03821603620001395760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b0381168114620001a057600080fd5b50565b600080600060608486031215620001b957600080fd5b8351620001c6816200018a565b6020850151909350620001d9816200018a565b6040850151909250620001ec816200018a565b809150509250925092565b60805160a05160c0516112656200025f600039600081816101080152818161049f01528181610507015281816105cd015261063501526000818161018f0152610cb60152600081816101dc015281816103a201528181610ac90152610b8101526112656000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c80639b9bd4de11610081578063db37983b1161005b578063db37983b146101d7578063f2fde38b146101fe578063f465c77e1461021157600080fd5b80639b9bd4de1461018a578063a4c0ed36146101b1578063a9a23409146101c457600080fd5b806379ba5097116100b257806379ba50971461014f5780638a38f365146101595780638da5cb5b1461016c57600080fd5b8063088070f5146100ce578063140fcfb114610103575b600080fd5b6002546003546100e29163ffffffff169082565b6040805163ffffffff90931683526020830191909152015b60405180910390f35b61012a7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100fa565b610157610232565b005b610157610167366004610d5b565b610334565b60005473ffffffffffffffffffffffffffffffffffffffff1661012a565b61012a7f000000000000000000000000000000000000000000000000000000000000000081565b6101576101bf366004610dfb565b61038a565b6101576101d2366004610e57565b610487565b61012a7f000000000000000000000000000000000000000000000000000000000000000081565b61015761020c366004610eb7565b61059d565b61022461021f366004610edb565b6105b1565b6040516100fa929190610f2f565b60015473ffffffffffffffffffffffffffffffffffffffff1633146102b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61033c610849565b6040805180820190915263ffffffff9092168083526020909201819052600280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000016909217909155600355565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146103f9576040517f44b0e3c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208114610433576040517f8129bbcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061044182840184610eb7565b73ffffffffffffffffffffffffffffffffffffffff811660009081526005602052604081208054929350869290919061047b908490610fd1565b90915550505050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610534576040517f295a81c100000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660248201526044016102af565b60008061054384860186610fe4565b9150915080610551846108cc565b61055b9190610fd1565b73ffffffffffffffffffffffffffffffffffffffff831660009081526005602052604081208054909190610590908490611002565b9091555050505050505050565b6105a5610849565b6105ae816108f8565b50565b606060003373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610662576040517f295a81c100000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660248201526044016102af565b60008481526004602052604090205460ff16156106ae576040517f7413dcf8000000000000000000000000000000000000000000000000000000008152600481018590526024016102af565b60006106b9866109ed565b90506000816106c7866108cc565b6106d19190610fd1565b905080600560006106e560208b018b610eb7565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410156107b057806005600061073860208b018b610eb7565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546040517f03eb8b540000000000000000000000000000000000000000000000000000000081526004016102af929190918252602082015260400190565b600086815260046020908152604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556107f690880188610eb7565b6040805173ffffffffffffffffffffffffffffffffffffffff9092166020830152810183905260600160405160208183030381529060405261083b6000806000610c29565b935093505050935093915050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146108ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016102af565b565b60006108d6610c61565b6108e883670de0b6b3a7640000611015565b6108f2919061102c565b92915050565b3373ffffffffffffffffffffffffffffffffffffffff821603610977576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016102af565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60006109fd610120830183611067565b9050601403610a0e57506000919050565b6000610a1e610120840184611067565b6014818110610a2f57610a2f6110cc565b919091013560f81c9150819050610c23576000610a50610120850185611067565b610a5e9160159082906110fb565b810190610a6b9190611125565b90508060200151600014158015610b385750602081015181516040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821660048201527f0000000000000000000000000000000000000000000000000000000000000000909116906370a0823190602401602060405180830381865afa158015610b12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b3691906111ae565b105b15610c2157805160408083015190517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169263a9059cbb92610bd59260040173ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b6020604051808303816000875af1158015610bf4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1891906111c7565b50806040015192505b505b50919050565b600060d08265ffffffffffff16901b60a08465ffffffffffff16901b85610c51576000610c54565b60015b60ff161717949350505050565b600254604080517ffeaf968c000000000000000000000000000000000000000000000000000000008152905160009263ffffffff1691821515918491829173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169163feaf968c9160048083019260a09291908290030181865afa158015610d01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d259190611208565b509450909250849150508015610d495750610d408242611002565b8463ffffffff16105b15610d5357506003545b949350505050565b60008060408385031215610d6e57600080fd5b823563ffffffff81168114610d8257600080fd5b946020939093013593505050565b73ffffffffffffffffffffffffffffffffffffffff811681146105ae57600080fd5b60008083601f840112610dc457600080fd5b50813567ffffffffffffffff811115610ddc57600080fd5b602083019150836020828501011115610df457600080fd5b9250929050565b60008060008060608587031215610e1157600080fd5b8435610e1c81610d90565b935060208501359250604085013567ffffffffffffffff811115610e3f57600080fd5b610e4b87828801610db2565b95989497509550505050565b60008060008060608587031215610e6d57600080fd5b843560038110610e7c57600080fd5b9350602085013567ffffffffffffffff811115610e9857600080fd5b610ea487828801610db2565b9598909750949560400135949350505050565b600060208284031215610ec957600080fd5b8135610ed481610d90565b9392505050565b600080600060608486031215610ef057600080fd5b833567ffffffffffffffff811115610f0757600080fd5b84016101608187031215610f1a57600080fd5b95602085013595506040909401359392505050565b604081526000835180604084015260005b81811015610f5d5760208187018101516060868401015201610f40565b5060006060828501015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168401019150508260208301529392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156108f2576108f2610fa2565b60008060408385031215610ff757600080fd5b8235610d8281610d90565b818103818111156108f2576108f2610fa2565b80820281158282048414176108f2576108f2610fa2565b600082611062577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261109c57600080fd5b83018035915067ffffffffffffffff8211156110b757600080fd5b602001915036819003821315610df457600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000808585111561110b57600080fd5b8386111561111857600080fd5b5050820193919092039150565b60006060828403121561113757600080fd5b6040516060810181811067ffffffffffffffff82111715611181577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604052823561118f81610d90565b8152602083810135908201526040928301359281019290925250919050565b6000602082840312156111c057600080fd5b5051919050565b6000602082840312156111d957600080fd5b81518015158114610ed457600080fd5b805169ffffffffffffffffffff8116811461120357600080fd5b919050565b600080600080600060a0868803121561122057600080fd5b611229866111e9565b945060208601519350604086015192506060860151915061124c608087016111e9565b9050929550929590935056fea164736f6c6343000813000a", -} - -var PaymasterABI = PaymasterMetaData.ABI - -var PaymasterBin = PaymasterMetaData.Bin - -func DeployPaymaster(auth *bind.TransactOpts, backend bind.ContractBackend, linkToken common.Address, linkEthFeed common.Address, entryPoint common.Address) (common.Address, *types.Transaction, *Paymaster, error) { - parsed, err := PaymasterMetaData.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(PaymasterBin), backend, linkToken, linkEthFeed, entryPoint) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &Paymaster{address: address, abi: *parsed, PaymasterCaller: PaymasterCaller{contract: contract}, PaymasterTransactor: PaymasterTransactor{contract: contract}, PaymasterFilterer: PaymasterFilterer{contract: contract}}, nil -} - -type Paymaster struct { - address common.Address - abi abi.ABI - PaymasterCaller - PaymasterTransactor - PaymasterFilterer -} - -type PaymasterCaller struct { - contract *bind.BoundContract -} - -type PaymasterTransactor struct { - contract *bind.BoundContract -} - -type PaymasterFilterer struct { - contract *bind.BoundContract -} - -type PaymasterSession struct { - Contract *Paymaster - CallOpts bind.CallOpts - TransactOpts bind.TransactOpts -} - -type PaymasterCallerSession struct { - Contract *PaymasterCaller - CallOpts bind.CallOpts -} - -type PaymasterTransactorSession struct { - Contract *PaymasterTransactor - TransactOpts bind.TransactOpts -} - -type PaymasterRaw struct { - Contract *Paymaster -} - -type PaymasterCallerRaw struct { - Contract *PaymasterCaller -} - -type PaymasterTransactorRaw struct { - Contract *PaymasterTransactor -} - -func NewPaymaster(address common.Address, backend bind.ContractBackend) (*Paymaster, error) { - abi, err := abi.JSON(strings.NewReader(PaymasterABI)) - if err != nil { - return nil, err - } - contract, err := bindPaymaster(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &Paymaster{address: address, abi: abi, PaymasterCaller: PaymasterCaller{contract: contract}, PaymasterTransactor: PaymasterTransactor{contract: contract}, PaymasterFilterer: PaymasterFilterer{contract: contract}}, nil -} - -func NewPaymasterCaller(address common.Address, caller bind.ContractCaller) (*PaymasterCaller, error) { - contract, err := bindPaymaster(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &PaymasterCaller{contract: contract}, nil -} - -func NewPaymasterTransactor(address common.Address, transactor bind.ContractTransactor) (*PaymasterTransactor, error) { - contract, err := bindPaymaster(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &PaymasterTransactor{contract: contract}, nil -} - -func NewPaymasterFilterer(address common.Address, filterer bind.ContractFilterer) (*PaymasterFilterer, error) { - contract, err := bindPaymaster(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &PaymasterFilterer{contract: contract}, nil -} - -func bindPaymaster(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := PaymasterMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -func (_Paymaster *PaymasterRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Paymaster.Contract.PaymasterCaller.contract.Call(opts, result, method, params...) -} - -func (_Paymaster *PaymasterRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Paymaster.Contract.PaymasterTransactor.contract.Transfer(opts) -} - -func (_Paymaster *PaymasterRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Paymaster.Contract.PaymasterTransactor.contract.Transact(opts, method, params...) -} - -func (_Paymaster *PaymasterCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Paymaster.Contract.contract.Call(opts, result, method, params...) -} - -func (_Paymaster *PaymasterTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Paymaster.Contract.contract.Transfer(opts) -} - -func (_Paymaster *PaymasterTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Paymaster.Contract.contract.Transact(opts, method, params...) -} - -func (_Paymaster *PaymasterCaller) IEntryPoint(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _Paymaster.contract.Call(opts, &out, "i_entryPoint") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -func (_Paymaster *PaymasterSession) IEntryPoint() (common.Address, error) { - return _Paymaster.Contract.IEntryPoint(&_Paymaster.CallOpts) -} - -func (_Paymaster *PaymasterCallerSession) IEntryPoint() (common.Address, error) { - return _Paymaster.Contract.IEntryPoint(&_Paymaster.CallOpts) -} - -func (_Paymaster *PaymasterCaller) ILinkEthFeed(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _Paymaster.contract.Call(opts, &out, "i_linkEthFeed") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -func (_Paymaster *PaymasterSession) ILinkEthFeed() (common.Address, error) { - return _Paymaster.Contract.ILinkEthFeed(&_Paymaster.CallOpts) -} - -func (_Paymaster *PaymasterCallerSession) ILinkEthFeed() (common.Address, error) { - return _Paymaster.Contract.ILinkEthFeed(&_Paymaster.CallOpts) -} - -func (_Paymaster *PaymasterCaller) ILinkToken(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _Paymaster.contract.Call(opts, &out, "i_linkToken") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -func (_Paymaster *PaymasterSession) ILinkToken() (common.Address, error) { - return _Paymaster.Contract.ILinkToken(&_Paymaster.CallOpts) -} - -func (_Paymaster *PaymasterCallerSession) ILinkToken() (common.Address, error) { - return _Paymaster.Contract.ILinkToken(&_Paymaster.CallOpts) -} - -func (_Paymaster *PaymasterCaller) Owner(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _Paymaster.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 (_Paymaster *PaymasterSession) Owner() (common.Address, error) { - return _Paymaster.Contract.Owner(&_Paymaster.CallOpts) -} - -func (_Paymaster *PaymasterCallerSession) Owner() (common.Address, error) { - return _Paymaster.Contract.Owner(&_Paymaster.CallOpts) -} - -func (_Paymaster *PaymasterCaller) SConfig(opts *bind.CallOpts) (SConfig, - - error) { - var out []interface{} - err := _Paymaster.contract.Call(opts, &out, "s_config") - - outstruct := new(SConfig) - if err != nil { - return *outstruct, err - } - - outstruct.StalenessSeconds = *abi.ConvertType(out[0], new(uint32)).(*uint32) - outstruct.FallbackWeiPerUnitLink = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) - - return *outstruct, err - -} - -func (_Paymaster *PaymasterSession) SConfig() (SConfig, - - error) { - return _Paymaster.Contract.SConfig(&_Paymaster.CallOpts) -} - -func (_Paymaster *PaymasterCallerSession) SConfig() (SConfig, - - error) { - return _Paymaster.Contract.SConfig(&_Paymaster.CallOpts) -} - -func (_Paymaster *PaymasterTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Paymaster.contract.Transact(opts, "acceptOwnership") -} - -func (_Paymaster *PaymasterSession) AcceptOwnership() (*types.Transaction, error) { - return _Paymaster.Contract.AcceptOwnership(&_Paymaster.TransactOpts) -} - -func (_Paymaster *PaymasterTransactorSession) AcceptOwnership() (*types.Transaction, error) { - return _Paymaster.Contract.AcceptOwnership(&_Paymaster.TransactOpts) -} - -func (_Paymaster *PaymasterTransactor) OnTokenTransfer(opts *bind.TransactOpts, arg0 common.Address, _amount *big.Int, _data []byte) (*types.Transaction, error) { - return _Paymaster.contract.Transact(opts, "onTokenTransfer", arg0, _amount, _data) -} - -func (_Paymaster *PaymasterSession) OnTokenTransfer(arg0 common.Address, _amount *big.Int, _data []byte) (*types.Transaction, error) { - return _Paymaster.Contract.OnTokenTransfer(&_Paymaster.TransactOpts, arg0, _amount, _data) -} - -func (_Paymaster *PaymasterTransactorSession) OnTokenTransfer(arg0 common.Address, _amount *big.Int, _data []byte) (*types.Transaction, error) { - return _Paymaster.Contract.OnTokenTransfer(&_Paymaster.TransactOpts, arg0, _amount, _data) -} - -func (_Paymaster *PaymasterTransactor) PostOp(opts *bind.TransactOpts, arg0 uint8, context []byte, actualGasCost *big.Int) (*types.Transaction, error) { - return _Paymaster.contract.Transact(opts, "postOp", arg0, context, actualGasCost) -} - -func (_Paymaster *PaymasterSession) PostOp(arg0 uint8, context []byte, actualGasCost *big.Int) (*types.Transaction, error) { - return _Paymaster.Contract.PostOp(&_Paymaster.TransactOpts, arg0, context, actualGasCost) -} - -func (_Paymaster *PaymasterTransactorSession) PostOp(arg0 uint8, context []byte, actualGasCost *big.Int) (*types.Transaction, error) { - return _Paymaster.Contract.PostOp(&_Paymaster.TransactOpts, arg0, context, actualGasCost) -} - -func (_Paymaster *PaymasterTransactor) SetConfig(opts *bind.TransactOpts, stalenessSeconds uint32, fallbackWeiPerUnitLink *big.Int) (*types.Transaction, error) { - return _Paymaster.contract.Transact(opts, "setConfig", stalenessSeconds, fallbackWeiPerUnitLink) -} - -func (_Paymaster *PaymasterSession) SetConfig(stalenessSeconds uint32, fallbackWeiPerUnitLink *big.Int) (*types.Transaction, error) { - return _Paymaster.Contract.SetConfig(&_Paymaster.TransactOpts, stalenessSeconds, fallbackWeiPerUnitLink) -} - -func (_Paymaster *PaymasterTransactorSession) SetConfig(stalenessSeconds uint32, fallbackWeiPerUnitLink *big.Int) (*types.Transaction, error) { - return _Paymaster.Contract.SetConfig(&_Paymaster.TransactOpts, stalenessSeconds, fallbackWeiPerUnitLink) -} - -func (_Paymaster *PaymasterTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { - return _Paymaster.contract.Transact(opts, "transferOwnership", to) -} - -func (_Paymaster *PaymasterSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _Paymaster.Contract.TransferOwnership(&_Paymaster.TransactOpts, to) -} - -func (_Paymaster *PaymasterTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _Paymaster.Contract.TransferOwnership(&_Paymaster.TransactOpts, to) -} - -func (_Paymaster *PaymasterTransactor) ValidatePaymasterUserOp(opts *bind.TransactOpts, userOp UserOperation, userOpHash [32]byte, maxCost *big.Int) (*types.Transaction, error) { - return _Paymaster.contract.Transact(opts, "validatePaymasterUserOp", userOp, userOpHash, maxCost) -} - -func (_Paymaster *PaymasterSession) ValidatePaymasterUserOp(userOp UserOperation, userOpHash [32]byte, maxCost *big.Int) (*types.Transaction, error) { - return _Paymaster.Contract.ValidatePaymasterUserOp(&_Paymaster.TransactOpts, userOp, userOpHash, maxCost) -} - -func (_Paymaster *PaymasterTransactorSession) ValidatePaymasterUserOp(userOp UserOperation, userOpHash [32]byte, maxCost *big.Int) (*types.Transaction, error) { - return _Paymaster.Contract.ValidatePaymasterUserOp(&_Paymaster.TransactOpts, userOp, userOpHash, maxCost) -} - -type PaymasterOwnershipTransferRequestedIterator struct { - Event *PaymasterOwnershipTransferRequested - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *PaymasterOwnershipTransferRequestedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(PaymasterOwnershipTransferRequested) - 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(PaymasterOwnershipTransferRequested) - 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 *PaymasterOwnershipTransferRequestedIterator) Error() error { - return it.fail -} - -func (it *PaymasterOwnershipTransferRequestedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type PaymasterOwnershipTransferRequested struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_Paymaster *PaymasterFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*PaymasterOwnershipTransferRequestedIterator, 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 := _Paymaster.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) - if err != nil { - return nil, err - } - return &PaymasterOwnershipTransferRequestedIterator{contract: _Paymaster.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil -} - -func (_Paymaster *PaymasterFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *PaymasterOwnershipTransferRequested, 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 := _Paymaster.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(PaymasterOwnershipTransferRequested) - if err := _Paymaster.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 (_Paymaster *PaymasterFilterer) ParseOwnershipTransferRequested(log types.Log) (*PaymasterOwnershipTransferRequested, error) { - event := new(PaymasterOwnershipTransferRequested) - if err := _Paymaster.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type PaymasterOwnershipTransferredIterator struct { - Event *PaymasterOwnershipTransferred - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *PaymasterOwnershipTransferredIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(PaymasterOwnershipTransferred) - 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(PaymasterOwnershipTransferred) - 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 *PaymasterOwnershipTransferredIterator) Error() error { - return it.fail -} - -func (it *PaymasterOwnershipTransferredIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type PaymasterOwnershipTransferred struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_Paymaster *PaymasterFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*PaymasterOwnershipTransferredIterator, 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 := _Paymaster.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) - if err != nil { - return nil, err - } - return &PaymasterOwnershipTransferredIterator{contract: _Paymaster.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil -} - -func (_Paymaster *PaymasterFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *PaymasterOwnershipTransferred, 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 := _Paymaster.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(PaymasterOwnershipTransferred) - if err := _Paymaster.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 (_Paymaster *PaymasterFilterer) ParseOwnershipTransferred(log types.Log) (*PaymasterOwnershipTransferred, error) { - event := new(PaymasterOwnershipTransferred) - if err := _Paymaster.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type SConfig struct { - StalenessSeconds uint32 - FallbackWeiPerUnitLink *big.Int -} - -func (_Paymaster *Paymaster) ParseLog(log types.Log) (generated.AbigenLog, error) { - switch log.Topics[0] { - case _Paymaster.abi.Events["OwnershipTransferRequested"].ID: - return _Paymaster.ParseOwnershipTransferRequested(log) - case _Paymaster.abi.Events["OwnershipTransferred"].ID: - return _Paymaster.ParseOwnershipTransferred(log) - - default: - return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) - } -} - -func (PaymasterOwnershipTransferRequested) Topic() common.Hash { - return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") -} - -func (PaymasterOwnershipTransferred) Topic() common.Hash { - return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") -} - -func (_Paymaster *Paymaster) Address() common.Address { - return _Paymaster.address -} - -type PaymasterInterface interface { - IEntryPoint(opts *bind.CallOpts) (common.Address, error) - - ILinkEthFeed(opts *bind.CallOpts) (common.Address, error) - - ILinkToken(opts *bind.CallOpts) (common.Address, error) - - Owner(opts *bind.CallOpts) (common.Address, error) - - SConfig(opts *bind.CallOpts) (SConfig, - - error) - - AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) - - OnTokenTransfer(opts *bind.TransactOpts, arg0 common.Address, _amount *big.Int, _data []byte) (*types.Transaction, error) - - PostOp(opts *bind.TransactOpts, arg0 uint8, context []byte, actualGasCost *big.Int) (*types.Transaction, error) - - SetConfig(opts *bind.TransactOpts, stalenessSeconds uint32, fallbackWeiPerUnitLink *big.Int) (*types.Transaction, error) - - TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) - - ValidatePaymasterUserOp(opts *bind.TransactOpts, userOp UserOperation, userOpHash [32]byte, maxCost *big.Int) (*types.Transaction, error) - - FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*PaymasterOwnershipTransferRequestedIterator, error) - - WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *PaymasterOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferRequested(log types.Log) (*PaymasterOwnershipTransferRequested, error) - - FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*PaymasterOwnershipTransferredIterator, error) - - WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *PaymasterOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferred(log types.Log) (*PaymasterOwnershipTransferred, error) - - ParseLog(log types.Log) (generated.AbigenLog, error) - - Address() common.Address -} diff --git a/core/gethwrappers/transmission/generated/sca_wrapper/sca_wrapper.go b/core/gethwrappers/transmission/generated/sca_wrapper/sca_wrapper.go deleted file mode 100644 index 989e4058685..00000000000 --- a/core/gethwrappers/transmission/generated/sca_wrapper/sca_wrapper.go +++ /dev/null @@ -1,292 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package sca_wrapper - -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 -) - -type UserOperation struct { - Sender common.Address - Nonce *big.Int - InitCode []byte - CallData []byte - CallGasLimit *big.Int - VerificationGasLimit *big.Int - PreVerificationGas *big.Int - MaxFeePerGas *big.Int - MaxPriorityFeePerGas *big.Int - PaymasterAndData []byte - Signature []byte -} - -var SCAMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"entryPoint\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"BadFormatOrOOG\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"currentNonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nonceGiven\",\"type\":\"uint256\"}],\"name\":\"IncorrectNonce\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"operationHash\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"NotAuthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"currentTimestamp\",\"type\":\"uint256\"}],\"name\":\"TransactionExpired\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint48\",\"name\":\"deadline\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"executeTransactionFromEntryPoint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_entryPoint\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_nonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"structUserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"validateUserOp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"validationData\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60c060405234801561001057600080fd5b50604051610acb380380610acb83398101604081905261002f91610062565b6001600160a01b039182166080521660a052610095565b80516001600160a01b038116811461005d57600080fd5b919050565b6000806040838503121561007557600080fd5b61007e83610046565b915061008c60208401610046565b90509250929050565b60805160a051610a046100c760003960008181607101526102b801526000818161010101526101e30152610a046000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c80637eccf63e116100505780637eccf63e146100de57806389553be4146100e7578063dba6335f146100fc57600080fd5b8063140fcfb11461006c5780633a871cdd146100bd575b600080fd5b6100937f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100d06100cb366004610646565b610123565b6040519081526020016100b4565b6100d060005481565b6100fa6100f53660046106da565b6102a0565b005b6100937f000000000000000000000000000000000000000000000000000000000000000081565b60008054846020013514610179576000546040517f7ba633940000000000000000000000000000000000000000000000000000000081526004810191909152602085013560248201526044015b60405180910390fd5b60006101858430610439565b90506000610197610140870187610777565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016915061021190508284610550565b73ffffffffffffffffffffffffffffffffffffffff161461024257610239600160008061060e565b92505050610299565b60008054908061025183610812565b90915550600090506102666060880188610777565b61027491600490829061084a565b81019061028191906108a3565b5092505050610293600082600061060e565b93505050505b9392505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610311576040517f4a0bfec1000000000000000000000000000000000000000000000000000000008152336004820152602401610170565b65ffffffffffff83161580159061032f57508265ffffffffffff1642115b15610376576040517f300249d700000000000000000000000000000000000000000000000000000000815265ffffffffffff84166004820152426024820152604401610170565b6000808673ffffffffffffffffffffffffffffffffffffffff168685856040516103a192919061099f565b60006040518083038185875af1925050503d80600081146103de576040519150601f19603f3d011682016040523d82523d6000602084013e6103e3565b606091505b509150915081610430578051600003610428576040517f20e9b5d200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b50505050505050565b604080517f4750045d47fce615521b32cee713ff8db50147e98aec5ca94926b52651ca3fa0602080830191909152818301859052825180830384018152606080840185528151918301919091207f190000000000000000000000000000000000000000000000000000000000000060808501527f010000000000000000000000000000000000000000000000000000000000000060818501527f1c7d3b72b37a35523e273aaadd7b4cd66f618bb81429ab053412d51f50ccea6160828501524660a28501529085901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660c284015260d6808401919091528351808403909101815260f690920190925280519101205b92915050565b602082015160408084015184516000939284918791908110610574576105746109af565b016020015160f81c905060018561058c83601b6109de565b6040805160008152602081018083529390935260ff90911690820152606081018590526080810184905260a0016020604051602081039080840390855afa1580156105db573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00151979650505050505050565b600060d08265ffffffffffff16901b60a08465ffffffffffff16901b85610636576000610639565b60015b60ff161717949350505050565b60008060006060848603121561065b57600080fd5b833567ffffffffffffffff81111561067257600080fd5b8401610160818703121561068557600080fd5b95602085013595506040909401359392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146106bc57600080fd5b50565b803565ffffffffffff811681146106d557600080fd5b919050565b6000806000806000608086880312156106f257600080fd5b85356106fd8161069a565b945060208601359350610712604087016106bf565b9250606086013567ffffffffffffffff8082111561072f57600080fd5b818801915088601f83011261074357600080fd5b81358181111561075257600080fd5b89602082850101111561076457600080fd5b9699959850939650602001949392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126107ac57600080fd5b83018035915067ffffffffffffffff8211156107c757600080fd5b6020019150368190038213156107dc57600080fd5b9250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610843576108436107e3565b5060010190565b6000808585111561085a57600080fd5b8386111561086757600080fd5b5050820193919092039150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600080608085870312156108b957600080fd5b84356108c48161069a565b9350602085013592506108d9604086016106bf565b9150606085013567ffffffffffffffff808211156108f657600080fd5b818701915087601f83011261090a57600080fd5b81358181111561091c5761091c610874565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561096257610962610874565b816040528281528a602084870101111561097b57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60ff818116838216019081111561054a5761054a6107e356fea164736f6c6343000813000a", -} - -var SCAABI = SCAMetaData.ABI - -var SCABin = SCAMetaData.Bin - -func DeploySCA(auth *bind.TransactOpts, backend bind.ContractBackend, owner common.Address, entryPoint common.Address) (common.Address, *types.Transaction, *SCA, error) { - parsed, err := SCAMetaData.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(SCABin), backend, owner, entryPoint) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &SCA{address: address, abi: *parsed, SCACaller: SCACaller{contract: contract}, SCATransactor: SCATransactor{contract: contract}, SCAFilterer: SCAFilterer{contract: contract}}, nil -} - -type SCA struct { - address common.Address - abi abi.ABI - SCACaller - SCATransactor - SCAFilterer -} - -type SCACaller struct { - contract *bind.BoundContract -} - -type SCATransactor struct { - contract *bind.BoundContract -} - -type SCAFilterer struct { - contract *bind.BoundContract -} - -type SCASession struct { - Contract *SCA - CallOpts bind.CallOpts - TransactOpts bind.TransactOpts -} - -type SCACallerSession struct { - Contract *SCACaller - CallOpts bind.CallOpts -} - -type SCATransactorSession struct { - Contract *SCATransactor - TransactOpts bind.TransactOpts -} - -type SCARaw struct { - Contract *SCA -} - -type SCACallerRaw struct { - Contract *SCACaller -} - -type SCATransactorRaw struct { - Contract *SCATransactor -} - -func NewSCA(address common.Address, backend bind.ContractBackend) (*SCA, error) { - abi, err := abi.JSON(strings.NewReader(SCAABI)) - if err != nil { - return nil, err - } - contract, err := bindSCA(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &SCA{address: address, abi: abi, SCACaller: SCACaller{contract: contract}, SCATransactor: SCATransactor{contract: contract}, SCAFilterer: SCAFilterer{contract: contract}}, nil -} - -func NewSCACaller(address common.Address, caller bind.ContractCaller) (*SCACaller, error) { - contract, err := bindSCA(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &SCACaller{contract: contract}, nil -} - -func NewSCATransactor(address common.Address, transactor bind.ContractTransactor) (*SCATransactor, error) { - contract, err := bindSCA(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &SCATransactor{contract: contract}, nil -} - -func NewSCAFilterer(address common.Address, filterer bind.ContractFilterer) (*SCAFilterer, error) { - contract, err := bindSCA(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &SCAFilterer{contract: contract}, nil -} - -func bindSCA(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := SCAMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -func (_SCA *SCARaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _SCA.Contract.SCACaller.contract.Call(opts, result, method, params...) -} - -func (_SCA *SCARaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _SCA.Contract.SCATransactor.contract.Transfer(opts) -} - -func (_SCA *SCARaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _SCA.Contract.SCATransactor.contract.Transact(opts, method, params...) -} - -func (_SCA *SCACallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _SCA.Contract.contract.Call(opts, result, method, params...) -} - -func (_SCA *SCATransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _SCA.Contract.contract.Transfer(opts) -} - -func (_SCA *SCATransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _SCA.Contract.contract.Transact(opts, method, params...) -} - -func (_SCA *SCACaller) IEntryPoint(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _SCA.contract.Call(opts, &out, "i_entryPoint") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -func (_SCA *SCASession) IEntryPoint() (common.Address, error) { - return _SCA.Contract.IEntryPoint(&_SCA.CallOpts) -} - -func (_SCA *SCACallerSession) IEntryPoint() (common.Address, error) { - return _SCA.Contract.IEntryPoint(&_SCA.CallOpts) -} - -func (_SCA *SCACaller) IOwner(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _SCA.contract.Call(opts, &out, "i_owner") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -func (_SCA *SCASession) IOwner() (common.Address, error) { - return _SCA.Contract.IOwner(&_SCA.CallOpts) -} - -func (_SCA *SCACallerSession) IOwner() (common.Address, error) { - return _SCA.Contract.IOwner(&_SCA.CallOpts) -} - -func (_SCA *SCACaller) SNonce(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _SCA.contract.Call(opts, &out, "s_nonce") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_SCA *SCASession) SNonce() (*big.Int, error) { - return _SCA.Contract.SNonce(&_SCA.CallOpts) -} - -func (_SCA *SCACallerSession) SNonce() (*big.Int, error) { - return _SCA.Contract.SNonce(&_SCA.CallOpts) -} - -func (_SCA *SCATransactor) ExecuteTransactionFromEntryPoint(opts *bind.TransactOpts, to common.Address, value *big.Int, deadline *big.Int, data []byte) (*types.Transaction, error) { - return _SCA.contract.Transact(opts, "executeTransactionFromEntryPoint", to, value, deadline, data) -} - -func (_SCA *SCASession) ExecuteTransactionFromEntryPoint(to common.Address, value *big.Int, deadline *big.Int, data []byte) (*types.Transaction, error) { - return _SCA.Contract.ExecuteTransactionFromEntryPoint(&_SCA.TransactOpts, to, value, deadline, data) -} - -func (_SCA *SCATransactorSession) ExecuteTransactionFromEntryPoint(to common.Address, value *big.Int, deadline *big.Int, data []byte) (*types.Transaction, error) { - return _SCA.Contract.ExecuteTransactionFromEntryPoint(&_SCA.TransactOpts, to, value, deadline, data) -} - -func (_SCA *SCATransactor) ValidateUserOp(opts *bind.TransactOpts, userOp UserOperation, userOpHash [32]byte, arg2 *big.Int) (*types.Transaction, error) { - return _SCA.contract.Transact(opts, "validateUserOp", userOp, userOpHash, arg2) -} - -func (_SCA *SCASession) ValidateUserOp(userOp UserOperation, userOpHash [32]byte, arg2 *big.Int) (*types.Transaction, error) { - return _SCA.Contract.ValidateUserOp(&_SCA.TransactOpts, userOp, userOpHash, arg2) -} - -func (_SCA *SCATransactorSession) ValidateUserOp(userOp UserOperation, userOpHash [32]byte, arg2 *big.Int) (*types.Transaction, error) { - return _SCA.Contract.ValidateUserOp(&_SCA.TransactOpts, userOp, userOpHash, arg2) -} - -func (_SCA *SCA) Address() common.Address { - return _SCA.address -} - -type SCAInterface interface { - IEntryPoint(opts *bind.CallOpts) (common.Address, error) - - IOwner(opts *bind.CallOpts) (common.Address, error) - - SNonce(opts *bind.CallOpts) (*big.Int, error) - - ExecuteTransactionFromEntryPoint(opts *bind.TransactOpts, to common.Address, value *big.Int, deadline *big.Int, data []byte) (*types.Transaction, error) - - ValidateUserOp(opts *bind.TransactOpts, userOp UserOperation, userOpHash [32]byte, arg2 *big.Int) (*types.Transaction, error) - - Address() common.Address -} diff --git a/core/gethwrappers/transmission/generated/smart_contract_account_factory/smart_contract_account_factory.go b/core/gethwrappers/transmission/generated/smart_contract_account_factory/smart_contract_account_factory.go deleted file mode 100644 index aa9205641c5..00000000000 --- a/core/gethwrappers/transmission/generated/smart_contract_account_factory/smart_contract_account_factory.go +++ /dev/null @@ -1,333 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package smart_contract_account_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 SmartContractAccountFactoryMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"DeploymentFailed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"scaAddress\",\"type\":\"address\"}],\"name\":\"ContractCreated\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"abiEncodedOwnerAddress\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"}],\"name\":\"deploySmartContractAccount\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"scaAddress\",\"type\":\"address\"}],\"stateMutability\":\"payable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5061021e806100206000396000f3fe60806040526004361061001e5760003560e01c80630af4926f14610023575b600080fd5b610036610031366004610138565b61005f565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6000828251836020016000f5905073ffffffffffffffffffffffffffffffffffffffff81166100ba576040517f3011642500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405173ffffffffffffffffffffffffffffffffffffffff821681527fcf78cf0d6f3d8371e1075c69c492ab4ec5d8cf23a1a239b6a51a1d00be7ca3129060200160405180910390a192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806040838503121561014b57600080fd5b82359150602083013567ffffffffffffffff8082111561016a57600080fd5b818501915085601f83011261017e57600080fd5b81358181111561019057610190610109565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156101d6576101d6610109565b816040528281528860208487010111156101ef57600080fd5b826020860160208301376000602084830101528095505050505050925092905056fea164736f6c6343000813000a", -} - -var SmartContractAccountFactoryABI = SmartContractAccountFactoryMetaData.ABI - -var SmartContractAccountFactoryBin = SmartContractAccountFactoryMetaData.Bin - -func DeploySmartContractAccountFactory(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *SmartContractAccountFactory, error) { - parsed, err := SmartContractAccountFactoryMetaData.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(SmartContractAccountFactoryBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &SmartContractAccountFactory{address: address, abi: *parsed, SmartContractAccountFactoryCaller: SmartContractAccountFactoryCaller{contract: contract}, SmartContractAccountFactoryTransactor: SmartContractAccountFactoryTransactor{contract: contract}, SmartContractAccountFactoryFilterer: SmartContractAccountFactoryFilterer{contract: contract}}, nil -} - -type SmartContractAccountFactory struct { - address common.Address - abi abi.ABI - SmartContractAccountFactoryCaller - SmartContractAccountFactoryTransactor - SmartContractAccountFactoryFilterer -} - -type SmartContractAccountFactoryCaller struct { - contract *bind.BoundContract -} - -type SmartContractAccountFactoryTransactor struct { - contract *bind.BoundContract -} - -type SmartContractAccountFactoryFilterer struct { - contract *bind.BoundContract -} - -type SmartContractAccountFactorySession struct { - Contract *SmartContractAccountFactory - CallOpts bind.CallOpts - TransactOpts bind.TransactOpts -} - -type SmartContractAccountFactoryCallerSession struct { - Contract *SmartContractAccountFactoryCaller - CallOpts bind.CallOpts -} - -type SmartContractAccountFactoryTransactorSession struct { - Contract *SmartContractAccountFactoryTransactor - TransactOpts bind.TransactOpts -} - -type SmartContractAccountFactoryRaw struct { - Contract *SmartContractAccountFactory -} - -type SmartContractAccountFactoryCallerRaw struct { - Contract *SmartContractAccountFactoryCaller -} - -type SmartContractAccountFactoryTransactorRaw struct { - Contract *SmartContractAccountFactoryTransactor -} - -func NewSmartContractAccountFactory(address common.Address, backend bind.ContractBackend) (*SmartContractAccountFactory, error) { - abi, err := abi.JSON(strings.NewReader(SmartContractAccountFactoryABI)) - if err != nil { - return nil, err - } - contract, err := bindSmartContractAccountFactory(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &SmartContractAccountFactory{address: address, abi: abi, SmartContractAccountFactoryCaller: SmartContractAccountFactoryCaller{contract: contract}, SmartContractAccountFactoryTransactor: SmartContractAccountFactoryTransactor{contract: contract}, SmartContractAccountFactoryFilterer: SmartContractAccountFactoryFilterer{contract: contract}}, nil -} - -func NewSmartContractAccountFactoryCaller(address common.Address, caller bind.ContractCaller) (*SmartContractAccountFactoryCaller, error) { - contract, err := bindSmartContractAccountFactory(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &SmartContractAccountFactoryCaller{contract: contract}, nil -} - -func NewSmartContractAccountFactoryTransactor(address common.Address, transactor bind.ContractTransactor) (*SmartContractAccountFactoryTransactor, error) { - contract, err := bindSmartContractAccountFactory(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &SmartContractAccountFactoryTransactor{contract: contract}, nil -} - -func NewSmartContractAccountFactoryFilterer(address common.Address, filterer bind.ContractFilterer) (*SmartContractAccountFactoryFilterer, error) { - contract, err := bindSmartContractAccountFactory(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &SmartContractAccountFactoryFilterer{contract: contract}, nil -} - -func bindSmartContractAccountFactory(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := SmartContractAccountFactoryMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -func (_SmartContractAccountFactory *SmartContractAccountFactoryRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _SmartContractAccountFactory.Contract.SmartContractAccountFactoryCaller.contract.Call(opts, result, method, params...) -} - -func (_SmartContractAccountFactory *SmartContractAccountFactoryRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _SmartContractAccountFactory.Contract.SmartContractAccountFactoryTransactor.contract.Transfer(opts) -} - -func (_SmartContractAccountFactory *SmartContractAccountFactoryRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _SmartContractAccountFactory.Contract.SmartContractAccountFactoryTransactor.contract.Transact(opts, method, params...) -} - -func (_SmartContractAccountFactory *SmartContractAccountFactoryCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _SmartContractAccountFactory.Contract.contract.Call(opts, result, method, params...) -} - -func (_SmartContractAccountFactory *SmartContractAccountFactoryTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _SmartContractAccountFactory.Contract.contract.Transfer(opts) -} - -func (_SmartContractAccountFactory *SmartContractAccountFactoryTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _SmartContractAccountFactory.Contract.contract.Transact(opts, method, params...) -} - -func (_SmartContractAccountFactory *SmartContractAccountFactoryTransactor) DeploySmartContractAccount(opts *bind.TransactOpts, abiEncodedOwnerAddress [32]byte, initCode []byte) (*types.Transaction, error) { - return _SmartContractAccountFactory.contract.Transact(opts, "deploySmartContractAccount", abiEncodedOwnerAddress, initCode) -} - -func (_SmartContractAccountFactory *SmartContractAccountFactorySession) DeploySmartContractAccount(abiEncodedOwnerAddress [32]byte, initCode []byte) (*types.Transaction, error) { - return _SmartContractAccountFactory.Contract.DeploySmartContractAccount(&_SmartContractAccountFactory.TransactOpts, abiEncodedOwnerAddress, initCode) -} - -func (_SmartContractAccountFactory *SmartContractAccountFactoryTransactorSession) DeploySmartContractAccount(abiEncodedOwnerAddress [32]byte, initCode []byte) (*types.Transaction, error) { - return _SmartContractAccountFactory.Contract.DeploySmartContractAccount(&_SmartContractAccountFactory.TransactOpts, abiEncodedOwnerAddress, initCode) -} - -type SmartContractAccountFactoryContractCreatedIterator struct { - Event *SmartContractAccountFactoryContractCreated - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *SmartContractAccountFactoryContractCreatedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(SmartContractAccountFactoryContractCreated) - 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(SmartContractAccountFactoryContractCreated) - 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 *SmartContractAccountFactoryContractCreatedIterator) Error() error { - return it.fail -} - -func (it *SmartContractAccountFactoryContractCreatedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type SmartContractAccountFactoryContractCreated struct { - ScaAddress common.Address - Raw types.Log -} - -func (_SmartContractAccountFactory *SmartContractAccountFactoryFilterer) FilterContractCreated(opts *bind.FilterOpts) (*SmartContractAccountFactoryContractCreatedIterator, error) { - - logs, sub, err := _SmartContractAccountFactory.contract.FilterLogs(opts, "ContractCreated") - if err != nil { - return nil, err - } - return &SmartContractAccountFactoryContractCreatedIterator{contract: _SmartContractAccountFactory.contract, event: "ContractCreated", logs: logs, sub: sub}, nil -} - -func (_SmartContractAccountFactory *SmartContractAccountFactoryFilterer) WatchContractCreated(opts *bind.WatchOpts, sink chan<- *SmartContractAccountFactoryContractCreated) (event.Subscription, error) { - - logs, sub, err := _SmartContractAccountFactory.contract.WatchLogs(opts, "ContractCreated") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(SmartContractAccountFactoryContractCreated) - if err := _SmartContractAccountFactory.contract.UnpackLog(event, "ContractCreated", 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 (_SmartContractAccountFactory *SmartContractAccountFactoryFilterer) ParseContractCreated(log types.Log) (*SmartContractAccountFactoryContractCreated, error) { - event := new(SmartContractAccountFactoryContractCreated) - if err := _SmartContractAccountFactory.contract.UnpackLog(event, "ContractCreated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -func (_SmartContractAccountFactory *SmartContractAccountFactory) ParseLog(log types.Log) (generated.AbigenLog, error) { - switch log.Topics[0] { - case _SmartContractAccountFactory.abi.Events["ContractCreated"].ID: - return _SmartContractAccountFactory.ParseContractCreated(log) - - default: - return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) - } -} - -func (SmartContractAccountFactoryContractCreated) Topic() common.Hash { - return common.HexToHash("0xcf78cf0d6f3d8371e1075c69c492ab4ec5d8cf23a1a239b6a51a1d00be7ca312") -} - -func (_SmartContractAccountFactory *SmartContractAccountFactory) Address() common.Address { - return _SmartContractAccountFactory.address -} - -type SmartContractAccountFactoryInterface interface { - DeploySmartContractAccount(opts *bind.TransactOpts, abiEncodedOwnerAddress [32]byte, initCode []byte) (*types.Transaction, error) - - FilterContractCreated(opts *bind.FilterOpts) (*SmartContractAccountFactoryContractCreatedIterator, error) - - WatchContractCreated(opts *bind.WatchOpts, sink chan<- *SmartContractAccountFactoryContractCreated) (event.Subscription, error) - - ParseContractCreated(log types.Log) (*SmartContractAccountFactoryContractCreated, error) - - ParseLog(log types.Log) (generated.AbigenLog, error) - - Address() common.Address -} diff --git a/core/gethwrappers/transmission/generated/smart_contract_account_helper/smart_contract_account_helper.go b/core/gethwrappers/transmission/generated/smart_contract_account_helper/smart_contract_account_helper.go deleted file mode 100644 index 36e63e3683e..00000000000 --- a/core/gethwrappers/transmission/generated/smart_contract_account_helper/smart_contract_account_helper.go +++ /dev/null @@ -1,322 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package smart_contract_account_helper - -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 SmartContractAccountHelperMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"entryPoint\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"factory\",\"type\":\"address\"}],\"name\":\"calculateSmartContractAccountAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"topupThreshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"topupAmount\",\"type\":\"uint256\"}],\"name\":\"getAbiEncodedDirectRequestData\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"endContract\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"getFullEndTxEncoding\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"encoding\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"scaAddress\",\"type\":\"address\"}],\"name\":\"getFullHashForSigning\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"entryPoint\",\"type\":\"address\"}],\"name\":\"getInitCode\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"entryPoint\",\"type\":\"address\"}],\"name\":\"getSCAInitCodeWithConstructor\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x61161361003a600b82828239805160001a60731461002d57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361061007c5760003560e01c8063e0237bef1161005a578063e0237bef14610134578063e464b3631461016c578063fc59bac31461017f57600080fd5b80632c86cb35146100815780634b770f561461010057806382311e3314610113575b600080fd5b6100ea61008f36600461076d565b604080516060808201835273ffffffffffffffffffffffffffffffffffffffff959095168082526020808301958652918301938452825191820152925183820152905182840152805180830390930183526080909101905290565b6040516100f7919061080e565b60405180910390f35b6100ea61010e366004610821565b610192565b610126610121366004610864565b610336565b6040519081526020016100f7565b610147610142366004610821565b610456565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100f7565b6100ea61017a366004610890565b6105e1565b6100ea61018d3660046108e9565b61069f565b6040516060907fffffffffffffffffffffffffffffffffffffffff00000000000000000000000084831b16906000906101cd60208201610737565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f90910116604081815273ffffffffffffffffffffffffffffffffffffffff8881166020840152871690820152606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905261026292916020016109dc565b60405160208183030381529060405290508560601b630af4926f60e01b8383604051602401610292929190610a0b565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909516949094179093525161031c939201610a2c565b604051602081830303815290604052925050509392505050565b600061044d8383604080517f4750045d47fce615521b32cee713ff8db50147e98aec5ca94926b52651ca3fa060208083019190915281830194909452815180820383018152606080830184528151918601919091207f190000000000000000000000000000000000000000000000000000000000000060808401527f010000000000000000000000000000000000000000000000000000000000000060818401527f1c7d3b72b37a35523e273aaadd7b4cd66f618bb81429ab053412d51f50ccea6160828401524660a284015293901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660c282015260d6808201939093528151808203909301835260f6019052805191012090565b90505b92915050565b6040516000907fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1690829061049260208201610737565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f90910116604081815273ffffffffffffffffffffffffffffffffffffffff8981166020840152881690820152606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905261052792916020016109dc565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815282825280516020918201207fff000000000000000000000000000000000000000000000000000000000000008285015260609790971b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166021840152603583019490945260558083019690965280518083039096018652607590910190525082519201919091209392505050565b6060604051806020016105f390610737565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f90910116604081815273ffffffffffffffffffffffffffffffffffffffff8681166020840152851690820152606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905261068892916020016109dc565b604051602081830303815290604052905092915050565b60607f89553be40000000000000000000000000000000000000000000000000000000085856106ce8642610a74565b856040516020016106e29493929190610aae565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905261071e9291602001610af3565b6040516020818303038152906040529050949350505050565b610acb80610b3c83390190565b803573ffffffffffffffffffffffffffffffffffffffff8116811461076857600080fd5b919050565b60008060006060848603121561078257600080fd5b61078b84610744565b95602085013595506040909401359392505050565b60005b838110156107bb5781810151838201526020016107a3565b50506000910152565b600081518084526107dc8160208601602086016107a0565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061044d60208301846107c4565b60008060006060848603121561083657600080fd5b61083f84610744565b925061084d60208501610744565b915061085b60408501610744565b90509250925092565b6000806040838503121561087757600080fd5b8235915061088760208401610744565b90509250929050565b600080604083850312156108a357600080fd5b6108ac83610744565b915061088760208401610744565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600080608085870312156108ff57600080fd5b61090885610744565b93506020850135925060408501359150606085013567ffffffffffffffff8082111561093357600080fd5b818701915087601f83011261094757600080fd5b813581811115610959576109596108ba565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561099f5761099f6108ba565b816040528281528a60208487010111156109b857600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b600083516109ee8184602088016107a0565b835190830190610a028183602088016107a0565b01949350505050565b828152604060208201526000610a2460408301846107c4565b949350505050565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008316815260008251610a668160148501602087016107a0565b919091016014019392505050565b80820180821115610450577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff85168152836020820152826040820152608060608201526000610ae960808301846107c4565b9695505050505050565b7fffffffff000000000000000000000000000000000000000000000000000000008316815260008251610b2d8160048501602087016107a0565b91909101600401939250505056fe60c060405234801561001057600080fd5b50604051610acb380380610acb83398101604081905261002f91610062565b6001600160a01b039182166080521660a052610095565b80516001600160a01b038116811461005d57600080fd5b919050565b6000806040838503121561007557600080fd5b61007e83610046565b915061008c60208401610046565b90509250929050565b60805160a051610a046100c760003960008181607101526102b801526000818161010101526101e30152610a046000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c80637eccf63e116100505780637eccf63e146100de57806389553be4146100e7578063dba6335f146100fc57600080fd5b8063140fcfb11461006c5780633a871cdd146100bd575b600080fd5b6100937f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100d06100cb366004610646565b610123565b6040519081526020016100b4565b6100d060005481565b6100fa6100f53660046106da565b6102a0565b005b6100937f000000000000000000000000000000000000000000000000000000000000000081565b60008054846020013514610179576000546040517f7ba633940000000000000000000000000000000000000000000000000000000081526004810191909152602085013560248201526044015b60405180910390fd5b60006101858430610439565b90506000610197610140870187610777565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016915061021190508284610550565b73ffffffffffffffffffffffffffffffffffffffff161461024257610239600160008061060e565b92505050610299565b60008054908061025183610812565b90915550600090506102666060880188610777565b61027491600490829061084a565b81019061028191906108a3565b5092505050610293600082600061060e565b93505050505b9392505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610311576040517f4a0bfec1000000000000000000000000000000000000000000000000000000008152336004820152602401610170565b65ffffffffffff83161580159061032f57508265ffffffffffff1642115b15610376576040517f300249d700000000000000000000000000000000000000000000000000000000815265ffffffffffff84166004820152426024820152604401610170565b6000808673ffffffffffffffffffffffffffffffffffffffff168685856040516103a192919061099f565b60006040518083038185875af1925050503d80600081146103de576040519150601f19603f3d011682016040523d82523d6000602084013e6103e3565b606091505b509150915081610430578051600003610428576040517f20e9b5d200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b50505050505050565b604080517f4750045d47fce615521b32cee713ff8db50147e98aec5ca94926b52651ca3fa0602080830191909152818301859052825180830384018152606080840185528151918301919091207f190000000000000000000000000000000000000000000000000000000000000060808501527f010000000000000000000000000000000000000000000000000000000000000060818501527f1c7d3b72b37a35523e273aaadd7b4cd66f618bb81429ab053412d51f50ccea6160828501524660a28501529085901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660c284015260d6808401919091528351808403909101815260f690920190925280519101205b92915050565b602082015160408084015184516000939284918791908110610574576105746109af565b016020015160f81c905060018561058c83601b6109de565b6040805160008152602081018083529390935260ff90911690820152606081018590526080810184905260a0016020604051602081039080840390855afa1580156105db573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00151979650505050505050565b600060d08265ffffffffffff16901b60a08465ffffffffffff16901b85610636576000610639565b60015b60ff161717949350505050565b60008060006060848603121561065b57600080fd5b833567ffffffffffffffff81111561067257600080fd5b8401610160818703121561068557600080fd5b95602085013595506040909401359392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146106bc57600080fd5b50565b803565ffffffffffff811681146106d557600080fd5b919050565b6000806000806000608086880312156106f257600080fd5b85356106fd8161069a565b945060208601359350610712604087016106bf565b9250606086013567ffffffffffffffff8082111561072f57600080fd5b818801915088601f83011261074357600080fd5b81358181111561075257600080fd5b89602082850101111561076457600080fd5b9699959850939650602001949392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126107ac57600080fd5b83018035915067ffffffffffffffff8211156107c757600080fd5b6020019150368190038213156107dc57600080fd5b9250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610843576108436107e3565b5060010190565b6000808585111561085a57600080fd5b8386111561086757600080fd5b5050820193919092039150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600080608085870312156108b957600080fd5b84356108c48161069a565b9350602085013592506108d9604086016106bf565b9150606085013567ffffffffffffffff808211156108f657600080fd5b818701915087601f83011261090a57600080fd5b81358181111561091c5761091c610874565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561096257610962610874565b816040528281528a602084870101111561097b57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60ff818116838216019081111561054a5761054a6107e356fea164736f6c6343000813000aa164736f6c6343000813000a", -} - -var SmartContractAccountHelperABI = SmartContractAccountHelperMetaData.ABI - -var SmartContractAccountHelperBin = SmartContractAccountHelperMetaData.Bin - -func DeploySmartContractAccountHelper(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *SmartContractAccountHelper, error) { - parsed, err := SmartContractAccountHelperMetaData.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(SmartContractAccountHelperBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &SmartContractAccountHelper{address: address, abi: *parsed, SmartContractAccountHelperCaller: SmartContractAccountHelperCaller{contract: contract}, SmartContractAccountHelperTransactor: SmartContractAccountHelperTransactor{contract: contract}, SmartContractAccountHelperFilterer: SmartContractAccountHelperFilterer{contract: contract}}, nil -} - -type SmartContractAccountHelper struct { - address common.Address - abi abi.ABI - SmartContractAccountHelperCaller - SmartContractAccountHelperTransactor - SmartContractAccountHelperFilterer -} - -type SmartContractAccountHelperCaller struct { - contract *bind.BoundContract -} - -type SmartContractAccountHelperTransactor struct { - contract *bind.BoundContract -} - -type SmartContractAccountHelperFilterer struct { - contract *bind.BoundContract -} - -type SmartContractAccountHelperSession struct { - Contract *SmartContractAccountHelper - CallOpts bind.CallOpts - TransactOpts bind.TransactOpts -} - -type SmartContractAccountHelperCallerSession struct { - Contract *SmartContractAccountHelperCaller - CallOpts bind.CallOpts -} - -type SmartContractAccountHelperTransactorSession struct { - Contract *SmartContractAccountHelperTransactor - TransactOpts bind.TransactOpts -} - -type SmartContractAccountHelperRaw struct { - Contract *SmartContractAccountHelper -} - -type SmartContractAccountHelperCallerRaw struct { - Contract *SmartContractAccountHelperCaller -} - -type SmartContractAccountHelperTransactorRaw struct { - Contract *SmartContractAccountHelperTransactor -} - -func NewSmartContractAccountHelper(address common.Address, backend bind.ContractBackend) (*SmartContractAccountHelper, error) { - abi, err := abi.JSON(strings.NewReader(SmartContractAccountHelperABI)) - if err != nil { - return nil, err - } - contract, err := bindSmartContractAccountHelper(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &SmartContractAccountHelper{address: address, abi: abi, SmartContractAccountHelperCaller: SmartContractAccountHelperCaller{contract: contract}, SmartContractAccountHelperTransactor: SmartContractAccountHelperTransactor{contract: contract}, SmartContractAccountHelperFilterer: SmartContractAccountHelperFilterer{contract: contract}}, nil -} - -func NewSmartContractAccountHelperCaller(address common.Address, caller bind.ContractCaller) (*SmartContractAccountHelperCaller, error) { - contract, err := bindSmartContractAccountHelper(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &SmartContractAccountHelperCaller{contract: contract}, nil -} - -func NewSmartContractAccountHelperTransactor(address common.Address, transactor bind.ContractTransactor) (*SmartContractAccountHelperTransactor, error) { - contract, err := bindSmartContractAccountHelper(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &SmartContractAccountHelperTransactor{contract: contract}, nil -} - -func NewSmartContractAccountHelperFilterer(address common.Address, filterer bind.ContractFilterer) (*SmartContractAccountHelperFilterer, error) { - contract, err := bindSmartContractAccountHelper(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &SmartContractAccountHelperFilterer{contract: contract}, nil -} - -func bindSmartContractAccountHelper(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := SmartContractAccountHelperMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -func (_SmartContractAccountHelper *SmartContractAccountHelperRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _SmartContractAccountHelper.Contract.SmartContractAccountHelperCaller.contract.Call(opts, result, method, params...) -} - -func (_SmartContractAccountHelper *SmartContractAccountHelperRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _SmartContractAccountHelper.Contract.SmartContractAccountHelperTransactor.contract.Transfer(opts) -} - -func (_SmartContractAccountHelper *SmartContractAccountHelperRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _SmartContractAccountHelper.Contract.SmartContractAccountHelperTransactor.contract.Transact(opts, method, params...) -} - -func (_SmartContractAccountHelper *SmartContractAccountHelperCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _SmartContractAccountHelper.Contract.contract.Call(opts, result, method, params...) -} - -func (_SmartContractAccountHelper *SmartContractAccountHelperTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _SmartContractAccountHelper.Contract.contract.Transfer(opts) -} - -func (_SmartContractAccountHelper *SmartContractAccountHelperTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _SmartContractAccountHelper.Contract.contract.Transact(opts, method, params...) -} - -func (_SmartContractAccountHelper *SmartContractAccountHelperCaller) CalculateSmartContractAccountAddress(opts *bind.CallOpts, owner common.Address, entryPoint common.Address, factory common.Address) (common.Address, error) { - var out []interface{} - err := _SmartContractAccountHelper.contract.Call(opts, &out, "calculateSmartContractAccountAddress", owner, entryPoint, factory) - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -func (_SmartContractAccountHelper *SmartContractAccountHelperSession) CalculateSmartContractAccountAddress(owner common.Address, entryPoint common.Address, factory common.Address) (common.Address, error) { - return _SmartContractAccountHelper.Contract.CalculateSmartContractAccountAddress(&_SmartContractAccountHelper.CallOpts, owner, entryPoint, factory) -} - -func (_SmartContractAccountHelper *SmartContractAccountHelperCallerSession) CalculateSmartContractAccountAddress(owner common.Address, entryPoint common.Address, factory common.Address) (common.Address, error) { - return _SmartContractAccountHelper.Contract.CalculateSmartContractAccountAddress(&_SmartContractAccountHelper.CallOpts, owner, entryPoint, factory) -} - -func (_SmartContractAccountHelper *SmartContractAccountHelperCaller) GetAbiEncodedDirectRequestData(opts *bind.CallOpts, recipient common.Address, topupThreshold *big.Int, topupAmount *big.Int) ([]byte, error) { - var out []interface{} - err := _SmartContractAccountHelper.contract.Call(opts, &out, "getAbiEncodedDirectRequestData", recipient, topupThreshold, topupAmount) - - if err != nil { - return *new([]byte), err - } - - out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) - - return out0, err - -} - -func (_SmartContractAccountHelper *SmartContractAccountHelperSession) GetAbiEncodedDirectRequestData(recipient common.Address, topupThreshold *big.Int, topupAmount *big.Int) ([]byte, error) { - return _SmartContractAccountHelper.Contract.GetAbiEncodedDirectRequestData(&_SmartContractAccountHelper.CallOpts, recipient, topupThreshold, topupAmount) -} - -func (_SmartContractAccountHelper *SmartContractAccountHelperCallerSession) GetAbiEncodedDirectRequestData(recipient common.Address, topupThreshold *big.Int, topupAmount *big.Int) ([]byte, error) { - return _SmartContractAccountHelper.Contract.GetAbiEncodedDirectRequestData(&_SmartContractAccountHelper.CallOpts, recipient, topupThreshold, topupAmount) -} - -func (_SmartContractAccountHelper *SmartContractAccountHelperCaller) GetFullEndTxEncoding(opts *bind.CallOpts, endContract common.Address, value *big.Int, deadline *big.Int, data []byte) ([]byte, error) { - var out []interface{} - err := _SmartContractAccountHelper.contract.Call(opts, &out, "getFullEndTxEncoding", endContract, value, deadline, data) - - if err != nil { - return *new([]byte), err - } - - out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) - - return out0, err - -} - -func (_SmartContractAccountHelper *SmartContractAccountHelperSession) GetFullEndTxEncoding(endContract common.Address, value *big.Int, deadline *big.Int, data []byte) ([]byte, error) { - return _SmartContractAccountHelper.Contract.GetFullEndTxEncoding(&_SmartContractAccountHelper.CallOpts, endContract, value, deadline, data) -} - -func (_SmartContractAccountHelper *SmartContractAccountHelperCallerSession) GetFullEndTxEncoding(endContract common.Address, value *big.Int, deadline *big.Int, data []byte) ([]byte, error) { - return _SmartContractAccountHelper.Contract.GetFullEndTxEncoding(&_SmartContractAccountHelper.CallOpts, endContract, value, deadline, data) -} - -func (_SmartContractAccountHelper *SmartContractAccountHelperCaller) GetFullHashForSigning(opts *bind.CallOpts, userOpHash [32]byte, scaAddress common.Address) ([32]byte, error) { - var out []interface{} - err := _SmartContractAccountHelper.contract.Call(opts, &out, "getFullHashForSigning", userOpHash, scaAddress) - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -func (_SmartContractAccountHelper *SmartContractAccountHelperSession) GetFullHashForSigning(userOpHash [32]byte, scaAddress common.Address) ([32]byte, error) { - return _SmartContractAccountHelper.Contract.GetFullHashForSigning(&_SmartContractAccountHelper.CallOpts, userOpHash, scaAddress) -} - -func (_SmartContractAccountHelper *SmartContractAccountHelperCallerSession) GetFullHashForSigning(userOpHash [32]byte, scaAddress common.Address) ([32]byte, error) { - return _SmartContractAccountHelper.Contract.GetFullHashForSigning(&_SmartContractAccountHelper.CallOpts, userOpHash, scaAddress) -} - -func (_SmartContractAccountHelper *SmartContractAccountHelperCaller) GetInitCode(opts *bind.CallOpts, factory common.Address, owner common.Address, entryPoint common.Address) ([]byte, error) { - var out []interface{} - err := _SmartContractAccountHelper.contract.Call(opts, &out, "getInitCode", factory, owner, entryPoint) - - if err != nil { - return *new([]byte), err - } - - out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) - - return out0, err - -} - -func (_SmartContractAccountHelper *SmartContractAccountHelperSession) GetInitCode(factory common.Address, owner common.Address, entryPoint common.Address) ([]byte, error) { - return _SmartContractAccountHelper.Contract.GetInitCode(&_SmartContractAccountHelper.CallOpts, factory, owner, entryPoint) -} - -func (_SmartContractAccountHelper *SmartContractAccountHelperCallerSession) GetInitCode(factory common.Address, owner common.Address, entryPoint common.Address) ([]byte, error) { - return _SmartContractAccountHelper.Contract.GetInitCode(&_SmartContractAccountHelper.CallOpts, factory, owner, entryPoint) -} - -func (_SmartContractAccountHelper *SmartContractAccountHelperCaller) GetSCAInitCodeWithConstructor(opts *bind.CallOpts, owner common.Address, entryPoint common.Address) ([]byte, error) { - var out []interface{} - err := _SmartContractAccountHelper.contract.Call(opts, &out, "getSCAInitCodeWithConstructor", owner, entryPoint) - - if err != nil { - return *new([]byte), err - } - - out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) - - return out0, err - -} - -func (_SmartContractAccountHelper *SmartContractAccountHelperSession) GetSCAInitCodeWithConstructor(owner common.Address, entryPoint common.Address) ([]byte, error) { - return _SmartContractAccountHelper.Contract.GetSCAInitCodeWithConstructor(&_SmartContractAccountHelper.CallOpts, owner, entryPoint) -} - -func (_SmartContractAccountHelper *SmartContractAccountHelperCallerSession) GetSCAInitCodeWithConstructor(owner common.Address, entryPoint common.Address) ([]byte, error) { - return _SmartContractAccountHelper.Contract.GetSCAInitCodeWithConstructor(&_SmartContractAccountHelper.CallOpts, owner, entryPoint) -} - -func (_SmartContractAccountHelper *SmartContractAccountHelper) Address() common.Address { - return _SmartContractAccountHelper.address -} - -type SmartContractAccountHelperInterface interface { - CalculateSmartContractAccountAddress(opts *bind.CallOpts, owner common.Address, entryPoint common.Address, factory common.Address) (common.Address, error) - - GetAbiEncodedDirectRequestData(opts *bind.CallOpts, recipient common.Address, topupThreshold *big.Int, topupAmount *big.Int) ([]byte, error) - - GetFullEndTxEncoding(opts *bind.CallOpts, endContract common.Address, value *big.Int, deadline *big.Int, data []byte) ([]byte, error) - - GetFullHashForSigning(opts *bind.CallOpts, userOpHash [32]byte, scaAddress common.Address) ([32]byte, error) - - GetInitCode(opts *bind.CallOpts, factory common.Address, owner common.Address, entryPoint common.Address) ([]byte, error) - - GetSCAInitCodeWithConstructor(opts *bind.CallOpts, owner common.Address, entryPoint common.Address) ([]byte, error) - - Address() common.Address -} diff --git a/core/gethwrappers/transmission/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/transmission/generation/generated-wrapper-dependency-versions-do-not-edit.txt deleted file mode 100644 index 3ccf8656388..00000000000 --- a/core/gethwrappers/transmission/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ /dev/null @@ -1,9 +0,0 @@ -GETH_VERSION: 1.14.11 -entry_point: ../../../contracts/solc/v0.8.19/EntryPoint/EntryPoint.abi ../../../contracts/solc/v0.8.19/EntryPoint/EntryPoint.bin e43da0e61256471b317cab1c87f2425cecba9b81ac21633334f889bab2f0777d -greeter: ../../../contracts/solc/v0.8.15/Greeter.abi ../../../contracts/solc/v0.8.15/Greeter.bin 653dcba5c33a46292073939ce1e639372cf521c0ec2814d4c9f20c72f796f18c -greeter_wrapper: ../../../contracts/solc/v0.8.19/Greeter/Greeter.abi ../../../contracts/solc/v0.8.19/Greeter/Greeter.bin 7f6def58e337a53553a46cb7992cf2d75ec951014d79376fcb869a2b16b53f6d -paymaster_wrapper: ../../../contracts/solc/v0.8.19/Paymaster/Paymaster.abi ../../../contracts/solc/v0.8.19/Paymaster/Paymaster.bin dbdd1341cfa2d5c09730e0decc32339f62d1a4ea89835a51ff774226ddfbd04b -sca: ../../../contracts/solc/v0.8.15/SCA.abi ../../../contracts/solc/v0.8.15/SCA.bin ae0f860cdac87d4ac505edbd228bd3ea1108550453aba67aebcb61f09cf70d0b -sca_wrapper: ../../../contracts/solc/v0.8.19/SCA/SCA.abi ../../../contracts/solc/v0.8.19/SCA/SCA.bin 6ef817bdefad1b5e84f06e0bdc40848000ab00e1a38371435b793946f425a8e6 -smart_contract_account_factory: ../../../contracts/solc/v0.8.19/SmartContractAccountFactory/SmartContractAccountFactory.abi ../../../contracts/solc/v0.8.19/SmartContractAccountFactory/SmartContractAccountFactory.bin a357132e2782c462fa31ed80c270fe002e666a48ecfe407b71c278fc3a0d3679 -smart_contract_account_helper: ../../../contracts/solc/v0.8.19/SmartContractAccountHelper/SmartContractAccountHelper.abi ../../../contracts/solc/v0.8.19/SmartContractAccountHelper/SmartContractAccountHelper.bin a06aff23aded74d53bd342fdc32d80c3b474ff38223df27f3395e9fd90abd12a diff --git a/core/gethwrappers/transmission/go_generate.go b/core/gethwrappers/transmission/go_generate.go deleted file mode 100644 index b3f2b4b0eb9..00000000000 --- a/core/gethwrappers/transmission/go_generate.go +++ /dev/null @@ -1,11 +0,0 @@ -// Package gethwrappers provides tools for wrapping solidity contracts with -// golang packages, using abigen. -package gethwrappers - -// Transmission -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/Greeter/Greeter.abi ../../../contracts/solc/v0.8.19/Greeter/Greeter.bin Greeter greeter_wrapper -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/SmartContractAccountFactory/SmartContractAccountFactory.abi ../../../contracts/solc/v0.8.19/SmartContractAccountFactory/SmartContractAccountFactory.bin SmartContractAccountFactory smart_contract_account_factory -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/EntryPoint/EntryPoint.abi ../../../contracts/solc/v0.8.19/EntryPoint/EntryPoint.bin EntryPoint entry_point -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/SmartContractAccountHelper/SmartContractAccountHelper.abi ../../../contracts/solc/v0.8.19/SmartContractAccountHelper/SmartContractAccountHelper.bin SmartContractAccountHelper smart_contract_account_helper -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/SCA/SCA.abi ../../../contracts/solc/v0.8.19/SCA/SCA.bin SCA sca_wrapper -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/Paymaster/Paymaster.abi ../../../contracts/solc/v0.8.19/Paymaster/Paymaster.bin Paymaster paymaster_wrapper diff --git a/core/gethwrappers/workflow/generated/workflow_registry_wrapper/workflow_registry_wrapper.go b/core/gethwrappers/workflow/generated/workflow_registry_wrapper/workflow_registry_wrapper.go index a81d69c343e..ca75b4a82d9 100644 --- a/core/gethwrappers/workflow/generated/workflow_registry_wrapper/workflow_registry_wrapper.go +++ b/core/gethwrappers/workflow/generated/workflow_registry_wrapper/workflow_registry_wrapper.go @@ -42,8 +42,8 @@ type WorkflowRegistryWorkflowMetadata struct { } var WorkflowRegistryMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AddressNotAuthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotWorkflowOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"}],\"name\":\"DONNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidWorkflowID\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryLocked\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"providedLength\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"maxAllowedLength\",\"type\":\"uint8\"}],\"name\":\"URLTooLong\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WorkflowAlreadyInDesiredStatus\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WorkflowAlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WorkflowContentNotUpdated\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WorkflowDoesNotExist\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WorkflowIDAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WorkflowIDNotUpdated\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"providedLength\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"maxAllowedLength\",\"type\":\"uint8\"}],\"name\":\"WorkflowNameTooLong\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32[]\",\"name\":\"donIDs\",\"type\":\"uint32[]\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"AllowedDONsUpdatedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"addresses\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"AuthorizedAddressesUpdatedV1\",\"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\":\"lockedBy\",\"type\":\"address\"}],\"name\":\"RegistryLockedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"unlockedBy\",\"type\":\"address\"}],\"name\":\"RegistryUnlockedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"}],\"name\":\"WorkflowActivatedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"}],\"name\":\"WorkflowDeletedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"secretsURLHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"}],\"name\":\"WorkflowForceUpdateSecretsRequestedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"}],\"name\":\"WorkflowPausedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"enumWorkflowRegistry.WorkflowStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"name\":\"WorkflowRegisteredV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"oldWorkflowID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"newWorkflowID\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"name\":\"WorkflowUpdatedV1\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"workflowKey\",\"type\":\"bytes32\"}],\"name\":\"activateWorkflow\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"field\",\"type\":\"string\"}],\"name\":\"computeHashKey\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"workflowKey\",\"type\":\"bytes32\"}],\"name\":\"deleteWorkflow\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAllowedDONs\",\"outputs\":[{\"internalType\":\"uint32[]\",\"name\":\"allowedDONs\",\"type\":\"uint32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"authorizedAddresses\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"}],\"name\":\"getWorkflowMetadata\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"internalType\":\"enumWorkflowRegistry.WorkflowStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"internalType\":\"structWorkflowRegistry.WorkflowMetadata\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"limit\",\"type\":\"uint256\"}],\"name\":\"getWorkflowMetadataListByDON\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"internalType\":\"enumWorkflowRegistry.WorkflowStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"internalType\":\"structWorkflowRegistry.WorkflowMetadata[]\",\"name\":\"workflowMetadataList\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"limit\",\"type\":\"uint256\"}],\"name\":\"getWorkflowMetadataListByOwner\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"internalType\":\"enumWorkflowRegistry.WorkflowStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"internalType\":\"structWorkflowRegistry.WorkflowMetadata[]\",\"name\":\"workflowMetadataList\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isRegistryLocked\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lockRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"workflowKey\",\"type\":\"bytes32\"}],\"name\":\"pauseWorkflow\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"},{\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"internalType\":\"enumWorkflowRegistry.WorkflowStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"name\":\"registerWorkflow\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"name\":\"requestForceUpdateSecrets\",\"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\":[],\"name\":\"unlockRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"donIDs\",\"type\":\"uint32[]\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"updateAllowedDONs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"addresses\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"updateAuthorizedAddresses\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"workflowKey\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"newWorkflowID\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"name\":\"updateWorkflow\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6080806040523461004a57331561003b57600180546001600160a01b03191633179055600b805460ff191690556040516134e290816100508239f35b639b15e16f60e01b8152600490fd5b600080fdfe6080604052600436101561001257600080fd5b60003560e01c806308e7f63a1461210e578063181f5a771461207f5780632303348a14611f425780632b596f6d14611eb45780633ccd14ff14611572578063695e1340146113965780636f351771146112bd578063724c13dd146111c65780637497066b146110ab57806379ba509714610fd55780637ec0846d14610f4a5780638da5cb5b14610ef85780639f4cb53414610ed7578063b87a019414610e81578063d4b89c7414610698578063db800092146105fd578063e3dce080146104d6578063e690f33214610362578063f2fde38b14610284578063f794bdeb146101495763f99ecb6b1461010357600080fd5b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457602060ff600b54166040519015158152f35b600080fd5b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610144576007805461018581612488565b610192604051918261230f565b81815261019e82612488565b916020937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060208401940136853760005b82811061023257505050906040519283926020840190602085525180915260408401929160005b82811061020557505050500390f35b835173ffffffffffffffffffffffffffffffffffffffff16855286955093810193928101926001016101f6565b6001908260005273ffffffffffffffffffffffffffffffffffffffff817fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68801541661027d82876125ba565b52016101cf565b346101445760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610144576102bb6123f6565b6102c3612c53565b73ffffffffffffffffffffffffffffffffffffffff8091169033821461033857817fffffffffffffffffffffffff00000000000000000000000000000000000000006000541617600055600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b60046040517fdad89dca000000000000000000000000000000000000000000000000000000008152fd5b346101445760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760ff600b54166104ac576103a760043533612eb0565b600181019081549160ff8360c01c16600281101561047d576001146104535778010000000000000000000000000000000000000000000000007fffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffff841617905580547f6a0ed88e9cf3cb493ab4028fcb1dc7d18f0130fcdfba096edde0aadbfbf5e99f63ffffffff604051946020865260a01c16938061044e3395600260208401910161265c565b0390a4005b60046040517f6f861db1000000000000000000000000000000000000000000000000000000008152fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60046040517f78a4e7d9000000000000000000000000000000000000000000000000000000008152fd5b34610144576104e43661237e565b916104ed612c53565b60ff600b54166104ac5760005b828110610589575060405191806040840160408552526060830191906000905b8082106105515785151560208601527f509460cccbb176edde6cac28895a4415a24961b8f3a0bd2617b9bb7b4e166c9b85850386a1005b90919283359073ffffffffffffffffffffffffffffffffffffffff82168092036101445760019181526020809101940192019061051a565b60019084156105cb576105c373ffffffffffffffffffffffffffffffffffffffff6105bd6105b8848888612af3565b612c32565b1661308b565b505b016104fa565b6105f773ffffffffffffffffffffffffffffffffffffffff6105f16105b8848888612af3565b166132bc565b506105c5565b346101445761061d61060e36612419565b916106176124a0565b50612b14565b6000526004602052604060002073ffffffffffffffffffffffffffffffffffffffff6001820154161561066e5761065661066a91612710565b6040519182916020835260208301906121cc565b0390f35b60046040517f871e01b2000000000000000000000000000000000000000000000000000000008152fd5b346101445760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760443567ffffffffffffffff8111610144576106e7903690600401612350565b9060643567ffffffffffffffff811161014457610708903690600401612350565b9160843567ffffffffffffffff811161014457610729903690600401612350565b60ff600b94929454166104ac57610741818688612d48565b61074d60043533612eb0565b9163ffffffff600184015460a01c16956107673388612c9e565b8354946024358614610e57576107a26040516107918161078a8160038b0161265c565b038261230f565b61079c368c856128c4565b90612f1f565b6107c46040516107b98161078a8160048c0161265c565b61079c3686886128c4565b6107e66040516107db8161078a8160058d0161265c565b61079c36898d6128c4565b918080610e50575b80610e49575b610e1f57610803602435612e08565b88600052600660205260406000207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008154169055602435885515610cca575b15610b79575b156108cc575b926108bc7f41161473ce2ed633d9f902aab9702d16a5531da27ec84e1939abeffe54ad7353959361044e936108ae6108a0978d604051998a996024358b5260a060208c0152600260a08c01910161265c565b9189830360408b0152612987565b918683036060880152612987565b9083820360808501523397612987565b6108d96005860154612609565b610b12575b67ffffffffffffffff8411610ae357610907846108fe6005880154612609565b60058801612940565b6000601f85116001146109e3579284926108ae6108bc938a9b9c61098b876108a09b9a61044e9a7f41161473ce2ed633d9f902aab9702d16a5531da27ec84e1939abeffe54ad73539e9f6000926109d8575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b60058a01555b8c87806109ae575b50509c9b9a995093505092949550925061084e565b6109b89133612b14565b60005260056020526109d060043560406000206130dd565b508c87610999565b013590508f80610959565b9860058601600052602060002060005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe087168110610acb5750926108ae6108bc9361044e969388968c7f41161473ce2ed633d9f902aab9702d16a5531da27ec84e1939abeffe54ad73539c9d9e9f897fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06108a09e9d1610610a93575b505050600187811b0160058a0155610991565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88b60031b161c199101351690558e8d81610a80565b898c0135825560209b8c019b600190920191016109f3565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516020810190610b5881610b2c60058a0133866129c6565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810183528261230f565b5190206000526005602052610b736004356040600020613383565b506108de565b67ffffffffffffffff8311610ae357610ba283610b996004890154612609565b60048901612940565b600083601f8111600114610c035780610bee92600091610bf8575b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b6004870155610848565b90508601358d610bbd565b506004870160005260206000209060005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086168110610cb25750847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0811610610c7a575b5050600183811b016004870155610848565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88660031b161c19908601351690558a80610c68565b9091602060018192858a013581550193019101610c14565b67ffffffffffffffff8b11610ae357610cf38b610cea60038a0154612609565b60038a01612940565b60008b601f8111600114610d535780610d3e92600091610d4857507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b6003880155610842565b90508501358e610bbd565b506003880160005260206000209060005b8d7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081168210610e06578091507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0811610610dcd575b905060018092501b016003880155610842565b60f87fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9160031b161c19908501351690558b808c610dba565b5085820135835560019092019160209182019101610d64565b60046040517f6b4a810d000000000000000000000000000000000000000000000000000000008152fd5b50826107f4565b50816107ee565b60046040517f95406722000000000000000000000000000000000000000000000000000000008152fd5b346101445760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445761066a610ecb610ebe6123f6565b6044359060243590612b6f565b60405191829182612270565b34610144576020610ef0610eea36612419565b91612b14565b604051908152f35b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457610f81612c53565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00600b5416600b557f11a03e25ee25bf1459f9e1cb293ea03707d84917f54a65e32c9a7be2f2edd68a6020604051338152a1005b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760005473ffffffffffffffffffffffffffffffffffffffff808216330361108157600154917fffffffffffffffffffffffff0000000000000000000000000000000000000000903382851617600155166000553391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b60046040517f02b543c6000000000000000000000000000000000000000000000000000000008152fd5b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457600980546110e781612488565b6110f4604051918261230f565b81815261110082612488565b916020937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060208401940136853760005b82811061118457505050906040519283926020840190602085525180915260408401929160005b82811061116757505050500390f35b835163ffffffff1685528695509381019392810192600101611158565b6001908260005263ffffffff817f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0154166111bf82876125ba565b5201611131565b34610144576111d43661237e565b916111dd612c53565b60ff600b54166104ac5760005b828110611269575060405191806040840160408552526060830191906000905b8082106112415785151560208601527fcab63bf31d1e656baa23cebef64e12033ea0ffbd44b1278c3747beec2d2f618c85850386a1005b90919283359063ffffffff82168092036101445760019181526020809101940192019061120a565b600190841561129b5761129363ffffffff61128d611288848888612af3565b612b03565b16612fd2565b505b016111ea565b6112b763ffffffff6112b1611288848888612af3565b16613169565b50611295565b346101445760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760ff600b54166104ac5761130260043533612eb0565b600181019081549163ffffffff8360a01c169260ff8160c01c16600281101561047d5715610453577fffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffff906113563386612c9e565b16905580547f17b2d730bb5e064df3fbc6165c8aceb3b0d62c524c196c0bc1012209280bc9a6604051602081528061044e3395600260208401910161265c565b34610144576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610144576004359060ff600b54166104ac576113de8233612eb0565b916113f6336000526008602052604060002054151590565b156115425782600493546000526006835260406000207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0081541690553360005260028352611448826040600020613383565b50600181019063ffffffff80835460a01c166000526003855261146f846040600020613383565b506005820161147e8154612609565b61150e575b508154925460a01c16917f76ee2dfcae10cb8522e62e713e62660e09ecfaab08db15d9404de19141322571604051868152806114c6339560028a8401910161265c565b0390a46000525261150c6005604060002060008155600060018201556114ee60028201612aaa565b6114fa60038201612aaa565b61150660048201612aaa565b01612aaa565b005b60405161152381610b2c8982019433866129c6565b5190206000526005855261153b846040600020613383565b5086611483565b60246040517f85982a00000000000000000000000000000000000000000000000000000000008152336004820152fd5b346101445760e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760043567ffffffffffffffff8111610144576115c1903690600401612350565b6044359163ffffffff8316830361014457600260643510156101445760843567ffffffffffffffff8111610144576115fd903690600401612350565b91909260a43567ffffffffffffffff811161014457611620903690600401612350565b60c43567ffffffffffffffff811161014457611640903690600401612350565b96909560ff600b54166104ac57611657338a612c9e565b60408511611e7c5761166a888483612d48565b611675858733612b14565b80600052600460205273ffffffffffffffffffffffffffffffffffffffff60016040600020015416611e52576116ac602435612e08565b604051906116b9826122f2565b602435825233602083015263ffffffff8b1660408301526116df606435606084016125fd565b6116ea36888a6128c4565b60808301526116fa3684866128c4565b60a083015261170a3686886128c4565b60c083015261171a368b8b6128c4565b60e0830152806000526004602052604060002091805183556001830173ffffffffffffffffffffffffffffffffffffffff60208301511681549077ffffffff0000000000000000000000000000000000000000604085015160a01b16906060850151600281101561047d5778ff0000000000000000000000000000000000000000000000007fffffffffffffff000000000000000000000000000000000000000000000000009160c01b1693161717179055608081015180519067ffffffffffffffff8211610ae3576117fd826117f46002880154612609565b60028801612940565b602090601f8311600114611d865761184a929160009183611caf5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b60028401555b60a081015180519067ffffffffffffffff8211610ae357611881826118786003880154612609565b60038801612940565b602090601f8311600114611cba576118ce929160009183611caf5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b60038401555b60c081015180519067ffffffffffffffff8211610ae357611905826118fc6004880154612609565b60048801612940565b602090601f8311600114611be25791806119569260e09594600092611abd5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b60048501555b015180519267ffffffffffffffff8411610ae357838d9261198e8e966119856005860154612609565b60058601612940565b602090601f8311600114611ac8579463ffffffff6108ae95819a957fc4399022965bad9b2b468bbd8c758a7e80cdde36ff3088ddbb7f93bdfb5623cb9f9e9d9994611a1a8761044e9f9b98600593611a7e9f9a600092611abd5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b9101555b336000526002602052611a358360406000206130dd565b50166000526003602052611a4d8160406000206130dd565b508d82611a94575b5050506108a06040519a8b9a611a6d8c606435612161565b60a060208d015260a08c0191612987565b9783890360808501521696339660243596612987565b611ab492611aa29133612b14565b600052600560205260406000206130dd565b508c8f8d611a55565b015190503880610959565b906005840160005260206000209160005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe085168110611bb857506108ae9563ffffffff9a957fc4399022965bad9b2b468bbd8c758a7e80cdde36ff3088ddbb7f93bdfb5623cb9f9e9d999460018761044e9f9b96928f9693611a7e9f9a94837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06005971610611b81575b505050811b01910155611a1e565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c19169055388080611b73565b939550918194969750600160209291839285015181550194019201918f9492918f97969492611ad9565b906004860160005260206000209160005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe085168110611c975750918391600193837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060e098971610611c60575b505050811b01600485015561195c565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690558f8080611c50565b91926020600181928685015181550194019201611bf3565b015190508f80610959565b9190600386016000526020600020906000935b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084168510611d6b5760019450837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0811610611d34575b505050811b0160038401556118d4565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690558e8080611d24565b81810151835560209485019460019093019290910190611ccd565b9190600286016000526020600020906000935b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084168510611e375760019450837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0811610611e00575b505050811b016002840155611850565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690558e8080611df0565b81810151835560209485019460019093019290910190611d99565b60046040517fa0677dd0000000000000000000000000000000000000000000000000000000008152fd5b604485604051907f36a7c503000000000000000000000000000000000000000000000000000000008252600482015260406024820152fd5b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457611eeb612c53565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00600b541617600b557f2789711f6fd67d131ad68378617b5d1d21a2c92b34d7c3745d70b3957c08096c6020604051338152a1005b34610144576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760043567ffffffffffffffff811161014457611f92903690600401612350565b60ff600b54166104ac57611fa69133612b14565b90816000526005602052604060002091825491821561066e5760005b838110611fcb57005b80611fd860019287612fba565b90549060031b1c60005260048352604060002063ffffffff8382015460a01c16600052600a8452604060002054151580612062575b612019575b5001611fc2565b7f95d94f817db4971aa99ba35d0fe019bd8cc39866fbe02b6d47b5f0f3727fb673604051868152604086820152806120593394600260408401910161265c565b0390a286612012565b5061207a336000526008602052604060002054151590565b61200d565b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457604051604081019080821067ffffffffffffffff831117610ae35761066a91604052601a81527f576f726b666c6f77526567697374727920312e302e302d646576000000000000602082015260405191829160208352602083019061216e565b346101445760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760043563ffffffff8116810361014457610ecb61066a9160443590602435906127cf565b90600282101561047d5752565b919082519283825260005b8481106121b85750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b602081830181015184830182015201612179565b61226d9160e061225c61224a6122386101008651865273ffffffffffffffffffffffffffffffffffffffff602088015116602087015263ffffffff604088015116604087015261222460608801516060880190612161565b60808701519080608088015286019061216e565b60a086015185820360a087015261216e565b60c085015184820360c086015261216e565b9201519060e081840391015261216e565b90565b6020808201906020835283518092526040830192602060408460051b8301019501936000915b8483106122a65750505050505090565b90919293949584806122e2837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc086600196030187528a516121cc565b9801930193019194939290612296565b610100810190811067ffffffffffffffff821117610ae357604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610ae357604052565b9181601f840112156101445782359167ffffffffffffffff8311610144576020838186019501011161014457565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126101445760043567ffffffffffffffff9283821161014457806023830112156101445781600401359384116101445760248460051b8301011161014457602401919060243580151581036101445790565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361014457565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126101445760043573ffffffffffffffffffffffffffffffffffffffff8116810361014457916024359067ffffffffffffffff82116101445761248491600401612350565b9091565b67ffffffffffffffff8111610ae35760051b60200190565b604051906124ad826122f2565b606060e0836000815260006020820152600060408201526000838201528260808201528260a08201528260c08201520152565b6040516020810181811067ffffffffffffffff821117610ae3576040526000815290565b9061250e82612488565b61251b604051918261230f565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06125498294612488565b019060005b82811061255a57505050565b6020906125656124a0565b8282850101520161254e565b9190820180921161257e57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9190820391821161257e57565b80518210156125ce5760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600282101561047d5752565b90600182811c92168015612652575b602083101461262357565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f1691612618565b80546000939261266b82612609565b918282526020936001916001811690816000146126d35750600114612692575b5050505050565b90939495506000929192528360002092846000945b8386106126bf5750505050010190388080808061268b565b8054858701830152940193859082016126a7565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168685015250505090151560051b01019150388080808061268b565b90600560e06040936127cb855191612727836122f2565b6127c483978254855261277160ff600185015473ffffffffffffffffffffffffffffffffffffffff8116602089015263ffffffff8160a01c168489015260c01c16606087016125fd565b80516127848161078a816002880161265c565b6080860152805161279c8161078a816003880161265c565b60a086015280516127b48161078a816004880161265c565b60c086015251809681930161265c565b038461230f565b0152565b63ffffffff1691600083815260036020906003602052604093604084205490818710156128b4576128239181606489931180156128ac575b6128a4575b816128178285612571565b111561289457506125ad565b9461282d86612504565b96845b87811061284257505050505050505090565b60019082875284865261286188882061285b8387612571565b90612fba565b905490861b1c875260048652612878888820612710565b612882828c6125ba565b5261288d818b6125ba565b5001612830565b61289f915082612571565b6125ad565b50606461280c565b508015612807565b505050505050505061226d6124e0565b92919267ffffffffffffffff8211610ae3576040519161290c60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116018461230f565b829481845281830111610144578281602093846000960137010152565b818110612934575050565b60008155600101612929565b9190601f811161294f57505050565b61297b926000526020600020906020601f840160051c8301931061297d575b601f0160051c0190612929565b565b909150819061296e565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b91907fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009060601b168252601490600092815492612a0284612609565b92600194600181169081600014612a695750600114612a24575b505050505090565b9091929395945060005260209460206000206000905b858210612a565750505050601492935001013880808080612a1c565b8054858301850152908701908201612a3a565b92505050601494507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091935016838301528015150201013880808080612a1c565b612ab48154612609565b9081612abe575050565b81601f60009311600114612ad0575055565b908083918252612aef601f60208420940160051c840160018501612929565b5555565b91908110156125ce5760051b0190565b3563ffffffff811681036101445790565b91906034612b6991836040519485927fffffffffffffffffffffffffffffffffffffffff000000000000000000000000602085019860601b16885284840137810160008382015203601481018452018261230f565b51902090565b73ffffffffffffffffffffffffffffffffffffffff169160008381526002926020906002602052604093604084205490818310156128b457612bc69181606485931180156128ac576128a457816128178285612571565b94612bd086612504565b96845b878110612be557505050505050505090565b600190828752838652612bfe88882061285b8388612571565b90549060031b1c875260048652612c16888820612710565b612c20828c6125ba565b52612c2b818b6125ba565b5001612bd3565b3573ffffffffffffffffffffffffffffffffffffffff811681036101445790565b73ffffffffffffffffffffffffffffffffffffffff600154163303612c7457565b60046040517f2b5c74de000000000000000000000000000000000000000000000000000000008152fd5b63ffffffff1680600052600a60205260406000205415612d17575073ffffffffffffffffffffffffffffffffffffffff1680600052600860205260406000205415612ce65750565b602490604051907f85982a000000000000000000000000000000000000000000000000000000000082526004820152fd5b602490604051907f8fe6d7e10000000000000000000000000000000000000000000000000000000082526004820152fd5b9060c891828111612dd25750818111612d9d5750808211612d67575050565b60449250604051917ecd56a800000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b604491604051917ecd56a800000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b60449083604051917ecd56a800000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b8015612e865780600052600660205260ff60406000205416612e5c576000526006602052604060002060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055565b60046040517f4cb050e4000000000000000000000000000000000000000000000000000000008152fd5b60046040517f7dc2f4e1000000000000000000000000000000000000000000000000000000008152fd5b90600052600460205260406000209073ffffffffffffffffffffffffffffffffffffffff8060018401541691821561066e5716809103612eee575090565b602490604051907f31ee6dc70000000000000000000000000000000000000000000000000000000082526004820152fd5b9081518151908181149384612f36575b5050505090565b6020929394508201209201201438808080612f2f565b6009548110156125ce5760096000527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0190600090565b6007548110156125ce5760076000527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6880190600090565b80548210156125ce5760005260206000200190600090565b6000818152600a6020526040812054613086576009546801000000000000000081101561305957908261304561301084600160409601600955612f4c565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b9055600954928152600a6020522055600190565b6024827f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b905090565b60008181526008602052604081205461308657600754680100000000000000008110156130595790826130c961301084600160409601600755612f83565b905560075492815260086020522055600190565b9190600183016000908282528060205260408220541560001461316357845494680100000000000000008610156131365783613126613010886001604098999a01855584612fba565b9055549382526020522055600190565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b50925050565b6000818152600a602052604081205490919080156132b7577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9081810181811161328a576009549083820191821161325d57818103613229575b50505060095480156131fc578101906131db82612f4c565b909182549160031b1b191690556009558152600a6020526040812055600190565b6024847f4e487b710000000000000000000000000000000000000000000000000000000081526031600452fd5b61324761323861301093612f4c565b90549060031b1c928392612f4c565b90558452600a60205260408420553880806131c3565b6024867f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6024857f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b505090565b60008181526008602052604081205490919080156132b7577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9081810181811161328a576007549083820191821161325d5781810361334f575b50505060075480156131fc5781019061332e82612f83565b909182549160031b1b19169055600755815260086020526040812055600190565b61336d61335e61301093612f83565b90549060031b1c928392612f83565b9055845260086020526040842055388080613316565b90600182019060009281845282602052604084205490811515600014612f2f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff918281018181116134a85782549084820191821161347b57818103613446575b50505080548015613419578201916133fc8383612fba565b909182549160031b1b191690555582526020526040812055600190565b6024867f4e487b710000000000000000000000000000000000000000000000000000000081526031600452fd5b6134666134566130109386612fba565b90549060031b1c92839286612fba565b905586528460205260408620553880806133e4565b6024887f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6024877f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fdfea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AddressNotAuthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BinaryURLRequired\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotWorkflowOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"}],\"name\":\"DONNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidWorkflowID\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryLocked\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"providedLength\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"maxAllowedLength\",\"type\":\"uint8\"}],\"name\":\"URLTooLong\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WorkflowAlreadyInDesiredStatus\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WorkflowAlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WorkflowContentNotUpdated\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WorkflowDoesNotExist\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WorkflowIDAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WorkflowNameRequired\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"providedLength\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"maxAllowedLength\",\"type\":\"uint8\"}],\"name\":\"WorkflowNameTooLong\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32[]\",\"name\":\"donIDs\",\"type\":\"uint32[]\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"AllowedDONsUpdatedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"addresses\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"AuthorizedAddressesUpdatedV1\",\"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\":\"lockedBy\",\"type\":\"address\"}],\"name\":\"RegistryLockedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"unlockedBy\",\"type\":\"address\"}],\"name\":\"RegistryUnlockedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"}],\"name\":\"WorkflowActivatedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"}],\"name\":\"WorkflowDeletedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"secretsURLHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"}],\"name\":\"WorkflowForceUpdateSecretsRequestedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"}],\"name\":\"WorkflowPausedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"enumWorkflowRegistry.WorkflowStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"name\":\"WorkflowRegisteredV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"oldWorkflowID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"newWorkflowID\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"name\":\"WorkflowUpdatedV1\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"workflowKey\",\"type\":\"bytes32\"}],\"name\":\"activateWorkflow\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"field\",\"type\":\"string\"}],\"name\":\"computeHashKey\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"workflowKey\",\"type\":\"bytes32\"}],\"name\":\"deleteWorkflow\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAllowedDONs\",\"outputs\":[{\"internalType\":\"uint32[]\",\"name\":\"allowedDONs\",\"type\":\"uint32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"authorizedAddresses\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"}],\"name\":\"getWorkflowMetadata\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"internalType\":\"enumWorkflowRegistry.WorkflowStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"internalType\":\"structWorkflowRegistry.WorkflowMetadata\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"limit\",\"type\":\"uint256\"}],\"name\":\"getWorkflowMetadataListByDON\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"internalType\":\"enumWorkflowRegistry.WorkflowStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"internalType\":\"structWorkflowRegistry.WorkflowMetadata[]\",\"name\":\"workflowMetadataList\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"limit\",\"type\":\"uint256\"}],\"name\":\"getWorkflowMetadataListByOwner\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"internalType\":\"enumWorkflowRegistry.WorkflowStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"internalType\":\"structWorkflowRegistry.WorkflowMetadata[]\",\"name\":\"workflowMetadataList\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isRegistryLocked\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lockRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"workflowKey\",\"type\":\"bytes32\"}],\"name\":\"pauseWorkflow\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"},{\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"internalType\":\"enumWorkflowRegistry.WorkflowStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"name\":\"registerWorkflow\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"name\":\"requestForceUpdateSecrets\",\"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\":[],\"name\":\"unlockRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"donIDs\",\"type\":\"uint32[]\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"updateAllowedDONs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"addresses\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"updateAuthorizedAddresses\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"workflowKey\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"newWorkflowID\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"name\":\"updateWorkflow\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x6080806040523461004a57331561003b57600180546001600160a01b03191633179055600b805460ff1916905560405161354290816100508239f35b639b15e16f60e01b8152600490fd5b600080fdfe6080604052600436101561001257600080fd5b60003560e01c806308e7f63a1461213e578063181f5a77146120af5780632303348a14611f725780632b596f6d14611ee45780633ccd14ff14611572578063695e1340146113965780636f351771146112ba578063724c13dd146111af5780637497066b1461109457806379ba509714610fbe5780637ec0846d14610f335780638da5cb5b14610ee15780639f4cb53414610ec0578063b87a019414610e6a578063d4b89c74146106af578063db80009214610614578063e3dce080146104d9578063e690f33214610362578063f2fde38b14610284578063f794bdeb146101495763f99ecb6b1461010357600080fd5b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457602060ff600b54166040519015158152f35b600080fd5b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760078054610185816124b8565b610192604051918261233f565b81815261019e826124b8565b916020937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060208401940136853760005b82811061023257505050906040519283926020840190602085525180915260408401929160005b82811061020557505050500390f35b835173ffffffffffffffffffffffffffffffffffffffff16855286955093810193928101926001016101f6565b6001908260005273ffffffffffffffffffffffffffffffffffffffff817fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68801541661027d82876125ea565b52016101cf565b346101445760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610144576102bb612426565b6102c3612c83565b73ffffffffffffffffffffffffffffffffffffffff8091169033821461033857817fffffffffffffffffffffffff00000000000000000000000000000000000000006000541617600055600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b60046040517fdad89dca000000000000000000000000000000000000000000000000000000008152fd5b346101445760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760ff600b54166104af576103a760043533612f10565b600181019081549060ff8260c01c1660028110156104805760011461045657780100000000000000000000000000000000000000000000000091817fffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffff92549060405191602083527f6a0ed88e9cf3cb493ab4028fcb1dc7d18f0130fcdfba096edde0aadbfbf5e99f63ffffffff8560a01c16938061044d3395600260208401910161268c565b0390a416179055005b60046040517f6f861db1000000000000000000000000000000000000000000000000000000008152fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60046040517f78a4e7d9000000000000000000000000000000000000000000000000000000008152fd5b34610144576104e7366123ae565b916104f0612c83565b60ff600b54166104af5782156105ce5760005b82811061059357505b60405191806040840160408552526060830191906000905b80821061055b5785151560208601527f509460cccbb176edde6cac28895a4415a24961b8f3a0bd2617b9bb7b4e166c9b85850386a1005b90919283359073ffffffffffffffffffffffffffffffffffffffff821680920361014457600191815260208091019401920190610524565b806105c773ffffffffffffffffffffffffffffffffffffffff6105c16105bc6001958888612b23565b612c62565b166130eb565b5001610503565b60005b8281106105de575061050c565b8061060d73ffffffffffffffffffffffffffffffffffffffff6106076105bc6001958888612b23565b1661331c565b50016105d1565b346101445761063461062536612449565b9161062e6124d0565b50612b44565b6000526004602052604060002073ffffffffffffffffffffffffffffffffffffffff600182015416156106855761066d61068191612740565b6040519182916020835260208301906121fc565b0390f35b60046040517f871e01b2000000000000000000000000000000000000000000000000000000008152fd5b346101445760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760443567ffffffffffffffff8111610144576106fe903690600401612380565b9060643567ffffffffffffffff81116101445761071f903690600401612380565b9160843567ffffffffffffffff811161014457610740903690600401612380565b60ff600b94929454166104af57610758818688612d78565b61076460043533612f10565b9163ffffffff600184015460a01c169561077e3388612cce565b8354946107b060405161079f816107988160038b0161268c565b038261233f565b6107aa368c856128f4565b90612f7f565b6107d26040516107c7816107988160048c0161268c565b6107aa3686886128f4565b6107f46040516107e9816107988160058d0161268c565b6107aa36898d6128f4565b918080610e63575b80610e5c575b610e3257610811602435612e68565b88600052600660205260406000207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008154169055602435885515610cdd575b15610b8c575b156108df575b926108ca7f41161473ce2ed633d9f902aab9702d16a5531da27ec84e1939abeffe54ad735395936108da936108bc6108ae978d604051998a996024358b5260a060208c0152600260a08c01910161268c565b9189830360408b01526129b7565b9186830360608801526129b7565b90838203608085015233976129b7565b0390a4005b6108ec6005860154612639565b610b25575b67ffffffffffffffff8411610af65761091a846109116005880154612639565b60058801612970565b6000601f85116001146109f6579284926108bc6108ca938a9b9c61099e876108ae9b9a6108da9a7f41161473ce2ed633d9f902aab9702d16a5531da27ec84e1939abeffe54ad73539e9f6000926109eb575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b60058a01555b8c87806109c1575b50509c9b9a995093505092949550925061085c565b6109cb9133612b44565b60005260056020526109e3600435604060002061313d565b508c876109ac565b013590508f8061096c565b9860058601600052602060002060005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe087168110610ade5750926108bc6108ca936108da969388968c7f41161473ce2ed633d9f902aab9702d16a5531da27ec84e1939abeffe54ad73539c9d9e9f897fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06108ae9e9d1610610aa6575b505050600187811b0160058a01556109a4565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88b60031b161c199101351690558e8d81610a93565b898c0135825560209b8c019b60019092019101610a06565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516020810190610b6b81610b3f60058a0133866129f6565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810183528261233f565b5190206000526005602052610b8660043560406000206133e3565b506108f1565b67ffffffffffffffff8311610af657610bb583610bac6004890154612639565b60048901612970565b600083601f8111600114610c165780610c0192600091610c0b575b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b6004870155610856565b90508601358d610bd0565b506004870160005260206000209060005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086168110610cc55750847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0811610610c8d575b5050600183811b016004870155610856565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88660031b161c19908601351690558a80610c7b565b9091602060018192858a013581550193019101610c27565b67ffffffffffffffff8b11610af657610d068b610cfd60038a0154612639565b60038a01612970565b60008b601f8111600114610d665780610d5192600091610d5b57507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b6003880155610850565b90508501358e610bd0565b506003880160005260206000209060005b8d7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081168210610e19578091507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0811610610de0575b905060018092501b016003880155610850565b60f87fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9160031b161c19908501351690558b808c610dcd565b5085820135835560019092019160209182019101610d77565b60046040517f6b4a810d000000000000000000000000000000000000000000000000000000008152fd5b5082610802565b50816107fc565b346101445760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457610681610eb4610ea7612426565b6044359060243590612b9f565b604051918291826122a0565b34610144576020610ed9610ed336612449565b91612b44565b604051908152f35b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457610f6a612c83565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00600b5416600b557f11a03e25ee25bf1459f9e1cb293ea03707d84917f54a65e32c9a7be2f2edd68a6020604051338152a1005b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760005473ffffffffffffffffffffffffffffffffffffffff808216330361106a57600154917fffffffffffffffffffffffff0000000000000000000000000000000000000000903382851617600155166000553391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b60046040517f02b543c6000000000000000000000000000000000000000000000000000000008152fd5b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457600980546110d0816124b8565b6110dd604051918261233f565b8181526110e9826124b8565b916020937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060208401940136853760005b82811061116d57505050906040519283926020840190602085525180915260408401929160005b82811061115057505050500390f35b835163ffffffff1685528695509381019392810192600101611141565b6001908260005263ffffffff817f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0154166111a882876125ea565b520161111a565b34610144576111bd366123ae565b916111c6612c83565b60ff600b54166104af5782156112845760005b82811061125957505b60405191806040840160408552526060830191906000905b8082106112315785151560208601527fcab63bf31d1e656baa23cebef64e12033ea0ffbd44b1278c3747beec2d2f618c85850386a1005b90919283359063ffffffff8216809203610144576001918152602080910194019201906111fa565b8061127d63ffffffff6112776112726001958888612b23565b612b33565b16613032565b50016111d9565b60005b82811061129457506111e2565b806112b363ffffffff6112ad6112726001958888612b23565b166131c9565b5001611287565b346101445760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760ff600b54166104af576112ff60043533612f10565b6001810190815463ffffffff8160a01c1660ff8260c01c1660028110156104805715610456577fffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffff926113513383612cce565b80547f17b2d730bb5e064df3fbc6165c8aceb3b0d62c524c196c0bc1012209280bc9a6604051602081528061138e3395600260208401910161268c565b0390a4169055005b34610144576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610144576004359060ff600b54166104af576113de8233612f10565b916113f6336000526008602052604060002054151590565b156115425782600493546000526006835260406000207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00815416905533600052600283526114488260406000206133e3565b50600181019063ffffffff80835460a01c166000526003855261146f8460406000206133e3565b506005820161147e8154612639565b61150e575b508154925460a01c16917f76ee2dfcae10cb8522e62e713e62660e09ecfaab08db15d9404de19141322571604051868152806114c6339560028a8401910161268c565b0390a46000525261150c6005604060002060008155600060018201556114ee60028201612ada565b6114fa60038201612ada565b61150660048201612ada565b01612ada565b005b60405161152381610b3f8982019433866129f6565b5190206000526005855261153b8460406000206133e3565b5086611483565b60246040517f85982a00000000000000000000000000000000000000000000000000000000008152336004820152fd5b346101445760e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760043567ffffffffffffffff8111610144576115c1903690600401612380565b6044359163ffffffff8316830361014457600260643510156101445760843567ffffffffffffffff8111610144576115fd903690600401612380565b91909260a43567ffffffffffffffff811161014457611620903690600401612380565b60c43567ffffffffffffffff811161014457611640903690600401612380565b96909560ff600b54166104af57611657338a612cce565b8415611eba5760408511611e8257611670888483612d78565b61167b858733612b44565b80600052600460205273ffffffffffffffffffffffffffffffffffffffff60016040600020015416611e58576116b2602435612e68565b604051906116bf82612322565b602435825233602083015263ffffffff8b1660408301526116e56064356060840161262d565b6116f036888a6128f4565b60808301526117003684866128f4565b60a08301526117103686886128f4565b60c0830152611720368b8b6128f4565b60e0830152806000526004602052604060002091805183556001830173ffffffffffffffffffffffffffffffffffffffff60208301511681549077ffffffff0000000000000000000000000000000000000000604085015160a01b1690606085015160028110156104805778ff0000000000000000000000000000000000000000000000007fffffffffffffff000000000000000000000000000000000000000000000000009160c01b1693161717179055608081015180519067ffffffffffffffff8211610af657611803826117fa6002880154612639565b60028801612970565b602090601f8311600114611d8c57611850929160009183611cb55750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b60028401555b60a081015180519067ffffffffffffffff8211610af6576118878261187e6003880154612639565b60038801612970565b602090601f8311600114611cc0576118d4929160009183611cb55750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b60038401555b60c081015180519067ffffffffffffffff8211610af65761190b826119026004880154612639565b60048801612970565b602090601f8311600114611be857918061195c9260e09594600092611ac35750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b60048501555b015180519267ffffffffffffffff8411610af657838d926119948e9661198b6005860154612639565b60058601612970565b602090601f8311600114611ace579463ffffffff6108bc95819a957fc4399022965bad9b2b468bbd8c758a7e80cdde36ff3088ddbb7f93bdfb5623cb9f9e9d9994611a20876108da9f9b98600593611a849f9a600092611ac35750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b9101555b336000526002602052611a3b83604060002061313d565b50166000526003602052611a5381604060002061313d565b508d82611a9a575b5050506108ae6040519a8b9a611a738c606435612191565b60a060208d015260a08c01916129b7565b97838903608085015216963396602435966129b7565b611aba92611aa89133612b44565b6000526005602052604060002061313d565b508c8f8d611a5b565b01519050388061096c565b906005840160005260206000209160005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe085168110611bbe57506108bc9563ffffffff9a957fc4399022965bad9b2b468bbd8c758a7e80cdde36ff3088ddbb7f93bdfb5623cb9f9e9d99946001876108da9f9b96928f9693611a849f9a94837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06005971610611b87575b505050811b01910155611a24565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c19169055388080611b79565b939550918194969750600160209291839285015181550194019201918f9492918f97969492611adf565b906004860160005260206000209160005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe085168110611c9d5750918391600193837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060e098971610611c66575b505050811b016004850155611962565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690558f8080611c56565b91926020600181928685015181550194019201611bf9565b015190508f8061096c565b9190600386016000526020600020906000935b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084168510611d715760019450837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0811610611d3a575b505050811b0160038401556118da565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690558e8080611d2a565b81810151835560209485019460019093019290910190611cd3565b9190600286016000526020600020906000935b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084168510611e3d5760019450837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0811610611e06575b505050811b016002840155611856565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690558e8080611df6565b81810151835560209485019460019093019290910190611d9f565b60046040517fa0677dd0000000000000000000000000000000000000000000000000000000008152fd5b604485604051907f36a7c503000000000000000000000000000000000000000000000000000000008252600482015260406024820152fd5b60046040517f485b8ed4000000000000000000000000000000000000000000000000000000008152fd5b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457611f1b612c83565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00600b541617600b557f2789711f6fd67d131ad68378617b5d1d21a2c92b34d7c3745d70b3957c08096c6020604051338152a1005b34610144576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760043567ffffffffffffffff811161014457611fc2903690600401612380565b60ff600b54166104af57611fd69133612b44565b9081600052600560205260406000209182549182156106855760005b838110611ffb57005b806120086001928761301a565b90549060031b1c60005260048352604060002063ffffffff8382015460a01c16600052600a8452604060002054151580612092575b612049575b5001611ff2565b7f95d94f817db4971aa99ba35d0fe019bd8cc39866fbe02b6d47b5f0f3727fb673604051868152604086820152806120893394600260408401910161268c565b0390a286612042565b506120aa336000526008602052604060002054151590565b61203d565b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457604051604081019080821067ffffffffffffffff831117610af65761068191604052601a81527f576f726b666c6f77526567697374727920312e302e302d646576000000000000602082015260405191829160208352602083019061219e565b346101445760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760043563ffffffff8116810361014457610eb46106819160443590602435906127ff565b9060028210156104805752565b919082519283825260005b8481106121e85750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b6020818301810151848301820152016121a9565b61229d9160e061228c61227a6122686101008651865273ffffffffffffffffffffffffffffffffffffffff602088015116602087015263ffffffff604088015116604087015261225460608801516060880190612191565b60808701519080608088015286019061219e565b60a086015185820360a087015261219e565b60c085015184820360c086015261219e565b9201519060e081840391015261219e565b90565b6020808201906020835283518092526040830192602060408460051b8301019501936000915b8483106122d65750505050505090565b9091929394958480612312837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc086600196030187528a516121fc565b98019301930191949392906122c6565b610100810190811067ffffffffffffffff821117610af657604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610af657604052565b9181601f840112156101445782359167ffffffffffffffff8311610144576020838186019501011161014457565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126101445760043567ffffffffffffffff9283821161014457806023830112156101445781600401359384116101445760248460051b8301011161014457602401919060243580151581036101445790565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361014457565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126101445760043573ffffffffffffffffffffffffffffffffffffffff8116810361014457916024359067ffffffffffffffff8211610144576124b491600401612380565b9091565b67ffffffffffffffff8111610af65760051b60200190565b604051906124dd82612322565b606060e0836000815260006020820152600060408201526000838201528260808201528260a08201528260c08201520152565b6040516020810181811067ffffffffffffffff821117610af6576040526000815290565b9061253e826124b8565b61254b604051918261233f565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061257982946124b8565b019060005b82811061258a57505050565b6020906125956124d0565b8282850101520161257e565b919082018092116125ae57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b919082039182116125ae57565b80518210156125fe5760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60028210156104805752565b90600182811c92168015612682575b602083101461265357565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f1691612648565b80546000939261269b82612639565b9182825260209360019160018116908160001461270357506001146126c2575b5050505050565b90939495506000929192528360002092846000945b8386106126ef575050505001019038808080806126bb565b8054858701830152940193859082016126d7565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168685015250505090151560051b0101915038808080806126bb565b90600560e06040936127fb85519161275783612322565b6127f48397825485526127a160ff600185015473ffffffffffffffffffffffffffffffffffffffff8116602089015263ffffffff8160a01c168489015260c01c166060870161262d565b80516127b481610798816002880161268c565b608086015280516127cc81610798816003880161268c565b60a086015280516127e481610798816004880161268c565b60c086015251809681930161268c565b038461233f565b0152565b63ffffffff1691600083815260036020906003602052604093604084205490818710156128e4576128539181606489931180156128dc575b6128d4575b8161284782856125a1565b11156128c457506125dd565b9461285d86612534565b96845b87811061287257505050505050505090565b60019082875284865261289188882061288b83876125a1565b9061301a565b905490861b1c8752600486526128a8888820612740565b6128b2828c6125ea565b526128bd818b6125ea565b5001612860565b6128cf9150826125a1565b6125dd565b50606461283c565b508015612837565b505050505050505061229d612510565b92919267ffffffffffffffff8211610af6576040519161293c60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116018461233f565b829481845281830111610144578281602093846000960137010152565b818110612964575050565b60008155600101612959565b9190601f811161297f57505050565b6129ab926000526020600020906020601f840160051c830193106129ad575b601f0160051c0190612959565b565b909150819061299e565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b91907fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009060601b168252601490600092815492612a3284612639565b92600194600181169081600014612a995750600114612a54575b505050505090565b9091929395945060005260209460206000206000905b858210612a865750505050601492935001013880808080612a4c565b8054858301850152908701908201612a6a565b92505050601494507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091935016838301528015150201013880808080612a4c565b612ae48154612639565b9081612aee575050565b81601f60009311600114612b00575055565b908083918252612b1f601f60208420940160051c840160018501612959565b5555565b91908110156125fe5760051b0190565b3563ffffffff811681036101445790565b91906034612b9991836040519485927fffffffffffffffffffffffffffffffffffffffff000000000000000000000000602085019860601b16885284840137810160008382015203601481018452018261233f565b51902090565b73ffffffffffffffffffffffffffffffffffffffff169160008381526002926020906002602052604093604084205490818310156128e457612bf69181606485931180156128dc576128d4578161284782856125a1565b94612c0086612534565b96845b878110612c1557505050505050505090565b600190828752838652612c2e88882061288b83886125a1565b90549060031b1c875260048652612c46888820612740565b612c50828c6125ea565b52612c5b818b6125ea565b5001612c03565b3573ffffffffffffffffffffffffffffffffffffffff811681036101445790565b73ffffffffffffffffffffffffffffffffffffffff600154163303612ca457565b60046040517f2b5c74de000000000000000000000000000000000000000000000000000000008152fd5b63ffffffff1680600052600a60205260406000205415612d47575073ffffffffffffffffffffffffffffffffffffffff1680600052600860205260406000205415612d165750565b602490604051907f85982a000000000000000000000000000000000000000000000000000000000082526004820152fd5b602490604051907f8fe6d7e10000000000000000000000000000000000000000000000000000000082526004820152fd5b908115612e3e5760c891828111612e085750818111612dd35750808211612d9d575050565b60449250604051917ecd56a800000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b604491604051917ecd56a800000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b60449083604051917ecd56a800000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b60046040517f9cd963cf000000000000000000000000000000000000000000000000000000008152fd5b8015612ee65780600052600660205260ff60406000205416612ebc576000526006602052604060002060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055565b60046040517f4cb050e4000000000000000000000000000000000000000000000000000000008152fd5b60046040517f7dc2f4e1000000000000000000000000000000000000000000000000000000008152fd5b90600052600460205260406000209073ffffffffffffffffffffffffffffffffffffffff806001840154169182156106855716809103612f4e575090565b602490604051907f31ee6dc70000000000000000000000000000000000000000000000000000000082526004820152fd5b9081518151908181149384612f96575b5050505090565b6020929394508201209201201438808080612f8f565b6009548110156125fe5760096000527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0190600090565b6007548110156125fe5760076000527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6880190600090565b80548210156125fe5760005260206000200190600090565b6000818152600a60205260408120546130e657600954680100000000000000008110156130b95790826130a561307084600160409601600955612fac565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b9055600954928152600a6020522055600190565b6024827f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b905090565b6000818152600860205260408120546130e657600754680100000000000000008110156130b957908261312961307084600160409601600755612fe3565b905560075492815260086020522055600190565b919060018301600090828252806020526040822054156000146131c357845494680100000000000000008610156131965783613186613070886001604098999a0185558461301a565b9055549382526020522055600190565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b50925050565b6000818152600a60205260408120549091908015613317577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff908181018181116132ea57600954908382019182116132bd57818103613289575b505050600954801561325c5781019061323b82612fac565b909182549160031b1b191690556009558152600a6020526040812055600190565b6024847f4e487b710000000000000000000000000000000000000000000000000000000081526031600452fd5b6132a761329861307093612fac565b90549060031b1c928392612fac565b90558452600a6020526040842055388080613223565b6024867f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6024857f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b505090565b6000818152600860205260408120549091908015613317577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff908181018181116132ea57600754908382019182116132bd578181036133af575b505050600754801561325c5781019061338e82612fe3565b909182549160031b1b19169055600755815260086020526040812055600190565b6133cd6133be61307093612fe3565b90549060031b1c928392612fe3565b9055845260086020526040842055388080613376565b90600182019060009281845282602052604084205490811515600014612f8f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff91828101818111613508578254908482019182116134db578181036134a6575b505050805480156134795782019161345c838361301a565b909182549160031b1b191690555582526020526040812055600190565b6024867f4e487b710000000000000000000000000000000000000000000000000000000081526031600452fd5b6134c66134b6613070938661301a565b90549060031b1c9283928661301a565b90558652846020526040862055388080613444565b6024887f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6024877f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fdfea164736f6c6343000818000a", } var WorkflowRegistryABI = WorkflowRegistryMetaData.ABI diff --git a/core/gethwrappers/workflow/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/workflow/generation/generated-wrapper-dependency-versions-do-not-edit.txt index a908ff2e724..afc0ccbefd9 100644 --- a/core/gethwrappers/workflow/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/workflow/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,2 +1,2 @@ GETH_VERSION: 1.14.11 -workflow_registry_wrapper: ../../../contracts/solc/v0.8.24/WorkflowRegistry/WorkflowRegistry.abi ../../../contracts/solc/v0.8.24/WorkflowRegistry/WorkflowRegistry.bin bad48df0196c8a170a8e5486d0334183defd60e74bd89d3885989e00d6f13d23 +workflow_registry_wrapper: ../../../contracts/solc/v0.8.24/WorkflowRegistry/WorkflowRegistry.abi ../../../contracts/solc/v0.8.24/WorkflowRegistry/WorkflowRegistry.bin 88356c4673d32f7d17b5e418d411a418a24ac972e6ec9cb740d8b731d6b9916a diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go index a55c57cc9a2..5780410ab60 100644 --- a/core/internal/cltest/cltest.go +++ b/core/internal/cltest/cltest.go @@ -48,8 +48,8 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink-framework/multinode" - "github.com/smartcontractkit/chainlink/v2/common/client" commonmocks "github.com/smartcontractkit/chainlink/v2/common/types/mocks" "github.com/smartcontractkit/chainlink/v2/core/auth" "github.com/smartcontractkit/chainlink/v2/core/bridges" @@ -82,6 +82,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/solkey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/starkkey" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/tronkey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/vrfkey" "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" @@ -133,6 +134,7 @@ var ( DefaultSolanaKey = solkey.MustNewInsecure(keystest.NewRandReaderFromSeed(KeyBigIntSeed)) DefaultStarkNetKey = starkkey.MustNewInsecure(keystest.NewRandReaderFromSeed(KeyBigIntSeed)) DefaultAptosKey = aptoskey.MustNewInsecure(keystest.NewRandReaderFromSeed(KeyBigIntSeed)) + DefaultTronKey = tronkey.MustNewInsecure(keystest.NewRandReaderFromSeed(KeyBigIntSeed)) DefaultVRFKey = vrfkey.MustNewV2XXXTestingOnly(big.NewInt(KeyBigIntSeed)) ) @@ -471,6 +473,13 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn } initOps = append(initOps, chainlink.InitAptos(ctx, relayerFactory, aptosCfg)) } + if cfg.TronEnabled() { + tronCfg := chainlink.TronFactoryConfig{ + Keystore: keyStore.Tron(), + TOMLConfigs: cfg.TronConfigs(), + } + initOps = append(initOps, chainlink.InitTron(ctx, relayerFactory, tronCfg)) + } relayChainInterops, err := chainlink.NewCoreRelayerChainInteroperators(initOps...) if err != nil { @@ -561,7 +570,7 @@ func NewEthMocksWithTransactionsOnBlocksAssertions(t testing.TB) *evmclimocks.Cl c.On("Dial", mock.Anything).Maybe().Return(nil) c.On("SubscribeToHeads", mock.Anything).Maybe().Return(chHead, EmptyMockSubscription(t), nil) c.On("SendTransaction", mock.Anything, mock.Anything).Maybe().Return(nil) - c.On("SendTransactionReturnCode", mock.Anything, mock.Anything, mock.Anything).Maybe().Return(client.Successful, nil) + c.On("SendTransactionReturnCode", mock.Anything, mock.Anything, mock.Anything).Maybe().Return(multinode.Successful, nil) // Construct chain h2 := Head(2) h1 := HeadWithHash(1, h2.ParentHash) diff --git a/core/internal/mocks/application.go b/core/internal/mocks/application.go index 69a8a60ef45..65dfbde7559 100644 --- a/core/internal/mocks/application.go +++ b/core/internal/mocks/application.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -108,7 +108,7 @@ func (_c *Application_AddJobV2_Call) RunAndReturn(run func(context.Context, *job return _c } -// AuthenticationProvider provides a mock function with given fields: +// AuthenticationProvider provides a mock function with no fields func (_m *Application) AuthenticationProvider() sessions.AuthenticationProvider { ret := _m.Called() @@ -155,7 +155,7 @@ func (_c *Application_AuthenticationProvider_Call) RunAndReturn(run func() sessi return _c } -// BasicAdminUsersORM provides a mock function with given fields: +// BasicAdminUsersORM provides a mock function with no fields func (_m *Application) BasicAdminUsersORM() sessions.BasicAdminUsersORM { ret := _m.Called() @@ -202,7 +202,7 @@ func (_c *Application_BasicAdminUsersORM_Call) RunAndReturn(run func() sessions. return _c } -// BridgeORM provides a mock function with given fields: +// BridgeORM provides a mock function with no fields func (_m *Application) BridgeORM() bridges.ORM { ret := _m.Called() @@ -344,7 +344,7 @@ func (_c *Application_DeleteLogPollerDataAfter_Call) RunAndReturn(run func(conte return _c } -// EVMORM provides a mock function with given fields: +// EVMORM provides a mock function with no fields func (_m *Application) EVMORM() types.Configs { ret := _m.Called() @@ -450,7 +450,7 @@ func (_c *Application_FindLCA_Call) RunAndReturn(run func(context.Context, *big. return _c } -// GetAuditLogger provides a mock function with given fields: +// GetAuditLogger provides a mock function with no fields func (_m *Application) GetAuditLogger() audit.AuditLogger { ret := _m.Called() @@ -497,7 +497,7 @@ func (_c *Application_GetAuditLogger_Call) RunAndReturn(run func() audit.AuditLo return _c } -// GetConfig provides a mock function with given fields: +// GetConfig provides a mock function with no fields func (_m *Application) GetConfig() chainlink.GeneralConfig { ret := _m.Called() @@ -544,7 +544,7 @@ func (_c *Application_GetConfig_Call) RunAndReturn(run func() chainlink.GeneralC return _c } -// GetDB provides a mock function with given fields: +// GetDB provides a mock function with no fields func (_m *Application) GetDB() sqlutil.DataSource { ret := _m.Called() @@ -591,7 +591,7 @@ func (_c *Application_GetDB_Call) RunAndReturn(run func() sqlutil.DataSource) *A return _c } -// GetExternalInitiatorManager provides a mock function with given fields: +// GetExternalInitiatorManager provides a mock function with no fields func (_m *Application) GetExternalInitiatorManager() webhook.ExternalInitiatorManager { ret := _m.Called() @@ -638,7 +638,7 @@ func (_c *Application_GetExternalInitiatorManager_Call) RunAndReturn(run func() return _c } -// GetFeedsService provides a mock function with given fields: +// GetFeedsService provides a mock function with no fields func (_m *Application) GetFeedsService() feeds.Service { ret := _m.Called() @@ -685,7 +685,7 @@ func (_c *Application_GetFeedsService_Call) RunAndReturn(run func() feeds.Servic return _c } -// GetHealthChecker provides a mock function with given fields: +// GetHealthChecker provides a mock function with no fields func (_m *Application) GetHealthChecker() services.Checker { ret := _m.Called() @@ -732,7 +732,7 @@ func (_c *Application_GetHealthChecker_Call) RunAndReturn(run func() services.Ch return _c } -// GetKeyStore provides a mock function with given fields: +// GetKeyStore provides a mock function with no fields func (_m *Application) GetKeyStore() keystore.Master { ret := _m.Called() @@ -779,7 +779,7 @@ func (_c *Application_GetKeyStore_Call) RunAndReturn(run func() keystore.Master) return _c } -// GetLogger provides a mock function with given fields: +// GetLogger provides a mock function with no fields func (_m *Application) GetLogger() logger.SugaredLogger { ret := _m.Called() @@ -826,7 +826,7 @@ func (_c *Application_GetLogger_Call) RunAndReturn(run func() logger.SugaredLogg return _c } -// GetLoopRegistrarConfig provides a mock function with given fields: +// GetLoopRegistrarConfig provides a mock function with no fields func (_m *Application) GetLoopRegistrarConfig() plugins.RegistrarConfig { ret := _m.Called() @@ -873,7 +873,7 @@ func (_c *Application_GetLoopRegistrarConfig_Call) RunAndReturn(run func() plugi return _c } -// GetLoopRegistry provides a mock function with given fields: +// GetLoopRegistry provides a mock function with no fields func (_m *Application) GetLoopRegistry() *plugins.LoopRegistry { ret := _m.Called() @@ -920,7 +920,7 @@ func (_c *Application_GetLoopRegistry_Call) RunAndReturn(run func() *plugins.Loo return _c } -// GetRelayers provides a mock function with given fields: +// GetRelayers provides a mock function with no fields func (_m *Application) GetRelayers() chainlink.RelayerChainInteroperators { ret := _m.Called() @@ -967,7 +967,7 @@ func (_c *Application_GetRelayers_Call) RunAndReturn(run func() chainlink.Relaye return _c } -// GetWebAuthnConfiguration provides a mock function with given fields: +// GetWebAuthnConfiguration provides a mock function with no fields func (_m *Application) GetWebAuthnConfiguration() sessions.WebAuthnConfiguration { ret := _m.Called() @@ -1012,7 +1012,7 @@ func (_c *Application_GetWebAuthnConfiguration_Call) RunAndReturn(run func() ses return _c } -// ID provides a mock function with given fields: +// ID provides a mock function with no fields func (_m *Application) ID() uuid.UUID { ret := _m.Called() @@ -1059,7 +1059,7 @@ func (_c *Application_ID_Call) RunAndReturn(run func() uuid.UUID) *Application_I return _c } -// JobORM provides a mock function with given fields: +// JobORM provides a mock function with no fields func (_m *Application) JobORM() job.ORM { ret := _m.Called() @@ -1106,7 +1106,7 @@ func (_c *Application_JobORM_Call) RunAndReturn(run func() job.ORM) *Application return _c } -// JobSpawner provides a mock function with given fields: +// JobSpawner provides a mock function with no fields func (_m *Application) JobSpawner() job.Spawner { ret := _m.Called() @@ -1153,7 +1153,7 @@ func (_c *Application_JobSpawner_Call) RunAndReturn(run func() job.Spawner) *App return _c } -// PipelineORM provides a mock function with given fields: +// PipelineORM provides a mock function with no fields func (_m *Application) PipelineORM() pipeline.ORM { ret := _m.Called() @@ -1413,7 +1413,7 @@ func (_c *Application_RunWebhookJobV2_Call) RunAndReturn(run func(context.Contex return _c } -// SecretGenerator provides a mock function with given fields: +// SecretGenerator provides a mock function with no fields func (_m *Application) SecretGenerator() chainlink.SecretGenerator { ret := _m.Called() @@ -1552,7 +1552,7 @@ func (_c *Application_Start_Call) RunAndReturn(run func(context.Context) error) return _c } -// Stop provides a mock function with given fields: +// Stop provides a mock function with no fields func (_m *Application) Stop() error { ret := _m.Called() @@ -1597,7 +1597,7 @@ func (_c *Application_Stop_Call) RunAndReturn(run func() error) *Application_Sto return _c } -// TxmStorageService provides a mock function with given fields: +// TxmStorageService provides a mock function with no fields func (_m *Application) TxmStorageService() txmgr.EvmTxStore { ret := _m.Called() @@ -1644,7 +1644,7 @@ func (_c *Application_TxmStorageService_Call) RunAndReturn(run func() txmgr.EvmT return _c } -// WakeSessionReaper provides a mock function with given fields: +// WakeSessionReaper provides a mock function with no fields func (_m *Application) WakeSessionReaper() { _m.Called() } @@ -1672,7 +1672,7 @@ func (_c *Application_WakeSessionReaper_Call) Return() *Application_WakeSessionR } func (_c *Application_WakeSessionReaper_Call) RunAndReturn(run func()) *Application_WakeSessionReaper_Call { - _c.Call.Return(run) + _c.Run(run) return _c } diff --git a/core/internal/mocks/flags.go b/core/internal/mocks/flags.go index 538af708893..53e340b0262 100644 --- a/core/internal/mocks/flags.go +++ b/core/internal/mocks/flags.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -147,7 +147,7 @@ func (_c *Flags_AddAccess_Call) RunAndReturn(run func(*bind.TransactOpts, common return _c } -// Address provides a mock function with given fields: +// Address provides a mock function with no fields func (_m *Flags) Address() common.Address { ret := _m.Called() diff --git a/core/internal/mocks/flux_aggregator.go b/core/internal/mocks/flux_aggregator.go index 9dd63173fb1..9360a22fba5 100644 --- a/core/internal/mocks/flux_aggregator.go +++ b/core/internal/mocks/flux_aggregator.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -149,7 +149,7 @@ func (_c *FluxAggregator_AcceptOwnership_Call) RunAndReturn(run func(*bind.Trans return _c } -// Address provides a mock function with given fields: +// Address provides a mock function with no fields func (_m *FluxAggregator) Address() common.Address { ret := _m.Called() diff --git a/core/internal/testutils/httptest/httptest.go b/core/internal/testutils/httptest/httptest.go index a1bd941fb02..69549ae3e45 100644 --- a/core/internal/testutils/httptest/httptest.go +++ b/core/internal/testutils/httptest/httptest.go @@ -12,7 +12,8 @@ import ( // NewTestHTTPClient returns a real HTTP client that may only make requests to // localhost func NewTestLocalOnlyHTTPClient() *http.Client { - tr := http.DefaultTransport.(*http.Transport).Clone() + // Don't use the default transport, we want zero limits and zero timeouts + tr := &http.Transport{} tr.DialContext = testDialContext tr.DisableCompression = true return &http.Client{Transport: tr} diff --git a/core/internal/testutils/testutils.go b/core/internal/testutils/testutils.go index 53b555c0e8b..c2f7351186e 100644 --- a/core/internal/testutils/testutils.go +++ b/core/internal/testutils/testutils.go @@ -126,19 +126,7 @@ func WaitTimeout(t *testing.T) time.Duration { // Context returns a context with the test's deadline, if available. func Context(tb testing.TB) context.Context { - ctx := context.Background() - var cancel func() - switch t := tb.(type) { - case *testing.T: - if d, ok := t.Deadline(); ok { - ctx, cancel = context.WithDeadline(ctx, d) - } - } - if cancel == nil { - ctx, cancel = context.WithCancel(ctx) - } - tb.Cleanup(cancel) - return ctx + return tests.Context(tb) } // MustParseURL parses the URL or fails the test diff --git a/core/logger/logger_mocks.go b/core/logger/logger_mocks.go index 643f5ff141f..09b303e02d0 100644 --- a/core/logger/logger_mocks.go +++ b/core/logger/logger_mocks.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package logger @@ -58,7 +58,7 @@ func (_c *MockLogger_Critical_Call) Return() *MockLogger_Critical_Call { } func (_c *MockLogger_Critical_Call) RunAndReturn(run func(...interface{})) *MockLogger_Critical_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -102,7 +102,7 @@ func (_c *MockLogger_Criticalf_Call) Return() *MockLogger_Criticalf_Call { } func (_c *MockLogger_Criticalf_Call) RunAndReturn(run func(string, ...interface{})) *MockLogger_Criticalf_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -146,7 +146,7 @@ func (_c *MockLogger_Criticalw_Call) Return() *MockLogger_Criticalw_Call { } func (_c *MockLogger_Criticalw_Call) RunAndReturn(run func(string, ...interface{})) *MockLogger_Criticalw_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -188,7 +188,7 @@ func (_c *MockLogger_Debug_Call) Return() *MockLogger_Debug_Call { } func (_c *MockLogger_Debug_Call) RunAndReturn(run func(...interface{})) *MockLogger_Debug_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -232,7 +232,7 @@ func (_c *MockLogger_Debugf_Call) Return() *MockLogger_Debugf_Call { } func (_c *MockLogger_Debugf_Call) RunAndReturn(run func(string, ...interface{})) *MockLogger_Debugf_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -276,7 +276,7 @@ func (_c *MockLogger_Debugw_Call) Return() *MockLogger_Debugw_Call { } func (_c *MockLogger_Debugw_Call) RunAndReturn(run func(string, ...interface{})) *MockLogger_Debugw_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -318,7 +318,7 @@ func (_c *MockLogger_Error_Call) Return() *MockLogger_Error_Call { } func (_c *MockLogger_Error_Call) RunAndReturn(run func(...interface{})) *MockLogger_Error_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -362,7 +362,7 @@ func (_c *MockLogger_Errorf_Call) Return() *MockLogger_Errorf_Call { } func (_c *MockLogger_Errorf_Call) RunAndReturn(run func(string, ...interface{})) *MockLogger_Errorf_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -406,7 +406,7 @@ func (_c *MockLogger_Errorw_Call) Return() *MockLogger_Errorw_Call { } func (_c *MockLogger_Errorw_Call) RunAndReturn(run func(string, ...interface{})) *MockLogger_Errorw_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -448,7 +448,7 @@ func (_c *MockLogger_Fatal_Call) Return() *MockLogger_Fatal_Call { } func (_c *MockLogger_Fatal_Call) RunAndReturn(run func(...interface{})) *MockLogger_Fatal_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -492,7 +492,7 @@ func (_c *MockLogger_Fatalf_Call) Return() *MockLogger_Fatalf_Call { } func (_c *MockLogger_Fatalf_Call) RunAndReturn(run func(string, ...interface{})) *MockLogger_Fatalf_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -536,7 +536,7 @@ func (_c *MockLogger_Fatalw_Call) Return() *MockLogger_Fatalw_Call { } func (_c *MockLogger_Fatalw_Call) RunAndReturn(run func(string, ...interface{})) *MockLogger_Fatalw_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -626,7 +626,7 @@ func (_c *MockLogger_Info_Call) Return() *MockLogger_Info_Call { } func (_c *MockLogger_Info_Call) RunAndReturn(run func(...interface{})) *MockLogger_Info_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -670,7 +670,7 @@ func (_c *MockLogger_Infof_Call) Return() *MockLogger_Infof_Call { } func (_c *MockLogger_Infof_Call) RunAndReturn(run func(string, ...interface{})) *MockLogger_Infof_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -714,11 +714,11 @@ func (_c *MockLogger_Infow_Call) Return() *MockLogger_Infow_Call { } func (_c *MockLogger_Infow_Call) RunAndReturn(run func(string, ...interface{})) *MockLogger_Infow_Call { - _c.Call.Return(run) + _c.Run(run) return _c } -// Name provides a mock function with given fields: +// Name provides a mock function with no fields func (_m *MockLogger) Name() string { ret := _m.Called() @@ -849,7 +849,7 @@ func (_c *MockLogger_Panic_Call) Return() *MockLogger_Panic_Call { } func (_c *MockLogger_Panic_Call) RunAndReturn(run func(...interface{})) *MockLogger_Panic_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -893,7 +893,7 @@ func (_c *MockLogger_Panicf_Call) Return() *MockLogger_Panicf_Call { } func (_c *MockLogger_Panicf_Call) RunAndReturn(run func(string, ...interface{})) *MockLogger_Panicf_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -937,7 +937,7 @@ func (_c *MockLogger_Panicw_Call) Return() *MockLogger_Panicw_Call { } func (_c *MockLogger_Panicw_Call) RunAndReturn(run func(string, ...interface{})) *MockLogger_Panicw_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -970,7 +970,7 @@ func (_c *MockLogger_Recover_Call) Return() *MockLogger_Recover_Call { } func (_c *MockLogger_Recover_Call) RunAndReturn(run func(interface{})) *MockLogger_Recover_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -1003,11 +1003,11 @@ func (_c *MockLogger_SetLogLevel_Call) Return() *MockLogger_SetLogLevel_Call { } func (_c *MockLogger_SetLogLevel_Call) RunAndReturn(run func(zapcore.Level)) *MockLogger_SetLogLevel_Call { - _c.Call.Return(run) + _c.Run(run) return _c } -// Sync provides a mock function with given fields: +// Sync provides a mock function with no fields func (_m *MockLogger) Sync() error { ret := _m.Called() @@ -1090,7 +1090,7 @@ func (_c *MockLogger_Trace_Call) Return() *MockLogger_Trace_Call { } func (_c *MockLogger_Trace_Call) RunAndReturn(run func(...interface{})) *MockLogger_Trace_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -1134,7 +1134,7 @@ func (_c *MockLogger_Tracef_Call) Return() *MockLogger_Tracef_Call { } func (_c *MockLogger_Tracef_Call) RunAndReturn(run func(string, ...interface{})) *MockLogger_Tracef_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -1178,7 +1178,7 @@ func (_c *MockLogger_Tracew_Call) Return() *MockLogger_Tracew_Call { } func (_c *MockLogger_Tracew_Call) RunAndReturn(run func(string, ...interface{})) *MockLogger_Tracew_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -1220,7 +1220,7 @@ func (_c *MockLogger_Warn_Call) Return() *MockLogger_Warn_Call { } func (_c *MockLogger_Warn_Call) RunAndReturn(run func(...interface{})) *MockLogger_Warn_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -1264,7 +1264,7 @@ func (_c *MockLogger_Warnf_Call) Return() *MockLogger_Warnf_Call { } func (_c *MockLogger_Warnf_Call) RunAndReturn(run func(string, ...interface{})) *MockLogger_Warnf_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -1308,7 +1308,7 @@ func (_c *MockLogger_Warnw_Call) Return() *MockLogger_Warnw_Call { } func (_c *MockLogger_Warnw_Call) RunAndReturn(run func(string, ...interface{})) *MockLogger_Warnw_Call { - _c.Call.Return(run) + _c.Run(run) return _c } diff --git a/core/scripts/ccip/.example.env b/core/scripts/ccip/.example.env new file mode 100644 index 00000000000..72918dcc3e6 --- /dev/null +++ b/core/scripts/ccip/.example.env @@ -0,0 +1,9 @@ +## DO NOT EDIT THIS FILE. PLEASE COPY TO .env AND EDIT THAT FILE INSTEAD +OWNER_KEY=DEF + +RPC_5=wss://rpc.com +RPC_43113=wss://rpc.com +RPC_420=wss://rpc.com +RPC_11155111=wss://rpc.com +RPC_421613=wss://rpc.com +RPC_80001=wss://rpc.com \ No newline at end of file diff --git a/core/scripts/ccip/ccip-revert-reason/main.go b/core/scripts/ccip/ccip-revert-reason/main.go new file mode 100644 index 00000000000..e357086306e --- /dev/null +++ b/core/scripts/ccip/ccip-revert-reason/main.go @@ -0,0 +1,71 @@ +package main + +import ( + "flag" + "fmt" + + "github.com/ethereum/go-ethereum/ethclient" + + "github.com/smartcontractkit/chainlink/core/scripts/ccip/revert-reason/handler" + "github.com/smartcontractkit/chainlink/core/scripts/ccip/secrets" +) + +var ( + errorCodeString = flag.String("errorCode", "", "Error code string (e.g. 0x08c379a0)") + + chainID = flag.Uint64("chainId", 0, "Chain ID for the transaction (e.g. 420)") + txHash = flag.String("txHash", "", "Transaction hash (e.g. 0x97be8559164442595aba46b5f849c23257905b78e72ee43d9b998b28eee78b84)") + txRequester = flag.String("txRequester", "", "Transaction requester address (e.g. 0xe88ff73814fb891bb0e149f5578796fa41f20242)") + rpcURL = flag.String("rpcURL", "", "RPC URL for the chain (can also be set in env var RPC_)") +) + +func main() { + flag.Usage = func() { + fmt.Println("Usage: go run . [flags]") + fmt.Println("You must provide either an error code string or the transaction details and an RPC URL to decode the error") + flag.PrintDefaults() + } + + flag.Parse() + + if *errorCodeString == "" && (*chainID == 0 || *txHash == "" || *txRequester == "") { + flag.Usage() + return + } + + errorString, err := getErrorString() + if err != nil { + fmt.Printf("Error getting error string: %v\n", err) + return + } + decodedError, err := handler.DecodeErrorStringFromABI(errorString) + if err != nil { + fmt.Printf("Error decoding error string: %v\n", err) + return + } + + fmt.Println(decodedError) +} + +func getErrorString() (string, error) { + if *errorCodeString != "" { + return *errorCodeString, nil + } + + if *rpcURL == "" { + fmt.Printf("RPC URL not provided, looking for RPC_%d env var\n", *chainID) + envRPC := secrets.GetRPC(*chainID) + rpcURL = &envRPC + } + + ec, err := ethclient.Dial(*rpcURL) + if err != nil { + return "", err + } + errString, err := handler.GetErrorForTx(ec, *txHash, *txRequester) + if err != nil { + return "", err + } + + return errString, nil +} diff --git a/core/scripts/ccip/ccip-revert-reason/main_test.go b/core/scripts/ccip/ccip-revert-reason/main_test.go new file mode 100644 index 00000000000..a73a1f7a3ba --- /dev/null +++ b/core/scripts/ccip/ccip-revert-reason/main_test.go @@ -0,0 +1,20 @@ +package main + +import ( + "fmt" + "testing" + + "github.com/smartcontractkit/chainlink/core/scripts/ccip/revert-reason/handler" +) + +func TestRevertReason(t *testing.T) { + errorCodeString := "e1cd55090000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000008408c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002645524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + decodedError, err := handler.DecodeErrorStringFromABI(errorCodeString) + if err != nil { + fmt.Printf("Error decoding error string: %v\n", err) + return + } + + fmt.Println(decodedError) +} diff --git a/core/scripts/ccip/debugreceiver/main.go b/core/scripts/ccip/debugreceiver/main.go new file mode 100644 index 00000000000..db742ed126a --- /dev/null +++ b/core/scripts/ccip/debugreceiver/main.go @@ -0,0 +1,120 @@ +package main + +import ( + "bytes" + "context" + "fmt" + "math/big" + "strings" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/ethclient" +) + +type ccipAny struct { + SourceChainID *big.Int + Sender []byte + Data []byte + Tokens []common.Address + Amounts []*big.Int +} + +func panicErr(err error) { + if err != nil { + panic(err) + } +} + +// ABIEncode is the equivalent of abi.encode. +// See a full set of examples https://github.com/ethereum/go-ethereum/blob/420b78659bef661a83c5c442121b13f13288c09f/accounts/abi/packing_test.go#L31 +func ABIEncode(abiStr string, values ...interface{}) ([]byte, error) { + // Create a dummy method with arguments + inDef := fmt.Sprintf(`[{ "name" : "method", "type": "function", "inputs": %s}]`, abiStr) + inAbi, err := abi.JSON(strings.NewReader(inDef)) + if err != nil { + return nil, err + } + res, err := inAbi.Pack("method", values...) + if err != nil { + return nil, err + } + return res[4:], nil +} + +// ABIDecode is the equivalent of abi.decode. +// See a full set of examples https://github.com/ethereum/go-ethereum/blob/420b78659bef661a83c5c442121b13f13288c09f/accounts/abi/packing_test.go#L31 +func ABIDecode(abiStr string, data []byte) ([]interface{}, error) { + inDef := fmt.Sprintf(`[{ "name" : "method", "type": "function", "outputs": %s}]`, abiStr) + inAbi, err := abi.JSON(strings.NewReader(inDef)) + if err != nil { + return nil, err + } + return inAbi.Unpack("method", data) +} + +func main() { + // User inputs + source, err := ethclient.Dial("TODO goerli URL") + panicErr(err) + dest, err := ethclient.Dial("TODO optimism URL") + panicErr(err) + var ( + requestBlock = int64(7916078) + receiveBlock = int64(2518035) + ccipReceiver = common.HexToAddress("0x9fE056F44510F970d724adA16903ba5D75CC4742") + ) + + log, err := source.FilterLogs(context.Background(), ethereum.FilterQuery{ + FromBlock: big.NewInt(requestBlock), + ToBlock: big.NewInt(requestBlock), + Topics: [][]common.Hash{{common.HexToHash("0x73dfb9df8214728e699dbaaf6ba97aa125afaaba83a5d0de7903062e7c5b3139")}}, // CCIPSendRequested + }) + panicErr(err) + encodedMsg, err := ABIDecode(`[{"components":[ +{"internalType":"uint256","name":"sourceChainId","type":"uint256"}, +{"internalType":"uint64","name":"sequenceNumber","type":"uint64"}, +{"internalType":"address","name":"sender","type":"address"}, +{"internalType":"address","name":"receiver","type":"address"}, +{"internalType":"uint64","name":"nonce","type":"uint64"}, +{"internalType":"bytes","name":"data","type":"bytes"}, +{"internalType":"address[]","name":"tokens","type":"address[]"}, +{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}, +{"internalType":"uint256","name":"gasLimit","type":"uint256"}], +"internalType":"structCCIP.EVM2EVMSubscriptionMessage","name":"message","type":"tuple"}]`, + log[0].Data) + panicErr(err) + send := encodedMsg[0].(struct { + SourceChainID *big.Int `json:"sourceChainId"` + SequenceNumber uint64 `json:"sequenceNumber"` + Sender common.Address `json:"sender"` + Receiver common.Address `json:"receiver"` + Nonce uint64 `json:"nonce"` + Data []uint8 `json:"data"` + Tokens []common.Address `json:"tokens"` + Amounts []*big.Int `json:"amounts"` + GasLimit *big.Int `json:"gasLimit"` + }) + sender, err := ABIEncode(`[{"type":"bytes", "name":"sender"}]`, send.Sender.Bytes()) + panicErr(err) + any2evm, err := ABIEncode(`[{"components":[ +{"internalType":"uint256","name":"sourceChainId","type":"uint256"}, +{"internalType":"bytes","name":"sender","type":"bytes"}, +{"internalType":"bytes","name":"data","type":"bytes"}, +{"internalType":"address[]","name":"tokens","type":"address[]"}, +{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}], +"internalType":"structCCIP.Any2EVMMessage","name":"message","type":"tuple"}]`, + ccipAny{send.SourceChainID, sender, send.Data, send.Tokens, send.Amounts}) + panicErr(err) + a, err := dest.CallContract(context.Background(), ethereum.CallMsg{ + From: common.HexToAddress("0x2b7ab40413da5077e168546ea376920591aee8e7"), // offramp router + To: &ccipReceiver, + Gas: send.GasLimit.Uint64(), + GasPrice: big.NewInt(0), + Data: bytes.Join([][]byte{hexutil.MustDecode("0xa0c6df15"), any2evm}, []byte{}), // ccipReceive selector + AccessList: nil, + }, big.NewInt(receiveBlock)) + fmt.Println(a, err) +} diff --git a/core/scripts/ccip/manual-execution/batch_runner/README.md b/core/scripts/ccip/manual-execution/batch_runner/README.md new file mode 100644 index 00000000000..9a46519b34a --- /dev/null +++ b/core/scripts/ccip/manual-execution/batch_runner/README.md @@ -0,0 +1,22 @@ +# batchrun.py + +This script will run the manual-execution script repeatedly using a CSV file to +supply message IDs and txn hashes. + +## Usage + +Build main.go and copy 'manual-execution' into the same directory as this script. + +Export messages to a file named 'msgs.csv' in the same directory as this script. +CSV file will ignore the first line (header) and each line should have two values separated by a comma. + +The first value is the message ID and the second value is the CCIP send transaction hash. + +Example csv file: +``` +"message_id","transaction_hash" +0x1e221l7db3f193d19353d42e1bcece771e7edar57149a7f30afd31r8aa783e9a,0x03c88qfd30ar54f36a353262a67362838r52029a47h2a31141a0430bda937ba2 +0x1e221l7db3f193d19353d42e1bcece771e7edar57149a7f30afd31r8aa783e9a,0x03c88qfd30ar54f36a353262a67362838r52029a47h2a31141a0430bda937ba2 +0x1e221l7db3f193d19353d42e1bcece771e7edar57149a7f30afd31r8aa783e9a,0x03c88qfd30ar54f36a353262a67362838r52029a47h2a31141a0430bda937ba2 +0x1e221l7db3f193d19353d42e1bcece771e7edar57149a7f30afd31r8aa783e9a,0x03c88qfd30ar54f36a353262a67362838r52029a47h2a31141a0430bda937ba2 +``` diff --git a/core/scripts/ccip/manual-execution/batch_runner/batchrun.py b/core/scripts/ccip/manual-execution/batch_runner/batchrun.py new file mode 100755 index 00000000000..a731914772a --- /dev/null +++ b/core/scripts/ccip/manual-execution/batch_runner/batchrun.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 + +import subprocess +import os +import tempfile +import json + +binary_name = "./manual-execution" +input_msgs = "msgs.csv" + +# global config +src_rpc = "" +dest_rpc = "" +dest_owner_key = "" +commit_store = "" +off_ramp = "" +on_ramp = "" +dest_start_block = 11063581 # set to block where the messages commit report was written. +gas_limit_override = 2000000 # you can change this or leave it as is. + +lines = open(input_msgs, "r").read().split("\n")[1:] + +for i, pairs in enumerate(lines): + # per msg config + parts = pairs.split(",") + if len(parts) != 2: + if pairs != "": + print("skipping CSV line with unexpected format: %s" % pairs) + continue + + msg_id = parts[0] + ccip_send_tx = parts[1] + + print("[%d/%d] >>> %s %s" % (i, len(lines), ccip_send_tx, msg_id)) + + config = { + "source_chain_tx": ccip_send_tx, + "ccip_msg_id": msg_id, + "src_rpc": src_rpc, + "dest_rpc": dest_rpc, + "dest_owner_key": dest_owner_key, + "commit_store": commit_store, + "off_ramp": off_ramp, + "dest_start_block": dest_start_block, + "gas_limit_override": gas_limit_override + } + json_config = json.dumps(config) + + with open("config.json", 'w') as f: + f.write(json_config) + + try: + subprocess.run([binary_name]) + except subprocess.CalledProcessError as e: + print("called process error: ", e) diff --git a/core/scripts/ccip/manual-execution/config.json b/core/scripts/ccip/manual-execution/config.json new file mode 100644 index 00000000000..8c8832c8487 --- /dev/null +++ b/core/scripts/ccip/manual-execution/config.json @@ -0,0 +1,12 @@ +{ + "src_rpc": "", + "dest_rpc": "", + "dest_owner_key": "", + "commit_store": "0xd2Aa03c8C6E6a8E227223E72f314d4398ABe6eD0", + "off_ramp": "0x60475789dF0d8739cda56aF1D914749A5b48B3f7", + "on_ramp": "0xBb0e1066888F9Ef72824f63fd2067ff469378f6F", + "dest_start_block": 0, + "source_chain_tx": "0x517f6d4742568d531bc9b980bc7f82460a5012fce5dd7c57ec703444f88f5d92", + "ccip_msg_id": "0xba2312c236dd9f83ccd22ff6636fca5af739abb0cdc9824b8f59ec9824a5daf1", + "dest_deployed_at": 3043616 +} \ No newline at end of file diff --git a/core/scripts/ccip/manual-execution/go.mod b/core/scripts/ccip/manual-execution/go.mod new file mode 100644 index 00000000000..91e028c9314 --- /dev/null +++ b/core/scripts/ccip/manual-execution/go.mod @@ -0,0 +1,33 @@ +module manual-execution + +go 1.20 + +require ( + github.com/ethereum/go-ethereum v1.11.3 + github.com/pkg/errors v0.9.1 + github.com/smartcontractkit/chain-selectors v1.0.35 + go.uber.org/multierr v1.1.0 + golang.org/x/crypto v0.1.0 +) + +require ( + github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect + github.com/deckarep/golang-set/v2 v2.1.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/go-ole/go-ole v1.2.1 // indirect + github.com/go-stack/stack v1.8.1 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/gorilla/websocket v1.4.2 // indirect + github.com/mr-tron/base58 v1.2.0 // indirect + github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect + github.com/tklauser/go-sysconf v0.3.5 // indirect + github.com/tklauser/numcpus v0.2.2 // indirect + go.uber.org/atomic v1.3.2 // indirect + golang.org/x/sys v0.5.0 // indirect + gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +exclude github.com/sourcegraph/sourcegraph/lib v0.0.0-20221216004406-749998a2ac74 diff --git a/core/scripts/ccip/manual-execution/go.sum b/core/scripts/ccip/manual-execution/go.sum new file mode 100644 index 00000000000..3d4ea701977 --- /dev/null +++ b/core/scripts/ccip/manual-execution/go.sum @@ -0,0 +1,107 @@ +github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= +github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= +github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= +github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 h1:ytcWPaNPhNoGMWEhDvS3zToKcDpRsLuRolQJBVGdozk= +github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= +github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= +github.com/ethereum/go-ethereum v1.11.3 h1:uuBkYUJW9aY5JYi3+sqLHz+XWyo5fmn/ab9XcbtVDTU= +github.com/ethereum/go-ethereum v1.11.3/go.mod h1:rBUvAl5cdVrAei9q5lgOU7RSEuPJk1nlBDnS/YSoKQE= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= +github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= +github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= +github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= +github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/golang-jwt/jwt/v4 v4.3.0 h1:kHL1vqdqWNfATmA0FNMdmZNMyZI1U6O31X4rlIPoBog= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= +github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e h1:pIYdhNkDh+YENVNi3gto8n9hAmRxKxoar0iE6BLucjw= +github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= +github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= +github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= +github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= +github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= +github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= +github.com/prometheus/common v0.39.0 h1:oOyhkDq05hPZKItWVBkJ6g6AtGxi+fy7F4JvUV8uhsI= +github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/smartcontractkit/chain-selectors v1.0.35 h1:k7iJqChFbH10WFpahjDtDJoYyDz4qRNq6ReIB41M8Tg= +github.com/smartcontractkit/chain-selectors v1.0.35/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= +github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= +github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= +github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= +github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= +github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/exp v0.0.0-20230206171751-46f607a40771 h1:xP7rWLUr1e1n2xkK5YB4LI0hPEy3LJC6Wk+D4pGlOJg= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/time v0.0.0-20220922220347-f3bd1da661af h1:Yx9k8YCG3dvF87UAn2tu2HQLf2dt/eR1bXxpLMWeH+Y= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/core/scripts/ccip/manual-execution/helpers/contractmodels.go b/core/scripts/ccip/manual-execution/helpers/contractmodels.go new file mode 100644 index 00000000000..000b32dd39a --- /dev/null +++ b/core/scripts/ccip/manual-execution/helpers/contractmodels.go @@ -0,0 +1,85 @@ +package helpers + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" +) + +type CommitStoreReportAccepted struct { + Report ICommitStoreCommitReport + Raw types.Log +} + +type ICommitStoreCommitReport struct { + PriceUpdates InternalPriceUpdates + Interval ICommitStoreInterval + MerkleRoot [32]byte +} + +type InternalGasPriceUpdate struct { + DestChainSelector uint64 + UsdPerUnitGas *big.Int +} + +type InternalPriceUpdates struct { + TokenPriceUpdates []InternalTokenPriceUpdate + GasPriceUpdates []InternalGasPriceUpdate +} + +type InternalTokenPriceUpdate struct { + SourceToken common.Address + UsdPerToken *big.Int +} + +type ICommitStoreInterval struct { + Min uint64 + Max uint64 +} + +type InternalEVM2EVMMessage struct { + SourceChainSelector uint64 + Sender common.Address + Receiver common.Address + SequenceNumber uint64 + GasLimit *big.Int + Strict bool + Nonce uint64 + FeeToken common.Address + FeeTokenAmount *big.Int + Data []byte + TokenAmounts []ClientEVMTokenAmount + SourceTokenData [][]byte + MessageId [32]byte +} + +type ClientEVMTokenAmount struct { + Token common.Address + Amount *big.Int +} + +type SendRequestedEvent struct { + Message InternalEVM2EVMMessage + Raw types.Log +} + +type InternalExecutionReport struct { + Messages []InternalEVM2EVMMessage + OffchainTokenData [][][]byte + Proofs [][32]byte + ProofFlagBits *big.Int +} + +type EVM2EVMOffRampExecutionStateChanged struct { + SequenceNumber uint64 + MessageId [32]byte + State uint8 + ReturnData []byte + Raw types.Log +} + +type EVM2EVMOffRampGasLimitOverride struct { + ReceiverExecutionGasLimit *big.Int + TokenGasOverrides []*big.Int +} diff --git a/core/scripts/ccip/manual-execution/helpers/contractwrappers.go b/core/scripts/ccip/manual-execution/helpers/contractwrappers.go new file mode 100644 index 00000000000..027577b9126 --- /dev/null +++ b/core/scripts/ccip/manual-execution/helpers/contractwrappers.go @@ -0,0 +1,189 @@ +package helpers + +import ( + "fmt" + "strings" + + "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/ethclient" + "github.com/ethereum/go-ethereum/event" +) + +const ( + OffRampABI = "[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"commitStore\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"armProxy\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"internalType\":\"contractIERC20[]\",\"name\":\"sourceTokens\",\"type\":\"address[]\"},{\"internalType\":\"contractIPool[]\",\"name\":\"pools\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyExecuted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BadARMSignal\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CommitStoreAlreadyInUse\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"error\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"message\",\"type\":\"string\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidMessageId\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidSourceChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTokenPoolConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualSize\",\"type\":\"uint256\"}],\"name\":\"MessageTooLarge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdminOrOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PoolDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"PriceNotFoundForToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"error\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"error\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenPoolMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"commitStore\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"armProxy\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"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\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"ExecutionStateChanged\",\"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\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"name\":\"PoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"name\":\"PoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SkippedIncorrectNonce\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SkippedSenderWithPreviousRampMessageInflight\",\"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\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"internalType\":\"structInternal.PoolUpdate[]\",\"name\":\"removes\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"internalType\":\"structInternal.PoolUpdate[]\",\"name\":\"adds\",\"type\":\"tuple[]\"}],\"name\":\"applyPoolUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"strict\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[]\",\"name\":\"sourceTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.EVM2EVMMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"sourceToken\",\"type\":\"address\"}],\"name\":\"getDestinationToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDestinationTokens\",\"outputs\":[{\"internalType\":\"contractIERC20[]\",\"name\":\"destTokens\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"}],\"internalType\":\"structEVM2EVMOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"destToken\",\"type\":\"address\"}],\"name\":\"getPoolByDestToken\",\"outputs\":[{\"internalType\":\"contractIPool\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"sourceToken\",\"type\":\"address\"}],\"name\":\"getPoolBySourceToken\",\"outputs\":[{\"internalType\":\"contractIPool\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"getSenderNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"commitStore\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"armProxy\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedTokens\",\"outputs\":[{\"internalType\":\"contractIERC20[]\",\"name\":\"sourceTokens\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitters\",\"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\":[{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"strict\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[]\",\"name\":\"sourceTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.EVM2EVMMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReport\",\"name\":\"report\",\"type\":\"tuple\"},{\"internalType\":\"uint256[]\",\"name\":\"gasLimitOverrides\",\"type\":\"uint256[]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"setAdmin\",\"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\":\"onchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setOCR2Config\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"setRateLimiterConfig\",\"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\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"transmit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]" + CommitStoreABI = "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"armProxy\",\"type\":\"address\"}],\"internalType\":\"structCommitStore.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"BadARMSignal\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidCommitStoreConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"message\",\"type\":\"string\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structCommitStore.Interval\",\"name\":\"interval\",\"type\":\"tuple\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PausedError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleReport\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"armProxy\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structCommitStore.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structCommitStore.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"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\":\"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\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structCommitStore.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structCommitStore.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"ReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"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\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"}],\"internalType\":\"structCommitStore.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceEpochAndRound\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"armProxy\",\"type\":\"address\"}],\"internalType\":\"structCommitStore.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitters\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isARMHealthy\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"isBlessed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isUnpausedAndARMHealthy\",\"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\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"rootToReset\",\"type\":\"bytes32[]\"}],\"name\":\"resetUnblessedRoots\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint40\",\"name\":\"latestPriceEpochAndRound\",\"type\":\"uint40\"}],\"name\":\"setLatestPriceEpochAndRound\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"}],\"name\":\"setMinSeqNr\",\"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\":\"onchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setOCR2Config\",\"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\":\"report\",\"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\":\"bytes32[]\",\"name\":\"hashedLeaves\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"name\":\"verify\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]" + OnRampABI = "[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"internalType\":\"uint96\",\"name\":\"maxNopFeesJuels\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"prevOnRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"armProxy\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"}],\"internalType\":\"structEVM2EVMOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"internalType\":\"structInternal.PoolUpdate[]\",\"name\":\"tokensAndPools\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structEVM2EVMOnRamp.FeeTokenConfigArgs[]\",\"name\":\"feeTokenConfigs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"}],\"internalType\":\"structEVM2EVMOnRamp.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"nop\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"weight\",\"type\":\"uint16\"}],\"internalType\":\"structEVM2EVMOnRamp.NopAndWeight[]\",\"name\":\"nopsAndWeights\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BadARMSignal\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"nop\",\"type\":\"address\"}],\"name\":\"InvalidNopAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTokenPoolConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidWithdrawParams\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LinkBalanceNotSettled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MaxFeeBalanceReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MessageGasLimitTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualSize\",\"type\":\"uint256\"}],\"name\":\"MessageTooLarge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoFeesToPay\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoNopsToPay\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"NotAFeeToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdminOrOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdminOrNop\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"PoolDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"PriceNotFoundForToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SourceTokenDataTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenPoolMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyNops\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"strict\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[]\",\"name\":\"sourceTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2EVMMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"internalType\":\"uint96\",\"name\":\"maxNopFeesJuels\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"prevOnRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"armProxy\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMOnRamp.FeeTokenConfigArgs[]\",\"name\":\"feeConfig\",\"type\":\"tuple[]\"}],\"name\":\"FeeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"nop\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NopPaid\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nopWeightsTotal\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"nop\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"weight\",\"type\":\"uint16\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMOnRamp.NopAndWeight[]\",\"name\":\"nopsAndWeights\",\"type\":\"tuple[]\"}],\"name\":\"NopsSet\",\"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\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"name\":\"PoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"name\":\"PoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMOnRamp.TokenTransferFeeConfigArgs[]\",\"name\":\"transferFeeConfig\",\"type\":\"tuple[]\"}],\"name\":\"TokenTransferFeeConfigSet\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"internalType\":\"structInternal.PoolUpdate[]\",\"name\":\"removes\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"internalType\":\"structInternal.PoolUpdate[]\",\"name\":\"adds\",\"type\":\"tuple[]\"}],\"name\":\"applyPoolUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"}],\"name\":\"forwardFromRouter\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"}],\"internalType\":\"structEVM2EVMOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getFeeTokenConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structEVM2EVMOnRamp.FeeTokenConfig\",\"name\":\"feeTokenConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNopFeesJuels\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNops\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"nop\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"weight\",\"type\":\"uint16\"}],\"internalType\":\"structEVM2EVMOnRamp.NopAndWeight[]\",\"name\":\"nopsAndWeights\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256\",\"name\":\"weightsTotal\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"sourceToken\",\"type\":\"address\"}],\"name\":\"getPoolBySourceToken\",\"outputs\":[{\"internalType\":\"contractIPool\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"getSenderNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"internalType\":\"uint96\",\"name\":\"maxNopFeesJuels\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"prevOnRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"armProxy\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMOnRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenTransferFeeConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"}],\"internalType\":\"structEVM2EVMOnRamp.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"linkAvailableForPayment\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"payNops\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"setAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"}],\"internalType\":\"structEVM2EVMOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structEVM2EVMOnRamp.FeeTokenConfigArgs[]\",\"name\":\"feeTokenConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setFeeTokenConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"nop\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"weight\",\"type\":\"uint16\"}],\"internalType\":\"structEVM2EVMOnRamp.NopAndWeight[]\",\"name\":\"nopsAndWeights\",\"type\":\"tuple[]\"}],\"name\":\"setNops\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"setRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"}],\"internalType\":\"structEVM2EVMOnRamp.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setTokenTransferFeeConfig\",\"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\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawNonLinkFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" +) + +func DecodeEvents( + ethC *ethclient.Client, + opts *bind.FilterOpts, + address, contractABI, eventName string, + query ...[]interface{}, +) (*bind.BoundContract, chan types.Log, event.Subscription, error) { + contractAddress := common.HexToAddress(address) + abi, err := abi.JSON(strings.NewReader(contractABI)) + if err != nil { + return nil, nil, nil, err + } + boundContract := bind.NewBoundContract(contractAddress, abi, ethC, ethC, ethC) + logs, subs, err := boundContract.FilterLogs(opts, eventName, query...) + if err != nil { + return nil, nil, nil, err + } + return boundContract, logs, subs, err +} + +type logIterator struct { + Raw types.Log + Contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *logIterator) Next() bool { + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *logIterator) Error() error { + return it.fail +} + +func (it *logIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +func FilterCCIPSendRequested(chain *ethclient.Client, opts *bind.FilterOpts, onRampAddr string) (*logIterator, error) { + onRampContract, logs, sub, err := DecodeEvents(chain, opts, onRampAddr, OnRampABI, "CCIPSendRequested") + if err != nil { + return nil, err + } + return &logIterator{ + Contract: onRampContract, + event: "CCIPSendRequested", + logs: logs, + sub: sub, + }, nil +} + +func (it *logIterator) SendRequestedEventFromLog() (*SendRequestedEvent, error) { + event := new(SendRequestedEvent) + err := it.Contract.UnpackLog(event, "CCIPSendRequested", it.Raw) + if err != nil { + return nil, err + } + return event, nil +} + +func (it *logIterator) CommitStoreReportAcceptedFromLog() (*CommitStoreReportAccepted, error) { + event := new(CommitStoreReportAccepted) + err := it.Contract.UnpackLog(event, "ReportAccepted", it.Raw) + if err != nil { + return nil, err + } + return event, nil +} + +func FilterReportAccepted(chain *ethclient.Client, opts *bind.FilterOpts, commitStoreAddr string) (*logIterator, error) { + commitStoreContract, logs, sub, err := DecodeEvents(chain, opts, commitStoreAddr, CommitStoreABI, "ReportAccepted") + if err != nil { + return nil, err + } + return &logIterator{ + Contract: commitStoreContract, + event: "ReportAccepted", + logs: logs, + sub: sub, + }, nil +} + +func FilterExecutionStateChanged( + chain *ethclient.Client, + opts *bind.FilterOpts, + offRampAddr string, + sequenceNumber []uint64, + messageId [][32]byte, +) (int, error) { + var sequenceNumberRule []interface{} + for _, sequenceNumberItem := range sequenceNumber { + sequenceNumberRule = append(sequenceNumberRule, sequenceNumberItem) + } + var messageIdRule []interface{} + for _, messageIdItem := range messageId { + messageIdRule = append(messageIdRule, messageIdItem) + } + offRamp, logs, sub, err := DecodeEvents(chain, opts, offRampAddr, OffRampABI, "ExecutionStateChanged", sequenceNumberRule, messageIdRule) + if err != nil { + return 0, err + } + it := &logIterator{ + Contract: offRamp, + event: "ExecutionStateChanged", + logs: logs, + sub: sub, + } + + executionState := -1 + for it.Next() && executionState != 2 { + execStateEvent := new(EVM2EVMOffRampExecutionStateChanged) + err = it.Contract.UnpackLog(execStateEvent, "ExecutionStateChanged", it.Raw) + if err != nil { + return 0, err + } + executionState = int(execStateEvent.State) + } + + if executionState == -1 { + return 0, fmt.Errorf("no ExecutionStateChanged found for seq num %v and msg id %v", sequenceNumber, messageId) + } + return executionState, nil +} + +func ManuallyExecute( + ethC *ethclient.Client, + opts *bind.TransactOpts, + address string, + report InternalExecutionReport, + gasLimitOverrides []*EVM2EVMOffRampGasLimitOverride, +) (*types.Transaction, error) { + offRampContract := common.HexToAddress(address) + abi, err := abi.JSON(strings.NewReader(OffRampABI)) + if err != nil { + return nil, err + } + boundContract := bind.NewBoundContract(offRampContract, abi, ethC, ethC, ethC) + return boundContract.Transact(opts, "manuallyExecute", report, gasLimitOverrides) +} diff --git a/core/scripts/ccip/manual-execution/helpers/execReport.go b/core/scripts/ccip/manual-execution/helpers/execReport.go new file mode 100644 index 00000000000..efb593d2b44 --- /dev/null +++ b/core/scripts/ccip/manual-execution/helpers/execReport.go @@ -0,0 +1,325 @@ +package helpers + +import ( + "bytes" + "fmt" + "math/big" + "strings" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/core/types" + "github.com/pkg/errors" + "golang.org/x/crypto/sha3" +) + +// Hash contains all supported hash formats. +// Add additional hash types e.g. [20]byte as needed here. +type Hash interface { + [32]byte +} + +type Ctx[H Hash] interface { + Hash(l []byte) H + HashInternal(a, b H) H + ZeroHash() H +} + +type keccakCtx struct { + InternalDomainSeparator [32]byte +} + +func NewKeccakCtx() Ctx[[32]byte] { + return keccakCtx{ + InternalDomainSeparator: [32]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + } +} + +// Hash hashes a byte array with Keccak256 +func (k keccakCtx) Hash(l []byte) [32]byte { + // Note this Keccak256 cannot error https://github.com/golang/crypto/blob/master/sha3/sha3.go#L126 + // if we start supporting hashing algos which do, we can change this API to include an error. + return Keccak256Fixed(l) +} + +// HashInternal orders two [32]byte values and prepends them with +// a separator before hashing them. +func (k keccakCtx) HashInternal(a, b [32]byte) [32]byte { + if bytes.Compare(a[:], b[:]) < 0 { + return k.Hash(append(k.InternalDomainSeparator[:], append(a[:], b[:]...)...)) + } + return k.Hash(append(k.InternalDomainSeparator[:], append(b[:], a[:]...)...)) +} + +// ZeroHash returns the zero hash: 0xFF..FF +// We use bytes32 0xFF..FF for zeroHash in the CCIP research spec, this needs to match. +// This value is chosen since it is unlikely to be the result of a hash, and cannot match any internal node preimage. +func (k keccakCtx) ZeroHash() [32]byte { + var zeroes [32]byte + for i := 0; i < 32; i++ { + zeroes[i] = 0xFF + } + return zeroes +} + +var ( + LeafDomainSeparator = [1]byte{0x00} +) + +type LeafHasher struct { + geABI abi.ABI + metaDataHash [32]byte + ctx Ctx[[32]byte] +} + +func (t *LeafHasher) HashLeaf(log types.Log) ([32]byte, error) { + event, err := t.ParseEVM2EVMLog(log) + if err != nil { + return [32]byte{}, err + } + encodedTokens, err := ABIEncode(`[{"components": [{"name": "token","type": "address"}, {"name": "amount", "type": "uint256"}],"type": "tuple[]"}]`, event.Message.TokenAmounts) + if err != nil { + return [32]byte{}, err + } + + bytesArray, err := abi.NewType("bytes[]", "bytes[]", nil) + if err != nil { + return [32]byte{}, err + } + + encodedSourceTokenData, err := abi.Arguments{abi.Argument{Type: bytesArray}}.PackValues([]interface{}{event.Message.SourceTokenData}) + if err != nil { + return [32]byte{}, err + } + + packedFixedSizeValues, err := ABIEncode( + `[ +{"name": "sender", "type":"address"}, +{"name": "receiver", "type":"address"}, +{"name": "sequenceNumber", "type":"uint64"}, +{"name": "gasLimit", "type":"uint256"}, +{"name": "strict", "type":"bool"}, +{"name": "nonce", "type":"uint64"}, +{"name": "feeToken","type": "address"}, +{"name": "feeTokenAmount","type": "uint256"} +]`, + event.Message.Sender, + event.Message.Receiver, + event.Message.SequenceNumber, + event.Message.GasLimit, + event.Message.Strict, + event.Message.Nonce, + event.Message.FeeToken, + event.Message.FeeTokenAmount, + ) + if err != nil { + return [32]byte{}, err + } + fixedSizeValuesHash := t.ctx.Hash(packedFixedSizeValues) + + packedValues, err := ABIEncode( + `[ +{"name": "leafDomainSeparator","type":"bytes1"}, +{"name": "metadataHash", "type":"bytes32"}, +{"name": "fixedSizeValuesHash", "type":"bytes32"}, +{"name": "dataHash", "type":"bytes32"}, +{"name": "tokenAmountsHash", "type":"bytes32"}, +{"name": "sourceTokenDataHash", "type":"bytes32"} +]`, + LeafDomainSeparator, + t.metaDataHash, + fixedSizeValuesHash, + t.ctx.Hash(event.Message.Data), + t.ctx.Hash(encodedTokens), + t.ctx.Hash(encodedSourceTokenData), + ) + if err != nil { + return [32]byte{}, err + } + return t.ctx.Hash(packedValues), nil +} + +func (t *LeafHasher) ParseEVM2EVMLog(log types.Log) (*SendRequestedEvent, error) { + event := new(SendRequestedEvent) + err := bind.NewBoundContract(common.Address{}, t.geABI, nil, nil, nil).UnpackLog(event, "CCIPSendRequested", log) + return event, err +} + +func NewLeafHasher(sourceChainId uint64, destChainId uint64, onRampId common.Address, ctx Ctx[[32]byte]) *LeafHasher { + geABI, _ := abi.JSON(strings.NewReader(OnRampABI)) + return &LeafHasher{ + geABI: geABI, + metaDataHash: getMetaDataHash(ctx, ctx.Hash([]byte("EVM2EVMMessageHashV2")), sourceChainId, onRampId, destChainId), + ctx: ctx, + } +} + +func Keccak256Fixed(in []byte) [32]byte { + hash := sha3.NewLegacyKeccak256() + // Note this Keccak256 cannot error https://github.com/golang/crypto/blob/master/sha3/sha3.go#L126 + // if we start supporting hashing algos which do, we can change this API to include an error. + hash.Write(in) + var h [32]byte + copy(h[:], hash.Sum(nil)) + return h +} + +func getMetaDataHash[H Hash](ctx Ctx[H], prefix [32]byte, sourceChainId uint64, onRampId common.Address, destChainId uint64) H { + paddedOnRamp := onRampId.Hash() + return ctx.Hash(ConcatBytes(prefix[:], + math.U256Bytes(big.NewInt(0).SetUint64(sourceChainId)), + math.U256Bytes(big.NewInt(0).SetUint64(destChainId)), paddedOnRamp[:])) +} + +// ConcatBytes appends a bunch of byte arrays into a single byte array +func ConcatBytes(bufs ...[]byte) []byte { + return bytes.Join(bufs, []byte{}) +} + +// ABIEncode is the equivalent of abi.encode. +// See a full set of examples https://github.com/ethereum/go-ethereum/blob/420b78659bef661a83c5c442121b13f13288c09f/accounts/abi/packing_test.go#L31 +func ABIEncode(abiStr string, values ...interface{}) ([]byte, error) { + // Create a dummy method with arguments + inDef := fmt.Sprintf(`[{ "name" : "method", "type": "function", "inputs": %s}]`, abiStr) + inAbi, err := abi.JSON(strings.NewReader(inDef)) + if err != nil { + return nil, err + } + res, err := inAbi.Pack("method", values...) + if err != nil { + return nil, err + } + return res[4:], nil +} + +const ( + SourceFromHashes = true + SourceFromProof = false +) + +type Proof[H Hash] struct { + Hashes []H `json:"hashes"` + SourceFlags []bool `json:"source_flags"` +} + +type singleLayerProof[H Hash] struct { + nextIndices []int + subProof []H + sourceFlags []bool +} + +type Tree[H Hash] struct { + layers [][]H +} + +func NewTree[H Hash](ctx Ctx[H], leafHashes []H) (*Tree[H], error) { + if len(leafHashes) == 0 { + return nil, errors.New("Cannot construct a tree without leaves") + } + var layer = make([]H, len(leafHashes)) + copy(layer, leafHashes) + var layers = [][]H{layer} + var curr int + for len(layer) > 1 { + paddedLayer, nextLayer := computeNextLayer(ctx, layer) + layers[curr] = paddedLayer + curr++ + layers = append(layers, nextLayer) + layer = nextLayer + } + return &Tree[H]{ + layers: layers, + }, nil +} + +// Revive appears confused with the generics "receiver name t should be consistent with previous receiver name p for invalid-type" +// +//revive:disable:receiver-naming +func (t *Tree[H]) String() string { + b := strings.Builder{} + for _, layer := range t.layers { + b.WriteString(fmt.Sprintf("%v", layer)) + } + return b.String() +} + +func (t *Tree[H]) Root() H { + return t.layers[len(t.layers)-1][0] +} + +func (t *Tree[H]) Prove(indices []int) Proof[H] { + var proof Proof[H] + for _, layer := range t.layers[:len(t.layers)-1] { + res := proveSingleLayer(layer, indices) + indices = res.nextIndices + proof.Hashes = append(proof.Hashes, res.subProof...) + proof.SourceFlags = append(proof.SourceFlags, res.sourceFlags...) + } + return proof +} + +func computeNextLayer[H Hash](ctx Ctx[H], layer []H) ([]H, []H) { + if len(layer) == 1 { + return layer, layer + } + if len(layer)%2 != 0 { + layer = append(layer, ctx.ZeroHash()) + } + var nextLayer []H + for i := 0; i < len(layer); i += 2 { + nextLayer = append(nextLayer, ctx.HashInternal(layer[i], layer[i+1])) + } + return layer, nextLayer +} + +func parentIndex(idx int) int { + return idx / 2 +} + +func siblingIndex(idx int) int { + return idx ^ 1 +} + +func proveSingleLayer[H Hash](layer []H, indices []int) singleLayerProof[H] { + var ( + authIndices []int + nextIndices []int + sourceFlags []bool + ) + j := 0 + for j < len(indices) { + x := indices[j] + nextIndices = append(nextIndices, parentIndex(x)) + if j+1 < len(indices) && indices[j+1] == siblingIndex(x) { + j++ + sourceFlags = append(sourceFlags, SourceFromHashes) + } else { + authIndices = append(authIndices, siblingIndex(x)) + sourceFlags = append(sourceFlags, SourceFromProof) + } + j++ + } + var subProof []H + for _, i := range authIndices { + subProof = append(subProof, layer[i]) + } + return singleLayerProof[H]{ + nextIndices: nextIndices, + subProof: subProof, + sourceFlags: sourceFlags, + } +} + +// ProofFlagsToBits transforms a list of boolean proof flags to a *big.Int +// encoded number. +func ProofFlagsToBits(proofFlags []bool) *big.Int { + encodedFlags := big.NewInt(0) + for i := 0; i < len(proofFlags); i++ { + if proofFlags[i] { + encodedFlags.SetBit(encodedFlags, i, 1) + } + } + return encodedFlags +} diff --git a/core/scripts/ccip/manual-execution/helpers/utils.go b/core/scripts/ccip/manual-execution/helpers/utils.go new file mode 100644 index 00000000000..ac04fc70f0e --- /dev/null +++ b/core/scripts/ccip/manual-execution/helpers/utils.go @@ -0,0 +1,47 @@ +package helpers + +import ( + "context" + "fmt" + "log" + "time" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" +) + +func VerifyAddress(addr string) error { + if addr == "" { + return fmt.Errorf("address is blank") + } + if !common.IsHexAddress(addr) { + return fmt.Errorf("address %s is invalid", addr) + } + return nil +} + +func WaitForSuccessfulTxReceipt(client ethereum.TransactionReader, hash common.Hash) error { + ticker := time.NewTicker(5 * time.Second) + defer ticker.Stop() + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Minute) + defer cancel() + for { + select { + case <-ticker.C: + log.Println("[MINING] waiting for tx to be mined...") + receipt, _ := client.TransactionReceipt(context.Background(), hash) + if receipt != nil { + if receipt.Status == types.ReceiptStatusFailed { + return fmt.Errorf("[MINING] ERROR tx reverted %s", hash.Hex()) + } + if receipt.Status == types.ReceiptStatusSuccessful { + log.Println("[MINING] tx mined %s successful", hash.Hex()) + return nil + } + } + case <-ctx.Done(): + return fmt.Errorf("tx not confirmed within time") + } + } +} diff --git a/core/scripts/ccip/manual-execution/main.go b/core/scripts/ccip/manual-execution/main.go new file mode 100644 index 00000000000..35f5de954ed --- /dev/null +++ b/core/scripts/ccip/manual-execution/main.go @@ -0,0 +1,451 @@ +package main + +import ( + "context" + "encoding/hex" + "encoding/json" + "flag" + "fmt" + "log" + "math" + "math/big" + "os" + "strings" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient" + "go.uber.org/multierr" + + chainselectors "github.com/smartcontractkit/chain-selectors" + + "manual-execution/helpers" +) + +const NumberOfBlocks = 20000 + +// Config represents configuration fields +type Config struct { + SrcNodeURL string `json:"src_rpc"` + DestNodeURL string `json:"dest_rpc"` + DestOwner string `json:"dest_owner_key"` + CommitStore string `json:"commit_store"` + OffRamp string `json:"off_ramp"` + DestStartBlock uint64 `json:"dest_start_block"` + SourceChainTx string `json:"source_chain_tx"` + CCIPMsgID string `json:"ccip_msg_id"` + DestDeployedAt uint64 `json:"dest_deployed_at"` + GasLimitOverride uint64 `json:"gas_limit_override"` +} + +type execArgs struct { + cfg Config + seqNum uint64 + msgID [32]byte + sourceChain *ethclient.Client + sourceChainId *big.Int + destChain *ethclient.Client + destUser *bind.TransactOpts + destChainId *big.Int + srcStartBlock *big.Int + destStartBlock uint64 + destLatestBlock uint64 + OnRamp common.Address + tokenGasOverrides []*big.Int +} + +func main() { + configPath := flag.String("configFile", "./config.json", "config for manually executing a failed ccip message "+ + "which has been successfully committed but failed to get executed") + flag.Parse() + + if *configPath == "" { + log.Println("config json is required") + os.Exit(1) + } + cData, err := os.ReadFile(*configPath) + if err != nil { + log.Println("unable to read the json at ", *configPath, "error - ", err) + os.Exit(1) + } + var cfg Config + err = json.Unmarshal(cData, &cfg) + if err != nil { + log.Println("unable to marshal the json at ", *configPath, "error - ", err, `sample json +{ + "src_rpc": "", + "dest_rpc": "", + "dest_owner_key": "", + "commit_store": "", + "off_ramp": "", + "dest_start_block": "", + "ccip_send_tx": "", + "source_start_block": "", + "dest_deployed_at": 0, + "gas_limit_override": 0, +}`) + os.Exit(1) + } + // mandatory fields check + err = cfg.verifyConfig() + if err != nil { + log.Println("config validation failed: \n", err) + os.Exit(1) + } + args := &execArgs{cfg: cfg} + err = args.populateValues() + if err != nil { + log.Println("error instantiating manual execution args ", err) + os.Exit(1) + } + err = args.execute() + if err != nil { + log.Println("manual execution was not successful - ", err) + os.Exit(1) + } +} + +func (cfg Config) verifyConfig() error { + var allErr error + if cfg.SrcNodeURL == "" { + allErr = multierr.Append(allErr, fmt.Errorf("must set src_rpc - source chain rpc\n")) + } + if cfg.DestNodeURL == "" { + allErr = multierr.Append(allErr, fmt.Errorf("must set dest_rpc - destination chain rpc\n")) + } + if cfg.DestOwner == "" { + allErr = multierr.Append(allErr, fmt.Errorf("must set dest_owner_key - destination user private key\n")) + } + if cfg.SourceChainTx == "" { + allErr = multierr.Append(allErr, fmt.Errorf("must set source_chain_tx - txHash of ccip-send request\n")) + } + + if cfg.DestStartBlock == 0 && cfg.DestDeployedAt == 0 { + allErr = multierr.Append(allErr, fmt.Errorf(`must set either of - +dest_deployed_at - the block number before destination contracts were deployed; +dest_start_block - the block number from which events will be filtered at destination chain. +`)) + } + if cfg.GasLimitOverride == 0 { + allErr = multierr.Append(allErr, fmt.Errorf("must set gas_limit_override - new value of gas limit for ccip-send request\n")) + } + err := helpers.VerifyAddress(cfg.CommitStore) + if err != nil { + allErr = multierr.Append(allErr, fmt.Errorf("check the commit_store address - %v\n", err)) + } + err = helpers.VerifyAddress(cfg.OffRamp) + if err != nil { + allErr = multierr.Append(allErr, fmt.Errorf("check the off_ramp address - %v\n", err)) + } + + return allErr +} + +func (args *execArgs) populateValues() error { + var err error + cfg := args.cfg + args.sourceChain, err = ethclient.Dial(cfg.SrcNodeURL) + if err != nil { + return err + } + args.sourceChainId, err = args.sourceChain.ChainID(context.Background()) + if err != nil { + return err + } + + args.destChain, err = ethclient.Dial(cfg.DestNodeURL) + if err != nil { + return err + } + args.destChainId, err = args.destChain.ChainID(context.Background()) + if err != nil { + return err + } + ownerKey, err := crypto.HexToECDSA(cfg.DestOwner) + if err != nil { + return err + } + + args.destUser, err = bind.NewKeyedTransactorWithChainID(ownerKey, args.destChainId) + if err != nil { + return err + } + log.Println("--- Owner address---/n", args.destUser.From.Hex()) + + var txReceipt *types.Receipt + txReceipt, err = args.sourceChain.TransactionReceipt(context.Background(), common.HexToHash(cfg.SourceChainTx)) + if err != nil { + return err + } + args.srcStartBlock = big.NewInt(0).Sub(txReceipt.BlockNumber, big.NewInt(NumberOfBlocks)) + args.destLatestBlock, err = args.destChain.BlockNumber(context.Background()) + if err != nil { + return err + } + + err = args.seqNumFromCCIPSendRequested(txReceipt.Logs) + if err != nil { + return err + } + if args.cfg.DestStartBlock < 1 { + err = args.approxDestStartBlock() + if err != nil { + return err + } + } else { + args.destStartBlock = args.cfg.DestStartBlock + } + return nil +} + +func (args *execArgs) execute() error { + iterator, err := helpers.FilterReportAccepted(args.destChain, &bind.FilterOpts{Start: args.destStartBlock}, args.cfg.CommitStore) + if err != nil { + return err + } + + var commitReport *helpers.ICommitStoreCommitReport + for iterator.Next() { + eventReport, err := iterator.CommitStoreReportAcceptedFromLog() + if err != nil { + return err + } + + if eventReport.Report.Interval.Min <= args.seqNum && eventReport.Report.Interval.Max >= args.seqNum { + commitReport = &eventReport.Report + log.Println("Found root") + break + } + } + if commitReport == nil { + return fmt.Errorf("unable to find seq num %d in commit report", args.seqNum) + } + log.Println("Executing request manually") + seqNr := args.seqNum + // Build a merkle tree for the report + mctx := helpers.NewKeccakCtx() + leafHasher := helpers.NewLeafHasher( + GetCCIPChainSelector(args.sourceChainId.Uint64()), + GetCCIPChainSelector(args.destChainId.Uint64()), + args.OnRamp, + mctx, + ) + + var leaves [][32]byte + var curr, prove int + var tokenData [][][]byte + var msgs []helpers.InternalEVM2EVMMessage + + sendRequestedIterator, err := helpers.FilterCCIPSendRequested(args.sourceChain, &bind.FilterOpts{ + Start: args.srcStartBlock.Uint64(), + }, args.OnRamp.Hex()) + if err != nil { + return err + } + + for sendRequestedIterator.Next() { + event, err := sendRequestedIterator.SendRequestedEventFromLog() + if err != nil { + return err + } + if event.Message.SequenceNumber <= commitReport.Interval.Max && + event.Message.SequenceNumber >= commitReport.Interval.Min { + log.Println("Found seq num in commit report", event.Message.SequenceNumber, commitReport.Interval) + hash, err := leafHasher.HashLeaf(sendRequestedIterator.Raw) + if err != nil { + return err + } + leaves = append(leaves, hash) + if event.Message.SequenceNumber == seqNr && event.Message.MessageId == args.msgID { + log.Printf("Found proving %d %+v\n\n", curr, event.Message) + msgs = append(msgs, event.Message) + + var msgTokenData [][]byte + for range event.Message.TokenAmounts { + msgTokenData = append(msgTokenData, []byte{}) + } + + tokenData = append(tokenData, msgTokenData) + prove = curr + } + curr++ + } + } + + sendRequestedIterator.Close() + if len(msgs) == 0 { + return fmt.Errorf("unable to find msg with seqNr %d", seqNr) + } + + expectedNumberOfLeaves := int(commitReport.Interval.Max) - int(commitReport.Interval.Min) + 1 + if len(leaves) != expectedNumberOfLeaves { + return fmt.Errorf("not enough leaves gather to build a commit root - want %d got %d. Please set NumberOfBlocks const to a higher value", expectedNumberOfLeaves, len(leaves)) + } + + tree, err := helpers.NewTree(mctx, leaves) + if err != nil { + return err + } + if tree.Root() != commitReport.MerkleRoot { + return fmt.Errorf("root doesn't match. cannot execute") + } + + proof := tree.Prove([]int{prove}) + offRampProof := helpers.InternalExecutionReport{ + Messages: msgs, + Proofs: proof.Hashes, + OffchainTokenData: tokenData, + ProofFlagBits: helpers.ProofFlagsToBits(proof.SourceFlags), + } + + gasLimitOverrides := make([]*helpers.EVM2EVMOffRampGasLimitOverride, len(offRampProof.Messages)) + + for range offRampProof.Messages { + evm2evmOffRampGasLimitOverride := &helpers.EVM2EVMOffRampGasLimitOverride{ + ReceiverExecutionGasLimit: big.NewInt(int64(args.cfg.GasLimitOverride)), + TokenGasOverrides: args.tokenGasOverrides, + } + gasLimitOverrides = append(gasLimitOverrides, evm2evmOffRampGasLimitOverride) + } + + // GasLimit may need to be raised if the TX is reverting. Must be set to a value larger than the GasLimitOverride. + // args.destUser.GasLimit = 5000000 + tx, err := helpers.ManuallyExecute(args.destChain, args.destUser, args.cfg.OffRamp, offRampProof, gasLimitOverrides) + if err != nil { + return err + } + // wait for tx confirmation + err = helpers.WaitForSuccessfulTxReceipt(args.destChain, tx.Hash()) + if err != nil { + log.Println("Failures may be due to insufficient gas, try increasing args.destUser.GasLimit.") + return err + } + + // check if the message got successfully delivered + changed, err := helpers.FilterExecutionStateChanged(args.destChain, &bind.FilterOpts{ + Start: args.destStartBlock, + }, args.cfg.OffRamp, []uint64{args.seqNum}, [][32]byte{args.msgID}) + if err != nil { + return err + } + if changed != 2 { + return fmt.Errorf("manual execution did not result in ExecutionStateChanged as success") + } + return nil +} + +func (args *execArgs) seqNumFromCCIPSendRequested(logs []*types.Log) error { + abi, err := abi.JSON(strings.NewReader(helpers.OnRampABI)) + if err != nil { + return err + } + var topic0 common.Hash + for name, abiEvent := range abi.Events { + if name == "CCIPSendRequested" { + topic0 = abiEvent.ID + break + } + } + if topic0 == (common.Hash{}) { + return fmt.Errorf("no CCIPSendRequested event found in ABI") + } + var sendRequestedLogs []types.Log + for _, sendReqLog := range logs { + if sendReqLog.Topics[0] == topic0 && sendReqLog.TxHash == common.HexToHash(args.cfg.SourceChainTx) { + args.OnRamp = sendReqLog.Address + sendRequestedLogs = append(sendRequestedLogs, *sendReqLog) + } + } + + if len(sendRequestedLogs) == 0 { + return fmt.Errorf("no CCIPSendRequested logs found for in txReceipt for txhash %s", args.cfg.SourceChainTx) + } + onRampContract := bind.NewBoundContract(args.OnRamp, abi, args.sourceChain, args.sourceChain, args.sourceChain) + + for _, sendReqLog := range sendRequestedLogs { + var event helpers.SendRequestedEvent + + err = onRampContract.UnpackLog(&event, "CCIPSendRequested", sendReqLog) + if err != nil { + return err + } + + if args.cfg.CCIPMsgID != "" && + "0x"+hex.EncodeToString(event.Message.MessageId[:]) != args.cfg.CCIPMsgID { + continue + } + + args.seqNum = event.Message.SequenceNumber + args.msgID = event.Message.MessageId + return nil + } + + return fmt.Errorf("send request not found in logs") +} + +func (args *execArgs) approxDestStartBlock() error { + sourceBlockHdr, err := args.sourceChain.HeaderByNumber(context.Background(), args.srcStartBlock) + if err != nil { + return err + } + sendTxTime := sourceBlockHdr.Time + maxBlockNum := args.destLatestBlock + // setting this to an approx value of 1000 considering destination chain would have at least 1000 blocks before the transaction started + minBlockNum := args.cfg.DestDeployedAt + closestBlockNum := uint64(math.Floor((float64(maxBlockNum) + float64(minBlockNum)) / 2)) + var closestBlockHdr *types.Header + closestBlockHdr, err = args.destChain.HeaderByNumber(context.Background(), big.NewInt(int64(closestBlockNum))) + if err != nil { + return err + } + // to reduce the number of RPC calls increase the value of blockOffset + blockOffset := uint64(10) + for { + blockNum := closestBlockHdr.Number.Uint64() + if minBlockNum > maxBlockNum { + break + } + timeDiff := math.Abs(float64(closestBlockHdr.Time - sendTxTime)) + // break if the difference in timestamp is lesser than 1 minute + if timeDiff < 60 { + break + } else if closestBlockHdr.Time > sendTxTime { + maxBlockNum = blockNum - 1 + } else { + minBlockNum = blockNum + 1 + } + closestBlockNum = uint64(math.Floor((float64(maxBlockNum) + float64(minBlockNum)) / 2)) + closestBlockHdr, err = args.destChain.HeaderByNumber(context.Background(), big.NewInt(int64(closestBlockNum))) + if err != nil { + return err + } + } + + for { + if closestBlockHdr.Time <= sendTxTime { + break + } + closestBlockNum = closestBlockNum - blockOffset + if closestBlockNum <= 0 { + return fmt.Errorf("approx destination blocknumber not found") + } + closestBlockHdr, err = args.destChain.HeaderByNumber(context.Background(), big.NewInt(int64(closestBlockNum))) + if err != nil { + return err + } + } + args.destStartBlock = closestBlockHdr.Number.Uint64() + log.Printf("using approx destination start block number %d for filtering event", args.destStartBlock) + return nil +} + +func GetCCIPChainSelector(chainId uint64) uint64 { + selector, err := chainselectors.SelectorFromChainId(chainId) + if err != nil { + panic(fmt.Sprintf("no chain selector for %d", chainId)) + } + return selector +} diff --git a/core/scripts/ccip/revert-reason/Makefile b/core/scripts/ccip/revert-reason/Makefile new file mode 100644 index 00000000000..e52d2b27f72 --- /dev/null +++ b/core/scripts/ccip/revert-reason/Makefile @@ -0,0 +1,3 @@ +# Build the CLI binary +build: + go build -o bin/ccip-revert-reason . diff --git a/core/scripts/ccip/revert-reason/README.md b/core/scripts/ccip/revert-reason/README.md new file mode 100644 index 00000000000..9a3aa128526 --- /dev/null +++ b/core/scripts/ccip/revert-reason/README.md @@ -0,0 +1,41 @@ +## Setup + +Before starting: + +1. Create `.env` file based on the example `.env.example` next to the CLI binary. + +2. If you plan to resolve revert reasons from a transaction hash, you will need: + 1. An EVM chain endpoint URL + 2. A from address + +The endpoint URL can be a locally running node (archive mode), or an externally hosted one like +[alchemy](https://www.alchemy.com/). + + + +To see all available commands, run the following: +```bash +go run main.go --help +``` + + +## Usage + +Decoding an error code string (offline): + +```bash +> ./ccip-revert-reason reason --from-error "0x4e487b710000000000000000000000000000000000000000000000000000000000000032" +2022/12/05 15:18:33 Using config file .env +Decoded error: Assertion failure +If you access an array, bytesN or an array slice at an out-of-bounds or negative index (i.e. x[i] where i >= x.length or i < 0).% +``` + + +Resolving from a transaction hash (`NODE_URL` and `FROM_ADDRESS` env vars need to be defined) + +```bash +> ./ccip-revert-reason reason "0x4e487b710000000000000" +2022/12/05 15:18:33 Using config file .env +Decoded error: Assertion failure +If you access an array, bytesN or an array slice at an out-of-bounds or negative index (i.e. x[i] where i >= x.length or i < 0).% +``` \ No newline at end of file diff --git a/core/scripts/ccip/revert-reason/command/revert_reason.go b/core/scripts/ccip/revert-reason/command/revert_reason.go new file mode 100644 index 00000000000..7258eaba719 --- /dev/null +++ b/core/scripts/ccip/revert-reason/command/revert_reason.go @@ -0,0 +1,42 @@ +package command + +import ( + "fmt" + "log" + + "github.com/spf13/cobra" + + "github.com/smartcontractkit/chainlink/core/scripts/ccip/revert-reason/config" + "github.com/smartcontractkit/chainlink/core/scripts/ccip/revert-reason/handler" +) + +// RevertReasonCmd takes in a failed tx hash and tries to give you the reason +var RevertReasonCmd = &cobra.Command{ + Use: "reason ", + Short: "Revert reason for failed TX.", + Long: `Given a failed TX tries to find the revert reason. args = tx hex address`, + Args: cobra.ExactArgs(1), + Run: func(cmd *cobra.Command, args []string) { + cfg := config.New() + baseHandler := handler.NewBaseHandler(cfg) + + decodeFromError, err := cmd.Flags().GetBool("from-error") + if err != nil { + log.Fatal("failed to get withdraw flag: ", err) + } + + if decodeFromError { + result, err := baseHandler.RevertReasonFromErrorCodeString(args[0]) + if err != nil { + log.Fatal("failed to decode error code string: ", err) + } + fmt.Print(result) + } else { + result, err := baseHandler.RevertReasonFromTx(args[0]) + if err != nil { + log.Fatal("failed to decode error code string: ", err) + } + fmt.Print(result) + } + }, +} diff --git a/core/scripts/ccip/revert-reason/command/root.go b/core/scripts/ccip/revert-reason/command/root.go new file mode 100644 index 00000000000..31578fc46f1 --- /dev/null +++ b/core/scripts/ccip/revert-reason/command/root.go @@ -0,0 +1,35 @@ +package command + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var configFile string + +// RootCmd represents the base command when called without any subcommands +var RootCmd = &cobra.Command{ + Use: "ccip-revert-reason", + Short: "ChainLink CLI tool to resolve CCIP revert reasons", + Long: `ccip-revert-reason is a CLI for running the CCIP revert reason resolution commands.`, +} + +// Execute adds all child commands to the root command and sets flags appropriately. +// This is called by main.main(). It only needs to happen once to the RootCmd. +func Execute() { + if err := RootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } +} + +func init() { + RootCmd.PersistentFlags().StringVar(&configFile, "config", "", "config file (default is .env)") + _ = viper.BindPFlag("config", RootCmd.PersistentFlags().Lookup("config")) + + RootCmd.AddCommand(RevertReasonCmd) + RevertReasonCmd.Flags().Bool("from-error", false, "Whether to decode an error string instead of transaction hash") +} diff --git a/core/scripts/ccip/revert-reason/config/config.go b/core/scripts/ccip/revert-reason/config/config.go new file mode 100644 index 00000000000..014f44906c4 --- /dev/null +++ b/core/scripts/ccip/revert-reason/config/config.go @@ -0,0 +1,42 @@ +package config + +import ( + "log" + + "github.com/spf13/viper" +) + +// Config represents configuration fields +type Config struct { + NodeURL string `mapstructure:"NODE_URL"` + FromAddress string `mapstructure:"FROM_ADDRESS"` +} + +// New creates a new config +func New() *Config { + var cfg Config + configFile := viper.GetString("config") + if configFile != "" { + // Use config file from the flag. + viper.SetConfigFile(configFile) + } else { + viper.SetConfigFile(".env") + } + viper.AutomaticEnv() + if err := viper.ReadInConfig(); err != nil { + log.Fatal("failed to read config: ", err) + } + if err := viper.Unmarshal(&cfg); err != nil { + log.Fatal("failed to unmarshal config: ", err) + } + if err := cfg.Validate(); err != nil { + log.Fatal("failed to validate config: ", err) + } + + return &cfg +} + +// Validate validates the given config +func (c *Config) Validate() error { + return nil +} diff --git a/core/scripts/ccip/revert-reason/handler/handler.go b/core/scripts/ccip/revert-reason/handler/handler.go new file mode 100644 index 00000000000..e1ea13396c9 --- /dev/null +++ b/core/scripts/ccip/revert-reason/handler/handler.go @@ -0,0 +1,17 @@ +package handler + +import ( + "github.com/smartcontractkit/chainlink/core/scripts/ccip/revert-reason/config" +) + +// BaseHandler is the common handler with a common logic +type BaseHandler struct { + cfg *config.Config +} + +// NewBaseHandler is the constructor of baseHandler +func NewBaseHandler(cfg *config.Config) *BaseHandler { + return &BaseHandler{ + cfg: cfg, + } +} diff --git a/core/scripts/ccip/revert-reason/handler/reason.go b/core/scripts/ccip/revert-reason/handler/reason.go new file mode 100644 index 00000000000..ee354aca928 --- /dev/null +++ b/core/scripts/ccip/revert-reason/handler/reason.go @@ -0,0 +1,208 @@ +package handler + +import ( + "bytes" + "context" + "encoding/hex" + "encoding/json" + "fmt" + "strings" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/pkg/errors" + + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/burn_mint_token_pool" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/burn_mint_token_pool_1_2_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_offramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/lock_release_token_pool" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/lock_release_token_pool_1_4_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/maybe_revert_message_receiver" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_contract" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_admin_registry" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/usdc_token_pool" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/usdc_token_pool_1_4_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/erc20" +) + +// RevertReasonFromErrorCodeString attempts to decode an error code string +func (h *BaseHandler) RevertReasonFromErrorCodeString(errorCodeString string) (string, error) { + errorCodeString = strings.TrimPrefix(errorCodeString, "0x") + return DecodeErrorStringFromABI(errorCodeString) +} + +// RevertReasonFromTx attempts to fetch more info on failed TX +func (h *BaseHandler) RevertReasonFromTx(txHash string) (string, error) { + // Need a node URL + // NOTE: this node needs to run in archive mode + ethURL := h.cfg.NodeURL + if ethURL == "" { + panicErr(errors.New("you must define ETH_NODE env variable")) + } + requester := h.cfg.FromAddress + + ec, err := ethclient.Dial(ethURL) + panicErr(err) + errorString, _ := GetErrorForTx(ec, txHash, requester) + + return DecodeErrorStringFromABI(errorString) +} + +func DecodeErrorStringFromABI(errorString string) (string, error) { + contractABIs := getAllABIs() + + // Sanitize error string + errorString = strings.TrimPrefix(errorString, "Reverted ") + errorString = strings.TrimPrefix(errorString, "0x") + + data, err := hex.DecodeString(errorString) + if err != nil { + return "", errors.Wrap(err, "error decoding error string") + } + + for _, contractABI := range contractABIs { + parsedAbi, err2 := abi.JSON(strings.NewReader(contractABI)) + if err2 != nil { + return "", errors.Wrap(err2, "error loading ABI") + } + + for errorName, abiError := range parsedAbi.Errors { + if bytes.Equal(data[:4], abiError.ID.Bytes()[:4]) { + // Found a matching error + v, err3 := abiError.Unpack(data) + if err3 != nil { + return "", errors.Wrap(err3, "error unpacking data") + } + + // If exec error, the actual error is within the revert reason + if errorName == "ExecutionError" || errorName == "TokenRateLimitError" || errorName == "TokenHandlingError" || errorName == "ReceiverError" { + // Get the inner type, which is `bytes` + fmt.Printf("Error is \"%v\" \ninner error: ", errorName) + errorBytes := v.([]interface{})[0].([]byte) + if len(errorBytes) < 4 { + return "[reverted without error code]", nil + } + return DecodeErrorStringFromABI(hex.EncodeToString(errorBytes)) + } + return fmt.Sprintf("error is \"%v\" args %v\n", errorName, v), nil + } + } + } + + if len(errorString) > 8 && errorString[:8] == "4e487b71" { + fmt.Println("Assertion failure") + indicator := errorString[len(errorString)-2:] + switch indicator { + case "01": + return "If you call assert with an argument that evaluates to false.", nil + case "11": + return "If an arithmetic operation results in underflow or overflow outside of an unchecked { ... } block.", nil + case "12": + return "If you divide or modulo by zero (e.g. 5 / 0 or 23 modulo 0).", nil + case "21": + return "If you convert a value that is too big or negative into an enum type.", nil + case "31": + return "If you call .pop() on an empty array.", nil + case "32": + return "If you access an array, bytesN or an array slice at an out-of-bounds or negative index (i.e. x[i] where i >= x.length or i < 0).", nil + case "41": + return "If you allocate too much memory or create an array that is too large.", nil + case "51": + return "If you call a zero-initialized variable of internal function type.", nil + default: + return fmt.Sprintf("This is a revert produced by an assertion failure. Exact code not found \"%s\"", indicator), nil + } + } + + stringErr, err := abi.UnpackRevert(data) + if err == nil { + return "string error: " + stringErr, nil + } + + return "", errors.Errorf(`cannot match error with contract ABI. Error code "%s"`, errorString) +} + +func getAllABIs() []string { + return []string{ + rmn_contract.RMNContractABI, + lock_release_token_pool_1_4_0.LockReleaseTokenPoolABI, + burn_mint_token_pool_1_2_0.BurnMintTokenPoolABI, + usdc_token_pool_1_4_0.USDCTokenPoolABI, + burn_mint_erc677.BurnMintERC677ABI, + erc20.ERC20ABI, + lock_release_token_pool.LockReleaseTokenPoolABI, + burn_mint_token_pool.BurnMintTokenPoolABI, + usdc_token_pool.USDCTokenPoolABI, + commit_store.CommitStoreABI, + token_admin_registry.TokenAdminRegistryABI, + fee_quoter.FeeQuoterABI, + evm_2_evm_onramp.EVM2EVMOnRampABI, + evm_2_evm_offramp.EVM2EVMOffRampABI, + router.RouterABI, + onramp.OnRampABI, + offramp.OffRampABI, + maybe_revert_message_receiver.MaybeRevertMessageReceiverABI, + } +} + +func GetErrorForTx(client *ethclient.Client, txHash string, requester string) (string, error) { + tx, _, err := client.TransactionByHash(context.Background(), common.HexToHash(txHash)) + if err != nil { + return "", errors.Wrap(err, "error getting transaction from hash") + } + re, err := client.TransactionReceipt(context.Background(), common.HexToHash(txHash)) + if err != nil { + return "", errors.Wrap(err, "error getting transaction receipt") + } + + call := ethereum.CallMsg{ + From: common.HexToAddress(requester), + To: tx.To(), + Data: tx.Data(), + Value: tx.Value(), + Gas: tx.Gas(), + GasPrice: tx.GasPrice(), + } + _, err = client.CallContract(context.Background(), call, re.BlockNumber) + if err == nil { + panic("no error calling contract") + } + + return parseError(err) +} + +func parseError(txError error) (string, error) { + b, err := json.Marshal(txError) + if err != nil { + return "", err + } + var callErr struct { + Code int + Data string `json:"data"` + Message string `json:"message"` + } + if json.Unmarshal(b, &callErr) != nil { + return "", err + } + + if callErr.Data == "" && strings.Contains(callErr.Message, "missing trie node") { + return "", errors.Errorf("please use an archive node") + } + + return callErr.Data, nil +} + +func panicErr(err error) { + if err != nil { + panic(err) + } +} diff --git a/core/scripts/ccip/revert-reason/handler/reason_test.go b/core/scripts/ccip/revert-reason/handler/reason_test.go new file mode 100644 index 00000000000..4a9363550ce --- /dev/null +++ b/core/scripts/ccip/revert-reason/handler/reason_test.go @@ -0,0 +1,68 @@ +package handler + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/core/scripts/ccip/revert-reason/config" +) + +func Test_RevertReasonFromTx(t *testing.T) { + type fields struct { + cfg *config.Config + } + type args struct { + txHash string + } + var tests []struct { + name string + fields fields + args args + expected string + } // TODO: Add test cases. + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + h := &BaseHandler{ + cfg: tt.fields.cfg, + } + got, err := h.RevertReasonFromTx(tt.args.txHash) + require.NoError(t, err) + require.Equal(t, tt.expected, got) + }) + } +} + +func Test_RevertReasonFromErrorCodeString(t *testing.T) { + type fields struct { + cfg *config.Config + } + type args struct { + errorCodeString string + } + tests := []struct { + name string + fields fields + args args + expected string + }{ + { + name: "decode error string", + fields: fields{cfg: &config.Config{}}, + args: args{ + errorCodeString: "0x4e487b710000000000000000000000000000000000000000000000000000000000000032", + }, + expected: "If you access an array, bytesN or an array slice at an out-of-bounds or negative index (i.e. x[i] where i >= x.length or i < 0).", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + h := &BaseHandler{ + cfg: tt.fields.cfg, + } + got, err := h.RevertReasonFromErrorCodeString(tt.args.errorCodeString) + require.NoError(t, err) + require.Equal(t, tt.expected, got) + }) + } +} diff --git a/core/scripts/ccip/revert-reason/main.go b/core/scripts/ccip/revert-reason/main.go new file mode 100644 index 00000000000..1eac8b66baa --- /dev/null +++ b/core/scripts/ccip/revert-reason/main.go @@ -0,0 +1,9 @@ +package main + +import ( + "github.com/smartcontractkit/chainlink/core/scripts/ccip/revert-reason/command" +) + +func main() { + command.Execute() +} diff --git a/core/scripts/ccip/secrets/secrets.go b/core/scripts/ccip/secrets/secrets.go new file mode 100644 index 00000000000..e47f644b37e --- /dev/null +++ b/core/scripts/ccip/secrets/secrets.go @@ -0,0 +1,16 @@ +package secrets + +import ( + "fmt" + "os" + "strconv" +) + +func GetRPC(chainID uint64) string { + envVariable := "RPC_" + strconv.FormatUint(chainID, 10) + rpc := os.Getenv(envVariable) + if rpc != "" { + return rpc + } + panic(fmt.Errorf("RPC not found. Please set the environment variable for chain %d e.g. RPC_420=https://rpc.420.com", chainID)) +} diff --git a/core/scripts/ccip/shared/helpers.go b/core/scripts/ccip/shared/helpers.go new file mode 100644 index 00000000000..8aa8b9ab222 --- /dev/null +++ b/core/scripts/ccip/shared/helpers.go @@ -0,0 +1,52 @@ +package shared + +import ( + "context" + "testing" + "time" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" + "github.com/stretchr/testify/require" + + evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +const RetryTiming = 5 * time.Second +const CrossChainTimout = 5 * time.Minute +const TxInclusionTimout = 3 * time.Minute + +// WaitForMined wait for a tx to be included on chain. It will panic when +// the tx is reverted/successful based on the shouldSucceed parameter. +func WaitForMined(lggr logger.Logger, client ethereum.TransactionReader, hash common.Hash, shouldSucceed bool) error { + maxIterations := TxInclusionTimout / RetryTiming + for i := 0; i < int(maxIterations); i++ { + lggr.Info("[MINING] waiting for tx to be mined...") + receipt, _ := client.TransactionReceipt(context.Background(), hash) + + if receipt != nil { + if shouldSucceed && receipt.Status == 0 { + lggr.Infof("[MINING] ERROR tx reverted %s", hash.Hex()) + panic(receipt) + } else if !shouldSucceed && receipt.Status != 0 { + lggr.Infof("[MINING] ERROR expected tx to revert %s", hash.Hex()) + panic(receipt) + } + lggr.Infof("[MINING] tx mined %s successful %t", hash.Hex(), shouldSucceed) + return nil + } + + time.Sleep(RetryTiming) + } + return errors.New("No tx found within the given timeout") +} + +func RequireNoError(t *testing.T, err error) { + if err != nil { + jErr, _ := evmclient.ExtractRPCError(err) + t.Log(jErr) + } + require.NoError(t, err) +} diff --git a/core/scripts/common/helpers.go b/core/scripts/common/helpers.go index 57c8c15e405..f852c88de5b 100644 --- a/core/scripts/common/helpers.go +++ b/core/scripts/common/helpers.go @@ -3,10 +3,12 @@ package common import ( "context" "crypto/ecdsa" + "crypto/tls" "encoding/hex" "flag" "fmt" "math/big" + "net/http" "os" "strconv" "strings" @@ -69,11 +71,17 @@ func SetupEnv(overrideNonce bool) Environment { panic("need account key") } - ec, err := ethclient.Dial(ethURL) - PanicErr(err) - - jsonRPCClient, err := rpc.Dial(ethURL) + insecureSkipVerify := os.Getenv("INSECURE_SKIP_VERIFY") == "true" + tr := &http.Transport{ + // User enables this at their own risk! + // #nosec G402 + TLSClientConfig: &tls.Config{InsecureSkipVerify: insecureSkipVerify}, + } + httpClient := &http.Client{Transport: tr} + rpcConfig := rpc.WithHTTPClient(httpClient) + jsonRPCClient, err := rpc.DialOptions(context.Background(), ethURL, rpcConfig) PanicErr(err) + ec := ethclient.NewClient(jsonRPCClient) chainID, err := strconv.ParseInt(chainIDEnv, 10, 64) PanicErr(err) @@ -290,6 +298,11 @@ func TenderlySimLink(simID string) string { // ConfirmTXMined confirms that the given transaction is mined and prints useful execution information. func ConfirmTXMined(context context.Context, client *ethclient.Client, transaction *types.Transaction, chainID int64, txInfo ...string) (receipt *types.Receipt) { + if transaction == nil { + fmt.Println("No transaction to confirm") + return + } + fmt.Println("Executing TX", ExplorerLink(chainID, transaction.Hash()), txInfo) receipt, err := bind.WaitMined(context, client, transaction) PanicErr(err) diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 47ab9cf536c..01b6bb09a0f 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -13,7 +13,7 @@ replace github.com/smartcontractkit/chainlink/deployment => ../../deployment // creating potential merge conflicts. require ( github.com/smartcontractkit/chainlink/deployment v0.0.0-20241206210521-125d98cdaf66 - github.com/smartcontractkit/chainlink/v2 v2.0.0-20241206210521-125d98cdaf66 + github.com/smartcontractkit/chainlink/v2 v2.14.0-mercury-20240807.0.20241106193309-5560cd76211a ) require ( @@ -30,25 +30,29 @@ require ( github.com/montanaflynn/stats v0.7.1 github.com/olekukonko/tablewriter v0.0.5 github.com/pelletier/go-toml/v2 v2.2.3 + github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.20.5 github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241214155818-b403079b2805 - github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 + github.com/smartcontractkit/chainlink-common v0.4.2-0.20250116214855-f49c5c27db51 + github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250115135646-ac859d85e7e3 + github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 + github.com/smartcontractkit/libocr v0.0.0-20241223215956-e5b78d8e3919 github.com/spf13/cobra v1.8.1 github.com/spf13/viper v1.19.0 - github.com/stretchr/testify v1.9.0 + github.com/stretchr/testify v1.10.0 github.com/umbracle/ethgo v0.1.3 github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722 github.com/urfave/cli v1.22.14 + go.uber.org/zap v1.27.0 google.golang.org/protobuf v1.35.1 + gopkg.in/yaml.v3 v3.0.1 k8s.io/api v0.31.1 k8s.io/apimachinery v0.31.1 k8s.io/client-go v0.31.1 ) require ( - contrib.go.opencensus.io/exporter/stackdriver v0.13.5 // indirect cosmossdk.io/api v0.3.1 // indirect cosmossdk.io/core v0.5.1 // indirect cosmossdk.io/depinject v1.0.0-alpha.4 // indirect @@ -74,6 +78,7 @@ require ( github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c // indirect github.com/avast/retry-go/v4 v4.6.0 // indirect github.com/aws/aws-sdk-go v1.54.19 // indirect + github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect @@ -81,10 +86,11 @@ require ( github.com/bits-and-blooms/bitset v1.13.0 // indirect github.com/blendle/zapdriver v1.3.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129 // indirect github.com/buger/jsonparser v1.1.1 // indirect github.com/bytecodealliance/wasmtime-go/v23 v23.0.0 // indirect - github.com/bytedance/sonic v1.11.6 // indirect - github.com/bytedance/sonic/loader v0.1.1 // indirect + github.com/bytedance/sonic v1.12.3 // indirect + github.com/bytedance/sonic/loader v0.2.0 // indirect github.com/cenkalti/backoff v2.2.1+incompatible // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash v1.1.0 // indirect @@ -118,8 +124,7 @@ require ( github.com/danielkov/gin-helmet v0.0.0-20171108135313-1387e224435e // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect - github.com/dfuse-io/logging v0.0.0-20210109005628-b97a57253f70 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect github.com/dgraph-io/badger/v2 v2.2007.4 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect @@ -127,6 +132,7 @@ require ( github.com/docker/distribution v2.8.2+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dominikbraun/graph v0.23.0 // indirect + github.com/doyensec/safeurl v0.2.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.7.0 // indirect github.com/emicklei/go-restful/v3 v3.12.1 // indirect @@ -137,10 +143,11 @@ require ( github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect - github.com/gabriel-vasile/mimetype v1.4.3 // indirect - github.com/gagliardetto/binary v0.7.7 // indirect - github.com/gagliardetto/solana-go v1.8.4 // indirect + github.com/gabriel-vasile/mimetype v1.4.6 // indirect + github.com/gagliardetto/binary v0.8.0 // indirect + github.com/gagliardetto/solana-go v1.12.0 // indirect github.com/gagliardetto/treeout v0.1.4 // indirect + github.com/gagliardetto/utilz v0.1.1 // indirect github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813 // indirect github.com/getsentry/sentry-go v0.27.0 // indirect @@ -166,7 +173,7 @@ require ( github.com/go-openapi/swag v0.23.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.22.0 // indirect + github.com/go-playground/validator/v10 v10.22.1 // indirect github.com/go-viper/mapstructure/v2 v2.1.0 // indirect github.com/go-webauthn/webauthn v0.9.4 // indirect github.com/go-webauthn/x v0.1.5 // indirect @@ -178,7 +185,6 @@ require ( github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang-jwt/jwt/v5 v5.2.1 // indirect github.com/golang/glog v1.2.2 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/btree v1.1.2 // indirect @@ -202,6 +208,7 @@ require ( github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/gtank/merlin v0.1.1 // indirect github.com/gtank/ristretto255 v0.1.2 // indirect + github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026 // indirect github.com/hashicorp/consul/sdk v0.16.1 // indirect github.com/hashicorp/go-bexpr v0.1.10 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect @@ -254,8 +261,9 @@ require ( github.com/maruel/natural v1.1.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.14 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mfridman/interpolate v0.0.2 // indirect + github.com/miekg/dns v1.1.61 // indirect github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect @@ -277,41 +285,41 @@ require ( github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/patrickmn/go-cache v2.1.0+incompatible // indirect github.com/pelletier/go-toml v1.9.5 // indirect - github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect - github.com/pkg/errors v0.9.1 // indirect + github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/pressly/goose/v3 v3.21.1 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.60.0 // indirect + github.com/prometheus/common v0.60.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/prometheus/prometheus v0.54.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect - github.com/rivo/uniseg v0.4.4 // indirect + github.com/rivo/uniseg v0.4.7 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect github.com/rogpeppe/go-internal v1.13.1 // indirect github.com/rs/cors v1.10.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/ryanuber/go-glob v1.0.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sanity-io/litter v1.5.5 // indirect github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect - github.com/sasha-s/go-deadlock v0.3.1 // indirect + github.com/sasha-s/go-deadlock v0.3.5 // indirect github.com/scylladb/go-reflectx v1.0.1 // indirect github.com/sethvargo/go-retry v0.2.4 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/shirou/gopsutil/v3 v3.24.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix // indirect - github.com/smartcontractkit/chain-selectors v1.0.34 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241213122413-5e8f65dd6b1b // indirect + github.com/smartcontractkit/chain-selectors v1.0.36 // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20250120130359-cc025272bbff // indirect + github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250103152858-8973fd0c912b // indirect github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e // indirect - github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.1 // indirect + github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250115203616-a2ea5e50b260 // indirect github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 // indirect github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241210172617-6fd1891d0fbc // indirect - github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 // indirect - github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.1-0.20250117143722-fb6416c087a5 // indirect + github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20250117171710-b6481e9fcb34 // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de // indirect github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de // indirect @@ -321,13 +329,12 @@ require ( github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/status-im/keycard-go v0.2.0 // indirect - github.com/streamingfast/logging v0.0.0-20220405224725-2755dab2ce75 // indirect + github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/supranational/blst v0.3.13 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tendermint/go-amino v0.16.0 // indirect - github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 // indirect github.com/test-go/testify v1.1.4 // indirect github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a // indirect github.com/tidwall/btree v1.6.0 // indirect @@ -354,7 +361,6 @@ require ( go.dedis.ch/kyber/v3 v3.1.0 // indirect go.etcd.io/bbolt v1.3.9 // indirect go.mongodb.org/mongo-driver v1.15.0 // indirect - go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.49.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect @@ -378,19 +384,18 @@ require ( go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/ratelimit v0.3.1 // indirect - go.uber.org/zap v1.27.0 // indirect golang.org/x/arch v0.11.0 // indirect golang.org/x/crypto v0.31.0 // indirect - golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect - golang.org/x/mod v0.21.0 // indirect - golang.org/x/net v0.30.0 // indirect + golang.org/x/exp v0.0.0-20241210194714-1829a127f884 // indirect + golang.org/x/mod v0.22.0 // indirect + golang.org/x/net v0.32.0 // indirect golang.org/x/oauth2 v0.23.0 // indirect golang.org/x/sync v0.10.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/term v0.27.0 // indirect golang.org/x/text v0.21.0 // indirect golang.org/x/time v0.7.0 // indirect - golang.org/x/tools v0.26.0 // indirect + golang.org/x/tools v0.28.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect gonum.org/v1/gonum v0.15.1 // indirect google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 // indirect @@ -402,7 +407,6 @@ require ( gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f // indirect k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 2840c675dfa..77be91a0c89 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -3,7 +3,6 @@ cel.dev/expr v0.17.0/go.mod h1:HCwbrn+qQoHPXgfz6cl2J0hDybnX2N1sQQkl9EggXx8= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= @@ -54,10 +53,6 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.45.0 h1:5av0QcIVj77t+44mV4gffFC/LscFRUhto6UBMB5SimM= cloud.google.com/go/storage v1.45.0/go.mod h1:wpPblkIuMP5jCB/E48Pz9zIo2S/zD8g+ITmxKkPCITE= -contrib.go.opencensus.io/exporter/stackdriver v0.12.6/go.mod h1:8x999/OcIPy5ivx/wDiV7Gx4D+VUPODf0mWRGRc5kSk= -contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= -contrib.go.opencensus.io/exporter/stackdriver v0.13.5 h1:TNaexHK16gPUoc7uzELKOU7JULqccn1NDuqUxmxSqfo= -contrib.go.opencensus.io/exporter/stackdriver v0.13.5/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= cosmossdk.io/api v0.3.1 h1:NNiOclKRR0AOlO4KIqeaG6PS6kswOMhHD0ir0SscNXE= cosmossdk.io/api v0.3.1/go.mod h1:DfHfMkiNA2Uhy8fj0JJlOCYOBp4eWUUJ1te5zBGNyIw= cosmossdk.io/core v0.5.1 h1:vQVtFrIYOQJDV3f7rw4pjjVqc1id4+mE0L9hHP66pyI= @@ -72,8 +67,9 @@ cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= cosmossdk.io/tools/rosetta v0.2.1 h1:ddOMatOH+pbxWbrGJKRAawdBkPYLfKXutK9IETnjYxw= cosmossdk.io/tools/rosetta v0.2.1/go.mod h1:Pqdc1FdvkNV3LcNIkYWt2RQY6IP1ge6YWZk8MhhO9Hw= +dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -100,8 +96,6 @@ github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/Depado/ginprom v1.8.0 h1:zaaibRLNI1dMiiuj1MKzatm8qrcHzikMlCc1anqOdyo= github.com/Depado/ginprom v1.8.0/go.mod h1:XBaKzeNBqPF4vxJpNLincSQZeMDnZp1tIbU0FU0UKgg= -github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0= -github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.3 h1:cb3br57K508pQEFgBxn9GDhPS9HefpyMPK1RzmtMNzk= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.3/go.mod h1:itPGVDKf9cC/ov4MdvJ2QZ0khw4bfoo9jzwTJlaxy2k= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.3 h1:xir5X8TS8UBVPWg2jHL+cSTf0jZgqYQSA54TscSt1/0= @@ -128,7 +122,6 @@ github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrd github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/XSAM/otelsql v0.27.0 h1:i9xtxtdcqXV768a5C6SoT/RkG+ue3JTOgkYInzlTOqs= github.com/XSAM/otelsql v0.27.0/go.mod h1:0mFB3TvLa7NCuhm/2nU7/b2wEtsczkj8Rey8ygO7V+A= -github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -138,7 +131,6 @@ github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1L github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129/go.mod h1:rFgpPQZYZ8vdbc+48xibu8ALc3yeyd64IhHS+PU6Yyg= github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA= github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= @@ -156,10 +148,38 @@ github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c h1:cxQ github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c/go.mod h1:3XzxudkrYVUvbduN/uI2fl4lSrMSzU0+3RCu2mpnfx8= github.com/avast/retry-go/v4 v4.6.0 h1:K9xNA+KeB8HHc2aWFuLb25Offp+0iVRXEvFx8IinRJA= github.com/avast/retry-go/v4 v4.6.0/go.mod h1:gvWlPhBVsvBbLkVGDg/KwvBv0bEkCOLRRSHKIr2PyOE= -github.com/aws/aws-sdk-go v1.22.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.54.19 h1:tyWV+07jagrNiCcGRzRhdtVjQs7Vy41NwsuOcl0IbVI= github.com/aws/aws-sdk-go v1.54.19/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= +github.com/aws/aws-sdk-go-v2 v1.32.2 h1:AkNLZEyYMLnx/Q/mSKkcMqwNFXMAvFto9bNsHqcTduI= +github.com/aws/aws-sdk-go-v2 v1.32.2/go.mod h1:2SK5n0a2karNTv5tbP1SjsX0uhttou00v/HpXKM1ZUo= +github.com/aws/aws-sdk-go-v2/config v1.28.0 h1:FosVYWcqEtWNxHn8gB/Vs6jOlNwSoyOCA/g/sxyySOQ= +github.com/aws/aws-sdk-go-v2/config v1.28.0/go.mod h1:pYhbtvg1siOOg8h5an77rXle9tVG8T+BWLWAo7cOukc= +github.com/aws/aws-sdk-go-v2/credentials v1.17.41 h1:7gXo+Axmp+R4Z+AK8YFQO0ZV3L0gizGINCOWxSLY9W8= +github.com/aws/aws-sdk-go-v2/credentials v1.17.41/go.mod h1:u4Eb8d3394YLubphT4jLEwN1rLNq2wFOlT6OuxFwPzU= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.17 h1:TMH3f/SCAWdNtXXVPPu5D6wrr4G5hI1rAxbcocKfC7Q= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.17/go.mod h1:1ZRXLdTpzdJb9fwTMXiLipENRxkGMTn1sfKexGllQCw= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.21 h1:UAsR3xA31QGf79WzpG/ixT9FZvQlh5HY1NRqSHBNOCk= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.21/go.mod h1:JNr43NFf5L9YaG3eKTm7HQzls9J+A9YYcGI5Quh1r2Y= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.21 h1:6jZVETqmYCadGFvrYEQfC5fAQmlo80CeL5psbno6r0s= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.21/go.mod h1:1SR0GbLlnN3QUmYaflZNiH1ql+1qrSiB2vwcJ+4UM60= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0 h1:TToQNkvGguu209puTojY/ozlqy2d/SFNcoLIqTFi42g= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0/go.mod h1:0jp+ltwkf+SwG2fm/PKo8t4y8pJSgOCO4D8Lz3k0aHQ= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2 h1:s7NA1SOw8q/5c0wr8477yOPp0z+uBaXBnLE0XYb0POA= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2/go.mod h1:fnjjWyAW/Pj5HYOxl9LJqWtEwS7W2qgcRLWP+uWbss0= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.2 h1:Rrqru2wYkKQCS2IM5/JrgKUQIoNTqA6y/iuxkjzxC6M= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.2/go.mod h1:QuCURO98Sqee2AXmqDNxKXYFm2OEDAVAPApMqO0Vqnc= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.2 h1:bSYXVyUzoTHoKalBmwaZxs97HU9DWWI3ehHSAMa7xOk= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.2/go.mod h1:skMqY7JElusiOUjMJMOv1jJsP7YUg7DrhgqZZWuzu1U= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.2 h1:AhmO1fHINP9vFYUE0LHzCWg/LfUWUF+zFPEcY9QXb7o= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.2/go.mod h1:o8aQygT2+MVP0NaV6kbdE1YnnIM8RRVQzoeUH45GOdI= +github.com/aws/aws-sdk-go-v2/service/sts v1.32.2 h1:CiS7i0+FUe+/YY1GvIBLLrR/XNGZ4CtM1Ll0XavNuVo= +github.com/aws/aws-sdk-go-v2/service/sts v1.32.2/go.mod h1:HtaiBI8CjYoNVde8arShXb94UbQQi9L4EMr6D+xGBwo= +github.com/aws/smithy-go v1.22.0 h1:uunKnWlcoL3zO7q+gG2Pk53joueEOsnNB28QdMsmiMM= +github.com/aws/smithy-go v1.22.0/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= +github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 h1:WWB576BN5zNSZc/M9d/10pqEx5VHNhaQ/yOVAkmj5Yo= +github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -176,7 +196,6 @@ github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 h1:41iFGWnSlI2 github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHfpE= github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox4J2u4eHCc= @@ -189,14 +208,17 @@ github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6 github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= +github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129 h1:gfAMKE626QEuKG3si0pdTRcr/YEbBoxY+3GOH3gWvl4= +github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129/go.mod h1:u9UyCz2eTrSGy6fbupqJ54eY5c4IC8gREQ1053dK12U= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/bytecodealliance/wasmtime-go/v23 v23.0.0 h1:NJvU4S8KEk1GnF6+FvlnzMD/8wXTj/mYJSG6Q4yu3Pw= github.com/bytecodealliance/wasmtime-go/v23 v23.0.0/go.mod h1:5YIL+Ouiww2zpO7u+iZ1U1G5NvmwQYaXdmCZQGjQM0U= -github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= -github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= -github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= +github.com/bytedance/sonic v1.12.3 h1:W2MGa7RCU1QTeYRTPE3+88mVC0yXmsRQRChiyVocVjU= +github.com/bytedance/sonic v1.12.3/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/bytedance/sonic/loader v0.2.0 h1:zNprn+lsIP06C/IqCHs3gPQIvnvpKbbxyXQP1iU4kWM= +github.com/bytedance/sonic/loader v0.2.0/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= @@ -263,16 +285,15 @@ github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7b github.com/containerd/continuity v0.4.3/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= +github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= @@ -296,6 +317,8 @@ github.com/cosmos/ledger-cosmos-go v0.12.4 h1:drvWt+GJP7Aiw550yeb3ON/zsrgW0jgh5s github.com/cosmos/ledger-cosmos-go v0.12.4/go.mod h1:fjfVWRf++Xkygt9wzCsjEBdjcf7wiiY35fv3ctT+k4M= github.com/cosmos/rosetta-sdk-go v0.10.0 h1:E5RhTruuoA7KTIXUcMicL76cffyeoyvNybzUGSKFTcM= github.com/cosmos/rosetta-sdk-go v0.10.0/go.mod h1:SImAZkb96YbwvoRkzSMQB6noNJXFgWl/ENIznEoYQI4= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= @@ -310,7 +333,6 @@ github.com/creachadair/taskgroup v0.4.2 h1:jsBLdAJE42asreGss2xZGZ8fJra7WtwnHWeJF github.com/creachadair/taskgroup v0.4.2/go.mod h1:qiXUOSrbwAY3u0JPGTzObbE3yf9hcXHDKBZ2ZjpCbgM= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E= github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= github.com/danielkov/gin-helmet v0.0.0-20171108135313-1387e224435e h1:5jVSh2l/ho6ajWhSPNN84eHEdq3dp0T7+f6r3Tc6hsk= @@ -324,23 +346,18 @@ github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80N github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= -github.com/dfuse-io/logging v0.0.0-20201110202154-26697de88c79/go.mod h1:V+ED4kT/t/lKtH99JQmKIb0v9WL3VaYkJ36CfHlVECI= -github.com/dfuse-io/logging v0.0.0-20210109005628-b97a57253f70 h1:CuJS05R9jmNlUK8GOxrEELPbfXm0EuGh/30LjkjN5vo= -github.com/dfuse-io/logging v0.0.0-20210109005628-b97a57253f70/go.mod h1:EoK/8RFbMEteaCaz89uessDTnCWjbbcr+DXcBh4el5o= github.com/dgraph-io/badger/v2 v2.2007.4 h1:TRWBQg8UrlUhaFdco01nO2uXwzKS7zd+HVdwV/GHc4o= github.com/dgraph-io/badger/v2 v2.2007.4/go.mod h1:vSw/ax2qojzbN6eXHIx6KPKtCSHJN/Uz0X0VPruTIhk= github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= @@ -353,6 +370,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dominikbraun/graph v0.23.0 h1:TdZB4pPqCLFxYhdyMFb1TBdFxp8XLcJfTTBQucVPgCo= github.com/dominikbraun/graph v0.23.0/go.mod h1:yOjYyogZLY1LSG9E33JWZJiq5k83Qy2C6POAuiViluc= +github.com/doyensec/safeurl v0.2.1 h1:DY15JorEfQsnpBWhBkVQIkaif2jfxCC14PIuGDsjDVs= +github.com/doyensec/safeurl v0.2.1/go.mod h1:wzSXqC/6Z410qHz23jtBWT+wQ8yTxcY0p8bZH/4EZIg= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= @@ -380,7 +399,6 @@ github.com/ethereum/go-ethereum v1.14.11/go.mod h1:+l/fr42Mma+xBnhefL/+z11/hcmJ2 github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9 h1:8NfxH2iXvJ60YRB8ChToFTUzl8awsc3cJ8CbLjGIl/A= github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= @@ -397,16 +415,19 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= -github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= -github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= -github.com/gagliardetto/binary v0.7.7 h1:QZpT38+sgoPg+TIQjH94sLbl/vX+nlIRA37pEyOsjfY= -github.com/gagliardetto/binary v0.7.7/go.mod h1:mUuay5LL8wFVnIlecHakSZMvcdqfs+CsotR5n77kyjM= +github.com/gabriel-vasile/mimetype v1.4.6 h1:3+PzJTKLkvgjeTbts6msPJt4DixhT4YtFNf1gtGe3zc= +github.com/gabriel-vasile/mimetype v1.4.6/go.mod h1:JX1qVKqZd40hUPpAfiNTe0Sne7hdfKSbOqqmkq8GCXc= +github.com/gagliardetto/binary v0.8.0 h1:U9ahc45v9HW0d15LoN++vIXSJyqR/pWw8DDlhd7zvxg= +github.com/gagliardetto/binary v0.8.0/go.mod h1:2tfj51g5o9dnvsc+fL3Jxr22MuWzYXwx9wEoN0XQ7/c= github.com/gagliardetto/gofuzz v1.2.2 h1:XL/8qDMzcgvR4+CyRQW9UGdwPRPMHVJfqQ/uMvSUuQw= github.com/gagliardetto/gofuzz v1.2.2/go.mod h1:bkH/3hYLZrMLbfYWA0pWzXmi5TTRZnu4pMGZBkqMKvY= -github.com/gagliardetto/solana-go v1.8.4 h1:vmD/JmTlonyXGy39bAo0inMhmbdAwV7rXZtLDMZeodE= -github.com/gagliardetto/solana-go v1.8.4/go.mod h1:i+7aAyNDTHG0jK8GZIBSI4OVvDqkt2Qx+LklYclRNG8= +github.com/gagliardetto/hashsearch v0.0.0-20191005111333-09dd671e19f9/go.mod h1:513DXpQPzeRo7d4dsCP3xO3XI8hgvruMl9njxyQeraQ= +github.com/gagliardetto/solana-go v1.12.0 h1:rzsbilDPj6p+/DOPXBMLhwMZeBgeRuXjm5zQFCoXgsg= +github.com/gagliardetto/solana-go v1.12.0/go.mod h1:l/qqqIN6qJJPtxW/G1PF4JtcE3Zg2vD2EliZrr9Gn5k= github.com/gagliardetto/treeout v0.1.4 h1:ozeYerrLCmCubo1TcIjFiOWTTGteOOHND1twdFpgwaw= github.com/gagliardetto/treeout v0.1.4/go.mod h1:loUefvXTrlRG5rYmJmExNryyBRh8f89VZhmMOyCyqok= +github.com/gagliardetto/utilz v0.1.1 h1:/etW4hl607emKg6R6Lj9jRJ9d6ue2AQOyjhuAwjzs1U= +github.com/gagliardetto/utilz v0.1.1/go.mod h1:b+rGFkRHz3HWJD0RYMzat47JyvbTtpE0iEcYTRJTLLA= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813 h1:Uc+IZ7gYqAf/rSGFplbWBSHaGolEQlNLgMgSE3ccnIQ= @@ -483,8 +504,8 @@ github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= -github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao= -github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA= +github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -520,7 +541,6 @@ github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVI github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -556,7 +576,6 @@ github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= @@ -632,12 +651,10 @@ github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/rpc v1.2.0/go.mod h1:V4h9r+4sF5HnzqbwIez0fKSpANP0zlYd3qR7p36jkTQ= github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY= github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/grafana/pyroscope-go v1.1.2 h1:7vCfdORYQMCxIzI3NlYAs3FcBP760+gWuYWOyiVyYx8= @@ -648,15 +665,12 @@ github.com/graph-gophers/dataloader v5.0.0+incompatible h1:R+yjsbrNq1Mo3aPG+Z/EK github.com/graph-gophers/dataloader v5.0.0+incompatible/go.mod h1:jk4jk0c5ZISbKaMe8WsVopGB5/15GvGHMdMdPtwlRp4= github.com/graph-gophers/graphql-go v1.5.0 h1:fDqblo50TEpD0LY7RXk/LFVYEVqo3+tXMNMPSVXA1yc= github.com/graph-gophers/graphql-go v1.5.0/go.mod h1:YtmJZDLbF1YYNrlNAuiO5zAStUWc3XZT07iGsVqe1Os= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= @@ -668,6 +682,8 @@ github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is= github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc= github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o= +github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026 h1:BpJ2o0OR5FV7vrkDYfXYVJQeMNWa8RhklZOpW2ITAIQ= +github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026/go.mod h1:5Scbynm8dF1XAPwIwkGPqzkM/shndPm79Jd1003hTjE= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.16.1 h1:V8TxTnImoPD5cj0U9Spl0TUxcytjcbbJeADFF07KdHg= @@ -709,7 +725,6 @@ github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09 github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru v0.6.0 h1:uL2shRDx7RTrOrTCUZEGP/wJUFiUI8QT6E7z5o8jga4= github.com/hashicorp/golang-lru v0.6.0/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= @@ -799,10 +814,8 @@ github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0f github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= @@ -813,7 +826,6 @@ github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4= github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -833,7 +845,6 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= @@ -873,9 +884,9 @@ github.com/linxGnu/grocksdb v1.7.16 h1:Q2co1xrpdkr5Hx3Fp+f+f7fRGhQFQhvi/+226dtLm github.com/linxGnu/grocksdb v1.7.16/go.mod h1:JkS7pl5qWpGpuVb3bPqTz8nC12X3YtPZT+Xq7+QfQo4= github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= @@ -891,7 +902,6 @@ github.com/maruel/natural v1.1.1 h1:Hja7XhhmvEFhcByqDoHz9QZbkWey+COd9xWfCfn1ioo= github.com/maruel/natural v1.1.1/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= @@ -900,16 +910,14 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= -github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= @@ -917,6 +925,9 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5 github.com/mfridman/interpolate v0.0.2 h1:pnuTK7MQIxxFz1Gr+rjSIx9u7qVjf5VOoM/u6BbAxPY= github.com/mfridman/interpolate v0.0.2/go.mod h1:p+7uk6oE07mpE/Ik1b8EckO0O4ZXiGAfshKBWLUM9Xg= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= +github.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs= +github.com/miekg/dns v1.1.61/go.mod h1:mnAarhS3nWaW+NVP2wTkYVIZyHNJ098SJZUki3eykwQ= github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 h1:QRUSJEgZn2Snx0EmT/QLXibWjSUDjKWvXIT19NBVp94= github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= @@ -945,6 +956,14 @@ github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqky github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= +github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= +github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko= +github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo= +github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= +github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= +github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -954,7 +973,6 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= @@ -973,7 +991,6 @@ github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJm github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1 h1:dOYG7LS/WK00RWZc8XGgcUTlTxpp3mKhdR2Q9z9HbXM= github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1/go.mod h1:mpRZBD8SJ55OIICQ3iWH0Yz3cjzA61JdqMLoWXeB2+8= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= @@ -981,7 +998,6 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -1021,9 +1037,8 @@ github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCko github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= -github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= -github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 h1:hDSdbBuw3Lefr6R18ax0tZ2BJeNB3NehB3trOwYBsdU= -github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 h1:Dx7Ovyv/SFnMFw3fD4oEoeorXc6saIiQ23LrGLth0Gw= +github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= @@ -1046,7 +1061,6 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:Om github.com/pressly/goose/v3 v3.21.1 h1:5SSAKKWej8LVVzNLuT6KIvP1eFDuPvxa+B6H0w78buQ= github.com/pressly/goose/v3 v3.21.1/go.mod h1:sqthmzV8PitchEkjecFJII//l43dLOCzfWh8pHEe+vE= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= @@ -1057,21 +1071,17 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1: github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= -github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= +github.com/prometheus/common v0.60.1 h1:FUas6GcOw66yB/73KC+BOZoFJmbo/1pojoILArPAaSc= +github.com/prometheus/common v0.60.1/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/prometheus v0.54.1 h1:vKuwQNjnYN2/mDoWfHXDhAsz/68q/dQDb+YbcEqU7MQ= github.com/prometheus/prometheus v0.54.1/go.mod h1:xlLByHhk2g3ycakQGrMaU8K7OySZx98BzeCR99991NY= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= @@ -1081,11 +1091,10 @@ github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= @@ -1105,6 +1114,8 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= +github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= @@ -1113,8 +1124,8 @@ github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQ github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= -github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= -github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= +github.com/sasha-s/go-deadlock v0.3.5 h1:tNCOEEDG6tBqrNDOX35j/7hL5FcFViG6awUGROb2NsU= +github.com/sasha-s/go-deadlock v0.3.5/go.mod h1:bugP6EGbdGYObIlx7pUZtWqlvo8k9H6vCBBsiChJQ5U= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/scylladb/go-reflectx v1.0.1 h1:b917wZM7189pZdlND9PbIJ6NQxfDPfBvUaQ7cjj1iZQ= github.com/scylladb/go-reflectx v1.0.1/go.mod h1:rWnOfDIRWBGN0miMLIcoPt/Dhi2doCMZqwMCJ3KupFc= @@ -1125,6 +1136,7 @@ github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKl github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/gopsutil/v3 v3.24.3 h1:eoUGJSmdfLzJ3mxIhmOAhgKEKgQkeOwKpz1NbhVnuPE= github.com/shirou/gopsutil/v3 v3.24.3/go.mod h1:JpND7O217xa72ewWz9zN2eIIkPWsDN/3pl0H8Qt0uwg= +github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= @@ -1144,34 +1156,40 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix h1:DPJD++yKLSx0EfT+U14P8vLVxjXFmoIETiCO9lVwQo8= github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= -github.com/smartcontractkit/chain-selectors v1.0.34 h1:MJ17OGu8+jjl426pcKrJkCf3fePb3eCreuAnUA3RBj4= -github.com/smartcontractkit/chain-selectors v1.0.34/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= +github.com/smartcontractkit/chain-selectors v1.0.36 h1:KSpO8I+JOiuyN4FuXsV471sPorGF//PAqwq2Cm4gRK0= +github.com/smartcontractkit/chain-selectors v1.0.36/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241213122413-5e8f65dd6b1b h1:iSQJ6ng4FhEswf8SXunGkaJlVP3E3JlgLB8Oo2f3Ud4= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241213122413-5e8f65dd6b1b/go.mod h1:F8xQAIW0ymb2BZhqn89sWZLXreJhM5KDVF6Qb4y44N0= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241214155818-b403079b2805 h1:Pz8jB/6qe10xT10h2S3LFYJrnebNpG5rJ/w16HZGwPQ= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241214155818-b403079b2805/go.mod h1:yti7e1+G9hhkYhj+L5sVUULn9Bn3bBL5/AxaNqdJ5YQ= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250120130359-cc025272bbff h1:ZEOlcleVdT0/y9V5yjgFJF0j7MpvdrFmKis/xmFNIgE= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250120130359-cc025272bbff/go.mod h1:JJZMCB75aVSAiPNW032F9WUKTlLztTd8bbQB5MEaZa4= +github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250103152858-8973fd0c912b h1:UBXi9Yj8YSMHDDaxQLu273x1fWjyEL9xP58nuJsqZfg= +github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250103152858-8973fd0c912b/go.mod h1:Bmwq4lNb5tE47sydN0TKetcLEGbgl+VxHEWp4S0LI60= +github.com/smartcontractkit/chainlink-common v0.4.2-0.20250116214855-f49c5c27db51 h1:YdjQiEu5uHWM1ApwdV+nLyJmu1+tt3IeiwPKNGoXwBI= +github.com/smartcontractkit/chainlink-common v0.4.2-0.20250116214855-f49c5c27db51/go.mod h1:yti7e1+G9hhkYhj+L5sVUULn9Bn3bBL5/AxaNqdJ5YQ= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3 h1:aeiBdBHGY8QNftps+VqrIk6OnfeeOD5z4jrAabW4ZSc= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3/go.mod h1:AS6zY2BkcRwfiGzNabGbHhfrLSrXrcI/GmjnT4jQ5/s= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250115135646-ac859d85e7e3 h1:GcPYNVFYjB065CNq0h8nK/VeU08nUkHgBX0cJIEpuHY= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250115135646-ac859d85e7e3/go.mod h1:pDZagSGjs9U+l4YIFhveDznMHqxuuz+5vRxvVgpbdr8= github.com/smartcontractkit/chainlink-feeds v0.1.1 h1:JzvUOM/OgGQA1sOqTXXl52R6AnNt+Wg64sVG+XSA49c= github.com/smartcontractkit/chainlink-feeds v0.1.1/go.mod h1:55EZ94HlKCfAsUiKUTNI7QlE/3d3IwTlsU3YNa/nBb4= +github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250115203616-a2ea5e50b260 h1:See2isL6KdrTJDlVKWv8qiyYqWhYUcubU2e5yKXV1oY= +github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250115203616-a2ea5e50b260/go.mod h1:4JqpgFy01LaqG1yM2iFTzwX3ZgcAvW9WdstBZQgPHzU= github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 h1:0ewLMbAz3rZrovdRUCgd028yOXX8KigB4FndAUdI2kM= github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0/go.mod h1:/dVVLXrsp+V0AbcYGJo3XMzKg3CkELsweA/TTopCsKE= github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0 h1:ZBat8EBvE2LpSQR9U1gEbRV6PfAkiFdINmQ8nVnXIAQ= github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241210172617-6fd1891d0fbc h1:dssRwJhmzJkUN/OajaDj2GsxBn+Tupk3bI1BkPEoJg0= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241210172617-6fd1891d0fbc/go.mod h1:p8aUDfJeley6oer7y+Ucd3edOtRlMTnWg3mN6rhaLWo= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 h1:tNS7U9lrxkFvEuyxQv11HHOiV9LPDGC9wYEy+yM/Jv4= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8/go.mod h1:EBrEgcdIbwepqguClkv8Ohy7CbyWSJaE4EC9aBJlQK0= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20250117143722-fb6416c087a5 h1:kDW6Ab8vGRK2y+DPEvvhU2It8UCS9FK5ZQqIVjDfpK4= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20250117143722-fb6416c087a5/go.mod h1:uHVnYLMgJ1rTcNoVxhBpy38t69gXq0j+LN3TkcIVE3U= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20250117171710-b6481e9fcb34 h1:tQCjnIjY88AClWXApaTS+/ihQYM1GVCrbD9W00eh11E= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20250117171710-b6481e9fcb34/go.mod h1:lgG9JT2P19KnYuBheKIis5ZeCO+AaSta+RfzvwDQS2Y= +github.com/smartcontractkit/chainlink-testing-framework/framework v0.4.2-0.20250110073248-456673e8eea2 h1:nTUoe7GZLw17nPLV5t3Vgf4U4pf+VW0Uko5xpNiKdKU= +github.com/smartcontractkit/chainlink-testing-framework/framework v0.4.2-0.20250110073248-456673e8eea2/go.mod h1:mMUqvS3BZfvN1OfK4OFTYf1+T0X6nwmSXJM2keaPsSM= github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 h1:T0kbw07Vb6xUyA9MIJZfErMgWseWi1zf7cYvRpoq7ug= github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13/go.mod h1:1CKUOzoK+Ga19WuhRH9pxZ+qUUnrlIx108VEA6qSzeQ= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA= -github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 h1:NzZGjaqez21I3DU7objl3xExTH4fxYvzTqar8DC6360= -github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= +github.com/smartcontractkit/libocr v0.0.0-20241223215956-e5b78d8e3919 h1:IpGoPTXpvllN38kT2z2j13sifJMz4nbHglidvop7mfg= +github.com/smartcontractkit/libocr v0.0.0-20241223215956-e5b78d8e3919/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de h1:n0w0rKF+SVM+S3WNlup6uabXj2zFlFNfrlsKCMMb/co= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:Sl2MF/Fp3fgJIVzhdGhmZZX2BlnM0oUUyBP4s4xYb6o= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de h1:66VQxXx3lvTaAZrMBkIcdH9VEjujUEvmBQdnyOJnkOc= @@ -1182,7 +1200,6 @@ github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= @@ -1197,7 +1214,6 @@ github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= @@ -1207,15 +1223,13 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= -github.com/streamingfast/logging v0.0.0-20220405224725-2755dab2ce75 h1:ZqpS7rAhhKD7S7DnrpEdrnW1/gZcv82ytpMviovkli4= -github.com/streamingfast/logging v0.0.0-20220405224725-2755dab2ce75/go.mod h1:VlduQ80JcGJSargkRU4Sg9Xo63wZD/l8A5NC/Uo1/uU= +github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 h1:RN5mrigyirb8anBEtdjtHFIufXdacyTi6i4KBfeNXeo= +github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091/go.mod h1:VlduQ80JcGJSargkRU4Sg9Xo63wZD/l8A5NC/Uo1/uU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= @@ -1235,8 +1249,9 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= @@ -1246,22 +1261,19 @@ github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDd github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= -github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0= -github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 h1:3SNcvBmEPE1YlB1JpVZouslJpI3GBNoiqW7+wb0Rz7w= -github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0= github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE= github.com/test-go/testify v1.1.4/go.mod h1:rH7cfJo/47vWGdi4GPj16x3/t1xGOj2YxzmNQzk2ghU= +github.com/testcontainers/testcontainers-go v0.34.0 h1:5fbgF0vIN5u+nD3IWabQwRybuB4GY8G2HHgCkbMzMHo= +github.com/testcontainers/testcontainers-go v0.34.0/go.mod h1:6P/kMkQe8yqPHfPWNulFGdFHTD8HB2vLq/231xY2iPQ= github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a h1:YuO+afVc3eqrjiCUizNCxI53bl/BnPiVwXqLzqYTqgU= github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a/go.mod h1:/sfW47zCZp9FrtGcWyo1VjbgDaodxX9ovZvgLb/MxaA= github.com/tidwall/btree v1.6.0 h1:LDZfKfQIBHGHWSwckhXI0RPSXzlo+KYdjK7FWSqOzzg= github.com/tidwall/btree v1.6.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= -github.com/tidwall/gjson v1.9.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM= github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= -github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= @@ -1271,7 +1283,6 @@ github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFA github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= @@ -1297,24 +1308,17 @@ github.com/urfave/cli v1.22.14 h1:ebbhrRiGK2i4naQJr+1Xj92HXZCrK7MsyTS/ob3HnAk= github.com/urfave/cli v1.22.14/go.mod h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA= github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fastjson v1.4.1 h1:hrltpHpIpkaxll8QltMU8c3QZ5+qIiCL8yKqPFJI/yE= github.com/valyala/fastjson v1.4.1/go.mod h1:nV6MsjxL2IMJQUoHDIrjEI7oLyeqK6aBD7EFWPsvP8o= -github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= -github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= -github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= -github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -1339,18 +1343,15 @@ go.dedis.ch/kyber/v3 v3.1.0/go.mod h1:kXy7p3STAurkADD+/aZcsznZGKVHEqbtmdIzvPfrs1 go.dedis.ch/protobuf v1.0.5/go.mod h1:eIV4wicvi6JK0q/QnfIEGeSFNG0ZeB24kzut5+HaRLo= go.dedis.ch/protobuf v1.0.7/go.mod h1:pv5ysfkDX/EawiPqcW3ikOxsL5t+BqnV6xHSmE79KI4= go.dedis.ch/protobuf v1.0.11/go.mod h1:97QR256dnkimeNdfmURz0wAMNVbd1VmLXhG1CrTYrJ4= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= -go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= go.mongodb.org/mongo-driver v1.15.0 h1:rJCKC8eEliewXjZGf0ddURtl7tTVy1TK3bfl0gkUSLc= go.mongodb.org/mongo-driver v1.15.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -1422,20 +1423,16 @@ go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKY go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/ratelimit v0.2.0/go.mod h1:YYBV4e4naJvhpitQrWJu1vCpgB7CboMe0qhltKt6mUg= go.uber.org/ratelimit v0.3.1 h1:K4qVE+byfv/B3tC+4nYWP7v/6SimcO7HzHekoMNBma0= go.uber.org/ratelimit v0.3.1/go.mod h1:6euWsTB6U/Nb3X++xEUXA8ciPJvr19Q/0h1+oDcJhRk= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.11.0 h1:KXV8WWKCXm6tRpLirl2szsO5j/oOODwZf4hATmGVNs4= golang.org/x/arch v0.11.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1457,7 +1454,6 @@ golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= @@ -1471,8 +1467,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY= -golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= +golang.org/x/exp v0.0.0-20241210194714-1829a127f884 h1:Y/Mj/94zIQQGHVSv1tTtQBDaQaJe62U9bkDZKKyhPCU= +golang.org/x/exp v0.0.0-20241210194714-1829a127f884/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1501,15 +1497,14 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= +golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -1555,8 +1550,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= -golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= +golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= +golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1591,7 +1586,6 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1607,10 +1601,10 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1672,7 +1666,6 @@ golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= @@ -1717,7 +1710,6 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1763,8 +1755,8 @@ golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= -golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= -golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= +golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8= +golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1780,7 +1772,6 @@ google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEt google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.10.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= @@ -1805,7 +1796,6 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= @@ -1815,7 +1805,6 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -1864,9 +1853,7 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go. google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= @@ -1920,16 +1907,13 @@ gopkg.in/guregu/null.v4 v4.0.0/go.mod h1:YoQhUrADuG3i9WqesrCmpNRwm1ypAgSHYqoOcTu gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1986,7 +1970,6 @@ nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYm pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw= pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= diff --git a/core/scripts/keystone/01_deploy_contracts-sample.sh b/core/scripts/keystone/01_deploy_contracts-sample.sh deleted file mode 100755 index 89e77f4556f..00000000000 --- a/core/scripts/keystone/01_deploy_contracts-sample.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -go run main.go \ - deploy-contracts \ - --ocrfile=ocr_config.json \ - --chainid=11155111 \ - --ethurl=ETH_URL \ - --accountkey=ACCOUNT_KEY \ - --onlysetconfig=false \ - --skipfunding=false \ - --dryrun=false diff --git a/core/scripts/keystone/02_deploy_jobspecs-sample.sh b/core/scripts/keystone/02_deploy_jobspecs-sample.sh deleted file mode 100755 index e99d54e0d3b..00000000000 --- a/core/scripts/keystone/02_deploy_jobspecs-sample.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -go run main.go \ - deploy-jobspecs \ - --chainid=11155111 \ - --p2pport=6690 \ - --onlyreplay=false diff --git a/core/scripts/keystone/03_gen_crib-sample.sh b/core/scripts/keystone/03_gen_crib-sample.sh deleted file mode 100755 index 9193ef4f75b..00000000000 --- a/core/scripts/keystone/03_gen_crib-sample.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -go run main.go \ - generate-crib \ - --chainid=11155111 \ - --outpath=/tmp diff --git a/core/scripts/keystone/04_delete_ocr3_jobs-sample.sh b/core/scripts/keystone/04_delete_ocr3_jobs-sample.sh deleted file mode 100755 index 3f3b50b055c..00000000000 --- a/core/scripts/keystone/04_delete_ocr3_jobs-sample.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -go run main.go delete-ocr3-jobs diff --git a/core/scripts/keystone/05_deploy_and_initialize_capabilities_registry-sample.sh b/core/scripts/keystone/05_deploy_and_initialize_capabilities_registry-sample.sh deleted file mode 100755 index 21c764be0e8..00000000000 --- a/core/scripts/keystone/05_deploy_and_initialize_capabilities_registry-sample.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -go run main.go \ - deploy-and-initialize-capabilities-registry \ - --chainid=11155111 \ - --ethurl=$ETH_URL \ - --accountkey=$ACCOUNT_KEY \ - --craddress=$CR_ADDRESS \ // 0x0d36aAC2Fd9d6d1C1F59251be6A2B337af27C52B diff --git a/core/scripts/keystone/README.md b/core/scripts/keystone/README.md deleted file mode 100644 index 9bf6adfff4e..00000000000 --- a/core/scripts/keystone/README.md +++ /dev/null @@ -1,91 +0,0 @@ -# Provisioning a CRIB keystone cluster - -Kudos to Functions team for inspiration. - -This document outlines the steps to provision a CRIB keystone cluster for testing OCR3. - -## Pre-requisites - -### Blockchain Node - -An HTTP URL to a blockchain node, such as a Geth node. This should be the same blockchain node that you used to deploy the chainlink node cluster. - -### Private Key - -A private key to a testing wallet to use for deployment and funding. This wallet should have some native token on the chain you're deploying to. For Sepolia, around 2 ETH should be sufficient. - -The easiest way to set this up is to download [Metamask](https://metamask.io/) and create a new wallet. Once you have created a wallet, you can export the private key by clicking on the three dots next to the wallet name, selecting "Account Details", and then "Show Private Key". - -## Usage - -### Your first deployment - -Using devspace, we can deploy a cluster and provision it via the `keystone` devspace profile. You'll want to follow the instructions in the [CRIB README](../../../crib/README.md) to set up your environment and deploy the cluster. - -**NOTE**: You'll want to deploy using the `keystone` profile, not the default profile file. - -```bash -# From /crib -devspace deploy --profile keystone -``` - -For convenience, setting the TTL to be a much longer value is helpful, otherwise the testnet native tokens that you send to nodes will be lost. You can set this in your crib `.env` file, or interactively via: - -```bash -# From /crib -devspace run ttl ${namespace} 7d -``` - -Everytime the interactive command is run, the TTL is reset. - -### Iterate -Let's say you made some changes to the codebase, and you want to see that reflected within the cluster. Simply redeploy via: -```bash -devspace deploy --profile keystone -``` - -### Restarting from a fresh slate - -If you want to redeploy all resources, then you'll want to do the following: - -```bash -# From /crib -devspace purge --profile keystone # Remove all k8s resources -./cribbit.sh crib- # Purge currently leaves some hanging resources, make a new namespace -devspace deploy --profile keysone --clean # Wipe any keystone related persisted data, like artefacts and caches. -``` - -## What does Provisioning a CRIB keystone cluster do? - -### Provision On-Chain Resources - -This will provision on-chain resources, namely: - -1. Deploy the forwarder contract -2. Deploy OCR3 config contract -3. Setting the configuration for the OCR3 contract -4. Funding transmitters with native tokens - -When the on-chain resources are deployed, a json file within `artefacts` will be generated. This file will contain the addresses of the forwarder contract, the OCR3 config contract, and the block number at which the configuration was set. Be careful about deleting this file, as if you lose it, you will need to redeploy the contracts and run through all proceeding steps. - -### Job Spec Deployment - -The next step is to deploy the OCR3 job specs to the chainlink node cluster. This will create a bootstrapping job for the first node of the cluster (determined via alphabetical order) and an OCR job for each other node in the cluster. - -### Update Per-Node TOML Configuration - -While we already have the chainlink node cluster deployed, we need to update the TOML configuration for each node to configure the `ChainWriter`. -After updated TOML configuration overrides are generated per node, the cluster is redeployed such that the updates that effect without wiping the databases. - -## Future Work - -### Keystone workflow deployment -Workflow style job spec deployments are not currently support, but it should be a minor modification to the existing OCR job spec deployment logic - -### Multi-DON support -Multiple DONs are not currently supported -- the devspace profile will need to be expanded so that we have multiple deployments, one per DON. -- network policy / open ports will likely have to be adjusted in the chart - -### Smarter jobspec deployment -Currently, job specs deployment logic is dumb. The scripts don't check if the jobspec to deploy already exists. If you need to redeploy a job spec that has the same name as a currently uploaded one, you'll want to delete the existing job specs via `./04_delete_ocr3_jobs.sh`. diff --git a/core/scripts/keystone/artefacts/README.md b/core/scripts/keystone/artefacts/README.md deleted file mode 100644 index 68f06dbd1c8..00000000000 --- a/core/scripts/keystone/artefacts/README.md +++ /dev/null @@ -1 +0,0 @@ -All generated artefacts will be saved here. \ No newline at end of file diff --git a/core/scripts/keystone/main.go b/core/scripts/keystone/main.go index 3486830ca32..3f14540e22c 100644 --- a/core/scripts/keystone/main.go +++ b/core/scripts/keystone/main.go @@ -15,13 +15,10 @@ type command interface { func main() { commands := []command{ - src.NewDeployContractsCommand(), - src.NewDeployJobSpecsCommand(), - src.NewGenerateCribClusterOverridesCommand(), - src.NewDeleteJobsCommand(), + src.NewProvisionKeystoneCommand(), src.NewDeployAndInitializeCapabilitiesRegistryCommand(), - src.NewDeployWorkflowsCommand(), - src.NewDeleteWorkflowsCommand(), + src.NewToolkit(), + src.NewGenerateLocalOCR3ConfigCommand(), } commandsList := func(commands []command) string { diff --git a/core/scripts/keystone/src/01_deploy_contracts_cmd.go b/core/scripts/keystone/src/01_deploy_contracts_cmd.go deleted file mode 100644 index 24fcaacd36c..00000000000 --- a/core/scripts/keystone/src/01_deploy_contracts_cmd.go +++ /dev/null @@ -1,226 +0,0 @@ -package src - -import ( - "context" - "encoding/json" - "flag" - "fmt" - "math/big" - "os" - "path/filepath" - - "github.com/ethereum/go-ethereum/common" - - helpers "github.com/smartcontractkit/chainlink/core/scripts/common" - ksdeploy "github.com/smartcontractkit/chainlink/deployment/keystone" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability" -) - -type deployedContracts struct { - OCRContract common.Address `json:"ocrContract"` - ForwarderContract common.Address `json:"forwarderContract"` - // The block number of the transaction that set the config on the OCR3 contract. We use this to replay blocks from this point on - // when we load the OCR3 job specs on the nodes. - SetConfigTxBlock uint64 `json:"setConfigTxBlock"` -} - -type deployContracts struct{} - -func NewDeployContractsCommand() *deployContracts { - return &deployContracts{} -} - -func (g *deployContracts) Name() string { - return "deploy-contracts" -} - -// Run expects the follow environment variables to be set: -// -// 1. Deploys the OCR3 contract -// 2. Deploys the Forwarder contract -// 3. Sets the config on the OCR3 contract -// 4. Writes the deployed contract addresses to a file -// 5. Funds the transmitters -func (g *deployContracts) Run(args []string) { - fs := flag.NewFlagSet(g.Name(), flag.ExitOnError) - ocrConfigFile := fs.String("ocrfile", "config_example.json", "path to OCR config file") - // create flags for all of the env vars then set the env vars to normalize the interface - // this is a bit of a hack but it's the easiest way to make this work - ethUrl := fs.String("ethurl", "", "URL of the Ethereum node") - chainID := fs.Int64("chainid", 11155111, "chain ID of the Ethereum network to deploy to") - accountKey := fs.String("accountkey", "", "private key of the account to deploy from") - skipFunding := fs.Bool("skipfunding", false, "skip funding the transmitters") - onlySetConfig := fs.Bool("onlysetconfig", false, "set the config on the OCR3 contract without deploying the contracts or funding transmitters") - dryRun := fs.Bool("dryrun", false, "dry run, don't actually deploy the contracts and do not fund transmitters") - publicKeys := fs.String("publickeys", "", "Custom public keys json location") - nodeList := fs.String("nodes", "", "Custom node list location") - artefactsDir := fs.String("artefacts", "", "Custom artefacts directory location") - - err := fs.Parse(args) - - if err != nil || - *ocrConfigFile == "" || ocrConfigFile == nil || - *ethUrl == "" || ethUrl == nil || - *chainID == 0 || chainID == nil || - *accountKey == "" || accountKey == nil { - fs.Usage() - os.Exit(1) - } - - if *artefactsDir == "" { - *artefactsDir = defaultArtefactsDir - } - if *publicKeys == "" { - *publicKeys = defaultPublicKeys - } - if *nodeList == "" { - *nodeList = defaultNodeList - } - - os.Setenv("ETH_URL", *ethUrl) - os.Setenv("ETH_CHAIN_ID", fmt.Sprintf("%d", *chainID)) - os.Setenv("ACCOUNT_KEY", *accountKey) - - deploy(*nodeList, *publicKeys, *ocrConfigFile, *skipFunding, *dryRun, *onlySetConfig, *artefactsDir) -} - -// deploy does the following: -// 1. Deploys the OCR3 contract -// 2. Deploys the Forwarder contract -// 3. Sets the config on the OCR3 contract -// 4. Writes the deployed contract addresses to a file -// 5. Funds the transmitters -func deploy( - nodeList string, - publicKeys string, - configFile string, - skipFunding bool, - dryRun bool, - onlySetConfig bool, - artefacts string, -) { - env := helpers.SetupEnv(false) - ocrConfig := generateOCR3Config( - nodeList, - configFile, - env.ChainID, - publicKeys, - ) - - if dryRun { - fmt.Println("Dry run, skipping deployment and funding") - return - } - - if onlySetConfig { - fmt.Println("Skipping deployment of contracts and skipping funding transmitters, only setting config") - setOCR3Config(env, ocrConfig, artefacts) - return - } - - if ContractsAlreadyDeployed(artefacts) { - fmt.Println("Contracts already deployed") - return - } - - fmt.Println("Deploying keystone ocr3 contract...") - ocrContract := DeployKeystoneOCR3Capability(env) - fmt.Println("Deploying keystone forwarder contract...") - forwarderContract := DeployForwarder(env) - - fmt.Println("Writing deployed contract addresses to file...") - contracts := deployedContracts{ - OCRContract: ocrContract.Address(), - ForwarderContract: forwarderContract.Address(), - } - jsonBytes, err := json.Marshal(contracts) - PanicErr(err) - - err = os.WriteFile(DeployedContractsFilePath(artefacts), jsonBytes, 0600) - PanicErr(err) - - setOCR3Config(env, ocrConfig, artefacts) - - if skipFunding { - fmt.Println("Skipping funding transmitters") - return - } - fmt.Println("Funding transmitters...") - transmittersStr := []string{} - for _, t := range ocrConfig.Transmitters { - transmittersStr = append(transmittersStr, t.String()) - } - - helpers.FundNodes(env, transmittersStr, big.NewInt(50000000000000000)) // 0.05 ETH -} - -func setOCR3Config( - env helpers.Environment, - ocrConfig ksdeploy.OCR2OracleConfig, - artefacts string, -) { - loadedContracts, err := LoadDeployedContracts(artefacts) - PanicErr(err) - - ocrContract, err := ocr3_capability.NewOCR3Capability(loadedContracts.OCRContract, env.Ec) - PanicErr(err) - fmt.Println("Setting OCR3 contract config...") - tx, err := ocrContract.SetConfig(env.Owner, - ocrConfig.Signers, - ocrConfig.Transmitters, - ocrConfig.F, - ocrConfig.OnchainConfig, - ocrConfig.OffchainConfigVersion, - ocrConfig.OffchainConfig, - ) - PanicErr(err) - receipt := helpers.ConfirmTXMined(context.Background(), env.Ec, tx, env.ChainID) - - // Write blocknumber of the transaction to the deployed contracts file - loadedContracts.SetConfigTxBlock = receipt.BlockNumber.Uint64() - jsonBytes, err := json.Marshal(loadedContracts) - PanicErr(err) - err = os.WriteFile(DeployedContractsFilePath(artefacts), jsonBytes, 0600) - PanicErr(err) -} - -func LoadDeployedContracts(artefacts string) (deployedContracts, error) { - if !ContractsAlreadyDeployed(artefacts) { - return deployedContracts{}, fmt.Errorf("no deployed contracts found, run deploy first") - } - - jsonBytes, err := os.ReadFile(DeployedContractsFilePath(artefacts)) - if err != nil { - return deployedContracts{}, err - } - - var contracts deployedContracts - err = json.Unmarshal(jsonBytes, &contracts) - return contracts, err -} - -func ContractsAlreadyDeployed(artefacts string) bool { - _, err := os.Stat(DeployedContractsFilePath(artefacts)) - return err == nil -} - -func DeployedContractsFilePath(artefacts string) string { - return filepath.Join(artefacts, deployedContractsJSON) -} - -func DeployForwarder(e helpers.Environment) *forwarder.KeystoneForwarder { - _, tx, contract, err := forwarder.DeployKeystoneForwarder(e.Owner, e.Ec) - PanicErr(err) - helpers.ConfirmContractDeployed(context.Background(), e.Ec, tx, e.ChainID) - - return contract -} - -func DeployKeystoneOCR3Capability(e helpers.Environment) *ocr3_capability.OCR3Capability { - _, tx, contract, err := ocr3_capability.DeployOCR3Capability(e.Owner, e.Ec) - PanicErr(err) - helpers.ConfirmContractDeployed(context.Background(), e.Ec, tx, e.ChainID) - - return contract -} diff --git a/core/scripts/keystone/src/01_provision_keystone.go b/core/scripts/keystone/src/01_provision_keystone.go new file mode 100644 index 00000000000..c7a2dd97127 --- /dev/null +++ b/core/scripts/keystone/src/01_provision_keystone.go @@ -0,0 +1,217 @@ +package src + +import ( + "flag" + "fmt" + "os" + "path/filepath" + "strconv" + + helpers "github.com/smartcontractkit/chainlink/core/scripts/common" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" +) + +type provisionKeystone struct{} + +func NewProvisionKeystoneCommand() *provisionKeystone { + return &provisionKeystone{} +} + +func (g *provisionKeystone) Name() string { + return "provision-keystone" +} + +func (g *provisionKeystone) Run(args []string) { + fs := flag.NewFlagSet(g.Name(), flag.ExitOnError) + + // common flags + artefactsDir := fs.String("artefacts", defaultArtefactsDir, "Custom artefacts directory location") + nodeSetSize := fs.Int("nodesetsize", 5, "number of nodes in a nodeset") + nodeSetsPath := fs.String("nodesets", defaultNodeSetsPath, "Custom node sets location") + chainID := fs.Int64("chainid", 1337, "chain ID of the Ethereum network to deploy to") + + // preprovisioning flags + preprovison := fs.Bool("preprovision", false, "Preprovision crib") + + // provisioning flags + ethURL := fs.String("ethurl", "", "URL of the Ethereum node") + accountKey := fs.String("accountkey", "", "private key of the account to deploy from") + ocrConfigFile := fs.String("ocrfile", "ocr_config.json", "path to OCR config file") + p2pPort := fs.Int64("p2pport", 6690, "p2p port") + capabilitiesP2PPort := fs.Int64("capabilitiesp2pport", 6691, "p2p port for capabilities") + preprovisionConfigName := fs.String("preprovisionconfig", "crib-preprovision.yaml", "Name of the preprovision config file, stored in the artefacts directory") + postprovisionConfigName := fs.String("postprovisionconfig", "crib-postprovision.yaml", "Name of the postprovision config file, stored in the artefacts directory") + // additional flags + clean := fs.Bool("clean", false, "Clean up resources before provisioning") + + err := fs.Parse(args) + + if err != nil || (!*preprovison && (*ethURL == "" || *accountKey == "")) { + fs.Usage() + os.Exit(1) + } + + if *preprovison { + fmt.Println() + fmt.Println() + fmt.Println("========================") + fmt.Println("Writing Preprovisioning Config") + fmt.Println("========================") + fmt.Println() + fmt.Println() + writePreprovisionConfig(*nodeSetSize, filepath.Join(*artefactsDir, *preprovisionConfigName)) + return + } + + // We always want to start with a clean slate + /// when it comes to nodesets + err = os.RemoveAll(*nodeSetsPath) + PanicErr(err) + fmt.Println("Collecting node sets...") + nodeSets := downloadNodeSets(*chainID, *nodeSetsPath, *nodeSetSize) + + if *clean { + fmt.Println("Cleaning up resources") + for _, node := range nodeSets.Workflow.Nodes { + clearJobs(newNodeAPI(node)) + } + for _, node := range nodeSets.StreamsTrigger.Nodes { + clearJobs(newNodeAPI(node)) + } + os.RemoveAll(*artefactsDir) + } + + // Kinda hacky but it prevents us from refactoring the setupenv function which + // is used in many other places + os.Setenv("ETH_URL", *ethURL) + os.Setenv("ETH_CHAIN_ID", strconv.FormatInt(*chainID, 10)) + os.Setenv("ACCOUNT_KEY", *accountKey) + os.Setenv("INSECURE_SKIP_VERIFY", "true") + env := helpers.SetupEnv(false) + + provisionStreamsDON( + env, + nodeSets.StreamsTrigger, + *chainID, + *p2pPort, + *ocrConfigFile, + *artefactsDir, + ) + + reg := provisionCapabilitiesRegistry( + env, + nodeSets, + *chainID, + *artefactsDir, + ) + + onchainMeta := provisionWorkflowDON( + env, + nodeSets.Workflow, + *chainID, + *p2pPort, + *ocrConfigFile, + *artefactsDir, + reg, + ) + + fmt.Println() + fmt.Println() + fmt.Println("========================") + fmt.Println("Writing Postprovision Config") + fmt.Println("========================") + fmt.Println() + fmt.Println() + + writePostProvisionConfig( + nodeSets, + *chainID, + *capabilitiesP2PPort, + onchainMeta.Forwarder.Address().Hex(), + onchainMeta.CapabilitiesRegistry.Address().Hex(), + filepath.Join(*artefactsDir, *postprovisionConfigName), + ) +} + +func provisionCapabilitiesRegistry( + env helpers.Environment, + nodeSets NodeSets, + chainID int64, + artefactsDir string, +) kcr.CapabilitiesRegistryInterface { + fmt.Println() + fmt.Println() + fmt.Println("========================") + fmt.Println("Provisioning Capabilities Registry DON") + fmt.Println("========================") + fmt.Println() + fmt.Println() + reg := provisionCapabillitiesRegistry( + env, + nodeSets, + chainID, + artefactsDir, + ) + return reg +} + +func provisionStreamsDON( + env helpers.Environment, + nodeSet NodeSet, + chainID int64, + p2pPort int64, + ocrConfigFilePath string, + artefactsDir string, +) { + fmt.Println() + fmt.Println() + fmt.Println("========================") + fmt.Println("Provisioning streams DON") + fmt.Println("========================") + fmt.Println() + fmt.Println() + setupStreamsTrigger( + env, + nodeSet, + chainID, + p2pPort, + ocrConfigFilePath, + artefactsDir, + ) +} + +func provisionWorkflowDON( + env helpers.Environment, + nodeSet NodeSet, + chainID int64, + p2pPort int64, + ocrConfigFile string, + artefactsDir string, + reg kcr.CapabilitiesRegistryInterface, +) (onchainMeta *onchainMeta) { + fmt.Println() + fmt.Println() + fmt.Println("========================") + fmt.Println("Provisioning workflow DON") + fmt.Println("========================") + fmt.Println() + fmt.Println() + deployForwarder(env, artefactsDir) + + onchainMeta, _ = provisionOCR3( + env, + nodeSet, + chainID, + p2pPort, + ocrConfigFile, + artefactsDir, + ) + distributeFunds(nodeSet.NodeKeys, env) + + // We don't technically need the capability registry as a dependency + // as we just use it for a sanity check + // We could remove it so that we can execute provisioning in parallel + deployKeystoneWorkflowsTo(nodeSet, reg) + + return onchainMeta +} diff --git a/core/scripts/keystone/src/01_toolkit.go b/core/scripts/keystone/src/01_toolkit.go new file mode 100644 index 00000000000..6fe896667ce --- /dev/null +++ b/core/scripts/keystone/src/01_toolkit.go @@ -0,0 +1,212 @@ +// This sub CLI acts as a temporary shim for external aptos support + +package src + +import ( + "bufio" + "errors" + "flag" + "fmt" + "net/url" + "os" + "strconv" + "strings" + + helpers "github.com/smartcontractkit/chainlink/core/scripts/common" +) + +type Toolkit struct{} + +func (t *Toolkit) Name() string { + return "toolkit" +} + +func NewToolkit() *Toolkit { + return &Toolkit{} +} + +func (t *Toolkit) Run(args []string) { + if len(args) < 1 { + fmt.Println("Available commands:") + fmt.Println(" deploy-workflows") + fmt.Println(" deploy-ocr3-contracts") + fmt.Println(" deploy-ocr3-jobspecs") + os.Exit(1) + } + + command := args[0] + cmdArgs := args[1:] + + switch command { + case "get-aptos-keys": + t.AptosKeys(cmdArgs) + case "deploy-workflows": + t.DeployWorkflows(cmdArgs) + case "deploy-ocr3-contracts": + t.ProvisionOCR3Contracts(cmdArgs) + case "deploy-ocr3-jobspecs": + t.DeployOCR3JobSpecs(cmdArgs) + default: + fmt.Printf("Unknown command: %s\n", command) + os.Exit(1) + } +} + +func (t *Toolkit) AptosKeys(args []string) { + fs := flag.NewFlagSet("get-aptos-keys", flag.ExitOnError) + nodesListPath := fs.String("nodes", ".cache/NodesList.txt", "Path to file with list of nodes") + artefacts := fs.String("artefacts", defaultArtefactsDir, "Custom artefacts directory location") + chainID := fs.Int64("chainid", 1337, "Chain ID") + + if err := fs.Parse(args); err != nil { + fs.Usage() + os.Exit(1) + } + + nodes := mustReadNodesList(*nodesListPath) + keys := mustFetchNodeKeys(*chainID, nodes, true) + + mustWriteJSON(*artefacts+"/pubnodekeys.json", keys) +} + +func (t *Toolkit) ProvisionOCR3Contracts(args []string) { + fs := flag.NewFlagSet("deploy-ocr3-contracts", flag.ExitOnError) + ethURL := fs.String("ethurl", "", "URL of the Ethereum node") + accountKey := fs.String("accountkey", "", "Private key of the deployer account") + chainID := fs.Int64("chainid", 1337, "Chain ID") + nodesListPath := fs.String("nodes", ".cache/NodesList.txt", "Path to file with list of nodes") + artefactsDir := fs.String("artefacts", defaultArtefactsDir, "Custom artefacts directory location") + ocrConfigFile := fs.String("ocrfile", "ocr_config.json", "Path to OCR config file") + + if err := fs.Parse(args); err != nil || *ethURL == "" || *accountKey == "" { + fs.Usage() + os.Exit(1) + } + + // Set environment variables required by setupenv + os.Setenv("ETH_URL", *ethURL) + os.Setenv("ETH_CHAIN_ID", strconv.FormatInt(*chainID, 10)) + os.Setenv("ACCOUNT_KEY", *accountKey) + os.Setenv("INSECURE_SKIP_VERIFY", "true") + + env := helpers.SetupEnv(false) + + nodes := mustReadNodesList(*nodesListPath) + nodeKeys := mustFetchNodeKeys(*chainID, nodes, true) + + deployOCR3Contract(nodeKeys, env, *ocrConfigFile, *artefactsDir) +} + +func (t *Toolkit) DeployOCR3JobSpecs(args []string) { + fs := flag.NewFlagSet("deploy-ocr3-jobspecs", flag.ExitOnError) + + ethURL := fs.String("ethurl", "", "URL of the Ethereum node") + accountKey := fs.String("accountkey", "", "Private key of the deployer account") + chainID := fs.Int64("chainid", 1337, "Chain ID") + nodesListPath := fs.String("nodes", ".cache/NodesList.txt", "Path to file with list of nodes") + p2pPort := fs.Int64("p2pport", 6690, "P2P port") + artefactsDir := fs.String("artefacts", defaultArtefactsDir, "Custom artefacts directory location") + + if err := fs.Parse(args); err != nil || *ethURL == "" || *accountKey == "" { + fs.Usage() + os.Exit(1) + } + + os.Setenv("ETH_URL", *ethURL) + os.Setenv("ETH_CHAIN_ID", strconv.FormatInt(*chainID, 10)) + os.Setenv("ACCOUNT_KEY", *accountKey) + os.Setenv("INSECURE_SKIP_VERIFY", "true") + + env := helpers.SetupEnv(false) + + nodes := mustReadNodesList(*nodesListPath) + nodeKeys := mustFetchNodeKeys(*chainID, nodes, true) + o := LoadOnchainMeta(*artefactsDir, env) + + deployOCR3JobSpecs( + nodes, + *chainID, + nodeKeys, + *p2pPort, + o, + ) +} + +func (t *Toolkit) DeployWorkflows(args []string) { + fs := flag.NewFlagSet("deploy-workflows", flag.ExitOnError) + workflowFile := fs.String("workflow", "", "Path to workflow file") + nodesList := fs.String("nodes", ".cache/NodesList.txt", "Path to file with list of nodes") + + if err := fs.Parse(args); err != nil || *workflowFile == "" { + fs.Usage() + os.Exit(1) + } + + nodesWithCreds := mustReadNodesList(*nodesList) + + for _, node := range nodesWithCreds { + api := newNodeAPI(node) + workflowContent, err := os.ReadFile(*workflowFile) + PanicErr(err) + + upsertJob(api, "workflow", string(workflowContent)) + fmt.Println("Workflow deployed successfully") + } +} + +// Reads in a list of nodes from a file, where each line is in the format: +// http://localhost:50100 http://chainlink.core.1:50100 notreal@fakeemail.ch fj293fbBnlQ!f9vNs +func mustReadNodesList(path string) []NodeWithCreds { + fmt.Println("Reading nodes list from", path) + nodesList, err := readLines(path) + helpers.PanicErr(err) + + nodes := make([]NodeWithCreds, 0, len(nodesList)) + for _, r := range nodesList { + rr := strings.TrimSpace(r) + if len(rr) == 0 { + continue + } + s := strings.Split(rr, " ") + if len(s) != 4 { + helpers.PanicErr(errors.New("wrong nodes list format")) + } + + r := SimpleURL{ + Scheme: "http", + Host: s[0], + } + u := SimpleURL{ + Scheme: "http", + Host: s[1], + } + remoteURL, err := url.Parse(u.String()) + PanicErr(err) + nodes = append(nodes, NodeWithCreds{ + URL: u, + RemoteURL: r, + // This is the equivalent of "chainlink.core.1" in our above example + ServiceName: remoteURL.Hostname(), + APILogin: s[2], + APIPassword: s[3], + KeystorePassword: "", + }) + } + + return nodes +} + +func readLines(path string) ([]string, error) { + file, err := os.Open(path) + if err != nil { + return nil, err + } + defer file.Close() + + var lines []string + scanner := bufio.NewScanner(file) + for scanner.Scan() { + lines = append(lines, scanner.Text()) + } + return lines, scanner.Err() +} diff --git a/core/scripts/keystone/src/01_toolkit_test.go b/core/scripts/keystone/src/01_toolkit_test.go new file mode 100644 index 00000000000..6f4a083940e --- /dev/null +++ b/core/scripts/keystone/src/01_toolkit_test.go @@ -0,0 +1,49 @@ +package src + +import ( + "os" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestMustReadNodesList(t *testing.T) { + t.Run("valid nodes list", func(t *testing.T) { + content := "localhost:50100 chainlink.core.1:50100 user1 pass1\nlocalhost:50101 chainlink.core.2:50101 user2 pass2" + filePath := writeTempFile(t, content) + defer os.Remove(filePath) + + nodes := mustReadNodesList(filePath) + assert.Len(t, nodes, 2) + + assert.Equal(t, "user1", nodes[0].APILogin) + assert.Equal(t, "user2", nodes[1].APILogin) + + assert.Equal(t, "pass1", nodes[0].APIPassword) + assert.Equal(t, "pass2", nodes[1].APIPassword) + + assert.Equal(t, "http://localhost:50100", nodes[0].RemoteURL.String()) + assert.Equal(t, "http://localhost:50101", nodes[1].RemoteURL.String()) + + assert.Equal(t, "chainlink.core.1", nodes[0].ServiceName) + assert.Equal(t, "chainlink.core.2", nodes[1].ServiceName) + + assert.Equal(t, "http://chainlink.core.1:50100", nodes[0].URL.String()) + assert.Equal(t, "http://chainlink.core.2:50101", nodes[1].URL.String()) + }) +} + +func writeTempFile(t *testing.T, content string) string { + file, err := os.CreateTemp("", "nodeslist") + if err != nil { + t.Fatalf("failed to create temp file: %v", err) + } + defer file.Close() + + _, err = file.WriteString(content) + if err != nil { + t.Fatalf("failed to write to temp file: %v", err) + } + + return file.Name() +} diff --git a/core/scripts/keystone/src/02_deploy_jobspecs_cmd.go b/core/scripts/keystone/src/02_deploy_jobspecs_cmd.go deleted file mode 100644 index 275943d6388..00000000000 --- a/core/scripts/keystone/src/02_deploy_jobspecs_cmd.go +++ /dev/null @@ -1,165 +0,0 @@ -package src - -import ( - "bytes" - "errors" - "flag" - "fmt" - "os" - "reflect" - "runtime" - "strings" - - "github.com/urfave/cli" - - helpers "github.com/smartcontractkit/chainlink/core/scripts/common" - "github.com/smartcontractkit/chainlink/v2/core/cmd" -) - -type deployJobSpecs struct{} - -func NewDeployJobSpecsCommand() *deployJobSpecs { - return &deployJobSpecs{} -} - -func (g *deployJobSpecs) Name() string { - return "deploy-jobspecs" -} - -func (g *deployJobSpecs) Run(args []string) { - fs := flag.NewFlagSet(g.Name(), flag.ContinueOnError) - chainID := fs.Int64("chainid", 11155111, "chain id") - p2pPort := fs.Int64("p2pport", 6690, "p2p port") - onlyReplay := fs.Bool("onlyreplay", false, "only replay the block from the OCR3 contract setConfig transaction") - templatesLocation := fs.String("templates", "", "Custom templates location") - nodeList := fs.String("nodes", "", "Custom node list location") - publicKeys := fs.String("publickeys", "", "Custom public keys json location") - artefactsDir := fs.String("artefacts", "", "Custom artefacts directory location") - - err := fs.Parse(args) - if err != nil || chainID == nil || *chainID == 0 || p2pPort == nil || *p2pPort == 0 || onlyReplay == nil { - fs.Usage() - os.Exit(1) - } - if *onlyReplay { - fmt.Println("Only replaying OCR3 contract setConfig transaction") - } else { - fmt.Println("Deploying OCR3 job specs") - } - - if *artefactsDir == "" { - *artefactsDir = defaultArtefactsDir - } - if *publicKeys == "" { - *publicKeys = defaultPublicKeys - } - if *nodeList == "" { - *nodeList = defaultNodeList - } - if *templatesLocation == "" { - *templatesLocation = "templates" - } - - nodes := downloadNodeAPICredentials(*nodeList) - deployedContracts, err := LoadDeployedContracts(*artefactsDir) - PanicErr(err) - - jobspecs := genSpecs( - *publicKeys, - *nodeList, - *templatesLocation, - *chainID, *p2pPort, deployedContracts.OCRContract.Hex(), - ) - flattenedSpecs := []hostSpec{jobspecs.bootstrap} - flattenedSpecs = append(flattenedSpecs, jobspecs.oracles...) - - // sanity check arr lengths - if len(nodes) != len(flattenedSpecs) { - PanicErr(errors.New("Mismatched node and job spec lengths")) - } - - for i, n := range nodes { - output := &bytes.Buffer{} - client, app := newApp(n, output) - fmt.Println("Logging in:", n.url) - loginFs := flag.NewFlagSet("test", flag.ContinueOnError) - loginFs.Bool("bypass-version-check", true, "") - loginCtx := cli.NewContext(app, loginFs, nil) - err := client.RemoteLogin(loginCtx) - helpers.PanicErr(err) - output.Reset() - - if !*onlyReplay { - specToDeploy := flattenedSpecs[i].spec.ToString() - specFragment := flattenedSpecs[i].spec[0:1] - fmt.Printf("Deploying jobspec: %s\n... \n", specFragment) - fs := flag.NewFlagSet("test", flag.ExitOnError) - err = fs.Parse([]string{specToDeploy}) - - helpers.PanicErr(err) - err = client.CreateJob(cli.NewContext(app, fs, nil)) - if err != nil { - fmt.Println("Failed to deploy job spec:", specFragment, "Error:", err) - } - output.Reset() - } - - replayFs := flag.NewFlagSet("test", flag.ExitOnError) - flagSetApplyFromAction(client.ReplayFromBlock, replayFs, "") - err = replayFs.Set("block-number", fmt.Sprint(deployedContracts.SetConfigTxBlock)) - helpers.PanicErr(err) - err = replayFs.Set("evm-chain-id", fmt.Sprint(*chainID)) - helpers.PanicErr(err) - - fmt.Printf("Replaying from block: %d\n", deployedContracts.SetConfigTxBlock) - fmt.Printf("EVM Chain ID: %d\n\n", *chainID) - replayCtx := cli.NewContext(app, replayFs, nil) - err = client.ReplayFromBlock(replayCtx) - helpers.PanicErr(err) - } -} - -// flagSetApplyFromAction applies the flags from action to the flagSet. -// -// `parentCommand` will filter the app commands and only applies the flags if the command/subcommand has a parent with that name, if left empty no filtering is done -// -// Taken from: https://github.com/smartcontractkit/chainlink/blob/develop/core/cmd/shell_test.go#L590 -func flagSetApplyFromAction(action interface{}, flagSet *flag.FlagSet, parentCommand string) { - cliApp := cmd.Shell{} - app := cmd.NewApp(&cliApp) - - foundName := parentCommand == "" - actionFuncName := getFuncName(action) - - for _, command := range app.Commands { - flags := recursiveFindFlagsWithName(actionFuncName, command, parentCommand, foundName) - - for _, flag := range flags { - 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 - } - } - - for _, subcommand := range command.Subcommands { - if !foundName { - foundName = strings.EqualFold(subcommand.Name, parent) - } - - found := recursiveFindFlagsWithName(actionFuncName, subcommand, parent, foundName) - if found != nil { - return found - } - } - return nil -} - -func getFuncName(i interface{}) string { - return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name() -} diff --git a/core/scripts/keystone/src/02_deploy_keystone_workflows.go b/core/scripts/keystone/src/02_deploy_keystone_workflows.go new file mode 100644 index 00000000000..6c6580e21f0 --- /dev/null +++ b/core/scripts/keystone/src/02_deploy_keystone_workflows.go @@ -0,0 +1,134 @@ +package src + +import ( + "bytes" + "fmt" + "text/template" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" +) + +func deployKeystoneWorkflowsTo(nodeSet NodeSet, reg kcr.CapabilitiesRegistryInterface) { + fmt.Println("Deploying Keystone workflow jobs") + caps, err := reg.GetCapabilities(&bind.CallOpts{}) + PanicErr(err) + + streams := NewStreamsTriggerV1Capability() + ocr3 := NewOCR3V1ConsensusCapability() + testnetWrite := NewEthereumGethTestnetV1WriteCapability() + + capSet := NewCapabilitySet(streams, ocr3, testnetWrite) + expectedHashedCIDs := capSet.HashedIDs(reg) + + // Check that the capabilities are registered + for _, c := range caps { + found := false + for _, expected := range expectedHashedCIDs { + if c.HashedId == expected { + found = true + break + } + } + + if !found { + panic(fmt.Sprintf("Capability %s not found in registry", c.HashedId)) + } + } + + feedIDs := []string{} + for _, feed := range feeds { + feedIDs = append(feedIDs, fmt.Sprintf("0x%x", feed.id)) + } + workflowConfig := WorkflowJobSpecConfig{ + JobSpecName: "keystone_workflow", + WorkflowOwnerAddress: "0x1234567890abcdef1234567890abcdef12345678", + FeedIDs: feedIDs, + TargetID: testnetWrite.GetID(), + ConsensusID: ocr3.GetID(), + TriggerID: streams.GetID(), + TargetAddress: "0x1234567890abcdef1234567890abcdef12345678", + } + jobSpecStr := createKeystoneWorkflowJob(workflowConfig) + for _, n := range nodeSet.Nodes[1:] { // skip the bootstrap node + api := newNodeAPI(n) + upsertJob(api, workflowConfig.JobSpecName, jobSpecStr) + } +} + +type WorkflowJobSpecConfig struct { + JobSpecName string + WorkflowOwnerAddress string + FeedIDs []string + TargetID string + ConsensusID string + TriggerID string + TargetAddress string +} + +func createKeystoneWorkflowJob(workflowConfig WorkflowJobSpecConfig) string { + const keystoneWorkflowTemplate = ` +type = "workflow" +schemaVersion = 1 +name = "{{ .JobSpecName }}" +workflow = """ +name: "ccip_kiab1" +owner: '{{ .WorkflowOwnerAddress }}' +triggers: + - id: streams-trigger@1.1.0 + config: + maxFrequencyMs: 10000 + feedIds: +{{- range .FeedIDs }} + - '{{ . }}' +{{- end }} + +consensus: + - id: offchain_reporting@1.0.0 + ref: ccip_feeds + inputs: + observations: + - $(trigger.outputs) + config: + report_id: '0001' + key_id: 'evm' + aggregation_method: data_feeds + aggregation_config: + feeds: +{{- range .FeedIDs }} + '{{ . }}': + deviation: '0.05' + heartbeat: 1800 +{{- end }} + encoder: EVM + encoder_config: + abi: "(bytes32 FeedID, uint224 Price, uint32 Timestamp)[] Reports" + abi: (bytes32 FeedID, uint224 Price, uint32 Timestamp)[] Reports + +targets: + - id: {{ .TargetID }} + inputs: + signed_report: $(ccip_feeds.outputs) + config: + address: '{{ .TargetAddress }}' + deltaStage: 5s + schedule: oneAtATime + +""" +workflowOwner = "{{ .WorkflowOwnerAddress }}" +` + + tmpl, err := template.New("workflow").Parse(keystoneWorkflowTemplate) + + if err != nil { + panic(err) + } + var renderedTemplate bytes.Buffer + err = tmpl.Execute(&renderedTemplate, workflowConfig) + if err != nil { + panic(err) + } + + return renderedTemplate.String() +} diff --git a/core/scripts/keystone/src/02_deploy_keystone_workflows_test.go b/core/scripts/keystone/src/02_deploy_keystone_workflows_test.go new file mode 100644 index 00000000000..bef6a768dce --- /dev/null +++ b/core/scripts/keystone/src/02_deploy_keystone_workflows_test.go @@ -0,0 +1,21 @@ +package src + +import ( + "testing" + + "github.com/gkampitakis/go-snaps/snaps" +) + +func TestCreateKeystoneWorkflowJob(t *testing.T) { + workflowConfig := WorkflowJobSpecConfig{ + JobSpecName: "keystone_workflow", + WorkflowOwnerAddress: "0x1234567890abcdef1234567890abcdef12345678", + FeedIDs: []string{"feed1", "feed2", "feed3"}, + TargetID: "target_id", + TargetAddress: "0xabcdefabcdefabcdefabcdefabcdefabcdef", + } + + output := createKeystoneWorkflowJob(workflowConfig) + + snaps.MatchSnapshot(t, output) +} diff --git a/core/scripts/keystone/src/02_fund_transmitters.go b/core/scripts/keystone/src/02_fund_transmitters.go new file mode 100644 index 00000000000..751a90d22d8 --- /dev/null +++ b/core/scripts/keystone/src/02_fund_transmitters.go @@ -0,0 +1,52 @@ +package src + +import ( + "context" + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/conversions" + helpers "github.com/smartcontractkit/chainlink/core/scripts/common" +) + +func distributeFunds(nodeKeys []NodeKeys, env helpers.Environment) { + fmt.Println("Funding transmitters...") + transmittersStr := []string{} + fundingAmount := big.NewInt(500000000000000000) // 0.5 ETH + minThreshold := big.NewInt(50000000000000000) // 0.05 ETH + + for _, n := range nodeKeys { + balance, err := getBalance(n.EthAddress, env) + if err != nil { + fmt.Printf("Error fetching balance for %s: %v\n", n.EthAddress, err) + continue + } + if balance.Cmp(minThreshold) < 0 { + fmt.Printf( + "Transmitter %s has insufficient funds, funding with %s ETH. Current balance: %s, threshold: %s\n", + n.EthAddress, + conversions.WeiToEther(fundingAmount).String(), + conversions.WeiToEther(balance).String(), + conversions.WeiToEther(minThreshold).String(), + ) + transmittersStr = append(transmittersStr, n.EthAddress) + } + } + + if len(transmittersStr) > 0 { + helpers.FundNodes(env, transmittersStr, fundingAmount) + } else { + fmt.Println("All transmitters have sufficient funds.") + } +} + +func getBalance(address string, env helpers.Environment) (*big.Int, error) { + balance, err := env.Ec.BalanceAt(context.Background(), common.HexToAddress(address), nil) + if err != nil { + return nil, err + } + + return balance, nil +} diff --git a/core/scripts/keystone/src/02_provision_capabilities_registry.go b/core/scripts/keystone/src/02_provision_capabilities_registry.go new file mode 100644 index 00000000000..aa0f203f96b --- /dev/null +++ b/core/scripts/keystone/src/02_provision_capabilities_registry.go @@ -0,0 +1,68 @@ +package src + +import ( + "context" + "fmt" + + helpers "github.com/smartcontractkit/chainlink/core/scripts/common" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" +) + +func provisionCapabillitiesRegistry(env helpers.Environment, nodeSets NodeSets, chainID int64, artefactsDir string) kcr.CapabilitiesRegistryInterface { + fmt.Printf("Provisioning capabilities registry on chain %d\n", chainID) + ctx := context.Background() + reg := deployCR(ctx, artefactsDir, env) + crProvisioner := NewCapabilityRegistryProvisioner(reg, env) + streamsTriggerCapSet := NewCapabilitySet(NewStreamsTriggerV1Capability()) + workflowCapSet := NewCapabilitySet(NewOCR3V1ConsensusCapability(), NewEthereumGethTestnetV1WriteCapability()) + workflowDON := nodeKeysToDON(nodeSets.Workflow.Name, nodeSets.Workflow.NodeKeys[1:], workflowCapSet) + streamsTriggerDON := nodeKeysToDON(nodeSets.StreamsTrigger.Name, nodeSets.StreamsTrigger.NodeKeys[1:], streamsTriggerCapSet) + + crProvisioner.AddCapabilities(ctx, MergeCapabilitySets(streamsTriggerCapSet, workflowCapSet)) + dons := map[string]DON{workflowDON.Name: workflowDON, streamsTriggerDON.Name: streamsTriggerDON} + nodeOperator := NewNodeOperator(env.Owner.From, "MY_NODE_OPERATOR", dons) + crProvisioner.AddNodeOperator(ctx, nodeOperator) + + crProvisioner.AddNodes(ctx, nodeOperator, nodeSets.Workflow.Name, nodeSets.StreamsTrigger.Name) + + crProvisioner.AddDON(ctx, nodeOperator, nodeSets.Workflow.Name, true, true) + crProvisioner.AddDON(ctx, nodeOperator, nodeSets.StreamsTrigger.Name, true, false) + + return reg +} + +// nodeKeysToDON converts a slice of NodeKeys into a DON struct with the given name and CapabilitySet. +func nodeKeysToDON(donName string, nodeKeys []NodeKeys, capSet CapabilitySet) DON { + peers := []peer{} + for _, n := range nodeKeys { + p := peer{ + PeerID: n.P2PPeerID, + Signer: n.OCR2OnchainPublicKey, + } + peers = append(peers, p) + } + return DON{ + F: 1, + Name: donName, + Peers: peers, + CapabilitySet: capSet, + } +} + +func deployCR(ctx context.Context, artefactsDir string, env helpers.Environment) kcr.CapabilitiesRegistryInterface { + o := LoadOnchainMeta(artefactsDir, env) + // We always redeploy the capabilities registry to ensure it is up to date + // since we don't have diffing logic to determine if it has changed + // if o.CapabilitiesRegistry != nil { + // fmt.Println("CapabilitiesRegistry already deployed, skipping...") + // return o.CapabilitiesRegistry + // } + + _, tx, capabilitiesRegistry, innerErr := kcr.DeployCapabilitiesRegistry(env.Owner, env.Ec) + PanicErr(innerErr) + helpers.ConfirmContractDeployed(ctx, env.Ec, tx, env.ChainID) + + o.CapabilitiesRegistry = capabilitiesRegistry + WriteOnchainMeta(o, artefactsDir) + return capabilitiesRegistry +} diff --git a/core/scripts/keystone/src/02_provision_crib.go b/core/scripts/keystone/src/02_provision_crib.go new file mode 100644 index 00000000000..bf3a31f8b7e --- /dev/null +++ b/core/scripts/keystone/src/02_provision_crib.go @@ -0,0 +1,310 @@ +package src + +import ( + "fmt" + "os" + "path/filepath" + "strconv" + + ocrcommontypes "github.com/smartcontractkit/libocr/commontypes" + "gopkg.in/yaml.v3" + + helpers "github.com/smartcontractkit/chainlink/core/scripts/common" + evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" + "github.com/smartcontractkit/chainlink/v2/core/config/toml" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" +) + +type Helm struct { + Helm Chart `yaml:"helm"` +} + +type Chart struct { + HelmValues HelmValues `yaml:"values"` +} + +type HelmValues struct { + Chainlink Chainlink `yaml:"chainlink,omitempty"` + Ingress Ingress `yaml:"ingress,omitempty"` +} + +type Ingress struct { + Hosts []Host `yaml:"hosts,omitempty"` +} + +type Host struct { + Host string `yaml:"host,omitempty"` + HTTP HTTP `yaml:"http,omitempty"` +} + +type HTTP struct { + Paths []Path `yaml:"paths,omitempty"` +} + +type Path struct { + Path string `yaml:"path,omitempty"` + Backend Backend `yaml:"backend,omitempty"` +} + +type Backend struct { + Service Service `yaml:"service,omitempty"` +} + +type Service struct { + Name string `yaml:"name,omitempty"` + Port Port `yaml:"port,omitempty"` +} + +type Port struct { + Number int `yaml:"number,omitempty"` +} + +type Chainlink struct { + Nodes map[string]Node `yaml:"nodes,omitempty"` +} + +type Node struct { + Image string `yaml:"image,omitempty"` + OverridesToml string `yaml:"overridesToml,omitempty"` +} + +func writePreprovisionConfig(nodeSetSize int, outputPath string) { + chart := generatePreprovisionConfig(nodeSetSize) + + writeCribConfig(chart, outputPath) +} + +func writeCribConfig(chart Helm, outputPath string) { + yamlData, err := yaml.Marshal(chart) + helpers.PanicErr(err) + + if outputPath == "-" { + _, err = os.Stdout.Write(yamlData) + helpers.PanicErr(err) + } else { + ensureArtefactsDir(filepath.Dir(outputPath)) + err = os.WriteFile(outputPath, yamlData, 0600) + helpers.PanicErr(err) + } +} + +func generatePreprovisionConfig(nodeSetSize int) Helm { + nodeSets := []string{"ks-wf-", "ks-str-trig-"} + nodes := make(map[string]Node) + nodeNames := []string{} + + for nodeSetIndex, prefix := range nodeSets { + // Bootstrap node + btNodeName := fmt.Sprintf("%d-%sbt-node1", nodeSetIndex, prefix) + nodeNames = append(nodeNames, btNodeName) + nodes[btNodeName] = Node{ + Image: "${runtime.images.app}", + } + + // Other nodes + for i := 2; i <= nodeSetSize; i++ { + nodeName := fmt.Sprintf("%d-%snode%d", nodeSetIndex, prefix, i) + nodeNames = append(nodeNames, nodeName) + nodes[nodeName] = Node{ + Image: "${runtime.images.app}", + } + } + } + + ingress := generateIngress(nodeNames) + + helm := Helm{ + Chart{ + HelmValues: HelmValues{ + Chainlink: Chainlink{ + Nodes: nodes, + }, + Ingress: ingress, + }, + }, + } + + return helm +} + +func writePostProvisionConfig( + nodeSets NodeSets, + chainID int64, + capabilitiesP2PPort int64, + forwarderAddress string, + capabilitiesRegistryAddress string, + outputPath string, +) { + chart := generatePostprovisionConfig( + nodeSets, + chainID, + capabilitiesP2PPort, + forwarderAddress, + capabilitiesRegistryAddress, + ) + + writeCribConfig(chart, outputPath) +} + +func generatePostprovisionConfig( + nodeSets NodeSets, + chainID int64, + capabilitiesP2PPort int64, + forwarderAddress string, + capabillitiesRegistryAddress string, +) Helm { + nodes := make(map[string]Node) + nodeNames := []string{} + var capabilitiesBootstrapper *ocrcommontypes.BootstrapperLocator + + // Build nodes for each NodeSet + for nodeSetIndex, nodeSet := range []NodeSet{nodeSets.Workflow, nodeSets.StreamsTrigger} { + // Bootstrap node + btNodeName := fmt.Sprintf("%d-%sbt-node1", nodeSetIndex, nodeSet.Prefix) + // Note this line ordering is important, + // we assign capabilitiesBootstrapper after we generate overrides so that + // we do not include the bootstrapper config to itself + overridesToml := generateOverridesToml( + chainID, + capabilitiesP2PPort, + capabillitiesRegistryAddress, + "", + "", + capabilitiesBootstrapper, + nodeSet.Name, + ) + nodes[btNodeName] = Node{ + Image: "${runtime.images.app}", + OverridesToml: overridesToml, + } + if nodeSet.Name == WorkflowNodeSetName { + workflowBtNodeKey := nodeSets.Workflow.NodeKeys[0] // First node key as bootstrapper + wfBt, err := ocrcommontypes.NewBootstrapperLocator(workflowBtNodeKey.P2PPeerID, []string{fmt.Sprintf("%s:%d", nodeSets.Workflow.Nodes[0].ServiceName, capabilitiesP2PPort)}) + helpers.PanicErr(err) + capabilitiesBootstrapper = wfBt + } + nodeNames = append(nodeNames, btNodeName) + + // Other nodes + for i, nodeKey := range nodeSet.NodeKeys[1:] { // Start from second key + nodeName := fmt.Sprintf("%d-%snode%d", nodeSetIndex, nodeSet.Prefix, i+2) + nodeNames = append(nodeNames, nodeName) + overridesToml := generateOverridesToml( + chainID, + capabilitiesP2PPort, + capabillitiesRegistryAddress, + nodeKey.EthAddress, + forwarderAddress, + capabilitiesBootstrapper, + nodeSet.Name, + ) + nodes[nodeName] = Node{ + Image: "${runtime.images.app}", + OverridesToml: overridesToml, + } + } + } + + ingress := generateIngress(nodeNames) + + helm := Helm{ + Chart{ + HelmValues: HelmValues{ + Chainlink: Chainlink{ + Nodes: nodes, + }, + Ingress: ingress, + }, + }, + } + + return helm +} + +func generateOverridesToml( + chainID int64, + capabilitiesP2PPort int64, + externalRegistryAddress string, + fromAddress string, + forwarderAddress string, + capabilitiesBootstrapper *ocrcommontypes.BootstrapperLocator, + nodeSetName string, +) string { + evmConfig := &evmcfg.EVMConfig{ + ChainID: big.NewI(chainID), + Nodes: nil, // We have the rpc nodes set globally + } + + conf := chainlink.Config{ + Core: toml.Core{ + Capabilities: toml.Capabilities{ + ExternalRegistry: toml.ExternalRegistry{ + Address: ptr(externalRegistryAddress), + NetworkID: ptr("evm"), + ChainID: ptr(strconv.FormatInt(chainID, 10)), + }, + Peering: toml.P2P{ + V2: toml.P2PV2{ + Enabled: ptr(true), + ListenAddresses: ptr([]string{fmt.Sprintf("0.0.0.0:%d", capabilitiesP2PPort)}), + }, + }, + }, + }, + } + + if capabilitiesBootstrapper != nil { + conf.Core.Capabilities.Peering.V2.DefaultBootstrappers = ptr([]ocrcommontypes.BootstrapperLocator{*capabilitiesBootstrapper}) + + if nodeSetName == WorkflowNodeSetName { + evmConfig.Workflow = evmcfg.Workflow{ + FromAddress: ptr(evmtypes.MustEIP55Address(fromAddress)), + ForwarderAddress: ptr(evmtypes.MustEIP55Address(forwarderAddress)), + } + } + } + + conf.EVM = evmcfg.EVMConfigs{ + evmConfig, + } + + confStr, err := conf.TOMLString() + helpers.PanicErr(err) + + return confStr +} + +// New function to generate Ingress +func generateIngress(nodeNames []string) Ingress { + hosts := make([]Host, 0, len(nodeNames)) + + for _, nodeName := range nodeNames { + host := Host{ + Host: fmt.Sprintf("${DEVSPACE_NAMESPACE}-%s.${DEVSPACE_INGRESS_BASE_DOMAIN}", nodeName), + HTTP: HTTP{ + Paths: []Path{ + { + Path: "/", + Backend: Backend{ + Service: Service{ + Name: "app-" + nodeName, + Port: Port{ + Number: 6688, + }, + }, + }, + }, + }, + }, + } + hosts = append(hosts, host) + } + + return Ingress{ + Hosts: hosts, + } +} + +func ptr[T any](t T) *T { return &t } diff --git a/core/scripts/keystone/src/02_provision_crib_test.go b/core/scripts/keystone/src/02_provision_crib_test.go new file mode 100644 index 00000000000..4e4cbf1efd5 --- /dev/null +++ b/core/scripts/keystone/src/02_provision_crib_test.go @@ -0,0 +1,44 @@ +package src + +import ( + "strings" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/gkampitakis/go-snaps/snaps" + "gopkg.in/yaml.v3" +) + +func TestGeneratePostprovisionConfig(t *testing.T) { + chainID := int64(1337) + capabilitiesP2PPort := int64(6691) + nodeSetsPath := "./testdata/node_sets.json" + nodeSetSize := 5 + forwarderAddress := common.Address([20]byte{0: 1}).Hex() + capabilitiesRegistryAddress := common.Address([20]byte{0: 2}).Hex() + nodeSets := downloadNodeSets(chainID, nodeSetsPath, nodeSetSize) + + chart := generatePostprovisionConfig(nodeSets, chainID, capabilitiesP2PPort, forwarderAddress, capabilitiesRegistryAddress) + + yamlData, err := yaml.Marshal(chart) + if err != nil { + t.Fatalf("Failed to marshal chart: %v", err) + } + + linesStr := strings.Split(string(yamlData), "\n") + snaps.MatchSnapshot(t, strings.Join(linesStr, "\n")) +} + +func TestGeneratePreprovisionConfig(t *testing.T) { + nodeSetSize := 5 + + chart := generatePreprovisionConfig(nodeSetSize) + + yamlData, err := yaml.Marshal(chart) + if err != nil { + t.Fatalf("Failed to marshal chart: %v", err) + } + + linesStr := strings.Split(string(yamlData), "\n") + snaps.MatchSnapshot(t, strings.Join(linesStr, "\n")) +} diff --git a/core/scripts/keystone/src/02_provision_forwarder_contract.go b/core/scripts/keystone/src/02_provision_forwarder_contract.go new file mode 100644 index 00000000000..4cc3d7f70fa --- /dev/null +++ b/core/scripts/keystone/src/02_provision_forwarder_contract.go @@ -0,0 +1,33 @@ +package src + +import ( + "context" + "fmt" + + helpers "github.com/smartcontractkit/chainlink/core/scripts/common" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder" +) + +func deployForwarder( + env helpers.Environment, + artefacts string, +) { + o := LoadOnchainMeta(artefacts, env) + if o.Forwarder != nil { + fmt.Println("Forwarder contract already deployed, skipping") + return + } + + fmt.Println("Deploying forwarder contract...") + forwarderContract := DeployForwarder(env) + o.Forwarder = forwarderContract + WriteOnchainMeta(o, artefacts) +} + +func DeployForwarder(e helpers.Environment) *forwarder.KeystoneForwarder { + _, tx, contract, err := forwarder.DeployKeystoneForwarder(e.Owner, e.Ec) + PanicErr(err) + helpers.ConfirmContractDeployed(context.Background(), e.Ec, tx, e.ChainID) + + return contract +} diff --git a/core/scripts/keystone/src/02_provision_ocr3_capability.go b/core/scripts/keystone/src/02_provision_ocr3_capability.go new file mode 100644 index 00000000000..cd80bf4238b --- /dev/null +++ b/core/scripts/keystone/src/02_provision_ocr3_capability.go @@ -0,0 +1,286 @@ +package src + +import ( + "bytes" + "strconv" + "text/template" + + "context" + "flag" + "fmt" + + "github.com/smartcontractkit/chainlink/deployment" + + ksdeploy "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" + + "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + helpers "github.com/smartcontractkit/chainlink/core/scripts/common" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" +) + +func provisionOCR3( + env helpers.Environment, + nodeSet NodeSet, + chainID int64, + p2pPort int64, + ocrConfigFile string, + artefactsDir string, +) (onchainMeta *onchainMeta, cacheHit bool) { + nodeKeys := nodeSet.NodeKeys + nodes := nodeSet.Nodes + + onchainMeta, cacheHit = deployOCR3Contract( + nodeKeys, + env, + ocrConfigFile, + artefactsDir, + ) + + deployOCR3JobSpecs( + nodes, + chainID, + nodeKeys, + p2pPort, + onchainMeta, + ) + + return +} + +func deployOCR3Contract( + nodeKeys []NodeKeys, + env helpers.Environment, + configFile string, + artefacts string, +) (o *onchainMeta, cacheHit bool) { + o = LoadOnchainMeta(artefacts, env) + ocrConf := generateOCR3Config( + nodeKeys, + configFile, + ) + + if o.OCR3 != nil { + // types.ConfigDigestPrefixKeystoneOCR3Capability + fmt.Println("OCR3 Contract already deployed, checking config...") + latestConfigDigestBytes, err := o.OCR3.LatestConfigDetails(nil) + PanicErr(err) + latestConfigDigest, err := types.BytesToConfigDigest(latestConfigDigestBytes.ConfigDigest[:]) + PanicErr(err) + + cc := ocrConfToContractConfig(ocrConf, latestConfigDigestBytes.ConfigCount) + digester := evm.OCR3CapabilityOffchainConfigDigester{ + ChainID: uint64(env.ChainID), //nolint:gosec // this won't overflow + ContractAddress: o.OCR3.Address(), + } + digest, err := digester.ConfigDigest(context.Background(), cc) + PanicErr(err) + + if digest.Hex() == latestConfigDigest.Hex() { + fmt.Printf("OCR3 Contract already deployed with the same config (digest: %s), skipping...\n", digest.Hex()) + return o, false + } + + fmt.Printf("OCR3 Contract contains a different config, updating...\nOld digest: %s\nNew digest: %s\n", latestConfigDigest.Hex(), digest.Hex()) + setOCRConfig(o, env, ocrConf, artefacts) + return o, true + } + + fmt.Println("Deploying keystone ocr3 contract...") + _, tx, ocrContract, err := ocr3_capability.DeployOCR3Capability(env.Owner, env.Ec) + PanicErr(err) + helpers.ConfirmContractDeployed(context.Background(), env.Ec, tx, env.ChainID) + o.OCR3 = ocrContract + setOCRConfig(o, env, ocrConf, artefacts) + + return o, true +} + +func generateOCR3Config(nodeKeys []NodeKeys, configFile string) ksdeploy.OCR3OnchainConfig { + topLevelCfg := mustReadOCR3Config(configFile) + cfg := topLevelCfg.OracleConfig + secrets := deployment.XXXGenerateTestOCRSecrets() + c, err := ksdeploy.GenerateOCR3Config(cfg, nodeKeysToKsDeployNodeKeys(nodeKeys[1:]), secrets) // skip the bootstrap node + helpers.PanicErr(err) + return c +} + +func setOCRConfig(o *onchainMeta, env helpers.Environment, ocrConf ksdeploy.OCR3OnchainConfig, artefacts string) { + fmt.Println("Setting OCR3 contract config...") + tx, err := o.OCR3.SetConfig(env.Owner, + ocrConf.Signers, + ocrConf.Transmitters, + ocrConf.F, + ocrConf.OnchainConfig, + ocrConf.OffchainConfigVersion, + ocrConf.OffchainConfig, + ) + PanicErr(err) + receipt := helpers.ConfirmTXMined(context.Background(), env.Ec, tx, env.ChainID) + o.SetConfigTxBlock = receipt.BlockNumber.Uint64() + WriteOnchainMeta(o, artefacts) +} + +func deployOCR3JobSpecs( + nodes []NodeWithCreds, + chainID int64, + nodeKeys []NodeKeys, + p2pPort int64, + onchainMeta *onchainMeta, +) { + ocrAddress := onchainMeta.OCR3.Address().Hex() + bootstrapURI := fmt.Sprintf("%s@%s:%d", nodeKeys[0].P2PPeerID, nodes[0].ServiceName, p2pPort) + + var specName string + for i, n := range nodes { + var spec string + + if i == 0 { + bootstrapSpecConfig := BootstrapJobSpecConfig{ + JobSpecName: "ocr3_bootstrap", + OCRConfigContractAddress: ocrAddress, + ChainID: chainID, + } + specName = bootstrapSpecConfig.JobSpecName + spec = createBootstrapJobSpec(bootstrapSpecConfig) + } else { + oc := OracleJobSpecConfig{ + JobSpecName: "ocr3_oracle", + OCRConfigContractAddress: ocrAddress, + OCRKeyBundleID: nodeKeys[i].OCR2BundleID, + BootstrapURI: bootstrapURI, + TransmitterID: nodeKeys[i].EthAddress, + ChainID: chainID, + AptosKeyBundleID: nodeKeys[i].AptosBundleID, + } + specName = oc.JobSpecName + spec = createOracleJobSpec(oc) + } + + api := newNodeAPI(n) + upsertJob(api, specName, spec) + + fmt.Printf("Replaying from block: %d\n", onchainMeta.SetConfigTxBlock) + fmt.Printf("EVM Chain ID: %d\n\n", chainID) + api.withFlags(api.methods.ReplayFromBlock, func(fs *flag.FlagSet) { + err := fs.Set("block-number", strconv.FormatUint(onchainMeta.SetConfigTxBlock, 10)) + helpers.PanicErr(err) + err = fs.Set("evm-chain-id", strconv.FormatInt(chainID, 10)) + helpers.PanicErr(err) + }).mustExec() + } +} + +func mustReadOCR3Config(fileName string) (output ksdeploy.TopLevelConfigSource) { + return mustReadJSON[ksdeploy.TopLevelConfigSource](fileName) +} + +func nodeKeysToKsDeployNodeKeys(nks []NodeKeys) []ksdeploy.NodeKeys { + keys := []ksdeploy.NodeKeys{} + for _, nk := range nks { + keys = append(keys, ksdeploy.NodeKeys{ + EthAddress: nk.EthAddress, + AptosAccount: nk.AptosAccount, + AptosBundleID: nk.AptosBundleID, + AptosOnchainPublicKey: nk.AptosOnchainPublicKey, + P2PPeerID: nk.P2PPeerID, + OCR2BundleID: nk.OCR2BundleID, + OCR2OnchainPublicKey: nk.OCR2OnchainPublicKey, + OCR2OffchainPublicKey: nk.OCR2OffchainPublicKey, + OCR2ConfigPublicKey: nk.OCR2ConfigPublicKey, + CSAPublicKey: nk.CSAPublicKey, + }) + } + return keys +} + +// BootstrapJobSpecConfig holds configuration for the bootstrap job spec +type BootstrapJobSpecConfig struct { + JobSpecName string + OCRConfigContractAddress string + ChainID int64 +} + +// OracleJobSpecConfig holds configuration for the oracle job spec +type OracleJobSpecConfig struct { + JobSpecName string + OCRConfigContractAddress string + OCRKeyBundleID string + BootstrapURI string + TransmitterID string + ChainID int64 + AptosKeyBundleID string +} + +func createBootstrapJobSpec(config BootstrapJobSpecConfig) string { + const bootstrapTemplate = ` +type = "bootstrap" +schemaVersion = 1 +name = "{{ .JobSpecName }}" +contractID = "{{ .OCRConfigContractAddress }}" +relay = "evm" + +[relayConfig] +chainID = "{{ .ChainID }}" +providerType = "ocr3-capability" +` + + tmpl, err := template.New("bootstrap").Parse(bootstrapTemplate) + if err != nil { + panic(err) + } + + var rendered bytes.Buffer + err = tmpl.Execute(&rendered, config) + if err != nil { + panic(err) + } + + return rendered.String() +} + +func createOracleJobSpec(config OracleJobSpecConfig) string { + const oracleTemplate = ` +type = "offchainreporting2" +schemaVersion = 1 +name = "{{ .JobSpecName }}" +contractID = "{{ .OCRConfigContractAddress }}" +ocrKeyBundleID = "{{ .OCRKeyBundleID }}" +p2pv2Bootstrappers = [ + "{{ .BootstrapURI }}", +] +relay = "evm" +pluginType = "plugin" +transmitterID = "{{ .TransmitterID }}" + +[relayConfig] +chainID = "{{ .ChainID }}" + +[pluginConfig] +command = "chainlink-ocr3-capability" +ocrVersion = 3 +pluginName = "ocr-capability" +providerType = "ocr3-capability" +telemetryType = "plugin" + +[onchainSigningStrategy] +strategyName = 'multi-chain' +[onchainSigningStrategy.config] +evm = "{{ .OCRKeyBundleID }}" +aptos = "{{ .AptosKeyBundleID }}" +` + + tmpl, err := template.New("oracle").Parse(oracleTemplate) + if err != nil { + panic(err) + } + + var rendered bytes.Buffer + err = tmpl.Execute(&rendered, config) + if err != nil { + panic(err) + } + + return rendered.String() +} diff --git a/core/scripts/keystone/src/02_provision_ocr3_capability_test.go b/core/scripts/keystone/src/02_provision_ocr3_capability_test.go new file mode 100644 index 00000000000..df4d9a41f5c --- /dev/null +++ b/core/scripts/keystone/src/02_provision_ocr3_capability_test.go @@ -0,0 +1,67 @@ +package src + +import ( + "errors" + "fmt" + "testing" + + "github.com/gkampitakis/go-snaps/match" + "github.com/gkampitakis/go-snaps/snaps" +) + +func TestGenerateOCR3Config(t *testing.T) { + // Generate OCR3 config + nodeSet := downloadNodeSets(1337, "./testdata/node_sets.json", 4) + nodeKeys := nodeSet.Workflow.NodeKeys + config := generateOCR3Config(nodeKeys, "./testdata/SampleConfig.json") + + matchOffchainConfig := match.Custom("OffchainConfig", func(s any) (any, error) { + // coerce the value to a string + s, ok := s.(string) + if !ok { + return nil, errors.New("offchain config is not a string") + } + + // if the string is not empty + if s == "" { + return nil, errors.New("offchain config is empty") + } + + return "", nil + }) + + snaps.MatchJSON(t, config, matchOffchainConfig) +} + +func TestGenSpecs(t *testing.T) { + nodeSetsPath := "./testdata/node_sets.json" + chainID := int64(1337) + p2pPort := int64(6690) + contractAddress := "0xB29934624cAe3765E33115A9530a13f5aEC7fa8A" + nodeSet := downloadNodeSets(chainID, nodeSetsPath, 4).Workflow + + // Create Bootstrap Job Spec + bootstrapConfig := BootstrapJobSpecConfig{ + JobSpecName: "ocr3_bootstrap", + OCRConfigContractAddress: contractAddress, + ChainID: chainID, + } + bootstrapSpec := createBootstrapJobSpec(bootstrapConfig) + + // Create Oracle Job Spec + oracleConfig := OracleJobSpecConfig{ + JobSpecName: "ocr3_oracle", + OCRConfigContractAddress: contractAddress, + OCRKeyBundleID: nodeSet.NodeKeys[1].OCR2BundleID, + BootstrapURI: fmt.Sprintf("%s@%s:%d", nodeSet.NodeKeys[0].P2PPeerID, nodeSet.Nodes[0].ServiceName, p2pPort), + TransmitterID: nodeSet.NodeKeys[1].P2PPeerID, + ChainID: chainID, + AptosKeyBundleID: nodeSet.NodeKeys[1].AptosBundleID, + } + oracleSpec := createOracleJobSpec(oracleConfig) + + // Combine Specs + generatedSpecs := fmt.Sprintf("%s\n\n%s", bootstrapSpec, oracleSpec) + + snaps.MatchSnapshot(t, generatedSpecs) +} diff --git a/core/scripts/keystone/src/02_provision_streams_trigger_capability.go b/core/scripts/keystone/src/02_provision_streams_trigger_capability.go new file mode 100644 index 00000000000..f476319362b --- /dev/null +++ b/core/scripts/keystone/src/02_provision_streams_trigger_capability.go @@ -0,0 +1,522 @@ +package src + +// This package deploys "offchainreporting2" job specs, which setup the streams trigger +// for the targeted node set +// See https://github.com/smartcontractkit/chainlink/blob/4d5fc1943bd6a60b49cbc3d263c0aa47dc3cecb7/core/services/ocr2/plugins/mercury/integration_test.go#L92 +// for how to setup the mercury portion of the streams trigger +// You can see how all fields are being used here: https://github.com/smartcontractkit/chainlink/blob/4d5fc1943bd6a60b49cbc3d263c0aa47dc3cecb7/core/services/ocr2/plugins/mercury/helpers_test.go#L314 +// https://github.com/smartcontractkit/infra-k8s/blob/be47098adfb605d79b5bab6aa601bcf443a6c48b/projects/chainlink/files/chainlink-clusters/cl-keystone-cap-one/config.yaml#L1 +// Trigger gets added to the registry here: https://github.com/smartcontractkit/chainlink/blob/4d5fc1943bd6a60b49cbc3d263c0aa47dc3cecb7/core/services/relay/evm/evm.go#L360 +// See integration workflow here: https://github.com/smartcontractkit/chainlink/blob/4d5fc1943bd6a60b49cbc3d263c0aa47dc3cecb7/core/capabilities/integration_tests/workflow.go#L15 +import ( + "bytes" + "context" + "crypto/ed25519" + "encoding/binary" + "encoding/hex" + "encoding/json" + "fmt" + "html/template" + "math" + "math/big" + "time" + + "net/url" + + "github.com/ethereum/go-ethereum/common" + "github.com/shopspring/decimal" + + "github.com/ethereum/go-ethereum/core/types" + + "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" + + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + mercurytypes "github.com/smartcontractkit/chainlink-common/pkg/types/mercury" + datastreamsmercury "github.com/smartcontractkit/chainlink-data-streams/mercury" + + helpers "github.com/smartcontractkit/chainlink/core/scripts/common" + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/v2/core/bridges" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury" + + verifierContract "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/verifier" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/verifier_proxy" + + "github.com/smartcontractkit/chainlink/v2/core/store/models" + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +type feed struct { + id [32]byte + name string + + // we create a bridge for each feed + bridgeName string + bridgeURL string +} + +func v3FeedID(id [32]byte) [32]byte { + binary.BigEndian.PutUint16(id[:2], 3) + return id +} + +var feeds = []feed{ + { + v3FeedID([32]byte{5: 1}), + "BTC/USD", + "mock-bridge-btc", + "http://external-adapter:4001", + }, + { + v3FeedID([32]byte{5: 2}), + "LINK/USD", + "mock-bridge-link", + "http://external-adapter:4002", + }, + { + v3FeedID([32]byte{5: 3}), + "NATIVE/USD", + "mock-bridge-native", + "http://external-adapter:4003", + }, +} + +// See /core/services/ocr2/plugins/mercury/integration_test.go +func setupStreamsTrigger( + env helpers.Environment, + nodeSet NodeSet, + chainID int64, + p2pPort int64, + ocrConfigFilePath string, + artefactsDir string, +) { + fmt.Printf("Deploying streams trigger for chain %d\n", chainID) + fmt.Printf("Using OCR config file: %s\n", ocrConfigFilePath) + + fmt.Printf("Deploying Mercury V0.3 contracts\n") + verifier := deployMercuryV03Contracts(env, artefactsDir) + + fmt.Printf("Generating Mercury OCR config\n") + ocrConfig := generateMercuryOCR2Config(nodeSet.NodeKeys[1:]) // skip the bootstrap node + + for _, feed := range feeds { + fmt.Println("Configuring feeds...") + fmt.Printf("FeedID: %x\n", feed.id) + fmt.Printf("FeedName: %s\n", feed.name) + fmt.Printf("BridgeName: %s\n", feed.bridgeName) + fmt.Printf("BridgeURL: %s\n", feed.bridgeURL) + + latestConfigDetails, err := verifier.LatestConfigDetails(nil, feed.id) + PanicErr(err) + latestConfigDigest, err := ocrtypes.BytesToConfigDigest(latestConfigDetails.ConfigDigest[:]) + PanicErr(err) + + digester := mercury.NewOffchainConfigDigester( + feed.id, + big.NewInt(chainID), + verifier.Address(), + ocrtypes.ConfigDigestPrefixMercuryV02, + ) + configDigest, err := digester.ConfigDigest( + context.Background(), + mercuryOCRConfigToContractConfig( + ocrConfig, + latestConfigDetails.ConfigCount, + ), + ) + PanicErr(err) + + if configDigest.Hex() == latestConfigDigest.Hex() { + fmt.Printf("Verifier already deployed with the same config (digest: %s), skipping...\n", configDigest.Hex()) + } else { + fmt.Printf("Verifier contains a different config, updating...\nOld digest: %s\nNew digest: %s\n", latestConfigDigest.Hex(), configDigest.Hex()) + tx, err := verifier.SetConfig( + env.Owner, + feed.id, + ocrConfig.Signers, + ocrConfig.Transmitters, + ocrConfig.F, + ocrConfig.OnchainConfig, + ocrConfig.OffchainConfigVersion, + ocrConfig.OffchainConfig, + nil, + ) + helpers.ConfirmTXMined(context.Background(), env.Ec, tx, env.ChainID) + PanicErr(err) + } + + fmt.Printf("Deploying OCR2 job specs for feed %s\n", feed.name) + deployOCR2JobSpecsForFeed(nodeSet, verifier, feed, chainID, p2pPort) + } + + fmt.Println("Finished deploying streams trigger") +} + +func deployMercuryV03Contracts(env helpers.Environment, artefactsDir string) verifierContract.VerifierInterface { + var confirmDeploy = func(tx *types.Transaction, err error) { + helpers.ConfirmContractDeployed(context.Background(), env.Ec, tx, env.ChainID) + PanicErr(err) + } + o := LoadOnchainMeta(artefactsDir, env) + + if o.VerifierProxy != nil { + fmt.Printf("Verifier proxy contract already deployed at %s\n", o.VerifierProxy.Address()) + } else { + fmt.Printf("Deploying verifier proxy contract\n") + _, tx, verifierProxy, err := verifier_proxy.DeployVerifierProxy(env.Owner, env.Ec, common.Address{}) // zero address for access controller disables access control + confirmDeploy(tx, err) + o.VerifierProxy = verifierProxy + WriteOnchainMeta(o, artefactsDir) + } + + if o.Verifier == nil { + fmt.Printf("Deploying verifier contract\n") + _, tx, verifier, err := verifierContract.DeployVerifier(env.Owner, env.Ec, o.VerifierProxy.Address()) + confirmDeploy(tx, err) + o.Verifier = verifier + WriteOnchainMeta(o, artefactsDir) + } else { + fmt.Printf("Verifier contract already deployed at %s\n", o.Verifier.Address().Hex()) + } + + if o.InitializedVerifierAddress != o.Verifier.Address() { + fmt.Printf("Current initialized verifier address (%s) differs from the new verifier address (%s). Initializing verifier.\n", o.InitializedVerifierAddress.Hex(), o.Verifier.Address().Hex()) + tx, err := o.VerifierProxy.InitializeVerifier(env.Owner, o.Verifier.Address()) + receipt := helpers.ConfirmTXMined(context.Background(), env.Ec, tx, env.ChainID) + PanicErr(err) + inited, err := o.VerifierProxy.ParseVerifierInitialized(*receipt.Logs[0]) + PanicErr(err) + o.InitializedVerifierAddress = inited.VerifierAddress + WriteOnchainMeta(o, artefactsDir) + } else { + fmt.Printf("Verifier %s already initialized\n", o.Verifier.Address().Hex()) + } + + return o.Verifier +} + +func deployOCR2JobSpecsForFeed(nodeSet NodeSet, verifier verifierContract.VerifierInterface, feed feed, chainID int64, p2pPort int64) { + // we assign the first node as the bootstrap node + for i, n := range nodeSet.NodeKeys { + // parallel arrays + api := newNodeAPI(nodeSet.Nodes[i]) + jobSpecName := "" + jobSpecStr := "" + + upsertBridge(api, feed.bridgeName, feed.bridgeURL) + + if i == 0 { + // Prepare data for Bootstrap Job + bootstrapData := MercuryV3BootstrapJobSpecData{ + FeedName: feed.name, + VerifierAddress: verifier.Address().Hex(), + FeedID: fmt.Sprintf("%x", feed.id), + ChainID: chainID, + } + + // Create Bootstrap Job + jobSpecName, jobSpecStr = createMercuryV3BootstrapJob(bootstrapData) + } else { + // Prepare data for Mercury V3 Job + mercuryData := MercuryV3JobSpecData{ + FeedName: "feed-" + feed.name, + BootstrapHost: fmt.Sprintf("%s@%s:%d", nodeSet.NodeKeys[0].P2PPeerID, nodeSet.Nodes[0].ServiceName, p2pPort), + VerifierAddress: verifier.Address().Hex(), + Bridge: feed.bridgeName, + NodeCSAKey: n.CSAPublicKey, + FeedID: fmt.Sprintf("%x", feed.id), + LinkFeedID: fmt.Sprintf("%x", feeds[1].id), + NativeFeedID: fmt.Sprintf("%x", feeds[2].id), + OCRKeyBundleID: n.OCR2BundleID, + ChainID: chainID, + } + + // Create Mercury V3 Job + jobSpecName, jobSpecStr = createMercuryV3OracleJob(mercuryData) + } + + upsertJob(api, jobSpecName, jobSpecStr) + } +} + +// Template definitions +const mercuryV3OCR2bootstrapJobTemplate = ` +type = "bootstrap" +relay = "evm" +schemaVersion = 1 +name = "{{ .Name }}" +contractID = "{{ .VerifierAddress }}" +feedID = "0x{{ .FeedID }}" +contractConfigTrackerPollInterval = "1s" + +[relayConfig] +chainID = {{ .ChainID }} +enableTriggerCapability = true +` + +const mercuryV3OCR2OracleJobTemplate = ` +type = "offchainreporting2" +schemaVersion = 1 +name = "{{ .Name }}" +p2pv2Bootstrappers = ["{{ .BootstrapHost }}"] +forwardingAllowed = false +maxTaskDuration = "1s" +contractID = "{{ .VerifierAddress }}" +feedID = "0x{{ .FeedID }}" +contractConfigTrackerPollInterval = "1s" +ocrKeyBundleID = "{{ .OCRKeyBundleID }}" +relay = "evm" +pluginType = "mercury" +transmitterID = "{{ .NodeCSAKey }}" +observationSource = """ + price [type=bridge name="{{ .Bridge }}" timeout="50ms" requestData=""]; + + benchmark_price [type=jsonparse path="result,mid" index=0]; + price -> benchmark_price; + + bid_price [type=jsonparse path="result,bid" index=1]; + price -> bid_price; + + ask_price [type=jsonparse path="result,ask" index=2]; + price -> ask_price; +""" + +[relayConfig] +enableTriggerCapability = true +chainID = "{{ .ChainID }}" +` + +// Data structures +type MercuryV3BootstrapJobSpecData struct { + FeedName string + // Automatically generated from FeedName + Name string + VerifierAddress string + FeedID string + ChainID int64 +} + +type MercuryV3JobSpecData struct { + FeedName string + // Automatically generated from FeedName + Name string + BootstrapHost string + VerifierAddress string + Bridge string + NodeCSAKey string + FeedID string + LinkFeedID string + NativeFeedID string + OCRKeyBundleID string + ChainID int64 +} + +// createMercuryV3BootstrapJob creates a bootstrap job specification using the provided data. +func createMercuryV3BootstrapJob(data MercuryV3BootstrapJobSpecData) (name string, jobSpecStr string) { + name = "boot-" + data.FeedName + data.Name = name + + fmt.Printf("Creating bootstrap job (%s):\nverifier address: %s\nfeed name: %s\nfeed ID: %s\nchain ID: %d\n", + name, data.VerifierAddress, data.FeedName, data.FeedID, data.ChainID) + + tmpl, err := template.New("bootstrapJob").Parse(mercuryV3OCR2bootstrapJobTemplate) + PanicErr(err) + + var buf bytes.Buffer + err = tmpl.Execute(&buf, data) + PanicErr(err) + + jobSpecStr = buf.String() + + return name, jobSpecStr +} + +// createMercuryV3OracleJob creates a Mercury V3 job specification using the provided data. +func createMercuryV3OracleJob(data MercuryV3JobSpecData) (name string, jobSpecStr string) { + name = "mercury-" + data.FeedName + data.Name = name + fmt.Printf("Creating ocr2 job(%s):\nOCR key bundle ID: %s\nverifier address: %s\nbridge: %s\nnodeCSAKey: %s\nfeed name: %s\nfeed ID: %s\nlink feed ID: %s\nnative feed ID: %s\nchain ID: %d\n", + data.Name, data.OCRKeyBundleID, data.VerifierAddress, data.Bridge, data.NodeCSAKey, data.FeedName, data.FeedID, data.LinkFeedID, data.NativeFeedID, data.ChainID) + + tmpl, err := template.New("mercuryV3Job").Parse(mercuryV3OCR2OracleJobTemplate) + PanicErr(err) + + var buf bytes.Buffer + err = tmpl.Execute(&buf, data) + PanicErr(err) + + jobSpecStr = buf.String() + + return data.Name, jobSpecStr +} + +func strToBytes32(str string) [32]byte { + pkBytes, err := hex.DecodeString(str) + helpers.PanicErr(err) + + pkBytesFixed := [ed25519.PublicKeySize]byte{} + n := copy(pkBytesFixed[:], pkBytes) + if n != ed25519.PublicKeySize { + fmt.Printf("wrong num elements copied (%s): %d != 32\n", str, n) + panic("wrong num elements copied") + } + return pkBytesFixed +} + +func upsertBridge(api *nodeAPI, name string, eaURL string) { + u, err := url.Parse(eaURL) + helpers.PanicErr(err) + url := models.WebURL(*u) + // Confirmations and MinimumContractPayment are not used, so we can leave them as 0 + b := bridges.BridgeTypeRequest{ + Name: bridges.MustParseBridgeName(name), + URL: url, + } + payloadb, err := json.Marshal(b) + helpers.PanicErr(err) + payload := string(payloadb) + + bridgeActionType := bridgeAction(api, b) + switch bridgeActionType { + case shouldCreateBridge: + fmt.Printf("Creating bridge (%s): %s\n", name, eaURL) + resp := api.withArg(payload).mustExec(api.methods.CreateBridge) + resource := mustJSON[presenters.BridgeResource](resp) + fmt.Printf("Created bridge: %s %s\n", resource.Name, resource.URL) + case shouldUpdateBridge: + fmt.Println("Updating existing bridge") + api.withArgs(name, payload).mustExec(api.methods.UpdateBridge) + fmt.Println("Updated bridge", name) + case shouldNoChangeBridge: + fmt.Println("No changes needed for bridge", name) + } +} + +// create enum for 3 states: create, update, no change +var ( + shouldCreateBridge = 0 + shouldUpdateBridge = 1 + shouldNoChangeBridge = 2 +) + +func bridgeAction(api *nodeAPI, existingBridge bridges.BridgeTypeRequest) int { + resp, err := api.withArg(existingBridge.Name.String()).exec(api.methods.ShowBridge) + if err != nil { + return shouldCreateBridge + } + + b := mustJSON[presenters.BridgeResource](resp) + fmt.Printf("Found matching bridge: %s with URL: %s\n", b.Name, b.URL) + if b.URL == existingBridge.URL.String() { + return shouldNoChangeBridge + } + return shouldUpdateBridge +} + +func generateMercuryOCR2Config(nca []NodeKeys) MercuryOCR2Config { + ctx := context.Background() + f := uint8(1) + rawOnchainConfig := mercurytypes.OnchainConfig{ + Min: big.NewInt(0), + Max: big.NewInt(math.MaxInt64), + } + + // Values were taken from Data Streams 250ms feeds, given by @austinborn + rawReportingPluginConfig := datastreamsmercury.OffchainConfig{ + ExpirationWindow: 86400, + BaseUSDFee: decimal.NewFromInt(0), + } + + onchainConfig, err := (datastreamsmercury.StandardOnchainConfigCodec{}).Encode(ctx, rawOnchainConfig) + helpers.PanicErr(err) + reportingPluginConfig, err := json.Marshal(rawReportingPluginConfig) + helpers.PanicErr(err) + + onchainPubKeys := []common.Address{} + for _, n := range nca { + onchainPubKeys = append(onchainPubKeys, common.HexToAddress(n.OCR2OnchainPublicKey)) + } + + offchainPubKeysBytes := []ocrtypes.OffchainPublicKey{} + for _, n := range nca { + pkBytesFixed := strToBytes32(n.OCR2OffchainPublicKey) + offchainPubKeysBytes = append(offchainPubKeysBytes, ocrtypes.OffchainPublicKey(pkBytesFixed)) + } + + configPubKeysBytes := []ocrtypes.ConfigEncryptionPublicKey{} + for _, n := range nca { + pkBytesFixed := strToBytes32(n.OCR2ConfigPublicKey) + configPubKeysBytes = append(configPubKeysBytes, ocrtypes.ConfigEncryptionPublicKey(pkBytesFixed)) + } + + identities := []confighelper.OracleIdentityExtra{} + for index := range nca { + transmitterAccount := ocrtypes.Account(nca[index].CSAPublicKey) + + identities = append(identities, confighelper.OracleIdentityExtra{ + OracleIdentity: confighelper.OracleIdentity{ + OnchainPublicKey: onchainPubKeys[index][:], + OffchainPublicKey: offchainPubKeysBytes[index], + PeerID: nca[index].P2PPeerID, + TransmitAccount: transmitterAccount, + }, + ConfigEncryptionPublicKey: configPubKeysBytes[index], + }) + } + + secrets := deployment.XXXGenerateTestOCRSecrets() + // Values were taken from Data Streams 250ms feeds, given by @austinborn + signers, _, _, onchainConfig, offchainConfigVersion, offchainConfig, err := ocr3confighelper.ContractSetConfigArgsDeterministic( + secrets.EphemeralSk, + secrets.SharedSecret, + 10*time.Second, // DeltaProgress + 10*time.Second, // DeltaResend + 400*time.Millisecond, // DeltaInitial + 5*time.Second, // DeltaRound + 0, // DeltaGrace + 1*time.Second, // DeltaCertifiedCommitRequest + 0, // DeltaStage + 25, // rMax + []int{len(identities)}, // S + identities, + reportingPluginConfig, // reportingPluginConfig []byte, + nil, // maxDurationInitialization *time.Duration, + 0, // maxDurationQuery time.Duration, + 250*time.Millisecond, // Max duration observation + 0, // Max duration should accept attested report + 0, // Max duration should transmit accepted report + int(f), // f + onchainConfig, + ) + PanicErr(err) + signerAddresses, err := evm.OnchainPublicKeyToAddress(signers) + PanicErr(err) + + offChainTransmitters := make([][32]byte, len(nca)) + for i, n := range nca { + offChainTransmitters[i] = strToBytes32(n.CSAPublicKey) + } + + config := MercuryOCR2Config{ + Signers: signerAddresses, + Transmitters: offChainTransmitters, + F: f, + OnchainConfig: onchainConfig, + OffchainConfigVersion: offchainConfigVersion, + OffchainConfig: offchainConfig, + } + + return config +} + +type MercuryOCR2Config struct { + Signers []common.Address + Transmitters [][32]byte + F uint8 + OnchainConfig []byte + OffchainConfigVersion uint64 + OffchainConfig []byte +} diff --git a/core/scripts/keystone/src/02_provision_streams_trigger_capability_test.go b/core/scripts/keystone/src/02_provision_streams_trigger_capability_test.go new file mode 100644 index 00000000000..3a2234ba4d7 --- /dev/null +++ b/core/scripts/keystone/src/02_provision_streams_trigger_capability_test.go @@ -0,0 +1,57 @@ +package src + +import ( + "fmt" + "net/url" + "testing" + + "github.com/gkampitakis/go-snaps/snaps" +) + +var ( + chainID = int64(123456) + feedID = fmt.Sprintf("%x", [32]byte{0: 1}) + feedName = "BTC/USD" + verifierAddress = fmt.Sprintf("0x%x", [20]byte{0: 7}) +) + +func TestCreateMercuryV3Job(t *testing.T) { + ocrKeyBundleID := "ocr_key_bundle_id" + nodeCSAKey := "node_csa_key" + bridgeName := "bridge_name" + linkFeedID := fmt.Sprintf("%x", [32]byte{0: 2}) + nativeFeedID := fmt.Sprintf("%x", [32]byte{0: 3}) + u, err := url.Parse("https://crib-henry-keystone-node1.main.stage.cldev.sh") + if err != nil { + t.Fatal(err) + } + + jobConfigData := MercuryV3JobSpecData{ + BootstrapHost: u.Hostname(), + VerifierAddress: verifierAddress, + OCRKeyBundleID: ocrKeyBundleID, + NodeCSAKey: nodeCSAKey, + Bridge: bridgeName, + FeedName: feedName, + FeedID: feedID, + LinkFeedID: linkFeedID, + NativeFeedID: nativeFeedID, + ChainID: chainID, + } + _, output := createMercuryV3OracleJob(jobConfigData) + + snaps.MatchSnapshot(t, output) +} + +func TestCreateMercuryBootstrapJob(t *testing.T) { + jobConfigData := MercuryV3BootstrapJobSpecData{ + FeedName: feedName, + FeedID: feedID, + ChainID: chainID, + VerifierAddress: verifierAddress, + } + + _, output := createMercuryV3BootstrapJob(jobConfigData) + + snaps.MatchSnapshot(t, output) +} diff --git a/core/scripts/keystone/src/03_gen_crib_cluster_overrides_cmd.go b/core/scripts/keystone/src/03_gen_crib_cluster_overrides_cmd.go deleted file mode 100644 index 6b98951459e..00000000000 --- a/core/scripts/keystone/src/03_gen_crib_cluster_overrides_cmd.go +++ /dev/null @@ -1,86 +0,0 @@ -package src - -import ( - "flag" - "os" - "path/filepath" - "strings" - - helpers "github.com/smartcontractkit/chainlink/core/scripts/common" -) - -type generateCribClusterOverrides struct{} - -func NewGenerateCribClusterOverridesCommand() *generateCribClusterOverrides { - return &generateCribClusterOverrides{} -} - -func (g *generateCribClusterOverrides) Name() string { - return "generate-crib" -} - -func (g *generateCribClusterOverrides) Run(args []string) { - fs := flag.NewFlagSet(g.Name(), flag.ContinueOnError) - chainID := fs.Int64("chainid", 11155111, "chain id") - outputPath := fs.String("outpath", "../crib", "the path to output the generated overrides") - publicKeys := fs.String("publickeys", "", "Custom public keys json location") - nodeList := fs.String("nodes", "", "Custom node list location") - artefactsDir := fs.String("artefacts", "", "Custom artefacts directory location") - - templatesDir := "templates" - err := fs.Parse(args) - if err != nil || outputPath == nil || *outputPath == "" || chainID == nil || *chainID == 0 { - fs.Usage() - os.Exit(1) - } - - if *artefactsDir == "" { - *artefactsDir = defaultArtefactsDir - } - if *publicKeys == "" { - *publicKeys = defaultPublicKeys - } - if *nodeList == "" { - *nodeList = defaultNodeList - } - - deployedContracts, err := LoadDeployedContracts(*artefactsDir) - helpers.PanicErr(err) - - lines := generateCribConfig(*nodeList, *publicKeys, chainID, templatesDir, deployedContracts.ForwarderContract.Hex()) - - cribOverridesStr := strings.Join(lines, "\n") - err = os.WriteFile(filepath.Join(*outputPath, "crib-cluster-overrides.yaml"), []byte(cribOverridesStr), 0600) - helpers.PanicErr(err) -} - -func generateCribConfig(nodeList string, pubKeysPath string, chainID *int64, templatesDir string, forwarderAddress string) []string { - nca := downloadNodePubKeys(nodeList, *chainID, pubKeysPath) - nodeAddresses := []string{} - - for _, node := range nca[1:] { - nodeAddresses = append(nodeAddresses, node.EthAddress) - } - - lines, err := readLines(filepath.Join(templatesDir, cribOverrideTemplate)) - helpers.PanicErr(err) - lines = replaceCribPlaceholders(lines, forwarderAddress, nodeAddresses) - return lines -} - -func replaceCribPlaceholders( - lines []string, - forwarderAddress string, - nodeFromAddresses []string, -) (output []string) { - for _, l := range lines { - l = strings.Replace(l, "{{ forwarder_address }}", forwarderAddress, 1) - l = strings.Replace(l, "{{ node_2_address }}", nodeFromAddresses[0], 1) - l = strings.Replace(l, "{{ node_3_address }}", nodeFromAddresses[1], 1) - l = strings.Replace(l, "{{ node_4_address }}", nodeFromAddresses[2], 1) - l = strings.Replace(l, "{{ node_5_address }}", nodeFromAddresses[3], 1) - output = append(output, l) - } - - return output -} diff --git a/core/scripts/keystone/src/03_gen_crib_cluster_overrides_cmd_test.go b/core/scripts/keystone/src/03_gen_crib_cluster_overrides_cmd_test.go deleted file mode 100644 index 53d43c2342f..00000000000 --- a/core/scripts/keystone/src/03_gen_crib_cluster_overrides_cmd_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package src - -import ( - "strings" - "testing" - - "github.com/gkampitakis/go-snaps/snaps" -) - -func TestGenerateCribConfig(t *testing.T) { - chainID := int64(11155111) - templatesDir := "../templates" - forwarderAddress := "0x1234567890abcdef" - publicKeysPath := "./testdata/PublicKeys.json" - - lines := generateCribConfig(defaultNodeList, publicKeysPath, &chainID, templatesDir, forwarderAddress) - - snaps.MatchSnapshot(t, strings.Join(lines, "\n")) -} diff --git a/core/scripts/keystone/src/04_delete_ocr3_jobs_cmd.go b/core/scripts/keystone/src/04_delete_ocr3_jobs_cmd.go deleted file mode 100644 index 136691962dd..00000000000 --- a/core/scripts/keystone/src/04_delete_ocr3_jobs_cmd.go +++ /dev/null @@ -1,101 +0,0 @@ -package src - -import ( - "bytes" - "encoding/json" - "flag" - "fmt" - "os" - - "github.com/urfave/cli" - - helpers "github.com/smartcontractkit/chainlink/core/scripts/common" -) - -type deleteJobs struct{} - -type OCRSpec struct { - ContractID string -} - -type BootSpec struct { - ContractID string -} - -type WorkflowSpec struct { - WorkflowID string -} - -type JobSpec struct { - Id string - Name string - BootstrapSpec BootSpec - OffChainReporting2OracleSpec OCRSpec - WorkflowSpec WorkflowSpec -} - -func NewDeleteJobsCommand() *deleteJobs { - return &deleteJobs{} -} - -func (g *deleteJobs) Name() string { - return "delete-ocr3-jobs" -} - -func (g *deleteJobs) Run(args []string) { - fs := flag.NewFlagSet(g.Name(), flag.ContinueOnError) - nodeList := fs.String("nodes", "", "Custom node list location") - artefactsDir := fs.String("artefacts", "", "Custom artefacts directory location") - - err := fs.Parse(args) - if err != nil { - fs.Usage() - os.Exit(1) - } - - if *artefactsDir == "" { - *artefactsDir = defaultArtefactsDir - } - if *nodeList == "" { - *nodeList = defaultNodeList - } - - deployedContracts, err := LoadDeployedContracts(*artefactsDir) - helpers.PanicErr(err) - nodes := downloadNodeAPICredentials(*nodeList) - - for _, node := range nodes { - output := &bytes.Buffer{} - client, app := newApp(node, output) - - fmt.Println("Logging in:", node.url) - loginFs := flag.NewFlagSet("test", flag.ContinueOnError) - loginFs.Bool("bypass-version-check", true, "") - loginCtx := cli.NewContext(app, loginFs, nil) - err := client.RemoteLogin(loginCtx) - helpers.PanicErr(err) - output.Reset() - - fileFs := flag.NewFlagSet("test", flag.ExitOnError) - err = client.ListJobs(cli.NewContext(app, fileFs, nil)) - helpers.PanicErr(err) - - var parsed []JobSpec - err = json.Unmarshal(output.Bytes(), &parsed) - helpers.PanicErr(err) - - for _, jobSpec := range parsed { - if jobSpec.BootstrapSpec.ContractID == deployedContracts.OCRContract.String() || - jobSpec.OffChainReporting2OracleSpec.ContractID == deployedContracts.OCRContract.String() { - fmt.Println("Deleting OCR3 job ID:", jobSpec.Id, "name:", jobSpec.Name) - set := flag.NewFlagSet("test", flag.ExitOnError) - err = set.Parse([]string{jobSpec.Id}) - helpers.PanicErr(err) - err = client.DeleteJob(cli.NewContext(app, set, nil)) - helpers.PanicErr(err) - } - } - - output.Reset() - } -} diff --git a/core/scripts/keystone/src/05_deploy_initialize_capabilities_registry.go b/core/scripts/keystone/src/05_deploy_initialize_capabilities_registry.go index 86dbfa0c404..203c473a4b7 100644 --- a/core/scripts/keystone/src/05_deploy_initialize_capabilities_registry.go +++ b/core/scripts/keystone/src/05_deploy_initialize_capabilities_registry.go @@ -2,25 +2,20 @@ package src import ( "context" - "encoding/hex" "flag" "fmt" "log" "os" - "strings" "github.com/ethereum/go-ethereum/common" "google.golang.org/protobuf/proto" - ragetypes "github.com/smartcontractkit/libocr/ragep2p/types" - - capabilitiespb "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" "github.com/smartcontractkit/chainlink-common/pkg/values" "github.com/ethereum/go-ethereum/accounts/abi/bind" helpers "github.com/smartcontractkit/chainlink/core/scripts/common" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" ) type peer struct { @@ -30,7 +25,7 @@ type peer struct { } var ( - workflowDonPeers = []peer{ + hardcodedWorkflowDonPeers = []peer{ { PeerID: "12D3KooWQXfwA26jysiKKPXKuHcJtWTbGSwzoJxj4rYtEJyQTnFj", Signer: "0xC44686106b85687F741e1d6182a5e2eD2211a115", @@ -70,74 +65,6 @@ func (c *deployAndInitializeCapabilitiesRegistryCommand) Name() string { return "deploy-and-initialize-capabilities-registry" } -func peerIDToB(peerID string) ([32]byte, error) { - var peerIDB ragetypes.PeerID - err := peerIDB.UnmarshalText([]byte(peerID)) - if err != nil { - return [32]byte{}, err - } - - return peerIDB, nil -} - -func peers(ps []peer) ([][32]byte, error) { - out := [][32]byte{} - for _, p := range ps { - b, err := peerIDToB(p.PeerID) - if err != nil { - return nil, err - } - - out = append(out, b) - } - - return out, nil -} - -func peerToNode(nopID uint32, p peer) (kcr.CapabilitiesRegistryNodeParams, error) { - peerIDB, err := peerIDToB(p.PeerID) - if err != nil { - return kcr.CapabilitiesRegistryNodeParams{}, fmt.Errorf("failed to convert peerID: %w", err) - } - - sig := strings.TrimPrefix(p.Signer, "0x") - signerB, err := hex.DecodeString(sig) - if err != nil { - return kcr.CapabilitiesRegistryNodeParams{}, fmt.Errorf("failed to convert signer: %w", err) - } - - keyStr := strings.TrimPrefix(p.EncryptionPublicKey, "0x") - encKey, err := hex.DecodeString(keyStr) - if err != nil { - return kcr.CapabilitiesRegistryNodeParams{}, fmt.Errorf("failed to convert encryptionPublicKey: %w", err) - } - - var sigb [32]byte - var encKeyB [32]byte - copy(sigb[:], signerB) - copy(encKeyB[:], encKey) - - return kcr.CapabilitiesRegistryNodeParams{ - NodeOperatorId: nopID, - P2pId: peerIDB, - Signer: sigb, - EncryptionPublicKey: encKeyB, - }, nil -} - -// newCapabilityConfig returns a new capability config with the default config set as empty. -// Override the empty default config with functional options. -func newCapabilityConfig(opts ...func(*values.Map)) *capabilitiespb.CapabilityConfig { - dc := values.EmptyMap() - for _, opt := range opts { - opt(dc) - } - - return &capabilitiespb.CapabilityConfig{ - DefaultConfig: values.ProtoMap(dc), - } -} - // withDefaultConfig returns a function that sets the default config for a capability by merging // the provided map with the existing default config. This is a shallow merge. func withDefaultConfig(m map[string]any) func(*values.Map) { @@ -163,7 +90,7 @@ func (c *deployAndInitializeCapabilitiesRegistryCommand) Run(args []string) { // create flags for all of the env vars then set the env vars to normalize the interface // this is a bit of a hack but it's the easiest way to make this work ethUrl := fs.String("ethurl", "", "URL of the Ethereum node") - chainID := fs.Int64("chainid", 11155111, "chain ID of the Ethereum network to deploy to") + chainID := fs.Int64("chainid", 1337, "chain ID of the Ethereum network to deploy to") accountKey := fs.String("accountkey", "", "private key of the account to deploy from") capabilityRegistryAddress := fs.String("craddress", "", "address of the capability registry") @@ -179,6 +106,7 @@ func (c *deployAndInitializeCapabilitiesRegistryCommand) Run(args []string) { os.Setenv("ETH_URL", *ethUrl) os.Setenv("ETH_CHAIN_ID", fmt.Sprintf("%d", *chainID)) os.Setenv("ACCOUNT_KEY", *accountKey) + os.Setenv("INSECURE_SKIP_VERIFY", "true") env := helpers.SetupEnv(false) @@ -288,7 +216,7 @@ func (c *deployAndInitializeCapabilitiesRegistryCommand) Run(args []string) { nopID := recLog.NodeOperatorId nodes := []kcr.CapabilitiesRegistryNodeParams{} - for _, wfPeer := range workflowDonPeers { + for _, wfPeer := range hardcodedWorkflowDonPeers { n, innerErr := peerToNode(nopID, wfPeer) if innerErr != nil { panic(innerErr) @@ -306,7 +234,7 @@ func (c *deployAndInitializeCapabilitiesRegistryCommand) Run(args []string) { helpers.ConfirmTXMined(ctx, env.Ec, tx, env.ChainID) // workflow DON - ps, err := peers(workflowDonPeers) + ps, err := peers(hardcodedWorkflowDonPeers) if err != nil { panic(err) } diff --git a/core/scripts/keystone/src/06_deploy_workflows_cmd.go b/core/scripts/keystone/src/06_deploy_workflows_cmd.go deleted file mode 100644 index 0ca8e5d4a7b..00000000000 --- a/core/scripts/keystone/src/06_deploy_workflows_cmd.go +++ /dev/null @@ -1,71 +0,0 @@ -package src - -import ( - "bytes" - "errors" - "flag" - "fmt" - "os" - - "github.com/urfave/cli" - - helpers "github.com/smartcontractkit/chainlink/core/scripts/common" -) - -type deployWorkflows struct{} - -func NewDeployWorkflowsCommand() *deployWorkflows { - return &deployWorkflows{} -} - -func (g *deployWorkflows) Name() string { - return "deploy-workflows" -} - -func (g *deployWorkflows) Run(args []string) { - fs := flag.NewFlagSet(g.Name(), flag.ContinueOnError) - workflowFile := fs.String("workflow", "workflow.yml", "path to workflow file") - nodeList := fs.String("nodes", "", "Custom node list location") - err := fs.Parse(args) - if err != nil || workflowFile == nil || *workflowFile == "" { - fs.Usage() - os.Exit(1) - } - if *nodeList == "" { - *nodeList = defaultNodeList - } - fmt.Println("Deploying workflows") - - // use a separate list - nodes := downloadNodeAPICredentials(*nodeList) - - if _, err = os.Stat(*workflowFile); err != nil { - PanicErr(errors.New("toml file does not exist")) - } - - for i, n := range nodes { - if i == 0 { - continue // skip bootstrap node - } - output := &bytes.Buffer{} - client, app := newApp(n, output) - fmt.Println("Logging in:", n.url) - loginFs := flag.NewFlagSet("test", flag.ContinueOnError) - loginFs.Bool("bypass-version-check", true, "") - loginCtx := cli.NewContext(app, loginFs, nil) - err := client.RemoteLogin(loginCtx) - helpers.PanicErr(err) - output.Reset() - - fmt.Printf("Deploying workflow\n... \n") - fs := flag.NewFlagSet("test", flag.ExitOnError) - err = fs.Parse([]string{*workflowFile}) - - helpers.PanicErr(err) - err = client.CreateJob(cli.NewContext(app, fs, nil)) - if err != nil { - fmt.Println("Failed to deploy workflow:", "Error:", err) - } - output.Reset() - } -} diff --git a/core/scripts/keystone/src/07_delete_workflows_cmd.go b/core/scripts/keystone/src/07_delete_workflows_cmd.go deleted file mode 100644 index cccedaf9e70..00000000000 --- a/core/scripts/keystone/src/07_delete_workflows_cmd.go +++ /dev/null @@ -1,74 +0,0 @@ -package src - -import ( - "bytes" - "encoding/json" - "flag" - "fmt" - "os" - - "github.com/urfave/cli" - - helpers "github.com/smartcontractkit/chainlink/core/scripts/common" -) - -type deleteWorkflows struct{} - -func NewDeleteWorkflowsCommand() *deleteWorkflows { - return &deleteWorkflows{} -} - -func (g *deleteWorkflows) Name() string { - return "delete-workflows" -} - -func (g *deleteWorkflows) Run(args []string) { - fs := flag.NewFlagSet(g.Name(), flag.ExitOnError) - nodeList := fs.String("nodes", "", "Custom node list location") - - err := fs.Parse(args) - if err != nil { - fs.Usage() - os.Exit(1) - } - - if *nodeList == "" { - *nodeList = defaultNodeList - } - - nodes := downloadNodeAPICredentials(*nodeList) - - for _, node := range nodes { - output := &bytes.Buffer{} - client, app := newApp(node, output) - - fmt.Println("Logging in:", node.url) - loginFs := flag.NewFlagSet("test", flag.ContinueOnError) - loginFs.Bool("bypass-version-check", true, "") - loginCtx := cli.NewContext(app, loginFs, nil) - err := client.RemoteLogin(loginCtx) - helpers.PanicErr(err) - output.Reset() - - fileFs := flag.NewFlagSet("test", flag.ExitOnError) - err = client.ListJobs(cli.NewContext(app, fileFs, nil)) - helpers.PanicErr(err) - - var parsed []JobSpec - err = json.Unmarshal(output.Bytes(), &parsed) - helpers.PanicErr(err) - - for _, jobSpec := range parsed { - if jobSpec.WorkflowSpec.WorkflowID != "" { - fmt.Println("Deleting workflow job ID:", jobSpec.Id, "name:", jobSpec.Name) - set := flag.NewFlagSet("test", flag.ExitOnError) - err = set.Parse([]string{jobSpec.Id}) - helpers.PanicErr(err) - err = client.DeleteJob(cli.NewContext(app, set, nil)) - helpers.PanicErr(err) - } - } - - output.Reset() - } -} diff --git a/core/scripts/keystone/src/88_capabilities_registry_helpers.go b/core/scripts/keystone/src/88_capabilities_registry_helpers.go new file mode 100644 index 00000000000..b75b2fb48af --- /dev/null +++ b/core/scripts/keystone/src/88_capabilities_registry_helpers.go @@ -0,0 +1,588 @@ +package src + +import ( + "bytes" + "context" + "encoding/hex" + "encoding/json" + "errors" + "fmt" + "log" + "strings" + "time" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + gethCommon "github.com/ethereum/go-ethereum/common" + gethTypes "github.com/ethereum/go-ethereum/core/types" + ragetypes "github.com/smartcontractkit/libocr/ragep2p/types" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/durationpb" + + capabilitiespb "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" + "github.com/smartcontractkit/chainlink-common/pkg/values" + helpers "github.com/smartcontractkit/chainlink/core/scripts/common" + evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" +) + +type CapabilityRegistryProvisioner struct { + reg kcr.CapabilitiesRegistryInterface + env helpers.Environment +} + +func NewCapabilityRegistryProvisioner(reg kcr.CapabilitiesRegistryInterface, env helpers.Environment) *CapabilityRegistryProvisioner { + return &CapabilityRegistryProvisioner{reg: reg, env: env} +} + +func extractRevertReason(errData string, a abi.ABI) (string, string, error) { + data, err := hex.DecodeString(errData[2:]) + if err != nil { + return "", "", err + } + + for errName, abiError := range a.Errors { + if bytes.Equal(data[:4], abiError.ID.Bytes()[:4]) { + // Found a matching error + v, err := abiError.Unpack(data) + if err != nil { + return "", "", err + } + b, err := json.Marshal(v) + if err != nil { + return "", "", err + } + return errName, string(b), nil + } + } + return "", "", errors.New("revert Reason could not be found for given abistring") +} + +func (c *CapabilityRegistryProvisioner) testCallContract(method string, args ...interface{}) error { + abi := evmtypes.MustGetABI(kcr.CapabilitiesRegistryABI) + data, err := abi.Pack(method, args...) + helpers.PanicErr(err) + cAddress := c.reg.Address() + gasPrice, err := c.env.Ec.SuggestGasPrice(context.Background()) + helpers.PanicErr(err) + + msg := ethereum.CallMsg{ + From: c.env.Owner.From, + To: &cAddress, + Data: data, + Gas: 10_000_000, + GasPrice: gasPrice, + } + _, err = c.env.Ec.CallContract(context.Background(), msg, nil) + if err != nil { + if err.Error() == "execution reverted" { + rpcError, ierr := evmclient.ExtractRPCError(err) + if ierr != nil { + return ierr + } + + reason, abiErr, ierr := extractRevertReason(rpcError.Data.(string), abi) + if ierr != nil { + return ierr + } + + e := fmt.Errorf("failed to call %s: reason: %s reasonargs: %s", method, reason, abiErr) + return e + } + + return err + } + + return nil +} + +// AddCapabilities takes a capability set and provisions it in the registry. +func (c *CapabilityRegistryProvisioner) AddCapabilities(ctx context.Context, capSet CapabilitySet) { + fmt.Printf("Adding capabilities to registry: %s\n", capSet.IDs()) + tx, err := c.reg.AddCapabilities(c.env.Owner, capSet.Capabilities()) + + helpers.PanicErr(err) + helpers.ConfirmTXMined(ctx, c.env.Ec, tx, c.env.ChainID) +} + +// AddNodeOperator takes a node operator and provisions it in the registry. +// +// A node operator is a group of nodes that are all controlled by the same entity. The admin address is the +// address that controls the node operator. +// +// The name is a human-readable name for the node operator. +// +// The node operator is then added to the registry, and the registry will issue an ID for the node operator. +// The ID is then used when adding nodes to the registry such that the registry knows which nodes belong to which +// node operator. +func (c *CapabilityRegistryProvisioner) AddNodeOperator(ctx context.Context, nop *NodeOperator) { + fmt.Printf("Adding NodeOperator to registry: %s\n", nop.Name) + nop.BindToRegistry(c.reg) + + nops, err := c.reg.GetNodeOperators(&bind.CallOpts{}) + if err != nil { + log.Printf("failed to GetNodeOperators: %s", err) + } + for _, n := range nops { + if n.Admin == nop.Admin { + log.Printf("NodeOperator with admin address %s already exists", n.Admin.Hex()) + return + } + } + + tx, err := c.reg.AddNodeOperators(c.env.Owner, []kcr.CapabilitiesRegistryNodeOperator{ + { + Admin: nop.Admin, + Name: nop.Name, + }, + }) + if err != nil { + log.Printf("failed to AddNodeOperators: %s", err) + } + + receipt := helpers.ConfirmTXMined(ctx, c.env.Ec, tx, c.env.ChainID) + nop.SetCapabilityRegistryIssuedID(receipt) +} + +// AddNodes takes a node operators nodes, along with a capability set, then configures the registry such that +// each node is assigned the same capability set. The registry will then know that each node supports each of the +// capabilities in the set. +// +// This is a simplified version of the actual implementation, which is more flexible. The actual implementation +// allows for the ability to add different capability sets to different nodes, _and_ lets you add nodes from different +// node operators to the same capability set. This is not yet implemented here. +// +// Note that the registry must already have the capability set added via `AddCapabilities`, you cannot +// add capabilities that the registry is not yet aware of. +// +// Note that in terms of the provisioning process, this is not the last step. A capability is only active once +// there is a DON servicing it. This is done via `AddDON`. +func (c *CapabilityRegistryProvisioner) AddNodes(ctx context.Context, nop *NodeOperator, donNames ...string) { + fmt.Printf("Adding nodes to registry for NodeOperator %s with DONs: %v\n", nop.Name, donNames) + var params []kcr.CapabilitiesRegistryNodeParams + for _, donName := range donNames { + don, exists := nop.DONs[donName] + if !exists { + log.Fatalf("DON with name %s does not exist in NodeOperator %s", donName, nop.Name) + } + capSet := don.CapabilitySet + for i, peer := range don.Peers { + node, innerErr := peerToNode(nop.id, peer) + if innerErr != nil { + panic(innerErr) + } + node.HashedCapabilityIds = capSet.HashedIDs(c.reg) + node.EncryptionPublicKey = [32]byte{2: byte(i + 1)} + fmt.Printf("Adding node %s to registry with capabilities: %s\n", peer.PeerID, capSet.IDs()) + params = append(params, node) + } + } + + err := c.testCallContract("addNodes", params) + PanicErr(err) + + tx, err := c.reg.AddNodes(c.env.Owner, params) + if err != nil { + log.Printf("failed to AddNodes: %s", err) + } + helpers.ConfirmTXMined(ctx, c.env.Ec, tx, c.env.ChainID) +} + +// AddDON takes a node operator then provisions a DON with the given capabilities. +// +// A DON is a group of nodes that all support the same capability set. This set can be a subset of the +// capabilities that the nodes support. In other words, each node within the node set can support +// a different, possibly overlapping, set of capabilities, but a DON is a subgroup of those nodes that all support +// the same set of capabilities. +// +// A node can belong to multiple DONs, but it must belong to one and only one workflow DON. +// +// A DON can be a capability DON or a workflow DON, or both. +// +// When you want to add solely a workflow DON, you should set `acceptsWorkflows` to true and +// `isPublic` to false. +// This means that the DON can service workflow requests and will not service external capability requests. +// +// If you want to add solely a capability DON, you should set `acceptsWorkflows` to false and `isPublic` to true. This means that the DON +// will service external capability requests and reject workflow requests. +// +// If you want to add a DON that services both capabilities and workflows, you should set both `acceptsWorkflows` and `isPublic` to true. +// +// Another important distinction is that DON can comprise of nodes from different node operators, but for now, we're keeping it simple and restricting it to a single node operator. We also hard code F to 1. +func (c *CapabilityRegistryProvisioner) AddDON(ctx context.Context, nop *NodeOperator, donName string, isPublic bool, acceptsWorkflows bool) { + fmt.Printf("Adding DON %s to registry for NodeOperator %s with isPublic: %t and acceptsWorkflows: %t\n", donName, nop.Name, isPublic, acceptsWorkflows) + don, exists := nop.DONs[donName] + if !exists { + log.Fatalf("DON with name %s does not exist in NodeOperator %s", donName, nop.Name) + } + configs := don.CapabilitySet.Configs(c.reg) + + err := c.testCallContract("addDON", don.MustGetPeerIDs(), configs, isPublic, acceptsWorkflows, don.F) + PanicErr(err) + + tx, err := c.reg.AddDON(c.env.Owner, don.MustGetPeerIDs(), configs, isPublic, acceptsWorkflows, don.F) + + if err != nil { + log.Printf("failed to AddDON: %s", err) + } + helpers.ConfirmTXMined(ctx, c.env.Ec, tx, c.env.ChainID) +} + +/* + * + * Capabilities + * + * + */ +const ( // Taken from https://github.com/smartcontractkit/chainlink/blob/29117850e9be1be1993dbf8f21cf13cbb6af9d24/core/capabilities/integration_tests/keystone_contracts_setup.go#L43 + CapabilityTypeTrigger = uint8(0) + CapabilityTypeAction = uint8(1) + CapabilityTypeConsensus = uint8(2) + CapabilityTypeTarget = uint8(3) +) + +type CapabillityProvisioner interface { + Config() kcr.CapabilitiesRegistryCapabilityConfiguration + Capability() kcr.CapabilitiesRegistryCapability + BindToRegistry(reg kcr.CapabilitiesRegistryInterface) + GetHashedCID() [32]byte +} + +type baseCapability struct { + registry kcr.CapabilitiesRegistryInterface + capability kcr.CapabilitiesRegistryCapability +} + +func (b *baseCapability) BindToRegistry(reg kcr.CapabilitiesRegistryInterface) { + b.registry = reg +} + +func (b *baseCapability) GetHashedCID() [32]byte { + if b.registry == nil { + panic(errors.New("registry not bound to capability, cannot get hashed capability ID")) + } + + return mustHashCapabilityID(b.registry, b.capability) +} + +func (b *baseCapability) GetID() string { + return fmt.Sprintf("%s@%s", b.capability.LabelledName, b.capability.Version) +} + +func (b *baseCapability) config(config *capabilitiespb.CapabilityConfig) kcr.CapabilitiesRegistryCapabilityConfiguration { + configBytes, err := proto.Marshal(config) + if err != nil { + panic(err) + } + + return kcr.CapabilitiesRegistryCapabilityConfiguration{ + Config: configBytes, + CapabilityId: b.GetHashedCID(), + } +} + +func (b *baseCapability) Capability() kcr.CapabilitiesRegistryCapability { + return b.capability +} + +type ConsensusCapability struct { + baseCapability +} + +var _ CapabillityProvisioner = &ConsensusCapability{} + +func (c *ConsensusCapability) Config() kcr.CapabilitiesRegistryCapabilityConfiguration { + // Note that this is hard-coded for now, we'll want to support more flexible configurations in the future + // for configuring consensus once it has more configuration options + config := &capabilitiespb.CapabilityConfig{ + DefaultConfig: values.Proto(values.EmptyMap()).GetMapValue(), + } + + return c.config(config) +} + +// NewOCR3V1ConsensusCapability returns a new ConsensusCapability for OCR3 +func NewOCR3V1ConsensusCapability() *ConsensusCapability { + return &ConsensusCapability{ + baseCapability{ + capability: kcr.CapabilitiesRegistryCapability{ + LabelledName: "offchain_reporting", + Version: "1.0.0", + CapabilityType: CapabilityTypeConsensus, + }, + }, + } +} + +type TargetCapability struct { + baseCapability +} + +var _ CapabillityProvisioner = &TargetCapability{} + +func (t *TargetCapability) Config() kcr.CapabilitiesRegistryCapabilityConfiguration { + // Note that this is hard-coded for now, we'll want to support more flexible configurations in the future + // for configuring the target. This configuration is also specific to the write target + config := &capabilitiespb.CapabilityConfig{ + DefaultConfig: values.Proto(values.EmptyMap()).GetMapValue(), + RemoteConfig: &capabilitiespb.CapabilityConfig_RemoteTargetConfig{ + RemoteTargetConfig: &capabilitiespb.RemoteTargetConfig{ + RequestHashExcludedAttributes: []string{"signed_report.Signatures"}, + }, + }, + } + + return t.config(config) +} + +func NewEthereumGethTestnetV1WriteCapability() *TargetCapability { + return &TargetCapability{ + baseCapability{ + capability: kcr.CapabilitiesRegistryCapability{ + LabelledName: "write_geth-testnet", + Version: "1.0.0", + CapabilityType: CapabilityTypeTarget, + }, + }, + } +} + +type TriggerCapability struct { + baseCapability +} + +var _ CapabillityProvisioner = &TriggerCapability{} + +func (t *TriggerCapability) Config() kcr.CapabilitiesRegistryCapabilityConfiguration { + // Note that this is hard-coded for now, we'll want to support more flexible configurations in the future + // for configuring the trigger. This configuration is also possibly specific to the streams trigger. + config := &capabilitiespb.CapabilityConfig{ + DefaultConfig: values.Proto(values.EmptyMap()).GetMapValue(), + RemoteConfig: &capabilitiespb.CapabilityConfig_RemoteTriggerConfig{ + RemoteTriggerConfig: &capabilitiespb.RemoteTriggerConfig{ + RegistrationRefresh: durationpb.New(20 * time.Second), + RegistrationExpiry: durationpb.New(60 * time.Second), + MinResponsesToAggregate: uint32(1) + 1, // We've hardcoded F + 1 here + }, + }, + } + + return t.config(config) +} + +func NewStreamsTriggerV1Capability() *TriggerCapability { + return &TriggerCapability{ + baseCapability{ + capability: kcr.CapabilitiesRegistryCapability{ + LabelledName: "streams-trigger", + Version: "1.1.0", + CapabilityType: CapabilityTypeTrigger, + }, + }, + } +} + +func mustHashCapabilityID(reg kcr.CapabilitiesRegistryInterface, capability kcr.CapabilitiesRegistryCapability) [32]byte { + hashedCapabilityID, err := reg.GetHashedCapabilityId(&bind.CallOpts{}, capability.LabelledName, capability.Version) + if err != nil { + panic(err) + } + return hashedCapabilityID +} + +/* + * + * Capability Sets + * + * + */ +type CapabilitySet []CapabillityProvisioner + +func NewCapabilitySet(capabilities ...CapabillityProvisioner) CapabilitySet { + if len(capabilities) == 0 { + log.Fatalf("No capabilities provided to NewCapabilitySet") + } + + return capabilities +} + +func MergeCapabilitySets(sets ...CapabilitySet) CapabilitySet { + var merged CapabilitySet + for _, set := range sets { + merged = append(merged, set...) + } + + return merged +} + +func (c *CapabilitySet) Capabilities() []kcr.CapabilitiesRegistryCapability { + definitions := make([]kcr.CapabilitiesRegistryCapability, 0, len(*c)) + for _, cap := range *c { + definitions = append(definitions, cap.Capability()) + } + + return definitions +} + +func (c *CapabilitySet) IDs() []string { + strings := make([]string, 0, len(*c)) + for _, cap := range *c { + strings = append(strings, fmt.Sprintf("%s@%s", cap.Capability().LabelledName, cap.Capability().Version)) + } + + return strings +} + +func (c *CapabilitySet) HashedIDs(reg kcr.CapabilitiesRegistryInterface) [][32]byte { + ids := make([][32]byte, 0, len(*c)) + for _, cap := range *c { + cap.BindToRegistry(reg) + ids = append(ids, cap.GetHashedCID()) + } + + return ids +} + +func (c *CapabilitySet) Configs(reg kcr.CapabilitiesRegistryInterface) []kcr.CapabilitiesRegistryCapabilityConfiguration { + configs := make([]kcr.CapabilitiesRegistryCapabilityConfiguration, 0, len(*c)) + for _, cap := range *c { + cap.BindToRegistry(reg) + configs = append(configs, cap.Config()) + } + + return configs +} + +/* + * + * Node Operator + * + * + */ + +// DON represents a Decentralized Oracle Network with a name, peers, and associated capabilities. +type DON struct { + F uint8 + Name string + Peers []peer + CapabilitySet CapabilitySet +} + +// MustGetPeerIDs retrieves the peer IDs for the DON. It panics if any error occurs. +func (d *DON) MustGetPeerIDs() [][32]byte { + ps, err := peers(d.Peers) + if err != nil { + panic(fmt.Errorf("failed to get peer IDs for DON %s: %w", d.Name, err)) + } + return ps +} + +// NodeOperator represents a node operator with administrative details and multiple DONs. +type NodeOperator struct { + Admin gethCommon.Address + Name string + DONs map[string]DON + + reg kcr.CapabilitiesRegistryInterface + // This ID is generated by the registry when the NodeOperator is added + id uint32 +} + +// NewNodeOperator creates a new NodeOperator with the provided admin address, name, and DONs. +func NewNodeOperator(admin gethCommon.Address, name string, dons map[string]DON) *NodeOperator { + return &NodeOperator{ + Admin: admin, + Name: name, + DONs: dons, + } +} + +func (n *NodeOperator) BindToRegistry(reg kcr.CapabilitiesRegistryInterface) { + n.reg = reg +} + +func (n *NodeOperator) SetCapabilityRegistryIssuedID(receipt *gethTypes.Receipt) uint32 { + if n.reg == nil { + panic(errors.New("registry not bound to node operator, cannot set ID")) + } + // We'll need more complex handling for multiple node operators + // since we'll need to handle log ordering + recLog, err := n.reg.ParseNodeOperatorAdded(*receipt.Logs[0]) + if err != nil { + panic(err) + } + + n.id = recLog.NodeOperatorId + return n.id +} + +func peerIDToB(peerID string) ([32]byte, error) { + var peerIDB ragetypes.PeerID + err := peerIDB.UnmarshalText([]byte(peerID)) + if err != nil { + return [32]byte{}, err + } + + return peerIDB, nil +} + +func peers(ps []peer) ([][32]byte, error) { + out := [][32]byte{} + for _, p := range ps { + b, err := peerIDToB(p.PeerID) + if err != nil { + return nil, err + } + + out = append(out, b) + } + + return out, nil +} + +func peerToNode(nopID uint32, p peer) (kcr.CapabilitiesRegistryNodeParams, error) { + peerIDB, err := peerIDToB(p.PeerID) + if err != nil { + return kcr.CapabilitiesRegistryNodeParams{}, fmt.Errorf("failed to convert peerID: %w", err) + } + + sig := strings.TrimPrefix(p.Signer, "0x") + signerB, err := hex.DecodeString(sig) + if err != nil { + return kcr.CapabilitiesRegistryNodeParams{}, fmt.Errorf("failed to convert signer: %w", err) + } + + epk := strings.TrimPrefix(p.EncryptionPublicKey, "0x") + epkB, err := hex.DecodeString(epk) + if err != nil { + return kcr.CapabilitiesRegistryNodeParams{}, fmt.Errorf("failed to convert encryptionPublicKey: %w", err) + } + + var epkb [32]byte + copy(epkb[:], epkB) + + var sigb [32]byte + copy(sigb[:], signerB) + + return kcr.CapabilitiesRegistryNodeParams{ + NodeOperatorId: nopID, + P2pId: peerIDB, + Signer: sigb, + EncryptionPublicKey: epkb, + }, nil +} + +// newCapabilityConfig returns a new capability config with the default config set as empty. +// Override the empty default config with functional options. +func newCapabilityConfig(opts ...func(*values.Map)) *capabilitiespb.CapabilityConfig { + dc := values.EmptyMap() + for _, opt := range opts { + opt(dc) + } + + return &capabilitiespb.CapabilityConfig{ + DefaultConfig: values.ProtoMap(dc), + } +} diff --git a/core/scripts/keystone/src/88_contracts_helpers.go b/core/scripts/keystone/src/88_contracts_helpers.go new file mode 100644 index 00000000000..59bfeb68201 --- /dev/null +++ b/core/scripts/keystone/src/88_contracts_helpers.go @@ -0,0 +1,192 @@ +package src + +import ( + "context" + + "encoding/json" + "fmt" + "os" + "path/filepath" + + "github.com/ethereum/go-ethereum/common" + + helpers "github.com/smartcontractkit/chainlink/core/scripts/common" + capabilities_registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability" + verifierContract "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/verifier" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/verifier_proxy" +) + +var ZeroAddress = common.Address{} + +type OnChainMetaSerialized struct { + OCR common.Address `json:"ocrContract"` + Forwarder common.Address `json:"forwarderContract"` + // The block number of the transaction that set the config on the OCR3 contract. We use this to replay blocks from this point on + // when we load the OCR3 job specs on the nodes. + SetConfigTxBlock uint64 `json:"setConfigTxBlock"` + + CapabilitiesRegistry common.Address `json:"CapabilitiesRegistry"` + Verifier common.Address `json:"VerifierContract"` + VerifierProxy common.Address `json:"VerifierProxy"` + // Stores the address that has been initialized by the proxy, if any + InitializedVerifierAddress common.Address `json:"InitializedVerifierAddress"` +} + +type onchainMeta struct { + OCR3 ocr3_capability.OCR3CapabilityInterface + Forwarder forwarder.KeystoneForwarderInterface + // The block number of the transaction that set the config on the OCR3 contract. We use this to replay blocks from this point on + // when we load the OCR3 job specs on the nodes. + SetConfigTxBlock uint64 + + CapabilitiesRegistry capabilities_registry.CapabilitiesRegistryInterface + Verifier verifierContract.VerifierInterface + VerifierProxy verifier_proxy.VerifierProxyInterface + InitializedVerifierAddress common.Address `json:"InitializedVerifierAddress"` +} + +func WriteOnchainMeta(o *onchainMeta, artefactsDir string) { + ensureArtefactsDir(artefactsDir) + + fmt.Println("Writing deployed contract addresses to file...") + serialzed := OnChainMetaSerialized{} + + if o.OCR3 != nil { + serialzed.OCR = o.OCR3.Address() + } + + if o.Forwarder != nil { + serialzed.Forwarder = o.Forwarder.Address() + } + + serialzed.SetConfigTxBlock = o.SetConfigTxBlock + serialzed.InitializedVerifierAddress = o.InitializedVerifierAddress + + if o.CapabilitiesRegistry != nil { + serialzed.CapabilitiesRegistry = o.CapabilitiesRegistry.Address() + } + + if o.Verifier != nil { + serialzed.Verifier = o.Verifier.Address() + } + + if o.VerifierProxy != nil { + serialzed.VerifierProxy = o.VerifierProxy.Address() + } + + jsonBytes, err := json.Marshal(serialzed) + PanicErr(err) + + err = os.WriteFile(deployedContractsFilePath(artefactsDir), jsonBytes, 0600) + PanicErr(err) +} + +func LoadOnchainMeta(artefactsDir string, env helpers.Environment) *onchainMeta { + hydrated := &onchainMeta{} + if !ContractsAlreadyDeployed(artefactsDir) { + fmt.Printf("No deployed contracts file found at %s\n", deployedContractsFilePath(artefactsDir)) + return hydrated + } + + jsonBytes, err := os.ReadFile(deployedContractsFilePath(artefactsDir)) + if err != nil { + fmt.Printf("Error reading deployed contracts file: %s\n", err) + return hydrated + } + + var s OnChainMetaSerialized + err = json.Unmarshal(jsonBytes, &s) + if err != nil { + return hydrated + } + + hydrated.SetConfigTxBlock = s.SetConfigTxBlock + if s.OCR != ZeroAddress { + if !contractExists(s.OCR, env) { + fmt.Printf("OCR contract at %s does not exist\n", s.OCR.Hex()) + } else { + ocr3, e := ocr3_capability.NewOCR3Capability(s.OCR, env.Ec) + PanicErr(e) + hydrated.OCR3 = ocr3 + } + } + + if s.Forwarder != ZeroAddress { + if !contractExists(s.Forwarder, env) { + fmt.Printf("Forwarder contract at %s does not exist\n", s.Forwarder.Hex()) + } else { + fwdr, e := forwarder.NewKeystoneForwarder(s.Forwarder, env.Ec) + PanicErr(e) + hydrated.Forwarder = fwdr + } + } + + if s.CapabilitiesRegistry != ZeroAddress { + if !contractExists(s.CapabilitiesRegistry, env) { + fmt.Printf("CapabilityRegistry contract at %s does not exist\n", s.CapabilitiesRegistry.Hex()) + } else { + cr, e := capabilities_registry.NewCapabilitiesRegistry(s.CapabilitiesRegistry, env.Ec) + PanicErr(e) + hydrated.CapabilitiesRegistry = cr + } + } + + hydrated.InitializedVerifierAddress = s.InitializedVerifierAddress + + if s.Verifier != ZeroAddress { + if !contractExists(s.Verifier, env) { + fmt.Printf("Verifier contract at %s does not exist\n", s.Verifier.Hex()) + hydrated.InitializedVerifierAddress = ZeroAddress + } else { + verifier, e := verifierContract.NewVerifier(s.Verifier, env.Ec) + PanicErr(e) + hydrated.Verifier = verifier + } + } + + if s.VerifierProxy != ZeroAddress { + if !contractExists(s.VerifierProxy, env) { + fmt.Printf("VerifierProxy contract at %s does not exist\n", s.VerifierProxy.Hex()) + hydrated.InitializedVerifierAddress = ZeroAddress + } else { + verifierProxy, e := verifier_proxy.NewVerifierProxy(s.VerifierProxy, env.Ec) + PanicErr(e) + hydrated.VerifierProxy = verifierProxy + } + } + + blkNum, err := env.Ec.BlockNumber(context.Background()) + PanicErr(err) + + if s.SetConfigTxBlock > blkNum { + fmt.Printf("Stale SetConfigTxBlock: %d, current block number: %d\n", s.SetConfigTxBlock, blkNum) + hydrated.SetConfigTxBlock = 0 + } + + return hydrated +} + +func ContractsAlreadyDeployed(artefactsDir string) bool { + _, err := os.Stat(artefactsDir) + if err != nil { + return false + } + + _, err = os.Stat(deployedContractsFilePath(artefactsDir)) + + return err == nil +} + +func deployedContractsFilePath(artefactsDir string) string { + return filepath.Join(artefactsDir, deployedContractsJSON) +} + +func contractExists(address common.Address, env helpers.Environment) bool { + byteCode, err := env.Ec.CodeAt(context.Background(), address, nil) + if err != nil { + return false + } + return len(byteCode) != 0 +} diff --git a/core/scripts/keystone/src/88_gen_jobspecs.go b/core/scripts/keystone/src/88_gen_jobspecs.go deleted file mode 100644 index 4f59a89be2d..00000000000 --- a/core/scripts/keystone/src/88_gen_jobspecs.go +++ /dev/null @@ -1,91 +0,0 @@ -package src - -import ( - "fmt" - "path/filepath" - "strconv" - "strings" - - helpers "github.com/smartcontractkit/chainlink/core/scripts/common" - ksdeploy "github.com/smartcontractkit/chainlink/deployment/keystone" -) - -type spec []string - -func (s spec) ToString() string { - return strings.Join(s, "\n") -} - -type hostSpec struct { - spec spec - host string -} - -type donHostSpec struct { - bootstrap hostSpec - oracles []hostSpec -} - -func genSpecs( - pubkeysPath string, - nodeListPath string, - templatesDir string, - chainID int64, - p2pPort int64, - ocrConfigContractAddress string, -) donHostSpec { - nodes := downloadNodeAPICredentials(nodeListPath) - nca := downloadNodePubKeys(nodeListPath, chainID, pubkeysPath) - bootstrapNode := nca[0] - - bootstrapSpecLines, err := readLines(filepath.Join(templatesDir, bootstrapSpecTemplate)) - helpers.PanicErr(err) - bootHost := nodes[0].remoteURL.Hostname() - bootstrapSpecLines = replacePlaceholders( - bootstrapSpecLines, - chainID, p2pPort, - ocrConfigContractAddress, bootHost, - bootstrapNode, bootstrapNode, - ) - bootstrap := hostSpec{bootstrapSpecLines, bootHost} - - oracleSpecLinesTemplate, err := readLines(filepath.Join(templatesDir, oracleSpecTemplate)) - helpers.PanicErr(err) - oracles := []hostSpec{} - for i := 1; i < len(nodes); i++ { - oracleSpecLines := oracleSpecLinesTemplate - oracleSpecLines = replacePlaceholders( - oracleSpecLines, - chainID, p2pPort, - ocrConfigContractAddress, bootHost, - bootstrapNode, nca[i], - ) - oracles = append(oracles, hostSpec{oracleSpecLines, nodes[i].remoteURL.Host}) - } - - return donHostSpec{ - bootstrap: bootstrap, - oracles: oracles, - } -} - -func replacePlaceholders( - lines []string, - - chainID, p2pPort int64, - contractAddress, bootHost string, - boot, node ksdeploy.NodeKeys, -) (output []string) { - chainIDStr := strconv.FormatInt(chainID, 10) - bootstrapper := fmt.Sprintf("%s@%s:%d", boot.P2PPeerID, bootHost, p2pPort) - for _, l := range lines { - l = strings.Replace(l, "{{ chain_id }}", chainIDStr, 1) - l = strings.Replace(l, "{{ ocr_config_contract_address }}", contractAddress, 1) - l = strings.Replace(l, "{{ transmitter_id }}", node.EthAddress, 1) - l = strings.Replace(l, "{{ ocr_key_bundle_id }}", node.OCR2BundleID, 1) - l = strings.Replace(l, "{{ aptos_key_bundle_id }}", node.AptosBundleID, 1) - l = strings.Replace(l, "{{ bootstrapper_p2p_id }}", bootstrapper, 1) - output = append(output, l) - } - return -} diff --git a/core/scripts/keystone/src/88_gen_jobspecs_test.go b/core/scripts/keystone/src/88_gen_jobspecs_test.go deleted file mode 100644 index 7af11646c4e..00000000000 --- a/core/scripts/keystone/src/88_gen_jobspecs_test.go +++ /dev/null @@ -1,37 +0,0 @@ -package src - -import ( - "fmt" - "testing" - - "github.com/gkampitakis/go-snaps/snaps" -) - -func (d *donHostSpec) ToString() string { - var result string - result += "Bootstrap:\n" - result += "Host: " + d.bootstrap.host + "\n" - result += d.bootstrap.spec.ToString() - result += "\n\nOracles:\n" - for i, oracle := range d.oracles { - if i != 0 { - result += "--------------------------------\n" - } - result += fmt.Sprintf("Oracle %d:\n", i) - result += "Host: " + oracle.host + "\n" - result += oracle.spec.ToString() - result += "\n\n" - } - return result -} - -func TestGenSpecs(t *testing.T) { - pubkeysPath := "./testdata/PublicKeys.json" - nodeListPath := "./testdata/NodeList.txt" - chainID := int64(11155111) - p2pPort := int64(6690) - contractAddress := "0xB29934624cAe3765E33115A9530a13f5aEC7fa8A" - - specs := genSpecs(pubkeysPath, nodeListPath, "../templates", chainID, p2pPort, contractAddress) - snaps.MatchSnapshot(t, specs.ToString()) -} diff --git a/core/scripts/keystone/src/88_gen_ocr3_config.go b/core/scripts/keystone/src/88_gen_ocr3_config.go deleted file mode 100644 index 707616b833b..00000000000 --- a/core/scripts/keystone/src/88_gen_ocr3_config.go +++ /dev/null @@ -1,20 +0,0 @@ -package src - -import ( - helpers "github.com/smartcontractkit/chainlink/core/scripts/common" - "github.com/smartcontractkit/chainlink/deployment" - ksdeploy "github.com/smartcontractkit/chainlink/deployment/keystone" -) - -func mustReadConfig(fileName string) (output ksdeploy.TopLevelConfigSource) { - return mustParseJSON[ksdeploy.TopLevelConfigSource](fileName) -} - -func generateOCR3Config(nodeList string, configFile string, chainID int64, pubKeysPath string) ksdeploy.OCR2OracleConfig { - topLevelCfg := mustReadConfig(configFile) - cfg := topLevelCfg.OracleConfig - nca := downloadNodePubKeys(nodeList, chainID, pubKeysPath) - c, err := ksdeploy.GenerateOCR3Config(cfg, nca, deployment.XXXGenerateTestOCRSecrets()) - helpers.PanicErr(err) - return c -} diff --git a/core/scripts/keystone/src/88_gen_ocr3_config_test.go b/core/scripts/keystone/src/88_gen_ocr3_config_test.go deleted file mode 100644 index 10cdc07b204..00000000000 --- a/core/scripts/keystone/src/88_gen_ocr3_config_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package src - -import ( - "errors" - "testing" - - "github.com/gkampitakis/go-snaps/match" - "github.com/gkampitakis/go-snaps/snaps" -) - -func TestGenerateOCR3Config(t *testing.T) { - // Generate OCR3 config - config := generateOCR3Config(".cache/NodeList.txt", "./testdata/SampleConfig.json", 11155111, "./testdata/PublicKeys.json") - - matchOffchainConfig := match.Custom("OffchainConfig", func(s any) (any, error) { - // coerce the value to a string - s, ok := s.(string) - if !ok { - return nil, errors.New("offchain config is not a string") - } - - // if the string is not empty - if s == "" { - return nil, errors.New("offchain config is empty") - } - - return "", nil - }) - - snaps.MatchJSON(t, config, matchOffchainConfig) -} diff --git a/core/scripts/keystone/src/88_jobspecs_helpers.go b/core/scripts/keystone/src/88_jobspecs_helpers.go new file mode 100644 index 00000000000..0e6cc3a043a --- /dev/null +++ b/core/scripts/keystone/src/88_jobspecs_helpers.go @@ -0,0 +1,53 @@ +package src + +import ( + "fmt" +) + +type OCRSpec struct { + ContractID string +} + +type BootSpec struct { + ContractID string +} + +type WorkflowSpec struct { + WorkflowID string +} + +type JobSpec struct { + ID string + Name string + BootstrapSpec BootSpec + OffChainReporting2OracleSpec OCRSpec + WorkflowSpec WorkflowSpec +} + +func upsertJob(api *nodeAPI, jobSpecName string, jobSpecStr string) { + jobsResp := api.mustExec(api.methods.ListJobs) + jobs := mustJSON[[]JobSpec](jobsResp) + for _, job := range *jobs { + if job.Name == jobSpecName { + fmt.Printf("Job already exists: %s, replacing..\n", jobSpecName) + api.withArg(job.ID).mustExec(api.methods.DeleteJob) + break + } + } + + fmt.Printf("Deploying jobspec: %s\n", jobSpecName) + _, err := api.withArg(jobSpecStr).exec(api.methods.CreateJob) + if err != nil { + panic(fmt.Sprintf("Failed to deploy job spec: %s Error: %s", jobSpecStr, err)) + } +} + +func clearJobs(api *nodeAPI) { + jobsResp := api.mustExec(api.methods.ListJobs) + jobs := mustJSON[[]JobSpec](jobsResp) + for _, job := range *jobs { + fmt.Printf("Deleting job: %s\n", job.Name) + api.withArg(job.ID).mustExec(api.methods.DeleteJob) + } + fmt.Println("All jobs have been deleted.") +} diff --git a/core/scripts/keystone/src/88_ocr_helpers.go b/core/scripts/keystone/src/88_ocr_helpers.go new file mode 100644 index 00000000000..7cdfd72ca52 --- /dev/null +++ b/core/scripts/keystone/src/88_ocr_helpers.go @@ -0,0 +1,69 @@ +package src + +import ( + "encoding/hex" + + "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/libocr/offchainreporting2/types" + + ksdeploy "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" +) + +func ocrConfToContractConfig(ocrConf ksdeploy.OCR3OnchainConfig, configCount uint32) types.ContractConfig { + cc := types.ContractConfig{ + Signers: convertByteSliceToOnchainPublicKeys(ocrConf.Signers), + Transmitters: convertAddressesToAccounts(ocrConf.Transmitters), + F: ocrConf.F, + OnchainConfig: ocrConf.OnchainConfig, + OffchainConfigVersion: ocrConf.OffchainConfigVersion, + OffchainConfig: ocrConf.OffchainConfig, + ConfigCount: uint64(configCount), + } + return cc +} + +func mercuryOCRConfigToContractConfig(ocrConf MercuryOCR2Config, configCount uint32) types.ContractConfig { + cc := types.ContractConfig{ + Signers: convertAddressesToOnchainPublicKeys(ocrConf.Signers), + Transmitters: convertBytes32sToAccounts(ocrConf.Transmitters), + F: ocrConf.F, + OnchainConfig: ocrConf.OnchainConfig, + OffchainConfigVersion: ocrConf.OffchainConfigVersion, + OffchainConfig: ocrConf.OffchainConfig, + ConfigCount: uint64(configCount), + } + + return cc +} + +func convertAddressesToOnchainPublicKeys(addresses []common.Address) []types.OnchainPublicKey { + keys := make([]types.OnchainPublicKey, len(addresses)) + for i, addr := range addresses { + keys[i] = types.OnchainPublicKey(addr.Bytes()) + } + return keys +} + +func convertAddressesToAccounts(addresses []common.Address) []types.Account { + accounts := make([]types.Account, len(addresses)) + for i, addr := range addresses { + accounts[i] = types.Account(addr.Hex()) + } + return accounts +} + +func convertBytes32sToAccounts(bs [][32]byte) []types.Account { + accounts := make([]types.Account, len(bs)) + for i, b := range bs { + accounts[i] = types.Account(hex.EncodeToString(b[:])) + } + return accounts +} + +func convertByteSliceToOnchainPublicKeys(bs [][]byte) []types.OnchainPublicKey { + keys := make([]types.OnchainPublicKey, len(bs)) + for i, b := range bs { + keys[i] = types.OnchainPublicKey(b) + } + return keys +} diff --git a/core/scripts/keystone/src/99_app.go b/core/scripts/keystone/src/99_app.go index 6e59932aa71..29164959bec 100644 --- a/core/scripts/keystone/src/99_app.go +++ b/core/scripts/keystone/src/99_app.go @@ -1,31 +1,389 @@ package src import ( + "bytes" + "context" + "encoding/json" + "errors" "flag" "io" + "net/http" + "net/url" + "reflect" + "runtime" + "strings" + "sync" + "time" "github.com/urfave/cli" + "go.uber.org/zap/zapcore" helpers "github.com/smartcontractkit/chainlink/core/scripts/common" + "github.com/smartcontractkit/chainlink/v2/core/cmd" clcmd "github.com/smartcontractkit/chainlink/v2/core/cmd" + "github.com/smartcontractkit/chainlink/v2/core/logger" + clsessions "github.com/smartcontractkit/chainlink/v2/core/sessions" ) -func newApp(n *node, writer io.Writer) (*clcmd.Shell, *cli.App) { +// Package-level cache and mutex +var ( + nodeAPICache = make(map[string]*nodeAPI) + cacheMutex = &sync.Mutex{} +) + +func newApp(n NodeWithCreds, writer io.Writer) (*clcmd.Shell, *cli.App) { + loggingCfg := logger.Config{ + LogLevel: zapcore.InfoLevel, + JsonConsole: true, + } + logger, closeLggr := loggingCfg.New() + u, err := url.Parse(n.RemoteURL.String()) + PanicErr(err) + + clientOpts := clcmd.ClientOpts{RemoteNodeURL: *u, InsecureSkipVerify: true} + sr := clsessions.SessionRequest{Email: n.APILogin, Password: n.APIPassword} + + // Set the log level to error for the HTTP client, we don't care about + // the ssl warnings it emits for CRIB + logger.SetLogLevel(zapcore.ErrorLevel) + cookieAuth := cmd.NewSessionCookieAuthenticator( + clientOpts, + &cmd.MemoryCookieStore{}, + logger, + ) + + http := NewRetryableAuthenticatedHTTPClient(logger, clientOpts, cookieAuth, sr) + // Set the log level back to info for the shell + logger.SetLogLevel(zapcore.InfoLevel) client := &clcmd.Shell{ - Renderer: clcmd.RendererJSON{Writer: writer}, - AppFactory: clcmd.ChainlinkAppFactory{}, - KeyStoreAuthenticator: clcmd.TerminalKeyStoreAuthenticator{Prompter: n}, - FallbackAPIInitializer: clcmd.NewPromptingAPIInitializer(n), - Runner: clcmd.ChainlinkRunner{}, - PromptingSessionRequestBuilder: clcmd.NewPromptingSessionRequestBuilder(n), - ChangePasswordPrompter: clcmd.NewChangePasswordPrompter(), - PasswordPrompter: clcmd.NewPasswordPrompter(), + Logger: logger, + Renderer: clcmd.RendererJSON{Writer: writer}, + AppFactory: clcmd.ChainlinkAppFactory{}, + Runner: clcmd.ChainlinkRunner{}, + HTTP: http, + + CloseLogger: closeLggr, } app := clcmd.NewApp(client) - fs := flag.NewFlagSet("blah", flag.ContinueOnError) - fs.String("remote-node-url", n.url.String(), "") - helpers.PanicErr(app.Before(cli.NewContext(nil, fs, nil))) - // overwrite renderer since it's set to stdout after Before() is called - client.Renderer = clcmd.RendererJSON{Writer: writer} return client, app } + +type nodeAPI struct { + methods *cmd.Shell + app *cli.App + output *bytes.Buffer + fs *flag.FlagSet + clientMethod func(*cli.Context) error + logger logger.Logger +} + +func newNodeAPI(n NodeWithCreds) *nodeAPI { + // Create a unique key for the cache + key := n.RemoteURL.String() + + // Check if the nodeAPI exists in the cache + cacheMutex.Lock() + if api, exists := nodeAPICache[key]; exists { + cacheMutex.Unlock() + return api + } + cacheMutex.Unlock() + + output := &bytes.Buffer{} + methods, app := newApp(n, output) + + api := &nodeAPI{ + output: output, + methods: methods, + app: app, + fs: flag.NewFlagSet("test", flag.ContinueOnError), + logger: methods.Logger.Named("NodeAPI"), + } + + // Store the new nodeAPI in the cache + cacheMutex.Lock() + nodeAPICache[key] = api + cacheMutex.Unlock() + + return api +} + +func (c *nodeAPI) withArg(arg string) *nodeAPI { + err := c.fs.Parse([]string{arg}) + helpers.PanicErr(err) + + return c +} + +func (c *nodeAPI) withArgs(args ...string) *nodeAPI { + err := c.fs.Parse(args) + helpers.PanicErr(err) + + return c +} + +func (c *nodeAPI) withFlags(clientMethod func(*cli.Context) error, applyFlags func(*flag.FlagSet)) *nodeAPI { + flagSetApplyFromAction(clientMethod, c.fs, "") + applyFlags(c.fs) + + c.clientMethod = clientMethod + + return c +} + +func (c *nodeAPI) exec(clientMethod ...func(*cli.Context) error) ([]byte, error) { + if len(clientMethod) > 1 { + PanicErr(errors.New("Only one client method allowed")) + } + + defer c.output.Reset() + defer func() { + c.fs = flag.NewFlagSet("test", flag.ContinueOnError) + c.clientMethod = nil + }() + + if c.clientMethod == nil { + c.clientMethod = clientMethod[0] + } + + retryCount := 3 + for i := 0; i < retryCount; i++ { + c.logger.Tracew("Attempting API request", "attempt", i+1, "maxAttempts", retryCount) + c.output.Reset() + ctx := cli.NewContext(c.app, c.fs, nil) + err := c.clientMethod(ctx) + + if err == nil { + c.logger.Tracew("API request completed successfully", "attempt", i+1) + return c.output.Bytes(), nil + } + + if !strings.Contains(err.Error(), "invalid character '<' looking for beginning of value") { + c.logger.Tracew("API request failed with non-retriable error", + "attempt", i+1, + "err", err, + ) + return nil, err + } + + c.logger.Warnw("Encountered 504 gateway error during API request, retrying", + "attempt", i+1, + "maxAttempts", retryCount, + "err", err, + ) + + if i == retryCount-1 { + c.logger.Error("Failed to complete API request after all retry attempts") + return nil, err + } + + c.logger.Tracew("Waiting before retry attempt", + "attempt", i+1, + "waitTime", "1s", + ) + time.Sleep(3 * time.Second) + } + + return nil, errors.New("API request failed after retries") +} + +func (c *nodeAPI) mustExec(clientMethod ...func(*cli.Context) error) []byte { + bytes, err := c.exec(clientMethod...) + helpers.PanicErr(err) + return bytes +} + +// flagSetApplyFromAction applies the flags from action to the flagSet. +// +// `parentCommand` will filter the app commands and only applies the flags if the command/subcommand has a parent with that name, if left empty no filtering is done +// +// Taken from: https://github.com/smartcontractkit/chainlink/blob/develop/core/cmd/shell_test.go#L590 +func flagSetApplyFromAction(action interface{}, flagSet *flag.FlagSet, parentCommand string) { + cliApp := cmd.Shell{} + app := cmd.NewApp(&cliApp) + + foundName := parentCommand == "" + actionFuncName := getFuncName(action) + + for _, command := range app.Commands { + flags := recursiveFindFlagsWithName(actionFuncName, command, parentCommand, foundName) + + for _, flag := range flags { + 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 + } + } + + for _, subcommand := range command.Subcommands { + if !foundName { + foundName = strings.EqualFold(subcommand.Name, parent) + } + + found := recursiveFindFlagsWithName(actionFuncName, subcommand, parent, foundName) + if found != nil { + return found + } + } + return nil +} + +func getFuncName(i interface{}) string { + return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name() +} + +func mustJSON[T any](bytes []byte) *T { + typedPayload := new(T) + err := json.Unmarshal(bytes, typedPayload) + if err != nil { + PanicErr(err) + } + return typedPayload +} + +type retryableAuthenticatedHTTPClient struct { + client cmd.HTTPClient + logger logger.Logger +} + +func NewRetryableAuthenticatedHTTPClient(lggr logger.Logger, clientOpts clcmd.ClientOpts, cookieAuth cmd.CookieAuthenticator, sessionRequest clsessions.SessionRequest) cmd.HTTPClient { + return &retryableAuthenticatedHTTPClient{ + client: cmd.NewAuthenticatedHTTPClient(lggr, clientOpts, cookieAuth, sessionRequest), + logger: lggr.Named("RetryableAuthenticatedHTTPClient"), + } +} + +func logBody(body io.Reader) (string, io.Reader) { + if body == nil { + return "", nil + } + + var buf bytes.Buffer + tee := io.TeeReader(body, &buf) + bodyBytes, _ := io.ReadAll(tee) + return string(bodyBytes), bytes.NewReader(buf.Bytes()) +} + +func logResponse(logger logger.Logger, resp *http.Response) { + if resp == nil { + logger.Trace("Response was nil") + return + } + + bodyBytes, err := io.ReadAll(resp.Body) + if err != nil { + logger.Errorw("Failed to read response body for logging", "err", err) + return + } + // Replace the body so it can be read again by the caller + resp.Body = io.NopCloser(bytes.NewReader(bodyBytes)) + + logger.Tracew("Response details", + "statusCode", resp.StatusCode, + "status", resp.Status, + "headers", resp.Header, + "body", string(bodyBytes), + ) +} + +func (h *retryableAuthenticatedHTTPClient) Get(ctx context.Context, path string, headers ...map[string]string) (*http.Response, error) { + h.logger.Tracew("Making GET request", + "path", path, + "headers", headers, + ) + return h.doRequestWithRetry(ctx, func() (*http.Response, error) { + return h.client.Get(ctx, path, headers...) + }) +} + +func (h *retryableAuthenticatedHTTPClient) Post(ctx context.Context, path string, body io.Reader) (*http.Response, error) { + bodyStr, newBody := logBody(body) + h.logger.Tracew("Making POST request", + "path", path, + "body", bodyStr, + ) + return h.doRequestWithRetry(ctx, func() (*http.Response, error) { + return h.client.Post(ctx, path, newBody) + }) +} + +func (h *retryableAuthenticatedHTTPClient) Put(ctx context.Context, path string, body io.Reader) (*http.Response, error) { + bodyStr, newBody := logBody(body) + h.logger.Tracew("Making PUT request", + "path", path, + "body", bodyStr, + ) + return h.doRequestWithRetry(ctx, func() (*http.Response, error) { + return h.client.Put(ctx, path, newBody) + }) +} + +func (h *retryableAuthenticatedHTTPClient) Patch(ctx context.Context, path string, body io.Reader, headers ...map[string]string) (*http.Response, error) { + bodyStr, newBody := logBody(body) + h.logger.Tracew("Making PATCH request", + "path", path, + "headers", headers, + "body", bodyStr, + ) + return h.doRequestWithRetry(ctx, func() (*http.Response, error) { + return h.client.Patch(ctx, path, newBody, headers...) + }) +} + +func (h *retryableAuthenticatedHTTPClient) Delete(ctx context.Context, path string) (*http.Response, error) { + h.logger.Tracew("Making DELETE request", + "path", path, + ) + return h.doRequestWithRetry(ctx, func() (*http.Response, error) { + return h.client.Delete(ctx, path) + }) +} + +func (h *retryableAuthenticatedHTTPClient) doRequestWithRetry(_ context.Context, req func() (*http.Response, error)) (*http.Response, error) { + retryCount := 3 + for i := 0; i < retryCount; i++ { + h.logger.Tracew("Attempting request", "attempt", i+1, "maxAttempts", retryCount) + + response, err := req() + logResponse(h.logger, response) + + if err == nil || !strings.Contains(err.Error(), "invalid character '<' looking for beginning of value") { + if err != nil { + h.logger.Warn("Request completed with error", + "attempt", i+1, + "err", err, + ) + } else { + h.logger.Tracew("Request completed successfully", + "attempt", i+1, + "statusCode", response.StatusCode, + ) + } + return response, err + } + + h.logger.Warnw("Encountered 504 error during request, retrying", + "attempt", i+1, + "maxAttempts", retryCount, + "err", err, + ) + + if i == retryCount-1 { + h.logger.Error("Failed to complete request after all retry attempts") + return response, err + } + + h.logger.Tracew("Waiting before retry attempt", + "attempt", i+1, + "waitTime", "1s", + ) + time.Sleep(1 * time.Second) + } + return nil, errors.New("request failed after retries") +} diff --git a/core/scripts/keystone/src/99_crib_client.go b/core/scripts/keystone/src/99_crib_client.go index ebf9f9ee955..1a38cafe9bb 100644 --- a/core/scripts/keystone/src/99_crib_client.go +++ b/core/scripts/keystone/src/99_crib_client.go @@ -4,7 +4,7 @@ package src import ( "fmt" - "net/url" + "sort" "strings" ) @@ -12,12 +12,24 @@ type CribClient struct { k8sClient *K8sClient } -type CLNodeCredentials struct { - URL *url.URL - PodName string - Username string - Password string - NodePassword string +// SimpleURL lets us marshal a URL with only the fields we need. +type SimpleURL struct { + Scheme string `json:"scheme"` + Host string `json:"host"` + Path string `json:"path"` +} + +func (s SimpleURL) String() string { + return fmt.Sprintf("%s://%s%s", s.Scheme, s.Host, s.Path) +} + +type NodeWithCreds struct { + URL SimpleURL + RemoteURL SimpleURL + ServiceName string + APILogin string + APIPassword string + KeystorePassword string } func NewCribClient() *CribClient { @@ -27,35 +39,44 @@ func NewCribClient() *CribClient { } } -func (m *CribClient) GetCLNodeCredentials() ([]CLNodeCredentials, error) { - fmt.Println("Getting CL node pods with config maps...") - pods, err := m.k8sClient.GetPodsWithConfigMap() +func (m *CribClient) getCLNodes() ([]NodeWithCreds, error) { + fmt.Println("Getting CL node deployments with config maps...") + deployments, err := m.k8sClient.GetDeploymentsWithConfigMap() if err != nil { return nil, err } - clNodeCredentials := []CLNodeCredentials{} + nodes := []NodeWithCreds{} - for _, pod := range pods { - apiCredentials := pod.ConfigMap.Data["apicredentials"] + for _, deployment := range deployments { + apiCredentials := deployment.ConfigMap.Data["apicredentials"] splitCreds := strings.Split(strings.TrimSpace(apiCredentials), "\n") username := splitCreds[0] password := splitCreds[1] - nodePassword := pod.ConfigMap.Data["node-password"] - url, err := url.Parse("https://" + pod.Host) - if err != nil { - return nil, err + keystorePassword := deployment.ConfigMap.Data["node-password"] + url := SimpleURL{ + Scheme: "https", + Host: deployment.Host, + Path: "", } - clNodeCredential := CLNodeCredentials{ - URL: url, - PodName: pod.Name, - Username: username, - Password: password, - NodePassword: nodePassword, + node := NodeWithCreds{ + // We dont handle both in-cluster and out-of-cluster deployments + // Hence why both URL and RemoteURL are the same + URL: url, + RemoteURL: url, + ServiceName: deployment.ServiceName, + APILogin: username, + APIPassword: password, + KeystorePassword: keystorePassword, } - clNodeCredentials = append(clNodeCredentials, clNodeCredential) + nodes = append(nodes, node) } - return clNodeCredentials, nil + // Sort nodes by URL + sort.Slice(nodes, func(i, j int) bool { + return nodes[i].URL.Host < nodes[j].URL.Host + }) + + return nodes, nil } diff --git a/core/scripts/keystone/src/99_fetch_keys.go b/core/scripts/keystone/src/99_fetch_keys.go index 8899da95b11..63e191a1234 100644 --- a/core/scripts/keystone/src/99_fetch_keys.go +++ b/core/scripts/keystone/src/99_fetch_keys.go @@ -1,230 +1,271 @@ package src import ( - "bytes" "encoding/json" "errors" - "flag" "fmt" "os" - "sort" "strings" "github.com/urfave/cli" helpers "github.com/smartcontractkit/chainlink/core/scripts/common" - ksdeploy "github.com/smartcontractkit/chainlink/deployment/keystone" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) -func downloadNodePubKeys(nodeList string, chainID int64, pubKeysPath string) []ksdeploy.NodeKeys { - // Check if file exists already, and if so, return the keys - if _, err := os.Stat(pubKeysPath); err == nil { - fmt.Println("Loading existing public keys at:", pubKeysPath) - return mustParseJSON[[]ksdeploy.NodeKeys](pubKeysPath) - } - - nodes := downloadNodeAPICredentials(nodeList) - nodesKeys := mustFetchNodesKeys(chainID, nodes) +// NodeSet represents a set of nodes with associated metadata. +// NodeKeys are indexed by the same order as Nodes. +type NodeSet struct { + Name string + Prefix string + Nodes []NodeWithCreds + NodeKeys []NodeKeys +} - marshalledNodeKeys, err := json.MarshalIndent(nodesKeys, "", " ") - if err != nil { - panic(err) - } - err = os.WriteFile(pubKeysPath, marshalledNodeKeys, 0600) - if err != nil { - panic(err) - } - fmt.Println("Keystone OCR2 public keys have been saved to:", pubKeysPath) +var ( + WorkflowNodeSetName = "workflow" + WorkflowNodeSetPrefix = "ks-wf-" + StreamsTriggerNodeSetName = "streams-trigger" + StreamsTriggerNodeSetPrefix = "ks-str-trig-" +) - return nodesKeys +// NodeSets holds the two NodeSets: Workflow and StreamsTrigger. +type NodeSets struct { + Workflow NodeSet + StreamsTrigger NodeSet } -// downloadNodeAPICredentials downloads the node API credentials, or loads them from disk if they already exist -// -// The nodes are sorted by URL. In the case of crib, the bootstrap node is the first node in the list. -func downloadNodeAPICredentials(nodeListPath string) []*node { - if _, err := os.Stat(nodeListPath); err == nil { - fmt.Println("Loading existing node host list at:", nodeListPath) - nodesList := mustReadNodesList(nodeListPath) - return nodesList +func downloadNodeSets(chainID int64, nodeSetPath string, nodeSetSize int) NodeSets { + if _, err := os.Stat(nodeSetPath); err == nil { + fmt.Println("Loading existing nodesets at:", nodeSetPath) + nodeSets := mustReadJSON[NodeSets](nodeSetPath) + return nodeSets } fmt.Println("Connecting to Kubernetes to fetch node credentials...") crib := NewCribClient() - clNodesWithCreds, err := crib.GetCLNodeCredentials() - - if err != nil { - panic(err) + nodes, err := crib.getCLNodes() + PanicErr(err) + + totalNodes := len(nodes) + // Workflow and StreamsTrigger nodeSets should have the same number of nodes + // hence we need at least 2 * nodeSetSize nodes + requiredNodes := nodeSetSize * 2 + if totalNodes < requiredNodes { + panic(fmt.Errorf("not enough nodes to populate both nodeSets: required %d, got %d", requiredNodes, totalNodes)) } - nodesList := clNodesWithCredsToNodes(clNodesWithCreds) - err = writeNodesList(nodeListPath, nodesList) - if err != nil { - panic(err) - } - if len(nodesList) == 0 { - panic("No nodes found") + nodeSets := NodeSets{ + Workflow: NodeSet{ + Name: WorkflowNodeSetName, + Prefix: WorkflowNodeSetPrefix, + Nodes: nodes[:nodeSetSize], + }, + StreamsTrigger: NodeSet{ + Name: StreamsTriggerNodeSetName, + Prefix: StreamsTriggerNodeSetPrefix, + Nodes: nodes[nodeSetSize : nodeSetSize*2], + }, } - return nodesList + + nodeSets.Workflow.NodeKeys = mustFetchNodeKeys(chainID, nodeSets.Workflow.Nodes, true) + nodeSets.StreamsTrigger.NodeKeys = mustFetchNodeKeys(chainID, nodeSets.StreamsTrigger.Nodes, false) + mustWriteJSON(nodeSetPath, nodeSets) + + return nodeSets } -func clNodesWithCredsToNodes(clNodesWithCreds []CLNodeCredentials) []*node { - nodes := []*node{} - for _, cl := range clNodesWithCreds { - n := node{ - url: cl.URL, - password: cl.Password, - login: cl.Username, - } - nodes = append(nodes, &n) - } +// NodeKeys represents the keys for a single node. +// If there are multiple OCR2KBs or OCR2AptosKBs, only the first one is used. +type NodeKeys struct { + AptosAccount string `json:"AptosAccount"` + EthAddress string `json:"EthAddress"` + P2PPeerID string `json:"P2PPeerID"` + CSAPublicKey string `json:"CSAPublicKey"` + OCR2KBTrimmed + OCR2AptosKBTrimmed +} - // sort nodes by URL - sort.Slice(nodes, func(i, j int) bool { - return nodes[i].url.String() < nodes[j].url.String() - }) - return nodes +// This is an OCR key bundle with the prefixes on each respective key +// trimmed off +type OCR2KBTrimmed struct { + OCR2BundleID string `json:"OCR2BundleID"` // used only in job spec + OCR2OnchainPublicKey string `json:"OCR2OnchainPublicKey"` // ocr2on_evm_ + OCR2OffchainPublicKey string `json:"OCR2OffchainPublicKey"` // ocr2off_evm_ + OCR2ConfigPublicKey string `json:"OCR2ConfigPublicKey"` // ocr2cfg_evm_ } -type ocr2Bundle struct { - ID string `json:"id"` - ChainType string `json:"chainType"` - OnchainPublicKey string `json:"onchainPublicKey"` - OffchainPublicKey string `json:"offchainPublicKey"` - ConfigPublicKey string `json:"configPublicKey"` +// This is an Aptos key bundle with the prefixes on each respective key +// trimmed off +type OCR2AptosKBTrimmed struct { + AptosBundleID string `json:"AptosBundleID"` + AptosOnchainPublicKey string `json:"AptosOnchainPublicKey"` // ocr2on_aptos_ } -func mustFetchNodesKeys(chainID int64, nodes []*node) (nca []ksdeploy.NodeKeys) { - for _, n := range nodes { - output := &bytes.Buffer{} - client, app := newApp(n, output) - - fmt.Println("Logging in:", n.url) - loginFs := flag.NewFlagSet("test", flag.ContinueOnError) - loginFs.Bool("bypass-version-check", true, "") - loginCtx := cli.NewContext(app, loginFs, nil) - err := client.RemoteLogin(loginCtx) - helpers.PanicErr(err) - output.Reset() +func mustFetchNodeKeys(chainID int64, nodes []NodeWithCreds, createAptosKeys bool) []NodeKeys { + nodeKeys := []NodeKeys{} - err = client.ListETHKeys(&cli.Context{ - App: app, - }) - helpers.PanicErr(err) - var ethKeys []presenters.ETHKeyResource - helpers.PanicErr(json.Unmarshal(output.Bytes(), ðKeys)) - ethAddress, err := findFirstGoodEthKeyAddress(chainID, ethKeys) + for _, n := range nodes { + api := newNodeAPI(n) + // Get eth key + fmt.Printf("Fetching ETH keys for node %s\n", n.ServiceName) + eKey := api.mustExec(api.methods.ListETHKeys) + ethKeys := mustJSON[[]presenters.ETHKeyResource](eKey) + ethAddress, err := findFirstGoodEthKeyAddress(chainID, *ethKeys) helpers.PanicErr(err) - output.Reset() - keysClient := cmd.NewAptosKeysClient(client) - err = keysClient.ListKeys(&cli.Context{ - App: app, - }) - helpers.PanicErr(err) - var aptosKeys []presenters.AptosKeyResource - helpers.PanicErr(json.Unmarshal(output.Bytes(), &aptosKeys)) - if len(aptosKeys) != 1 { - helpers.PanicErr(errors.New("node must have single aptos key")) + var aptosAccount string + if createAptosKeys { + aptosAccount = getOrCreateAptosKey(api) } - aptosAccount := aptosKeys[0].Account - output.Reset() - err = client.ListP2PKeys(&cli.Context{ - App: app, - }) - helpers.PanicErr(err) - var p2pKeys []presenters.P2PKeyResource - helpers.PanicErr(json.Unmarshal(output.Bytes(), &p2pKeys)) - if len(p2pKeys) != 1 { + // Get p2p key + fmt.Printf("Fetching P2P key for node %s\n", n.ServiceName) + p2pKeys := api.mustExec(api.methods.ListP2PKeys) + p2pKey := mustJSON[[]presenters.P2PKeyResource](p2pKeys) + if len(*p2pKey) != 1 { helpers.PanicErr(errors.New("node must have single p2p key")) } - peerID := strings.TrimPrefix(p2pKeys[0].PeerID, "p2p_") - output.Reset() + peerID := strings.TrimPrefix((*p2pKey)[0].PeerID, "p2p_") + + // Get OCR2 key bundles for both EVM and Aptos chains + bundles := api.mustExec(api.methods.ListOCR2KeyBundles) + ocr2Bundles := mustJSON[cmd.OCR2KeyBundlePresenters](bundles) + + expectedBundleLen := 1 + + // evm key bundles + fmt.Printf("Fetching OCR2 EVM key bundles for node %s\n", n.ServiceName) + ocr2EvmBundles := getTrimmedEVMOCR2KBs(*ocr2Bundles) + evmBundleLen := len(ocr2EvmBundles) + if evmBundleLen < expectedBundleLen { + fmt.Printf("WARN: node has %d EVM OCR2 bundles when it should have at least %d, creating bundles...\n", evmBundleLen, expectedBundleLen) + for i := evmBundleLen; i < expectedBundleLen; i++ { + cBundle := api.withArg("evm").mustExec(api.methods.CreateOCR2KeyBundle) + createdBundle := mustJSON[cmd.OCR2KeyBundlePresenter](cBundle) + fmt.Printf("Created OCR2 EVM key bundle %s\n", string(cBundle)) + ocr2EvmBundles = append(ocr2EvmBundles, trimmedOCR2KB(*createdBundle)) + } + } - chainType := "evm" + // aptos key bundles + var ocr2AptosBundles []OCR2AptosKBTrimmed + if createAptosKeys { + fmt.Printf("Fetching OCR2 Aptos key bundles for node %s\n", n.ServiceName) + ocr2AptosBundles = createAptosOCR2KB(ocr2Bundles, expectedBundleLen, api) + } - var ocr2Bundles []ocr2Bundle - err = client.ListOCR2KeyBundles(&cli.Context{ - App: app, - }) + fmt.Printf("Fetching CSA keys for node %s\n", n.ServiceName) + csaKeys := api.mustExec(api.methods.ListCSAKeys) + csaKeyResources := mustJSON[[]presenters.CSAKeyResource](csaKeys) + csaPubKey, err := findFirstCSAPublicKey(*csaKeyResources) helpers.PanicErr(err) - helpers.PanicErr(json.Unmarshal(output.Bytes(), &ocr2Bundles)) - ocr2BundleIndex := findOCR2Bundle(ocr2Bundles, chainType) - output.Reset() - if ocr2BundleIndex == -1 { - fmt.Println("WARN: node does not have EVM OCR2 bundle, creating one") - fs := flag.NewFlagSet("test", flag.ContinueOnError) - err = fs.Parse([]string{chainType}) - helpers.PanicErr(err) - ocr2CreateBundleCtx := cli.NewContext(app, fs, nil) - err = client.CreateOCR2KeyBundle(ocr2CreateBundleCtx) - helpers.PanicErr(err) - output.Reset() - - err = client.ListOCR2KeyBundles(&cli.Context{ - App: app, - }) - helpers.PanicErr(err) - helpers.PanicErr(json.Unmarshal(output.Bytes(), &ocr2Bundles)) - ocr2BundleIndex = findOCR2Bundle(ocr2Bundles, chainType) - output.Reset() + + // We can handle multiple OCR bundles in the future + // but for now we only support a single bundle per node + keys := NodeKeys{ + OCR2KBTrimmed: ocr2EvmBundles[0], + EthAddress: ethAddress, + AptosAccount: aptosAccount, + P2PPeerID: peerID, + CSAPublicKey: strings.TrimPrefix(csaPubKey, "csa_"), } + if createAptosKeys { + keys.OCR2AptosKBTrimmed = ocr2AptosBundles[0] + } + + nodeKeys = append(nodeKeys, keys) + } - ocr2Bndl := ocr2Bundles[ocr2BundleIndex] - - aptosBundleIndex := findOCR2Bundle(ocr2Bundles, "aptos") - if aptosBundleIndex == -1 { - chainType2 := "aptos" - fmt.Println("WARN: node does not have Aptos OCR2 bundle, creating one") - fs := flag.NewFlagSet("test", flag.ContinueOnError) - err = fs.Parse([]string{chainType2}) - helpers.PanicErr(err) - ocr2CreateBundleCtx := cli.NewContext(app, fs, nil) - err = client.CreateOCR2KeyBundle(ocr2CreateBundleCtx) - helpers.PanicErr(err) - output.Reset() - - err = client.ListOCR2KeyBundles(&cli.Context{ - App: app, - }) - helpers.PanicErr(err) - helpers.PanicErr(json.Unmarshal(output.Bytes(), &ocr2Bundles)) - aptosBundleIndex = findOCR2Bundle(ocr2Bundles, chainType2) - output.Reset() + return nodeKeys +} + +func trimmedOCR2KB(ocr2Bndl cmd.OCR2KeyBundlePresenter) OCR2KBTrimmed { + return OCR2KBTrimmed{ + OCR2BundleID: ocr2Bndl.ID, + OCR2ConfigPublicKey: strings.TrimPrefix(ocr2Bndl.ConfigPublicKey, "ocr2cfg_evm_"), + OCR2OnchainPublicKey: strings.TrimPrefix(ocr2Bndl.OnchainPublicKey, "ocr2on_evm_"), + OCR2OffchainPublicKey: strings.TrimPrefix(ocr2Bndl.OffChainPublicKey, "ocr2off_evm_"), + } +} + +func trimmedAptosOCR2KB(ocr2Bndl cmd.OCR2KeyBundlePresenter) OCR2AptosKBTrimmed { + return OCR2AptosKBTrimmed{ + AptosBundleID: ocr2Bndl.ID, + AptosOnchainPublicKey: strings.TrimPrefix(ocr2Bndl.OnchainPublicKey, "ocr2on_aptos_"), + } +} + +func createAptosOCR2KB(ocr2Bundles *cmd.OCR2KeyBundlePresenters, expectedBundleLen int, api *nodeAPI) []OCR2AptosKBTrimmed { + ocr2AptosBundles := getTrimmedAptosOCR2KBs(*ocr2Bundles) + aptosBundleLen := len(ocr2AptosBundles) + + if aptosBundleLen < expectedBundleLen { + fmt.Printf("WARN: node has %d Aptos OCR2 bundles when it should have at least %d, creating bundles...\n", aptosBundleLen, expectedBundleLen) + for i := aptosBundleLen; i < expectedBundleLen; i++ { + cBundle := api.withArg("aptos").mustExec(api.methods.CreateOCR2KeyBundle) + createdBundle := mustJSON[cmd.OCR2KeyBundlePresenter](cBundle) + fmt.Println("Created OCR2 Aptos key bundle", string(cBundle)) + ocr2AptosBundles = append(ocr2AptosBundles, trimmedAptosOCR2KB(*createdBundle)) } + } - aptosBundle := ocr2Bundles[aptosBundleIndex] + return ocr2AptosBundles +} - err = client.ListCSAKeys(&cli.Context{ - App: app, - }) +// getOrCreateAptosKey returns the Aptos account of the node. +// +// If the node has no Aptos keys, it creates one and returns the account. +func getOrCreateAptosKey(api *nodeAPI) string { + api.output.Reset() + aKeysClient := cmd.NewAptosKeysClient(api.methods) + err := aKeysClient.ListKeys(&cli.Context{App: api.app}) + helpers.PanicErr(err) + var aptosKeys []presenters.AptosKeyResource + helpers.PanicErr(json.Unmarshal(api.output.Bytes(), &aptosKeys)) + if len(aptosKeys) == 0 { + api.output.Reset() + fmt.Printf("WARN: node has no aptos keys, creating one...\n") + err = aKeysClient.CreateKey(&cli.Context{App: api.app}) helpers.PanicErr(err) - var csaKeys []presenters.CSAKeyResource - helpers.PanicErr(json.Unmarshal(output.Bytes(), &csaKeys)) - csaPubKey, err := findFirstCSAPublicKey(csaKeys) + api.output.Reset() + err = aKeysClient.ListKeys(&cli.Context{App: api.app}) helpers.PanicErr(err) - output.Reset() - - nc := ksdeploy.NodeKeys{ - EthAddress: ethAddress, - AptosAccount: aptosAccount, - P2PPeerID: peerID, - AptosBundleID: aptosBundle.ID, - AptosOnchainPublicKey: strings.TrimPrefix(aptosBundle.OnchainPublicKey, fmt.Sprintf("ocr2on_%s_", "aptos")), - OCR2BundleID: ocr2Bndl.ID, - OCR2ConfigPublicKey: strings.TrimPrefix(ocr2Bndl.ConfigPublicKey, fmt.Sprintf("ocr2cfg_%s_", chainType)), - OCR2OnchainPublicKey: strings.TrimPrefix(ocr2Bndl.OnchainPublicKey, fmt.Sprintf("ocr2on_%s_", chainType)), - OCR2OffchainPublicKey: strings.TrimPrefix(ocr2Bndl.OffchainPublicKey, fmt.Sprintf("ocr2off_%s_", chainType)), - CSAPublicKey: csaPubKey, + helpers.PanicErr(json.Unmarshal(api.output.Bytes(), &aptosKeys)) + api.output.Reset() + } + + if len(aptosKeys) != 1 { + fmt.Printf("Node has %d aptos keys\n", len(aptosKeys)) + PanicErr(errors.New("node must have single aptos key")) + } + + aptosAccount := aptosKeys[0].Account + api.output.Reset() + + return aptosAccount +} + +func getTrimmedAptosOCR2KBs(ocr2Bundles cmd.OCR2KeyBundlePresenters) []OCR2AptosKBTrimmed { + aptosBundles := []OCR2AptosKBTrimmed{} + for _, b := range ocr2Bundles { + if b.ChainType == "aptos" { + aptosBundles = append(aptosBundles, trimmedAptosOCR2KB(b)) } + } + return aptosBundles +} - nca = append(nca, nc) +func getTrimmedEVMOCR2KBs(ocr2Bundles cmd.OCR2KeyBundlePresenters) []OCR2KBTrimmed { + evmBundles := []OCR2KBTrimmed{} + for _, b := range ocr2Bundles { + if b.ChainType == "evm" { + evmBundles = append(evmBundles, trimmedOCR2KB(b)) + } } - return + return evmBundles } func findFirstCSAPublicKey(csaKeyResources []presenters.CSAKeyResource) (string, error) { @@ -234,21 +275,9 @@ func findFirstCSAPublicKey(csaKeyResources []presenters.CSAKeyResource) (string, return "", errors.New("did not find any CSA Key Resources") } -func findOCR2Bundle(ocr2Bundles []ocr2Bundle, chainType string) int { - for i, b := range ocr2Bundles { - if b.ChainType == chainType { - return i - } - } - return -1 -} - func findFirstGoodEthKeyAddress(chainID int64, ethKeys []presenters.ETHKeyResource) (string, error) { for _, ethKey := range ethKeys { if ethKey.EVMChainID.Equal(ubig.NewI(chainID)) && !ethKey.Disabled { - if ethKey.EthBalance.IsZero() { - fmt.Println("WARN: selected ETH address has zero balance", ethKey.Address) - } return ethKey.Address, nil } } diff --git a/core/scripts/keystone/src/99_files.go b/core/scripts/keystone/src/99_files.go index 08ba12e4194..1848ba8fae9 100644 --- a/core/scripts/keystone/src/99_files.go +++ b/core/scripts/keystone/src/99_files.go @@ -1,71 +1,54 @@ package src import ( - "bufio" "encoding/json" "fmt" "io" "os" - - "github.com/smartcontractkit/chainlink/v2/core/utils" ) const ( defaultArtefactsDir = "artefacts" - defaultPublicKeys = ".cache/PublicKeys.json" - defaultNodeList = ".cache/NodeList.txt" + defaultNodeSetsPath = ".cache/node_sets.json" deployedContractsJSON = "deployed_contracts.json" - bootstrapSpecTemplate = "bootstrap.toml" - cribOverrideTemplate = "crib-overrides.yaml" - oracleSpecTemplate = "oracle.toml" ) -func writeLines(lines []string, path string) error { - file, err := os.Create(path) +func mustReadJSON[T any](fileName string) (output T) { + jsonFile, err := os.Open(fileName) if err != nil { - return err - } - wc := utils.NewDeferableWriteCloser(file) - defer wc.Close() - - w := bufio.NewWriter(file) - for _, line := range lines { - fmt.Fprintln(w, line) - } - if err := w.Flush(); err != nil { - return err + panic(fmt.Sprintf("failed to open file at %s: %v", fileName, err)) } - return wc.Close() -} - -func readLines(path string) ([]string, error) { - file, err := os.Open(path) + defer jsonFile.Close() + bytes, err := io.ReadAll(jsonFile) if err != nil { - return nil, err + panic(fmt.Sprintf("failed to read file at %s: %v", fileName, err)) } - defer file.Close() - - var lines []string - scanner := bufio.NewScanner(file) - for scanner.Scan() { - lines = append(lines, scanner.Text()) + err = json.Unmarshal(bytes, &output) + if err != nil { + panic(fmt.Sprintf("failed to unmarshal data: %v", err)) } - return lines, scanner.Err() + return } -func mustParseJSON[T any](fileName string) (output T) { - jsonFile, err := os.Open(fileName) +func mustWriteJSON[T any](fileName string, data T) { + jsonFile, err := os.Create(fileName) if err != nil { - panic(err) + panic(fmt.Sprintf("failed to create file at %s: %v", fileName, err)) } defer jsonFile.Close() - bytes, err := io.ReadAll(jsonFile) + encoder := json.NewEncoder(jsonFile) + encoder.SetIndent("", " ") + err = encoder.Encode(data) if err != nil { - panic(err) + panic(fmt.Sprintf("failed to encode data: %v", err)) } - err = json.Unmarshal(bytes, &output) +} + +func ensureArtefactsDir(artefactsDir string) { + _, err := os.Stat(artefactsDir) if err != nil { - panic(err) + fmt.Println("Creating artefacts directory" + artefactsDir) + err = os.MkdirAll(artefactsDir, 0700) + PanicErr(err) } - return } diff --git a/core/scripts/keystone/src/99_files_test.go b/core/scripts/keystone/src/99_files_test.go deleted file mode 100644 index 83ceb5cd9cc..00000000000 --- a/core/scripts/keystone/src/99_files_test.go +++ /dev/null @@ -1,36 +0,0 @@ -package src - -import ( - "path/filepath" - "strings" - "testing" - - "github.com/stretchr/testify/assert" -) - -func Test_writeLines(t *testing.T) { - type args struct { - lines []string - } - tests := []struct { - name string - args args - }{ - { - name: "write read lines", - args: args{ - lines: []string{"a", "b"}, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - pth := filepath.Join(t.TempDir(), strings.ReplaceAll(tt.name, " ", "_")) - err := writeLines(tt.args.lines, pth) - assert.NoError(t, err) - got, err := readLines(pth) - assert.NoError(t, err) - assert.Equal(t, tt.args.lines, got) - }) - } -} diff --git a/core/scripts/keystone/src/99_k8s_client.go b/core/scripts/keystone/src/99_k8s_client.go index 55a0ac82bcb..e4885e53a19 100644 --- a/core/scripts/keystone/src/99_k8s_client.go +++ b/core/scripts/keystone/src/99_k8s_client.go @@ -2,11 +2,13 @@ package src import ( "context" + "errors" "fmt" "log" "sort" "strings" + apps "k8s.io/api/apps/v1" v1 "k8s.io/api/core/v1" networkingV1 "k8s.io/api/networking/v1" metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -63,32 +65,33 @@ func MustNewK8sClient() *K8sClient { } } -type PodWithConfigMap struct { - v1.Pod - ConfigMap v1.ConfigMap - Host string +type DeploymentWithConfigMap struct { + apps.Deployment + ServiceName string + ConfigMap v1.ConfigMap + Host string } -func (m *K8sClient) GetPodsWithConfigMap() ([]PodWithConfigMap, error) { - pods, err := m.ListPods("app=app") +func (m *K8sClient) GetDeploymentsWithConfigMap() ([]DeploymentWithConfigMap, error) { + deployments, err := m.ListDeployments("app=app") if err != nil { return nil, err } - if len(pods.Items) == 0 { - return nil, fmt.Errorf("no chainlink node crib pods found, is your crib cluster deployed?") + if len(deployments.Items) == 0 { + return nil, errors.New("no deployments found, is your nodeset deployed?") } - podsWithConfigMaps := []PodWithConfigMap{} + deploymentsWithConfigMaps := []DeploymentWithConfigMap{} ingressList, err := m.ListIngresses() if err != nil { return nil, err } if len(ingressList.Items) == 0 { - return nil, fmt.Errorf("no ingress found, is your crib cluster deployed?") + return nil, errors.New("no ingress found, is your nodeset deployed?") } - for _, pod := range pods.Items { - for _, v := range pod.Spec.Volumes { + for _, deployment := range deployments.Items { + for _, v := range deployment.Spec.Template.Spec.Volumes { if v.ConfigMap == nil { continue } @@ -96,53 +99,48 @@ func (m *K8sClient) GetPodsWithConfigMap() ([]PodWithConfigMap, error) { if err != nil { return nil, err } - // - host: crib-henry-keystone-node2.main.stage.cldev.sh - // http: - // paths: - // - backend: - // service: - // name: app-node-2 - // port: - // number: 6688 - // path: /* - // pathType: ImplementationSpecific - instance := pod.Labels["instance"] + instance := deployment.Labels["instance"] var host string + var serviceName string for _, ingress := range ingressList.Items { for _, rule := range ingress.Spec.Rules { for _, path := range rule.HTTP.Paths { if strings.Contains(path.Backend.Service.Name, instance) { host = rule.Host + serviceName = path.Backend.Service.Name } } } } if host == "" { - return nil, fmt.Errorf("could not find host for pod %s", pod.Name) + return nil, fmt.Errorf("could not find host for deployment %s", deployment.Name) } - podWithConfigMap := PodWithConfigMap{ - Host: host, - Pod: pod, - ConfigMap: *cm, + deploymentWithConfigMap := DeploymentWithConfigMap{ + Host: host, + ServiceName: serviceName, + Deployment: deployment, + ConfigMap: *cm, } - podsWithConfigMaps = append(podsWithConfigMaps, podWithConfigMap) + deploymentsWithConfigMaps = append(deploymentsWithConfigMaps, deploymentWithConfigMap) } } - fmt.Printf("Found %d chainlink node crib pods\n", len(podsWithConfigMaps)) - return podsWithConfigMaps, nil + fmt.Printf("Found %d deployments with config maps\n", len(deploymentsWithConfigMaps)) + return deploymentsWithConfigMaps, nil } -// ListPods lists pods for a namespace and selector -func (m *K8sClient) ListPods(selector string) (*v1.PodList, error) { - pods, err := m.ClientSet.CoreV1().Pods(m.namespace).List(context.Background(), metaV1.ListOptions{LabelSelector: selector}) - sort.Slice(pods.Items, func(i, j int) bool { - return pods.Items[i].CreationTimestamp.Before(pods.Items[j].CreationTimestamp.DeepCopy()) +// ListDeployments lists deployments for a namespace +func (m *K8sClient) ListDeployments(selector string) (*apps.DeploymentList, error) { + deployments, err := m.ClientSet.AppsV1().Deployments(m.namespace).List(context.Background(), metaV1.ListOptions{LabelSelector: selector}) + if err != nil { + return nil, err + } + sort.Slice(deployments.Items, func(i, j int) bool { + return deployments.Items[i].CreationTimestamp.Before(deployments.Items[j].CreationTimestamp.DeepCopy()) }) - - return pods.DeepCopy(), err + return deployments.DeepCopy(), nil } // Get a config map diff --git a/core/scripts/keystone/src/99_nodes.go b/core/scripts/keystone/src/99_nodes.go deleted file mode 100644 index 68d3621ce63..00000000000 --- a/core/scripts/keystone/src/99_nodes.go +++ /dev/null @@ -1,72 +0,0 @@ -package src - -import ( - "errors" - "fmt" - "net/url" - "strings" - - helpers "github.com/smartcontractkit/chainlink/core/scripts/common" -) - -type node struct { - url *url.URL - remoteURL *url.URL - login string - password string -} - -func (n node) IsTerminal() bool { - return false -} - -func (n node) PasswordPrompt(p string) string { - return n.password -} - -func (n node) Prompt(p string) string { - return n.login -} - -func writeNodesList(path string, nodes []*node) error { - fmt.Println("Writing nodes list to", path) - var lines []string - for _, n := range nodes { - lines = append(lines, fmt.Sprintf("%s %s %s", n.url.String(), n.login, n.password)) - } - - return writeLines(lines, path) -} - -func mustReadNodesList(path string) []*node { - fmt.Println("Reading nodes list from", path) - nodesList, err := readLines(path) - helpers.PanicErr(err) - - var nodes []*node - var hasBoot bool - for _, r := range nodesList { - rr := strings.TrimSpace(r) - if len(rr) == 0 { - continue - } - s := strings.Split(rr, " ") - if len(s) != 4 { - helpers.PanicErr(errors.New("wrong nodes list format")) - } - if strings.Contains(s[0], "boot") && hasBoot { - helpers.PanicErr(errors.New("the single boot node must come first")) - } - hasBoot = true - url, err := url.Parse(s[0]) - remoteURL, err := url.Parse(s[1]) - helpers.PanicErr(err) - nodes = append(nodes, &node{ - url: url, - remoteURL: remoteURL, - login: s[2], - password: s[3], - }) - } - return nodes -} diff --git a/core/scripts/keystone/src/__snapshots__/02_deploy_keystone_workflows_test.snap b/core/scripts/keystone/src/__snapshots__/02_deploy_keystone_workflows_test.snap new file mode 100755 index 00000000000..8556ca9304c --- /dev/null +++ b/core/scripts/keystone/src/__snapshots__/02_deploy_keystone_workflows_test.snap @@ -0,0 +1,57 @@ + +[TestCreateKeystoneWorkflowJob - 1] + +type = "workflow" +schemaVersion = 1 +name = "keystone_workflow" +workflow = """ +name: "ccip_kiab1" +owner: '0x1234567890abcdef1234567890abcdef12345678' +triggers: + - id: streams-trigger@1.1.0 + config: + maxFrequencyMs: 10000 + feedIds: + - 'feed1' + - 'feed2' + - 'feed3' + +consensus: + - id: offchain_reporting@1.0.0 + ref: ccip_feeds + inputs: + observations: + - $(trigger.outputs) + config: + report_id: '0001' + key_id: 'evm' + aggregation_method: data_feeds + aggregation_config: + feeds: + 'feed1': + deviation: '0.05' + heartbeat: 1800 + 'feed2': + deviation: '0.05' + heartbeat: 1800 + 'feed3': + deviation: '0.05' + heartbeat: 1800 + encoder: EVM + encoder_config: + abi: "(bytes32 FeedID, uint224 Price, uint32 Timestamp)[] Reports" + abi: (bytes32 FeedID, uint224 Price, uint32 Timestamp)[] Reports + +targets: + - id: target_id + inputs: + signed_report: $(ccip_feeds.outputs) + config: + address: '0xabcdefabcdefabcdefabcdefabcdefabcdef' + deltaStage: 5s + schedule: oneAtATime + +""" +workflowOwner = "0x1234567890abcdef1234567890abcdef12345678" + +--- diff --git a/core/scripts/keystone/src/__snapshots__/02_provision_crib_test.snap b/core/scripts/keystone/src/__snapshots__/02_provision_crib_test.snap new file mode 100755 index 00000000000..06532bea727 --- /dev/null +++ b/core/scripts/keystone/src/__snapshots__/02_provision_crib_test.snap @@ -0,0 +1,415 @@ + +[TestGeneratePostprovisionConfig - 1] +helm: + values: + chainlink: + nodes: + 0-ks-wf-bt-node1: + image: ${runtime.images.app} + overridesToml: | + [Capabilities] + [Capabilities.Peering] + [Capabilities.Peering.V2] + Enabled = true + ListenAddresses = ['0.0.0.0:6691'] + + [Capabilities.ExternalRegistry] + Address = '0x0200000000000000000000000000000000000000' + NetworkID = 'evm' + ChainID = '1337' + + [[EVM]] + ChainID = '1337' + Nodes = [] + 0-ks-wf-node2: + image: ${runtime.images.app} + overridesToml: | + [Capabilities] + [Capabilities.Peering] + [Capabilities.Peering.V2] + Enabled = true + DefaultBootstrappers = ['12D3KooWFSmZaLFF1nu3mzxPKj43F89WgVDqkpvwFUHBfMHSqpVq@app-0-ks-wf-bt-node1:6691'] + ListenAddresses = ['0.0.0.0:6691'] + + [Capabilities.ExternalRegistry] + Address = '0x0200000000000000000000000000000000000000' + NetworkID = 'evm' + ChainID = '1337' + + [[EVM]] + ChainID = '1337' + Nodes = [] + + [EVM.Workflow] + FromAddress = '0x75cf1355cC4Eb358feaBb9e269a4DAEeB6721DBB' + ForwarderAddress = '0x0100000000000000000000000000000000000000' + 0-ks-wf-node3: + image: ${runtime.images.app} + overridesToml: | + [Capabilities] + [Capabilities.Peering] + [Capabilities.Peering.V2] + Enabled = true + DefaultBootstrappers = ['12D3KooWFSmZaLFF1nu3mzxPKj43F89WgVDqkpvwFUHBfMHSqpVq@app-0-ks-wf-bt-node1:6691'] + ListenAddresses = ['0.0.0.0:6691'] + + [Capabilities.ExternalRegistry] + Address = '0x0200000000000000000000000000000000000000' + NetworkID = 'evm' + ChainID = '1337' + + [[EVM]] + ChainID = '1337' + Nodes = [] + + [EVM.Workflow] + FromAddress = '0xc6dcE30f492CBD223b9946603192f22D86e783ca' + ForwarderAddress = '0x0100000000000000000000000000000000000000' + 0-ks-wf-node4: + image: ${runtime.images.app} + overridesToml: | + [Capabilities] + [Capabilities.Peering] + [Capabilities.Peering.V2] + Enabled = true + DefaultBootstrappers = ['12D3KooWFSmZaLFF1nu3mzxPKj43F89WgVDqkpvwFUHBfMHSqpVq@app-0-ks-wf-bt-node1:6691'] + ListenAddresses = ['0.0.0.0:6691'] + + [Capabilities.ExternalRegistry] + Address = '0x0200000000000000000000000000000000000000' + NetworkID = 'evm' + ChainID = '1337' + + [[EVM]] + ChainID = '1337' + Nodes = [] + + [EVM.Workflow] + FromAddress = '0x1289d00A6565Afcd6437B09548F6019EF49696d0' + ForwarderAddress = '0x0100000000000000000000000000000000000000' + 0-ks-wf-node5: + image: ${runtime.images.app} + overridesToml: | + [Capabilities] + [Capabilities.Peering] + [Capabilities.Peering.V2] + Enabled = true + DefaultBootstrappers = ['12D3KooWFSmZaLFF1nu3mzxPKj43F89WgVDqkpvwFUHBfMHSqpVq@app-0-ks-wf-bt-node1:6691'] + ListenAddresses = ['0.0.0.0:6691'] + + [Capabilities.ExternalRegistry] + Address = '0x0200000000000000000000000000000000000000' + NetworkID = 'evm' + ChainID = '1337' + + [[EVM]] + ChainID = '1337' + Nodes = [] + + [EVM.Workflow] + FromAddress = '0x4b92B0aaC39932B7302676F48e78FA91852DC0EE' + ForwarderAddress = '0x0100000000000000000000000000000000000000' + 1-ks-str-trig-bt-node1: + image: ${runtime.images.app} + overridesToml: | + [Capabilities] + [Capabilities.Peering] + [Capabilities.Peering.V2] + Enabled = true + DefaultBootstrappers = ['12D3KooWFSmZaLFF1nu3mzxPKj43F89WgVDqkpvwFUHBfMHSqpVq@app-0-ks-wf-bt-node1:6691'] + ListenAddresses = ['0.0.0.0:6691'] + + [Capabilities.ExternalRegistry] + Address = '0x0200000000000000000000000000000000000000' + NetworkID = 'evm' + ChainID = '1337' + + [[EVM]] + ChainID = '1337' + Nodes = [] + 1-ks-str-trig-node2: + image: ${runtime.images.app} + overridesToml: | + [Capabilities] + [Capabilities.Peering] + [Capabilities.Peering.V2] + Enabled = true + DefaultBootstrappers = ['12D3KooWFSmZaLFF1nu3mzxPKj43F89WgVDqkpvwFUHBfMHSqpVq@app-0-ks-wf-bt-node1:6691'] + ListenAddresses = ['0.0.0.0:6691'] + + [Capabilities.ExternalRegistry] + Address = '0x0200000000000000000000000000000000000000' + NetworkID = 'evm' + ChainID = '1337' + + [[EVM]] + ChainID = '1337' + Nodes = [] + 1-ks-str-trig-node3: + image: ${runtime.images.app} + overridesToml: | + [Capabilities] + [Capabilities.Peering] + [Capabilities.Peering.V2] + Enabled = true + DefaultBootstrappers = ['12D3KooWFSmZaLFF1nu3mzxPKj43F89WgVDqkpvwFUHBfMHSqpVq@app-0-ks-wf-bt-node1:6691'] + ListenAddresses = ['0.0.0.0:6691'] + + [Capabilities.ExternalRegistry] + Address = '0x0200000000000000000000000000000000000000' + NetworkID = 'evm' + ChainID = '1337' + + [[EVM]] + ChainID = '1337' + Nodes = [] + 1-ks-str-trig-node4: + image: ${runtime.images.app} + overridesToml: | + [Capabilities] + [Capabilities.Peering] + [Capabilities.Peering.V2] + Enabled = true + DefaultBootstrappers = ['12D3KooWFSmZaLFF1nu3mzxPKj43F89WgVDqkpvwFUHBfMHSqpVq@app-0-ks-wf-bt-node1:6691'] + ListenAddresses = ['0.0.0.0:6691'] + + [Capabilities.ExternalRegistry] + Address = '0x0200000000000000000000000000000000000000' + NetworkID = 'evm' + ChainID = '1337' + + [[EVM]] + ChainID = '1337' + Nodes = [] + 1-ks-str-trig-node5: + image: ${runtime.images.app} + overridesToml: | + [Capabilities] + [Capabilities.Peering] + [Capabilities.Peering.V2] + Enabled = true + DefaultBootstrappers = ['12D3KooWFSmZaLFF1nu3mzxPKj43F89WgVDqkpvwFUHBfMHSqpVq@app-0-ks-wf-bt-node1:6691'] + ListenAddresses = ['0.0.0.0:6691'] + + [Capabilities.ExternalRegistry] + Address = '0x0200000000000000000000000000000000000000' + NetworkID = 'evm' + ChainID = '1337' + + [[EVM]] + ChainID = '1337' + Nodes = [] + ingress: + hosts: + - host: ${DEVSPACE_NAMESPACE}-0-ks-wf-bt-node1.${DEVSPACE_INGRESS_BASE_DOMAIN} + http: + paths: + - path: / + backend: + service: + name: app-0-ks-wf-bt-node1 + port: + number: 6688 + - host: ${DEVSPACE_NAMESPACE}-0-ks-wf-node2.${DEVSPACE_INGRESS_BASE_DOMAIN} + http: + paths: + - path: / + backend: + service: + name: app-0-ks-wf-node2 + port: + number: 6688 + - host: ${DEVSPACE_NAMESPACE}-0-ks-wf-node3.${DEVSPACE_INGRESS_BASE_DOMAIN} + http: + paths: + - path: / + backend: + service: + name: app-0-ks-wf-node3 + port: + number: 6688 + - host: ${DEVSPACE_NAMESPACE}-0-ks-wf-node4.${DEVSPACE_INGRESS_BASE_DOMAIN} + http: + paths: + - path: / + backend: + service: + name: app-0-ks-wf-node4 + port: + number: 6688 + - host: ${DEVSPACE_NAMESPACE}-0-ks-wf-node5.${DEVSPACE_INGRESS_BASE_DOMAIN} + http: + paths: + - path: / + backend: + service: + name: app-0-ks-wf-node5 + port: + number: 6688 + - host: ${DEVSPACE_NAMESPACE}-1-ks-str-trig-bt-node1.${DEVSPACE_INGRESS_BASE_DOMAIN} + http: + paths: + - path: / + backend: + service: + name: app-1-ks-str-trig-bt-node1 + port: + number: 6688 + - host: ${DEVSPACE_NAMESPACE}-1-ks-str-trig-node2.${DEVSPACE_INGRESS_BASE_DOMAIN} + http: + paths: + - path: / + backend: + service: + name: app-1-ks-str-trig-node2 + port: + number: 6688 + - host: ${DEVSPACE_NAMESPACE}-1-ks-str-trig-node3.${DEVSPACE_INGRESS_BASE_DOMAIN} + http: + paths: + - path: / + backend: + service: + name: app-1-ks-str-trig-node3 + port: + number: 6688 + - host: ${DEVSPACE_NAMESPACE}-1-ks-str-trig-node4.${DEVSPACE_INGRESS_BASE_DOMAIN} + http: + paths: + - path: / + backend: + service: + name: app-1-ks-str-trig-node4 + port: + number: 6688 + - host: ${DEVSPACE_NAMESPACE}-1-ks-str-trig-node5.${DEVSPACE_INGRESS_BASE_DOMAIN} + http: + paths: + - path: / + backend: + service: + name: app-1-ks-str-trig-node5 + port: + number: 6688 + +--- + +[TestGeneratePreprovisionConfig - 1] +helm: + values: + chainlink: + nodes: + 0-ks-wf-bt-node1: + image: ${runtime.images.app} + 0-ks-wf-node2: + image: ${runtime.images.app} + 0-ks-wf-node3: + image: ${runtime.images.app} + 0-ks-wf-node4: + image: ${runtime.images.app} + 0-ks-wf-node5: + image: ${runtime.images.app} + 1-ks-str-trig-bt-node1: + image: ${runtime.images.app} + 1-ks-str-trig-node2: + image: ${runtime.images.app} + 1-ks-str-trig-node3: + image: ${runtime.images.app} + 1-ks-str-trig-node4: + image: ${runtime.images.app} + 1-ks-str-trig-node5: + image: ${runtime.images.app} + ingress: + hosts: + - host: ${DEVSPACE_NAMESPACE}-0-ks-wf-bt-node1.${DEVSPACE_INGRESS_BASE_DOMAIN} + http: + paths: + - path: / + backend: + service: + name: app-0-ks-wf-bt-node1 + port: + number: 6688 + - host: ${DEVSPACE_NAMESPACE}-0-ks-wf-node2.${DEVSPACE_INGRESS_BASE_DOMAIN} + http: + paths: + - path: / + backend: + service: + name: app-0-ks-wf-node2 + port: + number: 6688 + - host: ${DEVSPACE_NAMESPACE}-0-ks-wf-node3.${DEVSPACE_INGRESS_BASE_DOMAIN} + http: + paths: + - path: / + backend: + service: + name: app-0-ks-wf-node3 + port: + number: 6688 + - host: ${DEVSPACE_NAMESPACE}-0-ks-wf-node4.${DEVSPACE_INGRESS_BASE_DOMAIN} + http: + paths: + - path: / + backend: + service: + name: app-0-ks-wf-node4 + port: + number: 6688 + - host: ${DEVSPACE_NAMESPACE}-0-ks-wf-node5.${DEVSPACE_INGRESS_BASE_DOMAIN} + http: + paths: + - path: / + backend: + service: + name: app-0-ks-wf-node5 + port: + number: 6688 + - host: ${DEVSPACE_NAMESPACE}-1-ks-str-trig-bt-node1.${DEVSPACE_INGRESS_BASE_DOMAIN} + http: + paths: + - path: / + backend: + service: + name: app-1-ks-str-trig-bt-node1 + port: + number: 6688 + - host: ${DEVSPACE_NAMESPACE}-1-ks-str-trig-node2.${DEVSPACE_INGRESS_BASE_DOMAIN} + http: + paths: + - path: / + backend: + service: + name: app-1-ks-str-trig-node2 + port: + number: 6688 + - host: ${DEVSPACE_NAMESPACE}-1-ks-str-trig-node3.${DEVSPACE_INGRESS_BASE_DOMAIN} + http: + paths: + - path: / + backend: + service: + name: app-1-ks-str-trig-node3 + port: + number: 6688 + - host: ${DEVSPACE_NAMESPACE}-1-ks-str-trig-node4.${DEVSPACE_INGRESS_BASE_DOMAIN} + http: + paths: + - path: / + backend: + service: + name: app-1-ks-str-trig-node4 + port: + number: 6688 + - host: ${DEVSPACE_NAMESPACE}-1-ks-str-trig-node5.${DEVSPACE_INGRESS_BASE_DOMAIN} + http: + paths: + - path: / + backend: + service: + name: app-1-ks-str-trig-node5 + port: + number: 6688 + +--- diff --git a/core/scripts/keystone/src/__snapshots__/02_provision_ocr3_capability_test.snap b/core/scripts/keystone/src/__snapshots__/02_provision_ocr3_capability_test.snap new file mode 100755 index 00000000000..9d38f78899b --- /dev/null +++ b/core/scripts/keystone/src/__snapshots__/02_provision_ocr3_capability_test.snap @@ -0,0 +1,65 @@ + +[TestGenerateOCR3Config - 1] +{ + "F": 1, + "OffchainConfig": "", + "OffchainConfigVersion": 30, + "OnchainConfig": "0x", + "Signers": [ + "011400321bc7af41a634375526006365a31bf32b4cfa7c0520004ca789105da974eec967758ad32b575741d6cb36c1bb3bcfd87b235502cc1753", + "0114005192c43a68efb7a698c0459ff8591a115da128ee052000169008927a60e6c03e99aac6fa268dabaf4d00e117419861d87836211267361b", + "011400ed613636925af2df6ed8332d95028eabcbe95a3f052000ce86b34de67249f92058f69e47961907ebbf8a71c12123f1d2a7cab4874f6365", + "01140053b5bbc0efa2e2d2770029bab5d5a647a260a72b052000f2cb4932d3ce8c10bf67c60d35372a5ff1578255e25c2a119c2dea70e919567a" + ], + "Transmitters": [ + "0x75cf1355cC4Eb358feaBb9e269a4DAEeB6721DBB", + "0xc6dcE30f492CBD223b9946603192f22D86e783ca", + "0x1289d00A6565Afcd6437B09548F6019EF49696d0", + "0x4b92B0aaC39932B7302676F48e78FA91852DC0EE" + ] +} +--- + +[TestGenSpecs - 1] + +type = "bootstrap" +schemaVersion = 1 +name = "ocr3_bootstrap" +contractID = "0xB29934624cAe3765E33115A9530a13f5aEC7fa8A" +relay = "evm" + +[relayConfig] +chainID = "1337" +providerType = "ocr3-capability" + + + +type = "offchainreporting2" +schemaVersion = 1 +name = "ocr3_oracle" +contractID = "0xB29934624cAe3765E33115A9530a13f5aEC7fa8A" +ocrKeyBundleID = "20ccdc97afdf467465590115e3da4e5eb591bf5f43808e81a5d0807cd889b3c7" +p2pv2Bootstrappers = [ + "12D3KooWFSmZaLFF1nu3mzxPKj43F89WgVDqkpvwFUHBfMHSqpVq@app-0-ks-wf-bt-node1:6690", +] +relay = "evm" +pluginType = "plugin" +transmitterID = "12D3KooWHhXyDmHB6D1UQosLXmhczw3zxB3DLYBuq9Unb4iCD4Sc" + +[relayConfig] +chainID = "1337" + +[pluginConfig] +command = "chainlink-ocr3-capability" +ocrVersion = 3 +pluginName = "ocr-capability" +providerType = "ocr3-capability" +telemetryType = "plugin" + +[onchainSigningStrategy] +strategyName = 'multi-chain' +[onchainSigningStrategy.config] +evm = "20ccdc97afdf467465590115e3da4e5eb591bf5f43808e81a5d0807cd889b3c7" +aptos = "ac364cec9fe7d9ea1035fc511e5b2f30900caa6e65ac0501168005d05129e088" + +--- diff --git a/core/scripts/keystone/src/__snapshots__/02_provision_streams_trigger_capability_test.snap b/core/scripts/keystone/src/__snapshots__/02_provision_streams_trigger_capability_test.snap new file mode 100755 index 00000000000..07ac61b7264 --- /dev/null +++ b/core/scripts/keystone/src/__snapshots__/02_provision_streams_trigger_capability_test.snap @@ -0,0 +1,50 @@ + +[TestCreateMercuryV3Job - 1] + +type = "offchainreporting2" +schemaVersion = 1 +name = "mercury-BTC/USD" +p2pv2Bootstrappers = ["crib-henry-keystone-node1.main.stage.cldev.sh"] +forwardingAllowed = false +maxTaskDuration = "1s" +contractID = "0x0700000000000000000000000000000000000000" +feedID = "0x0100000000000000000000000000000000000000000000000000000000000000" +contractConfigTrackerPollInterval = "1s" +ocrKeyBundleID = "ocr_key_bundle_id" +relay = "evm" +pluginType = "mercury" +transmitterID = "node_csa_key" +observationSource = """ + price [type=bridge name="bridge_name" timeout="50ms" requestData=""]; + + benchmark_price [type=jsonparse path="result,mid" index=0]; + price -> benchmark_price; + + bid_price [type=jsonparse path="result,bid" index=1]; + price -> bid_price; + + ask_price [type=jsonparse path="result,ask" index=2]; + price -> ask_price; +""" + +[relayConfig] +enableTriggerCapability = true +chainID = "123456" + +--- + +[TestCreateMercuryBootstrapJob - 1] + +type = "bootstrap" +relay = "evm" +schemaVersion = 1 +name = "boot-BTC/USD" +contractID = "0x0700000000000000000000000000000000000000" +feedID = "0x0100000000000000000000000000000000000000000000000000000000000000" +contractConfigTrackerPollInterval = "1s" + +[relayConfig] +chainID = 123456 +enableTriggerCapability = true + +--- diff --git a/core/scripts/keystone/src/__snapshots__/03_gen_crib_cluster_overrides_cmd_test.snap b/core/scripts/keystone/src/__snapshots__/03_gen_crib_cluster_overrides_cmd_test.snap deleted file mode 100755 index 08b79a9f4f9..00000000000 --- a/core/scripts/keystone/src/__snapshots__/03_gen_crib_cluster_overrides_cmd_test.snap +++ /dev/null @@ -1,44 +0,0 @@ - -[TestGenerateCribConfig - 1] -helm: - values: - chainlink: - nodes: - node1: - image: ${runtime.images.app} - overridesToml: |- - [[EVM]] - ChainID = '11155111' - node2: - image: ${runtime.images.app} - overridesToml: |- - [[EVM]] - ChainID = '11155111' - [EVM.Workflow] - FromAddress = '0x8B60FDcc9CAC8ea476b31d17011CB204471431d9' - ForwarderAddress = '0x1234567890abcdef' - node3: - image: ${runtime.images.app} - overridesToml: |- - [[EVM]] - ChainID = '11155111' - [EVM.Workflow] - FromAddress = '0x6620F516F29979B214e2451498a057FDd3a0A85d' - ForwarderAddress = '0x1234567890abcdef' - node4: - image: ${runtime.images.app} - overridesToml: |- - [[EVM]] - ChainID = '11155111' - [EVM.Workflow] - FromAddress = '0xFeB61E22FCf4F9740c9D96b05199F195bd61A7c2' - ForwarderAddress = '0x1234567890abcdef' - node5: - image: ${runtime.images.app} - overridesToml: |- - [[EVM]] - ChainID = '11155111' - [EVM.Workflow] - FromAddress = '0x882Fd04D78A7e7D386Dd5b550f19479E5494B0B2' - ForwarderAddress = '0x1234567890abcdef' ---- diff --git a/core/scripts/keystone/src/__snapshots__/88_gen_jobspecs_test.snap b/core/scripts/keystone/src/__snapshots__/88_gen_jobspecs_test.snap deleted file mode 100755 index c0c7c7d7e67..00000000000 --- a/core/scripts/keystone/src/__snapshots__/88_gen_jobspecs_test.snap +++ /dev/null @@ -1,140 +0,0 @@ - -[TestGenSpecs - 1] -Bootstrap: -Host: crib-henry-keystone-node1.main.stage.cldev.sh -type = "bootstrap" -schemaVersion = 1 -name = "Keystone boot" -contractID = "0xB29934624cAe3765E33115A9530a13f5aEC7fa8A" -relay = "evm" - -[relayConfig] -chainID = "11155111" -providerType = "ocr3-capability" - -Oracles: -Oracle 0: -Host: crib-henry-keystone-node2.main.stage.cldev.sh -type = "offchainreporting2" -schemaVersion = 1 -name = "Keystone" -contractID = "0xB29934624cAe3765E33115A9530a13f5aEC7fa8A" -ocrKeyBundleID = "b3df4d8748b67731a1112e8b45a764941974f5590c93672eebbc4f3504dd10ed" -p2pv2Bootstrappers = [ - "12D3KooWNmhKZL1XW4Vv3rNjLXzJ6mqcVerihdijjGYuexPrFUFZ@crib-henry-keystone-node1.main.stage.cldev.sh:6690", -] -relay = "evm" -pluginType = "plugin" -transmitterID = "0x8B60FDcc9CAC8ea476b31d17011CB204471431d9" - -[relayConfig] -chainID = "11155111" - -[pluginConfig] -command = "chainlink-ocr3-capability" -ocrVersion = 3 -pluginName = "ocr-capability" -providerType = "ocr3-capability" -telemetryType = "plugin" - -[onchainSigningStrategy] -strategyName = 'multi-chain' -[onchainSigningStrategy.config] -evm = "b3df4d8748b67731a1112e8b45a764941974f5590c93672eebbc4f3504dd10ed" -aptos = "9bebfa953e7a7522746f72b4023308de36db626f3e0bcb9033407b8a183e8bfb" - --------------------------------- -Oracle 1: -Host: crib-henry-keystone-node3.main.stage.cldev.sh -type = "offchainreporting2" -schemaVersion = 1 -name = "Keystone" -contractID = "0xB29934624cAe3765E33115A9530a13f5aEC7fa8A" -ocrKeyBundleID = "38459ae37f29f2c1fde0f25972a973322be8cada82acf43f464756836725be97" -p2pv2Bootstrappers = [ - "12D3KooWNmhKZL1XW4Vv3rNjLXzJ6mqcVerihdijjGYuexPrFUFZ@crib-henry-keystone-node1.main.stage.cldev.sh:6690", -] -relay = "evm" -pluginType = "plugin" -transmitterID = "0x6620F516F29979B214e2451498a057FDd3a0A85d" - -[relayConfig] -chainID = "11155111" - -[pluginConfig] -command = "chainlink-ocr3-capability" -ocrVersion = 3 -pluginName = "ocr-capability" -providerType = "ocr3-capability" -telemetryType = "plugin" - -[onchainSigningStrategy] -strategyName = 'multi-chain' -[onchainSigningStrategy.config] -evm = "38459ae37f29f2c1fde0f25972a973322be8cada82acf43f464756836725be97" -aptos = "9bebfa953e7a7522746f72b4023308de36db626f3e0bcb9033407b8a183e8bfc" - --------------------------------- -Oracle 2: -Host: crib-henry-keystone-node4.main.stage.cldev.sh -type = "offchainreporting2" -schemaVersion = 1 -name = "Keystone" -contractID = "0xB29934624cAe3765E33115A9530a13f5aEC7fa8A" -ocrKeyBundleID = "b5dbc4c9da983cddde2e3226b85807eb7beaf818694a22576af4d80f352702ed" -p2pv2Bootstrappers = [ - "12D3KooWNmhKZL1XW4Vv3rNjLXzJ6mqcVerihdijjGYuexPrFUFZ@crib-henry-keystone-node1.main.stage.cldev.sh:6690", -] -relay = "evm" -pluginType = "plugin" -transmitterID = "0xFeB61E22FCf4F9740c9D96b05199F195bd61A7c2" - -[relayConfig] -chainID = "11155111" - -[pluginConfig] -command = "chainlink-ocr3-capability" -ocrVersion = 3 -pluginName = "ocr-capability" -providerType = "ocr3-capability" -telemetryType = "plugin" - -[onchainSigningStrategy] -strategyName = 'multi-chain' -[onchainSigningStrategy.config] -evm = "b5dbc4c9da983cddde2e3226b85807eb7beaf818694a22576af4d80f352702ed" -aptos = "9bebfa953e7a7522746f72b4023308de36db626f3e0bcb9033407b8a183e8bfd" - --------------------------------- -Oracle 3: -Host: crib-henry-keystone-node5.main.stage.cldev.sh -type = "offchainreporting2" -schemaVersion = 1 -name = "Keystone" -contractID = "0xB29934624cAe3765E33115A9530a13f5aEC7fa8A" -ocrKeyBundleID = "260d5c1a618cdf5324509d7db95f5a117511864ebb9e1f709e8969339eb225af" -p2pv2Bootstrappers = [ - "12D3KooWNmhKZL1XW4Vv3rNjLXzJ6mqcVerihdijjGYuexPrFUFZ@crib-henry-keystone-node1.main.stage.cldev.sh:6690", -] -relay = "evm" -pluginType = "plugin" -transmitterID = "0x882Fd04D78A7e7D386Dd5b550f19479E5494B0B2" - -[relayConfig] -chainID = "11155111" - -[pluginConfig] -command = "chainlink-ocr3-capability" -ocrVersion = 3 -pluginName = "ocr-capability" -providerType = "ocr3-capability" -telemetryType = "plugin" - -[onchainSigningStrategy] -strategyName = 'multi-chain' -[onchainSigningStrategy.config] -evm = "260d5c1a618cdf5324509d7db95f5a117511864ebb9e1f709e8969339eb225af" -aptos = "9bebfa953e7a7522746f72b4023308de36db626f3e0bcb9033407b8a183e8bfe" - - ---- diff --git a/core/scripts/keystone/src/__snapshots__/88_gen_ocr3_config_test.snap b/core/scripts/keystone/src/__snapshots__/88_gen_ocr3_config_test.snap deleted file mode 100755 index eac3cdaff4c..00000000000 --- a/core/scripts/keystone/src/__snapshots__/88_gen_ocr3_config_test.snap +++ /dev/null @@ -1,23 +0,0 @@ - -[TestGenerateOCR3Config - 1] -{ - "F": 1, - "OffchainConfig": "", - "OffchainConfigVersion": 30, - "OnchainConfig": "0x", - "Signers": [ - "011400a2402db8e549f094ea31e1c0edd77623f4ca5b12052000ea551e503b93a1c9ae26262b4db8f66db4cbe5ddcb6039e29d2665a634d48e4a", - "0114004af19c802b244d1d085492c3946391c965e10519052000ea551e503b93a1c9ae26262b4db8f66db4cbe5ddcb6039e29d2665a634d48e4b", - "01140061925685d2b80b121537341d063c4e57b2f9323c052000ea551e503b93a1c9ae26262b4db8f66db4cbe5ddcb6039e29d2665a634d48e4c", - "011400fd97efd53fc20acc098fcd746c04d8d7540d97e0052000ea551e503b93a1c9ae26262b4db8f66db4cbe5ddcb6039e29d2665a634d48e4d", - "011400a0b67dc5345a71d02b396147ae2cb75dda63cbe9052000ea551e503b93a1c9ae26262b4db8f66db4cbe5ddcb6039e29d2665a634d48e4e" - ], - "Transmitters": [ - "0xF4e7e516146c8567F8E8be0ED1f1A92798628d35", - "0x8B60FDcc9CAC8ea476b31d17011CB204471431d9", - "0x6620F516F29979B214e2451498a057FDd3a0A85d", - "0xFeB61E22FCf4F9740c9D96b05199F195bd61A7c2", - "0x882Fd04D78A7e7D386Dd5b550f19479E5494B0B2" - ] -} ---- diff --git a/core/scripts/keystone/src/external-adapter/.goreleaser.yaml b/core/scripts/keystone/src/external-adapter/.goreleaser.yaml new file mode 100644 index 00000000000..524be367e09 --- /dev/null +++ b/core/scripts/keystone/src/external-adapter/.goreleaser.yaml @@ -0,0 +1,49 @@ +project_name: kiab-mock-external-adapter +version: 2 + +builds: + - targets: + - go_first_class + no_unique_dist_dir: true + binary: kiab-mock-external-adapter + env: + - CGO_ENABLED=0 + +dockers: + - id: linux-arm64 + use: buildx + goos: linux + goarch: arm64 + image_templates: + - "{{ .Env.IMAGE }}" + build_flag_templates: + - --platform=linux/arm64 + + - id: linux-amd64 + use: buildx + goos: linux + goarch: amd64 + image_templates: + - "{{ .Env.IMAGE }}" + build_flag_templates: + - --platform=linux/amd64 +docker_manifests: + - name_template: '{{ .Env.IMAGE }}' + image_templates: + - '{{ .Env.IMAGE }}' +archives: + - format: binary + +release: + disable: true +changelog: + disable: true + +nightly: + version_template: "{{ .ProjectName }}-{{ .ShortCommit }}" + +snapshot: + version_template: "{{ .ProjectName }}-{{ .ShortCommit }}" + +partial: + by: target diff --git a/core/scripts/keystone/src/external-adapter/99_external_adapter.go b/core/scripts/keystone/src/external-adapter/99_external_adapter.go new file mode 100644 index 00000000000..8af035f30fd --- /dev/null +++ b/core/scripts/keystone/src/external-adapter/99_external_adapter.go @@ -0,0 +1,154 @@ +package main + +import ( + "fmt" + "math/rand" + "net" + "net/http" + "net/http/httptest" + "os" + "strconv" + "sync" + "time" +) + +func PanicErr(err error) { + if err != nil { + panic(err) + } +} + +// Price struct encapsulates bid, mid, ask values along with a mutex for synchronization +type Price struct { + mu sync.RWMutex + Bid float64 + Mid float64 + Ask float64 +} + +// Update safely updates the price values within the specified bounds +func (p *Price) Update(step, floor, ceiling float64) { + p.mu.Lock() + defer p.mu.Unlock() + + p.Mid = adjustValue(p.Mid, step, floor, ceiling) + p.Bid = adjustValue(p.Mid, step, floor, p.Mid) + p.Ask = adjustValue(p.Mid, step, p.Mid, ceiling) +} + +// GetSnapshot safely retrieves a copy of the current price values +func (p *Price) GetSnapshot() (bid, mid, ask float64) { + p.mu.RLock() + defer p.mu.RUnlock() + return p.Bid, p.Mid, p.Ask +} + +func main() { + // Get initial values from environment variables or use defaults + btcUsdInitialValue := getInitialValue("BTCUSD_INITIAL_VALUE", 1000.0) + linkInitialValue := getInitialValue("LINK_INITIAL_VALUE", 11.0) + nativeInitialValue := getInitialValue("NATIVE_INITIAL_VALUE", 2400.0) + + pctBounds := 0.3 + + // Start external adapters on different ports + externalAdapter(btcUsdInitialValue, "4001", pctBounds) + externalAdapter(linkInitialValue, "4002", pctBounds) + externalAdapter(nativeInitialValue, "4003", pctBounds) + + // Block main goroutine indefinitely + select {} +} + +// getInitialValue retrieves the initial value from the environment or returns a default +func getInitialValue(envVar string, defaultValue float64) float64 { + valueEnv := os.Getenv(envVar) + if valueEnv == "" { + fmt.Printf("%s not set, using default value: %.4f\n", envVar, defaultValue) + return defaultValue + } + fmt.Printf("%s set to %s\n", envVar, valueEnv) + val, err := strconv.ParseFloat(valueEnv, 64) + PanicErr(err) + return val +} + +// externalAdapter sets up a mock external adapter server for a specific asset +func externalAdapter(initialValue float64, port string, pctBounds float64) *httptest.Server { + // Create a custom listener on the specified port + listener, err := net.Listen("tcp", "0.0.0.0:"+port) + if err != nil { + panic(err) + } + + // Initialize the Price struct + price := &Price{ + Bid: initialValue, + Mid: initialValue, + Ask: initialValue, + } + + step := initialValue * pctBounds / 10 + ceiling := initialValue * (1 + pctBounds) + floor := initialValue * (1 - pctBounds) + + // Perform initial adjustment to set bid and ask + price.Update(step, floor, ceiling) + + // Start a goroutine to periodically update the price + go func() { + ticker := time.NewTicker(10 * time.Second) + defer ticker.Stop() + for range ticker.C { + price.Update(step, floor, ceiling) + fmt.Printf("Updated prices on port %s: bid=%.4f, mid=%.4f, ask=%.4f\n", port, price.Bid, price.Mid, price.Ask) + } + }() + + handler := http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + bid, mid, ask := price.GetSnapshot() + + res.Header().Set("Content-Type", "application/json") + res.WriteHeader(http.StatusOK) + resp := fmt.Sprintf(`{"result": {"bid": %.4f, "mid": %.4f, "ask": %.4f}}`, bid, mid, ask) + if _, err := res.Write([]byte(resp)); err != nil { + fmt.Printf("failed to write response: %v\n", err) + } + }) + + // Create and start the test server + ea := &httptest.Server{ + Listener: listener, + Config: &http.Server{ + Handler: handler, + ReadHeaderTimeout: 5 * time.Second, + }, + } + ea.Start() + + fmt.Printf("Mock external adapter started at %s\n", ea.URL) + fmt.Printf("Initial value: %.4f, Floor: %.4f, Ceiling: %.4f\n", initialValue, floor, ceiling) + return ea +} + +// adjustValue takes a starting value and randomly shifts it up or down by a step. +// It ensures that the value stays within the specified bounds. +func adjustValue(start, step, floor, ceiling float64) float64 { + // Randomly choose to increase or decrease the value + // #nosec G404 + if rand.Intn(2) == 0 { + step = -step + } + + // Apply the step to the starting value + newValue := start + step + + // Ensure the value is within the bounds + if newValue < floor { + newValue = floor + } else if newValue > ceiling { + newValue = ceiling + } + + return newValue +} diff --git a/core/scripts/keystone/src/external-adapter/Dockerfile b/core/scripts/keystone/src/external-adapter/Dockerfile new file mode 100644 index 00000000000..714d9397c34 --- /dev/null +++ b/core/scripts/keystone/src/external-adapter/Dockerfile @@ -0,0 +1,5 @@ +FROM scratch + +COPY ./kiab-mock-external-adapter / + +ENTRYPOINT ["/kiab-mock-external-adapter"] diff --git a/core/scripts/keystone/src/generate_local_ocr3_config.go b/core/scripts/keystone/src/generate_local_ocr3_config.go new file mode 100644 index 00000000000..c171c7f097d --- /dev/null +++ b/core/scripts/keystone/src/generate_local_ocr3_config.go @@ -0,0 +1,119 @@ +package src + +import ( + "encoding/json" + "os" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/keystone" + ksdeploy "github.com/smartcontractkit/chainlink/deployment/keystone" +) + +type generateLocalOCR3Config struct{} + +func NewGenerateLocalOCR3ConfigCommand() *generateLocalOCR3Config { + return &generateLocalOCR3Config{} +} + +func (g *generateLocalOCR3Config) Name() string { + return "generate-local-ocr3-config" +} + +func (g *generateLocalOCR3Config) Run(args []string) { + publicKeys := []byte(`[ + { + "EthAddress": "0xF4e7e516146c8567F8E8be0ED1f1A92798628d35", + "P2PPeerID": "12D3KooWNmhKZL1XW4Vv3rNjLXzJ6mqcVerihdijjGYuexPrFUFZ", + "OCR2BundleID": "2f92c96da20fbe39c89e59516e3a7473254523316887394e406527c72071d3db", + "OCR2OnchainPublicKey": "a2402db8e549f094ea31e1c0edd77623f4ca5b12", + "OCR2OffchainPublicKey": "3ca9918cd2787de8f9aff91f220f30a5cc54c394f73e173b12c93368bd7072ad", + "OCR2ConfigPublicKey": "19904debd03994fe9ea411cda7a6b2f01f20a3fe803df0fed67aaf00cc99113f", + "CSAPublicKey": "csa_dbae6965bad0b0fa95ecc34a602eee1c0c570ddc29b56502e400d18574b8c3df" + }, + { + "EthAddress": "0x8B60FDcc9CAC8ea476b31d17011CB204471431d9", + "P2PPeerID": "12D3KooWFUjV73ZYkAMhS2cVwte3kXDWD8Ybyx3u9CEDHNoeEhBH", + "OCR2BundleID": "b3df4d8748b67731a1112e8b45a764941974f5590c93672eebbc4f3504dd10ed", + "OCR2OnchainPublicKey": "4af19c802b244d1d085492c3946391c965e10519", + "OCR2OffchainPublicKey": "365b9e1c3c945fc3f51afb25772f0a5a1f1547935a4b5dc89c012f590709fefe", + "OCR2ConfigPublicKey": "15ff12569d11b8ff9f17f8999ea928d03a439f3fb116661cbc4669a0a3192775", + "CSAPublicKey": "csa_c5cc655a9c19b69626519c4a72c44a94a3675daeba9c16cc23e010a7a6dac1be" + }, + { + "EthAddress": "0x6620F516F29979B214e2451498a057FDd3a0A85d", + "P2PPeerID": "12D3KooWRTtH2WWrztD87Do1kXePSmGjyU4r7mZVWThmqTGgdbUC", + "OCR2BundleID": "38459ae37f29f2c1fde0f25972a973322be8cada82acf43f464756836725be97", + "OCR2OnchainPublicKey": "61925685d2b80b121537341d063c4e57b2f9323c", + "OCR2OffchainPublicKey": "7fe2dbd9f9fb96f7dbbe0410e32d435ad67dae6c91410189fe5664cf3057ef10", + "OCR2ConfigPublicKey": "2f02fd80b362e1c7acf91680fd48c062718233acd595a6ae7cbe434e118e6a4f", + "CSAPublicKey": "csa_7407fc90c70895c0fb2bdf385e2e4918364bec1f7a74bad7fdf696bffafbcab8" + }, + { + "EthAddress": "0xFeB61E22FCf4F9740c9D96b05199F195bd61A7c2", + "P2PPeerID": "12D3KooWMTZnZtcVK4EJsjkKsV9qXNoNRSjT62CZi3tKkXGaCsGh", + "OCR2BundleID": "b5dbc4c9da983cddde2e3226b85807eb7beaf818694a22576af4d80f352702ed", + "OCR2OnchainPublicKey": "fd97efd53fc20acc098fcd746c04d8d7540d97e0", + "OCR2OffchainPublicKey": "91b393bb5e6bd6fd9de23845bcd0e0d9b0dd28a1d65d3cfb1fce9f91bd3d8c19", + "OCR2ConfigPublicKey": "09eb53924ff8b33a08b4eae2f3819015314ce6e8864ac4f86e97caafd4181506", + "CSAPublicKey": "csa_ef55caf17eefc2a9d547b5a3978d396bd237c73af99cd849a4758701122e3cba" + }, + { + "EthAddress": "0x882Fd04D78A7e7D386Dd5b550f19479E5494B0B2", + "P2PPeerID": "12D3KooWRsM9yordRQDhLgbErH8WMMGz1bC1J4hR5gAGvMWu8goN", + "OCR2BundleID": "260d5c1a618cdf5324509d7db95f5a117511864ebb9e1f709e8969339eb225af", + "OCR2OnchainPublicKey": "a0b67dc5345a71d02b396147ae2cb75dda63cbe9", + "OCR2OffchainPublicKey": "4f42ef42e5cc351dbbd79c29ef33af25c0250cac84837c1ff997bc111199d07e", + "OCR2ConfigPublicKey": "3b90249731beb9e4f598371f0b96c3babf47bcc62121ebc9c195e3c33e4fd708", + "CSAPublicKey": "csa_1b874ac2d54b966cec5a8358678ca6f030261aabf3372ce9dbea2d4eb9cdab3d" + }]`) + + var pubKeys []ksdeploy.NodeKeys + err := json.Unmarshal(publicKeys, &pubKeys) + if err != nil { + panic(err) + } + + config := []byte(`{ + "MaxQueryLengthBytes": 1000000, + "MaxObservationLengthBytes": 1000000, + "MaxReportLengthBytes": 1000000, + "MaxRequestBatchSize": 1000, + "UniqueReports": true, + "DeltaProgressMillis": 5000, + "DeltaResendMillis": 5000, + "DeltaInitialMillis": 5000, + "DeltaRoundMillis": 2000, + "DeltaGraceMillis": 500, + "DeltaCertifiedCommitRequestMillis": 1000, + "DeltaStageMillis": 30000, + "MaxRoundsPerEpoch": 10, + "TransmissionSchedule": [4], + "MaxDurationQueryMillis": 1000, + "MaxDurationObservationMillis": 1000, + "MaxDurationReportMillis": 1000, + "MaxDurationAcceptMillis": 1000, + "MaxDurationTransmitMillis": 1000, + "MaxFaultyOracles": 1}`) + var cfg keystone.OracleConfig + err = json.Unmarshal(config, &cfg) + if err != nil { + panic(err) + } + + ocrConfig, err := ksdeploy.GenerateOCR3Config(cfg, pubKeys, deployment.XXXGenerateTestOCRSecrets()) + if err != nil { + panic(err) + } + + // Convert to JSON + jsonData, err := json.MarshalIndent(ocrConfig, "", " ") + if err != nil { + panic(err) + } + + // Generate a json file in `./OCR3Config.json` + err = os.WriteFile("./OCR3LocalConfig.json", jsonData, 0600) + if err != nil { + panic(err) + } +} diff --git a/core/scripts/keystone/src/testdata/NodeList.txt b/core/scripts/keystone/src/testdata/NodeList.txt deleted file mode 100644 index 6fb65dded69..00000000000 --- a/core/scripts/keystone/src/testdata/NodeList.txt +++ /dev/null @@ -1,5 +0,0 @@ -https://local-node1 https://crib-henry-keystone-node1.main.stage.cldev.sh notreal@fakeemail.ch fj293fbBnlQ!f9vNs -https://local-node2 https://crib-henry-keystone-node2.main.stage.cldev.sh notreal@fakeemail.ch fj293fbBnlQ!f9vNs -https://local-node3 https://crib-henry-keystone-node3.main.stage.cldev.sh notreal@fakeemail.ch fj293fbBnlQ!f9vNs -https://local-node4 https://crib-henry-keystone-node4.main.stage.cldev.sh notreal@fakeemail.ch fj293fbBnlQ!f9vNs -https://local-node5 https://crib-henry-keystone-node5.main.stage.cldev.sh notreal@fakeemail.ch fj293fbBnlQ!f9vNs diff --git a/core/scripts/keystone/src/testdata/PublicKeys.json b/core/scripts/keystone/src/testdata/PublicKeys.json deleted file mode 100644 index b29e8290895..00000000000 --- a/core/scripts/keystone/src/testdata/PublicKeys.json +++ /dev/null @@ -1,57 +0,0 @@ -[ - { - "AptosBundleID": "9bebfa953e7a7522746f72b4023308de36db626f3e0bcb9033407b8a183e8bfa", - "AptosOnchainPublicKey": "ea551e503b93a1c9ae26262b4db8f66db4cbe5ddcb6039e29d2665a634d48e4a", - "EthAddress": "0xF4e7e516146c8567F8E8be0ED1f1A92798628d35", - "P2PPeerID": "12D3KooWNmhKZL1XW4Vv3rNjLXzJ6mqcVerihdijjGYuexPrFUFZ", - "OCR2BundleID": "2f92c96da20fbe39c89e59516e3a7473254523316887394e406527c72071d3db", - "OCR2OnchainPublicKey": "a2402db8e549f094ea31e1c0edd77623f4ca5b12", - "OCR2OffchainPublicKey": "3ca9918cd2787de8f9aff91f220f30a5cc54c394f73e173b12c93368bd7072ad", - "OCR2ConfigPublicKey": "19904debd03994fe9ea411cda7a6b2f01f20a3fe803df0fed67aaf00cc99113f", - "CSAPublicKey": "csa_dbae6965bad0b0fa95ecc34a602eee1c0c570ddc29b56502e400d18574b8c3df" - }, - { - "AptosBundleID": "9bebfa953e7a7522746f72b4023308de36db626f3e0bcb9033407b8a183e8bfb", - "AptosOnchainPublicKey": "ea551e503b93a1c9ae26262b4db8f66db4cbe5ddcb6039e29d2665a634d48e4b", - "EthAddress": "0x8B60FDcc9CAC8ea476b31d17011CB204471431d9", - "P2PPeerID": "12D3KooWFUjV73ZYkAMhS2cVwte3kXDWD8Ybyx3u9CEDHNoeEhBH", - "OCR2BundleID": "b3df4d8748b67731a1112e8b45a764941974f5590c93672eebbc4f3504dd10ed", - "OCR2OnchainPublicKey": "4af19c802b244d1d085492c3946391c965e10519", - "OCR2OffchainPublicKey": "365b9e1c3c945fc3f51afb25772f0a5a1f1547935a4b5dc89c012f590709fefe", - "OCR2ConfigPublicKey": "15ff12569d11b8ff9f17f8999ea928d03a439f3fb116661cbc4669a0a3192775", - "CSAPublicKey": "csa_c5cc655a9c19b69626519c4a72c44a94a3675daeba9c16cc23e010a7a6dac1be" - }, - { - "AptosBundleID": "9bebfa953e7a7522746f72b4023308de36db626f3e0bcb9033407b8a183e8bfc", - "AptosOnchainPublicKey": "ea551e503b93a1c9ae26262b4db8f66db4cbe5ddcb6039e29d2665a634d48e4c", - "EthAddress": "0x6620F516F29979B214e2451498a057FDd3a0A85d", - "P2PPeerID": "12D3KooWRTtH2WWrztD87Do1kXePSmGjyU4r7mZVWThmqTGgdbUC", - "OCR2BundleID": "38459ae37f29f2c1fde0f25972a973322be8cada82acf43f464756836725be97", - "OCR2OnchainPublicKey": "61925685d2b80b121537341d063c4e57b2f9323c", - "OCR2OffchainPublicKey": "7fe2dbd9f9fb96f7dbbe0410e32d435ad67dae6c91410189fe5664cf3057ef10", - "OCR2ConfigPublicKey": "2f02fd80b362e1c7acf91680fd48c062718233acd595a6ae7cbe434e118e6a4f", - "CSAPublicKey": "csa_7407fc90c70895c0fb2bdf385e2e4918364bec1f7a74bad7fdf696bffafbcab8" - }, - { - "AptosBundleID": "9bebfa953e7a7522746f72b4023308de36db626f3e0bcb9033407b8a183e8bfd", - "AptosOnchainPublicKey": "ea551e503b93a1c9ae26262b4db8f66db4cbe5ddcb6039e29d2665a634d48e4d", - "EthAddress": "0xFeB61E22FCf4F9740c9D96b05199F195bd61A7c2", - "P2PPeerID": "12D3KooWMTZnZtcVK4EJsjkKsV9qXNoNRSjT62CZi3tKkXGaCsGh", - "OCR2BundleID": "b5dbc4c9da983cddde2e3226b85807eb7beaf818694a22576af4d80f352702ed", - "OCR2OnchainPublicKey": "fd97efd53fc20acc098fcd746c04d8d7540d97e0", - "OCR2OffchainPublicKey": "91b393bb5e6bd6fd9de23845bcd0e0d9b0dd28a1d65d3cfb1fce9f91bd3d8c19", - "OCR2ConfigPublicKey": "09eb53924ff8b33a08b4eae2f3819015314ce6e8864ac4f86e97caafd4181506", - "CSAPublicKey": "csa_ef55caf17eefc2a9d547b5a3978d396bd237c73af99cd849a4758701122e3cba" - }, - { - "AptosBundleID": "9bebfa953e7a7522746f72b4023308de36db626f3e0bcb9033407b8a183e8bfe", - "AptosOnchainPublicKey": "ea551e503b93a1c9ae26262b4db8f66db4cbe5ddcb6039e29d2665a634d48e4e", - "EthAddress": "0x882Fd04D78A7e7D386Dd5b550f19479E5494B0B2", - "P2PPeerID": "12D3KooWRsM9yordRQDhLgbErH8WMMGz1bC1J4hR5gAGvMWu8goN", - "OCR2BundleID": "260d5c1a618cdf5324509d7db95f5a117511864ebb9e1f709e8969339eb225af", - "OCR2OnchainPublicKey": "a0b67dc5345a71d02b396147ae2cb75dda63cbe9", - "OCR2OffchainPublicKey": "4f42ef42e5cc351dbbd79c29ef33af25c0250cac84837c1ff997bc111199d07e", - "OCR2ConfigPublicKey": "3b90249731beb9e4f598371f0b96c3babf47bcc62121ebc9c195e3c33e4fd708", - "CSAPublicKey": "csa_1b874ac2d54b966cec5a8358678ca6f030261aabf3372ce9dbea2d4eb9cdab3d" - } -] \ No newline at end of file diff --git a/core/scripts/keystone/src/testdata/node_sets.json b/core/scripts/keystone/src/testdata/node_sets.json new file mode 100644 index 00000000000..b5502a0ed53 --- /dev/null +++ b/core/scripts/keystone/src/testdata/node_sets.json @@ -0,0 +1,298 @@ +{ + "Workflow": { + "Name": "workflow", + "Prefix": "ks-wf-", + "Nodes": [ + { + "URL": { + "scheme": "https", + "host": "crib-local-0-ks-wf-bt-node1.local", + "path": "" + }, + "RemoteURL": { + "scheme": "https", + "host": "crib-local-0-ks-wf-bt-node1.local", + "path": "" + }, + "ServiceName": "app-0-ks-wf-bt-node1", + "APILogin": "notreal@fakeemail.ch", + "APIPassword": "fj293fbBnlQ!f9vNs", + "KeystorePassword": "T.tLHkcmwePT/p,]sYuntjwHKAsrhm#4eRs4LuKHwvHejWYAC2JP4M8HimwgmbaZ" + }, + { + "URL": { + "scheme": "https", + "host": "crib-local-0-ks-wf-node2.local", + "path": "" + }, + "RemoteURL": { + "scheme": "https", + "host": "crib-local-0-ks-wf-node2.local", + "path": "" + }, + "ServiceName": "app-0-ks-wf-node2", + "APILogin": "notreal@fakeemail.ch", + "APIPassword": "fj293fbBnlQ!f9vNs", + "KeystorePassword": "T.tLHkcmwePT/p,]sYuntjwHKAsrhm#4eRs4LuKHwvHejWYAC2JP4M8HimwgmbaZ" + }, + { + "URL": { + "scheme": "https", + "host": "crib-local-0-ks-wf-node3.local", + "path": "" + }, + "RemoteURL": { + "scheme": "https", + "host": "crib-local-0-ks-wf-node3.local", + "path": "" + }, + "ServiceName": "app-0-ks-wf-node3", + "APILogin": "notreal@fakeemail.ch", + "APIPassword": "fj293fbBnlQ!f9vNs", + "KeystorePassword": "T.tLHkcmwePT/p,]sYuntjwHKAsrhm#4eRs4LuKHwvHejWYAC2JP4M8HimwgmbaZ" + }, + { + "URL": { + "scheme": "https", + "host": "crib-local-0-ks-wf-node4.local", + "path": "" + }, + "RemoteURL": { + "scheme": "https", + "host": "crib-local-0-ks-wf-node4.local", + "path": "" + }, + "ServiceName": "app-0-ks-wf-node4", + "APILogin": "notreal@fakeemail.ch", + "APIPassword": "fj293fbBnlQ!f9vNs", + "KeystorePassword": "T.tLHkcmwePT/p,]sYuntjwHKAsrhm#4eRs4LuKHwvHejWYAC2JP4M8HimwgmbaZ" + }, + { + "URL": { + "scheme": "https", + "host": "crib-local-0-ks-wf-node5.local", + "path": "" + }, + "RemoteURL": { + "scheme": "https", + "host": "crib-local-0-ks-wf-node5.local", + "path": "" + }, + "ServiceName": "app-0-ks-wf-node5", + "APILogin": "notreal@fakeemail.ch", + "APIPassword": "fj293fbBnlQ!f9vNs", + "KeystorePassword": "T.tLHkcmwePT/p,]sYuntjwHKAsrhm#4eRs4LuKHwvHejWYAC2JP4M8HimwgmbaZ" + } + ], + "NodeKeys": [ + { + "AptosAccount": "38476e214b5c60e642019b38db9f06ce6c5a9bcb987d2bfbbbe750195aa7e964", + "EthAddress": "0x568C859E34F210a23847acE0D4960dB74f359dC4", + "P2PPeerID": "12D3KooWFSmZaLFF1nu3mzxPKj43F89WgVDqkpvwFUHBfMHSqpVq", + "CSAPublicKey": "981d781740ff79bb181a4c70390bd54e936f2d9211f5b20c708205b481a8efcc", + "OCR2BundleID": "782e4d14d0f53071ab7a45b9085eb99beed3350e7ab72d5edd4429169e5c87ef", + "OCR2OnchainPublicKey": "357ddc6c0fc6510ec67edbb9a63819dcb47f1506", + "OCR2OffchainPublicKey": "822488a7e4583eed41e5ab142dd6be721c2cc0f217ceee0912ff2db2a24e404c", + "OCR2ConfigPublicKey": "c92ae7ff9b1cef97bb875917456bc6b83df5f5a76ad00c914869c7068748f31a", + "AptosBundleID": "d4acd2c80860fd1e49363f08426e7e5efa7fcd57356a8aba408732e975d3e9a6", + "AptosOnchainPublicKey": "48b37d91fd2c2c784759021d421e7e6f98078b4343cf8cab378394aa357a49a2" + }, + { + "AptosAccount": "bd4d7e53622621af04a0100db7720508c41f3dd5fe9e97dd57eb9673d82a385d", + "EthAddress": "0x75cf1355cC4Eb358feaBb9e269a4DAEeB6721DBB", + "P2PPeerID": "12D3KooWHhXyDmHB6D1UQosLXmhczw3zxB3DLYBuq9Unb4iCD4Sc", + "CSAPublicKey": "6a4723752c843c8d91e542af5373b3d123eca05b570a6e910f5d2f28737a26f6", + "OCR2BundleID": "20ccdc97afdf467465590115e3da4e5eb591bf5f43808e81a5d0807cd889b3c7", + "OCR2OnchainPublicKey": "321bc7af41a634375526006365a31bf32b4cfa7c", + "OCR2OffchainPublicKey": "a2b7f0b85be445e2c7317bdff74c41acd9c67b5a35cda94ae31da8a9ef886db2", + "OCR2ConfigPublicKey": "faa4cfefb226ae8e86480e019bd5bbd6405c26e22dcea40d2c6f01e583213e21", + "AptosBundleID": "ac364cec9fe7d9ea1035fc511e5b2f30900caa6e65ac0501168005d05129e088", + "AptosOnchainPublicKey": "4ca789105da974eec967758ad32b575741d6cb36c1bb3bcfd87b235502cc1753" + }, + { + "AptosAccount": "9543634f4a73e4cfb284816b32d7ec6b7ac8d07b841f2c1f714750186cc28a5a", + "EthAddress": "0xc6dcE30f492CBD223b9946603192f22D86e783ca", + "P2PPeerID": "12D3KooWEWK8e627u6S5NuwXTgGLakGpn1vzQjyjp6Regu1pcpFC", + "CSAPublicKey": "a715467dd87ea210d685b82a32f30c781031df00c2c974dc5fad9159a7ba240c", + "OCR2BundleID": "c734a4bf01aabe8152b7d0df0b18111ce9b3fe1ef1bca1d6a580967c8e4afc2d", + "OCR2OnchainPublicKey": "5192c43a68efb7a698c0459ff8591a115da128ee", + "OCR2OffchainPublicKey": "5e68d07f82ea0bf7054560775c2919bc955dd7fa73b2a36391a4dc27cbb18fdb", + "OCR2ConfigPublicKey": "ebd66285a029f443277091bc4b191b13e21a9b806ce379584411277a265c8e5c", + "AptosBundleID": "f1dfc3d44ee349b4349f33ce4c0ec3716142e9be3ae3ba9276c616556f6430bb", + "AptosOnchainPublicKey": "169008927a60e6c03e99aac6fa268dabaf4d00e117419861d87836211267361b" + }, + { + "AptosAccount": "bcd6fdce3fdcd060fed58fe13be522dc3fb0cff138b0f4f4460392f5e6d88728", + "EthAddress": "0x1289d00A6565Afcd6437B09548F6019EF49696d0", + "P2PPeerID": "12D3KooW9uJ981ocDxTJrPVxMEzPcS14WTJSU1YWH5otcpZSqkUd", + "CSAPublicKey": "9db8641f2067bfdf476e375060a0bd97c21da46d9f54c6ff4f990c6aef882478", + "OCR2BundleID": "129377e1aea4f628b2a3274e528a131175ace13e7cc062b048a34f5b4cf7b512", + "OCR2OnchainPublicKey": "ed613636925af2df6ed8332d95028eabcbe95a3f", + "OCR2OffchainPublicKey": "4eb3e2f1d324804d0adf5169bc187425d3e665c29cddf13bd57ec40ee207ce75", + "OCR2ConfigPublicKey": "effd7d3535e1b6596068085b3e19f9577a536aeacbdeea318cbd870ec678334d", + "AptosBundleID": "2e39d555ec0d1e8795167d72d2a53faa5c537762c144f8a569c601f6bcc95d1d", + "AptosOnchainPublicKey": "ce86b34de67249f92058f69e47961907ebbf8a71c12123f1d2a7cab4874f6365" + }, + { + "AptosAccount": "6549063d427778024fc4230154753c1a30eac88a7a8eab1d36014a3db48c39b3", + "EthAddress": "0x4b92B0aaC39932B7302676F48e78FA91852DC0EE", + "P2PPeerID": "12D3KooWJJC2KgoP1oih7cky9B1wL12d5CBqWFKpdfQgfujmHGyz", + "CSAPublicKey": "8c8b473cc37664a21d548477cd268013256d1d70cd9a137bdfd99da7612a93e0", + "OCR2BundleID": "053f21bfd2bbdb65261308af2d0be48593229d644d8b9e3e5dbe36f85399ae6c", + "OCR2OnchainPublicKey": "53b5bbc0efa2e2d2770029bab5d5a647a260a72b", + "OCR2OffchainPublicKey": "eac02c66802acd9cd998b9b45c52b5b36837bfb829b2838cade040e0155c774a", + "OCR2ConfigPublicKey": "43b9d0c7cace05fd17426dad4386857025a71eb08205690dff5f76224e9c7f5c", + "AptosBundleID": "3de7ab03a5b6b7fcfd196c6101d9302c5e6a5221ebd82b1fd9afa9a6bc9b0445", + "AptosOnchainPublicKey": "f2cb4932d3ce8c10bf67c60d35372a5ff1578255e25c2a119c2dea70e919567a" + } + ] + }, + "StreamsTrigger": { + "Name": "streams-trigger", + "Prefix": "ks-str-trig-", + "Nodes": [ + { + "URL": { + "scheme": "https", + "host": "crib-local-1-ks-str-trig-bt-node1.local", + "path": "" + }, + "RemoteURL": { + "scheme": "https", + "host": "crib-local-1-ks-str-trig-bt-node1.local", + "path": "" + }, + "ServiceName": "app-1-ks-str-trig-bt-node1", + "APILogin": "notreal@fakeemail.ch", + "APIPassword": "fj293fbBnlQ!f9vNs", + "KeystorePassword": "T.tLHkcmwePT/p,]sYuntjwHKAsrhm#4eRs4LuKHwvHejWYAC2JP4M8HimwgmbaZ" + }, + { + "URL": { + "scheme": "https", + "host": "crib-local-1-ks-str-trig-node2.local", + "path": "" + }, + "RemoteURL": { + "scheme": "https", + "host": "crib-local-1-ks-str-trig-node2.local", + "path": "" + }, + "ServiceName": "app-1-ks-str-trig-node2", + "APILogin": "notreal@fakeemail.ch", + "APIPassword": "fj293fbBnlQ!f9vNs", + "KeystorePassword": "T.tLHkcmwePT/p,]sYuntjwHKAsrhm#4eRs4LuKHwvHejWYAC2JP4M8HimwgmbaZ" + }, + { + "URL": { + "scheme": "https", + "host": "crib-local-1-ks-str-trig-node3.local", + "path": "" + }, + "RemoteURL": { + "scheme": "https", + "host": "crib-local-1-ks-str-trig-node3.local", + "path": "" + }, + "ServiceName": "app-1-ks-str-trig-node3", + "APILogin": "notreal@fakeemail.ch", + "APIPassword": "fj293fbBnlQ!f9vNs", + "KeystorePassword": "T.tLHkcmwePT/p,]sYuntjwHKAsrhm#4eRs4LuKHwvHejWYAC2JP4M8HimwgmbaZ" + }, + { + "URL": { + "scheme": "https", + "host": "crib-local-1-ks-str-trig-node4.local", + "path": "" + }, + "RemoteURL": { + "scheme": "https", + "host": "crib-local-1-ks-str-trig-node4.local", + "path": "" + }, + "ServiceName": "app-1-ks-str-trig-node4", + "APILogin": "notreal@fakeemail.ch", + "APIPassword": "fj293fbBnlQ!f9vNs", + "KeystorePassword": "T.tLHkcmwePT/p,]sYuntjwHKAsrhm#4eRs4LuKHwvHejWYAC2JP4M8HimwgmbaZ" + }, + { + "URL": { + "scheme": "https", + "host": "crib-local-1-ks-str-trig-node5.local", + "path": "" + }, + "RemoteURL": { + "scheme": "https", + "host": "crib-local-1-ks-str-trig-node5.local", + "path": "" + }, + "ServiceName": "app-1-ks-str-trig-node5", + "APILogin": "notreal@fakeemail.ch", + "APIPassword": "fj293fbBnlQ!f9vNs", + "KeystorePassword": "T.tLHkcmwePT/p,]sYuntjwHKAsrhm#4eRs4LuKHwvHejWYAC2JP4M8HimwgmbaZ" + } + ], + "NodeKeys": [ + { + "AptosAccount": "", + "EthAddress": "0xCE59C33dc0807F194ba2566e093398dc5e459840", + "P2PPeerID": "12D3KooWGQkR76gPL7Qt1aYYHtPdU65zG4h36efLAERMwudHqGK3", + "CSAPublicKey": "b3dcb60fcf807453c95628a1e7970b077b5e2bbefb0b159841c28dc1776574de", + "OCR2BundleID": "ca2e13222b556f34ae5bc9cea72e6e7ce8221bf76e2d8b3d91505facdbbd71d3", + "OCR2OnchainPublicKey": "a4938b0552e830b45d481cca9893f319259d365c", + "OCR2OffchainPublicKey": "221fe1f972f01da727dbd6842daf4d322f7cab5a7e93816688be7a52f4088b86", + "OCR2ConfigPublicKey": "1af18519dfc5a22db640f1f8095bafaaeb987ab4e3e7ec366dfaa92df9a6ee7b", + "AptosBundleID": "", + "AptosOnchainPublicKey": "" + }, + { + "AptosAccount": "", + "EthAddress": "0x898D0206d3b3156b92bD499eDFBAfc476543A21F", + "P2PPeerID": "12D3KooWDN2jTmtrpZMpjFFuQdzxHyUecBE3zPLG4goaWG7H2iDa", + "CSAPublicKey": "bdf13ff3944d59a3e1ea5888f86c0bbfe5eb33e2140188516592bf245d080320", + "OCR2BundleID": "3b5d75124ef0f02efd46c08da4b67d36154eed680d7dafd360d976430fe11a7b", + "OCR2OnchainPublicKey": "3815f48818db64aa8d7b225e229a328826f3d1de", + "OCR2OffchainPublicKey": "ca6f4c20c00fb7af411060cfc226d61d11ce5e3532ebbd15786fe53c32244de3", + "OCR2ConfigPublicKey": "7b4e462c24d9076a8822bd4e2bdbd834fcc7898aabd9862dbcdb7df6686d2b41", + "AptosBundleID": "", + "AptosOnchainPublicKey": "" + }, + { + "AptosAccount": "", + "EthAddress": "0xb26dD9CD1Fc4Df2F84170960E2a36ed4a5ac6bB7", + "P2PPeerID": "12D3KooWJTedkdgDmkAms4pEKDnXX7CXshkxwEcK6hWki519YEqF", + "CSAPublicKey": "e95ded4fc733eac43292dc24d8630101cf0c3f40c3764233a6321077eacd0b90", + "OCR2BundleID": "742b2a8a90e59aeb8bb35313d4078ef3f950a9e42a157b7ee9e9abd8c7d97d94", + "OCR2OnchainPublicKey": "57b41043e9a2b21329be48ccf72943af20b322ff", + "OCR2OffchainPublicKey": "0d90fc04c4c0439c184a06478ec1fed7cedfb799b303a6d68c046d90f077b5bd", + "OCR2ConfigPublicKey": "a73c070b60c9a175ac34cfd5c6c7884e73b5c8d43417be3f00bc43ac0fb67f39", + "AptosBundleID": "", + "AptosOnchainPublicKey": "" + }, + { + "AptosAccount": "", + "EthAddress": "0x50b1bB407F0Ecd71416BfA8a1d703F6115112676", + "P2PPeerID": "12D3KooWS1i3x2r34vYCfYrz2ddWUVYtFGNaZvGNNxqzL4Rysd3V", + "CSAPublicKey": "46b50be4d72b03f1601ade056bc754f194d6418283065970d470f6f3243f0705", + "OCR2BundleID": "1232eb7cdb4145ec8b543b76f17fe59c69aa6df31c827a7553aea3a3d340c637", + "OCR2OnchainPublicKey": "dad1e5d6824d7b64df57e9ca3342e4caf66b2c91", + "OCR2OffchainPublicKey": "8a7e9833bf8a55435c82866dbe5f9a9bac63b9a93c8c55664dffe653ab4145a2", + "OCR2ConfigPublicKey": "48ce76ee5ddd8003ebbd10485a092f8bd237f0f855aca8aba5ccac78b593e62d", + "AptosBundleID": "", + "AptosOnchainPublicKey": "" + }, + { + "AptosAccount": "", + "EthAddress": "0xa2340108BE2c563bB89462b464aCF3f88cCd1584", + "P2PPeerID": "12D3KooWLZFWAhTejyR7WwwQndgNGGiW3XcGKK6nNtWbhdgCG1rC", + "CSAPublicKey": "0837cd5a8544664eaf04f68347bdba4cb7ac6af34488f0a26c65b03fe223d5af", + "OCR2BundleID": "2fcbac5dd48e995772d85c47d2744b0df7b74b71d17001f283318cae43b96add", + "OCR2OnchainPublicKey": "469d3c0c484c6846be1176920f1cbdc8abb6f638", + "OCR2OffchainPublicKey": "21aa97506b74e3bfcbe6eb87f2a6add07898fecbddbcec2447832dc343395499", + "OCR2ConfigPublicKey": "a6b7e8ca4faf6122165928d82354de3f9334cdb47af058f6a983d11473c21b5f", + "AptosBundleID": "", + "AptosOnchainPublicKey": "" + } + ] + } +} diff --git a/core/scripts/keystone/templates/bootstrap.toml b/core/scripts/keystone/templates/bootstrap.toml deleted file mode 100644 index cdd9065caba..00000000000 --- a/core/scripts/keystone/templates/bootstrap.toml +++ /dev/null @@ -1,9 +0,0 @@ -type = "bootstrap" -schemaVersion = 1 -name = "Keystone boot" -contractID = "{{ ocr_config_contract_address }}" -relay = "evm" - -[relayConfig] -chainID = "{{ chain_id }}" -providerType = "ocr3-capability" diff --git a/core/scripts/keystone/templates/crib-overrides.yaml b/core/scripts/keystone/templates/crib-overrides.yaml deleted file mode 100644 index baeaa5fa1d9..00000000000 --- a/core/scripts/keystone/templates/crib-overrides.yaml +++ /dev/null @@ -1,41 +0,0 @@ -helm: - values: - chainlink: - nodes: - node1: - image: ${runtime.images.app} - overridesToml: |- - [[EVM]] - ChainID = '11155111' - node2: - image: ${runtime.images.app} - overridesToml: |- - [[EVM]] - ChainID = '11155111' - [EVM.Workflow] - FromAddress = '{{ node_2_address }}' - ForwarderAddress = '{{ forwarder_address }}' - node3: - image: ${runtime.images.app} - overridesToml: |- - [[EVM]] - ChainID = '11155111' - [EVM.Workflow] - FromAddress = '{{ node_3_address }}' - ForwarderAddress = '{{ forwarder_address }}' - node4: - image: ${runtime.images.app} - overridesToml: |- - [[EVM]] - ChainID = '11155111' - [EVM.Workflow] - FromAddress = '{{ node_4_address }}' - ForwarderAddress = '{{ forwarder_address }}' - node5: - image: ${runtime.images.app} - overridesToml: |- - [[EVM]] - ChainID = '11155111' - [EVM.Workflow] - FromAddress = '{{ node_5_address }}' - ForwarderAddress = '{{ forwarder_address }}' diff --git a/core/scripts/keystone/templates/oracle.toml b/core/scripts/keystone/templates/oracle.toml deleted file mode 100644 index 053baa2223b..00000000000 --- a/core/scripts/keystone/templates/oracle.toml +++ /dev/null @@ -1,27 +0,0 @@ -type = "offchainreporting2" -schemaVersion = 1 -name = "Keystone" -contractID = "{{ ocr_config_contract_address }}" -ocrKeyBundleID = "{{ ocr_key_bundle_id }}" -p2pv2Bootstrappers = [ - "{{ bootstrapper_p2p_id }}", -] -relay = "evm" -pluginType = "plugin" -transmitterID = "{{ transmitter_id }}" - -[relayConfig] -chainID = "{{ chain_id }}" - -[pluginConfig] -command = "chainlink-ocr3-capability" -ocrVersion = 3 -pluginName = "ocr-capability" -providerType = "ocr3-capability" -telemetryType = "plugin" - -[onchainSigningStrategy] -strategyName = 'multi-chain' -[onchainSigningStrategy.config] -evm = "{{ ocr_key_bundle_id }}" -aptos = "{{ aptos_key_bundle_id }}" diff --git a/core/services/blockhashstore/mocks/bhs.go b/core/services/blockhashstore/mocks/bhs.go index 782b22e05f8..d3032c4bb0d 100644 --- a/core/services/blockhashstore/mocks/bhs.go +++ b/core/services/blockhashstore/mocks/bhs.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -80,7 +80,7 @@ func (_c *BHS_IsStored_Call) RunAndReturn(run func(context.Context, uint64) (boo return _c } -// IsTrusted provides a mock function with given fields: +// IsTrusted provides a mock function with no fields func (_m *BHS) IsTrusted() bool { ret := _m.Called() diff --git a/core/services/blockhashstore/mocks/timer.go b/core/services/blockhashstore/mocks/timer.go index 1fe06d98092..e6fa10fbd07 100644 --- a/core/services/blockhashstore/mocks/timer.go +++ b/core/services/blockhashstore/mocks/timer.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/ccip/mocks/orm.go b/core/services/ccip/mocks/orm.go index 8353cc0f28c..30c365b24f1 100644 --- a/core/services/ccip/mocks/orm.go +++ b/core/services/ccip/mocks/orm.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go index d8b9777cb5a..50921cc93cc 100644 --- a/core/services/chainlink/application.go +++ b/core/services/chainlink/application.go @@ -7,6 +7,7 @@ import ( "math/big" "net/http" "sync" + "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -20,10 +21,12 @@ import ( "go.uber.org/multierr" "go.uber.org/zap/zapcore" + "github.com/smartcontractkit/chainlink-common/pkg/beholder" "github.com/smartcontractkit/chainlink-common/pkg/custmsg" "github.com/smartcontractkit/chainlink-common/pkg/loop" commonservices "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" + "github.com/smartcontractkit/chainlink-common/pkg/timeutil" "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink-common/pkg/utils/jsonserializable" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" @@ -80,6 +83,8 @@ import ( "github.com/smartcontractkit/chainlink/v2/plugins" ) +const HeartbeatPeriod = time.Second + // Application implements the common functions used in the core node. type Application interface { Start(ctx context.Context) error @@ -192,6 +197,60 @@ type ApplicationOpts struct { NewOracleFactoryFn standardcapabilities.NewOracleFactoryFn } +type Heartbeat struct { + commonservices.Service + eng *commonservices.Engine + + beat time.Duration +} + +func NewHeartbeat(lggr logger.Logger) Heartbeat { + h := Heartbeat{ + beat: HeartbeatPeriod, + } + h.Service, h.eng = commonservices.Config{ + Name: "Heartbeat", + Start: h.start, + }.NewServiceEngine(lggr) + return h +} + +func (h *Heartbeat) start(_ context.Context) error { + // Setup beholder resources + gauge, err := beholder.GetMeter().Int64Gauge("heartbeat") + if err != nil { + return err + } + count, err := beholder.GetMeter().Int64Gauge("heartbeat_count") + if err != nil { + return err + } + + cme := custmsg.NewLabeler() + + // Define tick functions + beatFn := func(ctx context.Context) { + // TODO allow override of tracer provider into engine for beholder + _, innerSpan := beholder.GetTracer().Start(ctx, "heartbeat.beat") + defer innerSpan.End() + + gauge.Record(ctx, 1) + count.Record(ctx, 1) + + err = cme.Emit(ctx, "heartbeat") + if err != nil { + h.eng.Errorw("heartbeat emit failed", "err", err) + } + } + + h.eng.GoTick(timeutil.NewTicker(h.getBeat), beatFn) + return nil +} + +func (h *Heartbeat) getBeat() time.Duration { + return h.beat +} + // NewApplication initializes a new store if one is not already // present at the configured root directory (default: ~/.chainlink), // the logger at the same directory and returns the Application to @@ -199,6 +258,10 @@ type ApplicationOpts struct { // TODO: Inject more dependencies here to save booting up useless stuff in tests func NewApplication(opts ApplicationOpts) (Application, error) { var srvcs []services.ServiceCtx + + heartbeat := NewHeartbeat(opts.Logger) + srvcs = append(srvcs, &heartbeat) + auditLogger := opts.AuditLogger cfg := opts.Config relayerChainInterops := opts.RelayerChainInteroperators @@ -307,10 +370,6 @@ func NewApplication(opts ApplicationOpts) (Application, error) { fetcher.Fetch, workflowstore.NewDBStore(opts.DS, lggr, clockwork.NewRealClock()), opts.CapabilitiesRegistry, custmsg.NewLabeler(), clockwork.NewRealClock(), keys[0]) - loader := syncer.NewWorkflowRegistryContractLoader(lggr, cfg.Capabilities().WorkflowRegistry().Address(), func(ctx context.Context, bytes []byte) (syncer.ContractReader, error) { - return relayer.NewContractReader(ctx, bytes) - }, eventHandler) - globalLogger.Debugw("Creating WorkflowRegistrySyncer") wfSyncer := syncer.NewWorkflowRegistry( lggr, @@ -322,7 +381,6 @@ func NewApplication(opts ApplicationOpts) (Application, error) { QueryCount: 100, }, eventHandler, - loader, workflowDonNotifier, ) @@ -760,7 +818,7 @@ func (app *ChainlinkApplication) Start(ctx context.Context) error { return multierr.Combine(err, ms.Close()) } - app.logger.Debugw("Starting service...", "name", service.Name()) + app.logger.Infow("Starting service...", "name", service.Name()) if err := ms.Start(ctx, service); err != nil { return err diff --git a/core/services/chainlink/config.go b/core/services/chainlink/config.go index 9f083ef89af..dd54856cf0a 100644 --- a/core/services/chainlink/config.go +++ b/core/services/chainlink/config.go @@ -46,6 +46,8 @@ type Config struct { Starknet stkcfg.TOMLConfigs `toml:",omitempty"` Aptos RawConfigs `toml:",omitempty"` + + Tron RawConfigs `toml:",omitempty"` } // RawConfigs is a list of RawConfig. @@ -260,6 +262,7 @@ func (c *Config) TOMLString() (string, error) { // warnings aggregates warnings from valueWarnings and deprecationWarnings func (c *Config) warnings() (err error) { deprecationErr := c.deprecationWarnings() + warningErr := c.valueWarnings() err = multierr.Append(deprecationErr, warningErr) _, list := commonconfig.MultiErrorList(err) @@ -352,6 +355,10 @@ func (c *Config) SetFrom(f *Config) (err error) { err = multierr.Append(err, commonconfig.NamedMultiErrorList(err5, "Aptos")) } + if err6 := c.Tron.SetFrom(f.Tron); err6 != nil { + err = multierr.Append(err, commonconfig.NamedMultiErrorList(err6, "Tron")) + } + _, err = commonconfig.MultiErrorList(err) return err diff --git a/core/services/chainlink/config_database.go b/core/services/chainlink/config_database.go index fd8aa96419d..27e61479146 100644 --- a/core/services/chainlink/config_database.go +++ b/core/services/chainlink/config_database.go @@ -107,6 +107,9 @@ func (d *databaseConfig) DefaultQueryTimeout() time.Duration { } func (d *databaseConfig) URL() url.URL { + if d.s.URL == nil { + return url.URL{} + } return *d.s.URL.URL() } diff --git a/core/services/chainlink/config_general.go b/core/services/chainlink/config_general.go index dd0dc87b59a..e67d92fefc9 100644 --- a/core/services/chainlink/config_general.go +++ b/core/services/chainlink/config_general.go @@ -213,6 +213,10 @@ func (g *generalConfig) AptosConfigs() RawConfigs { return g.c.Aptos } +func (g *generalConfig) TronConfigs() RawConfigs { + return g.c.Tron +} + func (g *generalConfig) Validate() error { return g.validate(g.secrets.Validate) } @@ -358,6 +362,15 @@ func (g *generalConfig) AptosEnabled() bool { return false } +func (g *generalConfig) TronEnabled() bool { + for _, c := range g.c.Tron { + if c.IsEnabled() { + return true + } + } + return false +} + func (g *generalConfig) WebServer() config.WebServer { return &webServerConfig{c: g.c.WebServer, s: g.secrets.WebServer, rootDir: g.RootDir} } diff --git a/core/services/chainlink/config_general_test.go b/core/services/chainlink/config_general_test.go index 29393ee0fdd..3f02b880baf 100644 --- a/core/services/chainlink/config_general_test.go +++ b/core/services/chainlink/config_general_test.go @@ -28,6 +28,7 @@ func TestTOMLGeneralConfig_Defaults(t *testing.T) { assert.False(t, config.CosmosEnabled()) assert.False(t, config.SolanaEnabled()) assert.False(t, config.StarkNetEnabled()) + assert.False(t, config.TronEnabled()) assert.Equal(t, false, config.JobPipeline().ExternalInitiatorsEnabled()) assert.Equal(t, 15*time.Minute, config.WebServer().SessionTimeout().Duration()) } diff --git a/core/services/chainlink/config_mercury.go b/core/services/chainlink/config_mercury.go index 0e56105406b..06e2d7822a3 100644 --- a/core/services/chainlink/config_mercury.go +++ b/core/services/chainlink/config_mercury.go @@ -42,6 +42,10 @@ type mercuryTransmitterConfig struct { c toml.MercuryTransmitter } +func (m *mercuryTransmitterConfig) Protocol() string { + return *m.c.Protocol +} + func (m *mercuryTransmitterConfig) TransmitQueueMaxSize() uint32 { return *m.c.TransmitQueueMaxSize } diff --git a/core/services/chainlink/config_telemetry.go b/core/services/chainlink/config_telemetry.go index 125eeed64e5..f2359997933 100644 --- a/core/services/chainlink/config_telemetry.go +++ b/core/services/chainlink/config_telemetry.go @@ -1,6 +1,7 @@ package chainlink import ( + "fmt" "time" "github.com/smartcontractkit/chainlink/v2/core/config/toml" @@ -42,9 +43,13 @@ func (b *telemetryConfig) OtelExporterGRPCEndpoint() string { // // These can be overridden by the TOML if the user so chooses func (b *telemetryConfig) ResourceAttributes() map[string]string { + sha, ver := static.Short() + defaults := map[string]string{ - "service.name": "chainlink", - "service.version": static.Version, + "service.name": "chainlink", + "service.version": static.Version, + "service.sha": static.Sha, + "service.shortversion": fmt.Sprintf("%s@%s", ver, sha), } for k, v := range b.s.ResourceAttributes { diff --git a/core/services/chainlink/config_telemetry_test.go b/core/services/chainlink/config_telemetry_test.go index d0963129994..0627da03fb4 100644 --- a/core/services/chainlink/config_telemetry_test.go +++ b/core/services/chainlink/config_telemetry_test.go @@ -97,17 +97,21 @@ func TestTelemetryConfig_ResourceAttributes(t *testing.T) { "DefaultAttributes", toml.Telemetry{ResourceAttributes: nil}, map[string]string{ - "service.name": "chainlink", - "service.version": static.Version, + "service.name": "chainlink", + "service.sha": "unset", + "service.shortversion": "unset@unset", + "service.version": static.Version, }, }, { "CustomAttributes", toml.Telemetry{ResourceAttributes: map[string]string{"custom.key": "custom.value"}}, map[string]string{ - "service.name": "chainlink", - "service.version": static.Version, - "custom.key": "custom.value", + "service.name": "chainlink", + "service.sha": "unset", + "service.shortversion": "unset@unset", + "service.version": static.Version, + "custom.key": "custom.value", }, }, } diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go index 769005feb72..764830409fc 100644 --- a/core/services/chainlink/config_test.go +++ b/core/services/chainlink/config_test.go @@ -22,10 +22,10 @@ import ( commoncfg "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config" + "github.com/smartcontractkit/chainlink-framework/multinode" solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" stkcfg "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config" - "github.com/smartcontractkit/chainlink/v2/common/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" @@ -49,7 +49,7 @@ var ( second = *commoncfg.MustNewDuration(time.Second) minute = *commoncfg.MustNewDuration(time.Minute) - selectionMode = client.NodeSelectionModeHighestHead + selectionMode = multinode.NodeSelectionModeHighestHead multiChain = Config{ Core: toml.Core{ @@ -258,7 +258,7 @@ func TestConfig_Marshal(t *testing.T) { require.NoError(t, err) return &a } - selectionMode := client.NodeSelectionModeHighestHead + selectionMode := multinode.NodeSelectionModeHighestHead global := Config{ Core: toml.Core{ @@ -654,6 +654,7 @@ func TestConfig_Marshal(t *testing.T) { NoNewFinalizedHeadsThreshold: &hour, Transactions: evmcfg.Transactions{ + Enabled: ptr(true), MaxInFlight: ptr[uint32](19), MaxQueued: ptr[uint32](99), ReaperInterval: &minute, @@ -663,6 +664,9 @@ func TestConfig_Marshal(t *testing.T) { AutoPurge: evmcfg.AutoPurgeConfig{ Enabled: ptr(false), }, + TransactionManagerV2: evmcfg.TransactionManagerV2Config{ + Enabled: ptr(false), + }, }, HeadTracker: evmcfg.HeadTracker{ @@ -750,6 +754,7 @@ func TestConfig_Marshal(t *testing.T) { TxTimeout: commoncfg.MustNewDuration(time.Hour), TxRetryTimeout: commoncfg.MustNewDuration(time.Minute), TxConfirmTimeout: commoncfg.MustNewDuration(time.Second), + TxExpirationRebroadcast: ptr(false), TxRetentionTimeout: commoncfg.MustNewDuration(0 * time.Second), SkipPreflight: ptr(true), Commitment: ptr("banana"), @@ -841,6 +846,7 @@ func TestConfig_Marshal(t *testing.T) { CertFile: ptr("/path/to/cert.pem"), }, Transmitter: toml.MercuryTransmitter{ + Protocol: ptr("grpc"), TransmitQueueMaxSize: ptr(uint32(123)), TransmitTimeout: commoncfg.MustNewDuration(234 * time.Second), TransmitConcurrency: ptr(uint32(456)), @@ -1118,6 +1124,7 @@ FinalizedBlockOffset = 16 NoNewFinalizedHeadsThreshold = '1h0m0s' [EVM.Transactions] +Enabled = true ForwardersEnabled = true MaxInFlight = 19 MaxQueued = 99 @@ -1128,6 +1135,9 @@ ResendAfterThreshold = '1h0m0s' [EVM.Transactions.AutoPurge] Enabled = false +[EVM.Transactions.TransactionManagerV2] +Enabled = false + [EVM.BalanceMonitor] Enabled = true @@ -1279,6 +1289,7 @@ OCR2CacheTTL = '1h0m0s' TxTimeout = '1h0m0s' TxRetryTimeout = '1m0s' TxConfirmTimeout = '1s' +TxExpirationRebroadcast = false TxRetentionTimeout = '0s' SkipPreflight = true Commitment = 'banana' @@ -1352,6 +1363,7 @@ LatestReportDeadline = '1m42s' CertFile = '/path/to/cert.pem' [Mercury.Transmitter] +Protocol = 'grpc' TransmitQueueMaxSize = 123 TransmitTimeout = '3m54s' TransmitConcurrency = 456 @@ -1402,6 +1414,15 @@ func TestConfig_full(t *testing.T) { got.EVM[c].Nodes[n].Order = ptr(int32(100)) } } + if got.EVM[c].Transactions.TransactionManagerV2.BlockTime == nil { + got.EVM[c].Transactions.TransactionManagerV2.BlockTime = new(commoncfg.Duration) + } + if got.EVM[c].Transactions.TransactionManagerV2.CustomURL == nil { + got.EVM[c].Transactions.TransactionManagerV2.CustomURL = new(commoncfg.URL) + } + if got.EVM[c].Transactions.TransactionManagerV2.DualBroadcast == nil { + got.EVM[c].Transactions.TransactionManagerV2.DualBroadcast = ptr(false) + } if got.EVM[c].Transactions.AutoPurge.Threshold == nil { got.EVM[c].Transactions.AutoPurge.Threshold = ptr(uint32(0)) } @@ -1436,7 +1457,7 @@ func TestConfig_Validate(t *testing.T) { toml string exp string }{ - {name: "invalid", toml: invalidTOML, exp: `invalid configuration: 8 errors: + {name: "invalid", toml: invalidTOML, exp: `invalid configuration: 9 errors: - P2P.V2.Enabled: invalid value (false): P2P required for OCR or OCR2. Please enable P2P or disable OCR/OCR2. - Database.Lock.LeaseRefreshInterval: invalid value (6s): must be less than or equal to half of LeaseDuration (10s) - WebServer: 8 errors: @@ -1468,7 +1489,7 @@ func TestConfig_Validate(t *testing.T) { - 1: 10 errors: - ChainType: invalid value (Foo): must not be set with this chain id - Nodes: missing: must have at least one node - - ChainType: invalid value (Foo): must be one of arbitrum, astar, celo, gnosis, hedera, kroma, mantle, metis, optimismBedrock, scroll, wemix, xlayer, zkevm, zksync, zircuit or omitted + - ChainType: invalid value (Foo): must be one of arbitrum, astar, celo, gnosis, hedera, kroma, mantle, metis, optimismBedrock, sei, scroll, wemix, xlayer, zkevm, zksync, zircuit or omitted - HeadTracker.HistoryDepth: invalid value (30): must be greater than or equal to FinalizedBlockOffset - GasEstimator.BumpThreshold: invalid value (0): cannot be 0 if auto-purge feature is enabled for Foo - Transactions.AutoPurge.Threshold: missing: needs to be set if auto-purge feature is enabled for Foo @@ -1481,7 +1502,7 @@ func TestConfig_Validate(t *testing.T) { - 2: 5 errors: - ChainType: invalid value (Arbitrum): only "optimismBedrock" can be used with this chain id - Nodes: missing: must have at least one node - - ChainType: invalid value (Arbitrum): must be one of arbitrum, astar, celo, gnosis, hedera, kroma, mantle, metis, optimismBedrock, scroll, wemix, xlayer, zkevm, zksync, zircuit or omitted + - ChainType: invalid value (Arbitrum): must be one of arbitrum, astar, celo, gnosis, hedera, kroma, mantle, metis, optimismBedrock, sei, scroll, wemix, xlayer, zkevm, zksync, zircuit or omitted - FinalityDepth: invalid value (0): must be greater than or equal to 1 - MinIncomingConfirmations: invalid value (0): must be greater than or equal to 1 - 3: 3 errors: @@ -1533,6 +1554,11 @@ func TestConfig_Validate(t *testing.T) { - Nodes: missing: must have at least one node - Aptos: 2 errors: - 0.Nodes.1.Name: invalid value (primary): duplicate - must be unique + - 0: 2 errors: + - Enabled: invalid value (1): expected bool + - ChainID: missing: required for all chains + - Tron: 2 errors: + - 0.Nodes.1.Name: invalid value (tron-test): duplicate - must be unique - 0: 2 errors: - Enabled: invalid value (1): expected bool - ChainID: missing: required for all chains`}, diff --git a/core/services/chainlink/mocks/general_config.go b/core/services/chainlink/mocks/general_config.go index db1efb3d86f..9df0ab85985 100644 --- a/core/services/chainlink/mocks/general_config.go +++ b/core/services/chainlink/mocks/general_config.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -36,7 +36,7 @@ func (_m *GeneralConfig) EXPECT() *GeneralConfig_Expecter { return &GeneralConfig_Expecter{mock: &_m.Mock} } -// AppID provides a mock function with given fields: +// AppID provides a mock function with no fields func (_m *GeneralConfig) AppID() uuid.UUID { ret := _m.Called() @@ -83,7 +83,7 @@ func (_c *GeneralConfig_AppID_Call) RunAndReturn(run func() uuid.UUID) *GeneralC return _c } -// AptosConfigs provides a mock function with given fields: +// AptosConfigs provides a mock function with no fields func (_m *GeneralConfig) AptosConfigs() chainlink.RawConfigs { ret := _m.Called() @@ -130,7 +130,7 @@ func (_c *GeneralConfig_AptosConfigs_Call) RunAndReturn(run func() chainlink.Raw return _c } -// AptosEnabled provides a mock function with given fields: +// AptosEnabled provides a mock function with no fields func (_m *GeneralConfig) AptosEnabled() bool { ret := _m.Called() @@ -175,7 +175,7 @@ func (_c *GeneralConfig_AptosEnabled_Call) RunAndReturn(run func() bool) *Genera return _c } -// AuditLogger provides a mock function with given fields: +// AuditLogger provides a mock function with no fields func (_m *GeneralConfig) AuditLogger() config.AuditLogger { ret := _m.Called() @@ -222,7 +222,7 @@ func (_c *GeneralConfig_AuditLogger_Call) RunAndReturn(run func() config.AuditLo return _c } -// AutoPprof provides a mock function with given fields: +// AutoPprof provides a mock function with no fields func (_m *GeneralConfig) AutoPprof() config.AutoPprof { ret := _m.Called() @@ -269,7 +269,7 @@ func (_c *GeneralConfig_AutoPprof_Call) RunAndReturn(run func() config.AutoPprof return _c } -// Capabilities provides a mock function with given fields: +// Capabilities provides a mock function with no fields func (_m *GeneralConfig) Capabilities() config.Capabilities { ret := _m.Called() @@ -316,7 +316,7 @@ func (_c *GeneralConfig_Capabilities_Call) RunAndReturn(run func() config.Capabi return _c } -// ConfigTOML provides a mock function with given fields: +// ConfigTOML provides a mock function with no fields func (_m *GeneralConfig) ConfigTOML() (string, string) { ret := _m.Called() @@ -371,7 +371,7 @@ func (_c *GeneralConfig_ConfigTOML_Call) RunAndReturn(run func() (string, string return _c } -// CosmosConfigs provides a mock function with given fields: +// CosmosConfigs provides a mock function with no fields func (_m *GeneralConfig) CosmosConfigs() cosmosconfig.TOMLConfigs { ret := _m.Called() @@ -418,7 +418,7 @@ func (_c *GeneralConfig_CosmosConfigs_Call) RunAndReturn(run func() cosmosconfig return _c } -// CosmosEnabled provides a mock function with given fields: +// CosmosEnabled provides a mock function with no fields func (_m *GeneralConfig) CosmosEnabled() bool { ret := _m.Called() @@ -463,7 +463,7 @@ func (_c *GeneralConfig_CosmosEnabled_Call) RunAndReturn(run func() bool) *Gener return _c } -// Database provides a mock function with given fields: +// Database provides a mock function with no fields func (_m *GeneralConfig) Database() config.Database { ret := _m.Called() @@ -510,7 +510,7 @@ func (_c *GeneralConfig_Database_Call) RunAndReturn(run func() config.Database) return _c } -// EVMConfigs provides a mock function with given fields: +// EVMConfigs provides a mock function with no fields func (_m *GeneralConfig) EVMConfigs() toml.EVMConfigs { ret := _m.Called() @@ -557,7 +557,7 @@ func (_c *GeneralConfig_EVMConfigs_Call) RunAndReturn(run func() toml.EVMConfigs return _c } -// EVMEnabled provides a mock function with given fields: +// EVMEnabled provides a mock function with no fields func (_m *GeneralConfig) EVMEnabled() bool { ret := _m.Called() @@ -602,7 +602,7 @@ func (_c *GeneralConfig_EVMEnabled_Call) RunAndReturn(run func() bool) *GeneralC return _c } -// EVMRPCEnabled provides a mock function with given fields: +// EVMRPCEnabled provides a mock function with no fields func (_m *GeneralConfig) EVMRPCEnabled() bool { ret := _m.Called() @@ -647,7 +647,7 @@ func (_c *GeneralConfig_EVMRPCEnabled_Call) RunAndReturn(run func() bool) *Gener return _c } -// Feature provides a mock function with given fields: +// Feature provides a mock function with no fields func (_m *GeneralConfig) Feature() config.Feature { ret := _m.Called() @@ -694,7 +694,7 @@ func (_c *GeneralConfig_Feature_Call) RunAndReturn(run func() config.Feature) *G return _c } -// FluxMonitor provides a mock function with given fields: +// FluxMonitor provides a mock function with no fields func (_m *GeneralConfig) FluxMonitor() config.FluxMonitor { ret := _m.Called() @@ -741,7 +741,7 @@ func (_c *GeneralConfig_FluxMonitor_Call) RunAndReturn(run func() config.FluxMon return _c } -// Insecure provides a mock function with given fields: +// Insecure provides a mock function with no fields func (_m *GeneralConfig) Insecure() config.Insecure { ret := _m.Called() @@ -788,7 +788,7 @@ func (_c *GeneralConfig_Insecure_Call) RunAndReturn(run func() config.Insecure) return _c } -// InsecureFastScrypt provides a mock function with given fields: +// InsecureFastScrypt provides a mock function with no fields func (_m *GeneralConfig) InsecureFastScrypt() bool { ret := _m.Called() @@ -833,7 +833,7 @@ func (_c *GeneralConfig_InsecureFastScrypt_Call) RunAndReturn(run func() bool) * return _c } -// JobPipeline provides a mock function with given fields: +// JobPipeline provides a mock function with no fields func (_m *GeneralConfig) JobPipeline() config.JobPipeline { ret := _m.Called() @@ -880,7 +880,7 @@ func (_c *GeneralConfig_JobPipeline_Call) RunAndReturn(run func() config.JobPipe return _c } -// Keeper provides a mock function with given fields: +// Keeper provides a mock function with no fields func (_m *GeneralConfig) Keeper() config.Keeper { ret := _m.Called() @@ -927,7 +927,7 @@ func (_c *GeneralConfig_Keeper_Call) RunAndReturn(run func() config.Keeper) *Gen return _c } -// Log provides a mock function with given fields: +// Log provides a mock function with no fields func (_m *GeneralConfig) Log() config.Log { ret := _m.Called() @@ -1004,11 +1004,11 @@ func (_c *GeneralConfig_LogConfiguration_Call) Return() *GeneralConfig_LogConfig } func (_c *GeneralConfig_LogConfiguration_Call) RunAndReturn(run func(config.LogfFn, config.LogfFn)) *GeneralConfig_LogConfiguration_Call { - _c.Call.Return(run) + _c.Run(run) return _c } -// Mercury provides a mock function with given fields: +// Mercury provides a mock function with no fields func (_m *GeneralConfig) Mercury() config.Mercury { ret := _m.Called() @@ -1055,7 +1055,7 @@ func (_c *GeneralConfig_Mercury_Call) RunAndReturn(run func() config.Mercury) *G return _c } -// OCR provides a mock function with given fields: +// OCR provides a mock function with no fields func (_m *GeneralConfig) OCR() config.OCR { ret := _m.Called() @@ -1102,7 +1102,7 @@ func (_c *GeneralConfig_OCR_Call) RunAndReturn(run func() config.OCR) *GeneralCo return _c } -// OCR2 provides a mock function with given fields: +// OCR2 provides a mock function with no fields func (_m *GeneralConfig) OCR2() config.OCR2 { ret := _m.Called() @@ -1149,7 +1149,7 @@ func (_c *GeneralConfig_OCR2_Call) RunAndReturn(run func() config.OCR2) *General return _c } -// P2P provides a mock function with given fields: +// P2P provides a mock function with no fields func (_m *GeneralConfig) P2P() config.P2P { ret := _m.Called() @@ -1196,7 +1196,7 @@ func (_c *GeneralConfig_P2P_Call) RunAndReturn(run func() config.P2P) *GeneralCo return _c } -// Password provides a mock function with given fields: +// Password provides a mock function with no fields func (_m *GeneralConfig) Password() config.Password { ret := _m.Called() @@ -1243,7 +1243,7 @@ func (_c *GeneralConfig_Password_Call) RunAndReturn(run func() config.Password) return _c } -// Prometheus provides a mock function with given fields: +// Prometheus provides a mock function with no fields func (_m *GeneralConfig) Prometheus() config.Prometheus { ret := _m.Called() @@ -1290,7 +1290,7 @@ func (_c *GeneralConfig_Prometheus_Call) RunAndReturn(run func() config.Promethe return _c } -// Pyroscope provides a mock function with given fields: +// Pyroscope provides a mock function with no fields func (_m *GeneralConfig) Pyroscope() config.Pyroscope { ret := _m.Called() @@ -1337,7 +1337,7 @@ func (_c *GeneralConfig_Pyroscope_Call) RunAndReturn(run func() config.Pyroscope return _c } -// RootDir provides a mock function with given fields: +// RootDir provides a mock function with no fields func (_m *GeneralConfig) RootDir() string { ret := _m.Called() @@ -1382,7 +1382,7 @@ func (_c *GeneralConfig_RootDir_Call) RunAndReturn(run func() string) *GeneralCo return _c } -// Sentry provides a mock function with given fields: +// Sentry provides a mock function with no fields func (_m *GeneralConfig) Sentry() config.Sentry { ret := _m.Called() @@ -1504,7 +1504,7 @@ func (_c *GeneralConfig_SetLogSQL_Call) Return() *GeneralConfig_SetLogSQL_Call { } func (_c *GeneralConfig_SetLogSQL_Call) RunAndReturn(run func(bool)) *GeneralConfig_SetLogSQL_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -1538,11 +1538,11 @@ func (_c *GeneralConfig_SetPasswords_Call) Return() *GeneralConfig_SetPasswords_ } func (_c *GeneralConfig_SetPasswords_Call) RunAndReturn(run func(*string, *string)) *GeneralConfig_SetPasswords_Call { - _c.Call.Return(run) + _c.Run(run) return _c } -// ShutdownGracePeriod provides a mock function with given fields: +// ShutdownGracePeriod provides a mock function with no fields func (_m *GeneralConfig) ShutdownGracePeriod() time.Duration { ret := _m.Called() @@ -1587,7 +1587,7 @@ func (_c *GeneralConfig_ShutdownGracePeriod_Call) RunAndReturn(run func() time.D return _c } -// SolanaConfigs provides a mock function with given fields: +// SolanaConfigs provides a mock function with no fields func (_m *GeneralConfig) SolanaConfigs() solanaconfig.TOMLConfigs { ret := _m.Called() @@ -1634,7 +1634,7 @@ func (_c *GeneralConfig_SolanaConfigs_Call) RunAndReturn(run func() solanaconfig return _c } -// SolanaEnabled provides a mock function with given fields: +// SolanaEnabled provides a mock function with no fields func (_m *GeneralConfig) SolanaEnabled() bool { ret := _m.Called() @@ -1679,7 +1679,7 @@ func (_c *GeneralConfig_SolanaEnabled_Call) RunAndReturn(run func() bool) *Gener return _c } -// StarkNetEnabled provides a mock function with given fields: +// StarkNetEnabled provides a mock function with no fields func (_m *GeneralConfig) StarkNetEnabled() bool { ret := _m.Called() @@ -1724,7 +1724,7 @@ func (_c *GeneralConfig_StarkNetEnabled_Call) RunAndReturn(run func() bool) *Gen return _c } -// StarknetConfigs provides a mock function with given fields: +// StarknetConfigs provides a mock function with no fields func (_m *GeneralConfig) StarknetConfigs() chainlinkconfig.TOMLConfigs { ret := _m.Called() @@ -1771,7 +1771,7 @@ func (_c *GeneralConfig_StarknetConfigs_Call) RunAndReturn(run func() chainlinkc return _c } -// Telemetry provides a mock function with given fields: +// Telemetry provides a mock function with no fields func (_m *GeneralConfig) Telemetry() config.Telemetry { ret := _m.Called() @@ -1818,7 +1818,7 @@ func (_c *GeneralConfig_Telemetry_Call) RunAndReturn(run func() config.Telemetry return _c } -// TelemetryIngress provides a mock function with given fields: +// TelemetryIngress provides a mock function with no fields func (_m *GeneralConfig) TelemetryIngress() config.TelemetryIngress { ret := _m.Called() @@ -1865,7 +1865,7 @@ func (_c *GeneralConfig_TelemetryIngress_Call) RunAndReturn(run func() config.Te return _c } -// Threshold provides a mock function with given fields: +// Threshold provides a mock function with no fields func (_m *GeneralConfig) Threshold() config.Threshold { ret := _m.Called() @@ -1912,7 +1912,7 @@ func (_c *GeneralConfig_Threshold_Call) RunAndReturn(run func() config.Threshold return _c } -// Tracing provides a mock function with given fields: +// Tracing provides a mock function with no fields func (_m *GeneralConfig) Tracing() config.Tracing { ret := _m.Called() @@ -1959,7 +1959,99 @@ func (_c *GeneralConfig_Tracing_Call) RunAndReturn(run func() config.Tracing) *G return _c } -// Validate provides a mock function with given fields: +// TronConfigs provides a mock function with no fields +func (_m *GeneralConfig) TronConfigs() chainlink.RawConfigs { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for TronConfigs") + } + + var r0 chainlink.RawConfigs + if rf, ok := ret.Get(0).(func() chainlink.RawConfigs); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(chainlink.RawConfigs) + } + } + + return r0 +} + +// GeneralConfig_TronConfigs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TronConfigs' +type GeneralConfig_TronConfigs_Call struct { + *mock.Call +} + +// TronConfigs is a helper method to define mock.On call +func (_e *GeneralConfig_Expecter) TronConfigs() *GeneralConfig_TronConfigs_Call { + return &GeneralConfig_TronConfigs_Call{Call: _e.mock.On("TronConfigs")} +} + +func (_c *GeneralConfig_TronConfigs_Call) Run(run func()) *GeneralConfig_TronConfigs_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *GeneralConfig_TronConfigs_Call) Return(_a0 chainlink.RawConfigs) *GeneralConfig_TronConfigs_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *GeneralConfig_TronConfigs_Call) RunAndReturn(run func() chainlink.RawConfigs) *GeneralConfig_TronConfigs_Call { + _c.Call.Return(run) + return _c +} + +// TronEnabled provides a mock function with no fields +func (_m *GeneralConfig) TronEnabled() bool { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for TronEnabled") + } + + var r0 bool + if rf, ok := ret.Get(0).(func() bool); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + +// GeneralConfig_TronEnabled_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TronEnabled' +type GeneralConfig_TronEnabled_Call struct { + *mock.Call +} + +// TronEnabled is a helper method to define mock.On call +func (_e *GeneralConfig_Expecter) TronEnabled() *GeneralConfig_TronEnabled_Call { + return &GeneralConfig_TronEnabled_Call{Call: _e.mock.On("TronEnabled")} +} + +func (_c *GeneralConfig_TronEnabled_Call) Run(run func()) *GeneralConfig_TronEnabled_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *GeneralConfig_TronEnabled_Call) Return(_a0 bool) *GeneralConfig_TronEnabled_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *GeneralConfig_TronEnabled_Call) RunAndReturn(run func() bool) *GeneralConfig_TronEnabled_Call { + _c.Call.Return(run) + return _c +} + +// Validate provides a mock function with no fields func (_m *GeneralConfig) Validate() error { ret := _m.Called() @@ -2004,7 +2096,7 @@ func (_c *GeneralConfig_Validate_Call) RunAndReturn(run func() error) *GeneralCo return _c } -// ValidateDB provides a mock function with given fields: +// ValidateDB provides a mock function with no fields func (_m *GeneralConfig) ValidateDB() error { ret := _m.Called() @@ -2049,7 +2141,7 @@ func (_c *GeneralConfig_ValidateDB_Call) RunAndReturn(run func() error) *General return _c } -// WebServer provides a mock function with given fields: +// WebServer provides a mock function with no fields func (_m *GeneralConfig) WebServer() config.WebServer { ret := _m.Called() diff --git a/core/services/chainlink/mocks/relayer_chain_interoperators.go b/core/services/chainlink/mocks/relayer_chain_interoperators.go index bc30ede77ee..8d943243188 100644 --- a/core/services/chainlink/mocks/relayer_chain_interoperators.go +++ b/core/services/chainlink/mocks/relayer_chain_interoperators.go @@ -4,7 +4,6 @@ import ( "context" "slices" - commonTypes "github.com/smartcontractkit/chainlink/v2/common/types" services2 "github.com/smartcontractkit/chainlink/v2/core/services" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -70,6 +69,6 @@ func (f *FakeRelayerChainInteroperators) ChainStatus(ctx context.Context, id typ panic("unimplemented") } -func (f *FakeRelayerChainInteroperators) ChainStatuses(ctx context.Context, offset, limit int) ([]commonTypes.ChainStatusWithID, int, error) { +func (f *FakeRelayerChainInteroperators) ChainStatuses(ctx context.Context, offset, limit int) ([]chainlink.NetworkChainStatus, int, error) { panic("unimplemented") } diff --git a/core/services/chainlink/relayer_chain_interoperators.go b/core/services/chainlink/relayer_chain_interoperators.go index 2fc671bfe6e..f8d6de99c8f 100644 --- a/core/services/chainlink/relayer_chain_interoperators.go +++ b/core/services/chainlink/relayer_chain_interoperators.go @@ -14,7 +14,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/relay" - commonTypes "github.com/smartcontractkit/chainlink/v2/common/types" "github.com/smartcontractkit/chainlink/v2/core/chains" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/services" @@ -52,9 +51,15 @@ type LegacyChainer interface { LegacyCosmosChains() LegacyCosmosContainer } +// NetworkChainStatus is a ChainStatus from a particlar Network. +type NetworkChainStatus struct { + Network string + types.ChainStatus +} + type ChainStatuser interface { ChainStatus(ctx context.Context, id types.RelayID) (types.ChainStatus, error) - ChainStatuses(ctx context.Context, offset, limit int) ([]commonTypes.ChainStatusWithID, int, error) + ChainStatuses(ctx context.Context, offset, limit int) ([]NetworkChainStatus, int, error) } // NodesStatuser is an interface for node configuration and state. @@ -204,6 +209,23 @@ func InitAptos(ctx context.Context, factory RelayerFactory, config AptosFactoryC } } +// InitTron is a option for instantiating Tron relayers +func InitTron(ctx context.Context, factory RelayerFactory, config TronFactoryConfig) CoreRelayerChainInitFunc { + return func(op *CoreRelayerChainInteroperators) error { + tronRelayers, err := factory.NewTron(config.Keystore, config.TOMLConfigs) + if err != nil { + return fmt.Errorf("failed to setup Tron relayer: %w", err) + } + + for id, relayer := range tronRelayers { + op.srvs = append(op.srvs, relayer) + op.loopRelayers[id] = relayer + } + + return nil + } +} + // Get a [loop.Relayer] by id func (rs *CoreRelayerChainInteroperators) Get(id types.RelayID) (loop.Relayer, error) { rs.mu.Lock() @@ -262,9 +284,9 @@ func (rs *CoreRelayerChainInteroperators) ChainStatus(ctx context.Context, id ty return lr.GetChainStatus(ctx) } -func (rs *CoreRelayerChainInteroperators) ChainStatuses(ctx context.Context, offset, limit int) ([]commonTypes.ChainStatusWithID, int, error) { +func (rs *CoreRelayerChainInteroperators) ChainStatuses(ctx context.Context, offset, limit int) ([]NetworkChainStatus, int, error) { var ( - stats []commonTypes.ChainStatusWithID + stats []NetworkChainStatus totalErr error ) rs.mu.Lock() @@ -284,7 +306,7 @@ func (rs *CoreRelayerChainInteroperators) ChainStatuses(ctx context.Context, off totalErr = errors.Join(totalErr, err) continue } - stats = append(stats, commonTypes.ChainStatusWithID{ChainStatus: stat, RelayID: rid}) + stats = append(stats, NetworkChainStatus{ChainStatus: stat, Network: rid.Network}) } if totalErr != nil { diff --git a/core/services/chainlink/relayer_chain_interoperators_test.go b/core/services/chainlink/relayer_chain_interoperators_test.go index a4bd8c168ba..f03e172542c 100644 --- a/core/services/chainlink/relayer_chain_interoperators_test.go +++ b/core/services/chainlink/relayer_chain_interoperators_test.go @@ -378,6 +378,8 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { expectedChainCnt, expectedNodeCnt = tt.expectedDummyChainCnt, tt.expectedDummyNodeCnt case relay.NetworkAptos: t.Skip("aptos doesn't need a CoreRelayerChainInteroperator") + case relay.NetworkTron: + t.Skip("tron doesn't need a CoreRelayerChainInteroperator") default: require.Fail(t, "untested relay network", relayNetwork) diff --git a/core/services/chainlink/relayer_factory.go b/core/services/chainlink/relayer_factory.go index a1571663d5a..c173c7fecb7 100644 --- a/core/services/chainlink/relayer_factory.go +++ b/core/services/chainlink/relayer_factory.go @@ -371,3 +371,14 @@ func (r *RelayerFactory) NewLOOPRelayer(name string, network string, plugin env. } return relayers, nil } + +type TronFactoryConfig struct { + Keystore keystore.Tron + TOMLConfigs RawConfigs +} + +func (r *RelayerFactory) NewTron(ks keystore.Tron, chainCfgs RawConfigs) (map[types.RelayID]loop.Relayer, error) { + plugin := env.NewPlugin("tron") + loopKs := &keystore.TronLOOPKeystore{Tron: ks} + return r.NewLOOPRelayer("Tron", relay.NetworkTron, plugin, loopKs, chainCfgs) +} diff --git a/core/services/chainlink/testdata/config-empty-effective.toml b/core/services/chainlink/testdata/config-empty-effective.toml index a2052c04a8e..e219296e673 100644 --- a/core/services/chainlink/testdata/config-empty-effective.toml +++ b/core/services/chainlink/testdata/config-empty-effective.toml @@ -235,7 +235,8 @@ LatestReportDeadline = '5s' CertFile = '' [Mercury.Transmitter] -TransmitQueueMaxSize = 10000 +Protocol = 'wsrpc' +TransmitQueueMaxSize = 100000 TransmitTimeout = '5s' TransmitConcurrency = 100 diff --git a/core/services/chainlink/testdata/config-full.toml b/core/services/chainlink/testdata/config-full.toml index 47193f80184..b57f9a76cf2 100644 --- a/core/services/chainlink/testdata/config-full.toml +++ b/core/services/chainlink/testdata/config-full.toml @@ -245,6 +245,7 @@ LatestReportDeadline = '1m42s' CertFile = '/path/to/cert.pem' [Mercury.Transmitter] +Protocol = 'grpc' TransmitQueueMaxSize = 123 TransmitTimeout = '3m54s' TransmitConcurrency = 456 @@ -337,6 +338,7 @@ FinalizedBlockOffset = 16 NoNewFinalizedHeadsThreshold = '1h0m0s' [EVM.Transactions] +Enabled = true ForwardersEnabled = true MaxInFlight = 19 MaxQueued = 99 @@ -347,6 +349,9 @@ ResendAfterThreshold = '1h0m0s' [EVM.Transactions.AutoPurge] Enabled = false +[EVM.Transactions.TransactionManagerV2] +Enabled = false + [EVM.BalanceMonitor] Enabled = true @@ -498,6 +503,7 @@ OCR2CacheTTL = '1h0m0s' TxTimeout = '1h0m0s' TxRetryTimeout = '1m0s' TxConfirmTimeout = '1s' +TxExpirationRebroadcast = false TxRetentionTimeout = '0s' SkipPreflight = true Commitment = 'banana' diff --git a/core/services/chainlink/testdata/config-invalid.toml b/core/services/chainlink/testdata/config-invalid.toml index 967ef76de8e..2a3506da45b 100644 --- a/core/services/chainlink/testdata/config-invalid.toml +++ b/core/services/chainlink/testdata/config-invalid.toml @@ -58,6 +58,9 @@ FinalizedBlockOffset = 64 [EVM.Transactions.AutoPurge] Enabled = true +[EVM.Transactions.TransactionManagerV2] +Enabled = false + [EVM.GasEstimator] Mode = 'FixedPrice' BumpThreshold = 0 @@ -112,6 +115,9 @@ ChainType = 'scroll' Enabled = true DetectionApiUrl = '' +[EVM.Transactions.TransactionManagerV2] +Enabled = false + [[EVM.Nodes]] Name = 'scroll node' WSURL = 'ws://foo.bar' @@ -187,6 +193,15 @@ Name = 'primary' [[Aptos.Nodes]] Name = 'primary' +[[Tron]] +Enabled = 1 + +[[Tron.Nodes]] +Name = 'tron-test' + +[[Tron.Nodes]] +Name = 'tron-test' + [OCR2] Enabled = true diff --git a/core/services/chainlink/testdata/config-multi-chain-effective.toml b/core/services/chainlink/testdata/config-multi-chain-effective.toml index 7e658b170db..dbaafbe67d1 100644 --- a/core/services/chainlink/testdata/config-multi-chain-effective.toml +++ b/core/services/chainlink/testdata/config-multi-chain-effective.toml @@ -235,7 +235,8 @@ LatestReportDeadline = '5s' CertFile = '' [Mercury.Transmitter] -TransmitQueueMaxSize = 10000 +Protocol = 'wsrpc' +TransmitQueueMaxSize = 100000 TransmitTimeout = '5s' TransmitConcurrency = 100 @@ -320,6 +321,7 @@ FinalizedBlockOffset = 12 NoNewFinalizedHeadsThreshold = '9m0s' [EVM.Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -330,6 +332,9 @@ ResendAfterThreshold = '1m0s' [EVM.Transactions.AutoPurge] Enabled = false +[EVM.Transactions.TransactionManagerV2] +Enabled = false + [EVM.BalanceMonitor] Enabled = true @@ -430,6 +435,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [EVM.Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -440,6 +446,9 @@ ResendAfterThreshold = '1m0s' [EVM.Transactions.AutoPurge] Enabled = false +[EVM.Transactions.TransactionManagerV2] +Enabled = false + [EVM.BalanceMonitor] Enabled = true @@ -534,6 +543,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '6m0s' [EVM.Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 5000 @@ -544,6 +554,9 @@ ResendAfterThreshold = '1m0s' [EVM.Transactions.AutoPurge] Enabled = false +[EVM.Transactions.TransactionManagerV2] +Enabled = false + [EVM.BalanceMonitor] Enabled = true @@ -659,6 +672,7 @@ OCR2CacheTTL = '1m0s' TxTimeout = '1m0s' TxRetryTimeout = '10s' TxConfirmTimeout = '30s' +TxExpirationRebroadcast = false TxRetentionTimeout = '0s' SkipPreflight = true Commitment = 'confirmed' @@ -704,6 +718,7 @@ OCR2CacheTTL = '1m0s' TxTimeout = '1m0s' TxRetryTimeout = '10s' TxConfirmTimeout = '30s' +TxExpirationRebroadcast = false TxRetentionTimeout = '0s' SkipPreflight = true Commitment = 'confirmed' diff --git a/core/services/chainlink/types.go b/core/services/chainlink/types.go index 74ffc5dc66d..53e7d2a9366 100644 --- a/core/services/chainlink/types.go +++ b/core/services/chainlink/types.go @@ -16,6 +16,7 @@ type GeneralConfig interface { SolanaConfigs() solcfg.TOMLConfigs StarknetConfigs() stkcfg.TOMLConfigs AptosConfigs() RawConfigs + TronConfigs() RawConfigs // ConfigTOML returns both the user provided and effective configuration as TOML. ConfigTOML() (user, effective string) } diff --git a/core/services/feeds/mocks/connections_manager.go b/core/services/feeds/mocks/connections_manager.go index 2c7b71bd05c..20d68315297 100644 --- a/core/services/feeds/mocks/connections_manager.go +++ b/core/services/feeds/mocks/connections_manager.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -22,7 +22,7 @@ func (_m *ConnectionsManager) EXPECT() *ConnectionsManager_Expecter { return &ConnectionsManager_Expecter{mock: &_m.Mock} } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *ConnectionsManager) Close() { _m.Called() } @@ -50,7 +50,7 @@ func (_c *ConnectionsManager_Close_Call) Return() *ConnectionsManager_Close_Call } func (_c *ConnectionsManager_Close_Call) RunAndReturn(run func()) *ConnectionsManager_Close_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -83,7 +83,7 @@ func (_c *ConnectionsManager_Connect_Call) Return() *ConnectionsManager_Connect_ } func (_c *ConnectionsManager_Connect_Call) RunAndReturn(run func(feeds.ConnectOpts)) *ConnectionsManager_Connect_Call { - _c.Call.Return(run) + _c.Run(run) return _c } diff --git a/core/services/feeds/mocks/feeds_manager_client.go b/core/services/feeds/mocks/feeds_manager_client.go index b07362b7787..13ef5ed4c76 100644 --- a/core/services/feeds/mocks/feeds_manager_client.go +++ b/core/services/feeds/mocks/feeds_manager_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/feeds/mocks/orm.go b/core/services/feeds/mocks/orm.go index b4f5c47e51f..b6e00148682 100644 --- a/core/services/feeds/mocks/orm.go +++ b/core/services/feeds/mocks/orm.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/feeds/mocks/service.go b/core/services/feeds/mocks/service.go index 8ae42534f58..9d63e706c29 100644 --- a/core/services/feeds/mocks/service.go +++ b/core/services/feeds/mocks/service.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -117,7 +117,7 @@ func (_c *Service_CancelSpec_Call) RunAndReturn(run func(context.Context, int64) return _c } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *Service) Close() error { ret := _m.Called() @@ -1436,7 +1436,7 @@ func (_c *Service_Unsafe_SetConnectionsManager_Call) Return() *Service_Unsafe_Se } func (_c *Service_Unsafe_SetConnectionsManager_Call) RunAndReturn(run func(feeds.ConnectionsManager)) *Service_Unsafe_SetConnectionsManager_Call { - _c.Call.Return(run) + _c.Run(run) return _c } diff --git a/core/services/feeds/service_test.go b/core/services/feeds/service_test.go index d449d585401..2277a160e7f 100644 --- a/core/services/feeds/service_test.go +++ b/core/services/feeds/service_test.go @@ -588,6 +588,12 @@ func Test_Service_CreateChainConfig(t *testing.T) { expectedID: int64(1), expectedChainType: proto.ChainType_CHAIN_TYPE_APTOS, }, + { + name: "Tron Chain Type", + chainType: feeds.ChainTypeTron, + expectedID: int64(1), + expectedChainType: proto.ChainType_CHAIN_TYPE_TRON, + }, } for _, tt := range tests { @@ -755,6 +761,11 @@ func Test_Service_UpdateChainConfig(t *testing.T) { chainType: feeds.ChainTypeAptos, expectedChainType: proto.ChainType_CHAIN_TYPE_APTOS, }, + { + name: "Tron Chain Type", + chainType: feeds.ChainTypeTron, + expectedChainType: proto.ChainType_CHAIN_TYPE_TRON, + }, } for _, tt := range tests { @@ -1722,6 +1733,11 @@ func Test_Service_SyncNodeInfo(t *testing.T) { chainType: feeds.ChainTypeAptos, protoType: proto.ChainType_CHAIN_TYPE_APTOS, }, + { + name: "Tron Chain Type", + chainType: feeds.ChainTypeTron, + protoType: proto.ChainType_CHAIN_TYPE_TRON, + }, } for _, tt := range tests { diff --git a/core/services/fluxmonitorv2/mocks/contract_submitter.go b/core/services/fluxmonitorv2/mocks/contract_submitter.go index 79143fdbfdd..79fda08d29e 100644 --- a/core/services/fluxmonitorv2/mocks/contract_submitter.go +++ b/core/services/fluxmonitorv2/mocks/contract_submitter.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/fluxmonitorv2/mocks/flags.go b/core/services/fluxmonitorv2/mocks/flags.go index f37acea31c8..f1b098f7de6 100644 --- a/core/services/fluxmonitorv2/mocks/flags.go +++ b/core/services/fluxmonitorv2/mocks/flags.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -25,7 +25,7 @@ func (_m *Flags) EXPECT() *Flags_Expecter { return &Flags_Expecter{mock: &_m.Mock} } -// Address provides a mock function with given fields: +// Address provides a mock function with no fields func (_m *Flags) Address() common.Address { ret := _m.Called() @@ -72,7 +72,7 @@ func (_c *Flags_Address_Call) RunAndReturn(run func() common.Address) *Flags_Add return _c } -// ContractExists provides a mock function with given fields: +// ContractExists provides a mock function with no fields func (_m *Flags) ContractExists() bool { ret := _m.Called() diff --git a/core/services/fluxmonitorv2/mocks/key_store_interface.go b/core/services/fluxmonitorv2/mocks/key_store_interface.go index c147c7b619e..67a28f97e9b 100644 --- a/core/services/fluxmonitorv2/mocks/key_store_interface.go +++ b/core/services/fluxmonitorv2/mocks/key_store_interface.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/fluxmonitorv2/mocks/orm.go b/core/services/fluxmonitorv2/mocks/orm.go index 6ccd5f40ebe..24f516dcdc2 100644 --- a/core/services/fluxmonitorv2/mocks/orm.go +++ b/core/services/fluxmonitorv2/mocks/orm.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/functions/mocks/bridge_accessor.go b/core/services/functions/mocks/bridge_accessor.go index 59f6f8f3db9..6672c55bee9 100644 --- a/core/services/functions/mocks/bridge_accessor.go +++ b/core/services/functions/mocks/bridge_accessor.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/functions/mocks/external_adapter_client.go b/core/services/functions/mocks/external_adapter_client.go index a7d76c44a35..661ed076e4a 100644 --- a/core/services/functions/mocks/external_adapter_client.go +++ b/core/services/functions/mocks/external_adapter_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/functions/mocks/functions_listener.go b/core/services/functions/mocks/functions_listener.go index 58acb7981e3..52011a70167 100644 --- a/core/services/functions/mocks/functions_listener.go +++ b/core/services/functions/mocks/functions_listener.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -22,7 +22,7 @@ func (_m *FunctionsListener) EXPECT() *FunctionsListener_Expecter { return &FunctionsListener_Expecter{mock: &_m.Mock} } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *FunctionsListener) Close() error { ret := _m.Called() diff --git a/core/services/functions/mocks/offchain_transmitter.go b/core/services/functions/mocks/offchain_transmitter.go index 9b61f9072e5..91ca230be64 100644 --- a/core/services/functions/mocks/offchain_transmitter.go +++ b/core/services/functions/mocks/offchain_transmitter.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -22,7 +22,7 @@ func (_m *OffchainTransmitter) EXPECT() *OffchainTransmitter_Expecter { return &OffchainTransmitter_Expecter{mock: &_m.Mock} } -// ReportChannel provides a mock function with given fields: +// ReportChannel provides a mock function with no fields func (_m *OffchainTransmitter) ReportChannel() chan *functions.OffchainResponse { ret := _m.Called() diff --git a/core/services/functions/mocks/orm.go b/core/services/functions/mocks/orm.go index 22e6368ac1f..4e7f9d393cb 100644 --- a/core/services/functions/mocks/orm.go +++ b/core/services/functions/mocks/orm.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/gateway/connector/mocks/gateway_connector.go b/core/services/gateway/connector/mocks/gateway_connector.go index ba5c2213b5f..51dcafe7091 100644 --- a/core/services/gateway/connector/mocks/gateway_connector.go +++ b/core/services/gateway/connector/mocks/gateway_connector.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -179,7 +179,7 @@ func (_c *GatewayConnector_ChallengeResponse_Call) RunAndReturn(run func(*url.UR return _c } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *GatewayConnector) Close() error { ret := _m.Called() @@ -224,7 +224,7 @@ func (_c *GatewayConnector_Close_Call) RunAndReturn(run func() error) *GatewayCo return _c } -// DonID provides a mock function with given fields: +// DonID provides a mock function with no fields func (_m *GatewayConnector) DonID() string { ret := _m.Called() @@ -269,7 +269,7 @@ func (_c *GatewayConnector_DonID_Call) RunAndReturn(run func() string) *GatewayC return _c } -// GatewayIDs provides a mock function with given fields: +// GatewayIDs provides a mock function with no fields func (_m *GatewayConnector) GatewayIDs() []string { ret := _m.Called() @@ -316,7 +316,7 @@ func (_c *GatewayConnector_GatewayIDs_Call) RunAndReturn(run func() []string) *G return _c } -// HealthReport provides a mock function with given fields: +// HealthReport provides a mock function with no fields func (_m *GatewayConnector) HealthReport() map[string]error { ret := _m.Called() @@ -363,7 +363,7 @@ func (_c *GatewayConnector_HealthReport_Call) RunAndReturn(run func() map[string return _c } -// Name provides a mock function with given fields: +// Name provides a mock function with no fields func (_m *GatewayConnector) Name() string { ret := _m.Called() @@ -466,7 +466,7 @@ func (_c *GatewayConnector_NewAuthHeader_Call) RunAndReturn(run func(*url.URL) ( return _c } -// Ready provides a mock function with given fields: +// Ready provides a mock function with no fields func (_m *GatewayConnector) Ready() error { ret := _m.Called() diff --git a/core/services/gateway/connector/mocks/gateway_connector_handler.go b/core/services/gateway/connector/mocks/gateway_connector_handler.go index 6f21cb9dd2f..424f608a9b5 100644 --- a/core/services/gateway/connector/mocks/gateway_connector_handler.go +++ b/core/services/gateway/connector/mocks/gateway_connector_handler.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -23,7 +23,7 @@ func (_m *GatewayConnectorHandler) EXPECT() *GatewayConnectorHandler_Expecter { return &GatewayConnectorHandler_Expecter{mock: &_m.Mock} } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *GatewayConnectorHandler) Close() error { ret := _m.Called() @@ -99,7 +99,7 @@ func (_c *GatewayConnectorHandler_HandleGatewayMessage_Call) Return() *GatewayCo } func (_c *GatewayConnectorHandler_HandleGatewayMessage_Call) RunAndReturn(run func(context.Context, string, *api.Message)) *GatewayConnectorHandler_HandleGatewayMessage_Call { - _c.Call.Return(run) + _c.Run(run) return _c } diff --git a/core/services/gateway/connector/mocks/signer.go b/core/services/gateway/connector/mocks/signer.go index 0f240b87e33..9b2aa0fd97a 100644 --- a/core/services/gateway/connector/mocks/signer.go +++ b/core/services/gateway/connector/mocks/signer.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/gateway/handlers/capabilities/webapi.go b/core/services/gateway/handlers/capabilities/webapi.go index a0213eb8f42..f4a324420c0 100644 --- a/core/services/gateway/handlers/capabilities/webapi.go +++ b/core/services/gateway/handlers/capabilities/webapi.go @@ -1,5 +1,7 @@ package capabilities +import "errors" + type Request struct { URL string `json:"url"` // URL to query, only http and https protocols are supported. Method string `json:"method,omitempty"` // HTTP verb, defaults to GET. @@ -16,6 +18,25 @@ type Response struct { Body []byte `json:"body,omitempty"` // HTTP response body } +// Validate ensures the Response struct is consistent. +func (r Response) Validate() error { + if r.ExecutionError { + if r.ErrorMessage == "" { + return errors.New("executionError is true but errorMessage is empty") + } + if r.StatusCode != 0 || len(r.Headers) > 0 || len(r.Body) > 0 { + return errors.New("executionError is true but response details (statusCode, headers, body) are populated") + } + return nil + } + + if r.StatusCode < 100 || r.StatusCode > 599 { + return errors.New("statusCode must be a valid HTTP status code (100-599)") + } + + return nil +} + type TriggerResponsePayload struct { ErrorMessage string `json:"error_message,omitempty"` // ERROR, ACCEPTED, PENDING, COMPLETED diff --git a/core/services/gateway/handlers/capabilities/webapi_test.go b/core/services/gateway/handlers/capabilities/webapi_test.go new file mode 100644 index 00000000000..2030c898053 --- /dev/null +++ b/core/services/gateway/handlers/capabilities/webapi_test.go @@ -0,0 +1,54 @@ +package capabilities + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestResponseValidate(t *testing.T) { + tt := []struct { + name string + response Response + expectError string + }{ + { + name: "valid Response with ExecutionError", + response: Response{ExecutionError: true, ErrorMessage: "Some error"}, + }, + { + name: "invalid Response with ExecutionError but no ErrorMessage", + response: Response{ExecutionError: true}, + expectError: "executionError is true but errorMessage is empty", + }, + { + name: "valid HTTP Response", + response: Response{StatusCode: 200}, + }, + { + name: "invalid status code", + response: Response{ + Body: []byte("body"), + }, + expectError: "statusCode must be set when executionError is false", + }, + { + name: "invalid HTTP Response with bad StatusCode", + response: Response{StatusCode: 700}, + expectError: "statusCode must be a valid HTTP status code (100-599)", + }, + } + + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + err := tc.response.Validate() + + if tc.expectError != "" { + require.Error(t, err) + return + } + + require.NoError(t, err) + }) + } +} diff --git a/core/services/gateway/handlers/functions/allowlist/mocks/onchain_allowlist.go b/core/services/gateway/handlers/functions/allowlist/mocks/onchain_allowlist.go index 78fb7d4ec4f..8340413718e 100644 --- a/core/services/gateway/handlers/functions/allowlist/mocks/onchain_allowlist.go +++ b/core/services/gateway/handlers/functions/allowlist/mocks/onchain_allowlist.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -69,7 +69,7 @@ func (_c *OnchainAllowlist_Allow_Call) RunAndReturn(run func(common.Address) boo return _c } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *OnchainAllowlist) Close() error { ret := _m.Called() diff --git a/core/services/gateway/handlers/functions/allowlist/mocks/orm.go b/core/services/gateway/handlers/functions/allowlist/mocks/orm.go index 8a3bddfda78..261e967c820 100644 --- a/core/services/gateway/handlers/functions/allowlist/mocks/orm.go +++ b/core/services/gateway/handlers/functions/allowlist/mocks/orm.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/gateway/handlers/functions/subscriptions/mocks/onchain_subscriptions.go b/core/services/gateway/handlers/functions/subscriptions/mocks/onchain_subscriptions.go index 48f0c6cdadb..7312f2a6743 100644 --- a/core/services/gateway/handlers/functions/subscriptions/mocks/onchain_subscriptions.go +++ b/core/services/gateway/handlers/functions/subscriptions/mocks/onchain_subscriptions.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -24,7 +24,7 @@ func (_m *OnchainSubscriptions) EXPECT() *OnchainSubscriptions_Expecter { return &OnchainSubscriptions_Expecter{mock: &_m.Mock} } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *OnchainSubscriptions) Close() error { ret := _m.Called() diff --git a/core/services/gateway/handlers/functions/subscriptions/mocks/orm.go b/core/services/gateway/handlers/functions/subscriptions/mocks/orm.go index 118c8d317a1..c093bd1523e 100644 --- a/core/services/gateway/handlers/functions/subscriptions/mocks/orm.go +++ b/core/services/gateway/handlers/functions/subscriptions/mocks/orm.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/gateway/handlers/mocks/don.go b/core/services/gateway/handlers/mocks/don.go index 7e28a1c5e97..93ab52c2473 100644 --- a/core/services/gateway/handlers/mocks/don.go +++ b/core/services/gateway/handlers/mocks/don.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/gateway/handlers/mocks/handler.go b/core/services/gateway/handlers/mocks/handler.go index 3f129a9ca83..96f3faad15c 100644 --- a/core/services/gateway/handlers/mocks/handler.go +++ b/core/services/gateway/handlers/mocks/handler.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -25,7 +25,7 @@ func (_m *Handler) EXPECT() *Handler_Expecter { return &Handler_Expecter{mock: &_m.Mock} } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *Handler) Close() error { ret := _m.Called() diff --git a/core/services/gateway/network/httpclient.go b/core/services/gateway/network/httpclient.go index 52130c8d069..21de0b8b9f4 100644 --- a/core/services/gateway/network/httpclient.go +++ b/core/services/gateway/network/httpclient.go @@ -3,11 +3,14 @@ package network import ( "bytes" "context" + "errors" "io" "net/http" "strings" "time" + "github.com/doyensec/safeurl" + "github.com/smartcontractkit/chainlink-common/pkg/logger" ) @@ -19,6 +22,31 @@ type HTTPClient interface { type HTTPClientConfig struct { MaxResponseBytes uint32 DefaultTimeout time.Duration + BlockedIPs []string + BlockedIPsCIDR []string + AllowedPorts []int + AllowedSchemes []string + + // for testing + allowedIPs []string +} + +var ( + defaultAllowedPorts = []int{80, 443} + defaultAllowedSchemes = []string{"http", "https"} +) + +func (c *HTTPClientConfig) ApplyDefaults() { + if len(c.AllowedPorts) == 0 { + c.AllowedPorts = defaultAllowedPorts + } + + if len(c.AllowedSchemes) == 0 { + c.AllowedSchemes = defaultAllowedSchemes + } + + // safeurl automatically blocks internal IPs so no need + // to set defaults here. } type HTTPRequest struct { @@ -35,7 +63,7 @@ type HTTPResponse struct { } type httpClient struct { - client *http.Client + client *safeurl.WrappedClient config HTTPClientConfig lggr logger.Logger } @@ -43,16 +71,30 @@ type httpClient struct { // NewHTTPClient creates a new NewHTTPClient // As of now, the client does not support TLS configuration but may be extended in the future func NewHTTPClient(config HTTPClientConfig, lggr logger.Logger) (HTTPClient, error) { + config.ApplyDefaults() + safeConfig := safeurl. + GetConfigBuilder(). + SetTimeout(config.DefaultTimeout). + SetAllowedIPs(config.allowedIPs...). + SetAllowedPorts(config.AllowedPorts...). + SetAllowedSchemes(config.AllowedSchemes...). + SetBlockedIPs(config.BlockedIPs...). + SetBlockedIPsCIDR(config.BlockedIPsCIDR...). + SetCheckRedirect(disableRedirects). + EnableDebugLogging(true). + Build() + return &httpClient{ config: config, - client: &http.Client{ - Timeout: config.DefaultTimeout, - Transport: http.DefaultTransport, - }, - lggr: lggr, + client: safeurl.Client(safeConfig), + lggr: lggr, }, nil } +func disableRedirects(req *http.Request, via []*http.Request) error { + return errors.New("redirects are not allowed") +} + func (c *httpClient) Send(ctx context.Context, req HTTPRequest) (*HTTPResponse, error) { timeoutCtx, cancel := context.WithTimeout(ctx, req.Timeout) defer cancel() diff --git a/core/services/gateway/network/httpclient_test.go b/core/services/gateway/network/httpclient_test.go index 2f4cc448ef5..d6ccdbdce11 100644 --- a/core/services/gateway/network/httpclient_test.go +++ b/core/services/gateway/network/httpclient_test.go @@ -1,16 +1,19 @@ -package network_test +//go:debug netdns=go +package network import ( "context" + "errors" "net/http" "net/http/httptest" + "net/url" + "strconv" "testing" "time" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/gateway/network" ) func TestHTTPClient_Send(t *testing.T) { @@ -18,20 +21,13 @@ func TestHTTPClient_Send(t *testing.T) { // Setup the test environment lggr := logger.Test(t) - config := network.HTTPClientConfig{ - MaxResponseBytes: 1024, - DefaultTimeout: 5 * time.Second, - } - client, err := network.NewHTTPClient(config, lggr) - require.NoError(t, err) - // Define test cases tests := []struct { name string setupServer func() *httptest.Server - request network.HTTPRequest + request HTTPRequest expectedError error - expectedResp *network.HTTPResponse + expectedResp *HTTPResponse }{ { name: "successful request", @@ -42,7 +38,7 @@ func TestHTTPClient_Send(t *testing.T) { require.NoError(t, err2) })) }, - request: network.HTTPRequest{ + request: HTTPRequest{ Method: "GET", URL: "/", Headers: map[string]string{}, @@ -50,7 +46,7 @@ func TestHTTPClient_Send(t *testing.T) { Timeout: 2 * time.Second, }, expectedError: nil, - expectedResp: &network.HTTPResponse{ + expectedResp: &HTTPResponse{ StatusCode: http.StatusOK, Headers: map[string]string{"Content-Length": "7"}, Body: []byte("success"), @@ -66,7 +62,7 @@ func TestHTTPClient_Send(t *testing.T) { require.NoError(t, err2) })) }, - request: network.HTTPRequest{ + request: HTTPRequest{ Method: "GET", URL: "/", Headers: map[string]string{}, @@ -85,7 +81,7 @@ func TestHTTPClient_Send(t *testing.T) { require.NoError(t, err2) })) }, - request: network.HTTPRequest{ + request: HTTPRequest{ Method: "GET", URL: "/", Headers: map[string]string{}, @@ -93,7 +89,7 @@ func TestHTTPClient_Send(t *testing.T) { Timeout: 2 * time.Second, }, expectedError: nil, - expectedResp: &network.HTTPResponse{ + expectedResp: &HTTPResponse{ StatusCode: http.StatusInternalServerError, Headers: map[string]string{"Content-Length": "5"}, Body: []byte("error"), @@ -108,7 +104,7 @@ func TestHTTPClient_Send(t *testing.T) { require.NoError(t, err2) })) }, - request: network.HTTPRequest{ + request: HTTPRequest{ Method: "GET", URL: "/", Headers: map[string]string{}, @@ -118,6 +114,29 @@ func TestHTTPClient_Send(t *testing.T) { expectedError: &http.MaxBytesError{}, expectedResp: nil, }, + { + name: "redirects are blocked", + setupServer: func() *httptest.Server { + count := 0 + return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + count++ + if count <= 1 { + http.Redirect(w, r, "/", http.StatusMovedPermanently) + } else { + w.WriteHeader(http.StatusOK) + } + count++ + })) + }, + request: HTTPRequest{ + Method: "GET", + URL: "/", + Headers: map[string]string{}, + Body: nil, + Timeout: 2 * time.Second, + }, + expectedError: errors.New("redirects are not allowed"), + }, } // Execute test cases @@ -126,6 +145,23 @@ func TestHTTPClient_Send(t *testing.T) { server := tt.setupServer() defer server.Close() + u, err := url.Parse(server.URL) + require.NoError(t, err) + + hostname, port := u.Hostname(), u.Port() + portInt, err := strconv.ParseInt(port, 10, 32) + require.NoError(t, err) + + config := HTTPClientConfig{ + MaxResponseBytes: 1024, + DefaultTimeout: 5 * time.Second, + allowedIPs: []string{hostname}, + AllowedPorts: []int{int(portInt)}, + } + + client, err := NewHTTPClient(config, lggr) + require.NoError(t, err) + tt.request.URL = server.URL + tt.request.URL resp, err := client.Send(context.Background(), tt.request) @@ -145,3 +181,211 @@ func TestHTTPClient_Send(t *testing.T) { }) } } + +// IMPORTANT: The behaviour of Go's network stack is heavily dependent on the platform; +// this means that the errors returned can change depending on whether the tests are +// run on osx or on linux. +func TestHTTPClient_BlocksUnallowed(t *testing.T) { + t.Parallel() + + // Setup the test environment + lggr := logger.Test(t) + // Define test cases + tests := []struct { + name string + url string + expectedError string + blockPort bool + }{ + { + name: "blocked port", + url: "http://177.0.0.1:8080", + expectedError: "port: 8080 not found in allowlist", + blockPort: true, + }, + { + name: "blocked scheme", + url: "file://127.0.0.1", + expectedError: "scheme: file not found in allowlist", + }, + { + name: "explicitly blocked IP", + url: "http://169.254.0.1", + expectedError: "ip: 169.254.0.1 not found in allowlist", + }, + { + name: "explicitly blocked IP - internal network", + url: "http://169.254.0.1", + expectedError: "ip: 169.254.0.1 not found in allowlist", + }, + { + name: "explicitly blocked IP - loopback", + url: "http://127.0.0.1", + expectedError: "ip: 127.0.0.1 not found in allowlist", + }, + { + name: "explicitly blocked IP - loopback without scheme", + url: "127.0.0.1", + expectedError: "host: is not valid", + }, + { + name: "explicitly blocked IP - loopback", + url: "https://⑫7.0.0.1", + expectedError: "ip: 127.0.0.1 not found in allowlist", + }, + { + name: "explicitly blocked IP - loopback shortened", + url: "https://127.1", + expectedError: "no such host", + }, + { + name: "explicitly blocked IP - loopback shortened", + url: "https://127.0.1", + expectedError: "no such host", + }, + { + name: "explicitly blocked IP - loopback hex encoded with separators", + url: `https://0x7F.0x00.0x00.0x01`, + expectedError: "no such host", + }, + { + name: "explicitly blocked IP - loopback octal encoded", + url: `https://0177.0000.0000.0001`, + expectedError: "no such host", + }, + { + name: "explicitly blocked IP - loopback binary encoded", + url: `https://01111111.00000000.00000000.00000001`, + expectedError: "no such host", + }, + { + name: "explicitly blocked IP - loopback - dword no escape", + url: "https://2130706433", + expectedError: "no such host", + }, + { + name: "explicitly blocked IP - loopback - dword with overflow no escape", + url: "https://45080379393", + expectedError: "no such host", + }, + { + name: "explicitly blocked IP - loopback - ipv6", + url: `https://[::1]`, + expectedError: "ipv6 blocked", + }, + { + name: "explicitly blocked IP - loopback ipv6 mapped ipv4", + url: `https://[::FFF:7F00:0001]`, + expectedError: "ipv6 blocked", + }, + { + name: "explicitly blocked IP - loopback ipv6 mapped ipv4", + url: `https://[::FFFF:127.0.0.1]`, + expectedError: "ip: 127.0.0.1 not found in allowlist", + }, + { + name: "explicitly blocked IP - loopback long-form", + url: `https://[0000:0000:0000:0000:0000:0000:0000:0001]`, + expectedError: "ipv6 blocked", + }, + { + name: "explicitly blocked IP - current network", + url: "http://0.0.0.0/endpoint", + expectedError: "ip: 0.0.0.0 not found in allowlist", + }, + { + name: "explicitly blocked IP - current network - octal", + url: "http://0000.0000.0000.0001", + expectedError: "no such host", + }, + { + name: "explicitly blocked IP - current network - hex", + url: "http://0x00.0x00.0x00.0x01", + expectedError: "no such host", + }, + { + name: "explicitly blocked IP - current network - binary", + url: "http://00000000.00000000.00000000.00000001", + expectedError: "no such host", + }, + { + name: "explicitly blocked IP - current network - shortened", + url: "http://1", + expectedError: "no such host", + }, + { + name: "explicitly blocked IP - current network - shortened", + url: "http://0.1", + expectedError: "no such host", + }, + { + name: "explicitly blocked IP - current network - shortened", + url: "http://0.0.1", + expectedError: "no such host", + }, + { + name: "explicitly blocked IP - dword", + url: "http://42949672961", + expectedError: "no such host", + }, + { + name: "explicitly blocked IP - ipv6 mapped", + url: "http://[::FFFF:0000:0001]", + expectedError: "ip: 0.0.0.1 not found in allowlist", + }, + { + name: "explicitly blocked IP - ipv6 mapped", + url: "http://[::FFFF:0.0.0.1]", + expectedError: "ip: 0.0.0.1 not found in allowlist", + }, + } + + // Execute test cases + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + testURL, err := url.Parse(tt.url) + require.NoError(t, err) + + if testURL.Port() == "" { + // Setup a test server so the request succeeds if we don't block it, then modify the URL to add the port to it. + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + })) + defer server.Close() + + u, ierr := url.Parse(server.URL) + require.NoError(t, ierr) + + testURL.Host = testURL.Hostname() + ":" + u.Port() + } + + portInt, err := strconv.ParseInt(testURL.Port(), 10, 64) + require.NoError(t, err) + + allowedPorts := []int{} + if !tt.blockPort { + allowedPorts = []int{int(portInt)} + } + + config := HTTPClientConfig{ + MaxResponseBytes: 1024, + DefaultTimeout: 5 * time.Second, + AllowedPorts: allowedPorts, + } + + client, err := NewHTTPClient(config, lggr) + require.NoError(t, err) + + require.NoError(t, err) + _, err = client.Send(context.Background(), HTTPRequest{ + Method: "GET", + URL: testURL.String(), + Headers: map[string]string{}, + Body: nil, + Timeout: 1 * time.Second, + }) + require.Error(t, err) + require.ErrorContains(t, err, tt.expectedError) + }) + } +} diff --git a/core/services/gateway/network/mocks/connection_acceptor.go b/core/services/gateway/network/mocks/connection_acceptor.go index 4c2aaaabb18..48bcf9884a6 100644 --- a/core/services/gateway/network/mocks/connection_acceptor.go +++ b/core/services/gateway/network/mocks/connection_acceptor.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -50,7 +50,7 @@ func (_c *ConnectionAcceptor_AbortHandshake_Call) Return() *ConnectionAcceptor_A } func (_c *ConnectionAcceptor_AbortHandshake_Call) RunAndReturn(run func(string)) *ConnectionAcceptor_AbortHandshake_Call { - _c.Call.Return(run) + _c.Run(run) return _c } diff --git a/core/services/gateway/network/mocks/connection_initiator.go b/core/services/gateway/network/mocks/connection_initiator.go index 2c18ad59cb5..5bf10d01aa9 100644 --- a/core/services/gateway/network/mocks/connection_initiator.go +++ b/core/services/gateway/network/mocks/connection_initiator.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/gateway/network/mocks/http_client.go b/core/services/gateway/network/mocks/http_client.go index 2702cbd83fd..29bf4348036 100644 --- a/core/services/gateway/network/mocks/http_client.go +++ b/core/services/gateway/network/mocks/http_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/gateway/network/mocks/http_request_handler.go b/core/services/gateway/network/mocks/http_request_handler.go index 39b3c71be52..2756bddb3db 100644 --- a/core/services/gateway/network/mocks/http_request_handler.go +++ b/core/services/gateway/network/mocks/http_request_handler.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/gateway/network/mocks/http_server.go b/core/services/gateway/network/mocks/http_server.go index 0e29525bfc3..ae51ffaa512 100644 --- a/core/services/gateway/network/mocks/http_server.go +++ b/core/services/gateway/network/mocks/http_server.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -22,7 +22,7 @@ func (_m *HttpServer) EXPECT() *HttpServer_Expecter { return &HttpServer_Expecter{mock: &_m.Mock} } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *HttpServer) Close() error { ret := _m.Called() @@ -67,7 +67,7 @@ func (_c *HttpServer_Close_Call) RunAndReturn(run func() error) *HttpServer_Clos return _c } -// GetPort provides a mock function with given fields: +// GetPort provides a mock function with no fields func (_m *HttpServer) GetPort() int { ret := _m.Called() @@ -141,7 +141,7 @@ func (_c *HttpServer_SetHTTPRequestHandler_Call) Return() *HttpServer_SetHTTPReq } func (_c *HttpServer_SetHTTPRequestHandler_Call) RunAndReturn(run func(network.HTTPRequestHandler)) *HttpServer_SetHTTPRequestHandler_Call { - _c.Call.Return(run) + _c.Run(run) return _c } diff --git a/core/services/gateway/network/mocks/web_socket_server.go b/core/services/gateway/network/mocks/web_socket_server.go index 96e8a8ee22d..34e478533ee 100644 --- a/core/services/gateway/network/mocks/web_socket_server.go +++ b/core/services/gateway/network/mocks/web_socket_server.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -21,7 +21,7 @@ func (_m *WebSocketServer) EXPECT() *WebSocketServer_Expecter { return &WebSocketServer_Expecter{mock: &_m.Mock} } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *WebSocketServer) Close() error { ret := _m.Called() @@ -66,7 +66,7 @@ func (_c *WebSocketServer_Close_Call) RunAndReturn(run func() error) *WebSocketS return _c } -// GetPort provides a mock function with given fields: +// GetPort provides a mock function with no fields func (_m *WebSocketServer) GetPort() int { ret := _m.Called() diff --git a/core/services/headreporter/head_reporter_mock.go b/core/services/headreporter/head_reporter_mock.go index ad9923fd179..1636aec4631 100644 --- a/core/services/headreporter/head_reporter_mock.go +++ b/core/services/headreporter/head_reporter_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package headreporter diff --git a/core/services/headreporter/prometheus_backend_mock.go b/core/services/headreporter/prometheus_backend_mock.go index ebcc88b9722..031b5d4c937 100644 --- a/core/services/headreporter/prometheus_backend_mock.go +++ b/core/services/headreporter/prometheus_backend_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package headreporter @@ -51,7 +51,7 @@ func (_c *MockPrometheusBackend_SetMaxUnconfirmedAge_Call) Return() *MockPrometh } func (_c *MockPrometheusBackend_SetMaxUnconfirmedAge_Call) RunAndReturn(run func(*big.Int, float64)) *MockPrometheusBackend_SetMaxUnconfirmedAge_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -85,7 +85,7 @@ func (_c *MockPrometheusBackend_SetMaxUnconfirmedBlocks_Call) Return() *MockProm } func (_c *MockPrometheusBackend_SetMaxUnconfirmedBlocks_Call) RunAndReturn(run func(*big.Int, int64)) *MockPrometheusBackend_SetMaxUnconfirmedBlocks_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -118,7 +118,7 @@ func (_c *MockPrometheusBackend_SetPipelineRunsQueued_Call) Return() *MockPromet } func (_c *MockPrometheusBackend_SetPipelineRunsQueued_Call) RunAndReturn(run func(int)) *MockPrometheusBackend_SetPipelineRunsQueued_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -151,7 +151,7 @@ func (_c *MockPrometheusBackend_SetPipelineTaskRunsQueued_Call) Return() *MockPr } func (_c *MockPrometheusBackend_SetPipelineTaskRunsQueued_Call) RunAndReturn(run func(int)) *MockPrometheusBackend_SetPipelineTaskRunsQueued_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -185,7 +185,7 @@ func (_c *MockPrometheusBackend_SetUnconfirmedTransactions_Call) Return() *MockP } func (_c *MockPrometheusBackend_SetUnconfirmedTransactions_Call) RunAndReturn(run func(*big.Int, int64)) *MockPrometheusBackend_SetUnconfirmedTransactions_Call { - _c.Call.Return(run) + _c.Run(run) return _c } diff --git a/core/services/headreporter/prometheus_reporter_test.go b/core/services/headreporter/prometheus_reporter_test.go index 9fd42baa15e..9d2a2bb18a6 100644 --- a/core/services/headreporter/prometheus_reporter_test.go +++ b/core/services/headreporter/prometheus_reporter_test.go @@ -135,7 +135,8 @@ func newLegacyChainContainer(t *testing.T, db *sqlx.DB) legacyevm.LegacyChainCon lp, keyStore, estimator, - ht) + ht, + nil) require.NoError(t, err) cfg := configtest.NewGeneralConfig(t, nil) diff --git a/core/services/job/job_orm_test.go b/core/services/job/job_orm_test.go index 27223e0d706..6e7a0b2a034 100644 --- a/core/services/job/job_orm_test.go +++ b/core/services/job/job_orm_test.go @@ -1020,6 +1020,18 @@ func TestORM_ValidateKeyStoreMatch(t *testing.T) { require.NoError(t, err) }) + t.Run(("test Tron key validation"), func(t *testing.T) { + ctx := testutils.Context(t) + jb.OCR2OracleSpec.Relay = relay.NetworkTron + err := job.ValidateKeyStoreMatch(ctx, jb.OCR2OracleSpec, keyStore, "bad key") + require.EqualError(t, err, "no Tron key matching: \"bad key\"") + + tronKey, err := keyStore.Tron().Create(ctx) + require.NoError(t, err) + err = job.ValidateKeyStoreMatch(ctx, jb.OCR2OracleSpec, keyStore, tronKey.ID()) + require.NoError(t, err) + }) + t.Run("test Mercury ETH key validation", func(t *testing.T) { ctx := testutils.Context(t) jb.OCR2OracleSpec.PluginType = types.Mercury @@ -2107,7 +2119,8 @@ func TestORM_CreateJob_OCR2_With_DualTransmission(t *testing.T) { require.ErrorContains(t, jobORM.CreateJob(ctx, &jb), "invalid transmitter address in dual transmission config") dtTransmitterAddress := cltest.MustGenerateRandomKey(t) - completeDualTransmissionSpec := fmt.Sprintf(` + + metaNotSliceDualTransmissionSpec := fmt.Sprintf(` enableDualTransmission=true [relayConfig.dualTransmission] contractAddress = '0x613a38AC1659769640aaE063C651F48E0250454C' @@ -2118,6 +2131,96 @@ func TestORM_CreateJob_OCR2_With_DualTransmission(t *testing.T) { `, dtTransmitterAddress.Address.String()) + jb, err = ocr2validate.ValidatedOracleSpecToml(testutils.Context(t), config.OCR2(), config.Insecure(), baseJobSpec+metaNotSliceDualTransmissionSpec, nil) + require.NoError(t, err) + require.ErrorContains(t, jobORM.CreateJob(ctx, &jb), "dual transmission meta value key1 is not a slice") + + hintNotValidDualTransmissionSpec := fmt.Sprintf(` + enableDualTransmission=true + [relayConfig.dualTransmission] + contractAddress = '0x613a38AC1659769640aaE063C651F48E0250454C' + transmitterAddress = '%s' + [relayConfig.dualTransmission.meta] + hint = ['some-invalid-hint'] + key2 = ['val2','val3'] + `, + dtTransmitterAddress.Address.String()) + + jb, err = ocr2validate.ValidatedOracleSpecToml(testutils.Context(t), config.OCR2(), config.Insecure(), baseJobSpec+hintNotValidDualTransmissionSpec, nil) + require.NoError(t, err) + require.ErrorContains(t, jobORM.CreateJob(ctx, &jb), "dual transmission meta.hint value some-invalid-hint should be one of the following [contract_address function_selector logs calldata default_logs]") + + invalidRefundFormatDualTransmissionSpec := fmt.Sprintf(` + enableDualTransmission=true + [relayConfig.dualTransmission] + contractAddress = '0x613a38AC1659769640aaE063C651F48E0250454C' + transmitterAddress = '%s' + [relayConfig.dualTransmission.meta] + hint = ['calldata','logs'] + refund = ['0x00'] + `, + dtTransmitterAddress.Address.String()) + + jb, err = ocr2validate.ValidatedOracleSpecToml(testutils.Context(t), config.OCR2(), config.Insecure(), baseJobSpec+invalidRefundFormatDualTransmissionSpec, nil) + require.NoError(t, err) + require.ErrorContains(t, jobORM.CreateJob(ctx, &jb), "invalid dual transmission refund, format should be
:") + + invalidRefundAddressFormatDualTransmissionSpec := fmt.Sprintf(` + enableDualTransmission=true + [relayConfig.dualTransmission] + contractAddress = '0x613a38AC1659769640aaE063C651F48E0250454C' + transmitterAddress = '%s' + [relayConfig.dualTransmission.meta] + hint = ['calldata','logs'] + refund = ['0x000:50'] + `, + dtTransmitterAddress.Address.String()) + + jb, err = ocr2validate.ValidatedOracleSpecToml(testutils.Context(t), config.OCR2(), config.Insecure(), baseJobSpec+invalidRefundAddressFormatDualTransmissionSpec, nil) + require.NoError(t, err) + require.ErrorContains(t, jobORM.CreateJob(ctx, &jb), "invalid dual transmission refund address, 0x000 is not a valid address") + + invalidRefundPercentFormatDualTransmissionSpec := fmt.Sprintf(` + enableDualTransmission=true + [relayConfig.dualTransmission] + contractAddress = '0x613a38AC1659769640aaE063C651F48E0250454C' + transmitterAddress = '%s' + [relayConfig.dualTransmission.meta] + hint = ['calldata','logs'] + refund = ['0x0000000000000000000000000000000000000000:A'] + `, + dtTransmitterAddress.Address.String()) + + jb, err = ocr2validate.ValidatedOracleSpecToml(testutils.Context(t), config.OCR2(), config.Insecure(), baseJobSpec+invalidRefundPercentFormatDualTransmissionSpec, nil) + require.NoError(t, err) + require.ErrorContains(t, jobORM.CreateJob(ctx, &jb), "invalid dual transmission refund percent, A is not a number") + + invalidRefundPercentTotalFormatDualTransmissionSpec := fmt.Sprintf(` + enableDualTransmission=true + [relayConfig.dualTransmission] + contractAddress = '0x613a38AC1659769640aaE063C651F48E0250454C' + transmitterAddress = '%s' + [relayConfig.dualTransmission.meta] + hint = ['calldata','logs'] + refund = ['0x0000000000000000000000000000000000000000:50','0x0000000000000000000000000000000000000001:50'] + `, + dtTransmitterAddress.Address.String()) + + jb, err = ocr2validate.ValidatedOracleSpecToml(testutils.Context(t), config.OCR2(), config.Insecure(), baseJobSpec+invalidRefundPercentTotalFormatDualTransmissionSpec, nil) + require.NoError(t, err) + require.ErrorContains(t, jobORM.CreateJob(ctx, &jb), "invalid dual transmission refund percentages, total sum of percentages must be less than 100") + + completeDualTransmissionSpec := fmt.Sprintf(` + enableDualTransmission=true + [relayConfig.dualTransmission] + contractAddress = '0x613a38AC1659769640aaE063C651F48E0250454C' + transmitterAddress = '%s' + [relayConfig.dualTransmission.meta] + key1 = ['val1'] + key2 = ['val2','val3'] + `, + dtTransmitterAddress.Address.String()) + jb, err = ocr2validate.ValidatedOracleSpecToml(testutils.Context(t), config.OCR2(), config.Insecure(), baseJobSpec+completeDualTransmissionSpec, nil) require.NoError(t, err) diff --git a/core/services/job/mocks/kv_store.go b/core/services/job/mocks/kv_store.go index 5a606b12cca..7fe62ded59e 100644 --- a/core/services/job/mocks/kv_store.go +++ b/core/services/job/mocks/kv_store.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/job/mocks/orm.go b/core/services/job/mocks/orm.go index 96513866f37..170dfa25c58 100644 --- a/core/services/job/mocks/orm.go +++ b/core/services/job/mocks/orm.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -81,7 +81,7 @@ func (_c *ORM_AssertBridgesExist_Call) RunAndReturn(run func(context.Context, pi return _c } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *ORM) Close() error { ret := _m.Called() @@ -230,7 +230,7 @@ func (_c *ORM_CreateJob_Call) RunAndReturn(run func(context.Context, *job.Job) e return _c } -// DataSource provides a mock function with given fields: +// DataSource provides a mock function with no fields func (_m *ORM) DataSource() sqlutil.DataSource { ret := _m.Called() @@ -1609,7 +1609,7 @@ func (_c *ORM_TryRecordError_Call) Return() *ORM_TryRecordError_Call { } func (_c *ORM_TryRecordError_Call) RunAndReturn(run func(context.Context, int32, string)) *ORM_TryRecordError_Call { - _c.Call.Return(run) + _c.Run(run) return _c } diff --git a/core/services/job/mocks/service_ctx.go b/core/services/job/mocks/service_ctx.go index d7ac02bfd0e..8f1ba3596c1 100644 --- a/core/services/job/mocks/service_ctx.go +++ b/core/services/job/mocks/service_ctx.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -21,7 +21,7 @@ func (_m *ServiceCtx) EXPECT() *ServiceCtx_Expecter { return &ServiceCtx_Expecter{mock: &_m.Mock} } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *ServiceCtx) Close() error { ret := _m.Called() diff --git a/core/services/job/mocks/spawner.go b/core/services/job/mocks/spawner.go index aa40522f358..a8039643bd5 100644 --- a/core/services/job/mocks/spawner.go +++ b/core/services/job/mocks/spawner.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -24,7 +24,7 @@ func (_m *Spawner) EXPECT() *Spawner_Expecter { return &Spawner_Expecter{mock: &_m.Mock} } -// ActiveJobs provides a mock function with given fields: +// ActiveJobs provides a mock function with no fields func (_m *Spawner) ActiveJobs() map[int32]job.Job { ret := _m.Called() @@ -71,7 +71,7 @@ func (_c *Spawner_ActiveJobs_Call) RunAndReturn(run func() map[int32]job.Job) *S return _c } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *Spawner) Close() error { ret := _m.Called() @@ -212,7 +212,7 @@ func (_c *Spawner_DeleteJob_Call) RunAndReturn(run func(context.Context, sqlutil return _c } -// HealthReport provides a mock function with given fields: +// HealthReport provides a mock function with no fields func (_m *Spawner) HealthReport() map[string]error { ret := _m.Called() @@ -259,7 +259,7 @@ func (_c *Spawner_HealthReport_Call) RunAndReturn(run func() map[string]error) * return _c } -// Name provides a mock function with given fields: +// Name provides a mock function with no fields func (_m *Spawner) Name() string { ret := _m.Called() @@ -304,7 +304,7 @@ func (_c *Spawner_Name_Call) RunAndReturn(run func() string) *Spawner_Name_Call return _c } -// Ready provides a mock function with given fields: +// Ready provides a mock function with no fields func (_m *Spawner) Ready() error { ret := _m.Called() diff --git a/core/services/job/models.go b/core/services/job/models.go index 26d563c7ac8..63e521c5b3b 100644 --- a/core/services/job/models.go +++ b/core/services/job/models.go @@ -935,7 +935,7 @@ func (w *WorkflowSpec) SDKSpec(ctx context.Context) (sdk.WorkflowSpec, error) { } spec, rawSpec, cid, err := workflowSpecFactory.Spec(ctx, w.Workflow, w.Config) if err != nil { - return sdk.WorkflowSpec{}, err + return sdk.WorkflowSpec{}, fmt.Errorf("spec factory failed: %w", err) } w.sdkWorkflow = &spec w.rawSpec = rawSpec diff --git a/core/services/job/orm.go b/core/services/job/orm.go index cfd8060d60c..62cc2cd596a 100644 --- a/core/services/job/orm.go +++ b/core/services/job/orm.go @@ -7,6 +7,8 @@ import ( "fmt" "reflect" "slices" + "strconv" + "strings" "time" "github.com/ethereum/go-ethereum/common" @@ -326,9 +328,19 @@ func (o *orm) CreateJob(ctx context.Context, jb *Job) error { return errors.New("invalid transmitter address in dual transmission config") } + rawMeta, ok := dualTransmissionConfig["meta"].(map[string]interface{}) + if !ok { + return errors.New("invalid dual transmission meta") + } + + if err = validateDualTransmissionMeta(rawMeta); err != nil { + return err + } + if err = validateKeyStoreMatchForRelay(ctx, jb.OCR2OracleSpec.Relay, tx.keyStore, dtTransmitterAddress); err != nil { return errors.Wrap(err, "unknown dual transmission transmitterAddress") } + } specID, err := tx.insertOCR2OracleSpec(ctx, jb.OCR2OracleSpec) @@ -658,6 +670,11 @@ func validateKeyStoreMatchForRelay(ctx context.Context, network string, keyStore if err != nil { return errors.Errorf("no Aptos key matching: %q", key) } + case relay.NetworkTron: + _, err := keyStore.Tron().Get(key) + if err != nil { + return errors.Errorf("no Tron key matching: %q", key) + } } return nil } @@ -1664,3 +1681,67 @@ func (r legacyGasStationServerSpecRow) toLegacyGasStationServerSpec() *LegacyGas func (o *orm) loadJobSpecErrors(ctx context.Context, jb *Job) error { return errors.Wrapf(o.ds.SelectContext(ctx, &jb.JobSpecErrors, `SELECT * FROM job_spec_errors WHERE job_id = $1`, jb.ID), "failed to load job spec errors for job %d", jb.ID) } + +func validateDualTransmissionHint(vals []interface{}) error { + accepted := []string{"contract_address", "function_selector", "logs", "calldata", "default_logs"} + for _, v := range vals { + valString, ok := v.(string) + if !ok { + return errors.Errorf("dual transmission meta value %v is not a string", v) + } + if !slices.Contains(accepted, valString) { + return errors.Errorf("dual transmission meta.hint value %s should be one of the following %s", valString, accepted) + } + } + return nil +} + +func validateDualTransmissionRefund(vals []interface{}) error { + totalRefund := 0 + for _, v := range vals { + valString, ok := v.(string) + if !ok { + return errors.Errorf("dual transmission meta value %v is not a string", v) + } + + s := strings.Split(valString, ":") + if len(s) != 2 { + return errors.New("invalid dual transmission refund, format should be
:") + } + if !common.IsHexAddress(s[0]) { + return errors.Errorf("invalid dual transmission refund address, %s is not a valid address", s[0]) + } + percent, err := strconv.Atoi(s[1]) + if err != nil { + return errors.Errorf("invalid dual transmission refund percent, %s is not a number", s[1]) + } + totalRefund += percent + } + + if totalRefund >= 100 { + return errors.New("invalid dual transmission refund percentages, total sum of percentages must be less than 100") + } + return nil +} + +func validateDualTransmissionMeta(meta map[string]interface{}) error { + for k, v := range meta { + metaFieldValues, ok := v.([]interface{}) + if !ok { + return errors.Errorf("dual transmission meta value %s is not a slice", k) + } + if k == "hint" { + if err := validateDualTransmissionHint(metaFieldValues); err != nil { + return err + } + } + + if k == "refund" { + if err := validateDualTransmissionRefund(metaFieldValues); err != nil { + return err + } + } + } + + return nil +} diff --git a/core/services/keeper/registry_interface.go b/core/services/keeper/registry_interface.go index 04bcb8e257d..b37917cef60 100644 --- a/core/services/keeper/registry_interface.go +++ b/core/services/keeper/registry_interface.go @@ -16,7 +16,7 @@ import ( registry1_1 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_1" registry1_2 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_2" registry1_3 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_3" - type_and_version "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/type_and_version_interface_wrapper" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/type_and_version" ) type RegistryVersion int32 @@ -61,14 +61,14 @@ type RegistryWrapper struct { } func NewRegistryWrapper(address evmtypes.EIP55Address, evmClient evmclient.Client) (*RegistryWrapper, error) { - interface_wrapper, err := type_and_version.NewTypeAndVersionInterface( + interfaceWrapper, err := type_and_version.NewITypeAndVersion( address.Address(), evmClient, ) if err != nil { return nil, errors.Wrap(err, "unable to create type and interface wrapper") } - version, err := getRegistryVersion(interface_wrapper) + version, err := getRegistryVersion(interfaceWrapper) if err != nil { return nil, errors.Wrap(err, "unable to determine version of keeper registry contract") } @@ -105,7 +105,7 @@ func NewRegistryWrapper(address evmtypes.EIP55Address, evmClient evmclient.Clien }, nil } -func getRegistryVersion(contract *type_and_version.TypeAndVersionInterface) (*RegistryVersion, error) { +func getRegistryVersion(contract *type_and_version.ITypeAndVersion) (*RegistryVersion, error) { typeAndVersion, err := contract.TypeAndVersion(nil) if err != nil { jsonErr := evmclient.ExtractRPCErrorOrNil(err) diff --git a/core/services/keystore/chaintype/chaintype.go b/core/services/keystore/chaintype/chaintype.go index 419dfa2d073..8aca72d4f83 100644 --- a/core/services/keystore/chaintype/chaintype.go +++ b/core/services/keystore/chaintype/chaintype.go @@ -21,6 +21,8 @@ const ( StarkNet ChainType = "starknet" // Aptos for the Aptos chain Aptos ChainType = "aptos" + // Tron for the Tron chain + Tron ChainType = "tron" ) type ChainTypes []ChainType @@ -48,6 +50,8 @@ func NewChainType(typ uint8) (ChainType, error) { return StarkNet, nil case 5: return Aptos, nil + case 6: + return Tron, nil default: return "", fmt.Errorf("unexpected chaintype.ChainType: %#v", typ) } @@ -65,13 +69,15 @@ func (c ChainType) Type() (uint8, error) { return 4, nil case Aptos: return 5, nil + case Tron: + return 6, nil default: return 0, fmt.Errorf("unexpected chaintype.ChainType: %#v", c) } } // SupportedChainTypes contain all chains that are supported -var SupportedChainTypes = ChainTypes{EVM, Cosmos, Solana, StarkNet, Aptos} +var SupportedChainTypes = ChainTypes{EVM, Cosmos, Solana, StarkNet, Aptos, Tron} // ErrInvalidChainType is an error to indicate an unsupported chain type var ErrInvalidChainType error diff --git a/core/services/keystore/keys/csakey/key_v2.go b/core/services/keystore/keys/csakey/key_v2.go index ddccbfb488b..c90a1640b86 100644 --- a/core/services/keystore/keys/csakey/key_v2.go +++ b/core/services/keystore/keys/csakey/key_v2.go @@ -83,6 +83,10 @@ func (k KeyV2) Raw() Raw { return Raw(*k.privateKey) } +func (k KeyV2) PrivateKey() ed25519.PrivateKey { + return *k.privateKey +} + func (k KeyV2) String() string { return fmt.Sprintf("CSAKeyV2{PrivateKey: , PublicKey: %s}", k.PublicKey) } diff --git a/core/services/keystore/keys/ocr2key/export.go b/core/services/keystore/keys/ocr2key/export.go index 8fa5ffedfed..eb7fe5f5eb9 100644 --- a/core/services/keystore/keys/ocr2key/export.go +++ b/core/services/keystore/keys/ocr2key/export.go @@ -48,6 +48,8 @@ func FromEncryptedJSON(keyJSON []byte, password string) (KeyBundle, error) { kb = newKeyBundle(new(starkkey.OCR2Key)) case chaintype.Aptos: kb = newKeyBundle(new(aptosKeyring)) + case chaintype.Tron: + kb = newKeyBundle(new(evmKeyring)) default: return nil, chaintype.NewErrInvalidChainType(export.ChainType) } diff --git a/core/services/keystore/keys/ocr2key/export_test.go b/core/services/keystore/keys/ocr2key/export_test.go index b0ffa2db009..fd1e867dfa9 100644 --- a/core/services/keystore/keys/ocr2key/export_test.go +++ b/core/services/keystore/keys/ocr2key/export_test.go @@ -19,6 +19,7 @@ func TestExport(t *testing.T) { {chain: chaintype.Solana}, {chain: chaintype.StarkNet}, {chain: chaintype.Aptos}, + {chain: chaintype.Tron}, } for _, tc := range tt { tc := tc diff --git a/core/services/keystore/keys/ocr2key/key_bundle.go b/core/services/keystore/keys/ocr2key/key_bundle.go index a08bd84ac30..07ac352a17d 100644 --- a/core/services/keystore/keys/ocr2key/key_bundle.go +++ b/core/services/keystore/keys/ocr2key/key_bundle.go @@ -59,6 +59,8 @@ func New(chainType chaintype.ChainType) (KeyBundle, error) { return newKeyBundleRand(chaintype.StarkNet, starkkey.NewOCR2Key) case chaintype.Aptos: return newKeyBundleRand(chaintype.Aptos, newAptosKeyring) + case chaintype.Tron: + return newKeyBundleRand(chaintype.Tron, newEVMKeyring) } return nil, chaintype.NewErrInvalidChainType(chainType) } @@ -76,6 +78,8 @@ func MustNewInsecure(reader io.Reader, chainType chaintype.ChainType) KeyBundle return mustNewKeyBundleInsecure(chaintype.StarkNet, starkkey.NewOCR2Key, reader) case chaintype.Aptos: return mustNewKeyBundleInsecure(chaintype.Aptos, newAptosKeyring, reader) + case chaintype.Tron: + return mustNewKeyBundleInsecure(chaintype.Tron, newEVMKeyring, reader) } panic(chaintype.NewErrInvalidChainType(chainType)) } @@ -126,6 +130,8 @@ func (raw Raw) Key() (kb KeyBundle) { kb = newKeyBundle(new(starkkey.OCR2Key)) case chaintype.Aptos: kb = newKeyBundle(new(aptosKeyring)) + case chaintype.Tron: + kb = newKeyBundle(new(evmKeyring)) default: return nil } diff --git a/core/services/keystore/keys/tronkey/account.go b/core/services/keystore/keys/tronkey/account.go new file mode 100644 index 00000000000..9c90422d2a7 --- /dev/null +++ b/core/services/keystore/keys/tronkey/account.go @@ -0,0 +1,178 @@ +package tronkey + +import ( + "crypto/ecdsa" + "crypto/sha256" + "encoding/hex" + "errors" + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/crypto" + "github.com/mr-tron/base58" +) + +// Extracted from go-tron sdk: https://github.com/fbsobreira/gotron-sdk + +const ( + // HashLength is the expected length of the hash + HashLength = 32 + // AddressLengthBase58 is the expected length of the address in base58format + AddressLengthBase58 = 34 + // Tron Address Prefix + prefixMainnet = 0x41 + // TronBytePrefix is the hex prefix to address + TronBytePrefix = byte(prefixMainnet) + // Tron address should have 21 bytes (20 bytes + 1 byte prefix) + AddressLength = 21 +) + +// Address represents the 21 byte address of an Tron account. +type Address [AddressLength]byte + +// Bytes get bytes from address +func (a Address) Bytes() []byte { + return a[:] +} + +// Hex get bytes from address in string +func (a Address) Hex() string { + return BytesToHexString(a[:]) +} + +// HexToAddress returns Address with byte values of s. +func HexToAddress(s string) (Address, error) { + addr, err := FromHex(s) + if err != nil { + return Address{}, err + } + // Check if the address starts with '41' and is 21 characters long + if len(addr) != AddressLength || addr[0] != prefixMainnet { + return Address{}, errors.New("invalid Tron address") + } + return Address(addr), nil +} + +// Base58ToAddress returns Address with byte values of s. +func Base58ToAddress(s string) (Address, error) { + addr, err := DecodeCheck(s) + if err != nil { + return Address{}, err + } + return Address(addr), nil +} + +// String implements fmt.Stringer. +// Returns the address as a base58 encoded string. +func (a Address) String() string { + if len(a) == 0 { + return "" + } + + if a[0] == 0 { + return new(big.Int).SetBytes(a.Bytes()).String() + } + return EncodeCheck(a.Bytes()) +} + +// PubkeyToAddress returns address from ecdsa public key +func PubkeyToAddress(p ecdsa.PublicKey) Address { + address := crypto.PubkeyToAddress(p) + + addressTron := make([]byte, 0) + addressTron = append(addressTron, TronBytePrefix) + addressTron = append(addressTron, address.Bytes()...) + return Address(addressTron) +} + +// BytesToHexString encodes bytes as a hex string. +func BytesToHexString(bytes []byte) string { + encode := make([]byte, len(bytes)*2) + hex.Encode(encode, bytes) + return "0x" + string(encode) +} + +// FromHex returns the bytes represented by the hexadecimal string s. +// s may be prefixed with "0x". +func FromHex(s string) ([]byte, error) { + if Has0xPrefix(s) { + s = s[2:] + } + if len(s)%2 == 1 { + s = "0" + s + } + return HexToBytes(s) +} + +// Has0xPrefix validates str begins with '0x' or '0X'. +func Has0xPrefix(str string) bool { + return len(str) >= 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X') +} + +// HexToBytes returns the bytes represented by the hexadecimal string str. +func HexToBytes(str string) ([]byte, error) { + return hex.DecodeString(str) +} + +func Encode(input []byte) string { + return base58.Encode(input) +} + +func EncodeCheck(input []byte) string { + h256h0 := sha256.New() + h256h0.Write(input) + h0 := h256h0.Sum(nil) + + h256h1 := sha256.New() + h256h1.Write(h0) + h1 := h256h1.Sum(nil) + + inputCheck := input + inputCheck = append(inputCheck, h1[:4]...) + + return Encode(inputCheck) +} + +func DecodeCheck(input string) ([]byte, error) { + decodeCheck, err := Decode(input) + if err != nil { + return nil, err + } + + if len(decodeCheck) < 4 { + return nil, errors.New("base58 check error") + } + + // tron address should should have 21 bytes (including prefix) + 4 checksum + if len(decodeCheck) != AddressLength+4 { + return nil, fmt.Errorf("invalid address length: %d", len(decodeCheck)) + } + + // check prefix + if decodeCheck[0] != prefixMainnet { + return nil, errors.New("invalid prefix") + } + + decodeData := decodeCheck[:len(decodeCheck)-4] + + h256h0 := sha256.New() + h256h0.Write(decodeData) + h0 := h256h0.Sum(nil) + + h256h1 := sha256.New() + h256h1.Write(h0) + h1 := h256h1.Sum(nil) + + if h1[0] == decodeCheck[len(decodeData)] && + h1[1] == decodeCheck[len(decodeData)+1] && + h1[2] == decodeCheck[len(decodeData)+2] && + h1[3] == decodeCheck[len(decodeData)+3] { + return decodeData, nil + } + + return nil, errors.New("base58 check error") +} + +func Decode(input string) ([]byte, error) { + return base58.Decode(input) +} diff --git a/core/services/keystore/keys/tronkey/account_test.go b/core/services/keystore/keys/tronkey/account_test.go new file mode 100644 index 00000000000..9a92801bb13 --- /dev/null +++ b/core/services/keystore/keys/tronkey/account_test.go @@ -0,0 +1,177 @@ +package tronkey + +import ( + "bytes" + "regexp" + "strings" + "testing" + + "github.com/stretchr/testify/require" +) + +func Test_DecodeBase58(t *testing.T) { + invalidAddresses := []string{ + "TronEnergyioE1Z3ukeRv38sYkv5Jn55bL", + "TronEnergyioNijNo8g3LF2ABKUAae6D2Z", + "TronEnergyio3ZMcXA5hSjrTxaioKGgqyr", + } + + validAddresses := []string{ + "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", + "TVj7RNVHy6thbM7BWdSe9G6gXwKhjhdNZS", + "THPvaUhoh2Qn2y9THCZML3H815hhFhn5YC", + } + + for _, addr := range invalidAddresses { + _, err := DecodeCheck(addr) + require.Error(t, err) + } + + for _, addr := range validAddresses { + _, err := DecodeCheck(addr) + require.NoError(t, err) + } +} + +func TestAddress(t *testing.T) { + t.Run("Valid Addresses", func(t *testing.T) { + validAddresses := []string{ + "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", + "TVj7RNVHy6thbM7BWdSe9G6gXwKhjhdNZS", + "THPvaUhoh2Qn2y9THCZML3H815hhFhn5YC", + } + + for _, addrStr := range validAddresses { + t.Run(addrStr, func(t *testing.T) { + addr, err := Base58ToAddress(addrStr) + require.NoError(t, err) + require.Equal(t, addrStr, addr.String()) + + decoded, err := DecodeCheck(addrStr) + require.NoError(t, err) + require.True(t, bytes.Equal(decoded, addr.Bytes())) + }) + } + }) + + t.Run("Invalid Addresses", func(t *testing.T) { + invalidAddresses := []string{ + "TronEnergyioE1Z3ukeRv38sYkv5Jn55bL", + "TronEnergyioNijNo8g3LF2ABKUAae6D2Z", + "TronEnergyio3ZMcXA5hSjrTxaioKGgqyr", + } + + for _, addrStr := range invalidAddresses { + t.Run(addrStr, func(t *testing.T) { + _, err := Base58ToAddress(addrStr) + require.Error(t, err) + + _, err = DecodeCheck(addrStr) + require.Error(t, err) + }) + } + }) + + t.Run("Address Conversion", func(t *testing.T) { + addrStr := "TSvT6Bg3siokv3dbdtt9o4oM1CTXmymGn1" + addr, err := Base58ToAddress(addrStr) + require.NoError(t, err) + + t.Run("To Bytes", func(t *testing.T) { + bytes := addr.Bytes() + require.Len(t, bytes, 21) + }) + + t.Run("To Hex", func(t *testing.T) { + hex := addr.Hex() + require.Equal(t, "0x", hex[:2]) + require.Len(t, hex, 44) + }) + }) + + t.Run("Address Validity", func(t *testing.T) { + t.Run("Valid Address", func(t *testing.T) { + addr, err := Base58ToAddress("TSvT6Bg3siokv3dbdtt9o4oM1CTXmymGn1") + require.NoError(t, err) + require.True(t, isValid(addr)) + }) + + t.Run("Zero Address", func(t *testing.T) { + addr := Address{} + require.False(t, isValid(addr)) + }) + }) +} + +func TestHexToAddress(t *testing.T) { + t.Run("Valid Hex Addresses", func(t *testing.T) { + validHexAddresses := []string{ + "41a614f803b6fd780986a42c78ec9c7f77e6ded13c", + "41b2a2e1b2e1b2e1b2e1b2e1b2e1b2e1b2e1b2e1b2", + "41c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3", + } + + for _, hexStr := range validHexAddresses { + t.Run(hexStr, func(t *testing.T) { + addr, err := HexToAddress(hexStr) + require.NoError(t, err) + require.Equal(t, "0x"+hexStr, addr.Hex()) + }) + } + }) + + t.Run("Invalid Hex Addresses", func(t *testing.T) { + invalidHexAddresses := []string{ + "41a614f803b6fd780986a42c78ec9c7f77e6ded13", // Too short + "41b2a2e1b2e1b2e1b2e1b2e1b2e1b2e1b2e1b2e1b2e1b2", // Too long + "41g3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3", // Invalid character 'g' + "c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3", // Missing prefix '41' + } + + for _, hexStr := range invalidHexAddresses { + t.Run(hexStr, func(t *testing.T) { + _, err := HexToAddress(hexStr) + require.Error(t, err) + }) + } + }) +} + +// Helper Functions for testing + +// isValid checks if the address is a valid TRON address +func isValid(a Address) bool { + // Check if it's a valid Base58 address + base58Str := a.String() + if isValidBase58Address(base58Str) { + return true + } + + // Check if it's a valid hex address + hexStr := a.Hex() + return isValidHexAddress(strings.TrimPrefix(hexStr, "0x")) +} + +// isValidBase58Address check if a string is a valid Base58 TRON address +func isValidBase58Address(address string) bool { + // Check if the address starts with 'T' and is 34 characters long + if len(address) != 34 || address[0] != 'T' { + return false + } + + // Check if the address contains only valid Base58 characters + validChars := regexp.MustCompile("^[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+$") + return validChars.MatchString(address) +} + +// isValidHexAddressto check if a string is a valid hex TRON address +func isValidHexAddress(address string) bool { + // Check if the address starts with '41' and is 42 characters long + if len(address) != 42 || address[:2] != "41" { + return false + } + + // Check if the address contains only valid hexadecimal characters + validChars := regexp.MustCompile("^[0-9A-Fa-f]+$") + return validChars.MatchString(address[2:]) // Check the part after '41' +} diff --git a/core/services/keystore/keys/tronkey/export.go b/core/services/keystore/keys/tronkey/export.go new file mode 100644 index 00000000000..7688650c58d --- /dev/null +++ b/core/services/keystore/keys/tronkey/export.go @@ -0,0 +1,46 @@ +package tronkey + +import ( + "github.com/ethereum/go-ethereum/accounts/keystore" + + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys" + "github.com/smartcontractkit/chainlink/v2/core/utils" +) + +const keyTypeIdentifier = "Tron" + +// FromEncryptedJSON gets key from json and password +func FromEncryptedJSON(keyJSON []byte, password string) (Key, error) { + return keys.FromEncryptedJSON( + keyTypeIdentifier, + keyJSON, + password, + adulteratedPassword, + func(_ keys.EncryptedKeyExport, rawPrivKey []byte) (Key, error) { + return Raw(rawPrivKey).Key(), nil + }, + ) +} + +// ToEncryptedJSON returns encrypted JSON representing key +func (key Key) ToEncryptedJSON(password string, scryptParams utils.ScryptParams) (export []byte, err error) { + return keys.ToEncryptedJSON( + keyTypeIdentifier, + key.Raw(), + key, + password, + scryptParams, + adulteratedPassword, + func(id string, key Key, cryptoJSON keystore.CryptoJSON) keys.EncryptedKeyExport { + return keys.EncryptedKeyExport{ + KeyType: id, + PublicKey: key.PublicKeyStr(), + Crypto: cryptoJSON, + } + }, + ) +} + +func adulteratedPassword(password string) string { + return "tronkey" + password +} diff --git a/core/services/keystore/keys/tronkey/export_test.go b/core/services/keystore/keys/tronkey/export_test.go new file mode 100644 index 00000000000..5e3e605ed34 --- /dev/null +++ b/core/services/keystore/keys/tronkey/export_test.go @@ -0,0 +1,19 @@ +package tronkey + +import ( + "testing" + + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys" +) + +func TestTronKeys_ExportImport(t *testing.T) { + keys.RunKeyExportImportTestcase(t, createKey, decryptKey) +} + +func createKey() (keys.KeyType, error) { + return New() +} + +func decryptKey(keyJSON []byte, password string) (keys.KeyType, error) { + return FromEncryptedJSON(keyJSON, password) +} diff --git a/core/services/keystore/keys/tronkey/key.go b/core/services/keystore/keys/tronkey/key.go new file mode 100644 index 00000000000..5f5b36b8c14 --- /dev/null +++ b/core/services/keystore/keys/tronkey/key.go @@ -0,0 +1,109 @@ +package tronkey + +import ( + "crypto/ecdsa" + "crypto/rand" + "encoding/hex" + "fmt" + "io" + "math/big" + + "github.com/ethereum/go-ethereum/crypto" +) + +// Tron uses the same elliptic curve cryptography as Ethereum (ECDSA with secp256k1) +var curve = crypto.S256() + +// Raw represents the Tron private key +type Raw []byte + +// Key generates a public-private key pair from the raw private key +func (raw Raw) Key() Key { + var privKey ecdsa.PrivateKey + d := big.NewInt(0).SetBytes(raw) + privKey.PublicKey.Curve = curve + privKey.D = d + privKey.PublicKey.X, privKey.PublicKey.Y = curve.ScalarBaseMult(d.Bytes()) + return Key{ + pubKey: &privKey.PublicKey, + privKey: &privKey, + } +} + +func (raw Raw) String() string { + return "" +} + +func (raw Raw) GoString() string { + return raw.String() +} + +var _ fmt.GoStringer = &Key{} + +type Key struct { + privKey *ecdsa.PrivateKey + pubKey *ecdsa.PublicKey +} + +func New() (Key, error) { + return newFrom(rand.Reader) +} + +// MustNewInsecure return Key if no error +// This insecure function is used for testing purposes only +func MustNewInsecure(reader io.Reader) Key { + key, err := newFrom(reader) + if err != nil { + panic(err) + } + return key +} + +func newFrom(reader io.Reader) (Key, error) { + privKeyECDSA, err := ecdsa.GenerateKey(curve, reader) + if err != nil { + return Key{}, err + } + return Key{ + privKey: privKeyECDSA, + pubKey: &privKeyECDSA.PublicKey, + }, nil +} + +func (key Key) ID() string { + return key.Base58Address() +} + +func (key Key) Raw() Raw { + return key.privKey.D.Bytes() +} + +func (key Key) ToEcdsaPrivKey() *ecdsa.PrivateKey { + return key.privKey +} + +func (key Key) String() string { + return fmt.Sprintf("TronKey{PrivateKey: , Address: %s}", key.Base58Address()) +} + +// GoString wraps String() +func (key Key) GoString() string { + return key.String() +} + +// Sign is used to sign a message +func (key Key) Sign(msg []byte) ([]byte, error) { + return crypto.Sign(msg, key.privKey) +} + +// PublicKeyStr returns the public key as a hexadecimal string +func (key Key) PublicKeyStr() string { + pubKeyBytes := crypto.FromECDSAPub(key.pubKey) + return hex.EncodeToString(pubKeyBytes) +} + +// Base58Address returns the Tron address in Base58 format with checksum +func (key Key) Base58Address() string { + address := PubkeyToAddress(*key.pubKey) + return address.String() +} diff --git a/core/services/keystore/keys/tronkey/key_test.go b/core/services/keystore/keys/tronkey/key_test.go new file mode 100644 index 00000000000..d3714228483 --- /dev/null +++ b/core/services/keystore/keys/tronkey/key_test.go @@ -0,0 +1,85 @@ +package tronkey + +import ( + "crypto/ecdsa" + "crypto/rand" + "encoding/hex" + "testing" + + "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestTronKeyRawPrivateKey(t *testing.T) { + t.Run("Create from raw bytes and check string representation", func(t *testing.T) { + // Generate a private key + privateKeyECDSA, err := ecdsa.GenerateKey(crypto.S256(), rand.Reader) + require.NoError(t, err, "Failed to generate ECDSA key") + + // Create TronKey from raw bytes + tronKey := Raw(privateKeyECDSA.D.Bytes()) + + // Check string representation + expectedStr := "" + assert.Equal(t, expectedStr, tronKey.String(), "Unexpected string representation") + assert.Equal(t, expectedStr, tronKey.GoString(), "String() and GoString() should return the same value") + }) +} + +func TestTronKeyNewKeyGeneration(t *testing.T) { + t.Run("Generate new key and verify its components", func(t *testing.T) { + // Generate a new key + key, err := New() + require.NoError(t, err, "Failed to generate new TronKey") + + // Verify key components + assert.NotNil(t, key.pubKey, "Public key should not be nil") + assert.NotNil(t, key.privKey, "Private key should not be nil") + }) + + t.Run("Multiple key generations produce unique keys", func(t *testing.T) { + key1, err := New() + require.NoError(t, err, "Failed to generate first key") + + key2, err := New() + require.NoError(t, err, "Failed to generate second key") + + assert.NotEqual(t, key1.privKey, key2.privKey, "Generated private keys should be unique") + assert.NotEqual(t, key1.pubKey, key2.pubKey, "Generated public keys should be unique") + }) +} + +func TestKeyAddress(t *testing.T) { + t.Run("Known private key and expected address", func(t *testing.T) { + // Tests cases from https://developers.tron.network/docs/account + privateKeyHex := "b406adb115b43e103c7b1dc8b5931f63279a5b6b2cf7328638814c43171a2908" + expectedAddress := "TDdcf5iMDkB61oGM27TNak55eVX214thBG" + + privateKeyBytes, err := hex.DecodeString(privateKeyHex) + require.NoError(t, err, "Failed to decode private key hex") + + privateKey, err := crypto.ToECDSA(privateKeyBytes) + require.NoError(t, err, "Failed to convert private key to ECDSA") + + key := Key{ + privKey: privateKey, + pubKey: &privateKey.PublicKey, + } + require.NotNil(t, key.privKey, "Private key is nil") + + address := key.Base58Address() + require.Equal(t, expectedAddress, address, "Generated address does not match expected address") + }) + + t.Run("Generate new key and check address format", func(t *testing.T) { + newKey, err := New() + if err != nil { + t.Fatalf("Failed to generate new key: %v", err) + } + + newAddress := newKey.Base58Address() + isValid := isValidBase58Address(newAddress) + require.True(t, isValid, "Generated address is not valid") + }) +} diff --git a/core/services/keystore/keystoretest.go b/core/services/keystore/keystoretest.go index 626cc4bab99..9814801b2a5 100644 --- a/core/services/keystore/keystoretest.go +++ b/core/services/keystore/keystoretest.go @@ -74,6 +74,7 @@ func NewInMemory(ds sqlutil.DataSource, scryptParams utils.ScryptParams, lggr lo solana: newSolanaKeyStore(km), starknet: newStarkNetKeyStore(km), aptos: newAptosKeyStore(km), + tron: newTronKeyStore(km), vrf: newVRFKeyStore(km), workflow: newWorkflowKeyStore(km), } diff --git a/core/services/keystore/master.go b/core/services/keystore/master.go index 72677a166a3..50ca6d0c34d 100644 --- a/core/services/keystore/master.go +++ b/core/services/keystore/master.go @@ -20,6 +20,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/solkey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/starkkey" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/tronkey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/vrfkey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/workflowkey" "github.com/smartcontractkit/chainlink/v2/core/utils" @@ -45,6 +46,7 @@ type Master interface { Cosmos() Cosmos StarkNet() StarkNet Aptos() Aptos + Tron() Tron VRF() VRF Workflow() Workflow Unlock(ctx context.Context, password string) error @@ -62,6 +64,7 @@ type master struct { solana *solana starknet *starknet aptos *aptos + tron *tron vrf *vrf workflow *workflow } @@ -91,6 +94,7 @@ func newMaster(ds sqlutil.DataSource, scryptParams utils.ScryptParams, lggr logg solana: newSolanaKeyStore(km), starknet: newStarkNetKeyStore(km), aptos: newAptosKeyStore(km), + tron: newTronKeyStore(km), vrf: newVRFKeyStore(km), workflow: newWorkflowKeyStore(km), } @@ -132,6 +136,10 @@ func (ks *master) Aptos() Aptos { return ks.aptos } +func (ks *master) Tron() Tron { + return ks.tron +} + func (ks *master) VRF() VRF { return ks.vrf } @@ -273,6 +281,8 @@ func GetFieldNameForKey(unknownKey Key) (string, error) { return "StarkNet", nil case aptoskey.Key: return "Aptos", nil + case tronkey.Key: + return "Tron", nil case vrfkey.KeyV2: return "VRF", nil case workflowkey.Key: diff --git a/core/services/keystore/mocks/aptos.go b/core/services/keystore/mocks/aptos.go index 9c9124aeeac..98cb90457b7 100644 --- a/core/services/keystore/mocks/aptos.go +++ b/core/services/keystore/mocks/aptos.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -344,7 +344,7 @@ func (_c *Aptos_Get_Call) RunAndReturn(run func(string) (aptoskey.Key, error)) * return _c } -// GetAll provides a mock function with given fields: +// GetAll provides a mock function with no fields func (_m *Aptos) GetAll() ([]aptoskey.Key, error) { ret := _m.Called() diff --git a/core/services/keystore/mocks/cosmos.go b/core/services/keystore/mocks/cosmos.go index 74690bf6889..ef127191285 100644 --- a/core/services/keystore/mocks/cosmos.go +++ b/core/services/keystore/mocks/cosmos.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -344,7 +344,7 @@ func (_c *Cosmos_Get_Call) RunAndReturn(run func(string) (cosmoskey.Key, error)) return _c } -// GetAll provides a mock function with given fields: +// GetAll provides a mock function with no fields func (_m *Cosmos) GetAll() ([]cosmoskey.Key, error) { ret := _m.Called() diff --git a/core/services/keystore/mocks/csa.go b/core/services/keystore/mocks/csa.go index 5ce17c0beff..73a4c048806 100644 --- a/core/services/keystore/mocks/csa.go +++ b/core/services/keystore/mocks/csa.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -344,7 +344,7 @@ func (_c *CSA_Get_Call) RunAndReturn(run func(string) (csakey.KeyV2, error)) *CS return _c } -// GetAll provides a mock function with given fields: +// GetAll provides a mock function with no fields func (_m *CSA) GetAll() ([]csakey.KeyV2, error) { ret := _m.Called() diff --git a/core/services/keystore/mocks/eth.go b/core/services/keystore/mocks/eth.go index 4f2486464eb..7ed960663f7 100644 --- a/core/services/keystore/mocks/eth.go +++ b/core/services/keystore/mocks/eth.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -1293,7 +1293,7 @@ func (_c *Eth_XXXTestingOnlyAdd_Call) Return() *Eth_XXXTestingOnlyAdd_Call { } func (_c *Eth_XXXTestingOnlyAdd_Call) RunAndReturn(run func(context.Context, ethkey.KeyV2)) *Eth_XXXTestingOnlyAdd_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -1327,7 +1327,7 @@ func (_c *Eth_XXXTestingOnlySetState_Call) Return() *Eth_XXXTestingOnlySetState_ } func (_c *Eth_XXXTestingOnlySetState_Call) RunAndReturn(run func(context.Context, ethkey.State)) *Eth_XXXTestingOnlySetState_Call { - _c.Call.Return(run) + _c.Run(run) return _c } diff --git a/core/services/keystore/mocks/master.go b/core/services/keystore/mocks/master.go index 7c86001bc54..6ea57639196 100644 --- a/core/services/keystore/mocks/master.go +++ b/core/services/keystore/mocks/master.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -22,7 +22,7 @@ func (_m *Master) EXPECT() *Master_Expecter { return &Master_Expecter{mock: &_m.Mock} } -// Aptos provides a mock function with given fields: +// Aptos provides a mock function with no fields func (_m *Master) Aptos() keystore.Aptos { ret := _m.Called() @@ -69,7 +69,7 @@ func (_c *Master_Aptos_Call) RunAndReturn(run func() keystore.Aptos) *Master_Apt return _c } -// CSA provides a mock function with given fields: +// CSA provides a mock function with no fields func (_m *Master) CSA() keystore.CSA { ret := _m.Called() @@ -116,7 +116,7 @@ func (_c *Master_CSA_Call) RunAndReturn(run func() keystore.CSA) *Master_CSA_Cal return _c } -// Cosmos provides a mock function with given fields: +// Cosmos provides a mock function with no fields func (_m *Master) Cosmos() keystore.Cosmos { ret := _m.Called() @@ -163,7 +163,7 @@ func (_c *Master_Cosmos_Call) RunAndReturn(run func() keystore.Cosmos) *Master_C return _c } -// Eth provides a mock function with given fields: +// Eth provides a mock function with no fields func (_m *Master) Eth() keystore.Eth { ret := _m.Called() @@ -266,7 +266,7 @@ func (_c *Master_IsEmpty_Call) RunAndReturn(run func(context.Context) (bool, err return _c } -// OCR provides a mock function with given fields: +// OCR provides a mock function with no fields func (_m *Master) OCR() keystore.OCR { ret := _m.Called() @@ -313,7 +313,7 @@ func (_c *Master_OCR_Call) RunAndReturn(run func() keystore.OCR) *Master_OCR_Cal return _c } -// OCR2 provides a mock function with given fields: +// OCR2 provides a mock function with no fields func (_m *Master) OCR2() keystore.OCR2 { ret := _m.Called() @@ -360,7 +360,7 @@ func (_c *Master_OCR2_Call) RunAndReturn(run func() keystore.OCR2) *Master_OCR2_ return _c } -// P2P provides a mock function with given fields: +// P2P provides a mock function with no fields func (_m *Master) P2P() keystore.P2P { ret := _m.Called() @@ -407,7 +407,7 @@ func (_c *Master_P2P_Call) RunAndReturn(run func() keystore.P2P) *Master_P2P_Cal return _c } -// Solana provides a mock function with given fields: +// Solana provides a mock function with no fields func (_m *Master) Solana() keystore.Solana { ret := _m.Called() @@ -454,7 +454,7 @@ func (_c *Master_Solana_Call) RunAndReturn(run func() keystore.Solana) *Master_S return _c } -// StarkNet provides a mock function with given fields: +// StarkNet provides a mock function with no fields func (_m *Master) StarkNet() keystore.StarkNet { ret := _m.Called() @@ -501,6 +501,53 @@ func (_c *Master_StarkNet_Call) RunAndReturn(run func() keystore.StarkNet) *Mast return _c } +// Tron provides a mock function with no fields +func (_m *Master) Tron() keystore.Tron { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Tron") + } + + var r0 keystore.Tron + if rf, ok := ret.Get(0).(func() keystore.Tron); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(keystore.Tron) + } + } + + return r0 +} + +// Master_Tron_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Tron' +type Master_Tron_Call struct { + *mock.Call +} + +// Tron is a helper method to define mock.On call +func (_e *Master_Expecter) Tron() *Master_Tron_Call { + return &Master_Tron_Call{Call: _e.mock.On("Tron")} +} + +func (_c *Master_Tron_Call) Run(run func()) *Master_Tron_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Master_Tron_Call) Return(_a0 keystore.Tron) *Master_Tron_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Master_Tron_Call) RunAndReturn(run func() keystore.Tron) *Master_Tron_Call { + _c.Call.Return(run) + return _c +} + // Unlock provides a mock function with given fields: ctx, password func (_m *Master) Unlock(ctx context.Context, password string) error { ret := _m.Called(ctx, password) @@ -548,7 +595,7 @@ func (_c *Master_Unlock_Call) RunAndReturn(run func(context.Context, string) err return _c } -// VRF provides a mock function with given fields: +// VRF provides a mock function with no fields func (_m *Master) VRF() keystore.VRF { ret := _m.Called() @@ -595,7 +642,7 @@ func (_c *Master_VRF_Call) RunAndReturn(run func() keystore.VRF) *Master_VRF_Cal return _c } -// Workflow provides a mock function with given fields: +// Workflow provides a mock function with no fields func (_m *Master) Workflow() keystore.Workflow { ret := _m.Called() diff --git a/core/services/keystore/mocks/ocr.go b/core/services/keystore/mocks/ocr.go index d3bb15aec86..bb0ecae9bda 100644 --- a/core/services/keystore/mocks/ocr.go +++ b/core/services/keystore/mocks/ocr.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -344,7 +344,7 @@ func (_c *OCR_Get_Call) RunAndReturn(run func(string) (ocrkey.KeyV2, error)) *OC return _c } -// GetAll provides a mock function with given fields: +// GetAll provides a mock function with no fields func (_m *OCR) GetAll() ([]ocrkey.KeyV2, error) { ret := _m.Called() diff --git a/core/services/keystore/mocks/ocr2.go b/core/services/keystore/mocks/ocr2.go index 6ff7d2f6b58..3497fa7ac4d 100644 --- a/core/services/keystore/mocks/ocr2.go +++ b/core/services/keystore/mocks/ocr2.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -356,7 +356,7 @@ func (_c *OCR2_Get_Call) RunAndReturn(run func(string) (ocr2key.KeyBundle, error return _c } -// GetAll provides a mock function with given fields: +// GetAll provides a mock function with no fields func (_m *OCR2) GetAll() ([]ocr2key.KeyBundle, error) { ret := _m.Called() diff --git a/core/services/keystore/mocks/p2p.go b/core/services/keystore/mocks/p2p.go index 3dead948b14..917f620edd3 100644 --- a/core/services/keystore/mocks/p2p.go +++ b/core/services/keystore/mocks/p2p.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -344,7 +344,7 @@ func (_c *P2P_Get_Call) RunAndReturn(run func(p2pkey.PeerID) (p2pkey.KeyV2, erro return _c } -// GetAll provides a mock function with given fields: +// GetAll provides a mock function with no fields func (_m *P2P) GetAll() ([]p2pkey.KeyV2, error) { ret := _m.Called() diff --git a/core/services/keystore/mocks/solana.go b/core/services/keystore/mocks/solana.go index d55e85436df..3478b83bbe7 100644 --- a/core/services/keystore/mocks/solana.go +++ b/core/services/keystore/mocks/solana.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -344,7 +344,7 @@ func (_c *Solana_Get_Call) RunAndReturn(run func(string) (solkey.Key, error)) *S return _c } -// GetAll provides a mock function with given fields: +// GetAll provides a mock function with no fields func (_m *Solana) GetAll() ([]solkey.Key, error) { ret := _m.Called() diff --git a/core/services/keystore/mocks/starknet.go b/core/services/keystore/mocks/starknet.go index 720d16c9b2f..405408409b7 100644 --- a/core/services/keystore/mocks/starknet.go +++ b/core/services/keystore/mocks/starknet.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -344,7 +344,7 @@ func (_c *StarkNet_Get_Call) RunAndReturn(run func(string) (starkkey.Key, error) return _c } -// GetAll provides a mock function with given fields: +// GetAll provides a mock function with no fields func (_m *StarkNet) GetAll() ([]starkkey.Key, error) { ret := _m.Called() diff --git a/core/services/keystore/mocks/tron.go b/core/services/keystore/mocks/tron.go new file mode 100644 index 00000000000..0636f4e54e9 --- /dev/null +++ b/core/services/keystore/mocks/tron.go @@ -0,0 +1,534 @@ +// Code generated by mockery v2.50.0. DO NOT EDIT. + +package mocks + +import ( + context "context" + + mock "github.com/stretchr/testify/mock" + + tronkey "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/tronkey" +) + +// Tron is an autogenerated mock type for the Tron type +type Tron struct { + mock.Mock +} + +type Tron_Expecter struct { + mock *mock.Mock +} + +func (_m *Tron) EXPECT() *Tron_Expecter { + return &Tron_Expecter{mock: &_m.Mock} +} + +// Add provides a mock function with given fields: ctx, key +func (_m *Tron) Add(ctx context.Context, key tronkey.Key) error { + ret := _m.Called(ctx, key) + + if len(ret) == 0 { + panic("no return value specified for Add") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, tronkey.Key) error); ok { + r0 = rf(ctx, key) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Tron_Add_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Add' +type Tron_Add_Call struct { + *mock.Call +} + +// Add is a helper method to define mock.On call +// - ctx context.Context +// - key tronkey.Key +func (_e *Tron_Expecter) Add(ctx interface{}, key interface{}) *Tron_Add_Call { + return &Tron_Add_Call{Call: _e.mock.On("Add", ctx, key)} +} + +func (_c *Tron_Add_Call) Run(run func(ctx context.Context, key tronkey.Key)) *Tron_Add_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(tronkey.Key)) + }) + return _c +} + +func (_c *Tron_Add_Call) Return(_a0 error) *Tron_Add_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Tron_Add_Call) RunAndReturn(run func(context.Context, tronkey.Key) error) *Tron_Add_Call { + _c.Call.Return(run) + return _c +} + +// Create provides a mock function with given fields: ctx +func (_m *Tron) Create(ctx context.Context) (tronkey.Key, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for Create") + } + + var r0 tronkey.Key + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (tronkey.Key, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) tronkey.Key); ok { + r0 = rf(ctx) + } else { + r0 = ret.Get(0).(tronkey.Key) + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Tron_Create_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Create' +type Tron_Create_Call struct { + *mock.Call +} + +// Create is a helper method to define mock.On call +// - ctx context.Context +func (_e *Tron_Expecter) Create(ctx interface{}) *Tron_Create_Call { + return &Tron_Create_Call{Call: _e.mock.On("Create", ctx)} +} + +func (_c *Tron_Create_Call) Run(run func(ctx context.Context)) *Tron_Create_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *Tron_Create_Call) Return(_a0 tronkey.Key, _a1 error) *Tron_Create_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Tron_Create_Call) RunAndReturn(run func(context.Context) (tronkey.Key, error)) *Tron_Create_Call { + _c.Call.Return(run) + return _c +} + +// Delete provides a mock function with given fields: ctx, id +func (_m *Tron) Delete(ctx context.Context, id string) (tronkey.Key, error) { + ret := _m.Called(ctx, id) + + if len(ret) == 0 { + panic("no return value specified for Delete") + } + + var r0 tronkey.Key + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string) (tronkey.Key, error)); ok { + return rf(ctx, id) + } + if rf, ok := ret.Get(0).(func(context.Context, string) tronkey.Key); ok { + r0 = rf(ctx, id) + } else { + r0 = ret.Get(0).(tronkey.Key) + } + + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, id) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Tron_Delete_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Delete' +type Tron_Delete_Call struct { + *mock.Call +} + +// Delete is a helper method to define mock.On call +// - ctx context.Context +// - id string +func (_e *Tron_Expecter) Delete(ctx interface{}, id interface{}) *Tron_Delete_Call { + return &Tron_Delete_Call{Call: _e.mock.On("Delete", ctx, id)} +} + +func (_c *Tron_Delete_Call) Run(run func(ctx context.Context, id string)) *Tron_Delete_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string)) + }) + return _c +} + +func (_c *Tron_Delete_Call) Return(_a0 tronkey.Key, _a1 error) *Tron_Delete_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Tron_Delete_Call) RunAndReturn(run func(context.Context, string) (tronkey.Key, error)) *Tron_Delete_Call { + _c.Call.Return(run) + return _c +} + +// EnsureKey provides a mock function with given fields: ctx +func (_m *Tron) EnsureKey(ctx context.Context) error { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for EnsureKey") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(ctx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Tron_EnsureKey_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EnsureKey' +type Tron_EnsureKey_Call struct { + *mock.Call +} + +// EnsureKey is a helper method to define mock.On call +// - ctx context.Context +func (_e *Tron_Expecter) EnsureKey(ctx interface{}) *Tron_EnsureKey_Call { + return &Tron_EnsureKey_Call{Call: _e.mock.On("EnsureKey", ctx)} +} + +func (_c *Tron_EnsureKey_Call) Run(run func(ctx context.Context)) *Tron_EnsureKey_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *Tron_EnsureKey_Call) Return(_a0 error) *Tron_EnsureKey_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Tron_EnsureKey_Call) RunAndReturn(run func(context.Context) error) *Tron_EnsureKey_Call { + _c.Call.Return(run) + return _c +} + +// Export provides a mock function with given fields: id, password +func (_m *Tron) Export(id string, password string) ([]byte, error) { + ret := _m.Called(id, password) + + if len(ret) == 0 { + panic("no return value specified for Export") + } + + var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func(string, string) ([]byte, error)); ok { + return rf(id, password) + } + if rf, ok := ret.Get(0).(func(string, string) []byte); ok { + r0 = rf(id, password) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func(string, string) error); ok { + r1 = rf(id, password) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Tron_Export_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Export' +type Tron_Export_Call struct { + *mock.Call +} + +// Export is a helper method to define mock.On call +// - id string +// - password string +func (_e *Tron_Expecter) Export(id interface{}, password interface{}) *Tron_Export_Call { + return &Tron_Export_Call{Call: _e.mock.On("Export", id, password)} +} + +func (_c *Tron_Export_Call) Run(run func(id string, password string)) *Tron_Export_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string), args[1].(string)) + }) + return _c +} + +func (_c *Tron_Export_Call) Return(_a0 []byte, _a1 error) *Tron_Export_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Tron_Export_Call) RunAndReturn(run func(string, string) ([]byte, error)) *Tron_Export_Call { + _c.Call.Return(run) + return _c +} + +// Get provides a mock function with given fields: id +func (_m *Tron) Get(id string) (tronkey.Key, error) { + ret := _m.Called(id) + + if len(ret) == 0 { + panic("no return value specified for Get") + } + + var r0 tronkey.Key + var r1 error + if rf, ok := ret.Get(0).(func(string) (tronkey.Key, error)); ok { + return rf(id) + } + if rf, ok := ret.Get(0).(func(string) tronkey.Key); ok { + r0 = rf(id) + } else { + r0 = ret.Get(0).(tronkey.Key) + } + + if rf, ok := ret.Get(1).(func(string) error); ok { + r1 = rf(id) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Tron_Get_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Get' +type Tron_Get_Call struct { + *mock.Call +} + +// Get is a helper method to define mock.On call +// - id string +func (_e *Tron_Expecter) Get(id interface{}) *Tron_Get_Call { + return &Tron_Get_Call{Call: _e.mock.On("Get", id)} +} + +func (_c *Tron_Get_Call) Run(run func(id string)) *Tron_Get_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *Tron_Get_Call) Return(_a0 tronkey.Key, _a1 error) *Tron_Get_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Tron_Get_Call) RunAndReturn(run func(string) (tronkey.Key, error)) *Tron_Get_Call { + _c.Call.Return(run) + return _c +} + +// GetAll provides a mock function with no fields +func (_m *Tron) GetAll() ([]tronkey.Key, error) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for GetAll") + } + + var r0 []tronkey.Key + var r1 error + if rf, ok := ret.Get(0).(func() ([]tronkey.Key, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() []tronkey.Key); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]tronkey.Key) + } + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Tron_GetAll_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetAll' +type Tron_GetAll_Call struct { + *mock.Call +} + +// GetAll is a helper method to define mock.On call +func (_e *Tron_Expecter) GetAll() *Tron_GetAll_Call { + return &Tron_GetAll_Call{Call: _e.mock.On("GetAll")} +} + +func (_c *Tron_GetAll_Call) Run(run func()) *Tron_GetAll_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Tron_GetAll_Call) Return(_a0 []tronkey.Key, _a1 error) *Tron_GetAll_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Tron_GetAll_Call) RunAndReturn(run func() ([]tronkey.Key, error)) *Tron_GetAll_Call { + _c.Call.Return(run) + return _c +} + +// Import provides a mock function with given fields: ctx, keyJSON, password +func (_m *Tron) Import(ctx context.Context, keyJSON []byte, password string) (tronkey.Key, error) { + ret := _m.Called(ctx, keyJSON, password) + + if len(ret) == 0 { + panic("no return value specified for Import") + } + + var r0 tronkey.Key + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, []byte, string) (tronkey.Key, error)); ok { + return rf(ctx, keyJSON, password) + } + if rf, ok := ret.Get(0).(func(context.Context, []byte, string) tronkey.Key); ok { + r0 = rf(ctx, keyJSON, password) + } else { + r0 = ret.Get(0).(tronkey.Key) + } + + if rf, ok := ret.Get(1).(func(context.Context, []byte, string) error); ok { + r1 = rf(ctx, keyJSON, password) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Tron_Import_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Import' +type Tron_Import_Call struct { + *mock.Call +} + +// Import is a helper method to define mock.On call +// - ctx context.Context +// - keyJSON []byte +// - password string +func (_e *Tron_Expecter) Import(ctx interface{}, keyJSON interface{}, password interface{}) *Tron_Import_Call { + return &Tron_Import_Call{Call: _e.mock.On("Import", ctx, keyJSON, password)} +} + +func (_c *Tron_Import_Call) Run(run func(ctx context.Context, keyJSON []byte, password string)) *Tron_Import_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].([]byte), args[2].(string)) + }) + return _c +} + +func (_c *Tron_Import_Call) Return(_a0 tronkey.Key, _a1 error) *Tron_Import_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Tron_Import_Call) RunAndReturn(run func(context.Context, []byte, string) (tronkey.Key, error)) *Tron_Import_Call { + _c.Call.Return(run) + return _c +} + +// Sign provides a mock function with given fields: ctx, id, msg +func (_m *Tron) Sign(ctx context.Context, id string, msg []byte) ([]byte, error) { + ret := _m.Called(ctx, id, msg) + + if len(ret) == 0 { + panic("no return value specified for Sign") + } + + var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, []byte) ([]byte, error)); ok { + return rf(ctx, id, msg) + } + if rf, ok := ret.Get(0).(func(context.Context, string, []byte) []byte); ok { + r0 = rf(ctx, id, msg) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, []byte) error); ok { + r1 = rf(ctx, id, msg) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Tron_Sign_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Sign' +type Tron_Sign_Call struct { + *mock.Call +} + +// Sign is a helper method to define mock.On call +// - ctx context.Context +// - id string +// - msg []byte +func (_e *Tron_Expecter) Sign(ctx interface{}, id interface{}, msg interface{}) *Tron_Sign_Call { + return &Tron_Sign_Call{Call: _e.mock.On("Sign", ctx, id, msg)} +} + +func (_c *Tron_Sign_Call) Run(run func(ctx context.Context, id string, msg []byte)) *Tron_Sign_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string), args[2].([]byte)) + }) + return _c +} + +func (_c *Tron_Sign_Call) Return(signature []byte, err error) *Tron_Sign_Call { + _c.Call.Return(signature, err) + return _c +} + +func (_c *Tron_Sign_Call) RunAndReturn(run func(context.Context, string, []byte) ([]byte, error)) *Tron_Sign_Call { + _c.Call.Return(run) + return _c +} + +// NewTron creates a new instance of Tron. 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 NewTron(t interface { + mock.TestingT + Cleanup(func()) +}) *Tron { + mock := &Tron{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/core/services/keystore/mocks/vrf.go b/core/services/keystore/mocks/vrf.go index dff36e8a3e9..e1705daa64a 100644 --- a/core/services/keystore/mocks/vrf.go +++ b/core/services/keystore/mocks/vrf.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -356,7 +356,7 @@ func (_c *VRF_Get_Call) RunAndReturn(run func(string) (vrfkey.KeyV2, error)) *VR return _c } -// GetAll provides a mock function with given fields: +// GetAll provides a mock function with no fields func (_m *VRF) GetAll() ([]vrfkey.KeyV2, error) { ret := _m.Called() diff --git a/core/services/keystore/mocks/workflow.go b/core/services/keystore/mocks/workflow.go index f19045cecc4..91929e13768 100644 --- a/core/services/keystore/mocks/workflow.go +++ b/core/services/keystore/mocks/workflow.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -344,7 +344,7 @@ func (_c *Workflow_Get_Call) RunAndReturn(run func(string) (workflowkey.Key, err return _c } -// GetAll provides a mock function with given fields: +// GetAll provides a mock function with no fields func (_m *Workflow) GetAll() ([]workflowkey.Key, error) { ret := _m.Called() diff --git a/core/services/keystore/models.go b/core/services/keystore/models.go index 151934827c3..1ebc7480997 100644 --- a/core/services/keystore/models.go +++ b/core/services/keystore/models.go @@ -20,6 +20,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/solkey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/starkkey" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/tronkey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/vrfkey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/workflowkey" "github.com/smartcontractkit/chainlink/v2/core/utils" @@ -158,6 +159,7 @@ type keyRing struct { Solana map[string]solkey.Key StarkNet map[string]starkkey.Key Aptos map[string]aptoskey.Key + Tron map[string]tronkey.Key VRF map[string]vrfkey.KeyV2 Workflow map[string]workflowkey.Key LegacyKeys LegacyKeyStorage @@ -174,6 +176,7 @@ func newKeyRing() *keyRing { Solana: make(map[string]solkey.Key), StarkNet: make(map[string]starkkey.Key), Aptos: make(map[string]aptoskey.Key), + Tron: make(map[string]tronkey.Key), VRF: make(map[string]vrfkey.KeyV2), Workflow: make(map[string]workflowkey.Key), } @@ -236,6 +239,9 @@ func (kr *keyRing) raw() (rawKeys rawKeyRing) { for _, aptoskey := range kr.Aptos { rawKeys.Aptos = append(rawKeys.Aptos, aptoskey.Raw()) } + for _, tronkey := range kr.Tron { + rawKeys.Tron = append(rawKeys.Tron, tronkey.Raw()) + } for _, vrfKey := range kr.VRF { rawKeys.VRF = append(rawKeys.VRF, vrfKey.Raw()) } @@ -283,6 +289,10 @@ func (kr *keyRing) logPubKeys(lggr logger.Logger) { for _, aptosKey := range kr.Aptos { aptosIDs = append(aptosIDs, aptosKey.ID()) } + tronIDs := []string{} + for _, tronKey := range kr.Tron { + tronIDs = append(tronIDs, tronKey.ID()) + } var vrfIDs []string for _, VRFKey := range kr.VRF { vrfIDs = append(vrfIDs, VRFKey.ID()) @@ -320,6 +330,9 @@ func (kr *keyRing) logPubKeys(lggr logger.Logger) { if len(aptosIDs) > 0 { lggr.Infow(fmt.Sprintf("Unlocked %d Aptos keys", len(aptosIDs)), "keys", aptosIDs) } + if len(tronIDs) > 0 { + lggr.Infow(fmt.Sprintf("Unlocked %d Tron keys", len(tronIDs)), "keys", tronIDs) + } if len(vrfIDs) > 0 { lggr.Infow(fmt.Sprintf("Unlocked %d VRF keys", len(vrfIDs)), "keys", vrfIDs) } @@ -344,6 +357,7 @@ type rawKeyRing struct { Solana []solkey.Raw StarkNet []starkkey.Raw Aptos []aptoskey.Raw + Tron []tronkey.Raw VRF []vrfkey.Raw Workflow []workflowkey.Raw LegacyKeys LegacyKeyStorage `json:"-"` @@ -388,6 +402,10 @@ func (rawKeys rawKeyRing) keys() (*keyRing, error) { aptosKey := rawAptosKey.Key() keyRing.Aptos[aptosKey.ID()] = aptosKey } + for _, rawTronKey := range rawKeys.Tron { + tronKey := rawTronKey.Key() + keyRing.Tron[tronKey.ID()] = tronKey + } for _, rawVRFKey := range rawKeys.VRF { vrfKey := rawVRFKey.Key() keyRing.VRF[vrfKey.ID()] = vrfKey diff --git a/core/services/keystore/models_test.go b/core/services/keystore/models_test.go index a828fbbf4f6..a66e29865d1 100644 --- a/core/services/keystore/models_test.go +++ b/core/services/keystore/models_test.go @@ -16,6 +16,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocrkey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/solkey" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/tronkey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/vrfkey" "github.com/smartcontractkit/chainlink/v2/core/utils" ) @@ -40,6 +41,7 @@ func TestKeyRing_Encrypt_Decrypt(t *testing.T) { sol1, sol2 := solkey.MustNewInsecure(rand.Reader), solkey.MustNewInsecure(rand.Reader) vrf1, vrf2 := vrfkey.MustNewV2XXXTestingOnly(big.NewInt(1)), vrfkey.MustNewV2XXXTestingOnly(big.NewInt(2)) tk1, tk2 := cosmoskey.MustNewInsecure(rand.Reader), cosmoskey.MustNewInsecure(rand.Reader) + uk1, uk2 := tronkey.MustNewInsecure(rand.Reader), tronkey.MustNewInsecure(rand.Reader) originalKeyRingRaw := rawKeyRing{ CSA: []csakey.Raw{csa1.Raw(), csa2.Raw()}, Eth: []ethkey.Raw{eth1.Raw(), eth2.Raw()}, @@ -49,6 +51,7 @@ func TestKeyRing_Encrypt_Decrypt(t *testing.T) { Solana: []solkey.Raw{sol1.Raw(), sol2.Raw()}, VRF: []vrfkey.Raw{vrf1.Raw(), vrf2.Raw()}, Cosmos: []cosmoskey.Raw{tk1.Raw(), tk2.Raw()}, + Tron: []tronkey.Raw{uk1.Raw(), uk2.Raw()}, } originalKeyRing, kerr := originalKeyRingRaw.keys() require.NoError(t, kerr) @@ -62,6 +65,10 @@ func TestKeyRing_Encrypt_Decrypt(t *testing.T) { require.Equal(t, 2, len(decryptedKeyRing.Cosmos)) require.Equal(t, originalKeyRing.Cosmos[tk1.ID()].PublicKey(), decryptedKeyRing.Cosmos[tk1.ID()].PublicKey()) require.Equal(t, originalKeyRing.Cosmos[tk2.ID()].PublicKey(), decryptedKeyRing.Cosmos[tk2.ID()].PublicKey()) + // compare tron keys + require.Len(t, decryptedKeyRing.Tron, 2) + require.Equal(t, originalKeyRing.Tron[uk1.ID()].Base58Address(), decryptedKeyRing.Tron[uk1.ID()].Base58Address()) + require.Equal(t, originalKeyRing.Tron[uk2.ID()].Base58Address(), decryptedKeyRing.Tron[uk2.ID()].Base58Address()) // compare csa keys require.Equal(t, 2, len(decryptedKeyRing.CSA)) require.Equal(t, originalKeyRing.CSA[csa1.ID()].PublicKey, decryptedKeyRing.CSA[csa1.ID()].PublicKey) diff --git a/core/services/keystore/ocr2_test.go b/core/services/keystore/ocr2_test.go index 7288b86d1d1..027133294e1 100644 --- a/core/services/keystore/ocr2_test.go +++ b/core/services/keystore/ocr2_test.go @@ -192,9 +192,21 @@ func Test_OCR2KeyStore_E2E(t *testing.T) { assert.NoError(t, err) require.Equal(t, 3, len(keys)) - straknetKeys, err := ks.GetAllOfType(chaintype.StarkNet) - assert.NoError(t, err) - require.Equal(t, 1, len(straknetKeys)) - require.Equal(t, straknetKeys[0].ChainType(), chaintype.StarkNet) + starknetKeys, err := ks.GetAllOfType(chaintype.StarkNet) + require.NoError(t, err) + require.Len(t, starknetKeys, 1) + require.Equal(t, chaintype.StarkNet, starknetKeys[0].ChainType()) + + err = ks.EnsureKeys(ctx, chaintype.Tron) + require.NoError(t, err) + + keys, err = ks.GetAll() + require.NoError(t, err) + require.Len(t, keys, 4) + + tronKeys, err := ks.GetAllOfType(chaintype.Tron) + require.NoError(t, err) + require.Len(t, tronKeys, 1) + require.Equal(t, chaintype.Tron, tronKeys[0].ChainType()) }) } diff --git a/core/services/keystore/tron.go b/core/services/keystore/tron.go new file mode 100644 index 00000000000..d5302d572b0 --- /dev/null +++ b/core/services/keystore/tron.go @@ -0,0 +1,187 @@ +package keystore + +import ( + "context" + "fmt" + + "github.com/pkg/errors" + + "github.com/smartcontractkit/chainlink-common/pkg/loop" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/tronkey" +) + +type Tron interface { + Get(id string) (tronkey.Key, error) + GetAll() ([]tronkey.Key, error) + Create(ctx context.Context) (tronkey.Key, error) + Add(ctx context.Context, key tronkey.Key) error + Delete(ctx context.Context, id string) (tronkey.Key, error) + Import(ctx context.Context, keyJSON []byte, password string) (tronkey.Key, error) + Export(id string, password string) ([]byte, error) + EnsureKey(ctx context.Context) error + Sign(ctx context.Context, id string, msg []byte) (signature []byte, err error) +} + +type tron struct { + *keyManager +} + +var _ Tron = &tron{} + +func newTronKeyStore(km *keyManager) *tron { + return &tron{ + km, + } +} + +func (ks *tron) Get(id string) (tronkey.Key, error) { + ks.lock.RLock() + defer ks.lock.RUnlock() + if ks.isLocked() { + return tronkey.Key{}, ErrLocked + } + return ks.getByID(id) +} + +func (ks *tron) GetAll() (keys []tronkey.Key, _ error) { + ks.lock.RLock() + defer ks.lock.RUnlock() + if ks.isLocked() { + return nil, ErrLocked + } + for _, key := range ks.keyRing.Tron { + keys = append(keys, key) + } + return keys, nil +} + +func (ks *tron) Create(ctx context.Context) (tronkey.Key, error) { + ks.lock.Lock() + defer ks.lock.Unlock() + if ks.isLocked() { + return tronkey.Key{}, ErrLocked + } + key, err := tronkey.New() + if err != nil { + return tronkey.Key{}, err + } + return key, ks.safeAddKey(ctx, key) +} + +func (ks *tron) Add(ctx context.Context, key tronkey.Key) error { + ks.lock.Lock() + defer ks.lock.Unlock() + if ks.isLocked() { + return ErrLocked + } + if _, found := ks.keyRing.Tron[key.ID()]; found { + return fmt.Errorf("key with ID %s already exists", key.ID()) + } + return ks.safeAddKey(ctx, key) +} + +func (ks *tron) Delete(ctx context.Context, id string) (tronkey.Key, error) { + ks.lock.Lock() + defer ks.lock.Unlock() + if ks.isLocked() { + return tronkey.Key{}, ErrLocked + } + key, err := ks.getByID(id) + if err != nil { + return tronkey.Key{}, err + } + err = ks.safeRemoveKey(ctx, key) + return key, err +} + +func (ks *tron) Import(ctx context.Context, keyJSON []byte, password string) (tronkey.Key, error) { + ks.lock.Lock() + defer ks.lock.Unlock() + if ks.isLocked() { + return tronkey.Key{}, ErrLocked + } + key, err := tronkey.FromEncryptedJSON(keyJSON, password) + if err != nil { + return tronkey.Key{}, errors.Wrap(err, "TronKeyStore#ImportKey failed to decrypt key") + } + if _, found := ks.keyRing.Tron[key.ID()]; found { + return tronkey.Key{}, fmt.Errorf("key with ID %s already exists", key.ID()) + } + return key, ks.keyManager.safeAddKey(ctx, key) +} + +func (ks *tron) Export(id string, password string) ([]byte, error) { + ks.lock.RLock() + defer ks.lock.RUnlock() + if ks.isLocked() { + return nil, ErrLocked + } + key, err := ks.getByID(id) + if err != nil { + return nil, err + } + return key.ToEncryptedJSON(password, ks.scryptParams) +} + +func (ks *tron) EnsureKey(ctx context.Context) error { + ks.lock.Lock() + defer ks.lock.Unlock() + if ks.isLocked() { + return ErrLocked + } + + if len(ks.keyRing.Tron) > 0 { + return nil + } + + key, err := tronkey.New() + if err != nil { + return err + } + + ks.logger.Infof("Created Tron key with ID %s", key.ID()) + + return ks.safeAddKey(ctx, key) +} + +func (ks *tron) getByID(id string) (tronkey.Key, error) { + key, found := ks.keyRing.Tron[id] + if !found { + return tronkey.Key{}, KeyNotFoundError{ID: id, KeyType: "Tron"} + } + return key, nil +} + +func (ks *tron) Sign(_ context.Context, id string, msg []byte) (signature []byte, err error) { + k, err := ks.Get(id) + if err != nil { + return nil, err + } + // loopp spec requires passing nil hash to check existence of id + if msg == nil { + return nil, nil + } + return k.Sign(msg) +} + +// TronLOOPKeystore implements the [github.com/smartcontractkit/chainlink-common/pkg/loop.Keystore] interface and +// handles signing for Tron messages. +type TronLOOPKeystore struct { + Tron +} + +var _ loop.Keystore = &TronLOOPKeystore{} + +func (lk *TronLOOPKeystore) Accounts(ctx context.Context) ([]string, error) { + keys, err := lk.GetAll() + if err != nil { + return nil, err + } + + accounts := []string{} + for _, k := range keys { + accounts = append(accounts, k.PublicKeyStr()) + } + + return accounts, nil +} diff --git a/core/services/keystore/tron_test.go b/core/services/keystore/tron_test.go new file mode 100644 index 00000000000..2450e573898 --- /dev/null +++ b/core/services/keystore/tron_test.go @@ -0,0 +1,240 @@ +package keystore_test + +import ( + "context" + "crypto/sha256" + "encoding/json" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/utils" + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/tronkey" +) + +func Test_TronKeyStore_E2E(t *testing.T) { + db := pgtest.NewSqlxDB(t) + + keyStore := keystore.ExposedNewMaster(t, db) + require.NoError(t, keyStore.Unlock(testutils.Context(t), cltest.Password)) + ks := keyStore.Tron() + reset := func() { + ctx := context.Background() // Executed on cleanup + require.NoError(t, utils.JustError(db.Exec("DELETE FROM encrypted_key_rings"))) + keyStore.ResetXXXTestOnly() + require.NoError(t, keyStore.Unlock(ctx, cltest.Password)) + } + + t.Run("initializes with an empty state", func(t *testing.T) { + defer reset() + keys, err := ks.GetAll() + require.NoError(t, err) + require.Empty(t, keys) + }) + + t.Run("errors when getting non-existent ID", func(t *testing.T) { + defer reset() + _, err := ks.Get("non-existent-id") + require.Error(t, err) + }) + + t.Run("creates a key", func(t *testing.T) { + defer reset() + ctx := testutils.Context(t) + key, err := ks.Create(ctx) + require.NoError(t, err) + retrievedKey, err := ks.Get(key.ID()) + require.NoError(t, err) + require.Equal(t, key, retrievedKey) + }) + + t.Run("imports and exports a key", func(t *testing.T) { + defer reset() + ctx := testutils.Context(t) + key, err := ks.Create(ctx) + require.NoError(t, err) + exportJSON, err := ks.Export(key.ID(), cltest.Password) + require.NoError(t, err) + _, err = ks.Export("non-existent", cltest.Password) + require.Error(t, err) + _, err = ks.Delete(ctx, key.ID()) + require.NoError(t, err) + _, err = ks.Get(key.ID()) + require.Error(t, err) + importedKey, err := ks.Import(ctx, exportJSON, cltest.Password) + require.NoError(t, err) + _, err = ks.Import(ctx, exportJSON, cltest.Password) + require.Error(t, err) + _, err = ks.Import(ctx, []byte(""), cltest.Password) + require.Error(t, err) + require.Equal(t, key.ID(), importedKey.ID()) + retrievedKey, err := ks.Get(key.ID()) + require.NoError(t, err) + require.Equal(t, importedKey, retrievedKey) + }) + + t.Run("adds an externally created key / deletes a key", func(t *testing.T) { + defer reset() + ctx := testutils.Context(t) + newKey, err := tronkey.New() + require.NoError(t, err) + err = ks.Add(ctx, newKey) + require.NoError(t, err) + err = ks.Add(ctx, newKey) + require.Error(t, err) + keys, err := ks.GetAll() + require.NoError(t, err) + require.Len(t, keys, 1) + _, err = ks.Delete(ctx, newKey.ID()) + require.NoError(t, err) + _, err = ks.Delete(ctx, newKey.ID()) + require.Error(t, err) + keys, err = ks.GetAll() + require.NoError(t, err) + require.Empty(t, keys) + _, err = ks.Get(newKey.ID()) + require.Error(t, err) + }) + + t.Run("ensures key", func(t *testing.T) { + defer reset() + ctx := testutils.Context(t) + err := ks.EnsureKey(ctx) + require.NoError(t, err) + + err = ks.EnsureKey(ctx) + require.NoError(t, err) + + keys, err := ks.GetAll() + require.NoError(t, err) + require.Len(t, keys, 1) + }) + + t.Run("sign tx", func(t *testing.T) { + defer reset() + ctx := testutils.Context(t) + newKey, err := tronkey.New() + require.NoError(t, err) + require.NoError(t, ks.Add(ctx, newKey)) + + // sign unknown ID + _, err = ks.Sign(testutils.Context(t), "not-real", nil) + require.Error(t, err) + + // sign known key + + // Create a mock transaction + mockTx := createMockTronTransaction(newKey.PublicKeyStr(), "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8", 1000000) + serializedTx, err := serializeMockTransaction(mockTx) + require.NoError(t, err) + + hash := sha256.Sum256(serializedTx) + txHash := hash[:] + sig, err := ks.Sign(testutils.Context(t), newKey.ID(), txHash) + require.NoError(t, err) + + directSig, err := newKey.Sign(txHash) + require.NoError(t, err) + + // signatures should match using keystore sign or key sign + require.Equal(t, directSig, sig) + }) +} + +// MockTronTransaction represents a mock TRON transaction +// This is based on https://developers.tron.network/docs/tron-protocol-transaction +type MockTronTransaction struct { + RawData struct { + Contract []struct { + Parameter struct { + Value struct { + Amount int64 `json:"amount"` + OwnerAddress string `json:"owner_address"` + ToAddress string `json:"to_address"` + } `json:"value"` + TypeURL string `json:"type_url"` + } `json:"parameter"` + Type string `json:"type"` + } `json:"contract"` + RefBlockBytes string `json:"ref_block_bytes"` + RefBlockHash string `json:"ref_block_hash"` + Expiration int64 `json:"expiration"` + Timestamp int64 `json:"timestamp"` + FeeLimit int64 `json:"fee_limit"` + } `json:"raw_data"` + Signature []string `json:"signature"` + TxID string `json:"txID"` +} + +// CreateMockTronTransaction generates a mock TRON transaction for testing +func createMockTronTransaction(ownerAddress, toAddress string, amount int64) MockTronTransaction { + return MockTronTransaction{ + RawData: struct { + Contract []struct { + Parameter struct { + Value struct { + Amount int64 `json:"amount"` + OwnerAddress string `json:"owner_address"` + ToAddress string `json:"to_address"` + } `json:"value"` + TypeURL string `json:"type_url"` + } `json:"parameter"` + Type string `json:"type"` + } `json:"contract"` + RefBlockBytes string `json:"ref_block_bytes"` + RefBlockHash string `json:"ref_block_hash"` + Expiration int64 `json:"expiration"` + Timestamp int64 `json:"timestamp"` + FeeLimit int64 `json:"fee_limit"` + }{ + Contract: []struct { + Parameter struct { + Value struct { + Amount int64 `json:"amount"` + OwnerAddress string `json:"owner_address"` + ToAddress string `json:"to_address"` + } `json:"value"` + TypeURL string `json:"type_url"` + } `json:"parameter"` + Type string `json:"type"` + }{ + { + Parameter: struct { + Value struct { + Amount int64 `json:"amount"` + OwnerAddress string `json:"owner_address"` + ToAddress string `json:"to_address"` + } `json:"value"` + TypeURL string `json:"type_url"` + }{ + Value: struct { + Amount int64 `json:"amount"` + OwnerAddress string `json:"owner_address"` + ToAddress string `json:"to_address"` + }{ + Amount: amount, + OwnerAddress: ownerAddress, + ToAddress: toAddress, + }, + TypeURL: "type.googleapis.com/protocol.TransferContract", + }, + Type: "TransferContract", + }, + }, + RefBlockBytes: "1234", + RefBlockHash: "abcdef0123456789", + Expiration: time.Now().Unix() + 60*60, + Timestamp: time.Now().Unix(), + FeeLimit: 10000000, + }, + } +} + +func serializeMockTransaction(tx MockTronTransaction) ([]byte, error) { + return json.Marshal(tx) +} diff --git a/core/services/llo/codecs.go b/core/services/llo/codecs.go index f9c5b7b3380..050a1945873 100644 --- a/core/services/llo/codecs.go +++ b/core/services/llo/codecs.go @@ -14,6 +14,7 @@ func NewReportCodecs(lggr logger.Logger, donID uint32) map[llotypes.ReportFormat codecs[llotypes.ReportFormatJSON] = llo.JSONReportCodec{} codecs[llotypes.ReportFormatEVMPremiumLegacy] = evm.NewReportCodecPremiumLegacy(lggr, donID) + codecs[llotypes.ReportFormatEVMABIEncodeUnpacked] = evm.NewReportCodecEVMABIEncodeUnpacked(lggr, donID) return codecs } diff --git a/core/services/llo/data_source.go b/core/services/llo/data_source.go index 2afe9e090a3..855ac7d9940 100644 --- a/core/services/llo/data_source.go +++ b/core/services/llo/data_source.go @@ -2,15 +2,16 @@ package llo import ( "context" + "errors" "fmt" "slices" "sort" + "strconv" "sync" "time" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" - "github.com/shopspring/decimal" "golang.org/x/exp/maps" "github.com/smartcontractkit/chainlink-common/pkg/logger" @@ -19,7 +20,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/services/streams" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) var ( @@ -42,7 +42,7 @@ var ( ) type Registry interface { - Get(streamID streams.StreamID) (strm streams.Stream, exists bool) + Get(streamID streams.StreamID) (p streams.Pipeline, exists bool) } type ErrObservationFailed struct { @@ -109,43 +109,25 @@ func (d *dataSource) Observe(ctx context.Context, streamValues llo.StreamValues, successfulStreamIDs := make([]streams.StreamID, 0, len(streamValues)) var errs []ErrObservationFailed + // oc only lives for the duration of this Observe call + oc := NewObservationContext(d.registry, d.t) + for _, streamID := range maps.Keys(streamValues) { go func(streamID llotypes.StreamID) { defer wg.Done() - - var val llo.StreamValue - - stream, exists := d.registry.Get(streamID) - if !exists { - mu.Lock() - errs = append(errs, ErrObservationFailed{streamID: streamID, reason: fmt.Sprintf("missing stream: %d", streamID)}) - mu.Unlock() - promMissingStreamCount.WithLabelValues(fmt.Sprintf("%d", streamID)).Inc() - return - } - run, trrs, err := stream.Run(ctx) - if err != nil { - mu.Lock() - errs = append(errs, ErrObservationFailed{inner: err, run: run, streamID: streamID, reason: "pipeline run failed"}) - mu.Unlock() - promObservationErrorCount.WithLabelValues(fmt.Sprintf("%d", streamID)).Inc() - // TODO: Consolidate/reduce telemetry. We should send all observation results in a single packet - // https://smartcontract-it.atlassian.net/browse/MERC-6290 - d.t.EnqueueV3PremiumLegacy(run, trrs, streamID, opts, nil, err) - return - } - // TODO: Consolidate/reduce telemetry. We should send all observation results in a single packet - // https://smartcontract-it.atlassian.net/browse/MERC-6290 - val, err = ExtractStreamValue(trrs) + val, err := oc.Observe(ctx, streamID, opts) if err != nil { + strmIDStr := strconv.FormatUint(uint64(streamID), 10) + if errors.As(err, &MissingStreamError{}) { + promMissingStreamCount.WithLabelValues(strmIDStr).Inc() + } + promObservationErrorCount.WithLabelValues(strmIDStr).Inc() mu.Lock() - errs = append(errs, ErrObservationFailed{inner: err, run: run, streamID: streamID, reason: "failed to extract big.Int"}) + errs = append(errs, ErrObservationFailed{inner: err, streamID: streamID, reason: "failed to observe stream"}) mu.Unlock() return } - d.t.EnqueueV3PremiumLegacy(run, trrs, streamID, opts, val, nil) - mu.Lock() defer mu.Unlock() @@ -186,54 +168,3 @@ func (d *dataSource) Observe(ctx context.Context, streamValues llo.StreamValues, return nil } - -// ExtractStreamValue extracts a StreamValue from a TaskRunResults -func ExtractStreamValue(trrs pipeline.TaskRunResults) (llo.StreamValue, error) { - // pipeline.TaskRunResults comes ordered asc by index, this is guaranteed - // by the pipeline executor - finaltrrs := trrs.Terminals() - - // HACK: Right now we rely on the number of outputs to determine whether - // its a Decimal or a Quote. - // This isn't very robust or future-proof but is sufficient to support v0.3 - // compat. - // There are a number of different possible ways to solve this in future. - // See: https://smartcontract-it.atlassian.net/browse/MERC-5934 - switch len(finaltrrs) { - case 1: - res := finaltrrs[0].Result - if res.Error != nil { - return nil, res.Error - } - val, err := toDecimal(res.Value) - if err != nil { - return nil, fmt.Errorf("failed to parse BenchmarkPrice: %w", err) - } - return llo.ToDecimal(val), nil - case 3: - // Expect ordering of Benchmark, Bid, Ask - results := make([]decimal.Decimal, 3) - for i, trr := range finaltrrs { - res := trr.Result - if res.Error != nil { - return nil, fmt.Errorf("failed to parse stream output into Quote (task index: %d): %w", i, res.Error) - } - val, err := toDecimal(res.Value) - if err != nil { - return nil, fmt.Errorf("failed to parse decimal: %w", err) - } - results[i] = val - } - return &llo.Quote{ - Benchmark: results[0], - Bid: results[1], - Ask: results[2], - }, nil - default: - return nil, fmt.Errorf("invalid number of results, expected: 1 or 3, got: %d", len(finaltrrs)) - } -} - -func toDecimal(val interface{}) (decimal.Decimal, error) { - return utils.ToDecimal(val) -} diff --git a/core/services/llo/data_source_test.go b/core/services/llo/data_source_test.go index 932c4c0c73a..349ec70007d 100644 --- a/core/services/llo/data_source_test.go +++ b/core/services/llo/data_source_test.go @@ -3,6 +3,8 @@ package llo import ( "context" "errors" + "fmt" + "math" "math/big" "sync" "testing" @@ -10,38 +12,54 @@ import ( "github.com/shopspring/decimal" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gopkg.in/guregu/null.v4" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" + "github.com/smartcontractkit/chainlink-data-streams/llo" + "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + clhttptest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/httptest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/services/streams" ) -type mockStream struct { +type mockPipeline struct { run *pipeline.Run trrs pipeline.TaskRunResults err error + + streamIDs []streams.StreamID + + runCount int } -func (m *mockStream) Run(ctx context.Context) (*pipeline.Run, pipeline.TaskRunResults, error) { +func (m *mockPipeline) Run(ctx context.Context) (*pipeline.Run, pipeline.TaskRunResults, error) { + m.runCount++ return m.run, m.trrs, m.err } +func (m *mockPipeline) StreamIDs() []streams.StreamID { + return m.streamIDs +} + type mockRegistry struct { - streams map[streams.StreamID]*mockStream + pipelines map[streams.StreamID]*mockPipeline } -func (m *mockRegistry) Get(streamID streams.StreamID) (strm streams.Stream, exists bool) { - strm, exists = m.streams[streamID] +func (m *mockRegistry) Get(streamID streams.StreamID) (p streams.Pipeline, exists bool) { + p, exists = m.pipelines[streamID] return } -func makeStreamWithSingleResult[T any](runID int64, res T, err error) *mockStream { - return &mockStream{ +func makePipelineWithSingleResult[T any](runID int64, res T, err error) *mockPipeline { + return &mockPipeline{ run: &pipeline.Run{ID: runID}, trrs: []pipeline.TaskRunResult{pipeline.TaskRunResult{Task: &pipeline.MemoTask{}, Result: pipeline.Result{Value: res}}}, err: err, @@ -56,9 +74,11 @@ func makeStreamValues() llo.StreamValues { } } -type mockOpts struct{} +type mockOpts struct { + verboseLogging bool +} -func (m *mockOpts) VerboseLogging() bool { return true } +func (m *mockOpts) VerboseLogging() bool { return m.verboseLogging } func (m *mockOpts) SeqNr() uint64 { return 1042 } func (m *mockOpts) OutCtx() ocr3types.OutcomeContext { return ocr3types.OutcomeContext{SeqNr: 1042, PreviousOutcome: ocr3types.Outcome([]byte("foo"))} @@ -91,7 +111,7 @@ func (m *mockTelemeter) EnqueueV3PremiumLegacy(run *pipeline.Run, trrs pipeline. func Test_DataSource(t *testing.T) { lggr := logger.TestLogger(t) - reg := &mockRegistry{make(map[streams.StreamID]*mockStream)} + reg := &mockRegistry{make(map[streams.StreamID]*mockPipeline)} ds := newDataSource(lggr, reg, NullTelemeter) ctx := testutils.Context(t) opts := &mockOpts{} @@ -105,9 +125,9 @@ func Test_DataSource(t *testing.T) { assert.Equal(t, makeStreamValues(), vals) }) t.Run("observes each stream with success and returns values matching map argument", func(t *testing.T) { - reg.streams[1] = makeStreamWithSingleResult[*big.Int](1, big.NewInt(2181), nil) - reg.streams[2] = makeStreamWithSingleResult[*big.Int](2, big.NewInt(40602), nil) - reg.streams[3] = makeStreamWithSingleResult[*big.Int](3, big.NewInt(15), nil) + reg.pipelines[1] = makePipelineWithSingleResult[*big.Int](1, big.NewInt(2181), nil) + reg.pipelines[2] = makePipelineWithSingleResult[*big.Int](2, big.NewInt(40602), nil) + reg.pipelines[3] = makePipelineWithSingleResult[*big.Int](3, big.NewInt(15), nil) vals := makeStreamValues() err := ds.Observe(ctx, vals, opts) @@ -120,9 +140,9 @@ func Test_DataSource(t *testing.T) { }, vals) }) t.Run("observes each stream and returns success/errors", func(t *testing.T) { - reg.streams[1] = makeStreamWithSingleResult[*big.Int](1, big.NewInt(2181), errors.New("something exploded")) - reg.streams[2] = makeStreamWithSingleResult[*big.Int](2, big.NewInt(40602), nil) - reg.streams[3] = makeStreamWithSingleResult[*big.Int](3, nil, errors.New("something exploded 2")) + reg.pipelines[1] = makePipelineWithSingleResult[*big.Int](1, big.NewInt(2181), errors.New("something exploded")) + reg.pipelines[2] = makePipelineWithSingleResult[*big.Int](2, big.NewInt(40602), nil) + reg.pipelines[3] = makePipelineWithSingleResult[*big.Int](3, nil, errors.New("something exploded 2")) vals := makeStreamValues() err := ds.Observe(ctx, vals, opts) @@ -139,9 +159,9 @@ func Test_DataSource(t *testing.T) { tm := &mockTelemeter{} ds.t = tm - reg.streams[1] = makeStreamWithSingleResult[*big.Int](100, big.NewInt(2181), nil) - reg.streams[2] = makeStreamWithSingleResult[*big.Int](101, big.NewInt(40602), nil) - reg.streams[3] = makeStreamWithSingleResult[*big.Int](102, big.NewInt(15), nil) + reg.pipelines[1] = makePipelineWithSingleResult[*big.Int](100, big.NewInt(2181), nil) + reg.pipelines[2] = makePipelineWithSingleResult[*big.Int](101, big.NewInt(40602), nil) + reg.pipelines[3] = makePipelineWithSingleResult[*big.Int](102, big.NewInt(15), nil) vals := makeStreamValues() err := ds.Observe(ctx, vals, opts) @@ -166,5 +186,112 @@ func Test_DataSource(t *testing.T) { assert.Equal(t, "2181", pkt.val.(*llo.Decimal).String()) assert.Nil(t, pkt.err) }) + + t.Run("records telemetry for errors", func(t *testing.T) { + tm := &mockTelemeter{} + ds.t = tm + + reg.pipelines[1] = makePipelineWithSingleResult[*big.Int](100, big.NewInt(2181), errors.New("something exploded")) + reg.pipelines[2] = makePipelineWithSingleResult[*big.Int](101, big.NewInt(40602), nil) + reg.pipelines[3] = makePipelineWithSingleResult[*big.Int](102, nil, errors.New("something exploded 2")) + + vals := makeStreamValues() + err := ds.Observe(ctx, vals, opts) + require.NoError(t, err) + + assert.Equal(t, llo.StreamValues{ + 2: llo.ToDecimal(decimal.NewFromInt(40602)), + 1: nil, + 3: nil, + }, vals) + + require.Len(t, tm.v3PremiumLegacyPackets, 3) + m := make(map[int]v3PremiumLegacyPacket) + for _, pkt := range tm.v3PremiumLegacyPackets { + m[int(pkt.run.ID)] = pkt + } + pkt := m[100] + assert.Equal(t, 100, int(pkt.run.ID)) + assert.Len(t, pkt.trrs, 1) + assert.Equal(t, 1, int(pkt.streamID)) + assert.Equal(t, opts, pkt.opts) + assert.Nil(t, pkt.val) + assert.Error(t, pkt.err) + }) }) } + +func BenchmarkObserve(b *testing.B) { + lggr := logger.TestLogger(b) + ctx := testutils.Context(b) + // can enable/disable verbose logging to test performance here + opts := &mockOpts{verboseLogging: true} + + db := pgtest.NewSqlxDB(b) + bridgesORM := bridges.NewORM(db) + + if b.N > math.MaxInt32 { + b.Fatalf("N is too large: %d", b.N) + } + + n := uint32(b.N) //nolint:gosec // G115 // overflow impossible + + createBridge(b, "foo-bridge", `123.456`, bridgesORM, 0) + createBridge(b, "bar-bridge", `"124.456"`, bridgesORM, 0) + + c := clhttptest.NewTestLocalOnlyHTTPClient() + runner := pipeline.NewRunner( + nil, + bridgesORM, + &mockPipelineConfig{}, + &mockBridgeConfig{}, + nil, + nil, + nil, + lggr, + c, + c, + ) + + r := streams.NewRegistry(lggr, runner) + for i := uint32(0); i < n; i++ { + i := i + jb := job.Job{ + ID: int32(i), //nolint:gosec // G115 // overflow impossible + Name: null.StringFrom(fmt.Sprintf("job-%d", i)), + Type: job.Stream, + StreamID: &i, + PipelineSpec: &pipeline.Spec{ + ID: int32(i * 100), //nolint:gosec // G115 // overflow impossible + DotDagSource: fmt.Sprintf(` +// Benchmark Price +result1 [type=memo value="900.0022"]; +multiply2 [type=multiply times=1 streamID=%d index=0]; // force conversion to decimal + +result2 [type=bridge name="foo-bridge" requestData="{\"data\":{\"data\":\"foo\"}}"]; +result2_parse [type=jsonparse path="result" streamID=%d index=1]; + +result3 [type=bridge name="bar-bridge" requestData="{\"data\":{\"data\":\"bar\"}}"]; +result3_parse [type=jsonparse path="result"]; +multiply3 [type=multiply times=1 streamID=%d index=2]; // force conversion to decimal + +result1 -> multiply2; +result2 -> result2_parse; +result3 -> result3_parse -> multiply3; +`, i+n, i+2*n, i+3*n), + }, + } + err := r.Register(jb, nil) + require.NoError(b, err) + } + + ds := newDataSource(lggr, r, NullTelemeter) + vals := make(map[llotypes.StreamID]llo.StreamValue) + for i := uint32(0); i < 4*n; i++ { + vals[i] = nil + } + + b.ResetTimer() + err := ds.Observe(ctx, vals, opts) + require.NoError(b, err) +} diff --git a/core/services/llo/delegate.go b/core/services/llo/delegate.go index ba4ddbb8fb0..0c7d539427e 100644 --- a/core/services/llo/delegate.go +++ b/core/services/llo/delegate.go @@ -69,12 +69,12 @@ type DelegateConfig struct { // One Oracle will be started for each ContractConfigTracker ContractConfigTrackers []ocr2types.ContractConfigTracker ContractTransmitter ocr3types.ContractTransmitter[llotypes.ReportInfo] - Database ocr3types.Database OCR3MonitoringEndpoint ocrcommontypes.MonitoringEndpoint OffchainConfigDigester ocr2types.OffchainConfigDigester OffchainKeyring ocr2types.OffchainKeyring OnchainKeyring ocr3types.OnchainKeyring[llotypes.ReportInfo] LocalConfig ocr2types.LocalConfig + NewOCR3DB func(pluginID int32) ocr3types.Database } func NewDelegate(cfg DelegateConfig) (job.ServiceCtx, error) { @@ -146,7 +146,7 @@ func (d *delegate) Start(ctx context.Context) error { V2Bootstrappers: d.cfg.V2Bootstrappers, ContractConfigTracker: configTracker, ContractTransmitter: d.cfg.ContractTransmitter, - Database: d.cfg.Database, + Database: d.cfg.NewOCR3DB(int32(i)), // //nolint:gosec // G115 // impossible due to check on line 119 LocalConfig: d.cfg.LocalConfig, Logger: ocrLogger, MonitoringEndpoint: d.cfg.OCR3MonitoringEndpoint, diff --git a/core/services/llo/evm/fees.go b/core/services/llo/evm/fees.go index b74d68b08d2..a6ff7a31178 100644 --- a/core/services/llo/evm/fees.go +++ b/core/services/llo/evm/fees.go @@ -16,8 +16,9 @@ const Precision int32 = 18 // CalculateFee outputs a fee in wei according to the formula: baseUSDFee / tokenPriceInUSD func CalculateFee(tokenPriceInUSD decimal.Decimal, baseUSDFee decimal.Decimal) *big.Int { - if tokenPriceInUSD.IsZero() || baseUSDFee.IsZero() { + if baseUSDFee.IsZero() || baseUSDFee.IsNegative() || tokenPriceInUSD.IsZero() || tokenPriceInUSD.IsNegative() { // zero fee if token price or base fee is zero + // if either fee should somehow be negative, also, return zero return big.NewInt(0) } diff --git a/core/services/llo/evm/fees_test.go b/core/services/llo/evm/fees_test.go index 33888de14ec..4f3fedbaedc 100644 --- a/core/services/llo/evm/fees_test.go +++ b/core/services/llo/evm/fees_test.go @@ -38,8 +38,27 @@ func Test_Fees(t *testing.T) { t.Run("with base fee == 0", func(t *testing.T) { tokenPriceInUSD := decimal.NewFromInt32(123) - BaseUSDFee = decimal.NewFromInt32(0) - fee := CalculateFee(tokenPriceInUSD, BaseUSDFee) + baseUSDFee := decimal.NewFromInt32(0) + fee := CalculateFee(tokenPriceInUSD, baseUSDFee) + assert.Equal(t, big.NewInt(0), fee) + }) + + t.Run("negative fee rounds up to zero", func(t *testing.T) { + tokenPriceInUSD := decimal.NewFromInt32(-123) + baseUSDFee := decimal.NewFromInt32(1) + fee := CalculateFee(tokenPriceInUSD, baseUSDFee) + assert.Equal(t, big.NewInt(0), fee) + + tokenPriceInUSD = decimal.NewFromInt32(123) + baseUSDFee = decimal.NewFromInt32(-1) + fee = CalculateFee(tokenPriceInUSD, baseUSDFee) + assert.Equal(t, big.NewInt(0), fee) + + // Multiple negative values also return a zero fee since negative + // prices are always nonsensical + tokenPriceInUSD = decimal.NewFromInt32(-123) + baseUSDFee = decimal.NewFromInt32(-1) + fee = CalculateFee(tokenPriceInUSD, baseUSDFee) assert.Equal(t, big.NewInt(0), fee) }) diff --git a/core/services/llo/evm/report_codec_evm_abi_encode_unpacked.go b/core/services/llo/evm/report_codec_evm_abi_encode_unpacked.go new file mode 100644 index 00000000000..309675aea77 --- /dev/null +++ b/core/services/llo/evm/report_codec_evm_abi_encode_unpacked.go @@ -0,0 +1,256 @@ +package evm + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/shopspring/decimal" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" + "github.com/smartcontractkit/chainlink-data-streams/llo" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/codec" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" +) + +var ( + _ llo.ReportCodec = ReportCodecEVMABIEncodeUnpacked{} + + zero = big.NewInt(0) +) + +type ReportCodecEVMABIEncodeUnpacked struct { + logger.Logger + donID uint32 +} + +func NewReportCodecEVMABIEncodeUnpacked(lggr logger.Logger, donID uint32) ReportCodecEVMABIEncodeUnpacked { + return ReportCodecEVMABIEncodeUnpacked{logger.Sugared(lggr).Named("ReportCodecEVMABIEncodeUnpacked"), donID} +} + +// Opts format remains unchanged +type ReportFormatEVMABIEncodeOpts struct { + // BaseUSDFee is the cost on-chain of verifying a report + BaseUSDFee decimal.Decimal `json:"baseUSDFee"` + // Expiration window is the length of time in seconds the report is valid + // for, from the observation timestamp + ExpirationWindow uint32 `json:"expirationWindow"` + // FeedID is for compatibility with existing on-chain verifiers + FeedID common.Hash `json:"feedID"` + // ABI defines the encoding of the payload. Each element maps to exactly + // one stream (although sub-arrays may be specified for streams that + // produce a composite data type). + // + // EXAMPLE + // + // [{"streamID":123,"multiplier":"10000","type":"uint192"}, ...] + // + // See definition of ABIEncoder struct for more details. + // + // The total number of streams must be 2+n, where n is the number of + // top-level elements in this ABI array (stream 0 is always the native + // token price and stream 1 is the link token price). + ABI []ABIEncoder `json:"abi"` +} + +func (r *ReportFormatEVMABIEncodeOpts) Decode(opts []byte) error { + return json.Unmarshal(opts, r) +} + +func (r *ReportFormatEVMABIEncodeOpts) Encode() ([]byte, error) { + return json.Marshal(r) +} + +type BaseReportFields struct { + FeedID common.Hash + ValidFromTimestamp uint32 + Timestamp uint32 + NativeFee *big.Int + LinkFee *big.Int + ExpiresAt uint32 +} + +func (r ReportCodecEVMABIEncodeUnpacked) Encode(ctx context.Context, report llo.Report, cd llotypes.ChannelDefinition) ([]byte, error) { + if report.Specimen { + return nil, errors.New("ReportCodecEVMABIEncodeUnpacked does not support encoding specimen reports") + } + if len(report.Values) < 2 { + return nil, fmt.Errorf("ReportCodecEVMABIEncodeUnpacked requires at least 2 values (NativePrice, LinkPrice, ...); got report.Values: %v", report.Values) + } + nativePrice, err := extractPrice(report.Values[0]) + if err != nil { + return nil, fmt.Errorf("ReportCodecEVMABIEncodeUnpacked failed to extract native price: %w", err) + } + linkPrice, err := extractPrice(report.Values[1]) + if err != nil { + return nil, fmt.Errorf("ReportCodecEVMABIEncodeUnpacked failed to extract link price: %w", err) + } + + // NOTE: It seems suboptimal to have to parse the opts on every encode but + // not sure how to avoid it. Should be negligible performance hit as long + // as Opts is small. + opts := ReportFormatEVMABIEncodeOpts{} + if err = (&opts).Decode(cd.Opts); err != nil { + return nil, fmt.Errorf("failed to decode opts; got: '%s'; %w", cd.Opts, err) + } + + rf := BaseReportFields{ + FeedID: opts.FeedID, + ValidFromTimestamp: report.ValidAfterSeconds + 1, + Timestamp: report.ObservationTimestampSeconds, + NativeFee: CalculateFee(nativePrice, opts.BaseUSDFee), + LinkFee: CalculateFee(linkPrice, opts.BaseUSDFee), + ExpiresAt: report.ObservationTimestampSeconds + opts.ExpirationWindow, + } + + header, err := r.buildHeader(ctx, rf) + if err != nil { + return nil, fmt.Errorf("failed to build base report; %w", err) + } + + payload, err := r.buildPayload(ctx, opts.ABI, report.Values[2:]) + if err != nil { + return nil, fmt.Errorf("failed to build payload; %w", err) + } + + return append(header, payload...), nil +} + +// BaseSchema represents the fixed base schema that remains unchanged for all +// EVMABIEncodeUnpacked reports. +// +// An arbitrary payload will be appended to this. +var BaseSchema = getBaseSchema() + +func getBaseSchema() abi.Arguments { + mustNewType := func(t string) abi.Type { + result, err := abi.NewType(t, "", []abi.ArgumentMarshaling{}) + if err != nil { + panic(fmt.Sprintf("Unexpected error during abi.NewType: %s", err)) + } + return result + } + return abi.Arguments([]abi.Argument{ + {Name: "feedId", Type: mustNewType("bytes32")}, + {Name: "validFromTimestamp", Type: mustNewType("uint32")}, + {Name: "observationsTimestamp", Type: mustNewType("uint32")}, + {Name: "nativeFee", Type: mustNewType("uint192")}, + {Name: "linkFee", Type: mustNewType("uint192")}, + {Name: "expiresAt", Type: mustNewType("uint32")}, + }) +} + +func (r ReportCodecEVMABIEncodeUnpacked) buildHeader(ctx context.Context, rf BaseReportFields) ([]byte, error) { + var merr error + if rf.LinkFee == nil { + merr = errors.Join(merr, errors.New("linkFee may not be nil")) + } else if rf.LinkFee.Cmp(zero) < 0 { + merr = errors.Join(merr, fmt.Errorf("linkFee may not be negative (got: %s)", rf.LinkFee)) + } + if rf.NativeFee == nil { + merr = errors.Join(merr, errors.New("nativeFee may not be nil")) + } else if rf.NativeFee.Cmp(zero) < 0 { + merr = errors.Join(merr, fmt.Errorf("nativeFee may not be negative (got: %s)", rf.NativeFee)) + } + if merr != nil { + return nil, merr + } + b, err := BaseSchema.Pack(rf.FeedID, rf.ValidFromTimestamp, rf.Timestamp, rf.NativeFee, rf.LinkFee, rf.ExpiresAt) + if err != nil { + return nil, fmt.Errorf("failed to pack base report blob; %w", err) + } + return b, nil +} + +func (r ReportCodecEVMABIEncodeUnpacked) buildPayload(ctx context.Context, encoders []ABIEncoder, values []llo.StreamValue) (payload []byte, merr error) { + if len(encoders) != len(values) { + return nil, fmt.Errorf("ABI and values length mismatch; ABI: %d, Values: %d", len(encoders), len(values)) + } + + for i, encoder := range encoders { + b, err := encoder.Encode(ctx, values[i]) + if err != nil { + var vStr []byte + if values[i] == nil { + vStr = []byte("") + } else { + var marshalErr error + vStr, marshalErr = values[i].MarshalText() + if marshalErr != nil { + vStr = []byte(fmt.Sprintf("%v(failed to marshal: %s)", values[i], marshalErr)) + } + } + merr = errors.Join(merr, fmt.Errorf("failed to encode stream value %s at index %d with abi %q; %w", string(vStr), i, encoder.Type, err)) + continue + } + payload = append(payload, b...) + } + + return payload, merr +} + +// An ABIEncoder encodes exactly one stream value into a byte slice +type ABIEncoder struct { + // StreamID is the ID of the stream that this encoder is responsible for. + // MANDATORY + StreamID llotypes.StreamID `json:"streamID"` + // Type is the ABI type of the stream value. E.g. "uint192", "int256", "bool", "string" etc. + // MANDATORY + Type string `json:"type"` + // Multiplier, if provided, will be multiplied with the stream value before + // encoding. + // OPTIONAL + Multiplier *ubig.Big `json:"multiplier"` +} + +// getNormalizedMultiplier returns the multiplier as a decimal.Decimal, defaulting +// to 1 if the multiplier is nil. +// +// Negative multipliers are ok and will work as expected, flipping the sign of +// the value. +func (a ABIEncoder) getNormalizedMultiplier() (multiplier decimal.Decimal) { + if a.Multiplier == nil { + multiplier = decimal.NewFromInt(1) + } else { + multiplier = decimal.NewFromBigInt(a.Multiplier.ToInt(), 0) + } + return +} + +func (a ABIEncoder) applyMultiplier(d decimal.Decimal) *big.Int { + return d.Mul(a.getNormalizedMultiplier()).BigInt() +} + +func (a ABIEncoder) Encode(ctx context.Context, sv llo.StreamValue) ([]byte, error) { + var encode interface{} + switch sv := sv.(type) { + case *llo.Decimal: + if sv == nil { + return nil, fmt.Errorf("expected non-nil *Decimal; got: %v", sv) + } + encode = a.applyMultiplier(sv.Decimal()) + default: + return nil, fmt.Errorf("unhandled type; supported types are: *llo.Decimal; got: %T", sv) + } + evmEncoderConfig := fmt.Sprintf(`[{"Name":"streamValue","Type":"%s"}]`, a.Type) + + codecConfig := types.CodecConfig{Configs: map[string]types.ChainCodecConfig{ + "evm": {TypeABI: evmEncoderConfig}, + }} + c, err := codec.NewCodec(codecConfig) + if err != nil { + return nil, fmt.Errorf("failed to create codec; %w", err) + } + + result, err := c.Encode(ctx, map[string]any{"streamValue": encode}, "evm") + if err != nil { + return nil, fmt.Errorf("failed to encode stream value %v with ABI type %q; %w", sv, a.Type, err) + } + return result, nil +} diff --git a/core/services/llo/evm/report_codec_evm_abi_encode_unpacked_test.go b/core/services/llo/evm/report_codec_evm_abi_encode_unpacked_test.go new file mode 100644 index 00000000000..b16d52bb3c4 --- /dev/null +++ b/core/services/llo/evm/report_codec_evm_abi_encode_unpacked_test.go @@ -0,0 +1,780 @@ +package evm + +import ( + "encoding/hex" + "fmt" + "math" + "math/big" + "math/rand/v2" + "reflect" + "strings" + "testing" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/gen" + "github.com/leanovate/gopter/prop" + "github.com/shopspring/decimal" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/libocr/offchainreporting2/types" + + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" + + llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink-data-streams/llo" +) + +// AllTrue returns false if any element in the array is false. +func AllTrue(arr []bool) bool { + for _, v := range arr { + if !v { + return false + } + } + return true +} + +func TestReportFormatEVMABIEncodeOpts_Decode_Encode_properties(t *testing.T) { + properties := gopter.NewProperties(nil) + + runTest := func(opts ReportFormatEVMABIEncodeOpts) bool { + encoded, err := opts.Encode() + require.NoError(t, err) + + decoded := ReportFormatEVMABIEncodeOpts{} + err = decoded.Decode(encoded) + require.NoError(t, err) + + return decoded.BaseUSDFee.Equal(opts.BaseUSDFee) && decoded.ExpirationWindow == opts.ExpirationWindow && decoded.FeedID == opts.FeedID && assert.Equal(t, opts.ABI, decoded.ABI) + } + properties.Property("Encodes values", prop.ForAll( + runTest, + gen.StrictStruct(reflect.TypeOf(&ReportFormatEVMABIEncodeOpts{}), map[string]gopter.Gen{ + "BaseUSDFee": genBaseUSDFee(), + "ExpirationWindow": genExpirationWindow(), + "FeedID": genFeedID(), + "ABI": genABI(), + }))) + + properties.TestingRun(t) +} + +func genABI() gopter.Gen { + return gen.SliceOf(genABIEncoder()) +} + +func genABIEncoder() gopter.Gen { + return gen.StrictStruct(reflect.TypeOf(&ABIEncoder{}), map[string]gopter.Gen{ + "StreamID": gen.UInt32().Map(func(i uint32) llotypes.StreamID { return i }), + "Multiplier": genMultiplier(), + "Type": gen.AnyString(), + }) +} + +func TestReportCodecEVMABIEncodeUnpacked_Encode_properties(t *testing.T) { + ctx := tests.Context(t) + codec := ReportCodecEVMABIEncodeUnpacked{} + + properties := gopter.NewProperties(nil) + + linkQuoteStreamID := rand.Uint32() + ethQuoteStreamID := rand.Uint32() + dexBasedAssetDecimalStreamID := rand.Uint32() + benchmarkPriceStreamID := rand.Uint32() + baseMarketDepthStreamID := rand.Uint32() + quoteMarketDepthStreamID := rand.Uint32() + marketStatusStreamID := rand.Uint32() + binanceFundingRateStreamID := rand.Uint32() + binanceFundingTimeStreamID := rand.Uint32() + binanceFundingIntervalHoursStreamID := rand.Uint32() + deribitFundingRateStreamID := rand.Uint32() + deribitFundingTimeStreamID := rand.Uint32() + deribitFundingIntervalHoursStreamID := rand.Uint32() + + t.Run("DEX-based asset schema example", func(t *testing.T) { + expectedDEXBasedAssetSchema := abi.Arguments([]abi.Argument{ + {Name: "feedId", Type: mustNewABIType("bytes32")}, + {Name: "validFromTimestamp", Type: mustNewABIType("uint32")}, + {Name: "observationsTimestamp", Type: mustNewABIType("uint32")}, + {Name: "nativeFee", Type: mustNewABIType("uint192")}, + {Name: "linkFee", Type: mustNewABIType("uint192")}, + {Name: "expiresAt", Type: mustNewABIType("uint32")}, + {Name: "price", Type: mustNewABIType("int192")}, + {Name: "baseMarketDepth", Type: mustNewABIType("int192")}, + {Name: "quoteMarketDepth", Type: mustNewABIType("int192")}, + }) + runTest := func(sampleFeedID common.Hash, sampleObservationsTimestamp, sampleValidAfterSeconds, sampleExpirationWindow uint32, priceMultiplier, marketDepthMultiplier *ubig.Big, sampleBaseUSDFee, sampleLinkBenchmarkPrice, sampleNativeBenchmarkPrice, sampleDexBasedAssetPrice, sampleBaseMarketDepth, sampleQuoteMarketDepth decimal.Decimal) bool { + report := llo.Report{ + ConfigDigest: types.ConfigDigest{0x01}, + SeqNr: 0x02, + ChannelID: llotypes.ChannelID(0x03), + ValidAfterSeconds: sampleValidAfterSeconds, + ObservationTimestampSeconds: sampleObservationsTimestamp, + Values: []llo.StreamValue{ + &llo.Quote{Bid: decimal.NewFromFloat(6.1), Benchmark: sampleLinkBenchmarkPrice, Ask: decimal.NewFromFloat(8.2332)}, // Link price + &llo.Quote{Bid: decimal.NewFromFloat(9.4), Benchmark: sampleNativeBenchmarkPrice, Ask: decimal.NewFromFloat(11.33)}, // Native price + llo.ToDecimal(sampleDexBasedAssetPrice), // DEX-based asset price + llo.ToDecimal(sampleBaseMarketDepth), // Base market depth + llo.ToDecimal(sampleQuoteMarketDepth), // Quote market depth + }, + Specimen: false, + } + + opts := ReportFormatEVMABIEncodeOpts{ + BaseUSDFee: sampleBaseUSDFee, + ExpirationWindow: sampleExpirationWindow, + FeedID: sampleFeedID, + ABI: []ABIEncoder{ + // benchmark price + ABIEncoder{ + StreamID: dexBasedAssetDecimalStreamID, + Type: "int192", + Multiplier: priceMultiplier, // TODO: Default multiplier? + }, + // base market depth + ABIEncoder{ + StreamID: baseMarketDepthStreamID, + Type: "int192", + Multiplier: marketDepthMultiplier, + }, + // quote market depth + ABIEncoder{ + StreamID: quoteMarketDepthStreamID, + Type: "int192", + Multiplier: marketDepthMultiplier, + }, + }, + } + serializedOpts, err := opts.Encode() + require.NoError(t, err) + + cd := llotypes.ChannelDefinition{ + ReportFormat: llotypes.ReportFormatEVMABIEncodeUnpacked, + Streams: []llotypes.Stream{ + { + StreamID: linkQuoteStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: ethQuoteStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: dexBasedAssetDecimalStreamID, + Aggregator: llotypes.AggregatorQuote, + }, + { + StreamID: baseMarketDepthStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: quoteMarketDepthStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + }, + Opts: serializedOpts, + } + + encoded, err := codec.Encode(ctx, report, cd) + require.NoError(t, err) + + values, err := expectedDEXBasedAssetSchema.Unpack(encoded) + require.NoError(t, err) + + require.Len(t, values, len(expectedDEXBasedAssetSchema)) + + expectedLinkFee := CalculateFee(sampleLinkBenchmarkPrice, sampleBaseUSDFee) + expectedNativeFee := CalculateFee(sampleNativeBenchmarkPrice, sampleBaseUSDFee) + + // doesn't crash if values are nil + for i := range report.Values { + report.Values[i] = nil + } + _, err = codec.Encode(ctx, report, cd) + require.Error(t, err) + + return AllTrue([]bool{ + assert.Equal(t, sampleFeedID, (common.Hash)(values[0].([32]byte))), //nolint:testifylint // false positive // feedId + assert.Equal(t, sampleValidAfterSeconds+1, values[1].(uint32)), // validFromTimestamp + assert.Equal(t, sampleObservationsTimestamp, values[2].(uint32)), // observationsTimestamp + assert.Equal(t, expectedLinkFee.String(), values[3].(*big.Int).String()), // linkFee + assert.Equal(t, expectedNativeFee.String(), values[4].(*big.Int).String()), // nativeFee + assert.Equal(t, sampleObservationsTimestamp+sampleExpirationWindow, values[5].(uint32)), // expiresAt + assert.Equal(t, sampleDexBasedAssetPrice.Mul(decimal.NewFromBigInt(priceMultiplier.ToInt(), 0)).BigInt(), values[6].(*big.Int)), // price + assert.Equal(t, sampleBaseMarketDepth.Mul(decimal.NewFromBigInt(marketDepthMultiplier.ToInt(), 0)).BigInt(), values[7].(*big.Int)), // baseMarketDepth + assert.Equal(t, sampleQuoteMarketDepth.Mul(decimal.NewFromBigInt(marketDepthMultiplier.ToInt(), 0)).BigInt(), values[8].(*big.Int)), // quoteMarketDepth + }) + } + + properties.Property("Encodes values", prop.ForAll( + runTest, + genFeedID(), + genObservationsTimestamp(), + genValidAfterSeconds(), + genExpirationWindow(), + genPriceMultiplier(), + genMarketDepthMultiplier(), + genBaseUSDFee(), + genLinkBenchmarkPrice(), + genNativeBenchmarkPrice(), + genBenchmarkPrice(), + genBaseMarketDepth(), + genQuoteMarketDepth(), + )) + + properties.TestingRun(t) + }) + + t.Run("Market status schema", func(t *testing.T) { + expectedRWASchema := abi.Arguments([]abi.Argument{ + {Name: "feedId", Type: mustNewABIType("bytes32")}, + {Name: "validFromTimestamp", Type: mustNewABIType("uint32")}, + {Name: "observationsTimestamp", Type: mustNewABIType("uint32")}, + {Name: "nativeFee", Type: mustNewABIType("uint192")}, + {Name: "linkFee", Type: mustNewABIType("uint192")}, + {Name: "expiresAt", Type: mustNewABIType("uint32")}, + {Name: "marketStatus", Type: mustNewABIType("uint32")}, + }) + + runTest := func(sampleFeedID common.Hash, sampleObservationsTimestamp, sampleValidAfterSeconds, sampleExpirationWindow uint32, sampleBaseUSDFee, sampleLinkBenchmarkPrice, sampleNativeBenchmarkPrice, sampleMarketStatus decimal.Decimal) bool { + report := llo.Report{ + ConfigDigest: types.ConfigDigest{0x01}, + SeqNr: 0x02, + ChannelID: llotypes.ChannelID(0x03), + ValidAfterSeconds: sampleValidAfterSeconds, + ObservationTimestampSeconds: sampleObservationsTimestamp, + Values: []llo.StreamValue{ + &llo.Quote{Bid: decimal.NewFromFloat(6.1), Benchmark: sampleLinkBenchmarkPrice, Ask: decimal.NewFromFloat(8.2332)}, // Link price + &llo.Quote{Bid: decimal.NewFromFloat(9.4), Benchmark: sampleNativeBenchmarkPrice, Ask: decimal.NewFromFloat(11.33)}, // Native price + llo.ToDecimal(sampleMarketStatus), // DEX-based asset price + }, + Specimen: false, + } + + opts := ReportFormatEVMABIEncodeOpts{ + BaseUSDFee: sampleBaseUSDFee, + ExpirationWindow: sampleExpirationWindow, + FeedID: sampleFeedID, + ABI: []ABIEncoder{ + // market status + ABIEncoder{ + StreamID: marketStatusStreamID, + Type: "uint32", + }, + }, + } + serializedOpts, err := opts.Encode() + require.NoError(t, err) + + cd := llotypes.ChannelDefinition{ + // ReportFormat: llotypes.ReportFormatEVMABIEncodeUnpacked, + ReportFormat: llotypes.ReportFormat(4), // FIXME: When chainlink-common is fixed + Streams: []llotypes.Stream{ + { + StreamID: linkQuoteStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: ethQuoteStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: dexBasedAssetDecimalStreamID, + Aggregator: llotypes.AggregatorQuote, + }, + { + StreamID: baseMarketDepthStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: quoteMarketDepthStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + }, + Opts: serializedOpts, + } + + encoded, err := codec.Encode(ctx, report, cd) + require.NoError(t, err) + + values, err := expectedRWASchema.Unpack(encoded) + require.NoError(t, err) + + require.Len(t, values, len(expectedRWASchema)) + + expectedLinkFee := CalculateFee(sampleLinkBenchmarkPrice, sampleBaseUSDFee) + expectedNativeFee := CalculateFee(sampleNativeBenchmarkPrice, sampleBaseUSDFee) + + // doesn't crash if values are nil + for i := range report.Values { + report.Values[i] = nil + } + _, err = codec.Encode(ctx, report, cd) + require.Error(t, err) + + return AllTrue([]bool{ + assert.Equal(t, sampleFeedID, (common.Hash)(values[0].([32]byte))), //nolint:testifylint // false positive // feedId + assert.Equal(t, sampleValidAfterSeconds+1, values[1].(uint32)), // validFromTimestamp + assert.Equal(t, sampleObservationsTimestamp, values[2].(uint32)), // observationsTimestamp + assert.Equal(t, expectedLinkFee.String(), values[3].(*big.Int).String()), // linkFee + assert.Equal(t, expectedNativeFee.String(), values[4].(*big.Int).String()), // nativeFee + assert.Equal(t, sampleObservationsTimestamp+sampleExpirationWindow, values[5].(uint32)), // expiresAt + assert.Equal(t, uint32(sampleMarketStatus.BigInt().Int64()), values[6].(uint32)), //nolint:gosec // G115 // market status + }) + } + + properties.Property("Encodes values", prop.ForAll( + runTest, + genFeedID(), + genObservationsTimestamp(), + genValidAfterSeconds(), + genExpirationWindow(), + genBaseUSDFee(), + genLinkBenchmarkPrice(), + genNativeBenchmarkPrice(), + genMarketStatus(), + )) + + properties.TestingRun(t) + }) + + t.Run("benchmark price schema example", func(t *testing.T) { + expectedDEXBasedAssetSchema := abi.Arguments([]abi.Argument{ + {Name: "feedId", Type: mustNewABIType("bytes32")}, + {Name: "validFromTimestamp", Type: mustNewABIType("uint32")}, + {Name: "observationsTimestamp", Type: mustNewABIType("uint32")}, + {Name: "nativeFee", Type: mustNewABIType("uint192")}, + {Name: "linkFee", Type: mustNewABIType("uint192")}, + {Name: "expiresAt", Type: mustNewABIType("uint32")}, + {Name: "price", Type: mustNewABIType("int192")}, + }) + runTest := func(sampleFeedID common.Hash, sampleObservationsTimestamp, sampleValidAfterSeconds, sampleExpirationWindow uint32, priceMultiplier, marketDepthMultiplier *ubig.Big, sampleBaseUSDFee, sampleLinkBenchmarkPrice, sampleNativeBenchmarkPrice, sampleBenchmarkPrice decimal.Decimal) bool { + report := llo.Report{ + ConfigDigest: types.ConfigDigest{0x01}, + SeqNr: 0x02, + ChannelID: llotypes.ChannelID(0x03), + ValidAfterSeconds: sampleValidAfterSeconds, + ObservationTimestampSeconds: sampleObservationsTimestamp, + Values: []llo.StreamValue{ + &llo.Quote{Bid: decimal.NewFromFloat(6.1), Benchmark: sampleLinkBenchmarkPrice, Ask: decimal.NewFromFloat(8.2332)}, // Link price + &llo.Quote{Bid: decimal.NewFromFloat(9.4), Benchmark: sampleNativeBenchmarkPrice, Ask: decimal.NewFromFloat(11.33)}, // Native price + llo.ToDecimal(sampleBenchmarkPrice), // price + }, + Specimen: false, + } + + opts := ReportFormatEVMABIEncodeOpts{ + BaseUSDFee: sampleBaseUSDFee, + ExpirationWindow: sampleExpirationWindow, + FeedID: sampleFeedID, + ABI: []ABIEncoder{ + // benchmark price + ABIEncoder{ + StreamID: dexBasedAssetDecimalStreamID, + Type: "int192", + Multiplier: priceMultiplier, // TODO: Default multiplier? + }, + }, + } + serializedOpts, err := opts.Encode() + require.NoError(t, err) + + cd := llotypes.ChannelDefinition{ + ReportFormat: llotypes.ReportFormatEVMABIEncodeUnpacked, + Streams: []llotypes.Stream{ + { + StreamID: linkQuoteStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: ethQuoteStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: benchmarkPriceStreamID, + Aggregator: llotypes.AggregatorQuote, + }, + }, + Opts: serializedOpts, + } + + encoded, err := codec.Encode(ctx, report, cd) + require.NoError(t, err) + + values, err := expectedDEXBasedAssetSchema.Unpack(encoded) + require.NoError(t, err) + + require.Len(t, values, len(expectedDEXBasedAssetSchema)) + + expectedLinkFee := CalculateFee(sampleLinkBenchmarkPrice, sampleBaseUSDFee) + expectedNativeFee := CalculateFee(sampleNativeBenchmarkPrice, sampleBaseUSDFee) + + // doesn't crash if values are nil + for i := range report.Values { + report.Values[i] = nil + } + _, err = codec.Encode(ctx, report, cd) + require.Error(t, err) + + return AllTrue([]bool{ + assert.Equal(t, sampleFeedID, (common.Hash)(values[0].([32]byte))), //nolint:testifylint // false positive // feedId + assert.Equal(t, sampleValidAfterSeconds+1, values[1].(uint32)), // validFromTimestamp + assert.Equal(t, sampleObservationsTimestamp, values[2].(uint32)), // observationsTimestamp + assert.Equal(t, expectedLinkFee.String(), values[3].(*big.Int).String()), // linkFee + assert.Equal(t, expectedNativeFee.String(), values[4].(*big.Int).String()), // nativeFee + assert.Equal(t, sampleObservationsTimestamp+sampleExpirationWindow, values[5].(uint32)), // expiresAt + assert.Equal(t, sampleBenchmarkPrice.Mul(decimal.NewFromBigInt(priceMultiplier.ToInt(), 0)).BigInt(), values[6].(*big.Int)), // price + }) + } + + properties.Property("Encodes values", prop.ForAll( + runTest, + genFeedID(), + genObservationsTimestamp(), + genValidAfterSeconds(), + genExpirationWindow(), + genPriceMultiplier(), + genMarketDepthMultiplier(), + genBaseUSDFee(), + genLinkBenchmarkPrice(), + genNativeBenchmarkPrice(), + genBenchmarkPrice(), + )) + + properties.TestingRun(t) + }) + + t.Run("funding rate schema example", func(t *testing.T) { + expectedFundingRateSchema := abi.Arguments([]abi.Argument{ + {Name: "feedId", Type: mustNewABIType("bytes32")}, + {Name: "validFromTimestamp", Type: mustNewABIType("uint32")}, + {Name: "observationsTimestamp", Type: mustNewABIType("uint32")}, + {Name: "nativeFee", Type: mustNewABIType("uint192")}, + {Name: "linkFee", Type: mustNewABIType("uint192")}, + {Name: "expiresAt", Type: mustNewABIType("uint32")}, + {Name: "binanceFundingRate", Type: mustNewABIType("int192")}, + {Name: "binanceFundingTime", Type: mustNewABIType("uint32")}, + {Name: "binanceFundingIntervalHours", Type: mustNewABIType("uint32")}, + {Name: "deribitFundingRate", Type: mustNewABIType("int192")}, + {Name: "deribitFundingTime", Type: mustNewABIType("uint32")}, + {Name: "deribitFundingIntervalHours", Type: mustNewABIType("uint32")}, + }) + + runTest := func(sampleFeedID common.Hash, sampleObservationsTimestamp, sampleValidAfterSeconds, sampleExpirationWindow uint32, sampleBaseUSDFee, sampleLinkBenchmarkPrice, sampleNativeBenchmarkPrice, sampleBinanceFundingRate, sampleBinanceFundingTime, sampleBinanceFundingIntervalHours, sampleDeribitFundingRate, sampleDeribitFundingTime, sampleDeribitFundingIntervalHours decimal.Decimal) bool { + report := llo.Report{ + ConfigDigest: types.ConfigDigest{0x01}, + SeqNr: 0x02, + ChannelID: llotypes.ChannelID(0x03), + ValidAfterSeconds: sampleValidAfterSeconds, + ObservationTimestampSeconds: sampleObservationsTimestamp, + Values: []llo.StreamValue{ + &llo.Quote{Bid: decimal.NewFromFloat(6.1), Benchmark: sampleLinkBenchmarkPrice, Ask: decimal.NewFromFloat(8.2332)}, // Link price + &llo.Quote{Bid: decimal.NewFromFloat(9.4), Benchmark: sampleNativeBenchmarkPrice, Ask: decimal.NewFromFloat(11.33)}, // Native price + llo.ToDecimal(sampleBinanceFundingRate), // Binance funding rate + llo.ToDecimal(sampleBinanceFundingTime), // Binance funding time + llo.ToDecimal(sampleBinanceFundingIntervalHours), // Binance funding interval hours + llo.ToDecimal(sampleDeribitFundingRate), // Deribit funding rate + llo.ToDecimal(sampleDeribitFundingTime), // Deribit funding time + llo.ToDecimal(sampleDeribitFundingIntervalHours), // Deribit funding interval hours + }, + Specimen: false, + } + + opts := ReportFormatEVMABIEncodeOpts{ + BaseUSDFee: sampleBaseUSDFee, + ExpirationWindow: sampleExpirationWindow, + FeedID: sampleFeedID, + ABI: []ABIEncoder{ + ABIEncoder{StreamID: binanceFundingRateStreamID, Type: "int192"}, + ABIEncoder{StreamID: binanceFundingTimeStreamID, Type: "uint32"}, + ABIEncoder{StreamID: binanceFundingIntervalHoursStreamID, Type: "uint32"}, + ABIEncoder{StreamID: deribitFundingRateStreamID, Type: "int192"}, + ABIEncoder{StreamID: deribitFundingTimeStreamID, Type: "uint32"}, + ABIEncoder{StreamID: deribitFundingIntervalHoursStreamID, Type: "uint32"}, + }, + } + serializedOpts, err := opts.Encode() + require.NoError(t, err) + + cd := llotypes.ChannelDefinition{ + // ReportFormat: llotypes.ReportFormatEVMABIEncodeUnpacked, + ReportFormat: llotypes.ReportFormat(4), // FIXME: When chainlink-common is fixed + Streams: []llotypes.Stream{ + { + StreamID: linkQuoteStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: ethQuoteStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: dexBasedAssetDecimalStreamID, + Aggregator: llotypes.AggregatorQuote, + }, + { + StreamID: baseMarketDepthStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: quoteMarketDepthStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + }, + Opts: serializedOpts, + } + + encoded, err := codec.Encode(ctx, report, cd) + require.NoError(t, err) + + values, err := expectedFundingRateSchema.Unpack(encoded) + require.NoError(t, err) + + require.Len(t, values, len(expectedFundingRateSchema)) + + expectedLinkFee := CalculateFee(sampleLinkBenchmarkPrice, sampleBaseUSDFee) + expectedNativeFee := CalculateFee(sampleNativeBenchmarkPrice, sampleBaseUSDFee) + + // doesn't crash if values are nil + for i := range report.Values { + report.Values[i] = nil + } + _, err = codec.Encode(ctx, report, cd) + require.Error(t, err) + + return AllTrue([]bool{ + assert.Equal(t, sampleFeedID, (common.Hash)(values[0].([32]byte))), //nolint:testifylint // false positive // feedId + assert.Equal(t, sampleValidAfterSeconds+1, values[1].(uint32)), // validFromTimestamp + assert.Equal(t, sampleObservationsTimestamp, values[2].(uint32)), // observationsTimestamp + assert.Equal(t, expectedLinkFee.String(), values[3].(*big.Int).String()), // linkFee + assert.Equal(t, expectedNativeFee.String(), values[4].(*big.Int).String()), // nativeFee + assert.Equal(t, sampleObservationsTimestamp+sampleExpirationWindow, values[5].(uint32)), // expiresAt + assert.Equal(t, sampleBinanceFundingRate.BigInt().String(), values[6].(*big.Int).String()), // binanceFundingRate + assert.Equal(t, uint32(sampleBinanceFundingTime.BigInt().Int64()), values[7].(uint32)), //nolint:gosec // G115 // binanceFundingTime + assert.Equal(t, uint32(sampleBinanceFundingIntervalHours.BigInt().Int64()), values[8].(uint32)), //nolint:gosec // G115 // binanceFundingIntervalHours + assert.Equal(t, sampleDeribitFundingRate.BigInt().String(), values[9].(*big.Int).String()), // deribitFundingRate + assert.Equal(t, uint32(sampleDeribitFundingTime.BigInt().Int64()), values[10].(uint32)), //nolint:gosec // G115 // deribitFundingTime + assert.Equal(t, uint32(sampleDeribitFundingIntervalHours.BigInt().Int64()), values[11].(uint32)), //nolint:gosec // G115 // deribitFundingIntervalHours + }) + } + + properties.Property("Encodes values", prop.ForAll( + runTest, + genFeedID(), + genObservationsTimestamp(), + genValidAfterSeconds(), + genExpirationWindow(), + genBaseUSDFee(), + genLinkBenchmarkPrice(), + genNativeBenchmarkPrice(), + genFundingRate(), + genFundingTime(), + genFundingIntervalHours(), + genFundingRate(), + genFundingTime(), + genFundingIntervalHours(), + )) + + properties.TestingRun(t) + }) +} + +func TestReportCodecEVMABIEncodeUnpacked_Encode(t *testing.T) { + t.Run("ABI and values length mismatch error", func(t *testing.T) { + // TODO + }) +} + +func genFeedID() gopter.Gen { + return func(p *gopter.GenParameters) *gopter.GenResult { + var feedID common.Hash + p.Rng.Read(feedID[:]) + return gopter.NewGenResult(feedID, gopter.NoShrinker) + } +} + +func genObservationsTimestamp() gopter.Gen { + return gen.UInt32() +} + +func genValidAfterSeconds() gopter.Gen { + return gen.UInt32() +} + +func genExpirationWindow() gopter.Gen { + return gen.UInt32() +} + +func genPriceMultiplier() gopter.Gen { + return genMultiplier() +} + +func genMarketDepthMultiplier() gopter.Gen { + return genMultiplier() +} + +func genMultiplier() gopter.Gen { + return gen.UInt32().Map(func(i uint32) *ubig.Big { + return ubig.NewI(int64(i)) + }) +} + +func genDecimal() gopter.Gen { + return gen.Float32Range(-2e32, 2e32).Map(decimal.NewFromFloat32) +} + +func genBaseUSDFee() gopter.Gen { + return genDecimal() +} + +func genLinkBenchmarkPrice() gopter.Gen { + return genDecimal() +} + +func genNativeBenchmarkPrice() gopter.Gen { + return genDecimal() +} + +func genBenchmarkPrice() gopter.Gen { + return genDecimal() +} + +func genBaseMarketDepth() gopter.Gen { + return genDecimal() +} + +func genQuoteMarketDepth() gopter.Gen { + return genDecimal() +} + +func genMarketStatus() gopter.Gen { + return gen.UInt32().Map(func(i uint32) decimal.Decimal { + return decimal.NewFromInt(int64(i)) + }) +} + +func genFundingRate() gopter.Gen { + return genDecimal() +} + +func genFundingTime() gopter.Gen { + // Unix epochs + return gen.UInt32Range(1500000000, 2000000000).Map(func(i uint32) decimal.Decimal { + return decimal.NewFromInt(int64(i)) + }) +} + +func genFundingIntervalHours() gopter.Gen { + return gen.UInt32().Map(func(i uint32) decimal.Decimal { + return decimal.NewFromInt(int64(i)) + }) +} + +func mustNewABIType(t string) abi.Type { + result, err := abi.NewType(t, "", []abi.ArgumentMarshaling{}) + if err != nil { + panic(fmt.Sprintf("Unexpected error during abi.NewType: %s", err)) + } + return result +} + +func Test_ABIEncoder_Encode(t *testing.T) { + t.Run("encodes decimals", func(t *testing.T) { + tcs := []struct { + name string + sv llo.StreamValue + abiType string + multiplier *big.Int + errStr string + expected string + }{ + { + name: "overflow int8", + sv: llo.ToDecimal(decimal.NewFromFloat32(123456789.123456789)), + abiType: "int8", + errStr: "invalid type: cannot fit 123456790 into int8", + }, + { + name: "successful int8", + sv: llo.ToDecimal(decimal.NewFromFloat32(123.456)), + abiType: "int8", + expected: padLeft32Byte(fmt.Sprintf("%x", 123)), + }, + { + name: "negative multiplied int8", + sv: llo.ToDecimal(decimal.NewFromFloat32(1.11)), + multiplier: big.NewInt(-100), + abiType: "int8", + expected: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff91", + }, + { + name: "negative uint32", + sv: llo.ToDecimal(decimal.NewFromFloat32(-123.456)), + abiType: "uint32", + errStr: "invalid type: cannot fit -123 into uint32", + }, + { + name: "successful uint32", + sv: llo.ToDecimal(decimal.NewFromFloat32(123456.456)), + abiType: "uint32", + expected: padLeft32Byte(fmt.Sprintf("%x", 123456)), + }, + { + name: "multiplied uint32", + sv: llo.ToDecimal(decimal.NewFromFloat32(123.456)), + multiplier: big.NewInt(100), + abiType: "uint32", + expected: padLeft32Byte(fmt.Sprintf("%x", 12345)), + }, + { + name: "negative multiplied int32", + sv: llo.ToDecimal(decimal.NewFromFloat32(123.456)), + multiplier: big.NewInt(-100), + abiType: "int32", + expected: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcfc7", + }, + { + name: "overflowing multiplied int32", + sv: llo.ToDecimal(decimal.NewFromInt(math.MaxInt32)), + multiplier: big.NewInt(2), + abiType: "int32", + errStr: "invalid type: cannot fit 4294967294 into int32", + }, + { + name: "successful int192", + sv: llo.ToDecimal(decimal.NewFromFloat32(123456.789123)), + abiType: "int192", + multiplier: big.NewInt(1e18), + expected: "000000000000000000000000000000000000000000001a249b2292e49d8f0000", + }, + } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + enc := ABIEncoder{ + Type: tc.abiType, + Multiplier: (*ubig.Big)(tc.multiplier), + } + encoded, err := enc.Encode(tests.Context(t), tc.sv) + if tc.errStr != "" { + require.Error(t, err) + assert.Contains(t, err.Error(), tc.errStr) + } else { + require.NoError(t, err) + require.Equal(t, tc.expected, hex.EncodeToString(encoded)) + } + }) + } + }) +} + +func padLeft32Byte(str string) string { + if len(str) >= 64 { + return str + } + padding := strings.Repeat("0", 64-len(str)) + return padding + str +} diff --git a/core/services/llo/grpc/client.go b/core/services/llo/grpc/client.go new file mode 100644 index 00000000000..321c252978c --- /dev/null +++ b/core/services/llo/grpc/client.go @@ -0,0 +1,118 @@ +package grpc + +import ( + "context" + "crypto/ed25519" + "errors" + "fmt" + "time" + + "google.golang.org/grpc" + "google.golang.org/grpc/backoff" + "google.golang.org/grpc/keepalive" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-data-streams/rpc" + "github.com/smartcontractkit/chainlink-data-streams/rpc/mtls" +) + +type Client interface { + services.Service + Transmit(ctx context.Context, in *rpc.TransmitRequest) (*rpc.TransmitResponse, error) + ServerURL() string +} + +var _ Client = (*client)(nil) + +type client struct { + services.Service + eng *services.Engine + + clientPrivKey ed25519.PrivateKey + serverPubKey ed25519.PublicKey + serverURL string + + conn *grpc.ClientConn + client rpc.TransmitterClient +} + +type ClientOpts struct { + Logger logger.Logger + ClientPrivKey ed25519.PrivateKey + ServerPubKey ed25519.PublicKey + ServerURL string +} + +func NewClient(opts ClientOpts) Client { + return newClient(opts) +} + +func newClient(opts ClientOpts) Client { + c := &client{ + clientPrivKey: opts.ClientPrivKey, + serverPubKey: opts.ServerPubKey, + serverURL: opts.ServerURL, + } + c.Service, c.eng = services.Config{ + Name: "GRPCClient", + Start: c.start, + Close: c.close, + }.NewServiceEngine(opts.Logger) + return c +} + +func (c *client) start(context.Context) error { + cMtls, err := mtls.NewTransportCredentials(c.clientPrivKey, []ed25519.PublicKey{c.serverPubKey}) + if err != nil { + return fmt.Errorf("failed to create client mTLS credentials: %w", err) + } + // Latency is critical so configure aggressively for fast + // redial attempts and short keepalive + clientConn, err := grpc.NewClient( + c.serverURL, + grpc.WithTransportCredentials(cMtls), + grpc.WithConnectParams( + grpc.ConnectParams{ + Backoff: backoff.Config{ + BaseDelay: 1 * time.Second, + Multiplier: 2, + Jitter: 0.2, + MaxDelay: 30 * time.Second, + }, + MinConnectTimeout: time.Second, + }, + ), + grpc.WithKeepaliveParams( + keepalive.ClientParameters{ + Time: time.Second * 10, + Timeout: time.Second * 20, + PermitWithoutStream: true, + }), + grpc.WithDefaultCallOptions( + grpc.WaitForReady(true), + ), + ) + if err != nil { + return fmt.Errorf("failed to create client connection: %w", err) + } + c.conn = clientConn + c.client = rpc.NewTransmitterClient(c.conn) + return nil +} + +func (c *client) close() error { + return c.conn.Close() +} + +func (c *client) Transmit(ctx context.Context, req *rpc.TransmitRequest) (resp *rpc.TransmitResponse, err error) { + return c.client.Transmit(ctx, req) +} + +func (c *client) LatestReport(ctx context.Context, req *rpc.LatestReportRequest) (resp *rpc.LatestReportResponse, err error) { + return nil, errors.New("LatestReport is not supported in grpc mode") +} + +func (c *client) ServerURL() string { + return c.serverURL +} diff --git a/core/services/llo/keyring.go b/core/services/llo/keyring.go index d4bf615711c..443aa1968ba 100644 --- a/core/services/llo/keyring.go +++ b/core/services/llo/keyring.go @@ -80,7 +80,7 @@ func (okr *onchainKeyring) MaxSignatureLength() (n int) { func (okr *onchainKeyring) Sign(digest types.ConfigDigest, seqNr uint64, r ocr3types.ReportWithInfo[llotypes.ReportInfo]) (signature []byte, err error) { switch r.Info.ReportFormat { - case llotypes.ReportFormatEVMPremiumLegacy: + case llotypes.ReportFormatEVMPremiumLegacy, llotypes.ReportFormatEVMABIEncodeUnpacked: rf := r.Info.ReportFormat if key, exists := okr.keys[rf]; exists { // NOTE: Must use legacy Sign method for compatibility with v0.3 report verification @@ -101,7 +101,7 @@ func (okr *onchainKeyring) Sign(digest types.ConfigDigest, seqNr uint64, r ocr3t func (okr *onchainKeyring) Verify(key types.OnchainPublicKey, digest types.ConfigDigest, seqNr uint64, r ocr3types.ReportWithInfo[llotypes.ReportInfo], signature []byte) bool { switch r.Info.ReportFormat { - case llotypes.ReportFormatEVMPremiumLegacy: + case llotypes.ReportFormatEVMPremiumLegacy, llotypes.ReportFormatEVMABIEncodeUnpacked: rf := r.Info.ReportFormat if verifier, exists := okr.keys[rf]; exists { // NOTE: Must use legacy Verify method for compatibility with v0.3 report verification diff --git a/core/services/llo/mercurytransmitter/orm.go b/core/services/llo/mercurytransmitter/orm.go index 045161395b5..f557e2293a5 100644 --- a/core/services/llo/mercurytransmitter/orm.go +++ b/core/services/llo/mercurytransmitter/orm.go @@ -72,7 +72,7 @@ func (o *orm) Insert(ctx context.Context, transmissions []*Transmission) error { DonID: o.donID, ServerURL: t.ServerURL, ConfigDigest: t.ConfigDigest, - SeqNr: int64(t.SeqNr), //nolint:gosec // G115 false positive + SeqNr: int64(t.SeqNr), Report: t.Report.Report, LifecycleStage: string(t.Report.Info.LifeCycleStage), ReportFormat: uint32(t.Report.Info.ReportFormat), diff --git a/core/services/llo/mercurytransmitter/server.go b/core/services/llo/mercurytransmitter/server.go index 3ce2b0a4b4a..e87923eab6f 100644 --- a/core/services/llo/mercurytransmitter/server.go +++ b/core/services/llo/mercurytransmitter/server.go @@ -21,11 +21,11 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services" llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" "github.com/smartcontractkit/chainlink-data-streams/llo" + "github.com/smartcontractkit/chainlink-data-streams/rpc" corelogger "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/llo/evm" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/pb" + "github.com/smartcontractkit/chainlink/v2/core/services/llo/grpc" "github.com/smartcontractkit/chainlink/v2/core/utils" ) @@ -92,7 +92,7 @@ type server struct { transmitTimeout time.Duration - c wsrpc.Client + c grpc.Client pm *persistenceManager q TransmitQueue @@ -121,7 +121,7 @@ type QueueConfig interface { TransmitTimeout() commonconfig.Duration } -func newServer(lggr logger.Logger, verboseLogging bool, cfg QueueConfig, client wsrpc.Client, orm ORM, serverURL string) *server { +func newServer(lggr logger.Logger, verboseLogging bool, cfg QueueConfig, client grpc.Client, orm ORM, serverURL string) *server { pm := NewPersistenceManager(lggr, orm, serverURL, int(cfg.TransmitQueueMaxSize()), flushDeletesFrequency, pruneFrequency) donIDStr := fmt.Sprintf("%d", pm.DonID()) var codecLggr logger.Logger @@ -248,17 +248,23 @@ func (s *server) runQueueLoop(stopCh services.StopChan, wg *sync.WaitGroup, donI s.transmitThreadBusyCountInc() defer s.transmitThreadBusyCountDec() - req, res, err := func(ctx context.Context) (*pb.TransmitRequest, *pb.TransmitResponse, error) { + req, res, err := func(ctx context.Context) (*rpc.TransmitRequest, *rpc.TransmitResponse, error) { ctx, cancelFn := context.WithTimeout(ctx, utils.WithJitter(s.transmitTimeout)) defer cancelFn() return s.transmit(ctx, t) }(ctx) + + lggr := s.lggr.With("transmission", t, "response", res, "transmissionHash", fmt.Sprintf("%x", t.Hash())) + if req != nil { + lggr = s.lggr.With("req.Payload", req.Payload, "req.ReportFormat", req.ReportFormat) + } + if ctx.Err() != nil { // only canceled on transmitter close so we can exit return false } else if err != nil { s.transmitConnectionErrorCount.Inc() - s.lggr.Errorw("Transmit report failed", "err", err, "req.Payload", req.Payload, "req.ReportFormat", req.ReportFormat, "transmission", t) + lggr.Errorw("Transmit report failed", "err", err) if ok := s.q.Push(t); !ok { s.lggr.Error("Failed to push report to transmit queue; queue is closed") return false @@ -276,7 +282,7 @@ func (s *server) runQueueLoop(stopCh services.StopChan, wg *sync.WaitGroup, donI b.Reset() if res.Error == "" { s.transmitSuccessCount.Inc() - s.lggr.Debugw("Transmit report success", "req.ReportFormat", req.ReportFormat, "req.Payload", req.Payload, "transmission", t, "response", res) + lggr.Debug("Transmit report success") } else { // We don't need to retry here because the mercury server // has confirmed it received the report. We only need to retry @@ -285,31 +291,31 @@ func (s *server) runQueueLoop(stopCh services.StopChan, wg *sync.WaitGroup, donI case DuplicateReport: s.transmitSuccessCount.Inc() s.transmitDuplicateCount.Inc() - s.lggr.Debugw("Transmit report success; duplicate report", "req.ReportFormat", req.ReportFormat, "req.Payload", req.Payload, "transmission", t, "response", res) + lggr.Debug("Transmit report success; duplicate report") default: promTransmitServerErrorCount.WithLabelValues(donIDStr, s.url, strconv.FormatInt(int64(res.Code), 10)).Inc() - s.lggr.Errorw("Transmit report failed; mercury server returned error", "req.ReportFormat", req.ReportFormat, "req.Payload", req.Payload, "response", res, "transmission", t, "err", res.Error, "code", res.Code) + lggr.Errorw("Transmit report failed; mercury server returned error", "err", res.Error, "code", res.Code) } } select { case s.deleteQueue <- t.Hash(): default: - s.lggr.Criticalw("Delete queue is full", "transmission", t, "transmissionHash", fmt.Sprintf("%x", t.Hash())) + lggr.Criticalw("Delete queue is full") } return true }() } } -func (s *server) transmit(ctx context.Context, t *Transmission) (*pb.TransmitRequest, *pb.TransmitResponse, error) { +func (s *server) transmit(ctx context.Context, t *Transmission) (*rpc.TransmitRequest, *rpc.TransmitResponse, error) { var payload []byte var err error switch t.Report.Info.ReportFormat { case llotypes.ReportFormatJSON: payload, err = s.jsonPacker.Pack(t.ConfigDigest, t.SeqNr, t.Report.Report, t.Sigs) - case llotypes.ReportFormatEVMPremiumLegacy: + case llotypes.ReportFormatEVMPremiumLegacy, llotypes.ReportFormatEVMABIEncodeUnpacked: payload, err = s.evmPremiumLegacyPacker.Pack(t.ConfigDigest, t.SeqNr, t.Report.Report, t.Sigs) default: return nil, nil, fmt.Errorf("Transmit failed; don't know how to Pack unsupported report format: %q", t.Report.Info.ReportFormat) @@ -319,7 +325,7 @@ func (s *server) transmit(ctx context.Context, t *Transmission) (*pb.TransmitReq return nil, nil, fmt.Errorf("Transmit: encode failed; %w", err) } - req := &pb.TransmitRequest{ + req := &rpc.TransmitRequest{ Payload: payload, ReportFormat: uint32(t.Report.Info.ReportFormat), } diff --git a/core/services/llo/mercurytransmitter/transmitter.go b/core/services/llo/mercurytransmitter/transmitter.go index 23aa4b79e58..e9091fbe4cb 100644 --- a/core/services/llo/mercurytransmitter/transmitter.go +++ b/core/services/llo/mercurytransmitter/transmitter.go @@ -19,12 +19,12 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/types" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink/v2/core/services/llo/grpc" + commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" - - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc" ) const ( @@ -102,6 +102,7 @@ type Transmitter interface { var _ Transmitter = (*transmitter)(nil) type Config interface { + Protocol() string TransmitQueueMaxSize() uint32 TransmitTimeout() commonconfig.Duration TransmitConcurrency() uint32 @@ -129,7 +130,7 @@ type Opts struct { Registerer prometheus.Registerer VerboseLogging bool Cfg Config - Clients map[string]wsrpc.Client + Clients map[string]grpc.Client FromAccount ed25519.PublicKey DonID uint32 ORM ORM diff --git a/core/services/llo/mercurytransmitter/transmitter_test.go b/core/services/llo/mercurytransmitter/transmitter_test.go index fabc9bb0d0e..000933fe61d 100644 --- a/core/services/llo/mercurytransmitter/transmitter_test.go +++ b/core/services/llo/mercurytransmitter/transmitter_test.go @@ -14,17 +14,21 @@ import ( "github.com/smartcontractkit/libocr/commontypes" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink-data-streams/rpc" + commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/mocks" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/pb" + "github.com/smartcontractkit/chainlink/v2/core/services/llo/grpc" ) type mockCfg struct{} +func (m mockCfg) Protocol() string { + return "" +} + func (m mockCfg) TransmitQueueMaxSize() uint32 { return 10_000 } @@ -37,16 +41,30 @@ func (m mockCfg) TransmitConcurrency() uint32 { return 5 } +type MockGRPCClient struct { + TransmitF func(ctx context.Context, in *rpc.TransmitRequest) (*rpc.TransmitResponse, error) +} + +func (m *MockGRPCClient) Name() string { return "" } +func (m *MockGRPCClient) Start(context.Context) error { return nil } +func (m *MockGRPCClient) Close() error { return nil } +func (m *MockGRPCClient) HealthReport() map[string]error { return map[string]error{} } +func (m *MockGRPCClient) Ready() error { return nil } +func (m *MockGRPCClient) Transmit(ctx context.Context, in *rpc.TransmitRequest) (*rpc.TransmitResponse, error) { + return m.TransmitF(ctx, in) +} +func (m *MockGRPCClient) ServerURL() string { return "mock server url" } + func Test_Transmitter_Transmit(t *testing.T) { lggr := logger.TestLogger(t) db := pgtest.NewSqlxDB(t) donID := uint32(123456) orm := NewORM(db, donID) - clients := map[string]wsrpc.Client{} + clients := map[string]grpc.Client{} t.Run("with multiple mercury servers", func(t *testing.T) { t.Run("transmission successfully enqueued", func(t *testing.T) { - c := &mocks.MockWSRPCClient{} + c := &MockGRPCClient{} clients[sURL] = c clients[sURL2] = c clients[sURL3] = c @@ -133,7 +151,7 @@ func (m *mockQ) IsEmpty() bool { return false } func Test_Transmitter_runQueueLoop(t *testing.T) { donIDStr := "555" lggr := logger.TestLogger(t) - c := &mocks.MockWSRPCClient{} + c := &MockGRPCClient{} db := pgtest.NewSqlxDB(t) donID := uint32(123456) orm := NewORM(db, donID) @@ -142,10 +160,10 @@ func Test_Transmitter_runQueueLoop(t *testing.T) { s := newServer(lggr, true, cfg, c, orm, sURL) t.Run("pulls from queue and transmits successfully", func(t *testing.T) { - transmit := make(chan *pb.TransmitRequest, 1) - c.TransmitF = func(ctx context.Context, in *pb.TransmitRequest) (*pb.TransmitResponse, error) { + transmit := make(chan *rpc.TransmitRequest, 1) + c.TransmitF = func(ctx context.Context, in *rpc.TransmitRequest) (*rpc.TransmitResponse, error) { transmit <- in - return &pb.TransmitResponse{Code: 0, Error: ""}, nil + return &rpc.TransmitResponse{Code: 0, Error: ""}, nil } q := newMockQ() s.q = q @@ -170,10 +188,10 @@ func Test_Transmitter_runQueueLoop(t *testing.T) { }) t.Run("on duplicate, success", func(t *testing.T) { - transmit := make(chan *pb.TransmitRequest, 1) - c.TransmitF = func(ctx context.Context, in *pb.TransmitRequest) (*pb.TransmitResponse, error) { + transmit := make(chan *rpc.TransmitRequest, 1) + c.TransmitF = func(ctx context.Context, in *rpc.TransmitRequest) (*rpc.TransmitResponse, error) { transmit <- in - return &pb.TransmitResponse{Code: DuplicateReport, Error: ""}, nil + return &rpc.TransmitResponse{Code: DuplicateReport, Error: ""}, nil } q := newMockQ() s.q = q @@ -197,10 +215,10 @@ func Test_Transmitter_runQueueLoop(t *testing.T) { wg.Wait() }) t.Run("on server-side error, does not retry", func(t *testing.T) { - transmit := make(chan *pb.TransmitRequest, 1) - c.TransmitF = func(ctx context.Context, in *pb.TransmitRequest) (*pb.TransmitResponse, error) { + transmit := make(chan *rpc.TransmitRequest, 1) + c.TransmitF = func(ctx context.Context, in *rpc.TransmitRequest) (*rpc.TransmitResponse, error) { transmit <- in - return &pb.TransmitResponse{Code: DuplicateReport, Error: ""}, nil + return &rpc.TransmitResponse{Code: DuplicateReport, Error: ""}, nil } q := newMockQ() s.q = q @@ -224,10 +242,10 @@ func Test_Transmitter_runQueueLoop(t *testing.T) { wg.Wait() }) t.Run("on transmit error, retries", func(t *testing.T) { - transmit := make(chan *pb.TransmitRequest, 1) - c.TransmitF = func(ctx context.Context, in *pb.TransmitRequest) (*pb.TransmitResponse, error) { + transmit := make(chan *rpc.TransmitRequest, 1) + c.TransmitF = func(ctx context.Context, in *rpc.TransmitRequest) (*rpc.TransmitResponse, error) { transmit <- in - return &pb.TransmitResponse{}, errors.New("transmission error") + return &rpc.TransmitResponse{}, errors.New("transmission error") } q := newMockQ() s.q = q diff --git a/core/services/llo/observation_context.go b/core/services/llo/observation_context.go new file mode 100644 index 00000000000..5bf82fa5a79 --- /dev/null +++ b/core/services/llo/observation_context.go @@ -0,0 +1,193 @@ +package llo + +import ( + "context" + "fmt" + "sync" + + "github.com/shopspring/decimal" + + "github.com/smartcontractkit/chainlink-data-streams/llo" + "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" + "github.com/smartcontractkit/chainlink/v2/core/services/streams" + "github.com/smartcontractkit/chainlink/v2/core/utils" +) + +// ObservationContext ensures that each pipeline is only executed once. It is +// intended to be instantiated and used then discarded as part of one +// Observation cycle. Subsequent calls to Observe will return the same cached +// values. + +var _ ObservationContext = (*observationContext)(nil) + +type ObservationContext interface { + Observe(ctx context.Context, streamID streams.StreamID, opts llo.DSOpts) (val llo.StreamValue, err error) +} + +type execution struct { + done <-chan struct{} + + run *pipeline.Run + trrs pipeline.TaskRunResults + err error +} + +type observationContext struct { + r Registry + t Telemeter + + executionsMu sync.Mutex + // only execute each pipeline once + executions map[streams.Pipeline]*execution +} + +func NewObservationContext(r Registry, t Telemeter) ObservationContext { + return newObservationContext(r, t) +} + +func newObservationContext(r Registry, t Telemeter) *observationContext { + return &observationContext{r, t, sync.Mutex{}, make(map[streams.Pipeline]*execution)} +} + +func (oc *observationContext) Observe(ctx context.Context, streamID streams.StreamID, opts llo.DSOpts) (val llo.StreamValue, err error) { + run, trrs, err := oc.run(ctx, streamID) + if err != nil { + // FIXME: This is a hack specific for V3 telemetry, future schemas should + // use a generic stream value telemetry instead + // https://smartcontract-it.atlassian.net/browse/MERC-6290 + oc.t.EnqueueV3PremiumLegacy(run, trrs, streamID, opts, val, err) + return nil, err + } + // Extract stream value based on streamID attribute + for _, trr := range trrs { + if trr.Task.TaskStreamID() != nil && *trr.Task.TaskStreamID() == streamID { + val, err = resultToStreamValue(trr.Result.Value) + if err != nil { + return nil, fmt.Errorf("failed to convert result to StreamValue for streamID %d: %w", streamID, err) + } + return val, nil + } + } + // If no streamID attribute is found in the task results, then assume the + // final output is the stream ID and return that. This is safe to do since + // the registry will never return a spec that doesn't match either by tag + // or by spec streamID. + + val, err = extractFinalResultAsStreamValue(trrs) + // FIXME: This is a hack specific for V3 telemetry, future schemas should + // use a generic stream value telemetry instead + // https://smartcontract-it.atlassian.net/browse/MERC-6290 + oc.t.EnqueueV3PremiumLegacy(run, trrs, streamID, opts, val, err) + return +} + +func resultToStreamValue(val interface{}) (llo.StreamValue, error) { + switch v := val.(type) { + case decimal.Decimal: + return llo.ToDecimal(v), nil + case float64: + return llo.ToDecimal(decimal.NewFromFloat(v)), nil + case pipeline.ObjectParam: + switch v.Type { + case pipeline.DecimalType: + return llo.ToDecimal(decimal.Decimal(v.DecimalValue)), nil + default: + return nil, fmt.Errorf("don't know how to convert pipeline.ObjectParam with type %d to llo.StreamValue", v.Type) + } + default: + return nil, fmt.Errorf("don't know how to convert pipeline output result of type %T to llo.StreamValue (got: %v)", val, val) + } +} + +// extractFinalResultAsStreamValue extracts a final StreamValue from a TaskRunResults +func extractFinalResultAsStreamValue(trrs pipeline.TaskRunResults) (llo.StreamValue, error) { + // pipeline.TaskRunResults comes ordered asc by index, this is guaranteed + // by the pipeline executor + finaltrrs := trrs.Terminals() + + // HACK: Right now we rely on the number of outputs to determine whether + // its a Decimal or a Quote. + // This is a hack to support the legacy "Quote" case. + // Future stream specs should use streamID tags instead. + switch len(finaltrrs) { + case 1: + res := finaltrrs[0].Result + if res.Error != nil { + return nil, res.Error + } + val, err := toDecimal(res.Value) + if err != nil { + return nil, fmt.Errorf("failed to parse BenchmarkPrice: %w", err) + } + return llo.ToDecimal(val), nil + case 3: + // Expect ordering of Benchmark, Bid, Ask + results := make([]decimal.Decimal, 3) + for i, trr := range finaltrrs { + res := trr.Result + if res.Error != nil { + return nil, fmt.Errorf("failed to parse stream output into Quote (task index: %d): %w", i, res.Error) + } + val, err := toDecimal(res.Value) + if err != nil { + return nil, fmt.Errorf("failed to parse decimal: %w", err) + } + results[i] = val + } + return &llo.Quote{ + Benchmark: results[0], + Bid: results[1], + Ask: results[2], + }, nil + default: + return nil, fmt.Errorf("invalid number of results, expected: 1 or 3, got: %d", len(finaltrrs)) + } +} + +func toDecimal(val interface{}) (decimal.Decimal, error) { + return utils.ToDecimal(val) +} + +type MissingStreamError struct { + StreamID streams.StreamID +} + +func (e MissingStreamError) Error() string { + return fmt.Sprintf("no pipeline for stream: %d", e.StreamID) +} + +func (oc *observationContext) run(ctx context.Context, streamID streams.StreamID) (*pipeline.Run, pipeline.TaskRunResults, error) { + p, exists := oc.r.Get(streamID) + if !exists { + return nil, nil, MissingStreamError{StreamID: streamID} + } + + // In case of multiple streamIDs per pipeline then the + // first call executes and the others wait for result + oc.executionsMu.Lock() + ex, isExecuting := oc.executions[p] + if isExecuting { + oc.executionsMu.Unlock() + // wait for it to finish + select { + case <-ex.done: + return ex.run, ex.trrs, ex.err + case <-ctx.Done(): + return nil, nil, ctx.Err() + } + } + + // execute here + ch := make(chan struct{}) + ex = &execution{done: ch} + oc.executions[p] = ex + oc.executionsMu.Unlock() + + run, trrs, err := p.Run(ctx) + ex.run = run + ex.trrs = trrs + ex.err = err + close(ch) + + return run, trrs, err +} diff --git a/core/services/llo/observation_context_test.go b/core/services/llo/observation_context_test.go new file mode 100644 index 00000000000..fe626815603 --- /dev/null +++ b/core/services/llo/observation_context_test.go @@ -0,0 +1,358 @@ +package llo + +import ( + "errors" + "fmt" + "io" + "math" + "math/rand/v2" + "net/http" + "net/http/httptest" + "net/url" + "testing" + "time" + + "github.com/shopspring/decimal" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/atomic" + "golang.org/x/sync/errgroup" + + "gopkg.in/guregu/null.v4" + + commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink-data-streams/llo" + "github.com/smartcontractkit/chainlink/v2/core/bridges" + clhttptest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/httptest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" + "github.com/smartcontractkit/chainlink/v2/core/logger" + clnull "github.com/smartcontractkit/chainlink/v2/core/null" + "github.com/smartcontractkit/chainlink/v2/core/services/job" + "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" + "github.com/smartcontractkit/chainlink/v2/core/services/streams" + "github.com/smartcontractkit/chainlink/v2/core/store/models" +) + +func makeErroringPipeline() *mockPipeline { + return &mockPipeline{ + err: errors.New("pipeline error"), + } +} + +func makePipelineWithMultipleStreamResults(streamIDs []streams.StreamID, results []interface{}) *mockPipeline { + if len(streamIDs) != len(results) { + panic("streamIDs and results must have the same length") + } + trrs := make([]pipeline.TaskRunResult, len(streamIDs)) + for i, res := range results { + trrs[i] = pipeline.TaskRunResult{Task: &pipeline.MemoTask{BaseTask: pipeline.BaseTask{StreamID: clnull.Uint32From(streamIDs[i])}}, Result: pipeline.Result{Value: res}} + } + return &mockPipeline{ + run: &pipeline.Run{}, + trrs: trrs, + err: nil, + streamIDs: streamIDs, + } +} + +func TestObservationContext_Observe(t *testing.T) { + ctx := tests.Context(t) + r := &mockRegistry{} + telem := &mockTelemeter{} + oc := newObservationContext(r, telem) + opts := llo.DSOpts(nil) + + missingStreamID := streams.StreamID(0) + streamID1 := streams.StreamID(1) + streamID2 := streams.StreamID(2) + streamID3 := streams.StreamID(3) + streamID4 := streams.StreamID(4) + streamID5 := streams.StreamID(5) + streamID6 := streams.StreamID(6) + + multiPipelineDecimal := makePipelineWithMultipleStreamResults([]streams.StreamID{streamID4, streamID5, streamID6}, []interface{}{decimal.NewFromFloat(12.34), decimal.NewFromFloat(56.78), decimal.NewFromFloat(90.12)}) + + r.pipelines = map[streams.StreamID]*mockPipeline{ + streamID1: &mockPipeline{}, + streamID2: makePipelineWithSingleResult[decimal.Decimal](rand.Int64(), decimal.NewFromFloat(12.34), nil), + streamID3: makeErroringPipeline(), + streamID4: multiPipelineDecimal, + streamID5: multiPipelineDecimal, + streamID6: multiPipelineDecimal, + } + + t.Run("returns error in case of missing pipeline", func(t *testing.T) { + _, err := oc.Observe(ctx, missingStreamID, opts) + require.EqualError(t, err, "no pipeline for stream: 0") + }) + t.Run("returns error in case of zero results", func(t *testing.T) { + _, err := oc.Observe(ctx, streamID1, opts) + require.EqualError(t, err, "invalid number of results, expected: 1 or 3, got: 0") + }) + t.Run("returns composite value from legacy job with single top-level streamID", func(t *testing.T) { + val, err := oc.Observe(ctx, streamID2, opts) + require.NoError(t, err) + + assert.Equal(t, "12.34", val.(*llo.Decimal).String()) + }) + t.Run("returns error in case of erroring pipeline", func(t *testing.T) { + _, err := oc.Observe(ctx, streamID3, opts) + require.EqualError(t, err, "pipeline error") + }) + t.Run("returns values for multiple stream IDs within the same job based on streamID tag with a single pipeline execution", func(t *testing.T) { + val, err := oc.Observe(ctx, streamID4, opts) + require.NoError(t, err) + assert.Equal(t, "12.34", val.(*llo.Decimal).String()) + + val, err = oc.Observe(ctx, streamID5, opts) + require.NoError(t, err) + assert.Equal(t, "56.78", val.(*llo.Decimal).String()) + + val, err = oc.Observe(ctx, streamID6, opts) + require.NoError(t, err) + assert.Equal(t, "90.12", val.(*llo.Decimal).String()) + + assert.Equal(t, 1, multiPipelineDecimal.runCount) + + // returns cached values on subsequent calls + val, err = oc.Observe(ctx, streamID6, opts) + require.NoError(t, err) + assert.Equal(t, "90.12", val.(*llo.Decimal).String()) + + assert.Equal(t, 1, multiPipelineDecimal.runCount) + }) +} + +func TestObservationContext_Observe_concurrencyStressTest(t *testing.T) { + ctx := tests.Context(t) + r := &mockRegistry{} + telem := &mockTelemeter{} + oc := newObservationContext(r, telem) + opts := llo.DSOpts(nil) + + streamID := streams.StreamID(1) + val := decimal.NewFromFloat(123.456) + + // observes the same pipeline 1000 times to try and detect races etc + r.pipelines = make(map[streams.StreamID]*mockPipeline) + r.pipelines[streamID] = makePipelineWithSingleResult[decimal.Decimal](0, val, nil) + g, ctx := errgroup.WithContext(ctx) + for i := 0; i < 1000; i++ { + g.Go(func() error { + _, err := oc.Observe(ctx, streamID, opts) + return err + }) + } + if err := g.Wait(); err != nil { + t.Fatalf("Observation failed: %v", err) + } +} + +type mockPipelineConfig struct{} + +func (m *mockPipelineConfig) DefaultHTTPLimit() int64 { return 10000 } +func (m *mockPipelineConfig) DefaultHTTPTimeout() commonconfig.Duration { + return *commonconfig.MustNewDuration(1 * time.Hour) +} +func (m *mockPipelineConfig) MaxRunDuration() time.Duration { return 1 * time.Hour } +func (m *mockPipelineConfig) ReaperInterval() time.Duration { return 0 } +func (m *mockPipelineConfig) ReaperThreshold() time.Duration { return 0 } + +// func (m *mockPipelineConfig) VerboseLogging() bool { return true } +func (m *mockPipelineConfig) VerboseLogging() bool { return false } + +type mockBridgeConfig struct{} + +func (m *mockBridgeConfig) BridgeResponseURL() *url.URL { + return nil +} +func (m *mockBridgeConfig) BridgeCacheTTL() time.Duration { + return 0 +} + +func createBridge(t testing.TB, name string, val string, borm bridges.ORM, maxCalls int64) { + callcount := atomic.NewInt64(0) + bridge := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + n := callcount.Inc() + if maxCalls > 0 && n > maxCalls { + panic("too many calls to bridge" + name) + } + _, herr := io.ReadAll(req.Body) + if herr != nil { + panic(herr) + } + + res.WriteHeader(http.StatusOK) + resp := fmt.Sprintf(`{"result": %s}`, val) + _, herr = res.Write([]byte(resp)) + if herr != nil { + panic(herr) + } + })) + t.Cleanup(bridge.Close) + u, _ := url.Parse(bridge.URL) + require.NoError(t, borm.CreateBridgeType(tests.Context(t), &bridges.BridgeType{ + Name: bridges.BridgeName(name), + URL: models.WebURL(*u), + })) +} + +func TestObservationContext_Observe_integrationRealPipeline(t *testing.T) { + ctx := tests.Context(t) + lggr := logger.TestLogger(t) + db := pgtest.NewSqlxDB(t) + bridgesORM := bridges.NewORM(db) + + createBridge(t, "foo-bridge", `123.456`, bridgesORM, 1) + createBridge(t, "bar-bridge", `"124.456"`, bridgesORM, 1) + + c := clhttptest.NewTestLocalOnlyHTTPClient() + runner := pipeline.NewRunner( + nil, + bridgesORM, + &mockPipelineConfig{}, + &mockBridgeConfig{}, + nil, + nil, + nil, + lggr, + c, + c, + ) + + r := streams.NewRegistry(lggr, runner) + + jobStreamID := streams.StreamID(5) + + t.Run("using only streamID attributes", func(t *testing.T) { + jb := job.Job{ + Type: job.Stream, + StreamID: &jobStreamID, + PipelineSpec: &pipeline.Spec{ + DotDagSource: ` +// Benchmark Price +result1 [type=memo value="900.0022"]; +multiply2 [type=multiply times=1 streamID=1 index=0]; // force conversion to decimal + +result2 [type=bridge name="foo-bridge" requestData="{\"data\":{\"data\":\"foo\"}}"]; +result2_parse [type=jsonparse path="result" streamID=2 index=1]; + +result3 [type=bridge name="bar-bridge" requestData="{\"data\":{\"data\":\"bar\"}}"]; +result3_parse [type=jsonparse path="result"]; +multiply3 [type=multiply times=1 streamID=3 index=2]; // force conversion to decimal + +result1 -> multiply2; +result2 -> result2_parse; +result3 -> result3_parse -> multiply3; +`, + }, + } + err := r.Register(jb, nil) + require.NoError(t, err) + + telem := &mockTelemeter{} + oc := newObservationContext(r, telem) + opts := llo.DSOpts(nil) + + val, err := oc.Observe(ctx, streams.StreamID(1), opts) + require.NoError(t, err) + assert.Equal(t, "900.0022", val.(*llo.Decimal).String()) + val, err = oc.Observe(ctx, streams.StreamID(2), opts) + require.NoError(t, err) + assert.Equal(t, "123.456", val.(*llo.Decimal).String()) + val, err = oc.Observe(ctx, streams.StreamID(3), opts) + require.NoError(t, err) + assert.Equal(t, "124.456", val.(*llo.Decimal).String()) + + val, err = oc.Observe(ctx, jobStreamID, opts) + require.NoError(t, err) + assert.Equal(t, &llo.Quote{ + Bid: decimal.NewFromFloat32(123.456), + Benchmark: decimal.NewFromFloat32(900.0022), + Ask: decimal.NewFromFloat32(124.456), + }, val.(*llo.Quote)) + }) +} + +func BenchmarkObservationContext_Observe_integrationRealPipeline_concurrencyStressTest_manyStreams(b *testing.B) { + ctx := tests.Context(b) + lggr := logger.TestLogger(b) + db := pgtest.NewSqlxDB(b) + bridgesORM := bridges.NewORM(db) + + if b.N > math.MaxInt32 { + b.Fatalf("N is too large: %d", b.N) + } + n := uint32(b.N) //nolint:gosec // G115 // overflow impossible + + createBridge(b, "foo-bridge", `123.456`, bridgesORM, 0) + createBridge(b, "bar-bridge", `"124.456"`, bridgesORM, 0) + + c := clhttptest.NewTestLocalOnlyHTTPClient() + runner := pipeline.NewRunner( + nil, + bridgesORM, + &mockPipelineConfig{}, + &mockBridgeConfig{}, + nil, + nil, + nil, + lggr, + c, + c, + ) + + r := streams.NewRegistry(lggr, runner) + + for i := uint32(0); i < n; i++ { + i := i + jb := job.Job{ + ID: int32(i), //nolint:gosec // G115 // overflow impossible + Name: null.StringFrom(fmt.Sprintf("job-%d", i)), + Type: job.Stream, + StreamID: &i, + PipelineSpec: &pipeline.Spec{ + ID: int32(i * 100), //nolint:gosec // G115 // overflow impossible + DotDagSource: fmt.Sprintf(` +// Benchmark Price +result1 [type=memo value="900.0022"]; +multiply2 [type=multiply times=1 streamID=%d index=0]; // force conversion to decimal + +result2 [type=bridge name="foo-bridge" requestData="{\"data\":{\"data\":\"foo\"}}"]; +result2_parse [type=jsonparse path="result" streamID=%d index=1]; + +result3 [type=bridge name="bar-bridge" requestData="{\"data\":{\"data\":\"bar\"}}"]; +result3_parse [type=jsonparse path="result"]; +multiply3 [type=multiply times=1 streamID=%d index=2]; // force conversion to decimal + +result1 -> multiply2; +result2 -> result2_parse; +result3 -> result3_parse -> multiply3; +`, i+n, i+2*n, i+3*n), + }, + } + err := r.Register(jb, nil) + require.NoError(b, err) + } + + telem := &mockTelemeter{} + oc := newObservationContext(r, telem) + opts := llo.DSOpts(nil) + + // concurrency stress test + b.ResetTimer() + g, ctx := errgroup.WithContext(ctx) + for i := uint32(0); i < n; i++ { + for _, strmID := range []uint32{i, i + n, i + 2*n, i + 3*n} { + g.Go(func() error { + // ignore errors, only care about races + oc.Observe(ctx, strmID, opts) //nolint:errcheck // ignore error + return nil + }) + } + } + if err := g.Wait(); err != nil { + b.Fatalf("Observation failed: %v", err) + } +} diff --git a/core/services/llo/onchain_channel_definition_cache.go b/core/services/llo/onchain_channel_definition_cache.go index 78078d5c36e..461c309a73a 100644 --- a/core/services/llo/onchain_channel_definition_cache.go +++ b/core/services/llo/onchain_channel_definition_cache.go @@ -279,7 +279,6 @@ func (c *channelDefinitionCache) readLogs(ctx context.Context) (err error) { c.newLogCh <- unpacked } c.newLogMu.Unlock() - } return nil diff --git a/core/services/mocks/checker.go b/core/services/mocks/checker.go index 24b5315254c..cda33d50ad0 100644 --- a/core/services/mocks/checker.go +++ b/core/services/mocks/checker.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -20,7 +20,7 @@ func (_m *Checker) EXPECT() *Checker_Expecter { return &Checker_Expecter{mock: &_m.Mock} } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *Checker) Close() error { ret := _m.Called() @@ -65,7 +65,7 @@ func (_c *Checker_Close_Call) RunAndReturn(run func() error) *Checker_Close_Call return _c } -// IsHealthy provides a mock function with given fields: +// IsHealthy provides a mock function with no fields func (_m *Checker) IsHealthy() (bool, map[string]error) { ret := _m.Called() @@ -122,7 +122,7 @@ func (_c *Checker_IsHealthy_Call) RunAndReturn(run func() (bool, map[string]erro return _c } -// IsReady provides a mock function with given fields: +// IsReady provides a mock function with no fields func (_m *Checker) IsReady() (bool, map[string]error) { ret := _m.Called() @@ -225,7 +225,7 @@ func (_c *Checker_Register_Call) RunAndReturn(run func(pkgservices.HealthReporte return _c } -// Start provides a mock function with given fields: +// Start provides a mock function with no fields func (_m *Checker) Start() error { ret := _m.Called() diff --git a/core/services/ocr/contract_tracker.go b/core/services/ocr/contract_tracker.go index 618567f0bdb..f2cf1fee9d3 100644 --- a/core/services/ocr/contract_tracker.go +++ b/core/services/ocr/contract_tracker.go @@ -399,7 +399,7 @@ func (t *OCRContractTracker) LatestBlockHeight(ctx context.Context) (blockheight // care about the block height; we have no way of getting the L1 block // height anyway return 0, nil - case "", chaintype.ChainArbitrum, chaintype.ChainAstar, chaintype.ChainCelo, chaintype.ChainGnosis, chaintype.ChainHedera, chaintype.ChainKroma, chaintype.ChainOptimismBedrock, chaintype.ChainScroll, chaintype.ChainWeMix, chaintype.ChainXLayer, chaintype.ChainZkEvm, chaintype.ChainZkSync, chaintype.ChainZircuit: + case "", chaintype.ChainArbitrum, chaintype.ChainAstar, chaintype.ChainCelo, chaintype.ChainGnosis, chaintype.ChainHedera, chaintype.ChainKroma, chaintype.ChainOptimismBedrock, chaintype.ChainSei, chaintype.ChainScroll, chaintype.ChainWeMix, chaintype.ChainXLayer, chaintype.ChainZkEvm, chaintype.ChainZkSync, chaintype.ChainZircuit: // continue } latestBlockHeight := t.getLatestBlockHeight() diff --git a/core/services/ocr/mocks/ocr_contract_tracker_db.go b/core/services/ocr/mocks/ocr_contract_tracker_db.go index fc29c50f1ea..ea95cbd83f5 100644 --- a/core/services/ocr/mocks/ocr_contract_tracker_db.go +++ b/core/services/ocr/mocks/ocr_contract_tracker_db.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go index edcc816bf04..888cbfa5778 100644 --- a/core/services/ocr2/delegate.go +++ b/core/services/ocr2/delegate.go @@ -7,6 +7,7 @@ import ( "fmt" "log" "strconv" + "strings" "time" "gopkg.in/guregu/null.v4" @@ -14,6 +15,7 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" "github.com/smartcontractkit/chainlink-common/pkg/types/core" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" "github.com/ethereum/go-ethereum/common" @@ -41,7 +43,6 @@ import ( llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" datastreamsllo "github.com/smartcontractkit/chainlink-data-streams/llo" - "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" coreconfig "github.com/smartcontractkit/chainlink/v2/core/config" @@ -264,12 +265,12 @@ func (d *Delegate) JobType() job.Type { return job.OffchainReporting2 } -func (d *Delegate) BeforeJobCreated(spec job.Job) { +func (d *Delegate) BeforeJobCreated(_ job.Job) { // This is only called first time the job is created d.isNewlyCreatedJob = true } -func (d *Delegate) AfterJobCreated(spec job.Job) {} -func (d *Delegate) BeforeJobDeleted(spec job.Job) {} +func (d *Delegate) AfterJobCreated(_ job.Job) {} +func (d *Delegate) BeforeJobDeleted(_ job.Job) {} func (d *Delegate) OnDeleteJob(ctx context.Context, jb job.Job) error { // If the job spec is malformed in any way, we report the error but return nil so that // the job deletion itself isn't blocked. @@ -683,9 +684,9 @@ func (d *Delegate) newServicesGenericPlugin( providerClientConn = providerConn.ClientConn() } else { // We chose to deal with the difference between a LOOP provider and an embedded provider here rather than - //in NewServerAdapter because this has a smaller blast radius, as the scope of this workaround is to - //enable the medianpoc for EVM and not touch the other providers. - //TODO: remove this workaround when the EVM relayer is running inside of an LOOPP + // in NewServerAdapter because this has a smaller blast radius, as the scope of this workaround is to + // enable the medianpoc for EVM and not touch the other providers. + // TODO: remove this workaround when the EVM relayer is running inside of an LOOPP d.lggr.Info("provider is not a LOOPP provider, switching to provider server") ps, err2 := loop.NewProviderServer(provider, types.OCR2PluginType(pCfg.ProviderType), d.lggr) @@ -885,7 +886,8 @@ func (d *Delegate) newServicesMercury( lc.ContractConfigTrackerPollInterval = 1 * time.Second // 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) { + // Disable OCR debug+info logging for legacy mercury jobs unless tracelogging is enabled, because its simply too verbose (150 jobs => ~50k logs per second) + ocrLogger := ocrcommon.NewOCRWrapper(llo.NewSuppressedLogger(lggr, d.cfg.OCR2().TraceLogging()), d.cfg.OCR2().TraceLogging(), func(ctx context.Context, msg string) { lggr.ErrorIf(d.jobORM.RecordError(ctx, jb.ID, msg), "unable to record error") }) @@ -1007,7 +1009,7 @@ func (d *Delegate) newServicesLLO( // Also re-use EVM keys for signing the retirement report. This isn't // required, just seems easiest since it's the only key type available for // now. - for _, rf := range []llotypes.ReportFormat{llotypes.ReportFormatJSON, llotypes.ReportFormatEVMPremiumLegacy, llotypes.ReportFormatRetirement} { + for _, rf := range []llotypes.ReportFormat{llotypes.ReportFormatJSON, llotypes.ReportFormatEVMPremiumLegacy, llotypes.ReportFormatRetirement, llotypes.ReportFormatEVMABIEncodeUnpacked} { if _, exists := kbm[rf]; !exists { // Use the first if unspecified kbs, err3 := d.ks.GetAllOfType("evm") @@ -1055,7 +1057,6 @@ func (d *Delegate) newServicesLLO( V2Bootstrappers: bootstrapPeers, ContractTransmitter: provider.ContractTransmitter(), ContractConfigTrackers: provider.ContractConfigTrackers(), - Database: ocrDB, LocalConfig: lc, OCR3MonitoringEndpoint: d.monitoringEndpointGen.GenMonitoringEndpoint(rid.Network, rid.ChainID, telemetryContractID, synchronization.OCR3Mercury), OffchainConfigDigester: provider.OffchainConfigDigester(), @@ -1064,6 +1065,9 @@ func (d *Delegate) newServicesLLO( // Enable verbose logging if either Mercury.VerboseLogging is on or OCR2.TraceLogging is on ReportingPluginConfig: datastreamsllo.Config{VerboseLogging: d.cfg.Mercury().VerboseLogging() || d.cfg.OCR2().TraceLogging()}, + NewOCR3DB: func(pluginID int32) ocr3types.Database { + return NewDB(d.ds, spec.ID, pluginID, lggr) + }, } oracle, err := llo.NewDelegate(cfg) if err != nil { @@ -1647,7 +1651,85 @@ func (d *Delegate) newServicesCCIPCommit(ctx context.Context, lggr logger.Sugare MetricsRegisterer: prometheus.WrapRegistererWith(map[string]string{"job_name": jb.Name.ValueOrZero()}, prometheus.DefaultRegisterer), } - return ccipcommit.NewCommitServices(ctx, d.ds, srcProvider, dstProvider, d.legacyChains, jb, lggr, d.pipelineRunner, oracleArgsNoPlugin, d.isNewlyCreatedJob, int64(srcChainID), dstChainID, logError) + priceGetter, err := d.ccipCommitPriceGetter(ctx, lggr, pluginJobSpecConfig, jb) + if err != nil { + return nil, fmt.Errorf("failed to create price getter: %w", err) + } + //nolint:gosec // safe to cast + return ccipcommit.NewCommitServices(ctx, d.ds, srcProvider, dstProvider, priceGetter, jb, lggr, d.pipelineRunner, oracleArgsNoPlugin, d.isNewlyCreatedJob, int64(srcChainID), dstChainID, logError) +} + +func (d *Delegate) ccipCommitPriceGetter(ctx context.Context, lggr logger.SugaredLogger, pluginJobSpecConfig ccipconfig.CommitPluginJobSpecConfig, jb job.Job) (priceGetter ccip.AllTokensPriceGetter, err error) { + spec := jb.OCR2OracleSpec + withPipeline := strings.Trim(pluginJobSpecConfig.TokenPricesUSDPipeline, "\n\t ") != "" + if withPipeline { + priceGetter, err = ccip.NewPipelineGetter(pluginJobSpecConfig.TokenPricesUSDPipeline, d.pipelineRunner, jb.ID, jb.ExternalJobID, jb.Name.ValueOrZero(), lggr) + if err != nil { + return nil, fmt.Errorf("creating pipeline price getter: %w", err) + } + } else { + // Use dynamic price getter. + if pluginJobSpecConfig.PriceGetterConfig == nil { + return nil, errors.New("priceGetterConfig is nil") + } + + // Configure contract readers for all chains specified in the aggregator configurations. + // Some lanes (e.g. Wemix/Kroma) requires other clients than source and destination, since they use feeds from other chains. + aggregatorChainsToContracts := make(map[uint64][]common.Address) + for _, aggCfg := range pluginJobSpecConfig.PriceGetterConfig.AggregatorPrices { + if _, ok := aggregatorChainsToContracts[aggCfg.ChainID]; !ok { + aggregatorChainsToContracts[aggCfg.ChainID] = make([]common.Address, 0) + } + + aggregatorChainsToContracts[aggCfg.ChainID] = append(aggregatorChainsToContracts[aggCfg.ChainID], aggCfg.AggregatorContractAddress) + } + + contractReaders := map[uint64]types.ContractReader{} + + for chainID, aggregatorContracts := range aggregatorChainsToContracts { + relayID := types.RelayID{Network: spec.Relay, ChainID: strconv.FormatUint(chainID, 10)} + relay, rerr := d.RelayGetter.Get(relayID) + if rerr != nil { + return nil, fmt.Errorf("get relay by id=%v: %w", relayID, err) + } + + contractsConfig := make(map[string]evmrelaytypes.ChainContractReader, len(aggregatorContracts)) + for i := range aggregatorContracts { + contractsConfig[fmt.Sprintf("%v_%v", ccip.OffchainAggregator, i)] = evmrelaytypes.ChainContractReader{ + ContractABI: ccip.OffChainAggregatorABI, + Configs: map[string]*evmrelaytypes.ChainReaderDefinition{ + "decimals": { // CR consumers choose an alias + ChainSpecificName: "decimals", + }, + "latestRoundData": { + ChainSpecificName: "latestRoundData", + }, + }, + } + } + contractReaderConfig := evmrelaytypes.ChainReaderConfig{ + Contracts: contractsConfig, + } + + contractReaderConfigJSONBytes, jerr := json.Marshal(contractReaderConfig) + if jerr != nil { + return nil, fmt.Errorf("marshal contract reader config: %w", jerr) + } + + contractReader, cerr := relay.NewContractReader(ctx, contractReaderConfigJSONBytes) + if cerr != nil { + return nil, fmt.Errorf("new ccip commit contract reader %w", cerr) + } + + contractReaders[chainID] = contractReader + } + + priceGetter, err = ccip.NewDynamicPriceGetter(*pluginJobSpecConfig.PriceGetterConfig, contractReaders) + if err != nil { + return nil, fmt.Errorf("creating dynamic price getter: %w", err) + } + } + return priceGetter, nil } func newCCIPCommitPluginBytes(isSourceProvider bool, sourceStartBlock uint64, destStartBlock uint64) config.CommitPluginConfig { @@ -1831,7 +1913,7 @@ func (d *Delegate) ccipExecGetDstProvider(ctx context.Context, jb job.Job, plugi // PROVIDER BASED ARG CONSTRUCTION // Write PluginConfig bytes to send source/dest relayer provider + info outside of top level rargs/pargs over the wire - dstConfigBytes, err := newExecPluginConfig(false, pluginJobSpecConfig.SourceStartBlock, pluginJobSpecConfig.DestStartBlock, pluginJobSpecConfig.USDCConfig, string(jb.ID)).Encode() + dstConfigBytes, err := newExecPluginConfig(false, pluginJobSpecConfig.SourceStartBlock, pluginJobSpecConfig.DestStartBlock, pluginJobSpecConfig.USDCConfig, pluginJobSpecConfig.LBTCConfig, string(jb.ID)).Encode() if err != nil { return nil, err } @@ -1864,7 +1946,7 @@ func (d *Delegate) ccipExecGetDstProvider(ctx context.Context, jb job.Job, plugi func (d *Delegate) ccipExecGetSrcProvider(ctx context.Context, jb job.Job, pluginJobSpecConfig ccipconfig.ExecPluginJobSpecConfig, transmitterID string, dstProvider types.CCIPExecProvider) (srcProvider types.CCIPExecProvider, srcChainID uint64, err error) { spec := jb.OCR2OracleSpec - srcConfigBytes, err := newExecPluginConfig(true, pluginJobSpecConfig.SourceStartBlock, pluginJobSpecConfig.DestStartBlock, pluginJobSpecConfig.USDCConfig, string(jb.ID)).Encode() + srcConfigBytes, err := newExecPluginConfig(true, pluginJobSpecConfig.SourceStartBlock, pluginJobSpecConfig.DestStartBlock, pluginJobSpecConfig.USDCConfig, pluginJobSpecConfig.LBTCConfig, string(jb.ID)).Encode() if err != nil { return nil, 0, err } @@ -1913,12 +1995,13 @@ func (d *Delegate) ccipExecGetSrcProvider(ctx context.Context, jb job.Job, plugi return } -func newExecPluginConfig(isSourceProvider bool, srcStartBlock uint64, dstStartBlock uint64, usdcConfig ccipconfig.USDCConfig, jobID string) config.ExecPluginConfig { +func newExecPluginConfig(isSourceProvider bool, srcStartBlock uint64, dstStartBlock uint64, usdcConfig ccipconfig.USDCConfig, lbtcConfig ccipconfig.LBTCConfig, jobID string) config.ExecPluginConfig { return config.ExecPluginConfig{ IsSourceProvider: isSourceProvider, SourceStartBlock: srcStartBlock, DestStartBlock: dstStartBlock, USDCConfig: usdcConfig, + LBTCConfig: lbtcConfig, JobID: jobID, } } diff --git a/core/services/ocr2/plugins/ccip/ccipcommit/factory.go b/core/services/ocr2/plugins/ccip/ccipcommit/factory.go index c7a18567d26..784da3e7eab 100644 --- a/core/services/ocr2/plugins/ccip/ccipcommit/factory.go +++ b/core/services/ocr2/plugins/ccip/ccipcommit/factory.go @@ -74,8 +74,11 @@ type reportingPluginAndInfo struct { func (rf *CommitReportingPluginFactory) NewReportingPlugin(ctx context.Context, config types.ReportingPluginConfig) (types.ReportingPlugin, types.ReportingPluginInfo, error) { initialRetryDelay := rf.config.newReportingPluginRetryConfig.InitialDelay maxDelay := rf.config.newReportingPluginRetryConfig.MaxDelay + maxRetries := rf.config.newReportingPluginRetryConfig.MaxRetries - pluginAndInfo, err := ccipcommon.RetryUntilSuccess(rf.NewReportingPluginFn(ctx, config), initialRetryDelay, maxDelay) + pluginAndInfo, err := ccipcommon.RetryUntilSuccess( + rf.NewReportingPluginFn(ctx, config), initialRetryDelay, maxDelay, maxRetries, + ) if err != nil { return nil, types.ReportingPluginInfo{}, err } @@ -86,33 +89,33 @@ func (rf *CommitReportingPluginFactory) NewReportingPlugin(ctx context.Context, // retried via RetryUntilSuccess. NewReportingPlugin must return successfully in order for the Commit plugin to // function, hence why we can only keep retrying it until it succeeds. func (rf *CommitReportingPluginFactory) NewReportingPluginFn(ctx context.Context, config types.ReportingPluginConfig) func() (reportingPluginAndInfo, error) { - return func() (reportingPluginAndInfo, error) { + newReportingPluginFn := func() (reportingPluginAndInfo, error) { destPriceReg, err := rf.config.commitStore.ChangeConfig(ctx, config.OnchainConfig, config.OffchainConfig) if err != nil { - return reportingPluginAndInfo{}, err + return reportingPluginAndInfo{}, fmt.Errorf("commitStore.ChangeConfig error: %w", err) } priceRegEvmAddr, err := ccipcalc.GenericAddrToEvm(destPriceReg) if err != nil { - return reportingPluginAndInfo{}, err + return reportingPluginAndInfo{}, fmt.Errorf("GenericAddrToEvm error: %w", err) } if err = rf.UpdateDynamicReaders(ctx, priceRegEvmAddr); err != nil { - return reportingPluginAndInfo{}, err + return reportingPluginAndInfo{}, fmt.Errorf("UpdateDynamicReaders error: %w", err) } pluginOffChainConfig, err := rf.config.commitStore.OffchainConfig(ctx) if err != nil { - return reportingPluginAndInfo{}, err + return reportingPluginAndInfo{}, fmt.Errorf("commitStore.OffchainConfig error: %w", err) } gasPriceEstimator, err := rf.config.commitStore.GasPriceEstimator(ctx) if err != nil { - return reportingPluginAndInfo{}, err + return reportingPluginAndInfo{}, fmt.Errorf("commitStore.GasPriceEstimator error: %w", err) } err = rf.config.priceService.UpdateDynamicConfig(ctx, gasPriceEstimator, rf.destPriceRegReader) if err != nil { - return reportingPluginAndInfo{}, err + return reportingPluginAndInfo{}, fmt.Errorf("priceService.UpdateDynamicConfig error: %w", err) } lggr := rf.config.lggr.Named("CommitReportingPlugin") @@ -145,4 +148,14 @@ func (rf *CommitReportingPluginFactory) NewReportingPluginFn(ctx context.Context return reportingPluginAndInfo{plugin, pluginInfo}, nil } + + return func() (reportingPluginAndInfo, error) { + result, err := newReportingPluginFn() + if err != nil { + rf.config.lggr.Errorw("NewReportingPlugin failed", "err", err) + rf.config.metricsCollector.NewReportingPluginError() + } + + return result, err + } } diff --git a/core/services/ocr2/plugins/ccip/ccipcommit/factory_test.go b/core/services/ocr2/plugins/ccip/ccipcommit/factory_test.go index 44c63ec87e6..d3332435b06 100644 --- a/core/services/ocr2/plugins/ccip/ccipcommit/factory_test.go +++ b/core/services/ocr2/plugins/ccip/ccipcommit/factory_test.go @@ -14,6 +14,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink/v2/core/logger" + ccip2 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" ccipdataprovidermocks "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/ccipdataprovider/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks" @@ -28,6 +29,8 @@ import ( func TestNewReportingPluginRetriesUntilSuccess(t *testing.T) { ctx := tests.Context(t) commitConfig := CommitPluginStaticConfig{} + commitConfig.lggr = logger.TestLogger(t) + commitConfig.metricsCollector = ccip2.NoopMetricsCollector // For this unit test, ensure that there is no delay between retries commitConfig.newReportingPluginRetryConfig = ccipdata.RetryConfig{ diff --git a/core/services/ocr2/plugins/ccip/ccipcommit/initializers.go b/core/services/ocr2/plugins/ccip/ccipcommit/initializers.go index 771fdd322f3..3a6148d1b8a 100644 --- a/core/services/ocr2/plugins/ccip/ccipcommit/initializers.go +++ b/core/services/ocr2/plugins/ccip/ccipcommit/initializers.go @@ -3,14 +3,9 @@ package ccipcommit import ( "context" "encoding/json" - "fmt" "math/big" - "strings" "time" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/pricegetter" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/rpclib" - "github.com/Masterminds/semver/v3" "github.com/ethereum/go-ethereum/common" libocr2 "github.com/smartcontractkit/libocr/offchainreporting2plus" @@ -27,7 +22,6 @@ import ( db "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdb" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" - "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip" @@ -40,9 +34,29 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" ) -var defaultNewReportingPluginRetryConfig = ccipdata.RetryConfig{InitialDelay: time.Second, MaxDelay: 5 * time.Minute} +var defaultNewReportingPluginRetryConfig = ccipdata.RetryConfig{ + InitialDelay: time.Second, + MaxDelay: 10 * time.Minute, + // Retry for approximately 4hrs (MaxDelay of 10m = 6 times per hour, times 4 hours, plus 10 because the first + // 10 retries only take 20 minutes due to an initial retry of 1s and exponential backoff) + MaxRetries: (6 * 4) + 10, +} -func NewCommitServices(ctx context.Context, ds sqlutil.DataSource, srcProvider commontypes.CCIPCommitProvider, dstProvider commontypes.CCIPCommitProvider, chainSet legacyevm.LegacyChainContainer, jb job.Job, lggr logger.Logger, pr pipeline.Runner, argsNoPlugin libocr2.OCR2OracleArgs, new bool, sourceChainID int64, destChainID int64, logError func(string)) ([]job.ServiceCtx, error) { +func NewCommitServices( + ctx context.Context, + ds sqlutil.DataSource, + srcProvider commontypes.CCIPCommitProvider, + dstProvider commontypes.CCIPCommitProvider, + priceGetter ccip.AllTokensPriceGetter, + jb job.Job, + lggr logger.Logger, + pr pipeline.Runner, + argsNoPlugin libocr2.OCR2OracleArgs, + newInstance bool, + sourceChainID int64, + destChainID int64, + logError func(string), +) ([]job.ServiceCtx, error) { spec := jb.OCR2OracleSpec var pluginConfig ccipconfig.CommitPluginJobSpecConfig @@ -69,45 +83,6 @@ func NewCommitServices(ctx context.Context, ds sqlutil.DataSource, srcProvider c commitStoreReader = ccip.NewProviderProxyCommitStoreReader(srcCommitStore, dstCommitStore) commitLggr := lggr.Named("CCIPCommit").With("sourceChain", sourceChainID, "destChain", destChainID) - var priceGetter pricegetter.AllTokensPriceGetter - withPipeline := strings.Trim(pluginConfig.TokenPricesUSDPipeline, "\n\t ") != "" - if withPipeline { - priceGetter, err = pricegetter.NewPipelineGetter(pluginConfig.TokenPricesUSDPipeline, pr, jb.ID, jb.ExternalJobID, jb.Name.ValueOrZero(), lggr) - if err != nil { - return nil, fmt.Errorf("creating pipeline price getter: %w", err) - } - } else { - // Use dynamic price getter. - if pluginConfig.PriceGetterConfig == nil { - return nil, fmt.Errorf("priceGetterConfig is nil") - } - - // Build price getter clients for all chains specified in the aggregator configurations. - // Some lanes (e.g. Wemix/Kroma) requires other clients than source and destination, since they use feeds from other chains. - priceGetterClients := map[uint64]pricegetter.DynamicPriceGetterClient{} - for _, aggCfg := range pluginConfig.PriceGetterConfig.AggregatorPrices { - chainID := aggCfg.ChainID - // Retrieve the chain. - chain, _, err2 := ccipconfig.GetChainByChainID(chainSet, chainID) - if err2 != nil { - return nil, fmt.Errorf("retrieving chain for chainID %d: %w", chainID, err2) - } - caller := rpclib.NewDynamicLimitedBatchCaller( - lggr, - chain.Client(), - rpclib.DefaultRpcBatchSizeLimit, - rpclib.DefaultRpcBatchBackOffMultiplier, - rpclib.DefaultMaxParallelRpcCalls, - ) - priceGetterClients[chainID] = pricegetter.NewDynamicPriceGetterClient(caller) - } - - priceGetter, err = pricegetter.NewDynamicPriceGetter(*pluginConfig.PriceGetterConfig, priceGetterClients) - if err != nil { - return nil, fmt.Errorf("creating dynamic price getter: %w", err) - } - } - offRampReader, err := dstProvider.NewOffRampReader(ctx, pluginConfig.OffRamp) if err != nil { return nil, err @@ -156,7 +131,7 @@ func NewCommitServices(ctx context.Context, ds sqlutil.DataSource, srcProvider c onRampAddress, ) - orm, err := cciporm.NewObservedORM(ds, lggr) + orm, err := cciporm.NewORM(ds, lggr) if err != nil { return nil, err } @@ -193,7 +168,7 @@ func NewCommitServices(ctx context.Context, ds sqlutil.DataSource, srcProvider c return nil, err } // If this is a brand-new job, then we make use of the start blocks. If not then we're rebooting and log poller will pick up where we left off. - if new { + if newInstance { return []job.ServiceCtx{ oraclelib.NewChainAgnosticBackFilledOracle( lggr, diff --git a/core/services/ocr2/plugins/ccip/ccipcommit/ocr2.go b/core/services/ocr2/plugins/ccip/ccipcommit/ocr2.go index 55caf88f1c7..97b982b0e2e 100644 --- a/core/services/ocr2/plugins/ccip/ccipcommit/ocr2.go +++ b/core/services/ocr2/plugins/ccip/ccipcommit/ocr2.go @@ -461,24 +461,42 @@ func (r *CommitReportingPlugin) selectPriceUpdates(ctx context.Context, now time // The returned latestGasPrice and latestTokenPrices should not contain nil values. func (r *CommitReportingPlugin) calculatePriceUpdates(ctx context.Context, gasPriceObs map[uint64][]*big.Int, tokenPriceObs map[cciptypes.Address][]*big.Int, latestGasPrice map[uint64]update, latestTokenPrices map[cciptypes.Address]update) ([]cciptypes.GasPrice, []cciptypes.TokenPrice, error) { var tokenPriceUpdates []cciptypes.TokenPrice + // Token prices are mostly heartbeat driven. To maximize heartbeat batching, the price inclusion rule is as follows: + // If any token requires heartbeat update, include all token prices in the report. + // Otherwise, only include token prices that exceed deviation threshold. + needTokenHeartbeat := false + for token := range tokenPriceObs { + latestTokenPrice, exists := latestTokenPrices[token] + if !exists || time.Since(latestTokenPrice.timestamp) >= r.offchainConfig.TokenPriceHeartBeat { + r.lggr.Infow("Token requires heartbeat update", "token", token) + needTokenHeartbeat = true + break + } + } + for token, tokenPriceObservations := range tokenPriceObs { medianPrice := ccipcalc.BigIntSortedMiddle(tokenPriceObservations) + if needTokenHeartbeat { + r.lggr.Debugw("Token price update included due to heartbeat", "token", token, "newPrice", medianPrice) + tokenPriceUpdates = append(tokenPriceUpdates, cciptypes.TokenPrice{ + Token: token, + Value: medianPrice, + }) + continue + } + latestTokenPrice, exists := latestTokenPrices[token] if exists { - tokenPriceUpdatedRecently := time.Since(latestTokenPrice.timestamp) < r.offchainConfig.TokenPriceHeartBeat - tokenPriceNotChanged := !ccipcalc.Deviates(medianPrice, latestTokenPrice.value, int64(r.offchainConfig.TokenPriceDeviationPPB)) - if tokenPriceUpdatedRecently && tokenPriceNotChanged { - r.lggr.Debugw("token price was updated recently, skipping the update", + if ccipcalc.Deviates(medianPrice, latestTokenPrice.value, int64(r.offchainConfig.TokenPriceDeviationPPB)) { + r.lggr.Debugw("Token price update included due to deviation", "token", token, "newPrice", medianPrice, "existingPrice", latestTokenPrice.value) - continue // skip the update if we recently had a price update close to the new value + tokenPriceUpdates = append(tokenPriceUpdates, cciptypes.TokenPrice{ + Token: token, + Value: medianPrice, + }) } } - - tokenPriceUpdates = append(tokenPriceUpdates, cciptypes.TokenPrice{ - Token: token, - Value: medianPrice, - }) } // Determinism required. @@ -487,31 +505,49 @@ func (r *CommitReportingPlugin) calculatePriceUpdates(ctx context.Context, gasPr }) var gasPriceUpdate []cciptypes.GasPrice + // Gas prices are mostly heartbeat driven. To maximize heartbeat batching, the price inclusion rule is as follows: + // If any source chain gas price requires heartbeat update, include all gas prices in the report. + // Otherwise, only include gas prices that exceed deviation threshold. + needGasHeartbeat := false + for chainSelector := range gasPriceObs { + latestGasPrice, exists := latestGasPrice[chainSelector] + if !exists || latestGasPrice.value == nil || time.Since(latestGasPrice.timestamp) >= r.offchainConfig.GasPriceHeartBeat { + r.lggr.Infow("Chain gas price requires heartbeat update", "chainSelector", chainSelector) + needGasHeartbeat = true + break + } + } + for chainSelector, gasPriceObservations := range gasPriceObs { newGasPrice, err := r.gasPriceEstimator.Median(ctx, gasPriceObservations) // Compute the median price if err != nil { return nil, nil, fmt.Errorf("failed to calculate median gas price for chain selector %d: %w", chainSelector, err) } - // Default to updating so that we update if there are no prior updates. + if needGasHeartbeat { + r.lggr.Debugw("Gas price update included due to heartbeat", "chainSelector", chainSelector) + gasPriceUpdate = append(gasPriceUpdate, cciptypes.GasPrice{ + DestChainSelector: chainSelector, + Value: newGasPrice, + }) + continue + } + latestGasPrice, exists := latestGasPrice[chainSelector] if exists && latestGasPrice.value != nil { - gasPriceUpdatedRecently := time.Since(latestGasPrice.timestamp) < r.offchainConfig.GasPriceHeartBeat gasPriceDeviated, err := r.gasPriceEstimator.Deviates(ctx, newGasPrice, latestGasPrice.value) if err != nil { return nil, nil, err } - if gasPriceUpdatedRecently && !gasPriceDeviated { - r.lggr.Debugw("gas price was updated recently and not deviated sufficiently, skipping the update", + if gasPriceDeviated { + r.lggr.Debugw("Gas price update included due to deviation", "chainSelector", chainSelector, "newPrice", newGasPrice, "existingPrice", latestGasPrice.value) - continue + gasPriceUpdate = append(gasPriceUpdate, cciptypes.GasPrice{ + DestChainSelector: chainSelector, + Value: newGasPrice, + }) } } - - gasPriceUpdate = append(gasPriceUpdate, cciptypes.GasPrice{ - DestChainSelector: chainSelector, - Value: newGasPrice, - }) } sort.Slice(gasPriceUpdate, func(i, j int) bool { diff --git a/core/services/ocr2/plugins/ccip/ccipcommit/ocr2_test.go b/core/services/ocr2/plugins/ccip/ccipcommit/ocr2_test.go index 93d8de9f892..ecc0c56b982 100644 --- a/core/services/ocr2/plugins/ccip/ccipcommit/ocr2_test.go +++ b/core/services/ocr2/plugins/ccip/ccipcommit/ocr2_test.go @@ -20,15 +20,13 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/hashutil" "github.com/smartcontractkit/chainlink-common/pkg/merklemulti" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" - + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks" mocks2 "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" @@ -44,7 +42,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/factory" ccipdatamocks "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" - ccipdbmocks "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdb/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/prices" ) @@ -409,7 +406,9 @@ func TestCommitReportingPlugin_Report(t *testing.T) { evmEstimator := mocks.NewEvmFeeEstimator(t) evmEstimator.On("L1Oracle").Return(nil) - gasPriceEstimator := prices.NewDAGasPriceEstimator(evmEstimator, nil, 2e9, 2e9) // 200% deviation + + feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) + gasPriceEstimator := prices.NewDAGasPriceEstimator(evmEstimator, nil, 2e9, 2e9, feeEstimatorConfig) // 200% deviation var destTokens []cciptypes.Address for tk := range tc.tokenDecimals { @@ -433,7 +432,7 @@ func TestCommitReportingPlugin_Report(t *testing.T) { })).Return(destDecimals, nil).Maybe() lp := mocks2.NewLogPoller(t) - commitStoreReader, err := v1_2_0.NewCommitStore(logger.TestLogger(t), utils.RandomAddress(), nil, lp) + commitStoreReader, err := v1_2_0.NewCommitStore(logger.TestLogger(t), utils.RandomAddress(), nil, lp, feeEstimatorConfig) assert.NoError(t, err) healthCheck := ccipcachemocks.NewChainHealthcheck(t) @@ -1131,7 +1130,7 @@ func TestCommitReportingPlugin_calculatePriceUpdates(t *testing.T) { expGasUpdates: []cciptypes.GasPrice{{DestChainSelector: defaultSourceChainSelector, Value: val1e18(20)}}, }, { - name: "multichain gas prices", + name: "multi-chain gas price updates due to heartbeat", commitObservations: []ccip.CommitObservation{ {SourceGasPriceUSDPerChain: map[uint64]*big.Int{defaultSourceChainSelector: val1e18(1)}}, {SourceGasPriceUSDPerChain: map[uint64]*big.Int{defaultSourceChainSelector + 1: val1e18(11)}}, @@ -1161,9 +1160,47 @@ func TestCommitReportingPlugin_calculatePriceUpdates(t *testing.T) { f: 1, expGasUpdates: []cciptypes.GasPrice{ {DestChainSelector: defaultSourceChainSelector, Value: val1e18(2)}, + {DestChainSelector: defaultSourceChainSelector + 1, Value: val1e18(22)}, {DestChainSelector: defaultSourceChainSelector + 2, Value: val1e18(222)}, }, }, + { + name: "multi-chain gas prices but only one updates due to deviation", + commitObservations: []ccip.CommitObservation{ + {SourceGasPriceUSDPerChain: map[uint64]*big.Int{defaultSourceChainSelector: val1e18(1)}}, + {SourceGasPriceUSDPerChain: map[uint64]*big.Int{defaultSourceChainSelector + 1: val1e18(11)}}, + {SourceGasPriceUSDPerChain: map[uint64]*big.Int{defaultSourceChainSelector + 2: val1e18(111)}}, + {SourceGasPriceUSDPerChain: map[uint64]*big.Int{defaultSourceChainSelector: val1e18(2)}}, + {SourceGasPriceUSDPerChain: map[uint64]*big.Int{defaultSourceChainSelector + 1: val1e18(22)}}, + {SourceGasPriceUSDPerChain: map[uint64]*big.Int{defaultSourceChainSelector + 2: val1e18(222)}}, + {SourceGasPriceUSDPerChain: map[uint64]*big.Int{defaultSourceChainSelector: val1e18(3)}}, + {SourceGasPriceUSDPerChain: map[uint64]*big.Int{defaultSourceChainSelector + 1: val1e18(33)}}, + {SourceGasPriceUSDPerChain: map[uint64]*big.Int{defaultSourceChainSelector + 2: val1e18(333)}}, + }, + gasPriceHeartBeat: *config.MustNewDuration(time.Hour), + daGasPriceDeviationPPB: 20e7, + execGasPriceDeviationPPB: 20e7, + tokenPriceHeartBeat: *config.MustNewDuration(time.Hour), + tokenPriceDeviationPPB: 20e7, + latestGasPrice: map[uint64]update{ + defaultSourceChainSelector: { + timestamp: time.Now().Add(-30 * time.Minute), // recent + value: val1e18(9), // median deviates + }, + defaultSourceChainSelector + 1: { + timestamp: time.Now().Add(-30 * time.Minute), // recent + value: val1e18(20), // median does not deviate + }, + defaultSourceChainSelector + 2: { + timestamp: time.Now().Add(-30 * time.Minute), // recent + value: val1e18(220), // median does not deviate + }, + }, + f: 1, + expGasUpdates: []cciptypes.GasPrice{ + {DestChainSelector: defaultSourceChainSelector, Value: val1e18(2)}, + }, + }, { name: "median one token", commitObservations: []ccip.CommitObservation{ @@ -1204,14 +1241,14 @@ func TestCommitReportingPlugin_calculatePriceUpdates(t *testing.T) { expGasUpdates: []cciptypes.GasPrice{{DestChainSelector: defaultSourceChainSelector, Value: big.NewInt(0)}}, }, { - name: "token price update skipped because it is close to the latest", + name: "token price update skipped because it does not deviate and are recent", commitObservations: []ccip.CommitObservation{ { - TokenPricesUSD: map[cciptypes.Address]*big.Int{feeToken1: val1e18(11)}, + TokenPricesUSD: map[cciptypes.Address]*big.Int{feeToken1: val1e18(11), feeToken2: val1e18(11)}, SourceGasPriceUSDPerChain: map[uint64]*big.Int{defaultSourceChainSelector: val1e18(0)}, }, { - TokenPricesUSD: map[cciptypes.Address]*big.Int{feeToken1: val1e18(12)}, + TokenPricesUSD: map[cciptypes.Address]*big.Int{feeToken1: val1e18(12), feeToken2: val1e18(12)}, SourceGasPriceUSDPerChain: map[uint64]*big.Int{defaultSourceChainSelector: val1e18(0)}, }, }, @@ -1226,10 +1263,81 @@ func TestCommitReportingPlugin_calculatePriceUpdates(t *testing.T) { timestamp: time.Now().Add(-30 * time.Minute), value: val1e18(10), }, + feeToken2: { + timestamp: time.Now().Add(-30 * time.Minute), + value: val1e18(10), + }, }, // We expect a gas update because no latest expGasUpdates: []cciptypes.GasPrice{{DestChainSelector: defaultSourceChainSelector, Value: big.NewInt(0)}}, }, + { + name: "multiple token price update due to staleness", + commitObservations: []ccip.CommitObservation{ + { + TokenPricesUSD: map[cciptypes.Address]*big.Int{feeToken1: val1e18(11), feeToken2: val1e18(11)}, + SourceGasPriceUSDPerChain: map[uint64]*big.Int{defaultSourceChainSelector: val1e18(0)}, + }, + { + TokenPricesUSD: map[cciptypes.Address]*big.Int{feeToken1: val1e18(12), feeToken2: val1e18(12)}, + SourceGasPriceUSDPerChain: map[uint64]*big.Int{defaultSourceChainSelector: val1e18(0)}, + }, + }, + f: 1, + gasPriceHeartBeat: *config.MustNewDuration(time.Hour), + daGasPriceDeviationPPB: 20e7, + execGasPriceDeviationPPB: 20e7, + tokenPriceHeartBeat: *config.MustNewDuration(time.Hour), + tokenPriceDeviationPPB: 20e7, + latestTokenPrices: map[cciptypes.Address]update{ + feeToken1: { + timestamp: time.Now().Add(-90 * time.Minute), + value: val1e18(10), + }, + feeToken2: { + timestamp: time.Now().Add(-30 * time.Minute), + value: val1e18(10), + }, + }, + expTokenUpdates: []cciptypes.TokenPrice{ + {Token: feeToken1, Value: val1e18(12)}, + {Token: feeToken2, Value: val1e18(12)}, + }, + expGasUpdates: []cciptypes.GasPrice{{DestChainSelector: defaultSourceChainSelector, Value: big.NewInt(0)}}, + }, + { + name: "multiple token exist but only one updates due to deviation", + commitObservations: []ccip.CommitObservation{ + { + TokenPricesUSD: map[cciptypes.Address]*big.Int{feeToken1: val1e18(11), feeToken2: val1e18(13)}, + SourceGasPriceUSDPerChain: map[uint64]*big.Int{defaultSourceChainSelector: val1e18(0)}, + }, + { + TokenPricesUSD: map[cciptypes.Address]*big.Int{feeToken1: val1e18(12), feeToken2: val1e18(14)}, + SourceGasPriceUSDPerChain: map[uint64]*big.Int{defaultSourceChainSelector: val1e18(0)}, + }, + }, + f: 1, + gasPriceHeartBeat: *config.MustNewDuration(time.Hour), + daGasPriceDeviationPPB: 20e7, + execGasPriceDeviationPPB: 20e7, + tokenPriceHeartBeat: *config.MustNewDuration(time.Hour), + tokenPriceDeviationPPB: 20e7, + latestTokenPrices: map[cciptypes.Address]update{ + feeToken1: { + timestamp: time.Now().Add(-30 * time.Minute), + value: val1e18(10), + }, + feeToken2: { + timestamp: time.Now().Add(-30 * time.Minute), + value: val1e18(10), + }, + }, + expTokenUpdates: []cciptypes.TokenPrice{ + {Token: feeToken2, Value: val1e18(14)}, + }, + expGasUpdates: []cciptypes.GasPrice{{DestChainSelector: defaultSourceChainSelector, Value: big.NewInt(0)}}, + }, { name: "gas price and token price both included because they are not close to the latest", commitObservations: []ccip.CommitObservation{ @@ -1330,12 +1438,18 @@ func TestCommitReportingPlugin_calculatePriceUpdates(t *testing.T) { name: "gas price included because it deviates from latest and token price skipped because it does not deviate", commitObservations: []ccip.CommitObservation{ { - TokenPricesUSD: map[cciptypes.Address]*big.Int{feeToken1: val1e18(20)}, - SourceGasPriceUSDPerChain: map[uint64]*big.Int{defaultSourceChainSelector: val1e18(10)}, + TokenPricesUSD: map[cciptypes.Address]*big.Int{feeToken1: val1e18(20)}, + SourceGasPriceUSDPerChain: map[uint64]*big.Int{ + defaultSourceChainSelector: val1e18(10), + defaultSourceChainSelector + 1: val1e18(20), + }, }, { - TokenPricesUSD: map[cciptypes.Address]*big.Int{feeToken1: val1e18(21)}, - SourceGasPriceUSDPerChain: map[uint64]*big.Int{defaultSourceChainSelector: val1e18(11)}, + TokenPricesUSD: map[cciptypes.Address]*big.Int{feeToken1: val1e18(21)}, + SourceGasPriceUSDPerChain: map[uint64]*big.Int{ + defaultSourceChainSelector: val1e18(11), + defaultSourceChainSelector + 1: val1e18(21), + }, }, }, f: 1, @@ -1346,8 +1460,12 @@ func TestCommitReportingPlugin_calculatePriceUpdates(t *testing.T) { tokenPriceDeviationPPB: 200e7, latestGasPrice: map[uint64]update{ defaultSourceChainSelector: { - timestamp: time.Now().Add(-90 * time.Minute), - value: val1e18(9), + timestamp: time.Now().Add(-30 * time.Minute), + value: val1e18(8), + }, + defaultSourceChainSelector + 1: { + timestamp: time.Now().Add(-30 * time.Minute), + value: val1e18(21), }, }, latestTokenPrices: map[cciptypes.Address]update{ @@ -1362,11 +1480,11 @@ func TestCommitReportingPlugin_calculatePriceUpdates(t *testing.T) { name: "gas price skipped because it does not deviate and token price included because it has not been updated recently", commitObservations: []ccip.CommitObservation{ { - TokenPricesUSD: map[cciptypes.Address]*big.Int{feeToken1: val1e18(20)}, + TokenPricesUSD: map[cciptypes.Address]*big.Int{feeToken1: val1e18(10), feeToken2: val1e18(20)}, SourceGasPriceUSDPerChain: map[uint64]*big.Int{defaultSourceChainSelector: val1e18(10)}, }, { - TokenPricesUSD: map[cciptypes.Address]*big.Int{feeToken1: val1e18(21)}, + TokenPricesUSD: map[cciptypes.Address]*big.Int{feeToken1: val1e18(11), feeToken2: val1e18(21)}, SourceGasPriceUSDPerChain: map[uint64]*big.Int{defaultSourceChainSelector: val1e18(11)}, }, }, @@ -1385,11 +1503,16 @@ func TestCommitReportingPlugin_calculatePriceUpdates(t *testing.T) { latestTokenPrices: map[cciptypes.Address]update{ feeToken1: { timestamp: time.Now().Add(-4 * time.Hour), + value: val1e18(11), + }, + feeToken2: { + timestamp: time.Now().Add(-1 * time.Hour), value: val1e18(21), }, }, expTokenUpdates: []cciptypes.TokenPrice{ - {Token: feeToken1, Value: val1e18(21)}, + {Token: feeToken1, Value: val1e18(11)}, + {Token: feeToken2, Value: val1e18(21)}, }, expGasUpdates: nil, }, @@ -1408,6 +1531,7 @@ func TestCommitReportingPlugin_calculatePriceUpdates(t *testing.T) { nil, tc.daGasPriceDeviationPPB, tc.execGasPriceDeviationPPB, + ccipdatamocks.NewFeeEstimatorConfigReader(t), ) r := &CommitReportingPlugin{ diff --git a/core/services/ocr2/plugins/ccip/ccipexec/batching.go b/core/services/ocr2/plugins/ccip/ccipexec/batching.go index 866a20c4cde..f1beb035d32 100644 --- a/core/services/ocr2/plugins/ccip/ccipexec/batching.go +++ b/core/services/ocr2/plugins/ccip/ccipexec/batching.go @@ -24,6 +24,12 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/statuschecker" ) +// Batching strategies +const ( + BestEffortBatchingStrategyID = uint32(0) + ZKOverflowBatchingStrategyID = uint32(1) +) + type BatchContext struct { report commitReportWithSendRequests inflight []InflightInternalExecutionReport @@ -47,6 +53,7 @@ type BatchContext struct { type BatchingStrategy interface { BuildBatch(ctx context.Context, batchCtx *BatchContext) ([]ccip.ObservedMessage, []messageExecStatus) + GetBatchingStrategyID() uint32 } type BestEffortBatchingStrategy struct{} @@ -58,9 +65,9 @@ type ZKOverflowBatchingStrategy struct { func NewBatchingStrategy(batchingStrategyID uint32, statusChecker statuschecker.CCIPTransactionStatusChecker) (BatchingStrategy, error) { var batchingStrategy BatchingStrategy switch batchingStrategyID { - case 0: + case BestEffortBatchingStrategyID: batchingStrategy = &BestEffortBatchingStrategy{} - case 1: + case ZKOverflowBatchingStrategyID: batchingStrategy = &ZKOverflowBatchingStrategy{ statuschecker: statusChecker, } @@ -70,6 +77,10 @@ func NewBatchingStrategy(batchingStrategyID uint32, statusChecker statuschecker. return batchingStrategy, nil } +func (s *BestEffortBatchingStrategy) GetBatchingStrategyID() uint32 { + return BestEffortBatchingStrategyID +} + // BestEffortBatchingStrategy is a batching strategy that tries to batch as many messages as possible (up to certain limits). func (s *BestEffortBatchingStrategy) BuildBatch( ctx context.Context, @@ -95,6 +106,10 @@ func (s *BestEffortBatchingStrategy) BuildBatch( return batchBuilder.batch, batchBuilder.statuses } +func (bs *ZKOverflowBatchingStrategy) GetBatchingStrategyID() uint32 { + return ZKOverflowBatchingStrategyID +} + // ZKOverflowBatchingStrategy is a batching strategy for ZK chains overflowing under certain conditions. // It is a simple batching strategy that only allows one message to be added to the batch. // TXM is used to perform the ZK check: if the message failed the check, it will be skipped. diff --git a/core/services/ocr2/plugins/ccip/ccipexec/batching_test.go b/core/services/ocr2/plugins/ccip/ccipexec/batching_test.go index 0fd23496974..e57bc3aa86e 100644 --- a/core/services/ocr2/plugins/ccip/ccipexec/batching_test.go +++ b/core/services/ocr2/plugins/ccip/ccipexec/batching_test.go @@ -850,13 +850,13 @@ func runBatchingStrategyTests(t *testing.T, strategy BatchingStrategy, available seqNrs, execStates := strategy.BuildBatch(context.Background(), batchContext) - runAssertions(t, tc, seqNrs, execStates) + runAssertions(t, tc, seqNrs, execStates, strategy) }) } } // Utility function to run common assertions -func runAssertions(t *testing.T, tc testCase, seqNrs []ccip.ObservedMessage, execStates []messageExecStatus) { +func runAssertions(t *testing.T, tc testCase, seqNrs []ccip.ObservedMessage, execStates []messageExecStatus, strategy BatchingStrategy) { if tc.expectedSeqNrs == nil { assert.Len(t, seqNrs, 0) } else { @@ -868,6 +868,13 @@ func runAssertions(t *testing.T, tc testCase, seqNrs []ccip.ObservedMessage, exe } else { assert.Equal(t, tc.expectedStates, execStates) } + + batchingStratID := strategy.GetBatchingStrategyID() + if strategyType := reflect.TypeOf(strategy); strategyType == reflect.TypeOf(&BestEffortBatchingStrategy{}) { + assert.Equal(t, uint32(0), batchingStratID) + } else { + assert.Equal(t, uint32(1), batchingStratID) + } } func createTestMessage(seqNr uint64, sender cciptypes.Address, nonce uint64, feeToken cciptypes.Address, feeAmount *big.Int, executed bool, data []byte) cciptypes.EVM2EVMOnRampCCIPSendRequestedWithMeta { diff --git a/core/services/ocr2/plugins/ccip/ccipexec/factory.go b/core/services/ocr2/plugins/ccip/ccipexec/factory.go index 646121bdba8..20fe65b81a9 100644 --- a/core/services/ocr2/plugins/ccip/ccipexec/factory.go +++ b/core/services/ocr2/plugins/ccip/ccipexec/factory.go @@ -71,8 +71,11 @@ type reportingPluginAndInfo struct { func (rf *ExecutionReportingPluginFactory) NewReportingPlugin(ctx context.Context, config types.ReportingPluginConfig) (types.ReportingPlugin, types.ReportingPluginInfo, error) { initialRetryDelay := rf.config.newReportingPluginRetryConfig.InitialDelay maxDelay := rf.config.newReportingPluginRetryConfig.MaxDelay + maxRetries := rf.config.newReportingPluginRetryConfig.MaxRetries - pluginAndInfo, err := ccipcommon.RetryUntilSuccess(rf.NewReportingPluginFn(ctx, config), initialRetryDelay, maxDelay) + pluginAndInfo, err := ccipcommon.RetryUntilSuccess( + rf.NewReportingPluginFn(ctx, config), initialRetryDelay, maxDelay, maxRetries, + ) if err != nil { return nil, types.ReportingPluginInfo{}, err } @@ -83,7 +86,7 @@ func (rf *ExecutionReportingPluginFactory) NewReportingPlugin(ctx context.Contex // retried via RetryUntilSuccess. NewReportingPlugin must return successfully in order for the Exec plugin to function, // hence why we can only keep retrying it until it succeeds. func (rf *ExecutionReportingPluginFactory) NewReportingPluginFn(ctx context.Context, config types.ReportingPluginConfig) func() (reportingPluginAndInfo, error) { - return func() (reportingPluginAndInfo, error) { + newReportingPluginFn := func() (reportingPluginAndInfo, error) { destPriceRegistry, destWrappedNative, err := rf.config.offRampReader.ChangeConfig(ctx, config.OnchainConfig, config.OffchainConfig) if err != nil { return reportingPluginAndInfo{}, err @@ -159,4 +162,14 @@ func (rf *ExecutionReportingPluginFactory) NewReportingPluginFn(ctx context.Cont return reportingPluginAndInfo{plugin, pluginInfo}, nil } + + return func() (reportingPluginAndInfo, error) { + result, err := newReportingPluginFn() + if err != nil { + rf.config.lggr.Errorw("NewReportingPlugin failed", "err", err) + rf.config.metricsCollector.NewReportingPluginError() + } + + return result, err + } } diff --git a/core/services/ocr2/plugins/ccip/ccipexec/factory_test.go b/core/services/ocr2/plugins/ccip/ccipexec/factory_test.go index fe5e0ab1e23..a5df4c356ce 100644 --- a/core/services/ocr2/plugins/ccip/ccipexec/factory_test.go +++ b/core/services/ocr2/plugins/ccip/ccipexec/factory_test.go @@ -12,6 +12,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink/v2/core/logger" + ccip2 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" ccipdataprovidermocks "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/ccipdataprovider/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks" @@ -25,6 +26,8 @@ import ( func TestNewReportingPluginRetriesUntilSuccess(t *testing.T) { ctx := tests.Context(t) execConfig := ExecutionPluginStaticConfig{} + execConfig.lggr = logger.TestLogger(t) + execConfig.metricsCollector = ccip2.NoopMetricsCollector // For this unit test, ensure that there is no delay between retries execConfig.newReportingPluginRetryConfig = ccipdata.RetryConfig{ diff --git a/core/services/ocr2/plugins/ccip/ccipexec/gashelpers_test.go b/core/services/ocr2/plugins/ccip/ccipexec/gashelpers_test.go index afcd580e24b..42a62a1be99 100644 --- a/core/services/ocr2/plugins/ccip/ccipexec/gashelpers_test.go +++ b/core/services/ocr2/plugins/ccip/ccipexec/gashelpers_test.go @@ -168,12 +168,6 @@ func TestWaitBoostedFee(t *testing.T) { boosted := waitBoostedFee(tc.sendTimeDiff, tc.fee, tc.relativeBoostPerWaitHour) diff := big.NewInt(0).Sub(boosted, tc.fee) assert.Equal(t, diff, tc.diff) - // we check that the actual diff is approximately equals to expected diff, - // as we might get slightly different results locally vs. CI therefore normal Equal() would be unstable - // diffUpperLimit := big.NewInt(0).Add(tc.diff, big.NewInt(1e9)) - //diffLowerLimit := big.NewInt(0).Add(tc.diff, big.NewInt(-1e9)) - //require.Equalf(t, -1, diff.Cmp(diffUpperLimit), "actual diff (%s) is larger than expected (%s)", diff.String(), diffUpperLimit.String()) - //require.Equal(t, 1, diff.Cmp(diffLowerLimit), "actual diff (%s) is smaller than expected (%s)", diff.String(), diffLowerLimit.String()) }) } } diff --git a/core/services/ocr2/plugins/ccip/ccipexec/initializers.go b/core/services/ocr2/plugins/ccip/ccipexec/initializers.go index 7826f6058fe..3ad9c94dc74 100644 --- a/core/services/ocr2/plugins/ccip/ccipexec/initializers.go +++ b/core/services/ocr2/plugins/ccip/ccipexec/initializers.go @@ -18,8 +18,6 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/cache" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcalc" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/statuschecker" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" @@ -27,6 +25,8 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip" ccipconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/cache" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcalc" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/factory" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/observability" @@ -43,10 +43,18 @@ var ( // 5s for token data worker timeout is a reasonable default. tokenDataWorkerTimeout = 5 * time.Second // tokenDataWorkerNumWorkers is the number of workers that will be processing token data in parallel. - tokenDataWorkerNumWorkers = 5 + tokenDataWorkerNumWorkers = 10 + // expirationDur is the duration for which the token data will be cached. + expirationDurTokenData = 10 * time.Minute ) -var defaultNewReportingPluginRetryConfig = ccipdata.RetryConfig{InitialDelay: time.Second, MaxDelay: 5 * time.Minute} +var defaultNewReportingPluginRetryConfig = ccipdata.RetryConfig{ + InitialDelay: time.Second, + MaxDelay: 10 * time.Minute, + // Retry for approximately 4hrs (MaxDelay of 10m = 6 times per hour, times 4 hours, plus 10 because the first + // 10 retries only take 20 minutes due to an initial retry of 1s and exponential backoff) + MaxRetries: (6 * 4) + 10, +} func NewExecServices(ctx context.Context, lggr logger.Logger, jb job.Job, srcProvider types.CCIPExecProvider, dstProvider types.CCIPExecProvider, srcChainID int64, dstChainID int64, new bool, argsNoPlugin libocr2.OCR2OracleArgs, logError func(string)) ([]job.ServiceCtx, error) { if jb.OCR2OracleSpec == nil { @@ -115,6 +123,20 @@ func NewExecServices(ctx context.Context, lggr logger.Logger, jb job.Job, srcPro } tokenDataProviders[cciptypes.Address(pluginConfig.USDCConfig.SourceTokenAddress.String())] = usdcReader } + // init lbtc token data provider + if pluginConfig.LBTCConfig.AttestationAPI != "" { + lggr.Infof("LBTC token data provider enabled") + err2 := pluginConfig.LBTCConfig.ValidateLBTCConfig() + if err2 != nil { + return nil, err2 + } + + lbtcReader, err2 := srcProvider.NewTokenDataReader(ctx, ccip.EvmAddrToGeneric(pluginConfig.LBTCConfig.SourceTokenAddress)) + if err2 != nil { + return nil, fmt.Errorf("new lbtc reader: %w", err2) + } + tokenDataProviders[cciptypes.Address(pluginConfig.LBTCConfig.SourceTokenAddress.String())] = lbtcReader + } // Prom wrappers onRampReader = observability.NewObservedOnRampReader(onRampReader, srcChainID, ccip.ExecPluginLabel) @@ -149,7 +171,7 @@ func NewExecServices(ctx context.Context, lggr logger.Logger, jb job.Job, srcPro tokenDataProviders, tokenDataWorkerNumWorkers, tokenDataWorkerTimeout, - 2*tokenDataWorkerTimeout, + expirationDurTokenData, ) wrappedPluginFactory := NewExecutionReportingPluginFactory(ExecutionPluginStaticConfig{ diff --git a/core/services/ocr2/plugins/ccip/ccipexec/ocr2.go b/core/services/ocr2/plugins/ccip/ccipexec/ocr2.go index 4a09cf37b45..2c70cac4978 100644 --- a/core/services/ocr2/plugins/ccip/ccipexec/ocr2.go +++ b/core/services/ocr2/plugins/ccip/ccipexec/ocr2.go @@ -468,6 +468,19 @@ func (r *ExecutionReportingPlugin) buildReport(ctx context.Context, lggr logger. return encodedReport, nil } +// Returns required number of observations to reach consensus +func (r *ExecutionReportingPlugin) getConsensusThreshold() int { + // Default consensus threshold is F+1 + consensusThreshold := r.F + 1 + if r.batchingStrategy.GetBatchingStrategyID() == ZKOverflowBatchingStrategyID { + // For batching strategy 1, consensus threshold is 2F+1 + // This is because chains that can overflow need to reach consensus during the inflight cache period + // to avoid 2 transmissions round of an overflown message. + consensusThreshold = 2*r.F + 1 + } + return consensusThreshold +} + func (r *ExecutionReportingPlugin) Report(ctx context.Context, timestamp types.ReportTimestamp, query types.Query, observations []types.AttributedObservation) (bool, types.Report, error) { lggr := r.lggr.Named("ExecutionReport") if healthy, err := r.chainHealthcheck.IsHealthy(ctx); err != nil { @@ -475,14 +488,16 @@ func (r *ExecutionReportingPlugin) Report(ctx context.Context, timestamp types.R } else if !healthy { return false, nil, ccip.ErrChainIsNotHealthy } + consensusThreshold := r.getConsensusThreshold() + lggr.Infof("Consensus threshold set to: %d", consensusThreshold) + parsableObservations := ccip.GetParsableObservations[ccip.ExecutionObservation](lggr, observations) - // Need at least F+1 observations - if len(parsableObservations) <= r.F { - lggr.Warn("Non-empty observations <= F, need at least F+1 to continue") + if len(parsableObservations) < consensusThreshold { + lggr.Warnf("Insufficient observations: only %d received, but need more than %d to proceed", len(parsableObservations), consensusThreshold) return false, nil, nil } - observedMessages, err := calculateObservedMessagesConsensus(parsableObservations, r.F) + observedMessages, err := calculateObservedMessagesConsensus(parsableObservations, consensusThreshold) if err != nil { return false, nil, err } diff --git a/core/services/ocr2/plugins/ccip/ccipexec/ocr2_test.go b/core/services/ocr2/plugins/ccip/ccipexec/ocr2_test.go index ff6371fa2ce..73a1f431399 100644 --- a/core/services/ocr2/plugins/ccip/ccipexec/ocr2_test.go +++ b/core/services/ocr2/plugins/ccip/ccipexec/ocr2_test.go @@ -16,17 +16,18 @@ import ( mapset "github.com/deckarep/golang-set/v2" "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" - "github.com/smartcontractkit/libocr/commontypes" - "github.com/smartcontractkit/libocr/offchainreporting2/types" - ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" + "github.com/smartcontractkit/libocr/commontypes" + "github.com/smartcontractkit/libocr/offchainreporting2/types" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" lpMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/cache" @@ -40,8 +41,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/prices" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/tokendata" - - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/statuschecker" ) func TestExecutionReportingPlugin_Observation(t *testing.T) { @@ -232,19 +232,21 @@ func TestExecutionReportingPlugin_Observation(t *testing.T) { func TestExecutionReportingPlugin_Report(t *testing.T) { testCases := []struct { - name string - f int - committedSeqNum uint64 - observations []ccip.ExecutionObservation + name string + f int + batchingStrategyID uint32 + committedSeqNum uint64 + observations []ccip.ExecutionObservation expectingSomeReport bool expectedReport cciptypes.ExecReport expectingSomeErr bool }{ { - name: "not enough observations to form consensus", - f: 5, - committedSeqNum: 5, + name: "not enough observations to form consensus - best effort batching", + f: 5, + batchingStrategyID: 0, + committedSeqNum: 5, observations: []ccip.ExecutionObservation{ {Messages: map[uint64]ccip.MsgData{3: {}, 4: {}}}, {Messages: map[uint64]ccip.MsgData{3: {}, 4: {}}}, @@ -252,6 +254,21 @@ func TestExecutionReportingPlugin_Report(t *testing.T) { expectingSomeErr: false, expectingSomeReport: false, }, + { + name: "not enough observaitons to form consensus - zk batching", + f: 5, + batchingStrategyID: 1, + committedSeqNum: 5, + observations: []ccip.ExecutionObservation{ + {Messages: map[uint64]ccip.MsgData{3: {}, 4: {}}}, + {Messages: map[uint64]ccip.MsgData{3: {}, 4: {}}}, + {Messages: map[uint64]ccip.MsgData{3: {}, 4: {}}}, + {Messages: map[uint64]ccip.MsgData{3: {}, 4: {}}}, + {Messages: map[uint64]ccip.MsgData{3: {}, 4: {}}}, + {Messages: map[uint64]ccip.MsgData{3: {}, 4: {}}}, + {Messages: map[uint64]ccip.MsgData{3: {}, 4: {}}}, + }, + }, { name: "zero observations", f: 0, @@ -268,6 +285,9 @@ func TestExecutionReportingPlugin_Report(t *testing.T) { p := ExecutionReportingPlugin{} p.lggr = logger.TestLogger(t) p.F = tc.f + bs, err := NewBatchingStrategy(tc.batchingStrategyID, &statuschecker.TxmStatusChecker{}) + require.NoError(t, err) + p.batchingStrategy = bs p.commitStoreReader = ccipdatamocks.NewCommitStoreReader(t) chainHealthcheck := ccipcachemocks.NewChainHealthcheck(t) @@ -281,12 +301,12 @@ func TestExecutionReportingPlugin_Report(t *testing.T) { observations[i] = types.AttributedObservation{Observation: b, Observer: commontypes.OracleID(i + 1)} } - _, _, err := p.Report(ctx, types.ReportTimestamp{}, types.Query{}, observations) + _, _, err2 := p.Report(ctx, types.ReportTimestamp{}, types.Query{}, observations) if tc.expectingSomeErr { - assert.Error(t, err) + assert.Error(t, err2) return } - assert.NoError(t, err) + assert.NoError(t, err2) }) } } @@ -427,8 +447,10 @@ func TestExecutionReportingPlugin_buildReport(t *testing.T) { p.metricsCollector = ccip.NoopMetricsCollector p.commitStoreReader = commitStore + feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) + lp := lpMocks.NewLogPoller(t) - offRampReader, err := v1_2_0.NewOffRamp(logger.TestLogger(t), utils.RandomAddress(), nil, lp, nil, nil) + offRampReader, err := v1_2_0.NewOffRamp(logger.TestLogger(t), utils.RandomAddress(), nil, lp, nil, nil, feeEstimatorConfig) assert.NoError(t, err) p.offRampReader = offRampReader @@ -1375,7 +1397,9 @@ func Test_prepareTokenExecData(t *testing.T) { } func encodeExecutionReport(t *testing.T, report cciptypes.ExecReport) []byte { - reader, err := v1_2_0.NewOffRamp(logger.TestLogger(t), utils.RandomAddress(), nil, nil, nil, nil) + feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) + + reader, err := v1_2_0.NewOffRamp(logger.TestLogger(t), utils.RandomAddress(), nil, nil, nil, nil, feeEstimatorConfig) require.NoError(t, err) ctx := testutils.Context(t) encodedReport, err := reader.EncodeExecutionReport(ctx, report) @@ -1418,3 +1442,36 @@ func TestExecutionReportingPlugin_ensurePriceRegistrySynchronization(t *testing. require.NoError(t, err) require.Equal(t, mockPriceRegistryReader2, p.sourcePriceRegistry) } + +func TestExecutionReportingPlugin_getConsensusThreshold(t *testing.T) { + tests := []struct { + name string + batchingStrategyID uint32 + F int + expectedConsensusThreshold int + }{ + { + name: "zk batching strategy", + batchingStrategyID: uint32(1), + F: 5, + expectedConsensusThreshold: 11, + }, + { + name: "default batching strategy", + batchingStrategyID: uint32(0), + F: 5, + expectedConsensusThreshold: 6, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + p := &ExecutionReportingPlugin{} + p.F = tc.F + bs, err := NewBatchingStrategy(tc.batchingStrategyID, &statuschecker.TxmStatusChecker{}) + require.NoError(t, err) + p.batchingStrategy = bs + require.Equal(t, tc.expectedConsensusThreshold, p.getConsensusThreshold()) + }) + } +} diff --git a/core/services/ocr2/plugins/ccip/clo_ccip_integration_test.go b/core/services/ocr2/plugins/ccip/clo_ccip_integration_test.go index daac8cc37f9..52eb15c77d2 100644 --- a/core/services/ocr2/plugins/ccip/clo_ccip_integration_test.go +++ b/core/services/ocr2/plugins/ccip/clo_ccip_integration_test.go @@ -22,6 +22,7 @@ import ( ) func Test_CLOSpecApprovalFlow_pipeline(t *testing.T) { + t.Parallel() ccipTH := integrationtesthelpers.SetupCCIPIntegrationTH( t, testhelpers.SourceChainID, @@ -40,6 +41,7 @@ func Test_CLOSpecApprovalFlow_pipeline(t *testing.T) { } func Test_CLOSpecApprovalFlow_dynamicPriceGetter(t *testing.T) { + t.Parallel() ccipTH := integrationtesthelpers.SetupCCIPIntegrationTH( t, testhelpers.SourceChainID, diff --git a/core/services/ocr2/plugins/ccip/config/config.go b/core/services/ocr2/plugins/ccip/config/config.go index a24a6edfd13..fbf8d590cfe 100644 --- a/core/services/ocr2/plugins/ccip/config/config.go +++ b/core/services/ocr2/plugins/ccip/config/config.go @@ -108,6 +108,7 @@ func (c *DynamicPriceGetterConfig) Validate() error { type ExecPluginJobSpecConfig struct { SourceStartBlock, DestStartBlock uint64 // Only for first time job add. USDCConfig USDCConfig + LBTCConfig LBTCConfig } type USDCConfig struct { @@ -119,10 +120,19 @@ type USDCConfig struct { AttestationAPIIntervalMilliseconds int } +type LBTCConfig struct { + SourceTokenAddress common.Address + AttestationAPI string + AttestationAPITimeoutSeconds uint + // AttestationAPIIntervalMilliseconds can be set to -1 to disable or 0 to use a default interval. + AttestationAPIIntervalMilliseconds int +} + type ExecPluginConfig struct { SourceStartBlock, DestStartBlock uint64 // Only for first time job add. IsSourceProvider bool USDCConfig USDCConfig + LBTCConfig LBTCConfig JobID string } @@ -136,17 +146,30 @@ func (e ExecPluginConfig) Encode() ([]byte, error) { func (uc *USDCConfig) ValidateUSDCConfig() error { if uc.AttestationAPI == "" { - return errors.New("AttestationAPI is required") + return errors.New("USDCConfig: AttestationAPI is required") } if uc.AttestationAPIIntervalMilliseconds < -1 { - return errors.New("AttestationAPIIntervalMilliseconds must be -1 to disable, 0 for default or greater to define the exact interval") + return errors.New("USDCConfig: AttestationAPIIntervalMilliseconds must be -1 to disable, 0 for default or greater to define the exact interval") } if uc.SourceTokenAddress == utils.ZeroAddress { - return errors.New("SourceTokenAddress is required") + return errors.New("USDCConfig: SourceTokenAddress is required") } if uc.SourceMessageTransmitterAddress == utils.ZeroAddress { - return errors.New("SourceMessageTransmitterAddress is required") + return errors.New("USDCConfig: SourceMessageTransmitterAddress is required") } return nil } + +func (lc *LBTCConfig) ValidateLBTCConfig() error { + if lc.AttestationAPI == "" { + return errors.New("LBTCConfig: AttestationAPI is required") + } + if lc.AttestationAPIIntervalMilliseconds < -1 { + return errors.New("LBTCConfig: AttestationAPIIntervalMilliseconds must be -1 to disable, 0 for default or greater to define the exact interval") + } + if lc.SourceTokenAddress == utils.ZeroAddress { + return errors.New("LBTCConfig: SourceTokenAddress is required") + } + return nil +} diff --git a/core/services/ocr2/plugins/ccip/config/type_and_version.go b/core/services/ocr2/plugins/ccip/config/type_and_version.go index fdfd892b087..ecfe8d0c5a7 100644 --- a/core/services/ocr2/plugins/ccip/config/type_and_version.go +++ b/core/services/ocr2/plugins/ccip/config/type_and_version.go @@ -9,7 +9,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" - type_and_version "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/type_and_version_interface_wrapper" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/type_and_version" ) type ContractType string @@ -19,6 +19,7 @@ var ( EVM2EVMOffRamp ContractType = "EVM2EVMOffRamp" CommitStore ContractType = "CommitStore" PriceRegistry ContractType = "PriceRegistry" + Unknown ContractType = "Unknown" // 1.0.0 Contracts which have no TypeAndVersion ContractTypes = mapset.NewSet[ContractType]( EVM2EVMOffRamp, EVM2EVMOnRamp, @@ -39,7 +40,7 @@ func VerifyTypeAndVersion(addr common.Address, client bind.ContractBackend, expe } func TypeAndVersion(addr common.Address, client bind.ContractBackend) (ContractType, semver.Version, error) { - tv, err := type_and_version.NewTypeAndVersionInterface(addr, client) + tv, err := type_and_version.NewITypeAndVersion(addr, client) if err != nil { return "", semver.Version{}, err } @@ -63,7 +64,13 @@ func TypeAndVersion(addr common.Address, client bind.ContractBackend) (ContractT return ContractType(contractType), *v, nil } +// default version to use when TypeAndVersion is missing. +const defaultVersion = "1.0.0" + func ParseTypeAndVersion(tvStr string) (string, string, error) { + if tvStr == "" { + tvStr = string(Unknown) + " " + defaultVersion + } typeAndVersionValues := strings.Split(tvStr, " ") if len(typeAndVersionValues) < 2 { diff --git a/core/services/ocr2/plugins/ccip/config/type_and_version_test.go b/core/services/ocr2/plugins/ccip/config/type_and_version_test.go new file mode 100644 index 00000000000..807bb59f3be --- /dev/null +++ b/core/services/ocr2/plugins/ccip/config/type_and_version_test.go @@ -0,0 +1,50 @@ +package config + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestParseTypeAndVersion(t *testing.T) { + tests := []struct { + name string + input string + expectedType string + expectedVersion string + expectedError string + }{ + { + name: "Valid input", + input: string(EVM2EVMOnRamp) + " 1.2.0", + expectedType: string(EVM2EVMOnRamp), + expectedVersion: "1.2.0", + }, + { + name: "Empty input", + input: "", + expectedType: string(Unknown), + expectedVersion: defaultVersion, + }, + { + name: "Invalid input", + input: "InvalidInput", + expectedError: "invalid type and version InvalidInput", + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + actualType, actualVersion, err := ParseTypeAndVersion(tc.input) + + if tc.expectedError != "" { + require.EqualError(t, err, tc.expectedError) + } else { + require.NoError(t, err) + assert.Equal(t, tc.expectedType, actualType) + assert.Equal(t, tc.expectedVersion, actualVersion) + } + }) + } +} diff --git a/core/services/ocr2/plugins/ccip/estimatorconfig/config.go b/core/services/ocr2/plugins/ccip/estimatorconfig/config.go new file mode 100644 index 00000000000..4737bd33e89 --- /dev/null +++ b/core/services/ocr2/plugins/ccip/estimatorconfig/config.go @@ -0,0 +1,83 @@ +package estimatorconfig + +import ( + "context" + "math/big" + + "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" +) + +// FeeEstimatorConfigProvider implements abstract storage for the DataAvailability settings in onRamp dynamic Config. +// It's implemented to transfer DA config from different entities offRamp, onRamp, commitStore without injecting the +// strong dependency between modules. ConfigProvider fetch ccip.OnRampReader object reads and returns only relevant +// fields for the daGasEstimator from the encapsulated onRampReader. +type FeeEstimatorConfigProvider interface { + SetOnRampReader(reader ccip.OnRampReader) + AddGasPriceInterceptor(GasPriceInterceptor) + ModifyGasPriceComponents(ctx context.Context, execGasPrice, daGasPrice *big.Int) (modExecGasPrice, modDAGasPrice *big.Int, err error) + GetDataAvailabilityConfig(ctx context.Context) (destDataAvailabilityOverheadGas, destGasPerDataAvailabilityByte, destDataAvailabilityMultiplierBps int64, err error) +} + +type GasPriceInterceptor interface { + ModifyGasPriceComponents(ctx context.Context, execGasPrice, daGasPrice *big.Int) (modExecGasPrice, modDAGasPrice *big.Int, err error) +} + +type FeeEstimatorConfigService struct { + onRampReader ccip.OnRampReader + gasPriceInterceptors []GasPriceInterceptor +} + +func NewFeeEstimatorConfigService() *FeeEstimatorConfigService { + return &FeeEstimatorConfigService{} +} + +// SetOnRampReader Sets the onRamp reader instance. +// must be called once for each instance. +func (c *FeeEstimatorConfigService) SetOnRampReader(reader ccip.OnRampReader) { + c.onRampReader = reader +} + +// GetDataAvailabilityConfig Returns dynamic config data availability parameters. +// GetDynamicConfig should be cached in the onRamp reader to avoid unnecessary on-chain calls +func (c *FeeEstimatorConfigService) GetDataAvailabilityConfig(ctx context.Context) (destDataAvailabilityOverheadGas, destGasPerDataAvailabilityByte, destDataAvailabilityMultiplierBps int64, err error) { + if c.onRampReader == nil { + return 0, 0, 0, nil + } + + cfg, err := c.onRampReader.GetDynamicConfig(ctx) + if err != nil { + return 0, 0, 0, err + } + + return int64(cfg.DestDataAvailabilityOverheadGas), + int64(cfg.DestGasPerDataAvailabilityByte), + int64(cfg.DestDataAvailabilityMultiplierBps), + err +} + +// AddGasPriceInterceptor adds price interceptors that can modify gas price. +func (c *FeeEstimatorConfigService) AddGasPriceInterceptor(gpi GasPriceInterceptor) { + if gpi != nil { + c.gasPriceInterceptors = append(c.gasPriceInterceptors, gpi) + } +} + +// ModifyGasPriceComponents applies gasPrice interceptors and returns modified gasPrice. +func (c *FeeEstimatorConfigService) ModifyGasPriceComponents(ctx context.Context, gasPrice, daGasPrice *big.Int) (*big.Int, *big.Int, error) { + if len(c.gasPriceInterceptors) == 0 { + return gasPrice, daGasPrice, nil + } + + // values are mutable, it is necessary to copy the values to protect the arguments from modification. + cpGasPrice := new(big.Int).Set(gasPrice) + cpDAGasPrice := new(big.Int).Set(daGasPrice) + + var err error + for _, interceptor := range c.gasPriceInterceptors { + if cpGasPrice, cpDAGasPrice, err = interceptor.ModifyGasPriceComponents(ctx, cpGasPrice, cpDAGasPrice); err != nil { + return nil, nil, err + } + } + + return cpGasPrice, cpDAGasPrice, nil +} diff --git a/core/services/ocr2/plugins/ccip/estimatorconfig/config_test.go b/core/services/ocr2/plugins/ccip/estimatorconfig/config_test.go new file mode 100644 index 00000000000..3ecd88ae3bd --- /dev/null +++ b/core/services/ocr2/plugins/ccip/estimatorconfig/config_test.go @@ -0,0 +1,112 @@ +package estimatorconfig_test + +import ( + "context" + "errors" + "math/big" + "testing" + + "github.com/stretchr/testify/require" + + mocks2 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/estimatorconfig/mocks" + + "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/estimatorconfig" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks" +) + +func TestFeeEstimatorConfigService(t *testing.T) { + svc := estimatorconfig.NewFeeEstimatorConfigService() + ctx := context.Background() + + var expectedDestDataAvailabilityOverheadGas int64 = 1 + var expectedDestGasPerDataAvailabilityByte int64 = 2 + var expectedDestDataAvailabilityMultiplierBps int64 = 3 + + onRampReader := mocks.NewOnRampReader(t) + destDataAvailabilityOverheadGas, destGasPerDataAvailabilityByte, destDataAvailabilityMultiplierBps, err := svc.GetDataAvailabilityConfig(ctx) + require.NoError(t, err) // if onRampReader not set, return nil error and 0 values + require.EqualValues(t, 0, destDataAvailabilityOverheadGas) + require.EqualValues(t, 0, destGasPerDataAvailabilityByte) + require.EqualValues(t, 0, destDataAvailabilityMultiplierBps) + svc.SetOnRampReader(onRampReader) + + onRampReader.On("GetDynamicConfig", ctx). + Return(ccip.OnRampDynamicConfig{ + DestDataAvailabilityOverheadGas: uint32(expectedDestDataAvailabilityOverheadGas), + DestGasPerDataAvailabilityByte: uint16(expectedDestGasPerDataAvailabilityByte), + DestDataAvailabilityMultiplierBps: uint16(expectedDestDataAvailabilityMultiplierBps), + }, nil).Once() + + destDataAvailabilityOverheadGas, destGasPerDataAvailabilityByte, destDataAvailabilityMultiplierBps, err = svc.GetDataAvailabilityConfig(ctx) + require.NoError(t, err) + require.Equal(t, expectedDestDataAvailabilityOverheadGas, destDataAvailabilityOverheadGas) + require.Equal(t, expectedDestGasPerDataAvailabilityByte, destGasPerDataAvailabilityByte) + require.Equal(t, expectedDestDataAvailabilityMultiplierBps, destDataAvailabilityMultiplierBps) + + onRampReader.On("GetDynamicConfig", ctx). + Return(ccip.OnRampDynamicConfig{}, errors.New("test")).Once() + _, _, _, err = svc.GetDataAvailabilityConfig(ctx) + require.Error(t, err) +} + +func TestModifyGasPriceComponents(t *testing.T) { + t.Run("success modification", func(t *testing.T) { + svc := estimatorconfig.NewFeeEstimatorConfigService() + ctx := context.Background() + + initialExecGasPrice, initialDaGasPrice := big.NewInt(10), big.NewInt(1) + + gpi1 := mocks2.NewGasPriceInterceptor(t) + svc.AddGasPriceInterceptor(gpi1) + + // change in first interceptor + firstModExecGasPrice, firstModDaGasPrice := big.NewInt(5), big.NewInt(2) + gpi1.On("ModifyGasPriceComponents", ctx, initialExecGasPrice, initialDaGasPrice). + Return(firstModExecGasPrice, firstModDaGasPrice, nil) + + gpi2 := mocks2.NewGasPriceInterceptor(t) + svc.AddGasPriceInterceptor(gpi2) + + // change in second iterceptor + secondModExecGasPrice, secondModDaGasPrice := big.NewInt(50), big.NewInt(20) + gpi2.On("ModifyGasPriceComponents", ctx, firstModExecGasPrice, firstModDaGasPrice). + Return(secondModExecGasPrice, secondModDaGasPrice, nil) + + // has to return second interceptor values + resGasPrice, resDAGasPrice, err := svc.ModifyGasPriceComponents(ctx, initialExecGasPrice, initialDaGasPrice) + require.NoError(t, err) + require.Equal(t, secondModExecGasPrice.Int64(), resGasPrice.Int64()) + require.Equal(t, secondModDaGasPrice.Int64(), resDAGasPrice.Int64()) + }) + + t.Run("error modification", func(t *testing.T) { + svc := estimatorconfig.NewFeeEstimatorConfigService() + ctx := context.Background() + + initialExecGasPrice, initialDaGasPrice := big.NewInt(10), big.NewInt(1) + gpi1 := mocks2.NewGasPriceInterceptor(t) + svc.AddGasPriceInterceptor(gpi1) + gpi1.On("ModifyGasPriceComponents", ctx, initialExecGasPrice, initialDaGasPrice). + Return(nil, nil, errors.New("test")) + + // has to return second interceptor values + _, _, err := svc.ModifyGasPriceComponents(ctx, initialExecGasPrice, initialDaGasPrice) + require.Error(t, err) + }) + + t.Run("without interceptors", func(t *testing.T) { + svc := estimatorconfig.NewFeeEstimatorConfigService() + ctx := context.Background() + + initialExecGasPrice, initialDaGasPrice := big.NewInt(10), big.NewInt(1) + + // has to return second interceptor values + resGasPrice, resDAGasPrice, err := svc.ModifyGasPriceComponents(ctx, initialExecGasPrice, initialDaGasPrice) + require.NoError(t, err) + + // values should not be modified + require.Equal(t, initialExecGasPrice, resGasPrice) + require.Equal(t, initialDaGasPrice, resDAGasPrice) + }) +} diff --git a/core/services/ocr2/plugins/ccip/estimatorconfig/mocks/gas_price_interceptor_mock.go b/core/services/ocr2/plugins/ccip/estimatorconfig/mocks/gas_price_interceptor_mock.go new file mode 100644 index 00000000000..78d7fa7bb35 --- /dev/null +++ b/core/services/ocr2/plugins/ccip/estimatorconfig/mocks/gas_price_interceptor_mock.go @@ -0,0 +1,106 @@ +// Code generated by mockery v2.50.0. DO NOT EDIT. + +package mocks + +import ( + context "context" + big "math/big" + + mock "github.com/stretchr/testify/mock" +) + +// GasPriceInterceptor is an autogenerated mock type for the GasPriceInterceptor type +type GasPriceInterceptor struct { + mock.Mock +} + +type GasPriceInterceptor_Expecter struct { + mock *mock.Mock +} + +func (_m *GasPriceInterceptor) EXPECT() *GasPriceInterceptor_Expecter { + return &GasPriceInterceptor_Expecter{mock: &_m.Mock} +} + +// ModifyGasPriceComponents provides a mock function with given fields: ctx, execGasPrice, daGasPrice +func (_m *GasPriceInterceptor) ModifyGasPriceComponents(ctx context.Context, execGasPrice *big.Int, daGasPrice *big.Int) (*big.Int, *big.Int, error) { + ret := _m.Called(ctx, execGasPrice, daGasPrice) + + if len(ret) == 0 { + panic("no return value specified for ModifyGasPriceComponents") + } + + var r0 *big.Int + var r1 *big.Int + var r2 error + if rf, ok := ret.Get(0).(func(context.Context, *big.Int, *big.Int) (*big.Int, *big.Int, error)); ok { + return rf(ctx, execGasPrice, daGasPrice) + } + if rf, ok := ret.Get(0).(func(context.Context, *big.Int, *big.Int) *big.Int); ok { + r0 = rf(ctx, execGasPrice, daGasPrice) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *big.Int, *big.Int) *big.Int); ok { + r1 = rf(ctx, execGasPrice, daGasPrice) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*big.Int) + } + } + + if rf, ok := ret.Get(2).(func(context.Context, *big.Int, *big.Int) error); ok { + r2 = rf(ctx, execGasPrice, daGasPrice) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// GasPriceInterceptor_ModifyGasPriceComponents_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ModifyGasPriceComponents' +type GasPriceInterceptor_ModifyGasPriceComponents_Call struct { + *mock.Call +} + +// ModifyGasPriceComponents is a helper method to define mock.On call +// - ctx context.Context +// - execGasPrice *big.Int +// - daGasPrice *big.Int +func (_e *GasPriceInterceptor_Expecter) ModifyGasPriceComponents(ctx interface{}, execGasPrice interface{}, daGasPrice interface{}) *GasPriceInterceptor_ModifyGasPriceComponents_Call { + return &GasPriceInterceptor_ModifyGasPriceComponents_Call{Call: _e.mock.On("ModifyGasPriceComponents", ctx, execGasPrice, daGasPrice)} +} + +func (_c *GasPriceInterceptor_ModifyGasPriceComponents_Call) Run(run func(ctx context.Context, execGasPrice *big.Int, daGasPrice *big.Int)) *GasPriceInterceptor_ModifyGasPriceComponents_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*big.Int), args[2].(*big.Int)) + }) + return _c +} + +func (_c *GasPriceInterceptor_ModifyGasPriceComponents_Call) Return(modExecGasPrice *big.Int, modDAGasPrice *big.Int, err error) *GasPriceInterceptor_ModifyGasPriceComponents_Call { + _c.Call.Return(modExecGasPrice, modDAGasPrice, err) + return _c +} + +func (_c *GasPriceInterceptor_ModifyGasPriceComponents_Call) RunAndReturn(run func(context.Context, *big.Int, *big.Int) (*big.Int, *big.Int, error)) *GasPriceInterceptor_ModifyGasPriceComponents_Call { + _c.Call.Return(run) + return _c +} + +// NewGasPriceInterceptor creates a new instance of GasPriceInterceptor. 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 NewGasPriceInterceptor(t interface { + mock.TestingT + Cleanup(func()) +}) *GasPriceInterceptor { + mock := &GasPriceInterceptor{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/core/services/ocr2/plugins/ccip/exportinternal.go b/core/services/ocr2/plugins/ccip/exportinternal.go index 6b24cba4857..10b802eeabc 100644 --- a/core/services/ocr2/plugins/ccip/exportinternal.go +++ b/core/services/ocr2/plugins/ccip/exportinternal.go @@ -5,14 +5,17 @@ import ( "math/big" "time" + "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/ethereum/go-ethereum/common" + "github.com/google/uuid" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" - "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/internal/gethwrappers2/generated/offchainaggregator" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcalc" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" @@ -22,8 +25,13 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/pricegetter" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/rpclib" + "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" ) +const OffchainAggregator = "OffchainAggregator" +const DecimalsMethodName = "decimals" +const LatestRoundDataMethodName = "latestRoundData" + func GenericAddrToEvm(addr ccip.Address) (common.Address, error) { return ccipcalc.GenericAddrToEvm(addr) } @@ -38,20 +46,20 @@ func NewEvmPriceRegistry(lp logpoller.LogPoller, ec client.Client, lggr logger.L type VersionFinder = factory.VersionFinder -func NewCommitStoreReader(ctx context.Context, lggr logger.Logger, versionFinder VersionFinder, address ccip.Address, ec client.Client, lp logpoller.LogPoller) (ccipdata.CommitStoreReader, error) { - return factory.NewCommitStoreReader(ctx, lggr, versionFinder, address, ec, lp) +func NewCommitStoreReader(ctx context.Context, lggr logger.Logger, versionFinder VersionFinder, address ccip.Address, ec client.Client, lp logpoller.LogPoller, feeEstimatorConfig ccipdata.FeeEstimatorConfigReader) (ccipdata.CommitStoreReader, error) { + return factory.NewCommitStoreReader(ctx, lggr, versionFinder, address, ec, lp, feeEstimatorConfig) } -func CloseCommitStoreReader(ctx context.Context, lggr logger.Logger, versionFinder VersionFinder, address ccip.Address, ec client.Client, lp logpoller.LogPoller) error { - return factory.CloseCommitStoreReader(ctx, lggr, versionFinder, address, ec, lp) +func CloseCommitStoreReader(ctx context.Context, lggr logger.Logger, versionFinder VersionFinder, address ccip.Address, ec client.Client, lp logpoller.LogPoller, feeEstimatorConfig ccipdata.FeeEstimatorConfigReader) error { + return factory.CloseCommitStoreReader(ctx, lggr, versionFinder, address, ec, lp, feeEstimatorConfig) } -func NewOffRampReader(ctx context.Context, lggr logger.Logger, versionFinder VersionFinder, addr ccip.Address, destClient client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator, destMaxGasPrice *big.Int, registerFilters bool) (ccipdata.OffRampReader, error) { - return factory.NewOffRampReader(ctx, lggr, versionFinder, addr, destClient, lp, estimator, destMaxGasPrice, registerFilters) +func NewOffRampReader(ctx context.Context, lggr logger.Logger, versionFinder VersionFinder, addr ccip.Address, destClient client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator, destMaxGasPrice *big.Int, registerFilters bool, feeEstimatorConfig ccipdata.FeeEstimatorConfigReader) (ccipdata.OffRampReader, error) { + return factory.NewOffRampReader(ctx, lggr, versionFinder, addr, destClient, lp, estimator, destMaxGasPrice, registerFilters, feeEstimatorConfig) } -func CloseOffRampReader(ctx context.Context, lggr logger.Logger, versionFinder VersionFinder, addr ccip.Address, destClient client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator, destMaxGasPrice *big.Int) error { - return factory.CloseOffRampReader(ctx, lggr, versionFinder, addr, destClient, lp, estimator, destMaxGasPrice) +func CloseOffRampReader(ctx context.Context, lggr logger.Logger, versionFinder VersionFinder, addr ccip.Address, destClient client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator, destMaxGasPrice *big.Int, feeEstimatorConfig ccipdata.FeeEstimatorConfigReader) error { + return factory.CloseOffRampReader(ctx, lggr, versionFinder, addr, destClient, lp, estimator, destMaxGasPrice, feeEstimatorConfig) } func NewEvmVersionFinder() factory.EvmVersionFinder { @@ -72,12 +80,18 @@ type DynamicPriceGetterClient = pricegetter.DynamicPriceGetterClient type DynamicPriceGetter = pricegetter.DynamicPriceGetter +type AllTokensPriceGetter = pricegetter.AllTokensPriceGetter + +func NewPipelineGetter(source string, runner pipeline.Runner, jobID int32, externalJobID uuid.UUID, name string, lggr logger.Logger) (*pricegetter.PipelineGetter, error) { + return pricegetter.NewPipelineGetter(source, runner, jobID, externalJobID, name, lggr) +} + func NewDynamicPriceGetterClient(batchCaller rpclib.EvmBatchCaller) DynamicPriceGetterClient { return pricegetter.NewDynamicPriceGetterClient(batchCaller) } -func NewDynamicPriceGetter(cfg config.DynamicPriceGetterConfig, evmClients map[uint64]DynamicPriceGetterClient) (*DynamicPriceGetter, error) { - return pricegetter.NewDynamicPriceGetter(cfg, evmClients) +func NewDynamicPriceGetter(cfg config.DynamicPriceGetterConfig, contractReaders map[uint64]types.ContractReader) (*DynamicPriceGetter, error) { + return pricegetter.NewDynamicPriceGetter(cfg, contractReaders) } func NewDynamicLimitedBatchCaller( @@ -134,3 +148,5 @@ func NewCommitOffchainConfig( ) ccip.CommitOffchainConfig { return ccipdata.NewCommitOffchainConfig(gasPriceDeviationPPB, gasPriceHeartBeat, tokenPriceDeviationPPB, tokenPriceHeartBeat, inflightCacheExpiry, priceReportingDisabled) } + +const OffChainAggregatorABI = offchainaggregator.OffchainAggregatorABI diff --git a/core/services/ocr2/plugins/ccip/integration_test.go b/core/services/ocr2/plugins/ccip/integration_test.go index e644a3e6f4a..6a1aef98d0c 100644 --- a/core/services/ocr2/plugins/ccip/integration_test.go +++ b/core/services/ocr2/plugins/ccip/integration_test.go @@ -29,6 +29,7 @@ import ( ) func TestIntegration_CCIP(t *testing.T) { + t.Parallel() // Run tke batches of tests for both pipeline and dynamic price getter setups. // We will remove the pipeline batch once the feature is deleted from the code. tests := []struct { @@ -107,7 +108,6 @@ func TestIntegration_CCIP(t *testing.T) { require.NoError(t, err) priceGetterConfigJson = string(priceGetterConfigBytes) } - jobParams := ccipTH.SetUpNodesAndJobs(t, tokenPricesUSDPipeline, priceGetterConfigJson, "") // track sequence number and nonce separately since nonce doesn't bump for messages with allowOutOfOrderExecution == true, @@ -650,6 +650,7 @@ func TestIntegration_CCIP(t *testing.T) { // TestReorg ensures that CCIP works even when a below finality depth reorg happens func TestReorg(t *testing.T) { + t.Parallel() // We need higher finality depth on the destination to perform reorg deep enough to revert commit and execution reports destinationFinalityDepth := uint32(50) ccipTH := integrationtesthelpers.SetupCCIPIntegrationTH( @@ -694,8 +695,9 @@ func TestReorg(t *testing.T) { require.NoError(t, ccipTH.Dest.Chain.Fork(forkBlock.Hash()), "Error while forking the chain") // Make sure that fork is longer than the canonical chain to enforce switch - noOfBlocks := uint(currentBlock.NumberU64() - forkBlock.NumberU64()) - for i := uint(0); i < noOfBlocks+1; i++ { + //nolint:gosec // not a problem in tests + noOfBlocks := int(currentBlock.NumberU64() - forkBlock.NumberU64()) + for i := 0; i < noOfBlocks+1; i++ { ccipTH.Dest.Chain.Commit() } diff --git a/core/services/ocr2/plugins/ccip/internal/cache/commit_roots_test.go b/core/services/ocr2/plugins/ccip/internal/cache/commit_roots_test.go index c49a0448f96..5f12ae97b8a 100644 --- a/core/services/ocr2/plugins/ccip/internal/cache/commit_roots_test.go +++ b/core/services/ocr2/plugins/ccip/internal/cache/commit_roots_test.go @@ -9,7 +9,6 @@ import ( "github.com/stretchr/testify/require" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" @@ -18,6 +17,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/cache" + ccipdatamocks "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" ) @@ -56,7 +56,9 @@ func Test_RootsEligibleForExecution(t *testing.T) { BlockHash: utils.RandomBytes32(), BlockNumber: 2, BlockTimestamp: time.Now(), FinalizedBlockNumber: 1, })) - commitStore, err := v1_2_0.NewCommitStore(logger.TestLogger(t), commitStoreAddr, nil, lp) + feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) + + commitStore, err := v1_2_0.NewCommitStore(logger.TestLogger(t), commitStoreAddr, nil, lp, feeEstimatorConfig) require.NoError(t, err) rootsCache := cache.NewCommitRootsCache(logger.TestLogger(t), commitStore, 10*time.Hour, time.Second) @@ -170,7 +172,9 @@ func Test_RootsEligibleForExecutionWithReorgs(t *testing.T) { BlockHash: utils.RandomBytes32(), BlockNumber: 3, BlockTimestamp: time.Now(), FinalizedBlockNumber: 1, })) - commitStore, err := v1_2_0.NewCommitStore(logger.TestLogger(t), commitStoreAddr, nil, lp) + feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) + + commitStore, err := v1_2_0.NewCommitStore(logger.TestLogger(t), commitStoreAddr, nil, lp, feeEstimatorConfig) require.NoError(t, err) rootsCache := cache.NewCommitRootsCache(logger.TestLogger(t), commitStore, 10*time.Hour, time.Second) @@ -233,7 +237,9 @@ func Test_BlocksWithTheSameTimestamps(t *testing.T) { BlockHash: utils.RandomBytes32(), BlockNumber: 2, BlockTimestamp: time.Now(), FinalizedBlockNumber: 2, })) - commitStore, err := v1_2_0.NewCommitStore(logger.TestLogger(t), commitStoreAddr, nil, lp) + feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) + + commitStore, err := v1_2_0.NewCommitStore(logger.TestLogger(t), commitStoreAddr, nil, lp, feeEstimatorConfig) require.NoError(t, err) rootsCache := cache.NewCommitRootsCache(logger.TestLogger(t), commitStore, 10*time.Hour, time.Second) diff --git a/core/services/ocr2/plugins/ccip/internal/cache/mocks/chain_health_mock.go b/core/services/ocr2/plugins/ccip/internal/cache/mocks/chain_health_mock.go index 316f38f8ffc..5f9d9dcccac 100644 --- a/core/services/ocr2/plugins/ccip/internal/cache/mocks/chain_health_mock.go +++ b/core/services/ocr2/plugins/ccip/internal/cache/mocks/chain_health_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -21,7 +21,7 @@ func (_m *ChainHealthcheck) EXPECT() *ChainHealthcheck_Expecter { return &ChainHealthcheck_Expecter{mock: &_m.Mock} } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *ChainHealthcheck) Close() error { ret := _m.Called() diff --git a/core/services/ocr2/plugins/ccip/internal/ccipcommon/shortcuts.go b/core/services/ocr2/plugins/ccip/internal/ccipcommon/shortcuts.go index 8372ae47486..138d674f93f 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipcommon/shortcuts.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipcommon/shortcuts.go @@ -110,14 +110,19 @@ func SelectorToBytes(chainSelector uint64) [16]byte { return b } -// RetryUntilSuccess repeatedly calls fn until it returns a nil error. After each failed call there is an exponential -// backoff applied, between initialDelay and maxDelay. -func RetryUntilSuccess[T any](fn func() (T, error), initialDelay time.Duration, maxDelay time.Duration) (T, error) { +// RetryUntilSuccess repeatedly calls fn until it returns a nil error or retries have been exhausted. After each failed +// call there is an exponential backoff applied, between initialDelay and maxDelay. +func RetryUntilSuccess[T any]( + fn func() (T, error), + initialDelay time.Duration, + maxDelay time.Duration, + maxRetries uint, +) (T, error) { return retry.DoWithData( fn, retry.Delay(initialDelay), retry.MaxDelay(maxDelay), retry.DelayType(retry.BackOffDelay), - retry.UntilSucceeded(), + retry.Attempts(maxRetries), ) } diff --git a/core/services/ocr2/plugins/ccip/internal/ccipcommon/shortcuts_test.go b/core/services/ocr2/plugins/ccip/internal/ccipcommon/shortcuts_test.go index 6f1cdb4a6af..d298eecbbf3 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipcommon/shortcuts_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipcommon/shortcuts_test.go @@ -9,6 +9,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" ) @@ -145,14 +146,20 @@ func TestRetryUntilSuccess(t *testing.T) { } // Assert that RetryUntilSuccess returns the expected value when fn returns success on the 5th attempt - numCalls, err := RetryUntilSuccess(fn, initialDelay, maxDelay) - assert.Nil(t, err) + numCalls, err := RetryUntilSuccess(fn, initialDelay, maxDelay, 10) + require.NoError(t, err) assert.Equal(t, 5, numCalls) // Assert that RetryUntilSuccess returns the expected value when fn returns success on the 8th attempt numAttempts = 8 numCalls = 0 - numCalls, err = RetryUntilSuccess(fn, initialDelay, maxDelay) - assert.Nil(t, err) + numCalls, err = RetryUntilSuccess(fn, initialDelay, maxDelay, 10) + require.NoError(t, err) assert.Equal(t, 8, numCalls) + + // Assert that RetryUntilSuccess exhausts retries + numAttempts = 8 + numCalls = 0 + numCalls, err = RetryUntilSuccess(fn, initialDelay, maxDelay, 2) + require.Error(t, err) } diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/batchreader/mocks/token_pool_batched_reader_mock.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/batchreader/mocks/token_pool_batched_reader_mock.go index 5302ae0b54f..9bda468b31d 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/batchreader/mocks/token_pool_batched_reader_mock.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/batchreader/mocks/token_pool_batched_reader_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -23,7 +23,7 @@ func (_m *TokenPoolBatchedReader) EXPECT() *TokenPoolBatchedReader_Expecter { return &TokenPoolBatchedReader_Expecter{mock: &_m.Mock} } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *TokenPoolBatchedReader) Close() error { ret := _m.Called() diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/batchreader/token_pool_batch_reader.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/batchreader/token_pool_batch_reader.go index 32ec1b24ac9..6d5d000e1fe 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/batchreader/token_pool_batch_reader.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/batchreader/token_pool_batch_reader.go @@ -13,7 +13,7 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" "github.com/smartcontractkit/chainlink-common/pkg/logger" - type_and_version "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/type_and_version_interface_wrapper" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/type_and_version" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" ccipconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcalc" @@ -24,7 +24,7 @@ import ( ) var ( - typeAndVersionABI = abihelpers.MustParseABI(type_and_version.TypeAndVersionInterfaceABI) + typeAndVersionABI = abihelpers.MustParseABI(type_and_version.ITypeAndVersionABI) ) type EVMTokenPoolBatchedReader struct { diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/batchreader/token_pool_batch_reader_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/batchreader/token_pool_batch_reader_test.go index ceafdf22721..c67c3c15276 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/batchreader/token_pool_batch_reader_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/batchreader/token_pool_batch_reader_test.go @@ -13,15 +13,15 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-common/pkg/logger" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcalc" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" ) func TestTokenPoolFactory(t *testing.T) { - lggr := logger.Test(t) + lggr := logger.TestLogger(t) offRamp := utils.RandomAddress() ctx := context.Background() remoteChainSelector := uint64(2000) diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/ccipdataprovider/mocks/price_registry_mock.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/ccipdataprovider/mocks/price_registry_mock.go index 9a9cdb48cad..7655116ede4 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/ccipdataprovider/mocks/price_registry_mock.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/ccipdataprovider/mocks/price_registry_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/ccipdataprovider/provider.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/ccipdataprovider/provider.go index 971b507e828..42a7369c7e5 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/ccipdataprovider/provider.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/ccipdataprovider/provider.go @@ -5,7 +5,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/factory" diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_reader_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_reader_test.go index 0f234bab8a6..30e74d89e36 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_reader_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_reader_test.go @@ -1,6 +1,7 @@ package ccipdata_test import ( + "context" "math/big" "reflect" "testing" @@ -35,6 +36,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcalc" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/factory" + ccipdatamocks "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" ) @@ -179,8 +181,17 @@ func TestCommitStoreReaders(t *testing.T) { lm := new(rollupMocks.L1Oracle) ge.On("L1Oracle").Return(lm) + feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) + feeEstimatorConfig.On( + "ModifyGasPriceComponents", + mock.Anything, + mock.AnythingOfType("*big.Int"), + mock.AnythingOfType("*big.Int"), + ).Return(func(ctx context.Context, x, y *big.Int) (*big.Int, *big.Int, error) { + return x, y, nil + }) maxGasPrice := big.NewInt(1e8) - c12r, err := factory.NewCommitStoreReader(ctx, lggr, factory.NewEvmVersionFinder(), ccipcalc.EvmAddrToGeneric(addr2), ec, lp) + c12r, err := factory.NewCommitStoreReader(ctx, lggr, factory.NewEvmVersionFinder(), ccipcalc.EvmAddrToGeneric(addr2), ec, lp, feeEstimatorConfig) require.NoError(t, err) err = c12r.SetGasEstimator(ctx, ge) require.NoError(t, err) @@ -327,8 +338,10 @@ func TestCommitStoreReaders(t *testing.T) { require.NoError(t, err) assert.Equal(t, commonOffchain, c2) // We should be able to query for gas prices now. + gpe, err := cr.GasPriceEstimator(ctx) require.NoError(t, err) + gp, err := gpe.GetGasPrice(ctx) require.NoError(t, err) assert.True(t, gp.Cmp(big.NewInt(0)) > 0) @@ -370,7 +383,10 @@ func TestNewCommitStoreReader(t *testing.T) { if tc.expectedErr == "" { lp.On("RegisterFilter", mock.Anything, mock.Anything).Return(nil) } - _, err = factory.NewCommitStoreReader(ctx, logger.Test(t), factory.NewEvmVersionFinder(), addr, c, lp) + + feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) + + _, err = factory.NewCommitStoreReader(ctx, logger.Test(t), factory.NewEvmVersionFinder(), addr, c, lp, feeEstimatorConfig) if tc.expectedErr != "" { require.EqualError(t, err, tc.expectedErr) } else { diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/commit_store.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/commit_store.go index d9cd523d75e..2d40a526112 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/commit_store.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/commit_store.go @@ -21,16 +21,16 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0" ) -func NewCommitStoreReader(ctx context.Context, lggr logger.Logger, versionFinder VersionFinder, address cciptypes.Address, ec client.Client, lp logpoller.LogPoller) (ccipdata.CommitStoreReader, error) { - return initOrCloseCommitStoreReader(ctx, lggr, versionFinder, address, ec, lp, false) +func NewCommitStoreReader(ctx context.Context, lggr logger.Logger, versionFinder VersionFinder, address cciptypes.Address, ec client.Client, lp logpoller.LogPoller, feeEstimatorConfig ccipdata.FeeEstimatorConfigReader) (ccipdata.CommitStoreReader, error) { + return initOrCloseCommitStoreReader(ctx, lggr, versionFinder, address, ec, lp, feeEstimatorConfig, false) } -func CloseCommitStoreReader(ctx context.Context, lggr logger.Logger, versionFinder VersionFinder, address cciptypes.Address, ec client.Client, lp logpoller.LogPoller) error { - _, err := initOrCloseCommitStoreReader(ctx, lggr, versionFinder, address, ec, lp, true) +func CloseCommitStoreReader(ctx context.Context, lggr logger.Logger, versionFinder VersionFinder, address cciptypes.Address, ec client.Client, lp logpoller.LogPoller, feeEstimatorConfig ccipdata.FeeEstimatorConfigReader) error { + _, err := initOrCloseCommitStoreReader(ctx, lggr, versionFinder, address, ec, lp, feeEstimatorConfig, true) return err } -func initOrCloseCommitStoreReader(ctx context.Context, lggr logger.Logger, versionFinder VersionFinder, address cciptypes.Address, ec client.Client, lp logpoller.LogPoller, closeReader bool) (ccipdata.CommitStoreReader, error) { +func initOrCloseCommitStoreReader(ctx context.Context, lggr logger.Logger, versionFinder VersionFinder, address cciptypes.Address, ec client.Client, lp logpoller.LogPoller, feeEstimatorConfig ccipdata.FeeEstimatorConfigReader, closeReader bool) (ccipdata.CommitStoreReader, error) { contractType, version, err := versionFinder.TypeAndVersion(address, ec) if err != nil { return nil, errors.Wrapf(err, "unable to read type and version") @@ -48,7 +48,7 @@ func initOrCloseCommitStoreReader(ctx context.Context, lggr logger.Logger, versi switch version.String() { case ccipdata.V1_2_0: - cs, err := v1_2_0.NewCommitStore(lggr, evmAddr, ec, lp) + cs, err := v1_2_0.NewCommitStore(lggr, evmAddr, ec, lp, feeEstimatorConfig) if err != nil { return nil, err } @@ -57,7 +57,7 @@ func initOrCloseCommitStoreReader(ctx context.Context, lggr logger.Logger, versi } return cs, cs.RegisterFilters(ctx) case ccipdata.V1_5_0: - cs, err := v1_5_0.NewCommitStore(lggr, evmAddr, ec, lp) + cs, err := v1_5_0.NewCommitStore(lggr, evmAddr, ec, lp, feeEstimatorConfig) if err != nil { return nil, err } diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/commit_store_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/commit_store_test.go index cd81a0633ce..d4234bb1a33 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/commit_store_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/commit_store_test.go @@ -17,6 +17,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ccipconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" + ccipdatamocks "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" ) @@ -27,14 +28,16 @@ func TestCommitStore(t *testing.T) { addr := cciptypes.Address(utils.RandomAddress().String()) lp := mocks2.NewLogPoller(t) + feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) + lp.On("RegisterFilter", mock.Anything, mock.Anything).Return(nil) versionFinder := newMockVersionFinder(ccipconfig.CommitStore, *semver.MustParse(versionStr), nil) - _, err := NewCommitStoreReader(ctx, lggr, versionFinder, addr, nil, lp) + _, err := NewCommitStoreReader(ctx, lggr, versionFinder, addr, nil, lp, feeEstimatorConfig) assert.NoError(t, err) expFilterName := logpoller.FilterName(v1_2_0.ExecReportAccepts, addr) lp.On("UnregisterFilter", mock.Anything, expFilterName).Return(nil) - err = CloseCommitStoreReader(ctx, lggr, versionFinder, addr, nil, lp) + err = CloseCommitStoreReader(ctx, lggr, versionFinder, addr, nil, lp, feeEstimatorConfig) assert.NoError(t, err) } } diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/offramp.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/offramp.go index 136079b5b3e..7a1180a5590 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/offramp.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/offramp.go @@ -24,16 +24,16 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0" ) -func NewOffRampReader(ctx context.Context, lggr logger.Logger, versionFinder VersionFinder, addr cciptypes.Address, destClient client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator, destMaxGasPrice *big.Int, registerFilters bool) (ccipdata.OffRampReader, error) { - return initOrCloseOffRampReader(ctx, lggr, versionFinder, addr, destClient, lp, estimator, destMaxGasPrice, false, registerFilters) +func NewOffRampReader(ctx context.Context, lggr logger.Logger, versionFinder VersionFinder, addr cciptypes.Address, destClient client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator, destMaxGasPrice *big.Int, registerFilters bool, feeEstimatorConfig ccipdata.FeeEstimatorConfigReader) (ccipdata.OffRampReader, error) { + return initOrCloseOffRampReader(ctx, lggr, versionFinder, addr, destClient, lp, estimator, destMaxGasPrice, false, registerFilters, feeEstimatorConfig) } -func CloseOffRampReader(ctx context.Context, lggr logger.Logger, versionFinder VersionFinder, addr cciptypes.Address, destClient client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator, destMaxGasPrice *big.Int) error { - _, err := initOrCloseOffRampReader(ctx, lggr, versionFinder, addr, destClient, lp, estimator, destMaxGasPrice, true, false) +func CloseOffRampReader(ctx context.Context, lggr logger.Logger, versionFinder VersionFinder, addr cciptypes.Address, destClient client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator, destMaxGasPrice *big.Int, feeEstimatorConfig ccipdata.FeeEstimatorConfigReader) error { + _, err := initOrCloseOffRampReader(ctx, lggr, versionFinder, addr, destClient, lp, estimator, destMaxGasPrice, true, false, feeEstimatorConfig) return err } -func initOrCloseOffRampReader(ctx context.Context, lggr logger.Logger, versionFinder VersionFinder, addr cciptypes.Address, destClient client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator, destMaxGasPrice *big.Int, closeReader bool, registerFilters bool) (ccipdata.OffRampReader, error) { +func initOrCloseOffRampReader(ctx context.Context, lggr logger.Logger, versionFinder VersionFinder, addr cciptypes.Address, destClient client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator, destMaxGasPrice *big.Int, closeReader bool, registerFilters bool, feeEstimatorConfig ccipdata.FeeEstimatorConfigReader) (ccipdata.OffRampReader, error) { contractType, version, err := versionFinder.TypeAndVersion(addr, destClient) if err != nil { return nil, errors.Wrapf(err, "unable to read type and version") @@ -51,7 +51,7 @@ func initOrCloseOffRampReader(ctx context.Context, lggr logger.Logger, versionFi switch version.String() { case ccipdata.V1_2_0: - offRamp, err := v1_2_0.NewOffRamp(lggr, evmAddr, destClient, lp, estimator, destMaxGasPrice) + offRamp, err := v1_2_0.NewOffRamp(lggr, evmAddr, destClient, lp, estimator, destMaxGasPrice, feeEstimatorConfig) if err != nil { return nil, err } @@ -60,7 +60,7 @@ func initOrCloseOffRampReader(ctx context.Context, lggr logger.Logger, versionFi } return offRamp, offRamp.RegisterFilters(ctx) case ccipdata.V1_5_0: - offRamp, err := v1_5_0.NewOffRamp(lggr, evmAddr, destClient, lp, estimator, destMaxGasPrice) + offRamp, err := v1_5_0.NewOffRamp(lggr, evmAddr, destClient, lp, estimator, destMaxGasPrice, feeEstimatorConfig) if err != nil { return nil, err } diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/offramp_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/offramp_test.go index bfb8da5e32c..7640261786f 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/offramp_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/offramp_test.go @@ -16,6 +16,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ccipconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" + ccipdatamocks "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" ) @@ -26,6 +27,8 @@ func TestOffRamp(t *testing.T) { addr := cciptypes.Address(utils.RandomAddress().String()) lp := mocks2.NewLogPoller(t) + feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) + expFilterNames := []string{ logpoller.FilterName(v1_2_0.ExecExecutionStateChanges, addr), logpoller.FilterName(v1_2_0.ExecTokenPoolAdded, addr), @@ -34,13 +37,13 @@ func TestOffRamp(t *testing.T) { versionFinder := newMockVersionFinder(ccipconfig.EVM2EVMOffRamp, *semver.MustParse(versionStr), nil) lp.On("RegisterFilter", mock.Anything, mock.Anything).Return(nil).Times(len(expFilterNames)) - _, err := NewOffRampReader(ctx, lggr, versionFinder, addr, nil, lp, nil, nil, true) + _, err := NewOffRampReader(ctx, lggr, versionFinder, addr, nil, lp, nil, nil, true, feeEstimatorConfig) assert.NoError(t, err) for _, f := range expFilterNames { lp.On("UnregisterFilter", mock.Anything, f).Return(nil) } - err = CloseOffRampReader(ctx, lggr, versionFinder, addr, nil, lp, nil, nil) + err = CloseOffRampReader(ctx, lggr, versionFinder, addr, nil, lp, nil, nil, feeEstimatorConfig) assert.NoError(t, err) } } diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/onramp.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/onramp.go index 57bf6e2eeb3..85eee70e296 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/onramp.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/onramp.go @@ -10,7 +10,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - ccipconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcalc" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/fee_estimator_config.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/fee_estimator_config.go new file mode 100644 index 00000000000..0b4d1ce75ab --- /dev/null +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/fee_estimator_config.go @@ -0,0 +1,11 @@ +package ccipdata + +import ( + "context" + "math/big" +) + +type FeeEstimatorConfigReader interface { + GetDataAvailabilityConfig(ctx context.Context) (destDAOverheadGas, destGasPerDAByte, destDAMultiplierBps int64, err error) + ModifyGasPriceComponents(ctx context.Context, execGasPrice, daGasPrice *big.Int) (modExecGasPrice, modDAGasPrice *big.Int, err error) +} diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/commit_store_reader_mock.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/commit_store_reader_mock.go index a9de0fa0d88..eb8d8179c52 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/commit_store_reader_mock.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/commit_store_reader_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -87,7 +87,7 @@ func (_c *CommitStoreReader_ChangeConfig_Call) RunAndReturn(run func(context.Con return _c } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *CommitStoreReader) Close() error { ret := _m.Called() diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/fee_estimator_config_mock.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/fee_estimator_config_mock.go new file mode 100644 index 00000000000..9ce400406d4 --- /dev/null +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/fee_estimator_config_mock.go @@ -0,0 +1,177 @@ +// Code generated by mockery v2.50.0. DO NOT EDIT. + +package mocks + +import ( + big "math/big" + + context "context" + + mock "github.com/stretchr/testify/mock" +) + +// FeeEstimatorConfigReader is an autogenerated mock type for the FeeEstimatorConfigReader type +type FeeEstimatorConfigReader struct { + mock.Mock +} + +type FeeEstimatorConfigReader_Expecter struct { + mock *mock.Mock +} + +func (_m *FeeEstimatorConfigReader) EXPECT() *FeeEstimatorConfigReader_Expecter { + return &FeeEstimatorConfigReader_Expecter{mock: &_m.Mock} +} + +// GetDataAvailabilityConfig provides a mock function with given fields: ctx +func (_m *FeeEstimatorConfigReader) GetDataAvailabilityConfig(ctx context.Context) (int64, int64, int64, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for GetDataAvailabilityConfig") + } + + var r0 int64 + var r1 int64 + var r2 int64 + var r3 error + if rf, ok := ret.Get(0).(func(context.Context) (int64, int64, int64, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) int64); ok { + r0 = rf(ctx) + } else { + r0 = ret.Get(0).(int64) + } + + if rf, ok := ret.Get(1).(func(context.Context) int64); ok { + r1 = rf(ctx) + } else { + r1 = ret.Get(1).(int64) + } + + if rf, ok := ret.Get(2).(func(context.Context) int64); ok { + r2 = rf(ctx) + } else { + r2 = ret.Get(2).(int64) + } + + if rf, ok := ret.Get(3).(func(context.Context) error); ok { + r3 = rf(ctx) + } else { + r3 = ret.Error(3) + } + + return r0, r1, r2, r3 +} + +// FeeEstimatorConfigReader_GetDataAvailabilityConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetDataAvailabilityConfig' +type FeeEstimatorConfigReader_GetDataAvailabilityConfig_Call struct { + *mock.Call +} + +// GetDataAvailabilityConfig is a helper method to define mock.On call +// - ctx context.Context +func (_e *FeeEstimatorConfigReader_Expecter) GetDataAvailabilityConfig(ctx interface{}) *FeeEstimatorConfigReader_GetDataAvailabilityConfig_Call { + return &FeeEstimatorConfigReader_GetDataAvailabilityConfig_Call{Call: _e.mock.On("GetDataAvailabilityConfig", ctx)} +} + +func (_c *FeeEstimatorConfigReader_GetDataAvailabilityConfig_Call) Run(run func(ctx context.Context)) *FeeEstimatorConfigReader_GetDataAvailabilityConfig_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *FeeEstimatorConfigReader_GetDataAvailabilityConfig_Call) Return(destDAOverheadGas int64, destGasPerDAByte int64, destDAMultiplierBps int64, err error) *FeeEstimatorConfigReader_GetDataAvailabilityConfig_Call { + _c.Call.Return(destDAOverheadGas, destGasPerDAByte, destDAMultiplierBps, err) + return _c +} + +func (_c *FeeEstimatorConfigReader_GetDataAvailabilityConfig_Call) RunAndReturn(run func(context.Context) (int64, int64, int64, error)) *FeeEstimatorConfigReader_GetDataAvailabilityConfig_Call { + _c.Call.Return(run) + return _c +} + +// ModifyGasPriceComponents provides a mock function with given fields: ctx, execGasPrice, daGasPrice +func (_m *FeeEstimatorConfigReader) ModifyGasPriceComponents(ctx context.Context, execGasPrice *big.Int, daGasPrice *big.Int) (*big.Int, *big.Int, error) { + ret := _m.Called(ctx, execGasPrice, daGasPrice) + + if len(ret) == 0 { + panic("no return value specified for ModifyGasPriceComponents") + } + + var r0 *big.Int + var r1 *big.Int + var r2 error + if rf, ok := ret.Get(0).(func(context.Context, *big.Int, *big.Int) (*big.Int, *big.Int, error)); ok { + return rf(ctx, execGasPrice, daGasPrice) + } + if rf, ok := ret.Get(0).(func(context.Context, *big.Int, *big.Int) *big.Int); ok { + r0 = rf(ctx, execGasPrice, daGasPrice) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *big.Int, *big.Int) *big.Int); ok { + r1 = rf(ctx, execGasPrice, daGasPrice) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*big.Int) + } + } + + if rf, ok := ret.Get(2).(func(context.Context, *big.Int, *big.Int) error); ok { + r2 = rf(ctx, execGasPrice, daGasPrice) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// FeeEstimatorConfigReader_ModifyGasPriceComponents_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ModifyGasPriceComponents' +type FeeEstimatorConfigReader_ModifyGasPriceComponents_Call struct { + *mock.Call +} + +// ModifyGasPriceComponents is a helper method to define mock.On call +// - ctx context.Context +// - execGasPrice *big.Int +// - daGasPrice *big.Int +func (_e *FeeEstimatorConfigReader_Expecter) ModifyGasPriceComponents(ctx interface{}, execGasPrice interface{}, daGasPrice interface{}) *FeeEstimatorConfigReader_ModifyGasPriceComponents_Call { + return &FeeEstimatorConfigReader_ModifyGasPriceComponents_Call{Call: _e.mock.On("ModifyGasPriceComponents", ctx, execGasPrice, daGasPrice)} +} + +func (_c *FeeEstimatorConfigReader_ModifyGasPriceComponents_Call) Run(run func(ctx context.Context, execGasPrice *big.Int, daGasPrice *big.Int)) *FeeEstimatorConfigReader_ModifyGasPriceComponents_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*big.Int), args[2].(*big.Int)) + }) + return _c +} + +func (_c *FeeEstimatorConfigReader_ModifyGasPriceComponents_Call) Return(modExecGasPrice *big.Int, modDAGasPrice *big.Int, err error) *FeeEstimatorConfigReader_ModifyGasPriceComponents_Call { + _c.Call.Return(modExecGasPrice, modDAGasPrice, err) + return _c +} + +func (_c *FeeEstimatorConfigReader_ModifyGasPriceComponents_Call) RunAndReturn(run func(context.Context, *big.Int, *big.Int) (*big.Int, *big.Int, error)) *FeeEstimatorConfigReader_ModifyGasPriceComponents_Call { + _c.Call.Return(run) + return _c +} + +// NewFeeEstimatorConfigReader creates a new instance of FeeEstimatorConfigReader. 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 NewFeeEstimatorConfigReader(t interface { + mock.TestingT + Cleanup(func()) +}) *FeeEstimatorConfigReader { + mock := &FeeEstimatorConfigReader{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/offramp_reader_mock.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/offramp_reader_mock.go index e9766b48ddf..255102feed2 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/offramp_reader_mock.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/offramp_reader_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -144,7 +144,7 @@ func (_c *OffRampReader_ChangeConfig_Call) RunAndReturn(run func(context.Context return _c } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *OffRampReader) Close() error { ret := _m.Called() diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/onramp_reader_mock.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/onramp_reader_mock.go index 3b029054d17..1cd3d5ee49b 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/onramp_reader_mock.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/onramp_reader_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -79,7 +79,7 @@ func (_c *OnRampReader_Address_Call) RunAndReturn(run func(context.Context) (cci return _c } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *OnRampReader) Close() error { ret := _m.Called() diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/price_registry_reader_mock.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/price_registry_reader_mock.go index c312dda2a2f..49812d2a87c 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/price_registry_reader_mock.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/price_registry_reader_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -81,7 +81,7 @@ func (_c *PriceRegistryReader_Address_Call) RunAndReturn(run func(context.Contex return _c } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *PriceRegistryReader) Close() error { ret := _m.Called() diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/token_pool_reader_mock.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/token_pool_reader_mock.go index be50e765c91..6ae5a2478bb 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/token_pool_reader_mock.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/token_pool_reader_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -20,7 +20,7 @@ func (_m *TokenPoolReader) EXPECT() *TokenPoolReader_Expecter { return &TokenPoolReader_Expecter{mock: &_m.Mock} } -// Address provides a mock function with given fields: +// Address provides a mock function with no fields func (_m *TokenPoolReader) Address() common.Address { ret := _m.Called() @@ -67,7 +67,7 @@ func (_c *TokenPoolReader_Address_Call) RunAndReturn(run func() common.Address) return _c } -// Type provides a mock function with given fields: +// Type provides a mock function with no fields func (_m *TokenPoolReader) Type() string { ret := _m.Called() diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/usdc_reader_mock.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/usdc_reader_mock.go index 03085bd8973..67823035e5e 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/usdc_reader_mock.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/usdc_reader_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/offramp_reader_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/offramp_reader_test.go index 17f9bcfb370..420cd5bf64c 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/offramp_reader_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/offramp_reader_test.go @@ -12,7 +12,6 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-common/pkg/logger" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" @@ -28,10 +27,12 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_rmn_contract" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" + "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcalc" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/factory" + ccipdatamocks "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" ) @@ -108,7 +109,7 @@ func TestOffRampReaderInit(t *testing.T) { func setupOffRampReaderTH(t *testing.T, version string) offRampReaderTH { ctx := testutils.Context(t) user, bc := ccipdata.NewSimulation(t) - log := logger.Test(t) + log := logger.TestLogger(t) orm := logpoller.NewORM(testutils.SimulatedChainID, pgtest.NewSqlxDB(t), log) lpOpts := logpoller.Opts{ PollPeriod: 100 * time.Millisecond, @@ -139,8 +140,10 @@ func setupOffRampReaderTH(t *testing.T, version string) offRampReaderTH { require.Fail(t, "Unknown version: ", version) } + feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) + // Create the version-specific reader. - reader, err := factory.NewOffRampReader(ctx, log, factory.NewEvmVersionFinder(), ccipcalc.EvmAddrToGeneric(offRampAddress), bc, lp, nil, nil, true) + reader, err := factory.NewOffRampReader(ctx, log, factory.NewEvmVersionFinder(), ccipcalc.EvmAddrToGeneric(offRampAddress), bc, lp, nil, nil, true, feeEstimatorConfig) require.NoError(t, err) addr, err := reader.Address(ctx) require.NoError(t, err) @@ -311,11 +314,14 @@ func TestNewOffRampReader(t *testing.T) { b, err := utils.ABIEncode(`[{"type":"string"}]`, tc.typeAndVersion) require.NoError(t, err) c := evmclientmocks.NewClient(t) + + feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) + c.On("CallContract", mock.Anything, mock.Anything, mock.Anything).Return(b, nil) addr := ccipcalc.EvmAddrToGeneric(utils.RandomAddress()) lp := lpmocks.NewLogPoller(t) lp.On("RegisterFilter", mock.Anything, mock.Anything).Return(nil).Maybe() - _, err = factory.NewOffRampReader(ctx, logger.Test(t), factory.NewEvmVersionFinder(), addr, c, lp, nil, nil, true) + _, err = factory.NewOffRampReader(ctx, logger.TestLogger(t), factory.NewEvmVersionFinder(), addr, c, lp, nil, nil, true, feeEstimatorConfig) if tc.expectedErr != "" { assert.EqualError(t, err, tc.expectedErr) } else { diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/reader.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/reader.go index 3c82948b892..8655bc98acc 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/reader.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/reader.go @@ -8,7 +8,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/reader_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/reader_test.go index 0df76873915..06766be81ee 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/reader_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/reader_test.go @@ -10,9 +10,8 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + "github.com/smartcontractkit/chainlink/v2/core/logger" ) func Test_parseLogs(t *testing.T) { @@ -28,7 +27,7 @@ func Test_parseLogs(t *testing.T) { return &log.Index, nil } - parsedEvents, err := ParseLogs[uint](logs, logger.Test(t), parseFn) + parsedEvents, err := ParseLogs[uint](logs, logger.TestLogger(t), parseFn) require.NoError(t, err) assert.Len(t, parsedEvents, 100) @@ -56,7 +55,7 @@ func Test_parseLogs_withErrors(t *testing.T) { return &log.Index, nil } - log, observed := logger.TestObserved(t, zapcore.DebugLevel) + log, observed := logger.TestLoggerObserved(t, zapcore.DebugLevel) parsedEvents, err := ParseLogs[uint](logs, log, parseFn) assert.ErrorContains(t, err, fmt.Sprintf("%d logs were not parsed", len(logs)/2)) assert.Nil(t, parsedEvents, "No events are returned if there was an error.") diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/retry_config.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/retry_config.go index 41161ee9388..80c5364e18f 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/retry_config.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/retry_config.go @@ -2,8 +2,10 @@ package ccipdata import "time" -// RetryConfig configures an initial delay between retries and a max delay between retries +// RetryConfig configures an initial delay between retries, a max delay between retries, and a maximum number of +// times to retry type RetryConfig struct { InitialDelay time.Duration MaxDelay time.Duration + MaxRetries uint } diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/commit_store.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/commit_store.go index 2d772e3bd0a..78f60653668 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/commit_store.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/commit_store.go @@ -53,9 +53,10 @@ type CommitStore struct { commitReportArgs abi.Arguments // Dynamic config - configMu sync.RWMutex - gasPriceEstimator *prices.DAGasPriceEstimator - offchainConfig cciptypes.CommitOffchainConfig + configMu sync.RWMutex + gasPriceEstimator *prices.DAGasPriceEstimator + offchainConfig cciptypes.CommitOffchainConfig + feeEstimatorConfig ccipdata.FeeEstimatorConfigReader } func (c *CommitStore) GetCommitStoreStaticConfig(ctx context.Context) (cciptypes.CommitStoreStaticConfig, error) { @@ -259,6 +260,7 @@ func (c *CommitStore) ChangeConfig(_ context.Context, onchainConfig []byte, offc c.sourceMaxGasPrice, int64(offchainConfigParsed.ExecGasPriceDeviationPPB), int64(offchainConfigParsed.DAGasPriceDeviationPPB), + c.feeEstimatorConfig, ) c.offchainConfig = ccipdata.NewCommitOffchainConfig( offchainConfigParsed.ExecGasPriceDeviationPPB, @@ -353,7 +355,8 @@ func (c *CommitStore) GetAcceptedCommitReportsGteTimestamp(ctx context.Context, return nil, err } - reportsQuery, err := logpoller.Where( + reportsQuery, err := query.Where( + c.address.String(), logpoller.NewAddressFilter(c.address), logpoller.NewEventSigFilter(c.reportAcceptedSig), query.Timestamp(uint64(ts.Unix()), primitives.Gte), @@ -365,7 +368,7 @@ func (c *CommitStore) GetAcceptedCommitReportsGteTimestamp(ctx context.Context, logs, err := c.lp.FilteredLogs( ctx, - reportsQuery, + reportsQuery.Expressions, query.NewLimitAndSort(query.Limit{}, query.NewSortBySequence(query.Asc)), "GetAcceptedCommitReportsGteTimestamp", ) @@ -433,7 +436,7 @@ func (c *CommitStore) RegisterFilters(ctx context.Context) error { return logpollerutil.RegisterLpFilters(ctx, c.lp, c.filters) } -func NewCommitStore(lggr logger.Logger, addr common.Address, ec client.Client, lp logpoller.LogPoller) (*CommitStore, error) { +func NewCommitStore(lggr logger.Logger, addr common.Address, ec client.Client, lp logpoller.LogPoller, feeEstimatorConfig ccipdata.FeeEstimatorConfigReader) (*CommitStore, error) { commitStore, err := commit_store_1_2_0.NewCommitStore(addr, ec) if err != nil { return nil, err @@ -466,7 +469,8 @@ func NewCommitStore(lggr logger.Logger, addr common.Address, ec client.Client, l configMu: sync.RWMutex{}, // The fields below are initially empty and set on ChangeConfig method - offchainConfig: cciptypes.CommitOffchainConfig{}, - gasPriceEstimator: nil, + offchainConfig: cciptypes.CommitOffchainConfig{}, + gasPriceEstimator: nil, + feeEstimatorConfig: feeEstimatorConfig, }, nil } diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/commit_store_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/commit_store_test.go index e0771f33cb9..4307be0353c 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/commit_store_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/commit_store_test.go @@ -10,13 +10,14 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink-common/pkg/logger" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/logger" ccipconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" + ccipdatamocks "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks" ) func TestCommitReportEncoding(t *testing.T) { @@ -47,7 +48,9 @@ func TestCommitReportEncoding(t *testing.T) { Interval: cciptypes.CommitStoreInterval{Min: 1, Max: 10}, } - c, err := NewCommitStore(logger.Test(t), utils.RandomAddress(), nil, mocks.NewLogPoller(t)) + feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) + + c, err := NewCommitStore(logger.TestLogger(t), utils.RandomAddress(), nil, mocks.NewLogPoller(t), feeEstimatorConfig) assert.NoError(t, err) encodedReport, err := c.EncodeCommitReport(ctx, report) diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/offramp.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/offramp.go index e8017016690..881755d3f3c 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/offramp.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/offramp.go @@ -155,10 +155,11 @@ type OffRamp struct { // Dynamic config // configMu guards all the dynamic config fields. - configMu sync.RWMutex - gasPriceEstimator prices.GasPriceEstimatorExec - offchainConfig cciptypes.ExecOffchainConfig - onchainConfig cciptypes.ExecOnchainConfig + configMu sync.RWMutex + gasPriceEstimator prices.GasPriceEstimatorExec + offchainConfig cciptypes.ExecOffchainConfig + onchainConfig cciptypes.ExecOnchainConfig + feeEstimatorConfig ccipdata.FeeEstimatorConfigReader } func (o *OffRamp) GetStaticConfig(ctx context.Context) (cciptypes.OffRampStaticConfig, error) { @@ -416,7 +417,7 @@ func (o *OffRamp) ChangeConfig(ctx context.Context, onchainConfigBytes []byte, o PermissionLessExecutionThresholdSeconds: time.Second * time.Duration(onchainConfigParsed.PermissionLessExecutionThresholdSeconds), Router: cciptypes.Address(onchainConfigParsed.Router.String()), } - priceEstimator := prices.NewDAGasPriceEstimator(o.Estimator, o.DestMaxGasPrice, 0, 0) + priceEstimator := prices.NewDAGasPriceEstimator(o.Estimator, o.DestMaxGasPrice, 0, 0, o.feeEstimatorConfig) o.UpdateDynamicConfig(onchainConfig, offchainConfig, priceEstimator) @@ -614,7 +615,7 @@ func (o *OffRamp) DecodeExecutionReport(ctx context.Context, report []byte) (cci return DecodeExecReport(ctx, o.ExecutionReportArgs, report) } -func NewOffRamp(lggr logger.Logger, addr common.Address, ec client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator, destMaxGasPrice *big.Int) (*OffRamp, error) { +func NewOffRamp(lggr logger.Logger, addr common.Address, ec client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator, destMaxGasPrice *big.Int, feeEstimatorConfig ccipdata.FeeEstimatorConfigReader) (*OffRamp, error) { offRamp, err := evm_2_evm_offramp_1_2_0.NewEVM2EVMOffRamp(addr, ec) if err != nil { return nil, err @@ -669,8 +670,9 @@ func NewOffRamp(lggr logger.Logger, addr common.Address, ec client.Client, lp lo offRamp.Address(), ), // values set on the fly after ChangeConfig is called - gasPriceEstimator: prices.ExecGasPriceEstimator{}, - offchainConfig: cciptypes.ExecOffchainConfig{}, - onchainConfig: cciptypes.ExecOnchainConfig{}, + gasPriceEstimator: prices.ExecGasPriceEstimator{}, + offchainConfig: cciptypes.ExecOffchainConfig{}, + onchainConfig: cciptypes.ExecOnchainConfig{}, + feeEstimatorConfig: feeEstimatorConfig, }, nil } diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/offramp_reader_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/offramp_reader_test.go index 630b92f67fc..c2983492618 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/offramp_reader_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/offramp_reader_test.go @@ -6,12 +6,12 @@ import ( "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-common/pkg/logger" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" - lpmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" ) @@ -26,7 +26,9 @@ func TestExecutionReportEncodingV120(t *testing.T) { ProofFlagBits: big.NewInt(133), } - offRamp, err := v1_2_0.NewOffRamp(logger.Test(t), utils.RandomAddress(), nil, lpmocks.NewLogPoller(t), nil, nil) + feeEstimatorConfig := mocks.NewFeeEstimatorConfigReader(t) + + offRamp, err := v1_2_0.NewOffRamp(logger.TestLogger(t), utils.RandomAddress(), nil, lpmocks.NewLogPoller(t), nil, nil, feeEstimatorConfig) require.NoError(t, err) ctx := testutils.Context(t) diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/offramp_reader_unit_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/offramp_reader_unit_test.go index 15c91235b92..a1e7f9e6346 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/offramp_reader_unit_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/offramp_reader_unit_test.go @@ -197,7 +197,7 @@ func Test_LogsAreProperlyMarkedAsFinalized(t *testing.T) { lp.On("IndexedLogsTopicRange", mock.Anything, ExecutionStateChangedEvent, offrampAddress, 1, logpoller.EvmWord(minSeqNr), logpoller.EvmWord(maxSeqNr), evmtypes.Confirmations(0)). Return(inputLogs, nil) - offRamp, err := NewOffRamp(logger.Test(t), offrampAddress, evmclimocks.NewClient(t), lp, nil, nil) + offRamp, err := NewOffRamp(logger.Test(t), offrampAddress, evmclimocks.NewClient(t), lp, nil, nil, nil) require.NoError(t, err) logs, err := offRamp.GetExecutionStateChangesBetweenSeqNums(testutils.Context(t), minSeqNr, maxSeqNr, 0) require.NoError(t, err) diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/onramp.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/onramp.go index 52f241a30a6..4ae4eeb0d3e 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/onramp.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/onramp.go @@ -2,6 +2,7 @@ package v1_2_0 import ( "context" + "errors" "fmt" "strings" @@ -13,7 +14,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/hashutil" "github.com/smartcontractkit/chainlink-common/pkg/logger" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" - "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/ccip/generated/evm_2_evm_onramp_1_2_0" @@ -50,16 +50,16 @@ var _ ccipdata.OnRampReader = &OnRamp{} // Significant change in 1.2: // - CCIPSendRequested event signature has changed type OnRamp struct { - onRamp *evm_2_evm_onramp_1_2_0.EVM2EVMOnRamp - address common.Address - lggr logger.Logger - lp logpoller.LogPoller - leafHasher ccipdata.LeafHasherInterface[[32]byte] - client client.Client - sendRequestedEventSig common.Hash - sendRequestedSeqNumberWord int - filters []logpoller.Filter - cachedSourcePriceRegistryAddress cache.AutoSync[cciptypes.Address] + onRamp *evm_2_evm_onramp_1_2_0.EVM2EVMOnRamp + address common.Address + lggr logger.Logger + lp logpoller.LogPoller + leafHasher ccipdata.LeafHasherInterface[[32]byte] + client client.Client + sendRequestedEventSig common.Hash + sendRequestedSeqNumberWord int + filters []logpoller.Filter + cachedOnRampDynamicConfig cache.AutoSync[cciptypes.OnRampDynamicConfig] // Static config can be cached, because it's never expected to change. // The only way to change that is through the contract's constructor (redeployment) cachedStaticConfig cache.OnceCtxFunction[evm_2_evm_onramp_1_2_0.EVM2EVMOnRampStaticConfig] @@ -108,7 +108,7 @@ func NewOnRamp(lggr logger.Logger, sourceSelector, destSelector uint64, onRampAd address: onRampAddress, sendRequestedSeqNumberWord: CCIPSendRequestSeqNumIndex, sendRequestedEventSig: CCIPSendRequestEventSig, - cachedSourcePriceRegistryAddress: cache.NewLogpollerEventsBased[cciptypes.Address]( + cachedOnRampDynamicConfig: cache.NewLogpollerEventsBased[cciptypes.OnRampDynamicConfig]( sourceLP, []common.Hash{ConfigSetEventSig}, onRampAddress, @@ -122,38 +122,39 @@ func (o *OnRamp) Address(context.Context) (cciptypes.Address, error) { return cciptypes.Address(o.onRamp.Address().String()), nil } -func (o *OnRamp) GetDynamicConfig(context.Context) (cciptypes.OnRampDynamicConfig, error) { - if o.onRamp == nil { - return cciptypes.OnRampDynamicConfig{}, fmt.Errorf("onramp not initialized") - } - config, err := o.onRamp.GetDynamicConfig(&bind.CallOpts{}) - if err != nil { - return cciptypes.OnRampDynamicConfig{}, fmt.Errorf("get dynamic config v1.2: %w", err) - } - return cciptypes.OnRampDynamicConfig{ - Router: cciptypes.Address(config.Router.String()), - MaxNumberOfTokensPerMsg: config.MaxNumberOfTokensPerMsg, - DestGasOverhead: config.DestGasOverhead, - DestGasPerPayloadByte: config.DestGasPerPayloadByte, - DestDataAvailabilityOverheadGas: config.DestDataAvailabilityOverheadGas, - DestGasPerDataAvailabilityByte: config.DestGasPerDataAvailabilityByte, - DestDataAvailabilityMultiplierBps: config.DestDataAvailabilityMultiplierBps, - PriceRegistry: cciptypes.Address(config.PriceRegistry.String()), - MaxDataBytes: config.MaxDataBytes, - MaxPerMsgGasLimit: config.MaxPerMsgGasLimit, - }, nil -} - -func (o *OnRamp) SourcePriceRegistryAddress(ctx context.Context) (cciptypes.Address, error) { - return o.cachedSourcePriceRegistryAddress.Get(ctx, func(ctx context.Context) (cciptypes.Address, error) { - c, err := o.GetDynamicConfig(ctx) +func (o *OnRamp) GetDynamicConfig(ctx context.Context) (cciptypes.OnRampDynamicConfig, error) { + return o.cachedOnRampDynamicConfig.Get(ctx, func(ctx context.Context) (cciptypes.OnRampDynamicConfig, error) { + if o.onRamp == nil { + return cciptypes.OnRampDynamicConfig{}, errors.New("onramp not initialized") + } + config, err := o.onRamp.GetDynamicConfig(&bind.CallOpts{Context: ctx}) if err != nil { - return "", err + return cciptypes.OnRampDynamicConfig{}, fmt.Errorf("get dynamic config v1.2: %w", err) } - return c.PriceRegistry, nil + + return cciptypes.OnRampDynamicConfig{ + Router: cciptypes.Address(config.Router.String()), + MaxNumberOfTokensPerMsg: config.MaxNumberOfTokensPerMsg, + DestGasOverhead: config.DestGasOverhead, + DestGasPerPayloadByte: config.DestGasPerPayloadByte, + DestDataAvailabilityOverheadGas: config.DestDataAvailabilityOverheadGas, + DestGasPerDataAvailabilityByte: config.DestGasPerDataAvailabilityByte, + DestDataAvailabilityMultiplierBps: config.DestDataAvailabilityMultiplierBps, + PriceRegistry: cciptypes.Address(config.PriceRegistry.String()), + MaxDataBytes: config.MaxDataBytes, + MaxPerMsgGasLimit: config.MaxPerMsgGasLimit, + }, nil }) } +func (o *OnRamp) SourcePriceRegistryAddress(ctx context.Context) (cciptypes.Address, error) { + c, err := o.GetDynamicConfig(ctx) + if err != nil { + return "", err + } + return c.PriceRegistry, nil +} + func (o *OnRamp) GetSendRequestsBetweenSeqNums(ctx context.Context, seqNumMin, seqNumMax uint64, finalized bool) ([]cciptypes.EVM2EVMMessageWithTxMeta, error) { logs, err := o.lp.LogsDataWordRange( ctx, diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/onramp_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/onramp_test.go index bbdf52e23a4..ec912667ac7 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/onramp_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/onramp_test.go @@ -8,12 +8,11 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" ) @@ -21,7 +20,7 @@ func TestLogPollerClient_GetSendRequestsBetweenSeqNumsV1_2_0(t *testing.T) { onRampAddr := utils.RandomAddress() seqNum := uint64(100) limit := uint64(10) - lggr := logger.Test(t) + lggr := logger.TestLogger(t) tests := []struct { name string diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/price_registry.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/price_registry.go index 636b37c9100..5818f095ea0 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/price_registry.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/price_registry.go @@ -13,7 +13,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/commit_store.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/commit_store.go index fd768d4235c..a403139a015 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/commit_store.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/commit_store.go @@ -3,6 +3,8 @@ package v1_5_0 import ( "context" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" @@ -41,8 +43,14 @@ func (c *CommitStore) IsDown(ctx context.Context) (bool, error) { return !unPausedAndNotCursed, nil } -func NewCommitStore(lggr logger.Logger, addr common.Address, ec client.Client, lp logpoller.LogPoller) (*CommitStore, error) { - v120, err := v1_2_0.NewCommitStore(lggr, addr, ec, lp) +func NewCommitStore( + lggr logger.Logger, + addr common.Address, + ec client.Client, + lp logpoller.LogPoller, + feeEstimatorConfig ccipdata.FeeEstimatorConfigReader, +) (*CommitStore, error) { + v120, err := v1_2_0.NewCommitStore(lggr, addr, ec, lp, feeEstimatorConfig) if err != nil { return nil, err } diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/offramp.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/offramp.go index 0c45f0d6eac..d5e220c27b1 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/offramp.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/offramp.go @@ -70,6 +70,7 @@ type OffRamp struct { *v1_2_0.OffRamp offRampV150 evm_2_evm_offramp.EVM2EVMOffRampInterface cachedRateLimitTokens cache.AutoSync[cciptypes.OffRampTokens] + feeEstimatorConfig ccipdata.FeeEstimatorConfigReader } // GetTokens Returns no data as the offRamps no longer have this information. @@ -155,7 +156,7 @@ func (o *OffRamp) ChangeConfig(ctx context.Context, onchainConfigBytes []byte, o PermissionLessExecutionThresholdSeconds: time.Second * time.Duration(onchainConfigParsed.PermissionLessExecutionThresholdSeconds), Router: cciptypes.Address(onchainConfigParsed.Router.String()), } - priceEstimator := prices.NewDAGasPriceEstimator(o.Estimator, o.DestMaxGasPrice, 0, 0) + priceEstimator := prices.NewDAGasPriceEstimator(o.Estimator, o.DestMaxGasPrice, 0, 0, o.feeEstimatorConfig) o.UpdateDynamicConfig(onchainConfig, offchainConfig, priceEstimator) @@ -166,8 +167,16 @@ func (o *OffRamp) ChangeConfig(ctx context.Context, onchainConfigBytes []byte, o cciptypes.Address(destWrappedNative.String()), nil } -func NewOffRamp(lggr logger.Logger, addr common.Address, ec client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator, destMaxGasPrice *big.Int) (*OffRamp, error) { - v120, err := v1_2_0.NewOffRamp(lggr, addr, ec, lp, estimator, destMaxGasPrice) +func NewOffRamp( + lggr logger.Logger, + addr common.Address, + ec client.Client, + lp logpoller.LogPoller, + estimator gas.EvmFeeEstimator, + destMaxGasPrice *big.Int, + feeEstimatorConfig ccipdata.FeeEstimatorConfigReader, +) (*OffRamp, error) { + v120, err := v1_2_0.NewOffRamp(lggr, addr, ec, lp, estimator, destMaxGasPrice, feeEstimatorConfig) if err != nil { return nil, err } @@ -180,8 +189,9 @@ func NewOffRamp(lggr logger.Logger, addr common.Address, ec client.Client, lp lo v120.ExecutionReportArgs = abihelpers.MustGetMethodInputs("manuallyExecute", abiOffRamp)[:1] return &OffRamp{ - OffRamp: v120, - offRampV150: offRamp, + feeEstimatorConfig: feeEstimatorConfig, + OffRamp: v120, + offRampV150: offRamp, cachedRateLimitTokens: cache.NewLogpollerEventsBased[cciptypes.OffRampTokens]( lp, []common.Hash{RateLimitTokenAddedEvent, RateLimitTokenRemovedEvent}, diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/onramp.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/onramp.go index da41d116bc8..6329c8af672 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/onramp.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/onramp.go @@ -2,6 +2,7 @@ package v1_5_0 import ( "context" + "errors" "fmt" "strings" @@ -50,17 +51,17 @@ func init() { var _ ccipdata.OnRampReader = &OnRamp{} type OnRamp struct { - onRamp *evm_2_evm_onramp.EVM2EVMOnRamp - address common.Address - destChainSelectorBytes [16]byte - lggr logger.Logger - lp logpoller.LogPoller - leafHasher ccipdata.LeafHasherInterface[[32]byte] - client client.Client - sendRequestedEventSig common.Hash - sendRequestedSeqNumberWord int - filters []logpoller.Filter - cachedSourcePriceRegistryAddress cache.AutoSync[cciptypes.Address] + onRamp *evm_2_evm_onramp.EVM2EVMOnRamp + address common.Address + destChainSelectorBytes [16]byte + lggr logger.Logger + lp logpoller.LogPoller + leafHasher ccipdata.LeafHasherInterface[[32]byte] + client client.Client + sendRequestedEventSig common.Hash + sendRequestedSeqNumberWord int + filters []logpoller.Filter + cachedOnRampDynamicConfig cache.AutoSync[cciptypes.OnRampDynamicConfig] // Static config can be cached, because it's never expected to change. // The only way to change that is through the contract's constructor (redeployment) cachedStaticConfig cache.OnceCtxFunction[evm_2_evm_onramp.EVM2EVMOnRampStaticConfig] @@ -112,7 +113,7 @@ func NewOnRamp(lggr logger.Logger, sourceSelector, destSelector uint64, onRampAd address: onRampAddress, sendRequestedSeqNumberWord: CCIPSendRequestSeqNumIndex, sendRequestedEventSig: CCIPSendRequestEventSig, - cachedSourcePriceRegistryAddress: cache.NewLogpollerEventsBased[cciptypes.Address]( + cachedOnRampDynamicConfig: cache.NewLogpollerEventsBased[cciptypes.OnRampDynamicConfig]( sourceLP, []common.Hash{ConfigSetEventSig}, onRampAddress, @@ -126,38 +127,39 @@ func (o *OnRamp) Address(context.Context) (cciptypes.Address, error) { return ccipcalc.EvmAddrToGeneric(o.onRamp.Address()), nil } -func (o *OnRamp) GetDynamicConfig(context.Context) (cciptypes.OnRampDynamicConfig, error) { - if o.onRamp == nil { - return cciptypes.OnRampDynamicConfig{}, fmt.Errorf("onramp not initialized") - } - config, err := o.onRamp.GetDynamicConfig(&bind.CallOpts{}) - if err != nil { - return cciptypes.OnRampDynamicConfig{}, fmt.Errorf("get dynamic config v1.5: %w", err) - } - return cciptypes.OnRampDynamicConfig{ - Router: ccipcalc.EvmAddrToGeneric(config.Router), - MaxNumberOfTokensPerMsg: config.MaxNumberOfTokensPerMsg, - DestGasOverhead: config.DestGasOverhead, - DestGasPerPayloadByte: config.DestGasPerPayloadByte, - DestDataAvailabilityOverheadGas: config.DestDataAvailabilityOverheadGas, - DestGasPerDataAvailabilityByte: config.DestGasPerDataAvailabilityByte, - DestDataAvailabilityMultiplierBps: config.DestDataAvailabilityMultiplierBps, - PriceRegistry: ccipcalc.EvmAddrToGeneric(config.PriceRegistry), - MaxDataBytes: config.MaxDataBytes, - MaxPerMsgGasLimit: config.MaxPerMsgGasLimit, - }, nil -} - -func (o *OnRamp) SourcePriceRegistryAddress(ctx context.Context) (cciptypes.Address, error) { - return o.cachedSourcePriceRegistryAddress.Get(ctx, func(ctx context.Context) (cciptypes.Address, error) { - c, err := o.GetDynamicConfig(ctx) +func (o *OnRamp) GetDynamicConfig(ctx context.Context) (cciptypes.OnRampDynamicConfig, error) { + return o.cachedOnRampDynamicConfig.Get(ctx, func(ctx context.Context) (cciptypes.OnRampDynamicConfig, error) { + if o.onRamp == nil { + return cciptypes.OnRampDynamicConfig{}, errors.New("onramp not initialized") + } + config, err := o.onRamp.GetDynamicConfig(&bind.CallOpts{}) if err != nil { - return "", err + return cciptypes.OnRampDynamicConfig{}, fmt.Errorf("get dynamic config v1.5: %w", err) } - return c.PriceRegistry, nil + + return cciptypes.OnRampDynamicConfig{ + Router: ccipcalc.EvmAddrToGeneric(config.Router), + MaxNumberOfTokensPerMsg: config.MaxNumberOfTokensPerMsg, + DestGasOverhead: config.DestGasOverhead, + DestGasPerPayloadByte: config.DestGasPerPayloadByte, + DestDataAvailabilityOverheadGas: config.DestDataAvailabilityOverheadGas, + DestGasPerDataAvailabilityByte: config.DestGasPerDataAvailabilityByte, + DestDataAvailabilityMultiplierBps: config.DestDataAvailabilityMultiplierBps, + PriceRegistry: ccipcalc.EvmAddrToGeneric(config.PriceRegistry), + MaxDataBytes: config.MaxDataBytes, + MaxPerMsgGasLimit: config.MaxPerMsgGasLimit, + }, nil }) } +func (o *OnRamp) SourcePriceRegistryAddress(ctx context.Context) (cciptypes.Address, error) { + c, err := o.GetDynamicConfig(ctx) + if err != nil { + return "", err + } + return c.PriceRegistry, nil +} + func (o *OnRamp) GetSendRequestsBetweenSeqNums(ctx context.Context, seqNumMin, seqNumMax uint64, finalized bool) ([]cciptypes.EVM2EVMMessageWithTxMeta, error) { logs, err := o.lp.LogsDataWordRange( ctx, diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/onramp_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/onramp_test.go index 277b8fd9003..65fccb7821c 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/onramp_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/onramp_test.go @@ -11,7 +11,6 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" @@ -20,6 +19,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_rmn_contract" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcommon" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" @@ -29,7 +29,7 @@ func TestLogPollerClient_GetSendRequestsBetweenSeqNums1_4_0(t *testing.T) { onRampAddr := utils.RandomAddress() seqNum := uint64(100) limit := uint64(10) - lggr := logger.Test(t) + lggr := logger.TestLogger(t) tests := []struct { name string @@ -72,7 +72,7 @@ func Test_ProperlyRecognizesPerLaneCurses(t *testing.T) { sourceChainSelector := uint64(200) onRampAddress, mockRMN, mockRMNAddress := setupOnRampV1_5_0(t, user, bc) - onRamp, err := NewOnRamp(logger.Test(t), 1, destChainSelector, onRampAddress, mocks.NewLogPoller(t), bc) + onRamp, err := NewOnRamp(logger.TestLogger(t), 1, destChainSelector, onRampAddress, mocks.NewLogPoller(t), bc) require.NoError(t, err) onRamp.cachedStaticConfig = func(ctx context.Context) (evm_2_evm_onramp.EVM2EVMOnRampStaticConfig, error) { @@ -121,7 +121,7 @@ func BenchmarkIsSourceCursedWithCache(b *testing.B) { destChainSelector := uint64(100) onRampAddress, _, _ := setupOnRampV1_5_0(b, user, bc) - onRamp, err := NewOnRamp(logger.Test(b), 1, destChainSelector, onRampAddress, mocks.NewLogPoller(b), bc) + onRamp, err := NewOnRamp(logger.TestLogger(b), 1, destChainSelector, onRampAddress, mocks.NewLogPoller(b), bc) require.NoError(b, err) for i := 0; i < b.N; i++ { diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdb/mocks/price_service_mock.go b/core/services/ocr2/plugins/ccip/internal/ccipdb/mocks/price_service_mock.go index 76690f79bf8..8914ca0b987 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdb/mocks/price_service_mock.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdb/mocks/price_service_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -28,7 +28,7 @@ func (_m *PriceService) EXPECT() *PriceService_Expecter { return &PriceService_Expecter{mock: &_m.Mock} } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *PriceService) Close() error { ret := _m.Called() diff --git a/core/services/ocr2/plugins/ccip/internal/pricegetter/all_price_getter_mock.go b/core/services/ocr2/plugins/ccip/internal/pricegetter/all_price_getter_mock.go index 8281137e524..d05b14b67d2 100644 --- a/core/services/ocr2/plugins/ccip/internal/pricegetter/all_price_getter_mock.go +++ b/core/services/ocr2/plugins/ccip/internal/pricegetter/all_price_getter_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package pricegetter @@ -24,7 +24,7 @@ func (_m *MockAllTokensPriceGetter) EXPECT() *MockAllTokensPriceGetter_Expecter return &MockAllTokensPriceGetter_Expecter{mock: &_m.Mock} } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *MockAllTokensPriceGetter) Close() error { ret := _m.Called() diff --git a/core/services/ocr2/plugins/ccip/internal/pricegetter/evm.go b/core/services/ocr2/plugins/ccip/internal/pricegetter/evm.go index ac4002f53fb..732bbb6be4c 100644 --- a/core/services/ocr2/plugins/ccip/internal/pricegetter/evm.go +++ b/core/services/ocr2/plugins/ccip/internal/pricegetter/evm.go @@ -7,20 +7,23 @@ import ( "math/big" "strings" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/rpclib" - "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" + "go.uber.org/multierr" + "github.com/smartcontractkit/chainlink-common/pkg/types" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/aggregator_v3_interface" "github.com/smartcontractkit/chainlink/v2/core/internal/gethwrappers2/generated/offchainaggregator" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcalc" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/rpclib" ) -const decimalsMethodName = "decimals" -const latestRoundDataMethodName = "latestRoundData" +const OffchainAggregator = "OffchainAggregator" +const DecimalsMethodName = "decimals" +const LatestRoundDataMethodName = "latestRoundData" func init() { // Ensure existence of latestRoundData method on the Aggregator contract. @@ -28,8 +31,8 @@ func init() { if err != nil { panic(err) } - ensureMethodOnContract(aggregatorABI, decimalsMethodName) - ensureMethodOnContract(aggregatorABI, latestRoundDataMethodName) + ensureMethodOnContract(aggregatorABI, DecimalsMethodName) + ensureMethodOnContract(aggregatorABI, LatestRoundDataMethodName) } func ensureMethodOnContract(abi abi.ABI, methodName string) { @@ -49,9 +52,9 @@ func NewDynamicPriceGetterClient(batchCaller rpclib.EvmBatchCaller) DynamicPrice } type DynamicPriceGetter struct { - cfg config.DynamicPriceGetterConfig - evmClients map[uint64]DynamicPriceGetterClient - aggregatorAbi abi.ABI + cfg config.DynamicPriceGetterConfig + contractReaders map[uint64]types.ContractReader + aggregatorAbi abi.ABI } func NewDynamicPriceGetterConfig(configJson string) (config.DynamicPriceGetterConfig, error) { @@ -69,7 +72,7 @@ func NewDynamicPriceGetterConfig(configJson string) (config.DynamicPriceGetterCo // NewDynamicPriceGetter build a DynamicPriceGetter from a configuration and a map of chain ID to batch callers. // A batch caller should be provided for all retrieved prices. -func NewDynamicPriceGetter(cfg config.DynamicPriceGetterConfig, evmClients map[uint64]DynamicPriceGetterClient) (*DynamicPriceGetter, error) { +func NewDynamicPriceGetter(cfg config.DynamicPriceGetterConfig, contractReaders map[uint64]types.ContractReader) (*DynamicPriceGetter, error) { if err := cfg.Validate(); err != nil { return nil, fmt.Errorf("validating dynamic price getter config: %w", err) } @@ -77,13 +80,13 @@ func NewDynamicPriceGetter(cfg config.DynamicPriceGetterConfig, evmClients map[u if err != nil { return nil, fmt.Errorf("parsing offchainaggregator abi: %w", err) } - priceGetter := DynamicPriceGetter{cfg, evmClients, aggregatorAbi} + priceGetter := DynamicPriceGetter{cfg, contractReaders, aggregatorAbi} return &priceGetter, nil } // FilterConfiguredTokens implements the PriceGetter interface. // It filters a list of token addresses for only those that have a price resolution rule configured on the PriceGetterConfig -func (d *DynamicPriceGetter) FilterConfiguredTokens(ctx context.Context, tokens []cciptypes.Address) (configured []cciptypes.Address, unconfigured []cciptypes.Address, err error) { +func (d *DynamicPriceGetter) FilterConfiguredTokens(_ context.Context, tokens []cciptypes.Address) (configured []cciptypes.Address, unconfigured []cciptypes.Address, err error) { configured = []cciptypes.Address{} unconfigured = []cciptypes.Address{} for _, tk := range tokens { @@ -103,7 +106,7 @@ func (d *DynamicPriceGetter) FilterConfiguredTokens(ctx context.Context, tokens return configured, unconfigured, nil } -// It returns the prices of all tokens defined in the price getter. +// GetJobSpecTokenPricesUSD returns the prices of all tokens defined in the price getter. func (d *DynamicPriceGetter) GetJobSpecTokenPricesUSD(ctx context.Context) (map[cciptypes.Address]*big.Int, error) { return d.TokenPricesUSD(ctx, d.getAllTokensDefined()) } @@ -144,60 +147,113 @@ func (d *DynamicPriceGetter) performBatchCalls(ctx context.Context, batchCallsPe } // performBatchCall performs a batch call on a given chain to retrieve token prices. -func (d *DynamicPriceGetter) performBatchCall(ctx context.Context, chainID uint64, batchCalls *batchCallsForChain, prices map[cciptypes.Address]*big.Int) error { - // Retrieve the EVM caller for the chain. - client, exists := d.evmClients[chainID] - if !exists { - return fmt.Errorf("evm caller for chain %d not found", chainID) - } - evmCaller := client.BatchCaller - +func (d *DynamicPriceGetter) performBatchCall(ctx context.Context, chainID uint64, batchCalls *batchCallsForChain, prices map[cciptypes.Address]*big.Int) (err error) { nbDecimalCalls := len(batchCalls.decimalCalls) nbLatestRoundDataCalls := len(batchCalls.decimalCalls) + nbCalls := len(batchCalls.decimalCalls) - // Perform batched call (all decimals calls followed by latest round data calls). - calls := make([]rpclib.EvmCall, 0, nbDecimalCalls+nbLatestRoundDataCalls) - calls = append(calls, batchCalls.decimalCalls...) - calls = append(calls, batchCalls.latestRoundDataCalls...) + // Retrieve contract reader for the chain + contractReader := d.contractReaders[chainID] - results, err := evmCaller.BatchCall(ctx, 0, calls) + // Bind contract reader to the contract addresses necessary for the batch calls + bindings := make([]types.BoundContract, 0) + for i, call := range batchCalls.decimalCalls { + bindings = append(bindings, types.BoundContract{ + Address: string(ccipcalc.EvmAddrToGeneric(call.ContractAddress())), + Name: fmt.Sprintf("%v_%v", OffchainAggregator, i), + }) + } + + err = contractReader.Bind(ctx, bindings) if err != nil { - return fmt.Errorf("batch call on chain %d failed: %w", chainID, err) + return fmt.Errorf("binding contracts failed: %w", err) } - // Extract results. - decimals := make([]uint8, 0, nbDecimalCalls) - latestRounds := make([]*big.Int, 0, nbLatestRoundDataCalls) + // Construct request, adding a decimals and latestRound req per contract name + var decimalsReq uint8 + batchGetLatestValuesRequest := make(types.BatchGetLatestValuesRequest) + for i, call := range batchCalls.decimalCalls { + boundContract := types.BoundContract{ + Address: call.ContractAddress().Hex(), + Name: fmt.Sprintf("%v_%v", OffchainAggregator, i), + } + batchGetLatestValuesRequest[boundContract] = append(batchGetLatestValuesRequest[boundContract], types.BatchRead{ + ReadName: call.MethodName(), + ReturnVal: &decimalsReq, + }) + } - for i, res := range results[0:nbDecimalCalls] { - v, err1 := rpclib.ParseOutput[uint8](res, 0) - if err1 != nil { - callSignature := batchCalls.decimalCalls[i].String() - return fmt.Errorf("parse contract output while calling %v on chain %d: %w", callSignature, chainID, err1) + for i, call := range batchCalls.latestRoundDataCalls { + boundContract := types.BoundContract{ + Address: call.ContractAddress().Hex(), + Name: fmt.Sprintf("%v_%v", OffchainAggregator, i), } - decimals = append(decimals, v) + batchGetLatestValuesRequest[boundContract] = append(batchGetLatestValuesRequest[boundContract], types.BatchRead{ + ReadName: call.MethodName(), + ReturnVal: &aggregator_v3_interface.LatestRoundData{}, + }) + } + + // Perform call + result, err2 := contractReader.BatchGetLatestValues(ctx, batchGetLatestValuesRequest) + if err2 != nil { + return fmt.Errorf("BatchGetLatestValues failed %w", err2) } - for i, res := range results[nbDecimalCalls : nbDecimalCalls+nbLatestRoundDataCalls] { - // latestRoundData function has multiple outputs (roundId,answer,startedAt,updatedAt,answeredInRound). - // we want the second one (answer, at idx=1). - v, err1 := rpclib.ParseOutput[*big.Int](res, 1) - if err1 != nil { - callSignature := batchCalls.latestRoundDataCalls[i].String() - return fmt.Errorf("parse contract output while calling %v on chain %d: %w", callSignature, chainID, err1) + // Extract results + // give result the contract name (key ordering not guaranteed to match that of the request) + // and then you get slice of responses + decimalsCR := make([]uint8, 0, nbDecimalCalls) + latestRoundCR := make([]aggregator_v3_interface.LatestRoundData, 0, nbDecimalCalls) + var respErr error + for j := range nbCalls { + boundContract := types.BoundContract{ + Address: batchCalls.decimalCalls[j].ContractAddress().Hex(), + Name: fmt.Sprintf("%v_%v", OffchainAggregator, j), } - latestRounds = append(latestRounds, v) + offchainAggregatorRespSlice := result[boundContract] + + for _, read := range offchainAggregatorRespSlice { + val, readErr := read.GetResult() + if readErr != nil { + respErr = multierr.Append(respErr, fmt.Errorf("error with contract reader readName %v: %w", read.ReadName, readErr)) + continue + } + if read.ReadName == DecimalsMethodName { + decimal, ok := val.(*uint8) + if !ok { + return fmt.Errorf("expected type uint8 for method call %v on contract %v: %w", batchCalls.decimalCalls[j].MethodName(), batchCalls.decimalCalls[j].ContractAddress(), readErr) + } + + decimalsCR = append(decimalsCR, *decimal) + } else if read.ReadName == LatestRoundDataMethodName { + latestRoundDataRes, ok := val.(*aggregator_v3_interface.LatestRoundData) + if !ok { + return fmt.Errorf("expected type latestRoundDataConfig for method call %v on contract %v: %w", batchCalls.latestRoundDataCalls[j].MethodName(), batchCalls.latestRoundDataCalls[j].ContractAddress(), readErr) + } + + latestRoundCR = append(latestRoundCR, *latestRoundDataRes) + } + } + } + if respErr != nil { + return respErr + } + + latestRoundAnswerCR := make([]*big.Int, 0, nbLatestRoundDataCalls) + for i := range nbLatestRoundDataCalls { + latestRoundAnswerCR = append(latestRoundAnswerCR, latestRoundCR[i].Answer) } // Normalize and store prices. for i := range batchCalls.tokenOrder { // Normalize to 1e18. - if decimals[i] < 18 { - latestRounds[i].Mul(latestRounds[i], big.NewInt(0).Exp(big.NewInt(10), big.NewInt(18-int64(decimals[i])), nil)) - } else if decimals[i] > 18 { - latestRounds[i].Div(latestRounds[i], big.NewInt(0).Exp(big.NewInt(10), big.NewInt(int64(decimals[i])-18), nil)) + if decimalsCR[i] < 18 { + latestRoundAnswerCR[i].Mul(latestRoundAnswerCR[i], big.NewInt(0).Exp(big.NewInt(10), big.NewInt(18-int64(decimalsCR[i])), nil)) + } else if decimalsCR[i] > 18 { + latestRoundAnswerCR[i].Div(latestRoundAnswerCR[i], big.NewInt(0).Exp(big.NewInt(10), big.NewInt(int64(decimalsCR[i])-18), nil)) } - prices[ccipcalc.EvmAddrToGeneric(batchCalls.tokenOrder[i])] = latestRounds[i] + prices[ccipcalc.EvmAddrToGeneric(batchCalls.tokenOrder[i])] = latestRoundAnswerCR[i] } return nil } @@ -225,12 +281,12 @@ func (d *DynamicPriceGetter) preparePricesAndBatchCallsPerChain(tokens []cciptyp chainCalls := batchCallsPerChain[aggCfg.ChainID] chainCalls.decimalCalls = append(chainCalls.decimalCalls, rpclib.NewEvmCall( d.aggregatorAbi, - decimalsMethodName, + DecimalsMethodName, aggCfg.AggregatorContractAddress, )) chainCalls.latestRoundDataCalls = append(chainCalls.latestRoundDataCalls, rpclib.NewEvmCall( d.aggregatorAbi, - latestRoundDataMethodName, + LatestRoundDataMethodName, aggCfg.AggregatorContractAddress, )) chainCalls.tokenOrder = append(chainCalls.tokenOrder, tk) diff --git a/core/services/ocr2/plugins/ccip/internal/pricegetter/evm_test.go b/core/services/ocr2/plugins/ccip/internal/pricegetter/evm_test.go index 78de2699688..ada59d68573 100644 --- a/core/services/ocr2/plugins/ccip/internal/pricegetter/evm_test.go +++ b/core/services/ocr2/plugins/ccip/internal/pricegetter/evm_test.go @@ -1,28 +1,29 @@ package pricegetter import ( + "context" + "fmt" "math/big" "testing" + "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/aggregator_v3_interface" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/aggregator_v3_interface" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcalc" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/rpclib" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/rpclib/rpclibmocks" ) type testParameters struct { cfg config.DynamicPriceGetterConfig - evmClients map[uint64]DynamicPriceGetterClient + contractReaders map[uint64]types.ContractReader tokens []common.Address expectedTokenPrices map[common.Address]big.Int expectedTokenPricesForAll map[common.Address]big.Int @@ -92,13 +93,13 @@ func TestDynamicPriceGetterWithEmptyInput(t *testing.T) { }, { name: "get_all_tokens_static_only", - param: testGetAllTokensStaticOnly(), + param: testGetAllTokensStaticOnly(t), }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - pg, err := NewDynamicPriceGetter(test.param.cfg, test.param.evmClients) + pg, err := NewDynamicPriceGetter(test.param.cfg, test.param.contractReaders) if test.param.invalidConfigErrorExpected { require.Error(t, err) return @@ -194,11 +195,11 @@ func testParamAggregatorOnly(t *testing.T) testParameters { UpdatedAt: big.NewInt(1715753907), AnsweredInRound: big.NewInt(4000), } - evmClients := map[uint64]DynamicPriceGetterClient{ - uint64(101): mockClient(t, []uint8{8}, []aggregator_v3_interface.LatestRoundData{round1}), - uint64(102): mockClient(t, []uint8{8}, []aggregator_v3_interface.LatestRoundData{round2}), - uint64(103): mockClient(t, []uint8{18}, []aggregator_v3_interface.LatestRoundData{round3}), - uint64(104): mockClient(t, []uint8{20}, []aggregator_v3_interface.LatestRoundData{round4}), + contractReaders := map[uint64]types.ContractReader{ + uint64(101): mockCR([]uint8{8}, cfg, []common.Address{TK1}, []aggregator_v3_interface.LatestRoundData{round1}), + uint64(102): mockCR([]uint8{8}, cfg, []common.Address{TK2}, []aggregator_v3_interface.LatestRoundData{round2}), + uint64(103): mockCR([]uint8{18}, cfg, []common.Address{TK3}, []aggregator_v3_interface.LatestRoundData{round3}), + uint64(104): mockCR([]uint8{20}, cfg, []common.Address{TK4}, []aggregator_v3_interface.LatestRoundData{round4}), } expectedTokenPrices := map[common.Address]big.Int{ TK1: *multExp(round1.Answer, 10), // expected in 1e18 format. @@ -208,7 +209,7 @@ func testParamAggregatorOnly(t *testing.T) testParameters { } return testParameters{ cfg: cfg, - evmClients: evmClients, + contractReaders: contractReaders, tokens: []common.Address{TK1, TK2, TK3, TK4}, expectedTokenPrices: expectedTokenPrices, invalidConfigErrorExpected: false, @@ -257,9 +258,9 @@ func testParamAggregatorOnlyMulti(t *testing.T) testParameters { UpdatedAt: big.NewInt(1704897198), AnsweredInRound: big.NewInt(3000), } - evmClients := map[uint64]DynamicPriceGetterClient{ - uint64(101): mockClient(t, []uint8{8}, []aggregator_v3_interface.LatestRoundData{round1}), - uint64(102): mockClient(t, []uint8{8, 8}, []aggregator_v3_interface.LatestRoundData{round2, round3}), + contractReaders := map[uint64]types.ContractReader{ + uint64(101): mockCR([]uint8{8}, cfg, []common.Address{TK1}, []aggregator_v3_interface.LatestRoundData{round1}), + uint64(102): mockCR([]uint8{8, 8}, cfg, []common.Address{TK2, TK3}, []aggregator_v3_interface.LatestRoundData{round2, round3}), } expectedTokenPrices := map[common.Address]big.Int{ TK1: *multExp(round1.Answer, 10), @@ -268,7 +269,7 @@ func testParamAggregatorOnlyMulti(t *testing.T) testParameters { } return testParameters{ cfg: cfg, - evmClients: evmClients, + contractReaders: contractReaders, invalidConfigErrorExpected: false, tokens: []common.Address{TK1, TK2, TK3}, expectedTokenPrices: expectedTokenPrices, @@ -294,7 +295,7 @@ func testParamStaticOnly() testParameters { }, } // Real LINK/USD example from OP. - evmClients := map[uint64]DynamicPriceGetterClient{} + contractReaders := map[uint64]types.ContractReader{} expectedTokenPrices := map[common.Address]big.Int{ TK1: *cfg.StaticPrices[TK1].Price, TK2: *cfg.StaticPrices[TK2].Price, @@ -302,7 +303,7 @@ func testParamStaticOnly() testParameters { } return testParameters{ cfg: cfg, - evmClients: evmClients, + contractReaders: contractReaders, tokens: []common.Address{TK1, TK2, TK3}, expectedTokenPrices: expectedTokenPrices, } @@ -343,9 +344,9 @@ func testParamNoAggregatorForToken(t *testing.T) testParameters { UpdatedAt: big.NewInt(1704897197), AnsweredInRound: big.NewInt(2000), } - evmClients := map[uint64]DynamicPriceGetterClient{ - uint64(101): mockClient(t, []uint8{8}, []aggregator_v3_interface.LatestRoundData{round1}), - uint64(102): mockClient(t, []uint8{8}, []aggregator_v3_interface.LatestRoundData{round2}), + contractReaders := map[uint64]types.ContractReader{ + uint64(101): mockCR([]uint8{8}, cfg, []common.Address{TK1}, []aggregator_v3_interface.LatestRoundData{round1}), + uint64(102): mockCR([]uint8{8}, cfg, []common.Address{TK2}, []aggregator_v3_interface.LatestRoundData{round2}), } expectedTokenPrices := map[common.Address]big.Int{ TK1: *round1.Answer, @@ -355,7 +356,7 @@ func testParamNoAggregatorForToken(t *testing.T) testParameters { } return testParameters{ cfg: cfg, - evmClients: evmClients, + contractReaders: contractReaders, tokens: []common.Address{TK1, TK2, TK3, TK4}, expectedTokenPrices: expectedTokenPrices, priceResolutionErrorExpected: true, @@ -397,9 +398,9 @@ func testParamAggregatorAndStaticValid(t *testing.T) testParameters { UpdatedAt: big.NewInt(1704897197), AnsweredInRound: big.NewInt(2000), } - evmClients := map[uint64]DynamicPriceGetterClient{ - uint64(101): mockClient(t, []uint8{8}, []aggregator_v3_interface.LatestRoundData{round1}), - uint64(102): mockClient(t, []uint8{8}, []aggregator_v3_interface.LatestRoundData{round2}), + contractReaders := map[uint64]types.ContractReader{ + uint64(101): mockCR([]uint8{8}, cfg, []common.Address{TK1}, []aggregator_v3_interface.LatestRoundData{round1}), + uint64(102): mockCR([]uint8{8}, cfg, []common.Address{TK2}, []aggregator_v3_interface.LatestRoundData{round2}), } expectedTokenPrices := map[common.Address]big.Int{ TK1: *multExp(round1.Answer, 10), @@ -408,7 +409,7 @@ func testParamAggregatorAndStaticValid(t *testing.T) testParameters { } return testParameters{ cfg: cfg, - evmClients: evmClients, + contractReaders: contractReaders, tokens: []common.Address{TK1, TK2, TK3}, expectedTokenPrices: expectedTokenPrices, } @@ -460,14 +461,14 @@ func testParamAggregatorAndStaticTokenCollision(t *testing.T) testParameters { UpdatedAt: big.NewInt(1704897198), AnsweredInRound: big.NewInt(3000), } - evmClients := map[uint64]DynamicPriceGetterClient{ - uint64(101): mockClient(t, []uint8{8}, []aggregator_v3_interface.LatestRoundData{round1}), - uint64(102): mockClient(t, []uint8{8}, []aggregator_v3_interface.LatestRoundData{round2}), - uint64(103): mockClient(t, []uint8{8}, []aggregator_v3_interface.LatestRoundData{round3}), + contractReaders := map[uint64]types.ContractReader{ + uint64(101): mockCR([]uint8{8}, cfg, []common.Address{TK1}, []aggregator_v3_interface.LatestRoundData{round1}), + uint64(102): mockCR([]uint8{8}, cfg, []common.Address{TK2}, []aggregator_v3_interface.LatestRoundData{round2}), + uint64(103): mockCR([]uint8{8}, cfg, []common.Address{TK3}, []aggregator_v3_interface.LatestRoundData{round3}), } return testParameters{ cfg: cfg, - evmClients: evmClients, + contractReaders: contractReaders, tokens: []common.Address{TK1, TK2, TK3}, invalidConfigErrorExpected: true, } @@ -500,17 +501,15 @@ func testParamBatchCallReturnsErr(t *testing.T) testParameters { UpdatedAt: big.NewInt(1704896575), AnsweredInRound: big.NewInt(1000), } - evmClients := map[uint64]DynamicPriceGetterClient{ - uint64(101): mockClient(t, []uint8{8}, []aggregator_v3_interface.LatestRoundData{round1}), - uint64(102): { - BatchCaller: mockErrCaller(t), - }, + contractReaders := map[uint64]types.ContractReader{ + uint64(101): mockCR([]uint8{8}, cfg, []common.Address{TK1}, []aggregator_v3_interface.LatestRoundData{round1}), + uint64(102): mockErrCR(), } return testParameters{ - cfg: cfg, - evmClients: evmClients, - tokens: []common.Address{TK1, TK2, TK3}, - evmCallErr: true, + cfg: cfg, + contractReaders: contractReaders, + tokens: []common.Address{TK1, TK2, TK3}, + evmCallErr: true, } } @@ -561,10 +560,10 @@ func testLessInputsThanDefinedPrices(t *testing.T) testParameters { UpdatedAt: big.NewInt(1715743907), AnsweredInRound: big.NewInt(3000), } - evmClients := map[uint64]DynamicPriceGetterClient{ - uint64(101): mockClient(t, []uint8{8}, []aggregator_v3_interface.LatestRoundData{round1}), - uint64(102): mockClient(t, []uint8{8}, []aggregator_v3_interface.LatestRoundData{round2}), - uint64(103): mockClient(t, []uint8{8}, []aggregator_v3_interface.LatestRoundData{round3}), + contractReaders := map[uint64]types.ContractReader{ + uint64(101): mockCR([]uint8{8}, cfg, []common.Address{TK1}, []aggregator_v3_interface.LatestRoundData{round1}), + uint64(102): mockCR([]uint8{8}, cfg, []common.Address{TK2}, []aggregator_v3_interface.LatestRoundData{round2}), + uint64(103): mockCR([]uint8{8}, cfg, []common.Address{TK3}, []aggregator_v3_interface.LatestRoundData{round3}), } expectedTokenPrices := map[common.Address]big.Int{ TK1: *multExp(round1.Answer, 10), @@ -573,7 +572,7 @@ func testLessInputsThanDefinedPrices(t *testing.T) testParameters { } return testParameters{ cfg: cfg, - evmClients: evmClients, + contractReaders: contractReaders, tokens: []common.Address{TK1, TK2, TK3}, expectedTokenPrices: expectedTokenPrices, } @@ -626,10 +625,11 @@ func testGetAllTokensAggregatorAndStatic(t *testing.T) testParameters { UpdatedAt: big.NewInt(1715743907), AnsweredInRound: big.NewInt(3000), } - evmClients := map[uint64]DynamicPriceGetterClient{ - uint64(101): mockClient(t, []uint8{8}, []aggregator_v3_interface.LatestRoundData{round1}), - uint64(102): mockClient(t, []uint8{8}, []aggregator_v3_interface.LatestRoundData{round2}), - uint64(103): mockClient(t, []uint8{8}, []aggregator_v3_interface.LatestRoundData{round3}), + + contractReaders := map[uint64]types.ContractReader{ + uint64(101): mockCR([]uint8{8}, cfg, []common.Address{TK1}, []aggregator_v3_interface.LatestRoundData{round1}), + uint64(102): mockCR([]uint8{8}, cfg, []common.Address{TK2}, []aggregator_v3_interface.LatestRoundData{round2}), + uint64(103): mockCR([]uint8{8}, cfg, []common.Address{TK3}, []aggregator_v3_interface.LatestRoundData{round3}), } expectedTokenPricesForAll := map[common.Address]big.Int{ TK1: *multExp(round1.Answer, 10), @@ -639,8 +639,8 @@ func testGetAllTokensAggregatorAndStatic(t *testing.T) testParameters { } return testParameters{ cfg: cfg, - evmClients: evmClients, expectedTokenPricesForAll: expectedTokenPricesForAll, + contractReaders: contractReaders, } } @@ -686,11 +686,12 @@ func testGetAllTokensAggregatorOnly(t *testing.T) testParameters { UpdatedAt: big.NewInt(1715743907), AnsweredInRound: big.NewInt(3000), } - evmClients := map[uint64]DynamicPriceGetterClient{ - uint64(101): mockClient(t, []uint8{8}, []aggregator_v3_interface.LatestRoundData{round1}), - uint64(102): mockClient(t, []uint8{8}, []aggregator_v3_interface.LatestRoundData{round2}), - uint64(103): mockClient(t, []uint8{8}, []aggregator_v3_interface.LatestRoundData{round3}), + contractReaders := map[uint64]types.ContractReader{ + uint64(101): mockCR([]uint8{8}, cfg, []common.Address{TK1}, []aggregator_v3_interface.LatestRoundData{round1}), + uint64(102): mockCR([]uint8{8}, cfg, []common.Address{TK2}, []aggregator_v3_interface.LatestRoundData{round2}), + uint64(103): mockCR([]uint8{8}, cfg, []common.Address{TK3}, []aggregator_v3_interface.LatestRoundData{round3}), } + expectedTokenPricesForAll := map[common.Address]big.Int{ TK1: *multExp(round1.Answer, 10), TK2: *multExp(round2.Answer, 10), @@ -698,12 +699,12 @@ func testGetAllTokensAggregatorOnly(t *testing.T) testParameters { } return testParameters{ cfg: cfg, - evmClients: evmClients, expectedTokenPricesForAll: expectedTokenPricesForAll, + contractReaders: contractReaders, } } -func testGetAllTokensStaticOnly() testParameters { +func testGetAllTokensStaticOnly(t *testing.T) testParameters { cfg := config.DynamicPriceGetterConfig{ AggregatorPrices: map[common.Address]config.AggregatorPriceConfig{}, StaticPrices: map[common.Address]config.StaticPriceConfig{ @@ -722,7 +723,7 @@ func testGetAllTokensStaticOnly() testParameters { }, } - evmClients := map[uint64]DynamicPriceGetterClient{} + contractReaders := map[uint64]types.ContractReader{} expectedTokenPricesForAll := map[common.Address]big.Int{ TK1: *cfg.StaticPrices[TK1].Price, TK2: *cfg.StaticPrices[TK2].Price, @@ -730,43 +731,73 @@ func testGetAllTokensStaticOnly() testParameters { } return testParameters{ cfg: cfg, - evmClients: evmClients, + contractReaders: contractReaders, expectedTokenPricesForAll: expectedTokenPricesForAll, } } -func mockClient(t *testing.T, decimals []uint8, rounds []aggregator_v3_interface.LatestRoundData) DynamicPriceGetterClient { - return DynamicPriceGetterClient{ - BatchCaller: mockCaller(t, decimals, rounds), - } -} - -func mockCaller(t *testing.T, decimals []uint8, rounds []aggregator_v3_interface.LatestRoundData) *rpclibmocks.EvmBatchCaller { - caller := rpclibmocks.NewEvmBatchCaller(t) - +func mockCR(decimals []uint8, cfg config.DynamicPriceGetterConfig, addr []common.Address, rounds []aggregator_v3_interface.LatestRoundData) *mockContractReader { // Mock batch calls per chain: all decimals calls then all latestRoundData calls. - dataAndErrs := make([]rpclib.DataAndErr, 0, len(decimals)+len(rounds)) - for _, d := range decimals { - dataAndErrs = append(dataAndErrs, rpclib.DataAndErr{ - Outputs: []any{d}, - }) + bGLVR := make(types.BatchGetLatestValuesResult) + + for i := range len(decimals) { + boundContract := types.BoundContract{ + Address: cfg.AggregatorPrices[addr[i]].AggregatorContractAddress.Hex(), + Name: fmt.Sprintf("%v_%v", OffchainAggregator, i), + } + bGLVR[boundContract] = types.ContractBatchResults{} + } + for i, d := range decimals { + contractName := fmt.Sprintf("%v_%v", OffchainAggregator, i) + readRes := types.BatchReadResult{ + ReadName: DecimalsMethodName, + } + readRes.SetResult(&d, nil) + boundContract := types.BoundContract{ + Address: cfg.AggregatorPrices[addr[i]].AggregatorContractAddress.Hex(), + Name: contractName, + } + bGLVR[boundContract] = append(bGLVR[boundContract], readRes) } - for _, round := range rounds { - dataAndErrs = append(dataAndErrs, rpclib.DataAndErr{ - Outputs: []any{round.RoundId, round.Answer, round.StartedAt, round.UpdatedAt, round.AnsweredInRound}, - }) + + for i, r := range rounds { + contractName := fmt.Sprintf("%v_%v", OffchainAggregator, i) + readRes := types.BatchReadResult{ + ReadName: LatestRoundDataMethodName, + } + readRes.SetResult(&r, nil) + boundContract := types.BoundContract{ + Address: cfg.AggregatorPrices[addr[i]].AggregatorContractAddress.Hex(), + Name: contractName, + } + bGLVR[boundContract] = append(bGLVR[boundContract], readRes) } - caller.On("BatchCall", mock.Anything, uint64(0), mock.Anything).Return(dataAndErrs, nil).Maybe() - return caller + + return &mockContractReader{result: bGLVR} } -func mockErrCaller(t *testing.T) *rpclibmocks.EvmBatchCaller { - caller := rpclibmocks.NewEvmBatchCaller(t) - caller.On("BatchCall", mock.Anything, uint64(0), mock.Anything).Return(nil, assert.AnError).Maybe() - return caller +func mockErrCR() *mockContractReader { + return &mockContractReader{err: assert.AnError} } // multExp returns the result of multiplying x by 10^e. func multExp(x *big.Int, e int64) *big.Int { return big.NewInt(0).Mul(x, big.NewInt(0).Exp(big.NewInt(10), big.NewInt(e), nil)) } + +type mockContractReader struct { + types.UnimplementedContractReader + result types.BatchGetLatestValuesResult + err error +} + +func (m *mockContractReader) Bind(context.Context, []types.BoundContract) error { + return nil +} + +func (m *mockContractReader) BatchGetLatestValues(context.Context, types.BatchGetLatestValuesRequest) (types.BatchGetLatestValuesResult, error) { + if m.err != nil { + return nil, m.err + } + return m.result, nil +} diff --git a/core/services/ocr2/plugins/ccip/internal/pricegetter/mock.go b/core/services/ocr2/plugins/ccip/internal/pricegetter/mock.go index 6b520864a9f..abebd51494c 100644 --- a/core/services/ocr2/plugins/ccip/internal/pricegetter/mock.go +++ b/core/services/ocr2/plugins/ccip/internal/pricegetter/mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package pricegetter @@ -24,7 +24,7 @@ func (_m *MockPriceGetter) EXPECT() *MockPriceGetter_Expecter { return &MockPriceGetter_Expecter{mock: &_m.Mock} } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *MockPriceGetter) Close() error { ret := _m.Called() diff --git a/core/services/ocr2/plugins/ccip/internal/pricegetter/pipeline.go b/core/services/ocr2/plugins/ccip/internal/pricegetter/pipeline.go index 34977eda9f1..b9effffda15 100644 --- a/core/services/ocr2/plugins/ccip/internal/pricegetter/pipeline.go +++ b/core/services/ocr2/plugins/ccip/internal/pricegetter/pipeline.go @@ -10,8 +10,8 @@ import ( "github.com/google/uuid" "github.com/pkg/errors" + "github.com/smartcontractkit/chainlink-common/pkg/logger" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcalc" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/parseutil" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" diff --git a/core/services/ocr2/plugins/ccip/internal/rpclib/evm.go b/core/services/ocr2/plugins/ccip/internal/rpclib/evm.go index 6c4aabb4355..9fac4595464 100644 --- a/core/services/ocr2/plugins/ccip/internal/rpclib/evm.go +++ b/core/services/ocr2/plugins/ccip/internal/rpclib/evm.go @@ -280,6 +280,10 @@ func (c EvmCall) String() string { return fmt.Sprintf("%s: %s(%+v)", c.contractAddress.String(), c.methodName, c.args) } +func (c EvmCall) ContractAddress() common.Address { + return c.contractAddress +} + func EVMCallsToString(calls []EvmCall) string { callString := "" for _, call := range calls { diff --git a/core/services/ocr2/plugins/ccip/internal/rpclib/rpclibmocks/evm_mock.go b/core/services/ocr2/plugins/ccip/internal/rpclib/rpclibmocks/evm_mock.go index 3fc2f46cb3e..4d1d3b92735 100644 --- a/core/services/ocr2/plugins/ccip/internal/rpclib/rpclibmocks/evm_mock.go +++ b/core/services/ocr2/plugins/ccip/internal/rpclib/rpclibmocks/evm_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package rpclibmocks diff --git a/core/services/ocr2/plugins/ccip/metrics.go b/core/services/ocr2/plugins/ccip/metrics.go index f481b5d447d..9ec9fde316e 100644 --- a/core/services/ocr2/plugins/ccip/metrics.go +++ b/core/services/ocr2/plugins/ccip/metrics.go @@ -20,6 +20,10 @@ var ( Name: "ccip_sequence_number_counter", Help: "Sequence number of the last message processed by the plugin", }, []string{"plugin", "source", "dest", "ocrPhase"}) + newReportingPluginErrorCounter = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "ccip_new_reporting_plugin_error_counter", + Help: "The count of the number of errors when calling NewReportingPlugin", + }, []string{"plugin"}) ) type ocrPhase string @@ -35,6 +39,7 @@ type PluginMetricsCollector interface { NumberOfMessagesBasedOnInterval(phase ocrPhase, seqNrMin, seqNrMax uint64) UnexpiredCommitRoots(count int) SequenceNumber(phase ocrPhase, seqNr uint64) + NewReportingPluginError() } type pluginMetricsCollector struct { @@ -79,6 +84,12 @@ func (p *pluginMetricsCollector) SequenceNumber(phase ocrPhase, seqNr uint64) { Set(float64(seqNr)) } +func (p *pluginMetricsCollector) NewReportingPluginError() { + newReportingPluginErrorCounter. + WithLabelValues(p.pluginName). + Inc() +} + var ( // NoopMetricsCollector is a no-op implementation of PluginMetricsCollector NoopMetricsCollector PluginMetricsCollector = noop{} @@ -97,3 +108,6 @@ func (d noop) UnexpiredCommitRoots(int) { func (d noop) SequenceNumber(ocrPhase, uint64) { } + +func (d noop) NewReportingPluginError() { +} diff --git a/core/services/ocr2/plugins/ccip/metrics_test.go b/core/services/ocr2/plugins/ccip/metrics_test.go index eec67db7dd0..0487df2b28d 100644 --- a/core/services/ocr2/plugins/ccip/metrics_test.go +++ b/core/services/ocr2/plugins/ccip/metrics_test.go @@ -13,6 +13,7 @@ const ( ) func Test_SequenceNumbers(t *testing.T) { + t.Parallel() collector := NewPluginMetricsCollector("test", sourceChainId, destChainId) collector.SequenceNumber(Report, 10) @@ -23,6 +24,7 @@ func Test_SequenceNumbers(t *testing.T) { } func Test_NumberOfMessages(t *testing.T) { + t.Parallel() collector := NewPluginMetricsCollector("test", sourceChainId, destChainId) collector2 := NewPluginMetricsCollector("test2", destChainId, sourceChainId) @@ -37,6 +39,7 @@ func Test_NumberOfMessages(t *testing.T) { } func Test_UnexpiredCommitRoots(t *testing.T) { + t.Parallel() collector := NewPluginMetricsCollector("test", sourceChainId, destChainId) collector.UnexpiredCommitRoots(10) diff --git a/core/services/ocr2/plugins/ccip/observations.go b/core/services/ocr2/plugins/ccip/observations.go index f79d667a550..29fa85021fe 100644 --- a/core/services/ocr2/plugins/ccip/observations.go +++ b/core/services/ocr2/plugins/ccip/observations.go @@ -19,6 +19,10 @@ import ( // Note if a breaking change is introduced to this struct nodes running different versions // will not be able to unmarshal each other's observations. Do not modify unless you // know what you are doing. +// +// IMPORTANT: Both CommitObservation and ExecutionObservation are streamed and processed by Atlas. +// Any change to that struct must be reflected in the Atlas codebase. +// Additionally, you must test if OTI telemetry ingestion works with the new struct on staging environment. type CommitObservation struct { Interval cciptypes.CommitStoreInterval `json:"interval"` TokenPricesUSD map[cciptypes.Address]*big.Int `json:"tokensPerFeeCoin"` @@ -47,6 +51,10 @@ func (o CommitObservation) Marshal() ([]byte, error) { // Note if a breaking change is introduced to this struct nodes running different versions // will not be able to unmarshal each other's observations. Do not modify unless you // know what you are doing. +// +// IMPORTANT: Both CommitObservation and ExecutionObservation are streamed and processed by Atlas. +// Any change to that struct must be reflected in the Atlas codebase. +// Additionally, you must test if OTI telemetry ingestion works with the new struct on staging environment. type ExecutionObservation struct { Messages map[uint64]MsgData `json:"messages"` } diff --git a/core/services/ocr2/plugins/ccip/observations_test.go b/core/services/ocr2/plugins/ccip/observations_test.go index a3143f157d7..c39be8e5a2c 100644 --- a/core/services/ocr2/plugins/ccip/observations_test.go +++ b/core/services/ocr2/plugins/ccip/observations_test.go @@ -22,6 +22,7 @@ import ( ) func TestObservationFilter(t *testing.T) { + t.Parallel() lggr := logger.TestLogger(t) obs1 := CommitObservation{Interval: cciptypes.CommitStoreInterval{Min: 1, Max: 10}} b1, err := obs1.Marshal() @@ -39,6 +40,7 @@ type CommitObservationLegacy struct { } func TestObservationCompat_MultiChainGas(t *testing.T) { + t.Parallel() obsLegacy := CommitObservationLegacy{ Interval: cciptypes.CommitStoreInterval{ Min: 1, @@ -66,6 +68,7 @@ func TestObservationCompat_MultiChainGas(t *testing.T) { } func TestCommitObservationJsonDeserialization(t *testing.T) { + t.Parallel() expectedObservation := CommitObservation{ Interval: cciptypes.CommitStoreInterval{ Min: 1, @@ -93,6 +96,7 @@ func TestCommitObservationJsonDeserialization(t *testing.T) { } func TestCommitObservationMarshal(t *testing.T) { + t.Parallel() obs := CommitObservation{ Interval: cciptypes.CommitStoreInterval{ Min: 1, @@ -120,6 +124,7 @@ func TestCommitObservationMarshal(t *testing.T) { } func TestExecutionObservationJsonDeserialization(t *testing.T) { + t.Parallel() expectedObservation := ExecutionObservation{Messages: map[uint64]MsgData{ 2: {TokenData: tokenData("c")}, 1: {TokenData: tokenData("c")}, @@ -142,6 +147,7 @@ func TestExecutionObservationJsonDeserialization(t *testing.T) { } func TestObservationSize(t *testing.T) { + t.Parallel() testParams := gopter.DefaultTestParameters() testParams.MinSuccessfulTests = 100 p := gopter.NewProperties(testParams) @@ -166,6 +172,7 @@ func TestObservationSize(t *testing.T) { } func TestNewExecutionObservation(t *testing.T) { + t.Parallel() tests := []struct { name string observations []ObservedMessage @@ -222,6 +229,7 @@ func tokenData(value string) [][]byte { } func TestCommitObservationJsonSerializationDeserialization(t *testing.T) { + t.Parallel() jsonEncoded := `{ "interval": { "Min":1, @@ -276,6 +284,7 @@ func TestCommitObservationJsonSerializationDeserialization(t *testing.T) { } func TestAddressEncodingBackwardsCompatibility(t *testing.T) { + t.Parallel() // The intention of this test is to remind including proper formatting of addresses after config is updated. // // The following tests will fail when a new cciptypes.Address field is added or removed. diff --git a/core/services/ocr2/plugins/ccip/prices/da_price_estimator.go b/core/services/ocr2/plugins/ccip/prices/da_price_estimator.go index d0093e5d672..04002002f5c 100644 --- a/core/services/ocr2/plugins/ccip/prices/da_price_estimator.go +++ b/core/services/ocr2/plugins/ccip/prices/da_price_estimator.go @@ -5,6 +5,8 @@ import ( "fmt" "math/big" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" + cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups" @@ -14,11 +16,9 @@ import ( type DAGasPriceEstimator struct { execEstimator GasPriceEstimator l1Oracle rollups.L1Oracle + feeEstimatorConfig ccipdata.FeeEstimatorConfigReader priceEncodingLength uint daDeviationPPB int64 - daOverheadGas int64 - gasPerDAByte int64 - daMultiplier int64 } func NewDAGasPriceEstimator( @@ -26,12 +26,14 @@ func NewDAGasPriceEstimator( maxGasPrice *big.Int, deviationPPB int64, daDeviationPPB int64, + feeEstimatorConfig ccipdata.FeeEstimatorConfigReader, // DA Config Cache updates in the onRamp reader and shares the state ) *DAGasPriceEstimator { return &DAGasPriceEstimator{ execEstimator: NewExecGasPriceEstimator(estimator, maxGasPrice, deviationPPB), l1Oracle: estimator.L1Oracle(), priceEncodingLength: daGasPriceEncodingLength, daDeviationPPB: daDeviationPPB, + feeEstimatorConfig: feeEstimatorConfig, } } @@ -54,7 +56,14 @@ func (g DAGasPriceEstimator) GetGasPrice(ctx context.Context) (*big.Int, error) return nil, err } - if daGasPrice := daGasPriceWei.ToInt(); daGasPrice.Cmp(big.NewInt(0)) > 0 { + daGasPrice := daGasPriceWei.ToInt() + + gasPrice, daGasPrice, err = g.feeEstimatorConfig.ModifyGasPriceComponents(ctx, gasPrice, daGasPrice) + if err != nil { + return nil, fmt.Errorf("gasPrice modification failed: %w", err) + } + + if daGasPrice.Cmp(big.NewInt(0)) > 0 { if daGasPrice.BitLen() > int(g.priceEncodingLength) { return nil, fmt.Errorf("data availability gas price exceeded max range %+v", daGasPrice) } @@ -141,7 +150,10 @@ func (g DAGasPriceEstimator) EstimateMsgCostUSD(ctx context.Context, p *big.Int, // If there is data availability price component, then include data availability cost in fee estimation if daGasPrice.Cmp(big.NewInt(0)) > 0 { - daGasCostUSD := g.estimateDACostUSD(daGasPrice, wrappedNativePrice, msg) + daGasCostUSD, err := g.estimateDACostUSD(daGasPrice, wrappedNativePrice, msg) + if err != nil { + return nil, err + } execCostUSD = new(big.Int).Add(daGasCostUSD, execCostUSD) } return execCostUSD, nil @@ -160,17 +172,22 @@ func (g DAGasPriceEstimator) parseEncodedGasPrice(p *big.Int) (*big.Int, *big.In return daGasPrice, execGasPrice, nil } -func (g DAGasPriceEstimator) estimateDACostUSD(daGasPrice *big.Int, wrappedNativePrice *big.Int, msg cciptypes.EVM2EVMOnRampCCIPSendRequestedWithMeta) *big.Int { +func (g DAGasPriceEstimator) estimateDACostUSD(daGasPrice *big.Int, wrappedNativePrice *big.Int, msg cciptypes.EVM2EVMOnRampCCIPSendRequestedWithMeta) (*big.Int, error) { var sourceTokenDataLen int for _, tokenData := range msg.SourceTokenData { sourceTokenDataLen += len(tokenData) } + daOverheadGas, gasPerDAByte, daMultiplier, err := g.feeEstimatorConfig.GetDataAvailabilityConfig(context.Background()) + if err != nil { + return nil, err + } + dataLen := evmMessageFixedBytes + len(msg.Data) + len(msg.TokenAmounts)*evmMessageBytesPerToken + sourceTokenDataLen - dataGas := big.NewInt(int64(dataLen)*g.gasPerDAByte + g.daOverheadGas) + dataGas := big.NewInt(int64(dataLen)*gasPerDAByte + daOverheadGas) dataGasEstimate := new(big.Int).Mul(dataGas, daGasPrice) - dataGasEstimate = new(big.Int).Div(new(big.Int).Mul(dataGasEstimate, big.NewInt(g.daMultiplier)), big.NewInt(daMultiplierBase)) + dataGasEstimate = new(big.Int).Div(new(big.Int).Mul(dataGasEstimate, big.NewInt(daMultiplier)), big.NewInt(daMultiplierBase)) - return ccipcalc.CalculateUsdPerUnitGas(dataGasEstimate, wrappedNativePrice) + return ccipcalc.CalculateUsdPerUnitGas(dataGasEstimate, wrappedNativePrice), nil } diff --git a/core/services/ocr2/plugins/ccip/prices/da_price_estimator_test.go b/core/services/ocr2/plugins/ccip/prices/da_price_estimator_test.go index 2772042f68d..aadf969eadd 100644 --- a/core/services/ocr2/plugins/ccip/prices/da_price_estimator_test.go +++ b/core/services/ocr2/plugins/ccip/prices/da_price_estimator_test.go @@ -2,16 +2,19 @@ package prices import ( "context" + "errors" "math/big" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups/mocks" + ccipdatamocks "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks" ) func encodeGasPrice(daPrice, execPrice *big.Int) *big.Int { @@ -22,11 +25,13 @@ func TestDAPriceEstimator_GetGasPrice(t *testing.T) { ctx := context.Background() testCases := []struct { - name string - daGasPrice *big.Int - execGasPrice *big.Int - expPrice *big.Int - expErr bool + name string + daGasPrice *big.Int + execGasPrice *big.Int + expPrice *big.Int + modExecGasPrice *big.Int + modDAGasPrice *big.Int + expErr bool }{ { name: "base", @@ -56,6 +61,31 @@ func TestDAPriceEstimator_GetGasPrice(t *testing.T) { expPrice: encodeGasPrice(big.NewInt(1e9), big.NewInt(0)), expErr: false, }, + { + name: "execGasPrice Modified", + daGasPrice: big.NewInt(1e9), + execGasPrice: big.NewInt(0), + modExecGasPrice: big.NewInt(1), + expPrice: encodeGasPrice(big.NewInt(1e9), big.NewInt(1)), + expErr: false, + }, + { + name: "daGasPrice Modified", + daGasPrice: big.NewInt(1e9), + execGasPrice: big.NewInt(0), + modDAGasPrice: big.NewInt(1), + expPrice: encodeGasPrice(big.NewInt(1), big.NewInt(0)), + expErr: false, + }, + { + name: "daGasPrice and execGasPrice Modified", + daGasPrice: big.NewInt(1e9), + execGasPrice: big.NewInt(0), + modDAGasPrice: big.NewInt(1), + modExecGasPrice: big.NewInt(2), + expPrice: encodeGasPrice(big.NewInt(1), big.NewInt(2)), + expErr: false, + }, { name: "price out of bounds", daGasPrice: new(big.Int).Lsh(big.NewInt(1), daGasPriceEncodingLength), @@ -73,10 +103,25 @@ func TestDAPriceEstimator_GetGasPrice(t *testing.T) { l1Oracle := mocks.NewL1Oracle(t) l1Oracle.On("GasPrice", ctx).Return(assets.NewWei(tc.daGasPrice), nil) + feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) + + modRespExecGasPrice := tc.execGasPrice + if tc.modExecGasPrice != nil { + modRespExecGasPrice = tc.modExecGasPrice + } + + modRespDAGasPrice := tc.daGasPrice + if tc.modDAGasPrice != nil { + modRespDAGasPrice = tc.modDAGasPrice + } + feeEstimatorConfig.On("ModifyGasPriceComponents", mock.Anything, tc.execGasPrice, tc.daGasPrice). + Return(modRespExecGasPrice, modRespDAGasPrice, nil) + g := DAGasPriceEstimator{ execEstimator: execEstimator, l1Oracle: l1Oracle, priceEncodingLength: daGasPriceEncodingLength, + feeEstimatorConfig: feeEstimatorConfig, } gasPrice, err := g.GetGasPrice(ctx) @@ -329,14 +374,17 @@ func TestDAPriceEstimator_EstimateMsgCostUSD(t *testing.T) { execCostUSD := big.NewInt(100_000) testCases := []struct { - name string - gasPrice *big.Int - wrappedNativePrice *big.Int - msg cciptypes.EVM2EVMOnRampCCIPSendRequestedWithMeta - daOverheadGas int64 - gasPerDAByte int64 - daMultiplier int64 - expUSD *big.Int + name string + gasPrice *big.Int + wrappedNativePrice *big.Int + msg cciptypes.EVM2EVMOnRampCCIPSendRequestedWithMeta + daOverheadGas int64 + gasPerDAByte int64 + daMultiplier int64 + expUSD *big.Int + onRampConfig cciptypes.OnRampDynamicConfig + execEstimatorResponse []any + execEstimatorErr error }{ { name: "only DA overhead", @@ -349,10 +397,8 @@ func TestDAPriceEstimator_EstimateMsgCostUSD(t *testing.T) { SourceTokenData: [][]byte{}, }, }, - daOverheadGas: 100_000, - gasPerDAByte: 0, - daMultiplier: 10_000, // 1x multiplier - expUSD: new(big.Int).Add(execCostUSD, big.NewInt(100_000e9)), + expUSD: new(big.Int).Add(execCostUSD, big.NewInt(100_000e9)), + execEstimatorResponse: []any{int64(100_000), int64(0), int64(10_000), nil}, }, { name: "include message data gas", @@ -367,10 +413,8 @@ func TestDAPriceEstimator_EstimateMsgCostUSD(t *testing.T) { }, }, }, - daOverheadGas: 100_000, - gasPerDAByte: 16, - daMultiplier: 10_000, // 1x multiplier - expUSD: new(big.Int).Add(execCostUSD, big.NewInt(134_208e9)), + expUSD: new(big.Int).Add(execCostUSD, big.NewInt(134_208e9)), + execEstimatorResponse: []any{int64(100_000), int64(16), int64(10_000), nil}, }, { name: "zero DA price", @@ -383,10 +427,7 @@ func TestDAPriceEstimator_EstimateMsgCostUSD(t *testing.T) { SourceTokenData: [][]byte{}, }, }, - daOverheadGas: 100_000, - gasPerDAByte: 16, - daMultiplier: 10_000, // 1x multiplier - expUSD: execCostUSD, + expUSD: execCostUSD, }, { name: "double native price", @@ -399,10 +440,8 @@ func TestDAPriceEstimator_EstimateMsgCostUSD(t *testing.T) { SourceTokenData: [][]byte{}, }, }, - daOverheadGas: 100_000, - gasPerDAByte: 0, - daMultiplier: 10_000, // 1x multiplier - expUSD: new(big.Int).Add(execCostUSD, big.NewInt(200_000e9)), + expUSD: new(big.Int).Add(execCostUSD, big.NewInt(200_000e9)), + execEstimatorResponse: []any{int64(100_000), int64(0), int64(10_000), nil}, }, { name: "half multiplier", @@ -415,31 +454,68 @@ func TestDAPriceEstimator_EstimateMsgCostUSD(t *testing.T) { SourceTokenData: [][]byte{}, }, }, - daOverheadGas: 100_000, - gasPerDAByte: 0, - daMultiplier: 5_000, // 0.5x multiplier - expUSD: new(big.Int).Add(execCostUSD, big.NewInt(50_000e9)), + expUSD: new(big.Int).Add(execCostUSD, big.NewInt(50_000e9)), + execEstimatorResponse: []any{int64(100_000), int64(0), int64(5_000), nil}, + }, + { + name: "onRamp reader error", + gasPrice: encodeGasPrice(big.NewInt(1e9), big.NewInt(0)), // 1 gwei DA price, 0 exec price + wrappedNativePrice: big.NewInt(1e18), // $1 + msg: cciptypes.EVM2EVMOnRampCCIPSendRequestedWithMeta{ + EVM2EVMMessage: cciptypes.EVM2EVMMessage{ + Data: []byte{}, + TokenAmounts: []cciptypes.TokenAmount{}, + SourceTokenData: [][]byte{}, + }, + }, + execEstimatorResponse: []any{int64(0), int64(0), int64(0), errors.New("some reader error")}, + }, + { + name: "execEstimator error", + gasPrice: encodeGasPrice(big.NewInt(1e9), big.NewInt(0)), // 1 gwei DA price, 0 exec price + wrappedNativePrice: big.NewInt(1e18), // $1 + msg: cciptypes.EVM2EVMOnRampCCIPSendRequestedWithMeta{ + EVM2EVMMessage: cciptypes.EVM2EVMMessage{ + Data: []byte{}, + TokenAmounts: []cciptypes.TokenAmount{}, + SourceTokenData: [][]byte{}, + }, + }, + execEstimatorErr: errors.New("some estimator error"), }, } for _, tc := range testCases { - execEstimator := NewMockGasPriceEstimator(t) - execEstimator.On("EstimateMsgCostUSD", mock.Anything, mock.Anything, tc.wrappedNativePrice, tc.msg).Return(execCostUSD, nil) - t.Run(tc.name, func(t *testing.T) { ctx := tests.Context(t) + + execEstimator := NewMockGasPriceEstimator(t) + execEstimator.On("EstimateMsgCostUSD", mock.Anything, mock.Anything, tc.wrappedNativePrice, tc.msg). + Return(execCostUSD, tc.execEstimatorErr) + + feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) + if len(tc.execEstimatorResponse) > 0 { + feeEstimatorConfig.On("GetDataAvailabilityConfig", mock.Anything). + Return(tc.execEstimatorResponse...) + } + g := DAGasPriceEstimator{ execEstimator: execEstimator, l1Oracle: nil, priceEncodingLength: daGasPriceEncodingLength, - daOverheadGas: tc.daOverheadGas, - gasPerDAByte: tc.gasPerDAByte, - daMultiplier: tc.daMultiplier, + feeEstimatorConfig: feeEstimatorConfig, } costUSD, err := g.EstimateMsgCostUSD(ctx, tc.gasPrice, tc.wrappedNativePrice, tc.msg) - assert.NoError(t, err) - assert.Equal(t, tc.expUSD, costUSD) + + switch { + case len(tc.execEstimatorResponse) == 4 && tc.execEstimatorResponse[3] != nil, + tc.execEstimatorErr != nil: + require.Error(t, err) + default: + require.NoError(t, err) + assert.Equal(t, tc.expUSD, costUSD) + } }) } } diff --git a/core/services/ocr2/plugins/ccip/prices/gas_price_estimator.go b/core/services/ocr2/plugins/ccip/prices/gas_price_estimator.go index 49a6fbcc4ad..4aac664e33e 100644 --- a/core/services/ocr2/plugins/ccip/prices/gas_price_estimator.go +++ b/core/services/ocr2/plugins/ccip/prices/gas_price_estimator.go @@ -3,6 +3,8 @@ package prices import ( "math/big" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" + "github.com/Masterminds/semver/v3" "github.com/pkg/errors" @@ -47,12 +49,13 @@ func NewGasPriceEstimatorForCommitPlugin( maxExecGasPrice *big.Int, daDeviationPPB int64, execDeviationPPB int64, + feeEstimatorConfig ccipdata.FeeEstimatorConfigReader, ) (GasPriceEstimatorCommit, error) { switch commitStoreVersion.String() { case "1.0.0", "1.1.0": return NewExecGasPriceEstimator(estimator, maxExecGasPrice, execDeviationPPB), nil case "1.2.0": - return NewDAGasPriceEstimator(estimator, maxExecGasPrice, execDeviationPPB, daDeviationPPB), nil + return NewDAGasPriceEstimator(estimator, maxExecGasPrice, execDeviationPPB, daDeviationPPB, feeEstimatorConfig), nil default: return nil, errors.Errorf("Invalid commitStore version: %s", commitStoreVersion) } diff --git a/core/services/ocr2/plugins/ccip/prices/gas_price_estimator_commit_mock.go b/core/services/ocr2/plugins/ccip/prices/gas_price_estimator_commit_mock.go index 099c50ea2c0..4632ee0ca24 100644 --- a/core/services/ocr2/plugins/ccip/prices/gas_price_estimator_commit_mock.go +++ b/core/services/ocr2/plugins/ccip/prices/gas_price_estimator_commit_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package prices diff --git a/core/services/ocr2/plugins/ccip/prices/gas_price_estimator_exec_mock.go b/core/services/ocr2/plugins/ccip/prices/gas_price_estimator_exec_mock.go index 02f69b01e08..d45cbb202c3 100644 --- a/core/services/ocr2/plugins/ccip/prices/gas_price_estimator_exec_mock.go +++ b/core/services/ocr2/plugins/ccip/prices/gas_price_estimator_exec_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package prices diff --git a/core/services/ocr2/plugins/ccip/prices/gas_price_estimator_mock.go b/core/services/ocr2/plugins/ccip/prices/gas_price_estimator_mock.go index 7323f88e3ab..7376f16c0c0 100644 --- a/core/services/ocr2/plugins/ccip/prices/gas_price_estimator_mock.go +++ b/core/services/ocr2/plugins/ccip/prices/gas_price_estimator_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package prices diff --git a/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go b/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go index c2fec2903e8..9238d453966 100644 --- a/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go +++ b/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go @@ -75,6 +75,8 @@ var ( SourceChainSelector = uint64(11787463284727550157) DestChainID = uint64(1337) DestChainSelector = uint64(3379446385462418246) + + TokenDecimals = uint8(18) ) // Backwards compat, in principle these statuses are version dependent @@ -147,20 +149,20 @@ func (c ExecOffchainConfig) Encode() ([]byte, error) { } func NewExecOffchainConfig( - DestOptimisticConfirmations uint32, - BatchGasLimit uint32, - RelativeBoostPerWaitHour float64, - InflightCacheExpiry config.Duration, - RootSnoozeTime config.Duration, - BatchingStrategyID uint32, + destOptimisticConfirmations uint32, + batchGasLimit uint32, + relativeBoostPerWaitHour float64, + inflightCacheExpiry config.Duration, + rootSnoozeTime config.Duration, + batchingStrategyID uint32, // 0 = Standard, 1 = Out of Order ) ExecOffchainConfig { return ExecOffchainConfig{v1_2_0.JSONExecOffchainConfig{ - DestOptimisticConfirmations: DestOptimisticConfirmations, - BatchGasLimit: BatchGasLimit, - RelativeBoostPerWaitHour: RelativeBoostPerWaitHour, - InflightCacheExpiry: InflightCacheExpiry, - RootSnoozeTime: RootSnoozeTime, - BatchingStrategyID: BatchingStrategyID, + DestOptimisticConfirmations: destOptimisticConfirmations, + BatchGasLimit: batchGasLimit, + RelativeBoostPerWaitHour: relativeBoostPerWaitHour, + InflightCacheExpiry: inflightCacheExpiry, + RootSnoozeTime: rootSnoozeTime, + BatchingStrategyID: batchingStrategyID, }} } @@ -201,7 +203,7 @@ type Common struct { WrappedNative *weth9.WETH9 WrappedNativePool *lock_release_token_pool.LockReleaseTokenPool ARM *mock_rmn_contract.MockRMNContract - ARMProxy *rmn_proxy_contract.RMNProxyContract + ARMProxy *rmn_proxy_contract.RMNProxy PriceRegistry *price_registry_1_2_0.PriceRegistry TokenAdminRegistry *token_admin_registry.TokenAdminRegistry FinalityDepth uint32 @@ -698,14 +700,14 @@ func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destCh require.NoError(t, err) sourceARM, err := mock_rmn_contract.NewMockRMNContract(armSourceAddress, sourceChain.Client()) require.NoError(t, err) - armProxySourceAddress, _, _, err := rmn_proxy_contract.DeployRMNProxyContract( + armProxySourceAddress, _, _, err := rmn_proxy_contract.DeployRMNProxy( sourceUser, sourceChain.Client(), armSourceAddress, ) require.NoError(t, err) sourceChain.Commit() - sourceARMProxy, err := rmn_proxy_contract.NewRMNProxyContract(armProxySourceAddress, sourceChain.Client()) + sourceARMProxy, err := rmn_proxy_contract.NewRMNProxy(armProxySourceAddress, sourceChain.Client()) require.NoError(t, err) armDestAddress, _, _, err := mock_rmn_contract.DeployMockRMNContract( @@ -714,7 +716,7 @@ func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destCh ) require.NoError(t, err) destChain.Commit() - armProxyDestAddress, _, _, err := rmn_proxy_contract.DeployRMNProxyContract( + armProxyDestAddress, _, _, err := rmn_proxy_contract.DeployRMNProxy( destUser, destChain.Client(), armDestAddress, @@ -723,7 +725,7 @@ func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destCh destChain.Commit() destARM, err := mock_rmn_contract.NewMockRMNContract(armDestAddress, destChain.Client()) require.NoError(t, err) - destARMProxy, err := rmn_proxy_contract.NewRMNProxyContract(armProxyDestAddress, destChain.Client()) + destARMProxy, err := rmn_proxy_contract.NewRMNProxy(armProxyDestAddress, destChain.Client()) require.NoError(t, err) // ================================================================ diff --git a/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go b/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go index d21c5b12513..b1c3677e497 100644 --- a/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go +++ b/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go @@ -38,10 +38,10 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" - coretypes "github.com/smartcontractkit/chainlink-common/pkg/types/core/mocks" pb "github.com/smartcontractkit/chainlink-protos/orchestrator/feedsmanager" + evmcapabilities "github.com/smartcontractkit/chainlink/v2/core/capabilities" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" v2 "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" @@ -383,6 +383,7 @@ func setupNodeCCIP( fmt.Sprintf("127.0.0.1:%d", port), } c.Log.Level = &loglevel + c.Feature.CCIP = &trueRef c.Feature.UICSAKeys = &trueRef c.Feature.FeedsManager = &trueRef c.OCR.Enabled = &falseRef @@ -468,7 +469,7 @@ func setupNodeCCIP( Logger: lggr, LoopRegistry: loopRegistry, GRPCOpts: loop.GRPCOpts{}, - CapabilitiesRegistry: coretypes.NewCapabilitiesRegistry(t), + CapabilitiesRegistry: evmcapabilities.NewRegistry(logger.TestLogger(t)), } testCtx := testutils.Context(t) // evm alway enabled for backward compatibility diff --git a/core/services/ocr2/plugins/ccip/testhelpers/integration/jobspec.go b/core/services/ocr2/plugins/ccip/testhelpers/integration/jobspec.go index b10f51a9426..2a70ea0edd6 100644 --- a/core/services/ocr2/plugins/ccip/testhelpers/integration/jobspec.go +++ b/core/services/ocr2/plugins/ccip/testhelpers/integration/jobspec.go @@ -2,11 +2,13 @@ package integrationtesthelpers import ( "bytes" + "crypto/sha256" "fmt" "text/template" "time" "github.com/ethereum/go-ethereum/common" + "github.com/google/uuid" "github.com/lib/pq" "github.com/smartcontractkit/chainlink-common/pkg/types" @@ -28,6 +30,7 @@ type OCR2TaskJobSpec struct { ForwardingAllowed bool `toml:"forwardingAllowed"` OCR2OracleSpec job.OCR2OracleSpec ObservationSource string `toml:"observationSource"` // List of commands for the Chainlink node + ExternalJobID string `toml:"externalJobID"` } // Type returns the type of the job @@ -39,9 +42,14 @@ func (o *OCR2TaskJobSpec) String() (string, error) { if o.OCR2OracleSpec.FeedID != nil { feedID = o.OCR2OracleSpec.FeedID.Hex() } + externalID, err := ExternalJobID(o.Name) + if err != nil { + return "", err + } specWrap := struct { Name string JobType string + ExternalJobID string MaxTaskDuration string ForwardingAllowed bool ContractID string @@ -62,6 +70,7 @@ func (o *OCR2TaskJobSpec) String() (string, error) { }{ Name: o.Name, JobType: o.JobType, + ExternalJobID: externalID, ForwardingAllowed: o.ForwardingAllowed, MaxTaskDuration: o.MaxTaskDuration, ContractID: o.OCR2OracleSpec.ContractID, @@ -82,6 +91,7 @@ func (o *OCR2TaskJobSpec) String() (string, error) { ocr2TemplateString := ` type = "{{ .JobType }}" name = "{{.Name}}" +externalJobID = "{{.ExternalJobID}}" forwardingAllowed = {{.ForwardingAllowed}} {{if .MaxTaskDuration}} maxTaskDuration = "{{ .MaxTaskDuration }}" {{end}} @@ -146,7 +156,7 @@ type JobType string const ( Commit JobType = "commit" Execution JobType = "exec" - Boostrap JobType = "bootstrap" + Bootstrap JobType = "bootstrap" ) func JobName(jobType JobType, source string, destination, version string) string { @@ -170,6 +180,7 @@ type CCIPJobSpecParams struct { DestStartBlock uint64 USDCAttestationAPI string USDCConfig *config.USDCConfig + LBTCConfig *config.LBTCConfig P2PV2Bootstrappers pq.StringArray } @@ -295,6 +306,11 @@ func (params CCIPJobSpecParams) ExecutionJobSpec() (*OCR2TaskJobSpec, error) { ocrSpec.PluginConfig["USDCConfig.SourceMessageTransmitterAddress"] = fmt.Sprintf(`"%s"`, params.USDCConfig.SourceMessageTransmitterAddress) ocrSpec.PluginConfig["USDCConfig.AttestationAPITimeoutSeconds"] = params.USDCConfig.AttestationAPITimeoutSeconds } + if params.LBTCConfig != nil { + ocrSpec.PluginConfig["LBTCConfig.AttestationAPI"] = fmt.Sprintf(`"%s"`, params.LBTCConfig.AttestationAPI) + ocrSpec.PluginConfig["LBTCConfig.SourceTokenAddress"] = fmt.Sprintf(`"%s"`, params.LBTCConfig.SourceTokenAddress) + ocrSpec.PluginConfig["LBTCConfig.AttestationAPITimeoutSeconds"] = params.LBTCConfig.AttestationAPITimeoutSeconds + } return &OCR2TaskJobSpec{ OCR2OracleSpec: ocrSpec, JobType: "offchainreporting2", @@ -313,7 +329,7 @@ func (params CCIPJobSpecParams) BootstrapJob(contractID string) *OCR2TaskJobSpec }, } return &OCR2TaskJobSpec{ - Name: fmt.Sprintf("%s-%s", Boostrap, params.DestChainName), + Name: fmt.Sprintf("%s-%s-%s", Bootstrap, params.SourceChainName, params.DestChainName), JobType: "bootstrap", OCR2OracleSpec: bootstrapSpec, } @@ -332,3 +348,18 @@ func (c *CCIPIntegrationTestHarness) NewCCIPJobSpecParams(tokenPricesUSDPipeline USDCAttestationAPI: usdcAttestationAPI, } } + +func ExternalJobID(jobName string) (string, error) { + in := []byte(jobName) + sha256Hash := sha256.New() + sha256Hash.Write(in) + in = sha256Hash.Sum(nil)[:16] + // tag as valid UUID v4 https://github.com/google/uuid/blob/0f11ee6918f41a04c201eceeadf612a377bc7fbc/version4.go#L53-L54 + in[6] = (in[6] & 0x0f) | 0x40 // Version 4 + in[8] = (in[8] & 0x3f) | 0x80 // Variant is 10 + id, err := uuid.FromBytes(in) + if err != nil { + return "", err + } + return id.String(), nil +} diff --git a/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/ccip_contracts_1_4_0.go b/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/ccip_contracts_1_4_0.go new file mode 100644 index 00000000000..feb18ee50c1 --- /dev/null +++ b/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/ccip_contracts_1_4_0.go @@ -0,0 +1,1601 @@ +//nolint:revive // helpers for specific version +package testhelpers_1_4_0 + +import ( + "context" + "fmt" + "math" + "math/big" + "testing" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" + "github.com/pkg/errors" + "github.com/rs/zerolog/log" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/libocr/offchainreporting2/confighelper" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2/types" + ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink-common/pkg/hashutil" + "github.com/smartcontractkit/chainlink-common/pkg/merklemulti" + cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + burn_mint_token_pool "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/burn_mint_token_pool_1_4_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store_1_2_0" + evm_2_evm_offramp "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_offramp_1_2_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp_1_2_0" + evm_2_evm_onramp "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp_1_2_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/lock_release_token_pool_1_0_0" + lock_release_token_pool "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/lock_release_token_pool_1_4_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/maybe_revert_message_receiver" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_rmn_contract" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry_1_2_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_proxy_contract" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/weth9" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" + ccipconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers" +) + +var ( + // Source + SourcePool = "source Link pool" + SourcePriceRegistry = "source PriceRegistry" + OnRamp = "onramp" + OnRampNative = "onramp-native" + SourceRouter = "source router" + + // Dest + OffRamp = "offramp" + DestPool = "dest Link pool" + + Receiver = "receiver" + Sender = "sender" + Link = func(amount int64) *big.Int { return new(big.Int).Mul(big.NewInt(1e18), big.NewInt(amount)) } + HundredLink = Link(100) + LinkUSDValue = func(amount int64) *big.Int { return new(big.Int).Mul(big.NewInt(1e18), big.NewInt(amount)) } + SourceChainID = uint64(1000) + SourceChainSelector = uint64(11787463284727550157) + DestChainID = uint64(1337) + DestChainSelector = uint64(3379446385462418246) +) + +// Backwards compat, in principle these statuses are version dependent +// TODO: Adjust integration tests to be version agnostic using readers +var ( + ExecutionStateSuccess = MessageExecutionState(cciptypes.ExecutionStateSuccess) + ExecutionStateFailure = MessageExecutionState(cciptypes.ExecutionStateFailure) +) + +type MessageExecutionState cciptypes.MessageExecutionState +type CommitOffchainConfig struct { + v1_2_0.JSONCommitOffchainConfig +} + +func (c CommitOffchainConfig) Encode() ([]byte, error) { + return ccipconfig.EncodeOffchainConfig(c.JSONCommitOffchainConfig) +} + +func NewCommitOffchainConfig( + gasPriceHeartBeat config.Duration, + daGasPriceDeviationPPB uint32, + execGasPriceDeviationPPB uint32, + tokenPriceHeartBeat config.Duration, + tokenPriceDeviationPPB uint32, + inflightCacheExpiry config.Duration, + priceReportingDisabled bool, +) CommitOffchainConfig { + return CommitOffchainConfig{v1_2_0.JSONCommitOffchainConfig{ + GasPriceHeartBeat: gasPriceHeartBeat, + DAGasPriceDeviationPPB: daGasPriceDeviationPPB, + ExecGasPriceDeviationPPB: execGasPriceDeviationPPB, + TokenPriceHeartBeat: tokenPriceHeartBeat, + TokenPriceDeviationPPB: tokenPriceDeviationPPB, + InflightCacheExpiry: inflightCacheExpiry, + PriceReportingDisabled: priceReportingDisabled, + }} +} + +type CommitOnchainConfig struct { + ccipdata.CommitOnchainConfig +} + +func NewCommitOnchainConfig( + priceRegistry common.Address, +) CommitOnchainConfig { + return CommitOnchainConfig{ccipdata.CommitOnchainConfig{ + PriceRegistry: priceRegistry, + }} +} + +type ExecOnchainConfig struct { + v1_2_0.ExecOnchainConfig +} + +func NewExecOnchainConfig( + permissionLessExecutionThresholdSeconds uint32, + router common.Address, + priceRegistry common.Address, + maxNumberOfTokensPerMsg uint16, + maxDataBytes uint32, + maxPoolReleaseOrMintGas uint32, +) ExecOnchainConfig { + return ExecOnchainConfig{v1_2_0.ExecOnchainConfig{ + PermissionLessExecutionThresholdSeconds: permissionLessExecutionThresholdSeconds, + Router: router, + PriceRegistry: priceRegistry, + MaxNumberOfTokensPerMsg: maxNumberOfTokensPerMsg, + MaxDataBytes: maxDataBytes, + MaxPoolReleaseOrMintGas: maxPoolReleaseOrMintGas, + }} +} + +type ExecOffchainConfig struct { + v1_2_0.JSONExecOffchainConfig +} + +func (c ExecOffchainConfig) Encode() ([]byte, error) { + return ccipconfig.EncodeOffchainConfig(c.JSONExecOffchainConfig) +} + +func NewExecOffchainConfig( + destOptimisticConfirmations uint32, + batchGasLimit uint32, + relativeBoostPerWaitHour float64, + inflightCacheExpiry config.Duration, + rootSnoozeTime config.Duration, + batchingStrategyID uint32, +) ExecOffchainConfig { + return ExecOffchainConfig{v1_2_0.JSONExecOffchainConfig{ + DestOptimisticConfirmations: destOptimisticConfirmations, + BatchGasLimit: batchGasLimit, + RelativeBoostPerWaitHour: relativeBoostPerWaitHour, + InflightCacheExpiry: inflightCacheExpiry, + RootSnoozeTime: rootSnoozeTime, + BatchingStrategyID: batchingStrategyID, + }} +} + +type MaybeRevertReceiver struct { + Receiver *maybe_revert_message_receiver.MaybeRevertMessageReceiver + Strict bool +} + +type Common struct { + ChainID uint64 + ChainSelector uint64 + User *bind.TransactOpts + Chain *backends.SimulatedBackend + LinkToken *link_token_interface.LinkToken + LinkTokenPool *lock_release_token_pool.LockReleaseTokenPool + CustomToken *link_token_interface.LinkToken + WrappedNative *weth9.WETH9 + WrappedNativePool *lock_release_token_pool_1_0_0.LockReleaseTokenPool + ARM *mock_rmn_contract.MockRMNContract + ARMProxy *rmn_proxy_contract.RMNProxy + PriceRegistry *price_registry_1_2_0.PriceRegistry +} + +type SourceChain struct { + Common + Router *router.Router + OnRamp *evm_2_evm_onramp.EVM2EVMOnRamp +} + +type DestinationChain struct { + Common + + CommitStore *commit_store_1_2_0.CommitStore + Router *router.Router + OffRamp *evm_2_evm_offramp.EVM2EVMOffRamp + Receivers []MaybeRevertReceiver +} + +type OCR2Config struct { + Signers []common.Address + Transmitters []common.Address + F uint8 + OnchainConfig []byte + OffchainConfigVersion uint64 + OffchainConfig []byte +} + +type BalanceAssertion struct { + Name string + Address common.Address + Expected string + Getter func(t *testing.T, addr common.Address) *big.Int + Within string +} + +type BalanceReq struct { + Name string + Addr common.Address + Getter func(t *testing.T, addr common.Address) *big.Int +} + +type CCIPContracts struct { + Source SourceChain + Dest DestinationChain + Oracles []confighelper.OracleIdentityExtra + + commitOCRConfig, execOCRConfig *OCR2Config +} + +func (c *CCIPContracts) DeployNewOffRamp(t *testing.T) { + prevOffRamp := common.HexToAddress("") + if c.Dest.OffRamp != nil { + prevOffRamp = c.Dest.OffRamp.Address() + } + offRampAddress, _, _, err := evm_2_evm_offramp.DeployEVM2EVMOffRamp( + c.Dest.User, + c.Dest.Chain, + evm_2_evm_offramp.EVM2EVMOffRampStaticConfig{ + CommitStore: c.Dest.CommitStore.Address(), + ChainSelector: c.Dest.ChainSelector, + SourceChainSelector: c.Source.ChainSelector, + OnRamp: c.Source.OnRamp.Address(), + PrevOffRamp: prevOffRamp, + ArmProxy: c.Dest.ARMProxy.Address(), + }, + []common.Address{c.Source.LinkToken.Address()}, // source tokens + []common.Address{c.Dest.LinkTokenPool.Address()}, // pools + evm_2_evm_offramp.RateLimiterConfig{ + IsEnabled: true, + Capacity: LinkUSDValue(100), + Rate: LinkUSDValue(1), + }, + ) + require.NoError(t, err) + c.Dest.Chain.Commit() + + c.Dest.OffRamp, err = evm_2_evm_offramp.NewEVM2EVMOffRamp(offRampAddress, c.Dest.Chain) + require.NoError(t, err) + + c.Dest.Chain.Commit() + c.Source.Chain.Commit() +} + +func (c *CCIPContracts) EnableOffRamp(t *testing.T) { + _, err := c.Dest.Router.ApplyRampUpdates(c.Dest.User, nil, nil, []router.RouterOffRamp{{SourceChainSelector: SourceChainSelector, OffRamp: c.Dest.OffRamp.Address()}}) + require.NoError(t, err) + c.Dest.Chain.Commit() + + onChainConfig := c.CreateDefaultExecOnchainConfig(t) + offChainConfig := c.CreateDefaultExecOffchainConfig(t) + + c.SetupExecOCR2Config(t, onChainConfig, offChainConfig) +} + +func (c *CCIPContracts) EnableCommitStore(t *testing.T) { + onChainConfig := c.CreateDefaultCommitOnchainConfig(t) + offChainConfig := c.CreateDefaultCommitOffchainConfig(t) + + c.SetupCommitOCR2Config(t, onChainConfig, offChainConfig) + + _, err := c.Dest.PriceRegistry.ApplyPriceUpdatersUpdates(c.Dest.User, []common.Address{c.Dest.CommitStore.Address()}, []common.Address{}) + require.NoError(t, err) + c.Dest.Chain.Commit() +} + +func (c *CCIPContracts) DeployNewOnRamp(t *testing.T) { + t.Log("Deploying new onRamp") + // find the last onRamp + prevOnRamp := common.HexToAddress("") + if c.Source.OnRamp != nil { + prevOnRamp = c.Source.OnRamp.Address() + } + onRampAddress, _, _, err := evm_2_evm_onramp.DeployEVM2EVMOnRamp( + c.Source.User, // user + c.Source.Chain, // client + evm_2_evm_onramp.EVM2EVMOnRampStaticConfig{ + LinkToken: c.Source.LinkToken.Address(), + ChainSelector: c.Source.ChainSelector, + DestChainSelector: c.Dest.ChainSelector, + DefaultTxGasLimit: 200_000, + MaxNopFeesJuels: big.NewInt(0).Mul(big.NewInt(100_000_000), big.NewInt(1e18)), + PrevOnRamp: prevOnRamp, + ArmProxy: c.Source.ARM.Address(), // ARM + }, + evm_2_evm_onramp.EVM2EVMOnRampDynamicConfig{ + Router: c.Source.Router.Address(), + MaxNumberOfTokensPerMsg: 5, + DestGasOverhead: 350_000, + DestGasPerPayloadByte: 16, + DestDataAvailabilityOverheadGas: 33_596, + DestGasPerDataAvailabilityByte: 16, + DestDataAvailabilityMultiplierBps: 6840, // 0.684 + PriceRegistry: c.Source.PriceRegistry.Address(), + MaxDataBytes: 1e5, + MaxPerMsgGasLimit: 4_000_000, + }, + []evm_2_evm_onramp.InternalPoolUpdate{ + { + Token: c.Source.LinkToken.Address(), + Pool: c.Source.LinkTokenPool.Address(), + }, + }, + evm_2_evm_onramp.RateLimiterConfig{ + IsEnabled: true, + Capacity: LinkUSDValue(100), + Rate: LinkUSDValue(1), + }, + []evm_2_evm_onramp.EVM2EVMOnRampFeeTokenConfigArgs{ + { + Token: c.Source.LinkToken.Address(), + NetworkFeeUSDCents: 1_00, + GasMultiplierWeiPerEth: 1e18, + PremiumMultiplierWeiPerEth: 9e17, + Enabled: true, + }, + { + Token: c.Source.WrappedNative.Address(), + NetworkFeeUSDCents: 1_00, + GasMultiplierWeiPerEth: 1e18, + PremiumMultiplierWeiPerEth: 1e18, + Enabled: true, + }, + }, + []evm_2_evm_onramp.EVM2EVMOnRampTokenTransferFeeConfigArgs{ + { + Token: c.Source.LinkToken.Address(), + MinFeeUSDCents: 50, // $0.5 + MaxFeeUSDCents: 1_000_000_00, // $ 1 million + DeciBps: 5_0, // 5 bps + DestGasOverhead: 34_000, + DestBytesOverhead: 32, + }, + }, + []evm_2_evm_onramp.EVM2EVMOnRampNopAndWeight{}, + ) + + require.NoError(t, err) + c.Source.Chain.Commit() + c.Dest.Chain.Commit() + c.Source.OnRamp, err = evm_2_evm_onramp.NewEVM2EVMOnRamp(onRampAddress, c.Source.Chain) + require.NoError(t, err) + c.Source.Chain.Commit() + c.Dest.Chain.Commit() +} + +func (c *CCIPContracts) EnableOnRamp(t *testing.T) { + t.Log("Setting onRamp on source router") + _, err := c.Source.Router.ApplyRampUpdates(c.Source.User, []router.RouterOnRamp{{DestChainSelector: c.Dest.ChainSelector, OnRamp: c.Source.OnRamp.Address()}}, nil, nil) + require.NoError(t, err) + c.Source.Chain.Commit() + c.Dest.Chain.Commit() +} + +func (c *CCIPContracts) DeployNewCommitStore(t *testing.T) { + commitStoreAddress, _, _, err := commit_store_1_2_0.DeployCommitStore( + c.Dest.User, // user + c.Dest.Chain, // client + commit_store_1_2_0.CommitStoreStaticConfig{ + ChainSelector: c.Dest.ChainSelector, + SourceChainSelector: c.Source.ChainSelector, + OnRamp: c.Source.OnRamp.Address(), + ArmProxy: c.Dest.ARMProxy.Address(), + }, + ) + require.NoError(t, err) + c.Dest.Chain.Commit() + // since CommitStoreHelper derives from CommitStore, it's safe to instantiate both on same address + c.Dest.CommitStore, err = commit_store_1_2_0.NewCommitStore(commitStoreAddress, c.Dest.Chain) + require.NoError(t, err) +} + +func (c *CCIPContracts) DeployNewPriceRegistry(t *testing.T) { + t.Log("Deploying new Price Registry") + destPricesAddress, _, _, err := price_registry_1_2_0.DeployPriceRegistry( + c.Dest.User, + c.Dest.Chain, + []common.Address{c.Dest.CommitStore.Address()}, + []common.Address{c.Dest.LinkToken.Address()}, + 60*60*24*14, // two weeks + ) + require.NoError(t, err) + c.Source.Chain.Commit() + c.Dest.Chain.Commit() + c.Dest.PriceRegistry, err = price_registry_1_2_0.NewPriceRegistry(destPricesAddress, c.Dest.Chain) + require.NoError(t, err) + + priceUpdates := price_registry_1_2_0.InternalPriceUpdates{ + TokenPriceUpdates: []price_registry_1_2_0.InternalTokenPriceUpdate{ + { + SourceToken: c.Dest.LinkToken.Address(), + UsdPerToken: big.NewInt(8e18), // 8usd + }, + { + SourceToken: c.Dest.WrappedNative.Address(), + UsdPerToken: big.NewInt(1e18), // 1usd + }, + }, + GasPriceUpdates: []price_registry_1_2_0.InternalGasPriceUpdate{ + { + DestChainSelector: c.Source.ChainSelector, + UsdPerUnitGas: big.NewInt(2000e9), // $2000 per eth * 1gwei = 2000e9 + }, + }, + } + _, err = c.Dest.PriceRegistry.UpdatePrices(c.Dest.User, priceUpdates) + require.NoError(t, err) + + c.Source.Chain.Commit() + c.Dest.Chain.Commit() + + t.Logf("New Price Registry deployed at %s", destPricesAddress.String()) +} + +func (c *CCIPContracts) SetNopsOnRamp(t *testing.T, nopsAndWeights []evm_2_evm_onramp.EVM2EVMOnRampNopAndWeight) { + tx, err := c.Source.OnRamp.SetNops(c.Source.User, nopsAndWeights) + require.NoError(t, err) + c.Source.Chain.Commit() + _, err = bind.WaitMined(context.Background(), c.Source.Chain, tx) + require.NoError(t, err) +} + +func (c *CCIPContracts) GetSourceLinkBalance(t *testing.T, addr common.Address) *big.Int { + return GetBalance(t, c.Source.Chain, c.Source.LinkToken.Address(), addr) +} + +func (c *CCIPContracts) GetDestLinkBalance(t *testing.T, addr common.Address) *big.Int { + return GetBalance(t, c.Dest.Chain, c.Dest.LinkToken.Address(), addr) +} + +func (c *CCIPContracts) GetSourceWrappedTokenBalance(t *testing.T, addr common.Address) *big.Int { + return GetBalance(t, c.Source.Chain, c.Source.WrappedNative.Address(), addr) +} + +func (c *CCIPContracts) GetDestWrappedTokenBalance(t *testing.T, addr common.Address) *big.Int { + return GetBalance(t, c.Dest.Chain, c.Dest.WrappedNative.Address(), addr) +} + +func (c *CCIPContracts) AssertBalances(t *testing.T, bas []BalanceAssertion) { + for _, b := range bas { + actual := b.Getter(t, b.Address) + t.Log("Checking balance for", b.Name, "at", b.Address.Hex(), "got", actual) + require.NotNil(t, actual, "%v getter return nil", b.Name) + if b.Within == "" { + require.Equal(t, b.Expected, actual.String(), "wrong balance for %s got %s want %s", b.Name, actual, b.Expected) + } else { + bi, _ := big.NewInt(0).SetString(b.Expected, 10) + withinI, _ := big.NewInt(0).SetString(b.Within, 10) + high := big.NewInt(0).Add(bi, withinI) + low := big.NewInt(0).Sub(bi, withinI) + require.Equal(t, -1, actual.Cmp(high), "wrong balance for %s got %s outside expected range [%s, %s]", b.Name, actual, low, high) + require.Equal(t, 1, actual.Cmp(low), "wrong balance for %s got %s outside expected range [%s, %s]", b.Name, actual, low, high) + } + } +} + +func AccountToAddress(accounts []ocr2types.Account) (addresses []common.Address, err error) { + for _, signer := range accounts { + bytes, err := hexutil.Decode(string(signer)) + if err != nil { + return []common.Address{}, errors.Wrap(err, fmt.Sprintf("given address is not valid %s", signer)) + } + if len(bytes) != 20 { + return []common.Address{}, errors.Errorf("address is not 20 bytes %s", signer) + } + addresses = append(addresses, common.BytesToAddress(bytes)) + } + return addresses, nil +} + +func OnchainPublicKeyToAddress(publicKeys []ocrtypes.OnchainPublicKey) (addresses []common.Address, err error) { + for _, signer := range publicKeys { + if len(signer) != 20 { + return []common.Address{}, errors.Errorf("address is not 20 bytes %s", signer) + } + addresses = append(addresses, common.BytesToAddress(signer)) + } + return addresses, nil +} + +func (c *CCIPContracts) DeriveOCR2Config(t *testing.T, oracles []confighelper.OracleIdentityExtra, rawOnchainConfig []byte, rawOffchainConfig []byte) *OCR2Config { + signers, transmitters, threshold, onchainConfig, offchainConfigVersion, offchainConfig, err := confighelper.ContractSetConfigArgsForTests( + 2*time.Second, // deltaProgress + 1*time.Second, // deltaResend + 1*time.Second, // deltaRound + 500*time.Millisecond, // deltaGrace + 2*time.Second, // deltaStage + 3, + []int{1, 1, 1, 1}, + oracles, + rawOffchainConfig, + nil, + 50*time.Millisecond, // Max duration query + 1*time.Second, // Max duration observation + 100*time.Millisecond, + 100*time.Millisecond, + 100*time.Millisecond, + 1, // faults + rawOnchainConfig, + ) + require.NoError(t, err) + lggr := logger.TestLogger(t) + lggr.Infow("Setting Config on Oracle Contract", + "signers", signers, + "transmitters", transmitters, + "threshold", threshold, + "onchainConfig", onchainConfig, + "encodedConfigVersion", offchainConfigVersion, + ) + signerAddresses, err := OnchainPublicKeyToAddress(signers) + require.NoError(t, err) + transmitterAddresses, err := AccountToAddress(transmitters) + require.NoError(t, err) + + return &OCR2Config{ + Signers: signerAddresses, + Transmitters: transmitterAddresses, + F: threshold, + OnchainConfig: onchainConfig, + OffchainConfigVersion: offchainConfigVersion, + OffchainConfig: offchainConfig, + } +} + +func (c *CCIPContracts) SetupCommitOCR2Config(t *testing.T, commitOnchainConfig, commitOffchainConfig []byte) { + c.commitOCRConfig = c.DeriveOCR2Config(t, c.Oracles, commitOnchainConfig, commitOffchainConfig) + // Set the DON on the commit store + _, err := c.Dest.CommitStore.SetOCR2Config( + c.Dest.User, + c.commitOCRConfig.Signers, + c.commitOCRConfig.Transmitters, + c.commitOCRConfig.F, + c.commitOCRConfig.OnchainConfig, + c.commitOCRConfig.OffchainConfigVersion, + c.commitOCRConfig.OffchainConfig, + ) + require.NoError(t, err) + c.Dest.Chain.Commit() +} + +func (c *CCIPContracts) SetupExecOCR2Config(t *testing.T, execOnchainConfig, execOffchainConfig []byte) { + c.execOCRConfig = c.DeriveOCR2Config(t, c.Oracles, execOnchainConfig, execOffchainConfig) + // Same DON on the offramp + _, err := c.Dest.OffRamp.SetOCR2Config( + c.Dest.User, + c.execOCRConfig.Signers, + c.execOCRConfig.Transmitters, + c.execOCRConfig.F, + c.execOCRConfig.OnchainConfig, + c.execOCRConfig.OffchainConfigVersion, + c.execOCRConfig.OffchainConfig, + ) + require.NoError(t, err) + c.Dest.Chain.Commit() +} + +func (c *CCIPContracts) SetupOnchainConfig(t *testing.T, commitOnchainConfig, commitOffchainConfig, execOnchainConfig, execOffchainConfig []byte) int64 { + // Note We do NOT set the payees, payment is done in the OCR2Base implementation + blockBeforeConfig, err := c.Dest.Chain.BlockByNumber(context.Background(), nil) + require.NoError(t, err) + + c.SetupCommitOCR2Config(t, commitOnchainConfig, commitOffchainConfig) + c.SetupExecOCR2Config(t, execOnchainConfig, execOffchainConfig) + + return blockBeforeConfig.Number().Int64() +} + +func (c *CCIPContracts) SetupLockAndMintTokenPool( + sourceTokenAddress common.Address, + wrappedTokenName, + wrappedTokenSymbol string) (common.Address, *burn_mint_erc677.BurnMintERC677, error) { + // Deploy dest token & pool + destTokenAddress, _, _, err := burn_mint_erc677.DeployBurnMintERC677(c.Dest.User, c.Dest.Chain, wrappedTokenName, wrappedTokenSymbol, 18, big.NewInt(0)) + if err != nil { + return [20]byte{}, nil, err + } + c.Dest.Chain.Commit() + + destToken, err := burn_mint_erc677.NewBurnMintERC677(destTokenAddress, c.Dest.Chain) + if err != nil { + return [20]byte{}, nil, err + } + + destPoolAddress, _, destPool, err := burn_mint_token_pool.DeployBurnMintTokenPool( + c.Dest.User, + c.Dest.Chain, + destTokenAddress, + []common.Address{}, // pool originalSender allowList + c.Dest.ARMProxy.Address(), + c.Dest.Router.Address(), + ) + if err != nil { + return [20]byte{}, nil, err + } + c.Dest.Chain.Commit() + + _, err = destToken.GrantMintAndBurnRoles(c.Dest.User, destPoolAddress) + if err != nil { + return [20]byte{}, nil, err + } + + _, err = destPool.ApplyChainUpdates(c.Dest.User, + []burn_mint_token_pool.TokenPoolChainUpdate{ + { + RemoteChainSelector: c.Source.ChainSelector, + Allowed: true, + OutboundRateLimiterConfig: burn_mint_token_pool.RateLimiterConfig{ + IsEnabled: true, + Capacity: HundredLink, + Rate: big.NewInt(1e18), + }, + InboundRateLimiterConfig: burn_mint_token_pool.RateLimiterConfig{ + IsEnabled: true, + Capacity: HundredLink, + Rate: big.NewInt(1e18), + }, + }, + }) + if err != nil { + return [20]byte{}, nil, err + } + c.Dest.Chain.Commit() + + sourcePoolAddress, _, sourcePool, err := lock_release_token_pool.DeployLockReleaseTokenPool( + c.Source.User, + c.Source.Chain, + sourceTokenAddress, + []common.Address{}, // empty allowList at deploy time indicates pool has no original sender restrictions + c.Source.ARMProxy.Address(), + true, + c.Source.Router.Address(), + ) + if err != nil { + return [20]byte{}, nil, err + } + c.Source.Chain.Commit() + + // set onRamp as valid caller for source pool + _, err = sourcePool.ApplyChainUpdates(c.Source.User, []lock_release_token_pool.TokenPoolChainUpdate{ + { + RemoteChainSelector: c.Dest.ChainSelector, + Allowed: true, + OutboundRateLimiterConfig: lock_release_token_pool.RateLimiterConfig{ + IsEnabled: true, + Capacity: HundredLink, + Rate: big.NewInt(1e18), + }, + InboundRateLimiterConfig: lock_release_token_pool.RateLimiterConfig{ + IsEnabled: true, + Capacity: HundredLink, + Rate: big.NewInt(1e18), + }, + }, + }) + if err != nil { + return [20]byte{}, nil, err + } + c.Source.Chain.Commit() + + wrappedNativeAddress, err := c.Source.Router.GetWrappedNative(nil) + if err != nil { + return [20]byte{}, nil, err + } + + // native token is used as fee token + _, err = c.Source.PriceRegistry.UpdatePrices(c.Source.User, price_registry_1_2_0.InternalPriceUpdates{ + TokenPriceUpdates: []price_registry_1_2_0.InternalTokenPriceUpdate{ + { + SourceToken: sourceTokenAddress, + UsdPerToken: big.NewInt(5), + }, + }, + GasPriceUpdates: []price_registry_1_2_0.InternalGasPriceUpdate{}, + }) + if err != nil { + return [20]byte{}, nil, err + } + c.Source.Chain.Commit() + + _, err = c.Source.PriceRegistry.ApplyFeeTokensUpdates(c.Source.User, []common.Address{wrappedNativeAddress}, nil) + if err != nil { + return [20]byte{}, nil, err + } + c.Source.Chain.Commit() + + // add new token pool created above + _, err = c.Source.OnRamp.ApplyPoolUpdates(c.Source.User, nil, []evm_2_evm_onramp.InternalPoolUpdate{ + { + Token: sourceTokenAddress, + Pool: sourcePoolAddress, + }, + }) + if err != nil { + return [20]byte{}, nil, err + } + + _, err = c.Dest.OffRamp.ApplyPoolUpdates(c.Dest.User, nil, []evm_2_evm_offramp.InternalPoolUpdate{ + { + Token: sourceTokenAddress, + Pool: destPoolAddress, + }, + }) + if err != nil { + return [20]byte{}, nil, err + } + c.Dest.Chain.Commit() + + return sourcePoolAddress, destToken, err +} + +func (c *CCIPContracts) SendMessage(t *testing.T, gasLimit, tokenAmount *big.Int, receiverAddr common.Address) { + extraArgs, err := GetEVMExtraArgsV1(gasLimit, false) + require.NoError(t, err) + msg := router.ClientEVM2AnyMessage{ + Receiver: MustEncodeAddress(t, receiverAddr), + Data: []byte("hello"), + TokenAmounts: []router.ClientEVMTokenAmount{ + { + Token: c.Source.LinkToken.Address(), + Amount: tokenAmount, + }, + }, + FeeToken: c.Source.LinkToken.Address(), + ExtraArgs: extraArgs, + } + fee, err := c.Source.Router.GetFee(nil, c.Dest.ChainSelector, msg) + require.NoError(t, err) + // Currently no overhead and 1gwei dest gas price. So fee is simply gasLimit * gasPrice. + // require.Equal(t, new(big.Int).Mul(gasLimit, gasPrice).String(), fee.String()) + // Approve the fee amount + the token amount + _, err = c.Source.LinkToken.Approve(c.Source.User, c.Source.Router.Address(), new(big.Int).Add(fee, tokenAmount)) + require.NoError(t, err) + c.Source.Chain.Commit() + c.SendRequest(t, msg) +} + +func GetBalances(t *testing.T, brs []BalanceReq) (map[string]*big.Int, error) { + m := make(map[string]*big.Int) + for _, br := range brs { + m[br.Name] = br.Getter(t, br.Addr) + if m[br.Name] == nil { + return nil, fmt.Errorf("%v getter return nil", br.Name) + } + } + return m, nil +} + +func MustAddBigInt(a *big.Int, b string) *big.Int { + bi, _ := big.NewInt(0).SetString(b, 10) + return big.NewInt(0).Add(a, bi) +} + +func MustSubBigInt(a *big.Int, b string) *big.Int { + bi, _ := big.NewInt(0).SetString(b, 10) + return big.NewInt(0).Sub(a, bi) +} + +func MustEncodeAddress(t *testing.T, address common.Address) []byte { + bts, err := utils.ABIEncode(`[{"type":"address"}]`, address) + require.NoError(t, err) + return bts +} + +func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destChainID, destChainSelector uint64) CCIPContracts { + sourceChain, sourceUser := testhelpers.SetupChain(t) + destChain, destUser := testhelpers.SetupChain(t) + + armSourceAddress, _, _, err := mock_rmn_contract.DeployMockRMNContract( + sourceUser, + sourceChain.Client(), + ) + require.NoError(t, err) + sourceARM, err := mock_rmn_contract.NewMockRMNContract(armSourceAddress, sourceChain.Client()) + require.NoError(t, err) + armProxySourceAddress, _, _, err := rmn_proxy_contract.DeployRMNProxy( + sourceUser, + sourceChain.Client(), + armSourceAddress, + ) + require.NoError(t, err) + sourceARMProxy, err := rmn_proxy_contract.NewRMNProxy(armProxySourceAddress, sourceChain.Client()) + require.NoError(t, err) + sourceChain.Commit() + + armDestAddress, _, _, err := mock_rmn_contract.DeployMockRMNContract( + destUser, + destChain.Client(), + ) + require.NoError(t, err) + armProxyDestAddress, _, _, err := rmn_proxy_contract.DeployRMNProxy( + destUser, + destChain.Client(), + armDestAddress, + ) + require.NoError(t, err) + destChain.Commit() + destARM, err := mock_rmn_contract.NewMockRMNContract(armDestAddress, destChain.Client()) + require.NoError(t, err) + destARMProxy, err := rmn_proxy_contract.NewRMNProxy(armProxyDestAddress, destChain.Client()) + require.NoError(t, err) + + // Deploy link token and pool on source chain + sourceLinkTokenAddress, _, _, err := link_token_interface.DeployLinkToken(sourceUser, sourceChain.Client()) + require.NoError(t, err) + sourceChain.Commit() + sourceLinkToken, err := link_token_interface.NewLinkToken(sourceLinkTokenAddress, sourceChain.Client()) + require.NoError(t, err) + + // Create router + sourceWeth9addr, _, _, err := weth9.DeployWETH9(sourceUser, sourceChain.Client()) + require.NoError(t, err) + sourceWrapped, err := weth9.NewWETH9(sourceWeth9addr, sourceChain.Client()) + require.NoError(t, err) + + sourceRouterAddress, _, _, err := router.DeployRouter(sourceUser, sourceChain.Client(), sourceWeth9addr, armProxySourceAddress) + require.NoError(t, err) + sourceRouter, err := router.NewRouter(sourceRouterAddress, sourceChain.Client()) + require.NoError(t, err) + sourceChain.Commit() + + sourceWeth9PoolAddress, _, _, err := lock_release_token_pool_1_0_0.DeployLockReleaseTokenPool( + sourceUser, + sourceChain.Client(), + sourceWeth9addr, + []common.Address{}, + armProxySourceAddress, + ) + require.NoError(t, err) + sourceChain.Commit() + + sourceWeth9Pool, err := lock_release_token_pool_1_0_0.NewLockReleaseTokenPool(sourceWeth9PoolAddress, sourceChain.Client()) + require.NoError(t, err) + + sourcePoolAddress, _, _, err := lock_release_token_pool.DeployLockReleaseTokenPool( + sourceUser, + sourceChain.Client(), + sourceLinkTokenAddress, + []common.Address{}, + armProxySourceAddress, + true, + sourceRouterAddress, + ) + require.NoError(t, err) + sourceChain.Commit() + sourcePool, err := lock_release_token_pool.NewLockReleaseTokenPool(sourcePoolAddress, sourceChain.Client()) + require.NoError(t, err) + + // Deploy custom token pool source + sourceCustomTokenAddress, _, _, err := link_token_interface.DeployLinkToken(sourceUser, sourceChain.Client()) // Just re-use this, it's an ERC20. + require.NoError(t, err) + sourceCustomToken, err := link_token_interface.NewLinkToken(sourceCustomTokenAddress, sourceChain.Client()) + require.NoError(t, err) + destChain.Commit() + + // Deploy custom token pool dest + destCustomTokenAddress, _, _, err := link_token_interface.DeployLinkToken(destUser, destChain.Client()) // Just re-use this, it's an ERC20. + require.NoError(t, err) + destCustomToken, err := link_token_interface.NewLinkToken(destCustomTokenAddress, destChain.Client()) + require.NoError(t, err) + destChain.Commit() + + // Deploy and configure onramp + sourcePricesAddress, _, _, err := price_registry_1_2_0.DeployPriceRegistry( + sourceUser, + sourceChain.Client(), + nil, + []common.Address{sourceLinkTokenAddress, sourceWeth9addr}, + 60*60*24*14, // two weeks + ) + require.NoError(t, err) + + srcPriceRegistry, err := price_registry_1_2_0.NewPriceRegistry(sourcePricesAddress, sourceChain.Client()) + require.NoError(t, err) + + _, err = srcPriceRegistry.UpdatePrices(sourceUser, price_registry_1_2_0.InternalPriceUpdates{ + TokenPriceUpdates: []price_registry_1_2_0.InternalTokenPriceUpdate{ + { + SourceToken: sourceLinkTokenAddress, + UsdPerToken: new(big.Int).Mul(big.NewInt(1e18), big.NewInt(20)), + }, + { + SourceToken: sourceWeth9addr, + UsdPerToken: new(big.Int).Mul(big.NewInt(1e18), big.NewInt(2000)), + }, + }, + GasPriceUpdates: []price_registry_1_2_0.InternalGasPriceUpdate{ + { + DestChainSelector: destChainSelector, + UsdPerUnitGas: big.NewInt(20000e9), + }, + }, + }) + require.NoError(t, err) + + onRampAddress, _, _, err := evm_2_evm_onramp.DeployEVM2EVMOnRamp( + sourceUser, // user + sourceChain.Client(), // client + evm_2_evm_onramp.EVM2EVMOnRampStaticConfig{ + LinkToken: sourceLinkTokenAddress, + ChainSelector: sourceChainSelector, + DestChainSelector: destChainSelector, + DefaultTxGasLimit: 200_000, + MaxNopFeesJuels: big.NewInt(0).Mul(big.NewInt(100_000_000), big.NewInt(1e18)), + PrevOnRamp: common.HexToAddress(""), + ArmProxy: armProxySourceAddress, // ARM + }, + evm_2_evm_onramp.EVM2EVMOnRampDynamicConfig{ + Router: sourceRouterAddress, + MaxNumberOfTokensPerMsg: 5, + DestGasOverhead: 350_000, + DestGasPerPayloadByte: 16, + DestDataAvailabilityOverheadGas: 33_596, + DestGasPerDataAvailabilityByte: 16, + DestDataAvailabilityMultiplierBps: 6840, // 0.684 + PriceRegistry: sourcePricesAddress, + MaxDataBytes: 1e5, + MaxPerMsgGasLimit: 4_000_000, + }, + []evm_2_evm_onramp.InternalPoolUpdate{ + { + Token: sourceLinkTokenAddress, + Pool: sourcePoolAddress, + }, + { + Token: sourceWeth9addr, + Pool: sourceWeth9PoolAddress, + }, + }, + evm_2_evm_onramp.RateLimiterConfig{ + IsEnabled: true, + Capacity: LinkUSDValue(100), + Rate: LinkUSDValue(1), + }, + []evm_2_evm_onramp.EVM2EVMOnRampFeeTokenConfigArgs{ + { + Token: sourceLinkTokenAddress, + NetworkFeeUSDCents: 1_00, + GasMultiplierWeiPerEth: 1e18, + PremiumMultiplierWeiPerEth: 9e17, + Enabled: true, + }, + { + Token: sourceWeth9addr, + NetworkFeeUSDCents: 1_00, + GasMultiplierWeiPerEth: 1e18, + PremiumMultiplierWeiPerEth: 1e18, + Enabled: true, + }, + }, + []evm_2_evm_onramp.EVM2EVMOnRampTokenTransferFeeConfigArgs{ + { + Token: sourceLinkTokenAddress, + MinFeeUSDCents: 50, // $0.5 + MaxFeeUSDCents: 1_000_000_00, // $ 1 million + DeciBps: 5_0, // 5 bps + DestGasOverhead: 34_000, + DestBytesOverhead: 32, + }, + }, + []evm_2_evm_onramp.EVM2EVMOnRampNopAndWeight{}, + ) + require.NoError(t, err) + onRamp, err := evm_2_evm_onramp.NewEVM2EVMOnRamp(onRampAddress, sourceChain.Client()) + require.NoError(t, err) + _, err = sourcePool.ApplyChainUpdates( + sourceUser, + []lock_release_token_pool.TokenPoolChainUpdate{{ + RemoteChainSelector: DestChainSelector, + Allowed: true, + OutboundRateLimiterConfig: lock_release_token_pool.RateLimiterConfig{ + IsEnabled: true, + Capacity: HundredLink, + Rate: big.NewInt(1e18), + }, + InboundRateLimiterConfig: lock_release_token_pool.RateLimiterConfig{ + IsEnabled: true, + Capacity: HundredLink, + Rate: big.NewInt(1e18), + }, + }}, + ) + require.NoError(t, err) + _, err = sourceWeth9Pool.ApplyRampUpdates(sourceUser, + []lock_release_token_pool_1_0_0.TokenPoolRampUpdate{{Ramp: onRampAddress, Allowed: true, + RateLimiterConfig: lock_release_token_pool_1_0_0.RateLimiterConfig{ + IsEnabled: true, + Capacity: HundredLink, + Rate: big.NewInt(1e18), + }, + }}, + []lock_release_token_pool_1_0_0.TokenPoolRampUpdate{}, + ) + require.NoError(t, err) + sourceChain.Commit() + _, err = sourceRouter.ApplyRampUpdates(sourceUser, []router.RouterOnRamp{{DestChainSelector: destChainSelector, OnRamp: onRampAddress}}, nil, nil) + require.NoError(t, err) + sourceChain.Commit() + + destWethaddr, _, _, err := weth9.DeployWETH9(destUser, destChain.Client()) + require.NoError(t, err) + destWrapped, err := weth9.NewWETH9(destWethaddr, destChain.Client()) + require.NoError(t, err) + + // Create dest router + destRouterAddress, _, _, err := router.DeployRouter(destUser, destChain.Client(), destWethaddr, armProxyDestAddress) + require.NoError(t, err) + destChain.Commit() + destRouter, err := router.NewRouter(destRouterAddress, destChain.Client()) + require.NoError(t, err) + + // Deploy link token and pool on destination chain + destLinkTokenAddress, _, _, err := link_token_interface.DeployLinkToken(destUser, destChain.Client()) + require.NoError(t, err) + destChain.Commit() + destLinkToken, err := link_token_interface.NewLinkToken(destLinkTokenAddress, destChain.Client()) + require.NoError(t, err) + destPoolAddress, _, _, err := lock_release_token_pool.DeployLockReleaseTokenPool( + destUser, + destChain.Client(), + destLinkTokenAddress, + []common.Address{}, + armProxyDestAddress, + true, + destRouterAddress, + ) + require.NoError(t, err) + destChain.Commit() + destPool, err := lock_release_token_pool.NewLockReleaseTokenPool(destPoolAddress, destChain.Client()) + require.NoError(t, err) + destChain.Commit() + + // Float the offramp pool + o, err := destPool.Owner(nil) + require.NoError(t, err) + require.Equal(t, destUser.From.String(), o.String()) + _, err = destPool.SetRebalancer(destUser, destUser.From) + require.NoError(t, err) + _, err = destLinkToken.Approve(destUser, destPoolAddress, Link(200)) + require.NoError(t, err) + _, err = destPool.ProvideLiquidity(destUser, Link(200)) + require.NoError(t, err) + destChain.Commit() + + destWrappedPoolAddress, _, _, err := lock_release_token_pool_1_0_0.DeployLockReleaseTokenPool( + destUser, + destChain.Client(), + destWethaddr, + []common.Address{}, + armProxyDestAddress, + ) + require.NoError(t, err) + destWrappedPool, err := lock_release_token_pool_1_0_0.NewLockReleaseTokenPool(destWrappedPoolAddress, destChain.Client()) + require.NoError(t, err) + + poolFloatValue := big.NewInt(1e18) + + destUser.Value = poolFloatValue + _, err = destWrapped.Deposit(destUser) + require.NoError(t, err) + destChain.Commit() + destUser.Value = nil + + _, err = destWrapped.Transfer(destUser, destWrappedPool.Address(), poolFloatValue) + require.NoError(t, err) + destChain.Commit() + + // Deploy and configure ge offramp. + destPricesAddress, _, _, err := price_registry_1_2_0.DeployPriceRegistry( + destUser, + destChain.Client(), + nil, + []common.Address{destLinkTokenAddress}, + 60*60*24*14, // two weeks + ) + require.NoError(t, err) + destPriceRegistry, err := price_registry_1_2_0.NewPriceRegistry(destPricesAddress, destChain.Client()) + require.NoError(t, err) + + // Deploy commit store. + commitStoreAddress, _, _, err := commit_store_1_2_0.DeployCommitStore( + destUser, // user + destChain.Client(), // client + commit_store_1_2_0.CommitStoreStaticConfig{ + ChainSelector: destChainSelector, + SourceChainSelector: sourceChainSelector, + OnRamp: onRamp.Address(), + ArmProxy: destARMProxy.Address(), + }, + ) + require.NoError(t, err) + destChain.Commit() + commitStore, err := commit_store_1_2_0.NewCommitStore(commitStoreAddress, destChain.Client()) + require.NoError(t, err) + + offRampAddress, _, _, err := evm_2_evm_offramp.DeployEVM2EVMOffRamp( + destUser, + destChain.Client(), + evm_2_evm_offramp.EVM2EVMOffRampStaticConfig{ + CommitStore: commitStore.Address(), + ChainSelector: destChainSelector, + SourceChainSelector: sourceChainSelector, + OnRamp: onRampAddress, + PrevOffRamp: common.HexToAddress(""), + ArmProxy: armProxyDestAddress, + }, + []common.Address{sourceLinkTokenAddress, sourceWeth9addr}, + []common.Address{destPoolAddress, destWrappedPool.Address()}, + evm_2_evm_offramp.RateLimiterConfig{ + IsEnabled: true, + Capacity: LinkUSDValue(100), + Rate: LinkUSDValue(1), + }, + ) + require.NoError(t, err) + offRamp, err := evm_2_evm_offramp.NewEVM2EVMOffRamp(offRampAddress, destChain.Client()) + require.NoError(t, err) + _, err = destPool.ApplyChainUpdates(destUser, + []lock_release_token_pool.TokenPoolChainUpdate{{ + RemoteChainSelector: sourceChainSelector, + Allowed: true, + OutboundRateLimiterConfig: lock_release_token_pool.RateLimiterConfig{ + IsEnabled: true, + Capacity: HundredLink, + Rate: big.NewInt(1e18), + }, + InboundRateLimiterConfig: lock_release_token_pool.RateLimiterConfig{ + IsEnabled: true, + Capacity: HundredLink, + Rate: big.NewInt(1e18), + }, + }}, + ) + require.NoError(t, err) + + _, err = destWrappedPool.ApplyRampUpdates(destUser, + []lock_release_token_pool_1_0_0.TokenPoolRampUpdate{}, + []lock_release_token_pool_1_0_0.TokenPoolRampUpdate{{ + Ramp: offRampAddress, + Allowed: true, + RateLimiterConfig: lock_release_token_pool_1_0_0.RateLimiterConfig{ + IsEnabled: true, + Capacity: HundredLink, + Rate: big.NewInt(1e18), + }, + }}, + ) + require.NoError(t, err) + + destChain.Commit() + _, err = destPriceRegistry.ApplyPriceUpdatersUpdates(destUser, []common.Address{commitStoreAddress}, []common.Address{}) + require.NoError(t, err) + _, err = destRouter.ApplyRampUpdates(destUser, nil, + nil, []router.RouterOffRamp{{SourceChainSelector: sourceChainSelector, OffRamp: offRampAddress}}) + require.NoError(t, err) + + // Deploy 2 revertable (one SS one non-SS) + revertingMessageReceiver1Address, _, _, err := maybe_revert_message_receiver.DeployMaybeRevertMessageReceiver(destUser, destChain.Client(), false) + require.NoError(t, err) + revertingMessageReceiver1, _ := maybe_revert_message_receiver.NewMaybeRevertMessageReceiver(revertingMessageReceiver1Address, destChain.Client()) + revertingMessageReceiver2Address, _, _, err := maybe_revert_message_receiver.DeployMaybeRevertMessageReceiver(destUser, destChain.Client(), false) + require.NoError(t, err) + revertingMessageReceiver2, _ := maybe_revert_message_receiver.NewMaybeRevertMessageReceiver(revertingMessageReceiver2Address, destChain.Client()) + // Need to commit here, or we will hit the block gas limit when deploying the executor + sourceChain.Commit() + destChain.Commit() + + // Ensure we have at least finality blocks. + for i := 0; i < 50; i++ { + sourceChain.Commit() + destChain.Commit() + } + + source := SourceChain{ + Common: Common{ + ChainID: sourceChainID, + ChainSelector: sourceChainSelector, + User: sourceUser, + // FIXME + //Chain: sourceChain, + LinkToken: sourceLinkToken, + LinkTokenPool: sourcePool, + CustomToken: sourceCustomToken, + ARM: sourceARM, + ARMProxy: sourceARMProxy, + PriceRegistry: srcPriceRegistry, + WrappedNative: sourceWrapped, + WrappedNativePool: sourceWeth9Pool, + }, + Router: sourceRouter, + OnRamp: onRamp, + } + dest := DestinationChain{ + Common: Common{ + ChainID: destChainID, + ChainSelector: destChainSelector, + User: destUser, + // FIXME + //Chain: destChain, + LinkToken: destLinkToken, + LinkTokenPool: destPool, + CustomToken: destCustomToken, + ARM: destARM, + ARMProxy: destARMProxy, + PriceRegistry: destPriceRegistry, + WrappedNative: destWrapped, + WrappedNativePool: destWrappedPool, + }, + CommitStore: commitStore, + Router: destRouter, + OffRamp: offRamp, + Receivers: []MaybeRevertReceiver{{Receiver: revertingMessageReceiver1, Strict: false}, {Receiver: revertingMessageReceiver2, Strict: true}}, + } + + return CCIPContracts{ + Source: source, + Dest: dest, + } +} + +func (c *CCIPContracts) SendRequest(t *testing.T, msg router.ClientEVM2AnyMessage) *types.Transaction { + tx, err := c.Source.Router.CcipSend(c.Source.User, c.Dest.ChainSelector, msg) + require.NoError(t, err) + // FIXME + // testhelpers.ConfirmTxs(t, []*types.Transaction{tx}, c.Source.Chain) + return tx +} + +func (c *CCIPContracts) AssertExecState(t *testing.T, log logpoller.Log, state MessageExecutionState, offRampOpts ...common.Address) { + var offRamp *evm_2_evm_offramp.EVM2EVMOffRamp + var err error + if len(offRampOpts) > 0 { + offRamp, err = evm_2_evm_offramp.NewEVM2EVMOffRamp(offRampOpts[0], c.Dest.Chain) + require.NoError(t, err) + } else { + require.NotNil(t, c.Dest.OffRamp, "no offRamp configured") + offRamp = c.Dest.OffRamp + } + executionStateChanged, err := offRamp.ParseExecutionStateChanged(log.ToGethLog()) + require.NoError(t, err) + if MessageExecutionState(executionStateChanged.State) != state { + t.Log("Execution failed", hexutil.Encode(executionStateChanged.ReturnData)) + t.Fail() + } +} + +func GetEVMExtraArgsV1(gasLimit *big.Int, strict bool) ([]byte, error) { + EVMV1Tag := []byte{0x97, 0xa6, 0x57, 0xc9} + + encodedArgs, err := utils.ABIEncode(`[{"type":"uint256"},{"type":"bool"}]`, gasLimit, strict) + if err != nil { + return nil, err + } + + return append(EVMV1Tag, encodedArgs...), nil +} + +type ManualExecArgs struct { + SourceChainID, DestChainID uint64 + DestUser *bind.TransactOpts + SourceChain, DestChain bind.ContractBackend + SourceStartBlock *big.Int // the block in/after which failed ccip-send transaction was triggered + DestStartBlock uint64 // the start block for filtering ReportAccepted event (including the failed seq num) + // in destination chain. if not provided to be derived by ApproxDestStartBlock method + DestLatestBlockNum uint64 // current block number in destination + DestDeployedAt uint64 // destination block number for the initial destination contract deployment. + // Can be any number before the tx was reverted in destination chain. Preferably this needs to be set up with + // a value greater than zero to avoid performance issue in locating approximate destination block + SendReqLogIndex uint // log index of the CCIPSendRequested log in source chain + SendReqTxHash string // tx hash of the ccip-send transaction for which execution was reverted + CommitStore string + OnRamp string + OffRamp string + SeqNr uint64 + GasLimit *big.Int +} + +// ApproxDestStartBlock attempts to locate a block in destination chain with timestamp closest to the timestamp of the block +// in source chain in which ccip-send transaction was included +// it uses binary search to locate the block with the closest timestamp +// if the block located has a timestamp greater than the timestamp of mentioned source block +// it just returns the first block found with lesser timestamp of the source block +// providing a value of args.DestDeployedAt ensures better performance by reducing the range of block numbers to be traversed +func (args *ManualExecArgs) ApproxDestStartBlock() error { + sourceBlockHdr, err := args.SourceChain.HeaderByNumber(context.Background(), args.SourceStartBlock) + if err != nil { + return err + } + sendTxTime := sourceBlockHdr.Time + maxBlockNum := args.DestLatestBlockNum + // setting this to an approx value of 1000 considering destination chain would have at least 1000 blocks before the transaction started + minBlockNum := args.DestDeployedAt + closestBlockNum := uint64(math.Floor((float64(maxBlockNum) + float64(minBlockNum)) / 2)) + var closestBlockHdr *types.Header + //nolint:gosec // safe to casts in tests + closestBlockHdr, err = args.DestChain.HeaderByNumber(context.Background(), big.NewInt(int64(closestBlockNum))) + if err != nil { + return err + } + // to reduce the number of RPC calls increase the value of blockOffset + blockOffset := uint64(10) + for { + blockNum := closestBlockHdr.Number.Uint64() + if minBlockNum > maxBlockNum { + break + } + timeDiff := math.Abs(float64(closestBlockHdr.Time - sendTxTime)) + // break if the difference in timestamp is lesser than 1 minute + //nolint:gocritic // tests + if timeDiff < 60 { + break + } else if closestBlockHdr.Time > sendTxTime { + maxBlockNum = blockNum - 1 + } else { + minBlockNum = blockNum + 1 + } + closestBlockNum = uint64(math.Floor((float64(maxBlockNum) + float64(minBlockNum)) / 2)) + //nolint:gosec // safe to casts in tests + closestBlockHdr, err = args.DestChain.HeaderByNumber(context.Background(), big.NewInt(int64(closestBlockNum))) + if err != nil { + return err + } + } + + for closestBlockHdr.Time > sendTxTime { + closestBlockNum -= blockOffset + if closestBlockNum <= 0 { + return errors.New("approx destination blocknumber not found") + } + //nolint:gosec // safe to casts in tests + closestBlockHdr, err = args.DestChain.HeaderByNumber(context.Background(), big.NewInt(int64(closestBlockNum))) + if err != nil { + return err + } + } + args.DestStartBlock = closestBlockHdr.Number.Uint64() + fmt.Println("using approx destination start block number", args.DestStartBlock) + return nil +} + +func (args *ManualExecArgs) FindSeqNrFromCCIPSendRequested() (uint64, error) { + var seqNr uint64 + onRampContract, err := evm_2_evm_onramp.NewEVM2EVMOnRamp(common.HexToAddress(args.OnRamp), args.SourceChain) + if err != nil { + return seqNr, err + } + iterator, err := onRampContract.FilterCCIPSendRequested(&bind.FilterOpts{ + Start: args.SourceStartBlock.Uint64(), + }) + if err != nil { + return seqNr, err + } + for iterator.Next() { + if iterator.Event.Raw.Index == args.SendReqLogIndex && + iterator.Event.Raw.TxHash.Hex() == args.SendReqTxHash { + seqNr = iterator.Event.Message.SequenceNumber + break + } + } + if seqNr == 0 { + return seqNr, + fmt.Errorf("no CCIPSendRequested logs found for logIndex %d starting from block number %d", args.SendReqLogIndex, args.SourceStartBlock) + } + return seqNr, nil +} + +func (args *ManualExecArgs) ExecuteManually() (*types.Transaction, error) { + if args.SourceChainID == 0 || + args.DestChainID == 0 || + args.DestUser == nil { + return nil, errors.New("chain ids and owners are mandatory for source and dest chain") + } + if !common.IsHexAddress(args.CommitStore) || + !common.IsHexAddress(args.OffRamp) || + !common.IsHexAddress(args.OnRamp) { + return nil, errors.New("contract addresses must be valid hex address") + } + if args.SendReqTxHash == "" { + return nil, errors.New("tx hash of ccip-send request are required") + } + if args.SourceStartBlock == nil { + return nil, errors.New("must provide the value of source block in/after which ccip-send tx was included") + } + if args.SeqNr == 0 { + if args.SendReqLogIndex == 0 { + return nil, errors.New("must provide the value of log index of ccip-send request") + } + // locate seq nr from CCIPSendRequested log + seqNr, err := args.FindSeqNrFromCCIPSendRequested() + if err != nil { + return nil, err + } + args.SeqNr = seqNr + } + commitStore, err := commit_store_1_2_0.NewCommitStore(common.HexToAddress(args.CommitStore), args.DestChain) + if err != nil { + return nil, err + } + if args.DestStartBlock < 1 { + err = args.ApproxDestStartBlock() + if err != nil { + return nil, err + } + } + iterator, err := commitStore.FilterReportAccepted(&bind.FilterOpts{Start: args.DestStartBlock}) + if err != nil { + return nil, err + } + + var commitReport *commit_store_1_2_0.CommitStoreCommitReport + for iterator.Next() { + if iterator.Event.Report.Interval.Min <= args.SeqNr && iterator.Event.Report.Interval.Max >= args.SeqNr { + commitReport = &iterator.Event.Report + fmt.Println("Found root") + break + } + } + if commitReport == nil { + return nil, fmt.Errorf("unable to find seq num %d in commit report", args.SeqNr) + } + + return args.execute(commitReport) +} + +func (args *ManualExecArgs) execute(report *commit_store_1_2_0.CommitStoreCommitReport) (*types.Transaction, error) { + log.Info().Msg("Executing request manually") + seqNr := args.SeqNr + // Build a merkle tree for the report + mctx := hashutil.NewKeccak() + onRampContract, err := evm_2_evm_onramp_1_2_0.NewEVM2EVMOnRamp(common.HexToAddress(args.OnRamp), args.SourceChain) + if err != nil { + return nil, err + } + leafHasher := v1_2_0.NewLeafHasher(args.SourceChainID, args.DestChainID, common.HexToAddress(args.OnRamp), mctx, onRampContract) + if leafHasher == nil { + return nil, errors.New("unable to create leaf hasher") + } + + var leaves [][32]byte + var curr, prove int + var msgs []evm_2_evm_offramp.InternalEVM2EVMMessage + var manualExecGasLimits []*big.Int + var tokenData [][][]byte + sendRequestedIterator, err := onRampContract.FilterCCIPSendRequested(&bind.FilterOpts{ + Start: args.SourceStartBlock.Uint64(), + }) + if err != nil { + return nil, err + } + for sendRequestedIterator.Next() { + if sendRequestedIterator.Event.Message.SequenceNumber <= report.Interval.Max && + sendRequestedIterator.Event.Message.SequenceNumber >= report.Interval.Min { + fmt.Println("Found seq num", sendRequestedIterator.Event.Message.SequenceNumber, report.Interval) + hash, err2 := leafHasher.HashLeaf(sendRequestedIterator.Event.Raw) + if err2 != nil { + return nil, err2 + } + leaves = append(leaves, hash) + if sendRequestedIterator.Event.Message.SequenceNumber == seqNr { + fmt.Printf("Found proving %d %+v\n", curr, sendRequestedIterator.Event.Message) + var tokensAndAmounts []evm_2_evm_offramp.ClientEVMTokenAmount + for _, tokenAndAmount := range sendRequestedIterator.Event.Message.TokenAmounts { + tokensAndAmounts = append(tokensAndAmounts, evm_2_evm_offramp.ClientEVMTokenAmount{ + Token: tokenAndAmount.Token, + Amount: tokenAndAmount.Amount, + }) + } + msg := evm_2_evm_offramp.InternalEVM2EVMMessage{ + SourceChainSelector: sendRequestedIterator.Event.Message.SourceChainSelector, + Sender: sendRequestedIterator.Event.Message.Sender, + Receiver: sendRequestedIterator.Event.Message.Receiver, + SequenceNumber: sendRequestedIterator.Event.Message.SequenceNumber, + GasLimit: sendRequestedIterator.Event.Message.GasLimit, + Strict: sendRequestedIterator.Event.Message.Strict, + Nonce: sendRequestedIterator.Event.Message.Nonce, + FeeToken: sendRequestedIterator.Event.Message.FeeToken, + FeeTokenAmount: sendRequestedIterator.Event.Message.FeeTokenAmount, + Data: sendRequestedIterator.Event.Message.Data, + TokenAmounts: tokensAndAmounts, + SourceTokenData: sendRequestedIterator.Event.Message.SourceTokenData, + MessageId: sendRequestedIterator.Event.Message.MessageId, + } + msgs = append(msgs, msg) + if args.GasLimit != nil { + msg.GasLimit = args.GasLimit + } + manualExecGasLimits = append(manualExecGasLimits, msg.GasLimit) + var msgTokenData [][]byte + for range sendRequestedIterator.Event.Message.TokenAmounts { + msgTokenData = append(msgTokenData, []byte{}) + } + + tokenData = append(tokenData, msgTokenData) + prove = curr + } + curr++ + } + } + sendRequestedIterator.Close() + if msgs == nil { + return nil, fmt.Errorf("unable to find msg with seqNr %d", seqNr) + } + tree, err := merklemulti.NewTree(mctx, leaves) + if err != nil { + return nil, err + } + if tree.Root() != report.MerkleRoot { + return nil, errors.New("root doesn't match") + } + + proof, err := tree.Prove([]int{prove}) + if err != nil { + return nil, err + } + + offRampProof := evm_2_evm_offramp.InternalExecutionReport{ + Messages: msgs, + OffchainTokenData: tokenData, + Proofs: proof.Hashes, + ProofFlagBits: abihelpers.ProofFlagsToBits(proof.SourceFlags), + } + offRamp, err := evm_2_evm_offramp.NewEVM2EVMOffRamp(common.HexToAddress(args.OffRamp), args.DestChain) + if err != nil { + return nil, err + } + // Execute. + return offRamp.ManuallyExecute(args.DestUser, offRampProof, manualExecGasLimits) +} + +func (c *CCIPContracts) ExecuteMessage( + t *testing.T, + req logpoller.Log, + txHash common.Hash, + destStartBlock uint64, +) uint64 { + t.Log("Executing request manually") + sendReqReceipt, err := c.Source.Chain.TransactionReceipt(context.Background(), txHash) + require.NoError(t, err) + args := ManualExecArgs{ + SourceChainID: c.Source.ChainID, + DestChainID: c.Dest.ChainID, + DestUser: c.Dest.User, + SourceChain: c.Source.Chain, + DestChain: c.Dest.Chain, + SourceStartBlock: sendReqReceipt.BlockNumber, + DestStartBlock: destStartBlock, + // FIXME + //DestLatestBlockNum: c.Dest.Chain.Blockchain().CurrentBlock().Number.Uint64(), + //nolint:gosec // safe to casts in tests + SendReqLogIndex: uint(req.LogIndex), + SendReqTxHash: txHash.String(), + CommitStore: c.Dest.CommitStore.Address().String(), + OnRamp: c.Source.OnRamp.Address().String(), + OffRamp: c.Dest.OffRamp.Address().String(), + } + tx, err := args.ExecuteManually() + require.NoError(t, err) + c.Dest.Chain.Commit() + c.Source.Chain.Commit() + rec, err := c.Dest.Chain.TransactionReceipt(context.Background(), tx.Hash()) + require.NoError(t, err) + require.Equal(t, uint64(1), rec.Status, "manual execution failed") + t.Logf("Manual Execution completed for seqNum %d", args.SeqNr) + return args.SeqNr +} + +func GetBalance(t *testing.T, chain bind.ContractBackend, tokenAddr common.Address, addr common.Address) *big.Int { + token, err := link_token_interface.NewLinkToken(tokenAddr, chain) + require.NoError(t, err) + bal, err := token.BalanceOf(nil, addr) + require.NoError(t, err) + return bal +} diff --git a/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/chainlink.go b/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/chainlink.go new file mode 100644 index 00000000000..cec58136b5c --- /dev/null +++ b/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/chainlink.go @@ -0,0 +1,1054 @@ +//nolint:revive // helpers for specific version +package testhelpers_1_4_0 + +import ( + "context" + "encoding/hex" + "fmt" + "math/big" + "net/http" + "net/http/httptest" + "strconv" + "strings" + "testing" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" + "github.com/ethereum/go-ethereum/common" + types3 "github.com/ethereum/go-ethereum/core/types" + "github.com/google/uuid" + "github.com/hashicorp/consul/sdk/freeport" + "github.com/jmoiron/sqlx" + "github.com/onsi/gomega" + "github.com/pkg/errors" + + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "go.uber.org/zap" + "k8s.io/utils/pointer" //nolint:staticcheck // tests + + "github.com/smartcontractkit/libocr/commontypes" + "github.com/smartcontractkit/libocr/offchainreporting2/confighelper" + types4 "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink-common/pkg/loop" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + + cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" + + pb "github.com/smartcontractkit/chainlink-protos/orchestrator/feedsmanager" + + evmcapabilities "github.com/smartcontractkit/chainlink/v2/core/capabilities" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + v2 "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + evmUtils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" + "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" + configv2 "github.com/smartcontractkit/chainlink/v2/core/config/toml" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store_1_2_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_offramp_1_2_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp_1_2_0" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/logger/audit" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + feeds2 "github.com/smartcontractkit/chainlink/v2/core/services/feeds" + feedsMocks "github.com/smartcontractkit/chainlink/v2/core/services/feeds/mocks" + "github.com/smartcontractkit/chainlink/v2/core/services/job" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/csakey" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" + ksMocks "github.com/smartcontractkit/chainlink/v2/core/services/keystore/mocks" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers" + integrationtesthelpers "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers/integration" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" + "github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap" + evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" + clutils "github.com/smartcontractkit/chainlink/v2/core/utils" + "github.com/smartcontractkit/chainlink/v2/core/utils/crypto" + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" + "github.com/smartcontractkit/chainlink/v2/plugins" +) + +const ( + execSpecTemplate = ` + type = "offchainreporting2" + schemaVersion = 1 + name = "ccip-exec-1" + externalJobID = "67ffad71-d90f-4fe3-b4e4-494924b707fb" + forwardingAllowed = false + maxTaskDuration = "0s" + contractID = "%s" + contractConfigConfirmations = 1 + contractConfigTrackerPollInterval = "20s" + ocrKeyBundleID = "%s" + relay = "evm" + pluginType = "ccip-execution" + transmitterID = "%s" + + [relayConfig] + chainID = 1_337 + + [pluginConfig] + destStartBlock = 50 + + [pluginConfig.USDCConfig] + AttestationAPI = "http://blah.com" + SourceMessageTransmitterAddress = "%s" + SourceTokenAddress = "%s" + AttestationAPITimeoutSeconds = 10 + ` + commitSpecTemplatePipeline = ` + type = "offchainreporting2" + schemaVersion = 1 + name = "ccip-commit-1" + externalJobID = "13c997cf-1a14-4ab7-9068-07ee6d2afa55" + forwardingAllowed = false + maxTaskDuration = "0s" + contractID = "%s" + contractConfigConfirmations = 1 + contractConfigTrackerPollInterval = "20s" + ocrKeyBundleID = "%s" + relay = "evm" + pluginType = "ccip-commit" + transmitterID = "%s" + + [relayConfig] + chainID = 1_337 + + [pluginConfig] + destStartBlock = 50 + offRamp = "%s" + tokenPricesUSDPipeline = """ + %s + """ + ` + commitSpecTemplateDynamicPriceGetter = ` + type = "offchainreporting2" + schemaVersion = 1 + name = "ccip-commit-1" + externalJobID = "13c997cf-1a14-4ab7-9068-07ee6d2afa55" + forwardingAllowed = false + maxTaskDuration = "0s" + contractID = "%s" + contractConfigConfirmations = 1 + contractConfigTrackerPollInterval = "20s" + ocrKeyBundleID = "%s" + relay = "evm" + pluginType = "ccip-commit" + transmitterID = "%s" + + [relayConfig] + chainID = 1_337 + + [pluginConfig] + destStartBlock = 50 + offRamp = "%s" + priceGetterConfig = """ + %s + """ + ` +) + +type Node struct { + App chainlink.Application + Transmitter common.Address + PaymentReceiver common.Address + KeyBundle ocr2key.KeyBundle +} + +func (node *Node) FindJobIDForContract(t *testing.T, addr common.Address) int32 { + jobs := node.App.JobSpawner().ActiveJobs() + for _, j := range jobs { + if j.Type == job.OffchainReporting2 && j.OCR2OracleSpec.ContractID == addr.Hex() { + return j.ID + } + } + t.Fatalf("Could not find job for contract %s", addr.Hex()) + return 0 +} + +func (node *Node) EventuallyNodeUsesUpdatedPriceRegistry(t *testing.T, ccipContracts CCIPIntegrationTestHarness) logpoller.Log { + c, err := node.App.GetRelayers().LegacyEVMChains().Get(strconv.FormatUint(ccipContracts.Dest.ChainID, 10)) + require.NoError(t, err) + var log logpoller.Log + gomega.NewGomegaWithT(t).Eventually(func() bool { + ccipContracts.Source.Chain.Commit() + ccipContracts.Dest.Chain.Commit() + log, err := c.LogPoller().LatestLogByEventSigWithConfs( + testutils.Context(t), + v1_2_0.UsdPerUnitGasUpdated, + ccipContracts.Dest.PriceRegistry.Address(), + 0, + ) + // err can be transient errors such as sql row set empty + if err != nil { + return false + } + return log != nil + }, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue(), "node is not using updated price registry %s", ccipContracts.Dest.PriceRegistry.Address().Hex()) + return log +} + +func (node *Node) EventuallyNodeUsesNewCommitConfig(t *testing.T, ccipContracts CCIPIntegrationTestHarness, commitCfg ccipdata.CommitOnchainConfig) logpoller.Log { + c, err := node.App.GetRelayers().LegacyEVMChains().Get(strconv.FormatUint(ccipContracts.Dest.ChainID, 10)) + require.NoError(t, err) + var log logpoller.Log + gomega.NewGomegaWithT(t).Eventually(func() bool { + ccipContracts.Source.Chain.Commit() + ccipContracts.Dest.Chain.Commit() + log, err := c.LogPoller().LatestLogByEventSigWithConfs( + testutils.Context(t), + evmrelay.OCR2AggregatorLogDecoder.EventSig(), + ccipContracts.Dest.CommitStore.Address(), + 0, + ) + require.NoError(t, err) + var latestCfg ccipdata.CommitOnchainConfig + if log != nil { + latestCfg, err = DecodeCommitOnChainConfig(log.Data) + require.NoError(t, err) + return latestCfg == commitCfg + } + return false + }, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue(), "node is using old cfg") + return log +} + +func (node *Node) EventuallyNodeUsesNewExecConfig(t *testing.T, ccipContracts CCIPIntegrationTestHarness, execCfg v1_2_0.ExecOnchainConfig) logpoller.Log { + c, err := node.App.GetRelayers().LegacyEVMChains().Get(strconv.FormatUint(ccipContracts.Dest.ChainID, 10)) + require.NoError(t, err) + var log logpoller.Log + gomega.NewGomegaWithT(t).Eventually(func() bool { + ccipContracts.Source.Chain.Commit() + ccipContracts.Dest.Chain.Commit() + log, err := c.LogPoller().LatestLogByEventSigWithConfs( + testutils.Context(t), + evmrelay.OCR2AggregatorLogDecoder.EventSig(), + ccipContracts.Dest.OffRamp.Address(), + 0, + ) + require.NoError(t, err) + var latestCfg v1_2_0.ExecOnchainConfig + if log != nil { + latestCfg, err = DecodeExecOnChainConfig(log.Data) + require.NoError(t, err) + return latestCfg == execCfg + } + return false + }, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue(), "node is using old cfg") + return log +} + +//nolint:gosec // safe cast in tests +func (node *Node) EventuallyHasReqSeqNum(t *testing.T, ccipContracts *CCIPIntegrationTestHarness, onRamp common.Address, seqNum int) logpoller.Log { + c, err := node.App.GetRelayers().LegacyEVMChains().Get(strconv.FormatUint(ccipContracts.Source.ChainID, 10)) + require.NoError(t, err) + var log logpoller.Log + gomega.NewGomegaWithT(t).Eventually(func() bool { + ccipContracts.Source.Chain.Commit() + ccipContracts.Dest.Chain.Commit() + lgs, err := c.LogPoller().LogsDataWordRange( + testutils.Context(t), + v1_2_0.CCIPSendRequestEventSig, + onRamp, + v1_2_0.CCIPSendRequestSeqNumIndex, + abihelpers.EvmWord(uint64(seqNum)), + abihelpers.EvmWord(uint64(seqNum)), + 1, + ) + require.NoError(t, err) + t.Log("Send requested", len(lgs)) + if len(lgs) == 1 { + log = lgs[0] + return true + } + return false + }, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue(), "eventually has seq num") + return log +} + +//nolint:gosec // safe cast in tests +func (node *Node) EventuallyHasExecutedSeqNums(t *testing.T, ccipContracts *CCIPIntegrationTestHarness, offRamp common.Address, minSeqNum int, maxSeqNum int) []logpoller.Log { + c, err := node.App.GetRelayers().LegacyEVMChains().Get(strconv.FormatUint(ccipContracts.Dest.ChainID, 10)) + require.NoError(t, err) + var logs []logpoller.Log + gomega.NewGomegaWithT(t).Eventually(func() bool { + ccipContracts.Source.Chain.Commit() + ccipContracts.Dest.Chain.Commit() + lgs, err := c.LogPoller().IndexedLogsTopicRange( + testutils.Context(t), + v1_2_0.ExecutionStateChangedEvent, + offRamp, + v1_2_0.ExecutionStateChangedSeqNrIndex, + abihelpers.EvmWord(uint64(minSeqNum)), + abihelpers.EvmWord(uint64(maxSeqNum)), + 1, + ) + require.NoError(t, err) + t.Logf("Have executed logs %d want %d", len(lgs), maxSeqNum-minSeqNum+1) + if len(lgs) == maxSeqNum-minSeqNum+1 { + logs = lgs + t.Logf("Seq Num %d-%d executed", minSeqNum, maxSeqNum) + return true + } + return false + }, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue(), "eventually has not executed seq num") + return logs +} + +//nolint:gosec // safe to casts in tests +func (node *Node) ConsistentlySeqNumHasNotBeenExecuted(t *testing.T, ccipContracts *CCIPIntegrationTestHarness, offRamp common.Address, seqNum int) logpoller.Log { + c, err := node.App.GetRelayers().LegacyEVMChains().Get(strconv.FormatUint(ccipContracts.Dest.ChainID, 10)) + require.NoError(t, err) + var log logpoller.Log + gomega.NewGomegaWithT(t).Consistently(func() bool { + ccipContracts.Source.Chain.Commit() + ccipContracts.Dest.Chain.Commit() + lgs, err := c.LogPoller().IndexedLogsTopicRange( + testutils.Context(t), + v1_2_0.ExecutionStateChangedEvent, + offRamp, + v1_2_0.ExecutionStateChangedSeqNrIndex, + abihelpers.EvmWord(uint64(seqNum)), + abihelpers.EvmWord(uint64(seqNum)), + 1, + ) + require.NoError(t, err) + t.Log("Executed logs", lgs) + if len(lgs) == 1 { + log = lgs[0] + return true + } + return false + }, 10*time.Second, 1*time.Second).Should(gomega.BeFalse(), "seq number got executed") + return log +} + +func (node *Node) AddJob(t *testing.T, spec *integrationtesthelpers.OCR2TaskJobSpec) { + specString, err := spec.String() + require.NoError(t, err) + ccipJob, err := validate.ValidatedOracleSpecToml( + testutils.Context(t), + node.App.GetConfig().OCR2(), + node.App.GetConfig().Insecure(), + specString, + // FIXME Ani + nil, + ) + require.NoError(t, err) + err = node.App.AddJobV2(context.Background(), &ccipJob) + require.NoError(t, err) +} + +func (node *Node) AddBootstrapJob(t *testing.T, spec *integrationtesthelpers.OCR2TaskJobSpec) { + specString, err := spec.String() + require.NoError(t, err) + ccipJob, err := ocrbootstrap.ValidatedBootstrapSpecToml(specString) + require.NoError(t, err) + err = node.App.AddJobV2(context.Background(), &ccipJob) + require.NoError(t, err) +} + +func (node *Node) AddJobsWithSpec(t *testing.T, jobSpec *integrationtesthelpers.OCR2TaskJobSpec) { + // set node specific values + jobSpec.OCR2OracleSpec.OCRKeyBundleID.SetValid(node.KeyBundle.ID()) + jobSpec.OCR2OracleSpec.TransmitterID.SetValid(node.Transmitter.Hex()) + node.AddJob(t, jobSpec) +} + +func setupNodeCCIP( + t *testing.T, + owner *bind.TransactOpts, + port int64, + dbName string, + sourceChain *backends.SimulatedBackend, destChain *backends.SimulatedBackend, + sourceChainID *big.Int, destChainID *big.Int, + bootstrapPeerID string, + bootstrapPort int64, +) (chainlink.Application, string, common.Address, ocr2key.KeyBundle) { + trueRef, falseRef := true, false + + // Do not want to load fixtures as they contain a dummy chainID. + loglevel := configv2.LogLevel(zap.DebugLevel) + config, db := heavyweight.FullTestDBNoFixturesV2(t, func(c *chainlink.Config, _ *chainlink.Secrets) { + p2pAddresses := []string{ + fmt.Sprintf("127.0.0.1:%d", port), + } + c.Log.Level = &loglevel + c.Feature.CCIP = &trueRef + c.Feature.UICSAKeys = &trueRef + c.Feature.FeedsManager = &trueRef + c.OCR.Enabled = &falseRef + c.OCR.DefaultTransactionQueueDepth = pointer.Uint32(200) + c.OCR2.Enabled = &trueRef + c.Feature.LogPoller = &trueRef + c.P2P.V2.Enabled = &trueRef + + dur, err := config.NewDuration(500 * time.Millisecond) + if err != nil { + panic(err) + } + c.P2P.V2.DeltaDial = &dur + + dur2, err := config.NewDuration(5 * time.Second) + if err != nil { + panic(err) + } + + c.P2P.V2.DeltaReconcile = &dur2 + c.P2P.V2.ListenAddresses = &p2pAddresses + c.P2P.V2.AnnounceAddresses = &p2pAddresses + + c.EVM = []*v2.EVMConfig{createConfigV2Chain(sourceChainID), createConfigV2Chain(destChainID)} + + if bootstrapPeerID != "" { + // Supply the bootstrap IP and port as a V2 peer address + c.P2P.V2.DefaultBootstrappers = &[]commontypes.BootstrapperLocator{ + { + PeerID: bootstrapPeerID, Addrs: []string{ + fmt.Sprintf("127.0.0.1:%d", bootstrapPort), + }, + }, + } + } + }) + + lggr := logger.TestLogger(t) + + // The in-memory geth sim does not let you create a custom ChainID, it will always be 1337. + // In particular this means that if you sign an eip155 tx, the chainID used MUST be 1337 + // and the CHAINID op code will always emit 1337. To work around this to simulate a "multichain" + // test, we fake different chainIDs using the wrapped sim cltest.SimulatedBackend so the RPC + // appears to operate on different chainIDs and we use an EthKeyStoreSim wrapper which always + // signs 1337 see https://github.com/smartcontractkit/chainlink-ccip/blob/a24dd436810250a458d27d8bb3fb78096afeb79c/core/services/ocr2/plugins/ccip/testhelpers/simulated_backend.go#L35 + sourceClient := client.NewSimulatedBackendClient(t, sourceChain.Backend, sourceChainID) + destClient := client.NewSimulatedBackendClient(t, destChain.Backend, destChainID) + csaKeyStore := ksMocks.NewCSA(t) + + key, err := csakey.NewV2() + require.NoError(t, err) + csaKeyStore.On("GetAll").Return([]csakey.KeyV2{key}, nil) + keyStore := NewKsa(db, lggr, csaKeyStore) + + simEthKeyStore := testhelpers.EthKeyStoreSim{ + ETHKS: keyStore.Eth(), + CSAKS: keyStore.CSA(), + } + mailMon := mailbox.NewMonitor("CCIP", lggr.Named("Mailbox")) + evmOpts := chainlink.EVMFactoryConfig{ + ChainOpts: legacyevm.ChainOpts{ + AppConfig: config, + GenEthClient: func(chainID *big.Int) client.Client { + if chainID.String() == sourceChainID.String() { + return sourceClient + } else if chainID.String() == destChainID.String() { + return destClient + } + t.Fatalf("invalid chain ID %v", chainID.String()) + return nil + }, + MailMon: mailMon, + DS: db, + }, + CSAETHKeystore: simEthKeyStore, + } + loopRegistry := plugins.NewLoopRegistry(lggr.Named("LoopRegistry"), config.Tracing(), config.Telemetry(), nil, "") + relayerFactory := chainlink.RelayerFactory{ + Logger: lggr, + LoopRegistry: loopRegistry, + GRPCOpts: loop.GRPCOpts{}, + CapabilitiesRegistry: evmcapabilities.NewRegistry(lggr), + } + testCtx := testutils.Context(t) + // evm alway enabled for backward compatibility + initOps := []chainlink.CoreRelayerChainInitFunc{ + chainlink.InitEVM(testCtx, relayerFactory, evmOpts), + } + + relayChainInterops, err := chainlink.NewCoreRelayerChainInteroperators(initOps...) + if err != nil { + t.Fatal(err) + } + + app, err := chainlink.NewApplication(chainlink.ApplicationOpts{ + Config: config, + DS: db, + KeyStore: keyStore, + RelayerChainInteroperators: relayChainInterops, + Logger: lggr, + ExternalInitiatorManager: nil, + CloseLogger: lggr.Sync, + UnrestrictedHTTPClient: &http.Client{}, + RestrictedHTTPClient: &http.Client{}, + AuditLogger: audit.NoopLogger, + MailMon: mailMon, + LoopRegistry: plugins.NewLoopRegistry(lggr, config.Tracing(), config.Telemetry(), nil, ""), + }) + ctx := testutils.Context(t) + require.NoError(t, err) + require.NoError(t, app.GetKeyStore().Unlock(ctx, "password")) + _, err = app.GetKeyStore().P2P().Create(ctx) + require.NoError(t, err) + + p2pIDs, err := app.GetKeyStore().P2P().GetAll() + require.NoError(t, err) + require.Len(t, p2pIDs, 1) + peerID := p2pIDs[0].PeerID() + + _, err = app.GetKeyStore().Eth().Create(testCtx, destChainID) + require.NoError(t, err) + sendingKeys, err := app.GetKeyStore().Eth().EnabledKeysForChain(testCtx, destChainID) + require.NoError(t, err) + require.Len(t, sendingKeys, 1) + transmitter := sendingKeys[0].Address + s, err := app.GetKeyStore().Eth().GetState(testCtx, sendingKeys[0].ID(), destChainID) + require.NoError(t, err) + lggr.Debug(fmt.Sprintf("Transmitter address %s chainID %s", transmitter, s.EVMChainID.String())) + + // Fund the commitTransmitter address with some ETH + n, err := destChain.NonceAt(context.Background(), owner.From, nil) + require.NoError(t, err) + + tx := types3.NewTransaction(n, transmitter, big.NewInt(1000000000000000000), 21000, big.NewInt(1000000000), nil) + signedTx, err := owner.Signer(owner.From, tx) + require.NoError(t, err) + err = destChain.SendTransaction(context.Background(), signedTx) + require.NoError(t, err) + destChain.Commit() + + kb, err := app.GetKeyStore().OCR2().Create(ctx, chaintype.EVM) + require.NoError(t, err) + return app, peerID.Raw(), transmitter, kb +} + +func createConfigV2Chain(chainID *big.Int) *v2.EVMConfig { + // NOTE: For the executor jobs, the default of 500k is insufficient for a 3 message batch + defaultGasLimit := uint64(5000000) + tr := true + + sourceC := v2.Defaults((*evmUtils.Big)(chainID)) + sourceC.GasEstimator.LimitDefault = &defaultGasLimit + fixedPrice := "FixedPrice" + sourceC.GasEstimator.Mode = &fixedPrice + d, _ := config.NewDuration(100 * time.Millisecond) + sourceC.LogPollInterval = &d + fd := uint32(2) + sourceC.FinalityDepth = &fd + return &v2.EVMConfig{ + ChainID: (*evmUtils.Big)(chainID), + Enabled: &tr, + Chain: sourceC, + Nodes: v2.EVMNodes{&v2.Node{}}, + } +} + +type CCIPIntegrationTestHarness struct { + CCIPContracts + Nodes []Node + Bootstrap Node +} + +func SetupCCIPIntegrationTH(t *testing.T, sourceChainID, sourceChainSelector, destChainId, destChainSelector uint64) CCIPIntegrationTestHarness { + return CCIPIntegrationTestHarness{ + CCIPContracts: SetupCCIPContracts(t, sourceChainID, sourceChainSelector, destChainId, destChainSelector), + } +} + +//nolint:testifylint //require is used for assertions in handlers +func (c *CCIPIntegrationTestHarness) CreatePricesPipeline(t *testing.T) (string, *httptest.Server, *httptest.Server) { + linkUSD := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + _, err := w.Write([]byte(`{"UsdPerLink": "8000000000000000000"}`)) + require.NoError(t, err) + })) + ethUSD := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + _, err := w.Write([]byte(`{"UsdPerETH": "1700000000000000000000"}`)) + require.NoError(t, err) + })) + sourceWrappedNative, err := c.Source.Router.GetWrappedNative(nil) + require.NoError(t, err) + destWrappedNative, err := c.Dest.Router.GetWrappedNative(nil) + require.NoError(t, err) + tokenPricesUSDPipeline := fmt.Sprintf(` +// Price 1 +link [type=http method=GET url="%s"]; +link_parse [type=jsonparse path="UsdPerLink"]; +link->link_parse; +eth [type=http method=GET url="%s"]; +eth_parse [type=jsonparse path="UsdPerETH"]; +eth->eth_parse; +merge [type=merge left="{}" right="{\\\"%s\\\":$(link_parse), \\\"%s\\\":$(eth_parse), \\\"%s\\\":$(eth_parse)}"];`, + linkUSD.URL, ethUSD.URL, c.Dest.LinkToken.Address(), sourceWrappedNative, destWrappedNative) + + return tokenPricesUSDPipeline, linkUSD, ethUSD +} + +func (c *CCIPIntegrationTestHarness) AddAllJobs(t *testing.T, jobParams integrationtesthelpers.CCIPJobSpecParams) { + jobParams.OffRamp = c.Dest.OffRamp.Address() + + commitSpec, err := jobParams.CommitJobSpec() + require.NoError(t, err) + geExecutionSpec, err := jobParams.ExecutionJobSpec() + require.NoError(t, err) + nodes := c.Nodes + for _, node := range nodes { + node.AddJobsWithSpec(t, commitSpec) + node.AddJobsWithSpec(t, geExecutionSpec) + } +} + +func (c *CCIPIntegrationTestHarness) jobSpecProposal(t *testing.T, specTemplate string, f func() (*integrationtesthelpers.OCR2TaskJobSpec, error), feedsManagerId int64, version int32, opts ...any) feeds2.ProposeJobArgs { + spec, err := f() + require.NoError(t, err) + + args := []any{spec.OCR2OracleSpec.ContractID} + args = append(args, opts...) + + return feeds2.ProposeJobArgs{ + FeedsManagerID: feedsManagerId, + RemoteUUID: uuid.New(), + Multiaddrs: nil, + Version: version, + Spec: fmt.Sprintf(specTemplate, args...), + } +} + +func (c *CCIPIntegrationTestHarness) SetupFeedsManager(t *testing.T) { + ctx := testutils.Context(t) + for _, node := range c.Nodes { + f := node.App.GetFeedsService() + + managers, err := f.ListManagers(ctx) + require.NoError(t, err) + if len(managers) > 0 { + // Use at most one feeds manager, don't register if one already exists + continue + } + + secret := utils.RandomBytes32() + pkey, err := crypto.PublicKeyFromHex(hex.EncodeToString(secret[:])) + require.NoError(t, err) + + m := feeds2.RegisterManagerParams{ + Name: "CCIP", + URI: "http://localhost:8080", + PublicKey: *pkey, + } + + _, err = f.RegisterManager(testutils.Context(t), m) + require.NoError(t, err) + + connManager := feedsMocks.NewConnectionsManager(t) + connManager.On("GetClient", mock.Anything).Maybe().Return(NoopFeedsClient{}, nil) + connManager.On("Close").Maybe().Return() + connManager.On("IsConnected", mock.Anything).Maybe().Return(true) + f.Unsafe_SetConnectionsManager(connManager) + } +} + +func (c *CCIPIntegrationTestHarness) ApproveJobSpecs(t *testing.T, jobParams integrationtesthelpers.CCIPJobSpecParams) { + ctx := testutils.Context(t) + + for _, node := range c.Nodes { + f := node.App.GetFeedsService() + managers, err := f.ListManagers(ctx) + require.NoError(t, err) + require.Len(t, managers, 1, "expected exactly one feeds manager") + + execSpec := c.jobSpecProposal( + t, + execSpecTemplate, + jobParams.ExecutionJobSpec, + managers[0].ID, + 1, + node.KeyBundle.ID(), + node.Transmitter.Hex(), + utils.RandomAddress().String(), + utils.RandomAddress().String(), + ) + execID, err := f.ProposeJob(ctx, &execSpec) + require.NoError(t, err) + + err = f.ApproveSpec(ctx, execID, true) + require.NoError(t, err) + + var commitSpec feeds2.ProposeJobArgs + if jobParams.TokenPricesUSDPipeline != "" { + commitSpec = c.jobSpecProposal( + t, + commitSpecTemplatePipeline, + jobParams.CommitJobSpec, + managers[0].ID, + 2, + node.KeyBundle.ID(), + node.Transmitter.Hex(), + jobParams.OffRamp.String(), + jobParams.TokenPricesUSDPipeline, + ) + } else { + commitSpec = c.jobSpecProposal( + t, + commitSpecTemplateDynamicPriceGetter, + jobParams.CommitJobSpec, + managers[0].ID, + 2, + node.KeyBundle.ID(), + node.Transmitter.Hex(), + jobParams.OffRamp.String(), + jobParams.PriceGetterConfig, + ) + } + + commitID, err := f.ProposeJob(ctx, &commitSpec) + require.NoError(t, err) + + err = f.ApproveSpec(ctx, commitID, true) + require.NoError(t, err) + } +} + +func (c *CCIPIntegrationTestHarness) AllNodesHaveReqSeqNum(t *testing.T, seqNum int, onRampOpts ...common.Address) logpoller.Log { + var log logpoller.Log + nodes := c.Nodes + var onRamp common.Address + if len(onRampOpts) > 0 { + onRamp = onRampOpts[0] + } else { + require.NotNil(t, c.Source.OnRamp, "no onramp configured") + onRamp = c.Source.OnRamp.Address() + } + for _, node := range nodes { + log = node.EventuallyHasReqSeqNum(t, c, onRamp, seqNum) + } + return log +} + +func (c *CCIPIntegrationTestHarness) AllNodesHaveExecutedSeqNums(t *testing.T, minSeqNum int, maxSeqNum int, offRampOpts ...common.Address) []logpoller.Log { + var logs []logpoller.Log + nodes := c.Nodes + var offRamp common.Address + + if len(offRampOpts) > 0 { + offRamp = offRampOpts[0] + } else { + require.NotNil(t, c.Dest.OffRamp, "no offramp configured") + offRamp = c.Dest.OffRamp.Address() + } + for _, node := range nodes { + logs = node.EventuallyHasExecutedSeqNums(t, c, offRamp, minSeqNum, maxSeqNum) + } + return logs +} + +func (c *CCIPIntegrationTestHarness) NoNodesHaveExecutedSeqNum(t *testing.T, seqNum int, offRampOpts ...common.Address) logpoller.Log { + var log logpoller.Log + nodes := c.Nodes + var offRamp common.Address + if len(offRampOpts) > 0 { + offRamp = offRampOpts[0] + } else { + require.NotNil(t, c.Dest.OffRamp, "no offramp configured") + offRamp = c.Dest.OffRamp.Address() + } + for _, node := range nodes { + log = node.ConsistentlySeqNumHasNotBeenExecuted(t, c, offRamp, seqNum) + } + return log +} + +func (c *CCIPIntegrationTestHarness) EventuallyCommitReportAccepted(t *testing.T, currentBlock uint64, commitStoreOpts ...common.Address) commit_store_1_2_0.CommitStoreCommitReport { + var commitStore *commit_store_1_2_0.CommitStore + var err error + if len(commitStoreOpts) > 0 { + commitStore, err = commit_store_1_2_0.NewCommitStore(commitStoreOpts[0], c.Dest.Chain) + require.NoError(t, err) + } else { + require.NotNil(t, c.Dest.CommitStore, "no commitStore configured") + commitStore = c.Dest.CommitStore + } + g := gomega.NewGomegaWithT(t) + var report commit_store_1_2_0.CommitStoreCommitReport + g.Eventually(func() bool { + it, err := commitStore.FilterReportAccepted(&bind.FilterOpts{Start: currentBlock}) + g.Expect(err).NotTo(gomega.HaveOccurred(), "Error filtering ReportAccepted event") + g.Expect(it.Next()).To(gomega.BeTrue(), "No ReportAccepted event found") + report = it.Event.Report + if report.MerkleRoot != [32]byte{} { + t.Log("Report Accepted by commitStore") + return true + } + return false + }, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue(), "report has not been committed") + return report +} + +func (c *CCIPIntegrationTestHarness) EventuallyExecutionStateChangedToSuccess(t *testing.T, seqNum []uint64, blockNum uint64, offRampOpts ...common.Address) { + var offRamp *evm_2_evm_offramp_1_2_0.EVM2EVMOffRamp + var err error + if len(offRampOpts) > 0 { + offRamp, err = evm_2_evm_offramp_1_2_0.NewEVM2EVMOffRamp(offRampOpts[0], c.Dest.Chain) + require.NoError(t, err) + } else { + require.NotNil(t, c.Dest.OffRamp, "no offRamp configured") + offRamp = c.Dest.OffRamp + } + gomega.NewGomegaWithT(t).Eventually(func() bool { + it, err := offRamp.FilterExecutionStateChanged(&bind.FilterOpts{Start: blockNum}, seqNum, [][32]byte{}) + require.NoError(t, err) + for it.Next() { + if cciptypes.MessageExecutionState(it.Event.State) == cciptypes.ExecutionStateSuccess { + t.Logf("ExecutionStateChanged event found for seqNum %d", it.Event.SequenceNumber) + return true + } + } + c.Source.Chain.Commit() + c.Dest.Chain.Commit() + return false + }, testutils.WaitTimeout(t), time.Second). + Should(gomega.BeTrue(), "ExecutionStateChanged Event") +} + +//nolint:gosec // safe to casts in tests +func (c *CCIPIntegrationTestHarness) EventuallyReportCommitted(t *testing.T, maxSeqNr int, commitStoreOpts ...common.Address) uint64 { + var commitStore *commit_store_1_2_0.CommitStore + var err error + var committedSeqNum uint64 + if len(commitStoreOpts) > 0 { + commitStore, err = commit_store_1_2_0.NewCommitStore(commitStoreOpts[0], c.Dest.Chain) + require.NoError(t, err) + } else { + require.NotNil(t, c.Dest.CommitStore, "no commitStore configured") + commitStore = c.Dest.CommitStore + } + gomega.NewGomegaWithT(t).Eventually(func() bool { + minSeqNum, err := commitStore.GetExpectedNextSequenceNumber(nil) + require.NoError(t, err) + c.Source.Chain.Commit() + c.Dest.Chain.Commit() + t.Log("next expected seq num reported", minSeqNum) + committedSeqNum = minSeqNum + return minSeqNum > uint64(maxSeqNr) + }, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue(), "report has not been committed") + return committedSeqNum +} + +func (c *CCIPIntegrationTestHarness) EventuallySendRequested(t *testing.T, seqNum uint64, onRampOpts ...common.Address) { + var onRamp *evm_2_evm_onramp_1_2_0.EVM2EVMOnRamp + var err error + if len(onRampOpts) > 0 { + onRamp, err = evm_2_evm_onramp_1_2_0.NewEVM2EVMOnRamp(onRampOpts[0], c.Source.Chain) + require.NoError(t, err) + } else { + require.NotNil(t, c.Source.OnRamp, "no onRamp configured") + onRamp = c.Source.OnRamp + } + gomega.NewGomegaWithT(t).Eventually(func() bool { + it, err := onRamp.FilterCCIPSendRequested(nil) + require.NoError(t, err) + for it.Next() { + if it.Event.Message.SequenceNumber == seqNum { + t.Log("sendRequested generated for", seqNum) + return true + } + } + c.Source.Chain.Commit() + c.Dest.Chain.Commit() + return false + }, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue(), "sendRequested has not been generated") +} + +//nolint:gosec // safe to cast in tests +func (c *CCIPIntegrationTestHarness) ConsistentlyReportNotCommitted(t *testing.T, maxSeqNr int, commitStoreOpts ...common.Address) { + var commitStore *commit_store_1_2_0.CommitStore + var err error + if len(commitStoreOpts) > 0 { + commitStore, err = commit_store_1_2_0.NewCommitStore(commitStoreOpts[0], c.Dest.Chain) + require.NoError(t, err) + } else { + require.NotNil(t, c.Dest.CommitStore, "no commitStore configured") + commitStore = c.Dest.CommitStore + } + gomega.NewGomegaWithT(t).Consistently(func() bool { + minSeqNum, err := commitStore.GetExpectedNextSequenceNumber(nil) + require.NoError(t, err) + c.Source.Chain.Commit() + c.Dest.Chain.Commit() + t.Log("min seq num reported", minSeqNum) + return minSeqNum > uint64(maxSeqNr) + }, testutils.WaitTimeout(t), time.Second).Should(gomega.BeFalse(), "report has been committed") +} + +func (c *CCIPIntegrationTestHarness) SetupAndStartNodes(ctx context.Context, t *testing.T, bootstrapNodePort int64) (Node, []Node, int64) { + appBootstrap, bootstrapPeerID, bootstrapTransmitter, bootstrapKb := setupNodeCCIP(t, c.Dest.User, bootstrapNodePort, + "bootstrap_ccip", c.Source.Chain, c.Dest.Chain, big.NewInt(0).SetUint64(c.Source.ChainID), + big.NewInt(0).SetUint64(c.Dest.ChainID), "", 0) + var ( + oracles []confighelper.OracleIdentityExtra + nodes []Node + ) + err := appBootstrap.Start(ctx) + require.NoError(t, err) + t.Cleanup(func() { + require.NoError(t, appBootstrap.Stop()) + }) + bootstrapNode := Node{ + App: appBootstrap, + Transmitter: bootstrapTransmitter, + KeyBundle: bootstrapKb, + } + // Set up the minimum 4 oracles all funded with destination ETH + for i := int64(0); i < 4; i++ { + app, peerID, transmitter, kb := setupNodeCCIP( + t, + c.Dest.User, + int64(freeport.GetOne(t)), + fmt.Sprintf("oracle_ccip%d", i), + c.Source.Chain, + c.Dest.Chain, + big.NewInt(0).SetUint64(c.Source.ChainID), + big.NewInt(0).SetUint64(c.Dest.ChainID), + bootstrapPeerID, + bootstrapNodePort, + ) + nodes = append(nodes, Node{ + App: app, + Transmitter: transmitter, + KeyBundle: kb, + }) + offchainPublicKey, _ := hex.DecodeString(strings.TrimPrefix(kb.OnChainPublicKey(), "0x")) + oracles = append(oracles, confighelper.OracleIdentityExtra{ + OracleIdentity: confighelper.OracleIdentity{ + OnchainPublicKey: offchainPublicKey, + TransmitAccount: types4.Account(transmitter.String()), + OffchainPublicKey: kb.OffchainPublicKey(), + PeerID: peerID, + }, + ConfigEncryptionPublicKey: kb.ConfigEncryptionPublicKey(), + }) + err = app.Start(ctx) + require.NoError(t, err) + t.Cleanup(func() { + require.NoError(t, app.Stop()) + }) + } + + c.Oracles = oracles + commitOnchainConfig := c.CreateDefaultCommitOnchainConfig(t) + commitOffchainConfig := c.CreateDefaultCommitOffchainConfig(t) + execOnchainConfig := c.CreateDefaultExecOnchainConfig(t) + execOffchainConfig := c.CreateDefaultExecOffchainConfig(t) + + configBlock := c.SetupOnchainConfig(t, commitOnchainConfig, commitOffchainConfig, execOnchainConfig, execOffchainConfig) + c.Nodes = nodes + c.Bootstrap = bootstrapNode + return bootstrapNode, nodes, configBlock +} + +func (c *CCIPIntegrationTestHarness) SetUpNodesAndJobs(t *testing.T, pricePipeline string, priceGetterConfig string, usdcAttestationAPI string) integrationtesthelpers.CCIPJobSpecParams { + // setup Jobs + ctx := context.Background() + // Starts nodes and configures them in the OCR contracts. + bootstrapNode, _, configBlock := c.SetupAndStartNodes(ctx, t, int64(freeport.GetOne(t))) + + jobParams := c.NewCCIPJobSpecParams(pricePipeline, priceGetterConfig, configBlock, usdcAttestationAPI) + + // Add the bootstrap job + c.Bootstrap.AddBootstrapJob(t, jobParams.BootstrapJob(c.Dest.CommitStore.Address().Hex())) + c.AddAllJobs(t, jobParams) + + // Replay for bootstrap. + bc, err := bootstrapNode.App.GetRelayers().LegacyEVMChains().Get(strconv.FormatUint(c.Dest.ChainID, 10)) + require.NoError(t, err) + require.NoError(t, bc.LogPoller().Replay(context.Background(), configBlock)) + c.Dest.Chain.Commit() + + return jobParams +} + +//nolint:gosec // safe to cast in tests +func (c *CCIPIntegrationTestHarness) NewCCIPJobSpecParams(tokenPricesUSDPipeline string, priceGetterConfig string, configBlock int64, usdcAttestationAPI string) integrationtesthelpers.CCIPJobSpecParams { + return integrationtesthelpers.CCIPJobSpecParams{ + CommitStore: c.Dest.CommitStore.Address(), + OffRamp: c.Dest.OffRamp.Address(), + DestEvmChainId: c.Dest.ChainID, + SourceChainName: "SimulatedSource", + DestChainName: "SimulatedDest", + TokenPricesUSDPipeline: tokenPricesUSDPipeline, + PriceGetterConfig: priceGetterConfig, + DestStartBlock: uint64(configBlock), + USDCAttestationAPI: usdcAttestationAPI, + } +} + +func DecodeCommitOnChainConfig(encoded []byte) (ccipdata.CommitOnchainConfig, error) { + var onchainConfig ccipdata.CommitOnchainConfig + unpacked, err := abihelpers.DecodeOCR2Config(encoded) + if err != nil { + return onchainConfig, err + } + onChainCfg := unpacked.OnchainConfig + onchainConfig, err = abihelpers.DecodeAbiStruct[ccipdata.CommitOnchainConfig](onChainCfg) + if err != nil { + return onchainConfig, err + } + return onchainConfig, nil +} + +func DecodeExecOnChainConfig(encoded []byte) (v1_2_0.ExecOnchainConfig, error) { + var onchainConfig v1_2_0.ExecOnchainConfig + unpacked, err := abihelpers.DecodeOCR2Config(encoded) + if err != nil { + return onchainConfig, errors.Wrap(err, "failed to unpack log data") + } + onChainCfg := unpacked.OnchainConfig + onchainConfig, err = abihelpers.DecodeAbiStruct[v1_2_0.ExecOnchainConfig](onChainCfg) + if err != nil { + return onchainConfig, err + } + return onchainConfig, nil +} + +type ksa struct { + keystore.Master + csa keystore.CSA +} + +func (k *ksa) CSA() keystore.CSA { + return k.csa +} + +func NewKsa(db *sqlx.DB, lggr logger.Logger, csa keystore.CSA) *ksa { + return &ksa{ + Master: keystore.New(db, clutils.FastScryptParams, lggr), + csa: csa, + } +} + +type NoopFeedsClient struct{} + +func (n NoopFeedsClient) ApprovedJob(context.Context, *pb.ApprovedJobRequest) (*pb.ApprovedJobResponse, error) { + return &pb.ApprovedJobResponse{}, nil +} + +func (n NoopFeedsClient) Healthcheck(context.Context, *pb.HealthcheckRequest) (*pb.HealthcheckResponse, error) { + return &pb.HealthcheckResponse{}, nil +} + +func (n NoopFeedsClient) UpdateNode(context.Context, *pb.UpdateNodeRequest) (*pb.UpdateNodeResponse, error) { + return &pb.UpdateNodeResponse{}, nil +} + +func (n NoopFeedsClient) RejectedJob(context.Context, *pb.RejectedJobRequest) (*pb.RejectedJobResponse, error) { + return &pb.RejectedJobResponse{}, nil +} + +func (n NoopFeedsClient) CancelledJob(context.Context, *pb.CancelledJobRequest) (*pb.CancelledJobResponse, error) { + return &pb.CancelledJobResponse{}, nil +} diff --git a/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/config_1_4_0.go b/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/config_1_4_0.go new file mode 100644 index 00000000000..adfdfd9283e --- /dev/null +++ b/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/config_1_4_0.go @@ -0,0 +1,76 @@ +// Package testhelpers_1_4_0 pkg with set of configs that should be used only within tests suites +// +//nolint:revive // used in tests +package testhelpers_1_4_0 + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/config" + + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers" +) + +var PermissionLessExecutionThresholdSeconds = uint32(testhelpers.FirstBlockAge.Seconds()) + +func (c *CCIPContracts) CreateDefaultCommitOnchainConfig(t *testing.T) []byte { + config, err := abihelpers.EncodeAbiStruct(ccipdata.CommitOnchainConfig{ + PriceRegistry: c.Dest.PriceRegistry.Address(), + }) + require.NoError(t, err) + return config +} + +func (c *CCIPContracts) CreateDefaultCommitOffchainConfig(t *testing.T) []byte { + return c.createCommitOffchainConfig(t, 10*time.Second, 5*time.Second) +} + +func (c *CCIPContracts) createCommitOffchainConfig(t *testing.T, feeUpdateHearBeat time.Duration, inflightCacheExpiry time.Duration) []byte { + config, err := NewCommitOffchainConfig( + *config.MustNewDuration(feeUpdateHearBeat), + 1, + 1, + *config.MustNewDuration(feeUpdateHearBeat), + 1, + *config.MustNewDuration(inflightCacheExpiry), + false, + ).Encode() + require.NoError(t, err) + return config +} + +func (c *CCIPContracts) CreateDefaultExecOnchainConfig(t *testing.T) []byte { + config, err := abihelpers.EncodeAbiStruct(v1_2_0.ExecOnchainConfig{ + PermissionLessExecutionThresholdSeconds: PermissionLessExecutionThresholdSeconds, + Router: c.Dest.Router.Address(), + PriceRegistry: c.Dest.PriceRegistry.Address(), + MaxDataBytes: 1e5, + MaxNumberOfTokensPerMsg: 5, + MaxPoolReleaseOrMintGas: 200_000, + }) + require.NoError(t, err) + return config +} + +func (c *CCIPContracts) CreateDefaultExecOffchainConfig(t *testing.T) []byte { + return c.createExecOffchainConfig(t, 1*time.Minute, 1*time.Minute) +} + +func (c *CCIPContracts) createExecOffchainConfig(t *testing.T, inflightCacheExpiry time.Duration, rootSnoozeTime time.Duration) []byte { + config, err := NewExecOffchainConfig( + 1, + 5_000_000, + 0.07, + *config.MustNewDuration(inflightCacheExpiry), + *config.MustNewDuration(rootSnoozeTime), + uint32(0), + ).Encode() + require.NoError(t, err) + return config +} diff --git a/core/services/ocr2/plugins/ccip/tokendata/bgworker.go b/core/services/ocr2/plugins/ccip/tokendata/bgworker.go index bc5aba557e6..458c2e412cc 100644 --- a/core/services/ocr2/plugins/ccip/tokendata/bgworker.go +++ b/core/services/ocr2/plugins/ccip/tokendata/bgworker.go @@ -58,7 +58,7 @@ func NewBackgroundWorker( return &BackgroundWorker{ tokenDataReaders: tokenDataReaders, numWorkers: numWorkers, - jobsChan: make(chan cciptypes.EVM2EVMOnRampCCIPSendRequestedWithMeta, numWorkers*100), + jobsChan: make(chan cciptypes.EVM2EVMOnRampCCIPSendRequestedWithMeta, numWorkers*200), resultsCache: cache.New(expirationDur, expirationDur/2), timeoutDur: timeoutDur, stopChan: make(services.StopChan), diff --git a/core/services/ocr2/plugins/ccip/tokendata/http/http_client.go b/core/services/ocr2/plugins/ccip/tokendata/http/http_client.go index 79ec21b1b83..dd303822c79 100644 --- a/core/services/ocr2/plugins/ccip/tokendata/http/http_client.go +++ b/core/services/ocr2/plugins/ccip/tokendata/http/http_client.go @@ -12,18 +12,21 @@ import ( ) type IHttpClient interface { - // Get issue a GET request to the given url and return the response body and status code. + // Get issues a GET request to the given url and returns the response body and status code. Get(ctx context.Context, url string, timeout time.Duration) ([]byte, int, http.Header, error) + + // Post issues a POST request to the given url with the given request data and returns the response body and status code. + Post(ctx context.Context, url string, requestData io.Reader, timeout time.Duration) ([]byte, int, http.Header, error) } type HttpClient struct { } -func (s *HttpClient) Get(ctx context.Context, url string, timeout time.Duration) ([]byte, int, http.Header, error) { +func doRequest(ctx context.Context, url string, requestType string, requestBody io.Reader, timeout time.Duration) ([]byte, int, http.Header, error) { // Use a timeout to guard against attestation API hanging, causing observation timeout and failing to make any progress. timeoutCtx, cancel := context.WithTimeoutCause(ctx, timeout, tokendata.ErrTimeout) defer cancel() - req, err := http.NewRequestWithContext(timeoutCtx, http.MethodGet, url, nil) + req, err := http.NewRequestWithContext(timeoutCtx, requestType, url, requestBody) if err != nil { return nil, http.StatusBadRequest, nil, err } @@ -46,3 +49,11 @@ func (s *HttpClient) Get(ctx context.Context, url string, timeout time.Duration) body, err := io.ReadAll(res.Body) return body, res.StatusCode, res.Header, err } + +func (s *HttpClient) Get(ctx context.Context, url string, timeout time.Duration) ([]byte, int, http.Header, error) { + return doRequest(ctx, url, http.MethodGet, nil, timeout) +} + +func (s *HttpClient) Post(ctx context.Context, url string, requestBody io.Reader, timeout time.Duration) ([]byte, int, http.Header, error) { + return doRequest(ctx, url, http.MethodPost, requestBody, timeout) +} diff --git a/core/services/ocr2/plugins/ccip/tokendata/http/observed_http_client.go b/core/services/ocr2/plugins/ccip/tokendata/http/observed_http_client.go index d8fb9b1c576..bac36abf7ec 100644 --- a/core/services/ocr2/plugins/ccip/tokendata/http/observed_http_client.go +++ b/core/services/ocr2/plugins/ccip/tokendata/http/observed_http_client.go @@ -11,7 +11,7 @@ import ( ) var ( - usdcLatencyBuckets = []float64{ + latencyBuckets = []float64{ float64(10 * time.Millisecond), float64(25 * time.Millisecond), float64(50 * time.Millisecond), @@ -29,7 +29,12 @@ var ( usdcClientHistogram = promauto.NewHistogramVec(prometheus.HistogramOpts{ Name: "ccip_usdc_client_request_total", Help: "Latency of calls to the USDC client", - Buckets: usdcLatencyBuckets, + Buckets: latencyBuckets, + }, []string{"status", "success"}) + lbtcClientHistogram = promauto.NewHistogramVec(prometheus.HistogramOpts{ + Name: "ccip_lbtc_client_request_total", + Help: "Latency of calls to the LBTC client", + Buckets: latencyBuckets, }, []string{"status", "success"}) ) @@ -38,11 +43,16 @@ type ObservedIHttpClient struct { histogram *prometheus.HistogramVec } -// NewObservedIHttpClient Create a new ObservedIHttpClient with the USDC client metric. -func NewObservedIHttpClient(origin IHttpClient) *ObservedIHttpClient { +// NewObservedUsdcIHttpClient Create a new ObservedIHttpClient with the USDC client metric. +func NewObservedUsdcIHttpClient(origin IHttpClient) *ObservedIHttpClient { return NewObservedIHttpClientWithMetric(origin, usdcClientHistogram) } +// NewObservedLbtcIHttpClient Create a new ObservedIHttpClient with the LBTC client metric. +func NewObservedLbtcIHttpClient(origin IHttpClient) *ObservedIHttpClient { + return NewObservedIHttpClientWithMetric(origin, lbtcClientHistogram) +} + func NewObservedIHttpClientWithMetric(origin IHttpClient, histogram *prometheus.HistogramVec) *ObservedIHttpClient { return &ObservedIHttpClient{ IHttpClient: origin, diff --git a/core/services/ocr2/plugins/ccip/tokendata/lbtc/lbtc.go b/core/services/ocr2/plugins/ccip/tokendata/lbtc/lbtc.go new file mode 100644 index 00000000000..76245ef24a5 --- /dev/null +++ b/core/services/ocr2/plugins/ccip/tokendata/lbtc/lbtc.go @@ -0,0 +1,275 @@ +package lbtc + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "net/url" + "sync" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/pkg/errors" + "golang.org/x/time/rate" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/tokendata" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/tokendata/http" +) + +const ( + apiVersion = "v1" + attestationPath = "deposits/getByHash" + defaultAttestationTimeout = 5 * time.Second + + // defaultCoolDownDurationSec defines the default time to wait after getting rate limited. + // this value is only used if the 429 response does not contain the Retry-After header + defaultCoolDownDuration = 30 * time.Second + + // defaultRequestInterval defines the rate in requests per second that the attestation API can be called. + // this is set according to the APIs recommended 5 requests per second rate limit. + defaultRequestInterval = 200 * time.Millisecond + + // APIIntervalRateLimitDisabled is a special value to disable the rate limiting. + APIIntervalRateLimitDisabled = -1 + // APIIntervalRateLimitDefault is a special value to select the default rate limit interval. + APIIntervalRateLimitDefault = 0 +) + +type attestationStatus string + +const ( + attestationStatusUnspecified attestationStatus = "NOTARIZATION_STATUS_UNSPECIFIED" + attestationStatusPending attestationStatus = "NOTARIZATION_STATUS_PENDING" + attestationStatusSubmitted attestationStatus = "NOTARIZATION_STATUS_SUBMITTED" + attestationStatusSessionApproved attestationStatus = "NOTARIZATION_STATUS_SESSION_APPROVED" + attestationStatusFailed attestationStatus = "NOTARIZATION_STATUS_FAILED" +) + +var ( + ErrUnknownResponse = errors.New("unexpected response from attestation API") +) + +type TokenDataReader struct { + lggr logger.Logger + httpClient http.IHttpClient + attestationAPI *url.URL + attestationAPITimeout time.Duration + lbtcTokenAddress common.Address + rate *rate.Limiter + + // coolDownUntil defines whether requests are blocked or not. + coolDownUntil time.Time + coolDownMu *sync.RWMutex +} + +type messageAttestationResponse struct { + MessageHash string `json:"message_hash"` + Status attestationStatus `json:"status"` + Attestation string `json:"attestation,omitempty"` // Attestation represented by abi.encode(payload, proof) +} + +type attestationRequest struct { + PayloadHashes []string `json:"messageHash"` +} + +type attestationResponse struct { + Attestations []messageAttestationResponse `json:"attestations"` +} + +type sourceTokenData struct { + SourcePoolAddress []byte + DestTokenAddress []byte + ExtraData []byte + DestGasAmount uint32 +} + +func (m sourceTokenData) AbiString() string { + return `[{ + "components": [ + {"name": "sourcePoolAddress", "type": "bytes"}, + {"name": "destTokenAddress", "type": "bytes"}, + {"name": "extraData", "type": "bytes"}, + {"name": "destGasAmount", "type": "uint32"} + ], + "type": "tuple" + }]` +} + +func (m sourceTokenData) Validate() error { + if len(m.SourcePoolAddress) == 0 { + return errors.New("sourcePoolAddress must be non-empty") + } + if len(m.DestTokenAddress) == 0 { + return errors.New("destTokenAddress must be non-empty") + } + if len(m.ExtraData) == 0 { + return errors.New("extraData must be non-empty") + } + return nil +} + +var _ tokendata.Reader = &TokenDataReader{} + +func NewLBTCTokenDataReader( + lggr logger.Logger, + lbtcAttestationAPI *url.URL, + lbtcAttestationAPITimeoutSeconds int, + lbtcTokenAddress common.Address, + requestInterval time.Duration, +) *TokenDataReader { + timeout := time.Duration(lbtcAttestationAPITimeoutSeconds) * time.Second + if lbtcAttestationAPITimeoutSeconds == 0 { + timeout = defaultAttestationTimeout + } + + if requestInterval == APIIntervalRateLimitDisabled { + requestInterval = 0 + } else if requestInterval == APIIntervalRateLimitDefault { + requestInterval = defaultRequestInterval + } + + return &TokenDataReader{ + lggr: lggr, + httpClient: http.NewObservedLbtcIHttpClient(&http.HttpClient{}), + attestationAPI: lbtcAttestationAPI, + attestationAPITimeout: timeout, + lbtcTokenAddress: lbtcTokenAddress, + coolDownMu: &sync.RWMutex{}, + rate: rate.NewLimiter(rate.Every(requestInterval), 1), + } +} + +func NewLBTCTokenDataReaderWithHTTPClient( + origin TokenDataReader, + httpClient http.IHttpClient, + lbtcTokenAddress common.Address, + requestInterval time.Duration, +) *TokenDataReader { + return &TokenDataReader{ + lggr: origin.lggr, + httpClient: httpClient, + attestationAPI: origin.attestationAPI, + attestationAPITimeout: origin.attestationAPITimeout, + coolDownMu: origin.coolDownMu, + lbtcTokenAddress: lbtcTokenAddress, + rate: rate.NewLimiter(rate.Every(requestInterval), 1), + } +} + +// ReadTokenData queries the LBTC attestation API. +func (s *TokenDataReader) ReadTokenData(ctx context.Context, msg cciptypes.EVM2EVMOnRampCCIPSendRequestedWithMeta, tokenIndex int) ([]byte, error) { + if tokenIndex < 0 || tokenIndex >= len(msg.TokenAmounts) { + return nil, errors.New("token index out of bounds") + } + + if s.inCoolDownPeriod() { + // rate limiting cool-down period, we prevent new requests from being sent + return nil, tokendata.ErrRequestsBlocked + } + + if s.rate != nil { + // Wait blocks until it the attestation API can be called or the + // context is Done. + if waitErr := s.rate.Wait(ctx); waitErr != nil { + return nil, fmt.Errorf("lbtc rate limiting error: %w", waitErr) + } + } + + decodedSourceTokenData, err := abihelpers.DecodeAbiStruct[sourceTokenData](msg.SourceTokenData[tokenIndex]) + if err != nil { + return []byte{}, err + } + destTokenData := decodedSourceTokenData.ExtraData + // We don't have better way to determine if the extraData is a payload or sha256(payload) + // Last parameter of the payload struct is 32-bytes nonce (see Lombard's Bridge._deposit(...) method), + // so we can assume that payload always exceeds 32 bytes + if len(destTokenData) != 32 { + s.lggr.Infow("SourceTokenData.extraData size is not 32. This is deposit payload, not sha256(payload). Attestation is disabled onchain", + "destTokenData", hexutil.Encode(destTokenData)) + return destTokenData, nil + } + payloadHash := [32]byte(destTokenData) + + msgID := hexutil.Encode(msg.MessageID[:]) + payloadHashHex := hexutil.Encode(payloadHash[:]) + s.lggr.Infow("Calling attestation API", "messageBodyHash", payloadHashHex, "messageID", msgID) + + attestationResp, err := s.callAttestationAPI(ctx, payloadHash) + if err != nil { + return nil, errors.Wrap(err, "failed calling lbtc attestation API") + } + if len(attestationResp.Attestations) == 0 { + return nil, errors.New("attestation response is empty") + } + if len(attestationResp.Attestations) > 1 { + s.lggr.Warnw("Multiple attestations received, expected one", "attestations", attestationResp.Attestations) + } + var attestation messageAttestationResponse + for _, attestationCandidate := range attestationResp.Attestations { + if attestationCandidate.MessageHash == payloadHashHex { + attestation = attestationCandidate + } + } + if attestation == (messageAttestationResponse{}) { + return nil, fmt.Errorf("requested attestation %s not found in response", payloadHashHex) + } + s.lggr.Infow("Got response from attestation API", "messageID", msgID, + "attestationStatus", attestation.Status, "attestation", attestation) + switch attestation.Status { + case attestationStatusSessionApproved: + payloadAndProof, err := hexutil.Decode(attestation.Attestation) + if err != nil { + return nil, err + } + return payloadAndProof, nil + case attestationStatusPending: + return nil, tokendata.ErrNotReady + case attestationStatusSubmitted: + return nil, tokendata.ErrNotReady + default: + s.lggr.Errorw("Unexpected response from attestation API", "attestation", attestation) + return nil, ErrUnknownResponse + } +} + +func (s *TokenDataReader) callAttestationAPI(ctx context.Context, lbtcMessageHash [32]byte) (attestationResponse, error) { + attestationURL := fmt.Sprintf("%s/bridge/%s/%s", s.attestationAPI.String(), apiVersion, attestationPath) + request := attestationRequest{PayloadHashes: []string{hexutil.Encode(lbtcMessageHash[:])}} + encodedRequest, err := json.Marshal(request) + requestBuffer := bytes.NewBuffer(encodedRequest) + if err != nil { + return attestationResponse{}, err + } + respRaw, _, _, err := s.httpClient.Post(ctx, attestationURL, requestBuffer, s.attestationAPITimeout) + switch { + case errors.Is(err, tokendata.ErrRateLimit): + s.setCoolDownPeriod(defaultCoolDownDuration) + return attestationResponse{}, tokendata.ErrRateLimit + case err != nil: + return attestationResponse{}, err + } + var attestationResp attestationResponse + err = json.Unmarshal(respRaw, &attestationResp) + return attestationResp, err +} + +func (s *TokenDataReader) setCoolDownPeriod(d time.Duration) { + s.coolDownMu.Lock() + s.coolDownUntil = time.Now().Add(d) + s.coolDownMu.Unlock() +} + +func (s *TokenDataReader) inCoolDownPeriod() bool { + s.coolDownMu.RLock() + defer s.coolDownMu.RUnlock() + return time.Now().Before(s.coolDownUntil) +} + +func (s *TokenDataReader) Close() error { + return nil +} diff --git a/core/services/ocr2/plugins/ccip/tokendata/lbtc/lbtc_test.go b/core/services/ocr2/plugins/ccip/tokendata/lbtc/lbtc_test.go new file mode 100644 index 00000000000..8a3f02c289e --- /dev/null +++ b/core/services/ocr2/plugins/ccip/tokendata/lbtc/lbtc_test.go @@ -0,0 +1,492 @@ +package lbtc + +import ( + "context" + "encoding/json" + "net/http" + "net/http/httptest" + "net/url" + "strings" + "sync" + "testing" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/pkg/errors" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + + cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcalc" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/tokendata" +) + +var ( + lbtcMessageHash = "0xbc427abf571a5cfcf7c98799d1f0055f4db25f203f657d30026728a19d16f092" + lbtcMessageAttestation = "0x0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000e45c70a5050000000000000000000000000000000000000000000000000000000000aa36a7000000000000000000000000845f8e3c214d8d0e4d83fc094f302aa26a12a0bc0000000000000000000000000000000000000000000000000000000000014a34000000000000000000000000845f8e3c214d8d0e4d83fc094f302aa26a12a0bc00000000000000000000000062f10ce5b727edf787ea45776bd050308a61150800000000000000000000000000000000000000000000000000000000000003e60000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000040277eeafba008d767c2636d9428f2ebb13ab29ac70337f4fc34b0f5606767cae546f9be3f12160de6d142e5b3c1c3ebd0bf4298662b32b597d0cc5970c7742fc10000000000000000000000000000000000000000000000000000000000000040bbcd60ecc9e06f2effe7c94161219498a1eb435b419387adadb86ec9a52dfb066ce027532517df7216404049d193a25b85c35edfa3e7c5aa4757bfe84887a3980000000000000000000000000000000000000000000000000000000000000040da4a6dc619b5ca2349783cabecc4efdbc910090d3e234d7b8d0430165f8fae532f9a965ceb85c18bb92e059adefa7ce5835850a705761ab9e026d2db4a13ef9a" + payloadAndProof, _ = hexutil.Decode(lbtcMessageAttestation) +) + +func getMockLBTCEndpoint(t *testing.T, response attestationResponse) *httptest.Server { + responseBytes, err := json.Marshal(response) + require.NoError(t, err) + + return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + _, err := w.Write(responseBytes) + //nolint:testifylint // we need to use require here + require.NoError(t, err) + })) +} + +func TestLBTCReader_callAttestationApi(t *testing.T) { + t.Skipf("Skipping test because it uses the real LBTC attestation API") + attestationURI, err := url.ParseRequestURI("https://bridge-manager.staging.lombard.finance") + require.NoError(t, err) + lggr := logger.TestLogger(t) + lbtcService := NewLBTCTokenDataReader(lggr, attestationURI, 0, common.Address{}, APIIntervalRateLimitDisabled) + + attestation, err := lbtcService.callAttestationAPI(context.Background(), [32]byte(common.FromHex(lbtcMessageHash))) + require.NoError(t, err) + + require.Equal(t, lbtcMessageHash, attestation.Attestations[0].MessageHash) + require.Equal(t, attestationStatusSessionApproved, attestation.Attestations[0].Status) + require.Equal(t, lbtcMessageAttestation, attestation.Attestations[0].Attestation) +} + +func TestLBTCReader_callAttestationApiMock(t *testing.T) { + response := attestationResponse{ + Attestations: []messageAttestationResponse{ + { + MessageHash: lbtcMessageHash, + Status: attestationStatusSessionApproved, + Attestation: lbtcMessageAttestation, + }, + }, + } + + ts := getMockLBTCEndpoint(t, response) + defer ts.Close() + attestationURI, err := url.ParseRequestURI(ts.URL) + require.NoError(t, err) + + lggr := logger.TestLogger(t) + lbtcService := NewLBTCTokenDataReader(lggr, attestationURI, 0, common.Address{}, APIIntervalRateLimitDisabled) + attestation, err := lbtcService.callAttestationAPI(context.Background(), [32]byte(common.FromHex(lbtcMessageHash))) + require.NoError(t, err) + + require.Equal(t, response.Attestations[0].Status, attestation.Attestations[0].Status) + require.Equal(t, response.Attestations[0].Attestation, attestation.Attestations[0].Attestation) +} + +func TestLBTCReader_callAttestationApiMockError(t *testing.T) { + t.Parallel() + + sessionApprovedResponse := attestationResponse{ + Attestations: []messageAttestationResponse{ + { + MessageHash: lbtcMessageHash, + Status: attestationStatusSessionApproved, + Attestation: lbtcMessageAttestation, + }, + }, + } + + tests := []struct { + name string + getTs func() *httptest.Server + parentTimeoutSeconds int + customTimeoutSeconds int + expectedError error + }{ + { + name: "server error", + getTs: func() *httptest.Server { + return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusInternalServerError) + })) + }, + parentTimeoutSeconds: 60, + expectedError: nil, + }, + { + name: "default timeout", + getTs: func() *httptest.Server { + responseBytes, _ := json.Marshal(sessionApprovedResponse) + + return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + time.Sleep(defaultAttestationTimeout + time.Second) + _, err := w.Write(responseBytes) + //nolint:testifylint // we need to use require here + require.NoError(t, err) + })) + }, + parentTimeoutSeconds: 60, + expectedError: tokendata.ErrTimeout, + }, + { + name: "custom timeout", + getTs: func() *httptest.Server { + responseBytes, _ := json.Marshal(sessionApprovedResponse) + + return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + time.Sleep(2*time.Second + time.Second) + _, err := w.Write(responseBytes) + //nolint:testifylint // we need to use require here + require.NoError(t, err) + })) + }, + parentTimeoutSeconds: 60, + customTimeoutSeconds: 2, + expectedError: tokendata.ErrTimeout, + }, + { + name: "rate limit", + getTs: func() *httptest.Server { + return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusTooManyRequests) + })) + }, + parentTimeoutSeconds: 60, + expectedError: tokendata.ErrRateLimit, + }, + { + name: "parent context timeout", + getTs: func() *httptest.Server { + return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + time.Sleep(defaultAttestationTimeout + time.Second) + })) + }, + parentTimeoutSeconds: 1, + expectedError: nil, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + ts := test.getTs() + defer ts.Close() + + attestationURI, err := url.ParseRequestURI(ts.URL) + require.NoError(t, err) + + lggr := logger.TestLogger(t) + lbtcService := NewLBTCTokenDataReader(lggr, attestationURI, test.customTimeoutSeconds, common.Address{}, APIIntervalRateLimitDisabled) + + parentCtx, cancel := context.WithTimeout(context.Background(), time.Duration(test.parentTimeoutSeconds)*time.Second) + defer cancel() + + _, err = lbtcService.callAttestationAPI(parentCtx, [32]byte(common.FromHex(lbtcMessageHash))) + require.Error(t, err) + + if test.expectedError != nil { + require.True(t, errors.Is(err, test.expectedError)) + } + }) + } +} + +func TestLBTCReader_rateLimiting(t *testing.T) { + sessionApprovedResponse := attestationResponse{ + Attestations: []messageAttestationResponse{ + { + MessageHash: lbtcMessageHash, + Status: attestationStatusSessionApproved, + Attestation: lbtcMessageAttestation, + }, + }, + } + + testCases := []struct { + name string + requests uint64 + rateConfig time.Duration + testDuration time.Duration + timeout time.Duration + err string + additionalErr string + }{ + { + name: "no rate limit when disabled", + requests: 10, + rateConfig: APIIntervalRateLimitDisabled, + testDuration: 1 * time.Millisecond, + }, + { + name: "yes rate limited with default config", + requests: 5, + rateConfig: APIIntervalRateLimitDefault, + testDuration: 4 * defaultRequestInterval, + }, + { + name: "yes rate limited with config", + requests: 10, + rateConfig: 50 * time.Millisecond, + testDuration: 9 * 50 * time.Millisecond, + }, + { + name: "request timeout", + requests: 5, + rateConfig: 100 * time.Millisecond, + testDuration: 1 * time.Millisecond, + timeout: 1 * time.Millisecond, + err: "lbtc rate limiting error:", + additionalErr: "token data API timed out", + }, + } + + extraData, err := hexutil.Decode(lbtcMessageHash) + require.NoError(t, err) + + srcTokenData, err := abihelpers.EncodeAbiStruct[sourceTokenData](sourceTokenData{ + SourcePoolAddress: utils.RandomAddress().Bytes(), + DestTokenAddress: utils.RandomAddress().Bytes(), + ExtraData: extraData, + }) + require.NoError(t, err) + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + ts := getMockLBTCEndpoint(t, sessionApprovedResponse) + defer ts.Close() + attestationURI, err := url.ParseRequestURI(ts.URL) + require.NoError(t, err) + + lggr := logger.TestLogger(t) + lbtcService := NewLBTCTokenDataReader(lggr, attestationURI, 0, utils.RandomAddress(), tc.rateConfig) + + ctx := context.Background() + if tc.timeout > 0 { + var cf context.CancelFunc + ctx, cf = context.WithTimeout(ctx, tc.timeout) + defer cf() + } + + trigger := make(chan struct{}) + errorChan := make(chan error, tc.requests) + wg := sync.WaitGroup{} + for i := uint64(0); i < tc.requests; i++ { + wg.Add(1) + go func() { + defer wg.Done() + + <-trigger + _, err := lbtcService.ReadTokenData(ctx, cciptypes.EVM2EVMOnRampCCIPSendRequestedWithMeta{ + EVM2EVMMessage: cciptypes.EVM2EVMMessage{ + SourceTokenData: [][]byte{srcTokenData}, + TokenAmounts: []cciptypes.TokenAmount{{Token: ccipcalc.EvmAddrToGeneric(utils.ZeroAddress), Amount: nil}}, // trigger failure due to wrong address + }, + }, 0) + + if err != nil { + errorChan <- err + } + }() + } + + // Start the test + start := time.Now() + close(trigger) + + // Wait for requests to complete + wg.Wait() + finish := time.Now() + close(errorChan) + + // Collect errors + errorFound := false + for err := range errorChan { + //nolint:gocritic // easier to read using ifElse instead of switch + if tc.err != "" && strings.Contains(err.Error(), tc.err) { + errorFound = true + } else if tc.additionalErr != "" && strings.Contains(err.Error(), tc.additionalErr) { + errorFound = true + } else if err != nil { + require.Fail(t, "unexpected error", err) + } + } + + if tc.err != "" { + assert.True(t, errorFound) + } + assert.WithinDuration(t, start.Add(tc.testDuration), finish, 50*time.Millisecond) + }) + } +} + +func TestLBTCReader_skipApiOnFullPayload(t *testing.T) { + sessionApprovedResponse := attestationResponse{ + Attestations: []messageAttestationResponse{ + { + MessageHash: lbtcMessageHash, + Status: attestationStatusSessionApproved, + Attestation: lbtcMessageAttestation, + }, + }, + } + + srcTokenData, err := abihelpers.EncodeAbiStruct[sourceTokenData](sourceTokenData{ + SourcePoolAddress: utils.RandomAddress().Bytes(), + DestTokenAddress: utils.RandomAddress().Bytes(), + ExtraData: []byte(lbtcMessageHash), // more than 32 bytes + }) + require.NoError(t, err) + + ts := getMockLBTCEndpoint(t, sessionApprovedResponse) + defer ts.Close() + attestationURI, err := url.ParseRequestURI(ts.URL) + require.NoError(t, err) + + lggr, logs := logger.TestLoggerObserved(t, zapcore.InfoLevel) + lbtcService := NewLBTCTokenDataReader(lggr, attestationURI, 0, utils.RandomAddress(), APIIntervalRateLimitDefault) + + ctx := context.Background() + + destTokenData, err := lbtcService.ReadTokenData(ctx, cciptypes.EVM2EVMOnRampCCIPSendRequestedWithMeta{ + EVM2EVMMessage: cciptypes.EVM2EVMMessage{ + SourceTokenData: [][]byte{srcTokenData}, + TokenAmounts: []cciptypes.TokenAmount{{Token: ccipcalc.EvmAddrToGeneric(utils.ZeroAddress), Amount: nil}}, // trigger failure due to wrong address + }, + }, 0) + require.NoError(t, err) + require.EqualValues(t, []byte(lbtcMessageHash), destTokenData) + + require.Equal(t, 1, logs.Len()) + require.Contains(t, logs.All()[0].Message, "SourceTokenData.extraData size is not 32. This is deposit payload, not sha256(payload). Attestation is disabled onchain") +} + +func TestLBTCReader_expectedOutput(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + response attestationResponse + expectedReturn []byte + expectedError error + }{ + { + name: "expected payloadAndProof when status SESSION_APPROVED", + response: attestationResponse{ + Attestations: []messageAttestationResponse{ + { + MessageHash: lbtcMessageHash, + Status: attestationStatusSessionApproved, + Attestation: lbtcMessageAttestation, + }, + }, + }, + expectedReturn: payloadAndProof, + expectedError: nil, + }, + { + name: "expected ErrNotReady on status PENDING", + response: attestationResponse{ + Attestations: []messageAttestationResponse{ + { + MessageHash: lbtcMessageHash, + Status: attestationStatusPending, + Attestation: lbtcMessageAttestation, + }, + }, + }, + expectedReturn: nil, + expectedError: tokendata.ErrNotReady, + }, + { + name: "expected ErrNotReady on status SUBMITTED", + response: attestationResponse{ + Attestations: []messageAttestationResponse{ + { + MessageHash: lbtcMessageHash, + Status: attestationStatusSubmitted, + Attestation: lbtcMessageAttestation, + }, + }, + }, + expectedReturn: nil, + expectedError: tokendata.ErrNotReady, + }, + { + name: "expected ErrUnknownResponse on status UNSPECIFIED", + response: attestationResponse{ + Attestations: []messageAttestationResponse{ + { + MessageHash: lbtcMessageHash, + Status: attestationStatusUnspecified, + Attestation: lbtcMessageAttestation, + }, + }, + }, + expectedReturn: nil, + expectedError: ErrUnknownResponse, + }, + { + name: "expected ErrUnknownResponse on status FAILED", + response: attestationResponse{ + Attestations: []messageAttestationResponse{ + { + MessageHash: lbtcMessageHash, + Status: attestationStatusFailed, + Attestation: lbtcMessageAttestation, + }, + }, + }, + expectedReturn: nil, + expectedError: ErrUnknownResponse, + }, + } + + extraData, err := hexutil.Decode(lbtcMessageHash) + require.NoError(t, err) + + srcTokenData, err := abihelpers.EncodeAbiStruct[sourceTokenData](sourceTokenData{ + SourcePoolAddress: utils.RandomAddress().Bytes(), + DestTokenAddress: utils.RandomAddress().Bytes(), + ExtraData: extraData, + }) + require.NoError(t, err) + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + ts := getMockLBTCEndpoint(t, tc.response) + defer ts.Close() + attestationURI, err := url.ParseRequestURI(ts.URL) + require.NoError(t, err) + + lggr := logger.TestLogger(t) + lbtcService := NewLBTCTokenDataReader(lggr, attestationURI, 0, utils.RandomAddress(), APIIntervalRateLimitDefault) + + ctx := context.Background() + + payloadAndProof, err := lbtcService.ReadTokenData(ctx, cciptypes.EVM2EVMOnRampCCIPSendRequestedWithMeta{ + EVM2EVMMessage: cciptypes.EVM2EVMMessage{ + SourceTokenData: [][]byte{srcTokenData}, + TokenAmounts: []cciptypes.TokenAmount{{Token: ccipcalc.EvmAddrToGeneric(utils.ZeroAddress), Amount: nil}}, // trigger failure due to wrong address + }, + }, 0) + + if tc.expectedReturn != nil { + require.EqualValues(t, tc.expectedReturn, payloadAndProof) + } else if tc.expectedError != nil { + require.Contains(t, err.Error(), tc.expectedError.Error()) + } + }) + } +} + +func Test_DecodeSourceTokenData(t *testing.T) { + input, err := hexutil.Decode("0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000249f00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000267d40f64ecc4d95f3e8b2237df5f37b10812c250000000000000000000000000000000000000000000000000000000000000020000000000000000000000000c47e4b3124597fdf8dd07843d4a7052f2ee80c3000000000000000000000000000000000000000000000000000000000000000e45c70a5050000000000000000000000000000000000000000000000000000000000aa36a7000000000000000000000000845f8e3c214d8d0e4d83fc094f302aa26a12a0bc0000000000000000000000000000000000000000000000000000000000014a34000000000000000000000000845f8e3c214d8d0e4d83fc094f302aa26a12a0bc00000000000000000000000062f10ce5b727edf787ea45776bd050308a61150800000000000000000000000000000000000000000000000000000000000003e6000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000") + require.NoError(t, err) + decoded, err := abihelpers.DecodeAbiStruct[sourceTokenData](input) + require.NoError(t, err) + expected, err := hexutil.Decode("0x5c70a5050000000000000000000000000000000000000000000000000000000000aa36a7000000000000000000000000845f8e3c214d8d0e4d83fc094f302aa26a12a0bc0000000000000000000000000000000000000000000000000000000000014a34000000000000000000000000845f8e3c214d8d0e4d83fc094f302aa26a12a0bc00000000000000000000000062f10ce5b727edf787ea45776bd050308a61150800000000000000000000000000000000000000000000000000000000000003e60000000000000000000000000000000000000000000000000000000000000006") + require.NoError(t, err) + require.Equal(t, expected, decoded.ExtraData) +} diff --git a/core/services/ocr2/plugins/ccip/tokendata/reader_mock.go b/core/services/ocr2/plugins/ccip/tokendata/reader_mock.go index 93163fdcfb4..c553eed3586 100644 --- a/core/services/ocr2/plugins/ccip/tokendata/reader_mock.go +++ b/core/services/ocr2/plugins/ccip/tokendata/reader_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package tokendata @@ -23,7 +23,7 @@ func (_m *MockReader) EXPECT() *MockReader_Expecter { return &MockReader_Expecter{mock: &_m.Mock} } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *MockReader) Close() error { ret := _m.Called() diff --git a/core/services/ocr2/plugins/ccip/tokendata/usdc/usdc.go b/core/services/ocr2/plugins/ccip/tokendata/usdc/usdc.go index aaa6086fbc9..9e27ebcc59e 100644 --- a/core/services/ocr2/plugins/ccip/tokendata/usdc/usdc.go +++ b/core/services/ocr2/plugins/ccip/tokendata/usdc/usdc.go @@ -133,7 +133,7 @@ func NewUSDCTokenDataReader( return &TokenDataReader{ lggr: lggr, usdcReader: usdcReader, - httpClient: http.NewObservedIHttpClient(&http.HttpClient{}), + httpClient: http.NewObservedUsdcIHttpClient(&http.HttpClient{}), attestationApi: usdcAttestationApi, attestationApiTimeout: timeout, usdcTokenAddress: usdcTokenAddress, diff --git a/core/services/ocr2/plugins/ccip/transmitter/transmitter.go b/core/services/ocr2/plugins/ccip/transmitter/transmitter.go index 24123d03337..abb023a4251 100644 --- a/core/services/ocr2/plugins/ccip/transmitter/transmitter.go +++ b/core/services/ocr2/plugins/ccip/transmitter/transmitter.go @@ -26,6 +26,8 @@ type txManager interface { type Transmitter interface { CreateEthTransaction(ctx context.Context, toAddress common.Address, payload []byte, txMeta *txmgr.TxMeta) error FromAddress(context.Context) common.Address + + CreateSecondaryEthTransaction(context.Context, []byte, *txmgr.TxMeta) error } type transmitter struct { @@ -141,3 +143,7 @@ func (t *transmitter) forwarderAddress() common.Address { } return t.effectiveTransmitterAddress } + +func (t *transmitter) CreateSecondaryEthTransaction(ctx context.Context, bytes []byte, meta *txmgr.TxMeta) error { + return errors.New("trying to send a secondary transmission on a non dual transmitter") +} diff --git a/core/services/ocr2/plugins/llo/helpers_test.go b/core/services/ocr2/plugins/llo/helpers_test.go index 9cd8742ffa8..ff3f6e3461e 100644 --- a/core/services/ocr2/plugins/llo/helpers_test.go +++ b/core/services/ocr2/plugins/llo/helpers_test.go @@ -21,6 +21,10 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" "go.uber.org/zap/zaptest/observer" + "google.golang.org/grpc" + + "github.com/smartcontractkit/chainlink-data-streams/rpc" + "github.com/smartcontractkit/chainlink-data-streams/rpc/mtls" "github.com/smartcontractkit/wsrpc/credentials" "github.com/smartcontractkit/wsrpc/peer" @@ -48,33 +52,81 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" ) -var _ pb.MercuryServer = &mercuryServer{} +var _ pb.MercuryServer = &wsrpcMercuryServer{} -type request struct { - pk credentials.StaticSizedPublicKey - req *pb.TransmitRequest +type mercuryServer struct { + rpc.UnimplementedTransmitterServer + privKey ed25519.PrivateKey + reqsCh chan *rpc.TransmitRequest + t *testing.T } -func (r request) TransmitterID() ocr2types.Account { - return ocr2types.Account(fmt.Sprintf("%x", r.pk)) +func startMercuryServer(t *testing.T, srv *mercuryServer, pubKeys []ed25519.PublicKey) (serverURL string) { + // Set up the grpc server + lis, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + t.Fatalf("[MAIN] failed to listen: %v", err) + } + serverURL = lis.Addr().String() + sMtls, err := mtls.NewTransportCredentials(srv.privKey, pubKeys) + require.NoError(t, err) + s := grpc.NewServer(grpc.Creds(sMtls)) + + // Register mercury implementation with the wsrpc server + rpc.RegisterTransmitterServer(s, srv) + + // Start serving + go func() { + s.Serve(lis) //nolint:errcheck // don't care about errors in tests + }() + + t.Cleanup(s.Stop) + + return } -type mercuryServer struct { +func NewMercuryServer(t *testing.T, privKey ed25519.PrivateKey, reqsCh chan *rpc.TransmitRequest) *mercuryServer { + return &mercuryServer{rpc.UnimplementedTransmitterServer{}, privKey, reqsCh, t} +} + +func (s *mercuryServer) Transmit(ctx context.Context, req *rpc.TransmitRequest) (*rpc.TransmitResponse, error) { + s.reqsCh <- req + + return &rpc.TransmitResponse{ + Code: 1, + Error: "", + }, nil +} + +func (s *mercuryServer) LatestReport(ctx context.Context, lrr *rpc.LatestReportRequest) (*rpc.LatestReportResponse, error) { + panic("should not be called") +} + +type wsrpcMercuryServer struct { privKey ed25519.PrivateKey - reqsCh chan request + reqsCh chan wsrpcRequest t *testing.T } -func NewMercuryServer(t *testing.T, privKey ed25519.PrivateKey, reqsCh chan request) *mercuryServer { - return &mercuryServer{privKey, reqsCh, t} +type wsrpcRequest struct { + pk credentials.StaticSizedPublicKey + req *pb.TransmitRequest } -func (s *mercuryServer) Transmit(ctx context.Context, req *pb.TransmitRequest) (*pb.TransmitResponse, error) { +func (r wsrpcRequest) TransmitterID() ocr2types.Account { + return ocr2types.Account(fmt.Sprintf("%x", r.pk)) +} + +func NewWSRPCMercuryServer(t *testing.T, privKey ed25519.PrivateKey, reqsCh chan wsrpcRequest) *wsrpcMercuryServer { + return &wsrpcMercuryServer{privKey, reqsCh, t} +} + +func (s *wsrpcMercuryServer) Transmit(ctx context.Context, req *pb.TransmitRequest) (*pb.TransmitResponse, error) { p, ok := peer.FromContext(ctx) if !ok { return nil, errors.New("could not extract public key") } - r := request{p.PublicKey, req} + r := wsrpcRequest{p.PublicKey, req} s.reqsCh <- r return &pb.TransmitResponse{ @@ -83,11 +135,11 @@ func (s *mercuryServer) Transmit(ctx context.Context, req *pb.TransmitRequest) ( }, nil } -func (s *mercuryServer) LatestReport(ctx context.Context, lrr *pb.LatestReportRequest) (*pb.LatestReportResponse, error) { +func (s *wsrpcMercuryServer) LatestReport(ctx context.Context, lrr *pb.LatestReportRequest) (*pb.LatestReportResponse, error) { panic("should not be called") } -func startMercuryServer(t *testing.T, srv *mercuryServer, pubKeys []ed25519.PublicKey) (serverURL string) { +func startWSRPCMercuryServer(t *testing.T, srv *wsrpcMercuryServer, pubKeys []ed25519.PublicKey) (serverURL string) { // Set up the wsrpc server lis, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { @@ -147,6 +199,7 @@ func setupNode( dbName string, backend evmtypes.Backend, csaKey csakey.KeyV2, + transmissionMode string, ) (app chainlink.Application, peerID string, clientPubKey credentials.StaticSizedPublicKey, ocr2kb ocr2key.KeyBundle, observedLogs *observer.ObservedLogs) { k := big.NewInt(int64(port)) // keys unique to port p2pKey := p2pkey.MustNewV2XXXTestingOnly(k) @@ -186,6 +239,9 @@ func setupNode( // [Mercury] c.Mercury.VerboseLogging = ptr(true) c.Mercury.Transmitter.TransmitConcurrency = ptr(uint32(5)) // Avoid a ridiculous number of goroutines + if transmissionMode != "" { + c.Mercury.Transmitter.Protocol = ptr(transmissionMode) + } }) lggr, observedLogs := logger.TestLoggerObserved(t, zapcore.DebugLevel) @@ -232,6 +288,29 @@ observationSource = """ )) } +func addStreamSpec( + t *testing.T, + node Node, + name string, + streamID *uint32, + observationSource string, +) (id int32) { + optionalStreamID := "" + if streamID != nil { + optionalStreamID = fmt.Sprintf("streamID = %d\n", *streamID) + } + specTOML := fmt.Sprintf(` +type = "stream" +schemaVersion = 1 +name = "%s" +%s +observationSource = """ +%s +""" +`, name, optionalStreamID, observationSource) + return node.AddStreamJob(t, specTOML) +} + func addQuoteStreamJob( t *testing.T, node Node, @@ -331,7 +410,7 @@ transmitterID = "%x" )) } -func createBridge(t *testing.T, name string, i int, p decimal.Decimal, borm bridges.ORM) (bridgeName string) { +func createSingleDecimalBridge(t *testing.T, name string, i int, p decimal.Decimal, borm bridges.ORM) (bridgeName string) { ctx := testutils.Context(t) bridge := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { b, err := io.ReadAll(req.Body) @@ -355,6 +434,24 @@ func createBridge(t *testing.T, name string, i int, p decimal.Decimal, borm brid return bridgeName } +func createBridge(t *testing.T, bridgeName string, resultJSON string, borm bridges.ORM) { + ctx := testutils.Context(t) + bridge := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + res.WriteHeader(http.StatusOK) + resp := fmt.Sprintf(`{"result": %s}`, resultJSON) + _, err := res.Write([]byte(resp)) + if err != nil { + t.Fatalf("failed to write response: %v", err) + } + })) + t.Cleanup(bridge.Close) + u, _ := url.Parse(bridge.URL) + require.NoError(t, borm.CreateBridgeType(ctx, &bridges.BridgeType{ + Name: bridges.BridgeName(bridgeName), + URL: models.WebURL(*u), + })) +} + func addOCRJobsEVMPremiumLegacy( t *testing.T, streams []Stream, @@ -386,7 +483,7 @@ func addOCRJobsEVMPremiumLegacy( name = "linkprice" } name = fmt.Sprintf("%s-%d-%d", name, strm.id, j) - bmBridge := createBridge(t, name, i, strm.baseBenchmarkPrice, node.App.BridgeORM()) + bmBridge := createSingleDecimalBridge(t, name, i, strm.baseBenchmarkPrice, node.App.BridgeORM()) jobID := addSingleDecimalStreamJob( t, node, @@ -395,9 +492,9 @@ func addOCRJobsEVMPremiumLegacy( ) jobIDs[i][strm.id] = jobID } else { - bmBridge := createBridge(t, fmt.Sprintf("benchmarkprice-%d-%d", strm.id, j), i, strm.baseBenchmarkPrice, node.App.BridgeORM()) - bidBridge := createBridge(t, fmt.Sprintf("bid-%d-%d", strm.id, j), i, strm.baseBid, node.App.BridgeORM()) - askBridge := createBridge(t, fmt.Sprintf("ask-%d-%d", strm.id, j), i, strm.baseAsk, node.App.BridgeORM()) + bmBridge := createSingleDecimalBridge(t, fmt.Sprintf("benchmarkprice-%d-%d", strm.id, j), i, strm.baseBenchmarkPrice, node.App.BridgeORM()) + bidBridge := createSingleDecimalBridge(t, fmt.Sprintf("bid-%d-%d", strm.id, j), i, strm.baseBid, node.App.BridgeORM()) + askBridge := createSingleDecimalBridge(t, fmt.Sprintf("ask-%d-%d", strm.id, j), i, strm.baseAsk, node.App.BridgeORM()) jobID := addQuoteStreamJob( t, node, diff --git a/core/services/ocr2/plugins/llo/integration_test.go b/core/services/ocr2/plugins/llo/integration_test.go index 0491c29b39c..c942d44c954 100644 --- a/core/services/ocr2/plugins/llo/integration_test.go +++ b/core/services/ocr2/plugins/llo/integration_test.go @@ -14,6 +14,7 @@ import ( "time" "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" gethtypes "github.com/ethereum/go-ethereum/core/types" @@ -32,7 +33,10 @@ import ( llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" datastreamsllo "github.com/smartcontractkit/chainlink-data-streams/llo" + "github.com/smartcontractkit/chainlink-data-streams/rpc" 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/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" @@ -336,37 +340,40 @@ func promoteStagingConfig(t *testing.T, donID uint32, steve *bind.TransactOpts, backend.Commit() } -func TestIntegration_LLO(t *testing.T) { +func TestIntegration_LLO_evm_premium_legacy(t *testing.T) { t.Parallel() + testStartTimeStamp := time.Now() multiplier := decimal.New(1, 18) expirationWindow := time.Hour / time.Second + const salt = 100 + clientCSAKeys := make([]csakey.KeyV2, nNodes) clientPubKeys := make([]ed25519.PublicKey, nNodes) for i := 0; i < nNodes; i++ { - k := big.NewInt(int64(i)) + k := big.NewInt(int64(salt + i)) key := csakey.MustNewV2XXXTestingOnly(k) clientCSAKeys[i] = key clientPubKeys[i] = key.PublicKey } - steve, backend, configurator, configuratorAddress, verifier, _, verifierProxy, _, configStore, configStoreAddress, legacyVerifier, legacyVerifierAddr, _, _ := setupBlockchain(t) + steve, backend, _, _, verifier, _, verifierProxy, _, configStore, configStoreAddress, legacyVerifier, legacyVerifierAddr, _, _ := setupBlockchain(t) fromBlock := 1 // Setup bootstrap - bootstrapCSAKey := csakey.MustNewV2XXXTestingOnly(big.NewInt(-1)) + bootstrapCSAKey := csakey.MustNewV2XXXTestingOnly(big.NewInt(salt - 1)) bootstrapNodePort := freeport.GetOne(t) - appBootstrap, bootstrapPeerID, _, bootstrapKb, _ := setupNode(t, bootstrapNodePort, "bootstrap_llo", backend, bootstrapCSAKey) + appBootstrap, bootstrapPeerID, _, bootstrapKb, _ := setupNode(t, bootstrapNodePort, "bootstrap_llo", backend, bootstrapCSAKey, "") bootstrapNode := Node{App: appBootstrap, KeyBundle: bootstrapKb} t.Run("using legacy verifier configuration contract, produces reports in v0.3 format", func(t *testing.T) { - reqs := make(chan request, 100000) - serverKey := csakey.MustNewV2XXXTestingOnly(big.NewInt(-1)) + reqs := make(chan wsrpcRequest, 100000) + serverKey := csakey.MustNewV2XXXTestingOnly(big.NewInt(salt - 2)) serverPubKey := serverKey.PublicKey - srv := NewMercuryServer(t, ed25519.PrivateKey(serverKey.Raw()), reqs) + srv := NewWSRPCMercuryServer(t, ed25519.PrivateKey(serverKey.Raw()), reqs) - serverURL := startMercuryServer(t, srv, clientPubKeys) + serverURL := startWSRPCMercuryServer(t, srv, clientPubKeys) donID := uint32(995544) streams := []Stream{ethStream, linkStream, quoteStream1, quoteStream2} @@ -376,7 +383,7 @@ func TestIntegration_LLO(t *testing.T) { } // Setup oracle nodes - oracles, nodes := setupNodes(t, nNodes, backend, clientCSAKeys, streams) + oracles, nodes := setupNodes(t, nNodes, backend, clientCSAKeys, streams, "wsrpc") chainID := testutils.SimulatedChainID relayType := "evm" @@ -548,10 +555,516 @@ channelDefinitionsContractFromBlock = %d`, serverURL, serverPubKey, donID, confi } }) }) +} + +func TestIntegration_LLO_evm_abi_encode_unpacked(t *testing.T) { + t.Parallel() + + testStartTimeStamp := time.Now() + expirationWindow := uint32(3600) + + const salt = 200 + + clientCSAKeys := make([]csakey.KeyV2, nNodes) + clientPubKeys := make([]ed25519.PublicKey, nNodes) + for i := 0; i < nNodes; i++ { + k := big.NewInt(int64(salt + i)) + key := csakey.MustNewV2XXXTestingOnly(k) + clientCSAKeys[i] = key + clientPubKeys[i] = key.PublicKey + } + + steve, backend, configurator, configuratorAddress, _, _, _, _, configStore, configStoreAddress, _, _, _, _ := setupBlockchain(t) + fromBlock := 1 + + // Setup bootstrap + bootstrapCSAKey := csakey.MustNewV2XXXTestingOnly(big.NewInt(salt - 1)) + bootstrapNodePort := freeport.GetOne(t) + appBootstrap, bootstrapPeerID, _, bootstrapKb, _ := setupNode(t, bootstrapNodePort, "bootstrap_llo", backend, bootstrapCSAKey, "") + bootstrapNode := Node{App: appBootstrap, KeyBundle: bootstrapKb} + + t.Run("generates reports using go ReportFormatEVMABIEncodeUnpacked format", func(t *testing.T) { + reqs := make(chan *rpc.TransmitRequest, 100000) + serverKey := csakey.MustNewV2XXXTestingOnly(big.NewInt(salt - 2)) + serverPubKey := serverKey.PublicKey + srv := NewMercuryServer(t, ed25519.PrivateKey(serverKey.Raw()), reqs) + + serverURL := startMercuryServer(t, srv, clientPubKeys) + + donID := uint32(888333) + streams := []Stream{ethStream, linkStream} + streamMap := make(map[uint32]Stream) + for _, strm := range streams { + streamMap[strm.id] = strm + } + + // Setup oracle nodes + oracles, nodes := setupNodes(t, nNodes, backend, clientCSAKeys, streams, "grpc") + + chainID := testutils.SimulatedChainID + relayType := "evm" + relayConfig := fmt.Sprintf(` +chainID = "%s" +fromBlock = %d +lloDonID = %d +lloConfigMode = "bluegreen" +`, chainID, fromBlock, donID) + addBootstrapJob(t, bootstrapNode, configuratorAddress, "job-4", relayType, relayConfig) + + dexBasedAssetPriceStreamID := uint32(1) + marketStatusStreamID := uint32(2) + baseMarketDepthStreamID := uint32(3) + quoteMarketDepthStreamID := uint32(4) + benchmarkPriceStreamID := uint32(5) + binanceFundingRateStreamID := uint32(6) + binanceFundingTimeStreamID := uint32(7) + binanceFundingIntervalHoursStreamID := uint32(8) + deribitFundingRateStreamID := uint32(9) + deribitFundingTimeStreamID := uint32(10) + deribitFundingIntervalHoursStreamID := uint32(11) + + mustEncodeOpts := func(opts *lloevm.ReportFormatEVMABIEncodeOpts) []byte { + encoded, err := json.Marshal(opts) + require.NoError(t, err) + return encoded + } + + standardMultiplier := ubig.NewI(1e18) + + dexBasedAssetFeedID := utils.NewHash() + rwaFeedID := utils.NewHash() + benchmarkPriceFeedID := utils.NewHash() + fundingRateFeedID := utils.NewHash() + // Channel definitions + channelDefinitions := llotypes.ChannelDefinitions{ + // Sample DEX-based asset schema + 1: { + ReportFormat: llotypes.ReportFormatEVMABIEncodeUnpacked, + Streams: []llotypes.Stream{ + { + StreamID: ethStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: linkStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: dexBasedAssetPriceStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: baseMarketDepthStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: quoteMarketDepthStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + }, + Opts: mustEncodeOpts(&lloevm.ReportFormatEVMABIEncodeOpts{ + BaseUSDFee: decimal.NewFromFloat32(0.1), + ExpirationWindow: expirationWindow, + FeedID: dexBasedAssetFeedID, + ABI: []lloevm.ABIEncoder{ + lloevm.ABIEncoder{ + StreamID: dexBasedAssetPriceStreamID, + Type: "int192", + Multiplier: standardMultiplier, + }, + lloevm.ABIEncoder{ + StreamID: baseMarketDepthStreamID, + Type: "int192", + }, + lloevm.ABIEncoder{ + StreamID: quoteMarketDepthStreamID, + Type: "int192", + }, + }, + }), + }, + // Sample RWA schema + 2: { + ReportFormat: llotypes.ReportFormatEVMABIEncodeUnpacked, + Streams: []llotypes.Stream{ + { + StreamID: ethStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: linkStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: marketStatusStreamID, + Aggregator: llotypes.AggregatorMode, + }, + }, + Opts: mustEncodeOpts(&lloevm.ReportFormatEVMABIEncodeOpts{ + BaseUSDFee: decimal.NewFromFloat32(0.1), + ExpirationWindow: expirationWindow, + FeedID: rwaFeedID, + ABI: []lloevm.ABIEncoder{ + { + StreamID: marketStatusStreamID, + Type: "uint32", + }, + }, + }), + }, + // Sample Benchmark price schema + 3: { + ReportFormat: llotypes.ReportFormatEVMABIEncodeUnpacked, + Streams: []llotypes.Stream{ + { + StreamID: ethStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: linkStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: benchmarkPriceStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + }, + Opts: mustEncodeOpts(&lloevm.ReportFormatEVMABIEncodeOpts{ + BaseUSDFee: decimal.NewFromFloat32(0.1), + ExpirationWindow: expirationWindow, + FeedID: benchmarkPriceFeedID, + ABI: []lloevm.ABIEncoder{ + { + StreamID: benchmarkPriceStreamID, + Type: "int192", + Multiplier: standardMultiplier, + }, + }, + }), + }, + // Sample funding rate scheam + 4: { + ReportFormat: llotypes.ReportFormatEVMABIEncodeUnpacked, + Streams: []llotypes.Stream{ + { + StreamID: ethStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: linkStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: binanceFundingRateStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: binanceFundingTimeStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: binanceFundingIntervalHoursStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: deribitFundingRateStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: deribitFundingTimeStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: deribitFundingIntervalHoursStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + }, + Opts: mustEncodeOpts(&lloevm.ReportFormatEVMABIEncodeOpts{ + BaseUSDFee: decimal.NewFromFloat32(0.1), + ExpirationWindow: expirationWindow, + FeedID: fundingRateFeedID, + ABI: []lloevm.ABIEncoder{ + { + StreamID: binanceFundingRateStreamID, + Type: "int192", + }, + { + StreamID: binanceFundingTimeStreamID, + Type: "int192", + }, + { + StreamID: binanceFundingIntervalHoursStreamID, + Type: "int192", + }, + { + StreamID: deribitFundingRateStreamID, + Type: "int192", + }, + { + StreamID: deribitFundingTimeStreamID, + Type: "int192", + }, + { + StreamID: deribitFundingIntervalHoursStreamID, + Type: "int192", + }, + }, + }), + }, + } + url, sha := newChannelDefinitionsServer(t, channelDefinitions) + + // Set channel definitions + _, err := configStore.SetChannelDefinitions(steve, donID, url, sha) + require.NoError(t, err) + backend.Commit() + + pluginConfig := fmt.Sprintf(`servers = { "%s" = "%x" } +donID = %d +channelDefinitionsContractAddress = "0x%x" +channelDefinitionsContractFromBlock = %d`, serverURL, serverPubKey, donID, configStoreAddress, fromBlock) + + bridgeName := "superbridge" + + resultJSON := `{ + "benchmarkPrice": "2976.39", + "baseMarketDepth": "1000.1212", + "quoteMarketDepth": "998.5431", + "marketStatus": "1", + "binanceFundingRate": "1234.5678", + "binanceFundingTime": "1630000000", + "binanceFundingIntervalHours": "8", + "deribitFundingRate": "5432.2345", + "deribitFundingTime": "1630000000", + "deribitFundingIntervalHours": "8" +}` + + dexBasedAssetPipeline := fmt.Sprintf(` +dp [type=bridge name="%s" requestData="{\\"data\\":{\\"data\\":\\"foo\\"}}"]; + +bp_parse [type=jsonparse path="result,benchmarkPrice"]; +base_market_depth_parse [type=jsonparse path="result,baseMarketDepth"]; +quote_market_depth_parse [type=jsonparse path="result,quoteMarketDepth"]; + +bp_decimal [type=multiply times=1 streamID=%d]; +base_market_depth_decimal [type=multiply times=1 streamID=%d]; +quote_market_depth_decimal [type=multiply times=1 streamID=%d]; + +dp -> bp_parse -> bp_decimal; +dp -> base_market_depth_parse -> base_market_depth_decimal; +dp -> quote_market_depth_parse -> quote_market_depth_decimal; +`, bridgeName, dexBasedAssetPriceStreamID, baseMarketDepthStreamID, quoteMarketDepthStreamID) + + rwaPipeline := fmt.Sprintf(` +dp [type=bridge name="%s" requestData="{\\"data\\":{\\"data\\":\\"foo\\"}}"]; + +market_status_parse [type=jsonparse path="result,marketStatus"]; +market_status_decimal [type=multiply times=1 streamID=%d]; + +dp -> market_status_parse -> market_status_decimal; +`, bridgeName, marketStatusStreamID) + + benchmarkPricePipeline := fmt.Sprintf(` +dp [type=bridge name="%s" requestData="{\\"data\\":{\\"data\\":\\"foo\\"}}"]; + +bp_parse [type=jsonparse path="result,benchmarkPrice"]; +bp_decimal [type=multiply times=1 streamID=%d]; + +dp -> bp_parse -> bp_decimal; +`, bridgeName, benchmarkPriceStreamID) + + fundingRatePipeline := fmt.Sprintf(` +dp [type=bridge name="%s" requestData="{\\"data\\":{\\"data\\":\\"foo\\"}}"]; + +binance_funding_rate_parse [type=jsonparse path="result,binanceFundingRate"]; +binance_funding_rate_decimal [type=multiply times=1 streamID=%d]; + +binance_funding_time_parse [type=jsonparse path="result,binanceFundingTime"]; +binance_funding_time_decimal [type=multiply times=1 streamID=%d]; + +binance_funding_interval_hours_parse [type=jsonparse path="result,binanceFundingIntervalHours"]; +binance_funding_interval_hours_decimal [type=multiply times=1 streamID=%d]; + +deribit_funding_rate_parse [type=jsonparse path="result,deribitFundingRate"]; +deribit_funding_rate_decimal [type=multiply times=1 streamID=%d]; + +deribit_funding_time_parse [type=jsonparse path="result,deribitFundingTime"]; +deribit_funding_time_decimal [type=multiply times=1 streamID=%d]; + +deribit_funding_interval_hours_parse [type=jsonparse path="result,deribitFundingIntervalHours"]; +deribit_funding_interval_hours_decimal [type=multiply times=1 streamID=%d]; + +dp -> binance_funding_rate_parse -> binance_funding_rate_decimal; +dp -> binance_funding_time_parse -> binance_funding_time_decimal; +dp -> binance_funding_interval_hours_parse -> binance_funding_interval_hours_decimal; +dp -> deribit_funding_rate_parse -> deribit_funding_rate_decimal; +dp -> deribit_funding_time_parse -> deribit_funding_time_decimal; +dp -> deribit_funding_interval_hours_parse -> deribit_funding_interval_hours_decimal; +`, bridgeName, binanceFundingRateStreamID, binanceFundingTimeStreamID, binanceFundingIntervalHoursStreamID, deribitFundingRateStreamID, deribitFundingTimeStreamID, deribitFundingIntervalHoursStreamID) + + for i, node := range nodes { + // superBridge returns a JSON with everything you want in it, + // stream specs can just pick the individual fields they need + createBridge(t, bridgeName, resultJSON, node.App.BridgeORM()) + addStreamSpec(t, node, "dexBasedAssetPipeline", nil, dexBasedAssetPipeline) + addStreamSpec(t, node, "rwaPipeline", nil, rwaPipeline) + addStreamSpec(t, node, "benchmarkPricePipeline", nil, benchmarkPricePipeline) + addStreamSpec(t, node, "fundingRatePipeline", nil, fundingRatePipeline) + addLLOJob( + t, + node, + configuratorAddress, + bootstrapPeerID, + bootstrapNodePort, + clientPubKeys[i], + "llo-evm-abi-encode-unpacked-test", + pluginConfig, + relayType, + relayConfig, + ) + } + + // Set config on configurator + digest := setProductionConfig( + t, donID, steve, backend, configurator, configuratorAddress, nodes, oracles, + ) + + // NOTE: Wait for one of each type of report + feedIDs := map[[32]byte]struct{}{ + dexBasedAssetFeedID: {}, + rwaFeedID: {}, + benchmarkPriceFeedID: {}, + fundingRateFeedID: {}, + } + + for req := range reqs { + v := make(map[string]interface{}) + err := mercury.PayloadTypes.UnpackIntoMap(v, req.Payload) + require.NoError(t, err) + report, exists := v["report"] + if !exists { + t.Fatalf("expected payload %#v to contain 'report'", v) + } + reportCtx, exists := v["reportContext"] + if !exists { + t.Fatalf("expected payload %#v to contain 'reportContext'", v) + } + + // Check the report context + assert.Equal(t, [32]byte(digest), reportCtx.([3][32]uint8)[0]) // config digest + assert.Equal(t, "000000000000000000000000000000000000000000000000000d8e0d00000001", fmt.Sprintf("%x", reportCtx.([3][32]uint8)[2])) // extra hash + + reportElems := make(map[string]interface{}) + err = lloevm.BaseSchema.UnpackIntoMap(reportElems, report.([]byte)) + require.NoError(t, err) + + feedID := reportElems["feedId"].([32]uint8) + delete(feedIDs, feedID) + + // Check headers + assert.GreaterOrEqual(t, reportElems["validFromTimestamp"].(uint32), uint32(testStartTimeStamp.Unix())) //nolint:gosec // G115 + assert.GreaterOrEqual(t, int(reportElems["observationsTimestamp"].(uint32)), int(testStartTimeStamp.Unix())) + // Zero fees since both eth/link stream specs are missing, don't + // care about billing for purposes of this test + assert.Equal(t, "0", reportElems["nativeFee"].(*big.Int).String()) + assert.Equal(t, "0", reportElems["linkFee"].(*big.Int).String()) + assert.Equal(t, reportElems["observationsTimestamp"].(uint32)+expirationWindow, reportElems["expiresAt"].(uint32)) + + // Check payload values + payload := report.([]byte)[192:] + switch hex.EncodeToString(feedID[:]) { + case hex.EncodeToString(dexBasedAssetFeedID[:]): + require.Len(t, payload, 96) + args := abi.Arguments([]abi.Argument{ + {Name: "benchmarkPrice", Type: mustNewType("int192")}, + {Name: "baseMarketDepth", Type: mustNewType("int192")}, + {Name: "quoteMarketDepth", Type: mustNewType("int192")}, + }) + v := make(map[string]interface{}) + err := args.UnpackIntoMap(v, payload) + require.NoError(t, err) + + assert.Equal(t, "2976390000000000000000", v["benchmarkPrice"].(*big.Int).String()) + assert.Equal(t, "1000", v["baseMarketDepth"].(*big.Int).String()) + assert.Equal(t, "998", v["quoteMarketDepth"].(*big.Int).String()) + case hex.EncodeToString(rwaFeedID[:]): + require.Len(t, payload, 32) + args := abi.Arguments([]abi.Argument{ + {Name: "marketStatus", Type: mustNewType("uint32")}, + }) + v := make(map[string]interface{}) + err := args.UnpackIntoMap(v, payload) + require.NoError(t, err) + + assert.Equal(t, uint32(1), v["marketStatus"].(uint32)) + case hex.EncodeToString(benchmarkPriceFeedID[:]): + require.Len(t, payload, 32) + args := abi.Arguments([]abi.Argument{ + {Name: "benchmarkPrice", Type: mustNewType("int192")}, + }) + v := make(map[string]interface{}) + err := args.UnpackIntoMap(v, payload) + require.NoError(t, err) + + assert.Equal(t, "2976390000000000000000", v["benchmarkPrice"].(*big.Int).String()) + case hex.EncodeToString(fundingRateFeedID[:]): + require.Len(t, payload, 192) + args := abi.Arguments([]abi.Argument{ + {Name: "binanceFundingRate", Type: mustNewType("int192")}, + {Name: "binanceFundingTime", Type: mustNewType("int192")}, + {Name: "binanceFundingIntervalHours", Type: mustNewType("int192")}, + {Name: "deribitFundingRate", Type: mustNewType("int192")}, + {Name: "deribitFundingTime", Type: mustNewType("int192")}, + {Name: "deribitFundingIntervalHours", Type: mustNewType("int192")}, + }) + v := make(map[string]interface{}) + err := args.UnpackIntoMap(v, payload) + require.NoError(t, err) + + assert.Equal(t, "1234", v["binanceFundingRate"].(*big.Int).String()) + assert.Equal(t, "1630000000", v["binanceFundingTime"].(*big.Int).String()) + assert.Equal(t, "8", v["binanceFundingIntervalHours"].(*big.Int).String()) + assert.Equal(t, "5432", v["deribitFundingRate"].(*big.Int).String()) + assert.Equal(t, "1630000000", v["deribitFundingTime"].(*big.Int).String()) + assert.Equal(t, "8", v["deribitFundingIntervalHours"].(*big.Int).String()) + default: + t.Fatalf("unexpected feedID: %x", feedID) + } + + if len(feedIDs) == 0 { + break + } + } + }) +} + +func TestIntegration_LLO_blue_green_lifecycle(t *testing.T) { + t.Parallel() + + clientCSAKeys := make([]csakey.KeyV2, nNodes) + clientPubKeys := make([]ed25519.PublicKey, nNodes) + + const salt = 300 + + for i := 0; i < nNodes; i++ { + k := big.NewInt(int64(salt + i)) + key := csakey.MustNewV2XXXTestingOnly(k) + clientCSAKeys[i] = key + clientPubKeys[i] = key.PublicKey + } + + steve, backend, configurator, configuratorAddress, _, _, _, _, configStore, configStoreAddress, _, _, _, _ := setupBlockchain(t) + fromBlock := 1 + + // Setup bootstrap + bootstrapCSAKey := csakey.MustNewV2XXXTestingOnly(big.NewInt(salt - 1)) + bootstrapNodePort := freeport.GetOne(t) + appBootstrap, bootstrapPeerID, _, bootstrapKb, _ := setupNode(t, bootstrapNodePort, "bootstrap_llo", backend, bootstrapCSAKey, "") + bootstrapNode := Node{App: appBootstrap, KeyBundle: bootstrapKb} t.Run("Blue/Green lifecycle (using JSON report format)", func(t *testing.T) { - reqs := make(chan request, 100000) - serverKey := csakey.MustNewV2XXXTestingOnly(big.NewInt(-2)) + reqs := make(chan *rpc.TransmitRequest, 100000) + serverKey := csakey.MustNewV2XXXTestingOnly(big.NewInt(salt - 2)) serverPubKey := serverKey.PublicKey srv := NewMercuryServer(t, ed25519.PrivateKey(serverKey.Raw()), reqs) @@ -565,7 +1078,7 @@ channelDefinitionsContractFromBlock = %d`, serverURL, serverPubKey, donID, confi } // Setup oracle nodes - oracles, nodes := setupNodes(t, nNodes, backend, clientCSAKeys, streams) + oracles, nodes := setupNodes(t, nNodes, backend, clientCSAKeys, streams, "grpc") chainID := testutils.SimulatedChainID relayType := "evm" @@ -616,7 +1129,7 @@ channelDefinitionsContractFromBlock = %d`, serverURL, serverPubKey, donID, confi // NOTE: Wait until blue produces a report for req := range reqs { - _, _, r, _, err := (datastreamsllo.JSONReportCodec{}).UnpackDecode(req.req.Payload) + _, _, r, _, err := (datastreamsllo.JSONReportCodec{}).UnpackDecode(req.Payload) require.NoError(t, err) allReports[r.ConfigDigest] = append(allReports[r.ConfigDigest], r) @@ -637,7 +1150,7 @@ channelDefinitionsContractFromBlock = %d`, serverURL, serverPubKey, donID, confi // NOTE: Wait until green produces the first "specimen" report for req := range reqs { - _, _, r, _, err := (datastreamsllo.JSONReportCodec{}).UnpackDecode(req.req.Payload) + _, _, r, _, err := (datastreamsllo.JSONReportCodec{}).UnpackDecode(req.Payload) require.NoError(t, err) allReports[r.ConfigDigest] = append(allReports[r.ConfigDigest], r) @@ -658,7 +1171,7 @@ channelDefinitionsContractFromBlock = %d`, serverURL, serverPubKey, donID, confi // NOTE: Wait for first non-specimen report for the newly promoted (green) instance for req := range reqs { - _, _, r, _, err := (datastreamsllo.JSONReportCodec{}).UnpackDecode(req.req.Payload) + _, _, r, _, err := (datastreamsllo.JSONReportCodec{}).UnpackDecode(req.Payload) require.NoError(t, err) allReports[r.ConfigDigest] = append(allReports[r.ConfigDigest], r) @@ -727,7 +1240,7 @@ channelDefinitionsContractFromBlock = %d`, serverURL, serverPubKey, donID, confi if i == 5 { break } - _, _, r, _, err := (datastreamsllo.JSONReportCodec{}).UnpackDecode(req.req.Payload) + _, _, r, _, err := (datastreamsllo.JSONReportCodec{}).UnpackDecode(req.Payload) require.NoError(t, err) allReports[r.ConfigDigest] = append(allReports[r.ConfigDigest], r) @@ -744,7 +1257,7 @@ channelDefinitionsContractFromBlock = %d`, serverURL, serverPubKey, donID, confi // NOTE: Wait until blue produces the first "specimen" report for req := range reqs { - _, _, r, _, err := (datastreamsllo.JSONReportCodec{}).UnpackDecode(req.req.Payload) + _, _, r, _, err := (datastreamsllo.JSONReportCodec{}).UnpackDecode(req.Payload) require.NoError(t, err) allReports[r.ConfigDigest] = append(allReports[r.ConfigDigest], r) @@ -764,7 +1277,7 @@ channelDefinitionsContractFromBlock = %d`, serverURL, serverPubKey, donID, confi // NOTE: Wait for first non-specimen report for the newly promoted (blue) instance for req := range reqs { - _, _, r, _, err := (datastreamsllo.JSONReportCodec{}).UnpackDecode(req.req.Payload) + _, _, r, _, err := (datastreamsllo.JSONReportCodec{}).UnpackDecode(req.Payload) require.NoError(t, err) allReports[r.ConfigDigest] = append(allReports[r.ConfigDigest], r) @@ -804,7 +1317,7 @@ channelDefinitionsContractFromBlock = %d`, serverURL, serverPubKey, donID, confi // NOTE: Wait until the first report for the new channel definition is produced for req := range reqs { - _, _, r, _, err := (datastreamsllo.JSONReportCodec{}).UnpackDecode(req.req.Payload) + _, _, r, _, err := (datastreamsllo.JSONReportCodec{}).UnpackDecode(req.Payload) require.NoError(t, err) allReports[r.ConfigDigest] = append(allReports[r.ConfigDigest], r) @@ -831,10 +1344,10 @@ channelDefinitionsContractFromBlock = %d`, serverURL, serverPubKey, donID, confi }) } -func setupNodes(t *testing.T, nNodes int, backend evmtypes.Backend, clientCSAKeys []csakey.KeyV2, streams []Stream) (oracles []confighelper.OracleIdentityExtra, nodes []Node) { +func setupNodes(t *testing.T, nNodes int, backend evmtypes.Backend, clientCSAKeys []csakey.KeyV2, streams []Stream, transmissionMode string) (oracles []confighelper.OracleIdentityExtra, nodes []Node) { ports := freeport.GetN(t, nNodes) for i := 0; i < nNodes; i++ { - app, peerID, transmitter, kb, observedLogs := setupNode(t, ports[i], fmt.Sprintf("oracle_streams_%d", i), backend, clientCSAKeys[i]) + app, peerID, transmitter, kb, observedLogs := setupNode(t, ports[i], fmt.Sprintf("oracle_streams_%d", i), backend, clientCSAKeys[i], transmissionMode) nodes = append(nodes, Node{ app, transmitter, kb, observedLogs, @@ -871,3 +1384,11 @@ func newChannelDefinitionsServer(t *testing.T, channelDefinitions llotypes.Chann t.Cleanup(channelDefinitionsServer.Close) return channelDefinitionsServer.URL, channelDefinitionsSHA } + +func mustNewType(t string) abi.Type { + result, err := abi.NewType(t, "", []abi.ArgumentMarshaling{}) + if err != nil { + panic(fmt.Sprintf("Unexpected error during abi.NewType: %s", err)) + } + return result +} diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/mocks/registry.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/mocks/registry.go index ab4a8d5280d..b4d2eea2508 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/mocks/registry.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/mocks/registry.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core/mocks/upkeep_state_reader.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core/mocks/upkeep_state_reader.go index 969c85efac3..24b5d92ace4 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core/mocks/upkeep_state_reader.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core/mocks/upkeep_state_reader.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/http_client.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/http_client.go index e0ad6ae9467..896e1daec97 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/http_client.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/http_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/registry.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/registry.go index bb431966763..e386b7e0fab 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/registry.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/registry.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -6,7 +6,6 @@ import ( big "math/big" bind "github.com/ethereum/go-ethereum/accounts/abi/bind" - encoding "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding" generated "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" @@ -206,22 +205,22 @@ func (_c *Registry_GetState_Call) RunAndReturn(run func(*bind.CallOpts) (i_autom } // GetUpkeep provides a mock function with given fields: opts, id -func (_m *Registry) GetUpkeep(opts *bind.CallOpts, id *big.Int) (encoding.UpkeepInfo, error) { +func (_m *Registry) GetUpkeep(opts *bind.CallOpts, id *big.Int) (i_automation_v21_plus_common.IAutomationV21PlusCommonUpkeepInfoLegacy, error) { ret := _m.Called(opts, id) if len(ret) == 0 { panic("no return value specified for GetUpkeep") } - var r0 encoding.UpkeepInfo + var r0 i_automation_v21_plus_common.IAutomationV21PlusCommonUpkeepInfoLegacy var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, *big.Int) (encoding.UpkeepInfo, error)); ok { + if rf, ok := ret.Get(0).(func(*bind.CallOpts, *big.Int) (i_automation_v21_plus_common.IAutomationV21PlusCommonUpkeepInfoLegacy, error)); ok { return rf(opts, id) } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, *big.Int) encoding.UpkeepInfo); ok { + if rf, ok := ret.Get(0).(func(*bind.CallOpts, *big.Int) i_automation_v21_plus_common.IAutomationV21PlusCommonUpkeepInfoLegacy); ok { r0 = rf(opts, id) } else { - r0 = ret.Get(0).(encoding.UpkeepInfo) + r0 = ret.Get(0).(i_automation_v21_plus_common.IAutomationV21PlusCommonUpkeepInfoLegacy) } if rf, ok := ret.Get(1).(func(*bind.CallOpts, *big.Int) error); ok { @@ -252,12 +251,12 @@ func (_c *Registry_GetUpkeep_Call) Run(run func(opts *bind.CallOpts, id *big.Int return _c } -func (_c *Registry_GetUpkeep_Call) Return(_a0 encoding.UpkeepInfo, _a1 error) *Registry_GetUpkeep_Call { +func (_c *Registry_GetUpkeep_Call) Return(_a0 i_automation_v21_plus_common.IAutomationV21PlusCommonUpkeepInfoLegacy, _a1 error) *Registry_GetUpkeep_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *Registry_GetUpkeep_Call) RunAndReturn(run func(*bind.CallOpts, *big.Int) (encoding.UpkeepInfo, error)) *Registry_GetUpkeep_Call { +func (_c *Registry_GetUpkeep_Call) RunAndReturn(run func(*bind.CallOpts, *big.Int) (i_automation_v21_plus_common.IAutomationV21PlusCommonUpkeepInfoLegacy, error)) *Registry_GetUpkeep_Call { _c.Call.Return(run) return _c } diff --git a/core/services/ocr2/plugins/promwrapper/mocks/prometheus_backend.go b/core/services/ocr2/plugins/promwrapper/mocks/prometheus_backend.go index 2d38cc77387..1e85e0d2735 100644 --- a/core/services/ocr2/plugins/promwrapper/mocks/prometheus_backend.go +++ b/core/services/ocr2/plugins/promwrapper/mocks/prometheus_backend.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -47,7 +47,7 @@ func (_c *PrometheusBackend_SetAcceptFinalizedReportToTransmitAcceptedReportLate } func (_c *PrometheusBackend_SetAcceptFinalizedReportToTransmitAcceptedReportLatency_Call) RunAndReturn(run func([]string, float64)) *PrometheusBackend_SetAcceptFinalizedReportToTransmitAcceptedReportLatency_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -81,7 +81,7 @@ func (_c *PrometheusBackend_SetCloseDuration_Call) Return() *PrometheusBackend_S } func (_c *PrometheusBackend_SetCloseDuration_Call) RunAndReturn(run func([]string, float64)) *PrometheusBackend_SetCloseDuration_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -115,7 +115,7 @@ func (_c *PrometheusBackend_SetObservationDuration_Call) Return() *PrometheusBac } func (_c *PrometheusBackend_SetObservationDuration_Call) RunAndReturn(run func([]string, float64)) *PrometheusBackend_SetObservationDuration_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -149,7 +149,7 @@ func (_c *PrometheusBackend_SetObservationToReportLatency_Call) Return() *Promet } func (_c *PrometheusBackend_SetObservationToReportLatency_Call) RunAndReturn(run func([]string, float64)) *PrometheusBackend_SetObservationToReportLatency_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -183,7 +183,7 @@ func (_c *PrometheusBackend_SetQueryDuration_Call) Return() *PrometheusBackend_S } func (_c *PrometheusBackend_SetQueryDuration_Call) RunAndReturn(run func([]string, float64)) *PrometheusBackend_SetQueryDuration_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -217,7 +217,7 @@ func (_c *PrometheusBackend_SetQueryToObservationLatency_Call) Return() *Prometh } func (_c *PrometheusBackend_SetQueryToObservationLatency_Call) RunAndReturn(run func([]string, float64)) *PrometheusBackend_SetQueryToObservationLatency_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -251,7 +251,7 @@ func (_c *PrometheusBackend_SetReportDuration_Call) Return() *PrometheusBackend_ } func (_c *PrometheusBackend_SetReportDuration_Call) RunAndReturn(run func([]string, float64)) *PrometheusBackend_SetReportDuration_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -285,7 +285,7 @@ func (_c *PrometheusBackend_SetReportToAcceptFinalizedReportLatency_Call) Return } func (_c *PrometheusBackend_SetReportToAcceptFinalizedReportLatency_Call) RunAndReturn(run func([]string, float64)) *PrometheusBackend_SetReportToAcceptFinalizedReportLatency_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -319,7 +319,7 @@ func (_c *PrometheusBackend_SetShouldAcceptFinalizedReportDuration_Call) Return( } func (_c *PrometheusBackend_SetShouldAcceptFinalizedReportDuration_Call) RunAndReturn(run func([]string, float64)) *PrometheusBackend_SetShouldAcceptFinalizedReportDuration_Call { - _c.Call.Return(run) + _c.Run(run) return _c } @@ -353,7 +353,7 @@ func (_c *PrometheusBackend_SetShouldTransmitAcceptedReportDuration_Call) Return } func (_c *PrometheusBackend_SetShouldTransmitAcceptedReportDuration_Call) RunAndReturn(run func([]string, float64)) *PrometheusBackend_SetShouldTransmitAcceptedReportDuration_Call { - _c.Call.Return(run) + _c.Run(run) return _c } diff --git a/core/services/ocr2/plugins/threshold/mocks/decryptor.go b/core/services/ocr2/plugins/threshold/mocks/decryptor.go index edf19e8a284..6b001b73bcc 100644 --- a/core/services/ocr2/plugins/threshold/mocks/decryptor.go +++ b/core/services/ocr2/plugins/threshold/mocks/decryptor.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/ocr2/validate/validate.go b/core/services/ocr2/validate/validate.go index c2f3e455232..27a5a885369 100644 --- a/core/services/ocr2/validate/validate.go +++ b/core/services/ocr2/validate/validate.go @@ -269,8 +269,8 @@ func validateGenericPluginSpec(ctx context.Context, spec *job.OCR2OracleSpec, rc loopID := fmt.Sprintf("%s-%s-%s", p.PluginName, spec.ContractID, spec.GetID()) // Starting and stopping a LOOPP isn't efficient; ideally, we'd initiate the LOOPP once and then reference - //it later to conserve resources. This code will be revisited once BCF-3126 is implemented, and we have - //the ability to reference the LOOPP for future use. + // it later to conserve resources. This code will be revisited once BCF-3126 is implemented, and we have + // the ability to reference the LOOPP for future use. cmdFn, grpcOpts, err := rc.RegisterLOOP(plugins.CmdConfig{ ID: loopID, Cmd: command, diff --git a/core/services/ocrcommon/block_translator.go b/core/services/ocrcommon/block_translator.go index b25d617e2ab..8a755f767b9 100644 --- a/core/services/ocrcommon/block_translator.go +++ b/core/services/ocrcommon/block_translator.go @@ -22,7 +22,7 @@ func NewBlockTranslator(cfg Config, client evmclient.Client, lggr logger.Logger) switch cfg.ChainType() { case chaintype.ChainArbitrum: return NewArbitrumBlockTranslator(client, lggr) - case "", chaintype.ChainCelo, chaintype.ChainGnosis, chaintype.ChainKroma, chaintype.ChainMetis, chaintype.ChainOptimismBedrock, chaintype.ChainScroll, chaintype.ChainWeMix, chaintype.ChainXLayer, chaintype.ChainZkEvm, chaintype.ChainZkSync, chaintype.ChainZircuit: + case "", chaintype.ChainCelo, chaintype.ChainGnosis, chaintype.ChainKroma, chaintype.ChainMetis, chaintype.ChainOptimismBedrock, chaintype.ChainSei, chaintype.ChainScroll, chaintype.ChainWeMix, chaintype.ChainXLayer, chaintype.ChainZkEvm, chaintype.ChainZkSync, chaintype.ChainZircuit: fallthrough default: return &l1BlockTranslator{} diff --git a/core/services/ocrcommon/dual_transmitter.go b/core/services/ocrcommon/dual_transmitter.go new file mode 100644 index 00000000000..efc60978f19 --- /dev/null +++ b/core/services/ocrcommon/dual_transmitter.go @@ -0,0 +1,134 @@ +package ocrcommon + +import ( + "context" + "math/big" + "net/url" + "slices" + + "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" + + "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" +) + +type ocr2FeedsDualTransmission struct { + txm txManager + primaryFromAddresses []common.Address + gasLimit uint64 + primaryEffectiveTransmitterAddress common.Address + strategy types.TxStrategy + checker txmgr.TransmitCheckerSpec + chainID *big.Int + keystore roundRobinKeystore + + ocr2Aggregator common.Address + txManagerOCR2 + + secondaryContractAddress common.Address + secondaryFromAddress common.Address + secondaryMeta map[string][]string +} + +func (t *ocr2FeedsDualTransmission) forwarderAddress(ctx context.Context, eoa, ocr2Aggregator common.Address) (common.Address, error) { + // If effectiveTransmitterAddress is in fromAddresses, then forwarders aren't set. + if slices.Contains(t.primaryFromAddresses, t.primaryEffectiveTransmitterAddress) { + return common.Address{}, nil + } + + forwarderAddress, err := t.GetForwarderForEOAOCR2Feeds(ctx, eoa, ocr2Aggregator) + if err != nil { + return common.Address{}, err + } + + // if forwarder address is in fromAddresses, then none of the forwarders are valid + if slices.Contains(t.primaryFromAddresses, forwarderAddress) { + forwarderAddress = common.Address{} + } + + return forwarderAddress, nil +} + +func (t *ocr2FeedsDualTransmission) CreateEthTransaction(ctx context.Context, toAddress common.Address, payload []byte, txMeta *txmgr.TxMeta) error { + roundRobinFromAddress, err := t.keystore.GetRoundRobinAddress(ctx, t.chainID, t.primaryFromAddresses...) + if err != nil { + return errors.Wrap(err, "skipped OCR transmission, error getting round-robin address") + } + + forwarderAddress, err := t.forwarderAddress(ctx, roundRobinFromAddress, toAddress) + if err != nil { + return err + } + + _, err = t.txm.CreateTransaction(ctx, txmgr.TxRequest{ + FromAddress: roundRobinFromAddress, + ToAddress: toAddress, + EncodedPayload: payload, + FeeLimit: t.gasLimit, + ForwarderAddress: forwarderAddress, + Strategy: t.strategy, + Checker: t.checker, + Meta: txMeta, + }) + + return errors.Wrap(err, "skipped OCR transmission: skipped primary transmission") +} + +func (t *ocr2FeedsDualTransmission) CreateSecondaryEthTransaction(ctx context.Context, payload []byte, txMeta *txmgr.TxMeta) error { + forwarderAddress, err := t.forwarderAddress(ctx, t.secondaryFromAddress, t.secondaryContractAddress) + if err != nil { + return err + } + + if txMeta == nil { + txMeta = &txmgr.TxMeta{} + } + + dualBroadcast := true + dualBroadcastParams := t.urlParams() + + txMeta.DualBroadcast = &dualBroadcast + txMeta.DualBroadcastParams = &dualBroadcastParams + + _, err = t.txm.CreateTransaction(ctx, txmgr.TxRequest{ + FromAddress: t.secondaryFromAddress, + ToAddress: t.secondaryContractAddress, + EncodedPayload: payload, + ForwarderAddress: forwarderAddress, + FeeLimit: t.gasLimit, + Strategy: t.strategy, + Checker: t.checker, + Meta: txMeta, + }) + + return errors.Wrap(err, "skipped secondary transmission") +} + +func (t *ocr2FeedsDualTransmission) FromAddress(ctx context.Context) common.Address { + roundRobinFromAddress, err := t.keystore.GetRoundRobinAddress(ctx, t.chainID, t.primaryFromAddresses...) + if err != nil { + return t.primaryEffectiveTransmitterAddress + } + + forwarderAddress, err := t.GetForwarderForEOAOCR2Feeds(ctx, roundRobinFromAddress, t.ocr2Aggregator) + if errors.Is(err, forwarders.ErrForwarderForEOANotFound) { + // if there are no valid forwarders try to fallback to eoa + return roundRobinFromAddress + } else if err != nil { + return t.primaryEffectiveTransmitterAddress + } + + return forwarderAddress +} + +func (t *ocr2FeedsDualTransmission) urlParams() string { + values := url.Values{} + for k, v := range t.secondaryMeta { + for _, p := range v { + values.Add(k, p) + } + } + return values.Encode() +} diff --git a/core/services/ocrcommon/telemetry.go b/core/services/ocrcommon/telemetry.go index 5e4a65180d5..3872955e5a3 100644 --- a/core/services/ocrcommon/telemetry.go +++ b/core/services/ocrcommon/telemetry.go @@ -261,13 +261,11 @@ func hexStringToDecimal(hexString string) (decimal.Decimal, bool) { func (e *EnhancedTelemetryService[T]) getObservation(finalResult *pipeline.FinalResult) int64 { singularResult, err := finalResult.SingularResult() if err != nil { - e.lggr.Warnf("cannot get singular result, job %d", e.job.ID) return 0 } finalResultDecimal, err := utils.ToDecimal(singularResult.Value) if err != nil { - e.lggr.Warnf("cannot parse singular result from bridge task, job %d", e.job.ID) return 0 } @@ -277,7 +275,6 @@ func (e *EnhancedTelemetryService[T]) getObservation(finalResult *pipeline.Final func (e *EnhancedTelemetryService[T]) getParsedValue(trrs *pipeline.TaskRunResults, trr pipeline.TaskRunResult) float64 { parsedValue := getJsonParsedValue(trr, trrs) if parsedValue == nil { - e.lggr.Warnf("cannot get json parse value, job %d, id %s", e.job.ID, trr.Task.DotID()) return 0 } return *parsedValue @@ -302,23 +299,16 @@ func (e *EnhancedTelemetryService[T]) collectAndSend(trrs *pipeline.TaskRunResul if trr.Task.Type() != pipeline.TaskTypeBridge { continue } - var bridgeName string - if b, is := trr.Task.(*pipeline.BridgeTask); is { - bridgeName = b.Name - } if trr.Result.Error != nil { - e.lggr.Warnw(fmt.Sprintf("cannot get bridge response from bridge task, job=%d, id=%s, name=%q", e.job.ID, trr.Task.DotID(), bridgeName), "err", trr.Result.Error, "jobID", e.job.ID, "dotID", trr.Task.DotID(), "bridgeName", bridgeName) continue } bridgeRawResponse, ok := trr.Result.Value.(string) if !ok { - e.lggr.Warnw(fmt.Sprintf("cannot parse bridge response from bridge task, job=%d, id=%s, name=%q: expected string, got: %v (type %T)", e.job.ID, trr.Task.DotID(), bridgeName, trr.Result.Value, trr.Result.Value), "jobID", e.job.ID, "dotID", trr.Task.DotID(), "bridgeName", bridgeName) continue } eaTelem, err := parseEATelemetry([]byte(bridgeRawResponse)) if err != nil { - e.lggr.Warnw(fmt.Sprintf("cannot parse EA telemetry, job=%d, id=%s, name=%q", e.job.ID, trr.Task.DotID(), bridgeName), "err", err, "jobID", e.job.ID, "dotID", trr.Task.DotID(), "bridgeName", bridgeName) continue } value := e.getParsedValue(trrs, trr) @@ -635,12 +625,11 @@ func getPricesFromBridgeTaskByTelemetryField(lggr logger.Logger, bridgeTask pipe func parsePriceFromTask(lggr logger.Logger, trr pipeline.TaskRunResult) float64 { var val float64 if trr.Result.Error != nil { - lggr.Warnw(fmt.Sprintf("got error on EA telemetry price task, id %s: %s", trr.Task.DotID(), trr.Result.Error), "err", trr.Result.Error) return 0 } val, err := getResultFloat64(&trr) if err != nil { - lggr.Warnw(fmt.Sprintf("cannot parse EA telemetry price to float64, DOT id %s", trr.Task.DotID()), "task_type", trr.Task.Type(), "task_tags", trr.Task.TaskTags(), "err", err) + return 0 } return val } diff --git a/core/services/ocrcommon/telemetry_test.go b/core/services/ocrcommon/telemetry_test.go index 4c8f0eb1127..1059d653b62 100644 --- a/core/services/ocrcommon/telemetry_test.go +++ b/core/services/ocrcommon/telemetry_test.go @@ -385,8 +385,7 @@ func TestGetObservation(t *testing.T) { obs := e.getObservation(&pipeline.FinalResult{}) assert.Equal(t, obs, int64(0)) - assert.Equal(t, logs.Len(), 1) - assert.Contains(t, logs.All()[0].Message, "cannot get singular result") + assert.Equal(t, 0, logs.Len()) finalResult := &pipeline.FinalResult{ Values: []interface{}{"123456"}, @@ -457,8 +456,7 @@ func TestCollectAndSend(t *testing.T) { } wg.Wait() - assert.Equal(t, logs.Len(), 2) - assert.Contains(t, logs.All()[0].Message, "cannot parse bridge response from bridge task") + assert.Equal(t, 0, logs.Len()) badTrrs = &pipeline.TaskRunResults{ pipeline.TaskRunResult{ @@ -475,9 +473,7 @@ func TestCollectAndSend(t *testing.T) { RepTimestamp: observationTimestamp, } wg.Wait() - assert.Equal(t, 2, logs.Len()) - assert.Contains(t, logs.All()[0].Message, "cannot parse bridge response from bridge task") - assert.Contains(t, logs.All()[1].Message, "cannot get json parse value") + assert.Equal(t, 0, logs.Len()) doneCh <- struct{}{} } @@ -707,10 +703,7 @@ func TestGetPricesFromBridgeTaskByOrder(t *testing.T) { require.Equal(t, benchmarkPrice, float64(0)) require.Equal(t, bid, float64(0)) require.Equal(t, ask, float64(0)) - require.Equal(t, 3, logs.Len()) - require.Contains(t, logs.All()[0].Message, "cannot parse EA telemetry price to float64, DOT id ds1_benchmark") - require.Contains(t, logs.All()[1].Message, "cannot parse EA telemetry price to float64, DOT id ds2_bid") - require.Contains(t, logs.All()[2].Message, "cannot parse EA telemetry price to float64, DOT id ds3_ask") + require.Equal(t, 0, logs.Len()) benchmarkPrice, bid, ask = getPricesFromBridgeTask(lggr, trrsMercuryV1[0], trrsMercuryV2, 2) require.Equal(t, 123456.123456, benchmarkPrice) diff --git a/core/services/ocrcommon/transmitter.go b/core/services/ocrcommon/transmitter.go index 8121f3778d2..01200bbb7cb 100644 --- a/core/services/ocrcommon/transmitter.go +++ b/core/services/ocrcommon/transmitter.go @@ -2,10 +2,7 @@ package ocrcommon import ( "context" - errors2 "errors" - "fmt" "math/big" - "net/url" "slices" "github.com/ethereum/go-ethereum/common" @@ -28,6 +25,8 @@ type txManager interface { type Transmitter interface { CreateEthTransaction(ctx context.Context, toAddress common.Address, payload []byte, txMeta *txmgr.TxMeta) error FromAddress(context.Context) common.Address + + CreateSecondaryEthTransaction(context.Context, []byte, *txmgr.TxMeta) error } type transmitter struct { @@ -99,7 +98,24 @@ func NewOCR2FeedsTransmitter( return nil, errors.New("nil keystore provided to transmitter") } - baseTransmitter := &ocr2FeedsTransmitter{ + if dualTransmissionConfig != nil { + return &ocr2FeedsDualTransmission{ + ocr2Aggregator: ocr2Aggregator, + txm: txm, + txManagerOCR2: txm, + primaryFromAddresses: fromAddresses, + gasLimit: gasLimit, + primaryEffectiveTransmitterAddress: effectiveTransmitterAddress, + strategy: strategy, + checker: checker, + chainID: chainID, + keystore: keystore, + secondaryContractAddress: dualTransmissionConfig.ContractAddress, + secondaryFromAddress: dualTransmissionConfig.TransmitterAddress, + secondaryMeta: dualTransmissionConfig.Meta, + }, nil + } + return &ocr2FeedsTransmitter{ ocr2Aggregator: ocr2Aggregator, txManagerOCR2: txm, transmitter: transmitter{ @@ -112,17 +128,7 @@ func NewOCR2FeedsTransmitter( chainID: chainID, keystore: keystore, }, - } - - if dualTransmissionConfig != nil { - return &ocr2FeedsDualTransmission{ - transmitter: *baseTransmitter, - secondaryContractAddress: dualTransmissionConfig.ContractAddress, - secondaryFromAddress: dualTransmissionConfig.TransmitterAddress, - secondaryMeta: dualTransmissionConfig.Meta, - }, nil - } - return baseTransmitter, nil + }, nil } func (t *transmitter) CreateEthTransaction(ctx context.Context, toAddress common.Address, payload []byte, txMeta *txmgr.TxMeta) error { @@ -144,6 +150,10 @@ func (t *transmitter) CreateEthTransaction(ctx context.Context, toAddress common return errors.Wrap(err, "skipped OCR transmission") } +func (t *transmitter) CreateSecondaryEthTransaction(ctx context.Context, bytes []byte, meta *txmgr.TxMeta) error { + return errors.New("trying to send a secondary transmission on a non dual transmitter") +} + func (t *transmitter) FromAddress(context.Context) common.Address { return t.effectiveTransmitterAddress } @@ -219,56 +229,6 @@ func (t *ocr2FeedsTransmitter) forwarderAddress(ctx context.Context, eoa, ocr2Ag return forwarderAddress, nil } -type ocr2FeedsDualTransmission struct { - transmitter ocr2FeedsTransmitter - - secondaryContractAddress common.Address - secondaryFromAddress common.Address - secondaryMeta map[string][]string -} - -func (t *ocr2FeedsDualTransmission) CreateEthTransaction(ctx context.Context, toAddress common.Address, payload []byte, txMeta *txmgr.TxMeta) error { - // Primary transmission - errPrimary := t.transmitter.CreateEthTransaction(ctx, toAddress, payload, txMeta) - if errPrimary != nil { - errPrimary = fmt.Errorf("skipped primary transmission: %w", errPrimary) - } - - if txMeta == nil { - txMeta = &txmgr.TxMeta{} - } - - dualBroadcast := true - dualBroadcastParams := t.urlParams() - - txMeta.DualBroadcast = &dualBroadcast - txMeta.DualBroadcastParams = &dualBroadcastParams - - // Secondary transmission - _, errSecondary := t.transmitter.txm.CreateTransaction(ctx, txmgr.TxRequest{ - FromAddress: t.secondaryFromAddress, - ToAddress: t.secondaryContractAddress, - EncodedPayload: payload, - FeeLimit: t.transmitter.gasLimit, - Strategy: t.transmitter.strategy, - Checker: t.transmitter.checker, - Meta: txMeta, - }) - - errSecondary = errors.Wrap(errSecondary, "skipped secondary transmission") - return errors2.Join(errPrimary, errSecondary) -} - -func (t *ocr2FeedsDualTransmission) FromAddress(ctx context.Context) common.Address { - return t.transmitter.FromAddress(ctx) -} - -func (t *ocr2FeedsDualTransmission) urlParams() string { - values := url.Values{} - for k, v := range t.secondaryMeta { - for _, p := range v { - values.Add(k, p) - } - } - return values.Encode() +func (t *ocr2FeedsTransmitter) CreateSecondaryEthTransaction(ctx context.Context, bytes []byte, meta *txmgr.TxMeta) error { + return errors.New("trying to send a secondary transmission on a non dual transmitter") } diff --git a/core/services/ocrcommon/transmitter_test.go b/core/services/ocrcommon/transmitter_test.go index 5f434e59c62..bb91a87d517 100644 --- a/core/services/ocrcommon/transmitter_test.go +++ b/core/services/ocrcommon/transmitter_test.go @@ -241,6 +241,7 @@ func Test_DualTransmitter(t *testing.T) { })).Twice().Return(txmgr.Tx{}, nil) require.NoError(t, transmitter.CreateEthTransaction(testutils.Context(t), toAddress, payload, nil)) + require.NoError(t, transmitter.CreateSecondaryEthTransaction(testutils.Context(t), payload, nil)) require.True(t, primaryTxConfirmed) require.True(t, secondaryTxConfirmed) diff --git a/core/services/p2p/types/mocks/peer.go b/core/services/p2p/types/mocks/peer.go index a50bad780b8..e24c662ffaf 100644 --- a/core/services/p2p/types/mocks/peer.go +++ b/core/services/p2p/types/mocks/peer.go @@ -1,12 +1,14 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks import ( context "context" - types "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" + ragep2ptypes "github.com/smartcontractkit/libocr/ragep2p/types" mock "github.com/stretchr/testify/mock" + + types "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" ) // Peer is an autogenerated mock type for the Peer type @@ -22,7 +24,7 @@ func (_m *Peer) EXPECT() *Peer_Expecter { return &Peer_Expecter{mock: &_m.Mock} } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *Peer) Close() error { ret := _m.Called() @@ -67,7 +69,7 @@ func (_c *Peer_Close_Call) RunAndReturn(run func() error) *Peer_Close_Call { return _c } -// HealthReport provides a mock function with given fields: +// HealthReport provides a mock function with no fields func (_m *Peer) HealthReport() map[string]error { ret := _m.Called() @@ -114,20 +116,20 @@ func (_c *Peer_HealthReport_Call) RunAndReturn(run func() map[string]error) *Pee return _c } -// ID provides a mock function with given fields: -func (_m *Peer) ID() types.PeerID { +// ID provides a mock function with no fields +func (_m *Peer) ID() ragep2ptypes.PeerID { ret := _m.Called() if len(ret) == 0 { panic("no return value specified for ID") } - var r0 types.PeerID - if rf, ok := ret.Get(0).(func() types.PeerID); ok { + var r0 ragep2ptypes.PeerID + if rf, ok := ret.Get(0).(func() ragep2ptypes.PeerID); ok { r0 = rf() } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(types.PeerID) + r0 = ret.Get(0).(ragep2ptypes.PeerID) } } @@ -151,17 +153,17 @@ func (_c *Peer_ID_Call) Run(run func()) *Peer_ID_Call { return _c } -func (_c *Peer_ID_Call) Return(_a0 types.PeerID) *Peer_ID_Call { +func (_c *Peer_ID_Call) Return(_a0 ragep2ptypes.PeerID) *Peer_ID_Call { _c.Call.Return(_a0) return _c } -func (_c *Peer_ID_Call) RunAndReturn(run func() types.PeerID) *Peer_ID_Call { +func (_c *Peer_ID_Call) RunAndReturn(run func() ragep2ptypes.PeerID) *Peer_ID_Call { _c.Call.Return(run) return _c } -// Name provides a mock function with given fields: +// Name provides a mock function with no fields func (_m *Peer) Name() string { ret := _m.Called() @@ -206,7 +208,7 @@ func (_c *Peer_Name_Call) RunAndReturn(run func() string) *Peer_Name_Call { return _c } -// Ready provides a mock function with given fields: +// Ready provides a mock function with no fields func (_m *Peer) Ready() error { ret := _m.Called() @@ -251,7 +253,7 @@ func (_c *Peer_Ready_Call) RunAndReturn(run func() error) *Peer_Ready_Call { return _c } -// Receive provides a mock function with given fields: +// Receive provides a mock function with no fields func (_m *Peer) Receive() <-chan types.Message { ret := _m.Called() @@ -299,7 +301,7 @@ func (_c *Peer_Receive_Call) RunAndReturn(run func() <-chan types.Message) *Peer } // Send provides a mock function with given fields: peerID, msg -func (_m *Peer) Send(peerID types.PeerID, msg []byte) error { +func (_m *Peer) Send(peerID ragep2ptypes.PeerID, msg []byte) error { ret := _m.Called(peerID, msg) if len(ret) == 0 { @@ -307,7 +309,7 @@ func (_m *Peer) Send(peerID types.PeerID, msg []byte) error { } var r0 error - if rf, ok := ret.Get(0).(func(types.PeerID, []byte) error); ok { + if rf, ok := ret.Get(0).(func(ragep2ptypes.PeerID, []byte) error); ok { r0 = rf(peerID, msg) } else { r0 = ret.Error(0) @@ -322,15 +324,15 @@ type Peer_Send_Call struct { } // Send is a helper method to define mock.On call -// - peerID types.PeerID +// - peerID ragep2ptypes.PeerID // - msg []byte func (_e *Peer_Expecter) Send(peerID interface{}, msg interface{}) *Peer_Send_Call { return &Peer_Send_Call{Call: _e.mock.On("Send", peerID, msg)} } -func (_c *Peer_Send_Call) Run(run func(peerID types.PeerID, msg []byte)) *Peer_Send_Call { +func (_c *Peer_Send_Call) Run(run func(peerID ragep2ptypes.PeerID, msg []byte)) *Peer_Send_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.PeerID), args[1].([]byte)) + run(args[0].(ragep2ptypes.PeerID), args[1].([]byte)) }) return _c } @@ -340,7 +342,7 @@ func (_c *Peer_Send_Call) Return(_a0 error) *Peer_Send_Call { return _c } -func (_c *Peer_Send_Call) RunAndReturn(run func(types.PeerID, []byte) error) *Peer_Send_Call { +func (_c *Peer_Send_Call) RunAndReturn(run func(ragep2ptypes.PeerID, []byte) error) *Peer_Send_Call { _c.Call.Return(run) return _c } @@ -392,7 +394,7 @@ func (_c *Peer_Start_Call) RunAndReturn(run func(context.Context) error) *Peer_S } // UpdateConnections provides a mock function with given fields: peers -func (_m *Peer) UpdateConnections(peers map[types.PeerID]types.StreamConfig) error { +func (_m *Peer) UpdateConnections(peers map[ragep2ptypes.PeerID]types.StreamConfig) error { ret := _m.Called(peers) if len(ret) == 0 { @@ -400,7 +402,7 @@ func (_m *Peer) UpdateConnections(peers map[types.PeerID]types.StreamConfig) err } var r0 error - if rf, ok := ret.Get(0).(func(map[types.PeerID]types.StreamConfig) error); ok { + if rf, ok := ret.Get(0).(func(map[ragep2ptypes.PeerID]types.StreamConfig) error); ok { r0 = rf(peers) } else { r0 = ret.Error(0) @@ -415,14 +417,14 @@ type Peer_UpdateConnections_Call struct { } // UpdateConnections is a helper method to define mock.On call -// - peers map[types.PeerID]types.StreamConfig +// - peers map[ragep2ptypes.PeerID]types.StreamConfig func (_e *Peer_Expecter) UpdateConnections(peers interface{}) *Peer_UpdateConnections_Call { return &Peer_UpdateConnections_Call{Call: _e.mock.On("UpdateConnections", peers)} } -func (_c *Peer_UpdateConnections_Call) Run(run func(peers map[types.PeerID]types.StreamConfig)) *Peer_UpdateConnections_Call { +func (_c *Peer_UpdateConnections_Call) Run(run func(peers map[ragep2ptypes.PeerID]types.StreamConfig)) *Peer_UpdateConnections_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(map[types.PeerID]types.StreamConfig)) + run(args[0].(map[ragep2ptypes.PeerID]types.StreamConfig)) }) return _c } @@ -432,7 +434,7 @@ func (_c *Peer_UpdateConnections_Call) Return(_a0 error) *Peer_UpdateConnections return _c } -func (_c *Peer_UpdateConnections_Call) RunAndReturn(run func(map[types.PeerID]types.StreamConfig) error) *Peer_UpdateConnections_Call { +func (_c *Peer_UpdateConnections_Call) RunAndReturn(run func(map[ragep2ptypes.PeerID]types.StreamConfig) error) *Peer_UpdateConnections_Call { _c.Call.Return(run) return _c } diff --git a/core/services/p2p/types/mocks/peer_wrapper.go b/core/services/p2p/types/mocks/peer_wrapper.go index 7d1744cb0c5..98ebff5f618 100644 --- a/core/services/p2p/types/mocks/peer_wrapper.go +++ b/core/services/p2p/types/mocks/peer_wrapper.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -22,7 +22,7 @@ func (_m *PeerWrapper) EXPECT() *PeerWrapper_Expecter { return &PeerWrapper_Expecter{mock: &_m.Mock} } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *PeerWrapper) Close() error { ret := _m.Called() @@ -67,7 +67,7 @@ func (_c *PeerWrapper_Close_Call) RunAndReturn(run func() error) *PeerWrapper_Cl return _c } -// GetPeer provides a mock function with given fields: +// GetPeer provides a mock function with no fields func (_m *PeerWrapper) GetPeer() types.Peer { ret := _m.Called() @@ -114,7 +114,7 @@ func (_c *PeerWrapper_GetPeer_Call) RunAndReturn(run func() types.Peer) *PeerWra return _c } -// HealthReport provides a mock function with given fields: +// HealthReport provides a mock function with no fields func (_m *PeerWrapper) HealthReport() map[string]error { ret := _m.Called() @@ -161,7 +161,7 @@ func (_c *PeerWrapper_HealthReport_Call) RunAndReturn(run func() map[string]erro return _c } -// Name provides a mock function with given fields: +// Name provides a mock function with no fields func (_m *PeerWrapper) Name() string { ret := _m.Called() @@ -206,7 +206,7 @@ func (_c *PeerWrapper_Name_Call) RunAndReturn(run func() string) *PeerWrapper_Na return _c } -// Ready provides a mock function with given fields: +// Ready provides a mock function with no fields func (_m *PeerWrapper) Ready() error { ret := _m.Called() diff --git a/core/services/p2p/types/mocks/signer.go b/core/services/p2p/types/mocks/signer.go index 57afac0cecc..d027fca471a 100644 --- a/core/services/p2p/types/mocks/signer.go +++ b/core/services/p2p/types/mocks/signer.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/pipeline/common.go b/core/services/pipeline/common.go index 50611ee32a4..56af199078a 100644 --- a/core/services/pipeline/common.go +++ b/core/services/pipeline/common.go @@ -61,6 +61,7 @@ type ( TaskMinBackoff() time.Duration TaskMaxBackoff() time.Duration TaskTags() string + TaskStreamID() *uint32 GetDescendantTasks() []Task } diff --git a/core/services/pipeline/mocks/config.go b/core/services/pipeline/mocks/config.go index 87bf48047bf..f5c6a11b1d7 100644 --- a/core/services/pipeline/mocks/config.go +++ b/core/services/pipeline/mocks/config.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -22,7 +22,7 @@ func (_m *Config) EXPECT() *Config_Expecter { return &Config_Expecter{mock: &_m.Mock} } -// DefaultHTTPLimit provides a mock function with given fields: +// DefaultHTTPLimit provides a mock function with no fields func (_m *Config) DefaultHTTPLimit() int64 { ret := _m.Called() @@ -67,7 +67,7 @@ func (_c *Config_DefaultHTTPLimit_Call) RunAndReturn(run func() int64) *Config_D return _c } -// DefaultHTTPTimeout provides a mock function with given fields: +// DefaultHTTPTimeout provides a mock function with no fields func (_m *Config) DefaultHTTPTimeout() config.Duration { ret := _m.Called() @@ -112,7 +112,7 @@ func (_c *Config_DefaultHTTPTimeout_Call) RunAndReturn(run func() config.Duratio return _c } -// MaxRunDuration provides a mock function with given fields: +// MaxRunDuration provides a mock function with no fields func (_m *Config) MaxRunDuration() time.Duration { ret := _m.Called() @@ -157,7 +157,7 @@ func (_c *Config_MaxRunDuration_Call) RunAndReturn(run func() time.Duration) *Co return _c } -// ReaperInterval provides a mock function with given fields: +// ReaperInterval provides a mock function with no fields func (_m *Config) ReaperInterval() time.Duration { ret := _m.Called() @@ -202,7 +202,7 @@ func (_c *Config_ReaperInterval_Call) RunAndReturn(run func() time.Duration) *Co return _c } -// ReaperThreshold provides a mock function with given fields: +// ReaperThreshold provides a mock function with no fields func (_m *Config) ReaperThreshold() time.Duration { ret := _m.Called() @@ -247,7 +247,7 @@ func (_c *Config_ReaperThreshold_Call) RunAndReturn(run func() time.Duration) *C return _c } -// VerboseLogging provides a mock function with given fields: +// VerboseLogging provides a mock function with no fields func (_m *Config) VerboseLogging() bool { ret := _m.Called() diff --git a/core/services/pipeline/mocks/orm.go b/core/services/pipeline/mocks/orm.go index d79825fcf10..7c13aac4c9e 100644 --- a/core/services/pipeline/mocks/orm.go +++ b/core/services/pipeline/mocks/orm.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -30,7 +30,7 @@ func (_m *ORM) EXPECT() *ORM_Expecter { return &ORM_Expecter{mock: &_m.Mock} } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *ORM) Close() error { ret := _m.Called() @@ -180,7 +180,7 @@ func (_c *ORM_CreateSpec_Call) RunAndReturn(run func(context.Context, pipeline.P return _c } -// DataSource provides a mock function with given fields: +// DataSource provides a mock function with no fields func (_m *ORM) DataSource() sqlutil.DataSource { ret := _m.Called() @@ -484,7 +484,7 @@ func (_c *ORM_GetUnfinishedRuns_Call) RunAndReturn(run func(context.Context, tim return _c } -// HealthReport provides a mock function with given fields: +// HealthReport provides a mock function with no fields func (_m *ORM) HealthReport() map[string]error { ret := _m.Called() @@ -722,7 +722,7 @@ func (_c *ORM_InsertRun_Call) RunAndReturn(run func(context.Context, *pipeline.R return _c } -// Name provides a mock function with given fields: +// Name provides a mock function with no fields func (_m *ORM) Name() string { ret := _m.Called() @@ -767,7 +767,7 @@ func (_c *ORM_Name_Call) RunAndReturn(run func() string) *ORM_Name_Call { return _c } -// Ready provides a mock function with given fields: +// Ready provides a mock function with no fields func (_m *ORM) Ready() error { ret := _m.Called() diff --git a/core/services/pipeline/mocks/pipeline_param_unmarshaler.go b/core/services/pipeline/mocks/pipeline_param_unmarshaler.go index 3ca0dd54666..cb997d57081 100644 --- a/core/services/pipeline/mocks/pipeline_param_unmarshaler.go +++ b/core/services/pipeline/mocks/pipeline_param_unmarshaler.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/pipeline/mocks/runner.go b/core/services/pipeline/mocks/runner.go index 7a59569989a..9779d47d70d 100644 --- a/core/services/pipeline/mocks/runner.go +++ b/core/services/pipeline/mocks/runner.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -26,7 +26,7 @@ func (_m *Runner) EXPECT() *Runner_Expecter { return &Runner_Expecter{mock: &_m.Mock} } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *Runner) Close() error { ret := _m.Called() @@ -208,7 +208,7 @@ func (_c *Runner_ExecuteRun_Call) RunAndReturn(run func(context.Context, pipelin return _c } -// HealthReport provides a mock function with given fields: +// HealthReport provides a mock function with no fields func (_m *Runner) HealthReport() map[string]error { ret := _m.Called() @@ -411,7 +411,7 @@ func (_c *Runner_InsertFinishedRuns_Call) RunAndReturn(run func(context.Context, return _c } -// Name provides a mock function with given fields: +// Name provides a mock function with no fields func (_m *Runner) Name() string { ret := _m.Called() @@ -485,11 +485,11 @@ func (_c *Runner_OnRunFinished_Call) Return() *Runner_OnRunFinished_Call { } func (_c *Runner_OnRunFinished_Call) RunAndReturn(run func(func(*pipeline.Run))) *Runner_OnRunFinished_Call { - _c.Call.Return(run) + _c.Run(run) return _c } -// Ready provides a mock function with given fields: +// Ready provides a mock function with no fields func (_m *Runner) Ready() error { ret := _m.Called() diff --git a/core/services/pipeline/runner.go b/core/services/pipeline/runner.go index 2194cb8be46..30c7842914d 100644 --- a/core/services/pipeline/runner.go +++ b/core/services/pipeline/runner.go @@ -377,7 +377,9 @@ func (r *runner) InitializePipeline(spec Spec) (pipeline *Pipeline, err error) { func (r *runner) run(ctx context.Context, pipeline *Pipeline, run *Run, vars Vars) TaskRunResults { l := r.lggr.With("run.ID", run.ID, "executionID", uuid.New(), "specID", run.PipelineSpecID, "jobID", run.PipelineSpec.JobID, "jobName", run.PipelineSpec.JobName) - l.Debug("Initiating tasks for pipeline run of spec") + if r.config.VerboseLogging() { + l.Debug("Initiating tasks for pipeline run of spec") + } scheduler := newScheduler(pipeline, run, vars, l) go scheduler.Run() diff --git a/core/services/pipeline/task.base.go b/core/services/pipeline/task.base.go index 3e1db5fcdb5..fdedb69193e 100644 --- a/core/services/pipeline/task.base.go +++ b/core/services/pipeline/task.base.go @@ -24,6 +24,8 @@ type BaseTask struct { Tags string `mapstructure:"tags" json:"-"` + StreamID null.Uint32 `mapstructure:"streamID"` + uuid uuid.UUID } @@ -84,6 +86,13 @@ func (t BaseTask) TaskTags() string { return t.Tags } +func (t BaseTask) TaskStreamID() *uint32 { + if t.StreamID.Valid { + return &t.StreamID.Uint32 + } + return nil +} + // GetDescendantTasks retrieves all descendant tasks of a given task func (t BaseTask) GetDescendantTasks() []Task { if len(t.outputs) == 0 { diff --git a/core/services/registrysyncer/local_registry.go b/core/services/registrysyncer/local_registry.go index 5bec59412f4..3ac8927c028 100644 --- a/core/services/registrysyncer/local_registry.go +++ b/core/services/registrysyncer/local_registry.go @@ -7,7 +7,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/capabilities" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/logger" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" ) diff --git a/core/services/registrysyncer/mocks/orm.go b/core/services/registrysyncer/mocks/orm.go index 7fb44286a16..419fe9ae564 100644 --- a/core/services/registrysyncer/mocks/orm.go +++ b/core/services/registrysyncer/mocks/orm.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/registrysyncer/orm.go b/core/services/registrysyncer/orm.go index 9c666200752..7992f45413a 100644 --- a/core/services/registrysyncer/orm.go +++ b/core/services/registrysyncer/orm.go @@ -9,7 +9,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/logger" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" ) diff --git a/core/services/registrysyncer/orm_test.go b/core/services/registrysyncer/orm_test.go index 429bfff664b..b527f1ad8d7 100644 --- a/core/services/registrysyncer/orm_test.go +++ b/core/services/registrysyncer/orm_test.go @@ -17,7 +17,7 @@ import ( capabilitiespb "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" "github.com/smartcontractkit/chainlink-common/pkg/values" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" diff --git a/core/services/registrysyncer/syncer.go b/core/services/registrysyncer/syncer.go index 461824b403b..02797b42dd2 100644 --- a/core/services/registrysyncer/syncer.go +++ b/core/services/registrysyncer/syncer.go @@ -13,7 +13,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/logger" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" evmrelaytypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" @@ -76,7 +76,6 @@ func New( registryAddress string, orm ORM, ) (RegistrySyncer, error) { - metricLabeler, err := newSyncerMetricLabeler() if err != nil { return nil, fmt.Errorf("failed to create syncer metric labeler: %w", err) diff --git a/core/services/registrysyncer/syncer_test.go b/core/services/registrysyncer/syncer_test.go index e4a1dce476c..33920c36a55 100644 --- a/core/services/registrysyncer/syncer_test.go +++ b/core/services/registrysyncer/syncer_test.go @@ -31,7 +31,7 @@ import ( evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" diff --git a/core/services/relay/evm/capabilities/log_event_trigger_test.go b/core/services/relay/evm/capabilities/log_event_trigger_test.go index d248dbdc87f..c74f171a6c6 100644 --- a/core/services/relay/evm/capabilities/log_event_trigger_test.go +++ b/core/services/relay/evm/capabilities/log_event_trigger_test.go @@ -3,7 +3,6 @@ package logevent_test import ( "math/big" "testing" - "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" @@ -13,6 +12,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" commonmocks "github.com/smartcontractkit/chainlink-common/pkg/types/core/mocks" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink/v2/core/capabilities/triggers/logevent" coretestutils "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/capabilities/testutils" @@ -135,7 +135,7 @@ func emitLogTxnAndWaitForLog(t *testing.T, for _, expectedLogVal := range expectedLogVals { // Wait for logs with a timeout - _, output, err := testutils.WaitForLog(th.BackendTH.Lggr, log1Ch, 15*time.Second) + _, output, err := testutils.WaitForLog(th.BackendTH.Lggr, log1Ch, tests.WaitTimeout(t)) require.NoError(t, err) th.BackendTH.Lggr.Infow("EmitLog", "output", output) diff --git a/core/services/relay/evm/capabilities/testutils/chain_reader.go b/core/services/relay/evm/capabilities/testutils/chain_reader.go index 64fbf5fe720..07e0f3e05ac 100644 --- a/core/services/relay/evm/capabilities/testutils/chain_reader.go +++ b/core/services/relay/evm/capabilities/testutils/chain_reader.go @@ -14,7 +14,7 @@ import ( commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" commonvalues "github.com/smartcontractkit/chainlink-common/pkg/values" "github.com/smartcontractkit/chainlink/v2/core/capabilities/triggers/logevent/logeventcap" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/log_emitter" coretestutils "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" evmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" diff --git a/core/services/relay/evm/capabilities/workflows/syncer/workflow_syncer_test.go b/core/services/relay/evm/capabilities/workflows/syncer/workflow_syncer_test.go index c7c164803cb..aa2ef2c167c 100644 --- a/core/services/relay/evm/capabilities/workflows/syncer/workflow_syncer_test.go +++ b/core/services/relay/evm/capabilities/workflows/syncer/workflow_syncer_test.go @@ -22,6 +22,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink-common/pkg/workflows" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/workflow/generated/workflow_registry_wrapper" coretestutils "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -119,15 +120,13 @@ func Test_EventHandlerStateSync(t *testing.T) { DonID: donID, Status: uint8(1), SecretsURL: "someurl", + BinaryURL: "someurl", } workflow.ID = workflowID registerWorkflow(t, backendTH, wfRegistryC, workflow) } testEventHandler := newTestEvtHandler() - loader := syncer.NewWorkflowRegistryContractLoader(lggr, wfRegistryAddr.Hex(), func(ctx context.Context, bytes []byte) (syncer.ContractReader, error) { - return backendTH.NewContractReader(ctx, t, bytes) - }, testEventHandler) // Create the registry registry := syncer.NewWorkflowRegistry( @@ -140,7 +139,6 @@ func Test_EventHandlerStateSync(t *testing.T) { QueryCount: 20, }, testEventHandler, - loader, &testDonNotifier{ don: capabilities.DON{ ID: donID, @@ -155,7 +153,7 @@ func Test_EventHandlerStateSync(t *testing.T) { require.Eventually(t, func() bool { numEvents := len(testEventHandler.GetEvents()) return numEvents == numberWorkflows - }, 5*time.Second, time.Second) + }, tests.WaitTimeout(t), time.Second) for _, event := range testEventHandler.GetEvents() { assert.Equal(t, syncer.WorkflowRegisteredEvent, event.GetEventType()) @@ -174,6 +172,7 @@ func Test_EventHandlerStateSync(t *testing.T) { DonID: donID, Status: uint8(1), SecretsURL: "", + BinaryURL: "someurl", } workflow.ID = workflowID @@ -220,7 +219,7 @@ func Test_EventHandlerStateSync(t *testing.T) { } return false - }, 50*time.Second, time.Second) + }, tests.WaitTimeout(t), time.Second) } func Test_InitialStateSync(t *testing.T) { @@ -249,15 +248,13 @@ func Test_InitialStateSync(t *testing.T) { DonID: donID, Status: uint8(1), SecretsURL: "someurl", + BinaryURL: "someurl", } workflow.ID = workflowID registerWorkflow(t, backendTH, wfRegistryC, workflow) } testEventHandler := newTestEvtHandler() - loader := syncer.NewWorkflowRegistryContractLoader(lggr, wfRegistryAddr.Hex(), func(ctx context.Context, bytes []byte) (syncer.ContractReader, error) { - return backendTH.NewContractReader(ctx, t, bytes) - }, testEventHandler) // Create the worker worker := syncer.NewWorkflowRegistry( @@ -270,7 +267,6 @@ func Test_InitialStateSync(t *testing.T) { QueryCount: 20, }, testEventHandler, - loader, &testDonNotifier{ don: capabilities.DON{ ID: donID, @@ -284,7 +280,7 @@ func Test_InitialStateSync(t *testing.T) { require.Eventually(t, func() bool { return len(testEventHandler.GetEvents()) == numberWorkflows - }, 5*time.Second, time.Second) + }, tests.WaitTimeout(t), time.Second) for _, event := range testEventHandler.GetEvents() { assert.Equal(t, syncer.WorkflowRegisteredEvent, event.GetEventType()) @@ -308,6 +304,7 @@ func Test_SecretsWorker(t *testing.T) { DonID: donID, Status: uint8(1), SecretsURL: giveSecretsURL, + BinaryURL: "someurl", } giveContents = "contents" wantContents = "updated contents" @@ -346,8 +343,11 @@ func Test_SecretsWorker(t *testing.T) { require.NoError(t, err) require.Equal(t, contents, giveContents) - handler := syncer.NewEventHandler(lggr, orm, fetcherFn, nil, nil, - emitter, clockwork.NewFakeClock(), workflowkey.Key{}) + handler := &testSecretsWorkEventHandler{ + wrappedHandler: syncer.NewEventHandler(lggr, orm, fetcherFn, nil, nil, + emitter, clockwork.NewFakeClock(), workflowkey.Key{}), + registeredCh: make(chan syncer.Event, 1), + } worker := syncer.NewWorkflowRegistry( lggr, @@ -357,7 +357,6 @@ func Test_SecretsWorker(t *testing.T) { wfRegistryAddr.Hex(), syncer.WorkflowEventPollerConfig{QueryCount: 20}, handler, - &testWorkflowRegistryContractLoader{}, &testDonNotifier{ don: capabilities.DON{ ID: donID, @@ -374,6 +373,9 @@ func Test_SecretsWorker(t *testing.T) { servicetest.Run(t, worker) + // wait for the workflow to be registered + <-handler.registeredCh + // generate a log event requestForceUpdateSecrets(t, backendTH, wfRegistryC, giveSecretsURL) @@ -383,7 +385,7 @@ func Test_SecretsWorker(t *testing.T) { lggr.Debugf("got secrets %v", secrets) require.NoError(t, err) return secrets == wantContents - }, 15*time.Second, time.Second) + }, tests.WaitTimeout(t), time.Second) } func Test_RegistrySyncer_WorkflowRegistered_InitiallyPaused(t *testing.T) { @@ -434,7 +436,6 @@ func Test_RegistrySyncer_WorkflowRegistered_InitiallyPaused(t *testing.T) { wfRegistryAddr.Hex(), syncer.WorkflowEventPollerConfig{QueryCount: 20}, handler, - &testWorkflowRegistryContractLoader{}, &testDonNotifier{ don: capabilities.DON{ ID: donID, @@ -463,7 +464,7 @@ func Test_RegistrySyncer_WorkflowRegistered_InitiallyPaused(t *testing.T) { owner := strings.ToLower(backendTH.ContractsOwner.From.Hex()[2:]) _, err := orm.GetWorkflowSpec(ctx, owner, "test-wf") return err == nil - }, 15*time.Second, time.Second) + }, tests.WaitTimeout(t), time.Second) } type mockService struct{} @@ -543,7 +544,6 @@ func Test_RegistrySyncer_WorkflowRegistered_InitiallyActivated(t *testing.T) { wfRegistryAddr.Hex(), syncer.WorkflowEventPollerConfig{QueryCount: 20}, handler, - &testWorkflowRegistryContractLoader{}, &testDonNotifier{ don: capabilities.DON{ ID: donID, @@ -572,7 +572,7 @@ func Test_RegistrySyncer_WorkflowRegistered_InitiallyActivated(t *testing.T) { owner := strings.ToLower(backendTH.ContractsOwner.From.Hex()[2:]) _, err = orm.GetWorkflowSpec(ctx, owner, "test-wf") return err == nil - }, 15*time.Second, time.Second) + }, tests.WaitTimeout(t), time.Second) } func updateAuthorizedAddress( @@ -708,3 +708,24 @@ func updateWorkflow( th.Backend.Commit() th.Backend.Commit() } + +type evtHandler interface { + Handle(ctx context.Context, event syncer.Event) error +} + +type testSecretsWorkEventHandler struct { + wrappedHandler evtHandler + registeredCh chan syncer.Event +} + +func (m *testSecretsWorkEventHandler) Handle(ctx context.Context, event syncer.Event) error { + switch { + case event.GetEventType() == syncer.ForceUpdateSecretsEvent: + return m.wrappedHandler.Handle(ctx, event) + case event.GetEventType() == syncer.WorkflowRegisteredEvent: + m.registeredCh <- event + return nil + default: + panic(fmt.Sprintf("unexpected event type: %v", event.GetEventType())) + } +} diff --git a/core/services/relay/evm/ccip.go b/core/services/relay/evm/ccip.go index a06f60c6fd4..9fc6ae8b1a0 100644 --- a/core/services/relay/evm/ccip.go +++ b/core/services/relay/evm/ccip.go @@ -15,6 +15,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" ccipconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/estimatorconfig" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/prices" ) @@ -24,16 +25,18 @@ var _ cciptypes.CommitStoreReader = (*IncompleteDestCommitStoreReader)(nil) // IncompleteSourceCommitStoreReader is an implementation of CommitStoreReader with the only valid methods being // GasPriceEstimator, ChangeConfig, and OffchainConfig type IncompleteSourceCommitStoreReader struct { - estimator gas.EvmFeeEstimator - gasPriceEstimator *prices.DAGasPriceEstimator - sourceMaxGasPrice *big.Int - offchainConfig cciptypes.CommitOffchainConfig + estimator gas.EvmFeeEstimator + gasPriceEstimator *prices.DAGasPriceEstimator + sourceMaxGasPrice *big.Int + offchainConfig cciptypes.CommitOffchainConfig + feeEstimatorConfig estimatorconfig.FeeEstimatorConfigProvider } -func NewIncompleteSourceCommitStoreReader(estimator gas.EvmFeeEstimator, sourceMaxGasPrice *big.Int) *IncompleteSourceCommitStoreReader { +func NewIncompleteSourceCommitStoreReader(estimator gas.EvmFeeEstimator, sourceMaxGasPrice *big.Int, feeEstimatorConfig estimatorconfig.FeeEstimatorConfigProvider) *IncompleteSourceCommitStoreReader { return &IncompleteSourceCommitStoreReader{ - estimator: estimator, - sourceMaxGasPrice: sourceMaxGasPrice, + estimator: estimator, + sourceMaxGasPrice: sourceMaxGasPrice, + feeEstimatorConfig: feeEstimatorConfig, } } @@ -53,6 +56,7 @@ func (i *IncompleteSourceCommitStoreReader) ChangeConfig(ctx context.Context, on i.sourceMaxGasPrice, int64(offchainConfigParsed.ExecGasPriceDeviationPPB), int64(offchainConfigParsed.DAGasPriceDeviationPPB), + i.feeEstimatorConfig, ) i.offchainConfig = ccip.NewCommitOffchainConfig( offchainConfigParsed.ExecGasPriceDeviationPPB, @@ -131,8 +135,16 @@ type IncompleteDestCommitStoreReader struct { cs cciptypes.CommitStoreReader } -func NewIncompleteDestCommitStoreReader(ctx context.Context, lggr logger.Logger, versionFinder ccip.VersionFinder, address cciptypes.Address, ec client.Client, lp logpoller.LogPoller) (*IncompleteDestCommitStoreReader, error) { - cs, err := ccip.NewCommitStoreReader(ctx, lggr, versionFinder, address, ec, lp) +func NewIncompleteDestCommitStoreReader( + ctx context.Context, + lggr logger.Logger, + versionFinder ccip.VersionFinder, + address cciptypes.Address, + ec client.Client, + lp logpoller.LogPoller, + feeEstimatorConfig estimatorconfig.FeeEstimatorConfigProvider, +) (*IncompleteDestCommitStoreReader, error) { + cs, err := ccip.NewCommitStoreReader(ctx, lggr, versionFinder, address, ec, lp, feeEstimatorConfig) if err != nil { return nil, err } diff --git a/core/services/relay/evm/chain_components_test.go b/core/services/relay/evm/chain_components_test.go index 1e8c47c51ec..006236c060a 100644 --- a/core/services/relay/evm/chain_components_test.go +++ b/core/services/relay/evm/chain_components_test.go @@ -9,6 +9,7 @@ import ( "math/big" "os" "strconv" + "sync" "testing" "time" @@ -27,11 +28,11 @@ import ( commontestutils "github.com/smartcontractkit/chainlink-common/pkg/loop/testutils" clcommontypes "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" htMocks "github.com/smartcontractkit/chainlink/v2/common/headtracker/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" lpMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" evmtxmgr "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" @@ -50,6 +51,7 @@ import ( ) const commonGasLimitOnEvms = uint64(4712388) +const finalityDepth = 4 func TestContractReaderEventsInitValidation(t *testing.T) { tests := []struct { @@ -228,17 +230,51 @@ func TestChainReader_HealthReport(t *testing.T) { } func TestChainComponents(t *testing.T) { - tests.SkipFlakey(t, "https://smartcontract-it.atlassian.net/browse/BCFR-1083") t.Parallel() - it := &EVMChainComponentsInterfaceTester[*testing.T]{Helper: &helper{}} - // TODO, generated binding tests are broken - it.DisableTests([]string{interfacetests.ContractReaderGetLatestValue}) - it.Init(t) - + // shared helper so all tests can run efficiently in parallel + helper := &helper{} + helper.Init(t) + deployLock := sync.Mutex{} // add new subtests here so that it can be run on real chains too - RunChainComponentsEvmTests(t, it) - RunChainComponentsInLoopEvmTests[*testing.T](t, commontestutils.WrapContractReaderTesterForLoop(it)) - RunChainComponentsInLoopEvmTests(t, WrapContractReaderTesterWithBindings(t, it)) + t.Run("RunChainComponentsEvmTests", func(t *testing.T) { + t.Parallel() + it := &EVMChainComponentsInterfaceTester[*testing.T]{Helper: helper, DeployLock: &deployLock} + // These tests are broken in develop as well, so disable them for now + it.DisableTests([]string{ + interfacetests.ContractReaderQueryKeysReturnsDataTwoEventTypes, + interfacetests.ContractReaderQueryKeysReturnsDataAsValuesDotValue, + interfacetests.ContractReaderQueryKeysCanFilterWithValueComparator, + }) + it.Setup(t) + + RunChainComponentsEvmTests(t, it) + }) + + t.Run("RunChainComponentsInLoopEvmTests", func(t *testing.T) { + t.Parallel() + it := &EVMChainComponentsInterfaceTester[*testing.T]{Helper: helper, DeployLock: &deployLock} + wrapped := commontestutils.WrapContractReaderTesterForLoop(it) + // These tests are broken in develop as well, so disable them for now + wrapped.DisableTests([]string{ + interfacetests.ContractReaderQueryKeysReturnsDataTwoEventTypes, + interfacetests.ContractReaderQueryKeysReturnsDataAsValuesDotValue, + interfacetests.ContractReaderQueryKeysCanFilterWithValueComparator, + }) + wrapped.Setup(t) + + RunChainComponentsInLoopEvmTests[*testing.T](t, wrapped, true) + }) + + t.Run("RunChainComponentsInLoopEvmTestsWithBindings", func(t *testing.T) { + t.Parallel() + it := &EVMChainComponentsInterfaceTester[*testing.T]{Helper: helper, DeployLock: &deployLock} + wrapped := WrapContractReaderTesterWithBindings(t, it) + // TODO, generated binding tests are broken + wrapped.DisableTests([]string{interfacetests.ContractReaderGetLatestValue}) + wrapped.Setup(t) + // generated tests are not compatible with parallel running atm + RunChainComponentsInLoopEvmTests(t, wrapped, false) + }) } type helper struct { @@ -249,6 +285,40 @@ type helper struct { txm evmtxmgr.TxManager client client.Client db *sqlx.DB + lp logpoller.LogPoller + ht logpoller.HeadTracker +} + +func getLPOpts() logpoller.Opts { + return logpoller.Opts{ + PollPeriod: time.Millisecond, + FinalityDepth: finalityDepth, + BackfillBatchSize: 1, + RpcBatchSize: 1, + KeepFinalizedBlocksDepth: 10000, + } +} + +func (h *helper) LogPoller(t *testing.T) logpoller.LogPoller { + if h.lp != nil { + return h.lp + } + ctx := testutils.Context(t) + lggr := logger.NullLogger + db := h.Database() + + h.lp = logpoller.NewLogPoller(logpoller.NewORM(h.ChainID(), db, lggr), h.Client(t), lggr, h.HeadTracker(t), getLPOpts()) + require.NoError(t, h.lp.Start(ctx)) + return h.lp +} + +func (h *helper) HeadTracker(t *testing.T) logpoller.HeadTracker { + if h.ht != nil { + return h.ht + } + lpOpts := getLPOpts() + h.ht = headtracker.NewSimulatedHeadTracker(h.Client(t), lpOpts.UseFinalityTag, lpOpts.FinalityDepth) + return h.ht } func (h *helper) Init(t *testing.T) { @@ -260,6 +330,7 @@ func (h *helper) Init(t *testing.T) { h.Backend() h.client = h.Client(t) + h.LogPoller(t) h.txm = h.TXM(t, h.client) } @@ -320,6 +391,10 @@ func (h *helper) ChainID() *big.Int { return testutils.SimulatedChainID } +func (h *helper) Database() *sqlx.DB { + return h.db +} + func (h *helper) NewSqlxDB(t *testing.T) *sqlx.DB { return pgtest.NewSqlxDB(t) } diff --git a/core/services/relay/evm/codec/codec_test.go b/core/services/relay/evm/codec/codec_test.go index 66fc45a3037..ae75fff6eb6 100644 --- a/core/services/relay/evm/codec/codec_test.go +++ b/core/services/relay/evm/codec/codec_test.go @@ -19,7 +19,7 @@ import ( looptestutils "github.com/smartcontractkit/chainlink-common/pkg/loop/testutils" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/chain_reader_tester" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/chain_reader_tester" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/codec" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" diff --git a/core/services/relay/evm/codec/encoder.go b/core/services/relay/evm/codec/encoder.go index 18ad32831c2..47671520bf5 100644 --- a/core/services/relay/evm/codec/encoder.go +++ b/core/services/relay/evm/codec/encoder.go @@ -21,7 +21,7 @@ func (e *encoder) Encode(_ context.Context, item any, itemType string) (res []by defer func() { if r := recover(); r != nil { res = nil - err = fmt.Errorf("%w: cannot encode type", commontypes.ErrInvalidType) + err = fmt.Errorf("%w: cannot encode type; %v", commontypes.ErrInvalidType, r) } }() info, ok := e.Definitions[itemType] diff --git a/core/services/relay/evm/commit_provider.go b/core/services/relay/evm/commit_provider.go index 1a9260120f3..6be639674e2 100644 --- a/core/services/relay/evm/commit_provider.go +++ b/core/services/relay/evm/commit_provider.go @@ -14,24 +14,25 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" - "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/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/estimatorconfig" ) var _ commontypes.CCIPCommitProvider = (*SrcCommitProvider)(nil) var _ commontypes.CCIPCommitProvider = (*DstCommitProvider)(nil) type SrcCommitProvider struct { - lggr logger.Logger - startBlock uint64 - client client.Client - lp logpoller.LogPoller - estimator gas.EvmFeeEstimator - maxGasPrice *big.Int + lggr logger.Logger + startBlock uint64 + client client.Client + lp logpoller.LogPoller + estimator gas.EvmFeeEstimator + maxGasPrice *big.Int + feeEstimatorConfig estimatorconfig.FeeEstimatorConfigProvider // these values will be lazily initialized seenOnRampAddress *cciptypes.Address @@ -46,14 +47,16 @@ func NewSrcCommitProvider( lp logpoller.LogPoller, srcEstimator gas.EvmFeeEstimator, maxGasPrice *big.Int, + feeEstimatorConfig estimatorconfig.FeeEstimatorConfigProvider, ) commontypes.CCIPCommitProvider { return &SrcCommitProvider{ - lggr: logger.Named(lggr, "SrcCommitProvider"), - startBlock: startBlock, - client: client, - lp: lp, - estimator: srcEstimator, - maxGasPrice: maxGasPrice, + lggr: logger.Named(lggr, "SrcCommitProvider"), + startBlock: startBlock, + client: client, + lp: lp, + estimator: srcEstimator, + maxGasPrice: maxGasPrice, + feeEstimatorConfig: feeEstimatorConfig, } } @@ -67,6 +70,7 @@ type DstCommitProvider struct { configWatcher *configWatcher gasEstimator gas.EvmFeeEstimator maxGasPrice big.Int + feeEstimatorConfig estimatorconfig.FeeEstimatorConfigProvider // these values will be lazily initialized seenCommitStoreAddress *cciptypes.Address @@ -83,6 +87,7 @@ func NewDstCommitProvider( maxGasPrice big.Int, contractTransmitter contractTransmitter, configWatcher *configWatcher, + feeEstimatorConfig estimatorconfig.FeeEstimatorConfigProvider, ) commontypes.CCIPCommitProvider { return &DstCommitProvider{ lggr: logger.Named(lggr, "DstCommitProvider"), @@ -94,6 +99,7 @@ func NewDstCommitProvider( configWatcher: configWatcher, gasEstimator: gasEstimator, maxGasPrice: maxGasPrice, + feeEstimatorConfig: feeEstimatorConfig, } } @@ -173,13 +179,13 @@ func (p *DstCommitProvider) Close() error { if p.seenCommitStoreAddress == nil { return nil } - return ccip.CloseCommitStoreReader(ctx, p.lggr, versionFinder, *p.seenCommitStoreAddress, p.client, p.lp) + return ccip.CloseCommitStoreReader(ctx, p.lggr, versionFinder, *p.seenCommitStoreAddress, p.client, p.lp, p.feeEstimatorConfig) }) unregisterFuncs = append(unregisterFuncs, func(ctx context.Context) error { if p.seenOffRampAddress == nil { return nil } - return ccip.CloseOffRampReader(ctx, p.lggr, versionFinder, *p.seenOffRampAddress, p.client, p.lp, nil, big.NewInt(0)) + return ccip.CloseOffRampReader(ctx, p.lggr, versionFinder, *p.seenOffRampAddress, p.client, p.lp, nil, big.NewInt(0), p.feeEstimatorConfig) }) var multiErr error @@ -225,7 +231,7 @@ func (p *SrcCommitProvider) Start(ctx context.Context) error { if p.startBlock > math.MaxInt64 { return fmt.Errorf("start block overflows int64: %d", p.startBlock) } - return p.lp.Replay(ctx, int64(p.startBlock)) //nolint:gosec // G115 false positive + return p.lp.Replay(ctx, int64(p.startBlock)) } return nil } @@ -236,7 +242,7 @@ func (p *DstCommitProvider) Start(ctx context.Context) error { if p.startBlock > math.MaxInt64 { return fmt.Errorf("start block overflows int64: %d", p.startBlock) } - return p.lp.Replay(ctx, int64(p.startBlock)) //nolint:gosec // G115 false positive + return p.lp.Replay(ctx, int64(p.startBlock)) } return nil } @@ -250,7 +256,7 @@ func (p *DstCommitProvider) NewPriceGetter(ctx context.Context) (priceGetter cci } func (p *SrcCommitProvider) NewCommitStoreReader(ctx context.Context, commitStoreAddress cciptypes.Address) (commitStoreReader cciptypes.CommitStoreReader, err error) { - commitStoreReader = NewIncompleteSourceCommitStoreReader(p.estimator, p.maxGasPrice) + commitStoreReader = NewIncompleteSourceCommitStoreReader(p.estimator, p.maxGasPrice, p.feeEstimatorConfig) return } @@ -258,7 +264,7 @@ func (p *DstCommitProvider) NewCommitStoreReader(ctx context.Context, commitStor p.seenCommitStoreAddress = &commitStoreAddress versionFinder := ccip.NewEvmVersionFinder() - commitStoreReader, err = NewIncompleteDestCommitStoreReader(ctx, p.lggr, versionFinder, commitStoreAddress, p.client, p.lp) + commitStoreReader, err = NewIncompleteDestCommitStoreReader(ctx, p.lggr, versionFinder, commitStoreAddress, p.client, p.lp, p.feeEstimatorConfig) return } @@ -268,7 +274,12 @@ func (p *SrcCommitProvider) NewOnRampReader(ctx context.Context, onRampAddress c p.seenDestChainSelector = &destChainSelector versionFinder := ccip.NewEvmVersionFinder() + onRampReader, err = ccip.NewOnRampReader(ctx, p.lggr, versionFinder, sourceChainSelector, destChainSelector, onRampAddress, p.lp, p.client) + if err != nil { + return nil, err + } + p.feeEstimatorConfig.SetOnRampReader(onRampReader) return } @@ -281,7 +292,7 @@ func (p *SrcCommitProvider) NewOffRampReader(ctx context.Context, offRampAddr cc } func (p *DstCommitProvider) NewOffRampReader(ctx context.Context, offRampAddr cciptypes.Address) (offRampReader cciptypes.OffRampReader, err error) { - offRampReader, err = ccip.NewOffRampReader(ctx, p.lggr, p.versionFinder, offRampAddr, p.client, p.lp, p.gasEstimator, &p.maxGasPrice, true) + offRampReader, err = ccip.NewOffRampReader(ctx, p.lggr, p.versionFinder, offRampAddr, p.client, p.lp, p.gasEstimator, &p.maxGasPrice, true, p.feeEstimatorConfig) return } diff --git a/core/services/relay/evm/contract_transmitter.go b/core/services/relay/evm/contract_transmitter.go index aead9f6ca8a..248968ec053 100644 --- a/core/services/relay/evm/contract_transmitter.go +++ b/core/services/relay/evm/contract_transmitter.go @@ -34,6 +34,8 @@ var _ ContractTransmitter = &contractTransmitter{} type Transmitter interface { CreateEthTransaction(ctx context.Context, toAddress gethcommon.Address, payload []byte, txMeta *txmgr.TxMeta) error FromAddress(context.Context) gethcommon.Address + + CreateSecondaryEthTransaction(ctx context.Context, payload []byte, txMeta *txmgr.TxMeta) error } type ReportToEthMetadata func([]byte) (*txmgr.TxMeta, error) @@ -42,28 +44,35 @@ func reportToEvmTxMetaNoop([]byte) (*txmgr.TxMeta, error) { return nil, nil } -type OCRTransmitterOption func(transmitter *contractTransmitter) +type transmitterOps struct { + reportToEvmTxMeta ReportToEthMetadata + excludeSigs bool + retention time.Duration + maxLogsKept uint64 +} + +type OCRTransmitterOption func(transmitter *transmitterOps) func WithExcludeSignatures() OCRTransmitterOption { - return func(ct *contractTransmitter) { + return func(ct *transmitterOps) { ct.excludeSigs = true } } func WithRetention(retention time.Duration) OCRTransmitterOption { - return func(ct *contractTransmitter) { + return func(ct *transmitterOps) { ct.retention = retention } } func WithMaxLogsKept(maxLogsKept uint64) OCRTransmitterOption { - return func(ct *contractTransmitter) { + return func(ct *transmitterOps) { ct.maxLogsKept = maxLogsKept } } func WithReportToEthMetadata(reportToEvmTxMeta ReportToEthMetadata) OCRTransmitterOption { - return func(ct *contractTransmitter) { + return func(ct *transmitterOps) { if reportToEvmTxMeta != nil { ct.reportToEvmTxMeta = reportToEvmTxMeta } @@ -79,10 +88,7 @@ type contractTransmitter struct { lp logpoller.LogPoller lggr logger.Logger // Options - reportToEvmTxMeta ReportToEthMetadata - excludeSigs bool - retention time.Duration - maxLogsKept uint64 + transmitterOptions *transmitterOps } func transmitterFilterName(addr common.Address) string { @@ -112,17 +118,19 @@ func NewOCRContractTransmitter( lp: lp, contractReader: caller, lggr: logger.Named(lggr, "OCRContractTransmitter"), - reportToEvmTxMeta: reportToEvmTxMetaNoop, - excludeSigs: false, - retention: 0, - maxLogsKept: 0, + transmitterOptions: &transmitterOps{ + reportToEvmTxMeta: reportToEvmTxMetaNoop, + excludeSigs: false, + retention: 0, + maxLogsKept: 0, + }, } for _, opt := range opts { - opt(newContractTransmitter) + opt(newContractTransmitter.transmitterOptions) } - err := lp.RegisterFilter(ctx, logpoller.Filter{Name: transmitterFilterName(address), EventSigs: []common.Hash{transmitted.ID}, Addresses: []common.Address{address}, Retention: newContractTransmitter.retention, MaxLogsKept: newContractTransmitter.maxLogsKept}) + err := lp.RegisterFilter(ctx, logpoller.Filter{Name: transmitterFilterName(address), EventSigs: []common.Hash{transmitted.ID}, Addresses: []common.Address{address}, Retention: newContractTransmitter.transmitterOptions.retention, MaxLogsKept: newContractTransmitter.transmitterOptions.maxLogsKept}) if err != nil { return nil, err } @@ -142,7 +150,7 @@ func (oc *contractTransmitter) Transmit(ctx context.Context, reportCtx ocrtypes. if err != nil { panic("eventTransmit(ev): error in SplitSignature") } - if !oc.excludeSigs { + if !oc.transmitterOptions.excludeSigs { rs = append(rs, r) ss = append(ss, s) vs[i] = v @@ -150,7 +158,7 @@ func (oc *contractTransmitter) Transmit(ctx context.Context, reportCtx ocrtypes. } rawReportCtx := evmutil.RawReportContext(reportCtx) - txMeta, err := oc.reportToEvmTxMeta(report) + txMeta, err := oc.transmitterOptions.reportToEvmTxMeta(report) if err != nil { oc.lggr.Warnw("failed to generate tx metadata for report", "err", err) } @@ -163,6 +171,7 @@ func (oc *contractTransmitter) Transmit(ctx context.Context, reportCtx ocrtypes. } return errors.Wrap(oc.transmitter.CreateEthTransaction(ctx, oc.contractAddress, payload, txMeta), "failed to send Eth transaction") + } type contractReader interface { diff --git a/core/services/relay/evm/contract_transmitter_test.go b/core/services/relay/evm/contract_transmitter_test.go index 5b9e1ae5981..6106389f326 100644 --- a/core/services/relay/evm/contract_transmitter_test.go +++ b/core/services/relay/evm/contract_transmitter_test.go @@ -34,6 +34,10 @@ type mockTransmitter struct { lastPayload []byte } +func (m *mockTransmitter) CreateSecondaryEthTransaction(ctx context.Context, bytes []byte, meta *txmgr.TxMeta) error { + return nil +} + func (m *mockTransmitter) CreateEthTransaction(ctx context.Context, toAddress gethcommon.Address, payload []byte, _ *txmgr.TxMeta) error { m.lastPayload = payload return nil diff --git a/core/services/relay/evm/dual_contract_transmitter.go b/core/services/relay/evm/dual_contract_transmitter.go new file mode 100644 index 00000000000..86d7d38be2e --- /dev/null +++ b/core/services/relay/evm/dual_contract_transmitter.go @@ -0,0 +1,184 @@ +package evm + +import ( + "context" + "database/sql" + "encoding/hex" + errors2 "errors" + "fmt" + "strings" + "sync" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + gethcommon "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" + + "github.com/smartcontractkit/libocr/offchainreporting2plus/chains/evmutil" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" +) + +// TODO: Remove when new dual transmitter contracts are merged +var dtABI = `[{"inputs":[{"internalType":"bytes32[3]","name":"reportContext","type":"bytes32[3]"},{"internalType":"bytes","name":"report","type":"bytes"},{"internalType":"bytes32[]","name":"rs","type":"bytes32[]"},{"internalType":"bytes32[]","name":"ss","type":"bytes32[]"},{"internalType":"bytes32","name":"rawVs","type":"bytes32"}],"name":"transmitSecondary","outputs":[],"stateMutability":"nonpayable","type":"function"}]` + +var _ ContractTransmitter = (*dualContractTransmitter)(nil) + +type dualContractTransmitter struct { + contractAddress gethcommon.Address + contractABI abi.ABI + dualTransmissionABI abi.ABI + transmitter Transmitter + transmittedEventSig common.Hash + contractReader contractReader + lp logpoller.LogPoller + lggr logger.Logger + // Options + transmitterOptions *transmitterOps +} + +var dualTransmissionABI = sync.OnceValue(func() abi.ABI { + dualTransmissionABI, err := abi.JSON(strings.NewReader(dtABI)) + if err != nil { + panic(fmt.Errorf("failed to parse dualTransmission ABI: %w", err)) + } + return dualTransmissionABI +}) + +func NewOCRDualContractTransmitter( + ctx context.Context, + address gethcommon.Address, + caller contractReader, + contractABI abi.ABI, + transmitter Transmitter, + lp logpoller.LogPoller, + lggr logger.Logger, + opts ...OCRTransmitterOption, +) (*dualContractTransmitter, error) { + transmitted, ok := contractABI.Events["Transmitted"] + if !ok { + return nil, errors.New("invalid ABI, missing transmitted") + } + + newContractTransmitter := &dualContractTransmitter{ + contractAddress: address, + contractABI: contractABI, + dualTransmissionABI: dualTransmissionABI(), + transmitter: transmitter, + transmittedEventSig: transmitted.ID, + lp: lp, + contractReader: caller, + lggr: logger.Named(lggr, "OCRDualContractTransmitter"), + transmitterOptions: &transmitterOps{ + reportToEvmTxMeta: reportToEvmTxMetaNoop, + excludeSigs: false, + retention: 0, + maxLogsKept: 0, + }, + } + + for _, opt := range opts { + opt(newContractTransmitter.transmitterOptions) + } + + err := lp.RegisterFilter(ctx, logpoller.Filter{Name: transmitterFilterName(address), EventSigs: []common.Hash{transmitted.ID}, Addresses: []common.Address{address}, Retention: newContractTransmitter.transmitterOptions.retention, MaxLogsKept: newContractTransmitter.transmitterOptions.maxLogsKept}) + if err != nil { + return nil, err + } + return newContractTransmitter, nil +} + +// Transmit sends the report to the on-chain smart contract's Transmit method. +func (oc *dualContractTransmitter) Transmit(ctx context.Context, reportCtx ocrtypes.ReportContext, report ocrtypes.Report, signatures []ocrtypes.AttributedOnchainSignature) error { + var rs [][32]byte + var ss [][32]byte + var vs [32]byte + if len(signatures) > 32 { + return errors.New("too many signatures, maximum is 32") + } + for i, as := range signatures { + r, s, v, err := evmutil.SplitSignature(as.Signature) + if err != nil { + panic("eventTransmit(ev): error in SplitSignature") + } + if !oc.transmitterOptions.excludeSigs { + rs = append(rs, r) + ss = append(ss, s) + vs[i] = v + } + } + rawReportCtx := evmutil.RawReportContext(reportCtx) + + txMeta, err := oc.transmitterOptions.reportToEvmTxMeta(report) + if err != nil { + oc.lggr.Warnw("failed to generate tx metadata for report", "err", err) + } + + oc.lggr.Debugw("Transmitting report", "report", hex.EncodeToString(report), "rawReportCtx", rawReportCtx, "contractAddress", oc.contractAddress, "txMeta", txMeta) + + // Primary transmission + payload, err := oc.contractABI.Pack("transmit", rawReportCtx, []byte(report), rs, ss, vs) + if err != nil { + return errors.Wrap(err, "abi.Pack failed") + } + + transactionErr := errors.Wrap(oc.transmitter.CreateEthTransaction(ctx, oc.contractAddress, payload, txMeta), "failed to send primary Eth transaction") + + oc.lggr.Debugw("Created primary transaction", "error", transactionErr) + + // Secondary transmission + secondaryPayload, err := oc.dualTransmissionABI.Pack("transmitSecondary", rawReportCtx, []byte(report), rs, ss, vs) + if err != nil { + return errors.Wrap(err, "transmitSecondary abi.Pack failed") + } + + err = errors.Wrap(oc.transmitter.CreateSecondaryEthTransaction(ctx, secondaryPayload, txMeta), "failed to send secondary Eth transaction") + oc.lggr.Debugw("Created secondary transaction", "error", err) + return errors2.Join(transactionErr, err) +} + +// LatestConfigDigestAndEpoch retrieves the latest config digest and epoch from the OCR2 contract. +// It is plugin independent, in particular avoids use of the plugin specific generated evm wrappers +// by using the evm client Call directly for functions/events that are part of OCR2Abstract. +func (oc *dualContractTransmitter) LatestConfigDigestAndEpoch(ctx context.Context) (ocrtypes.ConfigDigest, uint32, error) { + latestConfigDigestAndEpoch, err := callContract(ctx, oc.contractAddress, oc.contractABI, "latestConfigDigestAndEpoch", nil, oc.contractReader) + if err != nil { + return ocrtypes.ConfigDigest{}, 0, err + } + // Panic on these conversions erroring, would mean a broken contract. + scanLogs := *abi.ConvertType(latestConfigDigestAndEpoch[0], new(bool)).(*bool) + configDigest := *abi.ConvertType(latestConfigDigestAndEpoch[1], new([32]byte)).(*[32]byte) + epoch := *abi.ConvertType(latestConfigDigestAndEpoch[2], new(uint32)).(*uint32) + if !scanLogs { + return configDigest, epoch, nil + } + + // Otherwise, we have to scan for the logs. + latest, err := oc.lp.LatestLogByEventSigWithConfs(ctx, oc.transmittedEventSig, oc.contractAddress, 1) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + // No transmissions yet + return configDigest, 0, nil + } + return ocrtypes.ConfigDigest{}, 0, err + } + return parseTransmitted(latest.Data) +} + +// FromAccount returns the account from which the transmitter invokes the contract +func (oc *dualContractTransmitter) FromAccount(ctx context.Context) (ocrtypes.Account, error) { + return ocrtypes.Account(oc.transmitter.FromAddress(ctx).String()), nil +} + +func (oc *dualContractTransmitter) Start(ctx context.Context) error { return nil } +func (oc *dualContractTransmitter) Close() error { return nil } + +// Has no state/lifecycle so it's always healthy and ready +func (oc *dualContractTransmitter) Ready() error { return nil } +func (oc *dualContractTransmitter) HealthReport() map[string]error { + return map[string]error{oc.Name(): nil} +} +func (oc *dualContractTransmitter) Name() string { return oc.lggr.Name() } diff --git a/core/services/relay/evm/dual_contract_transmitter_test.go b/core/services/relay/evm/dual_contract_transmitter_test.go new file mode 100644 index 00000000000..a5110398159 --- /dev/null +++ b/core/services/relay/evm/dual_contract_transmitter_test.go @@ -0,0 +1,164 @@ +package evm + +import ( + "context" + "encoding/hex" + "strings" + "testing" + + "github.com/ethereum/go-ethereum/accounts/abi" + gethcommon "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + lpmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/logger" + + "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator" + "github.com/smartcontractkit/libocr/offchainreporting2plus/chains/evmutil" + "github.com/smartcontractkit/libocr/offchainreporting2plus/types" +) + +var sampleAddressPrimary = testutils.NewAddress() + +type mockDualTransmitter struct { + lastPrimaryPayload []byte + lastSecondaryPayload []byte +} + +func (*mockDualTransmitter) FromAddress(ctx context.Context) gethcommon.Address { + return sampleAddressPrimary +} + +func (m *mockDualTransmitter) CreateEthTransaction(ctx context.Context, toAddress gethcommon.Address, payload []byte, _ *txmgr.TxMeta) error { + m.lastPrimaryPayload = payload + return nil +} + +func (m *mockDualTransmitter) CreateSecondaryEthTransaction(ctx context.Context, payload []byte, _ *txmgr.TxMeta) error { + m.lastSecondaryPayload = payload + return nil +} + +func TestDualContractTransmitter(t *testing.T) { + t.Parallel() + + lggr := logger.TestLogger(t) + c := evmclimocks.NewClient(t) + lp := lpmocks.NewLogPoller(t) + ctx := testutils.Context(t) + // scanLogs = false + digestAndEpochDontScanLogs, _ := hex.DecodeString( + "0000000000000000000000000000000000000000000000000000000000000000" + // false + "000130da6b9315bd59af6b0a3f5463c0d0a39e92eaa34cbcbdbace7b3bfcc776" + // config digest + "0000000000000000000000000000000000000000000000000000000000000002") // epoch + c.On("CallContract", mock.Anything, mock.Anything, mock.Anything).Return(digestAndEpochDontScanLogs, nil).Once() + contractABI, _ := abi.JSON(strings.NewReader(ocr2aggregator.OCR2AggregatorMetaData.ABI)) + lp.On("RegisterFilter", mock.Anything, mock.Anything).Return(nil) + reportToEvmTxMeta := func(b []byte) (*txmgr.TxMeta, error) { + return &txmgr.TxMeta{}, nil + } + ot, err := NewOCRDualContractTransmitter(ctx, gethcommon.Address{}, c, contractABI, &mockDualTransmitter{}, lp, lggr, + WithReportToEthMetadata(reportToEvmTxMeta)) + require.NoError(t, err) + digest, epoch, err := ot.LatestConfigDigestAndEpoch(testutils.Context(t)) + require.NoError(t, err) + assert.Equal(t, "000130da6b9315bd59af6b0a3f5463c0d0a39e92eaa34cbcbdbace7b3bfcc776", hex.EncodeToString(digest[:])) + assert.Equal(t, uint32(2), epoch) + + // scanLogs = true + digestAndEpochScanLogs, _ := hex.DecodeString( + "0000000000000000000000000000000000000000000000000000000000000001" + // true + "000130da6b9315bd59af6b0a3f5463c0d0a39e92eaa34cbcbdbace7b3bfcc776" + // config digest + "0000000000000000000000000000000000000000000000000000000000000002") // epoch + c.On("CallContract", mock.Anything, mock.Anything, mock.Anything).Return(digestAndEpochScanLogs, nil).Once() + transmitted2, _ := hex.DecodeString( + "000130da6b9315bd59af6b0a3f5463c0d0a39e92eaa34cbcbdbace7b3bfcc777" + // config digest + "0000000000000000000000000000000000000000000000000000000000000002") // epoch + lp.On("LatestLogByEventSigWithConfs", + mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&logpoller.Log{ + Data: transmitted2, + }, nil) + digest, epoch, err = ot.LatestConfigDigestAndEpoch(testutils.Context(t)) + require.NoError(t, err) + assert.Equal(t, "000130da6b9315bd59af6b0a3f5463c0d0a39e92eaa34cbcbdbace7b3bfcc777", hex.EncodeToString(digest[:])) + assert.Equal(t, uint32(2), epoch) + from, err := ot.FromAccount(tests.Context(t)) + require.NoError(t, err) + assert.Equal(t, sampleAddressPrimary.String(), string(from)) +} + +func Test_dualContractTransmitterNoSignatures_Transmit_SignaturesAreNotTransmitted(t *testing.T) { + t.Parallel() + + transmitter := &mockDualTransmitter{} + + ctx := context.Background() + reportCtx := types.ReportContext{} + report := types.Report{} + var signatures = oneSignature() + + oc := createDualContractTransmitter(ctx, t, transmitter, WithExcludeSignatures()) + + err := oc.Transmit(ctx, reportCtx, report, signatures) + require.NoError(t, err) + + var emptyRs [][32]byte + var emptySs [][32]byte + var emptyVs [32]byte + emptySignaturesPayloadPrimary, err := oc.contractABI.Pack("transmit", evmutil.RawReportContext(reportCtx), []byte(report), emptyRs, emptySs, emptyVs) + require.NoError(t, err) + emptySignaturesPayloadSecondary, err := oc.dualTransmissionABI.Pack("transmitSecondary", evmutil.RawReportContext(reportCtx), []byte(report), emptyRs, emptySs, emptyVs) + require.NoError(t, err) + require.Equal(t, transmitter.lastPrimaryPayload, emptySignaturesPayloadPrimary, "primary payload not equal") + require.Equal(t, transmitter.lastSecondaryPayload, emptySignaturesPayloadSecondary, "secondary payload not equal") +} + +func Test_dualContractTransmitter_Transmit_SignaturesAreTransmitted(t *testing.T) { + t.Parallel() + + transmitter := &mockDualTransmitter{} + + ctx := context.Background() + reportCtx := types.ReportContext{} + report := types.Report{} + var signatures = oneSignature() + + oc := createDualContractTransmitter(ctx, t, transmitter) + + err := oc.Transmit(ctx, reportCtx, report, signatures) + require.NoError(t, err) + + rs, ss, vs := signaturesAsPayload(t, signatures) + withSignaturesPayloadPrimary, err := oc.contractABI.Pack("transmit", evmutil.RawReportContext(reportCtx), []byte(report), rs, ss, vs) + require.NoError(t, err) + withSignaturesPayloadSecondary, err := oc.dualTransmissionABI.Pack("transmitSecondary", evmutil.RawReportContext(reportCtx), []byte(report), rs, ss, vs) + require.NoError(t, err) + require.Equal(t, transmitter.lastPrimaryPayload, withSignaturesPayloadPrimary, "primary payload not equal") + require.Equal(t, transmitter.lastSecondaryPayload, withSignaturesPayloadSecondary, "secondary payload not equal") +} + +func createDualContractTransmitter(ctx context.Context, t *testing.T, transmitter Transmitter, ops ...OCRTransmitterOption) *dualContractTransmitter { + contractABI, err := abi.JSON(strings.NewReader(ocr2aggregator.OCR2AggregatorMetaData.ABI)) + require.NoError(t, err) + lp := lpmocks.NewLogPoller(t) + lp.On("RegisterFilter", mock.Anything, mock.Anything).Return(nil) + contractTransmitter, err := NewOCRDualContractTransmitter( + ctx, + gethcommon.Address{}, + evmclimocks.NewClient(t), + contractABI, + transmitter, + lp, + logger.TestLogger(t), + ops..., + ) + require.NoError(t, err) + return contractTransmitter +} diff --git a/core/services/relay/evm/evm.go b/core/services/relay/evm/evm.go index e60dbe1bfdb..748e1c87a1e 100644 --- a/core/services/relay/evm/evm.go +++ b/core/services/relay/evm/evm.go @@ -3,6 +3,7 @@ package evm import ( "bytes" "context" + "crypto/ed25519" "crypto/sha256" "encoding/json" "errors" @@ -45,17 +46,20 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/llo" "github.com/smartcontractkit/chainlink/v2/core/services/llo/bm" + "github.com/smartcontractkit/chainlink/v2/core/services/llo/grpc" "github.com/smartcontractkit/chainlink/v2/core/services/llo/mercurytransmitter" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/ccipcommit" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/ccipexec" ccipconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/estimatorconfig" cciptransmitter "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/transmitter" lloconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/llo/config" mercuryconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/mercury/config" "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/codec" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/functions" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/interceptors/mantle" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury" mercuryutils "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/utils" reportcodecv1 "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v1/reportcodec" @@ -217,7 +221,7 @@ func NewRelayer(ctx context.Context, lggr logger.Logger, chain legacyevm.Chain, relayer := &Relayer{ ds: opts.DS, chain: chain, - lggr: sugared, + lggr: logger.Sugared(sugared), registerer: opts.Registerer, ks: opts.CSAETHKeystore, mercuryPool: opts.MercuryPool, @@ -505,6 +509,185 @@ func (r *Relayer) NewMercuryProvider(ctx context.Context, rargs commontypes.Rela return NewMercuryProvider(cp, r.codec, NewMercuryChainReader(r.chain.HeadTracker()), transmitter, reportCodecV1, reportCodecV2, reportCodecV3, reportCodecV4, lggr), nil } +func chainToUUID(chainID *big.Int) uuid.UUID { + // See https://www.rfc-editor.org/rfc/rfc4122.html#section-4.1.3 for the list of supported versions. + const VersionSHA1 = 5 + var buf bytes.Buffer + buf.WriteString("CCIP:") + buf.Write(chainID.Bytes()) + // We use SHA-256 instead of SHA-1 because the former has better collision resistance. + // The UUID will contain only the first 16 bytes of the hash. + // You can't say which algorithms was used just by looking at the UUID bytes. + return uuid.NewHash(sha256.New(), uuid.NameSpaceOID, buf.Bytes(), VersionSHA1) +} + +// NewCCIPCommitProvider constructs a provider of type CCIPCommitProvider. Since this is happening in the Relayer, +// which lives in a separate process from delegate which is requesting a provider, we need to wire in through pargs +// which *type* (impl) of CCIPCommitProvider should be created. CCIP is currently a special case where the provider has a +// subset of implementations of the complete interface as certain contracts in a CCIP lane are only deployed on the src +// chain or on the dst chain. This results in the two implementations of providers: a src and dst implementation. +func (r *Relayer) NewCCIPCommitProvider(ctx context.Context, rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.CCIPCommitProvider, error) { + versionFinder := ccip.NewEvmVersionFinder() + + var commitPluginConfig ccipconfig.CommitPluginConfig + err := json.Unmarshal(pargs.PluginConfig, &commitPluginConfig) + if err != nil { + return nil, err + } + sourceStartBlock := commitPluginConfig.SourceStartBlock + destStartBlock := commitPluginConfig.DestStartBlock + + feeEstimatorConfig := estimatorconfig.NewFeeEstimatorConfigService() + + // CCIPCommit reads only when source chain is Mantle, then reports to dest chain + // to minimize misconfigure risk, might make sense to wire Mantle only when Commit + Mantle + IsSourceProvider + if r.chain.Config().EVM().ChainID().Uint64() == 5003 || r.chain.Config().EVM().ChainID().Uint64() == 5000 { + if commitPluginConfig.IsSourceProvider { + oracleAddress := r.chain.Config().EVM().GasEstimator().DAOracle().OracleAddress() + mantleInterceptor, iErr := mantle.NewInterceptor(ctx, r.chain.Client(), oracleAddress) + if iErr != nil { + return nil, iErr + } + feeEstimatorConfig.AddGasPriceInterceptor(mantleInterceptor) + } + } + + // The src chain implementation of this provider does not need a configWatcher or contractTransmitter; + // bail early. + if commitPluginConfig.IsSourceProvider { + return NewSrcCommitProvider( + r.lggr, + sourceStartBlock, + r.chain.Client(), + r.chain.LogPoller(), + r.chain.GasEstimator(), + r.chain.Config().EVM().GasEstimator().PriceMax().ToInt(), + feeEstimatorConfig, + ), nil + } + + relayOpts := types.NewRelayOpts(rargs) + configWatcher, err := newStandardConfigProvider(ctx, r.lggr, r.chain, relayOpts) + if err != nil { + return nil, err + } + address := common.HexToAddress(relayOpts.ContractID) + typ, ver, err := ccipconfig.TypeAndVersion(address, r.chain.Client()) + if err != nil { + return nil, err + } + fn, err := ccipcommit.CommitReportToEthTxMeta(typ, ver) + if err != nil { + return nil, err + } + subjectID := chainToUUID(configWatcher.chain.ID()) + contractTransmitter, err := newOnChainContractTransmitter(ctx, r.lggr, rargs, r.ks.Eth(), configWatcher, configTransmitterOpts{ + subjectID: &subjectID, + }, OCR2AggregatorTransmissionContractABI, WithReportToEthMetadata(fn), WithRetention(0)) + if err != nil { + return nil, err + } + + return NewDstCommitProvider( + r.lggr, + versionFinder, + destStartBlock, + r.chain.Client(), + r.chain.LogPoller(), + r.chain.GasEstimator(), + *r.chain.Config().EVM().GasEstimator().PriceMax().ToInt(), + *contractTransmitter, + configWatcher, + feeEstimatorConfig, + ), nil +} + +// NewCCIPExecProvider constructs a provider of type CCIPExecProvider. Since this is happening in the Relayer, +// which lives in a separate process from delegate which is requesting a provider, we need to wire in through pargs +// which *type* (impl) of CCIPExecProvider should be created. CCIP is currently a special case where the provider has a +// subset of implementations of the complete interface as certain contracts in a CCIP lane are only deployed on the src +// chain or on the dst chain. This results in the two implementations of providers: a src and dst implementation. +func (r *Relayer) NewCCIPExecProvider(ctx context.Context, rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.CCIPExecProvider, error) { + versionFinder := ccip.NewEvmVersionFinder() + + var execPluginConfig ccipconfig.ExecPluginConfig + err := json.Unmarshal(pargs.PluginConfig, &execPluginConfig) + if err != nil { + return nil, err + } + + feeEstimatorConfig := estimatorconfig.NewFeeEstimatorConfigService() + + // CCIPExec reads when dest chain is mantle, and uses it to calc boosting in batching + // to minimize misconfigure risk, make sense to wire Mantle only when Exec + Mantle + !IsSourceProvider + if r.chain.Config().EVM().ChainID().Uint64() == 5003 || r.chain.Config().EVM().ChainID().Uint64() == 5000 { + if !execPluginConfig.IsSourceProvider { + oracleAddress := r.chain.Config().EVM().GasEstimator().DAOracle().OracleAddress() + mantleInterceptor, iErr := mantle.NewInterceptor(ctx, r.chain.Client(), oracleAddress) + if iErr != nil { + return nil, iErr + } + feeEstimatorConfig.AddGasPriceInterceptor(mantleInterceptor) + } + } + + // The src chain implementation of this provider does not need a configWatcher or contractTransmitter; + // bail early. + if execPluginConfig.IsSourceProvider { + return NewSrcExecProvider( + ctx, + r.lggr, + versionFinder, + r.chain.Client(), + r.chain.GasEstimator(), + r.chain.Config().EVM().GasEstimator().PriceMax().ToInt(), + r.chain.LogPoller(), + execPluginConfig.SourceStartBlock, + execPluginConfig.JobID, + execPluginConfig.USDCConfig, + execPluginConfig.LBTCConfig, + feeEstimatorConfig, + ) + } + + relayOpts := types.NewRelayOpts(rargs) + configWatcher, err := newStandardConfigProvider(ctx, r.lggr, r.chain, relayOpts) + if err != nil { + return nil, err + } + address := common.HexToAddress(relayOpts.ContractID) + typ, ver, err := ccipconfig.TypeAndVersion(address, r.chain.Client()) + if err != nil { + return nil, err + } + fn, err := ccipexec.ExecReportToEthTxMeta(ctx, typ, ver) + if err != nil { + return nil, err + } + subjectID := chainToUUID(configWatcher.chain.ID()) + contractTransmitter, err := newOnChainContractTransmitter(ctx, r.lggr, rargs, r.ks.Eth(), configWatcher, configTransmitterOpts{ + subjectID: &subjectID, + }, OCR2AggregatorTransmissionContractABI, WithReportToEthMetadata(fn), WithRetention(0), WithExcludeSignatures()) + if err != nil { + return nil, err + } + + return NewDstExecProvider( + r.lggr, + versionFinder, + r.chain.Client(), + r.chain.LogPoller(), + execPluginConfig.DestStartBlock, + contractTransmitter, + configWatcher, + r.chain.GasEstimator(), + *r.chain.Config().EVM().GasEstimator().PriceMax().ToInt(), + feeEstimatorConfig, + r.chain.TxManager(), + cciptypes.Address(rargs.ContractID), + ) +} + func (r *Relayer) NewLLOProvider(ctx context.Context, rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.LLOProvider, error) { relayOpts := types.NewRelayOpts(rargs) var relayConfig types.RelayConfig @@ -557,11 +740,25 @@ func (r *Relayer) NewLLOProvider(ctx context.Context, rargs commontypes.RelayArg r.lggr.Info("Benchmark mode enabled, using dummy transmitter. NOTE: THIS WILL NOT TRANSMIT ANYTHING") transmitter = bm.NewTransmitter(r.lggr, fmt.Sprintf("%x", privKey.PublicKey)) } else { - clients := make(map[string]wsrpc.Client) + clients := make(map[string]grpc.Client) for _, server := range lloCfg.GetServers() { - client, err2 := r.mercuryPool.Checkout(ctx, privKey, server.PubKey, server.URL) - if err2 != nil { - return nil, err2 + var client grpc.Client + switch r.mercuryCfg.Transmitter().Protocol() { + case "grpc": + client = grpc.NewClient(grpc.ClientOpts{ + Logger: r.lggr, + ClientPrivKey: privKey.PrivateKey(), + ServerPubKey: ed25519.PublicKey(server.PubKey), + ServerURL: server.URL, + }) + case "wsrpc": + wsrpcClient, checkoutErr := r.mercuryPool.Checkout(ctx, privKey, server.PubKey, server.URL) + if checkoutErr != nil { + return nil, checkoutErr + } + client = wsrpc.GRPCCompatibilityWrapper{Client: wsrpcClient} + default: + return nil, fmt.Errorf("unsupported protocol %q", r.mercuryCfg.Transmitter().Protocol()) } clients[server.URL] = client } @@ -759,6 +956,33 @@ func newOnChainContractTransmitter(ctx context.Context, lggr logger.Logger, rarg ) } +// newOnChainDualContractTransmitter creates a new dual contract transmitter. +func newOnChainDualContractTransmitter(ctx context.Context, lggr logger.Logger, rargs commontypes.RelayArgs, ethKeystore keystore.Eth, configWatcher *configWatcher, opts configTransmitterOpts, transmissionContractABI abi.ABI, ocrTransmitterOpts ...OCRTransmitterOption) (*dualContractTransmitter, error) { + transmitter, err := generateTransmitterFrom(ctx, rargs, ethKeystore, configWatcher, opts) + if err != nil { + return nil, err + } + + return NewOCRDualContractTransmitter( + ctx, + configWatcher.contractAddress, + configWatcher.chain.Client(), + transmissionContractABI, + transmitter, + configWatcher.chain.LogPoller(), + lggr, + ocrTransmitterOpts..., + ) +} + +func NewContractTransmitter(ctx context.Context, lggr logger.Logger, rargs commontypes.RelayArgs, ethKeystore keystore.Eth, configWatcher *configWatcher, opts configTransmitterOpts, transmissionContractABI abi.ABI, dualTransmission bool, ocrTransmitterOpts ...OCRTransmitterOption) (ContractTransmitter, error) { + if dualTransmission { + return newOnChainDualContractTransmitter(ctx, lggr, rargs, ethKeystore, configWatcher, opts, transmissionContractABI, ocrTransmitterOpts...) + } + + return newOnChainContractTransmitter(ctx, lggr, rargs, ethKeystore, configWatcher, opts, transmissionContractABI, ocrTransmitterOpts...) +} + func generateTransmitterFrom(ctx context.Context, rargs commontypes.RelayArgs, ethKeystore keystore.Eth, configWatcher *configWatcher, opts configTransmitterOpts) (Transmitter, error) { var relayConfig types.RelayConfig if err := json.Unmarshal(rargs.RelayConfig, &relayConfig); err != nil { @@ -896,7 +1120,7 @@ func (r *Relayer) NewMedianProvider(ctx context.Context, rargs commontypes.Relay reportCodec := evmreportcodec.ReportCodec{} - contractTransmitter, err := newOnChainContractTransmitter(ctx, lggr, rargs, r.ks.Eth(), configWatcher, configTransmitterOpts{}, OCR2AggregatorTransmissionContractABI) + ct, err := NewContractTransmitter(ctx, lggr, rargs, r.ks.Eth(), configWatcher, configTransmitterOpts{}, OCR2AggregatorTransmissionContractABI, relayConfig.EnableDualTransmission) if err != nil { return nil, err } @@ -910,7 +1134,7 @@ func (r *Relayer) NewMedianProvider(ctx context.Context, rargs commontypes.Relay lggr: lggr.Named("MedianProvider"), configWatcher: configWatcher, reportCodec: reportCodec, - contractTransmitter: contractTransmitter, + contractTransmitter: ct, medianContract: medianContract, } @@ -949,155 +1173,6 @@ func (r *Relayer) NewAutomationProvider(ctx context.Context, rargs commontypes.R return ocr2keeperRelayer.NewOCR2KeeperProvider(ctx, rargs, pargs) } -func chainToUUID(chainID *big.Int) uuid.UUID { - // See https://www.rfc-editor.org/rfc/rfc4122.html#section-4.1.3 for the list of supported versions. - const VersionSHA1 = 5 - var buf bytes.Buffer - buf.WriteString("CCIP:") - buf.Write(chainID.Bytes()) - // We use SHA-256 instead of SHA-1 because the former has better collision resistance. - // The UUID will contain only the first 16 bytes of the hash. - // You can't say which algorithms was used just by looking at the UUID bytes. - return uuid.NewHash(sha256.New(), uuid.NameSpaceOID, buf.Bytes(), VersionSHA1) -} - -// NewCCIPCommitProvider constructs a provider of type CCIPCommitProvider. Since this is happening in the Relayer, -// which lives in a separate process from delegate which is requesting a provider, we need to wire in through pargs -// which *type* (impl) of CCIPCommitProvider should be created. CCIP is currently a special case where the provider has a -// subset of implementations of the complete interface as certain contracts in a CCIP lane are only deployed on the src -// chain or on the dst chain. This results in the two implementations of providers: a src and dst implementation. -func (r *Relayer) NewCCIPCommitProvider(ctx context.Context, rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.CCIPCommitProvider, error) { - versionFinder := ccip.NewEvmVersionFinder() - - var commitPluginConfig ccipconfig.CommitPluginConfig - err := json.Unmarshal(pargs.PluginConfig, &commitPluginConfig) - if err != nil { - return nil, err - } - sourceStartBlock := commitPluginConfig.SourceStartBlock - destStartBlock := commitPluginConfig.DestStartBlock - - // The src chain implementation of this provider does not need a configWatcher or contractTransmitter; - // bail early. - if commitPluginConfig.IsSourceProvider { - return NewSrcCommitProvider( - r.lggr, - sourceStartBlock, - r.chain.Client(), - r.chain.LogPoller(), - r.chain.GasEstimator(), - r.chain.Config().EVM().GasEstimator().PriceMax().ToInt(), - ), nil - } - - relayOpts := types.NewRelayOpts(rargs) - configWatcher, err := newStandardConfigProvider(ctx, r.lggr, r.chain, relayOpts) - if err != nil { - return nil, err - } - address := common.HexToAddress(relayOpts.ContractID) - typ, ver, err := ccipconfig.TypeAndVersion(address, r.chain.Client()) - if err != nil { - return nil, err - } - fn, err := ccipcommit.CommitReportToEthTxMeta(typ, ver) - if err != nil { - return nil, err - } - subjectID := chainToUUID(configWatcher.chain.ID()) - contractTransmitter, err := newOnChainContractTransmitter(ctx, r.lggr, rargs, r.ks.Eth(), configWatcher, configTransmitterOpts{ - subjectID: &subjectID, - }, OCR2AggregatorTransmissionContractABI, WithReportToEthMetadata(fn), WithRetention(0)) - if err != nil { - return nil, err - } - - return NewDstCommitProvider( - r.lggr, - versionFinder, - destStartBlock, - r.chain.Client(), - r.chain.LogPoller(), - r.chain.GasEstimator(), - *r.chain.Config().EVM().GasEstimator().PriceMax().ToInt(), - *contractTransmitter, - configWatcher, - ), nil -} - -// NewCCIPExecProvider constructs a provider of type CCIPExecProvider. Since this is happening in the Relayer, -// which lives in a separate process from delegate which is requesting a provider, we need to wire in through pargs -// which *type* (impl) of CCIPExecProvider should be created. CCIP is currently a special case where the provider has a -// subset of implementations of the complete interface as certain contracts in a CCIP lane are only deployed on the src -// chain or on the dst chain. This results in the two implementations of providers: a src and dst implementation. -func (r *Relayer) NewCCIPExecProvider(ctx context.Context, rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.CCIPExecProvider, error) { - versionFinder := ccip.NewEvmVersionFinder() - - var execPluginConfig ccipconfig.ExecPluginConfig - err := json.Unmarshal(pargs.PluginConfig, &execPluginConfig) - if err != nil { - return nil, err - } - - usdcConfig := execPluginConfig.USDCConfig - - // The src chain implementation of this provider does not need a configWatcher or contractTransmitter; - // bail early. - if execPluginConfig.IsSourceProvider { - return NewSrcExecProvider( - ctx, - r.lggr, - versionFinder, - r.chain.Client(), - r.chain.GasEstimator(), - r.chain.Config().EVM().GasEstimator().PriceMax().ToInt(), - r.chain.LogPoller(), - execPluginConfig.SourceStartBlock, - execPluginConfig.JobID, - usdcConfig.AttestationAPI, - int(usdcConfig.AttestationAPITimeoutSeconds), - usdcConfig.AttestationAPIIntervalMilliseconds, - usdcConfig.SourceMessageTransmitterAddress, - ) - } - - relayOpts := types.NewRelayOpts(rargs) - configWatcher, err := newStandardConfigProvider(ctx, r.lggr, r.chain, relayOpts) - if err != nil { - return nil, err - } - address := common.HexToAddress(relayOpts.ContractID) - typ, ver, err := ccipconfig.TypeAndVersion(address, r.chain.Client()) - if err != nil { - return nil, err - } - fn, err := ccipexec.ExecReportToEthTxMeta(ctx, typ, ver) - if err != nil { - return nil, err - } - subjectID := chainToUUID(configWatcher.chain.ID()) - contractTransmitter, err := newOnChainContractTransmitter(ctx, r.lggr, rargs, r.ks.Eth(), configWatcher, configTransmitterOpts{ - subjectID: &subjectID, - }, OCR2AggregatorTransmissionContractABI, WithReportToEthMetadata(fn), WithRetention(0)) - if err != nil { - return nil, err - } - - return NewDstExecProvider( - r.lggr, - versionFinder, - r.chain.Client(), - r.chain.LogPoller(), - execPluginConfig.DestStartBlock, - contractTransmitter, - configWatcher, - r.chain.GasEstimator(), - *r.chain.Config().EVM().GasEstimator().PriceMax().ToInt(), - r.chain.TxManager(), - cciptypes.Address(rargs.ContractID), - ) -} - var _ commontypes.MedianProvider = (*medianProvider)(nil) type medianProvider struct { diff --git a/core/services/relay/evm/evmtesting/chain_components_interface_tester.go b/core/services/relay/evm/evmtesting/chain_components_interface_tester.go index 71bd94f0e9f..23fd97dd4d8 100644 --- a/core/services/relay/evm/evmtesting/chain_components_interface_tester.go +++ b/core/services/relay/evm/evmtesting/chain_components_interface_tester.go @@ -2,8 +2,8 @@ package evmtesting import ( "context" - "encoding/json" "math/big" + "sync" "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -15,17 +15,16 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/codec" + "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" clcommontypes "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "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/headtracker" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" evmtxmgr "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/chain_reader_tester" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/chain_reader_tester" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" _ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" // force binding for tx type "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -40,14 +39,13 @@ const ( triggerWithAllTopics = "TriggeredWithFourTopics" triggerWithAllTopicsWithHashed = "TriggeredWithFourTopicsWithHashed" staticBytesEventName = "StaticBytes" - finalityDepth = 4 ) type EVMChainComponentsInterfaceTesterHelper[T TestingT[T]] interface { - Init(t T) Client(t T) client.Client Commit() Backend() bind.ContractBackend + Database() *sqlx.DB ChainID() *big.Int Context(t T) context.Context NewSqlxDB(t T) *sqlx.DB @@ -58,67 +56,21 @@ type EVMChainComponentsInterfaceTesterHelper[T TestingT[T]] interface { // To enable the historical wrappers required for Simulated Backend tests. ChainReaderEVMClient(ctx context.Context, t T, ht logpoller.HeadTracker, conf types.ChainReaderConfig) client.Client WrappedChainWriter(cw clcommontypes.ContractWriter, client client.Client) clcommontypes.ContractWriter + LogPoller(t T) logpoller.LogPoller + HeadTracker(t T) logpoller.HeadTracker } type EVMChainComponentsInterfaceTester[T TestingT[T]] struct { TestSelectionSupport Helper EVMChainComponentsInterfaceTesterHelper[T] + DeployLock *sync.Mutex client client.Client - address string - address2 string - contractTesters map[string]*chain_reader_tester.ChainReaderTester - chainReaderConfig types.ChainReaderConfig - chainWriterConfig types.ChainWriterConfig - deployerAuth *bind.TransactOpts - senderAuth *bind.TransactOpts - cr evm.ChainReaderService - cw evm.ChainWriterService - dirtyContracts bool - txm evmtxmgr.TxManager - gasEstimator gas.EvmFeeEstimator chainReaderConfigSupplier func(t T) types.ChainReaderConfig chainWriterConfigSupplier func(t T) types.ChainWriterConfig - dirtyConfig bool } -func (it *EVMChainComponentsInterfaceTester[T]) Setup(t T) { - t.Cleanup(func() { - // DB may be closed by the test already, ignore errors - if it.cr != nil { - _ = it.cr.Close() - } - it.cr = nil - - if it.dirtyContracts { - it.contractTesters = nil - } - - if it.cw != nil { - _ = it.cw.Close() - } - it.cw = nil - }) - - // can re-use the same chain for tests, just make new contract for each test - if it.client != nil && !it.dirtyConfig { - it.deployNewContracts(t) - return - } - - // Need to separate accounts to ensure the nonce doesn't get misaligned after the - // contract deployments. - accounts := it.Helper.Accounts(t) - it.deployerAuth = accounts[0] - it.senderAuth = accounts[1] - - it.chainReaderConfig = it.chainReaderConfigSupplier(t) - it.GetContractReader(t) - - it.txm = it.Helper.TXM(t, it.client) - it.chainWriterConfig = it.chainWriterConfigSupplier(t) - - it.deployNewContracts(t) - it.dirtyConfig = false +func (it *EVMChainComponentsInterfaceTester[T]) GetBindings(t T) []clcommontypes.BoundContract { + return it.deployNewContracts(t) } func (it *EVMChainComponentsInterfaceTester[T]) getChainReaderConfig(t T) types.ChainReaderConfig { @@ -357,138 +309,94 @@ func (it *EVMChainComponentsInterfaceTester[T]) GetAccountString(i int) string { func (it *EVMChainComponentsInterfaceTester[T]) GetContractReader(t T) clcommontypes.ContractReader { ctx := it.Helper.Context(t) - if it.cr != nil { - return it.cr - } - lggr := logger.NullLogger - db := it.Helper.NewSqlxDB(t) - lpOpts := logpoller.Opts{ - PollPeriod: time.Millisecond, - FinalityDepth: finalityDepth, - BackfillBatchSize: 1, - RpcBatchSize: 1, - KeepFinalizedBlocksDepth: 10000, - } - ht := headtracker.NewSimulatedHeadTracker(it.Helper.Client(t), lpOpts.UseFinalityTag, lpOpts.FinalityDepth) - lp := logpoller.NewLogPoller(logpoller.NewORM(it.Helper.ChainID(), db, lggr), it.Helper.Client(t), lggr, ht, lpOpts) - require.NoError(t, lp.Start(ctx)) - // encode and decode the config to ensure the test covers type issues - confBytes, err := json.Marshal(it.chainReaderConfig) + cr, err := evm.NewChainReaderService(ctx, lggr, it.Helper.LogPoller(t), it.Helper.HeadTracker(t), it.client, it.chainReaderConfigSupplier(t)) require.NoError(t, err) + servicetest.Run(t, cr) - conf, err := types.ChainReaderConfigFromBytes(confBytes) - require.NoError(t, err) - - cwh := it.Helper.ChainReaderEVMClient(ctx, t, ht, conf) - it.client = cwh - - cr, err := evm.NewChainReaderService(ctx, lggr, lp, ht, it.client, conf) - require.NoError(t, err) - require.NoError(t, cr.Start(ctx)) - it.cr = cr return cr } -// This function is no longer necessary for Simulated Backend or Testnet tests. -func (it *EVMChainComponentsInterfaceTester[T]) GenerateBlocksTillConfidenceLevel(t T, contractName, readName string, confidenceLevel primitives.ConfidenceLevel) { -} - func (it *EVMChainComponentsInterfaceTester[T]) GetContractWriter(t T) clcommontypes.ContractWriter { - ctx := it.Helper.Context(t) - if it.cw != nil { - return it.cw - } - - cw, err := evm.NewChainWriterService(logger.NullLogger, it.client, it.txm, it.gasEstimator, it.chainWriterConfig) + cw, err := evm.NewChainWriterService(logger.NullLogger, it.client, it.Helper.TXM(t, it.client), nil, it.chainWriterConfigSupplier(t)) require.NoError(t, err) - it.cw = it.Helper.WrappedChainWriter(cw, it.client) + + cw = it.Helper.WrappedChainWriter(cw, it.client) require.NoError(t, err) - require.NoError(t, cw.Start(ctx)) - return it.cw + + servicetest.Run(t, cw) + + return cw } -func (it *EVMChainComponentsInterfaceTester[T]) GetBindings(_ T) []clcommontypes.BoundContract { - return []clcommontypes.BoundContract{ - {Name: AnyContractName, Address: it.address}, - {Name: AnySecondContractName, Address: it.address2}, - } +// This function is no longer necessary for Simulated Backend or Testnet tests. +func (it *EVMChainComponentsInterfaceTester[T]) GenerateBlocksTillConfidenceLevel(t T, contractName, readName string, confidenceLevel primitives.ConfidenceLevel) { } func (it *EVMChainComponentsInterfaceTester[T]) DirtyContracts() { - it.dirtyContracts = true } func (it *EVMChainComponentsInterfaceTester[T]) GetAuthWithGasSet(t T) *bind.TransactOpts { - gasPrice, err := it.client.SuggestGasPrice(it.Helper.Context(t)) + auth := *it.Helper.Accounts(t)[0] + gasPrice, err := it.Helper.Client(t).SuggestGasPrice(it.Helper.Context(t)) require.NoError(t, err) extra := new(big.Int).Mul(gasPrice, big.NewInt(it.Helper.GasPriceBufferPercent())) extra = extra.Div(extra, big.NewInt(100)) - it.deployerAuth.GasPrice = gasPrice.Add(gasPrice, extra) - return it.deployerAuth -} - -func (it *EVMChainComponentsInterfaceTester[T]) IncNonce() { - if it.deployerAuth.Nonce == nil { - it.deployerAuth.Nonce = big.NewInt(1) - } else { - it.deployerAuth.Nonce = it.deployerAuth.Nonce.Add(it.deployerAuth.Nonce, big.NewInt(1)) - } + auth.GasPrice = gasPrice.Add(gasPrice, extra) + auth.GasLimit = 10552800 + nonce, err := it.client.PendingNonceAt(it.Helper.Context(t), auth.From) + require.NoError(t, err) + auth.Nonce = new(big.Int).SetUint64(nonce) + return &auth } func (it *EVMChainComponentsInterfaceTester[T]) AwaitTx(t T, tx *gethtypes.Transaction) { ctx := it.Helper.Context(t) - receipt, err := bind.WaitMined(ctx, it.client, tx) + receipt, err := bind.WaitMined(ctx, it.Helper.Client(t), tx) require.NoError(t, err) require.Equal(t, gethtypes.ReceiptStatusSuccessful, receipt.Status) } -func (it *EVMChainComponentsInterfaceTester[T]) deployNewContracts(t T) { - // First test deploy both contracts, otherwise only deploy contracts if cleanup decides that we need to. - if it.address == "" || it.contractTesters == nil { - it.contractTesters = make(map[string]*chain_reader_tester.ChainReaderTester, 2) - address, ts1 := it.deployNewContract(t) - address2, ts2 := it.deployNewContract(t) - it.address, it.address2 = address, address2 - it.contractTesters[it.address] = ts1 - it.contractTesters[it.address2] = ts2 - it.dirtyContracts = false +func (it *EVMChainComponentsInterfaceTester[T]) deployNewContracts(t T) []clcommontypes.BoundContract { + it.DeployLock.Lock() + defer it.DeployLock.Unlock() + address := it.deployNewContract(t) + address2 := it.deployNewContract(t) + return []clcommontypes.BoundContract{ + {Name: AnyContractName, Address: address}, + {Name: AnySecondContractName, Address: address2}, } } -func (it *EVMChainComponentsInterfaceTester[T]) deployNewContract(t T) (string, *chain_reader_tester.ChainReaderTester) { - // 105528 was in the error: gas too low: have 0, want 105528 - // Not sure if there's a better way to get it. - it.deployerAuth.GasLimit = 10552800 - - address, tx, ts, err := chain_reader_tester.DeployChainReaderTester(it.GetAuthWithGasSet(t), it.Helper.Backend()) +func (it *EVMChainComponentsInterfaceTester[T]) deployNewContract(t T) string { + address, tx, _, err := chain_reader_tester.DeployChainReaderTester(it.GetAuthWithGasSet(t), it.Helper.Backend()) require.NoError(t, err) - it.Helper.Commit() - it.IncNonce() it.AwaitTx(t, tx) - return address.String(), ts + return address.String() } func (it *EVMChainComponentsInterfaceTester[T]) MaxWaitTimeForEvents() time.Duration { return it.Helper.MaxWaitTimeForEvents() } -func (it *EVMChainComponentsInterfaceTester[T]) Init(t T) { - it.Helper.Init(t) - it.chainWriterConfigSupplier = func(t T) types.ChainWriterConfig { return it.getChainWriterConfig(t) } - it.chainReaderConfigSupplier = func(t T) types.ChainReaderConfig { return it.getChainReaderConfig(t) } +func (it *EVMChainComponentsInterfaceTester[T]) Setup(t T) { + if it.chainReaderConfigSupplier == nil { + it.chainReaderConfigSupplier = func(t T) types.ChainReaderConfig { return it.getChainReaderConfig(t) } + } + if it.chainWriterConfigSupplier == nil { + it.chainWriterConfigSupplier = func(t T) types.ChainWriterConfig { return it.getChainWriterConfig(t) } + } + it.client = it.Helper.ChainReaderEVMClient(it.Helper.Context(t), t, it.Helper.HeadTracker(t), it.chainReaderConfigSupplier(t)) } func (it *EVMChainComponentsInterfaceTester[T]) SetChainReaderConfigSupplier(chainReaderConfigSupplier func(t T) types.ChainReaderConfig) { - it.dirtyConfig = true it.chainReaderConfigSupplier = chainReaderConfigSupplier } func (it *EVMChainComponentsInterfaceTester[T]) SetChainWriterConfigSupplier(chainWriterConfigSupplier func(t T) types.ChainWriterConfig) { - it.dirtyConfig = true it.chainWriterConfigSupplier = chainWriterConfigSupplier } diff --git a/core/services/relay/evm/evmtesting/run_tests.go b/core/services/relay/evm/evmtesting/run_tests.go index b6abffdcb2f..469cc3594b8 100644 --- a/core/services/relay/evm/evmtesting/run_tests.go +++ b/core/services/relay/evm/evmtesting/run_tests.go @@ -37,31 +37,31 @@ func RunChainComponentsEvmTests[T TestingT[T]](t T, it *EVMChainComponentsInterf // Add ChainWriter tests here } -func RunChainComponentsInLoopEvmTests[T TestingT[T]](t T, it ChainComponentsInterfaceTester[T]) { - RunContractReaderInLoopTests[T](t, it) +func RunChainComponentsInLoopEvmTests[T TestingT[T]](t T, it ChainComponentsInterfaceTester[T], parallel bool) { + RunContractReaderInLoopTests[T](t, it, parallel) // Add ChainWriter tests here } func RunContractReaderEvmTests[T TestingT[T]](t T, it *EVMChainComponentsInterfaceTester[T]) { - RunContractReaderInterfaceTests[T](t, it, false) + RunContractReaderInterfaceTests[T](t, it, false, true) testCases := []Testcase[T]{ { Name: ContractReaderDynamicTypedTopicsFilterAndCorrectReturn, Test: func(t T) { - it.Setup(t) + cr := it.GetContractReader(t) + cw := it.GetContractWriter(t) + bindings := it.GetBindings(t) anyString := "foo" ctx := it.Helper.Context(t) - cr := it.GetContractReader(t) - bindings := it.GetBindings(t) require.NoError(t, cr.Bind(ctx, bindings)) type DynamicEvent struct { Field string } - SubmitTransactionToCW(t, it, "triggerEventWithDynamicTopic", DynamicEvent{Field: anyString}, bindings[0], types.Unconfirmed) + SubmitTransactionToCW(t, it, cw, "triggerEventWithDynamicTopic", DynamicEvent{Field: anyString}, bindings[0], types.Unconfirmed) input := struct{ Field string }{Field: anyString} tp := cr.(clcommontypes.ContractTypeProvider) @@ -88,17 +88,17 @@ func RunContractReaderEvmTests[T TestingT[T]](t T, it *EVMChainComponentsInterfa { Name: ContractReaderMultipleTopicCanFilterTogether, Test: func(t T) { - it.Setup(t) - ctx := it.Helper.Context(t) cr := it.GetContractReader(t) + cw := it.GetContractWriter(t) bindings := it.GetBindings(t) + ctx := it.Helper.Context(t) require.NoError(t, cr.Bind(ctx, bindings)) - triggerFourTopics(t, it, int32(1), int32(2), int32(3)) - triggerFourTopics(t, it, int32(2), int32(2), int32(3)) - triggerFourTopics(t, it, int32(1), int32(3), int32(3)) - triggerFourTopics(t, it, int32(1), int32(2), int32(4)) + triggerFourTopics(t, it, cw, bindings, int32(1), int32(2), int32(3)) + triggerFourTopics(t, it, cw, bindings, int32(2), int32(2), int32(3)) + triggerFourTopics(t, it, cw, bindings, int32(1), int32(3), int32(3)) + triggerFourTopics(t, it, cw, bindings, int32(1), int32(2), int32(4)) var bound types.BoundContract for idx := range bindings { @@ -121,17 +121,17 @@ func RunContractReaderEvmTests[T TestingT[T]](t T, it *EVMChainComponentsInterfa { Name: ContractReaderFilteringCanBeDoneOnHashedIndexedTopics, Test: func(t T) { - it.Setup(t) - cr := it.GetContractReader(t) - ctx := it.Helper.Context(t) + cw := it.GetContractWriter(t) bindings := it.GetBindings(t) + ctx := it.Helper.Context(t) + require.NoError(t, cr.Bind(ctx, bindings)) - triggerFourTopicsWithHashed(t, it, "1", [32]uint8{2}, [32]byte{5}) - triggerFourTopicsWithHashed(t, it, "2", [32]uint8{2}, [32]byte{3}) - triggerFourTopicsWithHashed(t, it, "1", [32]uint8{3}, [32]byte{3}) + triggerFourTopicsWithHashed(t, it, cw, bindings, "1", [32]uint8{2}, [32]byte{5}) + triggerFourTopicsWithHashed(t, it, cw, bindings, "2", [32]uint8{2}, [32]byte{3}) + triggerFourTopicsWithHashed(t, it, cw, bindings, "1", [32]uint8{3}, [32]byte{3}) var bound types.BoundContract for idx := range bindings { @@ -158,10 +158,9 @@ func RunContractReaderEvmTests[T TestingT[T]](t T, it *EVMChainComponentsInterfa { Name: ContractReaderBindReturnsErrorOnMissingContractAtAddress, Test: func(t T) { - it.Setup(t) + reader := it.GetContractReader(t) addr := common.BigToAddress(big.NewInt(42)) - reader := it.GetContractReader(t) ctx := it.Helper.Context(t) err := reader.Bind(ctx, []clcommontypes.BoundContract{{Name: AnyContractName, Address: addr.Hex()}}) @@ -170,29 +169,29 @@ func RunContractReaderEvmTests[T TestingT[T]](t T, it *EVMChainComponentsInterfa }, }, } - RunTests(t, it, testCases) + RunTestsInParallel(t, it, testCases) } -func RunContractReaderInLoopTests[T TestingT[T]](t T, it ChainComponentsInterfaceTester[T]) { - RunContractReaderInterfaceTests[T](t, it, false) +func RunContractReaderInLoopTests[T TestingT[T]](t T, it ChainComponentsInterfaceTester[T], parallel bool) { + RunContractReaderInterfaceTests[T](t, it, false, parallel) testCases := []Testcase[T]{ { Name: ContractReaderQueryKeyFilterOnDataWordsWithValueComparator, Test: func(t T) { - ctx := tests.Context(t) cr := it.GetContractReader(t) - require.NoError(t, cr.Bind(ctx, it.GetBindings(t))) + cw := it.GetContractWriter(t) bindings := it.GetBindings(t) - boundContract := BindingsByName(bindings, AnyContractName)[0] + ctx := tests.Context(t) require.NoError(t, cr.Bind(ctx, bindings)) + boundContract := BindingsByName(bindings, AnyContractName)[0] ts1 := CreateTestStruct[T](0, it) - _ = SubmitTransactionToCW(t, it, MethodTriggeringEvent, ts1, boundContract, types.Unconfirmed) + _ = SubmitTransactionToCW(t, it, cw, MethodTriggeringEvent, ts1, boundContract, types.Unconfirmed) ts2 := CreateTestStruct[T](15, it) - _ = SubmitTransactionToCW(t, it, MethodTriggeringEvent, ts2, boundContract, types.Unconfirmed) + _ = SubmitTransactionToCW(t, it, cw, MethodTriggeringEvent, ts2, boundContract, types.Unconfirmed) ts3 := CreateTestStruct[T](35, it) - _ = SubmitTransactionToCW(t, it, MethodTriggeringEvent, ts3, boundContract, types.Unconfirmed) + _ = SubmitTransactionToCW(t, it, cw, MethodTriggeringEvent, ts3, boundContract, types.Unconfirmed) ts := &TestStruct{} assert.Eventually(t, func() bool { sequences, err := cr.QueryKey(ctx, boundContract, query.KeyFilter{ @@ -211,19 +210,20 @@ func RunContractReaderInLoopTests[T TestingT[T]](t T, it ChainComponentsInterfac { Name: ContractReaderQueryKeyOnDataWordsWithValueComparatorOnNestedField, Test: func(t T) { - ctx := tests.Context(t) cr := it.GetContractReader(t) - require.NoError(t, cr.Bind(ctx, it.GetBindings(t))) + cw := it.GetContractWriter(t) bindings := it.GetBindings(t) + ctx := tests.Context(t) + boundContract := BindingsByName(bindings, AnyContractName)[0] require.NoError(t, cr.Bind(ctx, bindings)) ts1 := CreateTestStruct[T](0, it) - _ = SubmitTransactionToCW(t, it, MethodTriggeringEvent, ts1, boundContract, types.Unconfirmed) + _ = SubmitTransactionToCW(t, it, cw, MethodTriggeringEvent, ts1, boundContract, types.Unconfirmed) ts2 := CreateTestStruct[T](15, it) - _ = SubmitTransactionToCW(t, it, MethodTriggeringEvent, ts2, boundContract, types.Unconfirmed) + _ = SubmitTransactionToCW(t, it, cw, MethodTriggeringEvent, ts2, boundContract, types.Unconfirmed) ts3 := CreateTestStruct[T](35, it) - _ = SubmitTransactionToCW(t, it, MethodTriggeringEvent, ts3, boundContract, types.Unconfirmed) + _ = SubmitTransactionToCW(t, it, cw, MethodTriggeringEvent, ts3, boundContract, types.Unconfirmed) ts := &TestStruct{} assert.Eventually(t, func() bool { sequences, err := cr.QueryKey(ctx, boundContract, query.KeyFilter{ @@ -247,19 +247,19 @@ func RunContractReaderInLoopTests[T TestingT[T]](t T, it ChainComponentsInterfac { Name: ContractReaderQueryKeyFilterOnDataWordsWithValueComparatorOnDynamicField, Test: func(t T) { - ctx := tests.Context(t) cr := it.GetContractReader(t) - require.NoError(t, cr.Bind(ctx, it.GetBindings(t))) + cw := it.GetContractWriter(t) bindings := it.GetBindings(t) - boundContract := BindingsByName(bindings, AnyContractName)[0] + ctx := tests.Context(t) require.NoError(t, cr.Bind(ctx, bindings)) + boundContract := BindingsByName(bindings, AnyContractName)[0] ts1 := CreateTestStruct[T](0, it) - _ = SubmitTransactionToCW(t, it, MethodTriggeringEvent, ts1, boundContract, types.Unconfirmed) + _ = SubmitTransactionToCW(t, it, cw, MethodTriggeringEvent, ts1, boundContract, types.Unconfirmed) ts2 := CreateTestStruct[T](15, it) - _ = SubmitTransactionToCW(t, it, MethodTriggeringEvent, ts2, boundContract, types.Unconfirmed) + _ = SubmitTransactionToCW(t, it, cw, MethodTriggeringEvent, ts2, boundContract, types.Unconfirmed) ts3 := CreateTestStruct[T](35, it) - _ = SubmitTransactionToCW(t, it, MethodTriggeringEvent, ts3, boundContract, types.Unconfirmed) + _ = SubmitTransactionToCW(t, it, cw, MethodTriggeringEvent, ts3, boundContract, types.Unconfirmed) ts := &TestStruct{} assert.Eventually(t, func() bool { sequences, err := cr.QueryKey(ctx, boundContract, query.KeyFilter{ @@ -283,12 +283,12 @@ func RunContractReaderInLoopTests[T TestingT[T]](t T, it ChainComponentsInterfac { Name: ContractReaderQueryKeyFilteringOnDataWordsUsingValueComparatorsOnFieldsWithManualIndex, Test: func(t T) { - ctx := tests.Context(t) cr := it.GetContractReader(t) - require.NoError(t, cr.Bind(ctx, it.GetBindings(t))) + cw := it.GetContractWriter(t) bindings := it.GetBindings(t) - boundContract := BindingsByName(bindings, AnyContractName)[0] + ctx := tests.Context(t) require.NoError(t, cr.Bind(ctx, bindings)) + boundContract := BindingsByName(bindings, AnyContractName)[0] empty12Bytes := [12]byte{} val1, val2, val3, val4 := uint32(1), uint32(2), uint32(3), uint64(4) val5, val6, val7 := [32]byte{}, [32]byte{6}, [32]byte{7} @@ -313,10 +313,10 @@ func RunContractReaderInLoopTests[T TestingT[T]](t T, it ChainComponentsInterfac wrapExpectedRes := eventResAsStruct{Message: &resExpected} // emit the one we want to search for and a couple of random ones to confirm that filtering works - triggerStaticBytes(t, it, val1, val2, val3, val4, val5, val6, val7, raw) - triggerStaticBytes(t, it, 1337, 7331, 4747, val4, val5, val6, val7, raw) - triggerStaticBytes(t, it, 7331, 4747, 1337, val4, val5, val6, val7, raw) - triggerStaticBytes(t, it, 4747, 1337, 7331, val4, val5, val6, val7, raw) + triggerStaticBytes(t, it, cw, bindings, val1, val2, val3, val4, val5, val6, val7, raw) + triggerStaticBytes(t, it, cw, bindings, 1337, 7331, 4747, val4, val5, val6, val7, raw) + triggerStaticBytes(t, it, cw, bindings, 7331, 4747, 1337, val4, val5, val6, val7, raw) + triggerStaticBytes(t, it, cw, bindings, 4747, 1337, 7331, val4, val5, val6, val7, raw) assert.Eventually(t, func() bool { sequences, err := cr.QueryKey(ctx, boundContract, query.KeyFilter{ @@ -333,31 +333,33 @@ func RunContractReaderInLoopTests[T TestingT[T]](t T, it ChainComponentsInterfac }, }, } - RunTests(t, it, testCases) + if parallel { + RunTestsInParallel(t, it, testCases) + } else { + RunTests(t, it, testCases) + } } -func triggerFourTopics[T TestingT[T]](t T, it *EVMChainComponentsInterfaceTester[T], i1, i2, i3 int32) { +func triggerFourTopics[T TestingT[T]](t T, it *EVMChainComponentsInterfaceTester[T], cw clcommontypes.ContractWriter, bindings []clcommontypes.BoundContract, i1, i2, i3 int32) { type DynamicEvent struct { Field1 int32 Field2 int32 Field3 int32 } - contracts := it.GetBindings(t) - SubmitTransactionToCW(t, it, "triggerWithFourTopics", DynamicEvent{Field1: i1, Field2: i2, Field3: i3}, contracts[0], types.Unconfirmed) + SubmitTransactionToCW(t, it, cw, "triggerWithFourTopics", DynamicEvent{Field1: i1, Field2: i2, Field3: i3}, bindings[0], types.Unconfirmed) } -func triggerFourTopicsWithHashed[T TestingT[T]](t T, it *EVMChainComponentsInterfaceTester[T], i1 string, i2 [32]uint8, i3 [32]byte) { +func triggerFourTopicsWithHashed[T TestingT[T]](t T, it *EVMChainComponentsInterfaceTester[T], cw clcommontypes.ContractWriter, bindings []clcommontypes.BoundContract, i1 string, i2 [32]uint8, i3 [32]byte) { type DynamicEvent struct { Field1 string Field2 [32]uint8 Field3 [32]byte } - contracts := it.GetBindings(t) - SubmitTransactionToCW(t, it, "triggerWithFourTopicsWithHashed", DynamicEvent{Field1: i1, Field2: i2, Field3: i3}, contracts[0], types.Unconfirmed) + SubmitTransactionToCW(t, it, cw, "triggerWithFourTopicsWithHashed", DynamicEvent{Field1: i1, Field2: i2, Field3: i3}, bindings[0], types.Unconfirmed) } // triggerStaticBytes emits a staticBytes events and returns the expected event bytes. -func triggerStaticBytes[T TestingT[T]](t T, it ChainComponentsInterfaceTester[T], val1, val2, val3 uint32, val4 uint64, val5, val6, val7 [32]byte, raw []byte) { +func triggerStaticBytes[T TestingT[T]](t T, it ChainComponentsInterfaceTester[T], cw clcommontypes.ContractWriter, bindings []clcommontypes.BoundContract, val1, val2, val3 uint32, val4 uint64, val5, val6, val7 [32]byte, raw []byte) { type StaticBytesEvent struct { Val1 uint32 Val2 uint32 @@ -369,8 +371,7 @@ func triggerStaticBytes[T TestingT[T]](t T, it ChainComponentsInterfaceTester[T] Raw []byte } - contracts := it.GetBindings(t) - SubmitTransactionToCW(t, it, "triggerStaticBytes", + SubmitTransactionToCW(t, it, cw, "triggerStaticBytes", StaticBytesEvent{ Val1: val1, Val2: val2, @@ -381,5 +382,5 @@ func triggerStaticBytes[T TestingT[T]](t T, it ChainComponentsInterfaceTester[T] Val7: val7, Raw: raw, }, - contracts[0], types.Unconfirmed) + bindings[0], types.Unconfirmed) } diff --git a/core/services/relay/evm/exec_provider.go b/core/services/relay/evm/exec_provider.go index da190d20356..e5b00205caa 100644 --- a/core/services/relay/evm/exec_provider.go +++ b/core/services/relay/evm/exec_provider.go @@ -10,13 +10,14 @@ import ( "go.uber.org/multierr" "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/types" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/tokendata/lbtc" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" @@ -24,22 +25,25 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/estimatorconfig" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/tokendata/usdc" ) type SrcExecProvider struct { - lggr logger.Logger - versionFinder ccip.VersionFinder - client client.Client - lp logpoller.LogPoller - startBlock uint64 - estimator gas.EvmFeeEstimator - maxGasPrice *big.Int - usdcReader *ccip.USDCReaderImpl - usdcAttestationAPI string - usdcAttestationAPITimeoutSeconds int - usdcAttestationAPIIntervalMilliseconds int - usdcSrcMsgTransmitterAddr common.Address + lggr logger.Logger + versionFinder ccip.VersionFinder + client client.Client + lp logpoller.LogPoller + startBlock uint64 + estimator gas.EvmFeeEstimator + maxGasPrice *big.Int + usdcReader *ccip.USDCReaderImpl + usdcConfig config.USDCConfig + lbtcConfig config.LBTCConfig + + feeEstimatorConfig estimatorconfig.FeeEstimatorConfigProvider + + // TODO: Add lbtc reader & api fields // these values are nil and are updated for Close() seenOnRampAddress *cciptypes.Address @@ -57,33 +61,31 @@ func NewSrcExecProvider( lp logpoller.LogPoller, startBlock uint64, jobID string, - usdcAttestationAPI string, - usdcAttestationAPITimeoutSeconds int, - usdcAttestationAPIIntervalMilliseconds int, - usdcSrcMsgTransmitterAddr common.Address, + usdcConfig config.USDCConfig, + lbtcConfig config.LBTCConfig, + feeEstimatorConfig estimatorconfig.FeeEstimatorConfigProvider, ) (commontypes.CCIPExecProvider, error) { var usdcReader *ccip.USDCReaderImpl var err error - if usdcAttestationAPI != "" { - usdcReader, err = ccip.NewUSDCReader(ctx, lggr, jobID, usdcSrcMsgTransmitterAddr, lp, true) + if usdcConfig.AttestationAPI != "" { + usdcReader, err = ccip.NewUSDCReader(ctx, lggr, jobID, usdcConfig.SourceMessageTransmitterAddress, lp, true) if err != nil { return nil, fmt.Errorf("new usdc reader: %w", err) } } return &SrcExecProvider{ - lggr: logger.Named(lggr, "SrcExecProvider"), - versionFinder: versionFinder, - client: client, - estimator: estimator, - maxGasPrice: maxGasPrice, - lp: lp, - startBlock: startBlock, - usdcReader: usdcReader, - usdcAttestationAPI: usdcAttestationAPI, - usdcAttestationAPITimeoutSeconds: usdcAttestationAPITimeoutSeconds, - usdcAttestationAPIIntervalMilliseconds: usdcAttestationAPIIntervalMilliseconds, - usdcSrcMsgTransmitterAddr: usdcSrcMsgTransmitterAddr, + lggr: logger.Named(lggr, "SrcExecProvider"), + versionFinder: versionFinder, + client: client, + estimator: estimator, + maxGasPrice: maxGasPrice, + lp: lp, + startBlock: startBlock, + usdcReader: usdcReader, + usdcConfig: usdcConfig, + lbtcConfig: lbtcConfig, + feeEstimatorConfig: feeEstimatorConfig, }, nil } @@ -113,10 +115,10 @@ func (s *SrcExecProvider) Close() error { return ccip.CloseOnRampReader(ctx, s.lggr, versionFinder, *s.seenSourceChainSelector, *s.seenDestChainSelector, *s.seenOnRampAddress, s.lp, s.client) }) unregisterFuncs = append(unregisterFuncs, func(ctx context.Context) error { - if s.usdcAttestationAPI == "" { + if s.usdcConfig.AttestationAPI == "" { return nil } - return ccip.CloseUSDCReader(ctx, s.lggr, s.lggr.Name(), s.usdcSrcMsgTransmitterAddr, s.lp) + return ccip.CloseUSDCReader(ctx, s.lggr, s.lggr.Name(), s.usdcConfig.SourceMessageTransmitterAddress, s.lp) }) var multiErr error for _, fn := range unregisterFuncs { @@ -166,7 +168,7 @@ func (s *SrcExecProvider) GetTransactionStatus(ctx context.Context, transactionI } func (s *SrcExecProvider) NewCommitStoreReader(ctx context.Context, addr cciptypes.Address) (commitStoreReader cciptypes.CommitStoreReader, err error) { - commitStoreReader = NewIncompleteSourceCommitStoreReader(s.estimator, s.maxGasPrice) + commitStoreReader = NewIncompleteSourceCommitStoreReader(s.estimator, s.maxGasPrice, s.feeEstimatorConfig) return } @@ -179,6 +181,10 @@ func (s *SrcExecProvider) NewOnRampReader(ctx context.Context, onRampAddress cci versionFinder := ccip.NewEvmVersionFinder() onRampReader, err = ccip.NewOnRampReader(ctx, s.lggr, versionFinder, sourceChainSelector, destChainSelector, onRampAddress, s.lp, s.client) + if err != nil { + return nil, err + } + s.feeEstimatorConfig.SetOnRampReader(onRampReader) return } @@ -188,24 +194,42 @@ func (s *SrcExecProvider) NewPriceRegistryReader(ctx context.Context, addr ccipt return } -func (s *SrcExecProvider) NewTokenDataReader(ctx context.Context, tokenAddress cciptypes.Address) (tokenDataReader cciptypes.TokenDataReader, err error) { - attestationURI, err2 := url.ParseRequestURI(s.usdcAttestationAPI) - if err2 != nil { - return nil, fmt.Errorf("failed to parse USDC attestation API: %w", err2) +func (s *SrcExecProvider) NewTokenDataReader(ctx context.Context, tokenAddress cciptypes.Address) (cciptypes.TokenDataReader, error) { + tokenAddr, err := ccip.GenericAddrToEvm(tokenAddress) + if err != nil { + return nil, fmt.Errorf("failed to parse token address: %w", err) } - tokenAddr, err2 := ccip.GenericAddrToEvm(tokenAddress) - if err2 != nil { - return nil, fmt.Errorf("failed to parse token address: %w", err2) + switch tokenAddr { + case s.usdcConfig.SourceTokenAddress: + attestationURI, err := url.ParseRequestURI(s.usdcConfig.AttestationAPI) + if err != nil { + return nil, fmt.Errorf("failed to parse USDC attestation API: %w", err) + } + return usdc.NewUSDCTokenDataReader( + s.lggr, + s.usdcReader, + attestationURI, + //nolint:gosec // integer overflow + int(s.usdcConfig.AttestationAPITimeoutSeconds), + tokenAddr, + time.Duration(s.usdcConfig.AttestationAPIIntervalMilliseconds)*time.Millisecond, + ), nil + case s.lbtcConfig.SourceTokenAddress: + attestationURI, err := url.ParseRequestURI(s.lbtcConfig.AttestationAPI) + if err != nil { + return nil, fmt.Errorf("failed to parse USDC attestation API: %w", err) + } + return lbtc.NewLBTCTokenDataReader( + s.lggr, + attestationURI, + //nolint:gosec // integer overflow + int(s.lbtcConfig.AttestationAPITimeoutSeconds), + tokenAddr, + time.Duration(s.lbtcConfig.AttestationAPIIntervalMilliseconds)*time.Millisecond, + ), nil + default: + return nil, fmt.Errorf("unsupported token address: %s", tokenAddress) } - tokenDataReader = usdc.NewUSDCTokenDataReader( - s.lggr, - s.usdcReader, - attestationURI, - s.usdcAttestationAPITimeoutSeconds, - tokenAddr, - time.Duration(s.usdcAttestationAPIIntervalMilliseconds)*time.Millisecond, - ) - return } func (s *SrcExecProvider) NewTokenPoolBatchedReader(ctx context.Context, offRampAddr cciptypes.Address, sourceChainSelector uint64) (cciptypes.TokenPoolBatchedReader, error) { @@ -239,6 +263,7 @@ type DstExecProvider struct { configWatcher *configWatcher gasEstimator gas.EvmFeeEstimator maxGasPrice big.Int + feeEstimatorConfig estimatorconfig.FeeEstimatorConfigProvider txm txmgr.TxManager offRampAddress cciptypes.Address @@ -256,6 +281,7 @@ func NewDstExecProvider( configWatcher *configWatcher, gasEstimator gas.EvmFeeEstimator, maxGasPrice big.Int, + feeEstimatorConfig estimatorconfig.FeeEstimatorConfigProvider, txm txmgr.TxManager, offRampAddress cciptypes.Address, ) (commontypes.CCIPExecProvider, error) { @@ -269,6 +295,7 @@ func NewDstExecProvider( configWatcher: configWatcher, gasEstimator: gasEstimator, maxGasPrice: maxGasPrice, + feeEstimatorConfig: feeEstimatorConfig, txm: txm, offRampAddress: offRampAddress, }, nil @@ -299,10 +326,10 @@ func (d *DstExecProvider) Close() error { if d.seenCommitStoreAddr == nil { return nil } - return ccip.CloseCommitStoreReader(ctx, d.lggr, versionFinder, *d.seenCommitStoreAddr, d.client, d.lp) + return ccip.CloseCommitStoreReader(ctx, d.lggr, versionFinder, *d.seenCommitStoreAddr, d.client, d.lp, d.feeEstimatorConfig) }) unregisterFuncs = append(unregisterFuncs, func(ctx context.Context) error { - return ccip.CloseOffRampReader(ctx, d.lggr, versionFinder, d.offRampAddress, d.client, d.lp, nil, big.NewInt(0)) + return ccip.CloseOffRampReader(ctx, d.lggr, versionFinder, d.offRampAddress, d.client, d.lp, nil, big.NewInt(0), d.feeEstimatorConfig) }) var multiErr error @@ -350,12 +377,12 @@ func (d *DstExecProvider) NewCommitStoreReader(ctx context.Context, addr cciptyp d.seenCommitStoreAddr = &addr versionFinder := ccip.NewEvmVersionFinder() - commitStoreReader, err = NewIncompleteDestCommitStoreReader(ctx, d.lggr, versionFinder, addr, d.client, d.lp) + commitStoreReader, err = NewIncompleteDestCommitStoreReader(ctx, d.lggr, versionFinder, addr, d.client, d.lp, d.feeEstimatorConfig) return } func (d *DstExecProvider) NewOffRampReader(ctx context.Context, offRampAddress cciptypes.Address) (offRampReader cciptypes.OffRampReader, err error) { - offRampReader, err = ccip.NewOffRampReader(ctx, d.lggr, d.versionFinder, offRampAddress, d.client, d.lp, d.gasEstimator, &d.maxGasPrice, true) + offRampReader, err = ccip.NewOffRampReader(ctx, d.lggr, d.versionFinder, offRampAddress, d.client, d.lp, d.gasEstimator, &d.maxGasPrice, true, d.feeEstimatorConfig) return } diff --git a/core/services/relay/evm/interceptors/mantle/interceptor.go b/core/services/relay/evm/interceptors/mantle/interceptor.go new file mode 100644 index 00000000000..c6ace3e6cbc --- /dev/null +++ b/core/services/relay/evm/interceptors/mantle/interceptor.go @@ -0,0 +1,85 @@ +package mantle + +import ( + "context" + "errors" + "fmt" + "math/big" + "strings" + "time" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + + evmClient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" +) + +const ( + // tokenRatio is not volatile and can be requested not often. + tokenRatioUpdateInterval = 60 * time.Minute + // tokenRatio fetches the tokenRatio used for Mantle's gas price calculation + tokenRatioMethod = "tokenRatio" + mantleTokenRatioAbiString = `[{"inputs":[],"name":"tokenRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]` +) + +type Interceptor struct { + client evmClient.Client + tokenRatioCallData []byte + tokenRatio *big.Int + tokenRatioLastUpdate time.Time + oracleAddress common.Address +} + +func NewInterceptor(_ context.Context, client evmClient.Client, address *evmtypes.EIP55Address) (*Interceptor, error) { + if address == nil { + return nil, errors.New("oracle address is missing") + } + // Encode calldata for tokenRatio method + tokenRatioMethodAbi, err := abi.JSON(strings.NewReader(mantleTokenRatioAbiString)) + if err != nil { + return nil, fmt.Errorf("failed to parse GasPriceOracle %s() method ABI for Mantle; %w", tokenRatioMethod, err) + } + tokenRatioCallData, err := tokenRatioMethodAbi.Pack(tokenRatioMethod) + if err != nil { + return nil, fmt.Errorf("failed to parse GasPriceOracle %s() calldata for Mantle; %w", tokenRatioMethod, err) + } + + return &Interceptor{ + client: client, + tokenRatioCallData: tokenRatioCallData, + oracleAddress: address.Address(), + }, nil +} + +// ModifyGasPriceComponents returns modified gasPrice. +func (i *Interceptor) ModifyGasPriceComponents(ctx context.Context, execGasPrice, daGasPrice *big.Int) (*big.Int, *big.Int, error) { + if time.Since(i.tokenRatioLastUpdate) > tokenRatioUpdateInterval { + mantleTokenRatio, err := i.getMantleTokenRatio(ctx) + if err != nil { + return nil, nil, err + } + + i.tokenRatio, i.tokenRatioLastUpdate = mantleTokenRatio, time.Now() + } + + // multiply daGasPrice and execGas price by tokenRatio + newExecGasPrice := new(big.Int).Mul(execGasPrice, i.tokenRatio) + newDAGasPrice := new(big.Int).Mul(daGasPrice, i.tokenRatio) + return newExecGasPrice, newDAGasPrice, nil +} + +// getMantleTokenRatio Requests and returns a token ratio value for the Mantle chain. +func (i *Interceptor) getMantleTokenRatio(ctx context.Context) (*big.Int, error) { + tokenRatio, err := i.client.CallContract(ctx, ethereum.CallMsg{ + To: &i.oracleAddress, + Data: i.tokenRatioCallData, + }, nil) + + if err != nil { + return nil, fmt.Errorf("getMantleTokenRatio call failed: %w", err) + } + + return new(big.Int).SetBytes(tokenRatio), nil +} diff --git a/core/services/relay/evm/interceptors/mantle/interceptor_test.go b/core/services/relay/evm/interceptors/mantle/interceptor_test.go new file mode 100644 index 00000000000..6fa485de487 --- /dev/null +++ b/core/services/relay/evm/interceptors/mantle/interceptor_test.go @@ -0,0 +1,103 @@ +package mantle + +import ( + "context" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" +) + +var randomAddress = types.MustEIP55Address(utils.RandomAddress().String()) + +func TestInterceptor(t *testing.T) { + ethClient := mocks.NewClient(t) + ctx := context.Background() + + _, err := NewInterceptor(ctx, ethClient, nil) + require.Error(t, err) + + tokenRatio := big.NewInt(10) + interceptor, err := NewInterceptor(ctx, ethClient, &randomAddress) + require.NoError(t, err) + + // request token ratio + ethClient.On("CallContract", ctx, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})). + Return(common.BigToHash(tokenRatio).Bytes(), nil).Once() + + modExecGasPrice, modDAGasPrice, err := interceptor.ModifyGasPriceComponents(ctx, big.NewInt(1), big.NewInt(1)) + require.NoError(t, err) + require.Equal(t, int64(10), modExecGasPrice.Int64()) + require.Equal(t, int64(10), modDAGasPrice.Int64()) + + // second call won't invoke eth client + modExecGasPrice, modDAGasPrice, err = interceptor.ModifyGasPriceComponents(ctx, big.NewInt(2), big.NewInt(1)) + require.NoError(t, err) + require.Equal(t, int64(20), modExecGasPrice.Int64()) + require.Equal(t, int64(10), modDAGasPrice.Int64()) +} + +func TestModifyGasPriceComponents(t *testing.T) { + testCases := map[string]struct { + execGasPrice *big.Int + daGasPrice *big.Int + tokenRatio *big.Int + resultExecGasPrice *big.Int + resultDAGasPrice *big.Int + }{ + "regular": { + execGasPrice: big.NewInt(1000), + daGasPrice: big.NewInt(100), + resultExecGasPrice: big.NewInt(2000), + resultDAGasPrice: big.NewInt(200), + tokenRatio: big.NewInt(2), + }, + "zero DAGasPrice": { + execGasPrice: big.NewInt(1000), + daGasPrice: big.NewInt(0), + resultExecGasPrice: big.NewInt(5000), + resultDAGasPrice: big.NewInt(0), + tokenRatio: big.NewInt(5), + }, + "zero ExecGasPrice": { + execGasPrice: big.NewInt(0), + daGasPrice: big.NewInt(10), + resultExecGasPrice: big.NewInt(0), + resultDAGasPrice: big.NewInt(50), + tokenRatio: big.NewInt(5), + }, + "zero token ratio": { + execGasPrice: big.NewInt(15), + daGasPrice: big.NewInt(10), + resultExecGasPrice: big.NewInt(0), + resultDAGasPrice: big.NewInt(0), + tokenRatio: big.NewInt(0), + }, + } + + for tcName, tc := range testCases { + t.Run(tcName, func(t *testing.T) { + ethClient := mocks.NewClient(t) + ctx := context.Background() + + interceptor, err := NewInterceptor(ctx, ethClient, &randomAddress) + require.NoError(t, err) + + // request token ratio + ethClient.On("CallContract", ctx, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})). + Return(common.BigToHash(tc.tokenRatio).Bytes(), nil).Once() + + modExecGasPrice, modDAGasPrice, err := interceptor.ModifyGasPriceComponents(ctx, tc.execGasPrice, tc.daGasPrice) + require.NoError(t, err) + require.Equal(t, tc.resultExecGasPrice.Int64(), modExecGasPrice.Int64()) + require.Equal(t, tc.resultDAGasPrice.Int64(), modDAGasPrice.Int64()) + }) + } +} diff --git a/core/services/relay/evm/mercury/mocks/async_deleter.go b/core/services/relay/evm/mercury/mocks/async_deleter.go index f94414af4a3..ce9dee690e5 100644 --- a/core/services/relay/evm/mercury/mocks/async_deleter.go +++ b/core/services/relay/evm/mercury/mocks/async_deleter.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -49,7 +49,7 @@ func (_c *AsyncDeleter_AsyncDelete_Call) Return() *AsyncDeleter_AsyncDelete_Call } func (_c *AsyncDeleter_AsyncDelete_Call) RunAndReturn(run func(*pb.TransmitRequest)) *AsyncDeleter_AsyncDelete_Call { - _c.Call.Return(run) + _c.Run(run) return _c } diff --git a/core/services/relay/evm/mercury/mocks/pipeline.go b/core/services/relay/evm/mercury/mocks/pipeline.go index a7183c9a037..429eba66674 100644 --- a/core/services/relay/evm/mercury/mocks/pipeline.go +++ b/core/services/relay/evm/mercury/mocks/pipeline.go @@ -41,3 +41,4 @@ func (m *MockTask) TaskTimeout() (time.Duration, bool) { return 0, false } func (m *MockTask) TaskRetries() uint32 { return 0 } func (m *MockTask) TaskMinBackoff() time.Duration { return 0 } func (m *MockTask) TaskMaxBackoff() time.Duration { return 0 } +func (m *MockTask) TaskStreamID() *uint32 { return nil } diff --git a/core/services/relay/evm/mercury/orm_test.go b/core/services/relay/evm/mercury/orm_test.go index f3ff70cdced..090b3f06eac 100644 --- a/core/services/relay/evm/mercury/orm_test.go +++ b/core/services/relay/evm/mercury/orm_test.go @@ -178,17 +178,17 @@ func TestORM_InsertTransmitRequest_MultipleServerURLs(t *testing.T) { transmissions, err := orm.GetTransmitRequests(ctx, sURL, jobID) require.NoError(t, err) require.Len(t, transmissions, 1) - assert.Equal(t, transmissions[0], &Transmission{Req: &pb.TransmitRequest{Payload: reports[0]}, ReportCtx: reportContexts[0]}) + assert.Equal(t, &Transmission{Req: &pb.TransmitRequest{Payload: reports[0]}, ReportCtx: reportContexts[0]}, transmissions[0]) transmissions, err = orm.GetTransmitRequests(ctx, sURL2, jobID) require.NoError(t, err) require.Len(t, transmissions, 1) - assert.Equal(t, transmissions[0], &Transmission{Req: &pb.TransmitRequest{Payload: reports[0]}, ReportCtx: reportContexts[0]}) + assert.Equal(t, &Transmission{Req: &pb.TransmitRequest{Payload: reports[0]}, ReportCtx: reportContexts[0]}, transmissions[0]) transmissions, err = orm.GetTransmitRequests(ctx, sURL3, jobID) require.NoError(t, err) require.Len(t, transmissions, 1) - assert.Equal(t, transmissions[0], &Transmission{Req: &pb.TransmitRequest{Payload: reports[0]}, ReportCtx: reportContexts[0]}) + assert.Equal(t, &Transmission{Req: &pb.TransmitRequest{Payload: reports[0]}, ReportCtx: reportContexts[0]}, transmissions[0]) l, err := orm.LatestReport(testutils.Context(t), feedID) require.NoError(t, err) diff --git a/core/services/relay/evm/mercury/persistence_manager_test.go b/core/services/relay/evm/mercury/persistence_manager_test.go index 1ba999614a6..f2f4c379a4c 100644 --- a/core/services/relay/evm/mercury/persistence_manager_test.go +++ b/core/services/relay/evm/mercury/persistence_manager_test.go @@ -129,7 +129,7 @@ func TestPersistenceManagerPrune(t *testing.T) { pm2, _ := bootstrapPersistenceManager(t, jobID2, db) for i := 0; i < 20; i++ { - err := pm2.Insert(ctx, &pb.TransmitRequest{Payload: reports[i]}, ocrtypes.ReportContext{ReportTimestamp: ocrtypes.ReportTimestamp{Epoch: uint32(i)}}) + err := pm2.Insert(ctx, &pb.TransmitRequest{Payload: reports[i]}, ocrtypes.ReportContext{ReportTimestamp: ocrtypes.ReportTimestamp{Epoch: uint32(i)}}) //nolint:gosec // G115 require.NoError(t, err) } diff --git a/core/services/relay/evm/mercury/transmitter.go b/core/services/relay/evm/mercury/transmitter.go index bdd324988bf..be500593bf3 100644 --- a/core/services/relay/evm/mercury/transmitter.go +++ b/core/services/relay/evm/mercury/transmitter.go @@ -236,7 +236,7 @@ func (s *server) runQueueLoop(stopCh services.StopChan, wg *sync.WaitGroup, feed } res, err := func(ctx context.Context) (*pb.TransmitResponse, error) { ctx, cancel := context.WithTimeout(ctx, utils.WithJitter(s.transmitTimeout)) - cancel() + defer cancel() return s.c.Transmit(ctx, t.Req) }(ctx) if ctx.Err() != nil { @@ -289,7 +289,6 @@ func (s *server) runQueueLoop(stopCh services.StopChan, wg *sync.WaitGroup, feed const TransmitQueueMaxSize = 10_000 // hardcode this for legacy transmitter since we want the config var to apply only to LLO func newServer(lggr logger.Logger, cfg TransmitterConfig, client wsrpc.Client, pm *PersistenceManager, serverURL, feedIDHex string) *server { - return &server{ logger.Sugared(lggr), cfg.TransmitTimeout().Duration(), diff --git a/core/services/relay/evm/mercury/transmitter_test.go b/core/services/relay/evm/mercury/transmitter_test.go index 70ee8fca74f..079f765f07c 100644 --- a/core/services/relay/evm/mercury/transmitter_test.go +++ b/core/services/relay/evm/mercury/transmitter_test.go @@ -28,6 +28,10 @@ import ( type mockCfg struct{} +func (m mockCfg) Protocol() string { + return "" +} + func (m mockCfg) TransmitQueueMaxSize() uint32 { return 10_000 } diff --git a/core/services/relay/evm/mercury/wsrpc/client.go b/core/services/relay/evm/mercury/wsrpc/client.go index c87b555e6a5..7aa7de27b8d 100644 --- a/core/services/relay/evm/mercury/wsrpc/client.go +++ b/core/services/relay/evm/mercury/wsrpc/client.go @@ -16,10 +16,13 @@ import ( "github.com/smartcontractkit/wsrpc" "github.com/smartcontractkit/wsrpc/connectivity" + "github.com/smartcontractkit/chainlink-data-streams/rpc" + "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/csakey" + "github.com/smartcontractkit/chainlink/v2/core/services/llo/grpc" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/cache" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/pb" "github.com/smartcontractkit/chainlink/v2/core/utils" @@ -70,11 +73,14 @@ type Client interface { } type Conn interface { + wsrpc.ClientInterface WaitForReady(ctx context.Context) bool GetState() grpc_connectivity.State Close() error } +type DialWithContextFunc func(ctxCaller context.Context, target string, opts ...wsrpc.DialOption) (Conn, error) + type client struct { services.StateMachine @@ -82,9 +88,12 @@ type client struct { serverPubKey []byte serverURL string + dialWithContext DialWithContextFunc + logger logger.Logger conn Conn rawClient pb.MercuryClient + mu sync.RWMutex consecutiveTimeoutCnt atomic.Int32 wg sync.WaitGroup @@ -101,25 +110,47 @@ type client struct { connectionResetCountMetric prometheus.Counter } +type ClientOpts struct { + Logger logger.Logger + ClientPrivKey csakey.KeyV2 + ServerPubKey []byte + ServerURL string + CacheSet cache.CacheSet + + // DialWithContext allows optional dependency injection for testing + DialWithContext DialWithContextFunc +} + // Consumers of wsrpc package should not usually call NewClient directly, but instead use the Pool -func NewClient(lggr logger.Logger, clientPrivKey csakey.KeyV2, serverPubKey []byte, serverURL string, cacheSet cache.CacheSet) Client { - return newClient(lggr, clientPrivKey, serverPubKey, serverURL, cacheSet) +func NewClient(opts ClientOpts) Client { + return newClient(opts) } -func newClient(lggr logger.Logger, clientPrivKey csakey.KeyV2, serverPubKey []byte, serverURL string, cacheSet cache.CacheSet) *client { +func newClient(opts ClientOpts) *client { + var dialWithContext DialWithContextFunc + if opts.DialWithContext != nil { + dialWithContext = opts.DialWithContext + } else { + // NOTE: Wrap here since wsrpc.DialWithContext returns a concrete *wsrpc.Conn, not an interface + dialWithContext = func(ctxCaller context.Context, target string, opts ...wsrpc.DialOption) (Conn, error) { + conn, err := wsrpc.DialWithContext(ctxCaller, target, opts...) + return conn, err + } + } return &client{ - csaKey: clientPrivKey, - serverPubKey: serverPubKey, - serverURL: serverURL, - logger: lggr.Named("WSRPC").Named(serverURL).With("serverURL", serverURL), + dialWithContext: dialWithContext, + csaKey: opts.ClientPrivKey, + serverPubKey: opts.ServerPubKey, + serverURL: opts.ServerURL, + logger: opts.Logger.Named("WSRPC").Named(opts.ServerURL).With("serverURL", opts.ServerURL), chResetTransport: make(chan struct{}, 1), - cacheSet: cacheSet, + cacheSet: opts.CacheSet, chStop: make(services.StopChan), - timeoutCountMetric: timeoutCount.WithLabelValues(serverURL), - dialCountMetric: dialCount.WithLabelValues(serverURL), - dialSuccessCountMetric: dialSuccessCount.WithLabelValues(serverURL), - dialErrorCountMetric: dialErrorCount.WithLabelValues(serverURL), - connectionResetCountMetric: connectionResetCount.WithLabelValues(serverURL), + timeoutCountMetric: timeoutCount.WithLabelValues(opts.ServerURL), + dialCountMetric: dialCount.WithLabelValues(opts.ServerURL), + dialSuccessCountMetric: dialSuccessCount.WithLabelValues(opts.ServerURL), + dialErrorCountMetric: dialErrorCount.WithLabelValues(opts.ServerURL), + connectionResetCountMetric: connectionResetCount.WithLabelValues(opts.ServerURL), } } @@ -148,7 +179,7 @@ func (w *client) Start(ctx context.Context) error { // with error. func (w *client) dial(ctx context.Context, opts ...wsrpc.DialOption) error { w.dialCountMetric.Inc() - conn, err := wsrpc.DialWithContext(ctx, w.serverURL, + conn, err := w.dialWithContext(ctx, w.serverURL, append(opts, wsrpc.WithTransportCreds(w.csaKey.Raw().Bytes(), w.serverPubKey), wsrpc.WithLogger(w.logger), @@ -161,8 +192,10 @@ func (w *client) dial(ctx context.Context, opts ...wsrpc.DialOption) error { } w.dialSuccessCountMetric.Inc() setLivenessMetric(true) + w.mu.Lock() w.conn = conn w.rawClient = pb.NewMercuryClient(conn) + w.mu.Unlock() return nil } @@ -184,6 +217,8 @@ func (w *client) runloop() { func (w *client) resetTransport() { w.connectionResetCountMetric.Inc() ok := w.IfStarted(func() { + w.mu.RLock() + defer w.mu.RUnlock() w.conn.Close() // Close is safe to call multiple times }) if !ok { @@ -211,7 +246,9 @@ func (w *client) resetTransport() { func (w *client) Close() error { return w.StopOnce("WSRPC Client", func() error { close(w.chStop) + w.mu.RLock() w.conn.Close() + w.mu.RUnlock() w.wg.Wait() return nil }) @@ -251,24 +288,39 @@ func (w *client) waitForReady(ctx context.Context) (err error) { } func (w *client) Transmit(ctx context.Context, req *pb.TransmitRequest) (resp *pb.TransmitResponse, err error) { - w.logger.Trace("Transmit") - start := time.Now() - if err = w.waitForReady(ctx); err != nil { - return nil, errors.Wrap(err, "Transmit call failed") - } - resp, err = w.rawClient.Transmit(ctx, req) - w.handleTimeout(err) - if err != nil { - w.logger.Warnw("Transmit call failed due to networking error", "err", err, "resp", resp) - incRequestStatusMetric(statusFailed) - } else { - w.logger.Tracew("Transmit call succeeded", "resp", resp) - incRequestStatusMetric(statusSuccess) - setRequestLatencyMetric(float64(time.Since(start).Milliseconds())) + ok := w.IfStarted(func() { + w.logger.Trace("Transmit") + start := time.Now() + if err = w.waitForReady(ctx); err != nil { + err = errors.Wrap(err, "Transmit call failed") + return + } + w.mu.RLock() + rc := w.rawClient + w.mu.RUnlock() + resp, err = rc.Transmit(ctx, req) + w.handleTimeout(err) + if err != nil { + w.logger.Warnw("Transmit call failed due to networking error", "err", err, "resp", resp) + incRequestStatusMetric(statusFailed) + } else { + w.logger.Tracew("Transmit call succeeded", "resp", resp) + incRequestStatusMetric(statusSuccess) + setRequestLatencyMetric(float64(time.Since(start).Milliseconds())) + } + }) + if !ok { + err = errors.New("client is not started") } return } +// hacky workaround to trap panics from buggy underlying wsrpc lib and restart +// the connection from a known good state +func (w *client) handlePanic(r interface{}) { + w.chResetTransport <- struct{}{} +} + func (w *client) handleTimeout(err error) { if errors.Is(err, context.DeadlineExceeded) { w.timeoutCountMetric.Inc() @@ -303,27 +355,37 @@ func (w *client) handleTimeout(err error) { } func (w *client) LatestReport(ctx context.Context, req *pb.LatestReportRequest) (resp *pb.LatestReportResponse, err error) { - lggr := w.logger.With("req.FeedId", hexutil.Encode(req.FeedId)) - lggr.Trace("LatestReport") - if err = w.waitForReady(ctx); err != nil { - return nil, errors.Wrap(err, "LatestReport failed") - } - var cached bool - if w.cache == nil { - resp, err = w.rawClient.LatestReport(ctx, req) - w.handleTimeout(err) - } else { - cached = true - resp, err = w.cache.LatestReport(ctx, req) - } - if err != nil { - lggr.Errorw("LatestReport failed", "err", err, "resp", resp, "cached", cached) - } else if resp.Error != "" { - lggr.Errorw("LatestReport failed; mercury server returned error", "err", resp.Error, "resp", resp, "cached", cached) - } else if !cached { - lggr.Debugw("LatestReport succeeded", "resp", resp, "cached", cached) - } else { - lggr.Tracew("LatestReport succeeded", "resp", resp, "cached", cached) + ok := w.IfStarted(func() { + lggr := w.logger.With("req.FeedId", hexutil.Encode(req.FeedId)) + lggr.Trace("LatestReport") + if err = w.waitForReady(ctx); err != nil { + err = errors.Wrap(err, "LatestReport failed") + return + } + var cached bool + if w.cache == nil { + w.mu.RLock() + rc := w.rawClient + w.mu.RUnlock() + resp, err = rc.LatestReport(ctx, req) + w.handleTimeout(err) + } else { + cached = true + resp, err = w.cache.LatestReport(ctx, req) + } + switch { + case err != nil: + lggr.Errorw("LatestReport failed", "err", err, "resp", resp, "cached", cached) + case resp.Error != "": + lggr.Errorw("LatestReport failed; mercury server returned error", "err", resp.Error, "resp", resp, "cached", cached) + case !cached: + lggr.Debugw("LatestReport succeeded", "resp", resp, "cached", cached) + default: + lggr.Tracew("LatestReport succeeded", "resp", resp, "cached", cached) + } + }) + if !ok { + err = errors.New("client is not started") } return } @@ -333,5 +395,28 @@ func (w *client) ServerURL() string { } func (w *client) RawClient() pb.MercuryClient { + w.mu.RLock() + defer w.mu.RUnlock() return w.rawClient } + +var _ grpc.Client = GRPCCompatibilityWrapper{} + +type GRPCCompatibilityWrapper struct { + Client +} + +func (w GRPCCompatibilityWrapper) Transmit(ctx context.Context, in *rpc.TransmitRequest) (*rpc.TransmitResponse, error) { + req := &pb.TransmitRequest{ + Payload: in.Payload, + ReportFormat: in.ReportFormat, + } + resp, err := w.Client.Transmit(ctx, req) + if err != nil { + return nil, err + } + return &rpc.TransmitResponse{ + Code: resp.Code, + Error: resp.Error, + }, nil +} diff --git a/core/services/relay/evm/mercury/wsrpc/client_test.go b/core/services/relay/evm/mercury/wsrpc/client_test.go index 539148f4ff6..7c6706eddf8 100644 --- a/core/services/relay/evm/mercury/wsrpc/client_test.go +++ b/core/services/relay/evm/mercury/wsrpc/client_test.go @@ -74,7 +74,15 @@ func Test_Client_Transmit(t *testing.T) { conn := &mocks.MockConn{ Ready: true, } - c := newClient(lggr, csakey.KeyV2{}, nil, "", noopCacheSet) + opts := ClientOpts{ + lggr, + csakey.KeyV2{}, + nil, + "", + noopCacheSet, + nil, + } + c := newClient(opts) c.conn = conn c.rawClient = wsrpcClient require.NoError(t, c.StartOnce("Mock WSRPC Client", func() error { return nil })) @@ -159,7 +167,7 @@ func Test_Client_LatestReport(t *testing.T) { conn := &mocks.MockConn{ Ready: true, } - c := newClient(lggr, csakey.KeyV2{}, nil, "", cacheSet) + c := newClient(ClientOpts{lggr, csakey.KeyV2{}, nil, "", cacheSet, nil}) c.conn = conn c.rawClient = wsrpcClient diff --git a/core/services/relay/evm/mercury/wsrpc/mocks/mocks.go b/core/services/relay/evm/mercury/wsrpc/mocks/mocks.go index e202802ea77..199e0b49fa8 100644 --- a/core/services/relay/evm/mercury/wsrpc/mocks/mocks.go +++ b/core/services/relay/evm/mercury/wsrpc/mocks/mocks.go @@ -29,9 +29,10 @@ func (m *MockWSRPCClient) ServerURL() string { return "mock server url" } func (m *MockWSRPCClient) RawClient() pb.MercuryClient { return nil } type MockConn struct { - State grpc_connectivity.State - Ready bool - Closed bool + State grpc_connectivity.State + Ready bool + Closed bool + InvokeF func(ctx context.Context, method string, args interface{}, reply interface{}) error } func (m *MockConn) Close() error { @@ -42,3 +43,7 @@ func (m MockConn) WaitForReady(ctx context.Context) bool { return m.Ready } func (m MockConn) GetState() grpc_connectivity.State { return m.State } + +func (m MockConn) Invoke(ctx context.Context, method string, args interface{}, reply interface{}) error { + return m.InvokeF(ctx, method, args, reply) +} diff --git a/core/services/relay/evm/mercury/wsrpc/pool.go b/core/services/relay/evm/mercury/wsrpc/pool.go index 0bd49ddb5ea..7754d6b2b96 100644 --- a/core/services/relay/evm/mercury/wsrpc/pool.go +++ b/core/services/relay/evm/mercury/wsrpc/pool.go @@ -60,7 +60,7 @@ func (conn *connection) checkout(ctx context.Context) (cco *clientCheckout, err // not thread-safe, access must be serialized func (conn *connection) ensureStartedClient(ctx context.Context) error { if len(conn.checkouts) == 0 { - conn.Client = conn.pool.newClient(conn.lggr, conn.clientPrivKey, conn.serverPubKey, conn.serverURL, conn.pool.cacheSet) + conn.Client = conn.pool.newClient(ClientOpts{conn.lggr, conn.clientPrivKey, conn.serverPubKey, conn.serverURL, conn.pool.cacheSet, nil}) return conn.Client.Start(ctx) } return nil @@ -121,7 +121,7 @@ type pool struct { connections map[string]map[credentials.StaticSizedPublicKey]*connection // embedding newClient makes testing/mocking easier - newClient func(lggr logger.Logger, privKey csakey.KeyV2, serverPubKey []byte, serverURL string, cacheSet cache.CacheSet) Client + newClient func(opts ClientOpts) Client mu sync.RWMutex diff --git a/core/services/relay/evm/mercury/wsrpc/pool_test.go b/core/services/relay/evm/mercury/wsrpc/pool_test.go index bb5ceec0bb6..b11079f3e9b 100644 --- a/core/services/relay/evm/mercury/wsrpc/pool_test.go +++ b/core/services/relay/evm/mercury/wsrpc/pool_test.go @@ -13,7 +13,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/csakey" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/cache" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/pb" ) @@ -64,10 +63,10 @@ func Test_Pool(t *testing.T) { serverURL := "example.com:443/ws" client := newMockClient(lggr) - p.newClient = func(lggr logger.Logger, cprivk csakey.KeyV2, spubk []byte, surl string, cs cache.CacheSet) Client { - assert.Equal(t, clientPrivKey, cprivk) - assert.Equal(t, serverPubKey, spubk) - assert.Equal(t, serverURL, surl) + p.newClient = func(opts ClientOpts) Client { + assert.Equal(t, clientPrivKey, opts.ClientPrivKey) + assert.Equal(t, serverPubKey, opts.ServerPubKey) + assert.Equal(t, serverURL, opts.ServerURL) return client } @@ -110,8 +109,8 @@ func Test_Pool(t *testing.T) { "example.invalid:8000/ws", } - p.newClient = func(lggr logger.Logger, cprivk csakey.KeyV2, spubk []byte, surl string, cs cache.CacheSet) Client { - return newMockClient(lggr) + p.newClient = func(opts ClientOpts) Client { + return newMockClient(opts.Logger) } // conn 1 @@ -226,8 +225,8 @@ func Test_Pool(t *testing.T) { } var clients []*mockClient - p.newClient = func(lggr logger.Logger, cprivk csakey.KeyV2, spubk []byte, surl string, cs cache.CacheSet) Client { - c := newMockClient(lggr) + p.newClient = func(opts ClientOpts) Client { + c := newMockClient(opts.Logger) clients = append(clients, c) return c } diff --git a/core/services/relay/evm/mocks/codec.go b/core/services/relay/evm/mocks/codec.go index acc9e3a7e3a..f4a1e097e5a 100644 --- a/core/services/relay/evm/mocks/codec.go +++ b/core/services/relay/evm/mocks/codec.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -22,7 +22,7 @@ func (_m *Codec) EXPECT() *Codec_Expecter { } // Decode provides a mock function with given fields: ctx, raw, into, itemType -func (_m *Codec) Decode(ctx context.Context, raw []byte, into any, itemType string) error { +func (_m *Codec) Decode(ctx context.Context, raw []byte, into interface{}, itemType string) error { ret := _m.Called(ctx, raw, into, itemType) if len(ret) == 0 { @@ -30,7 +30,7 @@ func (_m *Codec) Decode(ctx context.Context, raw []byte, into any, itemType stri } var r0 error - if rf, ok := ret.Get(0).(func(context.Context, []byte, any, string) error); ok { + if rf, ok := ret.Get(0).(func(context.Context, []byte, interface{}, string) error); ok { r0 = rf(ctx, raw, into, itemType) } else { r0 = ret.Error(0) @@ -47,15 +47,15 @@ type Codec_Decode_Call struct { // Decode is a helper method to define mock.On call // - ctx context.Context // - raw []byte -// - into any +// - into interface{} // - itemType string func (_e *Codec_Expecter) Decode(ctx interface{}, raw interface{}, into interface{}, itemType interface{}) *Codec_Decode_Call { return &Codec_Decode_Call{Call: _e.mock.On("Decode", ctx, raw, into, itemType)} } -func (_c *Codec_Decode_Call) Run(run func(ctx context.Context, raw []byte, into any, itemType string)) *Codec_Decode_Call { +func (_c *Codec_Decode_Call) Run(run func(ctx context.Context, raw []byte, into interface{}, itemType string)) *Codec_Decode_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].([]byte), args[2].(any), args[3].(string)) + run(args[0].(context.Context), args[1].([]byte), args[2].(interface{}), args[3].(string)) }) return _c } @@ -65,13 +65,13 @@ func (_c *Codec_Decode_Call) Return(_a0 error) *Codec_Decode_Call { return _c } -func (_c *Codec_Decode_Call) RunAndReturn(run func(context.Context, []byte, any, string) error) *Codec_Decode_Call { +func (_c *Codec_Decode_Call) RunAndReturn(run func(context.Context, []byte, interface{}, string) error) *Codec_Decode_Call { _c.Call.Return(run) return _c } // Encode provides a mock function with given fields: ctx, item, itemType -func (_m *Codec) Encode(ctx context.Context, item any, itemType string) ([]byte, error) { +func (_m *Codec) Encode(ctx context.Context, item interface{}, itemType string) ([]byte, error) { ret := _m.Called(ctx, item, itemType) if len(ret) == 0 { @@ -80,10 +80,10 @@ func (_m *Codec) Encode(ctx context.Context, item any, itemType string) ([]byte, var r0 []byte var r1 error - if rf, ok := ret.Get(0).(func(context.Context, any, string) ([]byte, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, interface{}, string) ([]byte, error)); ok { return rf(ctx, item, itemType) } - if rf, ok := ret.Get(0).(func(context.Context, any, string) []byte); ok { + if rf, ok := ret.Get(0).(func(context.Context, interface{}, string) []byte); ok { r0 = rf(ctx, item, itemType) } else { if ret.Get(0) != nil { @@ -91,7 +91,7 @@ func (_m *Codec) Encode(ctx context.Context, item any, itemType string) ([]byte, } } - if rf, ok := ret.Get(1).(func(context.Context, any, string) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, interface{}, string) error); ok { r1 = rf(ctx, item, itemType) } else { r1 = ret.Error(1) @@ -107,15 +107,15 @@ type Codec_Encode_Call struct { // Encode is a helper method to define mock.On call // - ctx context.Context -// - item any +// - item interface{} // - itemType string func (_e *Codec_Expecter) Encode(ctx interface{}, item interface{}, itemType interface{}) *Codec_Encode_Call { return &Codec_Encode_Call{Call: _e.mock.On("Encode", ctx, item, itemType)} } -func (_c *Codec_Encode_Call) Run(run func(ctx context.Context, item any, itemType string)) *Codec_Encode_Call { +func (_c *Codec_Encode_Call) Run(run func(ctx context.Context, item interface{}, itemType string)) *Codec_Encode_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(any), args[2].(string)) + run(args[0].(context.Context), args[1].(interface{}), args[2].(string)) }) return _c } @@ -125,7 +125,7 @@ func (_c *Codec_Encode_Call) Return(_a0 []byte, _a1 error) *Codec_Encode_Call { return _c } -func (_c *Codec_Encode_Call) RunAndReturn(run func(context.Context, any, string) ([]byte, error)) *Codec_Encode_Call { +func (_c *Codec_Encode_Call) RunAndReturn(run func(context.Context, interface{}, string) ([]byte, error)) *Codec_Encode_Call { _c.Call.Return(run) return _c } diff --git a/core/services/relay/evm/mocks/request_round_db.go b/core/services/relay/evm/mocks/request_round_db.go index c3c58b0b125..97a499f5d8e 100644 --- a/core/services/relay/evm/mocks/request_round_db.go +++ b/core/services/relay/evm/mocks/request_round_db.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/relay/evm/ocr3_capability_provider.go b/core/services/relay/evm/ocr3_capability_provider.go index 00859befe4c..f5bfdf46da4 100644 --- a/core/services/relay/evm/ocr3_capability_provider.go +++ b/core/services/relay/evm/ocr3_capability_provider.go @@ -16,7 +16,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability" + ocr3_capability "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability_1_0_0" "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" ) diff --git a/core/services/relay/evm/read/mocks/batch_caller.go b/core/services/relay/evm/read/mocks/batch_caller.go index 3ae9ec97b2a..4ac1d28b3e0 100644 --- a/core/services/relay/evm/read/mocks/batch_caller.go +++ b/core/services/relay/evm/read/mocks/batch_caller.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/relay/evm/read/mocks/reader.go b/core/services/relay/evm/read/mocks/reader.go index 79df3cf4025..94fbeecd0f9 100644 --- a/core/services/relay/evm/read/mocks/reader.go +++ b/core/services/relay/evm/read/mocks/reader.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -32,7 +32,7 @@ func (_m *Reader) EXPECT() *Reader_Expecter { } // BatchCall provides a mock function with given fields: address, params, retVal -func (_m *Reader) BatchCall(address common.Address, params any, retVal any) (read.Call, error) { +func (_m *Reader) BatchCall(address common.Address, params interface{}, retVal interface{}) (read.Call, error) { ret := _m.Called(address, params, retVal) if len(ret) == 0 { @@ -41,16 +41,16 @@ func (_m *Reader) BatchCall(address common.Address, params any, retVal any) (rea var r0 read.Call var r1 error - if rf, ok := ret.Get(0).(func(common.Address, any, any) (read.Call, error)); ok { + if rf, ok := ret.Get(0).(func(common.Address, interface{}, interface{}) (read.Call, error)); ok { return rf(address, params, retVal) } - if rf, ok := ret.Get(0).(func(common.Address, any, any) read.Call); ok { + if rf, ok := ret.Get(0).(func(common.Address, interface{}, interface{}) read.Call); ok { r0 = rf(address, params, retVal) } else { r0 = ret.Get(0).(read.Call) } - if rf, ok := ret.Get(1).(func(common.Address, any, any) error); ok { + if rf, ok := ret.Get(1).(func(common.Address, interface{}, interface{}) error); ok { r1 = rf(address, params, retVal) } else { r1 = ret.Error(1) @@ -66,15 +66,15 @@ type Reader_BatchCall_Call struct { // BatchCall is a helper method to define mock.On call // - address common.Address -// - params any -// - retVal any +// - params interface{} +// - retVal interface{} func (_e *Reader_Expecter) BatchCall(address interface{}, params interface{}, retVal interface{}) *Reader_BatchCall_Call { return &Reader_BatchCall_Call{Call: _e.mock.On("BatchCall", address, params, retVal)} } -func (_c *Reader_BatchCall_Call) Run(run func(address common.Address, params any, retVal any)) *Reader_BatchCall_Call { +func (_c *Reader_BatchCall_Call) Run(run func(address common.Address, params interface{}, retVal interface{})) *Reader_BatchCall_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(common.Address), args[1].(any), args[2].(any)) + run(args[0].(common.Address), args[1].(interface{}), args[2].(interface{})) }) return _c } @@ -84,7 +84,7 @@ func (_c *Reader_BatchCall_Call) Return(_a0 read.Call, _a1 error) *Reader_BatchC return _c } -func (_c *Reader_BatchCall_Call) RunAndReturn(run func(common.Address, any, any) (read.Call, error)) *Reader_BatchCall_Call { +func (_c *Reader_BatchCall_Call) RunAndReturn(run func(common.Address, interface{}, interface{}) (read.Call, error)) *Reader_BatchCall_Call { _c.Call.Return(run) return _c } @@ -151,7 +151,7 @@ func (_c *Reader_Bind_Call) RunAndReturn(run func(context.Context, ...common.Add } // GetLatestValueWithHeadData provides a mock function with given fields: ctx, addr, confidence, params, returnVal -func (_m *Reader) GetLatestValueWithHeadData(ctx context.Context, addr common.Address, confidence primitives.ConfidenceLevel, params any, returnVal any) (*types.Head, error) { +func (_m *Reader) GetLatestValueWithHeadData(ctx context.Context, addr common.Address, confidence primitives.ConfidenceLevel, params interface{}, returnVal interface{}) (*types.Head, error) { ret := _m.Called(ctx, addr, confidence, params, returnVal) if len(ret) == 0 { @@ -160,10 +160,10 @@ func (_m *Reader) GetLatestValueWithHeadData(ctx context.Context, addr common.Ad var r0 *types.Head var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Address, primitives.ConfidenceLevel, any, any) (*types.Head, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Address, primitives.ConfidenceLevel, interface{}, interface{}) (*types.Head, error)); ok { return rf(ctx, addr, confidence, params, returnVal) } - if rf, ok := ret.Get(0).(func(context.Context, common.Address, primitives.ConfidenceLevel, any, any) *types.Head); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Address, primitives.ConfidenceLevel, interface{}, interface{}) *types.Head); ok { r0 = rf(ctx, addr, confidence, params, returnVal) } else { if ret.Get(0) != nil { @@ -171,7 +171,7 @@ func (_m *Reader) GetLatestValueWithHeadData(ctx context.Context, addr common.Ad } } - if rf, ok := ret.Get(1).(func(context.Context, common.Address, primitives.ConfidenceLevel, any, any) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, common.Address, primitives.ConfidenceLevel, interface{}, interface{}) error); ok { r1 = rf(ctx, addr, confidence, params, returnVal) } else { r1 = ret.Error(1) @@ -189,15 +189,15 @@ type Reader_GetLatestValueWithHeadData_Call struct { // - ctx context.Context // - addr common.Address // - confidence primitives.ConfidenceLevel -// - params any -// - returnVal any +// - params interface{} +// - returnVal interface{} func (_e *Reader_Expecter) GetLatestValueWithHeadData(ctx interface{}, addr interface{}, confidence interface{}, params interface{}, returnVal interface{}) *Reader_GetLatestValueWithHeadData_Call { return &Reader_GetLatestValueWithHeadData_Call{Call: _e.mock.On("GetLatestValueWithHeadData", ctx, addr, confidence, params, returnVal)} } -func (_c *Reader_GetLatestValueWithHeadData_Call) Run(run func(ctx context.Context, addr common.Address, confidence primitives.ConfidenceLevel, params any, returnVal any)) *Reader_GetLatestValueWithHeadData_Call { +func (_c *Reader_GetLatestValueWithHeadData_Call) Run(run func(ctx context.Context, addr common.Address, confidence primitives.ConfidenceLevel, params interface{}, returnVal interface{})) *Reader_GetLatestValueWithHeadData_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(common.Address), args[2].(primitives.ConfidenceLevel), args[3].(any), args[4].(any)) + run(args[0].(context.Context), args[1].(common.Address), args[2].(primitives.ConfidenceLevel), args[3].(interface{}), args[4].(interface{})) }) return _c } @@ -207,13 +207,13 @@ func (_c *Reader_GetLatestValueWithHeadData_Call) Return(_a0 *types.Head, _a1 er return _c } -func (_c *Reader_GetLatestValueWithHeadData_Call) RunAndReturn(run func(context.Context, common.Address, primitives.ConfidenceLevel, any, any) (*types.Head, error)) *Reader_GetLatestValueWithHeadData_Call { +func (_c *Reader_GetLatestValueWithHeadData_Call) RunAndReturn(run func(context.Context, common.Address, primitives.ConfidenceLevel, interface{}, interface{}) (*types.Head, error)) *Reader_GetLatestValueWithHeadData_Call { _c.Call.Return(run) return _c } // QueryKey provides a mock function with given fields: _a0, _a1, _a2, _a3, _a4 -func (_m *Reader) QueryKey(_a0 context.Context, _a1 common.Address, _a2 query.KeyFilter, _a3 query.LimitAndSort, _a4 any) ([]types.Sequence, error) { +func (_m *Reader) QueryKey(_a0 context.Context, _a1 common.Address, _a2 query.KeyFilter, _a3 query.LimitAndSort, _a4 interface{}) ([]types.Sequence, error) { ret := _m.Called(_a0, _a1, _a2, _a3, _a4) if len(ret) == 0 { @@ -222,10 +222,10 @@ func (_m *Reader) QueryKey(_a0 context.Context, _a1 common.Address, _a2 query.Ke var r0 []types.Sequence var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Address, query.KeyFilter, query.LimitAndSort, any) ([]types.Sequence, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Address, query.KeyFilter, query.LimitAndSort, interface{}) ([]types.Sequence, error)); ok { return rf(_a0, _a1, _a2, _a3, _a4) } - if rf, ok := ret.Get(0).(func(context.Context, common.Address, query.KeyFilter, query.LimitAndSort, any) []types.Sequence); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Address, query.KeyFilter, query.LimitAndSort, interface{}) []types.Sequence); ok { r0 = rf(_a0, _a1, _a2, _a3, _a4) } else { if ret.Get(0) != nil { @@ -233,7 +233,7 @@ func (_m *Reader) QueryKey(_a0 context.Context, _a1 common.Address, _a2 query.Ke } } - if rf, ok := ret.Get(1).(func(context.Context, common.Address, query.KeyFilter, query.LimitAndSort, any) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, common.Address, query.KeyFilter, query.LimitAndSort, interface{}) error); ok { r1 = rf(_a0, _a1, _a2, _a3, _a4) } else { r1 = ret.Error(1) @@ -252,14 +252,14 @@ type Reader_QueryKey_Call struct { // - _a1 common.Address // - _a2 query.KeyFilter // - _a3 query.LimitAndSort -// - _a4 any +// - _a4 interface{} func (_e *Reader_Expecter) QueryKey(_a0 interface{}, _a1 interface{}, _a2 interface{}, _a3 interface{}, _a4 interface{}) *Reader_QueryKey_Call { return &Reader_QueryKey_Call{Call: _e.mock.On("QueryKey", _a0, _a1, _a2, _a3, _a4)} } -func (_c *Reader_QueryKey_Call) Run(run func(_a0 context.Context, _a1 common.Address, _a2 query.KeyFilter, _a3 query.LimitAndSort, _a4 any)) *Reader_QueryKey_Call { +func (_c *Reader_QueryKey_Call) Run(run func(_a0 context.Context, _a1 common.Address, _a2 query.KeyFilter, _a3 query.LimitAndSort, _a4 interface{})) *Reader_QueryKey_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(common.Address), args[2].(query.KeyFilter), args[3].(query.LimitAndSort), args[4].(any)) + run(args[0].(context.Context), args[1].(common.Address), args[2].(query.KeyFilter), args[3].(query.LimitAndSort), args[4].(interface{})) }) return _c } @@ -269,7 +269,7 @@ func (_c *Reader_QueryKey_Call) Return(_a0 []types.Sequence, _a1 error) *Reader_ return _c } -func (_c *Reader_QueryKey_Call) RunAndReturn(run func(context.Context, common.Address, query.KeyFilter, query.LimitAndSort, any) ([]types.Sequence, error)) *Reader_QueryKey_Call { +func (_c *Reader_QueryKey_Call) RunAndReturn(run func(context.Context, common.Address, query.KeyFilter, query.LimitAndSort, interface{}) ([]types.Sequence, error)) *Reader_QueryKey_Call { _c.Call.Return(run) return _c } @@ -349,7 +349,7 @@ func (_c *Reader_SetCodec_Call) Return() *Reader_SetCodec_Call { } func (_c *Reader_SetCodec_Call) RunAndReturn(run func(types.RemoteCodec)) *Reader_SetCodec_Call { - _c.Call.Return(run) + _c.Run(run) return _c } diff --git a/core/services/relay/evm/read/mocks/registrar.go b/core/services/relay/evm/read/mocks/registrar.go index 433a8771396..472e68622be 100644 --- a/core/services/relay/evm/read/mocks/registrar.go +++ b/core/services/relay/evm/read/mocks/registrar.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/relay/evm/statuschecker/mocks/ccip_transaction_status_checker.go b/core/services/relay/evm/statuschecker/mocks/ccip_transaction_status_checker.go index 4bbda1d75bc..82841882328 100644 --- a/core/services/relay/evm/statuschecker/mocks/ccip_transaction_status_checker.go +++ b/core/services/relay/evm/statuschecker/mocks/ccip_transaction_status_checker.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/relay/evm/types/mocks/log_poller_wrapper.go b/core/services/relay/evm/types/mocks/log_poller_wrapper.go index ee4946b0e4d..de9f9deca6c 100644 --- a/core/services/relay/evm/types/mocks/log_poller_wrapper.go +++ b/core/services/relay/evm/types/mocks/log_poller_wrapper.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -22,7 +22,7 @@ func (_m *LogPollerWrapper) EXPECT() *LogPollerWrapper_Expecter { return &LogPollerWrapper_Expecter{mock: &_m.Mock} } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *LogPollerWrapper) Close() error { ret := _m.Called() @@ -67,7 +67,7 @@ func (_c *LogPollerWrapper_Close_Call) RunAndReturn(run func() error) *LogPoller return _c } -// HealthReport provides a mock function with given fields: +// HealthReport provides a mock function with no fields func (_m *LogPollerWrapper) HealthReport() map[string]error { ret := _m.Called() @@ -181,7 +181,7 @@ func (_c *LogPollerWrapper_LatestEvents_Call) RunAndReturn(run func(context.Cont return _c } -// Name provides a mock function with given fields: +// Name provides a mock function with no fields func (_m *LogPollerWrapper) Name() string { ret := _m.Called() @@ -226,7 +226,7 @@ func (_c *LogPollerWrapper_Name_Call) RunAndReturn(run func() string) *LogPoller return _c } -// Ready provides a mock function with given fields: +// Ready provides a mock function with no fields func (_m *LogPollerWrapper) Ready() error { ret := _m.Called() @@ -348,7 +348,7 @@ func (_c *LogPollerWrapper_SubscribeToUpdates_Call) Return() *LogPollerWrapper_S } func (_c *LogPollerWrapper_SubscribeToUpdates_Call) RunAndReturn(run func(context.Context, string, types.RouteUpdateSubscriber)) *LogPollerWrapper_SubscribeToUpdates_Call { - _c.Call.Return(run) + _c.Run(run) return _c } diff --git a/core/services/relay/evm/write_target.go b/core/services/relay/evm/write_target.go index 994dbbb77ce..f14c13e5daa 100644 --- a/core/services/relay/evm/write_target.go +++ b/core/services/relay/evm/write_target.go @@ -11,7 +11,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/capabilities/targets" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder" + forwarder "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder_1_0_0" relayevmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) diff --git a/core/services/relay/evm/write_target_test.go b/core/services/relay/evm/write_target_test.go index 24d7dd8646e..c82c9ba81b9 100644 --- a/core/services/relay/evm/write_target_test.go +++ b/core/services/relay/evm/write_target_test.go @@ -27,7 +27,7 @@ import ( txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" evmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm/mocks" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder" + forwarder "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder_1_0_0" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" diff --git a/core/services/relay/relay.go b/core/services/relay/relay.go index 0b1293c8d79..8a6a12e30e3 100644 --- a/core/services/relay/relay.go +++ b/core/services/relay/relay.go @@ -14,6 +14,7 @@ const ( NetworkSolana = "solana" NetworkStarkNet = "starknet" NetworkAptos = "aptos" + NetworkTron = "tron" NetworkDummy = "dummy" ) @@ -24,6 +25,7 @@ var SupportedNetworks = map[string]struct{}{ NetworkSolana: {}, NetworkStarkNet: {}, NetworkAptos: {}, + NetworkTron: {}, NetworkDummy: {}, } diff --git a/core/services/s4/mocks/orm.go b/core/services/s4/mocks/orm.go index 36593dbe85c..a4ac8f7af37 100644 --- a/core/services/s4/mocks/orm.go +++ b/core/services/s4/mocks/orm.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/s4/mocks/storage.go b/core/services/s4/mocks/storage.go index e6fdb3b41b9..00ec97962a9 100644 --- a/core/services/s4/mocks/storage.go +++ b/core/services/s4/mocks/storage.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -25,7 +25,7 @@ func (_m *Storage) EXPECT() *Storage_Expecter { return &Storage_Expecter{mock: &_m.Mock} } -// Constraints provides a mock function with given fields: +// Constraints provides a mock function with no fields func (_m *Storage) Constraints() s4.Constraints { ret := _m.Called() diff --git a/core/services/streams/delegate.go b/core/services/streams/delegate.go index bf492d4bd15..092d1941831 100644 --- a/core/services/streams/delegate.go +++ b/core/services/streams/delegate.go @@ -43,17 +43,12 @@ func (d *Delegate) BeforeJobDeleted(jb job.Job) {} func (d *Delegate) OnDeleteJob(context.Context, job.Job) error { return nil } func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) (services []job.ServiceCtx, err error) { - if jb.StreamID == nil { - return nil, errors.New("streamID is required to be present for stream specs") - } - id := *jb.StreamID - lggr := d.lggr.Named(fmt.Sprintf("%d", id)).With("streamID", id) + lggr := d.lggr.Named(fmt.Sprintf("Job.%d", jb.ID)).With("jobID", jb.ID) rrs := ocrcommon.NewResultRunSaver(d.runner, lggr, d.cfg.MaxSuccessfulRuns(), d.cfg.ResultWriteQueueDepth()) services = append(services, rrs, &StreamService{ d.registry, - id, - jb.PipelineSpec, + jb, lggr, rrs, }) @@ -66,23 +61,22 @@ type ResultRunSaver interface { type StreamService struct { registry Registry - id StreamID - spec *pipeline.Spec + jb job.Job lggr logger.Logger rrs ResultRunSaver } func (s *StreamService) Start(_ context.Context) error { - if s.spec == nil { - return fmt.Errorf("pipeline spec unexpectedly missing for stream %q", s.id) + if s.jb.PipelineSpec == nil { + return errors.New("pipeline spec unexpectedly missing for stream") } - s.lggr.Debugf("Starting stream %d", s.id) - return s.registry.Register(s.id, *s.spec, s.rrs) + s.lggr.Debugw("Registering stream", "jobID", s.jb.ID) + return s.registry.Register(s.jb, s.rrs) } func (s *StreamService) Close() error { - s.lggr.Debugf("Stopping stream %d", s.id) - s.registry.Unregister(s.id) + s.lggr.Debugw("Unregistering stream", "jobID", s.jb.ID) + s.registry.Unregister(s.jb.ID) return nil } @@ -101,8 +95,23 @@ func ValidatedStreamSpec(tomlString string) (job.Job, error) { return jb, errors.Errorf("unsupported type: %q", jb.Type) } - if jb.StreamID == nil { - return jb, errors.New("jobs of type 'stream' require streamID to be specified") + // The spec stream ID is optional, but if provided represents the final output of the pipeline run. + // nodes in the DAG may also contain streamID tags. + // Every spec must have at least one streamID. + var streamIDs []StreamID + + if jb.StreamID != nil { + streamIDs = append(streamIDs, *jb.StreamID) + } + + for _, t := range jb.Pipeline.Tasks { + if streamID := t.TaskStreamID(); streamID != nil { + streamIDs = append(streamIDs, *streamID) + } + } + + if len(streamIDs) == 0 { + return jb, errors.New("no streamID found in spec (must be either specified as top-level key 'streamID' or at least one streamID tag must be provided in the pipeline)") } return jb, nil diff --git a/core/services/streams/delegate_test.go b/core/services/streams/delegate_test.go index d177c977e1b..4d14c31b11b 100644 --- a/core/services/streams/delegate_test.go +++ b/core/services/streams/delegate_test.go @@ -15,11 +15,11 @@ import ( type mockRegistry struct{} -func (m *mockRegistry) Get(streamID StreamID) (strm Stream, exists bool) { return } -func (m *mockRegistry) Register(streamID StreamID, spec pipeline.Spec, rrs ResultRunSaver) error { +func (m *mockRegistry) Get(streamID StreamID) (p Pipeline, exists bool) { return } +func (m *mockRegistry) Register(jb job.Job, rrs ResultRunSaver) error { return nil } -func (m *mockRegistry) Unregister(streamID StreamID) {} +func (m *mockRegistry) Unregister(int32) {} type mockDelegateConfig struct{} @@ -35,9 +35,9 @@ func Test_Delegate(t *testing.T) { t.Run("ServicesForSpec", func(t *testing.T) { jb := job.Job{PipelineSpec: &pipeline.Spec{ID: 1}} - t.Run("errors if job is missing streamID", func(t *testing.T) { + t.Run("no error if job is missing streamID", func(t *testing.T) { _, err := d.ServicesForSpec(testutils.Context(t), jb) - assert.EqualError(t, err, "streamID is required to be present for stream specs") + require.NoError(t, err) }) jb.StreamID = ptr(uint32(42)) t.Run("returns services", func(t *testing.T) { @@ -49,8 +49,7 @@ func Test_Delegate(t *testing.T) { strmSrv := srvs[1].(*StreamService) assert.Equal(t, registry, strmSrv.registry) - assert.Equal(t, StreamID(42), strmSrv.id) - assert.Equal(t, jb.PipelineSpec, strmSrv.spec) + assert.Equal(t, jb, strmSrv.jb) assert.NotNil(t, strmSrv.lggr) assert.Equal(t, srvs[0], strmSrv.rrs) }) @@ -168,7 +167,7 @@ answer1 [type=median index=0]; """ `, assertion: func(t *testing.T, jb job.Job, err error) { - assert.EqualError(t, err, "jobs of type 'stream' require streamID to be specified") + assert.EqualError(t, err, "no streamID found in spec (must be either specified as top-level key 'streamID' or at least one streamID tag must be provided in the pipeline)") }, }, } diff --git a/core/services/streams/pipeline.go b/core/services/streams/pipeline.go new file mode 100644 index 00000000000..de52fed26e5 --- /dev/null +++ b/core/services/streams/pipeline.go @@ -0,0 +1,131 @@ +package streams + +import ( + "context" + "fmt" + + "github.com/pkg/errors" + + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/job" + "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" +) + +type Runner interface { + ExecuteRun(ctx context.Context, spec pipeline.Spec, vars pipeline.Vars) (run *pipeline.Run, trrs pipeline.TaskRunResults, err error) + InitializePipeline(spec pipeline.Spec) (*pipeline.Pipeline, error) +} + +type RunResultSaver interface { + Save(run *pipeline.Run) +} + +type Pipeline interface { + Run(ctx context.Context) (*pipeline.Run, pipeline.TaskRunResults, error) + StreamIDs() []StreamID +} + +type multiStreamPipeline struct { + lggr logger.Logger + spec pipeline.Spec + runner Runner + rrs RunResultSaver + streamIDs []StreamID + vars pipeline.Vars +} + +func NewMultiStreamPipeline(lggr logger.Logger, jb job.Job, runner Runner, rrs RunResultSaver) (Pipeline, error) { + return newMultiStreamPipeline(lggr, jb, runner, rrs) +} + +func newMultiStreamPipeline(lggr logger.Logger, jb job.Job, runner Runner, rrs RunResultSaver) (*multiStreamPipeline, error) { + if jb.PipelineSpec == nil { + // should never happen + return nil, errors.New("job has no pipeline spec") + } + spec := *jb.PipelineSpec + spec.JobID = jb.ID + spec.JobName = jb.Name.ValueOrZero() + spec.JobType = string(jb.Type) + if spec.Pipeline == nil { + pipeline, err := spec.ParsePipeline() + if err != nil { + return nil, fmt.Errorf("unparseable pipeline: %w", err) + } + + spec.Pipeline = pipeline + // initialize it for the given runner + if _, err := runner.InitializePipeline(spec); err != nil { + return nil, fmt.Errorf("error while initializing pipeline: %w", err) + } + } + var streamIDs []StreamID + for _, t := range spec.Pipeline.Tasks { + if t.TaskStreamID() != nil { + streamIDs = append(streamIDs, *t.TaskStreamID()) + } + } + if jb.StreamID != nil { + streamIDs = append(streamIDs, *jb.StreamID) + } + if err := validateStreamIDs(streamIDs); err != nil { + return nil, fmt.Errorf("invalid stream IDs: %w", err) + } + vars := pipeline.NewVarsFrom(map[string]interface{}{ + "pipelineSpec": map[string]interface{}{ + "id": jb.PipelineSpecID, + }, + "jb": map[string]interface{}{ + "databaseID": jb.ID, + "externalJobID": jb.ExternalJobID, + "name": jb.Name.ValueOrZero(), + }, + }) + + return &multiStreamPipeline{ + lggr.Named("MultiStreamPipeline").With("spec.ID", spec.ID, "jobID", spec.JobID, "jobName", spec.JobName, "jobType", spec.JobType), + spec, + runner, + rrs, + streamIDs, + vars}, nil +} + +func validateStreamIDs(streamIDs []StreamID) error { + seen := make(map[StreamID]struct{}) + for _, id := range streamIDs { + if _, ok := seen[id]; ok { + return fmt.Errorf("duplicate stream ID: %v", id) + } + seen[id] = struct{}{} + } + return nil +} + +func (s *multiStreamPipeline) Run(ctx context.Context) (run *pipeline.Run, trrs pipeline.TaskRunResults, err error) { + run, trrs, err = s.executeRun(ctx) + + if err != nil { + return nil, nil, fmt.Errorf("Run failed: %w", err) + } + if s.rrs != nil { + s.rrs.Save(run) + } + + return +} + +func (s *multiStreamPipeline) StreamIDs() []StreamID { + return s.streamIDs +} + +// The context passed in here has a timeout of (ObservationTimeout + ObservationGracePeriod). +// Upon context cancellation, its expected that we return any usable values within ObservationGracePeriod. +func (s *multiStreamPipeline) executeRun(ctx context.Context) (*pipeline.Run, pipeline.TaskRunResults, error) { + run, trrs, err := s.runner.ExecuteRun(ctx, s.spec, s.vars) + if err != nil { + return nil, nil, fmt.Errorf("error executing run for spec ID %v: %w", s.spec.ID, err) + } + + return run, trrs, err +} diff --git a/core/services/streams/stream.go b/core/services/streams/stream.go deleted file mode 100644 index b65c6dc12f6..00000000000 --- a/core/services/streams/stream.go +++ /dev/null @@ -1,94 +0,0 @@ -package streams - -import ( - "context" - "fmt" - "sync" - - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" -) - -type Runner interface { - ExecuteRun(ctx context.Context, spec pipeline.Spec, vars pipeline.Vars) (run *pipeline.Run, trrs pipeline.TaskRunResults, err error) - InitializePipeline(spec pipeline.Spec) (*pipeline.Pipeline, error) -} - -type RunResultSaver interface { - Save(run *pipeline.Run) -} - -type Stream interface { - Run(ctx context.Context) (*pipeline.Run, pipeline.TaskRunResults, error) -} - -type stream struct { - sync.RWMutex - id StreamID - lggr logger.Logger - spec *pipeline.Spec - runner Runner - rrs RunResultSaver -} - -func NewStream(lggr logger.Logger, id StreamID, spec pipeline.Spec, runner Runner, rrs RunResultSaver) Stream { - return newStream(lggr, id, spec, runner, rrs) -} - -func newStream(lggr logger.Logger, id StreamID, spec pipeline.Spec, runner Runner, rrs RunResultSaver) *stream { - return &stream{sync.RWMutex{}, id, lggr.Named("Stream").With("streamID", id), &spec, runner, rrs} -} - -func (s *stream) Run(ctx context.Context) (run *pipeline.Run, trrs pipeline.TaskRunResults, err error) { - run, trrs, err = s.executeRun(ctx) - - if err != nil { - return nil, nil, fmt.Errorf("Run failed: %w", err) - } - if s.rrs != nil { - s.rrs.Save(run) - } - - return -} - -// The context passed in here has a timeout of (ObservationTimeout + ObservationGracePeriod). -// Upon context cancellation, its expected that we return any usable values within ObservationGracePeriod. -func (s *stream) executeRun(ctx context.Context) (*pipeline.Run, pipeline.TaskRunResults, error) { - // the hot path here is to avoid parsing and use the pre-parsed, cached, pipeline - s.RLock() - initialize := s.spec.Pipeline == nil - s.RUnlock() - if initialize { - pipeline, err := s.spec.ParsePipeline() - if err != nil { - return nil, nil, fmt.Errorf("Run failed due to unparseable pipeline: %w", err) - } - - s.Lock() - if s.spec.Pipeline == nil { - s.spec.Pipeline = pipeline - // initialize it for the given runner - if _, err := s.runner.InitializePipeline(*s.spec); err != nil { - return nil, nil, fmt.Errorf("Run failed due to error while initializing pipeline: %w", err) - } - } - s.Unlock() - } - - vars := pipeline.NewVarsFrom(map[string]interface{}{ - "pipelineSpec": map[string]interface{}{ - "id": s.spec.ID, - }, - "stream": map[string]interface{}{ - "id": s.id, - }, - }) - - run, trrs, err := s.runner.ExecuteRun(ctx, *s.spec, vars) - if err != nil { - return nil, nil, fmt.Errorf("error executing run for spec ID %v: %w", s.spec.ID, err) - } - - return run, trrs, err -} diff --git a/core/services/streams/stream_registry.go b/core/services/streams/stream_registry.go index 9ab2df11d33..cf5a59944b7 100644 --- a/core/services/streams/stream_registry.go +++ b/core/services/streams/stream_registry.go @@ -7,7 +7,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types/llo" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" + "github.com/smartcontractkit/chainlink/v2/core/services/job" ) // alias for easier refactoring @@ -15,19 +15,22 @@ type StreamID = llo.StreamID type Registry interface { Getter - Register(streamID StreamID, spec pipeline.Spec, rrs ResultRunSaver) error - Unregister(streamID StreamID) + Register(jb job.Job, rrs ResultRunSaver) error + Unregister(jobID int32) } type Getter interface { - Get(streamID StreamID) (strm Stream, exists bool) + Get(streamID StreamID) (p Pipeline, exists bool) } type streamRegistry struct { sync.RWMutex - lggr logger.Logger - runner Runner - streams map[StreamID]Stream + lggr logger.Logger + runner Runner + // keyed by stream ID + pipelines map[StreamID]Pipeline + // keyed by job ID + pipelinesByJobID map[int32]Pipeline } func NewRegistry(lggr logger.Logger, runner Runner) Registry { @@ -39,29 +42,53 @@ func newRegistry(lggr logger.Logger, runner Runner) *streamRegistry { sync.RWMutex{}, lggr.Named("Registry"), runner, - make(map[StreamID]Stream), + make(map[StreamID]Pipeline), + make(map[int32]Pipeline), } } -func (s *streamRegistry) Get(streamID StreamID) (strm Stream, exists bool) { +func (s *streamRegistry) Get(streamID StreamID) (p Pipeline, exists bool) { s.RLock() defer s.RUnlock() - strm, exists = s.streams[streamID] + p, exists = s.pipelines[streamID] return } -func (s *streamRegistry) Register(streamID StreamID, spec pipeline.Spec, rrs ResultRunSaver) error { +func (s *streamRegistry) Register(jb job.Job, rrs ResultRunSaver) error { + if jb.Type != job.Stream { + return fmt.Errorf("cannot register job type %s; only Stream jobs are supported", jb.Type) + } + p, err := NewMultiStreamPipeline(s.lggr, jb, s.runner, rrs) + if err != nil { + return fmt.Errorf("cannot register job with ID: %d; %w", jb.ID, err) + } s.Lock() defer s.Unlock() - if _, exists := s.streams[streamID]; exists { - return fmt.Errorf("stream already registered for id: %d", streamID) + if _, exists := s.pipelinesByJobID[jb.ID]; exists { + return fmt.Errorf("cannot register job with ID: %d; it is already registered", jb.ID) + } + for _, strmID := range p.StreamIDs() { + if _, exists := s.pipelines[strmID]; exists { + return fmt.Errorf("cannot register job with ID: %d; stream id %d is already registered", jb.ID, strmID) + } + } + s.pipelinesByJobID[jb.ID] = p + streamIDs := p.StreamIDs() + for _, strmID := range streamIDs { + s.pipelines[strmID] = p } - s.streams[streamID] = NewStream(s.lggr, streamID, spec, s.runner, rrs) return nil } -func (s *streamRegistry) Unregister(streamID StreamID) { +func (s *streamRegistry) Unregister(jobID int32) { s.Lock() defer s.Unlock() - delete(s.streams, streamID) + p, exists := s.pipelinesByJobID[jobID] + if !exists { + return + } + streamIDs := p.StreamIDs() + for _, id := range streamIDs { + delete(s.pipelines, id) + } } diff --git a/core/services/streams/stream_registry_test.go b/core/services/streams/stream_registry_test.go index 738b68f5d4d..e20b29e9262 100644 --- a/core/services/streams/stream_registry_test.go +++ b/core/services/streams/stream_registry_test.go @@ -5,22 +5,31 @@ import ( "testing" "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) -type mockStream struct { +var _ Pipeline = &mockPipeline{} + +type mockPipeline struct { run *pipeline.Run trrs pipeline.TaskRunResults err error + + streamIDs []StreamID } -func (m *mockStream) Run(ctx context.Context) (*pipeline.Run, pipeline.TaskRunResults, error) { +func (m *mockPipeline) Run(ctx context.Context) (*pipeline.Run, pipeline.TaskRunResults, error) { return m.run, m.trrs, m.err } +func (m *mockPipeline) StreamIDs() []StreamID { + return m.streamIDs +} + func Test_Registry(t *testing.T) { lggr := logger.TestLogger(t) runner := &mockRunner{} @@ -28,21 +37,21 @@ func Test_Registry(t *testing.T) { t.Run("Get", func(t *testing.T) { sr := newRegistry(lggr, runner) - sr.streams[1] = &mockStream{run: &pipeline.Run{ID: 1}} - sr.streams[2] = &mockStream{run: &pipeline.Run{ID: 2}} - sr.streams[3] = &mockStream{run: &pipeline.Run{ID: 3}} + sr.pipelines[1] = &mockPipeline{run: &pipeline.Run{ID: 1}} + sr.pipelines[2] = &mockPipeline{run: &pipeline.Run{ID: 2}} + sr.pipelines[3] = &mockPipeline{run: &pipeline.Run{ID: 3}} v, exists := sr.Get(1) assert.True(t, exists) - assert.Equal(t, sr.streams[1], v) + assert.Equal(t, sr.pipelines[1], v) v, exists = sr.Get(2) assert.True(t, exists) - assert.Equal(t, sr.streams[2], v) + assert.Equal(t, sr.pipelines[2], v) v, exists = sr.Get(3) assert.True(t, exists) - assert.Equal(t, sr.streams[3], v) + assert.Equal(t, sr.pipelines[3], v) v, exists = sr.Get(4) assert.Nil(t, v) @@ -51,56 +60,159 @@ func Test_Registry(t *testing.T) { t.Run("Register", func(t *testing.T) { sr := newRegistry(lggr, runner) - t.Run("registers new stream", func(t *testing.T) { - assert.Len(t, sr.streams, 0) - err := sr.Register(1, pipeline.Spec{ID: 32, DotDagSource: "source"}, nil) - require.NoError(t, err) - assert.Len(t, sr.streams, 1) - - v, exists := sr.Get(1) - require.True(t, exists) - strm := v.(*stream) - assert.Equal(t, StreamID(1), strm.id) - assert.Equal(t, int32(32), strm.spec.ID) - }) + // registers new pipeline with multiple stream IDs + assert.Empty(t, sr.pipelines) + // err := sr.Register(job.Job{PipelineSpec: &pipeline.Spec{ID: 32, DotDagSource: "source"}}, nil) + // TODO: what if the dag is unparseable? + // err := sr.Register(1, pipeline.Spec{ID: 32, DotDagSource: "source"}, nil) + err := sr.Register(job.Job{ID: 100, Type: job.Stream, PipelineSpec: &pipeline.Spec{ID: 32, DotDagSource: ` +result1 [type=memo value="900.0022"]; +multiply2 [type=multiply times=1 streamID=1 index=0]; // force conversion to decimal +result2 [type=bridge name="foo-bridge" requestData="{\"data\":{\"data\":\"foo\"}}"]; +result2_parse [type=jsonparse path="result" streamID=2 index=1]; +result3 [type=bridge name="bar-bridge" requestData="{\"data\":{\"data\":\"bar\"}}"]; +result3_parse [type=jsonparse path="result"]; +multiply3 [type=multiply times=1 streamID=3 index=2]; // force conversion to decimal +result1 -> multiply2; +result2 -> result2_parse; +result3 -> result3_parse -> multiply3; +`}}, nil) + require.NoError(t, err) + assert.Len(t, sr.pipelines, 3) // three streams, one pipeline + assert.Contains(t, sr.pipelines, StreamID(1)) + assert.Contains(t, sr.pipelines, StreamID(2)) + assert.Contains(t, sr.pipelines, StreamID(3)) + p := sr.pipelines[1] + assert.Equal(t, p, sr.pipelines[2]) + assert.Equal(t, p, sr.pipelines[3]) - t.Run("errors when attempt to re-register a stream with an existing ID", func(t *testing.T) { - assert.Len(t, sr.streams, 1) - err := sr.Register(1, pipeline.Spec{ID: 33, DotDagSource: "source"}, nil) - require.Error(t, err) - assert.Len(t, sr.streams, 1) - assert.EqualError(t, err, "stream already registered for id: 1") - - v, exists := sr.Get(1) - require.True(t, exists) - strm := v.(*stream) - assert.Equal(t, StreamID(1), strm.id) - assert.Equal(t, int32(32), strm.spec.ID) - }) + v, exists := sr.Get(1) + require.True(t, exists) + msp := v.(*multiStreamPipeline) + assert.Equal(t, []StreamID{1, 2, 3}, msp.StreamIDs()) + assert.Equal(t, int32(32), msp.spec.ID) + + // errors when attempt to re-register a stream with an existing job ID + err = sr.Register(job.Job{ID: 100, Type: job.Stream, PipelineSpec: &pipeline.Spec{ID: 33, DotDagSource: ` +result1 [type=memo value="900.0022"]; + `}}, nil) + require.EqualError(t, err, "cannot register job with ID: 100; it is already registered") + + // errors when attempt to register a new job with duplicates stream IDs within ig + err = sr.Register(job.Job{ID: 101, StreamID: ptr(StreamID(100)), Type: job.Stream, PipelineSpec: &pipeline.Spec{ID: 33, DotDagSource: ` +result1 [type=memo value="900.0022" streamID=100]; + `}}, nil) + require.EqualError(t, err, "cannot register job with ID: 101; invalid stream IDs: duplicate stream ID: 100") + + // errors with unparseable pipeline + err = sr.Register(job.Job{ID: 101, Type: job.Stream, PipelineSpec: &pipeline.Spec{ID: 33, DotDagSource: "source"}}, nil) + require.Error(t, err) + require.EqualError(t, err, "cannot register job with ID: 101; unparseable pipeline: UnmarshalTaskFromMap: unknown task type: \"\"") + + // errors when attempt to re-register a stream with an existing streamID at top-level + err = sr.Register(job.Job{ID: 101, StreamID: ptr(StreamID(3)), Type: job.Stream, PipelineSpec: &pipeline.Spec{ID: 33, DotDagSource: ` +result1 [type=memo value="900.0022"]; +multiply2 [type=multiply times=1 streamID=4 index=0]; // force conversion to decimal +result2 [type=bridge name="foo-bridge" requestData="{\"data\":{\"data\":\"foo\"}}"]; +result2_parse [type=jsonparse path="result" streamID=5 index=1]; +result3 [type=bridge name="bar-bridge" requestData="{\"data\":{\"data\":\"bar\"}}"]; +result3_parse [type=jsonparse path="result"]; +multiply3 [type=multiply times=1 streamID=6 index=2]; // force conversion to decimal +result1 -> multiply2; +result2 -> result2_parse; +result3 -> result3_parse -> multiply3; +`}}, nil) + require.Error(t, err) + require.EqualError(t, err, "cannot register job with ID: 101; stream id 3 is already registered") + + // errors when attempt to re-register a stream with an existing streamID in DAG + err = sr.Register(job.Job{ID: 101, StreamID: ptr(StreamID(4)), Type: job.Stream, PipelineSpec: &pipeline.Spec{ID: 33, DotDagSource: ` +result1 [type=memo value="900.0022"]; +multiply2 [type=multiply times=1 streamID=1 index=0]; // force conversion to decimal +result2 [type=bridge name="foo-bridge" requestData="{\"data\":{\"data\":\"foo\"}}"]; +result2_parse [type=jsonparse path="result" streamID=5 index=1]; +result3 [type=bridge name="bar-bridge" requestData="{\"data\":{\"data\":\"bar\"}}"]; +result3_parse [type=jsonparse path="result"]; +multiply3 [type=multiply times=1 streamID=6 index=2]; // force conversion to decimal +result1 -> multiply2; +result2 -> result2_parse; +result3 -> result3_parse -> multiply3; +`}}, nil) + require.Error(t, err) + require.EqualError(t, err, "cannot register job with ID: 101; stream id 1 is already registered") + + // registers new job with all new stream IDs + err = sr.Register(job.Job{ID: 101, StreamID: ptr(StreamID(4)), Type: job.Stream, PipelineSpec: &pipeline.Spec{ID: 33, DotDagSource: ` +result1 [type=memo value="900.0022"]; +multiply2 [type=multiply times=1 streamID=5 index=0]; // force conversion to decimal +result2 [type=bridge name="foo-bridge" requestData="{\"data\":{\"data\":\"foo\"}}"]; +result2_parse [type=jsonparse path="result" streamID=6 index=1]; +result3 [type=bridge name="bar-bridge" requestData="{\"data\":{\"data\":\"bar\"}}"]; +result3_parse [type=jsonparse path="result"]; +multiply3 [type=multiply times=1 streamID=7 index=2]; // force conversion to decimal +result1 -> multiply2; +result2 -> result2_parse; +result3 -> result3_parse -> multiply3; +`}}, nil) + require.NoError(t, err) + + // did not overwrite existing stream + assert.Len(t, sr.pipelines, 7) + assert.Equal(t, p, sr.pipelines[1]) + assert.Equal(t, p, sr.pipelines[2]) + assert.Equal(t, p, sr.pipelines[3]) + p2 := sr.pipelines[4] + assert.NotEqual(t, p, p2) + assert.Equal(t, p2, sr.pipelines[5]) + assert.Equal(t, p2, sr.pipelines[6]) + assert.Equal(t, p2, sr.pipelines[7]) + + v, exists = sr.Get(1) + require.True(t, exists) + msp = v.(*multiStreamPipeline) + assert.ElementsMatch(t, []StreamID{1, 2, 3}, msp.StreamIDs()) + assert.Equal(t, int32(32), msp.spec.ID) + + v, exists = sr.Get(4) + require.True(t, exists) + msp = v.(*multiStreamPipeline) + assert.ElementsMatch(t, []StreamID{4, 5, 6, 7}, msp.StreamIDs()) + assert.Equal(t, int32(33), msp.spec.ID) }) t.Run("Unregister", func(t *testing.T) { sr := newRegistry(lggr, runner) - sr.streams[1] = &mockStream{run: &pipeline.Run{ID: 1}} - sr.streams[2] = &mockStream{run: &pipeline.Run{ID: 2}} - sr.streams[3] = &mockStream{run: &pipeline.Run{ID: 3}} + err := sr.Register(job.Job{ID: 100, StreamID: ptr(StreamID(1)), Type: job.Stream, PipelineSpec: &pipeline.Spec{ID: 33, DotDagSource: ` +result1 [type=memo value="900.0022" streamID=2]; + `}}, nil) + require.NoError(t, err) + err = sr.Register(job.Job{ID: 101, Type: job.Stream, PipelineSpec: &pipeline.Spec{ID: 33, DotDagSource: ` +result1 [type=memo value="900.0022" streamID=3]; + `}}, nil) + require.NoError(t, err) + err = sr.Register(job.Job{ID: 102, Type: job.Stream, PipelineSpec: &pipeline.Spec{ID: 33, DotDagSource: ` +result1 [type=memo value="900.0022" streamID=4]; + `}}, nil) + require.NoError(t, err) t.Run("unregisters a stream", func(t *testing.T) { - assert.Len(t, sr.streams, 3) + assert.Len(t, sr.pipelines, 4) - sr.Unregister(1) + sr.Unregister(100) - assert.Len(t, sr.streams, 2) - _, exists := sr.streams[1] + assert.Len(t, sr.pipelines, 2) + _, exists := sr.pipelines[1] + assert.False(t, exists) + _, exists = sr.pipelines[2] assert.False(t, exists) }) t.Run("no effect when unregistering a non-existent stream", func(t *testing.T) { - assert.Len(t, sr.streams, 2) + assert.Len(t, sr.pipelines, 2) sr.Unregister(1) - assert.Len(t, sr.streams, 2) - _, exists := sr.streams[1] + assert.Len(t, sr.pipelines, 2) + _, exists := sr.pipelines[1] assert.False(t, exists) }) }) diff --git a/core/services/streams/stream_test.go b/core/services/streams/stream_test.go index 78174138121..905d421bddf 100644 --- a/core/services/streams/stream_test.go +++ b/core/services/streams/stream_test.go @@ -13,6 +13,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" ) @@ -57,24 +58,22 @@ func (m *MockTask) TaskMaxBackoff() time.Duration { return 0 } func Test_Stream(t *testing.T) { lggr := logger.TestLogger(t) runner := &mockRunner{} - spec := pipeline.Spec{} - id := StreamID(123) ctx := testutils.Context(t) - t.Run("Run", func(t *testing.T) { - strm := newStream(lggr, id, spec, runner, nil) - - t.Run("errors with empty pipeline", func(t *testing.T) { - _, _, err := strm.Run(ctx) - assert.EqualError(t, err, "Run failed: Run failed due to unparseable pipeline: empty pipeline") - }) + t.Run("errors with empty pipeline", func(t *testing.T) { + jbInvalid := job.Job{StreamID: ptr(StreamID(123)), PipelineSpec: &pipeline.Spec{DotDagSource: ``}} + _, err := newMultiStreamPipeline(lggr, jbInvalid, runner, nil) + require.EqualError(t, err, "unparseable pipeline: empty pipeline") + }) - spec.DotDagSource = ` -succeed [type=memo value=42] + jb := job.Job{StreamID: ptr(StreamID(123)), PipelineSpec: &pipeline.Spec{DotDagSource: ` +succeed [type=memo value=42 streamID=124]; succeed; -` + `}} - strm = newStream(lggr, id, spec, runner, nil) + t.Run("Run", func(t *testing.T) { + strm, err := newMultiStreamPipeline(lggr, jb, runner, nil) + require.NoError(t, err) t.Run("executes the pipeline (success)", func(t *testing.T) { runner.run = &pipeline.Run{ID: 42} diff --git a/core/services/synchronization/mocks/telem_client.go b/core/services/synchronization/mocks/telem_client.go index 5e4066d07b0..bc90bf2ffd6 100644 --- a/core/services/synchronization/mocks/telem_client.go +++ b/core/services/synchronization/mocks/telem_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/synchronization/mocks/telemetry_service.go b/core/services/synchronization/mocks/telemetry_service.go index c6450abd7ea..cd3d64de352 100644 --- a/core/services/synchronization/mocks/telemetry_service.go +++ b/core/services/synchronization/mocks/telemetry_service.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -22,7 +22,7 @@ func (_m *TelemetryService) EXPECT() *TelemetryService_Expecter { return &TelemetryService_Expecter{mock: &_m.Mock} } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *TelemetryService) Close() error { ret := _m.Called() @@ -67,7 +67,7 @@ func (_c *TelemetryService_Close_Call) RunAndReturn(run func() error) *Telemetry return _c } -// HealthReport provides a mock function with given fields: +// HealthReport provides a mock function with no fields func (_m *TelemetryService) HealthReport() map[string]error { ret := _m.Called() @@ -114,7 +114,7 @@ func (_c *TelemetryService_HealthReport_Call) RunAndReturn(run func() map[string return _c } -// Name provides a mock function with given fields: +// Name provides a mock function with no fields func (_m *TelemetryService) Name() string { ret := _m.Called() @@ -159,7 +159,7 @@ func (_c *TelemetryService_Name_Call) RunAndReturn(run func() string) *Telemetry return _c } -// Ready provides a mock function with given fields: +// Ready provides a mock function with no fields func (_m *TelemetryService) Ready() error { ret := _m.Called() @@ -236,7 +236,7 @@ func (_c *TelemetryService_Send_Call) Return() *TelemetryService_Send_Call { } func (_c *TelemetryService_Send_Call) RunAndReturn(run func(context.Context, []byte, string, synchronization.TelemetryType)) *TelemetryService_Send_Call { - _c.Call.Return(run) + _c.Run(run) return _c } diff --git a/core/services/telemetry/monitoring_endpoint_generator_mock.go b/core/services/telemetry/monitoring_endpoint_generator_mock.go index 9715d864f59..0f0c6a07dab 100644 --- a/core/services/telemetry/monitoring_endpoint_generator_mock.go +++ b/core/services/telemetry/monitoring_endpoint_generator_mock.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package telemetry diff --git a/core/services/transmission/integration_test.go b/core/services/transmission/integration_test.go deleted file mode 100644 index 6e38687313c..00000000000 --- a/core/services/transmission/integration_test.go +++ /dev/null @@ -1,495 +0,0 @@ -package transmission_test - -import ( - "math/big" - "testing" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_v3_aggregator_contract" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/solidity_vrf_consumer_interface_v08" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_mock" - - "github.com/ethereum/go-ethereum/core/types" - - evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/transmission/generated/entry_point" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/transmission/generated/greeter_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/transmission/generated/paymaster_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/transmission/generated/sca_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/transmission/generated/smart_contract_account_factory" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/transmission/generated/smart_contract_account_helper" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" - "github.com/smartcontractkit/chainlink/v2/core/services/transmission" -) - -var ( - greeterABI = evmtypes.MustGetABI(greeter_wrapper.GreeterABI) - consumerABI = evmtypes.MustGetABI(solidity_vrf_consumer_interface_v08.VRFConsumerABI) - entrypointABI = evmtypes.MustGetABI(entry_point.EntryPointABI) -) - -type EntryPointUniverse struct { - holder1 *bind.TransactOpts - holder1Key ethkey.KeyV2 - holder2 *bind.TransactOpts - backend evmtypes.Backend - entryPointAddress common.Address - entryPoint *entry_point.EntryPoint - factoryAddress common.Address - helper *smart_contract_account_helper.SmartContractAccountHelper - greeterAddress common.Address - greeter *greeter_wrapper.Greeter - linkTokenAddress common.Address - linkToken *link_token_interface.LinkToken - linkEthFeedAddress common.Address - vrfCoordinatorAddress common.Address - vrfCoordinator *vrf_coordinator_mock.VRFCoordinatorMock - vrfConsumerAddress common.Address -} - -func deployTransmissionUniverse(t *testing.T) *EntryPointUniverse { - // Create a key for holder1 that we can use to sign - holder1Key := cltest.MustGenerateRandomKey(t) - t.Log("Holder key:", holder1Key.String()) - - // Construct simulated blockchain environment. - holder1Transactor, err := bind.NewKeyedTransactorWithChainID(holder1Key.ToEcdsaPrivKey(), testutils.SimulatedChainID) - require.NoError(t, err) - var ( - holder1 = holder1Transactor - holder2 = testutils.MustNewSimTransactor(t) - ) - genesisData := types.GenesisAlloc{ - holder1.From: {Balance: assets.Ether(1000).ToInt()}, - holder2.From: {Balance: assets.Ether(1000).ToInt()}, - } - backend := cltest.NewSimulatedBackend(t, genesisData, 30e6) - backend.Commit() - - // Setup all contracts and addresses used by tests. - entryPointAddress, _, entryPoint, err := entry_point.DeployEntryPoint(holder1, backend.Client()) - require.NoError(t, err) - factoryAddress, _, _, _ := smart_contract_account_factory.DeploySmartContractAccountFactory(holder1, backend.Client()) - require.NoError(t, err) - _, _, helper, err := smart_contract_account_helper.DeploySmartContractAccountHelper(holder1, backend.Client()) - require.NoError(t, err) - greeterAddress, _, greeter, err := greeter_wrapper.DeployGreeter(holder1, backend.Client()) - require.NoError(t, err) - linkTokenAddress, _, linkToken, err := link_token_interface.DeployLinkToken(holder1, backend.Client()) - require.NoError(t, err) - linkEthFeedAddress, _, _, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract( - holder1, - backend.Client(), - 18, - (*big.Int)(assets.GWei(5000000)), // .005 ETH - ) - require.NoError(t, err) - vrfCoordinatorAddress, _, vrfCoordinator, err := vrf_coordinator_mock.DeployVRFCoordinatorMock(holder1, backend.Client(), linkTokenAddress) - require.NoError(t, err) - vrfConsumerAddress, _, _, err := solidity_vrf_consumer_interface_v08.DeployVRFConsumer(holder1, backend.Client(), vrfCoordinatorAddress, linkTokenAddress) - require.NoError(t, err) - backend.Commit() - - return &EntryPointUniverse{ - holder1: holder1, - holder1Key: holder1Key, - holder2: holder2, - backend: backend, - entryPointAddress: entryPointAddress, - entryPoint: entryPoint, - factoryAddress: factoryAddress, - helper: helper, - greeterAddress: greeterAddress, - greeter: greeter, - linkTokenAddress: linkTokenAddress, - linkToken: linkToken, - linkEthFeedAddress: linkEthFeedAddress, - vrfCoordinatorAddress: vrfCoordinatorAddress, - vrfCoordinator: vrfCoordinator, - vrfConsumerAddress: vrfConsumerAddress, - } -} - -func Test4337Basic(t *testing.T) { - // Deploy universe. - universe := deployTransmissionUniverse(t) - holder1 := universe.holder1 - holder2 := universe.holder2 - backend := universe.backend - - // Ensure no greeting is already set. - initialGreeting, err := universe.greeter.GetGreeting(nil) - require.NoError(t, err) - require.Equal(t, "", initialGreeting) - - // Get the address at which the Smart Contract Account will be deployed. - toDeployAddress, err := universe.helper.CalculateSmartContractAccountAddress( - nil, - holder1.From, - universe.entryPointAddress, - universe.factoryAddress, - ) - require.NoError(t, err) - t.Log("Smart Contract Account Address:", toDeployAddress) - - // Get the initialization code for the Smart Contract Account. - fullInitializeCode, err := universe.helper.GetInitCode(nil, universe.factoryAddress, holder1.From, universe.entryPointAddress) - require.NoError(t, err) - t.Log("Full initialization code:", common.Bytes2Hex(fullInitializeCode)) - - // Construct calldata for setGreeting. - encodedGreetingCall, err := greeterABI.Pack("setGreeting", "bye") - require.NoError(t, err) - t.Log("Encoded greeting call:", common.Bytes2Hex(encodedGreetingCall)) - - // Construct the calldata to be passed in the user operation. - var ( - value = big.NewInt(0) - nonce = big.NewInt(0) - deadline = big.NewInt(1000) - ) - fullEncoding, err := universe.helper.GetFullEndTxEncoding(nil, universe.greeterAddress, value, deadline, encodedGreetingCall) - require.NoError(t, err) - t.Log("Full user operation calldata:", common.Bytes2Hex(fullEncoding)) - - // Construct and execute user operation. - userOp := entry_point.UserOperation{ - Sender: toDeployAddress, - Nonce: nonce, - InitCode: fullInitializeCode, - CallData: fullEncoding, - CallGasLimit: big.NewInt(10_000_000), - VerificationGasLimit: big.NewInt(10_000_000), - PreVerificationGas: big.NewInt(10_000_000), - MaxFeePerGas: big.NewInt(100), - MaxPriorityFeePerGas: big.NewInt(200), - PaymasterAndData: []byte(""), - Signature: []byte(""), - } - - // Generate hash from user operation, sign it, and include it in the user operation. - userOpHash, err := universe.entryPoint.GetUserOpHash(nil, userOp) - require.NoError(t, err) - fullHash, err := universe.helper.GetFullHashForSigning(nil, userOpHash, toDeployAddress) - require.NoError(t, err) - t.Log("Full hash for signing:", common.Bytes2Hex(fullHash[:])) - sig, err := transmission.SignMessage(universe.holder1Key.ToEcdsaPrivKey(), fullHash[:]) - require.NoError(t, err) - t.Log("Signature:", common.Bytes2Hex(sig)) - userOp.Signature = sig - - // Deposit to the SCA's account to pay for this transaction. - holder1.Value = assets.Ether(10).ToInt() - tx, err := universe.entryPoint.DepositTo(holder1, toDeployAddress) - require.NoError(t, err) - backend.Commit() - _, err = bind.WaitMined(testutils.Context(t), backend.Client(), tx) - require.NoError(t, err) - holder1.Value = assets.Ether(0).ToInt() - balance, err := universe.entryPoint.BalanceOf(nil, toDeployAddress) - require.NoError(t, err) - require.Equal(t, assets.Ether(10).ToInt(), balance) - - // Run handleOps from holder2's account, to demonstrate that any account can execute this signed user operation. - tx, err = universe.entryPoint.HandleOps(holder2, []entry_point.UserOperation{userOp}, holder1.From) - require.NoError(t, err) - backend.Commit() - _, err = bind.WaitMined(testutils.Context(t), backend.Client(), tx) - require.NoError(t, err) - - // Ensure "bye" was successfully set as the greeting. - greetingResult, err := universe.greeter.GetGreeting(nil) - require.NoError(t, err) - require.Equal(t, "bye", greetingResult) - - // Assert smart contract account is created and nonce incremented. - sca, err := sca_wrapper.NewSCA(toDeployAddress, backend.Client()) - require.NoError(t, err) - onChainNonce, err := sca.SNonce(nil) - require.NoError(t, err) - require.Equal(t, big.NewInt(1), onChainNonce) -} - -func Test4337WithLinkTokenPaymaster(t *testing.T) { - // Deploy universe. - universe := deployTransmissionUniverse(t) - holder1 := universe.holder1 - holder2 := universe.holder2 - backend := universe.backend - - // Ensure no greeting is already set. - initialGreeting, err := universe.greeter.GetGreeting(nil) - require.NoError(t, err) - require.Equal(t, "", initialGreeting) - - // Get the address at which the Smart Contract Account will be deployed. - toDeployAddress, err := universe.helper.CalculateSmartContractAccountAddress( - nil, - holder1.From, - universe.entryPointAddress, - universe.factoryAddress, - ) - require.NoError(t, err) - t.Log("Smart Contract Account Address:", toDeployAddress) - - // Get the initialization code for the Smart Contract Account. - fullInitializeCode, err := universe.helper.GetInitCode(nil, universe.factoryAddress, holder1.From, universe.entryPointAddress) - require.NoError(t, err) - t.Log("Full initialization code:", common.Bytes2Hex(fullInitializeCode)) - - // Construct calldata for setGreeting. - encodedGreetingCall, err := greeterABI.Pack("setGreeting", "bye") - require.NoError(t, err) - t.Log("Encoded greeting call:", common.Bytes2Hex(encodedGreetingCall)) - - // Construct the calldata to be passed in the user operation. - var ( - value = big.NewInt(0) - nonce = big.NewInt(0) - deadline = big.NewInt(1000) - ) - fullEncoding, err := universe.helper.GetFullEndTxEncoding(nil, universe.greeterAddress, value, deadline, encodedGreetingCall) - require.NoError(t, err) - t.Log("Full user operation calldata:", common.Bytes2Hex(fullEncoding)) - - // Deposit to LINK paymaster. - linkTokenAddress, _, linkToken, err := link_token_interface.DeployLinkToken(holder1, backend.Client()) - require.NoError(t, err) - linkEthFeedAddress, _, _, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract( - holder1, - backend.Client(), - 18, - (*big.Int)(assets.GWei(5000000)), // .005 ETH - ) - require.NoError(t, err) - paymasterAddress, _, _, err := paymaster_wrapper.DeployPaymaster(holder1, backend.Client(), linkTokenAddress, linkEthFeedAddress, universe.entryPointAddress) - require.NoError(t, err) - backend.Commit() - tx, err := linkToken.TransferAndCall( - holder1, - paymasterAddress, - assets.Ether(1000).ToInt(), - common.LeftPadBytes(toDeployAddress.Bytes(), 32), - ) - require.NoError(t, err) - backend.Commit() - _, err = bind.WaitMined(testutils.Context(t), backend.Client(), tx) - require.NoError(t, err) - - // Construct and execute user operation. - userOp := entry_point.UserOperation{ - Sender: toDeployAddress, - Nonce: nonce, - InitCode: fullInitializeCode, - CallData: fullEncoding, - CallGasLimit: big.NewInt(10_000_000), - VerificationGasLimit: big.NewInt(10_000_000), - PreVerificationGas: big.NewInt(10_000_000), - MaxFeePerGas: big.NewInt(100), - MaxPriorityFeePerGas: big.NewInt(200), - PaymasterAndData: paymasterAddress.Bytes(), - Signature: []byte(""), - } - - // Generate hash from user operation, sign it, and include it in the user operation. - userOpHash, err := universe.entryPoint.GetUserOpHash(nil, userOp) - require.NoError(t, err) - fullHash, err := universe.helper.GetFullHashForSigning(nil, userOpHash, toDeployAddress) - require.NoError(t, err) - t.Log("Full hash for signing:", common.Bytes2Hex(fullHash[:])) - sig, err := transmission.SignMessage(universe.holder1Key.ToEcdsaPrivKey(), fullHash[:]) - require.NoError(t, err) - t.Log("Signature:", common.Bytes2Hex(sig)) - userOp.Signature = sig - - // Deposit to the Paymaster's account to pay for this transaction. - holder1.Value = assets.Ether(10).ToInt() - tx, err = universe.entryPoint.DepositTo(holder1, paymasterAddress) - require.NoError(t, err) - backend.Commit() - _, err = bind.WaitMined(testutils.Context(t), backend.Client(), tx) - require.NoError(t, err) - holder1.Value = assets.Ether(0).ToInt() - balance, err := universe.entryPoint.BalanceOf(nil, paymasterAddress) - require.NoError(t, err) - require.Equal(t, assets.Ether(10).ToInt(), balance) - - // Run handleOps from holder2's account, to demonstrate that any account can execute this signed user operation. - tx, err = universe.entryPoint.HandleOps(holder2, []entry_point.UserOperation{userOp}, holder1.From) - require.NoError(t, err) - backend.Commit() - _, err = bind.WaitMined(testutils.Context(t), backend.Client(), tx) - require.NoError(t, err) - - // Ensure "bye" was successfully set as the greeting. - greetingResult, err := universe.greeter.GetGreeting(nil) - require.NoError(t, err) - require.Equal(t, "bye", greetingResult) - - // Assert smart contract account is created and nonce incremented. - sca, err := sca_wrapper.NewSCA(toDeployAddress, backend.Client()) - require.NoError(t, err) - onChainNonce, err := sca.SNonce(nil) - require.NoError(t, err) - require.Equal(t, big.NewInt(1), onChainNonce) -} - -func Test4337WithLinkTokenVRFRequestAndPaymaster(t *testing.T) { - // Deploy universe. - universe := deployTransmissionUniverse(t) - holder1 := universe.holder1 - holder2 := universe.holder2 - backend := universe.backend - - // Get the address at which the Smart Contract Account will be deployed. - toDeployAddress, err := universe.helper.CalculateSmartContractAccountAddress( - nil, - holder1.From, - universe.entryPointAddress, - universe.factoryAddress, - ) - require.NoError(t, err) - t.Log("Smart Contract Account Address:", toDeployAddress) - - // Get the initialization code for the Smart Contract Account. - fullInitializeCode, err := universe.helper.GetInitCode(nil, universe.factoryAddress, holder1.From, universe.entryPointAddress) - require.NoError(t, err) - t.Log("Full initialization code:", common.Bytes2Hex(fullInitializeCode)) - - // Construct calldata for the vrf request. - var keyhash [32]byte - copy(keyhash[:], common.LeftPadBytes(big.NewInt(123).Bytes(), 32)) - var fee = assets.Ether(1).ToInt() - encodedVRFRequest, err := consumerABI.Pack("doRequestRandomness", keyhash, fee) - require.NoError(t, err) - t.Log("Encoded vrf request:", common.Bytes2Hex(encodedVRFRequest)) - - // Construct the calldata to be passed in the user operation. - var ( - value = big.NewInt(0) - nonce = big.NewInt(0) - deadline = big.NewInt(1000) - ) - fullEncoding, err := universe.helper.GetFullEndTxEncoding(nil, universe.vrfConsumerAddress, value, deadline, encodedVRFRequest) - require.NoError(t, err) - t.Log("Full user operation calldata:", common.Bytes2Hex(fullEncoding)) - - // Deposit to LINK paymaster. - paymasterAddress, _, _, err := paymaster_wrapper.DeployPaymaster(holder1, backend.Client(), universe.linkTokenAddress, universe.linkEthFeedAddress, universe.entryPointAddress) - require.NoError(t, err) - backend.Commit() - tx, err := universe.linkToken.TransferAndCall( - holder1, - paymasterAddress, - assets.Ether(1000).ToInt(), - common.LeftPadBytes(toDeployAddress.Bytes(), 32), - ) - require.NoError(t, err) - backend.Commit() - - ctx := testutils.Context(t) - _, err = bind.WaitMined(ctx, backend.Client(), tx) - require.NoError(t, err) - - // Generate encoded paymaster data to fund the VRF consumer. - encodedPaymasterData, err := universe.helper.GetAbiEncodedDirectRequestData(nil, universe.vrfConsumerAddress, fee, fee) - require.NoError(t, err) - - // Construct and execute user operation. - userOp := entry_point.UserOperation{ - Sender: toDeployAddress, - Nonce: nonce, - InitCode: fullInitializeCode, - CallData: fullEncoding, - CallGasLimit: big.NewInt(10_000_000), - VerificationGasLimit: big.NewInt(10_000_000), - PreVerificationGas: big.NewInt(10_000_000), - MaxFeePerGas: big.NewInt(100), - MaxPriorityFeePerGas: big.NewInt(200), - PaymasterAndData: append(append(paymasterAddress.Bytes(), byte(0)), encodedPaymasterData...), - Signature: []byte(""), - } - - // Generate hash from user operation, sign it, and include it in the user operation. - userOpHash, err := universe.entryPoint.GetUserOpHash(nil, userOp) - require.NoError(t, err) - fullHash, err := universe.helper.GetFullHashForSigning(nil, userOpHash, toDeployAddress) - require.NoError(t, err) - t.Log("Full hash for signing:", common.Bytes2Hex(fullHash[:])) - sig, err := transmission.SignMessage(universe.holder1Key.ToEcdsaPrivKey(), fullHash[:]) - require.NoError(t, err) - t.Log("Signature:", common.Bytes2Hex(sig)) - userOp.Signature = sig - - // Deposit to the Paymaster's account to pay for this transaction. - holder1.Value = assets.Ether(10).ToInt() - tx, err = universe.entryPoint.DepositTo(holder1, paymasterAddress) - require.NoError(t, err) - backend.Commit() - _, err = bind.WaitMined(ctx, backend.Client(), tx) - require.NoError(t, err) - holder1.Value = assets.Ether(0).ToInt() - balance, err := universe.entryPoint.BalanceOf(nil, paymasterAddress) - require.NoError(t, err) - require.Equal(t, assets.Ether(10).ToInt(), balance) - - // Run handleOps from holder2's account, to demonstrate that any account can execute this signed user operation. - // Manually execute transaction to test ABI packing. - gasPrice, err := backend.Client().SuggestGasPrice(ctx) - require.NoError(t, err) - accountNonce, err := backend.Client().PendingNonceAt(ctx, holder2.From) - require.NoError(t, err) - payload, err := entrypointABI.Pack("handleOps", []entry_point.UserOperation{userOp}, holder1.From) - require.NoError(t, err) - gas, err := backend.Client().EstimateGas(ctx, ethereum.CallMsg{ - From: holder2.From, - To: &universe.entryPointAddress, - Gas: 0, - Data: payload, - GasPrice: gasPrice, - }) - unsigned := types.NewTx(&types.LegacyTx{ - Nonce: accountNonce, - Gas: gas, - To: &universe.entryPointAddress, - Value: big.NewInt(0), - Data: payload, - GasPrice: gasPrice, - }) - require.NoError(t, err) - signedtx, err := holder2.Signer(holder2.From, unsigned) - require.NoError(t, err) - err = backend.Client().SendTransaction(ctx, signedtx) - require.NoError(t, err) - backend.Commit() - receipt, err := bind.WaitMined(ctx, backend.Client(), signedtx) - require.NoError(t, err) - t.Log("Receipt:", receipt.Status) - - // Assert the VRF request was correctly made. - logs, err := backend.Client().FilterLogs(ctx, ethereum.FilterQuery{ - Addresses: []common.Address{universe.vrfCoordinatorAddress}, - }) - require.NoError(t, err) - require.Equal(t, 1, len(logs)) - randomnessRequestLog, err := universe.vrfCoordinator.ParseRandomnessRequest(logs[0]) - require.NoError(t, err) - require.Equal(t, fee, randomnessRequestLog.Fee) - require.Equal(t, keyhash, randomnessRequestLog.KeyHash) - require.Equal(t, universe.vrfConsumerAddress, randomnessRequestLog.Sender) - - // Assert smart contract account is created and nonce incremented. - sca, err := sca_wrapper.NewSCA(toDeployAddress, backend.Client()) - require.NoError(t, err) - onChainNonce, err := sca.SNonce(nil) - require.NoError(t, err) - require.Equal(t, big.NewInt(1), onChainNonce) -} diff --git a/core/services/transmission/signature.go b/core/services/transmission/signature.go deleted file mode 100644 index 50b7bc584dc..00000000000 --- a/core/services/transmission/signature.go +++ /dev/null @@ -1,19 +0,0 @@ -package transmission - -import ( - "crypto/ecdsa" - - "github.com/ethereum/go-ethereum/crypto" -) - -func SignMessage( - ownerPrivateKey *ecdsa.PrivateKey, - message []byte, -) ([]byte, error) { - sig, err := crypto.Sign(message, ownerPrivateKey) - if err != nil { - return nil, err - } - - return sig, nil -} diff --git a/core/services/vrf/delegate.go b/core/services/vrf/delegate.go index c5b4df3f811..ec2139c014f 100644 --- a/core/services/vrf/delegate.go +++ b/core/services/vrf/delegate.go @@ -17,12 +17,12 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/aggregator_v3_interface" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_vrf_coordinator_v2" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/solidity_vrf_coordinator_interface" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2_5" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_owner" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/aggregator_v3_interface" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" diff --git a/core/services/vrf/delegate_test.go b/core/services/vrf/delegate_test.go index 7ef3febd021..03abaae29b6 100644 --- a/core/services/vrf/delegate_test.go +++ b/core/services/vrf/delegate_test.go @@ -82,7 +82,7 @@ func buildVrfUni(t *testing.T, db *sqlx.DB, cfg chainlink.GeneralConfig) vrfUniv btORM := bridges.NewORM(db) ks := keystore.NewInMemory(db, utils.FastScryptParams, lggr) _, dbConfig, evmConfig := txmgr.MakeTestConfigs(t) - txm, err := txmgr.NewTxm(db, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), nil, dbConfig, dbConfig.Listener(), ec, logger.TestLogger(t), nil, ks.Eth(), nil, nil) + txm, err := txmgr.NewTxm(db, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), nil, dbConfig, dbConfig.Listener(), ec, logger.TestLogger(t), nil, ks.Eth(), nil, nil, nil) orm := headtracker.NewORM(*testutils.FixtureChainID, db) require.NoError(t, orm.IdempotentInsertHead(testutils.Context(t), cltest.Head(51))) jrm := job.NewORM(db, prm, btORM, ks, lggr) diff --git a/core/services/vrf/mocks/aggregator_v3_interface.go b/core/services/vrf/mocks/aggregator_v3_interface.go index e5c1e215645..d4e9fd255e2 100644 --- a/core/services/vrf/mocks/aggregator_v3_interface.go +++ b/core/services/vrf/mocks/aggregator_v3_interface.go @@ -1,11 +1,11 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks import ( big "math/big" - aggregator_v3_interface "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/aggregator_v3_interface" + aggregator_v3_interface "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/aggregator_v3_interface" bind "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -27,7 +27,7 @@ func (_m *AggregatorV3InterfaceInterface) EXPECT() *AggregatorV3InterfaceInterfa return &AggregatorV3InterfaceInterface_Expecter{mock: &_m.Mock} } -// Address provides a mock function with given fields: +// Address provides a mock function with no fields func (_m *AggregatorV3InterfaceInterface) Address() common.Address { ret := _m.Called() diff --git a/core/services/vrf/mocks/config.go b/core/services/vrf/mocks/config.go index fa908d30f56..b6195933599 100644 --- a/core/services/vrf/mocks/config.go +++ b/core/services/vrf/mocks/config.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -17,7 +17,7 @@ func (_m *Config) EXPECT() *Config_Expecter { return &Config_Expecter{mock: &_m.Mock} } -// FinalityDepth provides a mock function with given fields: +// FinalityDepth provides a mock function with no fields func (_m *Config) FinalityDepth() uint32 { ret := _m.Called() @@ -62,7 +62,7 @@ func (_c *Config_FinalityDepth_Call) RunAndReturn(run func() uint32) *Config_Fin return _c } -// MinIncomingConfirmations provides a mock function with given fields: +// MinIncomingConfirmations provides a mock function with no fields func (_m *Config) MinIncomingConfirmations() uint32 { ret := _m.Called() diff --git a/core/services/vrf/mocks/fee_config.go b/core/services/vrf/mocks/fee_config.go index 3f3ca570460..ee0e869ffba 100644 --- a/core/services/vrf/mocks/fee_config.go +++ b/core/services/vrf/mocks/fee_config.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -24,7 +24,7 @@ func (_m *FeeConfig) EXPECT() *FeeConfig_Expecter { return &FeeConfig_Expecter{mock: &_m.Mock} } -// LimitDefault provides a mock function with given fields: +// LimitDefault provides a mock function with no fields func (_m *FeeConfig) LimitDefault() uint64 { ret := _m.Called() @@ -69,7 +69,7 @@ func (_c *FeeConfig_LimitDefault_Call) RunAndReturn(run func() uint64) *FeeConfi return _c } -// LimitJobType provides a mock function with given fields: +// LimitJobType provides a mock function with no fields func (_m *FeeConfig) LimitJobType() config.LimitJobType { ret := _m.Called() diff --git a/core/services/vrf/mocks/vrf_coordinator_v2.go b/core/services/vrf/mocks/vrf_coordinator_v2.go index 578ea83ce61..8db8fca7219 100644 --- a/core/services/vrf/mocks/vrf_coordinator_v2.go +++ b/core/services/vrf/mocks/vrf_coordinator_v2.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -209,7 +209,7 @@ func (_c *VRFCoordinatorV2Interface_AddConsumer_Call) RunAndReturn(run func(*bin return _c } -// Address provides a mock function with given fields: +// Address provides a mock function with no fields func (_m *VRFCoordinatorV2Interface) Address() common.Address { ret := _m.Called() diff --git a/core/services/vrf/solidity_cross_tests/vrf_v08_solidity_crosscheck_test.go b/core/services/vrf/solidity_cross_tests/vrf_v08_solidity_crosscheck_test.go index 98ca510a9ca..8b88ad73ea9 100644 --- a/core/services/vrf/solidity_cross_tests/vrf_v08_solidity_crosscheck_test.go +++ b/core/services/vrf/solidity_cross_tests/vrf_v08_solidity_crosscheck_test.go @@ -139,23 +139,6 @@ func TestVRFV08_CompareFieldHash(t *testing.T) { } } -// randomKey deterministically generates a secp256k1 key. -// -// Never use this if cryptographic security is required -//func randomKey(t *testing.T, r *mrand.Rand) *ecdsa.PrivateKey { -// secretKey := vrfkey.FieldSize -// for secretKey.Cmp(vrfkey.FieldSize) >= 0 { // Keep picking until secretKey < fieldSize -// secretKey = randomUint256(t, r) -// } -// cKey := crypto.ToECDSAUnsafe(secretKey.Bytes()) -// return cKey -//} -// -// pair returns the inputs as a length-2 big.Int array. Useful for translating -// coordinates to the uint256[2]'s VRF.sol uses to represent secp256k1 points. -//func pair(x, y *big.Int) [2]*big.Int { return [2]*big.Int{x, y} } -//func asPair(p kyber.Point) [2]*big.Int { return pair(secp256k1.Coordinates(p)) } - func TestVRFV08_CompareHashToCurve(t *testing.T) { t.Parallel() r := mrand.New(mrand.NewSource(4)) @@ -173,40 +156,6 @@ func TestVRFV08_CompareHashToCurve(t *testing.T) { } } -// randomPoint deterministically simulates a uniform sample of secp256k1 points, -// given r's seed -// -// Never use this if cryptographic security is required -//func randomPoint(t *testing.T, r *mrand.Rand) kyber.Point { -// p, err := vrfkey.HashToCurve(vrfkey.Generator, randomUint256(t, r), func(*big.Int) {}) -// require.NoError(t, err, -// "failed to hash random value to secp256k1 while generating random point") -// if r.Int63n(2) == 1 { // Uniform sample of ±p -// p.Neg(p) -// } -// return p -//} -// -//// randomPointWithPair returns a random secp256k1, both as a kyber.Point and as -//// a pair of *big.Int's. Useful for translating between the types needed by the -//// golang contract wrappers. -//func randomPointWithPair(t *testing.T, r *mrand.Rand) (kyber.Point, [2]*big.Int) { -// p := randomPoint(t, r) -// return p, asPair(p) -//} - -// randomScalar deterministically simulates a uniform sample of secp256k1 -// scalars, given r's seed -// -// Never use this if cryptographic security is required -//func randomScalar(t *testing.T, r *mrand.Rand) kyber.Scalar { -// s := randomUint256(t, r) -// for s.Cmp(secp256k1.GroupOrder) >= 0 { -// s = randomUint256(t, r) -// } -// return secp256k1.IntToScalar(s) -//} - func TestVRFV08_CheckSolidityPointAddition(t *testing.T) { t.Parallel() r := mrand.New(mrand.NewSource(5)) diff --git a/core/services/vrf/v2/integration_v2_test.go b/core/services/vrf/v2/integration_v2_test.go index 6cbcc799e1b..c07ad6c782f 100644 --- a/core/services/vrf/v2/integration_v2_test.go +++ b/core/services/vrf/v2/integration_v2_test.go @@ -141,7 +141,7 @@ func makeTestTxm(t *testing.T, txStore txmgr.TestEvmTxStore, keyStore keystore.M _, _, evmConfig := txmgr.MakeTestConfigs(t) txmConfig := txmgr.NewEvmTxmConfig(evmConfig) txm := txmgr.NewEvmTxm(ec.ConfiguredChainID(), txmConfig, evmConfig.Transactions(), keyStore.Eth(), logger.TestLogger(t), nil, nil, - nil, txStore, nil, nil, nil, nil, nil) + nil, txStore, nil, nil, nil, nil, nil, nil) return txm } diff --git a/core/services/vrf/v2/listener_v2.go b/core/services/vrf/v2/listener_v2.go index e820cff63b7..b9238d394a7 100644 --- a/core/services/vrf/v2/listener_v2.go +++ b/core/services/vrf/v2/listener_v2.go @@ -21,12 +21,12 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/aggregator_v3_interface" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_vrf_coordinator_v2" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_vrf_coordinator_v2plus" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2plus_interface" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_owner" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/aggregator_v3_interface" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" diff --git a/core/services/vrf/v2/listener_v2_log_listener_test.go b/core/services/vrf/v2/listener_v2_log_listener_test.go index 06af4c83f19..a29449a7ebf 100644 --- a/core/services/vrf/v2/listener_v2_log_listener_test.go +++ b/core/services/vrf/v2/listener_v2_log_listener_test.go @@ -26,9 +26,9 @@ import ( evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" evmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm/mocks" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_log_emitter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/log_emitter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/vrf_log_emitter" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" diff --git a/core/services/vrf/v2/listener_v2_test.go b/core/services/vrf/v2/listener_v2_test.go index b7a8710c4f8..e2a2a703de8 100644 --- a/core/services/vrf/v2/listener_v2_test.go +++ b/core/services/vrf/v2/listener_v2_test.go @@ -40,7 +40,7 @@ func makeTestTxm(t *testing.T, txStore txmgr.TestEvmTxStore, keyStore keystore.M ec := evmtest.NewEthClientMockWithDefaultChain(t) txmConfig := txmgr.NewEvmTxmConfig(evmConfig) txm := txmgr.NewEvmTxm(ec.ConfiguredChainID(), txmConfig, evmConfig.Transactions(), keyStore.Eth(), logger.TestLogger(t), nil, nil, - nil, txStore, nil, nil, nil, nil, nil) + nil, txStore, nil, nil, nil, nil, nil, nil) return txm } diff --git a/core/services/webhook/mocks/external_initiator_manager.go b/core/services/webhook/mocks/external_initiator_manager.go index e622217f0e5..3d3afc4d895 100644 --- a/core/services/webhook/mocks/external_initiator_manager.go +++ b/core/services/webhook/mocks/external_initiator_manager.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/webhook/mocks/http_client.go b/core/services/webhook/mocks/http_client.go index ff79cd20c8d..e795914057e 100644 --- a/core/services/webhook/mocks/http_client.go +++ b/core/services/webhook/mocks/http_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/workflows/delegate.go b/core/services/workflows/delegate.go index fc8fe3fe840..9e50f5ec092 100644 --- a/core/services/workflows/delegate.go +++ b/core/services/workflows/delegate.go @@ -81,7 +81,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) ([]job.Ser type noopSecretsFetcher struct{} -func (n *noopSecretsFetcher) SecretsFor(ctx context.Context, workflowOwner, workflowName, workflowID string) (map[string]string, error) { +func (n *noopSecretsFetcher) SecretsFor(ctx context.Context, workflowOwner, hexWorkflowName, decodedWorkflowName, workflowID string) (map[string]string, error) { return map[string]string{}, nil } diff --git a/core/services/workflows/engine.go b/core/services/workflows/engine.go index d153e53bc07..f6e73bb8bc5 100644 --- a/core/services/workflows/engine.go +++ b/core/services/workflows/engine.go @@ -96,7 +96,7 @@ func (sucm *stepUpdateManager) len() int64 { } type secretsFetcher interface { - SecretsFor(ctx context.Context, workflowOwner, workflowName, workflowID string) (map[string]string, error) + SecretsFor(ctx context.Context, workflowOwner, hexWorkflowName, decodedWorkflowName, workflowID string) (map[string]string, error) } // Engine handles the lifecycle of a single workflow and its executions. @@ -440,6 +440,7 @@ func (e *Engine) registerTrigger(ctx context.Context, t *triggerCapability, trig WorkflowDonID: e.localNode.WorkflowDON.ID, WorkflowDonConfigVersion: e.localNode.WorkflowDON.ConfigVersion, ReferenceID: t.Ref, + DecodedWorkflowName: e.workflow.name, }, Config: t.config.Load(), TriggerID: triggerID, @@ -868,7 +869,7 @@ func (e *Engine) interpolateEnvVars(config map[string]any, env exec.Env) (*value // registry (for capability-level configuration). It doesn't perform any caching of the config values, since // the two registries perform their own caching. func (e *Engine) configForStep(ctx context.Context, lggr logger.Logger, step *step) (*values.Map, error) { - secrets, err := e.secretsFetcher.SecretsFor(ctx, e.workflow.owner, e.workflow.hexName, e.workflow.id) + secrets, err := e.secretsFetcher.SecretsFor(ctx, e.workflow.owner, e.workflow.hexName, e.workflow.name, e.workflow.id) if err != nil { return nil, fmt.Errorf("failed to fetch secrets: %w", err) } @@ -964,6 +965,7 @@ func (e *Engine) executeStep(ctx context.Context, lggr logger.Logger, msg stepRe WorkflowDonID: e.localNode.WorkflowDON.ID, WorkflowDonConfigVersion: e.localNode.WorkflowDON.ConfigVersion, ReferenceID: msg.stepRef, + DecodedWorkflowName: e.workflow.name, }, } @@ -989,6 +991,7 @@ func (e *Engine) deregisterTrigger(ctx context.Context, t *triggerCapability, tr WorkflowName: e.workflow.hexName, WorkflowOwner: e.workflow.owner, ReferenceID: t.Ref, + DecodedWorkflowName: e.workflow.name, }, TriggerID: generateTriggerId(e.workflow.id, triggerIdx), Config: t.config.Load(), @@ -1188,22 +1191,23 @@ func (e *Engine) Name() string { } type Config struct { - Workflow sdk.WorkflowSpec - WorkflowID string - WorkflowOwner string - WorkflowName string - Lggr logger.Logger - Registry core.CapabilitiesRegistry - MaxWorkerLimit int - QueueSize int - NewWorkerTimeout time.Duration - MaxExecutionDuration time.Duration - Store store.Store - Config []byte - Binary []byte - SecretsFetcher secretsFetcher - HeartbeatCadence time.Duration - StepTimeout time.Duration + Workflow sdk.WorkflowSpec + WorkflowID string + WorkflowOwner string + WorkflowName string // Full human-readable workflow name. Intended for metrics and logging. + WorkflowNameTransform string // The Workflow Name in an on-chain format, which has requirements of being hex encoded and max 10 bytes + Lggr logger.Logger + Registry core.CapabilitiesRegistry + MaxWorkerLimit int + QueueSize int + NewWorkerTimeout time.Duration + MaxExecutionDuration time.Duration + Store store.Store + Config []byte + Binary []byte + SecretsFetcher secretsFetcher + HeartbeatCadence time.Duration + StepTimeout time.Duration // For testing purposes only maxRetries int @@ -1295,6 +1299,11 @@ func NewEngine(ctx context.Context, cfg Config) (engine *Engine, err error) { workflow.id = cfg.WorkflowID workflow.owner = cfg.WorkflowOwner workflow.hexName = hex.EncodeToString([]byte(cfg.WorkflowName)) + workflow.name = cfg.WorkflowName + + if len(cfg.WorkflowNameTransform) > 0 { + workflow.hexName = cfg.WorkflowNameTransform + } engine = &Engine{ cma: cma, diff --git a/core/services/workflows/engine_test.go b/core/services/workflows/engine_test.go index 95ac74f0c76..839e3680f72 100644 --- a/core/services/workflows/engine_test.go +++ b/core/services/workflows/engine_test.go @@ -153,7 +153,7 @@ func newTestEngineWithYAMLSpec(t *testing.T, reg *coreCap.Registry, spec string, type mockSecretsFetcher struct{} -func (s mockSecretsFetcher) SecretsFor(ctx context.Context, workflowOwner, workflowName, workflowID string) (map[string]string, error) { +func (s mockSecretsFetcher) SecretsFor(ctx context.Context, workflowOwner, hexWorkflowName, decodedWorkflowName, workflowID string) (map[string]string, error) { return map[string]string{}, nil } @@ -1606,7 +1606,7 @@ type mockFetcher struct { retval map[string]string } -func (m *mockFetcher) SecretsFor(ctx context.Context, workflowOwner, workflowName, workflowID string) (map[string]string, error) { +func (m *mockFetcher) SecretsFor(ctx context.Context, workflowOwner, hexWorkflowName, decodedWorkflowName, workflowID string) (map[string]string, error) { return m.retval, nil } diff --git a/core/services/workflows/models.go b/core/services/workflows/models.go index e5d26a474f6..ec149bf6371 100644 --- a/core/services/workflows/models.go +++ b/core/services/workflows/models.go @@ -23,6 +23,7 @@ type workflow struct { id string owner string hexName string + name string graph.Graph[string, *step] triggers []*triggerCapability diff --git a/core/services/workflows/syncer/engine_registry.go b/core/services/workflows/syncer/engine_registry.go index fa3771c5a0f..ecea3b98c2f 100644 --- a/core/services/workflows/syncer/engine_registry.go +++ b/core/services/workflows/syncer/engine_registry.go @@ -19,10 +19,14 @@ func NewEngineRegistry() *EngineRegistry { } // Add adds an engine to the registry. -func (r *EngineRegistry) Add(id string, engine services.Service) { +func (r *EngineRegistry) Add(id string, engine services.Service) error { r.mu.Lock() defer r.mu.Unlock() + if _, found := r.engines[id]; found { + return errors.New("attempting to register duplicate engine") + } r.engines[id] = engine + return nil } // Get retrieves an engine from the registry. diff --git a/core/services/workflows/syncer/fetcher.go b/core/services/workflows/syncer/fetcher.go index 6a80739bbfe..2e4fbd51354 100644 --- a/core/services/workflows/syncer/fetcher.go +++ b/core/services/workflows/syncer/fetcher.go @@ -93,12 +93,24 @@ func (s *FetcherService) Fetch(ctx context.Context, url string) ([]byte, error) return nil, err } - s.lggr.Debugw("received gateway response") + if err = resp.Validate(); err != nil { + return nil, fmt.Errorf("invalid response from gateway: %w", err) + } + + s.lggr.Debugw("received gateway response", "donID", resp.Body.DonId, "msgID", resp.Body.MessageId) + var payload ghcapabilities.Response - err = json.Unmarshal(resp.Body.Payload, &payload) - if err != nil { + if err = json.Unmarshal(resp.Body.Payload, &payload); err != nil { return nil, err } + if err = payload.Validate(); err != nil { + return nil, fmt.Errorf("invalid payload received from gateway message: %w", err) + } + + if payload.ExecutionError { + return nil, fmt.Errorf("execution error from gateway: %s", payload.ErrorMessage) + } + return payload.Body, nil } diff --git a/core/services/workflows/syncer/fetcher_test.go b/core/services/workflows/syncer/fetcher_test.go index ee59d22608a..600cde5c577 100644 --- a/core/services/workflows/syncer/fetcher_test.go +++ b/core/services/workflows/syncer/fetcher_test.go @@ -2,6 +2,7 @@ package syncer import ( "context" + "crypto/ecdsa" "encoding/json" "strings" "testing" @@ -11,10 +12,12 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/api" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/common" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/connector" gcmocks "github.com/smartcontractkit/chainlink/v2/core/services/gateway/connector/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/capabilities" ghcapabilities "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/capabilities" + "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/utils/matches" ) @@ -33,9 +36,11 @@ func TestNewFetcherService(t *testing.T) { connector := gcmocks.NewGatewayConnector(t) wrapper := &wrapper{c: connector} - url := "http://example.com" - - msgID := strings.Join([]string{ghcapabilities.MethodWorkflowSyncer, hash(url)}, "/") + var ( + url = "http://example.com" + msgID = strings.Join([]string{ghcapabilities.MethodWorkflowSyncer, hash(url)}, "/") + donID = "don-id" + ) t.Run("OK-valid_request", func(t *testing.T) { connector.EXPECT().AddHandler([]string{capabilities.MethodWorkflowSyncer}, mock.Anything).Return(nil) @@ -44,11 +49,11 @@ func TestNewFetcherService(t *testing.T) { require.NoError(t, fetcher.Start(ctx)) defer fetcher.Close() - gatewayResp := gatewayResponse(t, msgID) + gatewayResp := signGatewayResponse(t, gatewayResponse(t, msgID, donID)) connector.EXPECT().SignAndSendToGateway(mock.Anything, "gateway1", mock.Anything).Run(func(ctx context.Context, gatewayID string, msg *api.MessageBody) { fetcher.och.HandleGatewayMessage(ctx, "gateway1", gatewayResp) }).Return(nil).Times(1) - connector.EXPECT().DonID().Return("don-id") + connector.EXPECT().DonID().Return(donID) connector.EXPECT().AwaitConnection(matches.AnyContext, "gateway1").Return(nil) connector.EXPECT().GatewayIDs().Return([]string{"gateway1", "gateway2"}) @@ -58,23 +63,137 @@ func TestNewFetcherService(t *testing.T) { expectedPayload := []byte("response body") require.Equal(t, expectedPayload, payload) }) + + t.Run("fails with invalid payload response", func(t *testing.T) { + connector.EXPECT().AddHandler([]string{capabilities.MethodWorkflowSyncer}, mock.Anything).Return(nil) + + fetcher := NewFetcherService(lggr, wrapper) + require.NoError(t, fetcher.Start(ctx)) + defer fetcher.Close() + + gatewayResp := signGatewayResponse(t, inconsistentPayload(t, msgID, donID)) + connector.EXPECT().SignAndSendToGateway(mock.Anything, "gateway1", mock.Anything).Run(func(ctx context.Context, gatewayID string, msg *api.MessageBody) { + fetcher.och.HandleGatewayMessage(ctx, "gateway1", gatewayResp) + }).Return(nil).Times(1) + connector.EXPECT().DonID().Return(donID) + connector.EXPECT().AwaitConnection(matches.AnyContext, "gateway1").Return(nil) + connector.EXPECT().GatewayIDs().Return([]string{"gateway1", "gateway2"}) + + _, err := fetcher.Fetch(ctx, url) + require.Error(t, err) + }) + + t.Run("fails due to invalid gateway response", func(t *testing.T) { + connector.EXPECT().AddHandler([]string{capabilities.MethodWorkflowSyncer}, mock.Anything).Return(nil) + + fetcher := NewFetcherService(lggr, wrapper) + require.NoError(t, fetcher.Start(ctx)) + defer fetcher.Close() + + gatewayResp := gatewayResponse(t, msgID, donID) // gateway response that is not signed + connector.EXPECT().SignAndSendToGateway(mock.Anything, "gateway1", mock.Anything).Run(func(ctx context.Context, gatewayID string, msg *api.MessageBody) { + fetcher.och.HandleGatewayMessage(ctx, "gateway1", gatewayResp) + }).Return(nil).Times(1) + connector.EXPECT().DonID().Return(donID) + connector.EXPECT().AwaitConnection(matches.AnyContext, "gateway1").Return(nil) + connector.EXPECT().GatewayIDs().Return([]string{"gateway1", "gateway2"}) + + _, err := fetcher.Fetch(ctx, url) + require.Error(t, err) + require.ErrorContains(t, err, "invalid response from gateway") + }) + + t.Run("NOK-response_payload_too_large", func(t *testing.T) { + headers := map[string]string{"Content-Type": "application/json"} + responsePayload, err := json.Marshal(ghcapabilities.Response{ + StatusCode: 400, + Headers: headers, + ErrorMessage: "http: request body too large", + }) + require.NoError(t, err) + gatewayResponse := &api.Message{ + Body: api.MessageBody{ + MessageId: msgID, + Method: ghcapabilities.MethodWebAPITarget, + Payload: responsePayload, + }, + } + + connector.EXPECT().AddHandler([]string{capabilities.MethodWorkflowSyncer}, mock.Anything).Return(nil) + + fetcher := NewFetcherService(lggr, wrapper) + require.NoError(t, fetcher.Start(ctx)) + defer fetcher.Close() + + connector.EXPECT().SignAndSendToGateway(mock.Anything, "gateway1", mock.Anything).Run(func(ctx context.Context, gatewayID string, msg *api.MessageBody) { + fetcher.och.HandleGatewayMessage(ctx, "gateway1", gatewayResponse) + }).Return(nil).Times(1) + connector.EXPECT().DonID().Return(donID) + connector.EXPECT().AwaitConnection(matches.AnyContext, "gateway1").Return(nil) + connector.EXPECT().GatewayIDs().Return([]string{"gateway1", "gateway2"}) + + _, err = fetcher.Fetch(ctx, url) + require.Error(t, err, "execution error from gateway: http: request body too large") + }) } -func gatewayResponse(t *testing.T, msgID string) *api.Message { +// gatewayResponse creates an unsigned gateway response with a status code of 200 and a response body. +func gatewayResponse(t *testing.T, msgID string, donID string) *api.Message { headers := map[string]string{"Content-Type": "application/json"} body := []byte("response body") responsePayload, err := json.Marshal(ghcapabilities.Response{ - StatusCode: 200, - Headers: headers, - Body: body, - ExecutionError: false, + StatusCode: 200, + Headers: headers, + Body: body, }) require.NoError(t, err) return &api.Message{ Body: api.MessageBody{ MessageId: msgID, + DonId: donID, Method: ghcapabilities.MethodWebAPITarget, Payload: responsePayload, }, } } + +// inconsistentPayload creates an unsigned gateway response with an inconsistent payload. The +// ExecutionError is true, but there is no ErrorMessage, so it is invalid. +func inconsistentPayload(t *testing.T, msgID string, donID string) *api.Message { + responsePayload, err := json.Marshal(ghcapabilities.Response{ + ExecutionError: true, + }) + require.NoError(t, err) + return &api.Message{ + Body: api.MessageBody{ + MessageId: msgID, + DonId: donID, + Method: ghcapabilities.MethodWebAPITarget, + Payload: responsePayload, + }, + } +} + +// signGatewayResponse signs the gateway response with a private key and arbitrarily sets the receiver +// to the signer's address. A signature and receiver are required for a valid gateway response. +func signGatewayResponse(t *testing.T, msg *api.Message) *api.Message { + nodeKeys := common.NewTestNodes(t, 1) + s := &signer{pk: nodeKeys[0].PrivateKey} + signature, err := s.Sign(api.GetRawMessageBody(&msg.Body)...) + require.NoError(t, err) + msg.Signature = utils.StringToHex(string(signature)) + + signerBytes, err := msg.ExtractSigner() + require.NoError(t, err) + + msg.Body.Receiver = utils.StringToHex(string(signerBytes)) + return msg +} + +type signer struct { + pk *ecdsa.PrivateKey +} + +func (s *signer) Sign(data ...[]byte) ([]byte, error) { + return common.SignData(s.pk, data...) +} diff --git a/core/services/workflows/syncer/handler.go b/core/services/workflows/syncer/handler.go index 534dfd57e7b..f560a96da25 100644 --- a/core/services/workflows/syncer/handler.go +++ b/core/services/workflows/syncer/handler.go @@ -3,6 +3,7 @@ package syncer import ( "bytes" "context" + "database/sql" "encoding/base64" "encoding/hex" "encoding/json" @@ -223,7 +224,7 @@ func (h *eventHandler) refreshSecrets(ctx context.Context, workflowOwner, workfl return updatedSecrets, nil } -func (h *eventHandler) SecretsFor(ctx context.Context, workflowOwner, workflowName, workflowID string) (map[string]string, error) { +func (h *eventHandler) SecretsFor(ctx context.Context, workflowOwner, hexWorkflowName, decodedWorkflowName, workflowID string) (map[string]string, error) { secretsURLHash, secretsPayload, err := h.orm.GetContentsByWorkflowID(ctx, workflowID) if err != nil { // The workflow record was found, but secrets_id was empty. @@ -237,15 +238,16 @@ func (h *eventHandler) SecretsFor(ctx context.Context, workflowOwner, workflowNa lastFetchedAt, ok := h.lastFetchedAtMap.Get(secretsURLHash) if !ok || h.clock.Now().Sub(lastFetchedAt) > h.secretsFreshnessDuration { - updatedSecrets, innerErr := h.refreshSecrets(ctx, workflowOwner, workflowName, workflowID, secretsURLHash) + updatedSecrets, innerErr := h.refreshSecrets(ctx, workflowOwner, hexWorkflowName, workflowID, secretsURLHash) if innerErr != nil { msg := fmt.Sprintf("could not refresh secrets: proceeding with stale secrets for workflowID %s: %s", workflowID, innerErr) h.lggr.Error(msg) + logCustMsg( ctx, h.emitter.With( platform.KeyWorkflowID, workflowID, - platform.KeyWorkflowName, workflowName, + platform.KeyWorkflowName, decodedWorkflowName, platform.KeyWorkflowOwner, workflowOwner, ), msg, @@ -482,7 +484,11 @@ func (h *eventHandler) workflowRegisteredEvent( return fmt.Errorf("failed to start workflow engine: %w", err) } - h.engineRegistry.Add(wfID, engine) + // This shouldn't happen because we call the handler serially and + // check for running engines above, see the call to engineRegistry.IsRunning. + if err := h.engineRegistry.Add(wfID, engine); err != nil { + return fmt.Errorf("invariant violation: %w", err) + } return nil } @@ -493,34 +499,35 @@ func (h *eventHandler) getWorkflowArtifacts( ctx context.Context, payload WorkflowRegistryWorkflowRegisteredV1, ) ([]byte, []byte, error) { - spec, err := h.orm.GetWorkflowSpecByID(ctx, hex.EncodeToString(payload.WorkflowID[:])) - if err != nil { - binary, err2 := h.fetcher(ctx, payload.BinaryURL) - if err2 != nil { - return nil, nil, fmt.Errorf("failed to fetch binary from %s : %w", payload.BinaryURL, err) + // Check if the workflow spec is already stored in the database + if spec, err := h.orm.GetWorkflowSpecByID(ctx, hex.EncodeToString(payload.WorkflowID[:])); err == nil { + // there is no update in the BinaryURL or ConfigURL, lets decode the stored artifacts + decodedBinary, err := hex.DecodeString(spec.Workflow) + if err != nil { + return nil, nil, fmt.Errorf("failed to decode stored workflow spec: %w", err) } + return decodedBinary, []byte(spec.Config), nil + } - decodedBinary, err2 := base64.StdEncoding.DecodeString(string(binary)) - if err2 != nil { - return nil, nil, fmt.Errorf("failed to decode binary: %w", err) - } + // Fetch the binary and config files from the specified URLs. + var ( + binary, decodedBinary, config []byte + err error + ) + if binary, err = h.fetcher(ctx, payload.BinaryURL); err != nil { + return nil, nil, fmt.Errorf("failed to fetch binary from %s : %w", payload.BinaryURL, err) + } - var config []byte - if payload.ConfigURL != "" { - config, err2 = h.fetcher(ctx, payload.ConfigURL) - if err2 != nil { - return nil, nil, fmt.Errorf("failed to fetch config from %s : %w", payload.ConfigURL, err) - } - } - return decodedBinary, config, nil + if decodedBinary, err = base64.StdEncoding.DecodeString(string(binary)); err != nil { + return nil, nil, fmt.Errorf("failed to decode binary: %w", err) } - // there is no update in the BinaryURL or ConfigURL, lets decode the stored artifacts - decodedBinary, err := hex.DecodeString(spec.Workflow) - if err != nil { - return nil, nil, fmt.Errorf("failed to decode stored workflow spec: %w", err) + if payload.ConfigURL != "" { + if config, err = h.fetcher(ctx, payload.ConfigURL); err != nil { + return nil, nil, fmt.Errorf("failed to fetch config from %s : %w", payload.ConfigURL, err) + } } - return decodedBinary, []byte(spec.Config), nil + return decodedBinary, config, nil } func (h *eventHandler) engineFactoryFn(ctx context.Context, id string, owner string, name string, config []byte, binary []byte) (services.Service, error) { @@ -531,16 +538,20 @@ func (h *eventHandler) engineFactoryFn(ctx context.Context, id string, owner str } cfg := workflows.Config{ - Lggr: h.lggr, - Workflow: *sdkSpec, - WorkflowID: id, - WorkflowOwner: owner, // this gets hex encoded in the engine. - WorkflowName: name, - Registry: h.capRegistry, - Store: h.workflowStore, - Config: config, - Binary: binary, - SecretsFetcher: h, + Lggr: h.lggr, + Workflow: *sdkSpec, + WorkflowID: id, + WorkflowOwner: owner, // this gets hex encoded in the engine. + WorkflowName: name, + // Internal workflow names must not exceed 10 bytes for workflow engine and on-chain use. + // A name is used internally that is first hashed to avoid collisions, + // hex encoded to ensure UTF8 encoding, then truncated to 10 bytes. + WorkflowNameTransform: pkgworkflows.HashTruncateName(name), + Registry: h.capRegistry, + Store: h.workflowStore, + Config: config, + Binary: binary, + SecretsFetcher: h, } return workflows.NewEngine(ctx, cfg) } @@ -642,9 +653,15 @@ func (h *eventHandler) workflowDeletedEvent( return err } - if err := h.orm.DeleteWorkflowSpec(ctx, hex.EncodeToString(payload.WorkflowOwner), payload.WorkflowName); err != nil { + err := h.orm.DeleteWorkflowSpec(ctx, hex.EncodeToString(payload.WorkflowOwner), payload.WorkflowName) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + h.lggr.Warnw("workflow spec not found", "workflowID", hex.EncodeToString(payload.WorkflowID[:])) + return nil + } return fmt.Errorf("failed to delete workflow spec: %w", err) } + return nil } diff --git a/core/services/workflows/syncer/handler_test.go b/core/services/workflows/syncer/handler_test.go index f205cbde1cd..3b3231a3d3d 100644 --- a/core/services/workflows/syncer/handler_test.go +++ b/core/services/workflows/syncer/handler_test.go @@ -555,6 +555,61 @@ func Test_workflowDeletedHandler(t *testing.T) { _, err = h.engineRegistry.Get(wfIDs) require.Error(t, err) }) + t.Run("success deleting non-existing workflow spec", func(t *testing.T) { + var ( + ctx = testutils.Context(t) + lggr = logger.TestLogger(t) + db = pgtest.NewSqlxDB(t) + orm = NewWorkflowRegistryDS(db, lggr) + emitter = custmsg.NewLabeler() + + binary = wasmtest.CreateTestBinary(binaryCmd, binaryLocation, true, t) + encodedBinary = []byte(base64.StdEncoding.EncodeToString(binary)) + config = []byte("") + secretsURL = "http://example.com" + binaryURL = "http://example.com/binary" + configURL = "http://example.com/config" + wfOwner = []byte("0xOwner") + + fetcher = newMockFetcher(map[string]mockFetchResp{ + binaryURL: {Body: encodedBinary, Err: nil}, + configURL: {Body: config, Err: nil}, + secretsURL: {Body: []byte("secrets"), Err: nil}, + }) + ) + + giveWFID, err := pkgworkflows.GenerateWorkflowID(wfOwner, "workflow-name", binary, config, secretsURL) + require.NoError(t, err) + + er := NewEngineRegistry() + store := wfstore.NewDBStore(db, lggr, clockwork.NewFakeClock()) + registry := capabilities.NewRegistry(lggr) + registry.SetLocalRegistry(&capabilities.TestMetadataRegistry{}) + h := NewEventHandler( + lggr, + orm, + fetcher, + store, + registry, + emitter, + clockwork.NewFakeClock(), + workflowkey.Key{}, + WithEngineRegistry(er), + ) + + deleteEvent := WorkflowRegistryWorkflowDeletedV1{ + WorkflowID: giveWFID, + WorkflowOwner: wfOwner, + WorkflowName: "workflow-name", + DonID: 1, + } + err = h.workflowDeletedEvent(ctx, deleteEvent) + require.NoError(t, err) + + // Verify the record is deleted in the database + _, err = orm.GetWorkflowSpec(ctx, hex.EncodeToString(wfOwner), "workflow-name") + require.Error(t, err) + }) } func Test_workflowPausedActivatedUpdatedHandler(t *testing.T) { @@ -725,6 +780,7 @@ func Test_Handler_SecretsFor(t *testing.T) { workflowOwner := hex.EncodeToString([]byte("anOwner")) workflowName := "aName" workflowID := "anID" + decodedWorkflowName := "decodedName" encryptionKey, err := workflowkey.New() require.NoError(t, err) @@ -765,7 +821,7 @@ func Test_Handler_SecretsFor(t *testing.T) { encryptionKey, ) - gotSecrets, err := h.SecretsFor(testutils.Context(t), workflowOwner, workflowName, workflowID) + gotSecrets, err := h.SecretsFor(testutils.Context(t), workflowOwner, workflowName, decodedWorkflowName, workflowID) require.NoError(t, err) expectedSecrets := map[string]string{ @@ -782,6 +838,7 @@ func Test_Handler_SecretsFor_RefreshesSecrets(t *testing.T) { workflowOwner := hex.EncodeToString([]byte("anOwner")) workflowName := "aName" workflowID := "anID" + decodedWorkflowName := "decodedName" encryptionKey, err := workflowkey.New() require.NoError(t, err) @@ -826,7 +883,7 @@ func Test_Handler_SecretsFor_RefreshesSecrets(t *testing.T) { encryptionKey, ) - gotSecrets, err := h.SecretsFor(testutils.Context(t), workflowOwner, workflowName, workflowID) + gotSecrets, err := h.SecretsFor(testutils.Context(t), workflowOwner, workflowName, decodedWorkflowName, workflowID) require.NoError(t, err) expectedSecrets := map[string]string{ @@ -843,6 +900,7 @@ func Test_Handler_SecretsFor_RefreshLogic(t *testing.T) { workflowOwner := hex.EncodeToString([]byte("anOwner")) workflowName := "aName" workflowID := "anID" + decodedWorkflowName := "decodedName" encryptionKey, err := workflowkey.New() require.NoError(t, err) @@ -888,7 +946,7 @@ func Test_Handler_SecretsFor_RefreshLogic(t *testing.T) { encryptionKey, ) - gotSecrets, err := h.SecretsFor(testutils.Context(t), workflowOwner, workflowName, workflowID) + gotSecrets, err := h.SecretsFor(testutils.Context(t), workflowOwner, workflowName, decodedWorkflowName, workflowID) require.NoError(t, err) expectedSecrets := map[string]string{ @@ -900,7 +958,7 @@ func Test_Handler_SecretsFor_RefreshLogic(t *testing.T) { // SecretsFor should still succeed. fetcher.responseMap[url] = mockFetchResp{} - gotSecrets, err = h.SecretsFor(testutils.Context(t), workflowOwner, workflowName, workflowID) + gotSecrets, err = h.SecretsFor(testutils.Context(t), workflowOwner, workflowName, decodedWorkflowName, workflowID) require.NoError(t, err) assert.Equal(t, expectedSecrets, gotSecrets) @@ -908,7 +966,7 @@ func Test_Handler_SecretsFor_RefreshLogic(t *testing.T) { // Now advance so that we hit the freshness limit clock.Advance(48 * time.Hour) - _, err = h.SecretsFor(testutils.Context(t), workflowOwner, workflowName, workflowID) + _, err = h.SecretsFor(testutils.Context(t), workflowOwner, workflowName, decodedWorkflowName, workflowID) assert.ErrorContains(t, err, "unexpected end of JSON input") } diff --git a/core/services/workflows/syncer/mocks/orm.go b/core/services/workflows/syncer/mocks/orm.go index 09a543d65e3..29f26701bd0 100644 --- a/core/services/workflows/syncer/mocks/orm.go +++ b/core/services/workflows/syncer/mocks/orm.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/services/workflows/syncer/workflow_registry.go b/core/services/workflows/syncer/workflow_registry.go index 4809f3563ca..26c23411d67 100644 --- a/core/services/workflows/syncer/workflow_registry.go +++ b/core/services/workflows/syncer/workflow_registry.go @@ -130,14 +130,11 @@ type workflowRegistry struct { newContractReaderFn newContractReaderFn - eventPollerCfg WorkflowEventPollerConfig - eventTypes []WorkflowRegistryEventType - handler evtHandler - initialWorkflowsStateLoader initialWorkflowsStateLoader + eventPollerCfg WorkflowEventPollerConfig + eventTypes []WorkflowRegistryEventType + handler evtHandler workflowDonNotifier donNotifier - - reader ContractReader } // WithTicker allows external callers to provide a ticker to the workflowRegistry. This is useful @@ -152,12 +149,6 @@ type evtHandler interface { Handle(ctx context.Context, event Event) error } -type initialWorkflowsStateLoader interface { - // LoadWorkflows loads all the workflows for the given donID from the contract. Returns the head of the chain as of the - // point in time at which the load occurred. - LoadWorkflows(ctx context.Context, don capabilities.DON) (*types.Head, error) -} - type donNotifier interface { WaitForDon(ctx context.Context) (capabilities.DON, error) } @@ -172,7 +163,6 @@ func NewWorkflowRegistry( addr string, eventPollerConfig WorkflowEventPollerConfig, handler evtHandler, - initialWorkflowsStateLoader initialWorkflowsStateLoader, workflowDonNotifier donNotifier, opts ...func(*workflowRegistry), ) *workflowRegistry { @@ -184,16 +174,16 @@ func NewWorkflowRegistry( WorkflowRegisteredEvent, WorkflowUpdatedEvent, } + wr := &workflowRegistry{ - lggr: lggr, - newContractReaderFn: newContractReaderFn, - workflowRegistryAddress: addr, - eventPollerCfg: eventPollerConfig, - stopCh: make(services.StopChan), - eventTypes: ets, - handler: handler, - initialWorkflowsStateLoader: initialWorkflowsStateLoader, - workflowDonNotifier: workflowDonNotifier, + lggr: lggr, + newContractReaderFn: newContractReaderFn, + workflowRegistryAddress: addr, + eventPollerCfg: eventPollerConfig, + stopCh: make(services.StopChan), + eventTypes: ets, + handler: handler, + workflowDonNotifier: workflowDonNotifier, } for _, opt := range opts { @@ -220,8 +210,14 @@ func (w *workflowRegistry) Start(_ context.Context) error { return } + reader, err := w.newWorkflowRegistryContractReader(ctx) + if err != nil { + w.lggr.Criticalf("contract reader unavailable : %s", err) + return + } + w.lggr.Debugw("Loading initial workflows for DON", "DON", don.ID) - loadWorkflowsHead, err := w.initialWorkflowsStateLoader.LoadWorkflows(ctx, don) + loadWorkflowsHead, err := w.loadWorkflows(ctx, don, reader) if err != nil { // TODO - this is a temporary fix to handle the case where the chainreader errors because the contract // contains no workflows. To track: https://smartcontract-it.atlassian.net/browse/CAPPL-393 @@ -235,12 +231,6 @@ func (w *workflowRegistry) Start(_ context.Context) error { } } - reader, err := w.getContractReader(ctx) - if err != nil { - w.lggr.Criticalf("contract reader unavailable : %s", err) - return - } - w.readRegistryEvents(ctx, reader, loadWorkflowsHead.Height) }() @@ -359,36 +349,19 @@ func (w *workflowRegistry) getTicker() <-chan time.Time { return w.ticker } -// getContractReader initializes a contract reader if needed, otherwise returns the existing -// reader. -func (w *workflowRegistry) getContractReader(ctx context.Context) (ContractReader, error) { - c := types.BoundContract{ - Name: WorkflowRegistryContractName, - Address: w.workflowRegistryAddress, - } - - if w.reader == nil { - reader, err := getWorkflowRegistryEventReader(ctx, w.newContractReaderFn, c) - if err != nil { - return nil, err - } - - w.reader = reader - } - - return w.reader, nil -} - type sequenceWithEventType struct { Sequence types.Sequence EventType WorkflowRegistryEventType } -func getWorkflowRegistryEventReader( +func (w *workflowRegistry) newWorkflowRegistryContractReader( ctx context.Context, - newReaderFn newContractReaderFn, - bc types.BoundContract, ) (ContractReader, error) { + bc := types.BoundContract{ + Name: WorkflowRegistryContractName, + Address: w.workflowRegistryAddress, + } + contractReaderCfg := evmtypes.ChainReaderConfig{ Contracts: map[string]evmtypes.ChainContractReader{ WorkflowRegistryContractName: { @@ -404,6 +377,9 @@ func getWorkflowRegistryEventReader( }, ContractABI: workflow_registry_wrapper.WorkflowRegistryABI, Configs: map[string]*evmtypes.ChainReaderDefinition{ + GetWorkflowMetadataListByDONMethodName: { + ChainSpecificName: GetWorkflowMetadataListByDONMethodName, + }, string(ForceUpdateSecretsEvent): { ChainSpecificName: string(ForceUpdateSecretsEvent), ReadType: evmtypes.Event, @@ -438,7 +414,7 @@ func getWorkflowRegistryEventReader( return nil, err } - reader, err := newReaderFn(ctx, marshalledCfg) + reader, err := w.newContractReaderFn(ctx, marshalledCfg) if err != nil { return nil, err } @@ -468,59 +444,9 @@ func (r workflowAsEvent) GetData() any { return r.Data } -type workflowRegistryContractLoader struct { - lggr logger.Logger - workflowRegistryAddress string - newContractReaderFn newContractReaderFn - handler evtHandler -} - -func NewWorkflowRegistryContractLoader( - lggr logger.Logger, - workflowRegistryAddress string, - newContractReaderFn newContractReaderFn, - handler evtHandler, -) *workflowRegistryContractLoader { - return &workflowRegistryContractLoader{ - lggr: lggr.Named("WorkflowRegistryContractLoader"), - workflowRegistryAddress: workflowRegistryAddress, - newContractReaderFn: newContractReaderFn, - handler: handler, - } -} - -func (l *workflowRegistryContractLoader) LoadWorkflows(ctx context.Context, don capabilities.DON) (*types.Head, error) { - // Build the ContractReader config - contractReaderCfg := evmtypes.ChainReaderConfig{ - Contracts: map[string]evmtypes.ChainContractReader{ - WorkflowRegistryContractName: { - ContractABI: workflow_registry_wrapper.WorkflowRegistryABI, - Configs: map[string]*evmtypes.ChainReaderDefinition{ - GetWorkflowMetadataListByDONMethodName: { - ChainSpecificName: GetWorkflowMetadataListByDONMethodName, - }, - }, - }, - }, - } - - contractReaderCfgBytes, err := json.Marshal(contractReaderCfg) - if err != nil { - return nil, fmt.Errorf("failed to marshal contract reader config: %w", err) - } - - contractReader, err := l.newContractReaderFn(ctx, contractReaderCfgBytes) - if err != nil { - return nil, fmt.Errorf("failed to create contract reader: %w", err) - } - - err = contractReader.Bind(ctx, []types.BoundContract{{Name: WorkflowRegistryContractName, Address: l.workflowRegistryAddress}}) - if err != nil { - return nil, fmt.Errorf("failed to bind contract reader: %w", err) - } - +func (w *workflowRegistry) loadWorkflows(ctx context.Context, don capabilities.DON, contractReader ContractReader) (*types.Head, error) { contractBinding := types.BoundContract{ - Address: l.workflowRegistryAddress, + Address: w.workflowRegistryAddress, Name: WorkflowRegistryContractName, } @@ -540,7 +466,7 @@ func (l *workflowRegistryContractLoader) LoadWorkflows(ctx context.Context, don return nil, fmt.Errorf("failed to get lastest value with head data %w", err) } - l.lggr.Debugw("Rehydrating existing workflows", "len", len(workflows.WorkflowMetadataList)) + w.lggr.Debugw("Rehydrating existing workflows", "len", len(workflows.WorkflowMetadataList)) for _, workflow := range workflows.WorkflowMetadataList { toRegisteredEvent := WorkflowRegistryWorkflowRegisteredV1{ WorkflowID: workflow.WorkflowID, @@ -552,11 +478,11 @@ func (l *workflowRegistryContractLoader) LoadWorkflows(ctx context.Context, don ConfigURL: workflow.ConfigURL, SecretsURL: workflow.SecretsURL, } - if err = l.handler.Handle(ctx, workflowAsEvent{ + if err = w.handler.Handle(ctx, workflowAsEvent{ Data: toRegisteredEvent, EventType: WorkflowRegisteredEvent, }); err != nil { - l.lggr.Errorf("failed to handle workflow registration: %s", err) + w.lggr.Errorf("failed to handle workflow registration: %s", err) } } diff --git a/core/sessions/ldapauth/mocks/ldap_client.go b/core/sessions/ldapauth/mocks/ldap_client.go index 8f905c3cf70..7a09b6e1658 100644 --- a/core/sessions/ldapauth/mocks/ldap_client.go +++ b/core/sessions/ldapauth/mocks/ldap_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -20,7 +20,7 @@ func (_m *LDAPClient) EXPECT() *LDAPClient_Expecter { return &LDAPClient_Expecter{mock: &_m.Mock} } -// CreateEphemeralConnection provides a mock function with given fields: +// CreateEphemeralConnection provides a mock function with no fields func (_m *LDAPClient) CreateEphemeralConnection() (ldapauth.LDAPConn, error) { ret := _m.Called() diff --git a/core/sessions/ldapauth/mocks/ldap_conn.go b/core/sessions/ldapauth/mocks/ldap_conn.go index 63ba3ae5757..ccd9948f2f4 100644 --- a/core/sessions/ldapauth/mocks/ldap_conn.go +++ b/core/sessions/ldapauth/mocks/ldap_conn.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -68,7 +68,7 @@ func (_c *LDAPConn_Bind_Call) RunAndReturn(run func(string, string) error) *LDAP return _c } -// Close provides a mock function with given fields: +// Close provides a mock function with no fields func (_m *LDAPConn) Close() error { ret := _m.Called() diff --git a/core/sessions/mocks/authentication_provider.go b/core/sessions/mocks/authentication_provider.go index c319ebb0e60..844dc0f7d65 100644 --- a/core/sessions/mocks/authentication_provider.go +++ b/core/sessions/mocks/authentication_provider.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/sessions/mocks/basic_admin_users_orm.go b/core/sessions/mocks/basic_admin_users_orm.go index bf9c7f919cb..b69479f248e 100644 --- a/core/sessions/mocks/basic_admin_users_orm.go +++ b/core/sessions/mocks/basic_admin_users_orm.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks diff --git a/core/store/migrate/migrations/0036_external_job_id.go b/core/store/migrate/migrations/0036_external_job_id.go index 47442124a33..a32ff470d67 100644 --- a/core/store/migrate/migrations/0036_external_job_id.go +++ b/core/store/migrate/migrations/0036_external_job_id.go @@ -56,7 +56,6 @@ func Up36(ctx context.Context, tx *sql.Tx) error { stmt += ` AS vals(external_job_id, id) WHERE vals.id = j.id` if _, err := tx.ExecContext(ctx, stmt); err != nil { return err - } } diff --git a/core/store/migrate/migrations/0262_add_solana_schema.sql b/core/store/migrate/migrations/0262_add_solana_schema.sql new file mode 100644 index 00000000000..035d3ff3d61 --- /dev/null +++ b/core/store/migrate/migrations/0262_add_solana_schema.sql @@ -0,0 +1,72 @@ +-- +goose Up +-- +goose StatementBegin +-- This removes evm from the search path, to avoid risk of an unqualified query intended to act on a Solana table accidentally +-- acting on the corresponding evm table. This makes schema qualification mandatory for all chain-specific queries. +SET search_path TO public; +CREATE SCHEMA solana; + +CREATE TABLE solana.log_poller_filters ( + id BIGSERIAL PRIMARY KEY, + chain_id TEXT NOT NULL, -- use human-readable name instead of genesis block hash to reduce index size by 50% + name TEXT NOT NULL, + address BYTEA NOT NULL, + event_name TEXT NOT NULL, + event_sig BYTEA NOT NULL, + starting_block BIGINT NOT NULL, + event_idl TEXT, + subkey_paths json, -- A list of subkeys to be indexed, represented by their json paths in the event struct. Forced to use json's 2d array as text[][] requires all paths to have equal length. + retention BIGINT NOT NULL DEFAULT 0, -- we don’t have to implement this initially, but good to include it in the schema + max_logs_kept BIGINT NOT NULL DEFAULT 0, -- same as retention, no need to implement yet + is_deleted BOOLEAN NOT NULL DEFAULT FALSE +); + +CREATE UNIQUE INDEX IF NOT EXISTS solana_log_poller_filter_name ON solana.log_poller_filters (chain_id, name) WHERE NOT is_deleted; + +CREATE TABLE solana.logs ( + id BIGSERIAL PRIMARY KEY, + filter_id BIGINT NOT NULL REFERENCES solana.log_poller_filters (id) ON DELETE CASCADE, + chain_id TEXT not null, -- use human-readable name instead of genesis block hash to reduce index size by 50% + log_index bigint not null, + block_hash bytea not null, + block_number bigint not null CHECK (block_number > 0), + block_timestamp timestamp with time zone not null, + address bytea not null, + event_sig bytea not null, + subkey_values bytea[] not null, + tx_hash bytea not null, + data bytea not null, + created_at timestamp with time zone not null, + expires_at timestamp with time zone null, -- null to indicate no timebase expiry + sequence_num bigint not null +); + +CREATE INDEX IF NOT EXISTS solana_logs_idx_by_timestamp ON solana.logs (chain_id, address, event_sig, block_timestamp, block_number); + +CREATE INDEX IF NOT EXISTS solana_logs_idx ON solana.logs (chain_id, block_number, address, event_sig); + +CREATE INDEX IF NOT EXISTS solana_logs_idx_subkey_one ON solana.logs ((subkey_values[1])); +CREATE INDEX IF NOT EXISTS solana_logs_idx_subkey_two ON solana.logs ((subkey_values[2])); +CREATE INDEX IF NOT EXISTS solana_logs_idx_subkey_three ON solana.logs ((subkey_values[3])); +CREATE INDEX IF NOT EXISTS solana_logs_idx_subkey_four ON solana.logs ((subkey_values[4])); + +CREATE INDEX IF NOT EXISTS solana_logs_idx_tx_hash ON solana.logs (tx_hash); + +-- Useful for the current form of those queries: WHERE chain_id = $1 AND address = $2 AND event_sig = $3 ... ORDER BY block_number, log_index +-- log_index is not included in this index because it increases the index size by ~ 10% for a likely negligible performance benefit +CREATE INDEX IF NOT EXISTS solana_logs_idx_chain_address_event_block ON solana.logs (chain_id, address, event_sig, block_number); + +CREATE UNIQUE INDEX IF NOT EXISTS solana_logs_idx_chain_filter_block_logindex ON solana.logs USING btree (chain_id, filter_id, block_number, log_index); + +-- +goose StatementEnd + + +-- +goose Down +-- +goose StatementBegin + +DROP TABLE IF EXISTS solana.logs; +DROP TABLE IF EXISTS solana.log_poller_filters; + +DROP SCHEMA solana; + +SET search_path TO public,evm; +-- +goose StatementEnd diff --git a/core/store/migrate/migrations/0263_solana_filter_is_backfilled.sql b/core/store/migrate/migrations/0263_solana_filter_is_backfilled.sql new file mode 100644 index 00000000000..7e81e7c4c5e --- /dev/null +++ b/core/store/migrate/migrations/0263_solana_filter_is_backfilled.sql @@ -0,0 +1,14 @@ +-- +goose Up +-- +goose StatementBegin + +ALTER TABLE solana.log_poller_filters ADD COLUMN is_backfilled BOOLEAN; +UPDATE solana.log_poller_filters SET is_backfilled = true; +ALTER TABLE solana.log_poller_filters ALTER COLUMN is_backfilled SET NOT NULL; +-- +goose StatementEnd + + +-- +goose Down +-- +goose StatementBegin + +ALTER TABLE solana.log_poller_filters DROP COLUMN is_backfilled; +-- +goose StatementEnd diff --git a/core/web/assets/index.html b/core/web/assets/index.html index ae1aac9ede0..b878067d029 100644 --- a/core/web/assets/index.html +++ b/core/web/assets/index.html @@ -1 +1 @@ -Operator UIChainlink
\ No newline at end of file +Operator UIChainlink
\ No newline at end of file diff --git a/core/web/assets/index.html.gz b/core/web/assets/index.html.gz index a65173c97c8..56e0ad999c6 100644 Binary files a/core/web/assets/index.html.gz and b/core/web/assets/index.html.gz differ diff --git a/core/web/assets/main.008c37495ba29761321d.js b/core/web/assets/main.5fed0c0f926fb5542ed6.js similarity index 87% rename from core/web/assets/main.008c37495ba29761321d.js rename to core/web/assets/main.5fed0c0f926fb5542ed6.js index b9feeec3d83..34a761cf119 100644 --- a/core/web/assets/main.008c37495ba29761321d.js +++ b/core/web/assets/main.5fed0c0f926fb5542ed6.js @@ -168,7 +168,7 @@ object-assign * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - */ Object.defineProperty(t,"__esModule",{value:!0}),"undefined"==typeof window||"function"!=typeof MessageChannel){var n,r,i,a,o,s=null,u=null,c=function(){if(null!==s)try{var e=t.unstable_now();s(!0,e),s=null}catch(n){throw setTimeout(c,0),n}},l=Date.now();t.unstable_now=function(){return Date.now()-l},n=function(e){null!==s?setTimeout(n,0,e):(s=e,setTimeout(c,0))},r=function(e,t){u=setTimeout(e,t)},i=function(){clearTimeout(u)},a=function(){return!1},o=t.unstable_forceFrameRate=function(){}}else{var f=window.performance,d=window.Date,h=window.setTimeout,p=window.clearTimeout;if("undefined"!=typeof console){var b=window.cancelAnimationFrame;"function"!=typeof window.requestAnimationFrame&&console.error("This browser doesn't support requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills"),"function"!=typeof b&&console.error("This browser doesn't support cancelAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills")}if("object"==typeof f&&"function"==typeof f.now)t.unstable_now=function(){return f.now()};else{var m=d.now();t.unstable_now=function(){return d.now()-m}}var g=!1,v=null,y=-1,w=5,_=0;a=function(){return t.unstable_now()>=_},o=function(){},t.unstable_forceFrameRate=function(e){0>e||125M(o,n))void 0!==u&&0>M(u,o)?(e[r]=u,e[s]=n,r=s):(e[r]=o,e[a]=n,r=a);else if(void 0!==u&&0>M(u,n))e[r]=u,e[s]=n,r=s;else break a}}return t}return null}function M(e,t){var n=e.sortIndex-t.sortIndex;return 0!==n?n:e.id-t.id}var O=[],A=[],L=1,C=null,I=3,D=!1,N=!1,P=!1;function R(e){for(var t=x(A);null!==t;){if(null===t.callback)T(A);else if(t.startTime<=e)T(A),t.sortIndex=t.expirationTime,k(O,t);else break;t=x(A)}}function j(e){if(P=!1,R(e),!N){if(null!==x(O))N=!0,n(F);else{var t=x(A);null!==t&&r(j,t.startTime-e)}}}function F(e,n){N=!1,P&&(P=!1,i()),D=!0;var o=I;try{for(R(n),C=x(O);null!==C&&(!(C.expirationTime>n)||e&&!a());){var s=C.callback;if(null!==s){C.callback=null,I=C.priorityLevel;var u=s(C.expirationTime<=n);n=t.unstable_now(),"function"==typeof u?C.callback=u:C===x(O)&&T(O),R(n)}else T(O);C=x(O)}if(null!==C)var c=!0;else{var l=x(A);null!==l&&r(j,l.startTime-n),c=!1}return c}finally{C=null,I=o,D=!1}}function Y(e){switch(e){case 1:return -1;case 2:return 250;case 5:return 1073741823;case 4:return 1e4;default:return 5e3}}var B=o;t.unstable_ImmediatePriority=1,t.unstable_UserBlockingPriority=2,t.unstable_NormalPriority=3,t.unstable_IdlePriority=5,t.unstable_LowPriority=4,t.unstable_runWithPriority=function(e,t){switch(e){case 1:case 2:case 3:case 4:case 5:break;default:e=3}var n=I;I=e;try{return t()}finally{I=n}},t.unstable_next=function(e){switch(I){case 1:case 2:case 3:var t=3;break;default:t=I}var n=I;I=t;try{return e()}finally{I=n}},t.unstable_scheduleCallback=function(e,a,o){var s=t.unstable_now();if("object"==typeof o&&null!==o){var u=o.delay;u="number"==typeof u&&0s?(e.sortIndex=u,k(A,e),null===x(O)&&e===x(A)&&(P?i():P=!0,r(j,u-s))):(e.sortIndex=o,k(O,e),N||D||(N=!0,n(F))),e},t.unstable_cancelCallback=function(e){e.callback=null},t.unstable_wrapCallback=function(e){var t=I;return function(){var n=I;I=t;try{return e.apply(this,arguments)}finally{I=n}}},t.unstable_getCurrentPriorityLevel=function(){return I},t.unstable_shouldYield=function(){var e=t.unstable_now();R(e);var n=x(O);return n!==C&&null!==C&&null!==n&&null!==n.callback&&n.startTime<=e&&n.expirationTime>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function c(e,t,n){var r=t.length-1;if(r=0?(i>0&&(e.lastNeed=i-1),i):--r=0?(i>0&&(e.lastNeed=i-2),i):--r=0?(i>0&&(2===i?i=0:e.lastNeed=i-3),i):0}function l(e,t,n){if((192&t[0])!=128)return e.lastNeed=0,"�";if(e.lastNeed>1&&t.length>1){if((192&t[1])!=128)return e.lastNeed=1,"�";if(e.lastNeed>2&&t.length>2&&(192&t[2])!=128)return e.lastNeed=2,"�"}}function f(e){var t=this.lastTotal-this.lastNeed,n=l(this,e,t);return void 0!==n?n:this.lastNeed<=e.length?(e.copy(this.lastChar,t,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal)):void(e.copy(this.lastChar,t,0,e.length),this.lastNeed-=e.length)}function d(e,t){var n=c(this,e,t);if(!this.lastNeed)return e.toString("utf8",t);this.lastTotal=n;var r=e.length-(n-this.lastNeed);return e.copy(this.lastChar,0,r),e.toString("utf8",t,r)}function h(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+"�":t}function p(e,t){if((e.length-t)%2==0){var n=e.toString("utf16le",t);if(n){var r=n.charCodeAt(n.length-1);if(r>=55296&&r<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1],n.slice(0,-1)}return n}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=e[e.length-1],e.toString("utf16le",t,e.length-1)}function b(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed){var n=this.lastTotal-this.lastNeed;return t+this.lastChar.toString("utf16le",0,n)}return t}function m(e,t){var n=(e.length-t)%3;return 0===n?e.toString("base64",t):(this.lastNeed=3-n,this.lastTotal=3,1===n?this.lastChar[0]=e[e.length-1]:(this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1]),e.toString("base64",t,e.length-n))}function g(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+this.lastChar.toString("base64",0,3-this.lastNeed):t}function v(e){return e.toString(this.encoding)}function y(e){return e&&e.length?this.write(e):""}t.s=s,s.prototype.write=function(e){var t,n;if(0===e.length)return"";if(this.lastNeed){if(void 0===(t=this.fillLast(e)))return"";n=this.lastNeed,this.lastNeed=0}else n=0;return n */ var r=n(48764),i=r.Buffer;function a(e,t){for(var n in e)t[n]=e[n]}function o(e,t,n){return i(e,t,n)}i.from&&i.alloc&&i.allocUnsafe&&i.allocUnsafeSlow?e.exports=r:(a(r,t),t.Buffer=o),o.prototype=Object.create(i.prototype),a(i,o),o.from=function(e,t,n){if("number"==typeof e)throw TypeError("Argument must not be a number");return i(e,t,n)},o.alloc=function(e,t,n){if("number"!=typeof e)throw TypeError("Argument must be a number");var r=i(e);return void 0!==t?"string"==typeof n?r.fill(t,n):r.fill(t):r.fill(0),r},o.allocUnsafe=function(e){if("number"!=typeof e)throw TypeError("Argument must be a number");return i(e)},o.allocUnsafeSlow=function(e){if("number"!=typeof e)throw TypeError("Argument must be a number");return r.SlowBuffer(e)}},93379(e,t,n){"use strict";var r,i,a=function(){return void 0===r&&(r=Boolean(window&&document&&document.all&&!window.atob)),r},o=(i={},function(e){if(void 0===i[e]){var t=document.querySelector(e);if(window.HTMLIFrameElement&&t instanceof window.HTMLIFrameElement)try{t=t.contentDocument.head}catch(n){t=null}i[e]=t}return i[e]}),s=[];function u(e){for(var t=-1,n=0;nAp});var r,i,a,o,s,u,c,l=n(67294),f=n.t(l,2),d=n(39814),h=n(5977),p=n(57209),b=n(32316),m=n(95880),g=n(17051),v=n(71381),y=n(81701),w=n(3022),_=n(60323),E=n(87591),S=n(25649),k=n(28902),x=n(71426),T=n(48884),M=n(94184),O=n.n(M),A=n(37703),L=n(73935),C=function(){if("undefined"!=typeof Map)return Map;function e(e,t){var n=-1;return e.some(function(e,r){return e[0]===t&&(n=r,!0)}),n}return function(){function t(){this.__entries__=[]}return Object.defineProperty(t.prototype,"size",{get:function(){return this.__entries__.length},enumerable:!0,configurable:!0}),t.prototype.get=function(t){var n=e(this.__entries__,t),r=this.__entries__[n];return r&&r[1]},t.prototype.set=function(t,n){var r=e(this.__entries__,t);~r?this.__entries__[r][1]=n:this.__entries__.push([t,n])},t.prototype.delete=function(t){var n=this.__entries__,r=e(n,t);~r&&n.splice(r,1)},t.prototype.has=function(t){return!!~e(this.__entries__,t)},t.prototype.clear=function(){this.__entries__.splice(0)},t.prototype.forEach=function(e,t){void 0===t&&(t=null);for(var n=0,r=this.__entries__;n0},e.prototype.connect_=function(){I&&!this.connected_&&(document.addEventListener("transitionend",this.onTransitionEnd_),window.addEventListener("resize",this.refresh),Y?(this.mutationsObserver_=new MutationObserver(this.refresh),this.mutationsObserver_.observe(document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})):(document.addEventListener("DOMSubtreeModified",this.refresh),this.mutationEventsAdded_=!0),this.connected_=!0)},e.prototype.disconnect_=function(){I&&this.connected_&&(document.removeEventListener("transitionend",this.onTransitionEnd_),window.removeEventListener("resize",this.refresh),this.mutationsObserver_&&this.mutationsObserver_.disconnect(),this.mutationEventsAdded_&&document.removeEventListener("DOMSubtreeModified",this.refresh),this.mutationsObserver_=null,this.mutationEventsAdded_=!1,this.connected_=!1)},e.prototype.onTransitionEnd_=function(e){var t=e.propertyName,n=void 0===t?"":t;F.some(function(e){return!!~n.indexOf(e)})&&this.refresh()},e.getInstance=function(){return this.instance_||(this.instance_=new e),this.instance_},e.instance_=null,e}(),U=function(e,t){for(var n=0,r=Object.keys(t);n0},e}(),er="undefined"!=typeof WeakMap?new WeakMap:new C,ei=function(){function e(t){if(!(this instanceof e))throw TypeError("Cannot call a class as a function.");if(!arguments.length)throw TypeError("1 argument required, but only 0 present.");var n=B.getInstance(),r=new en(t,n,this);er.set(this,r)}return e}();["observe","unobserve","disconnect"].forEach(function(e){ei.prototype[e]=function(){var t;return(t=er.get(this))[e].apply(t,arguments)}});var ea=void 0!==D.ResizeObserver?D.ResizeObserver:ei;let eo=ea;var es=function(e){var t=[],n=null,r=function(){for(var r=arguments.length,i=Array(r),a=0;a=t||n<0||f&&r>=a}function g(){var e=eb();if(m(e))return v(e);s=setTimeout(g,b(e))}function v(e){return(s=void 0,d&&r)?h(e):(r=i=void 0,o)}function y(){void 0!==s&&clearTimeout(s),c=0,r=u=i=s=void 0}function w(){return void 0===s?o:v(eb())}function _(){var e=eb(),n=m(e);if(r=arguments,i=this,u=e,n){if(void 0===s)return p(u);if(f)return clearTimeout(s),s=setTimeout(g,t),h(u)}return void 0===s&&(s=setTimeout(g,t)),o}return t=ez(t)||0,ed(n)&&(l=!!n.leading,a=(f="maxWait"in n)?eW(ez(n.maxWait)||0,t):a,d="trailing"in n?!!n.trailing:d),_.cancel=y,_.flush=w,_}let eq=eV;var eZ="Expected a function";function eX(e,t,n){var r=!0,i=!0;if("function"!=typeof e)throw TypeError(eZ);return ed(n)&&(r="leading"in n?!!n.leading:r,i="trailing"in n?!!n.trailing:i),eq(e,t,{leading:r,maxWait:t,trailing:i})}let eJ=eX;var eQ={debounce:eq,throttle:eJ},e1=function(e){return eQ[e]},e0=function(e){return"function"==typeof e},e2=function(){return"undefined"==typeof window},e3=function(e){return e instanceof Element||e instanceof HTMLDocument};function e4(e){return(e4="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function e6(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}function e5(e,t){for(var n=0;ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&l.createElement(tG.Z,{variant:"indeterminate",classes:r}))};tK.propTypes={fetchCount:el().number.isRequired};let tV=(0,b.withStyles)(tW)(tK);var tq=n(5536);let tZ=n.p+"ba8bbf16ebf8e1d05bef.svg";function tX(){return(tX=Object.assign||function(e){for(var t=1;t120){for(var d=Math.floor(u/80),h=u%80,p=[],b=0;b0},name:{enumerable:!1},nodes:{enumerable:!1},source:{enumerable:!1},positions:{enumerable:!1},originalError:{enumerable:!1}}),null!=s&&s.stack)?(Object.defineProperty(nf(b),"stack",{value:s.stack,writable:!0,configurable:!0}),nl(b)):(Error.captureStackTrace?Error.captureStackTrace(nf(b),n):Object.defineProperty(nf(b),"stack",{value:Error().stack,writable:!0,configurable:!0}),b)}return ns(n,[{key:"toString",value:function(){return nw(this)}},{key:t4.YF,get:function(){return"Object"}}]),n}(nd(Error));function ny(e){return void 0===e||0===e.length?void 0:e}function nw(e){var t=e.message;if(e.nodes)for(var n=0,r=e.nodes;n",EOF:"",BANG:"!",DOLLAR:"$",AMP:"&",PAREN_L:"(",PAREN_R:")",SPREAD:"...",COLON:":",EQUALS:"=",AT:"@",BRACKET_L:"[",BRACKET_R:"]",BRACE_L:"{",PIPE:"|",BRACE_R:"}",NAME:"Name",INT:"Int",FLOAT:"Float",STRING:"String",BLOCK_STRING:"BlockString",COMMENT:"Comment"}),nx=n(10143),nT=Object.freeze({QUERY:"QUERY",MUTATION:"MUTATION",SUBSCRIPTION:"SUBSCRIPTION",FIELD:"FIELD",FRAGMENT_DEFINITION:"FRAGMENT_DEFINITION",FRAGMENT_SPREAD:"FRAGMENT_SPREAD",INLINE_FRAGMENT:"INLINE_FRAGMENT",VARIABLE_DEFINITION:"VARIABLE_DEFINITION",SCHEMA:"SCHEMA",SCALAR:"SCALAR",OBJECT:"OBJECT",FIELD_DEFINITION:"FIELD_DEFINITION",ARGUMENT_DEFINITION:"ARGUMENT_DEFINITION",INTERFACE:"INTERFACE",UNION:"UNION",ENUM:"ENUM",ENUM_VALUE:"ENUM_VALUE",INPUT_OBJECT:"INPUT_OBJECT",INPUT_FIELD_DEFINITION:"INPUT_FIELD_DEFINITION"}),nM=n(87392),nO=function(){function e(e){var t=new nS.WU(nk.SOF,0,0,0,0,null);this.source=e,this.lastToken=t,this.token=t,this.line=1,this.lineStart=0}var t=e.prototype;return t.advance=function(){return this.lastToken=this.token,this.token=this.lookahead()},t.lookahead=function(){var e,t=this.token;if(t.kind!==nk.EOF)do t=null!==(e=t.next)&&void 0!==e?e:t.next=nC(this,t);while(t.kind===nk.COMMENT)return t},e}();function nA(e){return e===nk.BANG||e===nk.DOLLAR||e===nk.AMP||e===nk.PAREN_L||e===nk.PAREN_R||e===nk.SPREAD||e===nk.COLON||e===nk.EQUALS||e===nk.AT||e===nk.BRACKET_L||e===nk.BRACKET_R||e===nk.BRACE_L||e===nk.PIPE||e===nk.BRACE_R}function nL(e){return isNaN(e)?nk.EOF:e<127?JSON.stringify(String.fromCharCode(e)):'"\\u'.concat(("00"+e.toString(16).toUpperCase()).slice(-4),'"')}function nC(e,t){for(var n=e.source,r=n.body,i=r.length,a=t.end;a31||9===a))return new nS.WU(nk.COMMENT,t,s,n,r,i,o.slice(t+1,s))}function nN(e,t,n,r,i,a){var o=e.body,s=n,u=t,c=!1;if(45===s&&(s=o.charCodeAt(++u)),48===s){if((s=o.charCodeAt(++u))>=48&&s<=57)throw n_(e,u,"Invalid number, unexpected digit after 0: ".concat(nL(s),"."))}else u=nP(e,u,s),s=o.charCodeAt(u);if(46===s&&(c=!0,s=o.charCodeAt(++u),u=nP(e,u,s),s=o.charCodeAt(u)),(69===s||101===s)&&(c=!0,(43===(s=o.charCodeAt(++u))||45===s)&&(s=o.charCodeAt(++u)),u=nP(e,u,s),s=o.charCodeAt(u)),46===s||nU(s))throw n_(e,u,"Invalid number, expected digit but got: ".concat(nL(s),"."));return new nS.WU(c?nk.FLOAT:nk.INT,t,u,r,i,a,o.slice(t,u))}function nP(e,t,n){var r=e.body,i=t,a=n;if(a>=48&&a<=57){do a=r.charCodeAt(++i);while(a>=48&&a<=57)return i}throw n_(e,i,"Invalid number, expected digit but got: ".concat(nL(a),"."))}function nR(e,t,n,r,i){for(var a=e.body,o=t+1,s=o,u=0,c="";o=48&&e<=57?e-48:e>=65&&e<=70?e-55:e>=97&&e<=102?e-87:-1}function nB(e,t,n,r,i){for(var a=e.body,o=a.length,s=t+1,u=0;s!==o&&!isNaN(u=a.charCodeAt(s))&&(95===u||u>=48&&u<=57||u>=65&&u<=90||u>=97&&u<=122);)++s;return new nS.WU(nk.NAME,t,s,n,r,i,a.slice(t,s))}function nU(e){return 95===e||e>=65&&e<=90||e>=97&&e<=122}function nH(e,t){return new n$(e,t).parseDocument()}var n$=function(){function e(e,t){var n=(0,nx.T)(e)?e:new nx.H(e);this._lexer=new nO(n),this._options=t}var t=e.prototype;return t.parseName=function(){var e=this.expectToken(nk.NAME);return{kind:nE.h.NAME,value:e.value,loc:this.loc(e)}},t.parseDocument=function(){var e=this._lexer.token;return{kind:nE.h.DOCUMENT,definitions:this.many(nk.SOF,this.parseDefinition,nk.EOF),loc:this.loc(e)}},t.parseDefinition=function(){if(this.peek(nk.NAME))switch(this._lexer.token.value){case"query":case"mutation":case"subscription":return this.parseOperationDefinition();case"fragment":return this.parseFragmentDefinition();case"schema":case"scalar":case"type":case"interface":case"union":case"enum":case"input":case"directive":return this.parseTypeSystemDefinition();case"extend":return this.parseTypeSystemExtension()}else if(this.peek(nk.BRACE_L))return this.parseOperationDefinition();else if(this.peekDescription())return this.parseTypeSystemDefinition();throw this.unexpected()},t.parseOperationDefinition=function(){var e,t=this._lexer.token;if(this.peek(nk.BRACE_L))return{kind:nE.h.OPERATION_DEFINITION,operation:"query",name:void 0,variableDefinitions:[],directives:[],selectionSet:this.parseSelectionSet(),loc:this.loc(t)};var n=this.parseOperationType();return this.peek(nk.NAME)&&(e=this.parseName()),{kind:nE.h.OPERATION_DEFINITION,operation:n,name:e,variableDefinitions:this.parseVariableDefinitions(),directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(t)}},t.parseOperationType=function(){var e=this.expectToken(nk.NAME);switch(e.value){case"query":return"query";case"mutation":return"mutation";case"subscription":return"subscription"}throw this.unexpected(e)},t.parseVariableDefinitions=function(){return this.optionalMany(nk.PAREN_L,this.parseVariableDefinition,nk.PAREN_R)},t.parseVariableDefinition=function(){var e=this._lexer.token;return{kind:nE.h.VARIABLE_DEFINITION,variable:this.parseVariable(),type:(this.expectToken(nk.COLON),this.parseTypeReference()),defaultValue:this.expectOptionalToken(nk.EQUALS)?this.parseValueLiteral(!0):void 0,directives:this.parseDirectives(!0),loc:this.loc(e)}},t.parseVariable=function(){var e=this._lexer.token;return this.expectToken(nk.DOLLAR),{kind:nE.h.VARIABLE,name:this.parseName(),loc:this.loc(e)}},t.parseSelectionSet=function(){var e=this._lexer.token;return{kind:nE.h.SELECTION_SET,selections:this.many(nk.BRACE_L,this.parseSelection,nk.BRACE_R),loc:this.loc(e)}},t.parseSelection=function(){return this.peek(nk.SPREAD)?this.parseFragment():this.parseField()},t.parseField=function(){var e,t,n=this._lexer.token,r=this.parseName();return this.expectOptionalToken(nk.COLON)?(e=r,t=this.parseName()):t=r,{kind:nE.h.FIELD,alias:e,name:t,arguments:this.parseArguments(!1),directives:this.parseDirectives(!1),selectionSet:this.peek(nk.BRACE_L)?this.parseSelectionSet():void 0,loc:this.loc(n)}},t.parseArguments=function(e){var t=e?this.parseConstArgument:this.parseArgument;return this.optionalMany(nk.PAREN_L,t,nk.PAREN_R)},t.parseArgument=function(){var e=this._lexer.token,t=this.parseName();return this.expectToken(nk.COLON),{kind:nE.h.ARGUMENT,name:t,value:this.parseValueLiteral(!1),loc:this.loc(e)}},t.parseConstArgument=function(){var e=this._lexer.token;return{kind:nE.h.ARGUMENT,name:this.parseName(),value:(this.expectToken(nk.COLON),this.parseValueLiteral(!0)),loc:this.loc(e)}},t.parseFragment=function(){var e=this._lexer.token;this.expectToken(nk.SPREAD);var t=this.expectOptionalKeyword("on");return!t&&this.peek(nk.NAME)?{kind:nE.h.FRAGMENT_SPREAD,name:this.parseFragmentName(),directives:this.parseDirectives(!1),loc:this.loc(e)}:{kind:nE.h.INLINE_FRAGMENT,typeCondition:t?this.parseNamedType():void 0,directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(e)}},t.parseFragmentDefinition=function(){var e,t=this._lexer.token;return(this.expectKeyword("fragment"),(null===(e=this._options)||void 0===e?void 0:e.experimentalFragmentVariables)===!0)?{kind:nE.h.FRAGMENT_DEFINITION,name:this.parseFragmentName(),variableDefinitions:this.parseVariableDefinitions(),typeCondition:(this.expectKeyword("on"),this.parseNamedType()),directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(t)}:{kind:nE.h.FRAGMENT_DEFINITION,name:this.parseFragmentName(),typeCondition:(this.expectKeyword("on"),this.parseNamedType()),directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(t)}},t.parseFragmentName=function(){if("on"===this._lexer.token.value)throw this.unexpected();return this.parseName()},t.parseValueLiteral=function(e){var t=this._lexer.token;switch(t.kind){case nk.BRACKET_L:return this.parseList(e);case nk.BRACE_L:return this.parseObject(e);case nk.INT:return this._lexer.advance(),{kind:nE.h.INT,value:t.value,loc:this.loc(t)};case nk.FLOAT:return this._lexer.advance(),{kind:nE.h.FLOAT,value:t.value,loc:this.loc(t)};case nk.STRING:case nk.BLOCK_STRING:return this.parseStringLiteral();case nk.NAME:switch(this._lexer.advance(),t.value){case"true":return{kind:nE.h.BOOLEAN,value:!0,loc:this.loc(t)};case"false":return{kind:nE.h.BOOLEAN,value:!1,loc:this.loc(t)};case"null":return{kind:nE.h.NULL,loc:this.loc(t)};default:return{kind:nE.h.ENUM,value:t.value,loc:this.loc(t)}}case nk.DOLLAR:if(!e)return this.parseVariable()}throw this.unexpected()},t.parseStringLiteral=function(){var e=this._lexer.token;return this._lexer.advance(),{kind:nE.h.STRING,value:e.value,block:e.kind===nk.BLOCK_STRING,loc:this.loc(e)}},t.parseList=function(e){var t=this,n=this._lexer.token,r=function(){return t.parseValueLiteral(e)};return{kind:nE.h.LIST,values:this.any(nk.BRACKET_L,r,nk.BRACKET_R),loc:this.loc(n)}},t.parseObject=function(e){var t=this,n=this._lexer.token,r=function(){return t.parseObjectField(e)};return{kind:nE.h.OBJECT,fields:this.any(nk.BRACE_L,r,nk.BRACE_R),loc:this.loc(n)}},t.parseObjectField=function(e){var t=this._lexer.token,n=this.parseName();return this.expectToken(nk.COLON),{kind:nE.h.OBJECT_FIELD,name:n,value:this.parseValueLiteral(e),loc:this.loc(t)}},t.parseDirectives=function(e){for(var t=[];this.peek(nk.AT);)t.push(this.parseDirective(e));return t},t.parseDirective=function(e){var t=this._lexer.token;return this.expectToken(nk.AT),{kind:nE.h.DIRECTIVE,name:this.parseName(),arguments:this.parseArguments(e),loc:this.loc(t)}},t.parseTypeReference=function(){var e,t=this._lexer.token;return(this.expectOptionalToken(nk.BRACKET_L)?(e=this.parseTypeReference(),this.expectToken(nk.BRACKET_R),e={kind:nE.h.LIST_TYPE,type:e,loc:this.loc(t)}):e=this.parseNamedType(),this.expectOptionalToken(nk.BANG))?{kind:nE.h.NON_NULL_TYPE,type:e,loc:this.loc(t)}:e},t.parseNamedType=function(){var e=this._lexer.token;return{kind:nE.h.NAMED_TYPE,name:this.parseName(),loc:this.loc(e)}},t.parseTypeSystemDefinition=function(){var e=this.peekDescription()?this._lexer.lookahead():this._lexer.token;if(e.kind===nk.NAME)switch(e.value){case"schema":return this.parseSchemaDefinition();case"scalar":return this.parseScalarTypeDefinition();case"type":return this.parseObjectTypeDefinition();case"interface":return this.parseInterfaceTypeDefinition();case"union":return this.parseUnionTypeDefinition();case"enum":return this.parseEnumTypeDefinition();case"input":return this.parseInputObjectTypeDefinition();case"directive":return this.parseDirectiveDefinition()}throw this.unexpected(e)},t.peekDescription=function(){return this.peek(nk.STRING)||this.peek(nk.BLOCK_STRING)},t.parseDescription=function(){if(this.peekDescription())return this.parseStringLiteral()},t.parseSchemaDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("schema");var n=this.parseDirectives(!0),r=this.many(nk.BRACE_L,this.parseOperationTypeDefinition,nk.BRACE_R);return{kind:nE.h.SCHEMA_DEFINITION,description:t,directives:n,operationTypes:r,loc:this.loc(e)}},t.parseOperationTypeDefinition=function(){var e=this._lexer.token,t=this.parseOperationType();this.expectToken(nk.COLON);var n=this.parseNamedType();return{kind:nE.h.OPERATION_TYPE_DEFINITION,operation:t,type:n,loc:this.loc(e)}},t.parseScalarTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("scalar");var n=this.parseName(),r=this.parseDirectives(!0);return{kind:nE.h.SCALAR_TYPE_DEFINITION,description:t,name:n,directives:r,loc:this.loc(e)}},t.parseObjectTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("type");var n=this.parseName(),r=this.parseImplementsInterfaces(),i=this.parseDirectives(!0),a=this.parseFieldsDefinition();return{kind:nE.h.OBJECT_TYPE_DEFINITION,description:t,name:n,interfaces:r,directives:i,fields:a,loc:this.loc(e)}},t.parseImplementsInterfaces=function(){var e;if(!this.expectOptionalKeyword("implements"))return[];if((null===(e=this._options)||void 0===e?void 0:e.allowLegacySDLImplementsInterfaces)===!0){var t=[];this.expectOptionalToken(nk.AMP);do t.push(this.parseNamedType());while(this.expectOptionalToken(nk.AMP)||this.peek(nk.NAME))return t}return this.delimitedMany(nk.AMP,this.parseNamedType)},t.parseFieldsDefinition=function(){var e;return(null===(e=this._options)||void 0===e?void 0:e.allowLegacySDLEmptyFields)===!0&&this.peek(nk.BRACE_L)&&this._lexer.lookahead().kind===nk.BRACE_R?(this._lexer.advance(),this._lexer.advance(),[]):this.optionalMany(nk.BRACE_L,this.parseFieldDefinition,nk.BRACE_R)},t.parseFieldDefinition=function(){var e=this._lexer.token,t=this.parseDescription(),n=this.parseName(),r=this.parseArgumentDefs();this.expectToken(nk.COLON);var i=this.parseTypeReference(),a=this.parseDirectives(!0);return{kind:nE.h.FIELD_DEFINITION,description:t,name:n,arguments:r,type:i,directives:a,loc:this.loc(e)}},t.parseArgumentDefs=function(){return this.optionalMany(nk.PAREN_L,this.parseInputValueDef,nk.PAREN_R)},t.parseInputValueDef=function(){var e,t=this._lexer.token,n=this.parseDescription(),r=this.parseName();this.expectToken(nk.COLON);var i=this.parseTypeReference();this.expectOptionalToken(nk.EQUALS)&&(e=this.parseValueLiteral(!0));var a=this.parseDirectives(!0);return{kind:nE.h.INPUT_VALUE_DEFINITION,description:n,name:r,type:i,defaultValue:e,directives:a,loc:this.loc(t)}},t.parseInterfaceTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("interface");var n=this.parseName(),r=this.parseImplementsInterfaces(),i=this.parseDirectives(!0),a=this.parseFieldsDefinition();return{kind:nE.h.INTERFACE_TYPE_DEFINITION,description:t,name:n,interfaces:r,directives:i,fields:a,loc:this.loc(e)}},t.parseUnionTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("union");var n=this.parseName(),r=this.parseDirectives(!0),i=this.parseUnionMemberTypes();return{kind:nE.h.UNION_TYPE_DEFINITION,description:t,name:n,directives:r,types:i,loc:this.loc(e)}},t.parseUnionMemberTypes=function(){return this.expectOptionalToken(nk.EQUALS)?this.delimitedMany(nk.PIPE,this.parseNamedType):[]},t.parseEnumTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("enum");var n=this.parseName(),r=this.parseDirectives(!0),i=this.parseEnumValuesDefinition();return{kind:nE.h.ENUM_TYPE_DEFINITION,description:t,name:n,directives:r,values:i,loc:this.loc(e)}},t.parseEnumValuesDefinition=function(){return this.optionalMany(nk.BRACE_L,this.parseEnumValueDefinition,nk.BRACE_R)},t.parseEnumValueDefinition=function(){var e=this._lexer.token,t=this.parseDescription(),n=this.parseName(),r=this.parseDirectives(!0);return{kind:nE.h.ENUM_VALUE_DEFINITION,description:t,name:n,directives:r,loc:this.loc(e)}},t.parseInputObjectTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("input");var n=this.parseName(),r=this.parseDirectives(!0),i=this.parseInputFieldsDefinition();return{kind:nE.h.INPUT_OBJECT_TYPE_DEFINITION,description:t,name:n,directives:r,fields:i,loc:this.loc(e)}},t.parseInputFieldsDefinition=function(){return this.optionalMany(nk.BRACE_L,this.parseInputValueDef,nk.BRACE_R)},t.parseTypeSystemExtension=function(){var e=this._lexer.lookahead();if(e.kind===nk.NAME)switch(e.value){case"schema":return this.parseSchemaExtension();case"scalar":return this.parseScalarTypeExtension();case"type":return this.parseObjectTypeExtension();case"interface":return this.parseInterfaceTypeExtension();case"union":return this.parseUnionTypeExtension();case"enum":return this.parseEnumTypeExtension();case"input":return this.parseInputObjectTypeExtension()}throw this.unexpected(e)},t.parseSchemaExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("schema");var t=this.parseDirectives(!0),n=this.optionalMany(nk.BRACE_L,this.parseOperationTypeDefinition,nk.BRACE_R);if(0===t.length&&0===n.length)throw this.unexpected();return{kind:nE.h.SCHEMA_EXTENSION,directives:t,operationTypes:n,loc:this.loc(e)}},t.parseScalarTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("scalar");var t=this.parseName(),n=this.parseDirectives(!0);if(0===n.length)throw this.unexpected();return{kind:nE.h.SCALAR_TYPE_EXTENSION,name:t,directives:n,loc:this.loc(e)}},t.parseObjectTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("type");var t=this.parseName(),n=this.parseImplementsInterfaces(),r=this.parseDirectives(!0),i=this.parseFieldsDefinition();if(0===n.length&&0===r.length&&0===i.length)throw this.unexpected();return{kind:nE.h.OBJECT_TYPE_EXTENSION,name:t,interfaces:n,directives:r,fields:i,loc:this.loc(e)}},t.parseInterfaceTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("interface");var t=this.parseName(),n=this.parseImplementsInterfaces(),r=this.parseDirectives(!0),i=this.parseFieldsDefinition();if(0===n.length&&0===r.length&&0===i.length)throw this.unexpected();return{kind:nE.h.INTERFACE_TYPE_EXTENSION,name:t,interfaces:n,directives:r,fields:i,loc:this.loc(e)}},t.parseUnionTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("union");var t=this.parseName(),n=this.parseDirectives(!0),r=this.parseUnionMemberTypes();if(0===n.length&&0===r.length)throw this.unexpected();return{kind:nE.h.UNION_TYPE_EXTENSION,name:t,directives:n,types:r,loc:this.loc(e)}},t.parseEnumTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("enum");var t=this.parseName(),n=this.parseDirectives(!0),r=this.parseEnumValuesDefinition();if(0===n.length&&0===r.length)throw this.unexpected();return{kind:nE.h.ENUM_TYPE_EXTENSION,name:t,directives:n,values:r,loc:this.loc(e)}},t.parseInputObjectTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("input");var t=this.parseName(),n=this.parseDirectives(!0),r=this.parseInputFieldsDefinition();if(0===n.length&&0===r.length)throw this.unexpected();return{kind:nE.h.INPUT_OBJECT_TYPE_EXTENSION,name:t,directives:n,fields:r,loc:this.loc(e)}},t.parseDirectiveDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("directive"),this.expectToken(nk.AT);var n=this.parseName(),r=this.parseArgumentDefs(),i=this.expectOptionalKeyword("repeatable");this.expectKeyword("on");var a=this.parseDirectiveLocations();return{kind:nE.h.DIRECTIVE_DEFINITION,description:t,name:n,arguments:r,repeatable:i,locations:a,loc:this.loc(e)}},t.parseDirectiveLocations=function(){return this.delimitedMany(nk.PIPE,this.parseDirectiveLocation)},t.parseDirectiveLocation=function(){var e=this._lexer.token,t=this.parseName();if(void 0!==nT[t.value])return t;throw this.unexpected(e)},t.loc=function(e){var t;if((null===(t=this._options)||void 0===t?void 0:t.noLocation)!==!0)return new nS.Ye(e,this._lexer.lastToken,this._lexer.source)},t.peek=function(e){return this._lexer.token.kind===e},t.expectToken=function(e){var t=this._lexer.token;if(t.kind===e)return this._lexer.advance(),t;throw n_(this._lexer.source,t.start,"Expected ".concat(nG(e),", found ").concat(nz(t),"."))},t.expectOptionalToken=function(e){var t=this._lexer.token;if(t.kind===e)return this._lexer.advance(),t},t.expectKeyword=function(e){var t=this._lexer.token;if(t.kind===nk.NAME&&t.value===e)this._lexer.advance();else throw n_(this._lexer.source,t.start,'Expected "'.concat(e,'", found ').concat(nz(t),"."))},t.expectOptionalKeyword=function(e){var t=this._lexer.token;return t.kind===nk.NAME&&t.value===e&&(this._lexer.advance(),!0)},t.unexpected=function(e){var t=null!=e?e:this._lexer.token;return n_(this._lexer.source,t.start,"Unexpected ".concat(nz(t),"."))},t.any=function(e,t,n){this.expectToken(e);for(var r=[];!this.expectOptionalToken(n);)r.push(t.call(this));return r},t.optionalMany=function(e,t,n){if(this.expectOptionalToken(e)){var r=[];do r.push(t.call(this));while(!this.expectOptionalToken(n))return r}return[]},t.many=function(e,t,n){this.expectToken(e);var r=[];do r.push(t.call(this));while(!this.expectOptionalToken(n))return r},t.delimitedMany=function(e,t){this.expectOptionalToken(e);var n=[];do n.push(t.call(this));while(this.expectOptionalToken(e))return n},e}();function nz(e){var t=e.value;return nG(e.kind)+(null!=t?' "'.concat(t,'"'):"")}function nG(e){return nA(e)?'"'.concat(e,'"'):e}var nW=new Map,nK=new Map,nV=!0,nq=!1;function nZ(e){return e.replace(/[\s,]+/g," ").trim()}function nX(e){return nZ(e.source.body.substring(e.start,e.end))}function nJ(e){var t=new Set,n=[];return e.definitions.forEach(function(e){if("FragmentDefinition"===e.kind){var r=e.name.value,i=nX(e.loc),a=nK.get(r);a&&!a.has(i)?nV&&console.warn("Warning: fragment with name "+r+" already exists.\ngraphql-tag enforces all fragment names across your application to be unique; read more about\nthis in the docs: http://dev.apollodata.com/core/fragments.html#unique-names"):a||nK.set(r,a=new Set),a.add(i),t.has(i)||(t.add(i),n.push(e))}else n.push(e)}),(0,t0.pi)((0,t0.pi)({},e),{definitions:n})}function nQ(e){var t=new Set(e.definitions);t.forEach(function(e){e.loc&&delete e.loc,Object.keys(e).forEach(function(n){var r=e[n];r&&"object"==typeof r&&t.add(r)})});var n=e.loc;return n&&(delete n.startToken,delete n.endToken),e}function n1(e){var t=nZ(e);if(!nW.has(t)){var n=nH(e,{experimentalFragmentVariables:nq,allowLegacyFragmentVariables:nq});if(!n||"Document"!==n.kind)throw Error("Not a valid GraphQL document.");nW.set(t,nQ(nJ(n)))}return nW.get(t)}function n0(e){for(var t=[],n=1;n, or pass an ApolloClient instance in via options.'):(0,n9.kG)(!!n,32),n}var rp=n(10542),rb=n(53712),rm=n(21436),rg=Object.prototype.hasOwnProperty;function rv(e,t){return void 0===t&&(t=Object.create(null)),ry(rh(t.client),e).useQuery(t)}function ry(e,t){var n=(0,l.useRef)();n.current&&e===n.current.client&&t===n.current.query||(n.current=new rw(e,t,n.current));var r=n.current,i=(0,l.useState)(0),a=(i[0],i[1]);return r.forceUpdate=function(){a(function(e){return e+1})},r}var rw=function(){function e(e,t,n){this.client=e,this.query=t,this.ssrDisabledResult=(0,rp.J)({loading:!0,data:void 0,error:void 0,networkStatus:ru.I.loading}),this.skipStandbyResult=(0,rp.J)({loading:!1,data:void 0,error:void 0,networkStatus:ru.I.ready}),this.toQueryResultCache=new(n7.mr?WeakMap:Map),rd(t,r.Query);var i=n&&n.result,a=i&&i.data;a&&(this.previousData=a)}return e.prototype.forceUpdate=function(){__DEV__&&n9.kG.warn("Calling default no-op implementation of InternalState#forceUpdate")},e.prototype.executeQuery=function(e){var t,n=this;e.query&&Object.assign(this,{query:e.query}),this.watchQueryOptions=this.createWatchQueryOptions(this.queryHookOptions=e);var r=this.observable.reobserveAsConcast(this.getObsQueryOptions());return this.previousData=(null===(t=this.result)||void 0===t?void 0:t.data)||this.previousData,this.result=void 0,this.forceUpdate(),new Promise(function(e){var t;r.subscribe({next:function(e){t=e},error:function(){e(n.toQueryResult(n.observable.getCurrentResult()))},complete:function(){e(n.toQueryResult(t))}})})},e.prototype.useQuery=function(e){var t=this;this.renderPromises=(0,l.useContext)((0,ro.K)()).renderPromises,this.useOptions(e);var n=this.useObservableQuery(),r=rt((0,l.useCallback)(function(){if(t.renderPromises)return function(){};var e=function(){var e=t.result,r=n.getCurrentResult();!(e&&e.loading===r.loading&&e.networkStatus===r.networkStatus&&(0,ri.D)(e.data,r.data))&&t.setResult(r)},r=function(a){var o=n.last;i.unsubscribe();try{n.resetLastResults(),i=n.subscribe(e,r)}finally{n.last=o}if(!rg.call(a,"graphQLErrors"))throw a;var s=t.result;(!s||s&&s.loading||!(0,ri.D)(a,s.error))&&t.setResult({data:s&&s.data,error:a,loading:!1,networkStatus:ru.I.error})},i=n.subscribe(e,r);return function(){return setTimeout(function(){return i.unsubscribe()})}},[n,this.renderPromises,this.client.disableNetworkFetches,]),function(){return t.getCurrentResult()},function(){return t.getCurrentResult()});return this.unsafeHandlePartialRefetch(r),this.toQueryResult(r)},e.prototype.useOptions=function(t){var n,r=this.createWatchQueryOptions(this.queryHookOptions=t),i=this.watchQueryOptions;!(0,ri.D)(r,i)&&(this.watchQueryOptions=r,i&&this.observable&&(this.observable.reobserve(this.getObsQueryOptions()),this.previousData=(null===(n=this.result)||void 0===n?void 0:n.data)||this.previousData,this.result=void 0)),this.onCompleted=t.onCompleted||e.prototype.onCompleted,this.onError=t.onError||e.prototype.onError,(this.renderPromises||this.client.disableNetworkFetches)&&!1===this.queryHookOptions.ssr&&!this.queryHookOptions.skip?this.result=this.ssrDisabledResult:this.queryHookOptions.skip||"standby"===this.watchQueryOptions.fetchPolicy?this.result=this.skipStandbyResult:(this.result===this.ssrDisabledResult||this.result===this.skipStandbyResult)&&(this.result=void 0)},e.prototype.getObsQueryOptions=function(){var e=[],t=this.client.defaultOptions.watchQuery;return t&&e.push(t),this.queryHookOptions.defaultOptions&&e.push(this.queryHookOptions.defaultOptions),e.push((0,rb.o)(this.observable&&this.observable.options,this.watchQueryOptions)),e.reduce(ra.J)},e.prototype.createWatchQueryOptions=function(e){void 0===e&&(e={});var t,n=e.skip,r=Object.assign((e.ssr,e.onCompleted,e.onError,e.defaultOptions,(0,t0._T)(e,["skip","ssr","onCompleted","onError","defaultOptions"])),{query:this.query});if(this.renderPromises&&("network-only"===r.fetchPolicy||"cache-and-network"===r.fetchPolicy)&&(r.fetchPolicy="cache-first"),r.variables||(r.variables={}),n){var i=r.fetchPolicy,a=void 0===i?this.getDefaultFetchPolicy():i,o=r.initialFetchPolicy;Object.assign(r,{initialFetchPolicy:void 0===o?a:o,fetchPolicy:"standby"})}else r.fetchPolicy||(r.fetchPolicy=(null===(t=this.observable)||void 0===t?void 0:t.options.initialFetchPolicy)||this.getDefaultFetchPolicy());return r},e.prototype.getDefaultFetchPolicy=function(){var e,t;return(null===(e=this.queryHookOptions.defaultOptions)||void 0===e?void 0:e.fetchPolicy)||(null===(t=this.client.defaultOptions.watchQuery)||void 0===t?void 0:t.fetchPolicy)||"cache-first"},e.prototype.onCompleted=function(e){},e.prototype.onError=function(e){},e.prototype.useObservableQuery=function(){var e=this.observable=this.renderPromises&&this.renderPromises.getSSRObservable(this.watchQueryOptions)||this.observable||this.client.watchQuery(this.getObsQueryOptions());this.obsQueryFields=(0,l.useMemo)(function(){return{refetch:e.refetch.bind(e),reobserve:e.reobserve.bind(e),fetchMore:e.fetchMore.bind(e),updateQuery:e.updateQuery.bind(e),startPolling:e.startPolling.bind(e),stopPolling:e.stopPolling.bind(e),subscribeToMore:e.subscribeToMore.bind(e)}},[e]);var t=!(!1===this.queryHookOptions.ssr||this.queryHookOptions.skip);return this.renderPromises&&t&&(this.renderPromises.registerSSRObservable(e),e.getCurrentResult().loading&&this.renderPromises.addObservableQueryPromise(e)),e},e.prototype.setResult=function(e){var t=this.result;t&&t.data&&(this.previousData=t.data),this.result=e,this.forceUpdate(),this.handleErrorOrCompleted(e)},e.prototype.handleErrorOrCompleted=function(e){var t=this;if(!e.loading){var n=this.toApolloError(e);Promise.resolve().then(function(){n?t.onError(n):e.data&&t.onCompleted(e.data)}).catch(function(e){__DEV__&&n9.kG.warn(e)})}},e.prototype.toApolloError=function(e){return(0,rm.O)(e.errors)?new rs.cA({graphQLErrors:e.errors}):e.error},e.prototype.getCurrentResult=function(){return this.result||this.handleErrorOrCompleted(this.result=this.observable.getCurrentResult()),this.result},e.prototype.toQueryResult=function(e){var t=this.toQueryResultCache.get(e);if(t)return t;var n=e.data,r=(e.partial,(0,t0._T)(e,["data","partial"]));return this.toQueryResultCache.set(e,t=(0,t0.pi)((0,t0.pi)((0,t0.pi)({data:n},r),this.obsQueryFields),{client:this.client,observable:this.observable,variables:this.observable.variables,called:!this.queryHookOptions.skip,previousData:this.previousData})),!t.error&&(0,rm.O)(e.errors)&&(t.error=new rs.cA({graphQLErrors:e.errors})),t},e.prototype.unsafeHandlePartialRefetch=function(e){e.partial&&this.queryHookOptions.partialRefetch&&!e.loading&&(!e.data||0===Object.keys(e.data).length)&&"cache-only"!==this.observable.options.fetchPolicy&&(Object.assign(e,{loading:!0,networkStatus:ru.I.refetch}),this.observable.refetch())},e}();function r_(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&void 0!==arguments[0]?arguments[0]:{};return rv(iH,e)},iz=function(){var e=ij(),t=parseInt(e.get("page")||"1",10),n=parseInt(e.get("per")||"50",10),r=i$({variables:{offset:(t-1)*n,limit:n},fetchPolicy:"network-only"}),i=r.data,a=r.loading,o=r.error;return a?l.createElement(iR,null):o?l.createElement(iD,{error:o}):i?l.createElement(iI,{chains:i.chains.results,page:t,pageSize:n,total:i.chains.metadata.total}):null},iG=n(67932),iW=n(8126),iK="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};function iV(e){if(iq())return Intl.DateTimeFormat.supportedLocalesOf(e)[0]}function iq(){return("undefined"==typeof Intl?"undefined":iK(Intl))==="object"&&"function"==typeof Intl.DateTimeFormat}var iZ="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},iX=function(){function e(e,t){for(var n=0;n=i.length)break;s=i[o++]}else{if((o=i.next()).done)break;s=o.value}var s,u=s;if((void 0===e?"undefined":iZ(e))!=="object")return;e=e[u]}return e}},{key:"put",value:function(){for(var e=arguments.length,t=Array(e),n=0;n=o.length)break;c=o[u++]}else{if((u=o.next()).done)break;c=u.value}var c,l=c;"object"!==iZ(a[l])&&(a[l]={}),a=a[l]}return a[i]=r}}]),e}();let i1=iQ;var i0=new i1;function i2(e,t){if(!iq())return function(e){return e.toString()};var n=i4(e),r=JSON.stringify(t),i=i0.get(String(n),r)||i0.put(String(n),r,new Intl.DateTimeFormat(n,t));return function(e){return i.format(e)}}var i3={};function i4(e){var t=e.toString();return i3[t]?i3[t]:i3[t]=iV(e)}var i6="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};function i5(e){return i8(e)?e:new Date(e)}function i8(e){return e instanceof Date||i9(e)}function i9(e){return(void 0===e?"undefined":i6(e))==="object"&&"function"==typeof e.getTime}var i7=n(54087),ae=n.n(i7);function at(e,t){if(0===e.length)return 0;for(var n=0,r=e.length-1,i=void 0;n<=r;){var a=t(e[i=Math.floor((r+n)/2)]);if(0===a)return i;if(a<0){if((n=i+1)>r)return n}else if((r=i-1)=t.nextUpdateTime)aa(t,this.instances);else break}},scheduleNextTick:function(){var e=this;this.scheduledTick=ae()(function(){e.tick(),e.scheduleNextTick()})},start:function(){this.scheduleNextTick()},stop:function(){ae().cancel(this.scheduledTick)}};function ai(e){var t=an(e.getNextValue(),2),n=t[0],r=t[1];e.setValue(n),e.nextUpdateTime=r}function aa(e,t){ai(e),as(t,e),ao(t,e)}function ao(e,t){var n=au(e,t);e.splice(n,0,t)}function as(e,t){var n=e.indexOf(t);e.splice(n,1)}function au(e,t){var n=t.nextUpdateTime;return at(e,function(e){return e.nextUpdateTime===n?0:e.nextUpdateTime>n?1:-1})}var ac=(0,ec.oneOfType)([(0,ec.shape)({minTime:ec.number,formatAs:ec.string.isRequired}),(0,ec.shape)({test:ec.func,formatAs:ec.string.isRequired}),(0,ec.shape)({minTime:ec.number,format:ec.func.isRequired}),(0,ec.shape)({test:ec.func,format:ec.func.isRequired})]),al=(0,ec.oneOfType)([ec.string,(0,ec.shape)({steps:(0,ec.arrayOf)(ac).isRequired,labels:(0,ec.oneOfType)([ec.string,(0,ec.arrayOf)(ec.string)]).isRequired,round:ec.string})]),af=Object.assign||function(e){for(var t=1;t=0)&&Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n}function ap(e){var t=e.date,n=e.future,r=e.timeStyle,i=e.round,a=e.minTimeLeft,o=e.tooltip,s=e.component,u=e.container,c=e.wrapperComponent,f=e.wrapperProps,d=e.locale,h=e.locales,p=e.formatVerboseDate,b=e.verboseDateFormat,m=e.updateInterval,g=e.tick,v=ah(e,["date","future","timeStyle","round","minTimeLeft","tooltip","component","container","wrapperComponent","wrapperProps","locale","locales","formatVerboseDate","verboseDateFormat","updateInterval","tick"]),y=(0,l.useMemo)(function(){return d&&(h=[d]),h.concat(iW.Z.getDefaultLocale())},[d,h]),w=(0,l.useMemo)(function(){return new iW.Z(y)},[y]);t=(0,l.useMemo)(function(){return i5(t)},[t]);var _=(0,l.useCallback)(function(){var e=Date.now(),o=void 0;if(n&&e>=t.getTime()&&(e=t.getTime(),o=!0),void 0!==a){var s=t.getTime()-1e3*a;e>s&&(e=s,o=!0)}var u=w.format(t,r,{getTimeToNextUpdate:!0,now:e,future:n,round:i}),c=ad(u,2),l=c[0],f=c[1];return f=o?ag:m||f||6e4,[l,e+f]},[t,n,r,m,i,a,w]),E=(0,l.useRef)();E.current=_;var S=(0,l.useMemo)(_,[]),k=ad(S,2),x=k[0],T=k[1],M=(0,l.useState)(x),O=ad(M,2),A=O[0],L=O[1],C=ad((0,l.useState)(),2),I=C[0],D=C[1],N=(0,l.useRef)();(0,l.useEffect)(function(){if(g)return N.current=ar.add({getNextValue:function(){return E.current()},setValue:L,nextUpdateTime:T}),function(){return N.current.stop()}},[g]),(0,l.useEffect)(function(){if(N.current)N.current.forceUpdate();else{var e=_(),t=ad(e,1)[0];L(t)}},[_]),(0,l.useEffect)(function(){D(!0)},[]);var P=(0,l.useMemo)(function(){if("undefined"!=typeof window)return i2(y,b)},[y,b]),R=(0,l.useMemo)(function(){if("undefined"!=typeof window)return p?p(t):P(t)},[t,p,P]),j=l.createElement(s,af({date:t,verboseDate:I?R:void 0,tooltip:o},v),A),F=c||u;return F?l.createElement(F,af({},f,{verboseDate:I?R:void 0}),j):j}ap.propTypes={date:el().oneOfType([el().instanceOf(Date),el().number]).isRequired,locale:el().string,locales:el().arrayOf(el().string),future:el().bool,timeStyle:al,round:el().string,minTimeLeft:el().number,component:el().elementType.isRequired,tooltip:el().bool.isRequired,formatVerboseDate:el().func,verboseDateFormat:el().object,updateInterval:el().oneOfType([el().number,el().arrayOf(el().shape({threshold:el().number,interval:el().number.isRequired}))]),tick:el().bool,wrapperComponent:el().func,wrapperProps:el().object},ap.defaultProps={locales:[],component:av,tooltip:!0,verboseDateFormat:{weekday:"long",day:"numeric",month:"long",year:"numeric",hour:"numeric",minute:"2-digit",second:"2-digit"},tick:!0},ap=l.memo(ap);let ab=ap;var am,ag=31536e9;function av(e){var t=e.date,n=e.verboseDate,r=e.tooltip,i=e.children,a=ah(e,["date","verboseDate","tooltip","children"]),o=(0,l.useMemo)(function(){return t.toISOString()},[t]);return l.createElement("time",af({},a,{dateTime:o,title:r?n:void 0}),i)}av.propTypes={date:el().instanceOf(Date).isRequired,verboseDate:el().string,tooltip:el().bool.isRequired,children:el().string.isRequired};var ay=n(30381),aw=n.n(ay),a_=n(31657);function aE(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function aS(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0?new rs.cA({graphQLErrors:i}):void 0;if(u===s.current.mutationId&&!c.ignoreResults){var f={called:!0,loading:!1,data:r,error:l,client:a};s.current.isMounted&&!(0,ri.D)(s.current.result,f)&&o(s.current.result=f)}var d=e.onCompleted||(null===(n=s.current.options)||void 0===n?void 0:n.onCompleted);return null==d||d(t.data,c),t}).catch(function(t){if(u===s.current.mutationId&&s.current.isMounted){var n,r={loading:!1,error:t,data:void 0,called:!0,client:a};(0,ri.D)(s.current.result,r)||o(s.current.result=r)}var i=e.onError||(null===(n=s.current.options)||void 0===n?void 0:n.onError);if(i)return i(t,c),{data:void 0,errors:t};throw t})},[]),c=(0,l.useCallback)(function(){s.current.isMounted&&o({called:!1,loading:!1,client:n})},[]);return(0,l.useEffect)(function(){return s.current.isMounted=!0,function(){s.current.isMounted=!1}},[]),[u,(0,t0.pi)({reset:c},a)]}var os=n(59067),ou=n(28428),oc=n(11186),ol=n(78513);function of(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var od=function(e){return(0,b.createStyles)({paper:{display:"flex",margin:"".concat(2.5*e.spacing.unit,"px 0"),padding:"".concat(3*e.spacing.unit,"px ").concat(3.5*e.spacing.unit,"px")},content:{flex:1,width:"100%"},actions:of({marginTop:-(1.5*e.spacing.unit),marginLeft:-(4*e.spacing.unit)},e.breakpoints.up("sm"),{marginLeft:0,marginRight:-(1.5*e.spacing.unit)}),itemBlock:{border:"1px solid rgba(224, 224, 224, 1)",borderRadius:e.shape.borderRadius,padding:2*e.spacing.unit,marginTop:e.spacing.unit},itemBlockText:{overflowWrap:"anywhere"}})},oh=(0,b.withStyles)(od)(function(e){var t=e.actions,n=e.children,r=e.classes;return l.createElement(ii.default,{className:r.paper},l.createElement("div",{className:r.content},n),t&&l.createElement("div",{className:r.actions},t))}),op=function(e){var t=e.title;return l.createElement(x.default,{variant:"subtitle2",gutterBottom:!0},t)},ob=function(e){var t=e.children,n=e.value;return l.createElement(x.default,{variant:"body1",noWrap:!0},t||n)},om=(0,b.withStyles)(od)(function(e){var t=e.children,n=e.classes,r=e.value;return l.createElement("div",{className:n.itemBlock},l.createElement(x.default,{variant:"body1",className:n.itemBlockText},t||r))});function og(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]-1}let sq=sV;function sZ(e,t){var n=this.__data__,r=sH(n,e);return r<0?(++this.size,n.push([e,t])):n[r][1]=t,this}let sX=sZ;function sJ(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t-1&&e%1==0&&e-1&&e%1==0&&e<=cC}let cD=cI;var cN="[object Arguments]",cP="[object Array]",cR="[object Boolean]",cj="[object Date]",cF="[object Error]",cY="[object Function]",cB="[object Map]",cU="[object Number]",cH="[object Object]",c$="[object RegExp]",cz="[object Set]",cG="[object String]",cW="[object WeakMap]",cK="[object ArrayBuffer]",cV="[object DataView]",cq="[object Float64Array]",cZ="[object Int8Array]",cX="[object Int16Array]",cJ="[object Int32Array]",cQ="[object Uint8Array]",c1="[object Uint8ClampedArray]",c0="[object Uint16Array]",c2="[object Uint32Array]",c3={};function c4(e){return eD(e)&&cD(e.length)&&!!c3[eC(e)]}c3["[object Float32Array]"]=c3[cq]=c3[cZ]=c3[cX]=c3[cJ]=c3[cQ]=c3[c1]=c3[c0]=c3[c2]=!0,c3[cN]=c3[cP]=c3[cK]=c3[cR]=c3[cV]=c3[cj]=c3[cF]=c3[cY]=c3[cB]=c3[cU]=c3[cH]=c3[c$]=c3[cz]=c3[cG]=c3[cW]=!1;let c6=c4;function c5(e){return function(t){return e(t)}}let c8=c5;var c9=n(79730),c7=c9.Z&&c9.Z.isTypedArray,le=c7?c8(c7):c6;let lt=le;var ln=Object.prototype.hasOwnProperty;function lr(e,t){var n=cx(e),r=!n&&cS(e),i=!n&&!r&&(0,cT.Z)(e),a=!n&&!r&&!i&<(e),o=n||r||i||a,s=o?cb(e.length,String):[],u=s.length;for(var c in e)(t||ln.call(e,c))&&!(o&&("length"==c||i&&("offset"==c||"parent"==c)||a&&("buffer"==c||"byteLength"==c||"byteOffset"==c)||cL(c,u)))&&s.push(c);return s}let li=lr;var la=Object.prototype;function lo(e){var t=e&&e.constructor;return e===("function"==typeof t&&t.prototype||la)}let ls=lo;var lu=sT(Object.keys,Object);let lc=lu;var ll=Object.prototype.hasOwnProperty;function lf(e){if(!ls(e))return lc(e);var t=[];for(var n in Object(e))ll.call(e,n)&&"constructor"!=n&&t.push(n);return t}let ld=lf;function lh(e){return null!=e&&cD(e.length)&&!ur(e)}let lp=lh;function lb(e){return lp(e)?li(e):ld(e)}let lm=lb;function lg(e,t){return e&&ch(t,lm(t),e)}let lv=lg;function ly(e){var t=[];if(null!=e)for(var n in Object(e))t.push(n);return t}let lw=ly;var l_=Object.prototype.hasOwnProperty;function lE(e){if(!ed(e))return lw(e);var t=ls(e),n=[];for(var r in e)"constructor"==r&&(t||!l_.call(e,r))||n.push(r);return n}let lS=lE;function lk(e){return lp(e)?li(e,!0):lS(e)}let lx=lk;function lT(e,t){return e&&ch(t,lx(t),e)}let lM=lT;var lO=n(42896);function lA(e,t){var n=-1,r=e.length;for(t||(t=Array(r));++n=0||(i[n]=e[n]);return i}function hu(e){if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}var hc=function(e){return Array.isArray(e)&&0===e.length},hl=function(e){return"function"==typeof e},hf=function(e){return null!==e&&"object"==typeof e},hd=function(e){return String(Math.floor(Number(e)))===e},hh=function(e){return"[object String]"===Object.prototype.toString.call(e)},hp=function(e){return 0===l.Children.count(e)},hb=function(e){return hf(e)&&hl(e.then)};function hm(e,t,n,r){void 0===r&&(r=0);for(var i=d8(t);e&&r=0?[]:{}}}return(0===a?e:i)[o[a]]===n?e:(void 0===n?delete i[o[a]]:i[o[a]]=n,0===a&&void 0===n&&delete r[o[a]],r)}function hv(e,t,n,r){void 0===n&&(n=new WeakMap),void 0===r&&(r={});for(var i=0,a=Object.keys(e);i0?t.map(function(t){return x(t,hm(e,t))}):[Promise.resolve("DO_NOT_DELETE_YOU_WILL_BE_FIRED")]).then(function(e){return e.reduce(function(e,n,r){return"DO_NOT_DELETE_YOU_WILL_BE_FIRED"===n||n&&(e=hg(e,t[r],n)),e},{})})},[x]),M=(0,l.useCallback)(function(e){return Promise.all([T(e),h.validationSchema?k(e):{},h.validate?S(e):{}]).then(function(e){var t=e[0],n=e[1],r=e[2];return sk.all([t,n,r],{arrayMerge:hL})})},[h.validate,h.validationSchema,T,S,k]),O=hN(function(e){return void 0===e&&(e=_.values),E({type:"SET_ISVALIDATING",payload:!0}),M(e).then(function(e){return v.current&&(E({type:"SET_ISVALIDATING",payload:!1}),sd()(_.errors,e)||E({type:"SET_ERRORS",payload:e})),e})});(0,l.useEffect)(function(){o&&!0===v.current&&sd()(p.current,h.initialValues)&&O(p.current)},[o,O]);var A=(0,l.useCallback)(function(e){var t=e&&e.values?e.values:p.current,n=e&&e.errors?e.errors:b.current?b.current:h.initialErrors||{},r=e&&e.touched?e.touched:m.current?m.current:h.initialTouched||{},i=e&&e.status?e.status:g.current?g.current:h.initialStatus;p.current=t,b.current=n,m.current=r,g.current=i;var a=function(){E({type:"RESET_FORM",payload:{isSubmitting:!!e&&!!e.isSubmitting,errors:n,touched:r,status:i,values:t,isValidating:!!e&&!!e.isValidating,submitCount:e&&e.submitCount&&"number"==typeof e.submitCount?e.submitCount:0}})};if(h.onReset){var o=h.onReset(_.values,V);hb(o)?o.then(a):a()}else a()},[h.initialErrors,h.initialStatus,h.initialTouched]);(0,l.useEffect)(function(){!0===v.current&&!sd()(p.current,h.initialValues)&&(c&&(p.current=h.initialValues,A()),o&&O(p.current))},[c,h.initialValues,A,o,O]),(0,l.useEffect)(function(){c&&!0===v.current&&!sd()(b.current,h.initialErrors)&&(b.current=h.initialErrors||hS,E({type:"SET_ERRORS",payload:h.initialErrors||hS}))},[c,h.initialErrors]),(0,l.useEffect)(function(){c&&!0===v.current&&!sd()(m.current,h.initialTouched)&&(m.current=h.initialTouched||hk,E({type:"SET_TOUCHED",payload:h.initialTouched||hk}))},[c,h.initialTouched]),(0,l.useEffect)(function(){c&&!0===v.current&&!sd()(g.current,h.initialStatus)&&(g.current=h.initialStatus,E({type:"SET_STATUS",payload:h.initialStatus}))},[c,h.initialStatus,h.initialTouched]);var L=hN(function(e){if(y.current[e]&&hl(y.current[e].validate)){var t=hm(_.values,e),n=y.current[e].validate(t);return hb(n)?(E({type:"SET_ISVALIDATING",payload:!0}),n.then(function(e){return e}).then(function(t){E({type:"SET_FIELD_ERROR",payload:{field:e,value:t}}),E({type:"SET_ISVALIDATING",payload:!1})})):(E({type:"SET_FIELD_ERROR",payload:{field:e,value:n}}),Promise.resolve(n))}return h.validationSchema?(E({type:"SET_ISVALIDATING",payload:!0}),k(_.values,e).then(function(e){return e}).then(function(t){E({type:"SET_FIELD_ERROR",payload:{field:e,value:t[e]}}),E({type:"SET_ISVALIDATING",payload:!1})})):Promise.resolve()}),C=(0,l.useCallback)(function(e,t){var n=t.validate;y.current[e]={validate:n}},[]),I=(0,l.useCallback)(function(e){delete y.current[e]},[]),D=hN(function(e,t){return E({type:"SET_TOUCHED",payload:e}),(void 0===t?i:t)?O(_.values):Promise.resolve()}),N=(0,l.useCallback)(function(e){E({type:"SET_ERRORS",payload:e})},[]),P=hN(function(e,t){var r=hl(e)?e(_.values):e;return E({type:"SET_VALUES",payload:r}),(void 0===t?n:t)?O(r):Promise.resolve()}),R=(0,l.useCallback)(function(e,t){E({type:"SET_FIELD_ERROR",payload:{field:e,value:t}})},[]),j=hN(function(e,t,r){return E({type:"SET_FIELD_VALUE",payload:{field:e,value:t}}),(void 0===r?n:r)?O(hg(_.values,e,t)):Promise.resolve()}),F=(0,l.useCallback)(function(e,t){var n,r=t,i=e;if(!hh(e)){e.persist&&e.persist();var a=e.target?e.target:e.currentTarget,o=a.type,s=a.name,u=a.id,c=a.value,l=a.checked,f=(a.outerHTML,a.options),d=a.multiple;r=t||s||u,i=/number|range/.test(o)?(n=parseFloat(c),isNaN(n)?"":n):/checkbox/.test(o)?hI(hm(_.values,r),l,c):d?hC(f):c}r&&j(r,i)},[j,_.values]),Y=hN(function(e){if(hh(e))return function(t){return F(t,e)};F(e)}),B=hN(function(e,t,n){return void 0===t&&(t=!0),E({type:"SET_FIELD_TOUCHED",payload:{field:e,value:t}}),(void 0===n?i:n)?O(_.values):Promise.resolve()}),U=(0,l.useCallback)(function(e,t){e.persist&&e.persist();var n,r=e.target,i=r.name,a=r.id;r.outerHTML,B(t||i||a,!0)},[B]),H=hN(function(e){if(hh(e))return function(t){return U(t,e)};U(e)}),$=(0,l.useCallback)(function(e){hl(e)?E({type:"SET_FORMIK_STATE",payload:e}):E({type:"SET_FORMIK_STATE",payload:function(){return e}})},[]),z=(0,l.useCallback)(function(e){E({type:"SET_STATUS",payload:e})},[]),G=(0,l.useCallback)(function(e){E({type:"SET_ISSUBMITTING",payload:e})},[]),W=hN(function(){return E({type:"SUBMIT_ATTEMPT"}),O().then(function(e){var t,n=e instanceof Error;if(!n&&0===Object.keys(e).length){try{if(void 0===(t=q()))return}catch(r){throw r}return Promise.resolve(t).then(function(e){return v.current&&E({type:"SUBMIT_SUCCESS"}),e}).catch(function(e){if(v.current)throw E({type:"SUBMIT_FAILURE"}),e})}if(v.current&&(E({type:"SUBMIT_FAILURE"}),n))throw e})}),K=hN(function(e){e&&e.preventDefault&&hl(e.preventDefault)&&e.preventDefault(),e&&e.stopPropagation&&hl(e.stopPropagation)&&e.stopPropagation(),W().catch(function(e){console.warn("Warning: An unhandled error was caught from submitForm()",e)})}),V={resetForm:A,validateForm:O,validateField:L,setErrors:N,setFieldError:R,setFieldTouched:B,setFieldValue:j,setStatus:z,setSubmitting:G,setTouched:D,setValues:P,setFormikState:$,submitForm:W},q=hN(function(){return f(_.values,V)}),Z=hN(function(e){e&&e.preventDefault&&hl(e.preventDefault)&&e.preventDefault(),e&&e.stopPropagation&&hl(e.stopPropagation)&&e.stopPropagation(),A()}),X=(0,l.useCallback)(function(e){return{value:hm(_.values,e),error:hm(_.errors,e),touched:!!hm(_.touched,e),initialValue:hm(p.current,e),initialTouched:!!hm(m.current,e),initialError:hm(b.current,e)}},[_.errors,_.touched,_.values]),J=(0,l.useCallback)(function(e){return{setValue:function(t,n){return j(e,t,n)},setTouched:function(t,n){return B(e,t,n)},setError:function(t){return R(e,t)}}},[j,B,R]),Q=(0,l.useCallback)(function(e){var t=hf(e),n=t?e.name:e,r=hm(_.values,n),i={name:n,value:r,onChange:Y,onBlur:H};if(t){var a=e.type,o=e.value,s=e.as,u=e.multiple;"checkbox"===a?void 0===o?i.checked=!!r:(i.checked=!!(Array.isArray(r)&&~r.indexOf(o)),i.value=o):"radio"===a?(i.checked=r===o,i.value=o):"select"===s&&u&&(i.value=i.value||[],i.multiple=!0)}return i},[H,Y,_.values]),ee=(0,l.useMemo)(function(){return!sd()(p.current,_.values)},[p.current,_.values]),et=(0,l.useMemo)(function(){return void 0!==s?ee?_.errors&&0===Object.keys(_.errors).length:!1!==s&&hl(s)?s(h):s:_.errors&&0===Object.keys(_.errors).length},[s,ee,_.errors,h]);return ha({},_,{initialValues:p.current,initialErrors:b.current,initialTouched:m.current,initialStatus:g.current,handleBlur:H,handleChange:Y,handleReset:Z,handleSubmit:K,resetForm:A,setErrors:N,setFormikState:$,setFieldTouched:B,setFieldValue:j,setFieldError:R,setStatus:z,setSubmitting:G,setTouched:D,setValues:P,submitForm:W,validateForm:O,validateField:L,isValid:et,dirty:ee,unregisterField:I,registerField:C,getFieldProps:Q,getFieldMeta:X,getFieldHelpers:J,validateOnBlur:i,validateOnChange:n,validateOnMount:o})}function hT(e){var t=hx(e),n=e.component,r=e.children,i=e.render,a=e.innerRef;return(0,l.useImperativeHandle)(a,function(){return t}),(0,l.createElement)(hw,{value:t},n?(0,l.createElement)(n,t):i?i(t):r?hl(r)?r(t):hp(r)?null:l.Children.only(r):null)}function hM(e){var t={};if(e.inner){if(0===e.inner.length)return hg(t,e.path,e.message);for(var n=e.inner,r=Array.isArray(n),i=0,n=r?n:n[Symbol.iterator]();;){if(r){if(i>=n.length)break;a=n[i++]}else{if((i=n.next()).done)break;a=i.value}var a,o=a;hm(t,o.path)||(t=hg(t,o.path,o.message))}}return t}function hO(e,t,n,r){void 0===n&&(n=!1),void 0===r&&(r={});var i=hA(e);return t[n?"validateSync":"validate"](i,{abortEarly:!1,context:r})}function hA(e){var t=Array.isArray(e)?[]:{};for(var n in e)if(Object.prototype.hasOwnProperty.call(e,n)){var r=String(n);!0===Array.isArray(e[r])?t[r]=e[r].map(function(e){return!0===Array.isArray(e)||sR(e)?hA(e):""!==e?e:void 0}):sR(e[r])?t[r]=hA(e[r]):t[r]=""!==e[r]?e[r]:void 0}return t}function hL(e,t,n){var r=e.slice();return t.forEach(function(t,i){if(void 0===r[i]){var a=!1!==n.clone&&n.isMergeableObject(t);r[i]=a?sk(Array.isArray(t)?[]:{},t,n):t}else n.isMergeableObject(t)?r[i]=sk(e[i],t,n):-1===e.indexOf(t)&&r.push(t)}),r}function hC(e){return Array.from(e).filter(function(e){return e.selected}).map(function(e){return e.value})}function hI(e,t,n){if("boolean"==typeof e)return Boolean(t);var r=[],i=!1,a=-1;if(Array.isArray(e))r=e,i=(a=e.indexOf(n))>=0;else if(!n||"true"==n||"false"==n)return Boolean(t);return t&&n&&!i?r.concat(n):i?r.slice(0,a).concat(r.slice(a+1)):r}var hD="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement?l.useLayoutEffect:l.useEffect;function hN(e){var t=(0,l.useRef)(e);return hD(function(){t.current=e}),(0,l.useCallback)(function(){for(var e=arguments.length,n=Array(e),r=0;re?t:e},0);return Array.from(ha({},e,{length:t+1}))};(function(e){function t(t){var n;return(n=e.call(this,t)||this).updateArrayField=function(e,t,r){var i=n.props,a=i.name;(0,i.formik.setFormikState)(function(n){var i="function"==typeof r?r:e,o="function"==typeof t?t:e,s=hg(n.values,a,e(hm(n.values,a))),u=r?i(hm(n.errors,a)):void 0,c=t?o(hm(n.touched,a)):void 0;return hc(u)&&(u=void 0),hc(c)&&(c=void 0),ha({},n,{values:s,errors:r?hg(n.errors,a,u):n.errors,touched:t?hg(n.touched,a,c):n.touched})})},n.push=function(e){return n.updateArrayField(function(t){return[].concat(hU(t),[hi(e)])},!1,!1)},n.handlePush=function(e){return function(){return n.push(e)}},n.swap=function(e,t){return n.updateArrayField(function(n){return hF(n,e,t)},!0,!0)},n.handleSwap=function(e,t){return function(){return n.swap(e,t)}},n.move=function(e,t){return n.updateArrayField(function(n){return hj(n,e,t)},!0,!0)},n.handleMove=function(e,t){return function(){return n.move(e,t)}},n.insert=function(e,t){return n.updateArrayField(function(n){return hY(n,e,t)},function(t){return hY(t,e,null)},function(t){return hY(t,e,null)})},n.handleInsert=function(e,t){return function(){return n.insert(e,t)}},n.replace=function(e,t){return n.updateArrayField(function(n){return hB(n,e,t)},!1,!1)},n.handleReplace=function(e,t){return function(){return n.replace(e,t)}},n.unshift=function(e){var t=-1;return n.updateArrayField(function(n){var r=n?[e].concat(n):[e];return t<0&&(t=r.length),r},function(e){var n=e?[null].concat(e):[null];return t<0&&(t=n.length),n},function(e){var n=e?[null].concat(e):[null];return t<0&&(t=n.length),n}),t},n.handleUnshift=function(e){return function(){return n.unshift(e)}},n.handleRemove=function(e){return function(){return n.remove(e)}},n.handlePop=function(){return function(){return n.pop()}},n.remove=n.remove.bind(hu(n)),n.pop=n.pop.bind(hu(n)),n}ho(t,e);var n=t.prototype;return n.componentDidUpdate=function(e){this.props.validateOnChange&&this.props.formik.validateOnChange&&!sd()(hm(e.formik.values,e.name),hm(this.props.formik.values,this.props.name))&&this.props.formik.validateForm(this.props.formik.values)},n.remove=function(e){var t;return this.updateArrayField(function(n){var r=n?hU(n):[];return t||(t=r[e]),hl(r.splice)&&r.splice(e,1),r},!0,!0),t},n.pop=function(){var e;return this.updateArrayField(function(t){var n=t;return e||(e=n&&n.pop&&n.pop()),n},!0,!0),e},n.render=function(){var e={push:this.push,pop:this.pop,swap:this.swap,move:this.move,insert:this.insert,replace:this.replace,unshift:this.unshift,remove:this.remove,handlePush:this.handlePush,handlePop:this.handlePop,handleSwap:this.handleSwap,handleMove:this.handleMove,handleInsert:this.handleInsert,handleReplace:this.handleReplace,handleUnshift:this.handleUnshift,handleRemove:this.handleRemove},t=this.props,n=t.component,r=t.render,i=t.children,a=t.name,o=hs(t.formik,["validate","validationSchema"]),s=ha({},e,{form:o,name:a});return n?(0,l.createElement)(n,s):r?r(s):i?"function"==typeof i?i(s):hp(i)?null:l.Children.only(i):null},t})(l.Component).defaultProps={validateOnChange:!0},l.Component,l.Component;var hH=n(24802),h$=n(71209),hz=n(91750),hG=n(11970),hW=n(4689),hK=n(67598),hV=function(){return(hV=Object.assign||function(e){for(var t,n=1,r=arguments.length;nt.indexOf(r)&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var i=0,r=Object.getOwnPropertySymbols(e);it.indexOf(r[i])&&(n[r[i]]=e[r[i]]);return n}function hZ(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hq(n,["onBlur"]),a=e.form,o=a.isSubmitting,s=a.touched,u=a.errors,c=e.onBlur,l=e.helperText,f=hq(e,["disabled","field","form","onBlur","helperText"]),d=hm(u,i.name),h=hm(s,i.name)&&!!d;return hV(hV({variant:f.variant,error:h,helperText:h?d:l,disabled:null!=t?t:o,onBlur:null!=c?c:function(e){r(null!=e?e:i.name)}},i),f)}function hX(e){var t=e.children,n=hq(e,["children"]);return(0,l.createElement)(iw.Z,hV({},hZ(n)),t)}function hJ(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hq(n,["onBlur"]),a=e.form.isSubmitting,o=(e.type,e.onBlur),s=hq(e,["disabled","field","form","type","onBlur"]);return hV(hV({disabled:null!=t?t:a,onBlur:null!=o?o:function(e){r(null!=e?e:i.name)}},i),s)}function hQ(e){return(0,l.createElement)(hH.Z,hV({},hJ(e)))}function h1(e){var t,n=e.disabled,r=e.field,i=r.onBlur,a=hq(r,["onBlur"]),o=e.form.isSubmitting,s=(e.type,e.onBlur),u=hq(e,["disabled","field","form","type","onBlur"]);return hV(hV({disabled:null!=n?n:o,indeterminate:!Array.isArray(a.value)&&null==a.value,onBlur:null!=s?s:function(e){i(null!=e?e:a.name)}},a),u)}function h0(e){return(0,l.createElement)(h$.Z,hV({},h1(e)))}function h2(e){var t=e.Label,n=hq(e,["Label"]);return(0,l.createElement)(hz.Z,hV({control:(0,l.createElement)(h$.Z,hV({},h1(n)))},t))}function h3(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hq(n,["onBlur"]),a=e.form.isSubmitting,o=e.onBlur,s=hq(e,["disabled","field","form","onBlur"]);return hV(hV({disabled:null!=t?t:a,onBlur:null!=o?o:function(e){r(null!=e?e:i.name)}},i),s)}function h4(e){return(0,l.createElement)(hG.default,hV({},h3(e)))}function h6(e){var t=e.field,n=t.onBlur,r=hq(t,["onBlur"]),i=(e.form,e.onBlur),a=hq(e,["field","form","onBlur"]);return hV(hV({onBlur:null!=i?i:function(e){n(null!=e?e:r.name)}},r),a)}function h5(e){return(0,l.createElement)(hW.Z,hV({},h6(e)))}function h8(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hq(n,["onBlur"]),a=e.form.isSubmitting,o=e.onBlur,s=hq(e,["disabled","field","form","onBlur"]);return hV(hV({disabled:null!=t?t:a,onBlur:null!=o?o:function(e){r(null!=e?e:i.name)}},i),s)}function h9(e){return(0,l.createElement)(hK.default,hV({},h8(e)))}hX.displayName="FormikMaterialUITextField",hQ.displayName="FormikMaterialUISwitch",h0.displayName="FormikMaterialUICheckbox",h2.displayName="FormikMaterialUICheckboxWithLabel",h4.displayName="FormikMaterialUISelect",h5.displayName="FormikMaterialUIRadioGroup",h9.displayName="FormikMaterialUIInputBase";try{a=Map}catch(h7){}try{o=Set}catch(pe){}function pt(e,t,n){if(!e||"object"!=typeof e||"function"==typeof e)return e;if(e.nodeType&&"cloneNode"in e)return e.cloneNode(!0);if(e instanceof Date)return new Date(e.getTime());if(e instanceof RegExp)return RegExp(e);if(Array.isArray(e))return e.map(pn);if(a&&e instanceof a)return new Map(Array.from(e.entries()));if(o&&e instanceof o)return new Set(Array.from(e.values()));if(e instanceof Object){t.push(e);var r=Object.create(e);for(var i in n.push(r),e){var s=t.findIndex(function(t){return t===e[i]});r[i]=s>-1?n[s]:pt(e[i],t,n)}return r}return e}function pn(e){return pt(e,[],[])}let pr=Object.prototype.toString,pi=Error.prototype.toString,pa=RegExp.prototype.toString,po="undefined"!=typeof Symbol?Symbol.prototype.toString:()=>"",ps=/^Symbol\((.*)\)(.*)$/;function pu(e){if(e!=+e)return"NaN";let t=0===e&&1/e<0;return t?"-0":""+e}function pc(e,t=!1){if(null==e||!0===e||!1===e)return""+e;let n=typeof e;if("number"===n)return pu(e);if("string"===n)return t?`"${e}"`:e;if("function"===n)return"[Function "+(e.name||"anonymous")+"]";if("symbol"===n)return po.call(e).replace(ps,"Symbol($1)");let r=pr.call(e).slice(8,-1);return"Date"===r?isNaN(e.getTime())?""+e:e.toISOString(e):"Error"===r||e instanceof Error?"["+pi.call(e)+"]":"RegExp"===r?pa.call(e):null}function pl(e,t){let n=pc(e,t);return null!==n?n:JSON.stringify(e,function(e,n){let r=pc(this[e],t);return null!==r?r:n},2)}let pf={default:"${path} is invalid",required:"${path} is a required field",oneOf:"${path} must be one of the following values: ${values}",notOneOf:"${path} must not be one of the following values: ${values}",notType({path:e,type:t,value:n,originalValue:r}){let i=null!=r&&r!==n,a=`${e} must be a \`${t}\` type, but the final value was: \`${pl(n,!0)}\``+(i?` (cast from the value \`${pl(r,!0)}\`).`:".");return null===n&&(a+='\n If "null" is intended as an empty value be sure to mark the schema as `.nullable()`'),a},defined:"${path} must be defined"},pd={length:"${path} must be exactly ${length} characters",min:"${path} must be at least ${min} characters",max:"${path} must be at most ${max} characters",matches:'${path} must match the following: "${regex}"',email:"${path} must be a valid email",url:"${path} must be a valid URL",uuid:"${path} must be a valid UUID",trim:"${path} must be a trimmed string",lowercase:"${path} must be a lowercase string",uppercase:"${path} must be a upper case string"},ph={min:"${path} must be greater than or equal to ${min}",max:"${path} must be less than or equal to ${max}",lessThan:"${path} must be less than ${less}",moreThan:"${path} must be greater than ${more}",positive:"${path} must be a positive number",negative:"${path} must be a negative number",integer:"${path} must be an integer"},pp={min:"${path} field must be later than ${min}",max:"${path} field must be at earlier than ${max}"},pb={isValue:"${path} field must be ${value}"},pm={noUnknown:"${path} field has unspecified keys: ${unknown}"},pg={min:"${path} field must have at least ${min} items",max:"${path} field must have less than or equal to ${max} items",length:"${path} must be have ${length} items"};Object.assign(Object.create(null),{mixed:pf,string:pd,number:ph,date:pp,object:pm,array:pg,boolean:pb});var pv=n(18721),py=n.n(pv);let pw=e=>e&&e.__isYupSchema__;class p_{constructor(e,t){if(this.refs=e,this.refs=e,"function"==typeof t){this.fn=t;return}if(!py()(t,"is"))throw TypeError("`is:` is required for `when()` conditions");if(!t.then&&!t.otherwise)throw TypeError("either `then:` or `otherwise:` is required for `when()` conditions");let{is:n,then:r,otherwise:i}=t,a="function"==typeof n?n:(...e)=>e.every(e=>e===n);this.fn=function(...e){let t=e.pop(),n=e.pop(),o=a(...e)?r:i;if(o)return"function"==typeof o?o(n):n.concat(o.resolve(t))}}resolve(e,t){let n=this.refs.map(e=>e.getValue(null==t?void 0:t.value,null==t?void 0:t.parent,null==t?void 0:t.context)),r=this.fn.apply(e,n.concat(e,t));if(void 0===r||r===e)return e;if(!pw(r))throw TypeError("conditions must return a schema object");return r.resolve(t)}}let pE=p_;function pS(e){return null==e?[]:[].concat(e)}function pk(){return(pk=Object.assign||function(e){for(var t=1;tpl(t[n])):"function"==typeof e?e(t):e}static isError(e){return e&&"ValidationError"===e.name}constructor(e,t,n,r){super(),this.name="ValidationError",this.value=t,this.path=n,this.type=r,this.errors=[],this.inner=[],pS(e).forEach(e=>{pT.isError(e)?(this.errors.push(...e.errors),this.inner=this.inner.concat(e.inner.length?e.inner:e)):this.errors.push(e)}),this.message=this.errors.length>1?`${this.errors.length} errors occurred`:this.errors[0],Error.captureStackTrace&&Error.captureStackTrace(this,pT)}}let pM=e=>{let t=!1;return(...n)=>{t||(t=!0,e(...n))}};function pO(e,t){let{endEarly:n,tests:r,args:i,value:a,errors:o,sort:s,path:u}=e,c=pM(t),l=r.length,f=[];if(o=o||[],!l)return o.length?c(new pT(o,a,u)):c(null,a);for(let d=0;d=0||(i[n]=e[n]);return i}function pR(e){function t(t,n){let{value:r,path:i="",label:a,options:o,originalValue:s,sync:u}=t,c=pP(t,["value","path","label","options","originalValue","sync"]),{name:l,test:f,params:d,message:h}=e,{parent:p,context:b}=o;function m(e){return pD.isRef(e)?e.getValue(r,p,b):e}function g(e={}){let t=pL()(pN({value:r,originalValue:s,label:a,path:e.path||i},d,e.params),m),n=new pT(pT.formatError(e.message||h,t),r,t.path,e.type||l);return n.params=t,n}let v=pN({path:i,parent:p,type:l,createError:g,resolve:m,options:o,originalValue:s},c);if(!u){try{Promise.resolve(f.call(v,r,v)).then(e=>{pT.isError(e)?n(e):e?n(null,e):n(g())})}catch(y){n(y)}return}let w;try{var _;if(w=f.call(v,r,v),"function"==typeof(null==(_=w)?void 0:_.then))throw Error(`Validation test of type: "${v.type}" returned a Promise during a synchronous validate. This test will finish after the validate call has returned`)}catch(E){n(E);return}pT.isError(w)?n(w):w?n(null,w):n(g())}return t.OPTIONS=e,t}pD.prototype.__isYupRef=!0;let pj=e=>e.substr(0,e.length-1).substr(1);function pF(e,t,n,r=n){let i,a,o;return t?((0,pC.forEach)(t,(s,u,c)=>{let l=u?pj(s):s;if((e=e.resolve({context:r,parent:i,value:n})).innerType){let f=c?parseInt(l,10):0;if(n&&f>=n.length)throw Error(`Yup.reach cannot resolve an array item at index: ${s}, in the path: ${t}. because there is no value at that index. `);i=n,n=n&&n[f],e=e.innerType}if(!c){if(!e.fields||!e.fields[l])throw Error(`The schema does not contain the path: ${t}. (failed at: ${o} which is a type: "${e._type}")`);i=n,n=n&&n[l],e=e.fields[l]}a=l,o=u?"["+s+"]":"."+s}),{schema:e,parent:i,parentPath:a}):{parent:i,parentPath:t,schema:e}}class pY{constructor(){this.list=new Set,this.refs=new Map}get size(){return this.list.size+this.refs.size}describe(){let e=[];for(let t of this.list)e.push(t);for(let[,n]of this.refs)e.push(n.describe());return e}toArray(){return Array.from(this.list).concat(Array.from(this.refs.values()))}add(e){pD.isRef(e)?this.refs.set(e.key,e):this.list.add(e)}delete(e){pD.isRef(e)?this.refs.delete(e.key):this.list.delete(e)}has(e,t){if(this.list.has(e))return!0;let n,r=this.refs.values();for(;!(n=r.next()).done;)if(t(n.value)===e)return!0;return!1}clone(){let e=new pY;return e.list=new Set(this.list),e.refs=new Map(this.refs),e}merge(e,t){let n=this.clone();return e.list.forEach(e=>n.add(e)),e.refs.forEach(e=>n.add(e)),t.list.forEach(e=>n.delete(e)),t.refs.forEach(e=>n.delete(e)),n}}function pB(){return(pB=Object.assign||function(e){for(var t=1;t{this.typeError(pf.notType)}),this.type=(null==e?void 0:e.type)||"mixed",this.spec=pB({strip:!1,strict:!1,abortEarly:!0,recursive:!0,nullable:!1,presence:"optional"},null==e?void 0:e.spec)}get _type(){return this.type}_typeCheck(e){return!0}clone(e){if(this._mutate)return e&&Object.assign(this.spec,e),this;let t=Object.create(Object.getPrototypeOf(this));return t.type=this.type,t._typeError=this._typeError,t._whitelistError=this._whitelistError,t._blacklistError=this._blacklistError,t._whitelist=this._whitelist.clone(),t._blacklist=this._blacklist.clone(),t.exclusiveTests=pB({},this.exclusiveTests),t.deps=[...this.deps],t.conditions=[...this.conditions],t.tests=[...this.tests],t.transforms=[...this.transforms],t.spec=pn(pB({},this.spec,e)),t}label(e){var t=this.clone();return t.spec.label=e,t}meta(...e){if(0===e.length)return this.spec.meta;let t=this.clone();return t.spec.meta=Object.assign(t.spec.meta||{},e[0]),t}withMutation(e){let t=this._mutate;this._mutate=!0;let n=e(this);return this._mutate=t,n}concat(e){if(!e||e===this)return this;if(e.type!==this.type&&"mixed"!==this.type)throw TypeError(`You cannot \`concat()\` schema's of different types: ${this.type} and ${e.type}`);let t=this,n=e.clone(),r=pB({},t.spec,n.spec);return n.spec=r,n._typeError||(n._typeError=t._typeError),n._whitelistError||(n._whitelistError=t._whitelistError),n._blacklistError||(n._blacklistError=t._blacklistError),n._whitelist=t._whitelist.merge(e._whitelist,e._blacklist),n._blacklist=t._blacklist.merge(e._blacklist,e._whitelist),n.tests=t.tests,n.exclusiveTests=t.exclusiveTests,n.withMutation(t=>{e.tests.forEach(e=>{t.test(e.OPTIONS)})}),n}isType(e){return!!this.spec.nullable&&null===e||this._typeCheck(e)}resolve(e){let t=this;if(t.conditions.length){let n=t.conditions;(t=t.clone()).conditions=[],t=(t=n.reduce((t,n)=>n.resolve(t,e),t)).resolve(e)}return t}cast(e,t={}){let n=this.resolve(pB({value:e},t)),r=n._cast(e,t);if(void 0!==e&&!1!==t.assert&&!0!==n.isType(r)){let i=pl(e),a=pl(r);throw TypeError(`The value of ${t.path||"field"} could not be cast to a value that satisfies the schema type: "${n._type}". + */ Object.defineProperty(t,"__esModule",{value:!0}),"undefined"==typeof window||"function"!=typeof MessageChannel){var n,r,i,a,o,s=null,u=null,c=function(){if(null!==s)try{var e=t.unstable_now();s(!0,e),s=null}catch(n){throw setTimeout(c,0),n}},l=Date.now();t.unstable_now=function(){return Date.now()-l},n=function(e){null!==s?setTimeout(n,0,e):(s=e,setTimeout(c,0))},r=function(e,t){u=setTimeout(e,t)},i=function(){clearTimeout(u)},a=function(){return!1},o=t.unstable_forceFrameRate=function(){}}else{var f=window.performance,d=window.Date,h=window.setTimeout,p=window.clearTimeout;if("undefined"!=typeof console){var b=window.cancelAnimationFrame;"function"!=typeof window.requestAnimationFrame&&console.error("This browser doesn't support requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills"),"function"!=typeof b&&console.error("This browser doesn't support cancelAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills")}if("object"==typeof f&&"function"==typeof f.now)t.unstable_now=function(){return f.now()};else{var m=d.now();t.unstable_now=function(){return d.now()-m}}var g=!1,v=null,y=-1,w=5,_=0;a=function(){return t.unstable_now()>=_},o=function(){},t.unstable_forceFrameRate=function(e){0>e||125M(o,n))void 0!==u&&0>M(u,o)?(e[r]=u,e[s]=n,r=s):(e[r]=o,e[a]=n,r=a);else if(void 0!==u&&0>M(u,n))e[r]=u,e[s]=n,r=s;else break a}}return t}return null}function M(e,t){var n=e.sortIndex-t.sortIndex;return 0!==n?n:e.id-t.id}var O=[],A=[],L=1,C=null,I=3,D=!1,N=!1,P=!1;function R(e){for(var t=x(A);null!==t;){if(null===t.callback)T(A);else if(t.startTime<=e)T(A),t.sortIndex=t.expirationTime,k(O,t);else break;t=x(A)}}function j(e){if(P=!1,R(e),!N){if(null!==x(O))N=!0,n(F);else{var t=x(A);null!==t&&r(j,t.startTime-e)}}}function F(e,n){N=!1,P&&(P=!1,i()),D=!0;var o=I;try{for(R(n),C=x(O);null!==C&&(!(C.expirationTime>n)||e&&!a());){var s=C.callback;if(null!==s){C.callback=null,I=C.priorityLevel;var u=s(C.expirationTime<=n);n=t.unstable_now(),"function"==typeof u?C.callback=u:C===x(O)&&T(O),R(n)}else T(O);C=x(O)}if(null!==C)var c=!0;else{var l=x(A);null!==l&&r(j,l.startTime-n),c=!1}return c}finally{C=null,I=o,D=!1}}function Y(e){switch(e){case 1:return -1;case 2:return 250;case 5:return 1073741823;case 4:return 1e4;default:return 5e3}}var B=o;t.unstable_ImmediatePriority=1,t.unstable_UserBlockingPriority=2,t.unstable_NormalPriority=3,t.unstable_IdlePriority=5,t.unstable_LowPriority=4,t.unstable_runWithPriority=function(e,t){switch(e){case 1:case 2:case 3:case 4:case 5:break;default:e=3}var n=I;I=e;try{return t()}finally{I=n}},t.unstable_next=function(e){switch(I){case 1:case 2:case 3:var t=3;break;default:t=I}var n=I;I=t;try{return e()}finally{I=n}},t.unstable_scheduleCallback=function(e,a,o){var s=t.unstable_now();if("object"==typeof o&&null!==o){var u=o.delay;u="number"==typeof u&&0s?(e.sortIndex=u,k(A,e),null===x(O)&&e===x(A)&&(P?i():P=!0,r(j,u-s))):(e.sortIndex=o,k(O,e),N||D||(N=!0,n(F))),e},t.unstable_cancelCallback=function(e){e.callback=null},t.unstable_wrapCallback=function(e){var t=I;return function(){var n=I;I=t;try{return e.apply(this,arguments)}finally{I=n}}},t.unstable_getCurrentPriorityLevel=function(){return I},t.unstable_shouldYield=function(){var e=t.unstable_now();R(e);var n=x(O);return n!==C&&null!==C&&null!==n&&null!==n.callback&&n.startTime<=e&&n.expirationTime>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function c(e,t,n){var r=t.length-1;if(r=0?(i>0&&(e.lastNeed=i-1),i):--r=0?(i>0&&(e.lastNeed=i-2),i):--r=0?(i>0&&(2===i?i=0:e.lastNeed=i-3),i):0}function l(e,t,n){if((192&t[0])!=128)return e.lastNeed=0,"�";if(e.lastNeed>1&&t.length>1){if((192&t[1])!=128)return e.lastNeed=1,"�";if(e.lastNeed>2&&t.length>2&&(192&t[2])!=128)return e.lastNeed=2,"�"}}function f(e){var t=this.lastTotal-this.lastNeed,n=l(this,e,t);return void 0!==n?n:this.lastNeed<=e.length?(e.copy(this.lastChar,t,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal)):void(e.copy(this.lastChar,t,0,e.length),this.lastNeed-=e.length)}function d(e,t){var n=c(this,e,t);if(!this.lastNeed)return e.toString("utf8",t);this.lastTotal=n;var r=e.length-(n-this.lastNeed);return e.copy(this.lastChar,0,r),e.toString("utf8",t,r)}function h(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+"�":t}function p(e,t){if((e.length-t)%2==0){var n=e.toString("utf16le",t);if(n){var r=n.charCodeAt(n.length-1);if(r>=55296&&r<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1],n.slice(0,-1)}return n}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=e[e.length-1],e.toString("utf16le",t,e.length-1)}function b(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed){var n=this.lastTotal-this.lastNeed;return t+this.lastChar.toString("utf16le",0,n)}return t}function m(e,t){var n=(e.length-t)%3;return 0===n?e.toString("base64",t):(this.lastNeed=3-n,this.lastTotal=3,1===n?this.lastChar[0]=e[e.length-1]:(this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1]),e.toString("base64",t,e.length-n))}function g(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+this.lastChar.toString("base64",0,3-this.lastNeed):t}function v(e){return e.toString(this.encoding)}function y(e){return e&&e.length?this.write(e):""}t.s=s,s.prototype.write=function(e){var t,n;if(0===e.length)return"";if(this.lastNeed){if(void 0===(t=this.fillLast(e)))return"";n=this.lastNeed,this.lastNeed=0}else n=0;return n */ var r=n(48764),i=r.Buffer;function a(e,t){for(var n in e)t[n]=e[n]}function o(e,t,n){return i(e,t,n)}i.from&&i.alloc&&i.allocUnsafe&&i.allocUnsafeSlow?e.exports=r:(a(r,t),t.Buffer=o),o.prototype=Object.create(i.prototype),a(i,o),o.from=function(e,t,n){if("number"==typeof e)throw TypeError("Argument must not be a number");return i(e,t,n)},o.alloc=function(e,t,n){if("number"!=typeof e)throw TypeError("Argument must be a number");var r=i(e);return void 0!==t?"string"==typeof n?r.fill(t,n):r.fill(t):r.fill(0),r},o.allocUnsafe=function(e){if("number"!=typeof e)throw TypeError("Argument must be a number");return i(e)},o.allocUnsafeSlow=function(e){if("number"!=typeof e)throw TypeError("Argument must be a number");return r.SlowBuffer(e)}},93379(e,t,n){"use strict";var r,i,a=function(){return void 0===r&&(r=Boolean(window&&document&&document.all&&!window.atob)),r},o=(i={},function(e){if(void 0===i[e]){var t=document.querySelector(e);if(window.HTMLIFrameElement&&t instanceof window.HTMLIFrameElement)try{t=t.contentDocument.head}catch(n){t=null}i[e]=t}return i[e]}),s=[];function u(e){for(var t=-1,n=0;nAk});var r,i,a,o,s,u,c,l=n(67294),f=n.t(l,2),d=n(39814),h=n(5977),p=n(57209),b=n(32316),m=n(95880),g=n(17051),v=n(71381),y=n(81701),w=n(3022),_=n(60323),E=n(87591),S=n(25649),k=n(28902),x=n(71426),T=n(48884),M=n(94184),O=n.n(M),A=n(37703),L=n(73935),C=function(){if("undefined"!=typeof Map)return Map;function e(e,t){var n=-1;return e.some(function(e,r){return e[0]===t&&(n=r,!0)}),n}return function(){function t(){this.__entries__=[]}return Object.defineProperty(t.prototype,"size",{get:function(){return this.__entries__.length},enumerable:!0,configurable:!0}),t.prototype.get=function(t){var n=e(this.__entries__,t),r=this.__entries__[n];return r&&r[1]},t.prototype.set=function(t,n){var r=e(this.__entries__,t);~r?this.__entries__[r][1]=n:this.__entries__.push([t,n])},t.prototype.delete=function(t){var n=this.__entries__,r=e(n,t);~r&&n.splice(r,1)},t.prototype.has=function(t){return!!~e(this.__entries__,t)},t.prototype.clear=function(){this.__entries__.splice(0)},t.prototype.forEach=function(e,t){void 0===t&&(t=null);for(var n=0,r=this.__entries__;n0},e.prototype.connect_=function(){I&&!this.connected_&&(document.addEventListener("transitionend",this.onTransitionEnd_),window.addEventListener("resize",this.refresh),Y?(this.mutationsObserver_=new MutationObserver(this.refresh),this.mutationsObserver_.observe(document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})):(document.addEventListener("DOMSubtreeModified",this.refresh),this.mutationEventsAdded_=!0),this.connected_=!0)},e.prototype.disconnect_=function(){I&&this.connected_&&(document.removeEventListener("transitionend",this.onTransitionEnd_),window.removeEventListener("resize",this.refresh),this.mutationsObserver_&&this.mutationsObserver_.disconnect(),this.mutationEventsAdded_&&document.removeEventListener("DOMSubtreeModified",this.refresh),this.mutationsObserver_=null,this.mutationEventsAdded_=!1,this.connected_=!1)},e.prototype.onTransitionEnd_=function(e){var t=e.propertyName,n=void 0===t?"":t;F.some(function(e){return!!~n.indexOf(e)})&&this.refresh()},e.getInstance=function(){return this.instance_||(this.instance_=new e),this.instance_},e.instance_=null,e}(),U=function(e,t){for(var n=0,r=Object.keys(t);n0},e}(),er="undefined"!=typeof WeakMap?new WeakMap:new C,ei=function(){function e(t){if(!(this instanceof e))throw TypeError("Cannot call a class as a function.");if(!arguments.length)throw TypeError("1 argument required, but only 0 present.");var n=B.getInstance(),r=new en(t,n,this);er.set(this,r)}return e}();["observe","unobserve","disconnect"].forEach(function(e){ei.prototype[e]=function(){var t;return(t=er.get(this))[e].apply(t,arguments)}});var ea=void 0!==D.ResizeObserver?D.ResizeObserver:ei;let eo=ea;var es=function(e){var t=[],n=null,r=function(){for(var r=arguments.length,i=Array(r),a=0;a=t||n<0||f&&r>=a}function g(){var e=eb();if(m(e))return v(e);s=setTimeout(g,b(e))}function v(e){return(s=void 0,d&&r)?h(e):(r=i=void 0,o)}function y(){void 0!==s&&clearTimeout(s),c=0,r=u=i=s=void 0}function w(){return void 0===s?o:v(eb())}function _(){var e=eb(),n=m(e);if(r=arguments,i=this,u=e,n){if(void 0===s)return p(u);if(f)return clearTimeout(s),s=setTimeout(g,t),h(u)}return void 0===s&&(s=setTimeout(g,t)),o}return t=ez(t)||0,ed(n)&&(l=!!n.leading,a=(f="maxWait"in n)?eW(ez(n.maxWait)||0,t):a,d="trailing"in n?!!n.trailing:d),_.cancel=y,_.flush=w,_}let eq=eV;var eZ="Expected a function";function eX(e,t,n){var r=!0,i=!0;if("function"!=typeof e)throw TypeError(eZ);return ed(n)&&(r="leading"in n?!!n.leading:r,i="trailing"in n?!!n.trailing:i),eq(e,t,{leading:r,maxWait:t,trailing:i})}let eJ=eX;var eQ={debounce:eq,throttle:eJ},e1=function(e){return eQ[e]},e0=function(e){return"function"==typeof e},e2=function(){return"undefined"==typeof window},e3=function(e){return e instanceof Element||e instanceof HTMLDocument};function e4(e){return(e4="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function e6(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}function e5(e,t){for(var n=0;ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&l.createElement(tG.Z,{variant:"indeterminate",classes:r}))};tK.propTypes={fetchCount:el().number.isRequired};let tV=(0,b.withStyles)(tW)(tK);var tq=n(5536);let tZ=n.p+"ba8bbf16ebf8e1d05bef.svg";function tX(){return(tX=Object.assign||function(e){for(var t=1;t120){for(var d=Math.floor(u/80),h=u%80,p=[],b=0;b0},name:{enumerable:!1},nodes:{enumerable:!1},source:{enumerable:!1},positions:{enumerable:!1},originalError:{enumerable:!1}}),null!=s&&s.stack)?(Object.defineProperty(nf(b),"stack",{value:s.stack,writable:!0,configurable:!0}),nl(b)):(Error.captureStackTrace?Error.captureStackTrace(nf(b),n):Object.defineProperty(nf(b),"stack",{value:Error().stack,writable:!0,configurable:!0}),b)}return ns(n,[{key:"toString",value:function(){return nw(this)}},{key:t4.YF,get:function(){return"Object"}}]),n}(nd(Error));function ny(e){return void 0===e||0===e.length?void 0:e}function nw(e){var t=e.message;if(e.nodes)for(var n=0,r=e.nodes;n",EOF:"",BANG:"!",DOLLAR:"$",AMP:"&",PAREN_L:"(",PAREN_R:")",SPREAD:"...",COLON:":",EQUALS:"=",AT:"@",BRACKET_L:"[",BRACKET_R:"]",BRACE_L:"{",PIPE:"|",BRACE_R:"}",NAME:"Name",INT:"Int",FLOAT:"Float",STRING:"String",BLOCK_STRING:"BlockString",COMMENT:"Comment"}),nx=n(10143),nT=Object.freeze({QUERY:"QUERY",MUTATION:"MUTATION",SUBSCRIPTION:"SUBSCRIPTION",FIELD:"FIELD",FRAGMENT_DEFINITION:"FRAGMENT_DEFINITION",FRAGMENT_SPREAD:"FRAGMENT_SPREAD",INLINE_FRAGMENT:"INLINE_FRAGMENT",VARIABLE_DEFINITION:"VARIABLE_DEFINITION",SCHEMA:"SCHEMA",SCALAR:"SCALAR",OBJECT:"OBJECT",FIELD_DEFINITION:"FIELD_DEFINITION",ARGUMENT_DEFINITION:"ARGUMENT_DEFINITION",INTERFACE:"INTERFACE",UNION:"UNION",ENUM:"ENUM",ENUM_VALUE:"ENUM_VALUE",INPUT_OBJECT:"INPUT_OBJECT",INPUT_FIELD_DEFINITION:"INPUT_FIELD_DEFINITION"}),nM=n(87392),nO=function(){function e(e){var t=new nS.WU(nk.SOF,0,0,0,0,null);this.source=e,this.lastToken=t,this.token=t,this.line=1,this.lineStart=0}var t=e.prototype;return t.advance=function(){return this.lastToken=this.token,this.token=this.lookahead()},t.lookahead=function(){var e,t=this.token;if(t.kind!==nk.EOF)do t=null!==(e=t.next)&&void 0!==e?e:t.next=nC(this,t);while(t.kind===nk.COMMENT)return t},e}();function nA(e){return e===nk.BANG||e===nk.DOLLAR||e===nk.AMP||e===nk.PAREN_L||e===nk.PAREN_R||e===nk.SPREAD||e===nk.COLON||e===nk.EQUALS||e===nk.AT||e===nk.BRACKET_L||e===nk.BRACKET_R||e===nk.BRACE_L||e===nk.PIPE||e===nk.BRACE_R}function nL(e){return isNaN(e)?nk.EOF:e<127?JSON.stringify(String.fromCharCode(e)):'"\\u'.concat(("00"+e.toString(16).toUpperCase()).slice(-4),'"')}function nC(e,t){for(var n=e.source,r=n.body,i=r.length,a=t.end;a31||9===a))return new nS.WU(nk.COMMENT,t,s,n,r,i,o.slice(t+1,s))}function nN(e,t,n,r,i,a){var o=e.body,s=n,u=t,c=!1;if(45===s&&(s=o.charCodeAt(++u)),48===s){if((s=o.charCodeAt(++u))>=48&&s<=57)throw n_(e,u,"Invalid number, unexpected digit after 0: ".concat(nL(s),"."))}else u=nP(e,u,s),s=o.charCodeAt(u);if(46===s&&(c=!0,s=o.charCodeAt(++u),u=nP(e,u,s),s=o.charCodeAt(u)),(69===s||101===s)&&(c=!0,(43===(s=o.charCodeAt(++u))||45===s)&&(s=o.charCodeAt(++u)),u=nP(e,u,s),s=o.charCodeAt(u)),46===s||nU(s))throw n_(e,u,"Invalid number, expected digit but got: ".concat(nL(s),"."));return new nS.WU(c?nk.FLOAT:nk.INT,t,u,r,i,a,o.slice(t,u))}function nP(e,t,n){var r=e.body,i=t,a=n;if(a>=48&&a<=57){do a=r.charCodeAt(++i);while(a>=48&&a<=57)return i}throw n_(e,i,"Invalid number, expected digit but got: ".concat(nL(a),"."))}function nR(e,t,n,r,i){for(var a=e.body,o=t+1,s=o,u=0,c="";o=48&&e<=57?e-48:e>=65&&e<=70?e-55:e>=97&&e<=102?e-87:-1}function nB(e,t,n,r,i){for(var a=e.body,o=a.length,s=t+1,u=0;s!==o&&!isNaN(u=a.charCodeAt(s))&&(95===u||u>=48&&u<=57||u>=65&&u<=90||u>=97&&u<=122);)++s;return new nS.WU(nk.NAME,t,s,n,r,i,a.slice(t,s))}function nU(e){return 95===e||e>=65&&e<=90||e>=97&&e<=122}function nH(e,t){return new n$(e,t).parseDocument()}var n$=function(){function e(e,t){var n=(0,nx.T)(e)?e:new nx.H(e);this._lexer=new nO(n),this._options=t}var t=e.prototype;return t.parseName=function(){var e=this.expectToken(nk.NAME);return{kind:nE.h.NAME,value:e.value,loc:this.loc(e)}},t.parseDocument=function(){var e=this._lexer.token;return{kind:nE.h.DOCUMENT,definitions:this.many(nk.SOF,this.parseDefinition,nk.EOF),loc:this.loc(e)}},t.parseDefinition=function(){if(this.peek(nk.NAME))switch(this._lexer.token.value){case"query":case"mutation":case"subscription":return this.parseOperationDefinition();case"fragment":return this.parseFragmentDefinition();case"schema":case"scalar":case"type":case"interface":case"union":case"enum":case"input":case"directive":return this.parseTypeSystemDefinition();case"extend":return this.parseTypeSystemExtension()}else if(this.peek(nk.BRACE_L))return this.parseOperationDefinition();else if(this.peekDescription())return this.parseTypeSystemDefinition();throw this.unexpected()},t.parseOperationDefinition=function(){var e,t=this._lexer.token;if(this.peek(nk.BRACE_L))return{kind:nE.h.OPERATION_DEFINITION,operation:"query",name:void 0,variableDefinitions:[],directives:[],selectionSet:this.parseSelectionSet(),loc:this.loc(t)};var n=this.parseOperationType();return this.peek(nk.NAME)&&(e=this.parseName()),{kind:nE.h.OPERATION_DEFINITION,operation:n,name:e,variableDefinitions:this.parseVariableDefinitions(),directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(t)}},t.parseOperationType=function(){var e=this.expectToken(nk.NAME);switch(e.value){case"query":return"query";case"mutation":return"mutation";case"subscription":return"subscription"}throw this.unexpected(e)},t.parseVariableDefinitions=function(){return this.optionalMany(nk.PAREN_L,this.parseVariableDefinition,nk.PAREN_R)},t.parseVariableDefinition=function(){var e=this._lexer.token;return{kind:nE.h.VARIABLE_DEFINITION,variable:this.parseVariable(),type:(this.expectToken(nk.COLON),this.parseTypeReference()),defaultValue:this.expectOptionalToken(nk.EQUALS)?this.parseValueLiteral(!0):void 0,directives:this.parseDirectives(!0),loc:this.loc(e)}},t.parseVariable=function(){var e=this._lexer.token;return this.expectToken(nk.DOLLAR),{kind:nE.h.VARIABLE,name:this.parseName(),loc:this.loc(e)}},t.parseSelectionSet=function(){var e=this._lexer.token;return{kind:nE.h.SELECTION_SET,selections:this.many(nk.BRACE_L,this.parseSelection,nk.BRACE_R),loc:this.loc(e)}},t.parseSelection=function(){return this.peek(nk.SPREAD)?this.parseFragment():this.parseField()},t.parseField=function(){var e,t,n=this._lexer.token,r=this.parseName();return this.expectOptionalToken(nk.COLON)?(e=r,t=this.parseName()):t=r,{kind:nE.h.FIELD,alias:e,name:t,arguments:this.parseArguments(!1),directives:this.parseDirectives(!1),selectionSet:this.peek(nk.BRACE_L)?this.parseSelectionSet():void 0,loc:this.loc(n)}},t.parseArguments=function(e){var t=e?this.parseConstArgument:this.parseArgument;return this.optionalMany(nk.PAREN_L,t,nk.PAREN_R)},t.parseArgument=function(){var e=this._lexer.token,t=this.parseName();return this.expectToken(nk.COLON),{kind:nE.h.ARGUMENT,name:t,value:this.parseValueLiteral(!1),loc:this.loc(e)}},t.parseConstArgument=function(){var e=this._lexer.token;return{kind:nE.h.ARGUMENT,name:this.parseName(),value:(this.expectToken(nk.COLON),this.parseValueLiteral(!0)),loc:this.loc(e)}},t.parseFragment=function(){var e=this._lexer.token;this.expectToken(nk.SPREAD);var t=this.expectOptionalKeyword("on");return!t&&this.peek(nk.NAME)?{kind:nE.h.FRAGMENT_SPREAD,name:this.parseFragmentName(),directives:this.parseDirectives(!1),loc:this.loc(e)}:{kind:nE.h.INLINE_FRAGMENT,typeCondition:t?this.parseNamedType():void 0,directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(e)}},t.parseFragmentDefinition=function(){var e,t=this._lexer.token;return(this.expectKeyword("fragment"),(null===(e=this._options)||void 0===e?void 0:e.experimentalFragmentVariables)===!0)?{kind:nE.h.FRAGMENT_DEFINITION,name:this.parseFragmentName(),variableDefinitions:this.parseVariableDefinitions(),typeCondition:(this.expectKeyword("on"),this.parseNamedType()),directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(t)}:{kind:nE.h.FRAGMENT_DEFINITION,name:this.parseFragmentName(),typeCondition:(this.expectKeyword("on"),this.parseNamedType()),directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(t)}},t.parseFragmentName=function(){if("on"===this._lexer.token.value)throw this.unexpected();return this.parseName()},t.parseValueLiteral=function(e){var t=this._lexer.token;switch(t.kind){case nk.BRACKET_L:return this.parseList(e);case nk.BRACE_L:return this.parseObject(e);case nk.INT:return this._lexer.advance(),{kind:nE.h.INT,value:t.value,loc:this.loc(t)};case nk.FLOAT:return this._lexer.advance(),{kind:nE.h.FLOAT,value:t.value,loc:this.loc(t)};case nk.STRING:case nk.BLOCK_STRING:return this.parseStringLiteral();case nk.NAME:switch(this._lexer.advance(),t.value){case"true":return{kind:nE.h.BOOLEAN,value:!0,loc:this.loc(t)};case"false":return{kind:nE.h.BOOLEAN,value:!1,loc:this.loc(t)};case"null":return{kind:nE.h.NULL,loc:this.loc(t)};default:return{kind:nE.h.ENUM,value:t.value,loc:this.loc(t)}}case nk.DOLLAR:if(!e)return this.parseVariable()}throw this.unexpected()},t.parseStringLiteral=function(){var e=this._lexer.token;return this._lexer.advance(),{kind:nE.h.STRING,value:e.value,block:e.kind===nk.BLOCK_STRING,loc:this.loc(e)}},t.parseList=function(e){var t=this,n=this._lexer.token,r=function(){return t.parseValueLiteral(e)};return{kind:nE.h.LIST,values:this.any(nk.BRACKET_L,r,nk.BRACKET_R),loc:this.loc(n)}},t.parseObject=function(e){var t=this,n=this._lexer.token,r=function(){return t.parseObjectField(e)};return{kind:nE.h.OBJECT,fields:this.any(nk.BRACE_L,r,nk.BRACE_R),loc:this.loc(n)}},t.parseObjectField=function(e){var t=this._lexer.token,n=this.parseName();return this.expectToken(nk.COLON),{kind:nE.h.OBJECT_FIELD,name:n,value:this.parseValueLiteral(e),loc:this.loc(t)}},t.parseDirectives=function(e){for(var t=[];this.peek(nk.AT);)t.push(this.parseDirective(e));return t},t.parseDirective=function(e){var t=this._lexer.token;return this.expectToken(nk.AT),{kind:nE.h.DIRECTIVE,name:this.parseName(),arguments:this.parseArguments(e),loc:this.loc(t)}},t.parseTypeReference=function(){var e,t=this._lexer.token;return(this.expectOptionalToken(nk.BRACKET_L)?(e=this.parseTypeReference(),this.expectToken(nk.BRACKET_R),e={kind:nE.h.LIST_TYPE,type:e,loc:this.loc(t)}):e=this.parseNamedType(),this.expectOptionalToken(nk.BANG))?{kind:nE.h.NON_NULL_TYPE,type:e,loc:this.loc(t)}:e},t.parseNamedType=function(){var e=this._lexer.token;return{kind:nE.h.NAMED_TYPE,name:this.parseName(),loc:this.loc(e)}},t.parseTypeSystemDefinition=function(){var e=this.peekDescription()?this._lexer.lookahead():this._lexer.token;if(e.kind===nk.NAME)switch(e.value){case"schema":return this.parseSchemaDefinition();case"scalar":return this.parseScalarTypeDefinition();case"type":return this.parseObjectTypeDefinition();case"interface":return this.parseInterfaceTypeDefinition();case"union":return this.parseUnionTypeDefinition();case"enum":return this.parseEnumTypeDefinition();case"input":return this.parseInputObjectTypeDefinition();case"directive":return this.parseDirectiveDefinition()}throw this.unexpected(e)},t.peekDescription=function(){return this.peek(nk.STRING)||this.peek(nk.BLOCK_STRING)},t.parseDescription=function(){if(this.peekDescription())return this.parseStringLiteral()},t.parseSchemaDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("schema");var n=this.parseDirectives(!0),r=this.many(nk.BRACE_L,this.parseOperationTypeDefinition,nk.BRACE_R);return{kind:nE.h.SCHEMA_DEFINITION,description:t,directives:n,operationTypes:r,loc:this.loc(e)}},t.parseOperationTypeDefinition=function(){var e=this._lexer.token,t=this.parseOperationType();this.expectToken(nk.COLON);var n=this.parseNamedType();return{kind:nE.h.OPERATION_TYPE_DEFINITION,operation:t,type:n,loc:this.loc(e)}},t.parseScalarTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("scalar");var n=this.parseName(),r=this.parseDirectives(!0);return{kind:nE.h.SCALAR_TYPE_DEFINITION,description:t,name:n,directives:r,loc:this.loc(e)}},t.parseObjectTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("type");var n=this.parseName(),r=this.parseImplementsInterfaces(),i=this.parseDirectives(!0),a=this.parseFieldsDefinition();return{kind:nE.h.OBJECT_TYPE_DEFINITION,description:t,name:n,interfaces:r,directives:i,fields:a,loc:this.loc(e)}},t.parseImplementsInterfaces=function(){var e;if(!this.expectOptionalKeyword("implements"))return[];if((null===(e=this._options)||void 0===e?void 0:e.allowLegacySDLImplementsInterfaces)===!0){var t=[];this.expectOptionalToken(nk.AMP);do t.push(this.parseNamedType());while(this.expectOptionalToken(nk.AMP)||this.peek(nk.NAME))return t}return this.delimitedMany(nk.AMP,this.parseNamedType)},t.parseFieldsDefinition=function(){var e;return(null===(e=this._options)||void 0===e?void 0:e.allowLegacySDLEmptyFields)===!0&&this.peek(nk.BRACE_L)&&this._lexer.lookahead().kind===nk.BRACE_R?(this._lexer.advance(),this._lexer.advance(),[]):this.optionalMany(nk.BRACE_L,this.parseFieldDefinition,nk.BRACE_R)},t.parseFieldDefinition=function(){var e=this._lexer.token,t=this.parseDescription(),n=this.parseName(),r=this.parseArgumentDefs();this.expectToken(nk.COLON);var i=this.parseTypeReference(),a=this.parseDirectives(!0);return{kind:nE.h.FIELD_DEFINITION,description:t,name:n,arguments:r,type:i,directives:a,loc:this.loc(e)}},t.parseArgumentDefs=function(){return this.optionalMany(nk.PAREN_L,this.parseInputValueDef,nk.PAREN_R)},t.parseInputValueDef=function(){var e,t=this._lexer.token,n=this.parseDescription(),r=this.parseName();this.expectToken(nk.COLON);var i=this.parseTypeReference();this.expectOptionalToken(nk.EQUALS)&&(e=this.parseValueLiteral(!0));var a=this.parseDirectives(!0);return{kind:nE.h.INPUT_VALUE_DEFINITION,description:n,name:r,type:i,defaultValue:e,directives:a,loc:this.loc(t)}},t.parseInterfaceTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("interface");var n=this.parseName(),r=this.parseImplementsInterfaces(),i=this.parseDirectives(!0),a=this.parseFieldsDefinition();return{kind:nE.h.INTERFACE_TYPE_DEFINITION,description:t,name:n,interfaces:r,directives:i,fields:a,loc:this.loc(e)}},t.parseUnionTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("union");var n=this.parseName(),r=this.parseDirectives(!0),i=this.parseUnionMemberTypes();return{kind:nE.h.UNION_TYPE_DEFINITION,description:t,name:n,directives:r,types:i,loc:this.loc(e)}},t.parseUnionMemberTypes=function(){return this.expectOptionalToken(nk.EQUALS)?this.delimitedMany(nk.PIPE,this.parseNamedType):[]},t.parseEnumTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("enum");var n=this.parseName(),r=this.parseDirectives(!0),i=this.parseEnumValuesDefinition();return{kind:nE.h.ENUM_TYPE_DEFINITION,description:t,name:n,directives:r,values:i,loc:this.loc(e)}},t.parseEnumValuesDefinition=function(){return this.optionalMany(nk.BRACE_L,this.parseEnumValueDefinition,nk.BRACE_R)},t.parseEnumValueDefinition=function(){var e=this._lexer.token,t=this.parseDescription(),n=this.parseName(),r=this.parseDirectives(!0);return{kind:nE.h.ENUM_VALUE_DEFINITION,description:t,name:n,directives:r,loc:this.loc(e)}},t.parseInputObjectTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("input");var n=this.parseName(),r=this.parseDirectives(!0),i=this.parseInputFieldsDefinition();return{kind:nE.h.INPUT_OBJECT_TYPE_DEFINITION,description:t,name:n,directives:r,fields:i,loc:this.loc(e)}},t.parseInputFieldsDefinition=function(){return this.optionalMany(nk.BRACE_L,this.parseInputValueDef,nk.BRACE_R)},t.parseTypeSystemExtension=function(){var e=this._lexer.lookahead();if(e.kind===nk.NAME)switch(e.value){case"schema":return this.parseSchemaExtension();case"scalar":return this.parseScalarTypeExtension();case"type":return this.parseObjectTypeExtension();case"interface":return this.parseInterfaceTypeExtension();case"union":return this.parseUnionTypeExtension();case"enum":return this.parseEnumTypeExtension();case"input":return this.parseInputObjectTypeExtension()}throw this.unexpected(e)},t.parseSchemaExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("schema");var t=this.parseDirectives(!0),n=this.optionalMany(nk.BRACE_L,this.parseOperationTypeDefinition,nk.BRACE_R);if(0===t.length&&0===n.length)throw this.unexpected();return{kind:nE.h.SCHEMA_EXTENSION,directives:t,operationTypes:n,loc:this.loc(e)}},t.parseScalarTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("scalar");var t=this.parseName(),n=this.parseDirectives(!0);if(0===n.length)throw this.unexpected();return{kind:nE.h.SCALAR_TYPE_EXTENSION,name:t,directives:n,loc:this.loc(e)}},t.parseObjectTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("type");var t=this.parseName(),n=this.parseImplementsInterfaces(),r=this.parseDirectives(!0),i=this.parseFieldsDefinition();if(0===n.length&&0===r.length&&0===i.length)throw this.unexpected();return{kind:nE.h.OBJECT_TYPE_EXTENSION,name:t,interfaces:n,directives:r,fields:i,loc:this.loc(e)}},t.parseInterfaceTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("interface");var t=this.parseName(),n=this.parseImplementsInterfaces(),r=this.parseDirectives(!0),i=this.parseFieldsDefinition();if(0===n.length&&0===r.length&&0===i.length)throw this.unexpected();return{kind:nE.h.INTERFACE_TYPE_EXTENSION,name:t,interfaces:n,directives:r,fields:i,loc:this.loc(e)}},t.parseUnionTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("union");var t=this.parseName(),n=this.parseDirectives(!0),r=this.parseUnionMemberTypes();if(0===n.length&&0===r.length)throw this.unexpected();return{kind:nE.h.UNION_TYPE_EXTENSION,name:t,directives:n,types:r,loc:this.loc(e)}},t.parseEnumTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("enum");var t=this.parseName(),n=this.parseDirectives(!0),r=this.parseEnumValuesDefinition();if(0===n.length&&0===r.length)throw this.unexpected();return{kind:nE.h.ENUM_TYPE_EXTENSION,name:t,directives:n,values:r,loc:this.loc(e)}},t.parseInputObjectTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("input");var t=this.parseName(),n=this.parseDirectives(!0),r=this.parseInputFieldsDefinition();if(0===n.length&&0===r.length)throw this.unexpected();return{kind:nE.h.INPUT_OBJECT_TYPE_EXTENSION,name:t,directives:n,fields:r,loc:this.loc(e)}},t.parseDirectiveDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("directive"),this.expectToken(nk.AT);var n=this.parseName(),r=this.parseArgumentDefs(),i=this.expectOptionalKeyword("repeatable");this.expectKeyword("on");var a=this.parseDirectiveLocations();return{kind:nE.h.DIRECTIVE_DEFINITION,description:t,name:n,arguments:r,repeatable:i,locations:a,loc:this.loc(e)}},t.parseDirectiveLocations=function(){return this.delimitedMany(nk.PIPE,this.parseDirectiveLocation)},t.parseDirectiveLocation=function(){var e=this._lexer.token,t=this.parseName();if(void 0!==nT[t.value])return t;throw this.unexpected(e)},t.loc=function(e){var t;if((null===(t=this._options)||void 0===t?void 0:t.noLocation)!==!0)return new nS.Ye(e,this._lexer.lastToken,this._lexer.source)},t.peek=function(e){return this._lexer.token.kind===e},t.expectToken=function(e){var t=this._lexer.token;if(t.kind===e)return this._lexer.advance(),t;throw n_(this._lexer.source,t.start,"Expected ".concat(nG(e),", found ").concat(nz(t),"."))},t.expectOptionalToken=function(e){var t=this._lexer.token;if(t.kind===e)return this._lexer.advance(),t},t.expectKeyword=function(e){var t=this._lexer.token;if(t.kind===nk.NAME&&t.value===e)this._lexer.advance();else throw n_(this._lexer.source,t.start,'Expected "'.concat(e,'", found ').concat(nz(t),"."))},t.expectOptionalKeyword=function(e){var t=this._lexer.token;return t.kind===nk.NAME&&t.value===e&&(this._lexer.advance(),!0)},t.unexpected=function(e){var t=null!=e?e:this._lexer.token;return n_(this._lexer.source,t.start,"Unexpected ".concat(nz(t),"."))},t.any=function(e,t,n){this.expectToken(e);for(var r=[];!this.expectOptionalToken(n);)r.push(t.call(this));return r},t.optionalMany=function(e,t,n){if(this.expectOptionalToken(e)){var r=[];do r.push(t.call(this));while(!this.expectOptionalToken(n))return r}return[]},t.many=function(e,t,n){this.expectToken(e);var r=[];do r.push(t.call(this));while(!this.expectOptionalToken(n))return r},t.delimitedMany=function(e,t){this.expectOptionalToken(e);var n=[];do n.push(t.call(this));while(this.expectOptionalToken(e))return n},e}();function nz(e){var t=e.value;return nG(e.kind)+(null!=t?' "'.concat(t,'"'):"")}function nG(e){return nA(e)?'"'.concat(e,'"'):e}var nW=new Map,nK=new Map,nV=!0,nq=!1;function nZ(e){return e.replace(/[\s,]+/g," ").trim()}function nX(e){return nZ(e.source.body.substring(e.start,e.end))}function nJ(e){var t=new Set,n=[];return e.definitions.forEach(function(e){if("FragmentDefinition"===e.kind){var r=e.name.value,i=nX(e.loc),a=nK.get(r);a&&!a.has(i)?nV&&console.warn("Warning: fragment with name "+r+" already exists.\ngraphql-tag enforces all fragment names across your application to be unique; read more about\nthis in the docs: http://dev.apollodata.com/core/fragments.html#unique-names"):a||nK.set(r,a=new Set),a.add(i),t.has(i)||(t.add(i),n.push(e))}else n.push(e)}),(0,t0.pi)((0,t0.pi)({},e),{definitions:n})}function nQ(e){var t=new Set(e.definitions);t.forEach(function(e){e.loc&&delete e.loc,Object.keys(e).forEach(function(n){var r=e[n];r&&"object"==typeof r&&t.add(r)})});var n=e.loc;return n&&(delete n.startToken,delete n.endToken),e}function n1(e){var t=nZ(e);if(!nW.has(t)){var n=nH(e,{experimentalFragmentVariables:nq,allowLegacyFragmentVariables:nq});if(!n||"Document"!==n.kind)throw Error("Not a valid GraphQL document.");nW.set(t,nQ(nJ(n)))}return nW.get(t)}function n0(e){for(var t=[],n=1;n, or pass an ApolloClient instance in via options.'):(0,n9.kG)(!!n,32),n}var rp=n(10542),rb=n(53712),rm=n(21436),rg=Object.prototype.hasOwnProperty;function rv(e,t){return void 0===t&&(t=Object.create(null)),ry(rh(t.client),e).useQuery(t)}function ry(e,t){var n=(0,l.useRef)();n.current&&e===n.current.client&&t===n.current.query||(n.current=new rw(e,t,n.current));var r=n.current,i=(0,l.useState)(0),a=(i[0],i[1]);return r.forceUpdate=function(){a(function(e){return e+1})},r}var rw=function(){function e(e,t,n){this.client=e,this.query=t,this.ssrDisabledResult=(0,rp.J)({loading:!0,data:void 0,error:void 0,networkStatus:ru.I.loading}),this.skipStandbyResult=(0,rp.J)({loading:!1,data:void 0,error:void 0,networkStatus:ru.I.ready}),this.toQueryResultCache=new(n7.mr?WeakMap:Map),rd(t,r.Query);var i=n&&n.result,a=i&&i.data;a&&(this.previousData=a)}return e.prototype.forceUpdate=function(){__DEV__&&n9.kG.warn("Calling default no-op implementation of InternalState#forceUpdate")},e.prototype.executeQuery=function(e){var t,n=this;e.query&&Object.assign(this,{query:e.query}),this.watchQueryOptions=this.createWatchQueryOptions(this.queryHookOptions=e);var r=this.observable.reobserveAsConcast(this.getObsQueryOptions());return this.previousData=(null===(t=this.result)||void 0===t?void 0:t.data)||this.previousData,this.result=void 0,this.forceUpdate(),new Promise(function(e){var t;r.subscribe({next:function(e){t=e},error:function(){e(n.toQueryResult(n.observable.getCurrentResult()))},complete:function(){e(n.toQueryResult(t))}})})},e.prototype.useQuery=function(e){var t=this;this.renderPromises=(0,l.useContext)((0,ro.K)()).renderPromises,this.useOptions(e);var n=this.useObservableQuery(),r=rt((0,l.useCallback)(function(){if(t.renderPromises)return function(){};var e=function(){var e=t.result,r=n.getCurrentResult();!(e&&e.loading===r.loading&&e.networkStatus===r.networkStatus&&(0,ri.D)(e.data,r.data))&&t.setResult(r)},r=function(a){var o=n.last;i.unsubscribe();try{n.resetLastResults(),i=n.subscribe(e,r)}finally{n.last=o}if(!rg.call(a,"graphQLErrors"))throw a;var s=t.result;(!s||s&&s.loading||!(0,ri.D)(a,s.error))&&t.setResult({data:s&&s.data,error:a,loading:!1,networkStatus:ru.I.error})},i=n.subscribe(e,r);return function(){return setTimeout(function(){return i.unsubscribe()})}},[n,this.renderPromises,this.client.disableNetworkFetches,]),function(){return t.getCurrentResult()},function(){return t.getCurrentResult()});return this.unsafeHandlePartialRefetch(r),this.toQueryResult(r)},e.prototype.useOptions=function(t){var n,r=this.createWatchQueryOptions(this.queryHookOptions=t),i=this.watchQueryOptions;!(0,ri.D)(r,i)&&(this.watchQueryOptions=r,i&&this.observable&&(this.observable.reobserve(this.getObsQueryOptions()),this.previousData=(null===(n=this.result)||void 0===n?void 0:n.data)||this.previousData,this.result=void 0)),this.onCompleted=t.onCompleted||e.prototype.onCompleted,this.onError=t.onError||e.prototype.onError,(this.renderPromises||this.client.disableNetworkFetches)&&!1===this.queryHookOptions.ssr&&!this.queryHookOptions.skip?this.result=this.ssrDisabledResult:this.queryHookOptions.skip||"standby"===this.watchQueryOptions.fetchPolicy?this.result=this.skipStandbyResult:(this.result===this.ssrDisabledResult||this.result===this.skipStandbyResult)&&(this.result=void 0)},e.prototype.getObsQueryOptions=function(){var e=[],t=this.client.defaultOptions.watchQuery;return t&&e.push(t),this.queryHookOptions.defaultOptions&&e.push(this.queryHookOptions.defaultOptions),e.push((0,rb.o)(this.observable&&this.observable.options,this.watchQueryOptions)),e.reduce(ra.J)},e.prototype.createWatchQueryOptions=function(e){void 0===e&&(e={});var t,n=e.skip,r=Object.assign((e.ssr,e.onCompleted,e.onError,e.defaultOptions,(0,t0._T)(e,["skip","ssr","onCompleted","onError","defaultOptions"])),{query:this.query});if(this.renderPromises&&("network-only"===r.fetchPolicy||"cache-and-network"===r.fetchPolicy)&&(r.fetchPolicy="cache-first"),r.variables||(r.variables={}),n){var i=r.fetchPolicy,a=void 0===i?this.getDefaultFetchPolicy():i,o=r.initialFetchPolicy;Object.assign(r,{initialFetchPolicy:void 0===o?a:o,fetchPolicy:"standby"})}else r.fetchPolicy||(r.fetchPolicy=(null===(t=this.observable)||void 0===t?void 0:t.options.initialFetchPolicy)||this.getDefaultFetchPolicy());return r},e.prototype.getDefaultFetchPolicy=function(){var e,t;return(null===(e=this.queryHookOptions.defaultOptions)||void 0===e?void 0:e.fetchPolicy)||(null===(t=this.client.defaultOptions.watchQuery)||void 0===t?void 0:t.fetchPolicy)||"cache-first"},e.prototype.onCompleted=function(e){},e.prototype.onError=function(e){},e.prototype.useObservableQuery=function(){var e=this.observable=this.renderPromises&&this.renderPromises.getSSRObservable(this.watchQueryOptions)||this.observable||this.client.watchQuery(this.getObsQueryOptions());this.obsQueryFields=(0,l.useMemo)(function(){return{refetch:e.refetch.bind(e),reobserve:e.reobserve.bind(e),fetchMore:e.fetchMore.bind(e),updateQuery:e.updateQuery.bind(e),startPolling:e.startPolling.bind(e),stopPolling:e.stopPolling.bind(e),subscribeToMore:e.subscribeToMore.bind(e)}},[e]);var t=!(!1===this.queryHookOptions.ssr||this.queryHookOptions.skip);return this.renderPromises&&t&&(this.renderPromises.registerSSRObservable(e),e.getCurrentResult().loading&&this.renderPromises.addObservableQueryPromise(e)),e},e.prototype.setResult=function(e){var t=this.result;t&&t.data&&(this.previousData=t.data),this.result=e,this.forceUpdate(),this.handleErrorOrCompleted(e)},e.prototype.handleErrorOrCompleted=function(e){var t=this;if(!e.loading){var n=this.toApolloError(e);Promise.resolve().then(function(){n?t.onError(n):e.data&&t.onCompleted(e.data)}).catch(function(e){__DEV__&&n9.kG.warn(e)})}},e.prototype.toApolloError=function(e){return(0,rm.O)(e.errors)?new rs.cA({graphQLErrors:e.errors}):e.error},e.prototype.getCurrentResult=function(){return this.result||this.handleErrorOrCompleted(this.result=this.observable.getCurrentResult()),this.result},e.prototype.toQueryResult=function(e){var t=this.toQueryResultCache.get(e);if(t)return t;var n=e.data,r=(e.partial,(0,t0._T)(e,["data","partial"]));return this.toQueryResultCache.set(e,t=(0,t0.pi)((0,t0.pi)((0,t0.pi)({data:n},r),this.obsQueryFields),{client:this.client,observable:this.observable,variables:this.observable.variables,called:!this.queryHookOptions.skip,previousData:this.previousData})),!t.error&&(0,rm.O)(e.errors)&&(t.error=new rs.cA({graphQLErrors:e.errors})),t},e.prototype.unsafeHandlePartialRefetch=function(e){e.partial&&this.queryHookOptions.partialRefetch&&!e.loading&&(!e.data||0===Object.keys(e.data).length)&&"cache-only"!==this.observable.options.fetchPolicy&&(Object.assign(e,{loading:!0,networkStatus:ru.I.refetch}),this.observable.refetch())},e}();function r_(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&void 0!==arguments[0]?arguments[0]:{};return rv(iH,e)},iz=function(){var e=ij(),t=parseInt(e.get("page")||"1",10),n=parseInt(e.get("per")||"50",10),r=i$({variables:{offset:(t-1)*n,limit:n},fetchPolicy:"network-only"}),i=r.data,a=r.loading,o=r.error;return a?l.createElement(iR,null):o?l.createElement(iD,{error:o}):i?l.createElement(iI,{chains:i.chains.results,page:t,pageSize:n,total:i.chains.metadata.total}):null},iG=n(67932),iW=n(8126),iK="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};function iV(e){if(iq())return Intl.DateTimeFormat.supportedLocalesOf(e)[0]}function iq(){return("undefined"==typeof Intl?"undefined":iK(Intl))==="object"&&"function"==typeof Intl.DateTimeFormat}var iZ="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},iX=function(){function e(e,t){for(var n=0;n=i.length)break;s=i[o++]}else{if((o=i.next()).done)break;s=o.value}var s,u=s;if((void 0===e?"undefined":iZ(e))!=="object")return;e=e[u]}return e}},{key:"put",value:function(){for(var e=arguments.length,t=Array(e),n=0;n=o.length)break;c=o[u++]}else{if((u=o.next()).done)break;c=u.value}var c,l=c;"object"!==iZ(a[l])&&(a[l]={}),a=a[l]}return a[i]=r}}]),e}();let i1=iQ;var i0=new i1;function i2(e,t){if(!iq())return function(e){return e.toString()};var n=i4(e),r=JSON.stringify(t),i=i0.get(String(n),r)||i0.put(String(n),r,new Intl.DateTimeFormat(n,t));return function(e){return i.format(e)}}var i3={};function i4(e){var t=e.toString();return i3[t]?i3[t]:i3[t]=iV(e)}var i6="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};function i5(e){return i8(e)?e:new Date(e)}function i8(e){return e instanceof Date||i9(e)}function i9(e){return(void 0===e?"undefined":i6(e))==="object"&&"function"==typeof e.getTime}var i7=n(54087),ae=n.n(i7);function at(e,t){if(0===e.length)return 0;for(var n=0,r=e.length-1,i=void 0;n<=r;){var a=t(e[i=Math.floor((r+n)/2)]);if(0===a)return i;if(a<0){if((n=i+1)>r)return n}else if((r=i-1)=t.nextUpdateTime)aa(t,this.instances);else break}},scheduleNextTick:function(){var e=this;this.scheduledTick=ae()(function(){e.tick(),e.scheduleNextTick()})},start:function(){this.scheduleNextTick()},stop:function(){ae().cancel(this.scheduledTick)}};function ai(e){var t=an(e.getNextValue(),2),n=t[0],r=t[1];e.setValue(n),e.nextUpdateTime=r}function aa(e,t){ai(e),as(t,e),ao(t,e)}function ao(e,t){var n=au(e,t);e.splice(n,0,t)}function as(e,t){var n=e.indexOf(t);e.splice(n,1)}function au(e,t){var n=t.nextUpdateTime;return at(e,function(e){return e.nextUpdateTime===n?0:e.nextUpdateTime>n?1:-1})}var ac=(0,ec.oneOfType)([(0,ec.shape)({minTime:ec.number,formatAs:ec.string.isRequired}),(0,ec.shape)({test:ec.func,formatAs:ec.string.isRequired}),(0,ec.shape)({minTime:ec.number,format:ec.func.isRequired}),(0,ec.shape)({test:ec.func,format:ec.func.isRequired})]),al=(0,ec.oneOfType)([ec.string,(0,ec.shape)({steps:(0,ec.arrayOf)(ac).isRequired,labels:(0,ec.oneOfType)([ec.string,(0,ec.arrayOf)(ec.string)]).isRequired,round:ec.string})]),af=Object.assign||function(e){for(var t=1;t=0)&&Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n}function ap(e){var t=e.date,n=e.future,r=e.timeStyle,i=e.round,a=e.minTimeLeft,o=e.tooltip,s=e.component,u=e.container,c=e.wrapperComponent,f=e.wrapperProps,d=e.locale,h=e.locales,p=e.formatVerboseDate,b=e.verboseDateFormat,m=e.updateInterval,g=e.tick,v=ah(e,["date","future","timeStyle","round","minTimeLeft","tooltip","component","container","wrapperComponent","wrapperProps","locale","locales","formatVerboseDate","verboseDateFormat","updateInterval","tick"]),y=(0,l.useMemo)(function(){return d&&(h=[d]),h.concat(iW.Z.getDefaultLocale())},[d,h]),w=(0,l.useMemo)(function(){return new iW.Z(y)},[y]);t=(0,l.useMemo)(function(){return i5(t)},[t]);var _=(0,l.useCallback)(function(){var e=Date.now(),o=void 0;if(n&&e>=t.getTime()&&(e=t.getTime(),o=!0),void 0!==a){var s=t.getTime()-1e3*a;e>s&&(e=s,o=!0)}var u=w.format(t,r,{getTimeToNextUpdate:!0,now:e,future:n,round:i}),c=ad(u,2),l=c[0],f=c[1];return f=o?ag:m||f||6e4,[l,e+f]},[t,n,r,m,i,a,w]),E=(0,l.useRef)();E.current=_;var S=(0,l.useMemo)(_,[]),k=ad(S,2),x=k[0],T=k[1],M=(0,l.useState)(x),O=ad(M,2),A=O[0],L=O[1],C=ad((0,l.useState)(),2),I=C[0],D=C[1],N=(0,l.useRef)();(0,l.useEffect)(function(){if(g)return N.current=ar.add({getNextValue:function(){return E.current()},setValue:L,nextUpdateTime:T}),function(){return N.current.stop()}},[g]),(0,l.useEffect)(function(){if(N.current)N.current.forceUpdate();else{var e=_(),t=ad(e,1)[0];L(t)}},[_]),(0,l.useEffect)(function(){D(!0)},[]);var P=(0,l.useMemo)(function(){if("undefined"!=typeof window)return i2(y,b)},[y,b]),R=(0,l.useMemo)(function(){if("undefined"!=typeof window)return p?p(t):P(t)},[t,p,P]),j=l.createElement(s,af({date:t,verboseDate:I?R:void 0,tooltip:o},v),A),F=c||u;return F?l.createElement(F,af({},f,{verboseDate:I?R:void 0}),j):j}ap.propTypes={date:el().oneOfType([el().instanceOf(Date),el().number]).isRequired,locale:el().string,locales:el().arrayOf(el().string),future:el().bool,timeStyle:al,round:el().string,minTimeLeft:el().number,component:el().elementType.isRequired,tooltip:el().bool.isRequired,formatVerboseDate:el().func,verboseDateFormat:el().object,updateInterval:el().oneOfType([el().number,el().arrayOf(el().shape({threshold:el().number,interval:el().number.isRequired}))]),tick:el().bool,wrapperComponent:el().func,wrapperProps:el().object},ap.defaultProps={locales:[],component:av,tooltip:!0,verboseDateFormat:{weekday:"long",day:"numeric",month:"long",year:"numeric",hour:"numeric",minute:"2-digit",second:"2-digit"},tick:!0},ap=l.memo(ap);let ab=ap;var am,ag=31536e9;function av(e){var t=e.date,n=e.verboseDate,r=e.tooltip,i=e.children,a=ah(e,["date","verboseDate","tooltip","children"]),o=(0,l.useMemo)(function(){return t.toISOString()},[t]);return l.createElement("time",af({},a,{dateTime:o,title:r?n:void 0}),i)}av.propTypes={date:el().instanceOf(Date).isRequired,verboseDate:el().string,tooltip:el().bool.isRequired,children:el().string.isRequired};var ay=n(30381),aw=n.n(ay),a_=n(31657);function aE(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function aS(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0?new rs.cA({graphQLErrors:i}):void 0;if(u===s.current.mutationId&&!c.ignoreResults){var f={called:!0,loading:!1,data:r,error:l,client:a};s.current.isMounted&&!(0,ri.D)(s.current.result,f)&&o(s.current.result=f)}var d=e.onCompleted||(null===(n=s.current.options)||void 0===n?void 0:n.onCompleted);return null==d||d(t.data,c),t}).catch(function(t){if(u===s.current.mutationId&&s.current.isMounted){var n,r={loading:!1,error:t,data:void 0,called:!0,client:a};(0,ri.D)(s.current.result,r)||o(s.current.result=r)}var i=e.onError||(null===(n=s.current.options)||void 0===n?void 0:n.onError);if(i)return i(t,c),{data:void 0,errors:t};throw t})},[]),c=(0,l.useCallback)(function(){s.current.isMounted&&o({called:!1,loading:!1,client:n})},[]);return(0,l.useEffect)(function(){return s.current.isMounted=!0,function(){s.current.isMounted=!1}},[]),[u,(0,t0.pi)({reset:c},a)]}var a4=n(59067),a6=n(28428),a5=n(11186),a8=n(78513);function a9(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var a7=function(e){return(0,b.createStyles)({paper:{display:"flex",margin:"".concat(2.5*e.spacing.unit,"px 0"),padding:"".concat(3*e.spacing.unit,"px ").concat(3.5*e.spacing.unit,"px")},content:{flex:1,width:"100%"},actions:a9({marginTop:-(1.5*e.spacing.unit),marginLeft:-(4*e.spacing.unit)},e.breakpoints.up("sm"),{marginLeft:0,marginRight:-(1.5*e.spacing.unit)}),itemBlock:{border:"1px solid rgba(224, 224, 224, 1)",borderRadius:e.shape.borderRadius,padding:2*e.spacing.unit,marginTop:e.spacing.unit},itemBlockText:{overflowWrap:"anywhere"}})},oe=(0,b.withStyles)(a7)(function(e){var t=e.actions,n=e.children,r=e.classes;return l.createElement(ii.default,{className:r.paper},l.createElement("div",{className:r.content},n),t&&l.createElement("div",{className:r.actions},t))}),ot=function(e){var t=e.title;return l.createElement(x.default,{variant:"subtitle2",gutterBottom:!0},t)},on=function(e){var t=e.children,n=e.value;return l.createElement(x.default,{variant:"body1",noWrap:!0},t||n)},or=(0,b.withStyles)(a7)(function(e){var t=e.children,n=e.classes,r=e.value;return l.createElement("div",{className:n.itemBlock},l.createElement(x.default,{variant:"body1",className:n.itemBlockText},t||r))});function oi(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]-1}let sF=sj;function sY(e,t){var n=this.__data__,r=sC(n,e);return r<0?(++this.size,n.push([e,t])):n[r][1]=t,this}let sB=sY;function sU(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t-1&&e%1==0&&e-1&&e%1==0&&e<=cw}let cE=c_;var cS="[object Arguments]",ck="[object Array]",cx="[object Boolean]",cT="[object Date]",cM="[object Error]",cO="[object Function]",cA="[object Map]",cL="[object Number]",cC="[object Object]",cI="[object RegExp]",cD="[object Set]",cN="[object String]",cP="[object WeakMap]",cR="[object ArrayBuffer]",cj="[object DataView]",cF="[object Float64Array]",cY="[object Int8Array]",cB="[object Int16Array]",cU="[object Int32Array]",cH="[object Uint8Array]",c$="[object Uint8ClampedArray]",cz="[object Uint16Array]",cG="[object Uint32Array]",cW={};function cK(e){return eD(e)&&cE(e.length)&&!!cW[eC(e)]}cW["[object Float32Array]"]=cW[cF]=cW[cY]=cW[cB]=cW[cU]=cW[cH]=cW[c$]=cW[cz]=cW[cG]=!0,cW[cS]=cW[ck]=cW[cR]=cW[cx]=cW[cj]=cW[cT]=cW[cM]=cW[cO]=cW[cA]=cW[cL]=cW[cC]=cW[cI]=cW[cD]=cW[cN]=cW[cP]=!1;let cV=cK;function cq(e){return function(t){return e(t)}}let cZ=cq;var cX=n(79730),cJ=cX.Z&&cX.Z.isTypedArray,cQ=cJ?cZ(cJ):cV;let c1=cQ;var c0=Object.prototype.hasOwnProperty;function c2(e,t){var n=cp(e),r=!n&&cd(e),i=!n&&!r&&(0,cb.Z)(e),a=!n&&!r&&!i&&c1(e),o=n||r||i||a,s=o?ci(e.length,String):[],u=s.length;for(var c in e)(t||c0.call(e,c))&&!(o&&("length"==c||i&&("offset"==c||"parent"==c)||a&&("buffer"==c||"byteLength"==c||"byteOffset"==c)||cy(c,u)))&&s.push(c);return s}let c3=c2;var c4=Object.prototype;function c6(e){var t=e&&e.constructor;return e===("function"==typeof t&&t.prototype||c4)}let c5=c6;var c8=sb(Object.keys,Object);let c9=c8;var c7=Object.prototype.hasOwnProperty;function le(e){if(!c5(e))return c9(e);var t=[];for(var n in Object(e))c7.call(e,n)&&"constructor"!=n&&t.push(n);return t}let lt=le;function ln(e){return null!=e&&cE(e.length)&&!s2(e)}let lr=ln;function li(e){return lr(e)?c3(e):lt(e)}let la=li;function lo(e,t){return e&&cn(t,la(t),e)}let ls=lo;function lu(e){var t=[];if(null!=e)for(var n in Object(e))t.push(n);return t}let lc=lu;var ll=Object.prototype.hasOwnProperty;function lf(e){if(!ed(e))return lc(e);var t=c5(e),n=[];for(var r in e)"constructor"==r&&(t||!ll.call(e,r))||n.push(r);return n}let ld=lf;function lh(e){return lr(e)?c3(e,!0):ld(e)}let lp=lh;function lb(e,t){return e&&cn(t,lp(t),e)}let lm=lb;var lg=n(42896);function lv(e,t){var n=-1,r=e.length;for(t||(t=Array(r));++n=0||(i[n]=e[n]);return i}function d8(e){if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}var d9=function(e){return Array.isArray(e)&&0===e.length},d7=function(e){return"function"==typeof e},he=function(e){return null!==e&&"object"==typeof e},ht=function(e){return String(Math.floor(Number(e)))===e},hn=function(e){return"[object String]"===Object.prototype.toString.call(e)},hr=function(e){return 0===l.Children.count(e)},hi=function(e){return he(e)&&d7(e.then)};function ha(e,t,n,r){void 0===r&&(r=0);for(var i=dZ(t);e&&r=0?[]:{}}}return(0===a?e:i)[o[a]]===n?e:(void 0===n?delete i[o[a]]:i[o[a]]=n,0===a&&void 0===n&&delete r[o[a]],r)}function hs(e,t,n,r){void 0===n&&(n=new WeakMap),void 0===r&&(r={});for(var i=0,a=Object.keys(e);i0?t.map(function(t){return x(t,ha(e,t))}):[Promise.resolve("DO_NOT_DELETE_YOU_WILL_BE_FIRED")]).then(function(e){return e.reduce(function(e,n,r){return"DO_NOT_DELETE_YOU_WILL_BE_FIRED"===n||n&&(e=ho(e,t[r],n)),e},{})})},[x]),M=(0,l.useCallback)(function(e){return Promise.all([T(e),h.validationSchema?k(e):{},h.validate?S(e):{}]).then(function(e){var t=e[0],n=e[1],r=e[2];return sh.all([t,n,r],{arrayMerge:hy})})},[h.validate,h.validationSchema,T,S,k]),O=hS(function(e){return void 0===e&&(e=_.values),E({type:"SET_ISVALIDATING",payload:!0}),M(e).then(function(e){return v.current&&(E({type:"SET_ISVALIDATING",payload:!1}),st()(_.errors,e)||E({type:"SET_ERRORS",payload:e})),e})});(0,l.useEffect)(function(){o&&!0===v.current&&st()(p.current,h.initialValues)&&O(p.current)},[o,O]);var A=(0,l.useCallback)(function(e){var t=e&&e.values?e.values:p.current,n=e&&e.errors?e.errors:b.current?b.current:h.initialErrors||{},r=e&&e.touched?e.touched:m.current?m.current:h.initialTouched||{},i=e&&e.status?e.status:g.current?g.current:h.initialStatus;p.current=t,b.current=n,m.current=r,g.current=i;var a=function(){E({type:"RESET_FORM",payload:{isSubmitting:!!e&&!!e.isSubmitting,errors:n,touched:r,status:i,values:t,isValidating:!!e&&!!e.isValidating,submitCount:e&&e.submitCount&&"number"==typeof e.submitCount?e.submitCount:0}})};if(h.onReset){var o=h.onReset(_.values,V);hi(o)?o.then(a):a()}else a()},[h.initialErrors,h.initialStatus,h.initialTouched]);(0,l.useEffect)(function(){!0===v.current&&!st()(p.current,h.initialValues)&&(c&&(p.current=h.initialValues,A()),o&&O(p.current))},[c,h.initialValues,A,o,O]),(0,l.useEffect)(function(){c&&!0===v.current&&!st()(b.current,h.initialErrors)&&(b.current=h.initialErrors||hd,E({type:"SET_ERRORS",payload:h.initialErrors||hd}))},[c,h.initialErrors]),(0,l.useEffect)(function(){c&&!0===v.current&&!st()(m.current,h.initialTouched)&&(m.current=h.initialTouched||hh,E({type:"SET_TOUCHED",payload:h.initialTouched||hh}))},[c,h.initialTouched]),(0,l.useEffect)(function(){c&&!0===v.current&&!st()(g.current,h.initialStatus)&&(g.current=h.initialStatus,E({type:"SET_STATUS",payload:h.initialStatus}))},[c,h.initialStatus,h.initialTouched]);var L=hS(function(e){if(y.current[e]&&d7(y.current[e].validate)){var t=ha(_.values,e),n=y.current[e].validate(t);return hi(n)?(E({type:"SET_ISVALIDATING",payload:!0}),n.then(function(e){return e}).then(function(t){E({type:"SET_FIELD_ERROR",payload:{field:e,value:t}}),E({type:"SET_ISVALIDATING",payload:!1})})):(E({type:"SET_FIELD_ERROR",payload:{field:e,value:n}}),Promise.resolve(n))}return h.validationSchema?(E({type:"SET_ISVALIDATING",payload:!0}),k(_.values,e).then(function(e){return e}).then(function(t){E({type:"SET_FIELD_ERROR",payload:{field:e,value:t[e]}}),E({type:"SET_ISVALIDATING",payload:!1})})):Promise.resolve()}),C=(0,l.useCallback)(function(e,t){var n=t.validate;y.current[e]={validate:n}},[]),I=(0,l.useCallback)(function(e){delete y.current[e]},[]),D=hS(function(e,t){return E({type:"SET_TOUCHED",payload:e}),(void 0===t?i:t)?O(_.values):Promise.resolve()}),N=(0,l.useCallback)(function(e){E({type:"SET_ERRORS",payload:e})},[]),P=hS(function(e,t){var r=d7(e)?e(_.values):e;return E({type:"SET_VALUES",payload:r}),(void 0===t?n:t)?O(r):Promise.resolve()}),R=(0,l.useCallback)(function(e,t){E({type:"SET_FIELD_ERROR",payload:{field:e,value:t}})},[]),j=hS(function(e,t,r){return E({type:"SET_FIELD_VALUE",payload:{field:e,value:t}}),(void 0===r?n:r)?O(ho(_.values,e,t)):Promise.resolve()}),F=(0,l.useCallback)(function(e,t){var n,r=t,i=e;if(!hn(e)){e.persist&&e.persist();var a=e.target?e.target:e.currentTarget,o=a.type,s=a.name,u=a.id,c=a.value,l=a.checked,f=(a.outerHTML,a.options),d=a.multiple;r=t||s||u,i=/number|range/.test(o)?(n=parseFloat(c),isNaN(n)?"":n):/checkbox/.test(o)?h_(ha(_.values,r),l,c):d?hw(f):c}r&&j(r,i)},[j,_.values]),Y=hS(function(e){if(hn(e))return function(t){return F(t,e)};F(e)}),B=hS(function(e,t,n){return void 0===t&&(t=!0),E({type:"SET_FIELD_TOUCHED",payload:{field:e,value:t}}),(void 0===n?i:n)?O(_.values):Promise.resolve()}),U=(0,l.useCallback)(function(e,t){e.persist&&e.persist();var n,r=e.target,i=r.name,a=r.id;r.outerHTML,B(t||i||a,!0)},[B]),H=hS(function(e){if(hn(e))return function(t){return U(t,e)};U(e)}),$=(0,l.useCallback)(function(e){d7(e)?E({type:"SET_FORMIK_STATE",payload:e}):E({type:"SET_FORMIK_STATE",payload:function(){return e}})},[]),z=(0,l.useCallback)(function(e){E({type:"SET_STATUS",payload:e})},[]),G=(0,l.useCallback)(function(e){E({type:"SET_ISSUBMITTING",payload:e})},[]),W=hS(function(){return E({type:"SUBMIT_ATTEMPT"}),O().then(function(e){var t,n=e instanceof Error;if(!n&&0===Object.keys(e).length){try{if(void 0===(t=q()))return}catch(r){throw r}return Promise.resolve(t).then(function(e){return v.current&&E({type:"SUBMIT_SUCCESS"}),e}).catch(function(e){if(v.current)throw E({type:"SUBMIT_FAILURE"}),e})}if(v.current&&(E({type:"SUBMIT_FAILURE"}),n))throw e})}),K=hS(function(e){e&&e.preventDefault&&d7(e.preventDefault)&&e.preventDefault(),e&&e.stopPropagation&&d7(e.stopPropagation)&&e.stopPropagation(),W().catch(function(e){console.warn("Warning: An unhandled error was caught from submitForm()",e)})}),V={resetForm:A,validateForm:O,validateField:L,setErrors:N,setFieldError:R,setFieldTouched:B,setFieldValue:j,setStatus:z,setSubmitting:G,setTouched:D,setValues:P,setFormikState:$,submitForm:W},q=hS(function(){return f(_.values,V)}),Z=hS(function(e){e&&e.preventDefault&&d7(e.preventDefault)&&e.preventDefault(),e&&e.stopPropagation&&d7(e.stopPropagation)&&e.stopPropagation(),A()}),X=(0,l.useCallback)(function(e){return{value:ha(_.values,e),error:ha(_.errors,e),touched:!!ha(_.touched,e),initialValue:ha(p.current,e),initialTouched:!!ha(m.current,e),initialError:ha(b.current,e)}},[_.errors,_.touched,_.values]),J=(0,l.useCallback)(function(e){return{setValue:function(t,n){return j(e,t,n)},setTouched:function(t,n){return B(e,t,n)},setError:function(t){return R(e,t)}}},[j,B,R]),Q=(0,l.useCallback)(function(e){var t=he(e),n=t?e.name:e,r=ha(_.values,n),i={name:n,value:r,onChange:Y,onBlur:H};if(t){var a=e.type,o=e.value,s=e.as,u=e.multiple;"checkbox"===a?void 0===o?i.checked=!!r:(i.checked=!!(Array.isArray(r)&&~r.indexOf(o)),i.value=o):"radio"===a?(i.checked=r===o,i.value=o):"select"===s&&u&&(i.value=i.value||[],i.multiple=!0)}return i},[H,Y,_.values]),ee=(0,l.useMemo)(function(){return!st()(p.current,_.values)},[p.current,_.values]),et=(0,l.useMemo)(function(){return void 0!==s?ee?_.errors&&0===Object.keys(_.errors).length:!1!==s&&d7(s)?s(h):s:_.errors&&0===Object.keys(_.errors).length},[s,ee,_.errors,h]);return d4({},_,{initialValues:p.current,initialErrors:b.current,initialTouched:m.current,initialStatus:g.current,handleBlur:H,handleChange:Y,handleReset:Z,handleSubmit:K,resetForm:A,setErrors:N,setFormikState:$,setFieldTouched:B,setFieldValue:j,setFieldError:R,setStatus:z,setSubmitting:G,setTouched:D,setValues:P,submitForm:W,validateForm:O,validateField:L,isValid:et,dirty:ee,unregisterField:I,registerField:C,getFieldProps:Q,getFieldMeta:X,getFieldHelpers:J,validateOnBlur:i,validateOnChange:n,validateOnMount:o})}function hb(e){var t=hp(e),n=e.component,r=e.children,i=e.render,a=e.innerRef;return(0,l.useImperativeHandle)(a,function(){return t}),(0,l.createElement)(hc,{value:t},n?(0,l.createElement)(n,t):i?i(t):r?d7(r)?r(t):hr(r)?null:l.Children.only(r):null)}function hm(e){var t={};if(e.inner){if(0===e.inner.length)return ho(t,e.path,e.message);for(var n=e.inner,r=Array.isArray(n),i=0,n=r?n:n[Symbol.iterator]();;){if(r){if(i>=n.length)break;a=n[i++]}else{if((i=n.next()).done)break;a=i.value}var a,o=a;ha(t,o.path)||(t=ho(t,o.path,o.message))}}return t}function hg(e,t,n,r){void 0===n&&(n=!1),void 0===r&&(r={});var i=hv(e);return t[n?"validateSync":"validate"](i,{abortEarly:!1,context:r})}function hv(e){var t=Array.isArray(e)?[]:{};for(var n in e)if(Object.prototype.hasOwnProperty.call(e,n)){var r=String(n);!0===Array.isArray(e[r])?t[r]=e[r].map(function(e){return!0===Array.isArray(e)||sx(e)?hv(e):""!==e?e:void 0}):sx(e[r])?t[r]=hv(e[r]):t[r]=""!==e[r]?e[r]:void 0}return t}function hy(e,t,n){var r=e.slice();return t.forEach(function(t,i){if(void 0===r[i]){var a=!1!==n.clone&&n.isMergeableObject(t);r[i]=a?sh(Array.isArray(t)?[]:{},t,n):t}else n.isMergeableObject(t)?r[i]=sh(e[i],t,n):-1===e.indexOf(t)&&r.push(t)}),r}function hw(e){return Array.from(e).filter(function(e){return e.selected}).map(function(e){return e.value})}function h_(e,t,n){if("boolean"==typeof e)return Boolean(t);var r=[],i=!1,a=-1;if(Array.isArray(e))r=e,i=(a=e.indexOf(n))>=0;else if(!n||"true"==n||"false"==n)return Boolean(t);return t&&n&&!i?r.concat(n):i?r.slice(0,a).concat(r.slice(a+1)):r}var hE="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement?l.useLayoutEffect:l.useEffect;function hS(e){var t=(0,l.useRef)(e);return hE(function(){t.current=e}),(0,l.useCallback)(function(){for(var e=arguments.length,n=Array(e),r=0;re?t:e},0);return Array.from(d4({},e,{length:t+1}))};(function(e){function t(t){var n;return(n=e.call(this,t)||this).updateArrayField=function(e,t,r){var i=n.props,a=i.name;(0,i.formik.setFormikState)(function(n){var i="function"==typeof r?r:e,o="function"==typeof t?t:e,s=ho(n.values,a,e(ha(n.values,a))),u=r?i(ha(n.errors,a)):void 0,c=t?o(ha(n.touched,a)):void 0;return d9(u)&&(u=void 0),d9(c)&&(c=void 0),d4({},n,{values:s,errors:r?ho(n.errors,a,u):n.errors,touched:t?ho(n.touched,a,c):n.touched})})},n.push=function(e){return n.updateArrayField(function(t){return[].concat(hL(t),[d3(e)])},!1,!1)},n.handlePush=function(e){return function(){return n.push(e)}},n.swap=function(e,t){return n.updateArrayField(function(n){return hM(n,e,t)},!0,!0)},n.handleSwap=function(e,t){return function(){return n.swap(e,t)}},n.move=function(e,t){return n.updateArrayField(function(n){return hT(n,e,t)},!0,!0)},n.handleMove=function(e,t){return function(){return n.move(e,t)}},n.insert=function(e,t){return n.updateArrayField(function(n){return hO(n,e,t)},function(t){return hO(t,e,null)},function(t){return hO(t,e,null)})},n.handleInsert=function(e,t){return function(){return n.insert(e,t)}},n.replace=function(e,t){return n.updateArrayField(function(n){return hA(n,e,t)},!1,!1)},n.handleReplace=function(e,t){return function(){return n.replace(e,t)}},n.unshift=function(e){var t=-1;return n.updateArrayField(function(n){var r=n?[e].concat(n):[e];return t<0&&(t=r.length),r},function(e){var n=e?[null].concat(e):[null];return t<0&&(t=n.length),n},function(e){var n=e?[null].concat(e):[null];return t<0&&(t=n.length),n}),t},n.handleUnshift=function(e){return function(){return n.unshift(e)}},n.handleRemove=function(e){return function(){return n.remove(e)}},n.handlePop=function(){return function(){return n.pop()}},n.remove=n.remove.bind(d8(n)),n.pop=n.pop.bind(d8(n)),n}d6(t,e);var n=t.prototype;return n.componentDidUpdate=function(e){this.props.validateOnChange&&this.props.formik.validateOnChange&&!st()(ha(e.formik.values,e.name),ha(this.props.formik.values,this.props.name))&&this.props.formik.validateForm(this.props.formik.values)},n.remove=function(e){var t;return this.updateArrayField(function(n){var r=n?hL(n):[];return t||(t=r[e]),d7(r.splice)&&r.splice(e,1),r},!0,!0),t},n.pop=function(){var e;return this.updateArrayField(function(t){var n=t;return e||(e=n&&n.pop&&n.pop()),n},!0,!0),e},n.render=function(){var e={push:this.push,pop:this.pop,swap:this.swap,move:this.move,insert:this.insert,replace:this.replace,unshift:this.unshift,remove:this.remove,handlePush:this.handlePush,handlePop:this.handlePop,handleSwap:this.handleSwap,handleMove:this.handleMove,handleInsert:this.handleInsert,handleReplace:this.handleReplace,handleUnshift:this.handleUnshift,handleRemove:this.handleRemove},t=this.props,n=t.component,r=t.render,i=t.children,a=t.name,o=d5(t.formik,["validate","validationSchema"]),s=d4({},e,{form:o,name:a});return n?(0,l.createElement)(n,s):r?r(s):i?"function"==typeof i?i(s):hr(i)?null:l.Children.only(i):null},t})(l.Component).defaultProps={validateOnChange:!0},l.Component,l.Component;var hC=n(24802),hI=n(71209),hD=n(91750),hN=n(11970),hP=n(4689),hR=n(67598),hj=function(){return(hj=Object.assign||function(e){for(var t,n=1,r=arguments.length;nt.indexOf(r)&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var i=0,r=Object.getOwnPropertySymbols(e);it.indexOf(r[i])&&(n[r[i]]=e[r[i]]);return n}function hY(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hF(n,["onBlur"]),a=e.form,o=a.isSubmitting,s=a.touched,u=a.errors,c=e.onBlur,l=e.helperText,f=hF(e,["disabled","field","form","onBlur","helperText"]),d=ha(u,i.name),h=ha(s,i.name)&&!!d;return hj(hj({variant:f.variant,error:h,helperText:h?d:l,disabled:null!=t?t:o,onBlur:null!=c?c:function(e){r(null!=e?e:i.name)}},i),f)}function hB(e){var t=e.children,n=hF(e,["children"]);return(0,l.createElement)(iw.Z,hj({},hY(n)),t)}function hU(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hF(n,["onBlur"]),a=e.form.isSubmitting,o=(e.type,e.onBlur),s=hF(e,["disabled","field","form","type","onBlur"]);return hj(hj({disabled:null!=t?t:a,onBlur:null!=o?o:function(e){r(null!=e?e:i.name)}},i),s)}function hH(e){return(0,l.createElement)(hC.Z,hj({},hU(e)))}function h$(e){var t,n=e.disabled,r=e.field,i=r.onBlur,a=hF(r,["onBlur"]),o=e.form.isSubmitting,s=(e.type,e.onBlur),u=hF(e,["disabled","field","form","type","onBlur"]);return hj(hj({disabled:null!=n?n:o,indeterminate:!Array.isArray(a.value)&&null==a.value,onBlur:null!=s?s:function(e){i(null!=e?e:a.name)}},a),u)}function hz(e){return(0,l.createElement)(hI.Z,hj({},h$(e)))}function hG(e){var t=e.Label,n=hF(e,["Label"]);return(0,l.createElement)(hD.Z,hj({control:(0,l.createElement)(hI.Z,hj({},h$(n)))},t))}function hW(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hF(n,["onBlur"]),a=e.form.isSubmitting,o=e.onBlur,s=hF(e,["disabled","field","form","onBlur"]);return hj(hj({disabled:null!=t?t:a,onBlur:null!=o?o:function(e){r(null!=e?e:i.name)}},i),s)}function hK(e){return(0,l.createElement)(hN.default,hj({},hW(e)))}function hV(e){var t=e.field,n=t.onBlur,r=hF(t,["onBlur"]),i=(e.form,e.onBlur),a=hF(e,["field","form","onBlur"]);return hj(hj({onBlur:null!=i?i:function(e){n(null!=e?e:r.name)}},r),a)}function hq(e){return(0,l.createElement)(hP.Z,hj({},hV(e)))}function hZ(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hF(n,["onBlur"]),a=e.form.isSubmitting,o=e.onBlur,s=hF(e,["disabled","field","form","onBlur"]);return hj(hj({disabled:null!=t?t:a,onBlur:null!=o?o:function(e){r(null!=e?e:i.name)}},i),s)}function hX(e){return(0,l.createElement)(hR.default,hj({},hZ(e)))}hB.displayName="FormikMaterialUITextField",hH.displayName="FormikMaterialUISwitch",hz.displayName="FormikMaterialUICheckbox",hG.displayName="FormikMaterialUICheckboxWithLabel",hK.displayName="FormikMaterialUISelect",hq.displayName="FormikMaterialUIRadioGroup",hX.displayName="FormikMaterialUIInputBase";try{a=Map}catch(hJ){}try{o=Set}catch(hQ){}function h1(e,t,n){if(!e||"object"!=typeof e||"function"==typeof e)return e;if(e.nodeType&&"cloneNode"in e)return e.cloneNode(!0);if(e instanceof Date)return new Date(e.getTime());if(e instanceof RegExp)return RegExp(e);if(Array.isArray(e))return e.map(h0);if(a&&e instanceof a)return new Map(Array.from(e.entries()));if(o&&e instanceof o)return new Set(Array.from(e.values()));if(e instanceof Object){t.push(e);var r=Object.create(e);for(var i in n.push(r),e){var s=t.findIndex(function(t){return t===e[i]});r[i]=s>-1?n[s]:h1(e[i],t,n)}return r}return e}function h0(e){return h1(e,[],[])}let h2=Object.prototype.toString,h3=Error.prototype.toString,h4=RegExp.prototype.toString,h6="undefined"!=typeof Symbol?Symbol.prototype.toString:()=>"",h5=/^Symbol\((.*)\)(.*)$/;function h8(e){if(e!=+e)return"NaN";let t=0===e&&1/e<0;return t?"-0":""+e}function h9(e,t=!1){if(null==e||!0===e||!1===e)return""+e;let n=typeof e;if("number"===n)return h8(e);if("string"===n)return t?`"${e}"`:e;if("function"===n)return"[Function "+(e.name||"anonymous")+"]";if("symbol"===n)return h6.call(e).replace(h5,"Symbol($1)");let r=h2.call(e).slice(8,-1);return"Date"===r?isNaN(e.getTime())?""+e:e.toISOString(e):"Error"===r||e instanceof Error?"["+h3.call(e)+"]":"RegExp"===r?h4.call(e):null}function h7(e,t){let n=h9(e,t);return null!==n?n:JSON.stringify(e,function(e,n){let r=h9(this[e],t);return null!==r?r:n},2)}let pe={default:"${path} is invalid",required:"${path} is a required field",oneOf:"${path} must be one of the following values: ${values}",notOneOf:"${path} must not be one of the following values: ${values}",notType({path:e,type:t,value:n,originalValue:r}){let i=null!=r&&r!==n,a=`${e} must be a \`${t}\` type, but the final value was: \`${h7(n,!0)}\``+(i?` (cast from the value \`${h7(r,!0)}\`).`:".");return null===n&&(a+='\n If "null" is intended as an empty value be sure to mark the schema as `.nullable()`'),a},defined:"${path} must be defined"},pt={length:"${path} must be exactly ${length} characters",min:"${path} must be at least ${min} characters",max:"${path} must be at most ${max} characters",matches:'${path} must match the following: "${regex}"',email:"${path} must be a valid email",url:"${path} must be a valid URL",uuid:"${path} must be a valid UUID",trim:"${path} must be a trimmed string",lowercase:"${path} must be a lowercase string",uppercase:"${path} must be a upper case string"},pn={min:"${path} must be greater than or equal to ${min}",max:"${path} must be less than or equal to ${max}",lessThan:"${path} must be less than ${less}",moreThan:"${path} must be greater than ${more}",positive:"${path} must be a positive number",negative:"${path} must be a negative number",integer:"${path} must be an integer"},pr={min:"${path} field must be later than ${min}",max:"${path} field must be at earlier than ${max}"},pi={isValue:"${path} field must be ${value}"},pa={noUnknown:"${path} field has unspecified keys: ${unknown}"},po={min:"${path} field must have at least ${min} items",max:"${path} field must have less than or equal to ${max} items",length:"${path} must be have ${length} items"};Object.assign(Object.create(null),{mixed:pe,string:pt,number:pn,date:pr,object:pa,array:po,boolean:pi});var ps=n(18721),pu=n.n(ps);let pc=e=>e&&e.__isYupSchema__;class pl{constructor(e,t){if(this.refs=e,this.refs=e,"function"==typeof t){this.fn=t;return}if(!pu()(t,"is"))throw TypeError("`is:` is required for `when()` conditions");if(!t.then&&!t.otherwise)throw TypeError("either `then:` or `otherwise:` is required for `when()` conditions");let{is:n,then:r,otherwise:i}=t,a="function"==typeof n?n:(...e)=>e.every(e=>e===n);this.fn=function(...e){let t=e.pop(),n=e.pop(),o=a(...e)?r:i;if(o)return"function"==typeof o?o(n):n.concat(o.resolve(t))}}resolve(e,t){let n=this.refs.map(e=>e.getValue(null==t?void 0:t.value,null==t?void 0:t.parent,null==t?void 0:t.context)),r=this.fn.apply(e,n.concat(e,t));if(void 0===r||r===e)return e;if(!pc(r))throw TypeError("conditions must return a schema object");return r.resolve(t)}}let pf=pl;function pd(e){return null==e?[]:[].concat(e)}function ph(){return(ph=Object.assign||function(e){for(var t=1;th7(t[n])):"function"==typeof e?e(t):e}static isError(e){return e&&"ValidationError"===e.name}constructor(e,t,n,r){super(),this.name="ValidationError",this.value=t,this.path=n,this.type=r,this.errors=[],this.inner=[],pd(e).forEach(e=>{pb.isError(e)?(this.errors.push(...e.errors),this.inner=this.inner.concat(e.inner.length?e.inner:e)):this.errors.push(e)}),this.message=this.errors.length>1?`${this.errors.length} errors occurred`:this.errors[0],Error.captureStackTrace&&Error.captureStackTrace(this,pb)}}let pm=e=>{let t=!1;return(...n)=>{t||(t=!0,e(...n))}};function pg(e,t){let{endEarly:n,tests:r,args:i,value:a,errors:o,sort:s,path:u}=e,c=pm(t),l=r.length,f=[];if(o=o||[],!l)return o.length?c(new pb(o,a,u)):c(null,a);for(let d=0;d=0||(i[n]=e[n]);return i}function px(e){function t(t,n){let{value:r,path:i="",label:a,options:o,originalValue:s,sync:u}=t,c=pk(t,["value","path","label","options","originalValue","sync"]),{name:l,test:f,params:d,message:h}=e,{parent:p,context:b}=o;function m(e){return pE.isRef(e)?e.getValue(r,p,b):e}function g(e={}){let t=py()(pS({value:r,originalValue:s,label:a,path:e.path||i},d,e.params),m),n=new pb(pb.formatError(e.message||h,t),r,t.path,e.type||l);return n.params=t,n}let v=pS({path:i,parent:p,type:l,createError:g,resolve:m,options:o,originalValue:s},c);if(!u){try{Promise.resolve(f.call(v,r,v)).then(e=>{pb.isError(e)?n(e):e?n(null,e):n(g())})}catch(y){n(y)}return}let w;try{var _;if(w=f.call(v,r,v),"function"==typeof(null==(_=w)?void 0:_.then))throw Error(`Validation test of type: "${v.type}" returned a Promise during a synchronous validate. This test will finish after the validate call has returned`)}catch(E){n(E);return}pb.isError(w)?n(w):w?n(null,w):n(g())}return t.OPTIONS=e,t}pE.prototype.__isYupRef=!0;let pT=e=>e.substr(0,e.length-1).substr(1);function pM(e,t,n,r=n){let i,a,o;return t?((0,pw.forEach)(t,(s,u,c)=>{let l=u?pT(s):s;if((e=e.resolve({context:r,parent:i,value:n})).innerType){let f=c?parseInt(l,10):0;if(n&&f>=n.length)throw Error(`Yup.reach cannot resolve an array item at index: ${s}, in the path: ${t}. because there is no value at that index. `);i=n,n=n&&n[f],e=e.innerType}if(!c){if(!e.fields||!e.fields[l])throw Error(`The schema does not contain the path: ${t}. (failed at: ${o} which is a type: "${e._type}")`);i=n,n=n&&n[l],e=e.fields[l]}a=l,o=u?"["+s+"]":"."+s}),{schema:e,parent:i,parentPath:a}):{parent:i,parentPath:t,schema:e}}class pO{constructor(){this.list=new Set,this.refs=new Map}get size(){return this.list.size+this.refs.size}describe(){let e=[];for(let t of this.list)e.push(t);for(let[,n]of this.refs)e.push(n.describe());return e}toArray(){return Array.from(this.list).concat(Array.from(this.refs.values()))}add(e){pE.isRef(e)?this.refs.set(e.key,e):this.list.add(e)}delete(e){pE.isRef(e)?this.refs.delete(e.key):this.list.delete(e)}has(e,t){if(this.list.has(e))return!0;let n,r=this.refs.values();for(;!(n=r.next()).done;)if(t(n.value)===e)return!0;return!1}clone(){let e=new pO;return e.list=new Set(this.list),e.refs=new Map(this.refs),e}merge(e,t){let n=this.clone();return e.list.forEach(e=>n.add(e)),e.refs.forEach(e=>n.add(e)),t.list.forEach(e=>n.delete(e)),t.refs.forEach(e=>n.delete(e)),n}}function pA(){return(pA=Object.assign||function(e){for(var t=1;t{this.typeError(pe.notType)}),this.type=(null==e?void 0:e.type)||"mixed",this.spec=pA({strip:!1,strict:!1,abortEarly:!0,recursive:!0,nullable:!1,presence:"optional"},null==e?void 0:e.spec)}get _type(){return this.type}_typeCheck(e){return!0}clone(e){if(this._mutate)return e&&Object.assign(this.spec,e),this;let t=Object.create(Object.getPrototypeOf(this));return t.type=this.type,t._typeError=this._typeError,t._whitelistError=this._whitelistError,t._blacklistError=this._blacklistError,t._whitelist=this._whitelist.clone(),t._blacklist=this._blacklist.clone(),t.exclusiveTests=pA({},this.exclusiveTests),t.deps=[...this.deps],t.conditions=[...this.conditions],t.tests=[...this.tests],t.transforms=[...this.transforms],t.spec=h0(pA({},this.spec,e)),t}label(e){var t=this.clone();return t.spec.label=e,t}meta(...e){if(0===e.length)return this.spec.meta;let t=this.clone();return t.spec.meta=Object.assign(t.spec.meta||{},e[0]),t}withMutation(e){let t=this._mutate;this._mutate=!0;let n=e(this);return this._mutate=t,n}concat(e){if(!e||e===this)return this;if(e.type!==this.type&&"mixed"!==this.type)throw TypeError(`You cannot \`concat()\` schema's of different types: ${this.type} and ${e.type}`);let t=this,n=e.clone(),r=pA({},t.spec,n.spec);return n.spec=r,n._typeError||(n._typeError=t._typeError),n._whitelistError||(n._whitelistError=t._whitelistError),n._blacklistError||(n._blacklistError=t._blacklistError),n._whitelist=t._whitelist.merge(e._whitelist,e._blacklist),n._blacklist=t._blacklist.merge(e._blacklist,e._whitelist),n.tests=t.tests,n.exclusiveTests=t.exclusiveTests,n.withMutation(t=>{e.tests.forEach(e=>{t.test(e.OPTIONS)})}),n}isType(e){return!!this.spec.nullable&&null===e||this._typeCheck(e)}resolve(e){let t=this;if(t.conditions.length){let n=t.conditions;(t=t.clone()).conditions=[],t=(t=n.reduce((t,n)=>n.resolve(t,e),t)).resolve(e)}return t}cast(e,t={}){let n=this.resolve(pA({value:e},t)),r=n._cast(e,t);if(void 0!==e&&!1!==t.assert&&!0!==n.isType(r)){let i=h7(e),a=h7(r);throw TypeError(`The value of ${t.path||"field"} could not be cast to a value that satisfies the schema type: "${n._type}". attempted value: ${i} -`+(a!==i?`result of cast: ${a}`:""))}return r}_cast(e,t){let n=void 0===e?e:this.transforms.reduce((t,n)=>n.call(this,t,e,this),e);return void 0===n&&(n=this.getDefault()),n}_validate(e,t={},n){let{sync:r,path:i,from:a=[],originalValue:o=e,strict:s=this.spec.strict,abortEarly:u=this.spec.abortEarly}=t,c=e;s||(c=this._cast(c,pB({assert:!1},t)));let l={value:c,path:i,options:t,originalValue:o,schema:this,label:this.spec.label,sync:r,from:a},f=[];this._typeError&&f.push(this._typeError),this._whitelistError&&f.push(this._whitelistError),this._blacklistError&&f.push(this._blacklistError),pO({args:l,value:c,path:i,sync:r,tests:f,endEarly:u},e=>{if(e)return void n(e,c);pO({tests:this.tests,args:l,path:i,sync:r,value:c,endEarly:u},n)})}validate(e,t,n){let r=this.resolve(pB({},t,{value:e}));return"function"==typeof n?r._validate(e,t,n):new Promise((n,i)=>r._validate(e,t,(e,t)=>{e?i(e):n(t)}))}validateSync(e,t){let n;return this.resolve(pB({},t,{value:e}))._validate(e,pB({},t,{sync:!0}),(e,t)=>{if(e)throw e;n=t}),n}isValid(e,t){return this.validate(e,t).then(()=>!0,e=>{if(pT.isError(e))return!1;throw e})}isValidSync(e,t){try{return this.validateSync(e,t),!0}catch(n){if(pT.isError(n))return!1;throw n}}_getDefault(){let e=this.spec.default;return null==e?e:"function"==typeof e?e.call(this):pn(e)}getDefault(e){return this.resolve(e||{})._getDefault()}default(e){return 0===arguments.length?this._getDefault():this.clone({default:e})}strict(e=!0){var t=this.clone();return t.spec.strict=e,t}_isPresent(e){return null!=e}defined(e=pf.defined){return this.test({message:e,name:"defined",exclusive:!0,test:e=>void 0!==e})}required(e=pf.required){return this.clone({presence:"required"}).withMutation(t=>t.test({message:e,name:"required",exclusive:!0,test(e){return this.schema._isPresent(e)}}))}notRequired(){var e=this.clone({presence:"optional"});return e.tests=e.tests.filter(e=>"required"!==e.OPTIONS.name),e}nullable(e=!0){return this.clone({nullable:!1!==e})}transform(e){var t=this.clone();return t.transforms.push(e),t}test(...e){let t;if(void 0===(t=1===e.length?"function"==typeof e[0]?{test:e[0]}:e[0]:2===e.length?{name:e[0],test:e[1]}:{name:e[0],message:e[1],test:e[2]}).message&&(t.message=pf.default),"function"!=typeof t.test)throw TypeError("`test` is a required parameters");let n=this.clone(),r=pR(t),i=t.exclusive||t.name&&!0===n.exclusiveTests[t.name];if(t.exclusive&&!t.name)throw TypeError("Exclusive tests must provide a unique `name` identifying the test");return t.name&&(n.exclusiveTests[t.name]=!!t.exclusive),n.tests=n.tests.filter(e=>e.OPTIONS.name!==t.name||!i&&e.OPTIONS.test!==r.OPTIONS.test),n.tests.push(r),n}when(e,t){Array.isArray(e)||"string"==typeof e||(t=e,e=".");let n=this.clone(),r=pS(e).map(e=>new pD(e));return r.forEach(e=>{e.isSibling&&n.deps.push(e.key)}),n.conditions.push(new pE(r,t)),n}typeError(e){var t=this.clone();return t._typeError=pR({message:e,name:"typeError",test(e){return!!(void 0===e||this.schema.isType(e))||this.createError({params:{type:this.schema._type}})}}),t}oneOf(e,t=pf.oneOf){var n=this.clone();return e.forEach(e=>{n._whitelist.add(e),n._blacklist.delete(e)}),n._whitelistError=pR({message:t,name:"oneOf",test(e){if(void 0===e)return!0;let t=this.schema._whitelist;return!!t.has(e,this.resolve)||this.createError({params:{values:t.toArray().join(", ")}})}}),n}notOneOf(e,t=pf.notOneOf){var n=this.clone();return e.forEach(e=>{n._blacklist.add(e),n._whitelist.delete(e)}),n._blacklistError=pR({message:t,name:"notOneOf",test(e){let t=this.schema._blacklist;return!t.has(e,this.resolve)||this.createError({params:{values:t.toArray().join(", ")}})}}),n}strip(e=!0){let t=this.clone();return t.spec.strip=e,t}describe(){let e=this.clone(),{label:t,meta:n}=e.spec,r={meta:n,label:t,type:e.type,oneOf:e._whitelist.describe(),notOneOf:e._blacklist.describe(),tests:e.tests.map(e=>({name:e.OPTIONS.name,params:e.OPTIONS.params})).filter((e,t,n)=>n.findIndex(t=>t.name===e.name)===t)};return r}}for(let pH of(pU.prototype.__isYupSchema__=!0,["validate","validateSync"]))pU.prototype[`${pH}At`]=function(e,t,n={}){let{parent:r,parentPath:i,schema:a}=pF(this,e,t,n.context);return a[pH](r&&r[i],pB({},n,{parent:r,path:e}))};for(let p$ of["equals","is"])pU.prototype[p$]=pU.prototype.oneOf;for(let pz of["not","nope"])pU.prototype[pz]=pU.prototype.notOneOf;pU.prototype.optional=pU.prototype.notRequired;let pG=pU;function pW(){return new pG}pW.prototype=pG.prototype;let pK=e=>null==e;function pV(){return new pq}class pq extends pU{constructor(){super({type:"boolean"}),this.withMutation(()=>{this.transform(function(e){if(!this.isType(e)){if(/^(true|1)$/i.test(String(e)))return!0;if(/^(false|0)$/i.test(String(e)))return!1}return e})})}_typeCheck(e){return e instanceof Boolean&&(e=e.valueOf()),"boolean"==typeof e}isTrue(e=pb.isValue){return this.test({message:e,name:"is-value",exclusive:!0,params:{value:"true"},test:e=>pK(e)||!0===e})}isFalse(e=pb.isValue){return this.test({message:e,name:"is-value",exclusive:!0,params:{value:"false"},test:e=>pK(e)||!1===e})}}pV.prototype=pq.prototype;let pZ=/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i,pX=/^((https?|ftp):)?\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i,pJ=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i,pQ=e=>pK(e)||e===e.trim(),p1=({}).toString();function p0(){return new p2}class p2 extends pU{constructor(){super({type:"string"}),this.withMutation(()=>{this.transform(function(e){if(this.isType(e)||Array.isArray(e))return e;let t=null!=e&&e.toString?e.toString():e;return t===p1?e:t})})}_typeCheck(e){return e instanceof String&&(e=e.valueOf()),"string"==typeof e}_isPresent(e){return super._isPresent(e)&&!!e.length}length(e,t=pd.length){return this.test({message:t,name:"length",exclusive:!0,params:{length:e},test(t){return pK(t)||t.length===this.resolve(e)}})}min(e,t=pd.min){return this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(t){return pK(t)||t.length>=this.resolve(e)}})}max(e,t=pd.max){return this.test({name:"max",exclusive:!0,message:t,params:{max:e},test(t){return pK(t)||t.length<=this.resolve(e)}})}matches(e,t){let n=!1,r,i;return t&&("object"==typeof t?{excludeEmptyString:n=!1,message:r,name:i}=t:r=t),this.test({name:i||"matches",message:r||pd.matches,params:{regex:e},test:t=>pK(t)||""===t&&n||-1!==t.search(e)})}email(e=pd.email){return this.matches(pZ,{name:"email",message:e,excludeEmptyString:!0})}url(e=pd.url){return this.matches(pX,{name:"url",message:e,excludeEmptyString:!0})}uuid(e=pd.uuid){return this.matches(pJ,{name:"uuid",message:e,excludeEmptyString:!1})}ensure(){return this.default("").transform(e=>null===e?"":e)}trim(e=pd.trim){return this.transform(e=>null!=e?e.trim():e).test({message:e,name:"trim",test:pQ})}lowercase(e=pd.lowercase){return this.transform(e=>pK(e)?e:e.toLowerCase()).test({message:e,name:"string_case",exclusive:!0,test:e=>pK(e)||e===e.toLowerCase()})}uppercase(e=pd.uppercase){return this.transform(e=>pK(e)?e:e.toUpperCase()).test({message:e,name:"string_case",exclusive:!0,test:e=>pK(e)||e===e.toUpperCase()})}}p0.prototype=p2.prototype;let p3=e=>e!=+e;function p4(){return new p6}class p6 extends pU{constructor(){super({type:"number"}),this.withMutation(()=>{this.transform(function(e){let t=e;if("string"==typeof t){if(""===(t=t.replace(/\s/g,"")))return NaN;t=+t}return this.isType(t)?t:parseFloat(t)})})}_typeCheck(e){return e instanceof Number&&(e=e.valueOf()),"number"==typeof e&&!p3(e)}min(e,t=ph.min){return this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(t){return pK(t)||t>=this.resolve(e)}})}max(e,t=ph.max){return this.test({message:t,name:"max",exclusive:!0,params:{max:e},test(t){return pK(t)||t<=this.resolve(e)}})}lessThan(e,t=ph.lessThan){return this.test({message:t,name:"max",exclusive:!0,params:{less:e},test(t){return pK(t)||tthis.resolve(e)}})}positive(e=ph.positive){return this.moreThan(0,e)}negative(e=ph.negative){return this.lessThan(0,e)}integer(e=ph.integer){return this.test({name:"integer",message:e,test:e=>pK(e)||Number.isInteger(e)})}truncate(){return this.transform(e=>pK(e)?e:0|e)}round(e){var t,n=["ceil","floor","round","trunc"];if("trunc"===(e=(null==(t=e)?void 0:t.toLowerCase())||"round"))return this.truncate();if(-1===n.indexOf(e.toLowerCase()))throw TypeError("Only valid options for round() are: "+n.join(", "));return this.transform(t=>pK(t)?t:Math[e](t))}}p4.prototype=p6.prototype;var p5=/^(\d{4}|[+\-]\d{6})(?:-?(\d{2})(?:-?(\d{2}))?)?(?:[ T]?(\d{2}):?(\d{2})(?::?(\d{2})(?:[,\.](\d{1,}))?)?(?:(Z)|([+\-])(\d{2})(?::?(\d{2}))?)?)?$/;function p8(e){var t,n,r=[1,4,5,6,7,10,11],i=0;if(n=p5.exec(e)){for(var a,o=0;a=r[o];++o)n[a]=+n[a]||0;n[2]=(+n[2]||1)-1,n[3]=+n[3]||1,n[7]=n[7]?String(n[7]).substr(0,3):0,(void 0===n[8]||""===n[8])&&(void 0===n[9]||""===n[9])?t=+new Date(n[1],n[2],n[3],n[4],n[5],n[6],n[7]):("Z"!==n[8]&&void 0!==n[9]&&(i=60*n[10]+n[11],"+"===n[9]&&(i=0-i)),t=Date.UTC(n[1],n[2],n[3],n[4],n[5]+i,n[6],n[7]))}else t=Date.parse?Date.parse(e):NaN;return t}let p9=new Date(""),p7=e=>"[object Date]"===Object.prototype.toString.call(e);function be(){return new bt}class bt extends pU{constructor(){super({type:"date"}),this.withMutation(()=>{this.transform(function(e){return this.isType(e)?e:(e=p8(e),isNaN(e)?p9:new Date(e))})})}_typeCheck(e){return p7(e)&&!isNaN(e.getTime())}prepareParam(e,t){let n;if(pD.isRef(e))n=e;else{let r=this.cast(e);if(!this._typeCheck(r))throw TypeError(`\`${t}\` must be a Date or a value that can be \`cast()\` to a Date`);n=r}return n}min(e,t=pp.min){let n=this.prepareParam(e,"min");return this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(e){return pK(e)||e>=this.resolve(n)}})}max(e,t=pp.max){var n=this.prepareParam(e,"max");return this.test({message:t,name:"max",exclusive:!0,params:{max:e},test(e){return pK(e)||e<=this.resolve(n)}})}}bt.INVALID_DATE=p9,be.prototype=bt.prototype,be.INVALID_DATE=p9;var bn=n(11865),br=n.n(bn),bi=n(68929),ba=n.n(bi),bo=n(67523),bs=n.n(bo),bu=n(94633),bc=n.n(bu);function bl(e,t=[]){let n=[],r=[];function i(e,i){var a=(0,pC.split)(e)[0];~r.indexOf(a)||r.push(a),~t.indexOf(`${i}-${a}`)||n.push([i,a])}for(let a in e)if(py()(e,a)){let o=e[a];~r.indexOf(a)||r.push(a),pD.isRef(o)&&o.isSibling?i(o.path,a):pw(o)&&"deps"in o&&o.deps.forEach(e=>i(e,a))}return bc().array(r,n).reverse()}function bf(e,t){let n=1/0;return e.some((e,r)=>{var i;if((null==(i=t.path)?void 0:i.indexOf(e))!==-1)return n=r,!0}),n}function bd(e){return(t,n)=>bf(e,t)-bf(e,n)}function bh(){return(bh=Object.assign||function(e){for(var t=1;t"[object Object]"===Object.prototype.toString.call(e);function bb(e,t){let n=Object.keys(e.fields);return Object.keys(t).filter(e=>-1===n.indexOf(e))}let bm=bd([]);class bg extends pU{constructor(e){super({type:"object"}),this.fields=Object.create(null),this._sortErrors=bm,this._nodes=[],this._excludedEdges=[],this.withMutation(()=>{this.transform(function(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(t){e=null}return this.isType(e)?e:null}),e&&this.shape(e)})}_typeCheck(e){return bp(e)||"function"==typeof e}_cast(e,t={}){var n;let r=super._cast(e,t);if(void 0===r)return this.getDefault();if(!this._typeCheck(r))return r;let i=this.fields,a=null!=(n=t.stripUnknown)?n:this.spec.noUnknown,o=this._nodes.concat(Object.keys(r).filter(e=>-1===this._nodes.indexOf(e))),s={},u=bh({},t,{parent:s,__validating:t.__validating||!1}),c=!1;for(let l of o){let f=i[l],d=py()(r,l);if(f){let h,p=r[l];u.path=(t.path?`${t.path}.`:"")+l;let b="spec"in(f=f.resolve({value:p,context:t.context,parent:s}))?f.spec:void 0,m=null==b?void 0:b.strict;if(null==b?void 0:b.strip){c=c||l in r;continue}void 0!==(h=t.__validating&&m?r[l]:f.cast(r[l],u))&&(s[l]=h)}else d&&!a&&(s[l]=r[l]);s[l]!==r[l]&&(c=!0)}return c?s:r}_validate(e,t={},n){let r=[],{sync:i,from:a=[],originalValue:o=e,abortEarly:s=this.spec.abortEarly,recursive:u=this.spec.recursive}=t;a=[{schema:this,value:o},...a],t.__validating=!0,t.originalValue=o,t.from=a,super._validate(e,t,(e,c)=>{if(e){if(!pT.isError(e)||s)return void n(e,c);r.push(e)}if(!u||!bp(c)){n(r[0]||null,c);return}o=o||c;let l=this._nodes.map(e=>(n,r)=>{let i=-1===e.indexOf(".")?(t.path?`${t.path}.`:"")+e:`${t.path||""}["${e}"]`,s=this.fields[e];if(s&&"validate"in s){s.validate(c[e],bh({},t,{path:i,from:a,strict:!0,parent:c,originalValue:o[e]}),r);return}r(null)});pO({sync:i,tests:l,value:c,errors:r,endEarly:s,sort:this._sortErrors,path:t.path},n)})}clone(e){let t=super.clone(e);return t.fields=bh({},this.fields),t._nodes=this._nodes,t._excludedEdges=this._excludedEdges,t._sortErrors=this._sortErrors,t}concat(e){let t=super.concat(e),n=t.fields;for(let[r,i]of Object.entries(this.fields)){let a=n[r];void 0===a?n[r]=i:a instanceof pU&&i instanceof pU&&(n[r]=i.concat(a))}return t.withMutation(()=>t.shape(n))}getDefaultFromShape(){let e={};return this._nodes.forEach(t=>{let n=this.fields[t];e[t]="default"in n?n.getDefault():void 0}),e}_getDefault(){return"default"in this.spec?super._getDefault():this._nodes.length?this.getDefaultFromShape():void 0}shape(e,t=[]){let n=this.clone(),r=Object.assign(n.fields,e);if(n.fields=r,n._sortErrors=bd(Object.keys(r)),t.length){Array.isArray(t[0])||(t=[t]);let i=t.map(([e,t])=>`${e}-${t}`);n._excludedEdges=n._excludedEdges.concat(i)}return n._nodes=bl(r,n._excludedEdges),n}pick(e){let t={};for(let n of e)this.fields[n]&&(t[n]=this.fields[n]);return this.clone().withMutation(e=>(e.fields={},e.shape(t)))}omit(e){let t=this.clone(),n=t.fields;for(let r of(t.fields={},e))delete n[r];return t.withMutation(()=>t.shape(n))}from(e,t,n){let r=(0,pC.getter)(e,!0);return this.transform(i=>{if(null==i)return i;let a=i;return py()(i,e)&&(a=bh({},i),n||delete a[e],a[t]=r(i)),a})}noUnknown(e=!0,t=pm.noUnknown){"string"==typeof e&&(t=e,e=!0);let n=this.test({name:"noUnknown",exclusive:!0,message:t,test(t){if(null==t)return!0;let n=bb(this.schema,t);return!e||0===n.length||this.createError({params:{unknown:n.join(", ")}})}});return n.spec.noUnknown=e,n}unknown(e=!0,t=pm.noUnknown){return this.noUnknown(!e,t)}transformKeys(e){return this.transform(t=>t&&bs()(t,(t,n)=>e(n)))}camelCase(){return this.transformKeys(ba())}snakeCase(){return this.transformKeys(br())}constantCase(){return this.transformKeys(e=>br()(e).toUpperCase())}describe(){let e=super.describe();return e.fields=pL()(this.fields,e=>e.describe()),e}}function bv(e){return new bg(e)}function by(){return(by=Object.assign||function(e){for(var t=1;t{this.transform(function(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(t){e=null}return this.isType(e)?e:null})})}_typeCheck(e){return Array.isArray(e)}get _subType(){return this.innerType}_cast(e,t){let n=super._cast(e,t);if(!this._typeCheck(n)||!this.innerType)return n;let r=!1,i=n.map((e,n)=>{let i=this.innerType.cast(e,by({},t,{path:`${t.path||""}[${n}]`}));return i!==e&&(r=!0),i});return r?i:n}_validate(e,t={},n){var r,i;let a=[],o=t.sync,s=t.path,u=this.innerType,c=null!=(r=t.abortEarly)?r:this.spec.abortEarly,l=null!=(i=t.recursive)?i:this.spec.recursive,f=null!=t.originalValue?t.originalValue:e;super._validate(e,t,(e,r)=>{if(e){if(!pT.isError(e)||c)return void n(e,r);a.push(e)}if(!l||!u||!this._typeCheck(r)){n(a[0]||null,r);return}f=f||r;let i=Array(r.length);for(let d=0;du.validate(h,b,t)}pO({sync:o,path:s,value:r,errors:a,endEarly:c,tests:i},n)})}clone(e){let t=super.clone(e);return t.innerType=this.innerType,t}concat(e){let t=super.concat(e);return t.innerType=this.innerType,e.innerType&&(t.innerType=t.innerType?t.innerType.concat(e.innerType):e.innerType),t}of(e){let t=this.clone();if(!pw(e))throw TypeError("`array.of()` sub-schema must be a valid yup schema not: "+pl(e));return t.innerType=e,t}length(e,t=pg.length){return this.test({message:t,name:"length",exclusive:!0,params:{length:e},test(t){return pK(t)||t.length===this.resolve(e)}})}min(e,t){return t=t||pg.min,this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(t){return pK(t)||t.length>=this.resolve(e)}})}max(e,t){return t=t||pg.max,this.test({message:t,name:"max",exclusive:!0,params:{max:e},test(t){return pK(t)||t.length<=this.resolve(e)}})}ensure(){return this.default(()=>[]).transform((e,t)=>this._typeCheck(e)?e:null==t?[]:[].concat(t))}compact(e){let t=e?(t,n,r)=>!e(t,n,r):e=>!!e;return this.transform(e=>null!=e?e.filter(t):e)}describe(){let e=super.describe();return this.innerType&&(e.innerType=this.innerType.describe()),e}nullable(e=!0){return super.nullable(e)}defined(){return super.defined()}required(e){return super.required(e)}}bw.prototype=b_.prototype;var bE=bv().shape({name:p0().required("Required"),url:p0().required("Required")}),bS=function(e){var t=e.initialValues,n=e.onSubmit,r=e.submitButtonText,i=e.nameDisabled,a=void 0!==i&&i;return l.createElement(hT,{initialValues:t,validationSchema:bE,onSubmit:n},function(e){var t=e.isSubmitting;return l.createElement(l.Fragment,null,l.createElement(hR,{"data-testid":"bridge-form",noValidate:!0},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(hP,{component:hX,id:"name",name:"name",label:"Name",disabled:a,required:!0,fullWidth:!0,FormHelperTextProps:{"data-testid":"name-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(hP,{component:hX,id:"url",name:"url",label:"Bridge URL",placeholder:"https://",required:!0,fullWidth:!0,FormHelperTextProps:{"data-testid":"url-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:7},l.createElement(hP,{component:hX,id:"minimumContractPayment",name:"minimumContractPayment",label:"Minimum Contract Payment",placeholder:"0",fullWidth:!0,inputProps:{min:0},FormHelperTextProps:{"data-testid":"minimumContractPayment-helper-text"}})),l.createElement(d.Z,{item:!0,xs:7},l.createElement(hP,{component:hX,id:"confirmations",name:"confirmations",label:"Confirmations",placeholder:"0",type:"number",fullWidth:!0,inputProps:{min:0},FormHelperTextProps:{"data-testid":"confirmations-helper-text"}})))),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(ok.default,{variant:"contained",color:"primary",type:"submit",disabled:t,size:"large"},r)))))})},bk=function(e){var t=e.bridge,n=e.onSubmit,r={name:t.name,url:t.url,minimumContractPayment:t.minimumContractPayment,confirmations:t.confirmations};return l.createElement(ig,null,l.createElement(d.Z,{container:!0,spacing:40},l.createElement(d.Z,{item:!0,xs:12,md:11,lg:9},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Edit Bridge",action:l.createElement(aA.Z,{component:tz,href:"/bridges/".concat(t.id)},"Cancel")}),l.createElement(aW.Z,null,l.createElement(bS,{nameDisabled:!0,initialValues:r,onSubmit:n,submitButtonText:"Save Bridge"}))))))};function bx(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&void 0!==arguments[0]&&arguments[0],t=e?function(){return l.createElement(x.default,{variant:"body1"},"Loading...")}:function(){return null};return{isLoading:e,LoadingPlaceholder:t}},mc=n(76023);function ml(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function mB(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n=4?[e[0],e[1],e[2],e[3],"".concat(e[0],".").concat(e[1]),"".concat(e[0],".").concat(e[2]),"".concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[0]),"".concat(e[1],".").concat(e[2]),"".concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[1]),"".concat(e[2],".").concat(e[3]),"".concat(e[3],".").concat(e[0]),"".concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[0]),"".concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[3],".").concat(e[1],".").concat(e[0]),"".concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[1],".").concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[2],".").concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[3],".").concat(e[0]),"".concat(e[2],".").concat(e[3],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[3],".").concat(e[1],".").concat(e[0]),"".concat(e[3],".").concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[3],".").concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[3],".").concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[3],".").concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[3],".").concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[3],".").concat(e[2],".").concat(e[1],".").concat(e[0])]:void 0}var mZ={};function mX(e){if(0===e.length||1===e.length)return e;var t=e.join(".");return mZ[t]||(mZ[t]=mq(e)),mZ[t]}function mJ(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2?arguments[2]:void 0;return mX(e.filter(function(e){return"token"!==e})).reduce(function(e,t){return mK({},e,n[t])},t)}function mQ(e){return e.join(" ")}function m1(e,t){var n=0;return function(r){return n+=1,r.map(function(r,i){return m0({node:r,stylesheet:e,useInlineStyles:t,key:"code-segment-".concat(n,"-").concat(i)})})}}function m0(e){var t=e.node,n=e.stylesheet,r=e.style,i=void 0===r?{}:r,a=e.useInlineStyles,o=e.key,s=t.properties,u=t.type,c=t.tagName,f=t.value;if("text"===u)return f;if(c){var d,h=m1(n,a);if(a){var p=Object.keys(n).reduce(function(e,t){return t.split(".").forEach(function(t){e.includes(t)||e.push(t)}),e},[]),b=s.className&&s.className.includes("token")?["token"]:[],m=s.className&&b.concat(s.className.filter(function(e){return!p.includes(e)}));d=mK({},s,{className:mQ(m)||void 0,style:mJ(s.className,Object.assign({},s.style,i),n)})}else d=mK({},s,{className:mQ(s.className)});var g=h(t.children);return l.createElement(c,(0,mV.Z)({key:o},d),g)}}let m2=function(e,t){return -1!==e.listLanguages().indexOf(t)};var m3=/\n/g;function m4(e){return e.match(m3)}function m6(e){var t=e.lines,n=e.startingLineNumber,r=e.style;return t.map(function(e,t){var i=t+n;return l.createElement("span",{key:"line-".concat(t),className:"react-syntax-highlighter-line-number",style:"function"==typeof r?r(i):r},"".concat(i,"\n"))})}function m5(e){var t=e.codeString,n=e.codeStyle,r=e.containerStyle,i=void 0===r?{float:"left",paddingRight:"10px"}:r,a=e.numberStyle,o=void 0===a?{}:a,s=e.startingLineNumber;return l.createElement("code",{style:Object.assign({},n,i)},m6({lines:t.replace(/\n$/,"").split("\n"),style:o,startingLineNumber:s}))}function m8(e){return"".concat(e.toString().length,".25em")}function m9(e,t){return{type:"element",tagName:"span",properties:{key:"line-number--".concat(e),className:["comment","linenumber","react-syntax-highlighter-line-number"],style:t},children:[{type:"text",value:e}]}}function m7(e,t,n){var r,i={display:"inline-block",minWidth:m8(n),paddingRight:"1em",textAlign:"right",userSelect:"none"};return mK({},i,"function"==typeof e?e(t):e)}function ge(e){var t=e.children,n=e.lineNumber,r=e.lineNumberStyle,i=e.largestLineNumber,a=e.showInlineLineNumbers,o=e.lineProps,s=void 0===o?{}:o,u=e.className,c=void 0===u?[]:u,l=e.showLineNumbers,f=e.wrapLongLines,d="function"==typeof s?s(n):s;if(d.className=c,n&&a){var h=m7(r,n,i);t.unshift(m9(n,h))}return f&l&&(d.style=mK({},d.style,{display:"flex"})),{type:"element",tagName:"span",properties:d,children:t}}function gt(e){for(var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[],r=0;r2&&void 0!==arguments[2]?arguments[2]:[];return ge({children:e,lineNumber:t,lineNumberStyle:s,largestLineNumber:o,showInlineLineNumbers:i,lineProps:n,className:a,showLineNumbers:r,wrapLongLines:u})}function b(e,t){if(r&&t&&i){var n=m7(s,t,o);e.unshift(m9(t,n))}return e}function m(e,n){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[];return t||r.length>0?p(e,n,r):b(e,n)}for(var g=function(){var e=l[h],t=e.children[0].value;if(m4(t)){var n=t.split("\n");n.forEach(function(t,i){var o=r&&f.length+a,s={type:"text",value:"".concat(t,"\n")};if(0===i){var u=l.slice(d+1,h).concat(ge({children:[s],className:e.properties.className})),c=m(u,o);f.push(c)}else if(i===n.length-1){if(l[h+1]&&l[h+1].children&&l[h+1].children[0]){var p={type:"text",value:"".concat(t)},b=ge({children:[p],className:e.properties.className});l.splice(h+1,0,b)}else{var g=[s],v=m(g,o,e.properties.className);f.push(v)}}else{var y=[s],w=m(y,o,e.properties.className);f.push(w)}}),d=h}h++};h code[class*="language-"]':{background:"#f5f2f0",padding:".1em",borderRadius:".3em",whiteSpace:"normal"},comment:{color:"slategray"},prolog:{color:"slategray"},doctype:{color:"slategray"},cdata:{color:"slategray"},punctuation:{color:"#999"},namespace:{Opacity:".7"},property:{color:"#905"},tag:{color:"#905"},boolean:{color:"#905"},number:{color:"#905"},constant:{color:"#905"},symbol:{color:"#905"},deleted:{color:"#905"},selector:{color:"#690"},"attr-name":{color:"#690"},string:{color:"#690"},char:{color:"#690"},builtin:{color:"#690"},inserted:{color:"#690"},operator:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},entity:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)",cursor:"help"},url:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},".language-css .token.string":{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},".style .token.string":{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},atrule:{color:"#07a"},"attr-value":{color:"#07a"},keyword:{color:"#07a"},function:{color:"#DD4A68"},"class-name":{color:"#DD4A68"},regex:{color:"#e90"},important:{color:"#e90",fontWeight:"bold"},variable:{color:"#e90"},bold:{fontWeight:"bold"},italic:{fontStyle:"italic"}};var gu=n(98695),gc=n.n(gu);let gl=["abap","abnf","actionscript","ada","agda","al","antlr4","apacheconf","apl","applescript","aql","arduino","arff","asciidoc","asm6502","aspnet","autohotkey","autoit","bash","basic","batch","bbcode","birb","bison","bnf","brainfuck","brightscript","bro","bsl","c","cil","clike","clojure","cmake","coffeescript","concurnas","cpp","crystal","csharp","csp","css-extras","css","cypher","d","dart","dax","dhall","diff","django","dns-zone-file","docker","ebnf","editorconfig","eiffel","ejs","elixir","elm","erb","erlang","etlua","excel-formula","factor","firestore-security-rules","flow","fortran","fsharp","ftl","gcode","gdscript","gedcom","gherkin","git","glsl","gml","go","graphql","groovy","haml","handlebars","haskell","haxe","hcl","hlsl","hpkp","hsts","http","ichigojam","icon","iecst","ignore","inform7","ini","io","j","java","javadoc","javadoclike","javascript","javastacktrace","jolie","jq","js-extras","js-templates","jsdoc","json","json5","jsonp","jsstacktrace","jsx","julia","keyman","kotlin","latex","latte","less","lilypond","liquid","lisp","livescript","llvm","lolcode","lua","makefile","markdown","markup-templating","markup","matlab","mel","mizar","mongodb","monkey","moonscript","n1ql","n4js","nand2tetris-hdl","naniscript","nasm","neon","nginx","nim","nix","nsis","objectivec","ocaml","opencl","oz","parigp","parser","pascal","pascaligo","pcaxis","peoplecode","perl","php-extras","php","phpdoc","plsql","powerquery","powershell","processing","prolog","properties","protobuf","pug","puppet","pure","purebasic","purescript","python","q","qml","qore","r","racket","reason","regex","renpy","rest","rip","roboconf","robotframework","ruby","rust","sas","sass","scala","scheme","scss","shell-session","smali","smalltalk","smarty","sml","solidity","solution-file","soy","sparql","splunk-spl","sqf","sql","stan","stylus","swift","t4-cs","t4-templating","t4-vb","tap","tcl","textile","toml","tsx","tt2","turtle","twig","typescript","typoscript","unrealscript","vala","vbnet","velocity","verilog","vhdl","vim","visual-basic","warpscript","wasm","wiki","xeora","xml-doc","xojo","xquery","yaml","yang","zig"];var gf=go(gc(),gs);gf.supportedLanguages=gl;let gd=gf;var gh=n(64566);function gp(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function gb(){var e=gp(["\n query FetchConfigV2 {\n configv2 {\n user\n effective\n }\n }\n"]);return gb=function(){return e},e}var gm=n0(gb()),gg=function(e){var t=e.children;return l.createElement(ir.Z,null,l.createElement(r7.default,{component:"th",scope:"row",colSpan:3},t))},gv=function(){return l.createElement(gg,null,"...")},gy=function(e){var t=e.children;return l.createElement(gg,null,t)},gw=function(e){var t=e.loading,n=e.toml,r=e.error,i=void 0===r?"":r,a=e.title,o=e.expanded;if(i)return l.createElement(gy,null,i);if(t)return l.createElement(gv,null);a||(a="TOML");var s={display:"block"};return l.createElement(x.default,null,l.createElement(mP.Z,{defaultExpanded:o},l.createElement(mR.Z,{expandIcon:l.createElement(gh.Z,null)},a),l.createElement(mj.Z,{style:s},l.createElement(gd,{language:"toml",style:gs},n))))},g_=function(){var e=rv(gm,{fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error;return(null==t?void 0:t.configv2.effective)=="N/A"?l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"TOML Configuration"}),l.createElement(gw,{title:"V2 config dump:",error:null==r?void 0:r.message,loading:n,toml:null==t?void 0:t.configv2.user,showHead:!0})))):l.createElement(l.Fragment,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"TOML Configuration"}),l.createElement(gw,{title:"User specified:",error:null==r?void 0:r.message,loading:n,toml:null==t?void 0:t.configv2.user,showHead:!0,expanded:!0}),l.createElement(gw,{title:"Effective (with defaults):",error:null==r?void 0:r.message,loading:n,toml:null==t?void 0:t.configv2.effective,showHead:!0})))))},gE=n(34823),gS=function(e){return(0,b.createStyles)({cell:{paddingTop:1.5*e.spacing.unit,paddingBottom:1.5*e.spacing.unit}})},gk=(0,b.withStyles)(gS)(function(e){var t=e.classes,n=(0,A.I0)();(0,l.useEffect)(function(){n((0,ty.DQ)())});var r=(0,A.v9)(gE.N,A.wU);return l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Node"}),l.createElement(r8.Z,null,l.createElement(r9.Z,null,l.createElement(ir.Z,null,l.createElement(r7.default,{className:t.cell},l.createElement(x.default,null,"Version"),l.createElement(x.default,{variant:"subtitle1",color:"textSecondary"},r.version))),l.createElement(ir.Z,null,l.createElement(r7.default,{className:t.cell},l.createElement(x.default,null,"SHA"),l.createElement(x.default,{variant:"subtitle1",color:"textSecondary"},r.commitSHA))))))}),gx=function(){return l.createElement(ig,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,sm:12,md:8},l.createElement(d.Z,{container:!0},l.createElement(g_,null))),l.createElement(d.Z,{item:!0,sm:12,md:4},l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(gk,null)),l.createElement(d.Z,{item:!0,xs:12},l.createElement(mN,null)),l.createElement(d.Z,{item:!0,xs:12},l.createElement(mE,null))))))},gT=function(){return l.createElement(gx,null)},gM=function(){return l.createElement(gT,null)},gO=n(44431),gA=1e18,gL=function(e){return new gO.BigNumber(e).dividedBy(gA).toFixed(8)},gC=function(e){var t=e.keys,n=e.chainID,r=e.hideHeaderTitle;return l.createElement(l.Fragment,null,l.createElement(sl.Z,{title:!r&&"Account Balances",subheader:"Chain ID "+n}),l.createElement(aW.Z,null,l.createElement(w.default,{dense:!1,disablePadding:!0},t&&t.map(function(e,r){return l.createElement(l.Fragment,null,l.createElement(_.default,{disableGutters:!0,key:["acc-balance",n.toString(),r.toString()].join("-")},l.createElement(E.Z,{primary:l.createElement(l.Fragment,null,l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12},l.createElement(op,{title:"Address"}),l.createElement(ob,{value:e.address})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(op,{title:"Native Token Balance"}),l.createElement(ob,{value:e.ethBalance||"--"})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(op,{title:"LINK Balance"}),l.createElement(ob,{value:e.linkBalance?gL(e.linkBalance):"--"}))))})),r+1s&&l.createElement(gB.Z,null,l.createElement(ir.Z,null,l.createElement(r7.default,{className:r.footer},l.createElement(aA.Z,{href:"/runs",component:tz},"View More"))))))});function vt(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function vn(){var e=vt(["\n ","\n query FetchRecentJobRuns($offset: Int, $limit: Int) {\n jobRuns(offset: $offset, limit: $limit) {\n results {\n ...RecentJobRunsPayload_ResultsFields\n }\n metadata {\n total\n }\n }\n }\n"]);return vn=function(){return e},e}var vr=5,vi=n0(vn(),g9),va=function(){var e=rv(vi,{variables:{offset:0,limit:vr},fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error;return l.createElement(ve,{data:t,errorMsg:null==r?void 0:r.message,loading:n,maxRunsSize:vr})},vo=function(e){return(0,b.createStyles)({style:{textAlign:"center",padding:2.5*e.spacing.unit,position:"fixed",left:"0",bottom:"0",width:"100%",borderRadius:0},bareAnchor:{color:e.palette.common.black,textDecoration:"none"}})},vs=(0,b.withStyles)(vo)(function(e){var t=e.classes,n=(0,A.v9)(gE.N,A.wU),r=(0,A.I0)();return(0,l.useEffect)(function(){r((0,ty.DQ)())}),l.createElement(ii.default,{className:t.style},l.createElement(x.default,null,"Chainlink Node ",n.version," at commit"," ",l.createElement("a",{target:"_blank",rel:"noopener noreferrer",href:"https://github.com/smartcontractkit/chainlink/commit/".concat(n.commitSHA),className:t.bareAnchor},n.commitSHA)))}),vu=function(e){return(0,b.createStyles)({cell:{borderColor:e.palette.divider,borderTop:"1px solid",borderBottom:"none",paddingTop:2*e.spacing.unit,paddingBottom:2*e.spacing.unit,paddingLeft:2*e.spacing.unit},block:{display:"block"},overflowEllipsis:{textOverflow:"ellipsis",overflow:"hidden"}})},vc=(0,b.withStyles)(vu)(function(e){var t=e.classes,n=e.job;return l.createElement(ir.Z,null,l.createElement(r7.default,{scope:"row",className:t.cell},l.createElement(d.Z,{container:!0,spacing:0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(ih,{href:"/jobs/".concat(n.id),classes:{linkContent:t.block}},l.createElement(x.default,{className:t.overflowEllipsis,variant:"body1",component:"span",color:"primary"},n.name||n.id))),l.createElement(d.Z,{item:!0,xs:12},l.createElement(x.default,{variant:"body1",color:"textSecondary"},"Created ",l.createElement(aO,{tooltip:!0},n.createdAt))))))});function vl(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function vf(){var e=vl(["\n fragment RecentJobsPayload_ResultsFields on Job {\n id\n name\n createdAt\n }\n"]);return vf=function(){return e},e}var vd=n0(vf()),vh=function(){return(0,b.createStyles)({cardHeader:{borderBottom:0},table:{tableLayout:"fixed"}})},vp=(0,b.withStyles)(vh)(function(e){var t,n,r=e.classes,i=e.data,a=e.errorMsg,o=e.loading;return l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Recent Jobs",className:r.cardHeader}),l.createElement(r8.Z,{className:r.table},l.createElement(r9.Z,null,l.createElement(g$,{visible:o}),l.createElement(gz,{visible:(null===(t=null==i?void 0:i.jobs.results)||void 0===t?void 0:t.length)===0},"No recently created jobs"),l.createElement(gU,{msg:a}),null===(n=null==i?void 0:i.jobs.results)||void 0===n?void 0:n.map(function(e,t){return l.createElement(vc,{job:e,key:t})}))))});function vb(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function vm(){var e=vb(["\n ","\n query FetchRecentJobs($offset: Int, $limit: Int) {\n jobs(offset: $offset, limit: $limit) {\n results {\n ...RecentJobsPayload_ResultsFields\n }\n }\n }\n"]);return vm=function(){return e},e}var vg=5,vv=n0(vm(),vd),vy=function(){var e=rv(vv,{variables:{offset:0,limit:vg},fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error;return l.createElement(vp,{data:t,errorMsg:null==r?void 0:r.message,loading:n})},vw=function(){return l.createElement(ig,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:8},l.createElement(va,null)),l.createElement(d.Z,{item:!0,xs:4},l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(gY,null)),l.createElement(d.Z,{item:!0,xs:12},l.createElement(vy,null))))),l.createElement(vs,null))},v_=function(){return l.createElement(vw,null)},vE=function(){return l.createElement(v_,null)},vS=n(87239),vk=function(e){switch(e){case"DirectRequestSpec":return"Direct Request";case"FluxMonitorSpec":return"Flux Monitor";default:return e.replace(/Spec$/,"")}},vx=n(5022),vT=n(78718),vM=n.n(vT);function vO(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n1?t-1:0),r=1;r1?t-1:0),r=1;re.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&n.map(function(e){return l.createElement(ir.Z,{key:e.id,style:{cursor:"pointer"},onClick:function(){return r.push("/runs/".concat(e.id))}},l.createElement(r7.default,{className:t.idCell,scope:"row"},l.createElement("div",{className:t.runDetails},l.createElement(x.default,{variant:"h5",color:"primary",component:"span"},e.id))),l.createElement(r7.default,{className:t.stampCell},l.createElement(x.default,{variant:"body1",color:"textSecondary",className:t.stamp},"Created ",l.createElement(aO,{tooltip:!0},e.createdAt))),l.createElement(r7.default,{className:t.statusCell,scope:"row"},l.createElement(x.default,{variant:"body1",className:O()(t.status,yh(t,e.status))},e.status.toLowerCase())))})))}),yb=n(16839),ym=n.n(yb);function yg(e){var t=e.replace(/\w+\s*=\s*<([^>]|[\r\n])*>/g,""),n=ym().read(t),r=n.edges();return n.nodes().map(function(e){var t={id:e,parentIds:r.filter(function(t){return t.w===e}).map(function(e){return e.v})};return Object.keys(n.node(e)).length>0&&(t.attributes=n.node(e)),t})}var yv=n(94164),yy=function(e){var t=e.data,n=[];return(null==t?void 0:t.attributes)&&Object.keys(t.attributes).forEach(function(e){var r;n.push(l.createElement("div",{key:e},l.createElement(x.default,{variant:"body1",color:"textSecondary",component:"div"},l.createElement("b",null,e,":")," ",null===(r=t.attributes)||void 0===r?void 0:r[e])))}),l.createElement("div",null,t&&l.createElement(x.default,{variant:"body1",color:"textPrimary"},l.createElement("b",null,t.id)),n)},yw=n(73343),y_=n(3379),yE=n.n(y_);function yS(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);nwindow.innerWidth?u-r.getBoundingClientRect().width-a:u+a,n=c+r.getBoundingClientRect().height+i>window.innerHeight?c-r.getBoundingClientRect().height-a:c+a,r.style.opacity=String(1),r.style.top="".concat(n,"px"),r.style.left="".concat(t,"px"),r.style.zIndex=String(1)}},h=function(e){var t=document.getElementById("tooltip-d3-chart-".concat(e));t&&(t.style.opacity=String(0),t.style.zIndex=String(-1))};return l.createElement("div",{style:{fontFamily:"sans-serif",fontWeight:"normal"}},l.createElement(yv.kJ,{id:"task-list-graph-d3",data:i,config:s,onMouseOverNode:d,onMouseOutNode:h},"D3 chart"),n.map(function(e){return l.createElement("div",{key:"d3-tooltip-key-".concat(e.id),id:"tooltip-d3-chart-".concat(e.id),style:{position:"absolute",opacity:"0",border:"1px solid rgba(0, 0, 0, 0.1)",padding:yw.r.spacing.unit,background:"white",borderRadius:5,zIndex:-1,inlineSize:"min-content"}},l.createElement(yy,{data:e}))}))};function yL(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);nyY&&l.createElement("div",{className:t.runDetails},l.createElement(aA.Z,{href:"/jobs/".concat(n.id,"/runs"),component:tz},"View more")))),l.createElement(d.Z,{item:!0,xs:12,sm:6},l.createElement(yF,{observationSource:n.observationSource})))});function yH(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&void 0!==arguments[0]?arguments[0]:"";try{return vx.parse(e),!0}catch(t){return!1}})}),wW=function(e){var t=e.initialValues,n=e.onSubmit,r=e.onTOMLChange;return l.createElement(hT,{initialValues:t,validationSchema:wG,onSubmit:n},function(e){var t=e.isSubmitting,n=e.values;return r&&r(n.toml),l.createElement(hR,{"data-testid":"job-form",noValidate:!0},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:hX,id:"toml",name:"toml",label:"Job Spec (TOML)",required:!0,fullWidth:!0,multiline:!0,rows:10,rowsMax:25,variant:"outlined",autoComplete:"off",FormHelperTextProps:{"data-testid":"toml-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(ok.default,{variant:"contained",color:"primary",type:"submit",disabled:t,size:"large"},"Create Job"))))})},wK=n(50109),wV="persistSpec";function wq(e){var t=e.query,n=new URLSearchParams(t).get("definition");return n?(wK.t8(wV,n),{toml:n}):{toml:wK.U2(wV)||""}}var wZ=function(e){var t=e.onSubmit,n=e.onTOMLChange,r=wq({query:(0,h.TH)().search}),i=function(e){var t=e.replace(/[\u200B-\u200D\uFEFF]/g,"");wK.t8("".concat(wV),t),n&&n(t)};return l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"New Job"}),l.createElement(aW.Z,null,l.createElement(wW,{initialValues:r,onSubmit:t,onTOMLChange:i})))};function wX(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n1&&void 0!==arguments[1]?arguments[1]:{},n=t.start,r=void 0===n?6:n,i=t.end,a=void 0===i?4:i;return e.substring(0,r)+"..."+e.substring(e.length-a)}function _M(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(_W,e)},_V=function(){var e=_K({fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error,i=e.refetch;return l.createElement(_U,{loading:n,data:t,errorMsg:null==r?void 0:r.message,refetch:i})},_q=function(e){var t=e.csaKey;return l.createElement(ir.Z,{hover:!0},l.createElement(r7.default,null,l.createElement(x.default,{variant:"body1"},t.publicKey," ",l.createElement(_x,{data:t.publicKey}))))};function _Z(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function _X(){var e=_Z(["\n fragment CSAKeysPayload_ResultsFields on CSAKey {\n id\n publicKey\n }\n"]);return _X=function(){return e},e}var _J=n0(_X()),_Q=function(e){var t,n,r,i=e.data,a=e.errorMsg,o=e.loading,s=e.onCreate;return l.createElement(r5.Z,null,l.createElement(sl.Z,{action:(null===(t=null==i?void 0:i.csaKeys.results)||void 0===t?void 0:t.length)===0&&l.createElement(ok.default,{variant:"outlined",color:"primary",onClick:s},"New CSA Key"),title:"CSA Key",subheader:"Manage your CSA Key"}),l.createElement(r8.Z,null,l.createElement(ie.Z,null,l.createElement(ir.Z,null,l.createElement(r7.default,null,"Public Key"))),l.createElement(r9.Z,null,l.createElement(g$,{visible:o}),l.createElement(gz,{visible:(null===(n=null==i?void 0:i.csaKeys.results)||void 0===n?void 0:n.length)===0}),l.createElement(gU,{msg:a}),null===(r=null==i?void 0:i.csaKeys.results)||void 0===r?void 0:r.map(function(e,t){return l.createElement(_q,{csaKey:e,key:t})}))))};function _1(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(EM,e)};function EA(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(EJ,e)},E3=function(){return oo(EQ)},E4=function(){return oo(E1)},E6=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return rv(E0,e)};function E5(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(SK,e)};function Sq(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function kV(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}var kq=function(e){var t=e.run,n=l.useMemo(function(){var e=t.inputs,n=t.outputs,r=t.taskRuns,i=kK(t,["inputs","outputs","taskRuns"]),a={};try{a=JSON.parse(e)}catch(o){a={}}return kW(kz({},i),{inputs:a,outputs:n,taskRuns:r})},[t]);return l.createElement(r5.Z,null,l.createElement(aW.Z,null,l.createElement(kH,{object:n})))};function kZ(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function kX(e){for(var t=1;t0&&l.createElement(kr,{errors:t.allErrors})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(h.rs,null,l.createElement(h.AW,{path:"".concat(n,"/json")},l.createElement(kq,{run:t})),l.createElement(h.AW,{path:n},t.taskRuns.length>0&&l.createElement(kN,{taskRuns:t.taskRuns,observationSource:t.job.observationSource}))))))))};function k5(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function k8(){var e=k5(["\n ","\n query FetchJobRun($id: ID!) {\n jobRun(id: $id) {\n __typename\n ... on JobRun {\n ...JobRunPayload_Fields\n }\n ... on NotFoundError {\n message\n }\n }\n }\n"]);return k8=function(){return e},e}var k9=n0(k8(),k4),k7=function(){var e=rv(k9,{variables:{id:(0,h.UO)().id}}),t=e.data,n=e.loading,r=e.error;if(n)return l.createElement(iR,null);if(r)return l.createElement(iD,{error:r});var i=null==t?void 0:t.jobRun;switch(null==i?void 0:i.__typename){case"JobRun":return l.createElement(k6,{run:i});case"NotFoundError":return l.createElement(oa,null);default:return null}};function xe(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xt(){var e=xe(["\n fragment JobRunsPayload_ResultsFields on JobRun {\n id\n allErrors\n createdAt\n finishedAt\n status\n job {\n id\n }\n }\n"]);return xt=function(){return e},e}var xn=n0(xt()),xr=function(e){var t=e.loading,n=e.data,r=e.page,i=e.pageSize,a=(0,h.k6)(),o=l.useMemo(function(){return null==n?void 0:n.jobRuns.results.map(function(e){var t,n=e.allErrors,r=e.id,i=e.createdAt;return{id:r,createdAt:i,errors:n,finishedAt:e.finishedAt,status:e.status}})},[n]);return l.createElement(ig,null,l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:12},l.createElement(iy,null,"Job Runs")),t&&l.createElement(iR,null),n&&o&&l.createElement(d.Z,{item:!0,xs:12},l.createElement(r5.Z,null,l.createElement(yp,{runs:o}),l.createElement(it.Z,{component:"div",count:n.jobRuns.metadata.total,rowsPerPage:i,rowsPerPageOptions:[i],page:r-1,onChangePage:function(e,t){a.push("/runs?page=".concat(t+1,"&per=").concat(i))},onChangeRowsPerPage:function(){},backIconButtonProps:{"aria-label":"prev-page"},nextIconButtonProps:{"aria-label":"next-page"}})))))};function xi(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xa(){var e=xi(["\n ","\n query FetchJobRuns($offset: Int, $limit: Int) {\n jobRuns(offset: $offset, limit: $limit) {\n results {\n ...JobRunsPayload_ResultsFields\n }\n metadata {\n total\n }\n }\n }\n"]);return xa=function(){return e},e}var xo=n0(xa(),xn),xs=function(){var e=ij(),t=parseInt(e.get("page")||"1",10),n=parseInt(e.get("per")||"25",10),r=rv(xo,{variables:{offset:(t-1)*n,limit:n},fetchPolicy:"cache-and-network"}),i=r.data,a=r.loading,o=r.error;return o?l.createElement(iD,{error:o}):l.createElement(xr,{loading:a,data:i,page:t,pageSize:n})},xu=function(){var e=(0,h.$B)().path;return l.createElement(h.rs,null,l.createElement(h.AW,{exact:!0,path:e},l.createElement(xs,null)),l.createElement(h.AW,{path:"".concat(e,"/:id")},l.createElement(k7,null)))};function xc(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xl(){var e=xc(["\n fragment FetchFeedsManagersPayload_ResultsFields on FeedsManager {\n __typename\n id\n name\n uri\n publicKey\n isConnectionActive\n createdAt\n disabledAt\n }\n query FetchFeedsManagers {\n feedsManagers {\n results {\n ...FetchFeedsManagersPayload_ResultsFields\n }\n }\n }\n"]);return xl=function(){return e},e}var xf=n0(xl()),xd=function(e){return rv(xf,e)},xh=n(47559),xp=n(83165),xb=n(47298),xm=n(81395),xg=function(){return(0,b.createStyles)({root:{display:"flex"},activeIcon:{color:xh.default[500]},inactiveIcon:{color:xp.default[500]},text:{marginLeft:4}})},xv=(0,b.withStyles)(xg)(function(e){var t=e.isActive,n=e.activeText,r=e.inactiveText,i=e.classes;return l.createElement("div",{className:i.root},t?l.createElement(xm.Z,{fontSize:"small",className:i.activeIcon}):l.createElement(xb.Z,{fontSize:"small",className:i.inactiveIcon}),l.createElement(x.default,{variant:"body1",inline:!0,className:i.text},t?n:r))}),xy=(0,b.withStyles)(iu)(function(e){var t=e.jobDistributor,n=e.classes;return l.createElement(ir.Z,{className:n.row,hover:!0},l.createElement(r7.default,{className:n.cell,component:"th",scope:"row"},l.createElement(ih,{className:n.link,href:"/job_distributors/".concat(t.id)},t.name)),l.createElement(r7.default,null,l.createElement(xv,{isActive:t.isConnectionActive,activeText:"Connected",inactiveText:"Disconnected"})),l.createElement(r7.default,null,l.createElement(xv,{isActive:!t.disabledAt,activeText:"Enabled",inactiveText:"Disabled"})),l.createElement(r7.default,null,_T(t.publicKey,{start:6,end:6}),l.createElement(_x,{data:t.publicKey})),l.createElement(r7.default,null,t.uri))}),xw=function(e){var t=e.jobDistributors;return l.createElement(ig,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:9},l.createElement(iy,null,"Job Distributors")),l.createElement(d.Z,{item:!0,xs:3},l.createElement(d.Z,{container:!0,justify:"flex-end"},l.createElement(d.Z,{item:!0},l.createElement(aA.Z,{variant:"secondary",component:tz,href:"/job_distributors/new"},"New Job Distributor")))),l.createElement(d.Z,{item:!0,xs:12},l.createElement(r5.Z,null,l.createElement(r8.Z,null,l.createElement(ie.Z,null,l.createElement(ir.Z,null,l.createElement(r7.default,null,"Name"),l.createElement(r7.default,null,"Connection Status"),l.createElement(r7.default,null,"Status"),l.createElement(r7.default,null,"CSA Public Key"),l.createElement(r7.default,null,"RPC URL"))),l.createElement(r9.Z,null,0===t.length&&l.createElement(ir.Z,null,l.createElement(r7.default,{component:"th",scope:"row",colSpan:3},"Job Distributors have not been registered")),t.map(function(e){return l.createElement(xy,{key:e.id,jobDistributor:e})})))))))},x_=function(){var e,t=xd({fetchPolicy:"cache-and-network"}),n=t.data,r=t.loading,i=t.error;return r?l.createElement(iR,null):i?l.createElement(iD,{error:i}):l.createElement(xw,{jobDistributors:null!==(e=null==n?void 0:n.feedsManagers.results)&&void 0!==e?e:[]})},xE=bv().shape({name:p0().required("Required"),uri:p0().required("Required"),publicKey:p0().required("Required")}),xS=function(e){var t=e.initialValues,n=e.onSubmit;return l.createElement(hT,{initialValues:t,validationSchema:xE,onSubmit:n},function(e){var t=e.isSubmitting,n=e.submitForm;return l.createElement(hR,{"data-testid":"feeds-manager-form"},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"name",name:"name",label:"Name",required:!0,fullWidth:!0,FormHelperTextProps:{"data-testid":"name-helper-text"}})),l.createElement(d.Z,{item:!0,xs:!1,md:6}),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"uri",name:"uri",label:"URI",required:!0,fullWidth:!0,helperText:"Provided by the Job Distributor operator",FormHelperTextProps:{"data-testid":"uri-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"publicKey",name:"publicKey",label:"Public Key",required:!0,fullWidth:!0,helperText:"Provided by the Job Distributor operator",FormHelperTextProps:{"data-testid":"publicKey-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(ok.default,{variant:"contained",color:"primary",disabled:t,onClick:n},"Submit"))))})},xk=function(e){var t=e.data,n=e.onSubmit,r={name:t.name,uri:t.uri,publicKey:t.publicKey};return l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12,md:11,lg:9},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Edit Job Distributor"}),l.createElement(aW.Z,null,l.createElement(xS,{initialValues:r,onSubmit:n})))))};function xx(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(xZ,e)},xJ=function(){return(0,b.createStyles)({root:{fontSize:24}})},xQ=(0,b.withStyles)(xJ)(function(e){var t=e.children,n=e.classes;return l.createElement(x.default,{variant:"h2",className:n.root},t)}),x1=n(9290),x0=n(74923);function x2(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function TT(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}function TM(e,t){return Tv(e)||TE(e,t)||TA(e,t)||TS()}function TO(e){return Ty(e)||T_(e)||TA(e)||Tk()}function TA(e,t){if(e){if("string"==typeof e)return Tg(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(n);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return Tg(e,t)}}var TL=function(e){return"SN_MAIN"===e||"SN_SEPOLIA"===e},TC=bv().shape({chainID:p0().required("Required"),chainType:p0().required("Required"),accountAddr:p0().required("Required"),accountAddrPubKey:p0().nullable(),adminAddr:p0(),ocr1Multiaddr:p0().when(["ocr1Enabled","ocr1IsBootstrap"],{is:function(e,t){return e&&t},then:p0().required("Required").nullable()}).nullable(),ocr1P2PPeerID:p0().when(["ocr1Enabled","ocr1IsBootstrap"],{is:function(e,t){return e&&!t},then:p0().required("Required").nullable()}).nullable(),ocr1KeyBundleID:p0().when(["ocr1Enabled","ocr1IsBootstrap"],{is:function(e,t){return e&&!t},then:p0().required("Required").nullable()}).nullable(),ocr2Multiaddr:p0().when(["ocr2Enabled","ocr2IsBootstrap"],{is:function(e,t){return e&&t},then:p0().required("Required").nullable()}).nullable(),ocr2P2PPeerID:p0().when(["ocr2Enabled","ocr2IsBootstrap"],{is:function(e,t){return e&&!t},then:p0().required("Required").nullable()}).nullable(),ocr2KeyBundleID:p0().when(["ocr2Enabled","ocr2IsBootstrap"],{is:function(e,t){return e&&!t},then:p0().required("Required").nullable()}).nullable(),ocr2CommitPluginEnabled:pV().required("Required"),ocr2ExecutePluginEnabled:pV().required("Required"),ocr2MedianPluginEnabled:pV().required("Required"),ocr2MercuryPluginEnabled:pV().required("Required"),ocr2ForwarderAddress:p0().nullable()}),TI=function(e){return(0,b.createStyles)({supportedJobOptionsPaper:{padding:2*e.spacing.unit}})},TD=function(e){var t=e.addresses,n=Tx(e,["addresses"]),r=h_(),i=r.values,a=i.chainID,o=i.accountAddr,s=r.setFieldValue,u=TM(l.useState(!1),2),c=u[0],f=u[1],d=l.useRef();l.useEffect(function(){d.current=a},[a]),l.useEffect(function(){a!==d.current&&(s(n.name,""),f(!1))},[a,s,n.name]);var h=function(e){var t=e.target.value;"custom"===t?(f(!0),s(n.name,"")):(f(!1),s(n.name,t))};return l.createElement(l.Fragment,null,!TL(a)&&l.createElement(hP,Tw({},n,{select:!0,value:c?"custom":o,onChange:h}),t.map(function(e){return l.createElement(tE.default,{key:e,value:e},e)})),TL(a)&&l.createElement(hP,{component:hX,id:"accountAddr",name:"accountAddr",label:"Enter your account address",inputProps:{"data-testid":"customAccountAddr-input"},helperText:"The account address used for this chain",required:!0,fullWidth:!0}),TL(a)&&l.createElement("div",null,l.createElement(hP,{component:hX,id:"accountAddrPubKey",name:"accountAddrPubKey",label:"Account Address Public Key",required:!0,fullWidth:!0,helperText:"The public key for your account address",FormHelperTextProps:{"data-testid":"accountAddrPubKey-helper-text"}})))},TN=(0,b.withStyles)(TI)(function(e){var t=e.classes,n=e.editing,r=void 0!==n&&n,i=e.innerRef,a=e.initialValues,o=e.onSubmit,s=e.chains,u=void 0===s?[]:s,c=e.accountsEVM,f=void 0===c?[]:c,h=e.accountsNonEvm,p=e.p2pKeys,b=void 0===p?[]:p,m=e.ocrKeys,g=void 0===m?[]:m,v=e.ocr2Keys,y=void 0===v?[]:v,w=e.showSubmit,_=void 0!==w&&w,E=TO(y).sort(function(e,t){var n,r,i;return e.chainType===t.chainType?e.id.localeCompare(t.id):null!==(i=null===(n=e.chainType)||void 0===n?void 0:n.localeCompare(null!==(r=t.chainType)&&void 0!==r?r:""))&&void 0!==i?i:0});return l.createElement(hT,{innerRef:i,initialValues:a,validationSchema:TC,onSubmit:o},function(e){var n,i,a=e.values,o=[];switch(a.chainType){case Tm.EVM:o=f.filter(function(e){return e.chain.id==a.chainID&&!e.isDisabled}).map(function(e){return e.address});break;case Tm.APTOS:o=null!==(n=null==h?void 0:h.aptosKeys.results.map(function(e){return e.account}))&&void 0!==n?n:[];break;case Tm.SOLANA:o=null!==(i=null==h?void 0:h.solanaKeys.results.map(function(e){return e.id}))&&void 0!==i?i:[];break;default:o=[]}var s=u.filter(function(e){return e.network.toUpperCase()===a.chainType});return l.createElement(hR,{"data-testid":"feeds-manager-form",id:"chain-configuration-form",noValidate:!0},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"chainType",name:"chainType",label:"Chain Type",select:!0,required:!0,fullWidth:!0,disabled:r},l.createElement(tE.default,{key:Tm.EVM,value:Tm.EVM},"EVM"),l.createElement(tE.default,{key:Tm.APTOS,value:Tm.APTOS},"APTOS"),l.createElement(tE.default,{key:Tm.SOLANA,value:Tm.SOLANA},"SOLANA"))),l.createElement(d.Z,{item:!0,xs:12,md:6},s.length>0&&!r?l.createElement(hP,{component:hX,id:"chainID",name:"chainID",label:"Chain ID",required:!0,fullWidth:!0,select:!0,disabled:r,inputProps:{"data-testid":"chainID-input"},FormHelperTextProps:{"data-testid":"chainID-helper-text"}},s.map(function(e){return l.createElement(tE.default,{key:e.id,value:e.id},e.id)})):l.createElement(hP,{component:hX,id:"chainID",name:"chainID",label:"Chain ID",required:!0,fullWidth:!0,disabled:r,inputProps:{"data-testid":"chainID-manual-input"},FormHelperTextProps:{"data-testid":"chainID-helper-manual-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:6},o.length>0?l.createElement(TD,{component:hX,id:"accountAddr",name:"accountAddr",label:"Account Address",inputProps:{"data-testid":"accountAddr-input"},required:!0,fullWidth:!0,select:!0,helperText:"The account address used for this chain",addresses:o,FormHelperTextProps:{"data-testid":"accountAddr-helper-text"}}):l.createElement(hP,{component:hX,id:"accountAddr",name:"accountAddr",label:"Account Address",inputProps:{"data-testid":"accountAddr-manual-input"},required:!0,fullWidth:!0,helperText:"The account address used for this chain",FormHelperTextProps:{"data-testid":"accountAddr-helper-manual-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"adminAddr",name:"adminAddr",label:"Admin Address",fullWidth:!0,helperText:"The address used for LINK payments",FormHelperTextProps:{"data-testid":"adminAddr-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(x.default,null,"Supported Job Types")),l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:h2,name:"fluxMonitorEnabled",type:"checkbox",Label:{label:"Flux Monitor"}})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:h2,name:"ocr1Enabled",type:"checkbox",Label:{label:"OCR"}}),a.ocr1Enabled&&l.createElement(ii.default,{className:t.supportedJobOptionsPaper},l.createElement(d.Z,{container:!0,spacing:8},l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:h2,name:"ocr1IsBootstrap",type:"checkbox",Label:{label:"Is this node running as a bootstrap peer?"}})),a.ocr1IsBootstrap?l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:hX,id:"ocr1Multiaddr",name:"ocr1Multiaddr",label:"Multiaddr",required:!0,fullWidth:!0,helperText:"The OCR Multiaddr which oracles use to query for network information",FormHelperTextProps:{"data-testid":"ocr1Multiaddr-helper-text"}})):l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"ocr1P2PPeerID",name:"ocr1P2PPeerID",label:"Peer ID",select:!0,required:!0,fullWidth:!0,helperText:"The Peer ID used for this chain",FormHelperTextProps:{"data-testid":"ocr1P2PPeerID-helper-text"}},b.map(function(e){return l.createElement(tE.default,{key:e.peerID,value:e.peerID},e.peerID)}))),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"ocr1KeyBundleID",name:"ocr1KeyBundleID",label:"Key Bundle ID",select:!0,required:!0,fullWidth:!0,helperText:"The OCR Key Bundle ID used for this chain",FormHelperTextProps:{"data-testid":"ocr1KeyBundleID-helper-text"}},g.map(function(e){return l.createElement(tE.default,{key:e.id,value:e.id},e.id)})))))))),l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:h2,name:"ocr2Enabled",type:"checkbox",Label:{label:"OCR2"}}),a.ocr2Enabled&&l.createElement(ii.default,{className:t.supportedJobOptionsPaper},l.createElement(d.Z,{container:!0,spacing:8},l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:h2,name:"ocr2IsBootstrap",type:"checkbox",Label:{label:"Is this node running as a bootstrap peer?"}})),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"ocr2P2PPeerID",name:"ocr2P2PPeerID",label:"Peer ID",select:!0,required:!a.ocr2IsBootstrap,fullWidth:!0,helperText:"The Peer ID used for this chain",FormHelperTextProps:{"data-testid":"ocr2P2PPeerID-helper-text"}},b.map(function(e){return l.createElement(tE.default,{key:e.peerID,value:e.peerID},e.peerID)}))),a.ocr2IsBootstrap?l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:hX,id:"ocr2Multiaddr",name:"ocr2Multiaddr",label:"Multiaddr",required:!0,fullWidth:!0,helperText:"The OCR2 Multiaddr which oracles use to query for network information",FormHelperTextProps:{"data-testid":"ocr2Multiaddr-helper-text"}})):l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"ocr2KeyBundleID",name:"ocr2KeyBundleID",label:"Key Bundle ID",select:!0,required:!0,fullWidth:!0,helperText:"The OCR2 Key Bundle ID used for this chain",FormHelperTextProps:{"data-testid":"ocr2KeyBundleID-helper-text"}},E.map(function(e){return l.createElement(tE.default,{key:e.id,value:e.id},e.id," (",e.chainType,")")}))),l.createElement(d.Z,{item:!0,xs:12},l.createElement(x.default,null,"Supported Plugins")),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hP,{component:h2,name:"ocr2CommitPluginEnabled",type:"checkbox",Label:{label:"Commit"}})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hP,{component:h2,name:"ocr2ExecutePluginEnabled",type:"checkbox",Label:{label:"Execute"}})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hP,{component:h2,name:"ocr2RebalancerPluginEnabled",type:"checkbox",Label:{label:"Rebalancer"}})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hP,{component:h2,name:"ocr2MedianPluginEnabled",type:"checkbox",Label:{label:"Median"}})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hP,{component:h2,name:"ocr2MercuryPluginEnabled",type:"checkbox",Label:{label:"Mercury"}})),l.createElement(d.Z,{item:!0,xs:12,md:12},l.createElement(hP,{component:hX,id:"ocr2ForwarderAddress",name:"ocr2ForwarderAddress",label:"Forwarder Address (optional)",fullWidth:!0,helperText:"The forwarder address from the Operator Forwarder Contract",FormHelperTextProps:{"data-testid":"ocr2ForwarderAddress-helper-text"}}))))))),_&&l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(ok.default,{variant:"contained",color:"primary",type:"submit",size:"large"},"Submit"))))})});function TP(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function TR(){var e=TP(["\n fragment AptosKeysPayload_ResultsFields on AptosKey {\n account\n id\n }\n"]);return TR=function(){return e},e}function Tj(){var e=TP(["\n fragment SolanaKeysPayload_ResultsFields on SolanaKey {\n id\n }\n"]);return Tj=function(){return e},e}function TF(){var e=TP(["\n ","\n ","\n query FetchNonEvmKeys {\n aptosKeys {\n results {\n ...AptosKeysPayload_ResultsFields\n }\n }\n solanaKeys {\n results {\n ...SolanaKeysPayload_ResultsFields\n }\n }\n }\n"]);return TF=function(){return e},e}var TY=n0(TR()),TB=n0(Tj()),TU=n0(TF(),TY,TB),TH=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return rv(TU,e)},T$=function(e){var t=e.onClose,n=e.open,r=e.onSubmit,i=l.useRef(),a=i$({fetchPolicy:"network-only"}).data,o=_K({fetchPolicy:"cache-and-network"}).data,s=TH({fetchPolicy:"cache-and-network"}).data,u=SV({fetchPolicy:"cache-and-network"}).data,c=EO({fetchPolicy:"cache-and-network"}).data,f=E2({fetchPolicy:"cache-and-network"}).data,d={chainID:"",chainType:Tm.EVM,accountAddr:"",adminAddr:"",accountAddrPubKey:"",fluxMonitorEnabled:!1,ocr1Enabled:!1,ocr1IsBootstrap:!1,ocr1Multiaddr:"",ocr1P2PPeerID:"",ocr1KeyBundleID:"",ocr2Enabled:!1,ocr2IsBootstrap:!1,ocr2Multiaddr:"",ocr2P2PPeerID:"",ocr2KeyBundleID:"",ocr2CommitPluginEnabled:!1,ocr2ExecutePluginEnabled:!1,ocr2MedianPluginEnabled:!1,ocr2MercuryPluginEnabled:!1,ocr2RebalancerPluginEnabled:!1,ocr2ForwarderAddress:""},h=a?a.chains.results:[],p=o?o.ethKeys.results:[],b=u?u.p2pKeys.results:[],m=c?c.ocrKeyBundles.results:[],g=f?f.ocr2KeyBundles.results:[];return l.createElement(aD.Z,{onClose:t,open:n,disableBackdropClick:!0},l.createElement(oO.Z,{disableTypography:!0},l.createElement(x.default,{variant:"body2"},"New Supported Chain")),l.createElement(oT.Z,null,l.createElement(TN,{innerRef:i,initialValues:d,onSubmit:r,chains:h,accountsEVM:p,accountsNonEvm:s,p2pKeys:b,ocrKeys:m,ocr2Keys:g})),l.createElement(ox.Z,null,l.createElement(ok.default,{onClick:t},"Cancel"),l.createElement(ok.default,{color:"primary",type:"submit",form:"chain-configuration-form",variant:"contained"},"Submit")))},Tz=function(e){var t=e.cfg,n=e.onClose,r=e.open,i=e.onSubmit,a=l.useRef(),o=i$({fetchPolicy:"network-only"}).data,s=_K({fetchPolicy:"cache-and-network"}).data,u=TH({fetchPolicy:"cache-and-network"}).data,c=SV({fetchPolicy:"cache-and-network"}).data,f=EO({fetchPolicy:"cache-and-network"}).data,d=E2({fetchPolicy:"cache-and-network"}).data;if(!t)return null;var h={chainID:t.chainID,chainType:t.chainType,accountAddr:t.accountAddr,adminAddr:t.adminAddr,accountAddrPubKey:t.accountAddrPubKey,fluxMonitorEnabled:t.fluxMonitorJobConfig.enabled,ocr1Enabled:t.ocr1JobConfig.enabled,ocr1IsBootstrap:t.ocr1JobConfig.isBootstrap,ocr1Multiaddr:t.ocr1JobConfig.multiaddr,ocr1P2PPeerID:t.ocr1JobConfig.p2pPeerID,ocr1KeyBundleID:t.ocr1JobConfig.keyBundleID,ocr2Enabled:t.ocr2JobConfig.enabled,ocr2IsBootstrap:t.ocr2JobConfig.isBootstrap,ocr2Multiaddr:t.ocr2JobConfig.multiaddr,ocr2P2PPeerID:t.ocr2JobConfig.p2pPeerID,ocr2KeyBundleID:t.ocr2JobConfig.keyBundleID,ocr2CommitPluginEnabled:t.ocr2JobConfig.plugins.commit,ocr2ExecutePluginEnabled:t.ocr2JobConfig.plugins.execute,ocr2MedianPluginEnabled:t.ocr2JobConfig.plugins.median,ocr2MercuryPluginEnabled:t.ocr2JobConfig.plugins.mercury,ocr2RebalancerPluginEnabled:t.ocr2JobConfig.plugins.rebalancer,ocr2ForwarderAddress:t.ocr2JobConfig.forwarderAddress},p=o?o.chains.results:[],b=s?s.ethKeys.results:[],m=c?c.p2pKeys.results:[],g=f?f.ocrKeyBundles.results:[],v=d?d.ocr2KeyBundles.results:[];return l.createElement(aD.Z,{onClose:n,open:r,disableBackdropClick:!0},l.createElement(oO.Z,{disableTypography:!0},l.createElement(x.default,{variant:"body2"},"Edit Supported Chain")),l.createElement(oT.Z,null,l.createElement(TN,{innerRef:a,initialValues:h,onSubmit:i,chains:p,accountsEVM:b,accountsNonEvm:u,p2pKeys:m,ocrKeys:g,ocr2Keys:v,editing:!0})),l.createElement(ox.Z,null,l.createElement(ok.default,{onClick:n},"Cancel"),l.createElement(ok.default,{color:"primary",type:"submit",form:"chain-configuration-form",variant:"contained"},"Submit")))};function TG(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);nt.version?e:t})},[o]),g=l.useMemo(function(){return M1(o).sort(function(e,t){return t.version-e.version})},[o]),v=function(e,t,n){switch(e){case"PENDING":return l.createElement(l.Fragment,null,l.createElement(ok.default,{variant:"text",color:"secondary",onClick:function(){return b("reject",t)}},"Reject"),m.id===t&&"DELETED"!==n.status&&"REVOKED"!==n.status&&l.createElement(ok.default,{variant:"contained",color:"primary",onClick:function(){return b("approve",t)}},"Approve"),m.id===t&&"DELETED"===n.status&&n.pendingUpdate&&l.createElement(l.Fragment,null,l.createElement(ok.default,{variant:"contained",color:"primary",onClick:function(){return b("cancel",t)}},"Cancel"),l.createElement(x.default,{color:"error"},"This proposal was deleted. Cancel the spec to delete any running jobs")));case"APPROVED":return l.createElement(l.Fragment,null,l.createElement(ok.default,{variant:"contained",onClick:function(){return b("cancel",t)}},"Cancel"),"DELETED"===n.status&&n.pendingUpdate&&l.createElement(x.default,{color:"error"},"This proposal was deleted. Cancel the spec to delete any running jobs"));case"CANCELLED":if(m.id===t&&"DELETED"!==n.status&&"REVOKED"!==n.status)return l.createElement(ok.default,{variant:"contained",color:"primary",onClick:function(){return b("approve",t)}},"Approve");return null;default:return null}};return l.createElement("div",null,g.map(function(e,n){return l.createElement(mP.Z,{defaultExpanded:0===n,key:n},l.createElement(mR.Z,{expandIcon:l.createElement(gh.Z,null)},l.createElement(x.default,{className:t.versionText},"Version ",e.version),l.createElement(Es.Z,{label:e.status,color:"APPROVED"===e.status?"primary":"default",variant:"REJECTED"===e.status||"CANCELLED"===e.status?"outlined":"default"}),l.createElement("div",{className:t.proposedAtContainer},l.createElement(x.default,null,"Proposed ",l.createElement(aO,{tooltip:!0},e.createdAt)))),l.createElement(mj.Z,{className:t.expansionPanelDetails},l.createElement("div",{className:t.actions},l.createElement("div",{className:t.editContainer},0===n&&("PENDING"===e.status||"CANCELLED"===e.status)&&"DELETED"!==s.status&&"REVOKED"!==s.status&&l.createElement(ok.default,{variant:"contained",onClick:function(){return p(!0)}},"Edit")),l.createElement("div",{className:t.actionsContainer},v(e.status,e.id,s))),l.createElement(gd,{language:"toml",style:gs,"data-testid":"codeblock"},e.definition)))}),l.createElement(oC,{open:null!=c,title:c?M6[c.action].title:"",body:c?M6[c.action].body:"",onConfirm:function(){if(c){switch(c.action){case"approve":n(c.id);break;case"cancel":r(c.id);break;case"reject":i(c.id)}f(null)}},cancelButtonText:"Cancel",onCancel:function(){return f(null)}}),l.createElement(Mz,{open:h,onClose:function(){return p(!1)},initialValues:{definition:m.definition,id:m.id},onSubmit:a}))});function M8(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function M9(){var e=M8(["\n ","\n fragment JobProposalPayloadFields on JobProposal {\n id\n externalJobID\n remoteUUID\n jobID\n specs {\n ...JobProposal_SpecsFields\n }\n status\n pendingUpdate\n }\n"]);return M9=function(){return e},e}var M7=n0(M9(),M3),Oe=function(e){var t=e.onApprove,n=e.onCancel,r=e.onReject,i=e.onUpdateSpec,a=e.proposal;return l.createElement(ig,null,l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:9},l.createElement(iy,null,"Job Proposal #",a.id))),l.createElement(MF,{proposal:a}),l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:9},l.createElement(xQ,null,"Specs"))),l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:12},l.createElement(M5,{proposal:a,specs:a.specs,onReject:r,onApprove:t,onCancel:n,onUpdateSpec:i}))))};function Ot(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);nU,tA:()=>$,KL:()=>H,Iw:()=>V,DQ:()=>W,cB:()=>T,LO:()=>M,t5:()=>k,qt:()=>x,Jc:()=>C,L7:()=>Y,EO:()=>B});var r,i,a=n(66289),o=n(41800),s=n.n(o),u=n(67932);(i=r||(r={})).IN_PROGRESS="in_progress",i.PENDING_INCOMING_CONFIRMATIONS="pending_incoming_confirmations",i.PENDING_CONNECTION="pending_connection",i.PENDING_BRIDGE="pending_bridge",i.PENDING_SLEEP="pending_sleep",i.ERRORED="errored",i.COMPLETED="completed";var c=n(87013),l=n(19084),f=n(34823);function d(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]j,v2:()=>F});var r=n(66289);function i(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var a="/sessions",o="/sessions",s=function e(t){var n=this;i(this,e),this.api=t,this.createSession=function(e){return n.create(e)},this.destroySession=function(){return n.destroy()},this.create=this.api.createResource(a),this.destroy=this.api.deleteResource(o)};function u(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var c="/v2/bulk_delete_runs",l=function e(t){var n=this;u(this,e),this.api=t,this.bulkDeleteJobRuns=function(e){return n.destroy(e)},this.destroy=this.api.deleteResource(c)};function f(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var d="/v2/chains/evm",h="".concat(d,"/:id"),p=function e(t){var n=this;f(this,e),this.api=t,this.getChains=function(){return n.index()},this.createChain=function(e){return n.create(e)},this.destroyChain=function(e){return n.destroy(void 0,{id:e})},this.updateChain=function(e,t){return n.update(t,{id:e})},this.index=this.api.fetchResource(d),this.create=this.api.createResource(d),this.destroy=this.api.deleteResource(h),this.update=this.api.updateResource(h)};function b(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var m="/v2/keys/evm/chain",g=function e(t){var n=this;b(this,e),this.api=t,this.chain=function(e){var t=new URLSearchParams;t.append("address",e.address),t.append("evmChainID",e.evmChainID),null!==e.abandon&&t.append("abandon",String(e.abandon)),null!==e.enabled&&t.append("enabled",String(e.enabled));var r=m+"?"+t.toString();return n.api.createResource(r)()}};function v(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var y="/v2/jobs",w="".concat(y,"/:specId/runs"),_=function e(t){var n=this;v(this,e),this.api=t,this.createJobRunV2=function(e,t){return n.post(t,{specId:e})},this.post=this.api.createResource(w,!0)};function E(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var S="/v2/log",k=function e(t){var n=this;E(this,e),this.api=t,this.getLogConfig=function(){return n.show()},this.updateLogConfig=function(e){return n.update(e)},this.show=this.api.fetchResource(S),this.update=this.api.updateResource(S)};function x(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var T="/v2/nodes",M=function e(t){var n=this;x(this,e),this.api=t,this.getNodes=function(){return n.index()},this.createNode=function(e){return n.create(e)},this.index=this.api.fetchResource(T),this.create=this.api.createResource(T)};function O(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var A="/v2/enroll_webauthn",L=function e(t){var n=this;O(this,e),this.api=t,this.beginKeyRegistration=function(e){return n.create(e)},this.finishKeyRegistration=function(e){return n.put(e)},this.create=this.api.fetchResource(A),this.put=this.api.createResource(A)};function C(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var I="/v2/build_info",D=function e(t){var n=this;C(this,e),this.api=t,this.show=function(){return n.api.GET(I)()}};function N(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var P=function e(t){N(this,e),this.api=t,this.buildInfo=new D(this.api),this.bulkDeleteRuns=new l(this.api),this.chains=new p(this.api),this.logConfig=new k(this.api),this.nodes=new M(this.api),this.jobs=new _(this.api),this.webauthn=new L(this.api),this.evmKeys=new g(this.api)},R=new r.V0({base:void 0}),j=new s(R),F=new P(R)},1398(e,t,n){"use strict";n.d(t,{Z:()=>d});var r=n(67294),i=n(32316),a=n(83638),o=n(94184),s=n.n(o);function u(){return(u=Object.assign||function(e){for(var t=1;tc});var r=n(67294),i=n(32316);function a(){return(a=Object.assign||function(e){for(var t=1;tx,jK:()=>v});var r=n(67294),i=n(37703),a=n(45697),o=n.n(a),s=n(82204),u=n(71426),c=n(94184),l=n.n(c),f=n(32316),d=function(e){var t=e.palette.success||{},n=e.palette.warning||{};return{base:{paddingLeft:5*e.spacing.unit,paddingRight:5*e.spacing.unit},success:{backgroundColor:t.main,color:t.contrastText},error:{backgroundColor:e.palette.error.dark,color:e.palette.error.contrastText},warning:{backgroundColor:n.contrastText,color:n.main}}},h=function(e){var t,n=e.success,r=e.error,i=e.warning,a=e.classes,o=e.className;return n?t=a.success:r?t=a.error:i&&(t=a.warning),l()(a.base,o,t)},p=function(e){return r.createElement(s.Z,{className:h(e),square:!0},r.createElement(u.default,{variant:"body2",color:"inherit",component:"div"},e.children))};p.defaultProps={success:!1,error:!1,warning:!1},p.propTypes={success:o().bool,error:o().bool,warning:o().bool};let b=(0,f.withStyles)(d)(p);var m=function(){return r.createElement(r.Fragment,null,"Unhandled error. Please help us by opening a"," ",r.createElement("a",{href:"https://github.com/smartcontractkit/chainlink/issues/new"},"bug report"))};let g=m;function v(e){return"string"==typeof e?e:e.component?e.component(e.props):r.createElement(g,null)}function y(e,t){var n;return n="string"==typeof e?e:e.component?e.component(e.props):r.createElement(g,null),r.createElement("p",{key:t},n)}var w=function(e){var t=e.notifications;return r.createElement(b,{error:!0},t.map(y))},_=function(e){var t=e.notifications;return r.createElement(b,{success:!0},t.map(y))},E=function(e){var t=e.errors,n=e.successes;return r.createElement("div",null,(null==t?void 0:t.length)>0&&r.createElement(w,{notifications:t}),n.length>0&&r.createElement(_,{notifications:n}))},S=function(e){return{errors:e.notifications.errors,successes:e.notifications.successes}},k=(0,i.$j)(S)(E);let x=k},9409(e,t,n){"use strict";n.d(t,{ZP:()=>j});var r=n(67294),i=n(37703),a=n(5977),o=n(32316),s=n(1398),u=n(82204),c=n(30060),l=n(71426),f=n(60520),d=n(39814),h=n(57209),p=n(26842),b=n(3950),m=n(5536),g=n(45697),v=n.n(g);let y=n.p+"9f6d832ef97e8493764e.svg";function w(){return(w=Object.assign||function(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&_.map(function(e,t){return r.createElement(d.Z,{item:!0,xs:12,key:t},r.createElement(u.Z,{raised:!1,className:v.error},r.createElement(c.Z,null,r.createElement(l.default,{variant:"body1",className:v.errorText},(0,b.jK)(e)))))}),r.createElement(d.Z,{item:!0,xs:12},r.createElement(f.Z,{id:"email",label:"Email",margin:"normal",value:n,onChange:m("email"),error:_.length>0,variant:"outlined",fullWidth:!0})),r.createElement(d.Z,{item:!0,xs:12},r.createElement(f.Z,{id:"password",label:"Password",type:"password",autoComplete:"password",margin:"normal",value:h,onChange:m("password"),error:_.length>0,variant:"outlined",fullWidth:!0})),r.createElement(d.Z,{item:!0,xs:12},r.createElement(d.Z,{container:!0,spacing:0,justify:"center"},r.createElement(d.Z,{item:!0},r.createElement(s.Z,{type:"submit",variant:"primary"},"Access Account")))),y&&r.createElement(l.default,{variant:"body1",color:"textSecondary"},"Signing in...")))))))},P=function(e){return{fetching:e.authentication.fetching,authenticated:e.authentication.allowed,errors:e.notifications.errors}},R=(0,i.$j)(P,x({submitSignIn:p.L7}))(N);let j=(0,h.wU)(e)((0,o.withStyles)(D)(R))},16353(e,t,n){"use strict";n.d(t,{ZP:()=>H,rH:()=>U});var r,i=n(37703),a=n(97779),o=n(9541),s=n(19084);function u(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:h,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case s.Mk.RECEIVE_SIGNOUT_SUCCESS:case s.Mk.RECEIVE_SIGNIN_SUCCESS:var n={allowed:t.authenticated};return o.Ks(n),f(c({},e,n),{errors:[]});case s.Mk.RECEIVE_SIGNIN_FAIL:var r={allowed:!1};return o.Ks(r),f(c({},e,r),{errors:[]});case s.Mk.RECEIVE_SIGNIN_ERROR:case s.Mk.RECEIVE_SIGNOUT_ERROR:var i={allowed:!1};return o.Ks(i),f(c({},e,i),{errors:t.errors||[]});default:return e}};let b=p;function m(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function g(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:_,t=arguments.length>1?arguments[1]:void 0;return t.type?t.type.startsWith(r.REQUEST)?y(g({},e),{count:e.count+1}):t.type.startsWith(r.RECEIVE)?y(g({},e),{count:Math.max(e.count-1,0)}):t.type.startsWith(r.RESPONSE)?y(g({},e),{count:Math.max(e.count-1,0)}):t.type===s.di.REDIRECT?y(g({},e),{count:0}):e:e};let S=E;function k(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function x(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:O,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case s.di.MATCH_ROUTE:return M(x({},O),{currentUrl:t.pathname});case s.Ih.NOTIFY_SUCCESS:var n={component:t.component,props:t.props};return M(x({},e),{successes:[n],errors:[]});case s.Ih.NOTIFY_SUCCESS_MSG:return M(x({},e),{successes:[t.msg],errors:[]});case s.Ih.NOTIFY_ERROR:var r=t.error.errors,i=null==r?void 0:r.map(function(e){return L(t,e)});return M(x({},e),{successes:[],errors:i});case s.Ih.NOTIFY_ERROR_MSG:return M(x({},e),{successes:[],errors:[t.msg]});case s.Mk.RECEIVE_SIGNIN_FAIL:return M(x({},e),{successes:[],errors:["Your email or password is incorrect. Please try again"]});default:return e}};function L(e,t){return{component:e.component,props:{msg:t.detail}}}let C=A;function I(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function D(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:R,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case s.di.REDIRECT:return P(D({},e),{to:t.to});case s.di.MATCH_ROUTE:return P(D({},e),{to:void 0});default:return e}};let F=j;var Y=n(87013),B=(0,a.UY)({authentication:b,fetching:S,notifications:C,redirect:F,buildInfo:Y.Z});B(void 0,{type:"INITIAL_STATE"});var U=i.v9;let H=B},19084(e,t,n){"use strict";var r,i,a,o,s,u,c,l,f,d;n.d(t,{Ih:()=>i,Mk:()=>a,Y0:()=>s,di:()=>r,jp:()=>o}),n(67294),(u=r||(r={})).REDIRECT="REDIRECT",u.MATCH_ROUTE="MATCH_ROUTE",(c=i||(i={})).NOTIFY_SUCCESS="NOTIFY_SUCCESS",c.NOTIFY_SUCCESS_MSG="NOTIFY_SUCCESS_MSG",c.NOTIFY_ERROR="NOTIFY_ERROR",c.NOTIFY_ERROR_MSG="NOTIFY_ERROR_MSG",(l=a||(a={})).REQUEST_SIGNIN="REQUEST_SIGNIN",l.RECEIVE_SIGNIN_SUCCESS="RECEIVE_SIGNIN_SUCCESS",l.RECEIVE_SIGNIN_FAIL="RECEIVE_SIGNIN_FAIL",l.RECEIVE_SIGNIN_ERROR="RECEIVE_SIGNIN_ERROR",l.RECEIVE_SIGNOUT_SUCCESS="RECEIVE_SIGNOUT_SUCCESS",l.RECEIVE_SIGNOUT_ERROR="RECEIVE_SIGNOUT_ERROR",(f=o||(o={})).RECEIVE_CREATE_ERROR="RECEIVE_CREATE_ERROR",f.RECEIVE_CREATE_SUCCESS="RECEIVE_CREATE_SUCCESS",f.RECEIVE_DELETE_ERROR="RECEIVE_DELETE_ERROR",f.RECEIVE_DELETE_SUCCESS="RECEIVE_DELETE_SUCCESS",f.RECEIVE_UPDATE_ERROR="RECEIVE_UPDATE_ERROR",f.RECEIVE_UPDATE_SUCCESS="RECEIVE_UPDATE_SUCCESS",f.REQUEST_CREATE="REQUEST_CREATE",f.REQUEST_DELETE="REQUEST_DELETE",f.REQUEST_UPDATE="REQUEST_UPDATE",f.UPSERT_CONFIGURATION="UPSERT_CONFIGURATION",f.UPSERT_JOB_RUN="UPSERT_JOB_RUN",f.UPSERT_JOB_RUNS="UPSERT_JOB_RUNS",f.UPSERT_TRANSACTION="UPSERT_TRANSACTION",f.UPSERT_TRANSACTIONS="UPSERT_TRANSACTIONS",f.UPSERT_BUILD_INFO="UPSERT_BUILD_INFO",(d=s||(s={})).FETCH_BUILD_INFO_REQUESTED="FETCH_BUILD_INFO_REQUESTED",d.FETCH_BUILD_INFO_SUCCEEDED="FETCH_BUILD_INFO_SUCCEEDED",d.FETCH_BUILD_INFO_FAILED="FETCH_BUILD_INFO_FAILED"},87013(e,t,n){"use strict";n.d(t,{Y:()=>o,Z:()=>u});var r=n(19084);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:o,t=arguments.length>1?arguments[1]:void 0;return t.type===r.Y0.FETCH_BUILD_INFO_SUCCEEDED?a({},t.buildInfo):e};let u=s},34823(e,t,n){"use strict";n.d(t,{N:()=>r});var r=function(e){return e.buildInfo}},73343(e,t,n){"use strict";n.d(t,{r:()=>u});var r=n(19350),i=n(32316),a=n(59114),o=n(5324),s={props:{MuiGrid:{spacing:3*o.default.unit},MuiCardHeader:{titleTypographyProps:{color:"secondary"}}},palette:{action:{hoverOpacity:.3},primary:{light:"#E5F1FF",main:"#3c40c6",contrastText:"#fff"},secondary:{main:"#3d5170"},success:{light:"#e8faf1",main:r.ek.A700,dark:r.ek[700],contrastText:r.y0.white},warning:{light:"#FFFBF1",main:"#fff6b6",contrastText:"#fad27a"},error:{light:"#ffdada",main:"#f44336",dark:"#d32f2f",contrastText:"#fff"},background:{default:"#f5f6f8",appBar:"#3c40c6"},text:{primary:(0,a.darken)(r.BA.A700,.7),secondary:"#818ea3"},listPendingStatus:{background:"#fef7e5",color:"#fecb4c"},listCompletedStatus:{background:"#e9faf2",color:"#4ed495"}},shape:{borderRadius:o.default.unit},overrides:{MuiButton:{root:{borderRadius:o.default.unit/2,textTransform:"none"},sizeLarge:{padding:void 0,fontSize:void 0,paddingTop:o.default.unit,paddingBottom:o.default.unit,paddingLeft:5*o.default.unit,paddingRight:5*o.default.unit}},MuiTableCell:{body:{fontSize:"1rem"},head:{fontSize:"1rem",fontWeight:400}},MuiCardHeader:{root:{borderBottom:"1px solid rgba(0, 0, 0, 0.12)"},action:{marginTop:-2,marginRight:0,"& >*":{marginLeft:2*o.default.unit}},subheader:{marginTop:.5*o.default.unit}}},typography:{useNextVariants:!0,fontFamily:"-apple-system,BlinkMacSystemFont,Roboto,Helvetica,Arial,sans-serif",button:{textTransform:"none",fontSize:"1.2em"},body1:{fontSize:"1.0rem",fontWeight:400,lineHeight:"1.46429em",color:"rgba(0, 0, 0, 0.87)",letterSpacing:-.4},body2:{fontSize:"1.0rem",fontWeight:500,lineHeight:"1.71429em",color:"rgba(0, 0, 0, 0.87)",letterSpacing:-.4},body1Next:{color:"rgb(29, 29, 29)",fontWeight:400,fontSize:"1rem",lineHeight:1.5,letterSpacing:-.4},body2Next:{color:"rgb(29, 29, 29)",fontWeight:400,fontSize:"0.875rem",lineHeight:1.5,letterSpacing:-.4},display1:{color:"#818ea3",fontSize:"2.125rem",fontWeight:400,lineHeight:"1.20588em",letterSpacing:-.4},display2:{color:"#818ea3",fontSize:"2.8125rem",fontWeight:400,lineHeight:"1.13333em",marginLeft:"-.02em",letterSpacing:-.4},display3:{color:"#818ea3",fontSize:"3.5rem",fontWeight:400,lineHeight:"1.30357em",marginLeft:"-.02em",letterSpacing:-.4},display4:{fontSize:14,fontWeightLight:300,fontWeightMedium:500,fontWeightRegular:400,letterSpacing:-.4},h1:{color:"rgb(29, 29, 29)",fontSize:"6rem",fontWeight:300,lineHeight:1},h2:{color:"rgb(29, 29, 29)",fontSize:"3.75rem",fontWeight:300,lineHeight:1},h3:{color:"rgb(29, 29, 29)",fontSize:"3rem",fontWeight:400,lineHeight:1.04},h4:{color:"rgb(29, 29, 29)",fontSize:"2.125rem",fontWeight:400,lineHeight:1.17},h5:{color:"rgb(29, 29, 29)",fontSize:"1.5rem",fontWeight:400,lineHeight:1.33,letterSpacing:-.4},h6:{fontSize:"0.8rem",fontWeight:450,lineHeight:"1.71429em",color:"rgba(0, 0, 0, 0.87)",letterSpacing:-.4},subheading:{color:"rgb(29, 29, 29)",fontSize:"1rem",fontWeight:400,lineHeight:"1.5em",letterSpacing:-.4},subtitle1:{color:"rgb(29, 29, 29)",fontSize:"1rem",fontWeight:400,lineHeight:1.75,letterSpacing:-.4},subtitle2:{color:"rgb(29, 29, 29)",fontSize:"0.875rem",fontWeight:500,lineHeight:1.57,letterSpacing:-.4}},shadows:["none","0px 1px 3px 0px rgba(0, 0, 0, 0.1),0px 1px 1px 0px rgba(0, 0, 0, 0.04),0px 2px 1px -1px rgba(0, 0, 0, 0.02)","0px 1px 5px 0px rgba(0, 0, 0, 0.1),0px 2px 2px 0px rgba(0, 0, 0, 0.04),0px 3px 1px -2px rgba(0, 0, 0, 0.02)","0px 1px 8px 0px rgba(0, 0, 0, 0.1),0px 3px 4px 0px rgba(0, 0, 0, 0.04),0px 3px 3px -2px rgba(0, 0, 0, 0.02)","0px 2px 4px -1px rgba(0, 0, 0, 0.1),0px 4px 5px 0px rgba(0, 0, 0, 0.04),0px 1px 10px 0px rgba(0, 0, 0, 0.02)","0px 3px 5px -1px rgba(0, 0, 0, 0.1),0px 5px 8px 0px rgba(0, 0, 0, 0.04),0px 1px 14px 0px rgba(0, 0, 0, 0.02)","0px 3px 5px -1px rgba(0, 0, 0, 0.1),0px 6px 10px 0px rgba(0, 0, 0, 0.04),0px 1px 18px 0px rgba(0, 0, 0, 0.02)","0px 4px 5px -2px rgba(0, 0, 0, 0.1),0px 7px 10px 1px rgba(0, 0, 0, 0.04),0px 2px 16px 1px rgba(0, 0, 0, 0.02)","0px 5px 5px -3px rgba(0, 0, 0, 0.1),0px 8px 10px 1px rgba(0, 0, 0, 0.04),0px 3px 14px 2px rgba(0, 0, 0, 0.02)","0px 5px 6px -3px rgba(0, 0, 0, 0.1),0px 9px 12px 1px rgba(0, 0, 0, 0.04),0px 3px 16px 2px rgba(0, 0, 0, 0.02)","0px 6px 6px -3px rgba(0, 0, 0, 0.1),0px 10px 14px 1px rgba(0, 0, 0, 0.04),0px 4px 18px 3px rgba(0, 0, 0, 0.02)","0px 6px 7px -4px rgba(0, 0, 0, 0.1),0px 11px 15px 1px rgba(0, 0, 0, 0.04),0px 4px 20px 3px rgba(0, 0, 0, 0.02)","0px 7px 8px -4px rgba(0, 0, 0, 0.1),0px 12px 17px 2px rgba(0, 0, 0, 0.04),0px 5px 22px 4px rgba(0, 0, 0, 0.02)","0px 7px 8px -4px rgba(0, 0, 0, 0.1),0px 13px 19px 2px rgba(0, 0, 0, 0.04),0px 5px 24px 4px rgba(0, 0, 0, 0.02)","0px 7px 9px -4px rgba(0, 0, 0, 0.1),0px 14px 21px 2px rgba(0, 0, 0, 0.04),0px 5px 26px 4px rgba(0, 0, 0, 0.02)","0px 8px 9px -5px rgba(0, 0, 0, 0.1),0px 15px 22px 2px rgba(0, 0, 0, 0.04),0px 6px 28px 5px rgba(0, 0, 0, 0.02)","0px 8px 10px -5px rgba(0, 0, 0, 0.1),0px 16px 24px 2px rgba(0, 0, 0, 0.04),0px 6px 30px 5px rgba(0, 0, 0, 0.02)","0px 8px 11px -5px rgba(0, 0, 0, 0.1),0px 17px 26px 2px rgba(0, 0, 0, 0.04),0px 6px 32px 5px rgba(0, 0, 0, 0.02)","0px 9px 11px -5px rgba(0, 0, 0, 0.1),0px 18px 28px 2px rgba(0, 0, 0, 0.04),0px 7px 34px 6px rgba(0, 0, 0, 0.02)","0px 9px 12px -6px rgba(0, 0, 0, 0.1),0px 19px 29px 2px rgba(0, 0, 0, 0.04),0px 7px 36px 6px rgba(0, 0, 0, 0.02)","0px 10px 13px -6px rgba(0, 0, 0, 0.1),0px 20px 31px 3px rgba(0, 0, 0, 0.04),0px 8px 38px 7px rgba(0, 0, 0, 0.02)","0px 10px 13px -6px rgba(0, 0, 0, 0.1),0px 21px 33px 3px rgba(0, 0, 0, 0.04),0px 8px 40px 7px rgba(0, 0, 0, 0.02)","0px 10px 14px -6px rgba(0, 0, 0, 0.1),0px 22px 35px 3px rgba(0, 0, 0, 0.04),0px 8px 42px 7px rgba(0, 0, 0, 0.02)","0px 11px 14px -7px rgba(0, 0, 0, 0.1),0px 23px 36px 3px rgba(0, 0, 0, 0.04),0px 9px 44px 8px rgba(0, 0, 0, 0.02)","0px 11px 15px -7px rgba(0, 0, 0, 0.1),0px 24px 38px 3px rgba(0, 0, 0, 0.04),0px 9px 46px 8px rgba(0, 0, 0, 0.02)",]},u=(0,i.createMuiTheme)(s)},66289(e,t,n){"use strict";function r(e){if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function i(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}function a(){if("undefined"==typeof Reflect||!Reflect.construct||Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch(e){return!1}}function o(e,t,n){return(o=a()?Reflect.construct:function(e,t,n){var r=[null];r.push.apply(r,t);var i=new(Function.bind.apply(e,r));return n&&f(i,n.prototype),i}).apply(null,arguments)}function s(e){return(s=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function u(e,t){if("function"!=typeof t&&null!==t)throw TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&f(e,t)}function c(e){return -1!==Function.toString.call(e).indexOf("[native code]")}function l(e,t){return t&&("object"===p(t)||"function"==typeof t)?t:r(e)}function f(e,t){return(f=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}n.d(t,{V0:()=>B,_7:()=>v});var d,h,p=function(e){return e&&"undefined"!=typeof Symbol&&e.constructor===Symbol?"symbol":typeof e};function b(e){var t="function"==typeof Map?new Map:void 0;return(b=function(e){if(null===e||!c(e))return e;if("function"!=typeof e)throw TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,n)}function n(){return o(e,arguments,s(this).constructor)}return n.prototype=Object.create(e.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),f(n,e)})(e)}function m(){if("undefined"==typeof Reflect||!Reflect.construct||Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch(e){return!1}}function g(e){var t=m();return function(){var n,r=s(e);if(t){var i=s(this).constructor;n=Reflect.construct(r,arguments,i)}else n=r.apply(this,arguments);return l(this,n)}}var v=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"AuthenticationError(".concat(e.statusText,")"))).errors=[{status:e.status,detail:e},],r}return n}(b(Error)),y=function(e){u(n,e);var t=g(n);function n(e){var r,a=e.errors;return i(this,n),(r=t.call(this,"BadRequestError")).errors=a,r}return n}(b(Error)),w=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"UnprocessableEntityError")).errors=e,r}return n}(b(Error)),_=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"ServerError")).errors=e,r}return n}(b(Error)),E=function(e){u(n,e);var t=g(n);function n(e){var r,a=e.errors;return i(this,n),(r=t.call(this,"ConflictError")).errors=a,r}return n}(b(Error)),S=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"UnknownResponseError(".concat(e.statusText,")"))).errors=[{status:e.status,detail:e.statusText},],r}return n}(b(Error));function k(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:2e4;return Promise.race([fetch(e,t),new Promise(function(e,t){return setTimeout(function(){return t(Error("timeout"))},n)}),])}function x(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]=200&&e.status<300))return[3,2];return[2,e.json()];case 2:if(400!==e.status)return[3,3];return[2,e.json().then(function(e){throw new y(e)})];case 3:if(401!==e.status)return[3,4];throw new v(e);case 4:if(422!==e.status)return[3,6];return[4,$(e)];case 5:throw n=i.sent(),new w(n);case 6:if(409!==e.status)return[3,7];return[2,e.json().then(function(e){throw new E(e)})];case 7:if(!(e.status>=500))return[3,9];return[4,$(e)];case 8:throw r=i.sent(),new _(r);case 9:throw new S(e);case 10:return[2]}})})).apply(this,arguments)}function $(e){return z.apply(this,arguments)}function z(){return(z=j(function(e){return Y(this,function(t){return[2,e.json().then(function(t){return t.errors?t.errors.map(function(t){return{status:e.status,detail:t.detail}}):G(e)}).catch(function(){return G(e)})]})})).apply(this,arguments)}function G(e){return[{status:e.status,detail:e.statusText},]}},50109(e,t,n){"use strict";n.d(t,{LK:()=>o,U2:()=>i,eT:()=>s,t8:()=>a});var r=n(12795);function i(e){return r.ZP.getItem("chainlink.".concat(e))}function a(e,t){r.ZP.setItem("chainlink.".concat(e),t)}function o(e){var t=i(e),n={};if(t)try{return JSON.parse(t)}catch(r){}return n}function s(e,t){a(e,JSON.stringify(t))}},9541(e,t,n){"use strict";n.d(t,{Ks:()=>u,Tp:()=>a,iR:()=>o,pm:()=>s});var r=n(50109),i="persistURL";function a(){return r.U2(i)||""}function o(e){r.t8(i,e)}function s(){return r.LK("authentication")}function u(e){r.eT("authentication",e)}},67121(e,t,n){"use strict";function r(e){var t,n=e.Symbol;return"function"==typeof n?n.observable?t=n.observable:(t=n("observable"),n.observable=t):t="@@observable",t}n.r(t),n.d(t,{default:()=>o}),e=n.hmd(e),i="undefined"!=typeof self?self:"undefined"!=typeof window?window:void 0!==n.g?n.g:e;var i,a=r(i);let o=a},2177(e,t,n){"use strict";n.d(t,{Z:()=>o});var r=!0,i="Invariant failed";function a(e,t){if(!e){if(r)throw Error(i);throw Error(i+": "+(t||""))}}let o=a},11742(e){e.exports=function(){var e=document.getSelection();if(!e.rangeCount)return function(){};for(var t=document.activeElement,n=[],r=0;ru,ZT:()=>i,_T:()=>o,ev:()=>c,mG:()=>s,pi:()=>a});var r=function(e,t){return(r=Object.setPrototypeOf||({__proto__:[]})instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])})(e,t)};function i(e,t){if("function"!=typeof t&&null!==t)throw TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var a=function(){return(a=Object.assign||function(e){for(var t,n=1,r=arguments.length;nt.indexOf(r)&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var i=0,r=Object.getOwnPropertySymbols(e);it.indexOf(r[i])&&Object.prototype.propertyIsEnumerable.call(e,r[i])&&(n[r[i]]=e[r[i]]);return n}function s(e,t,n,r){function i(e){return e instanceof n?e:new n(function(t){t(e)})}return new(n||(n=Promise))(function(n,a){function o(e){try{u(r.next(e))}catch(t){a(t)}}function s(e){try{u(r.throw(e))}catch(t){a(t)}}function u(e){e.done?n(e.value):i(e.value).then(o,s)}u((r=r.apply(e,t||[])).next())})}function u(e,t){var n,r,i,a,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return a={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function s(e){return function(t){return u([e,t])}}function u(a){if(n)throw TypeError("Generator is already executing.");for(;o;)try{if(n=1,r&&(i=2&a[0]?r.return:a[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,a[1])).done)return i;switch(r=0,i&&(a=[2&a[0],i.value]),a[0]){case 0:case 1:i=a;break;case 4:return o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!(i=(i=o.trys).length>0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]r})},94927(e,t,n){function r(e,t){if(i("noDeprecation"))return e;var n=!1;function r(){if(!n){if(i("throwDeprecation"))throw Error(t);i("traceDeprecation")?console.trace(t):console.warn(t),n=!0}return e.apply(this,arguments)}return r}function i(e){try{if(!n.g.localStorage)return!1}catch(t){return!1}var r=n.g.localStorage[e];return null!=r&&"true"===String(r).toLowerCase()}e.exports=r},42473(e){"use strict";var t=function(){};e.exports=t},84763(e){e.exports=Worker},47529(e){e.exports=n;var t=Object.prototype.hasOwnProperty;function n(){for(var e={},n=0;ne.length)&&(t=e.length);for(var n=0,r=Array(t);n=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}e.exports=i,e.exports.__esModule=!0,e.exports.default=e.exports},7071(e){function t(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports},94993(e,t,n){var r=n(18698).default,i=n(66115);function a(e,t){if(t&&("object"===r(t)||"function"==typeof t))return t;if(void 0!==t)throw TypeError("Derived constructors may only return object or undefined");return i(e)}e.exports=a,e.exports.__esModule=!0,e.exports.default=e.exports},6015(e){function t(n,r){return e.exports=t=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},e.exports.__esModule=!0,e.exports.default=e.exports,t(n,r)}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports},861(e,t,n){var r=n(63405),i=n(79498),a=n(86116),o=n(42281);function s(e){return r(e)||i(e)||a(e)||o()}e.exports=s,e.exports.__esModule=!0,e.exports.default=e.exports},18698(e){function t(n){return e.exports=t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},e.exports.__esModule=!0,e.exports.default=e.exports,t(n)}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports},86116(e,t,n){var r=n(73897);function i(e,t){if(e){if("string"==typeof e)return r(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return r(e,t)}}e.exports=i,e.exports.__esModule=!0,e.exports.default=e.exports},1644(e,t,n){"use strict";var r,i;function a(e){return!!e&&e<7}n.d(t,{I:()=>r,O:()=>a}),(i=r||(r={}))[i.loading=1]="loading",i[i.setVariables=2]="setVariables",i[i.fetchMore=3]="fetchMore",i[i.refetch=4]="refetch",i[i.poll=6]="poll",i[i.ready=7]="ready",i[i.error=8]="error"},30990(e,t,n){"use strict";n.d(t,{MS:()=>s,YG:()=>a,cA:()=>c,ls:()=>o});var r=n(70655);n(83952);var i=n(13154),a=Symbol();function o(e){return!!e.extensions&&Array.isArray(e.extensions[a])}function s(e){return e.hasOwnProperty("graphQLErrors")}var u=function(e){var t=(0,r.ev)((0,r.ev)((0,r.ev)([],e.graphQLErrors,!0),e.clientErrors,!0),e.protocolErrors,!0);return e.networkError&&t.push(e.networkError),t.map(function(e){return(0,i.s)(e)&&e.message||"Error message not found."}).join("\n")},c=function(e){function t(n){var r=n.graphQLErrors,i=n.protocolErrors,a=n.clientErrors,o=n.networkError,s=n.errorMessage,c=n.extraInfo,l=e.call(this,s)||this;return l.name="ApolloError",l.graphQLErrors=r||[],l.protocolErrors=i||[],l.clientErrors=a||[],l.networkError=o||null,l.message=s||u(l),l.extraInfo=c,l.__proto__=t.prototype,l}return(0,r.ZT)(t,e),t}(Error)},85317(e,t,n){"use strict";n.d(t,{K:()=>a});var r=n(67294),i=n(30320).aS?Symbol.for("__APOLLO_CONTEXT__"):"__APOLLO_CONTEXT__";function a(){var e=r.createContext[i];return e||(Object.defineProperty(r.createContext,i,{value:e=r.createContext({}),enumerable:!1,writable:!1,configurable:!0}),e.displayName="ApolloContext"),e}},21436(e,t,n){"use strict";n.d(t,{O:()=>i,k:()=>r});var r=Array.isArray;function i(e){return Array.isArray(e)&&e.length>0}},30320(e,t,n){"use strict";n.d(t,{DN:()=>s,JC:()=>l,aS:()=>o,mr:()=>i,sy:()=>a});var r=n(83952),i="function"==typeof WeakMap&&"ReactNative"!==(0,r.wY)(function(){return navigator.product}),a="function"==typeof WeakSet,o="function"==typeof Symbol&&"function"==typeof Symbol.for,s=o&&Symbol.asyncIterator,u="function"==typeof(0,r.wY)(function(){return window.document.createElement}),c=(0,r.wY)(function(){return navigator.userAgent.indexOf("jsdom")>=0})||!1,l=u&&!c},53712(e,t,n){"use strict";function r(){for(var e=[],t=0;tr})},10542(e,t,n){"use strict";n.d(t,{J:()=>o}),n(83952);var r=n(13154);function i(e){var t=new Set([e]);return t.forEach(function(e){(0,r.s)(e)&&a(e)===e&&Object.getOwnPropertyNames(e).forEach(function(n){(0,r.s)(e[n])&&t.add(e[n])})}),e}function a(e){if(__DEV__&&!Object.isFrozen(e))try{Object.freeze(e)}catch(t){if(t instanceof TypeError)return null;throw t}return e}function o(e){return __DEV__&&i(e),e}},14012(e,t,n){"use strict";n.d(t,{J:()=>a});var r=n(70655),i=n(53712);function a(e,t){return(0,i.o)(e,t,t.variables&&{variables:(0,r.pi)((0,r.pi)({},e&&e.variables),t.variables)})}},13154(e,t,n){"use strict";function r(e){return null!==e&&"object"==typeof e}n.d(t,{s:()=>r})},83952(e,t,n){"use strict";n.d(t,{ej:()=>u,kG:()=>c,wY:()=>h});var r,i=n(70655),a="Invariant Violation",o=Object.setPrototypeOf,s=void 0===o?function(e,t){return e.__proto__=t,e}:o,u=function(e){function t(n){void 0===n&&(n=a);var r=e.call(this,"number"==typeof n?a+": "+n+" (see https://github.com/apollographql/invariant-packages)":n)||this;return r.framesToPop=1,r.name=a,s(r,t.prototype),r}return(0,i.ZT)(t,e),t}(Error);function c(e,t){if(!e)throw new u(t)}var l=["debug","log","warn","error","silent"],f=l.indexOf("log");function d(e){return function(){if(l.indexOf(e)>=f)return(console[e]||console.log).apply(console,arguments)}}function h(e){try{return e()}catch(t){}}(r=c||(c={})).debug=d("debug"),r.log=d("log"),r.warn=d("warn"),r.error=d("error");let p=h(function(){return globalThis})||h(function(){return window})||h(function(){return self})||h(function(){return global})||h(function(){return h.constructor("return this")()});var b="__",m=[b,b].join("DEV");function g(){try{return Boolean(__DEV__)}catch(e){return Object.defineProperty(p,m,{value:"production"!==h(function(){return"production"}),enumerable:!1,configurable:!0,writable:!0}),p[m]}}let v=g();function y(e){try{return e()}catch(t){}}var w=y(function(){return globalThis})||y(function(){return window})||y(function(){return self})||y(function(){return global})||y(function(){return y.constructor("return this")()}),_=!1;function E(){!w||y(function(){return"production"})||y(function(){return process})||(Object.defineProperty(w,"process",{value:{env:{NODE_ENV:"production"}},configurable:!0,enumerable:!1,writable:!0}),_=!0)}function S(){_&&(delete w.process,_=!1)}E();var k=n(10143);function x(){return k.H,S()}function T(){__DEV__?c("boolean"==typeof v,v):c("boolean"==typeof v,39)}x(),T()},4942(e,t,n){"use strict";function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}n.d(t,{Z:()=>r})},87462(e,t,n){"use strict";function r(){return(r=Object.assign?Object.assign.bind():function(e){for(var t=1;tr})},51721(e,t,n){"use strict";function r(e,t){return(r=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e})(e,t)}function i(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,r(e,t)}n.d(t,{Z:()=>i})},63366(e,t,n){"use strict";function r(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}n.d(t,{Z:()=>r})},25821(e,t,n){"use strict";n.d(t,{Z:()=>s});var r=n(45695);function i(e){return(i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}var a=10,o=2;function s(e){return u(e,[])}function u(e,t){switch(i(e)){case"string":return JSON.stringify(e);case"function":return e.name?"[function ".concat(e.name,"]"):"[function]";case"object":if(null===e)return"null";return c(e,t);default:return String(e)}}function c(e,t){if(-1!==t.indexOf(e))return"[Circular]";var n=[].concat(t,[e]),r=d(e);if(void 0!==r){var i=r.call(e);if(i!==e)return"string"==typeof i?i:u(i,n)}else if(Array.isArray(e))return f(e,n);return l(e,n)}function l(e,t){var n=Object.keys(e);return 0===n.length?"{}":t.length>o?"["+h(e)+"]":"{ "+n.map(function(n){var r=u(e[n],t);return n+": "+r}).join(", ")+" }"}function f(e,t){if(0===e.length)return"[]";if(t.length>o)return"[Array]";for(var n=Math.min(a,e.length),r=e.length-n,i=[],s=0;s1&&i.push("... ".concat(r," more items")),"["+i.join(", ")+"]"}function d(e){var t=e[String(r.Z)];return"function"==typeof t?t:"function"==typeof e.inspect?e.inspect:void 0}function h(e){var t=Object.prototype.toString.call(e).replace(/^\[object /,"").replace(/]$/,"");if("Object"===t&&"function"==typeof e.constructor){var n=e.constructor.name;if("string"==typeof n&&""!==n)return n}return t}},45695(e,t,n){"use strict";n.d(t,{Z:()=>i});var r="function"==typeof Symbol&&"function"==typeof Symbol.for?Symbol.for("nodejs.util.inspect.custom"):void 0;let i=r},25217(e,t,n){"use strict";function r(e,t){if(!Boolean(e))throw Error(null!=t?t:"Unexpected invariant triggered.")}n.d(t,{Ye:()=>o,WU:()=>s,UG:()=>u});var i=n(45695);function a(e){var t=e.prototype.toJSON;"function"==typeof t||r(0),e.prototype.inspect=t,i.Z&&(e.prototype[i.Z]=t)}var o=function(){function e(e,t,n){this.start=e.start,this.end=t.end,this.startToken=e,this.endToken=t,this.source=n}return e.prototype.toJSON=function(){return{start:this.start,end:this.end}},e}();a(o);var s=function(){function e(e,t,n,r,i,a,o){this.kind=e,this.start=t,this.end=n,this.line=r,this.column=i,this.value=o,this.prev=a,this.next=null}return e.prototype.toJSON=function(){return{kind:this.kind,value:this.value,line:this.line,column:this.column}},e}();function u(e){return null!=e&&"string"==typeof e.kind}a(s)},87392(e,t,n){"use strict";function r(e){var t=e.split(/\r\n|[\n\r]/g),n=a(e);if(0!==n)for(var r=1;ro&&i(t[s-1]);)--s;return t.slice(o,s).join("\n")}function i(e){for(var t=0;t1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],r=-1===e.indexOf("\n"),i=" "===e[0]||" "===e[0],a='"'===e[e.length-1],o="\\"===e[e.length-1],s=!r||a||o||n,u="";return s&&!(r&&i)&&(u+="\n"+t),u+=t?e.replace(/\n/g,"\n"+t):e,s&&(u+="\n"),'"""'+u.replace(/"""/g,'\\"""')+'"""'}n.d(t,{LZ:()=>o,W7:()=>r})},97359(e,t,n){"use strict";n.d(t,{h:()=>r});var r=Object.freeze({NAME:"Name",DOCUMENT:"Document",OPERATION_DEFINITION:"OperationDefinition",VARIABLE_DEFINITION:"VariableDefinition",SELECTION_SET:"SelectionSet",FIELD:"Field",ARGUMENT:"Argument",FRAGMENT_SPREAD:"FragmentSpread",INLINE_FRAGMENT:"InlineFragment",FRAGMENT_DEFINITION:"FragmentDefinition",VARIABLE:"Variable",INT:"IntValue",FLOAT:"FloatValue",STRING:"StringValue",BOOLEAN:"BooleanValue",NULL:"NullValue",ENUM:"EnumValue",LIST:"ListValue",OBJECT:"ObjectValue",OBJECT_FIELD:"ObjectField",DIRECTIVE:"Directive",NAMED_TYPE:"NamedType",LIST_TYPE:"ListType",NON_NULL_TYPE:"NonNullType",SCHEMA_DEFINITION:"SchemaDefinition",OPERATION_TYPE_DEFINITION:"OperationTypeDefinition",SCALAR_TYPE_DEFINITION:"ScalarTypeDefinition",OBJECT_TYPE_DEFINITION:"ObjectTypeDefinition",FIELD_DEFINITION:"FieldDefinition",INPUT_VALUE_DEFINITION:"InputValueDefinition",INTERFACE_TYPE_DEFINITION:"InterfaceTypeDefinition",UNION_TYPE_DEFINITION:"UnionTypeDefinition",ENUM_TYPE_DEFINITION:"EnumTypeDefinition",ENUM_VALUE_DEFINITION:"EnumValueDefinition",INPUT_OBJECT_TYPE_DEFINITION:"InputObjectTypeDefinition",DIRECTIVE_DEFINITION:"DirectiveDefinition",SCHEMA_EXTENSION:"SchemaExtension",SCALAR_TYPE_EXTENSION:"ScalarTypeExtension",OBJECT_TYPE_EXTENSION:"ObjectTypeExtension",INTERFACE_TYPE_EXTENSION:"InterfaceTypeExtension",UNION_TYPE_EXTENSION:"UnionTypeExtension",ENUM_TYPE_EXTENSION:"EnumTypeExtension",INPUT_OBJECT_TYPE_EXTENSION:"InputObjectTypeExtension"})},10143(e,t,n){"use strict";n.d(t,{H:()=>c,T:()=>l});var r=n(99763),i=n(25821);function a(e,t){if(!Boolean(e))throw Error(t)}let o=function(e,t){return e instanceof t};function s(e,t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:"GraphQL request",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{line:1,column:1};"string"==typeof e||a(0,"Body must be a string. Received: ".concat((0,i.Z)(e),".")),this.body=e,this.name=t,this.locationOffset=n,this.locationOffset.line>0||a(0,"line in locationOffset is 1-indexed and must be positive."),this.locationOffset.column>0||a(0,"column in locationOffset is 1-indexed and must be positive.")}return u(e,[{key:r.YF,get:function(){return"Source"}}]),e}();function l(e){return o(e,c)}},99763(e,t,n){"use strict";n.d(t,{YF:()=>r});var r="function"==typeof Symbol&&null!=Symbol.toStringTag?Symbol.toStringTag:"@@toStringTag"},37452(e){"use strict";e.exports=JSON.parse('{"AElig":"\xc6","AMP":"&","Aacute":"\xc1","Acirc":"\xc2","Agrave":"\xc0","Aring":"\xc5","Atilde":"\xc3","Auml":"\xc4","COPY":"\xa9","Ccedil":"\xc7","ETH":"\xd0","Eacute":"\xc9","Ecirc":"\xca","Egrave":"\xc8","Euml":"\xcb","GT":">","Iacute":"\xcd","Icirc":"\xce","Igrave":"\xcc","Iuml":"\xcf","LT":"<","Ntilde":"\xd1","Oacute":"\xd3","Ocirc":"\xd4","Ograve":"\xd2","Oslash":"\xd8","Otilde":"\xd5","Ouml":"\xd6","QUOT":"\\"","REG":"\xae","THORN":"\xde","Uacute":"\xda","Ucirc":"\xdb","Ugrave":"\xd9","Uuml":"\xdc","Yacute":"\xdd","aacute":"\xe1","acirc":"\xe2","acute":"\xb4","aelig":"\xe6","agrave":"\xe0","amp":"&","aring":"\xe5","atilde":"\xe3","auml":"\xe4","brvbar":"\xa6","ccedil":"\xe7","cedil":"\xb8","cent":"\xa2","copy":"\xa9","curren":"\xa4","deg":"\xb0","divide":"\xf7","eacute":"\xe9","ecirc":"\xea","egrave":"\xe8","eth":"\xf0","euml":"\xeb","frac12":"\xbd","frac14":"\xbc","frac34":"\xbe","gt":">","iacute":"\xed","icirc":"\xee","iexcl":"\xa1","igrave":"\xec","iquest":"\xbf","iuml":"\xef","laquo":"\xab","lt":"<","macr":"\xaf","micro":"\xb5","middot":"\xb7","nbsp":"\xa0","not":"\xac","ntilde":"\xf1","oacute":"\xf3","ocirc":"\xf4","ograve":"\xf2","ordf":"\xaa","ordm":"\xba","oslash":"\xf8","otilde":"\xf5","ouml":"\xf6","para":"\xb6","plusmn":"\xb1","pound":"\xa3","quot":"\\"","raquo":"\xbb","reg":"\xae","sect":"\xa7","shy":"\xad","sup1":"\xb9","sup2":"\xb2","sup3":"\xb3","szlig":"\xdf","thorn":"\xfe","times":"\xd7","uacute":"\xfa","ucirc":"\xfb","ugrave":"\xf9","uml":"\xa8","uuml":"\xfc","yacute":"\xfd","yen":"\xa5","yuml":"\xff"}')},93580(e){"use strict";e.exports=JSON.parse('{"0":"�","128":"€","130":"‚","131":"ƒ","132":"„","133":"…","134":"†","135":"‡","136":"ˆ","137":"‰","138":"Š","139":"‹","140":"Œ","142":"Ž","145":"‘","146":"’","147":"“","148":"”","149":"•","150":"–","151":"—","152":"˜","153":"™","154":"š","155":"›","156":"œ","158":"ž","159":"Ÿ"}')},67946(e){"use strict";e.exports=JSON.parse('{"locale":"en","long":{"year":{"previous":"last year","current":"this year","next":"next year","past":{"one":"{0} year ago","other":"{0} years ago"},"future":{"one":"in {0} year","other":"in {0} years"}},"quarter":{"previous":"last quarter","current":"this quarter","next":"next quarter","past":{"one":"{0} quarter ago","other":"{0} quarters ago"},"future":{"one":"in {0} quarter","other":"in {0} quarters"}},"month":{"previous":"last month","current":"this month","next":"next month","past":{"one":"{0} month ago","other":"{0} months ago"},"future":{"one":"in {0} month","other":"in {0} months"}},"week":{"previous":"last week","current":"this week","next":"next week","past":{"one":"{0} week ago","other":"{0} weeks ago"},"future":{"one":"in {0} week","other":"in {0} weeks"}},"day":{"previous":"yesterday","current":"today","next":"tomorrow","past":{"one":"{0} day ago","other":"{0} days ago"},"future":{"one":"in {0} day","other":"in {0} days"}},"hour":{"current":"this hour","past":{"one":"{0} hour ago","other":"{0} hours ago"},"future":{"one":"in {0} hour","other":"in {0} hours"}},"minute":{"current":"this minute","past":{"one":"{0} minute ago","other":"{0} minutes ago"},"future":{"one":"in {0} minute","other":"in {0} minutes"}},"second":{"current":"now","past":{"one":"{0} second ago","other":"{0} seconds ago"},"future":{"one":"in {0} second","other":"in {0} seconds"}}},"short":{"year":{"previous":"last yr.","current":"this yr.","next":"next yr.","past":"{0} yr. ago","future":"in {0} yr."},"quarter":{"previous":"last qtr.","current":"this qtr.","next":"next qtr.","past":{"one":"{0} qtr. ago","other":"{0} qtrs. ago"},"future":{"one":"in {0} qtr.","other":"in {0} qtrs."}},"month":{"previous":"last mo.","current":"this mo.","next":"next mo.","past":"{0} mo. ago","future":"in {0} mo."},"week":{"previous":"last wk.","current":"this wk.","next":"next wk.","past":"{0} wk. ago","future":"in {0} wk."},"day":{"previous":"yesterday","current":"today","next":"tomorrow","past":{"one":"{0} day ago","other":"{0} days ago"},"future":{"one":"in {0} day","other":"in {0} days"}},"hour":{"current":"this hour","past":"{0} hr. ago","future":"in {0} hr."},"minute":{"current":"this minute","past":"{0} min. ago","future":"in {0} min."},"second":{"current":"now","past":"{0} sec. ago","future":"in {0} sec."}},"narrow":{"year":{"previous":"last yr.","current":"this yr.","next":"next yr.","past":"{0} yr. ago","future":"in {0} yr."},"quarter":{"previous":"last qtr.","current":"this qtr.","next":"next qtr.","past":{"one":"{0} qtr. ago","other":"{0} qtrs. ago"},"future":{"one":"in {0} qtr.","other":"in {0} qtrs."}},"month":{"previous":"last mo.","current":"this mo.","next":"next mo.","past":"{0} mo. ago","future":"in {0} mo."},"week":{"previous":"last wk.","current":"this wk.","next":"next wk.","past":"{0} wk. ago","future":"in {0} wk."},"day":{"previous":"yesterday","current":"today","next":"tomorrow","past":{"one":"{0} day ago","other":"{0} days ago"},"future":{"one":"in {0} day","other":"in {0} days"}},"hour":{"current":"this hour","past":"{0} hr. ago","future":"in {0} hr."},"minute":{"current":"this minute","past":"{0} min. ago","future":"in {0} min."},"second":{"current":"now","past":"{0} sec. ago","future":"in {0} sec."}},"now":{"now":{"current":"now","future":"in a moment","past":"just now"}},"mini":{"year":"{0}yr","month":"{0}mo","week":"{0}wk","day":"{0}d","hour":"{0}h","minute":"{0}m","second":"{0}s","now":"now"},"short-time":{"year":"{0} yr.","month":"{0} mo.","week":"{0} wk.","day":{"one":"{0} day","other":"{0} days"},"hour":"{0} hr.","minute":"{0} min.","second":"{0} sec."},"long-time":{"year":{"one":"{0} year","other":"{0} years"},"month":{"one":"{0} month","other":"{0} months"},"week":{"one":"{0} week","other":"{0} weeks"},"day":{"one":"{0} day","other":"{0} days"},"hour":{"one":"{0} hour","other":"{0} hours"},"minute":{"one":"{0} minute","other":"{0} minutes"},"second":{"one":"{0} second","other":"{0} seconds"}}}')}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={id:e,loaded:!1,exports:{}};return __webpack_modules__[e].call(n.exports,n,n.exports,__webpack_require__),n.loaded=!0,n.exports}__webpack_require__.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return __webpack_require__.d(t,{a:t}),t},(()=>{var e,t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__;__webpack_require__.t=function(n,r){if(1&r&&(n=this(n)),8&r||"object"==typeof n&&n&&(4&r&&n.__esModule||16&r&&"function"==typeof n.then))return n;var i=Object.create(null);__webpack_require__.r(i);var a={};e=e||[null,t({}),t([]),t(t)];for(var o=2&r&&n;"object"==typeof o&&!~e.indexOf(o);o=t(o))Object.getOwnPropertyNames(o).forEach(e=>a[e]=()=>n[e]);return a.default=()=>n,__webpack_require__.d(i,a),i}})(),__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),__webpack_require__.hmd=e=>((e=Object.create(e)).children||(e.children=[]),Object.defineProperty(e,"exports",{enumerable:!0,set(){throw Error("ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: "+e.id)}}),e),__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},__webpack_require__.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),__webpack_require__.p="/assets/",__webpack_require__.nc=void 0;var __webpack_exports__={};(()=>{"use strict";var e,t,n,r,i=__webpack_require__(32316),a=__webpack_require__(8126),o=__webpack_require__(5690),s=__webpack_require__(30381),u=__webpack_require__.n(s),c=__webpack_require__(67294),l=__webpack_require__(73935),f=__webpack_require__.n(l),d=__webpack_require__(57209),h=__webpack_require__(37703),p=__webpack_require__(97779),b=__webpack_require__(28500);function m(e){return function(t){var n=t.dispatch,r=t.getState;return function(t){return function(i){return"function"==typeof i?i(n,r,e):t(i)}}}}var g=m();g.withExtraArgument=m;let v=g;var y=__webpack_require__(76489);function w(e){return function(t){return function(n){return function(r){n(r);var i=e||document&&document.cookie||"",a=t.getState();if("MATCH_ROUTE"===r.type&&"/signin"!==a.notifications.currentUrl){var o=(0,y.Q)(i);if(o.explorer)try{var s=JSON.parse(o.explorer);if("error"===s.status){var u=_(s.url);n({type:"NOTIFY_ERROR_MSG",msg:u})}}catch(c){n({type:"NOTIFY_ERROR_MSG",msg:"Invalid explorer status"})}}}}}}function _(e){var t="Can't connect to explorer: ".concat(e);return e.match(/^wss?:.+/)?t:"".concat(t,". You must use a websocket.")}var E=__webpack_require__(16353);function S(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}}}throw TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function ei(e,t){if(e){if("string"==typeof e)return ea(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return ea(e,t)}}function ea(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n1,i=!1,a=arguments[1],o=a;return new n(function(n){return t.subscribe({next:function(t){var a=!i;if(i=!0,!a||r)try{o=e(o,t)}catch(s){return n.error(s)}else o=t},error:function(e){n.error(e)},complete:function(){if(!i&&!r)return n.error(TypeError("Cannot reduce an empty sequence"));n.next(o),n.complete()}})})},t.concat=function(){for(var e=this,t=arguments.length,n=Array(t),r=0;r=0&&i.splice(e,1),o()}});i.push(s)},error:function(e){r.error(e)},complete:function(){o()}});function o(){a.closed&&0===i.length&&r.complete()}return function(){i.forEach(function(e){return e.unsubscribe()}),a.unsubscribe()}})},t[ed]=function(){return this},e.from=function(t){var n="function"==typeof this?this:e;if(null==t)throw TypeError(t+" is not an object");var r=ep(t,ed);if(r){var i=r.call(t);if(Object(i)!==i)throw TypeError(i+" is not an object");return em(i)&&i.constructor===n?i:new n(function(e){return i.subscribe(e)})}if(ec("iterator")&&(r=ep(t,ef)))return new n(function(e){ev(function(){if(!e.closed){for(var n,i=er(r.call(t));!(n=i()).done;){var a=n.value;if(e.next(a),e.closed)return}e.complete()}})});if(Array.isArray(t))return new n(function(e){ev(function(){if(!e.closed){for(var n=0;n0))return n.connection.key;var r=n.connection.filter?n.connection.filter:[];r.sort();var i={};return r.forEach(function(e){i[e]=t[e]}),"".concat(n.connection.key,"(").concat(eV(i),")")}var a=e;if(t){var o=eV(t);a+="(".concat(o,")")}return n&&Object.keys(n).forEach(function(e){-1===eW.indexOf(e)&&(n[e]&&Object.keys(n[e]).length?a+="@".concat(e,"(").concat(eV(n[e]),")"):a+="@".concat(e))}),a},{setStringify:function(e){var t=eV;return eV=e,t}}),eV=function(e){return JSON.stringify(e,eq)};function eq(e,t){return(0,eO.s)(t)&&!Array.isArray(t)&&(t=Object.keys(t).sort().reduce(function(e,n){return e[n]=t[n],e},{})),t}function eZ(e,t){if(e.arguments&&e.arguments.length){var n={};return e.arguments.forEach(function(e){var r;return ez(n,e.name,e.value,t)}),n}return null}function eX(e){return e.alias?e.alias.value:e.name.value}function eJ(e,t,n){for(var r,i=0,a=t.selections;it.indexOf(i))throw __DEV__?new Q.ej("illegal argument: ".concat(i)):new Q.ej(27)}return e}function tt(e,t){return t?t(e):eT.of()}function tn(e){return"function"==typeof e?new ta(e):e}function tr(e){return e.request.length<=1}var ti=function(e){function t(t,n){var r=e.call(this,t)||this;return r.link=n,r}return(0,en.ZT)(t,e),t}(Error),ta=function(){function e(e){e&&(this.request=e)}return e.empty=function(){return new e(function(){return eT.of()})},e.from=function(t){return 0===t.length?e.empty():t.map(tn).reduce(function(e,t){return e.concat(t)})},e.split=function(t,n,r){var i=tn(n),a=tn(r||new e(tt));return new e(tr(i)&&tr(a)?function(e){return t(e)?i.request(e)||eT.of():a.request(e)||eT.of()}:function(e,n){return t(e)?i.request(e,n)||eT.of():a.request(e,n)||eT.of()})},e.execute=function(e,t){return e.request(eM(t.context,e7(te(t))))||eT.of()},e.concat=function(t,n){var r=tn(t);if(tr(r))return __DEV__&&Q.kG.warn(new ti("You are calling concat on a terminating link, which will have no effect",r)),r;var i=tn(n);return new e(tr(i)?function(e){return r.request(e,function(e){return i.request(e)||eT.of()})||eT.of()}:function(e,t){return r.request(e,function(e){return i.request(e,t)||eT.of()})||eT.of()})},e.prototype.split=function(t,n,r){return this.concat(e.split(t,n,r||new e(tt)))},e.prototype.concat=function(t){return e.concat(this,t)},e.prototype.request=function(e,t){throw __DEV__?new Q.ej("request is not implemented"):new Q.ej(22)},e.prototype.onError=function(e,t){if(t&&t.error)return t.error(e),!1;throw e},e.prototype.setOnError=function(e){return this.onError=e,this},e}(),to=__webpack_require__(25821),ts=__webpack_require__(25217),tu={Name:[],Document:["definitions"],OperationDefinition:["name","variableDefinitions","directives","selectionSet"],VariableDefinition:["variable","type","defaultValue","directives"],Variable:["name"],SelectionSet:["selections"],Field:["alias","name","arguments","directives","selectionSet"],Argument:["name","value"],FragmentSpread:["name","directives"],InlineFragment:["typeCondition","directives","selectionSet"],FragmentDefinition:["name","variableDefinitions","typeCondition","directives","selectionSet"],IntValue:[],FloatValue:[],StringValue:[],BooleanValue:[],NullValue:[],EnumValue:[],ListValue:["values"],ObjectValue:["fields"],ObjectField:["name","value"],Directive:["name","arguments"],NamedType:["name"],ListType:["type"],NonNullType:["type"],SchemaDefinition:["description","directives","operationTypes"],OperationTypeDefinition:["type"],ScalarTypeDefinition:["description","name","directives"],ObjectTypeDefinition:["description","name","interfaces","directives","fields"],FieldDefinition:["description","name","arguments","type","directives"],InputValueDefinition:["description","name","type","defaultValue","directives"],InterfaceTypeDefinition:["description","name","interfaces","directives","fields"],UnionTypeDefinition:["description","name","directives","types"],EnumTypeDefinition:["description","name","directives","values"],EnumValueDefinition:["description","name","directives"],InputObjectTypeDefinition:["description","name","directives","fields"],DirectiveDefinition:["description","name","arguments","locations"],SchemaExtension:["directives","operationTypes"],ScalarTypeExtension:["name","directives"],ObjectTypeExtension:["name","interfaces","directives","fields"],InterfaceTypeExtension:["name","interfaces","directives","fields"],UnionTypeExtension:["name","directives","types"],EnumTypeExtension:["name","directives","values"],InputObjectTypeExtension:["name","directives","fields"]},tc=Object.freeze({});function tl(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:tu,r=void 0,i=Array.isArray(e),a=[e],o=-1,s=[],u=void 0,c=void 0,l=void 0,f=[],d=[],h=e;do{var p,b=++o===a.length,m=b&&0!==s.length;if(b){if(c=0===d.length?void 0:f[f.length-1],u=l,l=d.pop(),m){if(i)u=u.slice();else{for(var g={},v=0,y=Object.keys(u);v1)for(var r=new tB,i=1;i=0;--a){var o=i[a],s=isNaN(+o)?{}:[];s[o]=t,t=s}n=r.merge(n,t)}),n}var tW=Object.prototype.hasOwnProperty;function tK(e,t){var n,r,i,a,o;return(0,en.mG)(this,void 0,void 0,function(){var s,u,c,l,f,d,h,p,b,m,g,v,y,w,_,E,S,k,x,T,M,O,A;return(0,en.Jh)(this,function(L){switch(L.label){case 0:if(void 0===TextDecoder)throw Error("TextDecoder must be defined in the environment: please import a polyfill.");s=new TextDecoder("utf-8"),u=null===(n=e.headers)||void 0===n?void 0:n.get("content-type"),c="boundary=",l=(null==u?void 0:u.includes(c))?null==u?void 0:u.substring((null==u?void 0:u.indexOf(c))+c.length).replace(/['"]/g,"").replace(/\;(.*)/gm,"").trim():"-",f="\r\n--".concat(l),d="",h=tI(e),p=!0,L.label=1;case 1:if(!p)return[3,3];return[4,h.next()];case 2:for(m=(b=L.sent()).value,g=b.done,v="string"==typeof m?m:s.decode(m),y=d.length-f.length+1,p=!g,d+=v,w=d.indexOf(f,y);w>-1;){if(_=void 0,_=(O=[d.slice(0,w),d.slice(w+f.length),])[0],d=O[1],E=_.indexOf("\r\n\r\n"),(k=(S=tV(_.slice(0,E)))["content-type"])&&-1===k.toLowerCase().indexOf("application/json"))throw Error("Unsupported patch content type: application/json is required.");if(x=_.slice(E))try{T=tq(e,x),Object.keys(T).length>1||"data"in T||"incremental"in T||"errors"in T||"payload"in T?tz(T)?(M={},"payload"in T&&(M=(0,en.pi)({},T.payload)),"errors"in T&&(M=(0,en.pi)((0,en.pi)({},M),{extensions:(0,en.pi)((0,en.pi)({},"extensions"in M?M.extensions:null),((A={})[tN.YG]=T.errors,A))})),null===(r=t.next)||void 0===r||r.call(t,M)):null===(i=t.next)||void 0===i||i.call(t,T):1===Object.keys(T).length&&"hasNext"in T&&!T.hasNext&&(null===(a=t.complete)||void 0===a||a.call(t))}catch(C){tZ(C,t)}w=d.indexOf(f)}return[3,1];case 3:return null===(o=t.complete)||void 0===o||o.call(t),[2]}})})}function tV(e){var t={};return e.split("\n").forEach(function(e){var n=e.indexOf(":");if(n>-1){var r=e.slice(0,n).trim().toLowerCase(),i=e.slice(n+1).trim();t[r]=i}}),t}function tq(e,t){e.status>=300&&tD(e,function(){try{return JSON.parse(t)}catch(e){return t}}(),"Response not successful: Received status code ".concat(e.status));try{return JSON.parse(t)}catch(n){var r=n;throw r.name="ServerParseError",r.response=e,r.statusCode=e.status,r.bodyText=t,r}}function tZ(e,t){var n,r;"AbortError"!==e.name&&(e.result&&e.result.errors&&e.result.data&&(null===(n=t.next)||void 0===n||n.call(t,e.result)),null===(r=t.error)||void 0===r||r.call(t,e))}function tX(e,t,n){tJ(t)(e).then(function(e){var t,r;null===(t=n.next)||void 0===t||t.call(n,e),null===(r=n.complete)||void 0===r||r.call(n)}).catch(function(e){return tZ(e,n)})}function tJ(e){return function(t){return t.text().then(function(e){return tq(t,e)}).then(function(n){return t.status>=300&&tD(t,n,"Response not successful: Received status code ".concat(t.status)),Array.isArray(n)||tW.call(n,"data")||tW.call(n,"errors")||tD(t,n,"Server response was missing for query '".concat(Array.isArray(e)?e.map(function(e){return e.operationName}):e.operationName,"'.")),n})}}var tQ=function(e){if(!e&&"undefined"==typeof fetch)throw __DEV__?new Q.ej("\n\"fetch\" has not been found globally and no fetcher has been configured. To fix this, install a fetch package (like https://www.npmjs.com/package/cross-fetch), instantiate the fetcher, and pass it into your HttpLink constructor. For example:\n\nimport fetch from 'cross-fetch';\nimport { ApolloClient, HttpLink } from '@apollo/client';\nconst client = new ApolloClient({\n link: new HttpLink({ uri: '/graphql', fetch })\n});\n "):new Q.ej(23)},t1=__webpack_require__(87392);function t0(e){return tl(e,{leave:t3})}var t2=80,t3={Name:function(e){return e.value},Variable:function(e){return"$"+e.name},Document:function(e){return t6(e.definitions,"\n\n")+"\n"},OperationDefinition:function(e){var t=e.operation,n=e.name,r=t8("(",t6(e.variableDefinitions,", "),")"),i=t6(e.directives," "),a=e.selectionSet;return n||i||r||"query"!==t?t6([t,t6([n,r]),i,a]," "):a},VariableDefinition:function(e){var t=e.variable,n=e.type,r=e.defaultValue,i=e.directives;return t+": "+n+t8(" = ",r)+t8(" ",t6(i," "))},SelectionSet:function(e){return t5(e.selections)},Field:function(e){var t=e.alias,n=e.name,r=e.arguments,i=e.directives,a=e.selectionSet,o=t8("",t,": ")+n,s=o+t8("(",t6(r,", "),")");return s.length>t2&&(s=o+t8("(\n",t9(t6(r,"\n")),"\n)")),t6([s,t6(i," "),a]," ")},Argument:function(e){var t;return e.name+": "+e.value},FragmentSpread:function(e){var t;return"..."+e.name+t8(" ",t6(e.directives," "))},InlineFragment:function(e){var t=e.typeCondition,n=e.directives,r=e.selectionSet;return t6(["...",t8("on ",t),t6(n," "),r]," ")},FragmentDefinition:function(e){var t=e.name,n=e.typeCondition,r=e.variableDefinitions,i=e.directives,a=e.selectionSet;return"fragment ".concat(t).concat(t8("(",t6(r,", "),")")," ")+"on ".concat(n," ").concat(t8("",t6(i," ")," "))+a},IntValue:function(e){return e.value},FloatValue:function(e){return e.value},StringValue:function(e,t){var n=e.value;return e.block?(0,t1.LZ)(n,"description"===t?"":" "):JSON.stringify(n)},BooleanValue:function(e){return e.value?"true":"false"},NullValue:function(){return"null"},EnumValue:function(e){return e.value},ListValue:function(e){return"["+t6(e.values,", ")+"]"},ObjectValue:function(e){return"{"+t6(e.fields,", ")+"}"},ObjectField:function(e){var t;return e.name+": "+e.value},Directive:function(e){var t;return"@"+e.name+t8("(",t6(e.arguments,", "),")")},NamedType:function(e){return e.name},ListType:function(e){return"["+e.type+"]"},NonNullType:function(e){return e.type+"!"},SchemaDefinition:t4(function(e){var t=e.directives,n=e.operationTypes;return t6(["schema",t6(t," "),t5(n)]," ")}),OperationTypeDefinition:function(e){var t;return e.operation+": "+e.type},ScalarTypeDefinition:t4(function(e){var t;return t6(["scalar",e.name,t6(e.directives," ")]," ")}),ObjectTypeDefinition:t4(function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["type",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")}),FieldDefinition:t4(function(e){var t=e.name,n=e.arguments,r=e.type,i=e.directives;return t+(ne(n)?t8("(\n",t9(t6(n,"\n")),"\n)"):t8("(",t6(n,", "),")"))+": "+r+t8(" ",t6(i," "))}),InputValueDefinition:t4(function(e){var t=e.name,n=e.type,r=e.defaultValue,i=e.directives;return t6([t+": "+n,t8("= ",r),t6(i," ")]," ")}),InterfaceTypeDefinition:t4(function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["interface",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")}),UnionTypeDefinition:t4(function(e){var t=e.name,n=e.directives,r=e.types;return t6(["union",t,t6(n," "),r&&0!==r.length?"= "+t6(r," | "):""]," ")}),EnumTypeDefinition:t4(function(e){var t=e.name,n=e.directives,r=e.values;return t6(["enum",t,t6(n," "),t5(r)]," ")}),EnumValueDefinition:t4(function(e){var t;return t6([e.name,t6(e.directives," ")]," ")}),InputObjectTypeDefinition:t4(function(e){var t=e.name,n=e.directives,r=e.fields;return t6(["input",t,t6(n," "),t5(r)]," ")}),DirectiveDefinition:t4(function(e){var t=e.name,n=e.arguments,r=e.repeatable,i=e.locations;return"directive @"+t+(ne(n)?t8("(\n",t9(t6(n,"\n")),"\n)"):t8("(",t6(n,", "),")"))+(r?" repeatable":"")+" on "+t6(i," | ")}),SchemaExtension:function(e){var t=e.directives,n=e.operationTypes;return t6(["extend schema",t6(t," "),t5(n)]," ")},ScalarTypeExtension:function(e){var t;return t6(["extend scalar",e.name,t6(e.directives," ")]," ")},ObjectTypeExtension:function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["extend type",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")},InterfaceTypeExtension:function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["extend interface",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")},UnionTypeExtension:function(e){var t=e.name,n=e.directives,r=e.types;return t6(["extend union",t,t6(n," "),r&&0!==r.length?"= "+t6(r," | "):""]," ")},EnumTypeExtension:function(e){var t=e.name,n=e.directives,r=e.values;return t6(["extend enum",t,t6(n," "),t5(r)]," ")},InputObjectTypeExtension:function(e){var t=e.name,n=e.directives,r=e.fields;return t6(["extend input",t,t6(n," "),t5(r)]," ")}};function t4(e){return function(t){return t6([t.description,e(t)],"\n")}}function t6(e){var t,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return null!==(t=null==e?void 0:e.filter(function(e){return e}).join(n))&&void 0!==t?t:""}function t5(e){return t8("{\n",t9(t6(e,"\n")),"\n}")}function t8(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";return null!=t&&""!==t?e+t+n:""}function t9(e){return t8(" ",e.replace(/\n/g,"\n "))}function t7(e){return -1!==e.indexOf("\n")}function ne(e){return null!=e&&e.some(t7)}var nt,nn,nr,ni={http:{includeQuery:!0,includeExtensions:!1,preserveHeaderCase:!1},headers:{accept:"*/*","content-type":"application/json"},options:{method:"POST"}},na=function(e,t){return t(e)};function no(e,t){for(var n=[],r=2;rObject.create(null),{forEach:nv,slice:ny}=Array.prototype,{hasOwnProperty:nw}=Object.prototype;class n_{constructor(e=!0,t=ng){this.weakness=e,this.makeData=t}lookup(...e){return this.lookupArray(e)}lookupArray(e){let t=this;return nv.call(e,e=>t=t.getChildTrie(e)),nw.call(t,"data")?t.data:t.data=this.makeData(ny.call(e))}peek(...e){return this.peekArray(e)}peekArray(e){let t=this;for(let n=0,r=e.length;t&&n=0;--o)t.definitions[o].kind===nL.h.OPERATION_DEFINITION&&++a;var s=nN(e),u=e.some(function(e){return e.remove}),c=function(e){return u&&e&&e.some(s)},l=new Map,f=!1,d={enter:function(e){if(c(e.directives))return f=!0,null}},h=tl(t,{Field:d,InlineFragment:d,VariableDefinition:{enter:function(){return!1}},Variable:{enter:function(e,t,n,r,a){var o=i(a);o&&o.variables.add(e.name.value)}},FragmentSpread:{enter:function(e,t,n,r,a){if(c(e.directives))return f=!0,null;var o=i(a);o&&o.fragmentSpreads.add(e.name.value)}},FragmentDefinition:{enter:function(e,t,n,r){l.set(JSON.stringify(r),e)},leave:function(e,t,n,i){return e===l.get(JSON.stringify(i))?e:a>0&&e.selectionSet.selections.every(function(e){return e.kind===nL.h.FIELD&&"__typename"===e.name.value})?(r(e.name.value).removed=!0,f=!0,null):void 0}},Directive:{leave:function(e){if(s(e))return f=!0,null}}});if(!f)return t;var p=function(e){return e.transitiveVars||(e.transitiveVars=new Set(e.variables),e.removed||e.fragmentSpreads.forEach(function(t){p(r(t)).transitiveVars.forEach(function(t){e.transitiveVars.add(t)})})),e},b=new Set;h.definitions.forEach(function(e){e.kind===nL.h.OPERATION_DEFINITION?p(n(e.name&&e.name.value)).fragmentSpreads.forEach(function(e){b.add(e)}):e.kind!==nL.h.FRAGMENT_DEFINITION||0!==a||r(e.name.value).removed||b.add(e.name.value)}),b.forEach(function(e){p(r(e)).fragmentSpreads.forEach(function(e){b.add(e)})});var m=function(e){return!!(!b.has(e)||r(e).removed)},g={enter:function(e){if(m(e.name.value))return null}};return nD(tl(h,{FragmentSpread:g,FragmentDefinition:g,OperationDefinition:{leave:function(e){if(e.variableDefinitions){var t=p(n(e.name&&e.name.value)).transitiveVars;if(t.size0},t.prototype.tearDownQuery=function(){this.isTornDown||(this.concast&&this.observer&&(this.concast.removeObserver(this.observer),delete this.concast,delete this.observer),this.stopPolling(),this.subscriptions.forEach(function(e){return e.unsubscribe()}),this.subscriptions.clear(),this.queryManager.stopQuery(this.queryId),this.observers.clear(),this.isTornDown=!0)},t}(eT);function n4(e){var t=e.options,n=t.fetchPolicy,r=t.nextFetchPolicy;return"cache-and-network"===n||"network-only"===n?e.reobserve({fetchPolicy:"cache-first",nextFetchPolicy:function(){return(this.nextFetchPolicy=r,"function"==typeof r)?r.apply(this,arguments):n}}):e.reobserve()}function n6(e){__DEV__&&Q.kG.error("Unhandled error",e.message,e.stack)}function n5(e){__DEV__&&e&&__DEV__&&Q.kG.debug("Missing cache result fields: ".concat(JSON.stringify(e)),e)}function n8(e){return"network-only"===e||"no-cache"===e||"standby"===e}nK(n3);function n9(e){return e.kind===nL.h.FIELD||e.kind===nL.h.FRAGMENT_SPREAD||e.kind===nL.h.INLINE_FRAGMENT}function n7(e){return e.kind===Kind.SCALAR_TYPE_DEFINITION||e.kind===Kind.OBJECT_TYPE_DEFINITION||e.kind===Kind.INTERFACE_TYPE_DEFINITION||e.kind===Kind.UNION_TYPE_DEFINITION||e.kind===Kind.ENUM_TYPE_DEFINITION||e.kind===Kind.INPUT_OBJECT_TYPE_DEFINITION}function re(e){return e.kind===Kind.SCALAR_TYPE_EXTENSION||e.kind===Kind.OBJECT_TYPE_EXTENSION||e.kind===Kind.INTERFACE_TYPE_EXTENSION||e.kind===Kind.UNION_TYPE_EXTENSION||e.kind===Kind.ENUM_TYPE_EXTENSION||e.kind===Kind.INPUT_OBJECT_TYPE_EXTENSION}var rt=function(){return Object.create(null)},rn=Array.prototype,rr=rn.forEach,ri=rn.slice,ra=function(){function e(e,t){void 0===e&&(e=!0),void 0===t&&(t=rt),this.weakness=e,this.makeData=t}return e.prototype.lookup=function(){for(var e=[],t=0;tclass{constructor(){this.id=["slot",rc++,Date.now(),Math.random().toString(36).slice(2),].join(":")}hasValue(){for(let e=rs;e;e=e.parent)if(this.id in e.slots){let t=e.slots[this.id];if(t===ru)break;return e!==rs&&(rs.slots[this.id]=t),!0}return rs&&(rs.slots[this.id]=ru),!1}getValue(){if(this.hasValue())return rs.slots[this.id]}withValue(e,t,n,r){let i={__proto__:null,[this.id]:e},a=rs;rs={parent:a,slots:i};try{return t.apply(r,n)}finally{rs=a}}static bind(e){let t=rs;return function(){let n=rs;try{return rs=t,e.apply(this,arguments)}finally{rs=n}}}static noContext(e,t,n){if(!rs)return e.apply(n,t);{let r=rs;try{return rs=null,e.apply(n,t)}finally{rs=r}}}};function rf(e){try{return e()}catch(t){}}let rd="@wry/context:Slot",rh=rf(()=>globalThis)||rf(()=>global)||Object.create(null),rp=rh,rb=rp[rd]||Array[rd]||function(e){try{Object.defineProperty(rp,rd,{value:e,enumerable:!1,writable:!1,configurable:!0})}finally{return e}}(rl()),{bind:rm,noContext:rg}=rb;function rv(){}var ry=function(){function e(e,t){void 0===e&&(e=1/0),void 0===t&&(t=rv),this.max=e,this.dispose=t,this.map=new Map,this.newest=null,this.oldest=null}return e.prototype.has=function(e){return this.map.has(e)},e.prototype.get=function(e){var t=this.getNode(e);return t&&t.value},e.prototype.getNode=function(e){var t=this.map.get(e);if(t&&t!==this.newest){var n=t.older,r=t.newer;r&&(r.older=n),n&&(n.newer=r),t.older=this.newest,t.older.newer=t,t.newer=null,this.newest=t,t===this.oldest&&(this.oldest=r)}return t},e.prototype.set=function(e,t){var n=this.getNode(e);return n?n.value=t:(n={key:e,value:t,newer:null,older:this.newest},this.newest&&(this.newest.newer=n),this.newest=n,this.oldest=this.oldest||n,this.map.set(e,n),n.value)},e.prototype.clean=function(){for(;this.oldest&&this.map.size>this.max;)this.delete(this.oldest.key)},e.prototype.delete=function(e){var t=this.map.get(e);return!!t&&(t===this.newest&&(this.newest=t.older),t===this.oldest&&(this.oldest=t.newer),t.newer&&(t.newer.older=t.older),t.older&&(t.older.newer=t.newer),this.map.delete(e),this.dispose(t.value,e),!0)},e}(),rw=new rb,r_=Object.prototype.hasOwnProperty,rE=void 0===(n=Array.from)?function(e){var t=[];return e.forEach(function(e){return t.push(e)}),t}:n;function rS(e){var t=e.unsubscribe;"function"==typeof t&&(e.unsubscribe=void 0,t())}var rk=[],rx=100;function rT(e,t){if(!e)throw Error(t||"assertion failure")}function rM(e,t){var n=e.length;return n>0&&n===t.length&&e[n-1]===t[n-1]}function rO(e){switch(e.length){case 0:throw Error("unknown value");case 1:return e[0];case 2:throw e[1]}}function rA(e){return e.slice(0)}var rL=function(){function e(t){this.fn=t,this.parents=new Set,this.childValues=new Map,this.dirtyChildren=null,this.dirty=!0,this.recomputing=!1,this.value=[],this.deps=null,++e.count}return e.prototype.peek=function(){if(1===this.value.length&&!rN(this))return rC(this),this.value[0]},e.prototype.recompute=function(e){return rT(!this.recomputing,"already recomputing"),rC(this),rN(this)?rI(this,e):rO(this.value)},e.prototype.setDirty=function(){this.dirty||(this.dirty=!0,this.value.length=0,rR(this),rS(this))},e.prototype.dispose=function(){var e=this;this.setDirty(),rH(this),rF(this,function(t,n){t.setDirty(),r$(t,e)})},e.prototype.forget=function(){this.dispose()},e.prototype.dependOn=function(e){e.add(this),this.deps||(this.deps=rk.pop()||new Set),this.deps.add(e)},e.prototype.forgetDeps=function(){var e=this;this.deps&&(rE(this.deps).forEach(function(t){return t.delete(e)}),this.deps.clear(),rk.push(this.deps),this.deps=null)},e.count=0,e}();function rC(e){var t=rw.getValue();if(t)return e.parents.add(t),t.childValues.has(e)||t.childValues.set(e,[]),rN(e)?rY(t,e):rB(t,e),t}function rI(e,t){return rH(e),rw.withValue(e,rD,[e,t]),rz(e,t)&&rP(e),rO(e.value)}function rD(e,t){e.recomputing=!0,e.value.length=0;try{e.value[0]=e.fn.apply(null,t)}catch(n){e.value[1]=n}e.recomputing=!1}function rN(e){return e.dirty||!!(e.dirtyChildren&&e.dirtyChildren.size)}function rP(e){e.dirty=!1,!rN(e)&&rj(e)}function rR(e){rF(e,rY)}function rj(e){rF(e,rB)}function rF(e,t){var n=e.parents.size;if(n)for(var r=rE(e.parents),i=0;i0&&e.childValues.forEach(function(t,n){r$(e,n)}),e.forgetDeps(),rT(null===e.dirtyChildren)}function r$(e,t){t.parents.delete(e),e.childValues.delete(t),rU(e,t)}function rz(e,t){if("function"==typeof e.subscribe)try{rS(e),e.unsubscribe=e.subscribe.apply(null,t)}catch(n){return e.setDirty(),!1}return!0}var rG={setDirty:!0,dispose:!0,forget:!0};function rW(e){var t=new Map,n=e&&e.subscribe;function r(e){var r=rw.getValue();if(r){var i=t.get(e);i||t.set(e,i=new Set),r.dependOn(i),"function"==typeof n&&(rS(i),i.unsubscribe=n(e))}}return r.dirty=function(e,n){var r=t.get(e);if(r){var i=n&&r_.call(rG,n)?n:"setDirty";rE(r).forEach(function(e){return e[i]()}),t.delete(e),rS(r)}},r}function rK(){var e=new ra("function"==typeof WeakMap);return function(){return e.lookupArray(arguments)}}var rV=rK(),rq=new Set;function rZ(e,t){void 0===t&&(t=Object.create(null));var n=new ry(t.max||65536,function(e){return e.dispose()}),r=t.keyArgs,i=t.makeCacheKey||rK(),a=function(){var a=i.apply(null,r?r.apply(null,arguments):arguments);if(void 0===a)return e.apply(null,arguments);var o=n.get(a);o||(n.set(a,o=new rL(e)),o.subscribe=t.subscribe,o.forget=function(){return n.delete(a)});var s=o.recompute(Array.prototype.slice.call(arguments));return n.set(a,o),rq.add(n),rw.hasValue()||(rq.forEach(function(e){return e.clean()}),rq.clear()),s};function o(e){var t=n.get(e);t&&t.setDirty()}function s(e){var t=n.get(e);if(t)return t.peek()}function u(e){return n.delete(e)}return Object.defineProperty(a,"size",{get:function(){return n.map.size},configurable:!1,enumerable:!1}),a.dirtyKey=o,a.dirty=function(){o(i.apply(null,arguments))},a.peekKey=s,a.peek=function(){return s(i.apply(null,arguments))},a.forgetKey=u,a.forget=function(){return u(i.apply(null,arguments))},a.makeCacheKey=i,a.getKey=r?function(){return i.apply(null,r.apply(null,arguments))}:i,Object.freeze(a)}var rX=new rb,rJ=new WeakMap;function rQ(e){var t=rJ.get(e);return t||rJ.set(e,t={vars:new Set,dep:rW()}),t}function r1(e){rQ(e).vars.forEach(function(t){return t.forgetCache(e)})}function r0(e){rQ(e).vars.forEach(function(t){return t.attachCache(e)})}function r2(e){var t=new Set,n=new Set,r=function(a){if(arguments.length>0){if(e!==a){e=a,t.forEach(function(e){rQ(e).dep.dirty(r),r3(e)});var o=Array.from(n);n.clear(),o.forEach(function(t){return t(e)})}}else{var s=rX.getValue();s&&(i(s),rQ(s).dep(r))}return e};r.onNextChange=function(e){return n.add(e),function(){n.delete(e)}};var i=r.attachCache=function(e){return t.add(e),rQ(e).vars.add(r),r};return r.forgetCache=function(e){return t.delete(e)},r}function r3(e){e.broadcastWatches&&e.broadcastWatches()}var r4=function(){function e(e){var t=e.cache,n=e.client,r=e.resolvers,i=e.fragmentMatcher;this.selectionsToResolveCache=new WeakMap,this.cache=t,n&&(this.client=n),r&&this.addResolvers(r),i&&this.setFragmentMatcher(i)}return e.prototype.addResolvers=function(e){var t=this;this.resolvers=this.resolvers||{},Array.isArray(e)?e.forEach(function(e){t.resolvers=tj(t.resolvers,e)}):this.resolvers=tj(this.resolvers,e)},e.prototype.setResolvers=function(e){this.resolvers={},this.addResolvers(e)},e.prototype.getResolvers=function(){return this.resolvers||{}},e.prototype.runResolvers=function(e){var t=e.document,n=e.remoteResult,r=e.context,i=e.variables,a=e.onlyRunForcedResolvers,o=void 0!==a&&a;return(0,en.mG)(this,void 0,void 0,function(){return(0,en.Jh)(this,function(e){return t?[2,this.resolveDocument(t,n.data,r,i,this.fragmentMatcher,o).then(function(e){return(0,en.pi)((0,en.pi)({},n),{data:e.result})})]:[2,n]})})},e.prototype.setFragmentMatcher=function(e){this.fragmentMatcher=e},e.prototype.getFragmentMatcher=function(){return this.fragmentMatcher},e.prototype.clientQuery=function(e){return tb(["client"],e)&&this.resolvers?e:null},e.prototype.serverQuery=function(e){return n$(e)},e.prototype.prepareContext=function(e){var t=this.cache;return(0,en.pi)((0,en.pi)({},e),{cache:t,getCacheKey:function(e){return t.identify(e)}})},e.prototype.addExportedVariables=function(e,t,n){return void 0===t&&(t={}),void 0===n&&(n={}),(0,en.mG)(this,void 0,void 0,function(){return(0,en.Jh)(this,function(r){return e?[2,this.resolveDocument(e,this.buildRootValueFromCache(e,t)||{},this.prepareContext(n),t).then(function(e){return(0,en.pi)((0,en.pi)({},t),e.exportedVariables)})]:[2,(0,en.pi)({},t)]})})},e.prototype.shouldForceResolvers=function(e){var t=!1;return tl(e,{Directive:{enter:function(e){if("client"===e.name.value&&e.arguments&&(t=e.arguments.some(function(e){return"always"===e.name.value&&"BooleanValue"===e.value.kind&&!0===e.value.value})))return tc}}}),t},e.prototype.buildRootValueFromCache=function(e,t){return this.cache.diff({query:nH(e),variables:t,returnPartialData:!0,optimistic:!1}).result},e.prototype.resolveDocument=function(e,t,n,r,i,a){return void 0===n&&(n={}),void 0===r&&(r={}),void 0===i&&(i=function(){return!0}),void 0===a&&(a=!1),(0,en.mG)(this,void 0,void 0,function(){var o,s,u,c,l,f,d,h,p,b,m;return(0,en.Jh)(this,function(g){return o=e8(e),s=e4(e),u=eL(s),c=this.collectSelectionsToResolve(o,u),f=(l=o.operation)?l.charAt(0).toUpperCase()+l.slice(1):"Query",d=this,h=d.cache,p=d.client,b={fragmentMap:u,context:(0,en.pi)((0,en.pi)({},n),{cache:h,client:p}),variables:r,fragmentMatcher:i,defaultOperationType:f,exportedVariables:{},selectionsToResolve:c,onlyRunForcedResolvers:a},m=!1,[2,this.resolveSelectionSet(o.selectionSet,m,t,b).then(function(e){return{result:e,exportedVariables:b.exportedVariables}})]})})},e.prototype.resolveSelectionSet=function(e,t,n,r){return(0,en.mG)(this,void 0,void 0,function(){var i,a,o,s,u,c=this;return(0,en.Jh)(this,function(l){return i=r.fragmentMap,a=r.context,o=r.variables,s=[n],u=function(e){return(0,en.mG)(c,void 0,void 0,function(){var u,c;return(0,en.Jh)(this,function(l){return(t||r.selectionsToResolve.has(e))&&td(e,o)?eQ(e)?[2,this.resolveField(e,t,n,r).then(function(t){var n;void 0!==t&&s.push(((n={})[eX(e)]=t,n))})]:(e1(e)?u=e:(u=i[e.name.value],__DEV__?(0,Q.kG)(u,"No fragment named ".concat(e.name.value)):(0,Q.kG)(u,11)),u&&u.typeCondition&&(c=u.typeCondition.name.value,r.fragmentMatcher(n,c,a)))?[2,this.resolveSelectionSet(u.selectionSet,t,n,r).then(function(e){s.push(e)})]:[2]:[2]})})},[2,Promise.all(e.selections.map(u)).then(function(){return tF(s)})]})})},e.prototype.resolveField=function(e,t,n,r){return(0,en.mG)(this,void 0,void 0,function(){var i,a,o,s,u,c,l,f,d,h=this;return(0,en.Jh)(this,function(p){return n?(i=r.variables,a=e.name.value,o=eX(e),s=a!==o,c=Promise.resolve(u=n[o]||n[a]),(!r.onlyRunForcedResolvers||this.shouldForceResolvers(e))&&(l=n.__typename||r.defaultOperationType,(f=this.resolvers&&this.resolvers[l])&&(d=f[s?a:o])&&(c=Promise.resolve(rX.withValue(this.cache,d,[n,eZ(e,i),r.context,{field:e,fragmentMap:r.fragmentMap},])))),[2,c.then(function(n){if(void 0===n&&(n=u),e.directives&&e.directives.forEach(function(e){"export"===e.name.value&&e.arguments&&e.arguments.forEach(function(e){"as"===e.name.value&&"StringValue"===e.value.kind&&(r.exportedVariables[e.value.value]=n)})}),!e.selectionSet||null==n)return n;var i,a,o=null!==(a=null===(i=e.directives)||void 0===i?void 0:i.some(function(e){return"client"===e.name.value}))&&void 0!==a&&a;return Array.isArray(n)?h.resolveSubSelectedArray(e,t||o,n,r):e.selectionSet?h.resolveSelectionSet(e.selectionSet,t||o,n,r):void 0})]):[2,null]})})},e.prototype.resolveSubSelectedArray=function(e,t,n,r){var i=this;return Promise.all(n.map(function(n){return null===n?null:Array.isArray(n)?i.resolveSubSelectedArray(e,t,n,r):e.selectionSet?i.resolveSelectionSet(e.selectionSet,t,n,r):void 0}))},e.prototype.collectSelectionsToResolve=function(e,t){var n=function(e){return!Array.isArray(e)},r=this.selectionsToResolveCache;function i(e){if(!r.has(e)){var a=new Set;r.set(e,a),tl(e,{Directive:function(e,t,r,i,o){"client"===e.name.value&&o.forEach(function(e){n(e)&&n9(e)&&a.add(e)})},FragmentSpread:function(e,r,o,s,u){var c=t[e.name.value];__DEV__?(0,Q.kG)(c,"No fragment named ".concat(e.name.value)):(0,Q.kG)(c,12);var l=i(c);l.size>0&&(u.forEach(function(e){n(e)&&n9(e)&&a.add(e)}),a.add(e),l.forEach(function(e){a.add(e)}))}})}return r.get(e)}return i(e)},e}(),r6=new(t_.mr?WeakMap:Map);function r5(e,t){var n=e[t];"function"==typeof n&&(e[t]=function(){return r6.set(e,(r6.get(e)+1)%1e15),n.apply(this,arguments)})}function r8(e){e.notifyTimeout&&(clearTimeout(e.notifyTimeout),e.notifyTimeout=void 0)}var r9=function(){function e(e,t){void 0===t&&(t=e.generateQueryId()),this.queryId=t,this.listeners=new Set,this.document=null,this.lastRequestId=1,this.subscriptions=new Set,this.stopped=!1,this.dirty=!1,this.observableQuery=null;var n=this.cache=e.cache;r6.has(n)||(r6.set(n,0),r5(n,"evict"),r5(n,"modify"),r5(n,"reset"))}return e.prototype.init=function(e){var t=e.networkStatus||nZ.I.loading;return this.variables&&this.networkStatus!==nZ.I.loading&&!(0,nm.D)(this.variables,e.variables)&&(t=nZ.I.setVariables),(0,nm.D)(e.variables,this.variables)||(this.lastDiff=void 0),Object.assign(this,{document:e.document,variables:e.variables,networkError:null,graphQLErrors:this.graphQLErrors||[],networkStatus:t}),e.observableQuery&&this.setObservableQuery(e.observableQuery),e.lastRequestId&&(this.lastRequestId=e.lastRequestId),this},e.prototype.reset=function(){r8(this),this.dirty=!1},e.prototype.getDiff=function(e){void 0===e&&(e=this.variables);var t=this.getDiffOptions(e);if(this.lastDiff&&(0,nm.D)(t,this.lastDiff.options))return this.lastDiff.diff;this.updateWatch(this.variables=e);var n=this.observableQuery;if(n&&"no-cache"===n.options.fetchPolicy)return{complete:!1};var r=this.cache.diff(t);return this.updateLastDiff(r,t),r},e.prototype.updateLastDiff=function(e,t){this.lastDiff=e?{diff:e,options:t||this.getDiffOptions()}:void 0},e.prototype.getDiffOptions=function(e){var t;return void 0===e&&(e=this.variables),{query:this.document,variables:e,returnPartialData:!0,optimistic:!0,canonizeResults:null===(t=this.observableQuery)||void 0===t?void 0:t.options.canonizeResults}},e.prototype.setDiff=function(e){var t=this,n=this.lastDiff&&this.lastDiff.diff;this.updateLastDiff(e),this.dirty||(0,nm.D)(n&&n.result,e&&e.result)||(this.dirty=!0,this.notifyTimeout||(this.notifyTimeout=setTimeout(function(){return t.notify()},0)))},e.prototype.setObservableQuery=function(e){var t=this;e!==this.observableQuery&&(this.oqListener&&this.listeners.delete(this.oqListener),this.observableQuery=e,e?(e.queryInfo=this,this.listeners.add(this.oqListener=function(){t.getDiff().fromOptimisticTransaction?e.observe():n4(e)})):delete this.oqListener)},e.prototype.notify=function(){var e=this;r8(this),this.shouldNotify()&&this.listeners.forEach(function(t){return t(e)}),this.dirty=!1},e.prototype.shouldNotify=function(){if(!this.dirty||!this.listeners.size)return!1;if((0,nZ.O)(this.networkStatus)&&this.observableQuery){var e=this.observableQuery.options.fetchPolicy;if("cache-only"!==e&&"cache-and-network"!==e)return!1}return!0},e.prototype.stop=function(){if(!this.stopped){this.stopped=!0,this.reset(),this.cancel(),this.cancel=e.prototype.cancel,this.subscriptions.forEach(function(e){return e.unsubscribe()});var t=this.observableQuery;t&&t.stopPolling()}},e.prototype.cancel=function(){},e.prototype.updateWatch=function(e){var t=this;void 0===e&&(e=this.variables);var n=this.observableQuery;if(!n||"no-cache"!==n.options.fetchPolicy){var r=(0,en.pi)((0,en.pi)({},this.getDiffOptions(e)),{watcher:this,callback:function(e){return t.setDiff(e)}});this.lastWatch&&(0,nm.D)(r,this.lastWatch)||(this.cancel(),this.cancel=this.cache.watch(this.lastWatch=r))}},e.prototype.resetLastWrite=function(){this.lastWrite=void 0},e.prototype.shouldWrite=function(e,t){var n=this.lastWrite;return!(n&&n.dmCount===r6.get(this.cache)&&(0,nm.D)(t,n.variables)&&(0,nm.D)(e.data,n.result.data))},e.prototype.markResult=function(e,t,n,r){var i=this,a=new tB,o=(0,tP.O)(e.errors)?e.errors.slice(0):[];if(this.reset(),"incremental"in e&&(0,tP.O)(e.incremental)){var s=tG(this.getDiff().result,e);e.data=s}else if("hasNext"in e&&e.hasNext){var u=this.getDiff();e.data=a.merge(u.result,e.data)}this.graphQLErrors=o,"no-cache"===n.fetchPolicy?this.updateLastDiff({result:e.data,complete:!0},this.getDiffOptions(n.variables)):0!==r&&(r7(e,n.errorPolicy)?this.cache.performTransaction(function(a){if(i.shouldWrite(e,n.variables))a.writeQuery({query:t,data:e.data,variables:n.variables,overwrite:1===r}),i.lastWrite={result:e,variables:n.variables,dmCount:r6.get(i.cache)};else if(i.lastDiff&&i.lastDiff.diff.complete){e.data=i.lastDiff.diff.result;return}var o=i.getDiffOptions(n.variables),s=a.diff(o);i.stopped||i.updateWatch(n.variables),i.updateLastDiff(s,o),s.complete&&(e.data=s.result)}):this.lastWrite=void 0)},e.prototype.markReady=function(){return this.networkError=null,this.networkStatus=nZ.I.ready},e.prototype.markError=function(e){return this.networkStatus=nZ.I.error,this.lastWrite=void 0,this.reset(),e.graphQLErrors&&(this.graphQLErrors=e.graphQLErrors),e.networkError&&(this.networkError=e.networkError),e},e}();function r7(e,t){void 0===t&&(t="none");var n="ignore"===t||"all"===t,r=!nO(e);return!r&&n&&e.data&&(r=!0),r}var ie=Object.prototype.hasOwnProperty,it=function(){function e(e){var t=e.cache,n=e.link,r=e.defaultOptions,i=e.queryDeduplication,a=void 0!==i&&i,o=e.onBroadcast,s=e.ssrMode,u=void 0!==s&&s,c=e.clientAwareness,l=void 0===c?{}:c,f=e.localState,d=e.assumeImmutableResults;this.clientAwareness={},this.queries=new Map,this.fetchCancelFns=new Map,this.transformCache=new(t_.mr?WeakMap:Map),this.queryIdCounter=1,this.requestIdCounter=1,this.mutationIdCounter=1,this.inFlightLinkObservables=new Map,this.cache=t,this.link=n,this.defaultOptions=r||Object.create(null),this.queryDeduplication=a,this.clientAwareness=l,this.localState=f||new r4({cache:t}),this.ssrMode=u,this.assumeImmutableResults=!!d,(this.onBroadcast=o)&&(this.mutationStore=Object.create(null))}return e.prototype.stop=function(){var e=this;this.queries.forEach(function(t,n){e.stopQueryNoBroadcast(n)}),this.cancelPendingFetches(__DEV__?new Q.ej("QueryManager stopped while query was in flight"):new Q.ej(14))},e.prototype.cancelPendingFetches=function(e){this.fetchCancelFns.forEach(function(t){return t(e)}),this.fetchCancelFns.clear()},e.prototype.mutate=function(e){var t,n,r=e.mutation,i=e.variables,a=e.optimisticResponse,o=e.updateQueries,s=e.refetchQueries,u=void 0===s?[]:s,c=e.awaitRefetchQueries,l=void 0!==c&&c,f=e.update,d=e.onQueryUpdated,h=e.fetchPolicy,p=void 0===h?(null===(t=this.defaultOptions.mutate)||void 0===t?void 0:t.fetchPolicy)||"network-only":h,b=e.errorPolicy,m=void 0===b?(null===(n=this.defaultOptions.mutate)||void 0===n?void 0:n.errorPolicy)||"none":b,g=e.keepRootFields,v=e.context;return(0,en.mG)(this,void 0,void 0,function(){var e,t,n,s,c,h;return(0,en.Jh)(this,function(b){switch(b.label){case 0:if(__DEV__?(0,Q.kG)(r,"mutation option is required. You must specify your GraphQL document in the mutation option."):(0,Q.kG)(r,15),__DEV__?(0,Q.kG)("network-only"===p||"no-cache"===p,"Mutations support only 'network-only' or 'no-cache' fetchPolicy strings. The default `network-only` behavior automatically writes mutation results to the cache. Passing `no-cache` skips the cache write."):(0,Q.kG)("network-only"===p||"no-cache"===p,16),e=this.generateMutationId(),n=(t=this.transform(r)).document,s=t.hasClientExports,r=this.cache.transformForLink(n),i=this.getVariables(r,i),!s)return[3,2];return[4,this.localState.addExportedVariables(r,i,v)];case 1:i=b.sent(),b.label=2;case 2:return c=this.mutationStore&&(this.mutationStore[e]={mutation:r,variables:i,loading:!0,error:null}),a&&this.markMutationOptimistic(a,{mutationId:e,document:r,variables:i,fetchPolicy:p,errorPolicy:m,context:v,updateQueries:o,update:f,keepRootFields:g}),this.broadcastQueries(),h=this,[2,new Promise(function(t,n){return nM(h.getObservableFromLink(r,(0,en.pi)((0,en.pi)({},v),{optimisticResponse:a}),i,!1),function(t){if(nO(t)&&"none"===m)throw new tN.cA({graphQLErrors:nA(t)});c&&(c.loading=!1,c.error=null);var n=(0,en.pi)({},t);return"function"==typeof u&&(u=u(n)),"ignore"===m&&nO(n)&&delete n.errors,h.markMutationResult({mutationId:e,result:n,document:r,variables:i,fetchPolicy:p,errorPolicy:m,context:v,update:f,updateQueries:o,awaitRefetchQueries:l,refetchQueries:u,removeOptimistic:a?e:void 0,onQueryUpdated:d,keepRootFields:g})}).subscribe({next:function(e){h.broadcastQueries(),"hasNext"in e&&!1!==e.hasNext||t(e)},error:function(t){c&&(c.loading=!1,c.error=t),a&&h.cache.removeOptimistic(e),h.broadcastQueries(),n(t instanceof tN.cA?t:new tN.cA({networkError:t}))}})})]}})})},e.prototype.markMutationResult=function(e,t){var n=this;void 0===t&&(t=this.cache);var r=e.result,i=[],a="no-cache"===e.fetchPolicy;if(!a&&r7(r,e.errorPolicy)){if(tU(r)||i.push({result:r.data,dataId:"ROOT_MUTATION",query:e.document,variables:e.variables}),tU(r)&&(0,tP.O)(r.incremental)){var o=t.diff({id:"ROOT_MUTATION",query:this.transform(e.document).asQuery,variables:e.variables,optimistic:!1,returnPartialData:!0}),s=void 0;o.result&&(s=tG(o.result,r)),void 0!==s&&(r.data=s,i.push({result:s,dataId:"ROOT_MUTATION",query:e.document,variables:e.variables}))}var u=e.updateQueries;u&&this.queries.forEach(function(e,a){var o=e.observableQuery,s=o&&o.queryName;if(s&&ie.call(u,s)){var c,l=u[s],f=n.queries.get(a),d=f.document,h=f.variables,p=t.diff({query:d,variables:h,returnPartialData:!0,optimistic:!1}),b=p.result;if(p.complete&&b){var m=l(b,{mutationResult:r,queryName:d&&e3(d)||void 0,queryVariables:h});m&&i.push({result:m,dataId:"ROOT_QUERY",query:d,variables:h})}}})}if(i.length>0||e.refetchQueries||e.update||e.onQueryUpdated||e.removeOptimistic){var c=[];if(this.refetchQueries({updateCache:function(t){a||i.forEach(function(e){return t.write(e)});var o=e.update,s=!t$(r)||tU(r)&&!r.hasNext;if(o){if(!a){var u=t.diff({id:"ROOT_MUTATION",query:n.transform(e.document).asQuery,variables:e.variables,optimistic:!1,returnPartialData:!0});u.complete&&("incremental"in(r=(0,en.pi)((0,en.pi)({},r),{data:u.result}))&&delete r.incremental,"hasNext"in r&&delete r.hasNext)}s&&o(t,r,{context:e.context,variables:e.variables})}a||e.keepRootFields||!s||t.modify({id:"ROOT_MUTATION",fields:function(e,t){var n=t.fieldName,r=t.DELETE;return"__typename"===n?e:r}})},include:e.refetchQueries,optimistic:!1,removeOptimistic:e.removeOptimistic,onQueryUpdated:e.onQueryUpdated||null}).forEach(function(e){return c.push(e)}),e.awaitRefetchQueries||e.onQueryUpdated)return Promise.all(c).then(function(){return r})}return Promise.resolve(r)},e.prototype.markMutationOptimistic=function(e,t){var n=this,r="function"==typeof e?e(t.variables):e;return this.cache.recordOptimisticTransaction(function(e){try{n.markMutationResult((0,en.pi)((0,en.pi)({},t),{result:{data:r}}),e)}catch(i){__DEV__&&Q.kG.error(i)}},t.mutationId)},e.prototype.fetchQuery=function(e,t,n){return this.fetchQueryObservable(e,t,n).promise},e.prototype.getQueryStore=function(){var e=Object.create(null);return this.queries.forEach(function(t,n){e[n]={variables:t.variables,networkStatus:t.networkStatus,networkError:t.networkError,graphQLErrors:t.graphQLErrors}}),e},e.prototype.resetErrors=function(e){var t=this.queries.get(e);t&&(t.networkError=void 0,t.graphQLErrors=[])},e.prototype.transform=function(e){var t=this.transformCache;if(!t.has(e)){var n=this.cache.transformDocument(e),r=nY(n),i=this.localState.clientQuery(n),a=r&&this.localState.serverQuery(r),o={document:n,hasClientExports:tm(n),hasForcedResolvers:this.localState.shouldForceResolvers(n),clientQuery:i,serverQuery:a,defaultVars:e9(e2(n)),asQuery:(0,en.pi)((0,en.pi)({},n),{definitions:n.definitions.map(function(e){return"OperationDefinition"===e.kind&&"query"!==e.operation?(0,en.pi)((0,en.pi)({},e),{operation:"query"}):e})})},s=function(e){e&&!t.has(e)&&t.set(e,o)};s(e),s(n),s(i),s(a)}return t.get(e)},e.prototype.getVariables=function(e,t){return(0,en.pi)((0,en.pi)({},this.transform(e).defaultVars),t)},e.prototype.watchQuery=function(e){void 0===(e=(0,en.pi)((0,en.pi)({},e),{variables:this.getVariables(e.query,e.variables)})).notifyOnNetworkStatusChange&&(e.notifyOnNetworkStatusChange=!1);var t=new r9(this),n=new n3({queryManager:this,queryInfo:t,options:e});return this.queries.set(n.queryId,t),t.init({document:n.query,observableQuery:n,variables:n.variables}),n},e.prototype.query=function(e,t){var n=this;return void 0===t&&(t=this.generateQueryId()),__DEV__?(0,Q.kG)(e.query,"query option is required. You must specify your GraphQL document in the query option."):(0,Q.kG)(e.query,17),__DEV__?(0,Q.kG)("Document"===e.query.kind,'You must wrap the query string in a "gql" tag.'):(0,Q.kG)("Document"===e.query.kind,18),__DEV__?(0,Q.kG)(!e.returnPartialData,"returnPartialData option only supported on watchQuery."):(0,Q.kG)(!e.returnPartialData,19),__DEV__?(0,Q.kG)(!e.pollInterval,"pollInterval option only supported on watchQuery."):(0,Q.kG)(!e.pollInterval,20),this.fetchQuery(t,e).finally(function(){return n.stopQuery(t)})},e.prototype.generateQueryId=function(){return String(this.queryIdCounter++)},e.prototype.generateRequestId=function(){return this.requestIdCounter++},e.prototype.generateMutationId=function(){return String(this.mutationIdCounter++)},e.prototype.stopQueryInStore=function(e){this.stopQueryInStoreNoBroadcast(e),this.broadcastQueries()},e.prototype.stopQueryInStoreNoBroadcast=function(e){var t=this.queries.get(e);t&&t.stop()},e.prototype.clearStore=function(e){return void 0===e&&(e={discardWatches:!0}),this.cancelPendingFetches(__DEV__?new Q.ej("Store reset while query was in flight (not completed in link chain)"):new Q.ej(21)),this.queries.forEach(function(e){e.observableQuery?e.networkStatus=nZ.I.loading:e.stop()}),this.mutationStore&&(this.mutationStore=Object.create(null)),this.cache.reset(e)},e.prototype.getObservableQueries=function(e){var t=this;void 0===e&&(e="active");var n=new Map,r=new Map,i=new Set;return Array.isArray(e)&&e.forEach(function(e){"string"==typeof e?r.set(e,!1):eN(e)?r.set(t.transform(e).document,!1):(0,eO.s)(e)&&e.query&&i.add(e)}),this.queries.forEach(function(t,i){var a=t.observableQuery,o=t.document;if(a){if("all"===e){n.set(i,a);return}var s=a.queryName;if("standby"===a.options.fetchPolicy||"active"===e&&!a.hasObservers())return;("active"===e||s&&r.has(s)||o&&r.has(o))&&(n.set(i,a),s&&r.set(s,!0),o&&r.set(o,!0))}}),i.size&&i.forEach(function(e){var r=nG("legacyOneTimeQuery"),i=t.getQuery(r).init({document:e.query,variables:e.variables}),a=new n3({queryManager:t,queryInfo:i,options:(0,en.pi)((0,en.pi)({},e),{fetchPolicy:"network-only"})});(0,Q.kG)(a.queryId===r),i.setObservableQuery(a),n.set(r,a)}),__DEV__&&r.size&&r.forEach(function(e,t){!e&&__DEV__&&Q.kG.warn("Unknown query ".concat("string"==typeof t?"named ":"").concat(JSON.stringify(t,null,2)," requested in refetchQueries options.include array"))}),n},e.prototype.reFetchObservableQueries=function(e){var t=this;void 0===e&&(e=!1);var n=[];return this.getObservableQueries(e?"all":"active").forEach(function(r,i){var a=r.options.fetchPolicy;r.resetLastResults(),(e||"standby"!==a&&"cache-only"!==a)&&n.push(r.refetch()),t.getQuery(i).setDiff(null)}),this.broadcastQueries(),Promise.all(n)},e.prototype.setObservableQuery=function(e){this.getQuery(e.queryId).setObservableQuery(e)},e.prototype.startGraphQLSubscription=function(e){var t=this,n=e.query,r=e.fetchPolicy,i=e.errorPolicy,a=e.variables,o=e.context,s=void 0===o?{}:o;n=this.transform(n).document,a=this.getVariables(n,a);var u=function(e){return t.getObservableFromLink(n,s,e).map(function(a){"no-cache"!==r&&(r7(a,i)&&t.cache.write({query:n,result:a.data,dataId:"ROOT_SUBSCRIPTION",variables:e}),t.broadcastQueries());var o=nO(a),s=(0,tN.ls)(a);if(o||s){var u={};throw o&&(u.graphQLErrors=a.errors),s&&(u.protocolErrors=a.extensions[tN.YG]),new tN.cA(u)}return a})};if(this.transform(n).hasClientExports){var c=this.localState.addExportedVariables(n,a,s).then(u);return new eT(function(e){var t=null;return c.then(function(n){return t=n.subscribe(e)},e.error),function(){return t&&t.unsubscribe()}})}return u(a)},e.prototype.stopQuery=function(e){this.stopQueryNoBroadcast(e),this.broadcastQueries()},e.prototype.stopQueryNoBroadcast=function(e){this.stopQueryInStoreNoBroadcast(e),this.removeQuery(e)},e.prototype.removeQuery=function(e){this.fetchCancelFns.delete(e),this.queries.has(e)&&(this.getQuery(e).stop(),this.queries.delete(e))},e.prototype.broadcastQueries=function(){this.onBroadcast&&this.onBroadcast(),this.queries.forEach(function(e){return e.notify()})},e.prototype.getLocalState=function(){return this.localState},e.prototype.getObservableFromLink=function(e,t,n,r){var i,a,o=this;void 0===r&&(r=null!==(i=null==t?void 0:t.queryDeduplication)&&void 0!==i?i:this.queryDeduplication);var s=this.transform(e).serverQuery;if(s){var u=this,c=u.inFlightLinkObservables,l=u.link,f={query:s,variables:n,operationName:e3(s)||void 0,context:this.prepareContext((0,en.pi)((0,en.pi)({},t),{forceFetch:!r}))};if(t=f.context,r){var d=c.get(s)||new Map;c.set(s,d);var h=nx(n);if(!(a=d.get(h))){var p=new nq([np(l,f)]);d.set(h,a=p),p.beforeNext(function(){d.delete(h)&&d.size<1&&c.delete(s)})}}else a=new nq([np(l,f)])}else a=new nq([eT.of({data:{}})]),t=this.prepareContext(t);var b=this.transform(e).clientQuery;return b&&(a=nM(a,function(e){return o.localState.runResolvers({document:b,remoteResult:e,context:t,variables:n})})),a},e.prototype.getResultsFromLink=function(e,t,n){var r=e.lastRequestId=this.generateRequestId(),i=this.cache.transformForLink(this.transform(e.document).document);return nM(this.getObservableFromLink(i,n.context,n.variables),function(a){var o=nA(a),s=o.length>0;if(r>=e.lastRequestId){if(s&&"none"===n.errorPolicy)throw e.markError(new tN.cA({graphQLErrors:o}));e.markResult(a,i,n,t),e.markReady()}var u={data:a.data,loading:!1,networkStatus:nZ.I.ready};return s&&"ignore"!==n.errorPolicy&&(u.errors=o,u.networkStatus=nZ.I.error),u},function(t){var n=(0,tN.MS)(t)?t:new tN.cA({networkError:t});throw r>=e.lastRequestId&&e.markError(n),n})},e.prototype.fetchQueryObservable=function(e,t,n){return this.fetchConcastWithInfo(e,t,n).concast},e.prototype.fetchConcastWithInfo=function(e,t,n){var r,i,a=this;void 0===n&&(n=nZ.I.loading);var o=this.transform(t.query).document,s=this.getVariables(o,t.variables),u=this.getQuery(e),c=this.defaultOptions.watchQuery,l=t.fetchPolicy,f=void 0===l?c&&c.fetchPolicy||"cache-first":l,d=t.errorPolicy,h=void 0===d?c&&c.errorPolicy||"none":d,p=t.returnPartialData,b=void 0!==p&&p,m=t.notifyOnNetworkStatusChange,g=void 0!==m&&m,v=t.context,y=void 0===v?{}:v,w=Object.assign({},t,{query:o,variables:s,fetchPolicy:f,errorPolicy:h,returnPartialData:b,notifyOnNetworkStatusChange:g,context:y}),_=function(e){w.variables=e;var r=a.fetchQueryByPolicy(u,w,n);return"standby"!==w.fetchPolicy&&r.sources.length>0&&u.observableQuery&&u.observableQuery.applyNextFetchPolicy("after-fetch",t),r},E=function(){return a.fetchCancelFns.delete(e)};if(this.fetchCancelFns.set(e,function(e){E(),setTimeout(function(){return r.cancel(e)})}),this.transform(w.query).hasClientExports)r=new nq(this.localState.addExportedVariables(w.query,w.variables,w.context).then(_).then(function(e){return e.sources})),i=!0;else{var S=_(w.variables);i=S.fromLink,r=new nq(S.sources)}return r.promise.then(E,E),{concast:r,fromLink:i}},e.prototype.refetchQueries=function(e){var t=this,n=e.updateCache,r=e.include,i=e.optimistic,a=void 0!==i&&i,o=e.removeOptimistic,s=void 0===o?a?nG("refetchQueries"):void 0:o,u=e.onQueryUpdated,c=new Map;r&&this.getObservableQueries(r).forEach(function(e,n){c.set(n,{oq:e,lastDiff:t.getQuery(n).getDiff()})});var l=new Map;return n&&this.cache.batch({update:n,optimistic:a&&s||!1,removeOptimistic:s,onWatchUpdated:function(e,t,n){var r=e.watcher instanceof r9&&e.watcher.observableQuery;if(r){if(u){c.delete(r.queryId);var i=u(r,t,n);return!0===i&&(i=r.refetch()),!1!==i&&l.set(r,i),i}null!==u&&c.set(r.queryId,{oq:r,lastDiff:n,diff:t})}}}),c.size&&c.forEach(function(e,n){var r,i=e.oq,a=e.lastDiff,o=e.diff;if(u){if(!o){var s=i.queryInfo;s.reset(),o=s.getDiff()}r=u(i,o,a)}u&&!0!==r||(r=i.refetch()),!1!==r&&l.set(i,r),n.indexOf("legacyOneTimeQuery")>=0&&t.stopQueryNoBroadcast(n)}),s&&this.cache.removeOptimistic(s),l},e.prototype.fetchQueryByPolicy=function(e,t,n){var r=this,i=t.query,a=t.variables,o=t.fetchPolicy,s=t.refetchWritePolicy,u=t.errorPolicy,c=t.returnPartialData,l=t.context,f=t.notifyOnNetworkStatusChange,d=e.networkStatus;e.init({document:this.transform(i).document,variables:a,networkStatus:n});var h=function(){return e.getDiff(a)},p=function(t,n){void 0===n&&(n=e.networkStatus||nZ.I.loading);var o=t.result;!__DEV__||c||(0,nm.D)(o,{})||n5(t.missing);var s=function(e){return eT.of((0,en.pi)({data:e,loading:(0,nZ.O)(n),networkStatus:n},t.complete?null:{partial:!0}))};return o&&r.transform(i).hasForcedResolvers?r.localState.runResolvers({document:i,remoteResult:{data:o},context:l,variables:a,onlyRunForcedResolvers:!0}).then(function(e){return s(e.data||void 0)}):"none"===u&&n===nZ.I.refetch&&Array.isArray(t.missing)?s(void 0):s(o)},b="no-cache"===o?0:n===nZ.I.refetch&&"merge"!==s?1:2,m=function(){return r.getResultsFromLink(e,b,{variables:a,context:l,fetchPolicy:o,errorPolicy:u})},g=f&&"number"==typeof d&&d!==n&&(0,nZ.O)(n);switch(o){default:case"cache-first":var v=h();if(v.complete)return{fromLink:!1,sources:[p(v,e.markReady())]};if(c||g)return{fromLink:!0,sources:[p(v),m()]};return{fromLink:!0,sources:[m()]};case"cache-and-network":var v=h();if(v.complete||c||g)return{fromLink:!0,sources:[p(v),m()]};return{fromLink:!0,sources:[m()]};case"cache-only":return{fromLink:!1,sources:[p(h(),e.markReady())]};case"network-only":if(g)return{fromLink:!0,sources:[p(h()),m()]};return{fromLink:!0,sources:[m()]};case"no-cache":if(g)return{fromLink:!0,sources:[p(e.getDiff()),m(),]};return{fromLink:!0,sources:[m()]};case"standby":return{fromLink:!1,sources:[]}}},e.prototype.getQuery=function(e){return e&&!this.queries.has(e)&&this.queries.set(e,new r9(this,e)),this.queries.get(e)},e.prototype.prepareContext=function(e){void 0===e&&(e={});var t=this.localState.prepareContext(e);return(0,en.pi)((0,en.pi)({},t),{clientAwareness:this.clientAwareness})},e}(),ir=__webpack_require__(14012),ii=!1,ia=function(){function e(e){var t=this;this.resetStoreCallbacks=[],this.clearStoreCallbacks=[];var n=e.uri,r=e.credentials,i=e.headers,a=e.cache,o=e.ssrMode,s=void 0!==o&&o,u=e.ssrForceFetchDelay,c=void 0===u?0:u,l=e.connectToDevTools,f=void 0===l?"object"==typeof window&&!window.__APOLLO_CLIENT__&&__DEV__:l,d=e.queryDeduplication,h=void 0===d||d,p=e.defaultOptions,b=e.assumeImmutableResults,m=void 0!==b&&b,g=e.resolvers,v=e.typeDefs,y=e.fragmentMatcher,w=e.name,_=e.version,E=e.link;if(E||(E=n?new nh({uri:n,credentials:r,headers:i}):ta.empty()),!a)throw __DEV__?new Q.ej("To initialize Apollo Client, you must specify a 'cache' property in the options object. \nFor more information, please visit: https://go.apollo.dev/c/docs"):new Q.ej(9);if(this.link=E,this.cache=a,this.disableNetworkFetches=s||c>0,this.queryDeduplication=h,this.defaultOptions=p||Object.create(null),this.typeDefs=v,c&&setTimeout(function(){return t.disableNetworkFetches=!1},c),this.watchQuery=this.watchQuery.bind(this),this.query=this.query.bind(this),this.mutate=this.mutate.bind(this),this.resetStore=this.resetStore.bind(this),this.reFetchObservableQueries=this.reFetchObservableQueries.bind(this),f&&"object"==typeof window&&(window.__APOLLO_CLIENT__=this),!ii&&f&&__DEV__&&(ii=!0,"undefined"!=typeof window&&window.document&&window.top===window.self&&!window.__APOLLO_DEVTOOLS_GLOBAL_HOOK__)){var S=window.navigator,k=S&&S.userAgent,x=void 0;"string"==typeof k&&(k.indexOf("Chrome/")>-1?x="https://chrome.google.com/webstore/detail/apollo-client-developer-t/jdkknkkbebbapilgoeccciglkfbmbnfm":k.indexOf("Firefox/")>-1&&(x="https://addons.mozilla.org/en-US/firefox/addon/apollo-developer-tools/")),x&&__DEV__&&Q.kG.log("Download the Apollo DevTools for a better development experience: "+x)}this.version=nb,this.localState=new r4({cache:a,client:this,resolvers:g,fragmentMatcher:y}),this.queryManager=new it({cache:this.cache,link:this.link,defaultOptions:this.defaultOptions,queryDeduplication:h,ssrMode:s,clientAwareness:{name:w,version:_},localState:this.localState,assumeImmutableResults:m,onBroadcast:f?function(){t.devToolsHookCb&&t.devToolsHookCb({action:{},state:{queries:t.queryManager.getQueryStore(),mutations:t.queryManager.mutationStore||{}},dataWithOptimisticResults:t.cache.extract(!0)})}:void 0})}return e.prototype.stop=function(){this.queryManager.stop()},e.prototype.watchQuery=function(e){return this.defaultOptions.watchQuery&&(e=(0,ir.J)(this.defaultOptions.watchQuery,e)),this.disableNetworkFetches&&("network-only"===e.fetchPolicy||"cache-and-network"===e.fetchPolicy)&&(e=(0,en.pi)((0,en.pi)({},e),{fetchPolicy:"cache-first"})),this.queryManager.watchQuery(e)},e.prototype.query=function(e){return this.defaultOptions.query&&(e=(0,ir.J)(this.defaultOptions.query,e)),__DEV__?(0,Q.kG)("cache-and-network"!==e.fetchPolicy,"The cache-and-network fetchPolicy does not work with client.query, because client.query can only return a single result. Please use client.watchQuery to receive multiple results from the cache and the network, or consider using a different fetchPolicy, such as cache-first or network-only."):(0,Q.kG)("cache-and-network"!==e.fetchPolicy,10),this.disableNetworkFetches&&"network-only"===e.fetchPolicy&&(e=(0,en.pi)((0,en.pi)({},e),{fetchPolicy:"cache-first"})),this.queryManager.query(e)},e.prototype.mutate=function(e){return this.defaultOptions.mutate&&(e=(0,ir.J)(this.defaultOptions.mutate,e)),this.queryManager.mutate(e)},e.prototype.subscribe=function(e){return this.queryManager.startGraphQLSubscription(e)},e.prototype.readQuery=function(e,t){return void 0===t&&(t=!1),this.cache.readQuery(e,t)},e.prototype.readFragment=function(e,t){return void 0===t&&(t=!1),this.cache.readFragment(e,t)},e.prototype.writeQuery=function(e){var t=this.cache.writeQuery(e);return!1!==e.broadcast&&this.queryManager.broadcastQueries(),t},e.prototype.writeFragment=function(e){var t=this.cache.writeFragment(e);return!1!==e.broadcast&&this.queryManager.broadcastQueries(),t},e.prototype.__actionHookForDevTools=function(e){this.devToolsHookCb=e},e.prototype.__requestRaw=function(e){return np(this.link,e)},e.prototype.resetStore=function(){var e=this;return Promise.resolve().then(function(){return e.queryManager.clearStore({discardWatches:!1})}).then(function(){return Promise.all(e.resetStoreCallbacks.map(function(e){return e()}))}).then(function(){return e.reFetchObservableQueries()})},e.prototype.clearStore=function(){var e=this;return Promise.resolve().then(function(){return e.queryManager.clearStore({discardWatches:!0})}).then(function(){return Promise.all(e.clearStoreCallbacks.map(function(e){return e()}))})},e.prototype.onResetStore=function(e){var t=this;return this.resetStoreCallbacks.push(e),function(){t.resetStoreCallbacks=t.resetStoreCallbacks.filter(function(t){return t!==e})}},e.prototype.onClearStore=function(e){var t=this;return this.clearStoreCallbacks.push(e),function(){t.clearStoreCallbacks=t.clearStoreCallbacks.filter(function(t){return t!==e})}},e.prototype.reFetchObservableQueries=function(e){return this.queryManager.reFetchObservableQueries(e)},e.prototype.refetchQueries=function(e){var t=this.queryManager.refetchQueries(e),n=[],r=[];t.forEach(function(e,t){n.push(t),r.push(e)});var i=Promise.all(r);return i.queries=n,i.results=r,i.catch(function(e){__DEV__&&Q.kG.debug("In client.refetchQueries, Promise.all promise rejected with error ".concat(e))}),i},e.prototype.getObservableQueries=function(e){return void 0===e&&(e="active"),this.queryManager.getObservableQueries(e)},e.prototype.extract=function(e){return this.cache.extract(e)},e.prototype.restore=function(e){return this.cache.restore(e)},e.prototype.addResolvers=function(e){this.localState.addResolvers(e)},e.prototype.setResolvers=function(e){this.localState.setResolvers(e)},e.prototype.getResolvers=function(){return this.localState.getResolvers()},e.prototype.setLocalStateFragmentMatcher=function(e){this.localState.setFragmentMatcher(e)},e.prototype.setLink=function(e){this.link=this.queryManager.link=e},e}(),io=function(){function e(){this.getFragmentDoc=rZ(eA)}return e.prototype.batch=function(e){var t,n=this,r="string"==typeof e.optimistic?e.optimistic:!1===e.optimistic?null:void 0;return this.performTransaction(function(){return t=e.update(n)},r),t},e.prototype.recordOptimisticTransaction=function(e,t){this.performTransaction(e,t)},e.prototype.transformDocument=function(e){return e},e.prototype.transformForLink=function(e){return e},e.prototype.identify=function(e){},e.prototype.gc=function(){return[]},e.prototype.modify=function(e){return!1},e.prototype.readQuery=function(e,t){return void 0===t&&(t=!!e.optimistic),this.read((0,en.pi)((0,en.pi)({},e),{rootId:e.id||"ROOT_QUERY",optimistic:t}))},e.prototype.readFragment=function(e,t){return void 0===t&&(t=!!e.optimistic),this.read((0,en.pi)((0,en.pi)({},e),{query:this.getFragmentDoc(e.fragment,e.fragmentName),rootId:e.id,optimistic:t}))},e.prototype.writeQuery=function(e){var t=e.id,n=e.data,r=(0,en._T)(e,["id","data"]);return this.write(Object.assign(r,{dataId:t||"ROOT_QUERY",result:n}))},e.prototype.writeFragment=function(e){var t=e.id,n=e.data,r=e.fragment,i=e.fragmentName,a=(0,en._T)(e,["id","data","fragment","fragmentName"]);return this.write(Object.assign(a,{query:this.getFragmentDoc(r,i),dataId:t,result:n}))},e.prototype.updateQuery=function(e,t){return this.batch({update:function(n){var r=n.readQuery(e),i=t(r);return null==i?r:(n.writeQuery((0,en.pi)((0,en.pi)({},e),{data:i})),i)}})},e.prototype.updateFragment=function(e,t){return this.batch({update:function(n){var r=n.readFragment(e),i=t(r);return null==i?r:(n.writeFragment((0,en.pi)((0,en.pi)({},e),{data:i})),i)}})},e}(),is=function(e){function t(n,r,i,a){var o,s=e.call(this,n)||this;if(s.message=n,s.path=r,s.query=i,s.variables=a,Array.isArray(s.path)){s.missing=s.message;for(var u=s.path.length-1;u>=0;--u)s.missing=((o={})[s.path[u]]=s.missing,o)}else s.missing=s.path;return s.__proto__=t.prototype,s}return(0,en.ZT)(t,e),t}(Error),iu=__webpack_require__(10542),ic=Object.prototype.hasOwnProperty;function il(e){return null==e}function id(e,t){var n=e.__typename,r=e.id,i=e._id;if("string"==typeof n&&(t&&(t.keyObject=il(r)?il(i)?void 0:{_id:i}:{id:r}),il(r)&&!il(i)&&(r=i),!il(r)))return"".concat(n,":").concat("number"==typeof r||"string"==typeof r?r:JSON.stringify(r))}var ih={dataIdFromObject:id,addTypename:!0,resultCaching:!0,canonizeResults:!1};function ip(e){return(0,n1.o)(ih,e)}function ib(e){var t=e.canonizeResults;return void 0===t?ih.canonizeResults:t}function im(e,t){return eD(t)?e.get(t.__ref,"__typename"):t&&t.__typename}var ig=/^[_a-z][_0-9a-z]*/i;function iv(e){var t=e.match(ig);return t?t[0]:e}function iy(e,t,n){return!!(0,eO.s)(t)&&((0,tP.k)(t)?t.every(function(t){return iy(e,t,n)}):e.selections.every(function(e){if(eQ(e)&&td(e,n)){var r=eX(e);return ic.call(t,r)&&(!e.selectionSet||iy(e.selectionSet,t[r],n))}return!0}))}function iw(e){return(0,eO.s)(e)&&!eD(e)&&!(0,tP.k)(e)}function i_(){return new tB}function iE(e,t){var n=eL(e4(e));return{fragmentMap:n,lookupFragment:function(e){var r=n[e];return!r&&t&&(r=t.lookup(e)),r||null}}}var iS=Object.create(null),ik=function(){return iS},ix=Object.create(null),iT=function(){function e(e,t){var n=this;this.policies=e,this.group=t,this.data=Object.create(null),this.rootIds=Object.create(null),this.refs=Object.create(null),this.getFieldValue=function(e,t){return(0,iu.J)(eD(e)?n.get(e.__ref,t):e&&e[t])},this.canRead=function(e){return eD(e)?n.has(e.__ref):"object"==typeof e},this.toReference=function(e,t){if("string"==typeof e)return eI(e);if(eD(e))return e;var r=n.policies.identify(e)[0];if(r){var i=eI(r);return t&&n.merge(r,e),i}}}return e.prototype.toObject=function(){return(0,en.pi)({},this.data)},e.prototype.has=function(e){return void 0!==this.lookup(e,!0)},e.prototype.get=function(e,t){if(this.group.depend(e,t),ic.call(this.data,e)){var n=this.data[e];if(n&&ic.call(n,t))return n[t]}return"__typename"===t&&ic.call(this.policies.rootTypenamesById,e)?this.policies.rootTypenamesById[e]:this instanceof iL?this.parent.get(e,t):void 0},e.prototype.lookup=function(e,t){return(t&&this.group.depend(e,"__exists"),ic.call(this.data,e))?this.data[e]:this instanceof iL?this.parent.lookup(e,t):this.policies.rootTypenamesById[e]?Object.create(null):void 0},e.prototype.merge=function(e,t){var n,r=this;eD(e)&&(e=e.__ref),eD(t)&&(t=t.__ref);var i="string"==typeof e?this.lookup(n=e):e,a="string"==typeof t?this.lookup(n=t):t;if(a){__DEV__?(0,Q.kG)("string"==typeof n,"store.merge expects a string ID"):(0,Q.kG)("string"==typeof n,1);var o=new tB(iI).merge(i,a);if(this.data[n]=o,o!==i&&(delete this.refs[n],this.group.caching)){var s=Object.create(null);i||(s.__exists=1),Object.keys(a).forEach(function(e){if(!i||i[e]!==o[e]){s[e]=1;var t=iv(e);t===e||r.policies.hasKeyArgs(o.__typename,t)||(s[t]=1),void 0!==o[e]||r instanceof iL||delete o[e]}}),s.__typename&&!(i&&i.__typename)&&this.policies.rootTypenamesById[n]===o.__typename&&delete s.__typename,Object.keys(s).forEach(function(e){return r.group.dirty(n,e)})}}},e.prototype.modify=function(e,t){var n=this,r=this.lookup(e);if(r){var i=Object.create(null),a=!1,o=!0,s={DELETE:iS,INVALIDATE:ix,isReference:eD,toReference:this.toReference,canRead:this.canRead,readField:function(t,r){return n.policies.readField("string"==typeof t?{fieldName:t,from:r||eI(e)}:t,{store:n})}};if(Object.keys(r).forEach(function(u){var c=iv(u),l=r[u];if(void 0!==l){var f="function"==typeof t?t:t[u]||t[c];if(f){var d=f===ik?iS:f((0,iu.J)(l),(0,en.pi)((0,en.pi)({},s),{fieldName:c,storeFieldName:u,storage:n.getStorage(e,u)}));d===ix?n.group.dirty(e,u):(d===iS&&(d=void 0),d!==l&&(i[u]=d,a=!0,l=d))}void 0!==l&&(o=!1)}}),a)return this.merge(e,i),o&&(this instanceof iL?this.data[e]=void 0:delete this.data[e],this.group.dirty(e,"__exists")),!0}return!1},e.prototype.delete=function(e,t,n){var r,i=this.lookup(e);if(i){var a=this.getFieldValue(i,"__typename"),o=t&&n?this.policies.getStoreFieldName({typename:a,fieldName:t,args:n}):t;return this.modify(e,o?((r={})[o]=ik,r):ik)}return!1},e.prototype.evict=function(e,t){var n=!1;return e.id&&(ic.call(this.data,e.id)&&(n=this.delete(e.id,e.fieldName,e.args)),this instanceof iL&&this!==t&&(n=this.parent.evict(e,t)||n),(e.fieldName||n)&&this.group.dirty(e.id,e.fieldName||"__exists")),n},e.prototype.clear=function(){this.replace(null)},e.prototype.extract=function(){var e=this,t=this.toObject(),n=[];return this.getRootIdSet().forEach(function(t){ic.call(e.policies.rootTypenamesById,t)||n.push(t)}),n.length&&(t.__META={extraRootIds:n.sort()}),t},e.prototype.replace=function(e){var t=this;if(Object.keys(this.data).forEach(function(n){e&&ic.call(e,n)||t.delete(n)}),e){var n=e.__META,r=(0,en._T)(e,["__META"]);Object.keys(r).forEach(function(e){t.merge(e,r[e])}),n&&n.extraRootIds.forEach(this.retain,this)}},e.prototype.retain=function(e){return this.rootIds[e]=(this.rootIds[e]||0)+1},e.prototype.release=function(e){if(this.rootIds[e]>0){var t=--this.rootIds[e];return t||delete this.rootIds[e],t}return 0},e.prototype.getRootIdSet=function(e){return void 0===e&&(e=new Set),Object.keys(this.rootIds).forEach(e.add,e),this instanceof iL?this.parent.getRootIdSet(e):Object.keys(this.policies.rootTypenamesById).forEach(e.add,e),e},e.prototype.gc=function(){var e=this,t=this.getRootIdSet(),n=this.toObject();t.forEach(function(r){ic.call(n,r)&&(Object.keys(e.findChildRefIds(r)).forEach(t.add,t),delete n[r])});var r=Object.keys(n);if(r.length){for(var i=this;i instanceof iL;)i=i.parent;r.forEach(function(e){return i.delete(e)})}return r},e.prototype.findChildRefIds=function(e){if(!ic.call(this.refs,e)){var t=this.refs[e]=Object.create(null),n=this.data[e];if(!n)return t;var r=new Set([n]);r.forEach(function(e){eD(e)&&(t[e.__ref]=!0),(0,eO.s)(e)&&Object.keys(e).forEach(function(t){var n=e[t];(0,eO.s)(n)&&r.add(n)})})}return this.refs[e]},e.prototype.makeCacheKey=function(){return this.group.keyMaker.lookupArray(arguments)},e}(),iM=function(){function e(e,t){void 0===t&&(t=null),this.caching=e,this.parent=t,this.d=null,this.resetCaching()}return e.prototype.resetCaching=function(){this.d=this.caching?rW():null,this.keyMaker=new n_(t_.mr)},e.prototype.depend=function(e,t){if(this.d){this.d(iO(e,t));var n=iv(t);n!==t&&this.d(iO(e,n)),this.parent&&this.parent.depend(e,t)}},e.prototype.dirty=function(e,t){this.d&&this.d.dirty(iO(e,t),"__exists"===t?"forget":"setDirty")},e}();function iO(e,t){return t+"#"+e}function iA(e,t){iD(e)&&e.group.depend(t,"__exists")}!function(e){var t=function(e){function t(t){var n=t.policies,r=t.resultCaching,i=void 0===r||r,a=t.seed,o=e.call(this,n,new iM(i))||this;return o.stump=new iC(o),o.storageTrie=new n_(t_.mr),a&&o.replace(a),o}return(0,en.ZT)(t,e),t.prototype.addLayer=function(e,t){return this.stump.addLayer(e,t)},t.prototype.removeLayer=function(){return this},t.prototype.getStorage=function(){return this.storageTrie.lookupArray(arguments)},t}(e);e.Root=t}(iT||(iT={}));var iL=function(e){function t(t,n,r,i){var a=e.call(this,n.policies,i)||this;return a.id=t,a.parent=n,a.replay=r,a.group=i,r(a),a}return(0,en.ZT)(t,e),t.prototype.addLayer=function(e,n){return new t(e,this,n,this.group)},t.prototype.removeLayer=function(e){var t=this,n=this.parent.removeLayer(e);return e===this.id?(this.group.caching&&Object.keys(this.data).forEach(function(e){var r=t.data[e],i=n.lookup(e);i?r?r!==i&&Object.keys(r).forEach(function(n){(0,nm.D)(r[n],i[n])||t.group.dirty(e,n)}):(t.group.dirty(e,"__exists"),Object.keys(i).forEach(function(n){t.group.dirty(e,n)})):t.delete(e)}),n):n===this.parent?this:n.addLayer(this.id,this.replay)},t.prototype.toObject=function(){return(0,en.pi)((0,en.pi)({},this.parent.toObject()),this.data)},t.prototype.findChildRefIds=function(t){var n=this.parent.findChildRefIds(t);return ic.call(this.data,t)?(0,en.pi)((0,en.pi)({},n),e.prototype.findChildRefIds.call(this,t)):n},t.prototype.getStorage=function(){for(var e=this.parent;e.parent;)e=e.parent;return e.getStorage.apply(e,arguments)},t}(iT),iC=function(e){function t(t){return e.call(this,"EntityStore.Stump",t,function(){},new iM(t.group.caching,t.group))||this}return(0,en.ZT)(t,e),t.prototype.removeLayer=function(){return this},t.prototype.merge=function(){return this.parent.merge.apply(this.parent,arguments)},t}(iL);function iI(e,t,n){var r=e[n],i=t[n];return(0,nm.D)(r,i)?r:i}function iD(e){return!!(e instanceof iT&&e.group.caching)}function iN(e){return[e.selectionSet,e.objectOrReference,e.context,e.context.canonizeResults,]}var iP=function(){function e(e){var t=this;this.knownResults=new(t_.mr?WeakMap:Map),this.config=(0,n1.o)(e,{addTypename:!1!==e.addTypename,canonizeResults:ib(e)}),this.canon=e.canon||new nk,this.executeSelectionSet=rZ(function(e){var n,r=e.context.canonizeResults,i=iN(e);i[3]=!r;var a=(n=t.executeSelectionSet).peek.apply(n,i);return a?r?(0,en.pi)((0,en.pi)({},a),{result:t.canon.admit(a.result)}):a:(iA(e.context.store,e.enclosingRef.__ref),t.execSelectionSetImpl(e))},{max:this.config.resultCacheMaxSize,keyArgs:iN,makeCacheKey:function(e,t,n,r){if(iD(n.store))return n.store.makeCacheKey(e,eD(t)?t.__ref:t,n.varString,r)}}),this.executeSubSelectedArray=rZ(function(e){return iA(e.context.store,e.enclosingRef.__ref),t.execSubSelectedArrayImpl(e)},{max:this.config.resultCacheMaxSize,makeCacheKey:function(e){var t=e.field,n=e.array,r=e.context;if(iD(r.store))return r.store.makeCacheKey(t,n,r.varString)}})}return e.prototype.resetCanon=function(){this.canon=new nk},e.prototype.diffQueryAgainstStore=function(e){var t,n=e.store,r=e.query,i=e.rootId,a=void 0===i?"ROOT_QUERY":i,o=e.variables,s=e.returnPartialData,u=void 0===s||s,c=e.canonizeResults,l=void 0===c?this.config.canonizeResults:c,f=this.config.cache.policies;o=(0,en.pi)((0,en.pi)({},e9(e6(r))),o);var d=eI(a),h=this.executeSelectionSet({selectionSet:e8(r).selectionSet,objectOrReference:d,enclosingRef:d,context:(0,en.pi)({store:n,query:r,policies:f,variables:o,varString:nx(o),canonizeResults:l},iE(r,this.config.fragments))});if(h.missing&&(t=[new is(iR(h.missing),h.missing,r,o)],!u))throw t[0];return{result:h.result,complete:!t,missing:t}},e.prototype.isFresh=function(e,t,n,r){if(iD(r.store)&&this.knownResults.get(e)===n){var i=this.executeSelectionSet.peek(n,t,r,this.canon.isKnown(e));if(i&&e===i.result)return!0}return!1},e.prototype.execSelectionSetImpl=function(e){var t,n=this,r=e.selectionSet,i=e.objectOrReference,a=e.enclosingRef,o=e.context;if(eD(i)&&!o.policies.rootTypenamesById[i.__ref]&&!o.store.has(i.__ref))return{result:this.canon.empty,missing:"Dangling reference to missing ".concat(i.__ref," object")};var s=o.variables,u=o.policies,c=o.store.getFieldValue(i,"__typename"),l=[],f=new tB;function d(e,n){var r;return e.missing&&(t=f.merge(t,((r={})[n]=e.missing,r))),e.result}this.config.addTypename&&"string"==typeof c&&!u.rootIdsByTypename[c]&&l.push({__typename:c});var h=new Set(r.selections);h.forEach(function(e){var r,p;if(td(e,s)){if(eQ(e)){var b=u.readField({fieldName:e.name.value,field:e,variables:o.variables,from:i},o),m=eX(e);void 0===b?nj.added(e)||(t=f.merge(t,((r={})[m]="Can't find field '".concat(e.name.value,"' on ").concat(eD(i)?i.__ref+" object":"object "+JSON.stringify(i,null,2)),r))):(0,tP.k)(b)?b=d(n.executeSubSelectedArray({field:e,array:b,enclosingRef:a,context:o}),m):e.selectionSet?null!=b&&(b=d(n.executeSelectionSet({selectionSet:e.selectionSet,objectOrReference:b,enclosingRef:eD(b)?b:a,context:o}),m)):o.canonizeResults&&(b=n.canon.pass(b)),void 0!==b&&l.push(((p={})[m]=b,p))}else{var g=eC(e,o.lookupFragment);if(!g&&e.kind===nL.h.FRAGMENT_SPREAD)throw __DEV__?new Q.ej("No fragment named ".concat(e.name.value)):new Q.ej(5);g&&u.fragmentMatches(g,c)&&g.selectionSet.selections.forEach(h.add,h)}}});var p={result:tF(l),missing:t},b=o.canonizeResults?this.canon.admit(p):(0,iu.J)(p);return b.result&&this.knownResults.set(b.result,r),b},e.prototype.execSubSelectedArrayImpl=function(e){var t,n=this,r=e.field,i=e.array,a=e.enclosingRef,o=e.context,s=new tB;function u(e,n){var r;return e.missing&&(t=s.merge(t,((r={})[n]=e.missing,r))),e.result}return r.selectionSet&&(i=i.filter(o.store.canRead)),i=i.map(function(e,t){return null===e?null:(0,tP.k)(e)?u(n.executeSubSelectedArray({field:r,array:e,enclosingRef:a,context:o}),t):r.selectionSet?u(n.executeSelectionSet({selectionSet:r.selectionSet,objectOrReference:e,enclosingRef:eD(e)?e:a,context:o}),t):(__DEV__&&ij(o.store,r,e),e)}),{result:o.canonizeResults?this.canon.admit(i):i,missing:t}},e}();function iR(e){try{JSON.stringify(e,function(e,t){if("string"==typeof t)throw t;return t})}catch(t){return t}}function ij(e,t,n){if(!t.selectionSet){var r=new Set([n]);r.forEach(function(n){(0,eO.s)(n)&&(__DEV__?(0,Q.kG)(!eD(n),"Missing selection set for object of type ".concat(im(e,n)," returned for query field ").concat(t.name.value)):(0,Q.kG)(!eD(n),6),Object.values(n).forEach(r.add,r))})}}function iF(e){var t=nG("stringifyForDisplay");return JSON.stringify(e,function(e,n){return void 0===n?t:n}).split(JSON.stringify(t)).join("")}var iY=Object.create(null);function iB(e){var t=JSON.stringify(e);return iY[t]||(iY[t]=Object.create(null))}function iU(e){var t=iB(e);return t.keyFieldsFn||(t.keyFieldsFn=function(t,n){var r=function(e,t){return n.readField(t,e)},i=n.keyObject=i$(e,function(e){var i=iW(n.storeObject,e,r);return void 0===i&&t!==n.storeObject&&ic.call(t,e[0])&&(i=iW(t,e,iG)),__DEV__?(0,Q.kG)(void 0!==i,"Missing field '".concat(e.join("."),"' while extracting keyFields from ").concat(JSON.stringify(t))):(0,Q.kG)(void 0!==i,2),i});return"".concat(n.typename,":").concat(JSON.stringify(i))})}function iH(e){var t=iB(e);return t.keyArgsFn||(t.keyArgsFn=function(t,n){var r=n.field,i=n.variables,a=n.fieldName,o=JSON.stringify(i$(e,function(e){var n=e[0],a=n.charAt(0);if("@"===a){if(r&&(0,tP.O)(r.directives)){var o=n.slice(1),s=r.directives.find(function(e){return e.name.value===o}),u=s&&eZ(s,i);return u&&iW(u,e.slice(1))}return}if("$"===a){var c=n.slice(1);if(i&&ic.call(i,c)){var l=e.slice(0);return l[0]=c,iW(i,l)}return}if(t)return iW(t,e)}));return(t||"{}"!==o)&&(a+=":"+o),a})}function i$(e,t){var n=new tB;return iz(e).reduce(function(e,r){var i,a=t(r);if(void 0!==a){for(var o=r.length-1;o>=0;--o)a=((i={})[r[o]]=a,i);e=n.merge(e,a)}return e},Object.create(null))}function iz(e){var t=iB(e);if(!t.paths){var n=t.paths=[],r=[];e.forEach(function(t,i){(0,tP.k)(t)?(iz(t).forEach(function(e){return n.push(r.concat(e))}),r.length=0):(r.push(t),(0,tP.k)(e[i+1])||(n.push(r.slice(0)),r.length=0))})}return t.paths}function iG(e,t){return e[t]}function iW(e,t,n){return n=n||iG,iK(t.reduce(function e(t,r){return(0,tP.k)(t)?t.map(function(t){return e(t,r)}):t&&n(t,r)},e))}function iK(e){return(0,eO.s)(e)?(0,tP.k)(e)?e.map(iK):i$(Object.keys(e).sort(),function(t){return iW(e,t)}):e}function iV(e){return void 0!==e.args?e.args:e.field?eZ(e.field,e.variables):null}eK.setStringify(nx);var iq=function(){},iZ=function(e,t){return t.fieldName},iX=function(e,t,n){return(0,n.mergeObjects)(e,t)},iJ=function(e,t){return t},iQ=function(){function e(e){this.config=e,this.typePolicies=Object.create(null),this.toBeAdded=Object.create(null),this.supertypeMap=new Map,this.fuzzySubtypes=new Map,this.rootIdsByTypename=Object.create(null),this.rootTypenamesById=Object.create(null),this.usingPossibleTypes=!1,this.config=(0,en.pi)({dataIdFromObject:id},e),this.cache=this.config.cache,this.setRootTypename("Query"),this.setRootTypename("Mutation"),this.setRootTypename("Subscription"),e.possibleTypes&&this.addPossibleTypes(e.possibleTypes),e.typePolicies&&this.addTypePolicies(e.typePolicies)}return e.prototype.identify=function(e,t){var n,r,i=this,a=t&&(t.typename||(null===(n=t.storeObject)||void 0===n?void 0:n.__typename))||e.__typename;if(a===this.rootTypenamesById.ROOT_QUERY)return["ROOT_QUERY"];for(var o=t&&t.storeObject||e,s=(0,en.pi)((0,en.pi)({},t),{typename:a,storeObject:o,readField:t&&t.readField||function(){var e=i0(arguments,o);return i.readField(e,{store:i.cache.data,variables:e.variables})}}),u=a&&this.getTypePolicy(a),c=u&&u.keyFn||this.config.dataIdFromObject;c;){var l=c((0,en.pi)((0,en.pi)({},e),o),s);if((0,tP.k)(l))c=iU(l);else{r=l;break}}return r=r?String(r):void 0,s.keyObject?[r,s.keyObject]:[r]},e.prototype.addTypePolicies=function(e){var t=this;Object.keys(e).forEach(function(n){var r=e[n],i=r.queryType,a=r.mutationType,o=r.subscriptionType,s=(0,en._T)(r,["queryType","mutationType","subscriptionType"]);i&&t.setRootTypename("Query",n),a&&t.setRootTypename("Mutation",n),o&&t.setRootTypename("Subscription",n),ic.call(t.toBeAdded,n)?t.toBeAdded[n].push(s):t.toBeAdded[n]=[s]})},e.prototype.updateTypePolicy=function(e,t){var n=this,r=this.getTypePolicy(e),i=t.keyFields,a=t.fields;function o(e,t){e.merge="function"==typeof t?t:!0===t?iX:!1===t?iJ:e.merge}o(r,t.merge),r.keyFn=!1===i?iq:(0,tP.k)(i)?iU(i):"function"==typeof i?i:r.keyFn,a&&Object.keys(a).forEach(function(t){var r=n.getFieldPolicy(e,t,!0),i=a[t];if("function"==typeof i)r.read=i;else{var s=i.keyArgs,u=i.read,c=i.merge;r.keyFn=!1===s?iZ:(0,tP.k)(s)?iH(s):"function"==typeof s?s:r.keyFn,"function"==typeof u&&(r.read=u),o(r,c)}r.read&&r.merge&&(r.keyFn=r.keyFn||iZ)})},e.prototype.setRootTypename=function(e,t){void 0===t&&(t=e);var n="ROOT_"+e.toUpperCase(),r=this.rootTypenamesById[n];t!==r&&(__DEV__?(0,Q.kG)(!r||r===e,"Cannot change root ".concat(e," __typename more than once")):(0,Q.kG)(!r||r===e,3),r&&delete this.rootIdsByTypename[r],this.rootIdsByTypename[t]=n,this.rootTypenamesById[n]=t)},e.prototype.addPossibleTypes=function(e){var t=this;this.usingPossibleTypes=!0,Object.keys(e).forEach(function(n){t.getSupertypeSet(n,!0),e[n].forEach(function(e){t.getSupertypeSet(e,!0).add(n);var r=e.match(ig);r&&r[0]===e||t.fuzzySubtypes.set(e,RegExp(e))})})},e.prototype.getTypePolicy=function(e){var t=this;if(!ic.call(this.typePolicies,e)){var n=this.typePolicies[e]=Object.create(null);n.fields=Object.create(null);var r=this.supertypeMap.get(e);r&&r.size&&r.forEach(function(e){var r=t.getTypePolicy(e),i=r.fields;Object.assign(n,(0,en._T)(r,["fields"])),Object.assign(n.fields,i)})}var i=this.toBeAdded[e];return i&&i.length&&i.splice(0).forEach(function(n){t.updateTypePolicy(e,n)}),this.typePolicies[e]},e.prototype.getFieldPolicy=function(e,t,n){if(e){var r=this.getTypePolicy(e).fields;return r[t]||n&&(r[t]=Object.create(null))}},e.prototype.getSupertypeSet=function(e,t){var n=this.supertypeMap.get(e);return!n&&t&&this.supertypeMap.set(e,n=new Set),n},e.prototype.fragmentMatches=function(e,t,n,r){var i=this;if(!e.typeCondition)return!0;if(!t)return!1;var a=e.typeCondition.name.value;if(t===a)return!0;if(this.usingPossibleTypes&&this.supertypeMap.has(a))for(var o=this.getSupertypeSet(t,!0),s=[o],u=function(e){var t=i.getSupertypeSet(e,!1);t&&t.size&&0>s.indexOf(t)&&s.push(t)},c=!!(n&&this.fuzzySubtypes.size),l=!1,f=0;f1?a:t}:(r=(0,en.pi)({},i),ic.call(r,"from")||(r.from=t)),__DEV__&&void 0===r.from&&__DEV__&&Q.kG.warn("Undefined 'from' passed to readField with arguments ".concat(iF(Array.from(e)))),void 0===r.variables&&(r.variables=n),r}function i2(e){return function(t,n){if((0,tP.k)(t)||(0,tP.k)(n))throw __DEV__?new Q.ej("Cannot automatically merge arrays"):new Q.ej(4);if((0,eO.s)(t)&&(0,eO.s)(n)){var r=e.getFieldValue(t,"__typename"),i=e.getFieldValue(n,"__typename");if(r&&i&&r!==i)return n;if(eD(t)&&iw(n))return e.merge(t.__ref,n),t;if(iw(t)&&eD(n))return e.merge(t,n.__ref),n;if(iw(t)&&iw(n))return(0,en.pi)((0,en.pi)({},t),n)}return n}}function i3(e,t,n){var r="".concat(t).concat(n),i=e.flavors.get(r);return i||e.flavors.set(r,i=e.clientOnly===t&&e.deferred===n?e:(0,en.pi)((0,en.pi)({},e),{clientOnly:t,deferred:n})),i}var i4=function(){function e(e,t,n){this.cache=e,this.reader=t,this.fragments=n}return e.prototype.writeToStore=function(e,t){var n=this,r=t.query,i=t.result,a=t.dataId,o=t.variables,s=t.overwrite,u=e2(r),c=i_();o=(0,en.pi)((0,en.pi)({},e9(u)),o);var l=(0,en.pi)((0,en.pi)({store:e,written:Object.create(null),merge:function(e,t){return c.merge(e,t)},variables:o,varString:nx(o)},iE(r,this.fragments)),{overwrite:!!s,incomingById:new Map,clientOnly:!1,deferred:!1,flavors:new Map}),f=this.processSelectionSet({result:i||Object.create(null),dataId:a,selectionSet:u.selectionSet,mergeTree:{map:new Map},context:l});if(!eD(f))throw __DEV__?new Q.ej("Could not identify object ".concat(JSON.stringify(i))):new Q.ej(7);return l.incomingById.forEach(function(t,r){var i=t.storeObject,a=t.mergeTree,o=t.fieldNodeSet,s=eI(r);if(a&&a.map.size){var u=n.applyMerges(a,s,i,l);if(eD(u))return;i=u}if(__DEV__&&!l.overwrite){var c=Object.create(null);o.forEach(function(e){e.selectionSet&&(c[e.name.value]=!0)});var f=function(e){return!0===c[iv(e)]},d=function(e){var t=a&&a.map.get(e);return Boolean(t&&t.info&&t.info.merge)};Object.keys(i).forEach(function(e){f(e)&&!d(e)&&at(s,i,e,l.store)})}e.merge(r,i)}),e.retain(f.__ref),f},e.prototype.processSelectionSet=function(e){var t=this,n=e.dataId,r=e.result,i=e.selectionSet,a=e.context,o=e.mergeTree,s=this.cache.policies,u=Object.create(null),c=n&&s.rootTypenamesById[n]||eJ(r,i,a.fragmentMap)||n&&a.store.get(n,"__typename");"string"==typeof c&&(u.__typename=c);var l=function(){var e=i0(arguments,u,a.variables);if(eD(e.from)){var t=a.incomingById.get(e.from.__ref);if(t){var n=s.readField((0,en.pi)((0,en.pi)({},e),{from:t.storeObject}),a);if(void 0!==n)return n}}return s.readField(e,a)},f=new Set;this.flattenFields(i,r,a,c).forEach(function(e,n){var i,a=r[eX(n)];if(f.add(n),void 0!==a){var d=s.getStoreFieldName({typename:c,fieldName:n.name.value,field:n,variables:e.variables}),h=i5(o,d),p=t.processFieldValue(a,n,n.selectionSet?i3(e,!1,!1):e,h),b=void 0;n.selectionSet&&(eD(p)||iw(p))&&(b=l("__typename",p));var m=s.getMergeFunction(c,n.name.value,b);m?h.info={field:n,typename:c,merge:m}:i7(o,d),u=e.merge(u,((i={})[d]=p,i))}else __DEV__&&!e.clientOnly&&!e.deferred&&!nj.added(n)&&!s.getReadFunction(c,n.name.value)&&__DEV__&&Q.kG.error("Missing field '".concat(eX(n),"' while writing result ").concat(JSON.stringify(r,null,2)).substring(0,1e3))});try{var d=s.identify(r,{typename:c,selectionSet:i,fragmentMap:a.fragmentMap,storeObject:u,readField:l}),h=d[0],p=d[1];n=n||h,p&&(u=a.merge(u,p))}catch(b){if(!n)throw b}if("string"==typeof n){var m=eI(n),g=a.written[n]||(a.written[n]=[]);if(g.indexOf(i)>=0||(g.push(i),this.reader&&this.reader.isFresh(r,m,i,a)))return m;var v=a.incomingById.get(n);return v?(v.storeObject=a.merge(v.storeObject,u),v.mergeTree=i8(v.mergeTree,o),f.forEach(function(e){return v.fieldNodeSet.add(e)})):a.incomingById.set(n,{storeObject:u,mergeTree:i9(o)?void 0:o,fieldNodeSet:f}),m}return u},e.prototype.processFieldValue=function(e,t,n,r){var i=this;return t.selectionSet&&null!==e?(0,tP.k)(e)?e.map(function(e,a){var o=i.processFieldValue(e,t,n,i5(r,a));return i7(r,a),o}):this.processSelectionSet({result:e,selectionSet:t.selectionSet,context:n,mergeTree:r}):__DEV__?nJ(e):e},e.prototype.flattenFields=function(e,t,n,r){void 0===r&&(r=eJ(t,e,n.fragmentMap));var i=new Map,a=this.cache.policies,o=new n_(!1);return function e(s,u){var c=o.lookup(s,u.clientOnly,u.deferred);c.visited||(c.visited=!0,s.selections.forEach(function(o){if(td(o,n.variables)){var s=u.clientOnly,c=u.deferred;if(!(s&&c)&&(0,tP.O)(o.directives)&&o.directives.forEach(function(e){var t=e.name.value;if("client"===t&&(s=!0),"defer"===t){var r=eZ(e,n.variables);r&&!1===r.if||(c=!0)}}),eQ(o)){var l=i.get(o);l&&(s=s&&l.clientOnly,c=c&&l.deferred),i.set(o,i3(n,s,c))}else{var f=eC(o,n.lookupFragment);if(!f&&o.kind===nL.h.FRAGMENT_SPREAD)throw __DEV__?new Q.ej("No fragment named ".concat(o.name.value)):new Q.ej(8);f&&a.fragmentMatches(f,r,t,n.variables)&&e(f.selectionSet,i3(n,s,c))}}}))}(e,n),i},e.prototype.applyMerges=function(e,t,n,r,i){var a=this;if(e.map.size&&!eD(n)){var o,s,u=!(0,tP.k)(n)&&(eD(t)||iw(t))?t:void 0,c=n;u&&!i&&(i=[eD(u)?u.__ref:u]);var l=function(e,t){return(0,tP.k)(e)?"number"==typeof t?e[t]:void 0:r.store.getFieldValue(e,String(t))};e.map.forEach(function(e,t){var n=l(u,t),o=l(c,t);if(void 0!==o){i&&i.push(t);var f=a.applyMerges(e,n,o,r,i);f!==o&&(s=s||new Map).set(t,f),i&&(0,Q.kG)(i.pop()===t)}}),s&&(n=(0,tP.k)(c)?c.slice(0):(0,en.pi)({},c),s.forEach(function(e,t){n[t]=e}))}return e.info?this.cache.policies.runMergeFunction(t,n,e.info,r,i&&(o=r.store).getStorage.apply(o,i)):n},e}(),i6=[];function i5(e,t){var n=e.map;return n.has(t)||n.set(t,i6.pop()||{map:new Map}),n.get(t)}function i8(e,t){if(e===t||!t||i9(t))return e;if(!e||i9(e))return t;var n=e.info&&t.info?(0,en.pi)((0,en.pi)({},e.info),t.info):e.info||t.info,r=e.map.size&&t.map.size,i=r?new Map:e.map.size?e.map:t.map,a={info:n,map:i};if(r){var o=new Set(t.map.keys());e.map.forEach(function(e,n){a.map.set(n,i8(e,t.map.get(n))),o.delete(n)}),o.forEach(function(n){a.map.set(n,i8(t.map.get(n),e.map.get(n)))})}return a}function i9(e){return!e||!(e.info||e.map.size)}function i7(e,t){var n=e.map,r=n.get(t);r&&i9(r)&&(i6.push(r),n.delete(t))}var ae=new Set;function at(e,t,n,r){var i=function(e){var t=r.getFieldValue(e,n);return"object"==typeof t&&t},a=i(e);if(a){var o=i(t);if(!(!o||eD(a)||(0,nm.D)(a,o)||Object.keys(a).every(function(e){return void 0!==r.getFieldValue(o,e)}))){var s=r.getFieldValue(e,"__typename")||r.getFieldValue(t,"__typename"),u=iv(n),c="".concat(s,".").concat(u);if(!ae.has(c)){ae.add(c);var l=[];(0,tP.k)(a)||(0,tP.k)(o)||[a,o].forEach(function(e){var t=r.getFieldValue(e,"__typename");"string"!=typeof t||l.includes(t)||l.push(t)}),__DEV__&&Q.kG.warn("Cache data may be lost when replacing the ".concat(u," field of a ").concat(s," object.\n\nThis could cause additional (usually avoidable) network requests to fetch data that were otherwise cached.\n\nTo address this problem (which is not a bug in Apollo Client), ").concat(l.length?"either ensure all objects of type "+l.join(" and ")+" have an ID or a custom merge function, or ":"","define a custom merge function for the ").concat(c," field, so InMemoryCache can safely merge these objects:\n\n existing: ").concat(JSON.stringify(a).slice(0,1e3),"\n incoming: ").concat(JSON.stringify(o).slice(0,1e3),"\n\nFor more information about these options, please refer to the documentation:\n\n * Ensuring entity objects have IDs: https://go.apollo.dev/c/generating-unique-identifiers\n * Defining custom merge functions: https://go.apollo.dev/c/merging-non-normalized-objects\n"))}}}}var an=function(e){function t(t){void 0===t&&(t={});var n=e.call(this)||this;return n.watches=new Set,n.typenameDocumentCache=new Map,n.makeVar=r2,n.txCount=0,n.config=ip(t),n.addTypename=!!n.config.addTypename,n.policies=new iQ({cache:n,dataIdFromObject:n.config.dataIdFromObject,possibleTypes:n.config.possibleTypes,typePolicies:n.config.typePolicies}),n.init(),n}return(0,en.ZT)(t,e),t.prototype.init=function(){var e=this.data=new iT.Root({policies:this.policies,resultCaching:this.config.resultCaching});this.optimisticData=e.stump,this.resetResultCache()},t.prototype.resetResultCache=function(e){var t=this,n=this.storeReader,r=this.config.fragments;this.storeWriter=new i4(this,this.storeReader=new iP({cache:this,addTypename:this.addTypename,resultCacheMaxSize:this.config.resultCacheMaxSize,canonizeResults:ib(this.config),canon:e?void 0:n&&n.canon,fragments:r}),r),this.maybeBroadcastWatch=rZ(function(e,n){return t.broadcastWatch(e,n)},{max:this.config.resultCacheMaxSize,makeCacheKey:function(e){var n=e.optimistic?t.optimisticData:t.data;if(iD(n)){var r=e.optimistic,i=e.id,a=e.variables;return n.makeCacheKey(e.query,e.callback,nx({optimistic:r,id:i,variables:a}))}}}),new Set([this.data.group,this.optimisticData.group,]).forEach(function(e){return e.resetCaching()})},t.prototype.restore=function(e){return this.init(),e&&this.data.replace(e),this},t.prototype.extract=function(e){return void 0===e&&(e=!1),(e?this.optimisticData:this.data).extract()},t.prototype.read=function(e){var t=e.returnPartialData,n=void 0!==t&&t;try{return this.storeReader.diffQueryAgainstStore((0,en.pi)((0,en.pi)({},e),{store:e.optimistic?this.optimisticData:this.data,config:this.config,returnPartialData:n})).result||null}catch(r){if(r instanceof is)return null;throw r}},t.prototype.write=function(e){try{return++this.txCount,this.storeWriter.writeToStore(this.data,e)}finally{--this.txCount||!1===e.broadcast||this.broadcastWatches()}},t.prototype.modify=function(e){if(ic.call(e,"id")&&!e.id)return!1;var t=e.optimistic?this.optimisticData:this.data;try{return++this.txCount,t.modify(e.id||"ROOT_QUERY",e.fields)}finally{--this.txCount||!1===e.broadcast||this.broadcastWatches()}},t.prototype.diff=function(e){return this.storeReader.diffQueryAgainstStore((0,en.pi)((0,en.pi)({},e),{store:e.optimistic?this.optimisticData:this.data,rootId:e.id||"ROOT_QUERY",config:this.config}))},t.prototype.watch=function(e){var t=this;return this.watches.size||r0(this),this.watches.add(e),e.immediate&&this.maybeBroadcastWatch(e),function(){t.watches.delete(e)&&!t.watches.size&&r1(t),t.maybeBroadcastWatch.forget(e)}},t.prototype.gc=function(e){nx.reset();var t=this.optimisticData.gc();return e&&!this.txCount&&(e.resetResultCache?this.resetResultCache(e.resetResultIdentities):e.resetResultIdentities&&this.storeReader.resetCanon()),t},t.prototype.retain=function(e,t){return(t?this.optimisticData:this.data).retain(e)},t.prototype.release=function(e,t){return(t?this.optimisticData:this.data).release(e)},t.prototype.identify=function(e){if(eD(e))return e.__ref;try{return this.policies.identify(e)[0]}catch(t){__DEV__&&Q.kG.warn(t)}},t.prototype.evict=function(e){if(!e.id){if(ic.call(e,"id"))return!1;e=(0,en.pi)((0,en.pi)({},e),{id:"ROOT_QUERY"})}try{return++this.txCount,this.optimisticData.evict(e,this.data)}finally{--this.txCount||!1===e.broadcast||this.broadcastWatches()}},t.prototype.reset=function(e){var t=this;return this.init(),nx.reset(),e&&e.discardWatches?(this.watches.forEach(function(e){return t.maybeBroadcastWatch.forget(e)}),this.watches.clear(),r1(this)):this.broadcastWatches(),Promise.resolve()},t.prototype.removeOptimistic=function(e){var t=this.optimisticData.removeLayer(e);t!==this.optimisticData&&(this.optimisticData=t,this.broadcastWatches())},t.prototype.batch=function(e){var t,n=this,r=e.update,i=e.optimistic,a=void 0===i||i,o=e.removeOptimistic,s=e.onWatchUpdated,u=function(e){var i=n,a=i.data,o=i.optimisticData;++n.txCount,e&&(n.data=n.optimisticData=e);try{return t=r(n)}finally{--n.txCount,n.data=a,n.optimisticData=o}},c=new Set;return s&&!this.txCount&&this.broadcastWatches((0,en.pi)((0,en.pi)({},e),{onWatchUpdated:function(e){return c.add(e),!1}})),"string"==typeof a?this.optimisticData=this.optimisticData.addLayer(a,u):!1===a?u(this.data):u(),"string"==typeof o&&(this.optimisticData=this.optimisticData.removeLayer(o)),s&&c.size?(this.broadcastWatches((0,en.pi)((0,en.pi)({},e),{onWatchUpdated:function(e,t){var n=s.call(this,e,t);return!1!==n&&c.delete(e),n}})),c.size&&c.forEach(function(e){return n.maybeBroadcastWatch.dirty(e)})):this.broadcastWatches(e),t},t.prototype.performTransaction=function(e,t){return this.batch({update:e,optimistic:t||null!==t})},t.prototype.transformDocument=function(e){if(this.addTypename){var t=this.typenameDocumentCache.get(e);return t||(t=nj(e),this.typenameDocumentCache.set(e,t),this.typenameDocumentCache.set(t,t)),t}return e},t.prototype.transformForLink=function(e){var t=this.config.fragments;return t?t.transform(e):e},t.prototype.broadcastWatches=function(e){var t=this;this.txCount||this.watches.forEach(function(n){return t.maybeBroadcastWatch(n,e)})},t.prototype.broadcastWatch=function(e,t){var n=e.lastDiff,r=this.diff(e);(!t||(e.optimistic&&"string"==typeof t.optimistic&&(r.fromOptimisticTransaction=!0),!t.onWatchUpdated||!1!==t.onWatchUpdated.call(this,e,r,n)))&&(n&&(0,nm.D)(n.result,r.result)||e.callback(e.lastDiff=r,n))},t}(io),ar={possibleTypes:{ApproveJobProposalSpecPayload:["ApproveJobProposalSpecSuccess","JobAlreadyExistsError","NotFoundError"],BridgePayload:["Bridge","NotFoundError"],CancelJobProposalSpecPayload:["CancelJobProposalSpecSuccess","NotFoundError"],ChainPayload:["Chain","NotFoundError"],CreateAPITokenPayload:["CreateAPITokenSuccess","InputErrors"],CreateBridgePayload:["CreateBridgeSuccess"],CreateCSAKeyPayload:["CSAKeyExistsError","CreateCSAKeySuccess"],CreateFeedsManagerChainConfigPayload:["CreateFeedsManagerChainConfigSuccess","InputErrors","NotFoundError"],CreateFeedsManagerPayload:["CreateFeedsManagerSuccess","DuplicateFeedsManagerError","InputErrors","NotFoundError","SingleFeedsManagerError"],CreateJobPayload:["CreateJobSuccess","InputErrors"],CreateOCR2KeyBundlePayload:["CreateOCR2KeyBundleSuccess"],CreateOCRKeyBundlePayload:["CreateOCRKeyBundleSuccess"],CreateP2PKeyPayload:["CreateP2PKeySuccess"],DeleteAPITokenPayload:["DeleteAPITokenSuccess","InputErrors"],DeleteBridgePayload:["DeleteBridgeConflictError","DeleteBridgeInvalidNameError","DeleteBridgeSuccess","NotFoundError"],DeleteCSAKeyPayload:["DeleteCSAKeySuccess","NotFoundError"],DeleteFeedsManagerChainConfigPayload:["DeleteFeedsManagerChainConfigSuccess","NotFoundError"],DeleteJobPayload:["DeleteJobSuccess","NotFoundError"],DeleteOCR2KeyBundlePayload:["DeleteOCR2KeyBundleSuccess","NotFoundError"],DeleteOCRKeyBundlePayload:["DeleteOCRKeyBundleSuccess","NotFoundError"],DeleteP2PKeyPayload:["DeleteP2PKeySuccess","NotFoundError"],DeleteVRFKeyPayload:["DeleteVRFKeySuccess","NotFoundError"],DisableFeedsManagerPayload:["DisableFeedsManagerSuccess","NotFoundError"],DismissJobErrorPayload:["DismissJobErrorSuccess","NotFoundError"],EnableFeedsManagerPayload:["EnableFeedsManagerSuccess","NotFoundError"],Error:["CSAKeyExistsError","DeleteBridgeConflictError","DeleteBridgeInvalidNameError","DuplicateFeedsManagerError","InputError","JobAlreadyExistsError","NotFoundError","RunJobCannotRunError","SingleFeedsManagerError"],EthTransactionPayload:["EthTransaction","NotFoundError"],FeaturesPayload:["Features"],FeedsManagerPayload:["FeedsManager","NotFoundError"],GetSQLLoggingPayload:["SQLLogging"],GlobalLogLevelPayload:["GlobalLogLevel"],JobPayload:["Job","NotFoundError"],JobProposalPayload:["JobProposal","NotFoundError"],JobRunPayload:["JobRun","NotFoundError"],JobSpec:["BlockHeaderFeederSpec","BlockhashStoreSpec","BootstrapSpec","CronSpec","DirectRequestSpec","FluxMonitorSpec","GatewaySpec","KeeperSpec","OCR2Spec","OCRSpec","StandardCapabilitiesSpec","StreamSpec","VRFSpec","WebhookSpec","WorkflowSpec"],NodePayload:["Node","NotFoundError"],PaginatedPayload:["BridgesPayload","ChainsPayload","EthTransactionAttemptsPayload","EthTransactionsPayload","JobRunsPayload","JobsPayload","NodesPayload"],RejectJobProposalSpecPayload:["NotFoundError","RejectJobProposalSpecSuccess"],RunJobPayload:["NotFoundError","RunJobCannotRunError","RunJobSuccess"],SetGlobalLogLevelPayload:["InputErrors","SetGlobalLogLevelSuccess"],SetSQLLoggingPayload:["SetSQLLoggingSuccess"],SetServicesLogLevelsPayload:["InputErrors","SetServicesLogLevelsSuccess"],UpdateBridgePayload:["NotFoundError","UpdateBridgeSuccess"],UpdateFeedsManagerChainConfigPayload:["InputErrors","NotFoundError","UpdateFeedsManagerChainConfigSuccess"],UpdateFeedsManagerPayload:["InputErrors","NotFoundError","UpdateFeedsManagerSuccess"],UpdateJobProposalSpecDefinitionPayload:["NotFoundError","UpdateJobProposalSpecDefinitionSuccess"],UpdatePasswordPayload:["InputErrors","UpdatePasswordSuccess"],VRFKeyPayload:["NotFoundError","VRFKeySuccess"]}};let ai=ar;var aa=(r=void 0,location.origin),ao=new nh({uri:"".concat(aa,"/query"),credentials:"include"}),as=new ia({cache:new an({possibleTypes:ai.possibleTypes,dataIdFromObject:function(e){if("Chain"===e.__typename){if(!e.network)throw Error("Due to Chain ID not being unique across chain, ensure network is fetched too");return"Chain:".concat(e.network,":").concat(e.id)}return id(e)}}),link:ao});if(a.Z.locale(o),u().defaultFormat="YYYY-MM-DD h:mm:ss A","undefined"!=typeof document){var au,ac,al=f().hydrate;ac=X,al(c.createElement(et,{client:as},c.createElement(d.zj,null,c.createElement(i.MuiThemeProvider,{theme:J.r},c.createElement(ac,null)))),document.getElementById("root"))}})()})(); \ No newline at end of file +`+(a!==i?`result of cast: ${a}`:""))}return r}_cast(e,t){let n=void 0===e?e:this.transforms.reduce((t,n)=>n.call(this,t,e,this),e);return void 0===n&&(n=this.getDefault()),n}_validate(e,t={},n){let{sync:r,path:i,from:a=[],originalValue:o=e,strict:s=this.spec.strict,abortEarly:u=this.spec.abortEarly}=t,c=e;s||(c=this._cast(c,pA({assert:!1},t)));let l={value:c,path:i,options:t,originalValue:o,schema:this,label:this.spec.label,sync:r,from:a},f=[];this._typeError&&f.push(this._typeError),this._whitelistError&&f.push(this._whitelistError),this._blacklistError&&f.push(this._blacklistError),pg({args:l,value:c,path:i,sync:r,tests:f,endEarly:u},e=>{if(e)return void n(e,c);pg({tests:this.tests,args:l,path:i,sync:r,value:c,endEarly:u},n)})}validate(e,t,n){let r=this.resolve(pA({},t,{value:e}));return"function"==typeof n?r._validate(e,t,n):new Promise((n,i)=>r._validate(e,t,(e,t)=>{e?i(e):n(t)}))}validateSync(e,t){let n;return this.resolve(pA({},t,{value:e}))._validate(e,pA({},t,{sync:!0}),(e,t)=>{if(e)throw e;n=t}),n}isValid(e,t){return this.validate(e,t).then(()=>!0,e=>{if(pb.isError(e))return!1;throw e})}isValidSync(e,t){try{return this.validateSync(e,t),!0}catch(n){if(pb.isError(n))return!1;throw n}}_getDefault(){let e=this.spec.default;return null==e?e:"function"==typeof e?e.call(this):h0(e)}getDefault(e){return this.resolve(e||{})._getDefault()}default(e){return 0===arguments.length?this._getDefault():this.clone({default:e})}strict(e=!0){var t=this.clone();return t.spec.strict=e,t}_isPresent(e){return null!=e}defined(e=pe.defined){return this.test({message:e,name:"defined",exclusive:!0,test:e=>void 0!==e})}required(e=pe.required){return this.clone({presence:"required"}).withMutation(t=>t.test({message:e,name:"required",exclusive:!0,test(e){return this.schema._isPresent(e)}}))}notRequired(){var e=this.clone({presence:"optional"});return e.tests=e.tests.filter(e=>"required"!==e.OPTIONS.name),e}nullable(e=!0){return this.clone({nullable:!1!==e})}transform(e){var t=this.clone();return t.transforms.push(e),t}test(...e){let t;if(void 0===(t=1===e.length?"function"==typeof e[0]?{test:e[0]}:e[0]:2===e.length?{name:e[0],test:e[1]}:{name:e[0],message:e[1],test:e[2]}).message&&(t.message=pe.default),"function"!=typeof t.test)throw TypeError("`test` is a required parameters");let n=this.clone(),r=px(t),i=t.exclusive||t.name&&!0===n.exclusiveTests[t.name];if(t.exclusive&&!t.name)throw TypeError("Exclusive tests must provide a unique `name` identifying the test");return t.name&&(n.exclusiveTests[t.name]=!!t.exclusive),n.tests=n.tests.filter(e=>e.OPTIONS.name!==t.name||!i&&e.OPTIONS.test!==r.OPTIONS.test),n.tests.push(r),n}when(e,t){Array.isArray(e)||"string"==typeof e||(t=e,e=".");let n=this.clone(),r=pd(e).map(e=>new pE(e));return r.forEach(e=>{e.isSibling&&n.deps.push(e.key)}),n.conditions.push(new pf(r,t)),n}typeError(e){var t=this.clone();return t._typeError=px({message:e,name:"typeError",test(e){return!!(void 0===e||this.schema.isType(e))||this.createError({params:{type:this.schema._type}})}}),t}oneOf(e,t=pe.oneOf){var n=this.clone();return e.forEach(e=>{n._whitelist.add(e),n._blacklist.delete(e)}),n._whitelistError=px({message:t,name:"oneOf",test(e){if(void 0===e)return!0;let t=this.schema._whitelist;return!!t.has(e,this.resolve)||this.createError({params:{values:t.toArray().join(", ")}})}}),n}notOneOf(e,t=pe.notOneOf){var n=this.clone();return e.forEach(e=>{n._blacklist.add(e),n._whitelist.delete(e)}),n._blacklistError=px({message:t,name:"notOneOf",test(e){let t=this.schema._blacklist;return!t.has(e,this.resolve)||this.createError({params:{values:t.toArray().join(", ")}})}}),n}strip(e=!0){let t=this.clone();return t.spec.strip=e,t}describe(){let e=this.clone(),{label:t,meta:n}=e.spec,r={meta:n,label:t,type:e.type,oneOf:e._whitelist.describe(),notOneOf:e._blacklist.describe(),tests:e.tests.map(e=>({name:e.OPTIONS.name,params:e.OPTIONS.params})).filter((e,t,n)=>n.findIndex(t=>t.name===e.name)===t)};return r}}for(let pC of(pL.prototype.__isYupSchema__=!0,["validate","validateSync"]))pL.prototype[`${pC}At`]=function(e,t,n={}){let{parent:r,parentPath:i,schema:a}=pM(this,e,t,n.context);return a[pC](r&&r[i],pA({},n,{parent:r,path:e}))};for(let pI of["equals","is"])pL.prototype[pI]=pL.prototype.oneOf;for(let pD of["not","nope"])pL.prototype[pD]=pL.prototype.notOneOf;pL.prototype.optional=pL.prototype.notRequired;let pN=pL;function pP(){return new pN}pP.prototype=pN.prototype;let pR=e=>null==e;function pj(){return new pF}class pF extends pL{constructor(){super({type:"boolean"}),this.withMutation(()=>{this.transform(function(e){if(!this.isType(e)){if(/^(true|1)$/i.test(String(e)))return!0;if(/^(false|0)$/i.test(String(e)))return!1}return e})})}_typeCheck(e){return e instanceof Boolean&&(e=e.valueOf()),"boolean"==typeof e}isTrue(e=pi.isValue){return this.test({message:e,name:"is-value",exclusive:!0,params:{value:"true"},test:e=>pR(e)||!0===e})}isFalse(e=pi.isValue){return this.test({message:e,name:"is-value",exclusive:!0,params:{value:"false"},test:e=>pR(e)||!1===e})}}pj.prototype=pF.prototype;let pY=/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i,pB=/^((https?|ftp):)?\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i,pU=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i,pH=e=>pR(e)||e===e.trim(),p$=({}).toString();function pz(){return new pG}class pG extends pL{constructor(){super({type:"string"}),this.withMutation(()=>{this.transform(function(e){if(this.isType(e)||Array.isArray(e))return e;let t=null!=e&&e.toString?e.toString():e;return t===p$?e:t})})}_typeCheck(e){return e instanceof String&&(e=e.valueOf()),"string"==typeof e}_isPresent(e){return super._isPresent(e)&&!!e.length}length(e,t=pt.length){return this.test({message:t,name:"length",exclusive:!0,params:{length:e},test(t){return pR(t)||t.length===this.resolve(e)}})}min(e,t=pt.min){return this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(t){return pR(t)||t.length>=this.resolve(e)}})}max(e,t=pt.max){return this.test({name:"max",exclusive:!0,message:t,params:{max:e},test(t){return pR(t)||t.length<=this.resolve(e)}})}matches(e,t){let n=!1,r,i;return t&&("object"==typeof t?{excludeEmptyString:n=!1,message:r,name:i}=t:r=t),this.test({name:i||"matches",message:r||pt.matches,params:{regex:e},test:t=>pR(t)||""===t&&n||-1!==t.search(e)})}email(e=pt.email){return this.matches(pY,{name:"email",message:e,excludeEmptyString:!0})}url(e=pt.url){return this.matches(pB,{name:"url",message:e,excludeEmptyString:!0})}uuid(e=pt.uuid){return this.matches(pU,{name:"uuid",message:e,excludeEmptyString:!1})}ensure(){return this.default("").transform(e=>null===e?"":e)}trim(e=pt.trim){return this.transform(e=>null!=e?e.trim():e).test({message:e,name:"trim",test:pH})}lowercase(e=pt.lowercase){return this.transform(e=>pR(e)?e:e.toLowerCase()).test({message:e,name:"string_case",exclusive:!0,test:e=>pR(e)||e===e.toLowerCase()})}uppercase(e=pt.uppercase){return this.transform(e=>pR(e)?e:e.toUpperCase()).test({message:e,name:"string_case",exclusive:!0,test:e=>pR(e)||e===e.toUpperCase()})}}pz.prototype=pG.prototype;let pW=e=>e!=+e;function pK(){return new pV}class pV extends pL{constructor(){super({type:"number"}),this.withMutation(()=>{this.transform(function(e){let t=e;if("string"==typeof t){if(""===(t=t.replace(/\s/g,"")))return NaN;t=+t}return this.isType(t)?t:parseFloat(t)})})}_typeCheck(e){return e instanceof Number&&(e=e.valueOf()),"number"==typeof e&&!pW(e)}min(e,t=pn.min){return this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(t){return pR(t)||t>=this.resolve(e)}})}max(e,t=pn.max){return this.test({message:t,name:"max",exclusive:!0,params:{max:e},test(t){return pR(t)||t<=this.resolve(e)}})}lessThan(e,t=pn.lessThan){return this.test({message:t,name:"max",exclusive:!0,params:{less:e},test(t){return pR(t)||tthis.resolve(e)}})}positive(e=pn.positive){return this.moreThan(0,e)}negative(e=pn.negative){return this.lessThan(0,e)}integer(e=pn.integer){return this.test({name:"integer",message:e,test:e=>pR(e)||Number.isInteger(e)})}truncate(){return this.transform(e=>pR(e)?e:0|e)}round(e){var t,n=["ceil","floor","round","trunc"];if("trunc"===(e=(null==(t=e)?void 0:t.toLowerCase())||"round"))return this.truncate();if(-1===n.indexOf(e.toLowerCase()))throw TypeError("Only valid options for round() are: "+n.join(", "));return this.transform(t=>pR(t)?t:Math[e](t))}}pK.prototype=pV.prototype;var pq=/^(\d{4}|[+\-]\d{6})(?:-?(\d{2})(?:-?(\d{2}))?)?(?:[ T]?(\d{2}):?(\d{2})(?::?(\d{2})(?:[,\.](\d{1,}))?)?(?:(Z)|([+\-])(\d{2})(?::?(\d{2}))?)?)?$/;function pZ(e){var t,n,r=[1,4,5,6,7,10,11],i=0;if(n=pq.exec(e)){for(var a,o=0;a=r[o];++o)n[a]=+n[a]||0;n[2]=(+n[2]||1)-1,n[3]=+n[3]||1,n[7]=n[7]?String(n[7]).substr(0,3):0,(void 0===n[8]||""===n[8])&&(void 0===n[9]||""===n[9])?t=+new Date(n[1],n[2],n[3],n[4],n[5],n[6],n[7]):("Z"!==n[8]&&void 0!==n[9]&&(i=60*n[10]+n[11],"+"===n[9]&&(i=0-i)),t=Date.UTC(n[1],n[2],n[3],n[4],n[5]+i,n[6],n[7]))}else t=Date.parse?Date.parse(e):NaN;return t}let pX=new Date(""),pJ=e=>"[object Date]"===Object.prototype.toString.call(e);function pQ(){return new p1}class p1 extends pL{constructor(){super({type:"date"}),this.withMutation(()=>{this.transform(function(e){return this.isType(e)?e:(e=pZ(e),isNaN(e)?pX:new Date(e))})})}_typeCheck(e){return pJ(e)&&!isNaN(e.getTime())}prepareParam(e,t){let n;if(pE.isRef(e))n=e;else{let r=this.cast(e);if(!this._typeCheck(r))throw TypeError(`\`${t}\` must be a Date or a value that can be \`cast()\` to a Date`);n=r}return n}min(e,t=pr.min){let n=this.prepareParam(e,"min");return this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(e){return pR(e)||e>=this.resolve(n)}})}max(e,t=pr.max){var n=this.prepareParam(e,"max");return this.test({message:t,name:"max",exclusive:!0,params:{max:e},test(e){return pR(e)||e<=this.resolve(n)}})}}p1.INVALID_DATE=pX,pQ.prototype=p1.prototype,pQ.INVALID_DATE=pX;var p0=n(11865),p2=n.n(p0),p3=n(68929),p4=n.n(p3),p6=n(67523),p5=n.n(p6),p8=n(94633),p9=n.n(p8);function p7(e,t=[]){let n=[],r=[];function i(e,i){var a=(0,pw.split)(e)[0];~r.indexOf(a)||r.push(a),~t.indexOf(`${i}-${a}`)||n.push([i,a])}for(let a in e)if(pu()(e,a)){let o=e[a];~r.indexOf(a)||r.push(a),pE.isRef(o)&&o.isSibling?i(o.path,a):pc(o)&&"deps"in o&&o.deps.forEach(e=>i(e,a))}return p9().array(r,n).reverse()}function be(e,t){let n=1/0;return e.some((e,r)=>{var i;if((null==(i=t.path)?void 0:i.indexOf(e))!==-1)return n=r,!0}),n}function bt(e){return(t,n)=>be(e,t)-be(e,n)}function bn(){return(bn=Object.assign||function(e){for(var t=1;t"[object Object]"===Object.prototype.toString.call(e);function bi(e,t){let n=Object.keys(e.fields);return Object.keys(t).filter(e=>-1===n.indexOf(e))}let ba=bt([]);class bo extends pL{constructor(e){super({type:"object"}),this.fields=Object.create(null),this._sortErrors=ba,this._nodes=[],this._excludedEdges=[],this.withMutation(()=>{this.transform(function(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(t){e=null}return this.isType(e)?e:null}),e&&this.shape(e)})}_typeCheck(e){return br(e)||"function"==typeof e}_cast(e,t={}){var n;let r=super._cast(e,t);if(void 0===r)return this.getDefault();if(!this._typeCheck(r))return r;let i=this.fields,a=null!=(n=t.stripUnknown)?n:this.spec.noUnknown,o=this._nodes.concat(Object.keys(r).filter(e=>-1===this._nodes.indexOf(e))),s={},u=bn({},t,{parent:s,__validating:t.__validating||!1}),c=!1;for(let l of o){let f=i[l],d=pu()(r,l);if(f){let h,p=r[l];u.path=(t.path?`${t.path}.`:"")+l;let b="spec"in(f=f.resolve({value:p,context:t.context,parent:s}))?f.spec:void 0,m=null==b?void 0:b.strict;if(null==b?void 0:b.strip){c=c||l in r;continue}void 0!==(h=t.__validating&&m?r[l]:f.cast(r[l],u))&&(s[l]=h)}else d&&!a&&(s[l]=r[l]);s[l]!==r[l]&&(c=!0)}return c?s:r}_validate(e,t={},n){let r=[],{sync:i,from:a=[],originalValue:o=e,abortEarly:s=this.spec.abortEarly,recursive:u=this.spec.recursive}=t;a=[{schema:this,value:o},...a],t.__validating=!0,t.originalValue=o,t.from=a,super._validate(e,t,(e,c)=>{if(e){if(!pb.isError(e)||s)return void n(e,c);r.push(e)}if(!u||!br(c)){n(r[0]||null,c);return}o=o||c;let l=this._nodes.map(e=>(n,r)=>{let i=-1===e.indexOf(".")?(t.path?`${t.path}.`:"")+e:`${t.path||""}["${e}"]`,s=this.fields[e];if(s&&"validate"in s){s.validate(c[e],bn({},t,{path:i,from:a,strict:!0,parent:c,originalValue:o[e]}),r);return}r(null)});pg({sync:i,tests:l,value:c,errors:r,endEarly:s,sort:this._sortErrors,path:t.path},n)})}clone(e){let t=super.clone(e);return t.fields=bn({},this.fields),t._nodes=this._nodes,t._excludedEdges=this._excludedEdges,t._sortErrors=this._sortErrors,t}concat(e){let t=super.concat(e),n=t.fields;for(let[r,i]of Object.entries(this.fields)){let a=n[r];void 0===a?n[r]=i:a instanceof pL&&i instanceof pL&&(n[r]=i.concat(a))}return t.withMutation(()=>t.shape(n))}getDefaultFromShape(){let e={};return this._nodes.forEach(t=>{let n=this.fields[t];e[t]="default"in n?n.getDefault():void 0}),e}_getDefault(){return"default"in this.spec?super._getDefault():this._nodes.length?this.getDefaultFromShape():void 0}shape(e,t=[]){let n=this.clone(),r=Object.assign(n.fields,e);if(n.fields=r,n._sortErrors=bt(Object.keys(r)),t.length){Array.isArray(t[0])||(t=[t]);let i=t.map(([e,t])=>`${e}-${t}`);n._excludedEdges=n._excludedEdges.concat(i)}return n._nodes=p7(r,n._excludedEdges),n}pick(e){let t={};for(let n of e)this.fields[n]&&(t[n]=this.fields[n]);return this.clone().withMutation(e=>(e.fields={},e.shape(t)))}omit(e){let t=this.clone(),n=t.fields;for(let r of(t.fields={},e))delete n[r];return t.withMutation(()=>t.shape(n))}from(e,t,n){let r=(0,pw.getter)(e,!0);return this.transform(i=>{if(null==i)return i;let a=i;return pu()(i,e)&&(a=bn({},i),n||delete a[e],a[t]=r(i)),a})}noUnknown(e=!0,t=pa.noUnknown){"string"==typeof e&&(t=e,e=!0);let n=this.test({name:"noUnknown",exclusive:!0,message:t,test(t){if(null==t)return!0;let n=bi(this.schema,t);return!e||0===n.length||this.createError({params:{unknown:n.join(", ")}})}});return n.spec.noUnknown=e,n}unknown(e=!0,t=pa.noUnknown){return this.noUnknown(!e,t)}transformKeys(e){return this.transform(t=>t&&p5()(t,(t,n)=>e(n)))}camelCase(){return this.transformKeys(p4())}snakeCase(){return this.transformKeys(p2())}constantCase(){return this.transformKeys(e=>p2()(e).toUpperCase())}describe(){let e=super.describe();return e.fields=py()(this.fields,e=>e.describe()),e}}function bs(e){return new bo(e)}function bu(){return(bu=Object.assign||function(e){for(var t=1;t{this.transform(function(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(t){e=null}return this.isType(e)?e:null})})}_typeCheck(e){return Array.isArray(e)}get _subType(){return this.innerType}_cast(e,t){let n=super._cast(e,t);if(!this._typeCheck(n)||!this.innerType)return n;let r=!1,i=n.map((e,n)=>{let i=this.innerType.cast(e,bu({},t,{path:`${t.path||""}[${n}]`}));return i!==e&&(r=!0),i});return r?i:n}_validate(e,t={},n){var r,i;let a=[],o=t.sync,s=t.path,u=this.innerType,c=null!=(r=t.abortEarly)?r:this.spec.abortEarly,l=null!=(i=t.recursive)?i:this.spec.recursive,f=null!=t.originalValue?t.originalValue:e;super._validate(e,t,(e,r)=>{if(e){if(!pb.isError(e)||c)return void n(e,r);a.push(e)}if(!l||!u||!this._typeCheck(r)){n(a[0]||null,r);return}f=f||r;let i=Array(r.length);for(let d=0;du.validate(h,b,t)}pg({sync:o,path:s,value:r,errors:a,endEarly:c,tests:i},n)})}clone(e){let t=super.clone(e);return t.innerType=this.innerType,t}concat(e){let t=super.concat(e);return t.innerType=this.innerType,e.innerType&&(t.innerType=t.innerType?t.innerType.concat(e.innerType):e.innerType),t}of(e){let t=this.clone();if(!pc(e))throw TypeError("`array.of()` sub-schema must be a valid yup schema not: "+h7(e));return t.innerType=e,t}length(e,t=po.length){return this.test({message:t,name:"length",exclusive:!0,params:{length:e},test(t){return pR(t)||t.length===this.resolve(e)}})}min(e,t){return t=t||po.min,this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(t){return pR(t)||t.length>=this.resolve(e)}})}max(e,t){return t=t||po.max,this.test({message:t,name:"max",exclusive:!0,params:{max:e},test(t){return pR(t)||t.length<=this.resolve(e)}})}ensure(){return this.default(()=>[]).transform((e,t)=>this._typeCheck(e)?e:null==t?[]:[].concat(t))}compact(e){let t=e?(t,n,r)=>!e(t,n,r):e=>!!e;return this.transform(e=>null!=e?e.filter(t):e)}describe(){let e=super.describe();return this.innerType&&(e.innerType=this.innerType.describe()),e}nullable(e=!0){return super.nullable(e)}defined(){return super.defined()}required(e){return super.required(e)}}bc.prototype=bl.prototype;var bf=bs().shape({name:pz().required("Required"),url:pz().required("Required")}),bd=function(e){var t=e.initialValues,n=e.onSubmit,r=e.submitButtonText,i=e.nameDisabled,a=void 0!==i&&i;return l.createElement(hb,{initialValues:t,validationSchema:bf,onSubmit:n},function(e){var t=e.isSubmitting;return l.createElement(l.Fragment,null,l.createElement(hx,{"data-testid":"bridge-form",noValidate:!0},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(hk,{component:hB,id:"name",name:"name",label:"Name",disabled:a,required:!0,fullWidth:!0,FormHelperTextProps:{"data-testid":"name-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(hk,{component:hB,id:"url",name:"url",label:"Bridge URL",placeholder:"https://",required:!0,fullWidth:!0,FormHelperTextProps:{"data-testid":"url-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:7},l.createElement(hk,{component:hB,id:"minimumContractPayment",name:"minimumContractPayment",label:"Minimum Contract Payment",placeholder:"0",fullWidth:!0,inputProps:{min:0},FormHelperTextProps:{"data-testid":"minimumContractPayment-helper-text"}})),l.createElement(d.Z,{item:!0,xs:7},l.createElement(hk,{component:hB,id:"confirmations",name:"confirmations",label:"Confirmations",placeholder:"0",type:"number",fullWidth:!0,inputProps:{min:0},FormHelperTextProps:{"data-testid":"confirmations-helper-text"}})))),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(of.default,{variant:"contained",color:"primary",type:"submit",disabled:t,size:"large"},r)))))})},bh=function(e){var t=e.bridge,n=e.onSubmit,r={name:t.name,url:t.url,minimumContractPayment:t.minimumContractPayment,confirmations:t.confirmations};return l.createElement(ig,null,l.createElement(d.Z,{container:!0,spacing:40},l.createElement(d.Z,{item:!0,xs:12,md:11,lg:9},l.createElement(r5.Z,null,l.createElement(o7.Z,{title:"Edit Bridge",action:l.createElement(o1.Z,{component:tz,href:"/bridges/".concat(t.id)},"Cancel")}),l.createElement(aD.Z,null,l.createElement(bd,{nameDisabled:!0,initialValues:r,onSubmit:n,submitButtonText:"Save Bridge"}))))))};function bp(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&void 0!==arguments[0]&&arguments[0],t=e?function(){return l.createElement(x.default,{variant:"body1"},"Loading...")}:function(){return null};return{isLoading:e,LoadingPlaceholder:t}},b7=n(76023);function me(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function mL(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n=4?[e[0],e[1],e[2],e[3],"".concat(e[0],".").concat(e[1]),"".concat(e[0],".").concat(e[2]),"".concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[0]),"".concat(e[1],".").concat(e[2]),"".concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[1]),"".concat(e[2],".").concat(e[3]),"".concat(e[3],".").concat(e[0]),"".concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[0]),"".concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[3],".").concat(e[1],".").concat(e[0]),"".concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[1],".").concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[2],".").concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[3],".").concat(e[0]),"".concat(e[2],".").concat(e[3],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[3],".").concat(e[1],".").concat(e[0]),"".concat(e[3],".").concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[3],".").concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[3],".").concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[3],".").concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[3],".").concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[3],".").concat(e[2],".").concat(e[1],".").concat(e[0])]:void 0}var mB={};function mU(e){if(0===e.length||1===e.length)return e;var t=e.join(".");return mB[t]||(mB[t]=mY(e)),mB[t]}function mH(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2?arguments[2]:void 0;return mU(e.filter(function(e){return"token"!==e})).reduce(function(e,t){return mj({},e,n[t])},t)}function m$(e){return e.join(" ")}function mz(e,t){var n=0;return function(r){return n+=1,r.map(function(r,i){return mG({node:r,stylesheet:e,useInlineStyles:t,key:"code-segment-".concat(n,"-").concat(i)})})}}function mG(e){var t=e.node,n=e.stylesheet,r=e.style,i=void 0===r?{}:r,a=e.useInlineStyles,o=e.key,s=t.properties,u=t.type,c=t.tagName,f=t.value;if("text"===u)return f;if(c){var d,h=mz(n,a);if(a){var p=Object.keys(n).reduce(function(e,t){return t.split(".").forEach(function(t){e.includes(t)||e.push(t)}),e},[]),b=s.className&&s.className.includes("token")?["token"]:[],m=s.className&&b.concat(s.className.filter(function(e){return!p.includes(e)}));d=mj({},s,{className:m$(m)||void 0,style:mH(s.className,Object.assign({},s.style,i),n)})}else d=mj({},s,{className:m$(s.className)});var g=h(t.children);return l.createElement(c,(0,mF.Z)({key:o},d),g)}}let mW=function(e,t){return -1!==e.listLanguages().indexOf(t)};var mK=/\n/g;function mV(e){return e.match(mK)}function mq(e){var t=e.lines,n=e.startingLineNumber,r=e.style;return t.map(function(e,t){var i=t+n;return l.createElement("span",{key:"line-".concat(t),className:"react-syntax-highlighter-line-number",style:"function"==typeof r?r(i):r},"".concat(i,"\n"))})}function mZ(e){var t=e.codeString,n=e.codeStyle,r=e.containerStyle,i=void 0===r?{float:"left",paddingRight:"10px"}:r,a=e.numberStyle,o=void 0===a?{}:a,s=e.startingLineNumber;return l.createElement("code",{style:Object.assign({},n,i)},mq({lines:t.replace(/\n$/,"").split("\n"),style:o,startingLineNumber:s}))}function mX(e){return"".concat(e.toString().length,".25em")}function mJ(e,t){return{type:"element",tagName:"span",properties:{key:"line-number--".concat(e),className:["comment","linenumber","react-syntax-highlighter-line-number"],style:t},children:[{type:"text",value:e}]}}function mQ(e,t,n){var r,i={display:"inline-block",minWidth:mX(n),paddingRight:"1em",textAlign:"right",userSelect:"none"};return mj({},i,"function"==typeof e?e(t):e)}function m1(e){var t=e.children,n=e.lineNumber,r=e.lineNumberStyle,i=e.largestLineNumber,a=e.showInlineLineNumbers,o=e.lineProps,s=void 0===o?{}:o,u=e.className,c=void 0===u?[]:u,l=e.showLineNumbers,f=e.wrapLongLines,d="function"==typeof s?s(n):s;if(d.className=c,n&&a){var h=mQ(r,n,i);t.unshift(mJ(n,h))}return f&l&&(d.style=mj({},d.style,{display:"flex"})),{type:"element",tagName:"span",properties:d,children:t}}function m0(e){for(var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[],r=0;r2&&void 0!==arguments[2]?arguments[2]:[];return m1({children:e,lineNumber:t,lineNumberStyle:s,largestLineNumber:o,showInlineLineNumbers:i,lineProps:n,className:a,showLineNumbers:r,wrapLongLines:u})}function b(e,t){if(r&&t&&i){var n=mQ(s,t,o);e.unshift(mJ(t,n))}return e}function m(e,n){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[];return t||r.length>0?p(e,n,r):b(e,n)}for(var g=function(){var e=l[h],t=e.children[0].value;if(mV(t)){var n=t.split("\n");n.forEach(function(t,i){var o=r&&f.length+a,s={type:"text",value:"".concat(t,"\n")};if(0===i){var u=l.slice(d+1,h).concat(m1({children:[s],className:e.properties.className})),c=m(u,o);f.push(c)}else if(i===n.length-1){if(l[h+1]&&l[h+1].children&&l[h+1].children[0]){var p={type:"text",value:"".concat(t)},b=m1({children:[p],className:e.properties.className});l.splice(h+1,0,b)}else{var g=[s],v=m(g,o,e.properties.className);f.push(v)}}else{var y=[s],w=m(y,o,e.properties.className);f.push(w)}}),d=h}h++};h code[class*="language-"]':{background:"#f5f2f0",padding:".1em",borderRadius:".3em",whiteSpace:"normal"},comment:{color:"slategray"},prolog:{color:"slategray"},doctype:{color:"slategray"},cdata:{color:"slategray"},punctuation:{color:"#999"},namespace:{Opacity:".7"},property:{color:"#905"},tag:{color:"#905"},boolean:{color:"#905"},number:{color:"#905"},constant:{color:"#905"},symbol:{color:"#905"},deleted:{color:"#905"},selector:{color:"#690"},"attr-name":{color:"#690"},string:{color:"#690"},char:{color:"#690"},builtin:{color:"#690"},inserted:{color:"#690"},operator:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},entity:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)",cursor:"help"},url:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},".language-css .token.string":{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},".style .token.string":{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},atrule:{color:"#07a"},"attr-value":{color:"#07a"},keyword:{color:"#07a"},function:{color:"#DD4A68"},"class-name":{color:"#DD4A68"},regex:{color:"#e90"},important:{color:"#e90",fontWeight:"bold"},variable:{color:"#e90"},bold:{fontWeight:"bold"},italic:{fontStyle:"italic"}};var m9=n(98695),m7=n.n(m9);let ge=["abap","abnf","actionscript","ada","agda","al","antlr4","apacheconf","apl","applescript","aql","arduino","arff","asciidoc","asm6502","aspnet","autohotkey","autoit","bash","basic","batch","bbcode","birb","bison","bnf","brainfuck","brightscript","bro","bsl","c","cil","clike","clojure","cmake","coffeescript","concurnas","cpp","crystal","csharp","csp","css-extras","css","cypher","d","dart","dax","dhall","diff","django","dns-zone-file","docker","ebnf","editorconfig","eiffel","ejs","elixir","elm","erb","erlang","etlua","excel-formula","factor","firestore-security-rules","flow","fortran","fsharp","ftl","gcode","gdscript","gedcom","gherkin","git","glsl","gml","go","graphql","groovy","haml","handlebars","haskell","haxe","hcl","hlsl","hpkp","hsts","http","ichigojam","icon","iecst","ignore","inform7","ini","io","j","java","javadoc","javadoclike","javascript","javastacktrace","jolie","jq","js-extras","js-templates","jsdoc","json","json5","jsonp","jsstacktrace","jsx","julia","keyman","kotlin","latex","latte","less","lilypond","liquid","lisp","livescript","llvm","lolcode","lua","makefile","markdown","markup-templating","markup","matlab","mel","mizar","mongodb","monkey","moonscript","n1ql","n4js","nand2tetris-hdl","naniscript","nasm","neon","nginx","nim","nix","nsis","objectivec","ocaml","opencl","oz","parigp","parser","pascal","pascaligo","pcaxis","peoplecode","perl","php-extras","php","phpdoc","plsql","powerquery","powershell","processing","prolog","properties","protobuf","pug","puppet","pure","purebasic","purescript","python","q","qml","qore","r","racket","reason","regex","renpy","rest","rip","roboconf","robotframework","ruby","rust","sas","sass","scala","scheme","scss","shell-session","smali","smalltalk","smarty","sml","solidity","solution-file","soy","sparql","splunk-spl","sqf","sql","stan","stylus","swift","t4-cs","t4-templating","t4-vb","tap","tcl","textile","toml","tsx","tt2","turtle","twig","typescript","typoscript","unrealscript","vala","vbnet","velocity","verilog","vhdl","vim","visual-basic","warpscript","wasm","wiki","xeora","xml-doc","xojo","xquery","yaml","yang","zig"];var gt=m5(m7(),m8);gt.supportedLanguages=ge;let gn=gt;var gr=n(64566);function gi(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function ga(){var e=gi(["\n query FetchConfigV2 {\n configv2 {\n user\n effective\n }\n }\n"]);return ga=function(){return e},e}var go=n0(ga()),gs=function(e){var t=e.children;return l.createElement(ir.Z,null,l.createElement(r7.default,{component:"th",scope:"row",colSpan:3},t))},gu=function(){return l.createElement(gs,null,"...")},gc=function(e){var t=e.children;return l.createElement(gs,null,t)},gl=function(e){var t=e.loading,n=e.toml,r=e.error,i=void 0===r?"":r,a=e.title,o=e.expanded;if(i)return l.createElement(gc,null,i);if(t)return l.createElement(gu,null);a||(a="TOML");var s={display:"block"};return l.createElement(x.default,null,l.createElement(mx.Z,{defaultExpanded:o},l.createElement(mT.Z,{expandIcon:l.createElement(gr.Z,null)},a),l.createElement(mM.Z,{style:s},l.createElement(gn,{language:"toml",style:m8},n))))},gf=function(){var e=rv(go,{fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error;return(null==t?void 0:t.configv2.effective)=="N/A"?l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12},l.createElement(r5.Z,null,l.createElement(o7.Z,{title:"TOML Configuration"}),l.createElement(gl,{title:"V2 config dump:",error:null==r?void 0:r.message,loading:n,toml:null==t?void 0:t.configv2.user,showHead:!0})))):l.createElement(l.Fragment,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(r5.Z,null,l.createElement(o7.Z,{title:"TOML Configuration"}),l.createElement(gl,{title:"User specified:",error:null==r?void 0:r.message,loading:n,toml:null==t?void 0:t.configv2.user,showHead:!0,expanded:!0}),l.createElement(gl,{title:"Effective (with defaults):",error:null==r?void 0:r.message,loading:n,toml:null==t?void 0:t.configv2.effective,showHead:!0})))))},gd=n(34823),gh=function(e){return(0,b.createStyles)({cell:{paddingTop:1.5*e.spacing.unit,paddingBottom:1.5*e.spacing.unit}})},gp=(0,b.withStyles)(gh)(function(e){var t=e.classes,n=(0,A.I0)();(0,l.useEffect)(function(){n((0,ty.DQ)())});var r=(0,A.v9)(gd.N,A.wU);return l.createElement(r5.Z,null,l.createElement(o7.Z,{title:"Node"}),l.createElement(r8.Z,null,l.createElement(r9.Z,null,l.createElement(ir.Z,null,l.createElement(r7.default,{className:t.cell},l.createElement(x.default,null,"Version"),l.createElement(x.default,{variant:"subtitle1",color:"textSecondary"},r.version))),l.createElement(ir.Z,null,l.createElement(r7.default,{className:t.cell},l.createElement(x.default,null,"SHA"),l.createElement(x.default,{variant:"subtitle1",color:"textSecondary"},r.commitSHA))))))}),gb=function(){return l.createElement(ig,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,sm:12,md:8},l.createElement(d.Z,{container:!0},l.createElement(gf,null))),l.createElement(d.Z,{item:!0,sm:12,md:4},l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(gp,null)),l.createElement(d.Z,{item:!0,xs:12},l.createElement(mk,null)),l.createElement(d.Z,{item:!0,xs:12},l.createElement(md,null))))))},gm=function(){return l.createElement(gb,null)},gg=function(){return l.createElement(gm,null)},gv=n(44431),gy=1e18,gw=function(e){return new gv.BigNumber(e).dividedBy(gy).toFixed(8)},g_=function(e){var t=e.keys,n=e.chainID,r=e.hideHeaderTitle;return l.createElement(l.Fragment,null,l.createElement(o7.Z,{title:!r&&"Account Balances",subheader:"Chain ID "+n}),l.createElement(aD.Z,null,l.createElement(w.default,{dense:!1,disablePadding:!0},t&&t.map(function(e,r){return l.createElement(l.Fragment,null,l.createElement(_.default,{disableGutters:!0,key:["acc-balance",n.toString(),r.toString()].join("-")},l.createElement(E.Z,{primary:l.createElement(l.Fragment,null,l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12},l.createElement(ot,{title:"Address"}),l.createElement(on,{value:e.address})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(ot,{title:"Native Token Balance"}),l.createElement(on,{value:e.ethBalance||"--"})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(ot,{title:"LINK Balance"}),l.createElement(on,{value:e.linkBalance?gw(e.linkBalance):"--"}))))})),r+1s&&l.createElement(gL.Z,null,l.createElement(ir.Z,null,l.createElement(r7.default,{className:r.footer},l.createElement(o1.Z,{href:"/runs",component:tz},"View More"))))))});function g0(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function g2(){var e=g0(["\n ","\n query FetchRecentJobRuns($offset: Int, $limit: Int) {\n jobRuns(offset: $offset, limit: $limit) {\n results {\n ...RecentJobRunsPayload_ResultsFields\n }\n metadata {\n total\n }\n }\n }\n"]);return g2=function(){return e},e}var g3=5,g4=n0(g2(),gJ),g6=function(){var e=rv(g4,{variables:{offset:0,limit:g3},fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error;return l.createElement(g1,{data:t,errorMsg:null==r?void 0:r.message,loading:n,maxRunsSize:g3})},g5=function(e){return(0,b.createStyles)({style:{textAlign:"center",padding:2.5*e.spacing.unit,position:"fixed",left:"0",bottom:"0",width:"100%",borderRadius:0},bareAnchor:{color:e.palette.common.black,textDecoration:"none"}})},g8=(0,b.withStyles)(g5)(function(e){var t=e.classes,n=(0,A.v9)(gd.N,A.wU),r=(0,A.I0)();return(0,l.useEffect)(function(){r((0,ty.DQ)())}),l.createElement(ii.default,{className:t.style},l.createElement(x.default,null,"Chainlink Node ",n.version," at commit"," ",l.createElement("a",{target:"_blank",rel:"noopener noreferrer",href:"https://github.com/smartcontractkit/chainlink/commit/".concat(n.commitSHA),className:t.bareAnchor},n.commitSHA)))}),g9=function(e){return(0,b.createStyles)({cell:{borderColor:e.palette.divider,borderTop:"1px solid",borderBottom:"none",paddingTop:2*e.spacing.unit,paddingBottom:2*e.spacing.unit,paddingLeft:2*e.spacing.unit},block:{display:"block"},overflowEllipsis:{textOverflow:"ellipsis",overflow:"hidden"}})},g7=(0,b.withStyles)(g9)(function(e){var t=e.classes,n=e.job;return l.createElement(ir.Z,null,l.createElement(r7.default,{scope:"row",className:t.cell},l.createElement(d.Z,{container:!0,spacing:0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(ih,{href:"/jobs/".concat(n.id),classes:{linkContent:t.block}},l.createElement(x.default,{className:t.overflowEllipsis,variant:"body1",component:"span",color:"primary"},n.name||n.id))),l.createElement(d.Z,{item:!0,xs:12},l.createElement(x.default,{variant:"body1",color:"textSecondary"},"Created ",l.createElement(aO,{tooltip:!0},n.createdAt))))))});function ve(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function vt(){var e=ve(["\n fragment RecentJobsPayload_ResultsFields on Job {\n id\n name\n createdAt\n }\n"]);return vt=function(){return e},e}var vn=n0(vt()),vr=function(){return(0,b.createStyles)({cardHeader:{borderBottom:0},table:{tableLayout:"fixed"}})},vi=(0,b.withStyles)(vr)(function(e){var t,n,r=e.classes,i=e.data,a=e.errorMsg,o=e.loading;return l.createElement(r5.Z,null,l.createElement(o7.Z,{title:"Recent Jobs",className:r.cardHeader}),l.createElement(r8.Z,{className:r.table},l.createElement(r9.Z,null,l.createElement(gD,{visible:o}),l.createElement(gN,{visible:(null===(t=null==i?void 0:i.jobs.results)||void 0===t?void 0:t.length)===0},"No recently created jobs"),l.createElement(gC,{msg:a}),null===(n=null==i?void 0:i.jobs.results)||void 0===n?void 0:n.map(function(e,t){return l.createElement(g7,{job:e,key:t})}))))});function va(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function vo(){var e=va(["\n ","\n query FetchRecentJobs($offset: Int, $limit: Int) {\n jobs(offset: $offset, limit: $limit) {\n results {\n ...RecentJobsPayload_ResultsFields\n }\n }\n }\n"]);return vo=function(){return e},e}var vs=5,vu=n0(vo(),vn),vc=function(){var e=rv(vu,{variables:{offset:0,limit:vs},fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error;return l.createElement(vi,{data:t,errorMsg:null==r?void 0:r.message,loading:n})},vl=function(){return l.createElement(ig,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:8},l.createElement(g6,null)),l.createElement(d.Z,{item:!0,xs:4},l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(gA,null)),l.createElement(d.Z,{item:!0,xs:12},l.createElement(vc,null))))),l.createElement(g8,null))},vf=function(){return l.createElement(vl,null)},vd=function(){return l.createElement(vf,null)},vh=n(87239),vp=function(e){switch(e){case"DirectRequestSpec":return"Direct Request";case"FluxMonitorSpec":return"Flux Monitor";default:return e.replace(/Spec$/,"")}},vb=n(5022),vm=n(78718),vg=n.n(vm);function vv(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n1?t-1:0),r=1;r1?t-1:0),r=1;re.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&n.map(function(e){return l.createElement(ir.Z,{key:e.id,style:{cursor:"pointer"},onClick:function(){return r.push("/runs/".concat(e.id))}},l.createElement(r7.default,{className:t.idCell,scope:"row"},l.createElement("div",{className:t.runDetails},l.createElement(x.default,{variant:"h5",color:"primary",component:"span"},e.id))),l.createElement(r7.default,{className:t.stampCell},l.createElement(x.default,{variant:"body1",color:"textSecondary",className:t.stamp},"Created ",l.createElement(aO,{tooltip:!0},e.createdAt))),l.createElement(r7.default,{className:t.statusCell,scope:"row"},l.createElement(x.default,{variant:"body1",className:O()(t.status,yr(t,e.status))},e.status.toLowerCase())))})))}),ya=n(16839),yo=n.n(ya);function ys(e){var t=e.replace(/\w+\s*=\s*<([^>]|[\r\n])*>/g,""),n=yo().read(t),r=n.edges();return n.nodes().map(function(e){var t={id:e,parentIds:r.filter(function(t){return t.w===e}).map(function(e){return e.v})};return Object.keys(n.node(e)).length>0&&(t.attributes=n.node(e)),t})}var yu=n(94164),yc=function(e){var t=e.data,n=[];return(null==t?void 0:t.attributes)&&Object.keys(t.attributes).forEach(function(e){var r;n.push(l.createElement("div",{key:e},l.createElement(x.default,{variant:"body1",color:"textSecondary",component:"div"},l.createElement("b",null,e,":")," ",null===(r=t.attributes)||void 0===r?void 0:r[e])))}),l.createElement("div",null,t&&l.createElement(x.default,{variant:"body1",color:"textPrimary"},l.createElement("b",null,t.id)),n)},yl=n(73343),yf=n(3379),yd=n.n(yf);function yh(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);nwindow.innerWidth?u-r.getBoundingClientRect().width-a:u+a,n=c+r.getBoundingClientRect().height+i>window.innerHeight?c-r.getBoundingClientRect().height-a:c+a,r.style.opacity=String(1),r.style.top="".concat(n,"px"),r.style.left="".concat(t,"px"),r.style.zIndex=String(1)}},h=function(e){var t=document.getElementById("tooltip-d3-chart-".concat(e));t&&(t.style.opacity=String(0),t.style.zIndex=String(-1))};return l.createElement("div",{style:{fontFamily:"sans-serif",fontWeight:"normal"}},l.createElement(yu.kJ,{id:"task-list-graph-d3",data:i,config:s,onMouseOverNode:d,onMouseOutNode:h},"D3 chart"),n.map(function(e){return l.createElement("div",{key:"d3-tooltip-key-".concat(e.id),id:"tooltip-d3-chart-".concat(e.id),style:{position:"absolute",opacity:"0",border:"1px solid rgba(0, 0, 0, 0.1)",padding:yl.r.spacing.unit,background:"white",borderRadius:5,zIndex:-1,inlineSize:"min-content"}},l.createElement(yc,{data:e}))}))};function yw(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);nyA&&l.createElement("div",{className:t.runDetails},l.createElement(o1.Z,{href:"/jobs/".concat(n.id,"/runs"),component:tz},"View more")))),l.createElement(d.Z,{item:!0,xs:12,sm:6},l.createElement(yO,{observationSource:n.observationSource})))});function yI(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&void 0!==arguments[0]?arguments[0]:"";try{return vb.parse(e),!0}catch(t){return!1}})}),wR=function(e){var t=e.initialValues,n=e.onSubmit,r=e.onTOMLChange;return l.createElement(hb,{initialValues:t,validationSchema:wP,onSubmit:n},function(e){var t=e.isSubmitting,n=e.values;return r&&r(n.toml),l.createElement(hx,{"data-testid":"job-form",noValidate:!0},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12},l.createElement(hk,{component:hB,id:"toml",name:"toml",label:"Job Spec (TOML)",required:!0,fullWidth:!0,multiline:!0,rows:10,rowsMax:25,variant:"outlined",autoComplete:"off",FormHelperTextProps:{"data-testid":"toml-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(of.default,{variant:"contained",color:"primary",type:"submit",disabled:t,size:"large"},"Create Job"))))})},wj=n(50109),wF="persistSpec";function wY(e){var t=e.query,n=new URLSearchParams(t).get("definition");return n?(wj.t8(wF,n),{toml:n}):{toml:wj.U2(wF)||""}}var wB=function(e){var t=e.onSubmit,n=e.onTOMLChange,r=wY({query:(0,h.TH)().search}),i=function(e){var t=e.replace(/[\u200B-\u200D\uFEFF]/g,"");wj.t8("".concat(wF),t),n&&n(t)};return l.createElement(r5.Z,null,l.createElement(o7.Z,{title:"New Job"}),l.createElement(aD.Z,null,l.createElement(wR,{initialValues:r,onSubmit:t,onTOMLChange:i})))};function wU(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n1&&void 0!==arguments[1]?arguments[1]:{},n=t.start,r=void 0===n?6:n,i=t.end,a=void 0===i?4:i;return e.substring(0,r)+"..."+e.substring(e.length-a)}function _w(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(_Y,e)},_U=function(){var e=_B({fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error,i=e.refetch;return l.createElement(_N,{loading:n,data:t,errorMsg:null==r?void 0:r.message,refetch:i})},_H=function(e){var t=e.chainKey,n=e.fields;return l.createElement(ir.Z,{hover:!0},n.map(function(e,n){return l.createElement(r7.default,{key:n},l.createElement(x.default,{variant:"body1"},t[e.key]," ",e.copy&&l.createElement(_v,{data:t[e.key]})))}))},_$=function(e){var t,n,r,i=e.schema,a=e.data,o=e.errorMsg,s=e.loading,u=e.onCreate;return l.createElement(r5.Z,null,l.createElement(o7.Z,{action:(null==a?void 0:null===(t=a.results)||void 0===t?void 0:t.length)===0&&l.createElement(of.default,{variant:"outlined",color:"primary",onClick:u},"New Key"),title:"".concat(i.title," Keys"),subheader:"Manage your ".concat(i.title," Keys")}),l.createElement(r8.Z,null,l.createElement(ie.Z,null,i.fields.map(function(e,t){return l.createElement(r7.default,{key:t},e.label)})),l.createElement(r9.Z,null,l.createElement(gD,{visible:s}),l.createElement(gN,{visible:(null==a?void 0:null===(n=a.results)||void 0===n?void 0:n.length)===0}),l.createElement(gC,{msg:o}),null==a?void 0:null===(r=a.results)||void 0===r?void 0:r.map(function(e,t){return l.createElement(_H,{chainKey:e,fields:i.fields,key:t})}))))};function _z(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function _G(){var e=_z(["\n fragment AptosKeysPayload_ResultsFields on AptosKey {\n account\n id\n }\n"]);return _G=function(){return e},e}function _W(){var e=_z(["\n fragment SolanaKeysPayload_ResultsFields on SolanaKey {\n id\n }\n"]);return _W=function(){return e},e}function _K(){var e=_z(["\n fragment StarknetKeysPayload_ResultsFields on StarkNetKey {\n id\n }\n"]);return _K=function(){return e},e}function _V(){var e=_z(["\n fragment TronKeysPayload_ResultsFields on TronKey {\n id\n }\n"]);return _V=function(){return e},e}function _q(){var e=_z(["\n ","\n ","\n ","\n ","\n query FetchNonEvmKeys {\n aptosKeys {\n results {\n ...AptosKeysPayload_ResultsFields\n }\n }\n solanaKeys {\n results {\n ...SolanaKeysPayload_ResultsFields\n }\n }\n starknetKeys {\n results {\n ...StarknetKeysPayload_ResultsFields\n }\n }\n tronKeys {\n results {\n ...TronKeysPayload_ResultsFields\n }\n }\n }\n"]);return _q=function(){return e},e}var _Z=n0(_G()),_X=n0(_W()),_J=n0(_K()),_Q=n0(_V()),_1=n0(_q(),_Z,_X,_J,_Q),_0=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return rv(_1,e)};function _2(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&l.createElement(_$,{loading:r,schema:Et[o]||{title:o,fields:[{label:"Public Key",key:"id",copy:!0}]},data:s,errorMsg:null==i?void 0:i.message,onCreate:a,key:o})}))},Er=function(e){var t=e.csaKey;return l.createElement(ir.Z,{hover:!0},l.createElement(r7.default,null,l.createElement(x.default,{variant:"body1"},t.publicKey," ",l.createElement(_v,{data:t.publicKey}))))};function Ei(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function Ea(){var e=Ei(["\n fragment CSAKeysPayload_ResultsFields on CSAKey {\n id\n publicKey\n }\n"]);return Ea=function(){return e},e}var Eo=n0(Ea()),Es=function(e){var t,n,r,i=e.data,a=e.errorMsg,o=e.loading,s=e.onCreate;return l.createElement(r5.Z,null,l.createElement(o7.Z,{action:(null===(t=null==i?void 0:i.csaKeys.results)||void 0===t?void 0:t.length)===0&&l.createElement(of.default,{variant:"outlined",color:"primary",onClick:s},"New CSA Key"),title:"CSA Key",subheader:"Manage your CSA Key"}),l.createElement(r8.Z,null,l.createElement(ie.Z,null,l.createElement(ir.Z,null,l.createElement(r7.default,null,"Public Key"))),l.createElement(r9.Z,null,l.createElement(gD,{visible:o}),l.createElement(gN,{visible:(null===(n=null==i?void 0:i.csaKeys.results)||void 0===n?void 0:n.length)===0}),l.createElement(gC,{msg:a}),null===(r=null==i?void 0:i.csaKeys.results)||void 0===r?void 0:r.map(function(e,t){return l.createElement(Er,{csaKey:e,key:t})}))))};function Eu(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(EG,e)};function EK(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(So,e)},Sf=function(){return a3(Ss)},Sd=function(){return a3(Su)},Sh=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return rv(Sc,e)};function Sp(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(kt,e)};function kr(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function xn(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}var xr=function(e){var t=e.run,n=l.useMemo(function(){var e=t.inputs,n=t.outputs,r=t.taskRuns,i=xt(t,["inputs","outputs","taskRuns"]),a={};try{a=JSON.parse(e)}catch(o){a={}}return xe(k9({},i),{inputs:a,outputs:n,taskRuns:r})},[t]);return l.createElement(r5.Z,null,l.createElement(aD.Z,null,l.createElement(k5,{object:n})))};function xi(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function xa(e){for(var t=1;t0&&l.createElement(k_,{errors:t.allErrors})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(h.rs,null,l.createElement(h.AW,{path:"".concat(n,"/json")},l.createElement(xr,{run:t})),l.createElement(h.AW,{path:n},t.taskRuns.length>0&&l.createElement(kJ,{taskRuns:t.taskRuns,observationSource:t.job.observationSource}))))))))};function xp(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xb(){var e=xp(["\n ","\n query FetchJobRun($id: ID!) {\n jobRun(id: $id) {\n __typename\n ... on JobRun {\n ...JobRunPayload_Fields\n }\n ... on NotFoundError {\n message\n }\n }\n }\n"]);return xb=function(){return e},e}var xm=n0(xb(),xd),xg=function(){var e=rv(xm,{variables:{id:(0,h.UO)().id}}),t=e.data,n=e.loading,r=e.error;if(n)return l.createElement(iR,null);if(r)return l.createElement(iD,{error:r});var i=null==t?void 0:t.jobRun;switch(null==i?void 0:i.__typename){case"JobRun":return l.createElement(xh,{run:i});case"NotFoundError":return l.createElement(a2,null);default:return null}};function xv(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xy(){var e=xv(["\n fragment JobRunsPayload_ResultsFields on JobRun {\n id\n allErrors\n createdAt\n finishedAt\n status\n job {\n id\n }\n }\n"]);return xy=function(){return e},e}var xw=n0(xy()),x_=function(e){var t=e.loading,n=e.data,r=e.page,i=e.pageSize,a=(0,h.k6)(),o=l.useMemo(function(){return null==n?void 0:n.jobRuns.results.map(function(e){var t,n=e.allErrors,r=e.id,i=e.createdAt;return{id:r,createdAt:i,errors:n,finishedAt:e.finishedAt,status:e.status}})},[n]);return l.createElement(ig,null,l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:12},l.createElement(iy,null,"Job Runs")),t&&l.createElement(iR,null),n&&o&&l.createElement(d.Z,{item:!0,xs:12},l.createElement(r5.Z,null,l.createElement(yi,{runs:o}),l.createElement(it.Z,{component:"div",count:n.jobRuns.metadata.total,rowsPerPage:i,rowsPerPageOptions:[i],page:r-1,onChangePage:function(e,t){a.push("/runs?page=".concat(t+1,"&per=").concat(i))},onChangeRowsPerPage:function(){},backIconButtonProps:{"aria-label":"prev-page"},nextIconButtonProps:{"aria-label":"next-page"}})))))};function xE(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xS(){var e=xE(["\n ","\n query FetchJobRuns($offset: Int, $limit: Int) {\n jobRuns(offset: $offset, limit: $limit) {\n results {\n ...JobRunsPayload_ResultsFields\n }\n metadata {\n total\n }\n }\n }\n"]);return xS=function(){return e},e}var xk=n0(xS(),xw),xx=function(){var e=ij(),t=parseInt(e.get("page")||"1",10),n=parseInt(e.get("per")||"25",10),r=rv(xk,{variables:{offset:(t-1)*n,limit:n},fetchPolicy:"cache-and-network"}),i=r.data,a=r.loading,o=r.error;return o?l.createElement(iD,{error:o}):l.createElement(x_,{loading:a,data:i,page:t,pageSize:n})},xT=function(){var e=(0,h.$B)().path;return l.createElement(h.rs,null,l.createElement(h.AW,{exact:!0,path:e},l.createElement(xx,null)),l.createElement(h.AW,{path:"".concat(e,"/:id")},l.createElement(xg,null)))};function xM(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xO(){var e=xM(["\n fragment FetchFeedsManagersPayload_ResultsFields on FeedsManager {\n __typename\n id\n name\n uri\n publicKey\n isConnectionActive\n createdAt\n disabledAt\n }\n query FetchFeedsManagers {\n feedsManagers {\n results {\n ...FetchFeedsManagersPayload_ResultsFields\n }\n }\n }\n"]);return xO=function(){return e},e}var xA=n0(xO()),xL=function(e){return rv(xA,e)},xC=n(47559),xI=n(83165),xD=n(47298),xN=n(81395),xP=function(){return(0,b.createStyles)({root:{display:"flex"},activeIcon:{color:xC.default[500]},inactiveIcon:{color:xI.default[500]},text:{marginLeft:4}})},xR=(0,b.withStyles)(xP)(function(e){var t=e.isActive,n=e.activeText,r=e.inactiveText,i=e.classes;return l.createElement("div",{className:i.root},t?l.createElement(xN.Z,{fontSize:"small",className:i.activeIcon}):l.createElement(xD.Z,{fontSize:"small",className:i.inactiveIcon}),l.createElement(x.default,{variant:"body1",inline:!0,className:i.text},t?n:r))}),xj=(0,b.withStyles)(iu)(function(e){var t=e.jobDistributor,n=e.classes;return l.createElement(ir.Z,{className:n.row,hover:!0},l.createElement(r7.default,{className:n.cell,component:"th",scope:"row"},l.createElement(ih,{className:n.link,href:"/job_distributors/".concat(t.id)},t.name)),l.createElement(r7.default,null,l.createElement(xR,{isActive:t.isConnectionActive,activeText:"Connected",inactiveText:"Disconnected"})),l.createElement(r7.default,null,l.createElement(xR,{isActive:!t.disabledAt,activeText:"Enabled",inactiveText:"Disabled"})),l.createElement(r7.default,null,_y(t.publicKey,{start:6,end:6}),l.createElement(_v,{data:t.publicKey})),l.createElement(r7.default,null,t.uri))}),xF=function(e){var t=e.jobDistributors;return l.createElement(ig,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:9},l.createElement(iy,null,"Job Distributors")),l.createElement(d.Z,{item:!0,xs:3},l.createElement(d.Z,{container:!0,justify:"flex-end"},l.createElement(d.Z,{item:!0},l.createElement(o1.Z,{variant:"secondary",component:tz,href:"/job_distributors/new"},"New Job Distributor")))),l.createElement(d.Z,{item:!0,xs:12},l.createElement(r5.Z,null,l.createElement(r8.Z,null,l.createElement(ie.Z,null,l.createElement(ir.Z,null,l.createElement(r7.default,null,"Name"),l.createElement(r7.default,null,"Connection Status"),l.createElement(r7.default,null,"Status"),l.createElement(r7.default,null,"CSA Public Key"),l.createElement(r7.default,null,"RPC URL"))),l.createElement(r9.Z,null,0===t.length&&l.createElement(ir.Z,null,l.createElement(r7.default,{component:"th",scope:"row",colSpan:3},"Job Distributors have not been registered")),t.map(function(e){return l.createElement(xj,{key:e.id,jobDistributor:e})})))))))},xY=function(){var e,t=xL({fetchPolicy:"cache-and-network"}),n=t.data,r=t.loading,i=t.error;return r?l.createElement(iR,null):i?l.createElement(iD,{error:i}):l.createElement(xF,{jobDistributors:null!==(e=null==n?void 0:n.feedsManagers.results)&&void 0!==e?e:[]})},xB=bs().shape({name:pz().required("Required"),uri:pz().required("Required"),publicKey:pz().required("Required")}),xU=function(e){var t=e.initialValues,n=e.onSubmit;return l.createElement(hb,{initialValues:t,validationSchema:xB,onSubmit:n},function(e){var t=e.isSubmitting,n=e.submitForm;return l.createElement(hx,{"data-testid":"feeds-manager-form"},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hk,{component:hB,id:"name",name:"name",label:"Name",required:!0,fullWidth:!0,FormHelperTextProps:{"data-testid":"name-helper-text"}})),l.createElement(d.Z,{item:!0,xs:!1,md:6}),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hk,{component:hB,id:"uri",name:"uri",label:"URI",required:!0,fullWidth:!0,helperText:"Provided by the Job Distributor operator",FormHelperTextProps:{"data-testid":"uri-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hk,{component:hB,id:"publicKey",name:"publicKey",label:"Public Key",required:!0,fullWidth:!0,helperText:"Provided by the Job Distributor operator",FormHelperTextProps:{"data-testid":"publicKey-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(of.default,{variant:"contained",color:"primary",disabled:t,onClick:n},"Submit"))))})},xH=function(e){var t=e.data,n=e.onSubmit,r={name:t.name,uri:t.uri,publicKey:t.publicKey};return l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12,md:11,lg:9},l.createElement(r5.Z,null,l.createElement(o7.Z,{title:"Edit Job Distributor"}),l.createElement(aD.Z,null,l.createElement(xU,{initialValues:r,onSubmit:n})))))};function x$(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(Ti,e)},To=function(){return(0,b.createStyles)({root:{fontSize:24}})},Ts=(0,b.withStyles)(To)(function(e){var t=e.children,n=e.classes;return l.createElement(x.default,{variant:"h2",className:n.root},t)}),Tu=n(9290),Tc=n(74923);function Tl(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function Tz(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}function TG(e,t){return TR(e)||TB(e,t)||TK(e,t)||TU()}function TW(e){return Tj(e)||TY(e)||TK(e)||TH()}function TK(e,t){if(e){if("string"==typeof e)return TP(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(n);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return TP(e,t)}}var TV=function(e){return"STARKNET"===e},Tq=bs().shape({chainID:pz().required("Required"),chainType:pz().required("Required"),accountAddr:pz().required("Required"),accountAddrPubKey:pz().nullable(),adminAddr:pz(),ocr1Multiaddr:pz().when(["ocr1Enabled","ocr1IsBootstrap"],{is:function(e,t){return e&&t},then:pz().required("Required").nullable()}).nullable(),ocr1P2PPeerID:pz().when(["ocr1Enabled","ocr1IsBootstrap"],{is:function(e,t){return e&&!t},then:pz().required("Required").nullable()}).nullable(),ocr1KeyBundleID:pz().when(["ocr1Enabled","ocr1IsBootstrap"],{is:function(e,t){return e&&!t},then:pz().required("Required").nullable()}).nullable(),ocr2Multiaddr:pz().when(["ocr2Enabled","ocr2IsBootstrap"],{is:function(e,t){return e&&t},then:pz().required("Required").nullable()}).nullable(),ocr2P2PPeerID:pz().when(["ocr2Enabled","ocr2IsBootstrap"],{is:function(e,t){return e&&!t},then:pz().required("Required").nullable()}).nullable(),ocr2KeyBundleID:pz().when(["ocr2Enabled","ocr2IsBootstrap"],{is:function(e,t){return e&&!t},then:pz().required("Required").nullable()}).nullable(),ocr2CommitPluginEnabled:pj().required("Required"),ocr2ExecutePluginEnabled:pj().required("Required"),ocr2MedianPluginEnabled:pj().required("Required"),ocr2MercuryPluginEnabled:pj().required("Required"),ocr2ForwarderAddress:pz().nullable()}),TZ=function(e){return(0,b.createStyles)({supportedJobOptionsPaper:{padding:2*e.spacing.unit}})},TX=function(e){var t=e.addresses,n=T$(e,["addresses"]),r=hl(),i=r.values,a=i.chainID,o=i.chainType,s=i.accountAddr,u=r.setFieldValue,c=TG(l.useState(!1),2),f=c[0],d=c[1],h=l.useRef();l.useEffect(function(){h.current=a},[a]),l.useEffect(function(){a!==h.current&&(u(n.name,""),d(!1))},[a,u,n.name]);var p=function(e){var t=e.target.value;"custom"===t?(d(!0),u(n.name,"")):(d(!1),u(n.name,t))};return l.createElement(l.Fragment,null,!TV(o)&&l.createElement(hk,TF({},n,{select:!0,value:f?"custom":s,onChange:p}),t.map(function(e){return l.createElement(tE.default,{key:e,value:e},e)})),TV(o)&&l.createElement(hk,{component:hB,id:"accountAddr",name:"accountAddr",label:"Enter your account address",inputProps:{"data-testid":"customAccountAddr-input"},helperText:"The account address used for this chain",required:!0,fullWidth:!0}),TV(o)&&l.createElement("div",null,l.createElement(hk,{component:hB,id:"accountAddrPubKey",name:"accountAddrPubKey",label:"Account Address Public Key",required:!0,fullWidth:!0,helperText:"The public key for your account address",FormHelperTextProps:{"data-testid":"accountAddrPubKey-helper-text"}})))},TJ=(0,b.withStyles)(TZ)(function(e){var t=e.classes,n=e.editing,r=void 0!==n&&n,i=e.innerRef,a=e.initialValues,o=e.onSubmit,s=e.chains,u=void 0===s?[]:s,c=e.accountsEVM,f=void 0===c?[]:c,h=e.accountsNonEvm,p=e.p2pKeys,b=void 0===p?[]:p,m=e.ocrKeys,g=void 0===m?[]:m,v=e.ocr2Keys,y=void 0===v?[]:v,w=e.showSubmit,_=void 0!==w&&w,E=TW(y).sort(function(e,t){var n,r,i;return e.chainType===t.chainType?e.id.localeCompare(t.id):null!==(i=null===(n=e.chainType)||void 0===n?void 0:n.localeCompare(null!==(r=t.chainType)&&void 0!==r?r:""))&&void 0!==i?i:0});return l.createElement(hb,{innerRef:i,initialValues:a,validationSchema:Tq,onSubmit:o},function(e){var n,i,a,o=e.values,s=[];switch(o.chainType){case TN.EVM:s=f.filter(function(e){return e.chain.id==o.chainID&&!e.isDisabled}).map(function(e){return e.address});break;case TN.APTOS:s=null!==(n=null==h?void 0:h.aptosKeys.results.map(function(e){return e.account}))&&void 0!==n?n:[];break;case TN.SOLANA:s=null!==(i=null==h?void 0:h.solanaKeys.results.map(function(e){return e.id}))&&void 0!==i?i:[];break;case TN.TRON:s=null!==(a=null==h?void 0:h.tronKeys.results.map(function(e){return e.id}))&&void 0!==a?a:[];break;default:s=[]}var c=u.filter(function(e){return e.network.toUpperCase()===o.chainType});return l.createElement(hx,{"data-testid":"feeds-manager-form",id:"chain-configuration-form",noValidate:!0},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hk,{component:hB,id:"chainType",name:"chainType",label:"Chain Type",select:!0,required:!0,fullWidth:!0,disabled:r},l.createElement(tE.default,{key:TN.EVM,value:TN.EVM},"EVM"),l.createElement(tE.default,{key:TN.APTOS,value:TN.APTOS},"APTOS"),l.createElement(tE.default,{key:TN.SOLANA,value:TN.SOLANA},"SOLANA"),l.createElement(tE.default,{key:TN.TRON,value:TN.TRON},"TRON"))),l.createElement(d.Z,{item:!0,xs:12,md:6},c.length>0&&!r?l.createElement(hk,{component:hB,id:"chainID",name:"chainID",label:"Chain ID",required:!0,fullWidth:!0,select:!0,disabled:r,inputProps:{"data-testid":"chainID-input"},FormHelperTextProps:{"data-testid":"chainID-helper-text"}},c.map(function(e){return l.createElement(tE.default,{key:e.id,value:e.id},e.id)})):l.createElement(hk,{component:hB,id:"chainID",name:"chainID",label:"Chain ID",required:!0,fullWidth:!0,disabled:r,inputProps:{"data-testid":"chainID-manual-input"},FormHelperTextProps:{"data-testid":"chainID-helper-manual-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:6},s.length>0?l.createElement(TX,{component:hB,id:"accountAddr",name:"accountAddr",label:"Account Address",inputProps:{"data-testid":"accountAddr-input"},required:!0,fullWidth:!0,select:!0,helperText:"The account address used for this chain",addresses:s,FormHelperTextProps:{"data-testid":"accountAddr-helper-text"}}):l.createElement(hk,{component:hB,id:"accountAddr",name:"accountAddr",label:"Account Address",inputProps:{"data-testid":"accountAddr-manual-input"},required:!0,fullWidth:!0,helperText:"The account address used for this chain",FormHelperTextProps:{"data-testid":"accountAddr-helper-manual-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hk,{component:hB,id:"adminAddr",name:"adminAddr",label:"Admin Address",fullWidth:!0,helperText:"The address used for LINK payments",FormHelperTextProps:{"data-testid":"adminAddr-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(x.default,null,"Supported Job Types")),l.createElement(d.Z,{item:!0,xs:12},l.createElement(hk,{component:hG,name:"fluxMonitorEnabled",type:"checkbox",Label:{label:"Flux Monitor"}})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(hk,{component:hG,name:"ocr1Enabled",type:"checkbox",Label:{label:"OCR"}}),o.ocr1Enabled&&l.createElement(ii.default,{className:t.supportedJobOptionsPaper},l.createElement(d.Z,{container:!0,spacing:8},l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12},l.createElement(hk,{component:hG,name:"ocr1IsBootstrap",type:"checkbox",Label:{label:"Is this node running as a bootstrap peer?"}})),o.ocr1IsBootstrap?l.createElement(d.Z,{item:!0,xs:12},l.createElement(hk,{component:hB,id:"ocr1Multiaddr",name:"ocr1Multiaddr",label:"Multiaddr",required:!0,fullWidth:!0,helperText:"The OCR Multiaddr which oracles use to query for network information",FormHelperTextProps:{"data-testid":"ocr1Multiaddr-helper-text"}})):l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hk,{component:hB,id:"ocr1P2PPeerID",name:"ocr1P2PPeerID",label:"Peer ID",select:!0,required:!0,fullWidth:!0,helperText:"The Peer ID used for this chain",FormHelperTextProps:{"data-testid":"ocr1P2PPeerID-helper-text"}},b.map(function(e){return l.createElement(tE.default,{key:e.peerID,value:e.peerID},e.peerID)}))),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hk,{component:hB,id:"ocr1KeyBundleID",name:"ocr1KeyBundleID",label:"Key Bundle ID",select:!0,required:!0,fullWidth:!0,helperText:"The OCR Key Bundle ID used for this chain",FormHelperTextProps:{"data-testid":"ocr1KeyBundleID-helper-text"}},g.map(function(e){return l.createElement(tE.default,{key:e.id,value:e.id},e.id)})))))))),l.createElement(d.Z,{item:!0,xs:12},l.createElement(hk,{component:hG,name:"ocr2Enabled",type:"checkbox",Label:{label:"OCR2"}}),o.ocr2Enabled&&l.createElement(ii.default,{className:t.supportedJobOptionsPaper},l.createElement(d.Z,{container:!0,spacing:8},l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12},l.createElement(hk,{component:hG,name:"ocr2IsBootstrap",type:"checkbox",Label:{label:"Is this node running as a bootstrap peer?"}})),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hk,{component:hB,id:"ocr2P2PPeerID",name:"ocr2P2PPeerID",label:"Peer ID",select:!0,required:!o.ocr2IsBootstrap,fullWidth:!0,helperText:"The Peer ID used for this chain",FormHelperTextProps:{"data-testid":"ocr2P2PPeerID-helper-text"}},b.map(function(e){return l.createElement(tE.default,{key:e.peerID,value:e.peerID},e.peerID)}))),o.ocr2IsBootstrap?l.createElement(d.Z,{item:!0,xs:12},l.createElement(hk,{component:hB,id:"ocr2Multiaddr",name:"ocr2Multiaddr",label:"Multiaddr",required:!0,fullWidth:!0,helperText:"The OCR2 Multiaddr which oracles use to query for network information",FormHelperTextProps:{"data-testid":"ocr2Multiaddr-helper-text"}})):l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hk,{component:hB,id:"ocr2KeyBundleID",name:"ocr2KeyBundleID",label:"Key Bundle ID",select:!0,required:!0,fullWidth:!0,helperText:"The OCR2 Key Bundle ID used for this chain",FormHelperTextProps:{"data-testid":"ocr2KeyBundleID-helper-text"}},E.map(function(e){return l.createElement(tE.default,{key:e.id,value:e.id},e.id," (",e.chainType,")")}))),l.createElement(d.Z,{item:!0,xs:12},l.createElement(x.default,null,"Supported Plugins")),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hk,{component:hG,name:"ocr2CommitPluginEnabled",type:"checkbox",Label:{label:"Commit"}})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hk,{component:hG,name:"ocr2ExecutePluginEnabled",type:"checkbox",Label:{label:"Execute"}})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hk,{component:hG,name:"ocr2RebalancerPluginEnabled",type:"checkbox",Label:{label:"Rebalancer"}})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hk,{component:hG,name:"ocr2MedianPluginEnabled",type:"checkbox",Label:{label:"Median"}})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hk,{component:hG,name:"ocr2MercuryPluginEnabled",type:"checkbox",Label:{label:"Mercury"}})),l.createElement(d.Z,{item:!0,xs:12,md:12},l.createElement(hk,{component:hB,id:"ocr2ForwarderAddress",name:"ocr2ForwarderAddress",label:"Forwarder Address (optional)",fullWidth:!0,helperText:"The forwarder address from the Operator Forwarder Contract",FormHelperTextProps:{"data-testid":"ocr2ForwarderAddress-helper-text"}}))))))),_&&l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(of.default,{variant:"contained",color:"primary",type:"submit",size:"large"},"Submit"))))})}),TQ=function(e){var t=e.onClose,n=e.open,r=e.onSubmit,i=l.useRef(),a=i$({fetchPolicy:"network-only"}).data,o=_B({fetchPolicy:"cache-and-network"}).data,s=_0({fetchPolicy:"cache-and-network"}).data,u=kn({fetchPolicy:"cache-and-network"}).data,c=EW({fetchPolicy:"cache-and-network"}).data,f=Sl({fetchPolicy:"cache-and-network"}).data,d={chainID:"",chainType:TN.EVM,accountAddr:"",adminAddr:"",accountAddrPubKey:"",fluxMonitorEnabled:!1,ocr1Enabled:!1,ocr1IsBootstrap:!1,ocr1Multiaddr:"",ocr1P2PPeerID:"",ocr1KeyBundleID:"",ocr2Enabled:!1,ocr2IsBootstrap:!1,ocr2Multiaddr:"",ocr2P2PPeerID:"",ocr2KeyBundleID:"",ocr2CommitPluginEnabled:!1,ocr2ExecutePluginEnabled:!1,ocr2MedianPluginEnabled:!1,ocr2MercuryPluginEnabled:!1,ocr2RebalancerPluginEnabled:!1,ocr2ForwarderAddress:""},h=a?a.chains.results:[],p=o?o.ethKeys.results:[],b=u?u.p2pKeys.results:[],m=c?c.ocrKeyBundles.results:[],g=f?f.ocr2KeyBundles.results:[];return l.createElement(od.Z,{onClose:t,open:n,disableBackdropClick:!0},l.createElement(om.Z,{disableTypography:!0},l.createElement(x.default,{variant:"body2"},"New Supported Chain")),l.createElement(op.Z,null,l.createElement(TJ,{innerRef:i,initialValues:d,onSubmit:r,chains:h,accountsEVM:p,accountsNonEvm:s,p2pKeys:b,ocrKeys:m,ocr2Keys:g})),l.createElement(oh.Z,null,l.createElement(of.default,{onClick:t},"Cancel"),l.createElement(of.default,{color:"primary",type:"submit",form:"chain-configuration-form",variant:"contained"},"Submit")))},T1=function(e){var t=e.cfg,n=e.onClose,r=e.open,i=e.onSubmit,a=l.useRef(),o=i$({fetchPolicy:"network-only"}).data,s=_B({fetchPolicy:"cache-and-network"}).data,u=_0({fetchPolicy:"cache-and-network"}).data,c=kn({fetchPolicy:"cache-and-network"}).data,f=EW({fetchPolicy:"cache-and-network"}).data,d=Sl({fetchPolicy:"cache-and-network"}).data;if(!t)return null;var h={chainID:t.chainID,chainType:t.chainType,accountAddr:t.accountAddr,adminAddr:t.adminAddr,accountAddrPubKey:t.accountAddrPubKey,fluxMonitorEnabled:t.fluxMonitorJobConfig.enabled,ocr1Enabled:t.ocr1JobConfig.enabled,ocr1IsBootstrap:t.ocr1JobConfig.isBootstrap,ocr1Multiaddr:t.ocr1JobConfig.multiaddr,ocr1P2PPeerID:t.ocr1JobConfig.p2pPeerID,ocr1KeyBundleID:t.ocr1JobConfig.keyBundleID,ocr2Enabled:t.ocr2JobConfig.enabled,ocr2IsBootstrap:t.ocr2JobConfig.isBootstrap,ocr2Multiaddr:t.ocr2JobConfig.multiaddr,ocr2P2PPeerID:t.ocr2JobConfig.p2pPeerID,ocr2KeyBundleID:t.ocr2JobConfig.keyBundleID,ocr2CommitPluginEnabled:t.ocr2JobConfig.plugins.commit,ocr2ExecutePluginEnabled:t.ocr2JobConfig.plugins.execute,ocr2MedianPluginEnabled:t.ocr2JobConfig.plugins.median,ocr2MercuryPluginEnabled:t.ocr2JobConfig.plugins.mercury,ocr2RebalancerPluginEnabled:t.ocr2JobConfig.plugins.rebalancer,ocr2ForwarderAddress:t.ocr2JobConfig.forwarderAddress},p=o?o.chains.results:[],b=s?s.ethKeys.results:[],m=c?c.p2pKeys.results:[],g=f?f.ocrKeyBundles.results:[],v=d?d.ocr2KeyBundles.results:[];return l.createElement(od.Z,{onClose:n,open:r,disableBackdropClick:!0},l.createElement(om.Z,{disableTypography:!0},l.createElement(x.default,{variant:"body2"},"Edit Supported Chain")),l.createElement(op.Z,null,l.createElement(TJ,{innerRef:a,initialValues:h,onSubmit:i,chains:p,accountsEVM:b,accountsNonEvm:u,p2pKeys:m,ocrKeys:g,ocr2Keys:v,editing:!0})),l.createElement(oh.Z,null,l.createElement(of.default,{onClick:n},"Cancel"),l.createElement(of.default,{color:"primary",type:"submit",form:"chain-configuration-form",variant:"contained"},"Submit")))};function T0(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);nt.version?e:t})},[o]),g=l.useMemo(function(){return Oe(o).sort(function(e,t){return t.version-e.version})},[o]),v=function(e,t,n){switch(e){case"PENDING":return l.createElement(l.Fragment,null,l.createElement(of.default,{variant:"text",color:"secondary",onClick:function(){return b("reject",t)}},"Reject"),m.id===t&&"DELETED"!==n.status&&"REVOKED"!==n.status&&l.createElement(of.default,{variant:"contained",color:"primary",onClick:function(){return b("approve",t)}},"Approve"),m.id===t&&"DELETED"===n.status&&n.pendingUpdate&&l.createElement(l.Fragment,null,l.createElement(of.default,{variant:"contained",color:"primary",onClick:function(){return b("cancel",t)}},"Cancel"),l.createElement(x.default,{color:"error"},"This proposal was deleted. Cancel the spec to delete any running jobs")));case"APPROVED":return l.createElement(l.Fragment,null,l.createElement(of.default,{variant:"contained",onClick:function(){return b("cancel",t)}},"Cancel"),"DELETED"===n.status&&n.pendingUpdate&&l.createElement(x.default,{color:"error"},"This proposal was deleted. Cancel the spec to delete any running jobs"));case"CANCELLED":if(m.id===t&&"DELETED"!==n.status&&"REVOKED"!==n.status)return l.createElement(of.default,{variant:"contained",color:"primary",onClick:function(){return b("approve",t)}},"Approve");return null;default:return null}};return l.createElement("div",null,g.map(function(e,n){return l.createElement(mx.Z,{defaultExpanded:0===n,key:n},l.createElement(mT.Z,{expandIcon:l.createElement(gr.Z,null)},l.createElement(x.default,{className:t.versionText},"Version ",e.version),l.createElement(Ex.Z,{label:e.status,color:"APPROVED"===e.status?"primary":"default",variant:"REJECTED"===e.status||"CANCELLED"===e.status?"outlined":"default"}),l.createElement("div",{className:t.proposedAtContainer},l.createElement(x.default,null,"Proposed ",l.createElement(aO,{tooltip:!0},e.createdAt)))),l.createElement(mM.Z,{className:t.expansionPanelDetails},l.createElement("div",{className:t.actions},l.createElement("div",{className:t.editContainer},0===n&&("PENDING"===e.status||"CANCELLED"===e.status)&&"DELETED"!==s.status&&"REVOKED"!==s.status&&l.createElement(of.default,{variant:"contained",onClick:function(){return p(!0)}},"Edit")),l.createElement("div",{className:t.actionsContainer},v(e.status,e.id,s))),l.createElement(gn,{language:"toml",style:m8,"data-testid":"codeblock"},e.definition)))}),l.createElement(oy,{open:null!=c,title:c?Oa[c.action].title:"",body:c?Oa[c.action].body:"",onConfirm:function(){if(c){switch(c.action){case"approve":n(c.id);break;case"cancel":r(c.id);break;case"reject":i(c.id)}f(null)}},cancelButtonText:"Cancel",onCancel:function(){return f(null)}}),l.createElement(M1,{open:h,onClose:function(){return p(!1)},initialValues:{definition:m.definition,id:m.id},onSubmit:a}))});function Os(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function Ou(){var e=Os(["\n ","\n fragment JobProposalPayloadFields on JobProposal {\n id\n externalJobID\n remoteUUID\n jobID\n specs {\n ...JobProposal_SpecsFields\n }\n status\n pendingUpdate\n }\n"]);return Ou=function(){return e},e}var Oc=n0(Ou(),Or),Ol=function(e){var t=e.onApprove,n=e.onCancel,r=e.onReject,i=e.onUpdateSpec,a=e.proposal;return l.createElement(ig,null,l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:9},l.createElement(iy,null,"Job Proposal #",a.id))),l.createElement(MV,{proposal:a}),l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:9},l.createElement(Ts,null,"Specs"))),l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:12},l.createElement(Oo,{proposal:a,specs:a.specs,onReject:r,onApprove:t,onCancel:n,onUpdateSpec:i}))))};function Of(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);nB,tA:()=>U,Iw:()=>W,DQ:()=>z,cB:()=>T,LO:()=>M,t5:()=>k,qt:()=>x,Jc:()=>C,L7:()=>F,EO:()=>Y});var r,i,a=n(66289),o=n(41800),s=n.n(o),u=n(67932);(i=r||(r={})).IN_PROGRESS="in_progress",i.PENDING_INCOMING_CONFIRMATIONS="pending_incoming_confirmations",i.PENDING_CONNECTION="pending_connection",i.PENDING_BRIDGE="pending_bridge",i.PENDING_SLEEP="pending_sleep",i.ERRORED="errored",i.COMPLETED="completed";var c=n(87013),l=n(19084),f=n(34823);function d(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]R,v2:()=>j});var r=n(66289);function i(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var a="/sessions",o="/sessions",s=function e(t){var n=this;i(this,e),this.api=t,this.createSession=function(e){return n.create(e)},this.destroySession=function(){return n.destroy()},this.create=this.api.createResource(a),this.destroy=this.api.deleteResource(o)};function u(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var c="/v2/bulk_delete_runs",l=function e(t){var n=this;u(this,e),this.api=t,this.bulkDeleteJobRuns=function(e){return n.destroy(e)},this.destroy=this.api.deleteResource(c)};function f(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var d="/v2/chains/:network",h=function e(t){var n=this;f(this,e),this.api=t,this.getChains=function(e){return n.index(void 0,{network:e})},this.index=this.api.fetchResource(d)};function p(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var b="/v2/keys/evm/chain",m=function e(t){var n=this;p(this,e),this.api=t,this.chain=function(e){var t=new URLSearchParams;t.append("address",e.address),t.append("evmChainID",e.evmChainID),null!==e.abandon&&t.append("abandon",String(e.abandon)),null!==e.enabled&&t.append("enabled",String(e.enabled));var r=b+"?"+t.toString();return n.api.createResource(r)()}};function g(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var v="/v2/jobs",y="".concat(v,"/:specId/runs"),w=function e(t){var n=this;g(this,e),this.api=t,this.createJobRunV2=function(e,t){return n.post(t,{specId:e})},this.post=this.api.createResource(y,!0)};function _(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var E="/v2/log",S=function e(t){var n=this;_(this,e),this.api=t,this.getLogConfig=function(){return n.show()},this.updateLogConfig=function(e){return n.update(e)},this.show=this.api.fetchResource(E),this.update=this.api.updateResource(E)};function k(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var x="/v2/nodes",T=function e(t){var n=this;k(this,e),this.api=t,this.getNodes=function(){return n.index()},this.createNode=function(e){return n.create(e)},this.index=this.api.fetchResource(x),this.create=this.api.createResource(x)};function M(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var O="/v2/enroll_webauthn",A=function e(t){var n=this;M(this,e),this.api=t,this.beginKeyRegistration=function(e){return n.create(e)},this.finishKeyRegistration=function(e){return n.put(e)},this.create=this.api.fetchResource(O),this.put=this.api.createResource(O)};function L(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var C="/v2/build_info",I=function e(t){var n=this;L(this,e),this.api=t,this.show=function(){return n.api.GET(C)()}};function D(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var N=function e(t){D(this,e),this.api=t,this.buildInfo=new I(this.api),this.bulkDeleteRuns=new l(this.api),this.chains=new h(this.api),this.logConfig=new S(this.api),this.nodes=new T(this.api),this.jobs=new w(this.api),this.webauthn=new A(this.api),this.evmKeys=new m(this.api)},P=new r.V0({base:void 0}),R=new s(P),j=new N(P)},1398(e,t,n){"use strict";n.d(t,{Z:()=>d});var r=n(67294),i=n(32316),a=n(83638),o=n(94184),s=n.n(o);function u(){return(u=Object.assign||function(e){for(var t=1;tc});var r=n(67294),i=n(32316);function a(){return(a=Object.assign||function(e){for(var t=1;tx,jK:()=>v});var r=n(67294),i=n(37703),a=n(45697),o=n.n(a),s=n(82204),u=n(71426),c=n(94184),l=n.n(c),f=n(32316),d=function(e){var t=e.palette.success||{},n=e.palette.warning||{};return{base:{paddingLeft:5*e.spacing.unit,paddingRight:5*e.spacing.unit},success:{backgroundColor:t.main,color:t.contrastText},error:{backgroundColor:e.palette.error.dark,color:e.palette.error.contrastText},warning:{backgroundColor:n.contrastText,color:n.main}}},h=function(e){var t,n=e.success,r=e.error,i=e.warning,a=e.classes,o=e.className;return n?t=a.success:r?t=a.error:i&&(t=a.warning),l()(a.base,o,t)},p=function(e){return r.createElement(s.Z,{className:h(e),square:!0},r.createElement(u.default,{variant:"body2",color:"inherit",component:"div"},e.children))};p.defaultProps={success:!1,error:!1,warning:!1},p.propTypes={success:o().bool,error:o().bool,warning:o().bool};let b=(0,f.withStyles)(d)(p);var m=function(){return r.createElement(r.Fragment,null,"Unhandled error. Please help us by opening a"," ",r.createElement("a",{href:"https://github.com/smartcontractkit/chainlink/issues/new"},"bug report"))};let g=m;function v(e){return"string"==typeof e?e:e.component?e.component(e.props):r.createElement(g,null)}function y(e,t){var n;return n="string"==typeof e?e:e.component?e.component(e.props):r.createElement(g,null),r.createElement("p",{key:t},n)}var w=function(e){var t=e.notifications;return r.createElement(b,{error:!0},t.map(y))},_=function(e){var t=e.notifications;return r.createElement(b,{success:!0},t.map(y))},E=function(e){var t=e.errors,n=e.successes;return r.createElement("div",null,(null==t?void 0:t.length)>0&&r.createElement(w,{notifications:t}),n.length>0&&r.createElement(_,{notifications:n}))},S=function(e){return{errors:e.notifications.errors,successes:e.notifications.successes}},k=(0,i.$j)(S)(E);let x=k},9409(e,t,n){"use strict";n.d(t,{ZP:()=>j});var r=n(67294),i=n(37703),a=n(5977),o=n(32316),s=n(1398),u=n(82204),c=n(30060),l=n(71426),f=n(60520),d=n(39814),h=n(57209),p=n(26842),b=n(3950),m=n(5536),g=n(45697),v=n.n(g);let y=n.p+"9f6d832ef97e8493764e.svg";function w(){return(w=Object.assign||function(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&_.map(function(e,t){return r.createElement(d.Z,{item:!0,xs:12,key:t},r.createElement(u.Z,{raised:!1,className:v.error},r.createElement(c.Z,null,r.createElement(l.default,{variant:"body1",className:v.errorText},(0,b.jK)(e)))))}),r.createElement(d.Z,{item:!0,xs:12},r.createElement(f.Z,{id:"email",label:"Email",margin:"normal",value:n,onChange:m("email"),error:_.length>0,variant:"outlined",fullWidth:!0})),r.createElement(d.Z,{item:!0,xs:12},r.createElement(f.Z,{id:"password",label:"Password",type:"password",autoComplete:"password",margin:"normal",value:h,onChange:m("password"),error:_.length>0,variant:"outlined",fullWidth:!0})),r.createElement(d.Z,{item:!0,xs:12},r.createElement(d.Z,{container:!0,spacing:0,justify:"center"},r.createElement(d.Z,{item:!0},r.createElement(s.Z,{type:"submit",variant:"primary"},"Access Account")))),y&&r.createElement(l.default,{variant:"body1",color:"textSecondary"},"Signing in...")))))))},P=function(e){return{fetching:e.authentication.fetching,authenticated:e.authentication.allowed,errors:e.notifications.errors}},R=(0,i.$j)(P,x({submitSignIn:p.L7}))(N);let j=(0,h.wU)(e)((0,o.withStyles)(D)(R))},16353(e,t,n){"use strict";n.d(t,{ZP:()=>H,rH:()=>U});var r,i=n(37703),a=n(97779),o=n(9541),s=n(19084);function u(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:h,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case s.Mk.RECEIVE_SIGNOUT_SUCCESS:case s.Mk.RECEIVE_SIGNIN_SUCCESS:var n={allowed:t.authenticated};return o.Ks(n),f(c({},e,n),{errors:[]});case s.Mk.RECEIVE_SIGNIN_FAIL:var r={allowed:!1};return o.Ks(r),f(c({},e,r),{errors:[]});case s.Mk.RECEIVE_SIGNIN_ERROR:case s.Mk.RECEIVE_SIGNOUT_ERROR:var i={allowed:!1};return o.Ks(i),f(c({},e,i),{errors:t.errors||[]});default:return e}};let b=p;function m(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function g(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:_,t=arguments.length>1?arguments[1]:void 0;return t.type?t.type.startsWith(r.REQUEST)?y(g({},e),{count:e.count+1}):t.type.startsWith(r.RECEIVE)?y(g({},e),{count:Math.max(e.count-1,0)}):t.type.startsWith(r.RESPONSE)?y(g({},e),{count:Math.max(e.count-1,0)}):t.type===s.di.REDIRECT?y(g({},e),{count:0}):e:e};let S=E;function k(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function x(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:O,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case s.di.MATCH_ROUTE:return M(x({},O),{currentUrl:t.pathname});case s.Ih.NOTIFY_SUCCESS:var n={component:t.component,props:t.props};return M(x({},e),{successes:[n],errors:[]});case s.Ih.NOTIFY_SUCCESS_MSG:return M(x({},e),{successes:[t.msg],errors:[]});case s.Ih.NOTIFY_ERROR:var r=t.error.errors,i=null==r?void 0:r.map(function(e){return L(t,e)});return M(x({},e),{successes:[],errors:i});case s.Ih.NOTIFY_ERROR_MSG:return M(x({},e),{successes:[],errors:[t.msg]});case s.Mk.RECEIVE_SIGNIN_FAIL:return M(x({},e),{successes:[],errors:["Your email or password is incorrect. Please try again"]});default:return e}};function L(e,t){return{component:e.component,props:{msg:t.detail}}}let C=A;function I(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function D(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:R,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case s.di.REDIRECT:return P(D({},e),{to:t.to});case s.di.MATCH_ROUTE:return P(D({},e),{to:void 0});default:return e}};let F=j;var Y=n(87013),B=(0,a.UY)({authentication:b,fetching:S,notifications:C,redirect:F,buildInfo:Y.Z});B(void 0,{type:"INITIAL_STATE"});var U=i.v9;let H=B},19084(e,t,n){"use strict";var r,i,a,o,s,u,c,l,f,d;n.d(t,{Ih:()=>i,Mk:()=>a,Y0:()=>s,di:()=>r,jp:()=>o}),n(67294),(u=r||(r={})).REDIRECT="REDIRECT",u.MATCH_ROUTE="MATCH_ROUTE",(c=i||(i={})).NOTIFY_SUCCESS="NOTIFY_SUCCESS",c.NOTIFY_SUCCESS_MSG="NOTIFY_SUCCESS_MSG",c.NOTIFY_ERROR="NOTIFY_ERROR",c.NOTIFY_ERROR_MSG="NOTIFY_ERROR_MSG",(l=a||(a={})).REQUEST_SIGNIN="REQUEST_SIGNIN",l.RECEIVE_SIGNIN_SUCCESS="RECEIVE_SIGNIN_SUCCESS",l.RECEIVE_SIGNIN_FAIL="RECEIVE_SIGNIN_FAIL",l.RECEIVE_SIGNIN_ERROR="RECEIVE_SIGNIN_ERROR",l.RECEIVE_SIGNOUT_SUCCESS="RECEIVE_SIGNOUT_SUCCESS",l.RECEIVE_SIGNOUT_ERROR="RECEIVE_SIGNOUT_ERROR",(f=o||(o={})).RECEIVE_CREATE_ERROR="RECEIVE_CREATE_ERROR",f.RECEIVE_CREATE_SUCCESS="RECEIVE_CREATE_SUCCESS",f.RECEIVE_DELETE_ERROR="RECEIVE_DELETE_ERROR",f.RECEIVE_DELETE_SUCCESS="RECEIVE_DELETE_SUCCESS",f.RECEIVE_UPDATE_ERROR="RECEIVE_UPDATE_ERROR",f.RECEIVE_UPDATE_SUCCESS="RECEIVE_UPDATE_SUCCESS",f.REQUEST_CREATE="REQUEST_CREATE",f.REQUEST_DELETE="REQUEST_DELETE",f.REQUEST_UPDATE="REQUEST_UPDATE",f.UPSERT_CONFIGURATION="UPSERT_CONFIGURATION",f.UPSERT_JOB_RUN="UPSERT_JOB_RUN",f.UPSERT_JOB_RUNS="UPSERT_JOB_RUNS",f.UPSERT_TRANSACTION="UPSERT_TRANSACTION",f.UPSERT_TRANSACTIONS="UPSERT_TRANSACTIONS",f.UPSERT_BUILD_INFO="UPSERT_BUILD_INFO",(d=s||(s={})).FETCH_BUILD_INFO_REQUESTED="FETCH_BUILD_INFO_REQUESTED",d.FETCH_BUILD_INFO_SUCCEEDED="FETCH_BUILD_INFO_SUCCEEDED",d.FETCH_BUILD_INFO_FAILED="FETCH_BUILD_INFO_FAILED"},87013(e,t,n){"use strict";n.d(t,{Y:()=>o,Z:()=>u});var r=n(19084);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:o,t=arguments.length>1?arguments[1]:void 0;return t.type===r.Y0.FETCH_BUILD_INFO_SUCCEEDED?a({},t.buildInfo):e};let u=s},34823(e,t,n){"use strict";n.d(t,{N:()=>r});var r=function(e){return e.buildInfo}},73343(e,t,n){"use strict";n.d(t,{r:()=>u});var r=n(19350),i=n(32316),a=n(59114),o=n(5324),s={props:{MuiGrid:{spacing:3*o.default.unit},MuiCardHeader:{titleTypographyProps:{color:"secondary"}}},palette:{action:{hoverOpacity:.3},primary:{light:"#E5F1FF",main:"#3c40c6",contrastText:"#fff"},secondary:{main:"#3d5170"},success:{light:"#e8faf1",main:r.ek.A700,dark:r.ek[700],contrastText:r.y0.white},warning:{light:"#FFFBF1",main:"#fff6b6",contrastText:"#fad27a"},error:{light:"#ffdada",main:"#f44336",dark:"#d32f2f",contrastText:"#fff"},background:{default:"#f5f6f8",appBar:"#3c40c6"},text:{primary:(0,a.darken)(r.BA.A700,.7),secondary:"#818ea3"},listPendingStatus:{background:"#fef7e5",color:"#fecb4c"},listCompletedStatus:{background:"#e9faf2",color:"#4ed495"}},shape:{borderRadius:o.default.unit},overrides:{MuiButton:{root:{borderRadius:o.default.unit/2,textTransform:"none"},sizeLarge:{padding:void 0,fontSize:void 0,paddingTop:o.default.unit,paddingBottom:o.default.unit,paddingLeft:5*o.default.unit,paddingRight:5*o.default.unit}},MuiTableCell:{body:{fontSize:"1rem"},head:{fontSize:"1rem",fontWeight:400}},MuiCardHeader:{root:{borderBottom:"1px solid rgba(0, 0, 0, 0.12)"},action:{marginTop:-2,marginRight:0,"& >*":{marginLeft:2*o.default.unit}},subheader:{marginTop:.5*o.default.unit}}},typography:{useNextVariants:!0,fontFamily:"-apple-system,BlinkMacSystemFont,Roboto,Helvetica,Arial,sans-serif",button:{textTransform:"none",fontSize:"1.2em"},body1:{fontSize:"1.0rem",fontWeight:400,lineHeight:"1.46429em",color:"rgba(0, 0, 0, 0.87)",letterSpacing:-.4},body2:{fontSize:"1.0rem",fontWeight:500,lineHeight:"1.71429em",color:"rgba(0, 0, 0, 0.87)",letterSpacing:-.4},body1Next:{color:"rgb(29, 29, 29)",fontWeight:400,fontSize:"1rem",lineHeight:1.5,letterSpacing:-.4},body2Next:{color:"rgb(29, 29, 29)",fontWeight:400,fontSize:"0.875rem",lineHeight:1.5,letterSpacing:-.4},display1:{color:"#818ea3",fontSize:"2.125rem",fontWeight:400,lineHeight:"1.20588em",letterSpacing:-.4},display2:{color:"#818ea3",fontSize:"2.8125rem",fontWeight:400,lineHeight:"1.13333em",marginLeft:"-.02em",letterSpacing:-.4},display3:{color:"#818ea3",fontSize:"3.5rem",fontWeight:400,lineHeight:"1.30357em",marginLeft:"-.02em",letterSpacing:-.4},display4:{fontSize:14,fontWeightLight:300,fontWeightMedium:500,fontWeightRegular:400,letterSpacing:-.4},h1:{color:"rgb(29, 29, 29)",fontSize:"6rem",fontWeight:300,lineHeight:1},h2:{color:"rgb(29, 29, 29)",fontSize:"3.75rem",fontWeight:300,lineHeight:1},h3:{color:"rgb(29, 29, 29)",fontSize:"3rem",fontWeight:400,lineHeight:1.04},h4:{color:"rgb(29, 29, 29)",fontSize:"2.125rem",fontWeight:400,lineHeight:1.17},h5:{color:"rgb(29, 29, 29)",fontSize:"1.5rem",fontWeight:400,lineHeight:1.33,letterSpacing:-.4},h6:{fontSize:"0.8rem",fontWeight:450,lineHeight:"1.71429em",color:"rgba(0, 0, 0, 0.87)",letterSpacing:-.4},subheading:{color:"rgb(29, 29, 29)",fontSize:"1rem",fontWeight:400,lineHeight:"1.5em",letterSpacing:-.4},subtitle1:{color:"rgb(29, 29, 29)",fontSize:"1rem",fontWeight:400,lineHeight:1.75,letterSpacing:-.4},subtitle2:{color:"rgb(29, 29, 29)",fontSize:"0.875rem",fontWeight:500,lineHeight:1.57,letterSpacing:-.4}},shadows:["none","0px 1px 3px 0px rgba(0, 0, 0, 0.1),0px 1px 1px 0px rgba(0, 0, 0, 0.04),0px 2px 1px -1px rgba(0, 0, 0, 0.02)","0px 1px 5px 0px rgba(0, 0, 0, 0.1),0px 2px 2px 0px rgba(0, 0, 0, 0.04),0px 3px 1px -2px rgba(0, 0, 0, 0.02)","0px 1px 8px 0px rgba(0, 0, 0, 0.1),0px 3px 4px 0px rgba(0, 0, 0, 0.04),0px 3px 3px -2px rgba(0, 0, 0, 0.02)","0px 2px 4px -1px rgba(0, 0, 0, 0.1),0px 4px 5px 0px rgba(0, 0, 0, 0.04),0px 1px 10px 0px rgba(0, 0, 0, 0.02)","0px 3px 5px -1px rgba(0, 0, 0, 0.1),0px 5px 8px 0px rgba(0, 0, 0, 0.04),0px 1px 14px 0px rgba(0, 0, 0, 0.02)","0px 3px 5px -1px rgba(0, 0, 0, 0.1),0px 6px 10px 0px rgba(0, 0, 0, 0.04),0px 1px 18px 0px rgba(0, 0, 0, 0.02)","0px 4px 5px -2px rgba(0, 0, 0, 0.1),0px 7px 10px 1px rgba(0, 0, 0, 0.04),0px 2px 16px 1px rgba(0, 0, 0, 0.02)","0px 5px 5px -3px rgba(0, 0, 0, 0.1),0px 8px 10px 1px rgba(0, 0, 0, 0.04),0px 3px 14px 2px rgba(0, 0, 0, 0.02)","0px 5px 6px -3px rgba(0, 0, 0, 0.1),0px 9px 12px 1px rgba(0, 0, 0, 0.04),0px 3px 16px 2px rgba(0, 0, 0, 0.02)","0px 6px 6px -3px rgba(0, 0, 0, 0.1),0px 10px 14px 1px rgba(0, 0, 0, 0.04),0px 4px 18px 3px rgba(0, 0, 0, 0.02)","0px 6px 7px -4px rgba(0, 0, 0, 0.1),0px 11px 15px 1px rgba(0, 0, 0, 0.04),0px 4px 20px 3px rgba(0, 0, 0, 0.02)","0px 7px 8px -4px rgba(0, 0, 0, 0.1),0px 12px 17px 2px rgba(0, 0, 0, 0.04),0px 5px 22px 4px rgba(0, 0, 0, 0.02)","0px 7px 8px -4px rgba(0, 0, 0, 0.1),0px 13px 19px 2px rgba(0, 0, 0, 0.04),0px 5px 24px 4px rgba(0, 0, 0, 0.02)","0px 7px 9px -4px rgba(0, 0, 0, 0.1),0px 14px 21px 2px rgba(0, 0, 0, 0.04),0px 5px 26px 4px rgba(0, 0, 0, 0.02)","0px 8px 9px -5px rgba(0, 0, 0, 0.1),0px 15px 22px 2px rgba(0, 0, 0, 0.04),0px 6px 28px 5px rgba(0, 0, 0, 0.02)","0px 8px 10px -5px rgba(0, 0, 0, 0.1),0px 16px 24px 2px rgba(0, 0, 0, 0.04),0px 6px 30px 5px rgba(0, 0, 0, 0.02)","0px 8px 11px -5px rgba(0, 0, 0, 0.1),0px 17px 26px 2px rgba(0, 0, 0, 0.04),0px 6px 32px 5px rgba(0, 0, 0, 0.02)","0px 9px 11px -5px rgba(0, 0, 0, 0.1),0px 18px 28px 2px rgba(0, 0, 0, 0.04),0px 7px 34px 6px rgba(0, 0, 0, 0.02)","0px 9px 12px -6px rgba(0, 0, 0, 0.1),0px 19px 29px 2px rgba(0, 0, 0, 0.04),0px 7px 36px 6px rgba(0, 0, 0, 0.02)","0px 10px 13px -6px rgba(0, 0, 0, 0.1),0px 20px 31px 3px rgba(0, 0, 0, 0.04),0px 8px 38px 7px rgba(0, 0, 0, 0.02)","0px 10px 13px -6px rgba(0, 0, 0, 0.1),0px 21px 33px 3px rgba(0, 0, 0, 0.04),0px 8px 40px 7px rgba(0, 0, 0, 0.02)","0px 10px 14px -6px rgba(0, 0, 0, 0.1),0px 22px 35px 3px rgba(0, 0, 0, 0.04),0px 8px 42px 7px rgba(0, 0, 0, 0.02)","0px 11px 14px -7px rgba(0, 0, 0, 0.1),0px 23px 36px 3px rgba(0, 0, 0, 0.04),0px 9px 44px 8px rgba(0, 0, 0, 0.02)","0px 11px 15px -7px rgba(0, 0, 0, 0.1),0px 24px 38px 3px rgba(0, 0, 0, 0.04),0px 9px 46px 8px rgba(0, 0, 0, 0.02)",]},u=(0,i.createMuiTheme)(s)},66289(e,t,n){"use strict";function r(e){if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function i(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}function a(){if("undefined"==typeof Reflect||!Reflect.construct||Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch(e){return!1}}function o(e,t,n){return(o=a()?Reflect.construct:function(e,t,n){var r=[null];r.push.apply(r,t);var i=new(Function.bind.apply(e,r));return n&&f(i,n.prototype),i}).apply(null,arguments)}function s(e){return(s=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function u(e,t){if("function"!=typeof t&&null!==t)throw TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&f(e,t)}function c(e){return -1!==Function.toString.call(e).indexOf("[native code]")}function l(e,t){return t&&("object"===p(t)||"function"==typeof t)?t:r(e)}function f(e,t){return(f=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}n.d(t,{V0:()=>B,_7:()=>v});var d,h,p=function(e){return e&&"undefined"!=typeof Symbol&&e.constructor===Symbol?"symbol":typeof e};function b(e){var t="function"==typeof Map?new Map:void 0;return(b=function(e){if(null===e||!c(e))return e;if("function"!=typeof e)throw TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,n)}function n(){return o(e,arguments,s(this).constructor)}return n.prototype=Object.create(e.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),f(n,e)})(e)}function m(){if("undefined"==typeof Reflect||!Reflect.construct||Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch(e){return!1}}function g(e){var t=m();return function(){var n,r=s(e);if(t){var i=s(this).constructor;n=Reflect.construct(r,arguments,i)}else n=r.apply(this,arguments);return l(this,n)}}var v=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"AuthenticationError(".concat(e.statusText,")"))).errors=[{status:e.status,detail:e},],r}return n}(b(Error)),y=function(e){u(n,e);var t=g(n);function n(e){var r,a=e.errors;return i(this,n),(r=t.call(this,"BadRequestError")).errors=a,r}return n}(b(Error)),w=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"UnprocessableEntityError")).errors=e,r}return n}(b(Error)),_=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"ServerError")).errors=e,r}return n}(b(Error)),E=function(e){u(n,e);var t=g(n);function n(e){var r,a=e.errors;return i(this,n),(r=t.call(this,"ConflictError")).errors=a,r}return n}(b(Error)),S=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"UnknownResponseError(".concat(e.statusText,")"))).errors=[{status:e.status,detail:e.statusText},],r}return n}(b(Error));function k(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:2e4;return Promise.race([fetch(e,t),new Promise(function(e,t){return setTimeout(function(){return t(Error("timeout"))},n)}),])}function x(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]=200&&e.status<300))return[3,2];return[2,e.json()];case 2:if(400!==e.status)return[3,3];return[2,e.json().then(function(e){throw new y(e)})];case 3:if(401!==e.status)return[3,4];throw new v(e);case 4:if(422!==e.status)return[3,6];return[4,$(e)];case 5:throw n=i.sent(),new w(n);case 6:if(409!==e.status)return[3,7];return[2,e.json().then(function(e){throw new E(e)})];case 7:if(!(e.status>=500))return[3,9];return[4,$(e)];case 8:throw r=i.sent(),new _(r);case 9:throw new S(e);case 10:return[2]}})})).apply(this,arguments)}function $(e){return z.apply(this,arguments)}function z(){return(z=j(function(e){return Y(this,function(t){return[2,e.json().then(function(t){return t.errors?t.errors.map(function(t){return{status:e.status,detail:t.detail}}):G(e)}).catch(function(){return G(e)})]})})).apply(this,arguments)}function G(e){return[{status:e.status,detail:e.statusText},]}},50109(e,t,n){"use strict";n.d(t,{LK:()=>o,U2:()=>i,eT:()=>s,t8:()=>a});var r=n(12795);function i(e){return r.ZP.getItem("chainlink.".concat(e))}function a(e,t){r.ZP.setItem("chainlink.".concat(e),t)}function o(e){var t=i(e),n={};if(t)try{return JSON.parse(t)}catch(r){}return n}function s(e,t){a(e,JSON.stringify(t))}},9541(e,t,n){"use strict";n.d(t,{Ks:()=>u,Tp:()=>a,iR:()=>o,pm:()=>s});var r=n(50109),i="persistURL";function a(){return r.U2(i)||""}function o(e){r.t8(i,e)}function s(){return r.LK("authentication")}function u(e){r.eT("authentication",e)}},67121(e,t,n){"use strict";function r(e){var t,n=e.Symbol;return"function"==typeof n?n.observable?t=n.observable:(t=n("observable"),n.observable=t):t="@@observable",t}n.r(t),n.d(t,{default:()=>o}),e=n.hmd(e),i="undefined"!=typeof self?self:"undefined"!=typeof window?window:void 0!==n.g?n.g:e;var i,a=r(i);let o=a},2177(e,t,n){"use strict";n.d(t,{Z:()=>o});var r=!0,i="Invariant failed";function a(e,t){if(!e){if(r)throw Error(i);throw Error(i+": "+(t||""))}}let o=a},11742(e){e.exports=function(){var e=document.getSelection();if(!e.rangeCount)return function(){};for(var t=document.activeElement,n=[],r=0;ru,ZT:()=>i,_T:()=>o,ev:()=>c,mG:()=>s,pi:()=>a});var r=function(e,t){return(r=Object.setPrototypeOf||({__proto__:[]})instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])})(e,t)};function i(e,t){if("function"!=typeof t&&null!==t)throw TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var a=function(){return(a=Object.assign||function(e){for(var t,n=1,r=arguments.length;nt.indexOf(r)&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var i=0,r=Object.getOwnPropertySymbols(e);it.indexOf(r[i])&&Object.prototype.propertyIsEnumerable.call(e,r[i])&&(n[r[i]]=e[r[i]]);return n}function s(e,t,n,r){function i(e){return e instanceof n?e:new n(function(t){t(e)})}return new(n||(n=Promise))(function(n,a){function o(e){try{u(r.next(e))}catch(t){a(t)}}function s(e){try{u(r.throw(e))}catch(t){a(t)}}function u(e){e.done?n(e.value):i(e.value).then(o,s)}u((r=r.apply(e,t||[])).next())})}function u(e,t){var n,r,i,a,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return a={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function s(e){return function(t){return u([e,t])}}function u(a){if(n)throw TypeError("Generator is already executing.");for(;o;)try{if(n=1,r&&(i=2&a[0]?r.return:a[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,a[1])).done)return i;switch(r=0,i&&(a=[2&a[0],i.value]),a[0]){case 0:case 1:i=a;break;case 4:return o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!(i=(i=o.trys).length>0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]r})},94927(e,t,n){function r(e,t){if(i("noDeprecation"))return e;var n=!1;function r(){if(!n){if(i("throwDeprecation"))throw Error(t);i("traceDeprecation")?console.trace(t):console.warn(t),n=!0}return e.apply(this,arguments)}return r}function i(e){try{if(!n.g.localStorage)return!1}catch(t){return!1}var r=n.g.localStorage[e];return null!=r&&"true"===String(r).toLowerCase()}e.exports=r},42473(e){"use strict";var t=function(){};e.exports=t},84763(e){e.exports=Worker},47529(e){e.exports=n;var t=Object.prototype.hasOwnProperty;function n(){for(var e={},n=0;ne.length)&&(t=e.length);for(var n=0,r=Array(t);n=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}e.exports=i,e.exports.__esModule=!0,e.exports.default=e.exports},7071(e){function t(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports},94993(e,t,n){var r=n(18698).default,i=n(66115);function a(e,t){if(t&&("object"===r(t)||"function"==typeof t))return t;if(void 0!==t)throw TypeError("Derived constructors may only return object or undefined");return i(e)}e.exports=a,e.exports.__esModule=!0,e.exports.default=e.exports},6015(e){function t(n,r){return e.exports=t=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},e.exports.__esModule=!0,e.exports.default=e.exports,t(n,r)}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports},861(e,t,n){var r=n(63405),i=n(79498),a=n(86116),o=n(42281);function s(e){return r(e)||i(e)||a(e)||o()}e.exports=s,e.exports.__esModule=!0,e.exports.default=e.exports},18698(e){function t(n){return e.exports=t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},e.exports.__esModule=!0,e.exports.default=e.exports,t(n)}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports},86116(e,t,n){var r=n(73897);function i(e,t){if(e){if("string"==typeof e)return r(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return r(e,t)}}e.exports=i,e.exports.__esModule=!0,e.exports.default=e.exports},1644(e,t,n){"use strict";var r,i;function a(e){return!!e&&e<7}n.d(t,{I:()=>r,O:()=>a}),(i=r||(r={}))[i.loading=1]="loading",i[i.setVariables=2]="setVariables",i[i.fetchMore=3]="fetchMore",i[i.refetch=4]="refetch",i[i.poll=6]="poll",i[i.ready=7]="ready",i[i.error=8]="error"},30990(e,t,n){"use strict";n.d(t,{MS:()=>s,YG:()=>a,cA:()=>c,ls:()=>o});var r=n(70655);n(83952);var i=n(13154),a=Symbol();function o(e){return!!e.extensions&&Array.isArray(e.extensions[a])}function s(e){return e.hasOwnProperty("graphQLErrors")}var u=function(e){var t=(0,r.ev)((0,r.ev)((0,r.ev)([],e.graphQLErrors,!0),e.clientErrors,!0),e.protocolErrors,!0);return e.networkError&&t.push(e.networkError),t.map(function(e){return(0,i.s)(e)&&e.message||"Error message not found."}).join("\n")},c=function(e){function t(n){var r=n.graphQLErrors,i=n.protocolErrors,a=n.clientErrors,o=n.networkError,s=n.errorMessage,c=n.extraInfo,l=e.call(this,s)||this;return l.name="ApolloError",l.graphQLErrors=r||[],l.protocolErrors=i||[],l.clientErrors=a||[],l.networkError=o||null,l.message=s||u(l),l.extraInfo=c,l.__proto__=t.prototype,l}return(0,r.ZT)(t,e),t}(Error)},85317(e,t,n){"use strict";n.d(t,{K:()=>a});var r=n(67294),i=n(30320).aS?Symbol.for("__APOLLO_CONTEXT__"):"__APOLLO_CONTEXT__";function a(){var e=r.createContext[i];return e||(Object.defineProperty(r.createContext,i,{value:e=r.createContext({}),enumerable:!1,writable:!1,configurable:!0}),e.displayName="ApolloContext"),e}},21436(e,t,n){"use strict";n.d(t,{O:()=>i,k:()=>r});var r=Array.isArray;function i(e){return Array.isArray(e)&&e.length>0}},30320(e,t,n){"use strict";n.d(t,{DN:()=>s,JC:()=>l,aS:()=>o,mr:()=>i,sy:()=>a});var r=n(83952),i="function"==typeof WeakMap&&"ReactNative"!==(0,r.wY)(function(){return navigator.product}),a="function"==typeof WeakSet,o="function"==typeof Symbol&&"function"==typeof Symbol.for,s=o&&Symbol.asyncIterator,u="function"==typeof(0,r.wY)(function(){return window.document.createElement}),c=(0,r.wY)(function(){return navigator.userAgent.indexOf("jsdom")>=0})||!1,l=u&&!c},53712(e,t,n){"use strict";function r(){for(var e=[],t=0;tr})},10542(e,t,n){"use strict";n.d(t,{J:()=>o}),n(83952);var r=n(13154);function i(e){var t=new Set([e]);return t.forEach(function(e){(0,r.s)(e)&&a(e)===e&&Object.getOwnPropertyNames(e).forEach(function(n){(0,r.s)(e[n])&&t.add(e[n])})}),e}function a(e){if(__DEV__&&!Object.isFrozen(e))try{Object.freeze(e)}catch(t){if(t instanceof TypeError)return null;throw t}return e}function o(e){return __DEV__&&i(e),e}},14012(e,t,n){"use strict";n.d(t,{J:()=>a});var r=n(70655),i=n(53712);function a(e,t){return(0,i.o)(e,t,t.variables&&{variables:(0,r.pi)((0,r.pi)({},e&&e.variables),t.variables)})}},13154(e,t,n){"use strict";function r(e){return null!==e&&"object"==typeof e}n.d(t,{s:()=>r})},83952(e,t,n){"use strict";n.d(t,{ej:()=>u,kG:()=>c,wY:()=>h});var r,i=n(70655),a="Invariant Violation",o=Object.setPrototypeOf,s=void 0===o?function(e,t){return e.__proto__=t,e}:o,u=function(e){function t(n){void 0===n&&(n=a);var r=e.call(this,"number"==typeof n?a+": "+n+" (see https://github.com/apollographql/invariant-packages)":n)||this;return r.framesToPop=1,r.name=a,s(r,t.prototype),r}return(0,i.ZT)(t,e),t}(Error);function c(e,t){if(!e)throw new u(t)}var l=["debug","log","warn","error","silent"],f=l.indexOf("log");function d(e){return function(){if(l.indexOf(e)>=f)return(console[e]||console.log).apply(console,arguments)}}function h(e){try{return e()}catch(t){}}(r=c||(c={})).debug=d("debug"),r.log=d("log"),r.warn=d("warn"),r.error=d("error");let p=h(function(){return globalThis})||h(function(){return window})||h(function(){return self})||h(function(){return global})||h(function(){return h.constructor("return this")()});var b="__",m=[b,b].join("DEV");function g(){try{return Boolean(__DEV__)}catch(e){return Object.defineProperty(p,m,{value:"production"!==h(function(){return"production"}),enumerable:!1,configurable:!0,writable:!0}),p[m]}}let v=g();function y(e){try{return e()}catch(t){}}var w=y(function(){return globalThis})||y(function(){return window})||y(function(){return self})||y(function(){return global})||y(function(){return y.constructor("return this")()}),_=!1;function E(){!w||y(function(){return"production"})||y(function(){return process})||(Object.defineProperty(w,"process",{value:{env:{NODE_ENV:"production"}},configurable:!0,enumerable:!1,writable:!0}),_=!0)}function S(){_&&(delete w.process,_=!1)}E();var k=n(10143);function x(){return k.H,S()}function T(){__DEV__?c("boolean"==typeof v,v):c("boolean"==typeof v,39)}x(),T()},4942(e,t,n){"use strict";function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}n.d(t,{Z:()=>r})},87462(e,t,n){"use strict";function r(){return(r=Object.assign?Object.assign.bind():function(e){for(var t=1;tr})},51721(e,t,n){"use strict";function r(e,t){return(r=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e})(e,t)}function i(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,r(e,t)}n.d(t,{Z:()=>i})},63366(e,t,n){"use strict";function r(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}n.d(t,{Z:()=>r})},25821(e,t,n){"use strict";n.d(t,{Z:()=>s});var r=n(45695);function i(e){return(i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}var a=10,o=2;function s(e){return u(e,[])}function u(e,t){switch(i(e)){case"string":return JSON.stringify(e);case"function":return e.name?"[function ".concat(e.name,"]"):"[function]";case"object":if(null===e)return"null";return c(e,t);default:return String(e)}}function c(e,t){if(-1!==t.indexOf(e))return"[Circular]";var n=[].concat(t,[e]),r=d(e);if(void 0!==r){var i=r.call(e);if(i!==e)return"string"==typeof i?i:u(i,n)}else if(Array.isArray(e))return f(e,n);return l(e,n)}function l(e,t){var n=Object.keys(e);return 0===n.length?"{}":t.length>o?"["+h(e)+"]":"{ "+n.map(function(n){var r=u(e[n],t);return n+": "+r}).join(", ")+" }"}function f(e,t){if(0===e.length)return"[]";if(t.length>o)return"[Array]";for(var n=Math.min(a,e.length),r=e.length-n,i=[],s=0;s1&&i.push("... ".concat(r," more items")),"["+i.join(", ")+"]"}function d(e){var t=e[String(r.Z)];return"function"==typeof t?t:"function"==typeof e.inspect?e.inspect:void 0}function h(e){var t=Object.prototype.toString.call(e).replace(/^\[object /,"").replace(/]$/,"");if("Object"===t&&"function"==typeof e.constructor){var n=e.constructor.name;if("string"==typeof n&&""!==n)return n}return t}},45695(e,t,n){"use strict";n.d(t,{Z:()=>i});var r="function"==typeof Symbol&&"function"==typeof Symbol.for?Symbol.for("nodejs.util.inspect.custom"):void 0;let i=r},25217(e,t,n){"use strict";function r(e,t){if(!Boolean(e))throw Error(null!=t?t:"Unexpected invariant triggered.")}n.d(t,{Ye:()=>o,WU:()=>s,UG:()=>u});var i=n(45695);function a(e){var t=e.prototype.toJSON;"function"==typeof t||r(0),e.prototype.inspect=t,i.Z&&(e.prototype[i.Z]=t)}var o=function(){function e(e,t,n){this.start=e.start,this.end=t.end,this.startToken=e,this.endToken=t,this.source=n}return e.prototype.toJSON=function(){return{start:this.start,end:this.end}},e}();a(o);var s=function(){function e(e,t,n,r,i,a,o){this.kind=e,this.start=t,this.end=n,this.line=r,this.column=i,this.value=o,this.prev=a,this.next=null}return e.prototype.toJSON=function(){return{kind:this.kind,value:this.value,line:this.line,column:this.column}},e}();function u(e){return null!=e&&"string"==typeof e.kind}a(s)},87392(e,t,n){"use strict";function r(e){var t=e.split(/\r\n|[\n\r]/g),n=a(e);if(0!==n)for(var r=1;ro&&i(t[s-1]);)--s;return t.slice(o,s).join("\n")}function i(e){for(var t=0;t1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],r=-1===e.indexOf("\n"),i=" "===e[0]||" "===e[0],a='"'===e[e.length-1],o="\\"===e[e.length-1],s=!r||a||o||n,u="";return s&&!(r&&i)&&(u+="\n"+t),u+=t?e.replace(/\n/g,"\n"+t):e,s&&(u+="\n"),'"""'+u.replace(/"""/g,'\\"""')+'"""'}n.d(t,{LZ:()=>o,W7:()=>r})},97359(e,t,n){"use strict";n.d(t,{h:()=>r});var r=Object.freeze({NAME:"Name",DOCUMENT:"Document",OPERATION_DEFINITION:"OperationDefinition",VARIABLE_DEFINITION:"VariableDefinition",SELECTION_SET:"SelectionSet",FIELD:"Field",ARGUMENT:"Argument",FRAGMENT_SPREAD:"FragmentSpread",INLINE_FRAGMENT:"InlineFragment",FRAGMENT_DEFINITION:"FragmentDefinition",VARIABLE:"Variable",INT:"IntValue",FLOAT:"FloatValue",STRING:"StringValue",BOOLEAN:"BooleanValue",NULL:"NullValue",ENUM:"EnumValue",LIST:"ListValue",OBJECT:"ObjectValue",OBJECT_FIELD:"ObjectField",DIRECTIVE:"Directive",NAMED_TYPE:"NamedType",LIST_TYPE:"ListType",NON_NULL_TYPE:"NonNullType",SCHEMA_DEFINITION:"SchemaDefinition",OPERATION_TYPE_DEFINITION:"OperationTypeDefinition",SCALAR_TYPE_DEFINITION:"ScalarTypeDefinition",OBJECT_TYPE_DEFINITION:"ObjectTypeDefinition",FIELD_DEFINITION:"FieldDefinition",INPUT_VALUE_DEFINITION:"InputValueDefinition",INTERFACE_TYPE_DEFINITION:"InterfaceTypeDefinition",UNION_TYPE_DEFINITION:"UnionTypeDefinition",ENUM_TYPE_DEFINITION:"EnumTypeDefinition",ENUM_VALUE_DEFINITION:"EnumValueDefinition",INPUT_OBJECT_TYPE_DEFINITION:"InputObjectTypeDefinition",DIRECTIVE_DEFINITION:"DirectiveDefinition",SCHEMA_EXTENSION:"SchemaExtension",SCALAR_TYPE_EXTENSION:"ScalarTypeExtension",OBJECT_TYPE_EXTENSION:"ObjectTypeExtension",INTERFACE_TYPE_EXTENSION:"InterfaceTypeExtension",UNION_TYPE_EXTENSION:"UnionTypeExtension",ENUM_TYPE_EXTENSION:"EnumTypeExtension",INPUT_OBJECT_TYPE_EXTENSION:"InputObjectTypeExtension"})},10143(e,t,n){"use strict";n.d(t,{H:()=>c,T:()=>l});var r=n(99763),i=n(25821);function a(e,t){if(!Boolean(e))throw Error(t)}let o=function(e,t){return e instanceof t};function s(e,t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:"GraphQL request",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{line:1,column:1};"string"==typeof e||a(0,"Body must be a string. Received: ".concat((0,i.Z)(e),".")),this.body=e,this.name=t,this.locationOffset=n,this.locationOffset.line>0||a(0,"line in locationOffset is 1-indexed and must be positive."),this.locationOffset.column>0||a(0,"column in locationOffset is 1-indexed and must be positive.")}return u(e,[{key:r.YF,get:function(){return"Source"}}]),e}();function l(e){return o(e,c)}},99763(e,t,n){"use strict";n.d(t,{YF:()=>r});var r="function"==typeof Symbol&&null!=Symbol.toStringTag?Symbol.toStringTag:"@@toStringTag"},37452(e){"use strict";e.exports=JSON.parse('{"AElig":"\xc6","AMP":"&","Aacute":"\xc1","Acirc":"\xc2","Agrave":"\xc0","Aring":"\xc5","Atilde":"\xc3","Auml":"\xc4","COPY":"\xa9","Ccedil":"\xc7","ETH":"\xd0","Eacute":"\xc9","Ecirc":"\xca","Egrave":"\xc8","Euml":"\xcb","GT":">","Iacute":"\xcd","Icirc":"\xce","Igrave":"\xcc","Iuml":"\xcf","LT":"<","Ntilde":"\xd1","Oacute":"\xd3","Ocirc":"\xd4","Ograve":"\xd2","Oslash":"\xd8","Otilde":"\xd5","Ouml":"\xd6","QUOT":"\\"","REG":"\xae","THORN":"\xde","Uacute":"\xda","Ucirc":"\xdb","Ugrave":"\xd9","Uuml":"\xdc","Yacute":"\xdd","aacute":"\xe1","acirc":"\xe2","acute":"\xb4","aelig":"\xe6","agrave":"\xe0","amp":"&","aring":"\xe5","atilde":"\xe3","auml":"\xe4","brvbar":"\xa6","ccedil":"\xe7","cedil":"\xb8","cent":"\xa2","copy":"\xa9","curren":"\xa4","deg":"\xb0","divide":"\xf7","eacute":"\xe9","ecirc":"\xea","egrave":"\xe8","eth":"\xf0","euml":"\xeb","frac12":"\xbd","frac14":"\xbc","frac34":"\xbe","gt":">","iacute":"\xed","icirc":"\xee","iexcl":"\xa1","igrave":"\xec","iquest":"\xbf","iuml":"\xef","laquo":"\xab","lt":"<","macr":"\xaf","micro":"\xb5","middot":"\xb7","nbsp":"\xa0","not":"\xac","ntilde":"\xf1","oacute":"\xf3","ocirc":"\xf4","ograve":"\xf2","ordf":"\xaa","ordm":"\xba","oslash":"\xf8","otilde":"\xf5","ouml":"\xf6","para":"\xb6","plusmn":"\xb1","pound":"\xa3","quot":"\\"","raquo":"\xbb","reg":"\xae","sect":"\xa7","shy":"\xad","sup1":"\xb9","sup2":"\xb2","sup3":"\xb3","szlig":"\xdf","thorn":"\xfe","times":"\xd7","uacute":"\xfa","ucirc":"\xfb","ugrave":"\xf9","uml":"\xa8","uuml":"\xfc","yacute":"\xfd","yen":"\xa5","yuml":"\xff"}')},93580(e){"use strict";e.exports=JSON.parse('{"0":"�","128":"€","130":"‚","131":"ƒ","132":"„","133":"…","134":"†","135":"‡","136":"ˆ","137":"‰","138":"Š","139":"‹","140":"Œ","142":"Ž","145":"‘","146":"’","147":"“","148":"”","149":"•","150":"–","151":"—","152":"˜","153":"™","154":"š","155":"›","156":"œ","158":"ž","159":"Ÿ"}')},67946(e){"use strict";e.exports=JSON.parse('{"locale":"en","long":{"year":{"previous":"last year","current":"this year","next":"next year","past":{"one":"{0} year ago","other":"{0} years ago"},"future":{"one":"in {0} year","other":"in {0} years"}},"quarter":{"previous":"last quarter","current":"this quarter","next":"next quarter","past":{"one":"{0} quarter ago","other":"{0} quarters ago"},"future":{"one":"in {0} quarter","other":"in {0} quarters"}},"month":{"previous":"last month","current":"this month","next":"next month","past":{"one":"{0} month ago","other":"{0} months ago"},"future":{"one":"in {0} month","other":"in {0} months"}},"week":{"previous":"last week","current":"this week","next":"next week","past":{"one":"{0} week ago","other":"{0} weeks ago"},"future":{"one":"in {0} week","other":"in {0} weeks"}},"day":{"previous":"yesterday","current":"today","next":"tomorrow","past":{"one":"{0} day ago","other":"{0} days ago"},"future":{"one":"in {0} day","other":"in {0} days"}},"hour":{"current":"this hour","past":{"one":"{0} hour ago","other":"{0} hours ago"},"future":{"one":"in {0} hour","other":"in {0} hours"}},"minute":{"current":"this minute","past":{"one":"{0} minute ago","other":"{0} minutes ago"},"future":{"one":"in {0} minute","other":"in {0} minutes"}},"second":{"current":"now","past":{"one":"{0} second ago","other":"{0} seconds ago"},"future":{"one":"in {0} second","other":"in {0} seconds"}}},"short":{"year":{"previous":"last yr.","current":"this yr.","next":"next yr.","past":"{0} yr. ago","future":"in {0} yr."},"quarter":{"previous":"last qtr.","current":"this qtr.","next":"next qtr.","past":{"one":"{0} qtr. ago","other":"{0} qtrs. ago"},"future":{"one":"in {0} qtr.","other":"in {0} qtrs."}},"month":{"previous":"last mo.","current":"this mo.","next":"next mo.","past":"{0} mo. ago","future":"in {0} mo."},"week":{"previous":"last wk.","current":"this wk.","next":"next wk.","past":"{0} wk. ago","future":"in {0} wk."},"day":{"previous":"yesterday","current":"today","next":"tomorrow","past":{"one":"{0} day ago","other":"{0} days ago"},"future":{"one":"in {0} day","other":"in {0} days"}},"hour":{"current":"this hour","past":"{0} hr. ago","future":"in {0} hr."},"minute":{"current":"this minute","past":"{0} min. ago","future":"in {0} min."},"second":{"current":"now","past":"{0} sec. ago","future":"in {0} sec."}},"narrow":{"year":{"previous":"last yr.","current":"this yr.","next":"next yr.","past":"{0} yr. ago","future":"in {0} yr."},"quarter":{"previous":"last qtr.","current":"this qtr.","next":"next qtr.","past":{"one":"{0} qtr. ago","other":"{0} qtrs. ago"},"future":{"one":"in {0} qtr.","other":"in {0} qtrs."}},"month":{"previous":"last mo.","current":"this mo.","next":"next mo.","past":"{0} mo. ago","future":"in {0} mo."},"week":{"previous":"last wk.","current":"this wk.","next":"next wk.","past":"{0} wk. ago","future":"in {0} wk."},"day":{"previous":"yesterday","current":"today","next":"tomorrow","past":{"one":"{0} day ago","other":"{0} days ago"},"future":{"one":"in {0} day","other":"in {0} days"}},"hour":{"current":"this hour","past":"{0} hr. ago","future":"in {0} hr."},"minute":{"current":"this minute","past":"{0} min. ago","future":"in {0} min."},"second":{"current":"now","past":"{0} sec. ago","future":"in {0} sec."}},"now":{"now":{"current":"now","future":"in a moment","past":"just now"}},"mini":{"year":"{0}yr","month":"{0}mo","week":"{0}wk","day":"{0}d","hour":"{0}h","minute":"{0}m","second":"{0}s","now":"now"},"short-time":{"year":"{0} yr.","month":"{0} mo.","week":"{0} wk.","day":{"one":"{0} day","other":"{0} days"},"hour":"{0} hr.","minute":"{0} min.","second":"{0} sec."},"long-time":{"year":{"one":"{0} year","other":"{0} years"},"month":{"one":"{0} month","other":"{0} months"},"week":{"one":"{0} week","other":"{0} weeks"},"day":{"one":"{0} day","other":"{0} days"},"hour":{"one":"{0} hour","other":"{0} hours"},"minute":{"one":"{0} minute","other":"{0} minutes"},"second":{"one":"{0} second","other":"{0} seconds"}}}')}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={id:e,loaded:!1,exports:{}};return __webpack_modules__[e].call(n.exports,n,n.exports,__webpack_require__),n.loaded=!0,n.exports}__webpack_require__.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return __webpack_require__.d(t,{a:t}),t},(()=>{var e,t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__;__webpack_require__.t=function(n,r){if(1&r&&(n=this(n)),8&r||"object"==typeof n&&n&&(4&r&&n.__esModule||16&r&&"function"==typeof n.then))return n;var i=Object.create(null);__webpack_require__.r(i);var a={};e=e||[null,t({}),t([]),t(t)];for(var o=2&r&&n;"object"==typeof o&&!~e.indexOf(o);o=t(o))Object.getOwnPropertyNames(o).forEach(e=>a[e]=()=>n[e]);return a.default=()=>n,__webpack_require__.d(i,a),i}})(),__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),__webpack_require__.hmd=e=>((e=Object.create(e)).children||(e.children=[]),Object.defineProperty(e,"exports",{enumerable:!0,set(){throw Error("ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: "+e.id)}}),e),__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},__webpack_require__.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),__webpack_require__.p="/assets/",__webpack_require__.nc=void 0;var __webpack_exports__={};(()=>{"use strict";var e,t,n,r,i=__webpack_require__(32316),a=__webpack_require__(8126),o=__webpack_require__(5690),s=__webpack_require__(30381),u=__webpack_require__.n(s),c=__webpack_require__(67294),l=__webpack_require__(73935),f=__webpack_require__.n(l),d=__webpack_require__(57209),h=__webpack_require__(37703),p=__webpack_require__(97779),b=__webpack_require__(28500);function m(e){return function(t){var n=t.dispatch,r=t.getState;return function(t){return function(i){return"function"==typeof i?i(n,r,e):t(i)}}}}var g=m();g.withExtraArgument=m;let v=g;var y=__webpack_require__(76489);function w(e){return function(t){return function(n){return function(r){n(r);var i=e||document&&document.cookie||"",a=t.getState();if("MATCH_ROUTE"===r.type&&"/signin"!==a.notifications.currentUrl){var o=(0,y.Q)(i);if(o.explorer)try{var s=JSON.parse(o.explorer);if("error"===s.status){var u=_(s.url);n({type:"NOTIFY_ERROR_MSG",msg:u})}}catch(c){n({type:"NOTIFY_ERROR_MSG",msg:"Invalid explorer status"})}}}}}}function _(e){var t="Can't connect to explorer: ".concat(e);return e.match(/^wss?:.+/)?t:"".concat(t,". You must use a websocket.")}var E=__webpack_require__(16353);function S(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}}}throw TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function ei(e,t){if(e){if("string"==typeof e)return ea(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return ea(e,t)}}function ea(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n1,i=!1,a=arguments[1],o=a;return new n(function(n){return t.subscribe({next:function(t){var a=!i;if(i=!0,!a||r)try{o=e(o,t)}catch(s){return n.error(s)}else o=t},error:function(e){n.error(e)},complete:function(){if(!i&&!r)return n.error(TypeError("Cannot reduce an empty sequence"));n.next(o),n.complete()}})})},t.concat=function(){for(var e=this,t=arguments.length,n=Array(t),r=0;r=0&&i.splice(e,1),o()}});i.push(s)},error:function(e){r.error(e)},complete:function(){o()}});function o(){a.closed&&0===i.length&&r.complete()}return function(){i.forEach(function(e){return e.unsubscribe()}),a.unsubscribe()}})},t[ed]=function(){return this},e.from=function(t){var n="function"==typeof this?this:e;if(null==t)throw TypeError(t+" is not an object");var r=ep(t,ed);if(r){var i=r.call(t);if(Object(i)!==i)throw TypeError(i+" is not an object");return em(i)&&i.constructor===n?i:new n(function(e){return i.subscribe(e)})}if(ec("iterator")&&(r=ep(t,ef)))return new n(function(e){ev(function(){if(!e.closed){for(var n,i=er(r.call(t));!(n=i()).done;){var a=n.value;if(e.next(a),e.closed)return}e.complete()}})});if(Array.isArray(t))return new n(function(e){ev(function(){if(!e.closed){for(var n=0;n0))return n.connection.key;var r=n.connection.filter?n.connection.filter:[];r.sort();var i={};return r.forEach(function(e){i[e]=t[e]}),"".concat(n.connection.key,"(").concat(eV(i),")")}var a=e;if(t){var o=eV(t);a+="(".concat(o,")")}return n&&Object.keys(n).forEach(function(e){-1===eW.indexOf(e)&&(n[e]&&Object.keys(n[e]).length?a+="@".concat(e,"(").concat(eV(n[e]),")"):a+="@".concat(e))}),a},{setStringify:function(e){var t=eV;return eV=e,t}}),eV=function(e){return JSON.stringify(e,eq)};function eq(e,t){return(0,eO.s)(t)&&!Array.isArray(t)&&(t=Object.keys(t).sort().reduce(function(e,n){return e[n]=t[n],e},{})),t}function eZ(e,t){if(e.arguments&&e.arguments.length){var n={};return e.arguments.forEach(function(e){var r;return ez(n,e.name,e.value,t)}),n}return null}function eX(e){return e.alias?e.alias.value:e.name.value}function eJ(e,t,n){for(var r,i=0,a=t.selections;it.indexOf(i))throw __DEV__?new Q.ej("illegal argument: ".concat(i)):new Q.ej(27)}return e}function tt(e,t){return t?t(e):eT.of()}function tn(e){return"function"==typeof e?new ta(e):e}function tr(e){return e.request.length<=1}var ti=function(e){function t(t,n){var r=e.call(this,t)||this;return r.link=n,r}return(0,en.ZT)(t,e),t}(Error),ta=function(){function e(e){e&&(this.request=e)}return e.empty=function(){return new e(function(){return eT.of()})},e.from=function(t){return 0===t.length?e.empty():t.map(tn).reduce(function(e,t){return e.concat(t)})},e.split=function(t,n,r){var i=tn(n),a=tn(r||new e(tt));return new e(tr(i)&&tr(a)?function(e){return t(e)?i.request(e)||eT.of():a.request(e)||eT.of()}:function(e,n){return t(e)?i.request(e,n)||eT.of():a.request(e,n)||eT.of()})},e.execute=function(e,t){return e.request(eM(t.context,e7(te(t))))||eT.of()},e.concat=function(t,n){var r=tn(t);if(tr(r))return __DEV__&&Q.kG.warn(new ti("You are calling concat on a terminating link, which will have no effect",r)),r;var i=tn(n);return new e(tr(i)?function(e){return r.request(e,function(e){return i.request(e)||eT.of()})||eT.of()}:function(e,t){return r.request(e,function(e){return i.request(e,t)||eT.of()})||eT.of()})},e.prototype.split=function(t,n,r){return this.concat(e.split(t,n,r||new e(tt)))},e.prototype.concat=function(t){return e.concat(this,t)},e.prototype.request=function(e,t){throw __DEV__?new Q.ej("request is not implemented"):new Q.ej(22)},e.prototype.onError=function(e,t){if(t&&t.error)return t.error(e),!1;throw e},e.prototype.setOnError=function(e){return this.onError=e,this},e}(),to=__webpack_require__(25821),ts=__webpack_require__(25217),tu={Name:[],Document:["definitions"],OperationDefinition:["name","variableDefinitions","directives","selectionSet"],VariableDefinition:["variable","type","defaultValue","directives"],Variable:["name"],SelectionSet:["selections"],Field:["alias","name","arguments","directives","selectionSet"],Argument:["name","value"],FragmentSpread:["name","directives"],InlineFragment:["typeCondition","directives","selectionSet"],FragmentDefinition:["name","variableDefinitions","typeCondition","directives","selectionSet"],IntValue:[],FloatValue:[],StringValue:[],BooleanValue:[],NullValue:[],EnumValue:[],ListValue:["values"],ObjectValue:["fields"],ObjectField:["name","value"],Directive:["name","arguments"],NamedType:["name"],ListType:["type"],NonNullType:["type"],SchemaDefinition:["description","directives","operationTypes"],OperationTypeDefinition:["type"],ScalarTypeDefinition:["description","name","directives"],ObjectTypeDefinition:["description","name","interfaces","directives","fields"],FieldDefinition:["description","name","arguments","type","directives"],InputValueDefinition:["description","name","type","defaultValue","directives"],InterfaceTypeDefinition:["description","name","interfaces","directives","fields"],UnionTypeDefinition:["description","name","directives","types"],EnumTypeDefinition:["description","name","directives","values"],EnumValueDefinition:["description","name","directives"],InputObjectTypeDefinition:["description","name","directives","fields"],DirectiveDefinition:["description","name","arguments","locations"],SchemaExtension:["directives","operationTypes"],ScalarTypeExtension:["name","directives"],ObjectTypeExtension:["name","interfaces","directives","fields"],InterfaceTypeExtension:["name","interfaces","directives","fields"],UnionTypeExtension:["name","directives","types"],EnumTypeExtension:["name","directives","values"],InputObjectTypeExtension:["name","directives","fields"]},tc=Object.freeze({});function tl(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:tu,r=void 0,i=Array.isArray(e),a=[e],o=-1,s=[],u=void 0,c=void 0,l=void 0,f=[],d=[],h=e;do{var p,b=++o===a.length,m=b&&0!==s.length;if(b){if(c=0===d.length?void 0:f[f.length-1],u=l,l=d.pop(),m){if(i)u=u.slice();else{for(var g={},v=0,y=Object.keys(u);v1)for(var r=new tB,i=1;i=0;--a){var o=i[a],s=isNaN(+o)?{}:[];s[o]=t,t=s}n=r.merge(n,t)}),n}var tW=Object.prototype.hasOwnProperty;function tK(e,t){var n,r,i,a,o;return(0,en.mG)(this,void 0,void 0,function(){var s,u,c,l,f,d,h,p,b,m,g,v,y,w,_,E,S,k,x,T,M,O,A;return(0,en.Jh)(this,function(L){switch(L.label){case 0:if(void 0===TextDecoder)throw Error("TextDecoder must be defined in the environment: please import a polyfill.");s=new TextDecoder("utf-8"),u=null===(n=e.headers)||void 0===n?void 0:n.get("content-type"),c="boundary=",l=(null==u?void 0:u.includes(c))?null==u?void 0:u.substring((null==u?void 0:u.indexOf(c))+c.length).replace(/['"]/g,"").replace(/\;(.*)/gm,"").trim():"-",f="\r\n--".concat(l),d="",h=tI(e),p=!0,L.label=1;case 1:if(!p)return[3,3];return[4,h.next()];case 2:for(m=(b=L.sent()).value,g=b.done,v="string"==typeof m?m:s.decode(m),y=d.length-f.length+1,p=!g,d+=v,w=d.indexOf(f,y);w>-1;){if(_=void 0,_=(O=[d.slice(0,w),d.slice(w+f.length),])[0],d=O[1],E=_.indexOf("\r\n\r\n"),(k=(S=tV(_.slice(0,E)))["content-type"])&&-1===k.toLowerCase().indexOf("application/json"))throw Error("Unsupported patch content type: application/json is required.");if(x=_.slice(E))try{T=tq(e,x),Object.keys(T).length>1||"data"in T||"incremental"in T||"errors"in T||"payload"in T?tz(T)?(M={},"payload"in T&&(M=(0,en.pi)({},T.payload)),"errors"in T&&(M=(0,en.pi)((0,en.pi)({},M),{extensions:(0,en.pi)((0,en.pi)({},"extensions"in M?M.extensions:null),((A={})[tN.YG]=T.errors,A))})),null===(r=t.next)||void 0===r||r.call(t,M)):null===(i=t.next)||void 0===i||i.call(t,T):1===Object.keys(T).length&&"hasNext"in T&&!T.hasNext&&(null===(a=t.complete)||void 0===a||a.call(t))}catch(C){tZ(C,t)}w=d.indexOf(f)}return[3,1];case 3:return null===(o=t.complete)||void 0===o||o.call(t),[2]}})})}function tV(e){var t={};return e.split("\n").forEach(function(e){var n=e.indexOf(":");if(n>-1){var r=e.slice(0,n).trim().toLowerCase(),i=e.slice(n+1).trim();t[r]=i}}),t}function tq(e,t){e.status>=300&&tD(e,function(){try{return JSON.parse(t)}catch(e){return t}}(),"Response not successful: Received status code ".concat(e.status));try{return JSON.parse(t)}catch(n){var r=n;throw r.name="ServerParseError",r.response=e,r.statusCode=e.status,r.bodyText=t,r}}function tZ(e,t){var n,r;"AbortError"!==e.name&&(e.result&&e.result.errors&&e.result.data&&(null===(n=t.next)||void 0===n||n.call(t,e.result)),null===(r=t.error)||void 0===r||r.call(t,e))}function tX(e,t,n){tJ(t)(e).then(function(e){var t,r;null===(t=n.next)||void 0===t||t.call(n,e),null===(r=n.complete)||void 0===r||r.call(n)}).catch(function(e){return tZ(e,n)})}function tJ(e){return function(t){return t.text().then(function(e){return tq(t,e)}).then(function(n){return t.status>=300&&tD(t,n,"Response not successful: Received status code ".concat(t.status)),Array.isArray(n)||tW.call(n,"data")||tW.call(n,"errors")||tD(t,n,"Server response was missing for query '".concat(Array.isArray(e)?e.map(function(e){return e.operationName}):e.operationName,"'.")),n})}}var tQ=function(e){if(!e&&"undefined"==typeof fetch)throw __DEV__?new Q.ej("\n\"fetch\" has not been found globally and no fetcher has been configured. To fix this, install a fetch package (like https://www.npmjs.com/package/cross-fetch), instantiate the fetcher, and pass it into your HttpLink constructor. For example:\n\nimport fetch from 'cross-fetch';\nimport { ApolloClient, HttpLink } from '@apollo/client';\nconst client = new ApolloClient({\n link: new HttpLink({ uri: '/graphql', fetch })\n});\n "):new Q.ej(23)},t1=__webpack_require__(87392);function t0(e){return tl(e,{leave:t3})}var t2=80,t3={Name:function(e){return e.value},Variable:function(e){return"$"+e.name},Document:function(e){return t6(e.definitions,"\n\n")+"\n"},OperationDefinition:function(e){var t=e.operation,n=e.name,r=t8("(",t6(e.variableDefinitions,", "),")"),i=t6(e.directives," "),a=e.selectionSet;return n||i||r||"query"!==t?t6([t,t6([n,r]),i,a]," "):a},VariableDefinition:function(e){var t=e.variable,n=e.type,r=e.defaultValue,i=e.directives;return t+": "+n+t8(" = ",r)+t8(" ",t6(i," "))},SelectionSet:function(e){return t5(e.selections)},Field:function(e){var t=e.alias,n=e.name,r=e.arguments,i=e.directives,a=e.selectionSet,o=t8("",t,": ")+n,s=o+t8("(",t6(r,", "),")");return s.length>t2&&(s=o+t8("(\n",t9(t6(r,"\n")),"\n)")),t6([s,t6(i," "),a]," ")},Argument:function(e){var t;return e.name+": "+e.value},FragmentSpread:function(e){var t;return"..."+e.name+t8(" ",t6(e.directives," "))},InlineFragment:function(e){var t=e.typeCondition,n=e.directives,r=e.selectionSet;return t6(["...",t8("on ",t),t6(n," "),r]," ")},FragmentDefinition:function(e){var t=e.name,n=e.typeCondition,r=e.variableDefinitions,i=e.directives,a=e.selectionSet;return"fragment ".concat(t).concat(t8("(",t6(r,", "),")")," ")+"on ".concat(n," ").concat(t8("",t6(i," ")," "))+a},IntValue:function(e){return e.value},FloatValue:function(e){return e.value},StringValue:function(e,t){var n=e.value;return e.block?(0,t1.LZ)(n,"description"===t?"":" "):JSON.stringify(n)},BooleanValue:function(e){return e.value?"true":"false"},NullValue:function(){return"null"},EnumValue:function(e){return e.value},ListValue:function(e){return"["+t6(e.values,", ")+"]"},ObjectValue:function(e){return"{"+t6(e.fields,", ")+"}"},ObjectField:function(e){var t;return e.name+": "+e.value},Directive:function(e){var t;return"@"+e.name+t8("(",t6(e.arguments,", "),")")},NamedType:function(e){return e.name},ListType:function(e){return"["+e.type+"]"},NonNullType:function(e){return e.type+"!"},SchemaDefinition:t4(function(e){var t=e.directives,n=e.operationTypes;return t6(["schema",t6(t," "),t5(n)]," ")}),OperationTypeDefinition:function(e){var t;return e.operation+": "+e.type},ScalarTypeDefinition:t4(function(e){var t;return t6(["scalar",e.name,t6(e.directives," ")]," ")}),ObjectTypeDefinition:t4(function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["type",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")}),FieldDefinition:t4(function(e){var t=e.name,n=e.arguments,r=e.type,i=e.directives;return t+(ne(n)?t8("(\n",t9(t6(n,"\n")),"\n)"):t8("(",t6(n,", "),")"))+": "+r+t8(" ",t6(i," "))}),InputValueDefinition:t4(function(e){var t=e.name,n=e.type,r=e.defaultValue,i=e.directives;return t6([t+": "+n,t8("= ",r),t6(i," ")]," ")}),InterfaceTypeDefinition:t4(function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["interface",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")}),UnionTypeDefinition:t4(function(e){var t=e.name,n=e.directives,r=e.types;return t6(["union",t,t6(n," "),r&&0!==r.length?"= "+t6(r," | "):""]," ")}),EnumTypeDefinition:t4(function(e){var t=e.name,n=e.directives,r=e.values;return t6(["enum",t,t6(n," "),t5(r)]," ")}),EnumValueDefinition:t4(function(e){var t;return t6([e.name,t6(e.directives," ")]," ")}),InputObjectTypeDefinition:t4(function(e){var t=e.name,n=e.directives,r=e.fields;return t6(["input",t,t6(n," "),t5(r)]," ")}),DirectiveDefinition:t4(function(e){var t=e.name,n=e.arguments,r=e.repeatable,i=e.locations;return"directive @"+t+(ne(n)?t8("(\n",t9(t6(n,"\n")),"\n)"):t8("(",t6(n,", "),")"))+(r?" repeatable":"")+" on "+t6(i," | ")}),SchemaExtension:function(e){var t=e.directives,n=e.operationTypes;return t6(["extend schema",t6(t," "),t5(n)]," ")},ScalarTypeExtension:function(e){var t;return t6(["extend scalar",e.name,t6(e.directives," ")]," ")},ObjectTypeExtension:function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["extend type",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")},InterfaceTypeExtension:function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["extend interface",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")},UnionTypeExtension:function(e){var t=e.name,n=e.directives,r=e.types;return t6(["extend union",t,t6(n," "),r&&0!==r.length?"= "+t6(r," | "):""]," ")},EnumTypeExtension:function(e){var t=e.name,n=e.directives,r=e.values;return t6(["extend enum",t,t6(n," "),t5(r)]," ")},InputObjectTypeExtension:function(e){var t=e.name,n=e.directives,r=e.fields;return t6(["extend input",t,t6(n," "),t5(r)]," ")}};function t4(e){return function(t){return t6([t.description,e(t)],"\n")}}function t6(e){var t,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return null!==(t=null==e?void 0:e.filter(function(e){return e}).join(n))&&void 0!==t?t:""}function t5(e){return t8("{\n",t9(t6(e,"\n")),"\n}")}function t8(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";return null!=t&&""!==t?e+t+n:""}function t9(e){return t8(" ",e.replace(/\n/g,"\n "))}function t7(e){return -1!==e.indexOf("\n")}function ne(e){return null!=e&&e.some(t7)}var nt,nn,nr,ni={http:{includeQuery:!0,includeExtensions:!1,preserveHeaderCase:!1},headers:{accept:"*/*","content-type":"application/json"},options:{method:"POST"}},na=function(e,t){return t(e)};function no(e,t){for(var n=[],r=2;rObject.create(null),{forEach:nv,slice:ny}=Array.prototype,{hasOwnProperty:nw}=Object.prototype;class n_{constructor(e=!0,t=ng){this.weakness=e,this.makeData=t}lookup(...e){return this.lookupArray(e)}lookupArray(e){let t=this;return nv.call(e,e=>t=t.getChildTrie(e)),nw.call(t,"data")?t.data:t.data=this.makeData(ny.call(e))}peek(...e){return this.peekArray(e)}peekArray(e){let t=this;for(let n=0,r=e.length;t&&n=0;--o)t.definitions[o].kind===nL.h.OPERATION_DEFINITION&&++a;var s=nN(e),u=e.some(function(e){return e.remove}),c=function(e){return u&&e&&e.some(s)},l=new Map,f=!1,d={enter:function(e){if(c(e.directives))return f=!0,null}},h=tl(t,{Field:d,InlineFragment:d,VariableDefinition:{enter:function(){return!1}},Variable:{enter:function(e,t,n,r,a){var o=i(a);o&&o.variables.add(e.name.value)}},FragmentSpread:{enter:function(e,t,n,r,a){if(c(e.directives))return f=!0,null;var o=i(a);o&&o.fragmentSpreads.add(e.name.value)}},FragmentDefinition:{enter:function(e,t,n,r){l.set(JSON.stringify(r),e)},leave:function(e,t,n,i){return e===l.get(JSON.stringify(i))?e:a>0&&e.selectionSet.selections.every(function(e){return e.kind===nL.h.FIELD&&"__typename"===e.name.value})?(r(e.name.value).removed=!0,f=!0,null):void 0}},Directive:{leave:function(e){if(s(e))return f=!0,null}}});if(!f)return t;var p=function(e){return e.transitiveVars||(e.transitiveVars=new Set(e.variables),e.removed||e.fragmentSpreads.forEach(function(t){p(r(t)).transitiveVars.forEach(function(t){e.transitiveVars.add(t)})})),e},b=new Set;h.definitions.forEach(function(e){e.kind===nL.h.OPERATION_DEFINITION?p(n(e.name&&e.name.value)).fragmentSpreads.forEach(function(e){b.add(e)}):e.kind!==nL.h.FRAGMENT_DEFINITION||0!==a||r(e.name.value).removed||b.add(e.name.value)}),b.forEach(function(e){p(r(e)).fragmentSpreads.forEach(function(e){b.add(e)})});var m=function(e){return!!(!b.has(e)||r(e).removed)},g={enter:function(e){if(m(e.name.value))return null}};return nD(tl(h,{FragmentSpread:g,FragmentDefinition:g,OperationDefinition:{leave:function(e){if(e.variableDefinitions){var t=p(n(e.name&&e.name.value)).transitiveVars;if(t.size0},t.prototype.tearDownQuery=function(){this.isTornDown||(this.concast&&this.observer&&(this.concast.removeObserver(this.observer),delete this.concast,delete this.observer),this.stopPolling(),this.subscriptions.forEach(function(e){return e.unsubscribe()}),this.subscriptions.clear(),this.queryManager.stopQuery(this.queryId),this.observers.clear(),this.isTornDown=!0)},t}(eT);function n4(e){var t=e.options,n=t.fetchPolicy,r=t.nextFetchPolicy;return"cache-and-network"===n||"network-only"===n?e.reobserve({fetchPolicy:"cache-first",nextFetchPolicy:function(){return(this.nextFetchPolicy=r,"function"==typeof r)?r.apply(this,arguments):n}}):e.reobserve()}function n6(e){__DEV__&&Q.kG.error("Unhandled error",e.message,e.stack)}function n5(e){__DEV__&&e&&__DEV__&&Q.kG.debug("Missing cache result fields: ".concat(JSON.stringify(e)),e)}function n8(e){return"network-only"===e||"no-cache"===e||"standby"===e}nK(n3);function n9(e){return e.kind===nL.h.FIELD||e.kind===nL.h.FRAGMENT_SPREAD||e.kind===nL.h.INLINE_FRAGMENT}function n7(e){return e.kind===Kind.SCALAR_TYPE_DEFINITION||e.kind===Kind.OBJECT_TYPE_DEFINITION||e.kind===Kind.INTERFACE_TYPE_DEFINITION||e.kind===Kind.UNION_TYPE_DEFINITION||e.kind===Kind.ENUM_TYPE_DEFINITION||e.kind===Kind.INPUT_OBJECT_TYPE_DEFINITION}function re(e){return e.kind===Kind.SCALAR_TYPE_EXTENSION||e.kind===Kind.OBJECT_TYPE_EXTENSION||e.kind===Kind.INTERFACE_TYPE_EXTENSION||e.kind===Kind.UNION_TYPE_EXTENSION||e.kind===Kind.ENUM_TYPE_EXTENSION||e.kind===Kind.INPUT_OBJECT_TYPE_EXTENSION}var rt=function(){return Object.create(null)},rn=Array.prototype,rr=rn.forEach,ri=rn.slice,ra=function(){function e(e,t){void 0===e&&(e=!0),void 0===t&&(t=rt),this.weakness=e,this.makeData=t}return e.prototype.lookup=function(){for(var e=[],t=0;tclass{constructor(){this.id=["slot",rc++,Date.now(),Math.random().toString(36).slice(2),].join(":")}hasValue(){for(let e=rs;e;e=e.parent)if(this.id in e.slots){let t=e.slots[this.id];if(t===ru)break;return e!==rs&&(rs.slots[this.id]=t),!0}return rs&&(rs.slots[this.id]=ru),!1}getValue(){if(this.hasValue())return rs.slots[this.id]}withValue(e,t,n,r){let i={__proto__:null,[this.id]:e},a=rs;rs={parent:a,slots:i};try{return t.apply(r,n)}finally{rs=a}}static bind(e){let t=rs;return function(){let n=rs;try{return rs=t,e.apply(this,arguments)}finally{rs=n}}}static noContext(e,t,n){if(!rs)return e.apply(n,t);{let r=rs;try{return rs=null,e.apply(n,t)}finally{rs=r}}}};function rf(e){try{return e()}catch(t){}}let rd="@wry/context:Slot",rh=rf(()=>globalThis)||rf(()=>global)||Object.create(null),rp=rh,rb=rp[rd]||Array[rd]||function(e){try{Object.defineProperty(rp,rd,{value:e,enumerable:!1,writable:!1,configurable:!0})}finally{return e}}(rl()),{bind:rm,noContext:rg}=rb;function rv(){}var ry=function(){function e(e,t){void 0===e&&(e=1/0),void 0===t&&(t=rv),this.max=e,this.dispose=t,this.map=new Map,this.newest=null,this.oldest=null}return e.prototype.has=function(e){return this.map.has(e)},e.prototype.get=function(e){var t=this.getNode(e);return t&&t.value},e.prototype.getNode=function(e){var t=this.map.get(e);if(t&&t!==this.newest){var n=t.older,r=t.newer;r&&(r.older=n),n&&(n.newer=r),t.older=this.newest,t.older.newer=t,t.newer=null,this.newest=t,t===this.oldest&&(this.oldest=r)}return t},e.prototype.set=function(e,t){var n=this.getNode(e);return n?n.value=t:(n={key:e,value:t,newer:null,older:this.newest},this.newest&&(this.newest.newer=n),this.newest=n,this.oldest=this.oldest||n,this.map.set(e,n),n.value)},e.prototype.clean=function(){for(;this.oldest&&this.map.size>this.max;)this.delete(this.oldest.key)},e.prototype.delete=function(e){var t=this.map.get(e);return!!t&&(t===this.newest&&(this.newest=t.older),t===this.oldest&&(this.oldest=t.newer),t.newer&&(t.newer.older=t.older),t.older&&(t.older.newer=t.newer),this.map.delete(e),this.dispose(t.value,e),!0)},e}(),rw=new rb,r_=Object.prototype.hasOwnProperty,rE=void 0===(n=Array.from)?function(e){var t=[];return e.forEach(function(e){return t.push(e)}),t}:n;function rS(e){var t=e.unsubscribe;"function"==typeof t&&(e.unsubscribe=void 0,t())}var rk=[],rx=100;function rT(e,t){if(!e)throw Error(t||"assertion failure")}function rM(e,t){var n=e.length;return n>0&&n===t.length&&e[n-1]===t[n-1]}function rO(e){switch(e.length){case 0:throw Error("unknown value");case 1:return e[0];case 2:throw e[1]}}function rA(e){return e.slice(0)}var rL=function(){function e(t){this.fn=t,this.parents=new Set,this.childValues=new Map,this.dirtyChildren=null,this.dirty=!0,this.recomputing=!1,this.value=[],this.deps=null,++e.count}return e.prototype.peek=function(){if(1===this.value.length&&!rN(this))return rC(this),this.value[0]},e.prototype.recompute=function(e){return rT(!this.recomputing,"already recomputing"),rC(this),rN(this)?rI(this,e):rO(this.value)},e.prototype.setDirty=function(){this.dirty||(this.dirty=!0,this.value.length=0,rR(this),rS(this))},e.prototype.dispose=function(){var e=this;this.setDirty(),rH(this),rF(this,function(t,n){t.setDirty(),r$(t,e)})},e.prototype.forget=function(){this.dispose()},e.prototype.dependOn=function(e){e.add(this),this.deps||(this.deps=rk.pop()||new Set),this.deps.add(e)},e.prototype.forgetDeps=function(){var e=this;this.deps&&(rE(this.deps).forEach(function(t){return t.delete(e)}),this.deps.clear(),rk.push(this.deps),this.deps=null)},e.count=0,e}();function rC(e){var t=rw.getValue();if(t)return e.parents.add(t),t.childValues.has(e)||t.childValues.set(e,[]),rN(e)?rY(t,e):rB(t,e),t}function rI(e,t){return rH(e),rw.withValue(e,rD,[e,t]),rz(e,t)&&rP(e),rO(e.value)}function rD(e,t){e.recomputing=!0,e.value.length=0;try{e.value[0]=e.fn.apply(null,t)}catch(n){e.value[1]=n}e.recomputing=!1}function rN(e){return e.dirty||!!(e.dirtyChildren&&e.dirtyChildren.size)}function rP(e){e.dirty=!1,!rN(e)&&rj(e)}function rR(e){rF(e,rY)}function rj(e){rF(e,rB)}function rF(e,t){var n=e.parents.size;if(n)for(var r=rE(e.parents),i=0;i0&&e.childValues.forEach(function(t,n){r$(e,n)}),e.forgetDeps(),rT(null===e.dirtyChildren)}function r$(e,t){t.parents.delete(e),e.childValues.delete(t),rU(e,t)}function rz(e,t){if("function"==typeof e.subscribe)try{rS(e),e.unsubscribe=e.subscribe.apply(null,t)}catch(n){return e.setDirty(),!1}return!0}var rG={setDirty:!0,dispose:!0,forget:!0};function rW(e){var t=new Map,n=e&&e.subscribe;function r(e){var r=rw.getValue();if(r){var i=t.get(e);i||t.set(e,i=new Set),r.dependOn(i),"function"==typeof n&&(rS(i),i.unsubscribe=n(e))}}return r.dirty=function(e,n){var r=t.get(e);if(r){var i=n&&r_.call(rG,n)?n:"setDirty";rE(r).forEach(function(e){return e[i]()}),t.delete(e),rS(r)}},r}function rK(){var e=new ra("function"==typeof WeakMap);return function(){return e.lookupArray(arguments)}}var rV=rK(),rq=new Set;function rZ(e,t){void 0===t&&(t=Object.create(null));var n=new ry(t.max||65536,function(e){return e.dispose()}),r=t.keyArgs,i=t.makeCacheKey||rK(),a=function(){var a=i.apply(null,r?r.apply(null,arguments):arguments);if(void 0===a)return e.apply(null,arguments);var o=n.get(a);o||(n.set(a,o=new rL(e)),o.subscribe=t.subscribe,o.forget=function(){return n.delete(a)});var s=o.recompute(Array.prototype.slice.call(arguments));return n.set(a,o),rq.add(n),rw.hasValue()||(rq.forEach(function(e){return e.clean()}),rq.clear()),s};function o(e){var t=n.get(e);t&&t.setDirty()}function s(e){var t=n.get(e);if(t)return t.peek()}function u(e){return n.delete(e)}return Object.defineProperty(a,"size",{get:function(){return n.map.size},configurable:!1,enumerable:!1}),a.dirtyKey=o,a.dirty=function(){o(i.apply(null,arguments))},a.peekKey=s,a.peek=function(){return s(i.apply(null,arguments))},a.forgetKey=u,a.forget=function(){return u(i.apply(null,arguments))},a.makeCacheKey=i,a.getKey=r?function(){return i.apply(null,r.apply(null,arguments))}:i,Object.freeze(a)}var rX=new rb,rJ=new WeakMap;function rQ(e){var t=rJ.get(e);return t||rJ.set(e,t={vars:new Set,dep:rW()}),t}function r1(e){rQ(e).vars.forEach(function(t){return t.forgetCache(e)})}function r0(e){rQ(e).vars.forEach(function(t){return t.attachCache(e)})}function r2(e){var t=new Set,n=new Set,r=function(a){if(arguments.length>0){if(e!==a){e=a,t.forEach(function(e){rQ(e).dep.dirty(r),r3(e)});var o=Array.from(n);n.clear(),o.forEach(function(t){return t(e)})}}else{var s=rX.getValue();s&&(i(s),rQ(s).dep(r))}return e};r.onNextChange=function(e){return n.add(e),function(){n.delete(e)}};var i=r.attachCache=function(e){return t.add(e),rQ(e).vars.add(r),r};return r.forgetCache=function(e){return t.delete(e)},r}function r3(e){e.broadcastWatches&&e.broadcastWatches()}var r4=function(){function e(e){var t=e.cache,n=e.client,r=e.resolvers,i=e.fragmentMatcher;this.selectionsToResolveCache=new WeakMap,this.cache=t,n&&(this.client=n),r&&this.addResolvers(r),i&&this.setFragmentMatcher(i)}return e.prototype.addResolvers=function(e){var t=this;this.resolvers=this.resolvers||{},Array.isArray(e)?e.forEach(function(e){t.resolvers=tj(t.resolvers,e)}):this.resolvers=tj(this.resolvers,e)},e.prototype.setResolvers=function(e){this.resolvers={},this.addResolvers(e)},e.prototype.getResolvers=function(){return this.resolvers||{}},e.prototype.runResolvers=function(e){var t=e.document,n=e.remoteResult,r=e.context,i=e.variables,a=e.onlyRunForcedResolvers,o=void 0!==a&&a;return(0,en.mG)(this,void 0,void 0,function(){return(0,en.Jh)(this,function(e){return t?[2,this.resolveDocument(t,n.data,r,i,this.fragmentMatcher,o).then(function(e){return(0,en.pi)((0,en.pi)({},n),{data:e.result})})]:[2,n]})})},e.prototype.setFragmentMatcher=function(e){this.fragmentMatcher=e},e.prototype.getFragmentMatcher=function(){return this.fragmentMatcher},e.prototype.clientQuery=function(e){return tb(["client"],e)&&this.resolvers?e:null},e.prototype.serverQuery=function(e){return n$(e)},e.prototype.prepareContext=function(e){var t=this.cache;return(0,en.pi)((0,en.pi)({},e),{cache:t,getCacheKey:function(e){return t.identify(e)}})},e.prototype.addExportedVariables=function(e,t,n){return void 0===t&&(t={}),void 0===n&&(n={}),(0,en.mG)(this,void 0,void 0,function(){return(0,en.Jh)(this,function(r){return e?[2,this.resolveDocument(e,this.buildRootValueFromCache(e,t)||{},this.prepareContext(n),t).then(function(e){return(0,en.pi)((0,en.pi)({},t),e.exportedVariables)})]:[2,(0,en.pi)({},t)]})})},e.prototype.shouldForceResolvers=function(e){var t=!1;return tl(e,{Directive:{enter:function(e){if("client"===e.name.value&&e.arguments&&(t=e.arguments.some(function(e){return"always"===e.name.value&&"BooleanValue"===e.value.kind&&!0===e.value.value})))return tc}}}),t},e.prototype.buildRootValueFromCache=function(e,t){return this.cache.diff({query:nH(e),variables:t,returnPartialData:!0,optimistic:!1}).result},e.prototype.resolveDocument=function(e,t,n,r,i,a){return void 0===n&&(n={}),void 0===r&&(r={}),void 0===i&&(i=function(){return!0}),void 0===a&&(a=!1),(0,en.mG)(this,void 0,void 0,function(){var o,s,u,c,l,f,d,h,p,b,m;return(0,en.Jh)(this,function(g){return o=e8(e),s=e4(e),u=eL(s),c=this.collectSelectionsToResolve(o,u),f=(l=o.operation)?l.charAt(0).toUpperCase()+l.slice(1):"Query",d=this,h=d.cache,p=d.client,b={fragmentMap:u,context:(0,en.pi)((0,en.pi)({},n),{cache:h,client:p}),variables:r,fragmentMatcher:i,defaultOperationType:f,exportedVariables:{},selectionsToResolve:c,onlyRunForcedResolvers:a},m=!1,[2,this.resolveSelectionSet(o.selectionSet,m,t,b).then(function(e){return{result:e,exportedVariables:b.exportedVariables}})]})})},e.prototype.resolveSelectionSet=function(e,t,n,r){return(0,en.mG)(this,void 0,void 0,function(){var i,a,o,s,u,c=this;return(0,en.Jh)(this,function(l){return i=r.fragmentMap,a=r.context,o=r.variables,s=[n],u=function(e){return(0,en.mG)(c,void 0,void 0,function(){var u,c;return(0,en.Jh)(this,function(l){return(t||r.selectionsToResolve.has(e))&&td(e,o)?eQ(e)?[2,this.resolveField(e,t,n,r).then(function(t){var n;void 0!==t&&s.push(((n={})[eX(e)]=t,n))})]:(e1(e)?u=e:(u=i[e.name.value],__DEV__?(0,Q.kG)(u,"No fragment named ".concat(e.name.value)):(0,Q.kG)(u,11)),u&&u.typeCondition&&(c=u.typeCondition.name.value,r.fragmentMatcher(n,c,a)))?[2,this.resolveSelectionSet(u.selectionSet,t,n,r).then(function(e){s.push(e)})]:[2]:[2]})})},[2,Promise.all(e.selections.map(u)).then(function(){return tF(s)})]})})},e.prototype.resolveField=function(e,t,n,r){return(0,en.mG)(this,void 0,void 0,function(){var i,a,o,s,u,c,l,f,d,h=this;return(0,en.Jh)(this,function(p){return n?(i=r.variables,a=e.name.value,o=eX(e),s=a!==o,c=Promise.resolve(u=n[o]||n[a]),(!r.onlyRunForcedResolvers||this.shouldForceResolvers(e))&&(l=n.__typename||r.defaultOperationType,(f=this.resolvers&&this.resolvers[l])&&(d=f[s?a:o])&&(c=Promise.resolve(rX.withValue(this.cache,d,[n,eZ(e,i),r.context,{field:e,fragmentMap:r.fragmentMap},])))),[2,c.then(function(n){if(void 0===n&&(n=u),e.directives&&e.directives.forEach(function(e){"export"===e.name.value&&e.arguments&&e.arguments.forEach(function(e){"as"===e.name.value&&"StringValue"===e.value.kind&&(r.exportedVariables[e.value.value]=n)})}),!e.selectionSet||null==n)return n;var i,a,o=null!==(a=null===(i=e.directives)||void 0===i?void 0:i.some(function(e){return"client"===e.name.value}))&&void 0!==a&&a;return Array.isArray(n)?h.resolveSubSelectedArray(e,t||o,n,r):e.selectionSet?h.resolveSelectionSet(e.selectionSet,t||o,n,r):void 0})]):[2,null]})})},e.prototype.resolveSubSelectedArray=function(e,t,n,r){var i=this;return Promise.all(n.map(function(n){return null===n?null:Array.isArray(n)?i.resolveSubSelectedArray(e,t,n,r):e.selectionSet?i.resolveSelectionSet(e.selectionSet,t,n,r):void 0}))},e.prototype.collectSelectionsToResolve=function(e,t){var n=function(e){return!Array.isArray(e)},r=this.selectionsToResolveCache;function i(e){if(!r.has(e)){var a=new Set;r.set(e,a),tl(e,{Directive:function(e,t,r,i,o){"client"===e.name.value&&o.forEach(function(e){n(e)&&n9(e)&&a.add(e)})},FragmentSpread:function(e,r,o,s,u){var c=t[e.name.value];__DEV__?(0,Q.kG)(c,"No fragment named ".concat(e.name.value)):(0,Q.kG)(c,12);var l=i(c);l.size>0&&(u.forEach(function(e){n(e)&&n9(e)&&a.add(e)}),a.add(e),l.forEach(function(e){a.add(e)}))}})}return r.get(e)}return i(e)},e}(),r6=new(t_.mr?WeakMap:Map);function r5(e,t){var n=e[t];"function"==typeof n&&(e[t]=function(){return r6.set(e,(r6.get(e)+1)%1e15),n.apply(this,arguments)})}function r8(e){e.notifyTimeout&&(clearTimeout(e.notifyTimeout),e.notifyTimeout=void 0)}var r9=function(){function e(e,t){void 0===t&&(t=e.generateQueryId()),this.queryId=t,this.listeners=new Set,this.document=null,this.lastRequestId=1,this.subscriptions=new Set,this.stopped=!1,this.dirty=!1,this.observableQuery=null;var n=this.cache=e.cache;r6.has(n)||(r6.set(n,0),r5(n,"evict"),r5(n,"modify"),r5(n,"reset"))}return e.prototype.init=function(e){var t=e.networkStatus||nZ.I.loading;return this.variables&&this.networkStatus!==nZ.I.loading&&!(0,nm.D)(this.variables,e.variables)&&(t=nZ.I.setVariables),(0,nm.D)(e.variables,this.variables)||(this.lastDiff=void 0),Object.assign(this,{document:e.document,variables:e.variables,networkError:null,graphQLErrors:this.graphQLErrors||[],networkStatus:t}),e.observableQuery&&this.setObservableQuery(e.observableQuery),e.lastRequestId&&(this.lastRequestId=e.lastRequestId),this},e.prototype.reset=function(){r8(this),this.dirty=!1},e.prototype.getDiff=function(e){void 0===e&&(e=this.variables);var t=this.getDiffOptions(e);if(this.lastDiff&&(0,nm.D)(t,this.lastDiff.options))return this.lastDiff.diff;this.updateWatch(this.variables=e);var n=this.observableQuery;if(n&&"no-cache"===n.options.fetchPolicy)return{complete:!1};var r=this.cache.diff(t);return this.updateLastDiff(r,t),r},e.prototype.updateLastDiff=function(e,t){this.lastDiff=e?{diff:e,options:t||this.getDiffOptions()}:void 0},e.prototype.getDiffOptions=function(e){var t;return void 0===e&&(e=this.variables),{query:this.document,variables:e,returnPartialData:!0,optimistic:!0,canonizeResults:null===(t=this.observableQuery)||void 0===t?void 0:t.options.canonizeResults}},e.prototype.setDiff=function(e){var t=this,n=this.lastDiff&&this.lastDiff.diff;this.updateLastDiff(e),this.dirty||(0,nm.D)(n&&n.result,e&&e.result)||(this.dirty=!0,this.notifyTimeout||(this.notifyTimeout=setTimeout(function(){return t.notify()},0)))},e.prototype.setObservableQuery=function(e){var t=this;e!==this.observableQuery&&(this.oqListener&&this.listeners.delete(this.oqListener),this.observableQuery=e,e?(e.queryInfo=this,this.listeners.add(this.oqListener=function(){t.getDiff().fromOptimisticTransaction?e.observe():n4(e)})):delete this.oqListener)},e.prototype.notify=function(){var e=this;r8(this),this.shouldNotify()&&this.listeners.forEach(function(t){return t(e)}),this.dirty=!1},e.prototype.shouldNotify=function(){if(!this.dirty||!this.listeners.size)return!1;if((0,nZ.O)(this.networkStatus)&&this.observableQuery){var e=this.observableQuery.options.fetchPolicy;if("cache-only"!==e&&"cache-and-network"!==e)return!1}return!0},e.prototype.stop=function(){if(!this.stopped){this.stopped=!0,this.reset(),this.cancel(),this.cancel=e.prototype.cancel,this.subscriptions.forEach(function(e){return e.unsubscribe()});var t=this.observableQuery;t&&t.stopPolling()}},e.prototype.cancel=function(){},e.prototype.updateWatch=function(e){var t=this;void 0===e&&(e=this.variables);var n=this.observableQuery;if(!n||"no-cache"!==n.options.fetchPolicy){var r=(0,en.pi)((0,en.pi)({},this.getDiffOptions(e)),{watcher:this,callback:function(e){return t.setDiff(e)}});this.lastWatch&&(0,nm.D)(r,this.lastWatch)||(this.cancel(),this.cancel=this.cache.watch(this.lastWatch=r))}},e.prototype.resetLastWrite=function(){this.lastWrite=void 0},e.prototype.shouldWrite=function(e,t){var n=this.lastWrite;return!(n&&n.dmCount===r6.get(this.cache)&&(0,nm.D)(t,n.variables)&&(0,nm.D)(e.data,n.result.data))},e.prototype.markResult=function(e,t,n,r){var i=this,a=new tB,o=(0,tP.O)(e.errors)?e.errors.slice(0):[];if(this.reset(),"incremental"in e&&(0,tP.O)(e.incremental)){var s=tG(this.getDiff().result,e);e.data=s}else if("hasNext"in e&&e.hasNext){var u=this.getDiff();e.data=a.merge(u.result,e.data)}this.graphQLErrors=o,"no-cache"===n.fetchPolicy?this.updateLastDiff({result:e.data,complete:!0},this.getDiffOptions(n.variables)):0!==r&&(r7(e,n.errorPolicy)?this.cache.performTransaction(function(a){if(i.shouldWrite(e,n.variables))a.writeQuery({query:t,data:e.data,variables:n.variables,overwrite:1===r}),i.lastWrite={result:e,variables:n.variables,dmCount:r6.get(i.cache)};else if(i.lastDiff&&i.lastDiff.diff.complete){e.data=i.lastDiff.diff.result;return}var o=i.getDiffOptions(n.variables),s=a.diff(o);i.stopped||i.updateWatch(n.variables),i.updateLastDiff(s,o),s.complete&&(e.data=s.result)}):this.lastWrite=void 0)},e.prototype.markReady=function(){return this.networkError=null,this.networkStatus=nZ.I.ready},e.prototype.markError=function(e){return this.networkStatus=nZ.I.error,this.lastWrite=void 0,this.reset(),e.graphQLErrors&&(this.graphQLErrors=e.graphQLErrors),e.networkError&&(this.networkError=e.networkError),e},e}();function r7(e,t){void 0===t&&(t="none");var n="ignore"===t||"all"===t,r=!nO(e);return!r&&n&&e.data&&(r=!0),r}var ie=Object.prototype.hasOwnProperty,it=function(){function e(e){var t=e.cache,n=e.link,r=e.defaultOptions,i=e.queryDeduplication,a=void 0!==i&&i,o=e.onBroadcast,s=e.ssrMode,u=void 0!==s&&s,c=e.clientAwareness,l=void 0===c?{}:c,f=e.localState,d=e.assumeImmutableResults;this.clientAwareness={},this.queries=new Map,this.fetchCancelFns=new Map,this.transformCache=new(t_.mr?WeakMap:Map),this.queryIdCounter=1,this.requestIdCounter=1,this.mutationIdCounter=1,this.inFlightLinkObservables=new Map,this.cache=t,this.link=n,this.defaultOptions=r||Object.create(null),this.queryDeduplication=a,this.clientAwareness=l,this.localState=f||new r4({cache:t}),this.ssrMode=u,this.assumeImmutableResults=!!d,(this.onBroadcast=o)&&(this.mutationStore=Object.create(null))}return e.prototype.stop=function(){var e=this;this.queries.forEach(function(t,n){e.stopQueryNoBroadcast(n)}),this.cancelPendingFetches(__DEV__?new Q.ej("QueryManager stopped while query was in flight"):new Q.ej(14))},e.prototype.cancelPendingFetches=function(e){this.fetchCancelFns.forEach(function(t){return t(e)}),this.fetchCancelFns.clear()},e.prototype.mutate=function(e){var t,n,r=e.mutation,i=e.variables,a=e.optimisticResponse,o=e.updateQueries,s=e.refetchQueries,u=void 0===s?[]:s,c=e.awaitRefetchQueries,l=void 0!==c&&c,f=e.update,d=e.onQueryUpdated,h=e.fetchPolicy,p=void 0===h?(null===(t=this.defaultOptions.mutate)||void 0===t?void 0:t.fetchPolicy)||"network-only":h,b=e.errorPolicy,m=void 0===b?(null===(n=this.defaultOptions.mutate)||void 0===n?void 0:n.errorPolicy)||"none":b,g=e.keepRootFields,v=e.context;return(0,en.mG)(this,void 0,void 0,function(){var e,t,n,s,c,h;return(0,en.Jh)(this,function(b){switch(b.label){case 0:if(__DEV__?(0,Q.kG)(r,"mutation option is required. You must specify your GraphQL document in the mutation option."):(0,Q.kG)(r,15),__DEV__?(0,Q.kG)("network-only"===p||"no-cache"===p,"Mutations support only 'network-only' or 'no-cache' fetchPolicy strings. The default `network-only` behavior automatically writes mutation results to the cache. Passing `no-cache` skips the cache write."):(0,Q.kG)("network-only"===p||"no-cache"===p,16),e=this.generateMutationId(),n=(t=this.transform(r)).document,s=t.hasClientExports,r=this.cache.transformForLink(n),i=this.getVariables(r,i),!s)return[3,2];return[4,this.localState.addExportedVariables(r,i,v)];case 1:i=b.sent(),b.label=2;case 2:return c=this.mutationStore&&(this.mutationStore[e]={mutation:r,variables:i,loading:!0,error:null}),a&&this.markMutationOptimistic(a,{mutationId:e,document:r,variables:i,fetchPolicy:p,errorPolicy:m,context:v,updateQueries:o,update:f,keepRootFields:g}),this.broadcastQueries(),h=this,[2,new Promise(function(t,n){return nM(h.getObservableFromLink(r,(0,en.pi)((0,en.pi)({},v),{optimisticResponse:a}),i,!1),function(t){if(nO(t)&&"none"===m)throw new tN.cA({graphQLErrors:nA(t)});c&&(c.loading=!1,c.error=null);var n=(0,en.pi)({},t);return"function"==typeof u&&(u=u(n)),"ignore"===m&&nO(n)&&delete n.errors,h.markMutationResult({mutationId:e,result:n,document:r,variables:i,fetchPolicy:p,errorPolicy:m,context:v,update:f,updateQueries:o,awaitRefetchQueries:l,refetchQueries:u,removeOptimistic:a?e:void 0,onQueryUpdated:d,keepRootFields:g})}).subscribe({next:function(e){h.broadcastQueries(),"hasNext"in e&&!1!==e.hasNext||t(e)},error:function(t){c&&(c.loading=!1,c.error=t),a&&h.cache.removeOptimistic(e),h.broadcastQueries(),n(t instanceof tN.cA?t:new tN.cA({networkError:t}))}})})]}})})},e.prototype.markMutationResult=function(e,t){var n=this;void 0===t&&(t=this.cache);var r=e.result,i=[],a="no-cache"===e.fetchPolicy;if(!a&&r7(r,e.errorPolicy)){if(tU(r)||i.push({result:r.data,dataId:"ROOT_MUTATION",query:e.document,variables:e.variables}),tU(r)&&(0,tP.O)(r.incremental)){var o=t.diff({id:"ROOT_MUTATION",query:this.transform(e.document).asQuery,variables:e.variables,optimistic:!1,returnPartialData:!0}),s=void 0;o.result&&(s=tG(o.result,r)),void 0!==s&&(r.data=s,i.push({result:s,dataId:"ROOT_MUTATION",query:e.document,variables:e.variables}))}var u=e.updateQueries;u&&this.queries.forEach(function(e,a){var o=e.observableQuery,s=o&&o.queryName;if(s&&ie.call(u,s)){var c,l=u[s],f=n.queries.get(a),d=f.document,h=f.variables,p=t.diff({query:d,variables:h,returnPartialData:!0,optimistic:!1}),b=p.result;if(p.complete&&b){var m=l(b,{mutationResult:r,queryName:d&&e3(d)||void 0,queryVariables:h});m&&i.push({result:m,dataId:"ROOT_QUERY",query:d,variables:h})}}})}if(i.length>0||e.refetchQueries||e.update||e.onQueryUpdated||e.removeOptimistic){var c=[];if(this.refetchQueries({updateCache:function(t){a||i.forEach(function(e){return t.write(e)});var o=e.update,s=!t$(r)||tU(r)&&!r.hasNext;if(o){if(!a){var u=t.diff({id:"ROOT_MUTATION",query:n.transform(e.document).asQuery,variables:e.variables,optimistic:!1,returnPartialData:!0});u.complete&&("incremental"in(r=(0,en.pi)((0,en.pi)({},r),{data:u.result}))&&delete r.incremental,"hasNext"in r&&delete r.hasNext)}s&&o(t,r,{context:e.context,variables:e.variables})}a||e.keepRootFields||!s||t.modify({id:"ROOT_MUTATION",fields:function(e,t){var n=t.fieldName,r=t.DELETE;return"__typename"===n?e:r}})},include:e.refetchQueries,optimistic:!1,removeOptimistic:e.removeOptimistic,onQueryUpdated:e.onQueryUpdated||null}).forEach(function(e){return c.push(e)}),e.awaitRefetchQueries||e.onQueryUpdated)return Promise.all(c).then(function(){return r})}return Promise.resolve(r)},e.prototype.markMutationOptimistic=function(e,t){var n=this,r="function"==typeof e?e(t.variables):e;return this.cache.recordOptimisticTransaction(function(e){try{n.markMutationResult((0,en.pi)((0,en.pi)({},t),{result:{data:r}}),e)}catch(i){__DEV__&&Q.kG.error(i)}},t.mutationId)},e.prototype.fetchQuery=function(e,t,n){return this.fetchQueryObservable(e,t,n).promise},e.prototype.getQueryStore=function(){var e=Object.create(null);return this.queries.forEach(function(t,n){e[n]={variables:t.variables,networkStatus:t.networkStatus,networkError:t.networkError,graphQLErrors:t.graphQLErrors}}),e},e.prototype.resetErrors=function(e){var t=this.queries.get(e);t&&(t.networkError=void 0,t.graphQLErrors=[])},e.prototype.transform=function(e){var t=this.transformCache;if(!t.has(e)){var n=this.cache.transformDocument(e),r=nY(n),i=this.localState.clientQuery(n),a=r&&this.localState.serverQuery(r),o={document:n,hasClientExports:tm(n),hasForcedResolvers:this.localState.shouldForceResolvers(n),clientQuery:i,serverQuery:a,defaultVars:e9(e2(n)),asQuery:(0,en.pi)((0,en.pi)({},n),{definitions:n.definitions.map(function(e){return"OperationDefinition"===e.kind&&"query"!==e.operation?(0,en.pi)((0,en.pi)({},e),{operation:"query"}):e})})},s=function(e){e&&!t.has(e)&&t.set(e,o)};s(e),s(n),s(i),s(a)}return t.get(e)},e.prototype.getVariables=function(e,t){return(0,en.pi)((0,en.pi)({},this.transform(e).defaultVars),t)},e.prototype.watchQuery=function(e){void 0===(e=(0,en.pi)((0,en.pi)({},e),{variables:this.getVariables(e.query,e.variables)})).notifyOnNetworkStatusChange&&(e.notifyOnNetworkStatusChange=!1);var t=new r9(this),n=new n3({queryManager:this,queryInfo:t,options:e});return this.queries.set(n.queryId,t),t.init({document:n.query,observableQuery:n,variables:n.variables}),n},e.prototype.query=function(e,t){var n=this;return void 0===t&&(t=this.generateQueryId()),__DEV__?(0,Q.kG)(e.query,"query option is required. You must specify your GraphQL document in the query option."):(0,Q.kG)(e.query,17),__DEV__?(0,Q.kG)("Document"===e.query.kind,'You must wrap the query string in a "gql" tag.'):(0,Q.kG)("Document"===e.query.kind,18),__DEV__?(0,Q.kG)(!e.returnPartialData,"returnPartialData option only supported on watchQuery."):(0,Q.kG)(!e.returnPartialData,19),__DEV__?(0,Q.kG)(!e.pollInterval,"pollInterval option only supported on watchQuery."):(0,Q.kG)(!e.pollInterval,20),this.fetchQuery(t,e).finally(function(){return n.stopQuery(t)})},e.prototype.generateQueryId=function(){return String(this.queryIdCounter++)},e.prototype.generateRequestId=function(){return this.requestIdCounter++},e.prototype.generateMutationId=function(){return String(this.mutationIdCounter++)},e.prototype.stopQueryInStore=function(e){this.stopQueryInStoreNoBroadcast(e),this.broadcastQueries()},e.prototype.stopQueryInStoreNoBroadcast=function(e){var t=this.queries.get(e);t&&t.stop()},e.prototype.clearStore=function(e){return void 0===e&&(e={discardWatches:!0}),this.cancelPendingFetches(__DEV__?new Q.ej("Store reset while query was in flight (not completed in link chain)"):new Q.ej(21)),this.queries.forEach(function(e){e.observableQuery?e.networkStatus=nZ.I.loading:e.stop()}),this.mutationStore&&(this.mutationStore=Object.create(null)),this.cache.reset(e)},e.prototype.getObservableQueries=function(e){var t=this;void 0===e&&(e="active");var n=new Map,r=new Map,i=new Set;return Array.isArray(e)&&e.forEach(function(e){"string"==typeof e?r.set(e,!1):eN(e)?r.set(t.transform(e).document,!1):(0,eO.s)(e)&&e.query&&i.add(e)}),this.queries.forEach(function(t,i){var a=t.observableQuery,o=t.document;if(a){if("all"===e){n.set(i,a);return}var s=a.queryName;if("standby"===a.options.fetchPolicy||"active"===e&&!a.hasObservers())return;("active"===e||s&&r.has(s)||o&&r.has(o))&&(n.set(i,a),s&&r.set(s,!0),o&&r.set(o,!0))}}),i.size&&i.forEach(function(e){var r=nG("legacyOneTimeQuery"),i=t.getQuery(r).init({document:e.query,variables:e.variables}),a=new n3({queryManager:t,queryInfo:i,options:(0,en.pi)((0,en.pi)({},e),{fetchPolicy:"network-only"})});(0,Q.kG)(a.queryId===r),i.setObservableQuery(a),n.set(r,a)}),__DEV__&&r.size&&r.forEach(function(e,t){!e&&__DEV__&&Q.kG.warn("Unknown query ".concat("string"==typeof t?"named ":"").concat(JSON.stringify(t,null,2)," requested in refetchQueries options.include array"))}),n},e.prototype.reFetchObservableQueries=function(e){var t=this;void 0===e&&(e=!1);var n=[];return this.getObservableQueries(e?"all":"active").forEach(function(r,i){var a=r.options.fetchPolicy;r.resetLastResults(),(e||"standby"!==a&&"cache-only"!==a)&&n.push(r.refetch()),t.getQuery(i).setDiff(null)}),this.broadcastQueries(),Promise.all(n)},e.prototype.setObservableQuery=function(e){this.getQuery(e.queryId).setObservableQuery(e)},e.prototype.startGraphQLSubscription=function(e){var t=this,n=e.query,r=e.fetchPolicy,i=e.errorPolicy,a=e.variables,o=e.context,s=void 0===o?{}:o;n=this.transform(n).document,a=this.getVariables(n,a);var u=function(e){return t.getObservableFromLink(n,s,e).map(function(a){"no-cache"!==r&&(r7(a,i)&&t.cache.write({query:n,result:a.data,dataId:"ROOT_SUBSCRIPTION",variables:e}),t.broadcastQueries());var o=nO(a),s=(0,tN.ls)(a);if(o||s){var u={};throw o&&(u.graphQLErrors=a.errors),s&&(u.protocolErrors=a.extensions[tN.YG]),new tN.cA(u)}return a})};if(this.transform(n).hasClientExports){var c=this.localState.addExportedVariables(n,a,s).then(u);return new eT(function(e){var t=null;return c.then(function(n){return t=n.subscribe(e)},e.error),function(){return t&&t.unsubscribe()}})}return u(a)},e.prototype.stopQuery=function(e){this.stopQueryNoBroadcast(e),this.broadcastQueries()},e.prototype.stopQueryNoBroadcast=function(e){this.stopQueryInStoreNoBroadcast(e),this.removeQuery(e)},e.prototype.removeQuery=function(e){this.fetchCancelFns.delete(e),this.queries.has(e)&&(this.getQuery(e).stop(),this.queries.delete(e))},e.prototype.broadcastQueries=function(){this.onBroadcast&&this.onBroadcast(),this.queries.forEach(function(e){return e.notify()})},e.prototype.getLocalState=function(){return this.localState},e.prototype.getObservableFromLink=function(e,t,n,r){var i,a,o=this;void 0===r&&(r=null!==(i=null==t?void 0:t.queryDeduplication)&&void 0!==i?i:this.queryDeduplication);var s=this.transform(e).serverQuery;if(s){var u=this,c=u.inFlightLinkObservables,l=u.link,f={query:s,variables:n,operationName:e3(s)||void 0,context:this.prepareContext((0,en.pi)((0,en.pi)({},t),{forceFetch:!r}))};if(t=f.context,r){var d=c.get(s)||new Map;c.set(s,d);var h=nx(n);if(!(a=d.get(h))){var p=new nq([np(l,f)]);d.set(h,a=p),p.beforeNext(function(){d.delete(h)&&d.size<1&&c.delete(s)})}}else a=new nq([np(l,f)])}else a=new nq([eT.of({data:{}})]),t=this.prepareContext(t);var b=this.transform(e).clientQuery;return b&&(a=nM(a,function(e){return o.localState.runResolvers({document:b,remoteResult:e,context:t,variables:n})})),a},e.prototype.getResultsFromLink=function(e,t,n){var r=e.lastRequestId=this.generateRequestId(),i=this.cache.transformForLink(this.transform(e.document).document);return nM(this.getObservableFromLink(i,n.context,n.variables),function(a){var o=nA(a),s=o.length>0;if(r>=e.lastRequestId){if(s&&"none"===n.errorPolicy)throw e.markError(new tN.cA({graphQLErrors:o}));e.markResult(a,i,n,t),e.markReady()}var u={data:a.data,loading:!1,networkStatus:nZ.I.ready};return s&&"ignore"!==n.errorPolicy&&(u.errors=o,u.networkStatus=nZ.I.error),u},function(t){var n=(0,tN.MS)(t)?t:new tN.cA({networkError:t});throw r>=e.lastRequestId&&e.markError(n),n})},e.prototype.fetchQueryObservable=function(e,t,n){return this.fetchConcastWithInfo(e,t,n).concast},e.prototype.fetchConcastWithInfo=function(e,t,n){var r,i,a=this;void 0===n&&(n=nZ.I.loading);var o=this.transform(t.query).document,s=this.getVariables(o,t.variables),u=this.getQuery(e),c=this.defaultOptions.watchQuery,l=t.fetchPolicy,f=void 0===l?c&&c.fetchPolicy||"cache-first":l,d=t.errorPolicy,h=void 0===d?c&&c.errorPolicy||"none":d,p=t.returnPartialData,b=void 0!==p&&p,m=t.notifyOnNetworkStatusChange,g=void 0!==m&&m,v=t.context,y=void 0===v?{}:v,w=Object.assign({},t,{query:o,variables:s,fetchPolicy:f,errorPolicy:h,returnPartialData:b,notifyOnNetworkStatusChange:g,context:y}),_=function(e){w.variables=e;var r=a.fetchQueryByPolicy(u,w,n);return"standby"!==w.fetchPolicy&&r.sources.length>0&&u.observableQuery&&u.observableQuery.applyNextFetchPolicy("after-fetch",t),r},E=function(){return a.fetchCancelFns.delete(e)};if(this.fetchCancelFns.set(e,function(e){E(),setTimeout(function(){return r.cancel(e)})}),this.transform(w.query).hasClientExports)r=new nq(this.localState.addExportedVariables(w.query,w.variables,w.context).then(_).then(function(e){return e.sources})),i=!0;else{var S=_(w.variables);i=S.fromLink,r=new nq(S.sources)}return r.promise.then(E,E),{concast:r,fromLink:i}},e.prototype.refetchQueries=function(e){var t=this,n=e.updateCache,r=e.include,i=e.optimistic,a=void 0!==i&&i,o=e.removeOptimistic,s=void 0===o?a?nG("refetchQueries"):void 0:o,u=e.onQueryUpdated,c=new Map;r&&this.getObservableQueries(r).forEach(function(e,n){c.set(n,{oq:e,lastDiff:t.getQuery(n).getDiff()})});var l=new Map;return n&&this.cache.batch({update:n,optimistic:a&&s||!1,removeOptimistic:s,onWatchUpdated:function(e,t,n){var r=e.watcher instanceof r9&&e.watcher.observableQuery;if(r){if(u){c.delete(r.queryId);var i=u(r,t,n);return!0===i&&(i=r.refetch()),!1!==i&&l.set(r,i),i}null!==u&&c.set(r.queryId,{oq:r,lastDiff:n,diff:t})}}}),c.size&&c.forEach(function(e,n){var r,i=e.oq,a=e.lastDiff,o=e.diff;if(u){if(!o){var s=i.queryInfo;s.reset(),o=s.getDiff()}r=u(i,o,a)}u&&!0!==r||(r=i.refetch()),!1!==r&&l.set(i,r),n.indexOf("legacyOneTimeQuery")>=0&&t.stopQueryNoBroadcast(n)}),s&&this.cache.removeOptimistic(s),l},e.prototype.fetchQueryByPolicy=function(e,t,n){var r=this,i=t.query,a=t.variables,o=t.fetchPolicy,s=t.refetchWritePolicy,u=t.errorPolicy,c=t.returnPartialData,l=t.context,f=t.notifyOnNetworkStatusChange,d=e.networkStatus;e.init({document:this.transform(i).document,variables:a,networkStatus:n});var h=function(){return e.getDiff(a)},p=function(t,n){void 0===n&&(n=e.networkStatus||nZ.I.loading);var o=t.result;!__DEV__||c||(0,nm.D)(o,{})||n5(t.missing);var s=function(e){return eT.of((0,en.pi)({data:e,loading:(0,nZ.O)(n),networkStatus:n},t.complete?null:{partial:!0}))};return o&&r.transform(i).hasForcedResolvers?r.localState.runResolvers({document:i,remoteResult:{data:o},context:l,variables:a,onlyRunForcedResolvers:!0}).then(function(e){return s(e.data||void 0)}):"none"===u&&n===nZ.I.refetch&&Array.isArray(t.missing)?s(void 0):s(o)},b="no-cache"===o?0:n===nZ.I.refetch&&"merge"!==s?1:2,m=function(){return r.getResultsFromLink(e,b,{variables:a,context:l,fetchPolicy:o,errorPolicy:u})},g=f&&"number"==typeof d&&d!==n&&(0,nZ.O)(n);switch(o){default:case"cache-first":var v=h();if(v.complete)return{fromLink:!1,sources:[p(v,e.markReady())]};if(c||g)return{fromLink:!0,sources:[p(v),m()]};return{fromLink:!0,sources:[m()]};case"cache-and-network":var v=h();if(v.complete||c||g)return{fromLink:!0,sources:[p(v),m()]};return{fromLink:!0,sources:[m()]};case"cache-only":return{fromLink:!1,sources:[p(h(),e.markReady())]};case"network-only":if(g)return{fromLink:!0,sources:[p(h()),m()]};return{fromLink:!0,sources:[m()]};case"no-cache":if(g)return{fromLink:!0,sources:[p(e.getDiff()),m(),]};return{fromLink:!0,sources:[m()]};case"standby":return{fromLink:!1,sources:[]}}},e.prototype.getQuery=function(e){return e&&!this.queries.has(e)&&this.queries.set(e,new r9(this,e)),this.queries.get(e)},e.prototype.prepareContext=function(e){void 0===e&&(e={});var t=this.localState.prepareContext(e);return(0,en.pi)((0,en.pi)({},t),{clientAwareness:this.clientAwareness})},e}(),ir=__webpack_require__(14012),ii=!1,ia=function(){function e(e){var t=this;this.resetStoreCallbacks=[],this.clearStoreCallbacks=[];var n=e.uri,r=e.credentials,i=e.headers,a=e.cache,o=e.ssrMode,s=void 0!==o&&o,u=e.ssrForceFetchDelay,c=void 0===u?0:u,l=e.connectToDevTools,f=void 0===l?"object"==typeof window&&!window.__APOLLO_CLIENT__&&__DEV__:l,d=e.queryDeduplication,h=void 0===d||d,p=e.defaultOptions,b=e.assumeImmutableResults,m=void 0!==b&&b,g=e.resolvers,v=e.typeDefs,y=e.fragmentMatcher,w=e.name,_=e.version,E=e.link;if(E||(E=n?new nh({uri:n,credentials:r,headers:i}):ta.empty()),!a)throw __DEV__?new Q.ej("To initialize Apollo Client, you must specify a 'cache' property in the options object. \nFor more information, please visit: https://go.apollo.dev/c/docs"):new Q.ej(9);if(this.link=E,this.cache=a,this.disableNetworkFetches=s||c>0,this.queryDeduplication=h,this.defaultOptions=p||Object.create(null),this.typeDefs=v,c&&setTimeout(function(){return t.disableNetworkFetches=!1},c),this.watchQuery=this.watchQuery.bind(this),this.query=this.query.bind(this),this.mutate=this.mutate.bind(this),this.resetStore=this.resetStore.bind(this),this.reFetchObservableQueries=this.reFetchObservableQueries.bind(this),f&&"object"==typeof window&&(window.__APOLLO_CLIENT__=this),!ii&&f&&__DEV__&&(ii=!0,"undefined"!=typeof window&&window.document&&window.top===window.self&&!window.__APOLLO_DEVTOOLS_GLOBAL_HOOK__)){var S=window.navigator,k=S&&S.userAgent,x=void 0;"string"==typeof k&&(k.indexOf("Chrome/")>-1?x="https://chrome.google.com/webstore/detail/apollo-client-developer-t/jdkknkkbebbapilgoeccciglkfbmbnfm":k.indexOf("Firefox/")>-1&&(x="https://addons.mozilla.org/en-US/firefox/addon/apollo-developer-tools/")),x&&__DEV__&&Q.kG.log("Download the Apollo DevTools for a better development experience: "+x)}this.version=nb,this.localState=new r4({cache:a,client:this,resolvers:g,fragmentMatcher:y}),this.queryManager=new it({cache:this.cache,link:this.link,defaultOptions:this.defaultOptions,queryDeduplication:h,ssrMode:s,clientAwareness:{name:w,version:_},localState:this.localState,assumeImmutableResults:m,onBroadcast:f?function(){t.devToolsHookCb&&t.devToolsHookCb({action:{},state:{queries:t.queryManager.getQueryStore(),mutations:t.queryManager.mutationStore||{}},dataWithOptimisticResults:t.cache.extract(!0)})}:void 0})}return e.prototype.stop=function(){this.queryManager.stop()},e.prototype.watchQuery=function(e){return this.defaultOptions.watchQuery&&(e=(0,ir.J)(this.defaultOptions.watchQuery,e)),this.disableNetworkFetches&&("network-only"===e.fetchPolicy||"cache-and-network"===e.fetchPolicy)&&(e=(0,en.pi)((0,en.pi)({},e),{fetchPolicy:"cache-first"})),this.queryManager.watchQuery(e)},e.prototype.query=function(e){return this.defaultOptions.query&&(e=(0,ir.J)(this.defaultOptions.query,e)),__DEV__?(0,Q.kG)("cache-and-network"!==e.fetchPolicy,"The cache-and-network fetchPolicy does not work with client.query, because client.query can only return a single result. Please use client.watchQuery to receive multiple results from the cache and the network, or consider using a different fetchPolicy, such as cache-first or network-only."):(0,Q.kG)("cache-and-network"!==e.fetchPolicy,10),this.disableNetworkFetches&&"network-only"===e.fetchPolicy&&(e=(0,en.pi)((0,en.pi)({},e),{fetchPolicy:"cache-first"})),this.queryManager.query(e)},e.prototype.mutate=function(e){return this.defaultOptions.mutate&&(e=(0,ir.J)(this.defaultOptions.mutate,e)),this.queryManager.mutate(e)},e.prototype.subscribe=function(e){return this.queryManager.startGraphQLSubscription(e)},e.prototype.readQuery=function(e,t){return void 0===t&&(t=!1),this.cache.readQuery(e,t)},e.prototype.readFragment=function(e,t){return void 0===t&&(t=!1),this.cache.readFragment(e,t)},e.prototype.writeQuery=function(e){var t=this.cache.writeQuery(e);return!1!==e.broadcast&&this.queryManager.broadcastQueries(),t},e.prototype.writeFragment=function(e){var t=this.cache.writeFragment(e);return!1!==e.broadcast&&this.queryManager.broadcastQueries(),t},e.prototype.__actionHookForDevTools=function(e){this.devToolsHookCb=e},e.prototype.__requestRaw=function(e){return np(this.link,e)},e.prototype.resetStore=function(){var e=this;return Promise.resolve().then(function(){return e.queryManager.clearStore({discardWatches:!1})}).then(function(){return Promise.all(e.resetStoreCallbacks.map(function(e){return e()}))}).then(function(){return e.reFetchObservableQueries()})},e.prototype.clearStore=function(){var e=this;return Promise.resolve().then(function(){return e.queryManager.clearStore({discardWatches:!0})}).then(function(){return Promise.all(e.clearStoreCallbacks.map(function(e){return e()}))})},e.prototype.onResetStore=function(e){var t=this;return this.resetStoreCallbacks.push(e),function(){t.resetStoreCallbacks=t.resetStoreCallbacks.filter(function(t){return t!==e})}},e.prototype.onClearStore=function(e){var t=this;return this.clearStoreCallbacks.push(e),function(){t.clearStoreCallbacks=t.clearStoreCallbacks.filter(function(t){return t!==e})}},e.prototype.reFetchObservableQueries=function(e){return this.queryManager.reFetchObservableQueries(e)},e.prototype.refetchQueries=function(e){var t=this.queryManager.refetchQueries(e),n=[],r=[];t.forEach(function(e,t){n.push(t),r.push(e)});var i=Promise.all(r);return i.queries=n,i.results=r,i.catch(function(e){__DEV__&&Q.kG.debug("In client.refetchQueries, Promise.all promise rejected with error ".concat(e))}),i},e.prototype.getObservableQueries=function(e){return void 0===e&&(e="active"),this.queryManager.getObservableQueries(e)},e.prototype.extract=function(e){return this.cache.extract(e)},e.prototype.restore=function(e){return this.cache.restore(e)},e.prototype.addResolvers=function(e){this.localState.addResolvers(e)},e.prototype.setResolvers=function(e){this.localState.setResolvers(e)},e.prototype.getResolvers=function(){return this.localState.getResolvers()},e.prototype.setLocalStateFragmentMatcher=function(e){this.localState.setFragmentMatcher(e)},e.prototype.setLink=function(e){this.link=this.queryManager.link=e},e}(),io=function(){function e(){this.getFragmentDoc=rZ(eA)}return e.prototype.batch=function(e){var t,n=this,r="string"==typeof e.optimistic?e.optimistic:!1===e.optimistic?null:void 0;return this.performTransaction(function(){return t=e.update(n)},r),t},e.prototype.recordOptimisticTransaction=function(e,t){this.performTransaction(e,t)},e.prototype.transformDocument=function(e){return e},e.prototype.transformForLink=function(e){return e},e.prototype.identify=function(e){},e.prototype.gc=function(){return[]},e.prototype.modify=function(e){return!1},e.prototype.readQuery=function(e,t){return void 0===t&&(t=!!e.optimistic),this.read((0,en.pi)((0,en.pi)({},e),{rootId:e.id||"ROOT_QUERY",optimistic:t}))},e.prototype.readFragment=function(e,t){return void 0===t&&(t=!!e.optimistic),this.read((0,en.pi)((0,en.pi)({},e),{query:this.getFragmentDoc(e.fragment,e.fragmentName),rootId:e.id,optimistic:t}))},e.prototype.writeQuery=function(e){var t=e.id,n=e.data,r=(0,en._T)(e,["id","data"]);return this.write(Object.assign(r,{dataId:t||"ROOT_QUERY",result:n}))},e.prototype.writeFragment=function(e){var t=e.id,n=e.data,r=e.fragment,i=e.fragmentName,a=(0,en._T)(e,["id","data","fragment","fragmentName"]);return this.write(Object.assign(a,{query:this.getFragmentDoc(r,i),dataId:t,result:n}))},e.prototype.updateQuery=function(e,t){return this.batch({update:function(n){var r=n.readQuery(e),i=t(r);return null==i?r:(n.writeQuery((0,en.pi)((0,en.pi)({},e),{data:i})),i)}})},e.prototype.updateFragment=function(e,t){return this.batch({update:function(n){var r=n.readFragment(e),i=t(r);return null==i?r:(n.writeFragment((0,en.pi)((0,en.pi)({},e),{data:i})),i)}})},e}(),is=function(e){function t(n,r,i,a){var o,s=e.call(this,n)||this;if(s.message=n,s.path=r,s.query=i,s.variables=a,Array.isArray(s.path)){s.missing=s.message;for(var u=s.path.length-1;u>=0;--u)s.missing=((o={})[s.path[u]]=s.missing,o)}else s.missing=s.path;return s.__proto__=t.prototype,s}return(0,en.ZT)(t,e),t}(Error),iu=__webpack_require__(10542),ic=Object.prototype.hasOwnProperty;function il(e){return null==e}function id(e,t){var n=e.__typename,r=e.id,i=e._id;if("string"==typeof n&&(t&&(t.keyObject=il(r)?il(i)?void 0:{_id:i}:{id:r}),il(r)&&!il(i)&&(r=i),!il(r)))return"".concat(n,":").concat("number"==typeof r||"string"==typeof r?r:JSON.stringify(r))}var ih={dataIdFromObject:id,addTypename:!0,resultCaching:!0,canonizeResults:!1};function ip(e){return(0,n1.o)(ih,e)}function ib(e){var t=e.canonizeResults;return void 0===t?ih.canonizeResults:t}function im(e,t){return eD(t)?e.get(t.__ref,"__typename"):t&&t.__typename}var ig=/^[_a-z][_0-9a-z]*/i;function iv(e){var t=e.match(ig);return t?t[0]:e}function iy(e,t,n){return!!(0,eO.s)(t)&&((0,tP.k)(t)?t.every(function(t){return iy(e,t,n)}):e.selections.every(function(e){if(eQ(e)&&td(e,n)){var r=eX(e);return ic.call(t,r)&&(!e.selectionSet||iy(e.selectionSet,t[r],n))}return!0}))}function iw(e){return(0,eO.s)(e)&&!eD(e)&&!(0,tP.k)(e)}function i_(){return new tB}function iE(e,t){var n=eL(e4(e));return{fragmentMap:n,lookupFragment:function(e){var r=n[e];return!r&&t&&(r=t.lookup(e)),r||null}}}var iS=Object.create(null),ik=function(){return iS},ix=Object.create(null),iT=function(){function e(e,t){var n=this;this.policies=e,this.group=t,this.data=Object.create(null),this.rootIds=Object.create(null),this.refs=Object.create(null),this.getFieldValue=function(e,t){return(0,iu.J)(eD(e)?n.get(e.__ref,t):e&&e[t])},this.canRead=function(e){return eD(e)?n.has(e.__ref):"object"==typeof e},this.toReference=function(e,t){if("string"==typeof e)return eI(e);if(eD(e))return e;var r=n.policies.identify(e)[0];if(r){var i=eI(r);return t&&n.merge(r,e),i}}}return e.prototype.toObject=function(){return(0,en.pi)({},this.data)},e.prototype.has=function(e){return void 0!==this.lookup(e,!0)},e.prototype.get=function(e,t){if(this.group.depend(e,t),ic.call(this.data,e)){var n=this.data[e];if(n&&ic.call(n,t))return n[t]}return"__typename"===t&&ic.call(this.policies.rootTypenamesById,e)?this.policies.rootTypenamesById[e]:this instanceof iL?this.parent.get(e,t):void 0},e.prototype.lookup=function(e,t){return(t&&this.group.depend(e,"__exists"),ic.call(this.data,e))?this.data[e]:this instanceof iL?this.parent.lookup(e,t):this.policies.rootTypenamesById[e]?Object.create(null):void 0},e.prototype.merge=function(e,t){var n,r=this;eD(e)&&(e=e.__ref),eD(t)&&(t=t.__ref);var i="string"==typeof e?this.lookup(n=e):e,a="string"==typeof t?this.lookup(n=t):t;if(a){__DEV__?(0,Q.kG)("string"==typeof n,"store.merge expects a string ID"):(0,Q.kG)("string"==typeof n,1);var o=new tB(iI).merge(i,a);if(this.data[n]=o,o!==i&&(delete this.refs[n],this.group.caching)){var s=Object.create(null);i||(s.__exists=1),Object.keys(a).forEach(function(e){if(!i||i[e]!==o[e]){s[e]=1;var t=iv(e);t===e||r.policies.hasKeyArgs(o.__typename,t)||(s[t]=1),void 0!==o[e]||r instanceof iL||delete o[e]}}),s.__typename&&!(i&&i.__typename)&&this.policies.rootTypenamesById[n]===o.__typename&&delete s.__typename,Object.keys(s).forEach(function(e){return r.group.dirty(n,e)})}}},e.prototype.modify=function(e,t){var n=this,r=this.lookup(e);if(r){var i=Object.create(null),a=!1,o=!0,s={DELETE:iS,INVALIDATE:ix,isReference:eD,toReference:this.toReference,canRead:this.canRead,readField:function(t,r){return n.policies.readField("string"==typeof t?{fieldName:t,from:r||eI(e)}:t,{store:n})}};if(Object.keys(r).forEach(function(u){var c=iv(u),l=r[u];if(void 0!==l){var f="function"==typeof t?t:t[u]||t[c];if(f){var d=f===ik?iS:f((0,iu.J)(l),(0,en.pi)((0,en.pi)({},s),{fieldName:c,storeFieldName:u,storage:n.getStorage(e,u)}));d===ix?n.group.dirty(e,u):(d===iS&&(d=void 0),d!==l&&(i[u]=d,a=!0,l=d))}void 0!==l&&(o=!1)}}),a)return this.merge(e,i),o&&(this instanceof iL?this.data[e]=void 0:delete this.data[e],this.group.dirty(e,"__exists")),!0}return!1},e.prototype.delete=function(e,t,n){var r,i=this.lookup(e);if(i){var a=this.getFieldValue(i,"__typename"),o=t&&n?this.policies.getStoreFieldName({typename:a,fieldName:t,args:n}):t;return this.modify(e,o?((r={})[o]=ik,r):ik)}return!1},e.prototype.evict=function(e,t){var n=!1;return e.id&&(ic.call(this.data,e.id)&&(n=this.delete(e.id,e.fieldName,e.args)),this instanceof iL&&this!==t&&(n=this.parent.evict(e,t)||n),(e.fieldName||n)&&this.group.dirty(e.id,e.fieldName||"__exists")),n},e.prototype.clear=function(){this.replace(null)},e.prototype.extract=function(){var e=this,t=this.toObject(),n=[];return this.getRootIdSet().forEach(function(t){ic.call(e.policies.rootTypenamesById,t)||n.push(t)}),n.length&&(t.__META={extraRootIds:n.sort()}),t},e.prototype.replace=function(e){var t=this;if(Object.keys(this.data).forEach(function(n){e&&ic.call(e,n)||t.delete(n)}),e){var n=e.__META,r=(0,en._T)(e,["__META"]);Object.keys(r).forEach(function(e){t.merge(e,r[e])}),n&&n.extraRootIds.forEach(this.retain,this)}},e.prototype.retain=function(e){return this.rootIds[e]=(this.rootIds[e]||0)+1},e.prototype.release=function(e){if(this.rootIds[e]>0){var t=--this.rootIds[e];return t||delete this.rootIds[e],t}return 0},e.prototype.getRootIdSet=function(e){return void 0===e&&(e=new Set),Object.keys(this.rootIds).forEach(e.add,e),this instanceof iL?this.parent.getRootIdSet(e):Object.keys(this.policies.rootTypenamesById).forEach(e.add,e),e},e.prototype.gc=function(){var e=this,t=this.getRootIdSet(),n=this.toObject();t.forEach(function(r){ic.call(n,r)&&(Object.keys(e.findChildRefIds(r)).forEach(t.add,t),delete n[r])});var r=Object.keys(n);if(r.length){for(var i=this;i instanceof iL;)i=i.parent;r.forEach(function(e){return i.delete(e)})}return r},e.prototype.findChildRefIds=function(e){if(!ic.call(this.refs,e)){var t=this.refs[e]=Object.create(null),n=this.data[e];if(!n)return t;var r=new Set([n]);r.forEach(function(e){eD(e)&&(t[e.__ref]=!0),(0,eO.s)(e)&&Object.keys(e).forEach(function(t){var n=e[t];(0,eO.s)(n)&&r.add(n)})})}return this.refs[e]},e.prototype.makeCacheKey=function(){return this.group.keyMaker.lookupArray(arguments)},e}(),iM=function(){function e(e,t){void 0===t&&(t=null),this.caching=e,this.parent=t,this.d=null,this.resetCaching()}return e.prototype.resetCaching=function(){this.d=this.caching?rW():null,this.keyMaker=new n_(t_.mr)},e.prototype.depend=function(e,t){if(this.d){this.d(iO(e,t));var n=iv(t);n!==t&&this.d(iO(e,n)),this.parent&&this.parent.depend(e,t)}},e.prototype.dirty=function(e,t){this.d&&this.d.dirty(iO(e,t),"__exists"===t?"forget":"setDirty")},e}();function iO(e,t){return t+"#"+e}function iA(e,t){iD(e)&&e.group.depend(t,"__exists")}!function(e){var t=function(e){function t(t){var n=t.policies,r=t.resultCaching,i=void 0===r||r,a=t.seed,o=e.call(this,n,new iM(i))||this;return o.stump=new iC(o),o.storageTrie=new n_(t_.mr),a&&o.replace(a),o}return(0,en.ZT)(t,e),t.prototype.addLayer=function(e,t){return this.stump.addLayer(e,t)},t.prototype.removeLayer=function(){return this},t.prototype.getStorage=function(){return this.storageTrie.lookupArray(arguments)},t}(e);e.Root=t}(iT||(iT={}));var iL=function(e){function t(t,n,r,i){var a=e.call(this,n.policies,i)||this;return a.id=t,a.parent=n,a.replay=r,a.group=i,r(a),a}return(0,en.ZT)(t,e),t.prototype.addLayer=function(e,n){return new t(e,this,n,this.group)},t.prototype.removeLayer=function(e){var t=this,n=this.parent.removeLayer(e);return e===this.id?(this.group.caching&&Object.keys(this.data).forEach(function(e){var r=t.data[e],i=n.lookup(e);i?r?r!==i&&Object.keys(r).forEach(function(n){(0,nm.D)(r[n],i[n])||t.group.dirty(e,n)}):(t.group.dirty(e,"__exists"),Object.keys(i).forEach(function(n){t.group.dirty(e,n)})):t.delete(e)}),n):n===this.parent?this:n.addLayer(this.id,this.replay)},t.prototype.toObject=function(){return(0,en.pi)((0,en.pi)({},this.parent.toObject()),this.data)},t.prototype.findChildRefIds=function(t){var n=this.parent.findChildRefIds(t);return ic.call(this.data,t)?(0,en.pi)((0,en.pi)({},n),e.prototype.findChildRefIds.call(this,t)):n},t.prototype.getStorage=function(){for(var e=this.parent;e.parent;)e=e.parent;return e.getStorage.apply(e,arguments)},t}(iT),iC=function(e){function t(t){return e.call(this,"EntityStore.Stump",t,function(){},new iM(t.group.caching,t.group))||this}return(0,en.ZT)(t,e),t.prototype.removeLayer=function(){return this},t.prototype.merge=function(){return this.parent.merge.apply(this.parent,arguments)},t}(iL);function iI(e,t,n){var r=e[n],i=t[n];return(0,nm.D)(r,i)?r:i}function iD(e){return!!(e instanceof iT&&e.group.caching)}function iN(e){return[e.selectionSet,e.objectOrReference,e.context,e.context.canonizeResults,]}var iP=function(){function e(e){var t=this;this.knownResults=new(t_.mr?WeakMap:Map),this.config=(0,n1.o)(e,{addTypename:!1!==e.addTypename,canonizeResults:ib(e)}),this.canon=e.canon||new nk,this.executeSelectionSet=rZ(function(e){var n,r=e.context.canonizeResults,i=iN(e);i[3]=!r;var a=(n=t.executeSelectionSet).peek.apply(n,i);return a?r?(0,en.pi)((0,en.pi)({},a),{result:t.canon.admit(a.result)}):a:(iA(e.context.store,e.enclosingRef.__ref),t.execSelectionSetImpl(e))},{max:this.config.resultCacheMaxSize,keyArgs:iN,makeCacheKey:function(e,t,n,r){if(iD(n.store))return n.store.makeCacheKey(e,eD(t)?t.__ref:t,n.varString,r)}}),this.executeSubSelectedArray=rZ(function(e){return iA(e.context.store,e.enclosingRef.__ref),t.execSubSelectedArrayImpl(e)},{max:this.config.resultCacheMaxSize,makeCacheKey:function(e){var t=e.field,n=e.array,r=e.context;if(iD(r.store))return r.store.makeCacheKey(t,n,r.varString)}})}return e.prototype.resetCanon=function(){this.canon=new nk},e.prototype.diffQueryAgainstStore=function(e){var t,n=e.store,r=e.query,i=e.rootId,a=void 0===i?"ROOT_QUERY":i,o=e.variables,s=e.returnPartialData,u=void 0===s||s,c=e.canonizeResults,l=void 0===c?this.config.canonizeResults:c,f=this.config.cache.policies;o=(0,en.pi)((0,en.pi)({},e9(e6(r))),o);var d=eI(a),h=this.executeSelectionSet({selectionSet:e8(r).selectionSet,objectOrReference:d,enclosingRef:d,context:(0,en.pi)({store:n,query:r,policies:f,variables:o,varString:nx(o),canonizeResults:l},iE(r,this.config.fragments))});if(h.missing&&(t=[new is(iR(h.missing),h.missing,r,o)],!u))throw t[0];return{result:h.result,complete:!t,missing:t}},e.prototype.isFresh=function(e,t,n,r){if(iD(r.store)&&this.knownResults.get(e)===n){var i=this.executeSelectionSet.peek(n,t,r,this.canon.isKnown(e));if(i&&e===i.result)return!0}return!1},e.prototype.execSelectionSetImpl=function(e){var t,n=this,r=e.selectionSet,i=e.objectOrReference,a=e.enclosingRef,o=e.context;if(eD(i)&&!o.policies.rootTypenamesById[i.__ref]&&!o.store.has(i.__ref))return{result:this.canon.empty,missing:"Dangling reference to missing ".concat(i.__ref," object")};var s=o.variables,u=o.policies,c=o.store.getFieldValue(i,"__typename"),l=[],f=new tB;function d(e,n){var r;return e.missing&&(t=f.merge(t,((r={})[n]=e.missing,r))),e.result}this.config.addTypename&&"string"==typeof c&&!u.rootIdsByTypename[c]&&l.push({__typename:c});var h=new Set(r.selections);h.forEach(function(e){var r,p;if(td(e,s)){if(eQ(e)){var b=u.readField({fieldName:e.name.value,field:e,variables:o.variables,from:i},o),m=eX(e);void 0===b?nj.added(e)||(t=f.merge(t,((r={})[m]="Can't find field '".concat(e.name.value,"' on ").concat(eD(i)?i.__ref+" object":"object "+JSON.stringify(i,null,2)),r))):(0,tP.k)(b)?b=d(n.executeSubSelectedArray({field:e,array:b,enclosingRef:a,context:o}),m):e.selectionSet?null!=b&&(b=d(n.executeSelectionSet({selectionSet:e.selectionSet,objectOrReference:b,enclosingRef:eD(b)?b:a,context:o}),m)):o.canonizeResults&&(b=n.canon.pass(b)),void 0!==b&&l.push(((p={})[m]=b,p))}else{var g=eC(e,o.lookupFragment);if(!g&&e.kind===nL.h.FRAGMENT_SPREAD)throw __DEV__?new Q.ej("No fragment named ".concat(e.name.value)):new Q.ej(5);g&&u.fragmentMatches(g,c)&&g.selectionSet.selections.forEach(h.add,h)}}});var p={result:tF(l),missing:t},b=o.canonizeResults?this.canon.admit(p):(0,iu.J)(p);return b.result&&this.knownResults.set(b.result,r),b},e.prototype.execSubSelectedArrayImpl=function(e){var t,n=this,r=e.field,i=e.array,a=e.enclosingRef,o=e.context,s=new tB;function u(e,n){var r;return e.missing&&(t=s.merge(t,((r={})[n]=e.missing,r))),e.result}return r.selectionSet&&(i=i.filter(o.store.canRead)),i=i.map(function(e,t){return null===e?null:(0,tP.k)(e)?u(n.executeSubSelectedArray({field:r,array:e,enclosingRef:a,context:o}),t):r.selectionSet?u(n.executeSelectionSet({selectionSet:r.selectionSet,objectOrReference:e,enclosingRef:eD(e)?e:a,context:o}),t):(__DEV__&&ij(o.store,r,e),e)}),{result:o.canonizeResults?this.canon.admit(i):i,missing:t}},e}();function iR(e){try{JSON.stringify(e,function(e,t){if("string"==typeof t)throw t;return t})}catch(t){return t}}function ij(e,t,n){if(!t.selectionSet){var r=new Set([n]);r.forEach(function(n){(0,eO.s)(n)&&(__DEV__?(0,Q.kG)(!eD(n),"Missing selection set for object of type ".concat(im(e,n)," returned for query field ").concat(t.name.value)):(0,Q.kG)(!eD(n),6),Object.values(n).forEach(r.add,r))})}}function iF(e){var t=nG("stringifyForDisplay");return JSON.stringify(e,function(e,n){return void 0===n?t:n}).split(JSON.stringify(t)).join("")}var iY=Object.create(null);function iB(e){var t=JSON.stringify(e);return iY[t]||(iY[t]=Object.create(null))}function iU(e){var t=iB(e);return t.keyFieldsFn||(t.keyFieldsFn=function(t,n){var r=function(e,t){return n.readField(t,e)},i=n.keyObject=i$(e,function(e){var i=iW(n.storeObject,e,r);return void 0===i&&t!==n.storeObject&&ic.call(t,e[0])&&(i=iW(t,e,iG)),__DEV__?(0,Q.kG)(void 0!==i,"Missing field '".concat(e.join("."),"' while extracting keyFields from ").concat(JSON.stringify(t))):(0,Q.kG)(void 0!==i,2),i});return"".concat(n.typename,":").concat(JSON.stringify(i))})}function iH(e){var t=iB(e);return t.keyArgsFn||(t.keyArgsFn=function(t,n){var r=n.field,i=n.variables,a=n.fieldName,o=JSON.stringify(i$(e,function(e){var n=e[0],a=n.charAt(0);if("@"===a){if(r&&(0,tP.O)(r.directives)){var o=n.slice(1),s=r.directives.find(function(e){return e.name.value===o}),u=s&&eZ(s,i);return u&&iW(u,e.slice(1))}return}if("$"===a){var c=n.slice(1);if(i&&ic.call(i,c)){var l=e.slice(0);return l[0]=c,iW(i,l)}return}if(t)return iW(t,e)}));return(t||"{}"!==o)&&(a+=":"+o),a})}function i$(e,t){var n=new tB;return iz(e).reduce(function(e,r){var i,a=t(r);if(void 0!==a){for(var o=r.length-1;o>=0;--o)a=((i={})[r[o]]=a,i);e=n.merge(e,a)}return e},Object.create(null))}function iz(e){var t=iB(e);if(!t.paths){var n=t.paths=[],r=[];e.forEach(function(t,i){(0,tP.k)(t)?(iz(t).forEach(function(e){return n.push(r.concat(e))}),r.length=0):(r.push(t),(0,tP.k)(e[i+1])||(n.push(r.slice(0)),r.length=0))})}return t.paths}function iG(e,t){return e[t]}function iW(e,t,n){return n=n||iG,iK(t.reduce(function e(t,r){return(0,tP.k)(t)?t.map(function(t){return e(t,r)}):t&&n(t,r)},e))}function iK(e){return(0,eO.s)(e)?(0,tP.k)(e)?e.map(iK):i$(Object.keys(e).sort(),function(t){return iW(e,t)}):e}function iV(e){return void 0!==e.args?e.args:e.field?eZ(e.field,e.variables):null}eK.setStringify(nx);var iq=function(){},iZ=function(e,t){return t.fieldName},iX=function(e,t,n){return(0,n.mergeObjects)(e,t)},iJ=function(e,t){return t},iQ=function(){function e(e){this.config=e,this.typePolicies=Object.create(null),this.toBeAdded=Object.create(null),this.supertypeMap=new Map,this.fuzzySubtypes=new Map,this.rootIdsByTypename=Object.create(null),this.rootTypenamesById=Object.create(null),this.usingPossibleTypes=!1,this.config=(0,en.pi)({dataIdFromObject:id},e),this.cache=this.config.cache,this.setRootTypename("Query"),this.setRootTypename("Mutation"),this.setRootTypename("Subscription"),e.possibleTypes&&this.addPossibleTypes(e.possibleTypes),e.typePolicies&&this.addTypePolicies(e.typePolicies)}return e.prototype.identify=function(e,t){var n,r,i=this,a=t&&(t.typename||(null===(n=t.storeObject)||void 0===n?void 0:n.__typename))||e.__typename;if(a===this.rootTypenamesById.ROOT_QUERY)return["ROOT_QUERY"];for(var o=t&&t.storeObject||e,s=(0,en.pi)((0,en.pi)({},t),{typename:a,storeObject:o,readField:t&&t.readField||function(){var e=i0(arguments,o);return i.readField(e,{store:i.cache.data,variables:e.variables})}}),u=a&&this.getTypePolicy(a),c=u&&u.keyFn||this.config.dataIdFromObject;c;){var l=c((0,en.pi)((0,en.pi)({},e),o),s);if((0,tP.k)(l))c=iU(l);else{r=l;break}}return r=r?String(r):void 0,s.keyObject?[r,s.keyObject]:[r]},e.prototype.addTypePolicies=function(e){var t=this;Object.keys(e).forEach(function(n){var r=e[n],i=r.queryType,a=r.mutationType,o=r.subscriptionType,s=(0,en._T)(r,["queryType","mutationType","subscriptionType"]);i&&t.setRootTypename("Query",n),a&&t.setRootTypename("Mutation",n),o&&t.setRootTypename("Subscription",n),ic.call(t.toBeAdded,n)?t.toBeAdded[n].push(s):t.toBeAdded[n]=[s]})},e.prototype.updateTypePolicy=function(e,t){var n=this,r=this.getTypePolicy(e),i=t.keyFields,a=t.fields;function o(e,t){e.merge="function"==typeof t?t:!0===t?iX:!1===t?iJ:e.merge}o(r,t.merge),r.keyFn=!1===i?iq:(0,tP.k)(i)?iU(i):"function"==typeof i?i:r.keyFn,a&&Object.keys(a).forEach(function(t){var r=n.getFieldPolicy(e,t,!0),i=a[t];if("function"==typeof i)r.read=i;else{var s=i.keyArgs,u=i.read,c=i.merge;r.keyFn=!1===s?iZ:(0,tP.k)(s)?iH(s):"function"==typeof s?s:r.keyFn,"function"==typeof u&&(r.read=u),o(r,c)}r.read&&r.merge&&(r.keyFn=r.keyFn||iZ)})},e.prototype.setRootTypename=function(e,t){void 0===t&&(t=e);var n="ROOT_"+e.toUpperCase(),r=this.rootTypenamesById[n];t!==r&&(__DEV__?(0,Q.kG)(!r||r===e,"Cannot change root ".concat(e," __typename more than once")):(0,Q.kG)(!r||r===e,3),r&&delete this.rootIdsByTypename[r],this.rootIdsByTypename[t]=n,this.rootTypenamesById[n]=t)},e.prototype.addPossibleTypes=function(e){var t=this;this.usingPossibleTypes=!0,Object.keys(e).forEach(function(n){t.getSupertypeSet(n,!0),e[n].forEach(function(e){t.getSupertypeSet(e,!0).add(n);var r=e.match(ig);r&&r[0]===e||t.fuzzySubtypes.set(e,RegExp(e))})})},e.prototype.getTypePolicy=function(e){var t=this;if(!ic.call(this.typePolicies,e)){var n=this.typePolicies[e]=Object.create(null);n.fields=Object.create(null);var r=this.supertypeMap.get(e);r&&r.size&&r.forEach(function(e){var r=t.getTypePolicy(e),i=r.fields;Object.assign(n,(0,en._T)(r,["fields"])),Object.assign(n.fields,i)})}var i=this.toBeAdded[e];return i&&i.length&&i.splice(0).forEach(function(n){t.updateTypePolicy(e,n)}),this.typePolicies[e]},e.prototype.getFieldPolicy=function(e,t,n){if(e){var r=this.getTypePolicy(e).fields;return r[t]||n&&(r[t]=Object.create(null))}},e.prototype.getSupertypeSet=function(e,t){var n=this.supertypeMap.get(e);return!n&&t&&this.supertypeMap.set(e,n=new Set),n},e.prototype.fragmentMatches=function(e,t,n,r){var i=this;if(!e.typeCondition)return!0;if(!t)return!1;var a=e.typeCondition.name.value;if(t===a)return!0;if(this.usingPossibleTypes&&this.supertypeMap.has(a))for(var o=this.getSupertypeSet(t,!0),s=[o],u=function(e){var t=i.getSupertypeSet(e,!1);t&&t.size&&0>s.indexOf(t)&&s.push(t)},c=!!(n&&this.fuzzySubtypes.size),l=!1,f=0;f1?a:t}:(r=(0,en.pi)({},i),ic.call(r,"from")||(r.from=t)),__DEV__&&void 0===r.from&&__DEV__&&Q.kG.warn("Undefined 'from' passed to readField with arguments ".concat(iF(Array.from(e)))),void 0===r.variables&&(r.variables=n),r}function i2(e){return function(t,n){if((0,tP.k)(t)||(0,tP.k)(n))throw __DEV__?new Q.ej("Cannot automatically merge arrays"):new Q.ej(4);if((0,eO.s)(t)&&(0,eO.s)(n)){var r=e.getFieldValue(t,"__typename"),i=e.getFieldValue(n,"__typename");if(r&&i&&r!==i)return n;if(eD(t)&&iw(n))return e.merge(t.__ref,n),t;if(iw(t)&&eD(n))return e.merge(t,n.__ref),n;if(iw(t)&&iw(n))return(0,en.pi)((0,en.pi)({},t),n)}return n}}function i3(e,t,n){var r="".concat(t).concat(n),i=e.flavors.get(r);return i||e.flavors.set(r,i=e.clientOnly===t&&e.deferred===n?e:(0,en.pi)((0,en.pi)({},e),{clientOnly:t,deferred:n})),i}var i4=function(){function e(e,t,n){this.cache=e,this.reader=t,this.fragments=n}return e.prototype.writeToStore=function(e,t){var n=this,r=t.query,i=t.result,a=t.dataId,o=t.variables,s=t.overwrite,u=e2(r),c=i_();o=(0,en.pi)((0,en.pi)({},e9(u)),o);var l=(0,en.pi)((0,en.pi)({store:e,written:Object.create(null),merge:function(e,t){return c.merge(e,t)},variables:o,varString:nx(o)},iE(r,this.fragments)),{overwrite:!!s,incomingById:new Map,clientOnly:!1,deferred:!1,flavors:new Map}),f=this.processSelectionSet({result:i||Object.create(null),dataId:a,selectionSet:u.selectionSet,mergeTree:{map:new Map},context:l});if(!eD(f))throw __DEV__?new Q.ej("Could not identify object ".concat(JSON.stringify(i))):new Q.ej(7);return l.incomingById.forEach(function(t,r){var i=t.storeObject,a=t.mergeTree,o=t.fieldNodeSet,s=eI(r);if(a&&a.map.size){var u=n.applyMerges(a,s,i,l);if(eD(u))return;i=u}if(__DEV__&&!l.overwrite){var c=Object.create(null);o.forEach(function(e){e.selectionSet&&(c[e.name.value]=!0)});var f=function(e){return!0===c[iv(e)]},d=function(e){var t=a&&a.map.get(e);return Boolean(t&&t.info&&t.info.merge)};Object.keys(i).forEach(function(e){f(e)&&!d(e)&&at(s,i,e,l.store)})}e.merge(r,i)}),e.retain(f.__ref),f},e.prototype.processSelectionSet=function(e){var t=this,n=e.dataId,r=e.result,i=e.selectionSet,a=e.context,o=e.mergeTree,s=this.cache.policies,u=Object.create(null),c=n&&s.rootTypenamesById[n]||eJ(r,i,a.fragmentMap)||n&&a.store.get(n,"__typename");"string"==typeof c&&(u.__typename=c);var l=function(){var e=i0(arguments,u,a.variables);if(eD(e.from)){var t=a.incomingById.get(e.from.__ref);if(t){var n=s.readField((0,en.pi)((0,en.pi)({},e),{from:t.storeObject}),a);if(void 0!==n)return n}}return s.readField(e,a)},f=new Set;this.flattenFields(i,r,a,c).forEach(function(e,n){var i,a=r[eX(n)];if(f.add(n),void 0!==a){var d=s.getStoreFieldName({typename:c,fieldName:n.name.value,field:n,variables:e.variables}),h=i5(o,d),p=t.processFieldValue(a,n,n.selectionSet?i3(e,!1,!1):e,h),b=void 0;n.selectionSet&&(eD(p)||iw(p))&&(b=l("__typename",p));var m=s.getMergeFunction(c,n.name.value,b);m?h.info={field:n,typename:c,merge:m}:i7(o,d),u=e.merge(u,((i={})[d]=p,i))}else __DEV__&&!e.clientOnly&&!e.deferred&&!nj.added(n)&&!s.getReadFunction(c,n.name.value)&&__DEV__&&Q.kG.error("Missing field '".concat(eX(n),"' while writing result ").concat(JSON.stringify(r,null,2)).substring(0,1e3))});try{var d=s.identify(r,{typename:c,selectionSet:i,fragmentMap:a.fragmentMap,storeObject:u,readField:l}),h=d[0],p=d[1];n=n||h,p&&(u=a.merge(u,p))}catch(b){if(!n)throw b}if("string"==typeof n){var m=eI(n),g=a.written[n]||(a.written[n]=[]);if(g.indexOf(i)>=0||(g.push(i),this.reader&&this.reader.isFresh(r,m,i,a)))return m;var v=a.incomingById.get(n);return v?(v.storeObject=a.merge(v.storeObject,u),v.mergeTree=i8(v.mergeTree,o),f.forEach(function(e){return v.fieldNodeSet.add(e)})):a.incomingById.set(n,{storeObject:u,mergeTree:i9(o)?void 0:o,fieldNodeSet:f}),m}return u},e.prototype.processFieldValue=function(e,t,n,r){var i=this;return t.selectionSet&&null!==e?(0,tP.k)(e)?e.map(function(e,a){var o=i.processFieldValue(e,t,n,i5(r,a));return i7(r,a),o}):this.processSelectionSet({result:e,selectionSet:t.selectionSet,context:n,mergeTree:r}):__DEV__?nJ(e):e},e.prototype.flattenFields=function(e,t,n,r){void 0===r&&(r=eJ(t,e,n.fragmentMap));var i=new Map,a=this.cache.policies,o=new n_(!1);return function e(s,u){var c=o.lookup(s,u.clientOnly,u.deferred);c.visited||(c.visited=!0,s.selections.forEach(function(o){if(td(o,n.variables)){var s=u.clientOnly,c=u.deferred;if(!(s&&c)&&(0,tP.O)(o.directives)&&o.directives.forEach(function(e){var t=e.name.value;if("client"===t&&(s=!0),"defer"===t){var r=eZ(e,n.variables);r&&!1===r.if||(c=!0)}}),eQ(o)){var l=i.get(o);l&&(s=s&&l.clientOnly,c=c&&l.deferred),i.set(o,i3(n,s,c))}else{var f=eC(o,n.lookupFragment);if(!f&&o.kind===nL.h.FRAGMENT_SPREAD)throw __DEV__?new Q.ej("No fragment named ".concat(o.name.value)):new Q.ej(8);f&&a.fragmentMatches(f,r,t,n.variables)&&e(f.selectionSet,i3(n,s,c))}}}))}(e,n),i},e.prototype.applyMerges=function(e,t,n,r,i){var a=this;if(e.map.size&&!eD(n)){var o,s,u=!(0,tP.k)(n)&&(eD(t)||iw(t))?t:void 0,c=n;u&&!i&&(i=[eD(u)?u.__ref:u]);var l=function(e,t){return(0,tP.k)(e)?"number"==typeof t?e[t]:void 0:r.store.getFieldValue(e,String(t))};e.map.forEach(function(e,t){var n=l(u,t),o=l(c,t);if(void 0!==o){i&&i.push(t);var f=a.applyMerges(e,n,o,r,i);f!==o&&(s=s||new Map).set(t,f),i&&(0,Q.kG)(i.pop()===t)}}),s&&(n=(0,tP.k)(c)?c.slice(0):(0,en.pi)({},c),s.forEach(function(e,t){n[t]=e}))}return e.info?this.cache.policies.runMergeFunction(t,n,e.info,r,i&&(o=r.store).getStorage.apply(o,i)):n},e}(),i6=[];function i5(e,t){var n=e.map;return n.has(t)||n.set(t,i6.pop()||{map:new Map}),n.get(t)}function i8(e,t){if(e===t||!t||i9(t))return e;if(!e||i9(e))return t;var n=e.info&&t.info?(0,en.pi)((0,en.pi)({},e.info),t.info):e.info||t.info,r=e.map.size&&t.map.size,i=r?new Map:e.map.size?e.map:t.map,a={info:n,map:i};if(r){var o=new Set(t.map.keys());e.map.forEach(function(e,n){a.map.set(n,i8(e,t.map.get(n))),o.delete(n)}),o.forEach(function(n){a.map.set(n,i8(t.map.get(n),e.map.get(n)))})}return a}function i9(e){return!e||!(e.info||e.map.size)}function i7(e,t){var n=e.map,r=n.get(t);r&&i9(r)&&(i6.push(r),n.delete(t))}var ae=new Set;function at(e,t,n,r){var i=function(e){var t=r.getFieldValue(e,n);return"object"==typeof t&&t},a=i(e);if(a){var o=i(t);if(!(!o||eD(a)||(0,nm.D)(a,o)||Object.keys(a).every(function(e){return void 0!==r.getFieldValue(o,e)}))){var s=r.getFieldValue(e,"__typename")||r.getFieldValue(t,"__typename"),u=iv(n),c="".concat(s,".").concat(u);if(!ae.has(c)){ae.add(c);var l=[];(0,tP.k)(a)||(0,tP.k)(o)||[a,o].forEach(function(e){var t=r.getFieldValue(e,"__typename");"string"!=typeof t||l.includes(t)||l.push(t)}),__DEV__&&Q.kG.warn("Cache data may be lost when replacing the ".concat(u," field of a ").concat(s," object.\n\nThis could cause additional (usually avoidable) network requests to fetch data that were otherwise cached.\n\nTo address this problem (which is not a bug in Apollo Client), ").concat(l.length?"either ensure all objects of type "+l.join(" and ")+" have an ID or a custom merge function, or ":"","define a custom merge function for the ").concat(c," field, so InMemoryCache can safely merge these objects:\n\n existing: ").concat(JSON.stringify(a).slice(0,1e3),"\n incoming: ").concat(JSON.stringify(o).slice(0,1e3),"\n\nFor more information about these options, please refer to the documentation:\n\n * Ensuring entity objects have IDs: https://go.apollo.dev/c/generating-unique-identifiers\n * Defining custom merge functions: https://go.apollo.dev/c/merging-non-normalized-objects\n"))}}}}var an=function(e){function t(t){void 0===t&&(t={});var n=e.call(this)||this;return n.watches=new Set,n.typenameDocumentCache=new Map,n.makeVar=r2,n.txCount=0,n.config=ip(t),n.addTypename=!!n.config.addTypename,n.policies=new iQ({cache:n,dataIdFromObject:n.config.dataIdFromObject,possibleTypes:n.config.possibleTypes,typePolicies:n.config.typePolicies}),n.init(),n}return(0,en.ZT)(t,e),t.prototype.init=function(){var e=this.data=new iT.Root({policies:this.policies,resultCaching:this.config.resultCaching});this.optimisticData=e.stump,this.resetResultCache()},t.prototype.resetResultCache=function(e){var t=this,n=this.storeReader,r=this.config.fragments;this.storeWriter=new i4(this,this.storeReader=new iP({cache:this,addTypename:this.addTypename,resultCacheMaxSize:this.config.resultCacheMaxSize,canonizeResults:ib(this.config),canon:e?void 0:n&&n.canon,fragments:r}),r),this.maybeBroadcastWatch=rZ(function(e,n){return t.broadcastWatch(e,n)},{max:this.config.resultCacheMaxSize,makeCacheKey:function(e){var n=e.optimistic?t.optimisticData:t.data;if(iD(n)){var r=e.optimistic,i=e.id,a=e.variables;return n.makeCacheKey(e.query,e.callback,nx({optimistic:r,id:i,variables:a}))}}}),new Set([this.data.group,this.optimisticData.group,]).forEach(function(e){return e.resetCaching()})},t.prototype.restore=function(e){return this.init(),e&&this.data.replace(e),this},t.prototype.extract=function(e){return void 0===e&&(e=!1),(e?this.optimisticData:this.data).extract()},t.prototype.read=function(e){var t=e.returnPartialData,n=void 0!==t&&t;try{return this.storeReader.diffQueryAgainstStore((0,en.pi)((0,en.pi)({},e),{store:e.optimistic?this.optimisticData:this.data,config:this.config,returnPartialData:n})).result||null}catch(r){if(r instanceof is)return null;throw r}},t.prototype.write=function(e){try{return++this.txCount,this.storeWriter.writeToStore(this.data,e)}finally{--this.txCount||!1===e.broadcast||this.broadcastWatches()}},t.prototype.modify=function(e){if(ic.call(e,"id")&&!e.id)return!1;var t=e.optimistic?this.optimisticData:this.data;try{return++this.txCount,t.modify(e.id||"ROOT_QUERY",e.fields)}finally{--this.txCount||!1===e.broadcast||this.broadcastWatches()}},t.prototype.diff=function(e){return this.storeReader.diffQueryAgainstStore((0,en.pi)((0,en.pi)({},e),{store:e.optimistic?this.optimisticData:this.data,rootId:e.id||"ROOT_QUERY",config:this.config}))},t.prototype.watch=function(e){var t=this;return this.watches.size||r0(this),this.watches.add(e),e.immediate&&this.maybeBroadcastWatch(e),function(){t.watches.delete(e)&&!t.watches.size&&r1(t),t.maybeBroadcastWatch.forget(e)}},t.prototype.gc=function(e){nx.reset();var t=this.optimisticData.gc();return e&&!this.txCount&&(e.resetResultCache?this.resetResultCache(e.resetResultIdentities):e.resetResultIdentities&&this.storeReader.resetCanon()),t},t.prototype.retain=function(e,t){return(t?this.optimisticData:this.data).retain(e)},t.prototype.release=function(e,t){return(t?this.optimisticData:this.data).release(e)},t.prototype.identify=function(e){if(eD(e))return e.__ref;try{return this.policies.identify(e)[0]}catch(t){__DEV__&&Q.kG.warn(t)}},t.prototype.evict=function(e){if(!e.id){if(ic.call(e,"id"))return!1;e=(0,en.pi)((0,en.pi)({},e),{id:"ROOT_QUERY"})}try{return++this.txCount,this.optimisticData.evict(e,this.data)}finally{--this.txCount||!1===e.broadcast||this.broadcastWatches()}},t.prototype.reset=function(e){var t=this;return this.init(),nx.reset(),e&&e.discardWatches?(this.watches.forEach(function(e){return t.maybeBroadcastWatch.forget(e)}),this.watches.clear(),r1(this)):this.broadcastWatches(),Promise.resolve()},t.prototype.removeOptimistic=function(e){var t=this.optimisticData.removeLayer(e);t!==this.optimisticData&&(this.optimisticData=t,this.broadcastWatches())},t.prototype.batch=function(e){var t,n=this,r=e.update,i=e.optimistic,a=void 0===i||i,o=e.removeOptimistic,s=e.onWatchUpdated,u=function(e){var i=n,a=i.data,o=i.optimisticData;++n.txCount,e&&(n.data=n.optimisticData=e);try{return t=r(n)}finally{--n.txCount,n.data=a,n.optimisticData=o}},c=new Set;return s&&!this.txCount&&this.broadcastWatches((0,en.pi)((0,en.pi)({},e),{onWatchUpdated:function(e){return c.add(e),!1}})),"string"==typeof a?this.optimisticData=this.optimisticData.addLayer(a,u):!1===a?u(this.data):u(),"string"==typeof o&&(this.optimisticData=this.optimisticData.removeLayer(o)),s&&c.size?(this.broadcastWatches((0,en.pi)((0,en.pi)({},e),{onWatchUpdated:function(e,t){var n=s.call(this,e,t);return!1!==n&&c.delete(e),n}})),c.size&&c.forEach(function(e){return n.maybeBroadcastWatch.dirty(e)})):this.broadcastWatches(e),t},t.prototype.performTransaction=function(e,t){return this.batch({update:e,optimistic:t||null!==t})},t.prototype.transformDocument=function(e){if(this.addTypename){var t=this.typenameDocumentCache.get(e);return t||(t=nj(e),this.typenameDocumentCache.set(e,t),this.typenameDocumentCache.set(t,t)),t}return e},t.prototype.transformForLink=function(e){var t=this.config.fragments;return t?t.transform(e):e},t.prototype.broadcastWatches=function(e){var t=this;this.txCount||this.watches.forEach(function(n){return t.maybeBroadcastWatch(n,e)})},t.prototype.broadcastWatch=function(e,t){var n=e.lastDiff,r=this.diff(e);(!t||(e.optimistic&&"string"==typeof t.optimistic&&(r.fromOptimisticTransaction=!0),!t.onWatchUpdated||!1!==t.onWatchUpdated.call(this,e,r,n)))&&(n&&(0,nm.D)(n.result,r.result)||e.callback(e.lastDiff=r,n))},t}(io),ar={possibleTypes:{ApproveJobProposalSpecPayload:["ApproveJobProposalSpecSuccess","JobAlreadyExistsError","NotFoundError"],BridgePayload:["Bridge","NotFoundError"],CancelJobProposalSpecPayload:["CancelJobProposalSpecSuccess","NotFoundError"],ChainPayload:["Chain","NotFoundError"],CreateAPITokenPayload:["CreateAPITokenSuccess","InputErrors"],CreateBridgePayload:["CreateBridgeSuccess"],CreateCSAKeyPayload:["CSAKeyExistsError","CreateCSAKeySuccess"],CreateFeedsManagerChainConfigPayload:["CreateFeedsManagerChainConfigSuccess","InputErrors","NotFoundError"],CreateFeedsManagerPayload:["CreateFeedsManagerSuccess","DuplicateFeedsManagerError","InputErrors","NotFoundError","SingleFeedsManagerError"],CreateJobPayload:["CreateJobSuccess","InputErrors"],CreateOCR2KeyBundlePayload:["CreateOCR2KeyBundleSuccess"],CreateOCRKeyBundlePayload:["CreateOCRKeyBundleSuccess"],CreateP2PKeyPayload:["CreateP2PKeySuccess"],DeleteAPITokenPayload:["DeleteAPITokenSuccess","InputErrors"],DeleteBridgePayload:["DeleteBridgeConflictError","DeleteBridgeInvalidNameError","DeleteBridgeSuccess","NotFoundError"],DeleteCSAKeyPayload:["DeleteCSAKeySuccess","NotFoundError"],DeleteFeedsManagerChainConfigPayload:["DeleteFeedsManagerChainConfigSuccess","NotFoundError"],DeleteJobPayload:["DeleteJobSuccess","NotFoundError"],DeleteOCR2KeyBundlePayload:["DeleteOCR2KeyBundleSuccess","NotFoundError"],DeleteOCRKeyBundlePayload:["DeleteOCRKeyBundleSuccess","NotFoundError"],DeleteP2PKeyPayload:["DeleteP2PKeySuccess","NotFoundError"],DeleteVRFKeyPayload:["DeleteVRFKeySuccess","NotFoundError"],DisableFeedsManagerPayload:["DisableFeedsManagerSuccess","NotFoundError"],DismissJobErrorPayload:["DismissJobErrorSuccess","NotFoundError"],EnableFeedsManagerPayload:["EnableFeedsManagerSuccess","NotFoundError"],Error:["CSAKeyExistsError","DeleteBridgeConflictError","DeleteBridgeInvalidNameError","DuplicateFeedsManagerError","InputError","JobAlreadyExistsError","NotFoundError","RunJobCannotRunError","SingleFeedsManagerError"],EthTransactionPayload:["EthTransaction","NotFoundError"],FeaturesPayload:["Features"],FeedsManagerPayload:["FeedsManager","NotFoundError"],GetSQLLoggingPayload:["SQLLogging"],GlobalLogLevelPayload:["GlobalLogLevel"],JobPayload:["Job","NotFoundError"],JobProposalPayload:["JobProposal","NotFoundError"],JobRunPayload:["JobRun","NotFoundError"],JobSpec:["BlockHeaderFeederSpec","BlockhashStoreSpec","BootstrapSpec","CronSpec","DirectRequestSpec","FluxMonitorSpec","GatewaySpec","KeeperSpec","OCR2Spec","OCRSpec","StandardCapabilitiesSpec","StreamSpec","VRFSpec","WebhookSpec","WorkflowSpec"],NodePayload:["Node","NotFoundError"],PaginatedPayload:["BridgesPayload","ChainsPayload","EthTransactionAttemptsPayload","EthTransactionsPayload","JobRunsPayload","JobsPayload","NodesPayload"],RejectJobProposalSpecPayload:["NotFoundError","RejectJobProposalSpecSuccess"],RunJobPayload:["NotFoundError","RunJobCannotRunError","RunJobSuccess"],SetGlobalLogLevelPayload:["InputErrors","SetGlobalLogLevelSuccess"],SetSQLLoggingPayload:["SetSQLLoggingSuccess"],SetServicesLogLevelsPayload:["InputErrors","SetServicesLogLevelsSuccess"],UpdateBridgePayload:["NotFoundError","UpdateBridgeSuccess"],UpdateFeedsManagerChainConfigPayload:["InputErrors","NotFoundError","UpdateFeedsManagerChainConfigSuccess"],UpdateFeedsManagerPayload:["InputErrors","NotFoundError","UpdateFeedsManagerSuccess"],UpdateJobProposalSpecDefinitionPayload:["NotFoundError","UpdateJobProposalSpecDefinitionSuccess"],UpdatePasswordPayload:["InputErrors","UpdatePasswordSuccess"],VRFKeyPayload:["NotFoundError","VRFKeySuccess"]}};let ai=ar;var aa=(r=void 0,location.origin),ao=new nh({uri:"".concat(aa,"/query"),credentials:"include"}),as=new ia({cache:new an({possibleTypes:ai.possibleTypes,dataIdFromObject:function(e){if("Chain"===e.__typename){if(!e.network)throw Error("Due to Chain ID not being unique across chain, ensure network is fetched too");return"Chain:".concat(e.network,":").concat(e.id)}return id(e)}}),link:ao});if(a.Z.locale(o),u().defaultFormat="YYYY-MM-DD h:mm:ss A","undefined"!=typeof document){var au,ac,al=f().hydrate;ac=X,al(c.createElement(et,{client:as},c.createElement(d.zj,null,c.createElement(i.MuiThemeProvider,{theme:J.r},c.createElement(ac,null)))),document.getElementById("root"))}})()})(); \ No newline at end of file diff --git a/core/web/assets/main.008c37495ba29761321d.js.gz b/core/web/assets/main.5fed0c0f926fb5542ed6.js.gz similarity index 86% rename from core/web/assets/main.008c37495ba29761321d.js.gz rename to core/web/assets/main.5fed0c0f926fb5542ed6.js.gz index c5cb981d005..e726ba0ead3 100644 Binary files a/core/web/assets/main.008c37495ba29761321d.js.gz and b/core/web/assets/main.5fed0c0f926fb5542ed6.js.gz differ diff --git a/core/web/auth/auth_test.go b/core/web/auth/auth_test.go index 25479409545..4af1f91f9da 100644 --- a/core/web/auth/auth_test.go +++ b/core/web/auth/auth_test.go @@ -276,22 +276,27 @@ var routesRolesMap = [...]routeRules{ {"GET", "/v2/keys/cosmos", true, true, true}, {"GET", "/v2/keys/starknet", true, true, true}, {"GET", "/v2/keys/aptos", true, true, true}, + {"GET", "/v2/keys/tron", true, true, true}, {"POST", "/v2/keys/solana", false, false, true}, {"POST", "/v2/keys/cosmos", false, false, true}, {"POST", "/v2/keys/starknet", false, false, true}, {"POST", "/v2/keys/aptos", false, false, true}, + {"POST", "/v2/keys/tron", false, false, true}, {"DELETE", "/v2/keys/solana/MOCK", false, false, false}, {"DELETE", "/v2/keys/cosmos/MOCK", false, false, false}, {"DELETE", "/v2/keys/starknet/MOCK", false, false, false}, {"DELETE", "/v2/keys/aptos/MOCK", false, false, false}, + {"DELETE", "/v2/keys/tron/MOCK", false, false, false}, {"POST", "/v2/keys/solana/import", false, false, false}, {"POST", "/v2/keys/cosmos/import", false, false, false}, {"POST", "/v2/keys/starknet/import", false, false, false}, {"POST", "/v2/keys/aptos/import", false, false, false}, + {"POST", "/v2/keys/tron/import", false, false, false}, {"POST", "/v2/keys/solana/export/MOCK", false, false, false}, {"POST", "/v2/keys/cosmos/export/MOCK", false, false, false}, {"POST", "/v2/keys/starknet/export/MOCK", false, false, false}, {"POST", "/v2/keys/aptos/export/MOCK", false, false, false}, + {"POST", "/v2/keys/tron/export/MOCK", false, false, false}, {"GET", "/v2/keys/vrf", true, true, true}, {"POST", "/v2/keys/vrf", false, false, true}, {"DELETE", "/v2/keys/vrf/MOCK", false, false, false}, diff --git a/core/web/chains_controller.go b/core/web/chains_controller.go index a99cbf4ca4b..473bf3c490c 100644 --- a/core/web/chains_controller.go +++ b/core/web/chains_controller.go @@ -8,7 +8,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types" - commonTypes "github.com/smartcontractkit/chainlink/v2/common/types" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/logger/audit" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -33,7 +32,7 @@ func (e errChainDisabled) Error() string { type chainsController struct { chainStats chainlink.RelayerChainInteroperators - newResource func(commonTypes.ChainStatusWithID) presenters.ChainResource + newResource func(chainlink.NetworkChainStatus) presenters.ChainResource lggr logger.Logger auditLogger audit.AuditLogger } @@ -71,7 +70,7 @@ func (cc *chainsController) Index(c *gin.Context, size, page, offset int) { func (cc *chainsController) Show(c *gin.Context) { relayID := types.RelayID{Network: c.Param("network"), ChainID: c.Param("ID")} chain, err := cc.chainStats.ChainStatus(c.Request.Context(), relayID) - status := commonTypes.ChainStatusWithID{ChainStatus: chain, RelayID: relayID} + status := chainlink.NetworkChainStatus{ChainStatus: chain, Network: relayID.Network} if err != nil { jsonAPIError(c, http.StatusBadRequest, err) return diff --git a/core/web/chains_controller_test.go b/core/web/chains_controller_test.go index 9e6c32a9637..d4e9b785f23 100644 --- a/core/web/chains_controller_test.go +++ b/core/web/chains_controller_test.go @@ -418,6 +418,7 @@ OCR2CacheTTL = '1m0s' TxTimeout = '1h0m0s' TxRetryTimeout = '10s' TxConfirmTimeout = '30s' +TxExpirationRebroadcast = false TxRetentionTimeout = '0s' SkipPreflight = false Commitment = 'confirmed' diff --git a/core/web/loader/chain.go b/core/web/loader/chain.go index 0c66f55da4b..35b38f2c1ec 100644 --- a/core/web/loader/chain.go +++ b/core/web/loader/chain.go @@ -8,7 +8,6 @@ import ( commonTypes "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink/v2/common/types" "github.com/smartcontractkit/chainlink/v2/core/chains" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" ) @@ -28,7 +27,7 @@ func (b *chainBatcher) loadByIDs(ctx context.Context, keys dataloader.Keys) []*d keyOrder[key.String()] = ix } - var cs []types.ChainStatusWithID + var cs []chainlink.NetworkChainStatus relayersMap, err := b.app.GetRelayers().GetIDToRelayerMap() if err != nil { return []*dataloader.Result{{Data: nil, Error: err}} @@ -41,9 +40,9 @@ func (b *chainBatcher) loadByIDs(ctx context.Context, keys dataloader.Keys) []*d } if slices.Contains(chainIDs, s.ID) { - cs = append(cs, types.ChainStatusWithID{ + cs = append(cs, chainlink.NetworkChainStatus{ ChainStatus: s, - RelayID: k, + Network: k.Network, }) } } @@ -94,9 +93,9 @@ func (b *chainBatcher) loadByRelayIDs(ctx context.Context, keys dataloader.Keys) continue } - results = append(results, &dataloader.Result{Data: types.ChainStatusWithID{ + results = append(results, &dataloader.Result{Data: chainlink.NetworkChainStatus{ ChainStatus: status, - RelayID: relay, + Network: relay.Network, }, Error: err}) } diff --git a/core/web/loader/getters.go b/core/web/loader/getters.go index fef84b5eabd..e38a5a1459e 100644 --- a/core/web/loader/getters.go +++ b/core/web/loader/getters.go @@ -7,9 +7,9 @@ import ( "github.com/pkg/errors" "go.uber.org/multierr" - commonTypes "github.com/smartcontractkit/chainlink/v2/common/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/feeds" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" @@ -21,7 +21,7 @@ var ErrInvalidType = errors.New("invalid type") // GetChainByID fetches the chain by it's id. // Deprecated: use GetChainByRelayID. -func GetChainByID(ctx context.Context, id string) (*commonTypes.ChainStatusWithID, error) { +func GetChainByID(ctx context.Context, id string) (*chainlink.NetworkChainStatus, error) { ldr := For(ctx) thunk := ldr.ChainsByIDLoader.Load(ctx, dataloader.StringKey(id)) @@ -30,7 +30,7 @@ func GetChainByID(ctx context.Context, id string) (*commonTypes.ChainStatusWithI return nil, err } - chain, ok := result.(commonTypes.ChainStatusWithID) + chain, ok := result.(chainlink.NetworkChainStatus) if !ok { return nil, ErrInvalidType } @@ -39,7 +39,7 @@ func GetChainByID(ctx context.Context, id string) (*commonTypes.ChainStatusWithI } // GetChainByRelayID fetches the chain by it's relayId. -func GetChainByRelayID(ctx context.Context, id string) (*commonTypes.ChainStatusWithID, error) { +func GetChainByRelayID(ctx context.Context, id string) (*chainlink.NetworkChainStatus, error) { ldr := For(ctx) thunk := ldr.ChainsByRelayIDLoader.Load(ctx, dataloader.StringKey(id)) @@ -48,7 +48,7 @@ func GetChainByRelayID(ctx context.Context, id string) (*commonTypes.ChainStatus return nil, err } - chain, ok := result.(commonTypes.ChainStatusWithID) + chain, ok := result.(chainlink.NetworkChainStatus) if !ok { return nil, ErrInvalidType } diff --git a/core/web/loader/loader_test.go b/core/web/loader/loader_test.go index 953c0ff9319..a48b6ceb4b2 100644 --- a/core/web/loader/loader_test.go +++ b/core/web/loader/loader_test.go @@ -13,12 +13,12 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/loop" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink/v2/common/types" "github.com/smartcontractkit/chainlink/v2/core/chains" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtxmgrmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks" evmutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/relay" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" @@ -73,17 +73,17 @@ func TestLoader_Chains(t *testing.T) { assert.Len(t, results, 3) require.NoError(t, err) - want2 := types.ChainStatusWithID{ + want2 := chainlink.NetworkChainStatus{ ChainStatus: commontypes.ChainStatus{ID: "2", Enabled: true, Config: config2}, - RelayID: commontypes.RelayID{Network: relay.NetworkEVM, ChainID: "2"}, + Network: relay.NetworkEVM, } - assert.Equal(t, want2, results[0].Data.(types.ChainStatusWithID)) + assert.Equal(t, want2, results[0].Data.(chainlink.NetworkChainStatus)) - want1 := types.ChainStatusWithID{ + want1 := chainlink.NetworkChainStatus{ ChainStatus: commontypes.ChainStatus{ID: "1", Enabled: true, Config: config1}, - RelayID: commontypes.RelayID{Network: relay.NetworkEVM, ChainID: "1"}, + Network: relay.NetworkEVM, } - assert.Equal(t, want1, results[1].Data.(types.ChainStatusWithID)) + assert.Equal(t, want1, results[1].Data.(chainlink.NetworkChainStatus)) assert.Nil(t, results[2].Data) assert.Error(t, results[2].Error) assert.ErrorIs(t, results[2].Error, chains.ErrNotFound) @@ -148,15 +148,15 @@ func TestLoader_ChainsRelayID_HandleDuplicateIDAcrossNetworks(t *testing.T) { require.NoError(t, err) - assert.Equal(t, types.ChainStatusWithID{ + assert.Equal(t, chainlink.NetworkChainStatus{ ChainStatus: commontypes.ChainStatus{ID: "2", Enabled: true, Config: config2}, - RelayID: evm2, - }, results[0].Data.(types.ChainStatusWithID)) + Network: evm2.Network, + }, results[0].Data.(chainlink.NetworkChainStatus)) - assert.Equal(t, types.ChainStatusWithID{ + assert.Equal(t, chainlink.NetworkChainStatus{ ChainStatus: commontypes.ChainStatus{ID: "1", Enabled: true, Config: config1}, - RelayID: evm1, - }, results[1].Data.(types.ChainStatusWithID)) + Network: evm1.Network, + }, results[1].Data.(chainlink.NetworkChainStatus)) assert.Nil(t, results[2].Data) require.Error(t, results[2].Error) require.ErrorIs(t, results[2].Error, chains.ErrNotFound) diff --git a/core/web/presenters/chain.go b/core/web/presenters/chain.go index 280f7a7f8d4..d5a51e4509a 100644 --- a/core/web/presenters/chain.go +++ b/core/web/presenters/chain.go @@ -2,7 +2,7 @@ package presenters import ( "github.com/smartcontractkit/chainlink-common/pkg/types" - commonTypes "github.com/smartcontractkit/chainlink/v2/common/types" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" ) type ChainResource struct { @@ -18,10 +18,10 @@ func (r ChainResource) GetName() string { } // NewChainResource returns a new ChainResource for chain. -func NewChainResource(chain commonTypes.ChainStatusWithID) ChainResource { +func NewChainResource(chain chainlink.NetworkChainStatus) ChainResource { return ChainResource{ - JAID: NewJAID(chain.RelayID.ChainID), - Network: chain.RelayID.Network, + JAID: NewJAID(chain.ID), + Network: chain.Network, Config: chain.Config, Enabled: chain.Enabled, } diff --git a/core/web/presenters/node_test.go b/core/web/presenters/node_test.go index d2db83009d9..9f980e22484 100644 --- a/core/web/presenters/node_test.go +++ b/core/web/presenters/node_test.go @@ -15,7 +15,7 @@ func TestNodeResource(t *testing.T) { var nodeResource NodeResource state := "test" cfg := "cfg" - testCases := []string{"solana", "cosmos", "starknet"} + testCases := []string{"solana", "cosmos", "starknet", "tron"} for _, tc := range testCases { chainID := fmt.Sprintf("%s chain ID", tc) nodeName := fmt.Sprintf("%s_node", tc) diff --git a/core/web/presenters/tron_chain.go b/core/web/presenters/tron_chain.go new file mode 100644 index 00000000000..7ab6109bd39 --- /dev/null +++ b/core/web/presenters/tron_chain.go @@ -0,0 +1,45 @@ +package presenters + +import ( + "github.com/smartcontractkit/chainlink-common/pkg/types" +) + +// TronChainResource is an Tron chain JSONAPI resource. +type TronChainResource struct { + ChainResource +} + +// GetName implements the api2go EntityNamer interface +func (r TronChainResource) GetName() string { + return "tron_chain" +} + +// NewTronChainResource returns a new TronChainResource for chain. +func NewTronChainResource(chain types.ChainStatus) TronChainResource { + return TronChainResource{ChainResource{ + JAID: NewJAID(chain.ID), + Config: chain.Config, + Enabled: chain.Enabled, + }} +} + +// TronNodeResource is a Tron node JSONAPI resource. +type TronNodeResource struct { + NodeResource +} + +// GetName implements the api2go EntityNamer interface +func (r TronNodeResource) GetName() string { + return "tron_node" +} + +// NewTronNodeResource returns a new TronNodeResource for node. +func NewTronNodeResource(node types.NodeStatus) TronNodeResource { + return TronNodeResource{NodeResource{ + JAID: NewPrefixedJAID(node.Name, node.ChainID), + ChainID: node.ChainID, + Name: node.Name, + State: node.State, + Config: node.Config, + }} +} diff --git a/core/web/presenters/tron_key.go b/core/web/presenters/tron_key.go new file mode 100644 index 00000000000..abe74ed7f41 --- /dev/null +++ b/core/web/presenters/tron_key.go @@ -0,0 +1,34 @@ +package presenters + +import ( + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/tronkey" +) + +// TronKeyResource represents a Tron key JSONAPI resource. +type TronKeyResource struct { + JAID + PubKey string `json:"publicKey"` +} + +// GetName implements the api2go EntityNamer interface +func (TronKeyResource) GetName() string { + return "encryptedTronKeys" +} + +func NewTronKeyResource(key tronkey.Key) *TronKeyResource { + r := &TronKeyResource{ + JAID: JAID{ID: key.ID()}, + PubKey: key.PublicKeyStr(), + } + + return r +} + +func NewTronKeyResources(keys []tronkey.Key) []TronKeyResource { + rs := []TronKeyResource{} + for _, key := range keys { + rs = append(rs, *NewTronKeyResource(key)) + } + + return rs +} diff --git a/core/web/resolver/chain.go b/core/web/resolver/chain.go index 9e06c5a6308..0e8f3c35ea9 100644 --- a/core/web/resolver/chain.go +++ b/core/web/resolver/chain.go @@ -3,19 +3,19 @@ package resolver import ( "github.com/graph-gophers/graphql-go" - "github.com/smartcontractkit/chainlink/v2/common/types" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" ) // ChainResolver resolves the Chain type. type ChainResolver struct { - chain types.ChainStatusWithID + chain chainlink.NetworkChainStatus } -func NewChain(chain types.ChainStatusWithID) *ChainResolver { +func NewChain(chain chainlink.NetworkChainStatus) *ChainResolver { return &ChainResolver{chain: chain} } -func NewChains(chains []types.ChainStatusWithID) []*ChainResolver { +func NewChains(chains []chainlink.NetworkChainStatus) []*ChainResolver { var resolvers []*ChainResolver for _, c := range chains { resolvers = append(resolvers, NewChain(c)) @@ -45,11 +45,11 @@ func (r *ChainResolver) Network() string { } type ChainPayloadResolver struct { - chain types.ChainStatusWithID + chain chainlink.NetworkChainStatus NotFoundErrorUnionType } -func NewChainPayload(chain types.ChainStatusWithID, err error) *ChainPayloadResolver { +func NewChainPayload(chain chainlink.NetworkChainStatus, err error) *ChainPayloadResolver { e := NotFoundErrorUnionType{err: err, message: "chain not found", isExpectedErrorFn: nil} return &ChainPayloadResolver{chain: chain, NotFoundErrorUnionType: e} @@ -64,11 +64,11 @@ func (r *ChainPayloadResolver) ToChain() (*ChainResolver, bool) { } type ChainsPayloadResolver struct { - chains []types.ChainStatusWithID + chains []chainlink.NetworkChainStatus total int32 } -func NewChainsPayload(chains []types.ChainStatusWithID, total int32) *ChainsPayloadResolver { +func NewChainsPayload(chains []chainlink.NetworkChainStatus, total int32) *ChainsPayloadResolver { return &ChainsPayloadResolver{chains: chains, total: total} } diff --git a/core/web/resolver/feeds_manager_chain_config_test.go b/core/web/resolver/feeds_manager_chain_config_test.go index 957583dbb7d..b4118cfa873 100644 --- a/core/web/resolver/feeds_manager_chain_config_test.go +++ b/core/web/resolver/feeds_manager_chain_config_test.go @@ -375,6 +375,81 @@ func Test_CreateFeedsManagerChainConfig(t *testing.T) { } }`, }, + { + name: "success Tron", + authenticated: true, + before: func(ctx context.Context, f *gqlTestFramework) { + f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) + f.Mocks.feedsSvc.On("CreateChainConfig", mock.Anything, feeds.ChainConfig{ + FeedsManagerID: mgrID, + ChainType: feeds.ChainTypeTron, + ChainID: chainID, + AccountAddress: accountAddr, + AccountAddressPublicKey: null.StringFrom(acctAddrPubKey), + AdminAddress: adminAddr, + FluxMonitorConfig: feeds.FluxMonitorConfig{ + Enabled: false, + }, + OCR1Config: feeds.OCR1Config{ + Enabled: true, + P2PPeerID: peerID, + KeyBundleID: keyBundleID, + }, + OCR2Config: feeds.OCR2ConfigModel{ + Enabled: true, + P2PPeerID: peerID, + KeyBundleID: keyBundleID, + ForwarderAddress: null.StringFrom(forwarderAddr), + Plugins: feeds.Plugins{ + Commit: true, + Execute: true, + Median: false, + Mercury: true, + Rebalancer: true, + }, + }, + }).Return(cfgID, nil) + f.Mocks.feedsSvc.On("GetChainConfig", mock.Anything, cfgID).Return(&feeds.ChainConfig{ + ID: cfgID, + ChainType: feeds.ChainTypeTron, + ChainID: chainID, + AccountAddress: accountAddr, + AccountAddressPublicKey: null.StringFrom(acctAddrPubKey), + AdminAddress: adminAddr, + FluxMonitorConfig: feeds.FluxMonitorConfig{ + Enabled: false, + }, + OCR1Config: feeds.OCR1Config{ + Enabled: true, + P2PPeerID: peerID, + KeyBundleID: keyBundleID, + }, + OCR2Config: feeds.OCR2ConfigModel{ + Enabled: true, + P2PPeerID: peerID, + KeyBundleID: keyBundleID, + ForwarderAddress: null.StringFrom(forwarderAddr), + Plugins: feeds.Plugins{ + Commit: true, + Execute: true, + Median: false, + Mercury: true, + Rebalancer: true, + }, + }, + }, nil) + }, + query: mutation, + variables: withVariables("TRON"), + result: ` + { + "createFeedsManagerChainConfig": { + "chainConfig": { + "id": "1" + } + } + }`, + }, { name: "create call not found", authenticated: true, diff --git a/core/web/resolver/ocr2_keys.go b/core/web/resolver/ocr2_keys.go index d04ebbd0e2f..345dd07d984 100644 --- a/core/web/resolver/ocr2_keys.go +++ b/core/web/resolver/ocr2_keys.go @@ -27,6 +27,8 @@ const ( OCR2ChainTypeStarkNet = "STARKNET" // OCRChainTypeAptos defines OCR Aptos Chain Type OCRChainTypeAptos = "APTOS" + // OCRChainTypeTron defines OCR2 Tron Chain Type + OCRChainTypeTron = "TRON" ) // ToOCR2ChainType turns a valid string into a OCR2ChainType @@ -42,6 +44,8 @@ func ToOCR2ChainType(s string) (OCR2ChainType, error) { return OCR2ChainTypeStarkNet, nil case string(chaintype.Aptos): return OCRChainTypeAptos, nil + case string(chaintype.Tron): + return OCRChainTypeTron, nil default: return "", errors.New("unknown ocr2 chain type") } @@ -60,6 +64,8 @@ func FromOCR2ChainType(ct OCR2ChainType) string { return string(chaintype.StarkNet) case OCRChainTypeAptos: return string(chaintype.Aptos) + case OCRChainTypeTron: + return string(chaintype.Tron) default: return strings.ToLower(string(ct)) } diff --git a/core/web/resolver/ocr2_keys_test.go b/core/web/resolver/ocr2_keys_test.go index 033d22799b1..e131aa0b5f5 100644 --- a/core/web/resolver/ocr2_keys_test.go +++ b/core/web/resolver/ocr2_keys_test.go @@ -42,6 +42,7 @@ func TestResolver_GetOCR2KeyBundles(t *testing.T) { ocr2key.MustNewInsecure(keystest.NewRandReaderFromSeed(1), "solana"), ocr2key.MustNewInsecure(keystest.NewRandReaderFromSeed(1), "starknet"), ocr2key.MustNewInsecure(keystest.NewRandReaderFromSeed(1), "aptos"), + ocr2key.MustNewInsecure(keystest.NewRandReaderFromSeed(1), "tron"), } expectedBundles := []map[string]interface{}{} for _, k := range fakeKeys { diff --git a/core/web/resolver/query.go b/core/web/resolver/query.go index ae33e5688bb..67bad52c111 100644 --- a/core/web/resolver/query.go +++ b/core/web/resolver/query.go @@ -11,8 +11,8 @@ import ( "github.com/pkg/errors" "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" - commonTypes "github.com/smartcontractkit/chainlink/v2/common/types" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" @@ -80,7 +80,7 @@ func (r *Resolver) Chain(ctx context.Context, id, err := loader.GetChainByID(ctx, string(args.ID)) if err != nil { if errors.Is(err, chains.ErrNotFound) { - return NewChainPayload(commonTypes.ChainStatusWithID{}, chains.ErrNotFound), nil + return NewChainPayload(chainlink.NetworkChainStatus{}, chains.ErrNotFound), nil } return nil, err } @@ -91,7 +91,7 @@ func (r *Resolver) Chain(ctx context.Context, id, err := loader.GetChainByRelayID(ctx, relayID.Name()) if err != nil { if errors.Is(err, chains.ErrNotFound) { - return NewChainPayload(commonTypes.ChainStatusWithID{}, chains.ErrNotFound), nil + return NewChainPayload(chainlink.NetworkChainStatus{}, chains.ErrNotFound), nil } return nil, err } @@ -111,21 +111,21 @@ func (r *Resolver) Chains(ctx context.Context, args struct { offset := pageOffset(args.Offset) limit := pageLimit(args.Limit) - var chains []commonTypes.ChainStatusWithID relayersMap, err := r.App.GetRelayers().GetIDToRelayerMap() if err != nil { return nil, err } + chains := make([]chainlink.NetworkChainStatus, 0, len(relayersMap)) for k, v := range relayersMap { s, err := v.GetChainStatus(ctx) if err != nil { return nil, err } - chains = append(chains, commonTypes.ChainStatusWithID{ + chains = append(chains, chainlink.NetworkChainStatus{ ChainStatus: s, - RelayID: k, + Network: k.Network, }) } @@ -136,10 +136,10 @@ func (r *Resolver) Chains(ctx context.Context, args struct { } // bound the chain results - if offset >= len(chains) { + if offset >= count { return nil, fmt.Errorf("offset %d out of range", offset) } - end := len(chains) + end := count if limit > 0 && offset+limit < end { end = offset + limit } @@ -148,7 +148,7 @@ func (r *Resolver) Chains(ctx context.Context, args struct { return NewChainsPayload(chains[offset:end], int32(count)), nil } -func sortByNetworkAndID(chains []commonTypes.ChainStatusWithID) { +func sortByNetworkAndID(chains []chainlink.NetworkChainStatus) { sort.SliceStable(chains, func(i, j int) bool { if chains[i].Network == chains[j].Network { return chains[i].ID < chains[j].ID @@ -625,6 +625,19 @@ func (r *Resolver) StarkNetKeys(ctx context.Context) (*StarkNetKeysPayloadResolv return NewStarkNetKeysPayload(keys), nil } +func (r *Resolver) TronKeys(ctx context.Context) (*TronKeysPayloadResolver, error) { + if err := authenticateUser(ctx); err != nil { + return nil, err + } + + keys, err := r.App.GetKeyStore().Tron().GetAll() + if err != nil { + return nil, err + } + + return NewTronKeysPayload(keys), nil +} + func (r *Resolver) SQLLogging(ctx context.Context) (*GetSQLLoggingPayloadResolver, error) { if err := authenticateUser(ctx); err != nil { return nil, err diff --git a/core/web/resolver/resolver_test.go b/core/web/resolver/resolver_test.go index 0d365b0891e..6ff9d954b37 100644 --- a/core/web/resolver/resolver_test.go +++ b/core/web/resolver/resolver_test.go @@ -54,6 +54,7 @@ type mocks struct { aptos *keystoreMocks.Aptos cosmos *keystoreMocks.Cosmos starknet *keystoreMocks.StarkNet + tron *keystoreMocks.Tron chain *legacyEvmORMMocks.Chain legacyEVMChains *legacyEvmORMMocks.LegacyChainContainer relayerChainInterops *chainlinkMocks.FakeRelayerChainInteroperators @@ -112,6 +113,7 @@ func setupFramework(t *testing.T) *gqlTestFramework { aptos: keystoreMocks.NewAptos(t), cosmos: keystoreMocks.NewCosmos(t), starknet: keystoreMocks.NewStarkNet(t), + tron: keystoreMocks.NewTron(t), chain: legacyEvmORMMocks.NewChain(t), legacyEVMChains: legacyEvmORMMocks.NewLegacyChainContainer(t), relayerChainInterops: &chainlinkMocks.FakeRelayerChainInteroperators{}, diff --git a/core/web/resolver/testdata/config-empty-effective.toml b/core/web/resolver/testdata/config-empty-effective.toml index a2052c04a8e..e219296e673 100644 --- a/core/web/resolver/testdata/config-empty-effective.toml +++ b/core/web/resolver/testdata/config-empty-effective.toml @@ -235,7 +235,8 @@ LatestReportDeadline = '5s' CertFile = '' [Mercury.Transmitter] -TransmitQueueMaxSize = 10000 +Protocol = 'wsrpc' +TransmitQueueMaxSize = 100000 TransmitTimeout = '5s' TransmitConcurrency = 100 diff --git a/core/web/resolver/testdata/config-full.toml b/core/web/resolver/testdata/config-full.toml index ef26bfea75a..d2d4b90e3ca 100644 --- a/core/web/resolver/testdata/config-full.toml +++ b/core/web/resolver/testdata/config-full.toml @@ -245,6 +245,7 @@ LatestReportDeadline = '1m42s' CertFile = '' [Mercury.Transmitter] +Protocol = 'grpc' TransmitQueueMaxSize = 123 TransmitTimeout = '3m54s' TransmitConcurrency = 456 @@ -337,6 +338,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '15m0s' [EVM.Transactions] +Enabled = true ForwardersEnabled = true MaxInFlight = 19 MaxQueued = 99 @@ -347,6 +349,9 @@ ResendAfterThreshold = '1h0m0s' [EVM.Transactions.AutoPurge] Enabled = false +[EVM.Transactions.TransactionManagerV2] +Enabled = false + [EVM.BalanceMonitor] Enabled = true @@ -497,6 +502,7 @@ OCR2CacheTTL = '1h0m0s' TxTimeout = '1h0m0s' TxRetryTimeout = '1m0s' TxConfirmTimeout = '1s' +TxExpirationRebroadcast = false TxRetentionTimeout = '0s' SkipPreflight = true Commitment = 'banana' diff --git a/core/web/resolver/testdata/config-multi-chain-effective.toml b/core/web/resolver/testdata/config-multi-chain-effective.toml index 7bdf50b9080..82b82216371 100644 --- a/core/web/resolver/testdata/config-multi-chain-effective.toml +++ b/core/web/resolver/testdata/config-multi-chain-effective.toml @@ -235,7 +235,8 @@ LatestReportDeadline = '5s' CertFile = '' [Mercury.Transmitter] -TransmitQueueMaxSize = 10000 +Protocol = 'wsrpc' +TransmitQueueMaxSize = 100000 TransmitTimeout = '5s' TransmitConcurrency = 100 @@ -320,6 +321,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '9m0s' [EVM.Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -330,6 +332,9 @@ ResendAfterThreshold = '1m0s' [EVM.Transactions.AutoPurge] Enabled = false +[EVM.Transactions.TransactionManagerV2] +Enabled = false + [EVM.BalanceMonitor] Enabled = true @@ -430,6 +435,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [EVM.Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -440,6 +446,9 @@ ResendAfterThreshold = '1m0s' [EVM.Transactions.AutoPurge] Enabled = false +[EVM.Transactions.TransactionManagerV2] +Enabled = false + [EVM.BalanceMonitor] Enabled = true @@ -534,6 +543,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '6m0s' [EVM.Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 5000 @@ -544,6 +554,9 @@ ResendAfterThreshold = '1m0s' [EVM.Transactions.AutoPurge] Enabled = false +[EVM.Transactions.TransactionManagerV2] +Enabled = false + [EVM.BalanceMonitor] Enabled = true @@ -659,6 +672,7 @@ OCR2CacheTTL = '1m0s' TxTimeout = '1m0s' TxRetryTimeout = '10s' TxConfirmTimeout = '30s' +TxExpirationRebroadcast = false TxRetentionTimeout = '0s' SkipPreflight = true Commitment = 'confirmed' @@ -704,6 +718,7 @@ OCR2CacheTTL = '1m0s' TxTimeout = '1m0s' TxRetryTimeout = '10s' TxConfirmTimeout = '30s' +TxExpirationRebroadcast = false TxRetentionTimeout = '0s' SkipPreflight = true Commitment = 'confirmed' diff --git a/core/web/resolver/tron_key.go b/core/web/resolver/tron_key.go new file mode 100644 index 00000000000..d42ed2071c4 --- /dev/null +++ b/core/web/resolver/tron_key.go @@ -0,0 +1,43 @@ +package resolver + +import ( + "github.com/graph-gophers/graphql-go" + + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/tronkey" +) + +type TronKeyResolver struct { + key tronkey.Key +} + +func NewTronKey(key tronkey.Key) *TronKeyResolver { + return &TronKeyResolver{key: key} +} + +func NewTronKeys(keys []tronkey.Key) []*TronKeyResolver { + resolvers := make([]*TronKeyResolver, 0, len(keys)) + + for _, k := range keys { + resolvers = append(resolvers, NewTronKey(k)) + } + + return resolvers +} + +func (r *TronKeyResolver) ID() graphql.ID { + return graphql.ID(r.key.ID()) +} + +// -- GetTronKeys Query -- + +type TronKeysPayloadResolver struct { + keys []tronkey.Key +} + +func NewTronKeysPayload(keys []tronkey.Key) *TronKeysPayloadResolver { + return &TronKeysPayloadResolver{keys: keys} +} + +func (r *TronKeysPayloadResolver) Results() []*TronKeyResolver { + return NewTronKeys(r.keys) +} diff --git a/core/web/resolver/tron_key_test.go b/core/web/resolver/tron_key_test.go new file mode 100644 index 00000000000..6ccbeb1072d --- /dev/null +++ b/core/web/resolver/tron_key_test.go @@ -0,0 +1,74 @@ +package resolver + +import ( + "context" + "errors" + "fmt" + "testing" + + gqlerrors "github.com/graph-gophers/graphql-go/errors" + + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/keystest" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/tronkey" +) + +func TestResolver_TronKeys(t *testing.T) { + t.Parallel() + + query := ` + query GetTronKeys { + tronKeys { + results { + id + } + } + }` + k := tronkey.MustNewInsecure(keystest.NewRandReaderFromSeed(1)) + result := fmt.Sprintf(` + { + "tronKeys": { + "results": [ + { + "id": "%s" + } + ] + } + }`, k.ID()) + gError := errors.New("error") + + testCases := []GQLTestCase{ + unauthorizedTestCase(GQLTestCase{query: query}, "tronKeys"), + { + name: "success", + authenticated: true, + before: func(ctx context.Context, f *gqlTestFramework) { + f.Mocks.tron.On("GetAll").Return([]tronkey.Key{k}, nil) + f.Mocks.keystore.On("Tron").Return(f.Mocks.tron) + f.App.On("GetKeyStore").Return(f.Mocks.keystore) + }, + query: query, + result: result, + }, + { + name: "no keys returned by GetAll", + authenticated: true, + before: func(ctx context.Context, f *gqlTestFramework) { + f.Mocks.tron.On("GetAll").Return([]tronkey.Key{}, gError) + f.Mocks.keystore.On("Tron").Return(f.Mocks.tron) + f.App.On("GetKeyStore").Return(f.Mocks.keystore) + }, + query: query, + result: `null`, + errors: []*gqlerrors.QueryError{ + { + Extensions: nil, + ResolverError: gError, + Path: []interface{}{"tronKeys"}, + Message: gError.Error(), + }, + }, + }, + } + + RunGQLTests(t, testCases) +} diff --git a/core/web/router.go b/core/web/router.go index c57bf3c8095..f56d3e69651 100644 --- a/core/web/router.go +++ b/core/web/router.go @@ -351,6 +351,7 @@ func v2Routes(app chainlink.Application, r *gin.RouterGroup) { {"cosmos", NewCosmosKeysController(app)}, {"starknet", NewStarkNetKeysController(app)}, {"aptos", NewAptosKeysController(app)}, + {"tron", NewTronKeysController(app)}, } { authv2.GET("/keys/"+keys.path, keys.kc.Index) authv2.POST("/keys/"+keys.path, auth.RequiresEditRole(keys.kc.Create)) diff --git a/core/web/schema/schema.graphql b/core/web/schema/schema.graphql index 568716f7b76..6f9e51b79eb 100644 --- a/core/web/schema/schema.graphql +++ b/core/web/schema/schema.graphql @@ -36,6 +36,7 @@ type Query { aptosKeys: AptosKeysPayload! cosmosKeys: CosmosKeysPayload! starknetKeys: StarkNetKeysPayload! + tronKeys: TronKeysPayload! sqlLogging: GetSQLLoggingPayload! vrfKey(id: ID!): VRFKeyPayload! vrfKeys: VRFKeysPayload! diff --git a/core/web/schema/type/ocr2_keys.graphql b/core/web/schema/type/ocr2_keys.graphql index c25148c686a..89125d86b54 100644 --- a/core/web/schema/type/ocr2_keys.graphql +++ b/core/web/schema/type/ocr2_keys.graphql @@ -4,6 +4,7 @@ enum OCR2ChainType { SOLANA STARKNET APTOS + TRON } type OCR2KeyBundle { diff --git a/core/web/schema/type/tron_key.graphql b/core/web/schema/type/tron_key.graphql new file mode 100644 index 00000000000..e7319f08d6b --- /dev/null +++ b/core/web/schema/type/tron_key.graphql @@ -0,0 +1,7 @@ +type TronKey { + id: ID! +} + +type TronKeysPayload { + results: [TronKey!]! +} diff --git a/core/web/testdata/body/health.html b/core/web/testdata/body/health.html index 4692d452a5b..cff516904bc 100644 --- a/core/web/testdata/body/health.html +++ b/core/web/testdata/body/health.html @@ -93,6 +93,9 @@
HeadReporter
+
+ Heartbeat +
JobSpawner
diff --git a/core/web/testdata/body/health.json b/core/web/testdata/body/health.json index 8c4c3b312de..9c36f4d4a47 100644 --- a/core/web/testdata/body/health.json +++ b/core/web/testdata/body/health.json @@ -153,6 +153,15 @@ "output": "" } }, + { + "type": "checks", + "id": "Heartbeat", + "attributes": { + "name": "Heartbeat", + "status": "passing", + "output": "" + } + }, { "type": "checks", "id": "JobSpawner", diff --git a/core/web/testdata/body/health.txt b/core/web/testdata/body/health.txt index a098f906146..a12bbae56ef 100644 --- a/core/web/testdata/body/health.txt +++ b/core/web/testdata/body/health.txt @@ -16,6 +16,7 @@ ok EVM.0.Txm.Confirmer ok EVM.0.Txm.Finalizer ok EVM.0.Txm.WrappedEvmEstimator ok HeadReporter +ok Heartbeat ok JobSpawner ok Mailbox.Monitor ok Mercury.WSRPCPool diff --git a/core/web/tron_keys_controller.go b/core/web/tron_keys_controller.go new file mode 100644 index 00000000000..e9ac2e0252e --- /dev/null +++ b/core/web/tron_keys_controller.go @@ -0,0 +1,12 @@ +package web + +import ( + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/tronkey" + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +func NewTronKeysController(app chainlink.Application) KeysController { + return NewKeysController[tronkey.Key, presenters.TronKeyResource](app.GetKeyStore().Tron(), app.GetLogger(), app.GetAuditLogger(), + "tronKey", presenters.NewTronKeyResource, presenters.NewTronKeyResources) +} diff --git a/core/web/tron_keys_controller_test.go b/core/web/tron_keys_controller_test.go new file mode 100644 index 00000000000..5628d7ac2dc --- /dev/null +++ b/core/web/tron_keys_controller_test.go @@ -0,0 +1,105 @@ +package web_test + +import ( + "net/http" + "testing" + + "github.com/smartcontractkit/chainlink-common/pkg/utils" + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore" + "github.com/smartcontractkit/chainlink/v2/core/web" + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" + + "github.com/stretchr/testify/require" +) + +func TestTronKeysController_Index_HappyPath(t *testing.T) { + t.Parallel() + + client, keyStore := setupTronKeysControllerTests(t) + keys, _ := keyStore.Tron().GetAll() + + response, cleanup := client.Get("/v2/keys/tron") + t.Cleanup(cleanup) + cltest.AssertServerResponse(t, response, http.StatusOK) + + resources := []presenters.TronKeyResource{} + err := web.ParseJSONAPIResponse(cltest.ParseResponseBody(t, response), &resources) + require.NoError(t, err) + + require.Len(t, resources, len(keys)) + + require.Equal(t, keys[0].ID(), resources[0].ID) + require.Equal(t, keys[0].PublicKeyStr(), resources[0].PubKey) +} + +func TestTronKeysController_Create_HappyPath(t *testing.T) { + t.Parallel() + + app := cltest.NewApplicationEVMDisabled(t) + require.NoError(t, app.Start(testutils.Context(t))) + client := app.NewHTTPClient(nil) + keyStore := app.GetKeyStore() + + response, cleanup := client.Post("/v2/keys/tron", nil) + t.Cleanup(cleanup) + cltest.AssertServerResponse(t, response, http.StatusOK) + + keys, _ := keyStore.Tron().GetAll() + require.Len(t, keys, 1) + + resource := presenters.TronKeyResource{} + err := web.ParseJSONAPIResponse(cltest.ParseResponseBody(t, response), &resource) + require.NoError(t, err) + + require.Equal(t, keys[0].ID(), resource.ID) + require.Equal(t, keys[0].PublicKeyStr(), resource.PubKey) + + _, err = keyStore.Tron().Get(resource.ID) + require.NoError(t, err) +} + +func TestTronKeysController_Delete_NonExistentTronKeyID(t *testing.T) { + t.Parallel() + + client, _ := setupTronKeysControllerTests(t) + + nonExistentTronKeyID := "foobar" + response, cleanup := client.Delete("/v2/keys/tron/" + nonExistentTronKeyID) + t.Cleanup(cleanup) + require.Equal(t, http.StatusNotFound, response.StatusCode) +} + +func TestTronKeysController_Delete_HappyPath(t *testing.T) { + t.Parallel() + ctx := testutils.Context(t) + + client, keyStore := setupTronKeysControllerTests(t) + + keys, _ := keyStore.Tron().GetAll() + initialLength := len(keys) + key, _ := keyStore.Tron().Create(ctx) + + response, cleanup := client.Delete("/v2/keys/tron/" + key.ID()) + t.Cleanup(cleanup) + require.Equal(t, http.StatusOK, response.StatusCode) + require.Error(t, utils.JustError(keyStore.Tron().Get(key.ID()))) + + keys, _ = keyStore.Tron().GetAll() + require.Len(t, keys, initialLength) +} + +func setupTronKeysControllerTests(t *testing.T) (cltest.HTTPClientCleaner, keystore.Master) { + t.Helper() + ctx := testutils.Context(t) + + app := cltest.NewApplication(t) + require.NoError(t, app.Start(ctx)) + require.NoError(t, app.KeyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) + require.NoError(t, app.KeyStore.Tron().Add(ctx, cltest.DefaultTronKey)) + + client := app.NewHTTPClient(nil) + + return client, app.GetKeyStore() +} diff --git a/dashboard-lib/ccip-load-test-view/component.go b/dashboard-lib/ccip-load-test-view/component.go index 790ea6e9a9d..700a0a51077 100644 --- a/dashboard-lib/ccip-load-test-view/component.go +++ b/dashboard-lib/ccip-load-test-view/component.go @@ -310,6 +310,7 @@ func reqRespRow(p Props) []dashboard.Option { return []dashboard.Option{ dashboard.Row( "Requests/Responses", + row.Collapse(), row.WithStat( "Stats", stat.DataSource(p.LokiDataSource), diff --git a/deployment/.golangci.yml b/deployment/.golangci.yml index 0268ba7beaa..edfe43c7c43 100644 --- a/deployment/.golangci.yml +++ b/deployment/.golangci.yml @@ -1,15 +1,32 @@ run: timeout: 15m + allow-parallel-runners: true linters: enable: + - containedctx + - depguard + - errname + - errorlint - exhaustive - - exportloopref - - revive + - fatcontext + - ginkgolinter + - gocritic - goimports - gosec + - loggercheck + - mirror - misspell + - noctx + - nolintlint + - perfsprint + - prealloc + - revive - rowserrcheck - - errorlint + - spancheck + - sqlclosecheck + - testifylint + - unconvert + - whitespace linters-settings: exhaustive: default-signifies-exhaustive: true @@ -23,6 +40,28 @@ linters-settings: govet: enable: - shadow + settings: + printf: + # Additionally check chainlink custom loggers + funcs: + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Tracef + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Debugf + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Infof + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Warnf + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Errorf + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Criticalf + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Panicf + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Fatalf + - (github.com/smartcontractkit/chainlink/v2/core/logger.SugaredLogger).AssumptionViolationf + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Debugf + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Infof + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Warnf + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Errorf + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Panicf + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Fatalf + - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).AssumptionViolationf + - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).Tracef + - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).Criticalf revive: confidence: 0.8 rules: @@ -33,9 +72,10 @@ linters-settings: - name: error-return - name: error-strings - name: error-naming + - name: exported - name: if-return - name: increment-decrement - # - name: var-naming // doesn't work with some generated names + - name: var-naming - name: var-declaration - name: package-comments - name: range @@ -46,7 +86,7 @@ linters-settings: - name: errorf - name: empty-block - name: superfluous-else - #- name: unused-parameter + # - name: unused-parameter - name: unreachable-code - name: redefines-builtin-id - name: waitgroup-by-value @@ -61,15 +101,74 @@ linters-settings: - name: identical-branches - name: get-return # - name: flag-parameter // probably one we should work on doing better at in the future - # - name: early-return // probably one we should work on doing better at in the future + - name: early-return - name: defer - name: constant-logical-expr - name: confusing-naming - name: confusing-results - name: bool-literal-in-expr - name: atomic + depguard: + rules: + main: + list-mode: lax + deny: + - pkg: cosmossdk.io/errors + desc: Use the standard library instead + - pkg: github.com/gofrs/uuid + desc: Use github.com/google/uuid instead + - pkg: github.com/jackc/pgx3 + desc: Use github.com/jackc/pgx4 instead + - pkg: github.com/jackc/pgx5 + desc: Use github.com/jackc/pgx4 instead + - pkg: github.com/satori/go.uuid + desc: Use github.com/google/uuid instead + - pkg: github.com/test-go/testify/assert + desc: Use github.com/stretchr/testify/assert instead + - pkg: github.com/test-go/testify/mock + desc: Use github.com/stretchr/testify/mock instead + - pkg: github.com/test-go/testify/require + desc: Use github.com/stretchr/testify/require instead + - pkg: go.uber.org/multierr + desc: Use the standard library instead, for example https://pkg.go.dev/errors#Join + - pkg: gopkg.in/guregu/null.v1 + desc: Use gopkg.in/guregu/null.v4 instead + - pkg: gopkg.in/guregu/null.v2 + desc: Use gopkg.in/guregu/null.v4 instead + - pkg: gopkg.in/guregu/null.v3 + desc: Use gopkg.in/guregu/null.v4 instead + - pkg: github.com/go-gorm/gorm + desc: Use github.com/jmoiron/sqlx directly instead + loggercheck: + # Check that *w logging functions have even number of args (i.e., well formed key-value pairs). + rules: + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Tracew + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Debugw + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Infow + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Warnw + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Errorw + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Criticalw + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Panicw + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Fatalw + - (github.com/smartcontractkit/chainlink/v2/core/logger.SugaredLogger).AssumptionViolationw + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Debugw + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Infow + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Warnw + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Errorw + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Panicw + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Fatalw + - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).AssumptionViolationw + - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).Tracew + - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).Criticalw + - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).With + nolintlint: + require-specific: true + require-explanation: true issues: exclude-rules: + - text: "^var-naming: don't use an underscore in package name" + linters: + - revive - path: memory/(.+)\.go linters: - revive diff --git a/deployment/.mockery.yaml b/deployment/.mockery.yaml new file mode 100644 index 00000000000..79e4d52104a --- /dev/null +++ b/deployment/.mockery.yaml @@ -0,0 +1,13 @@ +dir: "{{ .InterfaceDir }}/mocks" +mockname: "{{ .InterfaceName }}" +outpkg: mocks +filename: "{{ .InterfaceName | snakecase }}.go" +packages: + github.com/smartcontractkit/chainlink/deployment: + interfaces: + OffchainClient: + config: + mockname: "Mock{{ .InterfaceName }}" + filename: offchain_client_mock.go + inpackage: true + dir: "{{ .InterfaceDir }}/mocks" \ No newline at end of file diff --git a/deployment/address_book.go b/deployment/address_book.go index 3ce0332a4c3..fde0adc2d97 100644 --- a/deployment/address_book.go +++ b/deployment/address_book.go @@ -14,9 +14,9 @@ import ( ) var ( - ErrInvalidChainSelector = fmt.Errorf("invalid chain selector") - ErrInvalidAddress = fmt.Errorf("invalid address") - ErrChainNotFound = fmt.Errorf("chain not found") + ErrInvalidChainSelector = errors.New("invalid chain selector") + ErrInvalidAddress = errors.New("invalid address") + ErrChainNotFound = errors.New("chain not found") ) // ContractType is a simple string type for identifying contract types. @@ -117,7 +117,7 @@ func (m *AddressBookMap) save(chainSelector uint64, address string, typeAndVersi // TODO NONEVM-960: Add validation for non-EVM chain addresses if typeAndVersion.Type == "" { - return fmt.Errorf("type cannot be empty") + return errors.New("type cannot be empty") } if _, exists := m.addressesByChain[chainSelector]; !exists { @@ -256,7 +256,7 @@ func SearchAddressBook(ab AddressBook, chain uint64, typ ContractType) (string, } } - return "", fmt.Errorf("not found") + return "", errors.New("not found") } func AddressBookContains(ab AddressBook, chain uint64, addrToFind string) (bool, error) { diff --git a/deployment/ccip/changeset/accept_ownership_test.go b/deployment/ccip/changeset/accept_ownership_test.go index 9b71e0ad5cb..264be42cce1 100644 --- a/deployment/ccip/changeset/accept_ownership_test.go +++ b/deployment/ccip/changeset/accept_ownership_test.go @@ -1,21 +1,21 @@ -package changeset +package changeset_test import ( "testing" - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" "golang.org/x/exp/maps" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" ) func Test_NewAcceptOwnershipChangeset(t *testing.T) { t.Parallel() - e := NewMemoryEnvironment(t) - state, err := LoadOnchainState(e.Env) + e, _ := testhelpers.NewMemoryEnvironment(t) + state, err := changeset.LoadOnchainState(e.Env) require.NoError(t, err) allChains := maps.Keys(e.Env.Chains) @@ -35,7 +35,7 @@ func Test_NewAcceptOwnershipChangeset(t *testing.T) { // at this point we have the initial deploys done, now we need to transfer ownership // to the timelock contract - state, err = LoadOnchainState(e.Env) + state, err = changeset.LoadOnchainState(e.Env) require.NoError(t, err) // compose the transfer ownership and accept ownership changesets @@ -43,82 +43,10 @@ func Test_NewAcceptOwnershipChangeset(t *testing.T) { // note this doesn't have proposals. { Changeset: commonchangeset.WrapChangeSet(commonchangeset.TransferToMCMSWithTimelock), - Config: genTestTransferOwnershipConfig(e, allChains, state), + Config: testhelpers.GenTestTransferOwnershipConfig(e, allChains, state), }, }) require.NoError(t, err) - assertTimelockOwnership(t, e, allChains, state) -} - -func genTestTransferOwnershipConfig( - e DeployedEnv, - chains []uint64, - state CCIPOnChainState, -) commonchangeset.TransferToMCMSWithTimelockConfig { - var ( - timelocksPerChain = make(map[uint64]common.Address) - contracts = make(map[uint64][]common.Address) - ) - - // chain contracts - for _, chain := range chains { - timelocksPerChain[chain] = state.Chains[chain].Timelock.Address() - contracts[chain] = []common.Address{ - state.Chains[chain].OnRamp.Address(), - state.Chains[chain].OffRamp.Address(), - state.Chains[chain].FeeQuoter.Address(), - state.Chains[chain].NonceManager.Address(), - state.Chains[chain].RMNRemote.Address(), - } - } - - // home chain - homeChainTimelockAddress := state.Chains[e.HomeChainSel].Timelock.Address() - timelocksPerChain[e.HomeChainSel] = homeChainTimelockAddress - contracts[e.HomeChainSel] = append(contracts[e.HomeChainSel], - state.Chains[e.HomeChainSel].CapabilityRegistry.Address(), - state.Chains[e.HomeChainSel].CCIPHome.Address(), - state.Chains[e.HomeChainSel].RMNHome.Address(), - ) - - return commonchangeset.TransferToMCMSWithTimelockConfig{ - ContractsByChain: contracts, - } -} - -// assertTimelockOwnership asserts that the ownership of the contracts has been transferred -// to the appropriate timelock contract on each chain. -func assertTimelockOwnership( - t *testing.T, - e DeployedEnv, - chains []uint64, - state CCIPOnChainState, -) { - // check that the ownership has been transferred correctly - for _, chain := range chains { - for _, contract := range []common.Address{ - state.Chains[chain].OnRamp.Address(), - state.Chains[chain].OffRamp.Address(), - state.Chains[chain].FeeQuoter.Address(), - state.Chains[chain].NonceManager.Address(), - state.Chains[chain].RMNRemote.Address(), - } { - owner, _, err := commonchangeset.LoadOwnableContract(contract, e.Env.Chains[chain].Client) - require.NoError(t, err) - require.Equal(t, state.Chains[chain].Timelock.Address(), owner) - } - } - - // check home chain contracts ownership - homeChainTimelockAddress := state.Chains[e.HomeChainSel].Timelock.Address() - for _, contract := range []common.Address{ - state.Chains[e.HomeChainSel].CapabilityRegistry.Address(), - state.Chains[e.HomeChainSel].CCIPHome.Address(), - state.Chains[e.HomeChainSel].RMNHome.Address(), - } { - owner, _, err := commonchangeset.LoadOwnableContract(contract, e.Env.Chains[e.HomeChainSel].Client) - require.NoError(t, err) - require.Equal(t, homeChainTimelockAddress, owner) - } + testhelpers.AssertTimelockOwnership(t, e, allChains, state) } diff --git a/deployment/ccip/changeset/cs_active_candidate_test.go b/deployment/ccip/changeset/cs_active_candidate_test.go new file mode 100644 index 00000000000..a3a0505b950 --- /dev/null +++ b/deployment/ccip/changeset/cs_active_candidate_test.go @@ -0,0 +1,245 @@ +package changeset_test + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "golang.org/x/exp/maps" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" + + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func Test_ActiveCandidate(t *testing.T) { + // Setup an environment with 2 chains, a source and a dest. + // We want to have the active instance execute a few messages + // and then setup a candidate instance. The candidate instance + // should not be able to transmit anything until we make it active. + tenv, _ := testhelpers.NewMemoryEnvironment(t, + testhelpers.WithNumOfChains(2), + testhelpers.WithNumOfNodes(4)) + state, err := changeset.LoadOnchainState(tenv.Env) + require.NoError(t, err) + + // Deploy to all chains. + allChains := maps.Keys(tenv.Env.Chains) + source := allChains[0] + dest := allChains[1] + + // Connect source to dest + sourceState := state.Chains[source] + tenv.Env, err = commonchangeset.ApplyChangesets(t, tenv.Env, tenv.TimelockContracts(t), []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(changeset.UpdateOnRampsDestsChangeset), + Config: changeset.UpdateOnRampDestsConfig{ + UpdatesByChain: map[uint64]map[uint64]changeset.OnRampDestinationUpdate{ + source: { + dest: { + IsEnabled: true, + AllowListEnabled: false, + }, + }, + }, + }, + }, + { + Changeset: commonchangeset.WrapChangeSet(changeset.UpdateFeeQuoterPricesChangeset), + Config: changeset.UpdateFeeQuoterPricesConfig{ + PricesByChain: map[uint64]changeset.FeeQuoterPriceUpdatePerSource{ + source: { + TokenPrices: map[common.Address]*big.Int{ + sourceState.LinkToken.Address(): testhelpers.DefaultLinkPrice, + sourceState.Weth9.Address(): testhelpers.DefaultWethPrice, + }, + GasPrices: map[uint64]*big.Int{ + dest: testhelpers.DefaultGasPrice, + }, + }, + }, + }, + }, + { + Changeset: commonchangeset.WrapChangeSet(changeset.UpdateFeeQuoterDestsChangeset), + Config: changeset.UpdateFeeQuoterDestsConfig{ + UpdatesByChain: map[uint64]map[uint64]fee_quoter.FeeQuoterDestChainConfig{ + source: { + dest: changeset.DefaultFeeQuoterDestChainConfig(), + }, + }, + }, + }, + { + Changeset: commonchangeset.WrapChangeSet(changeset.UpdateOffRampSourcesChangeset), + Config: changeset.UpdateOffRampSourcesConfig{ + UpdatesByChain: map[uint64]map[uint64]changeset.OffRampSourceUpdate{ + dest: { + source: { + IsEnabled: true, + }, + }, + }, + }, + }, + { + Changeset: commonchangeset.WrapChangeSet(changeset.UpdateRouterRampsChangeset), + Config: changeset.UpdateRouterRampsConfig{ + UpdatesByChain: map[uint64]changeset.RouterUpdates{ + // onRamp update on source chain + source: { + OnRampUpdates: map[uint64]bool{ + dest: true, + }, + }, + // offramp update on dest chain + dest: { + OffRampUpdates: map[uint64]bool{ + source: true, + }, + }, + }, + }, + }, + }) + require.NoError(t, err) + + // check that source router has dest enabled + onRamp, err := sourceState.Router.GetOnRamp(&bind.CallOpts{ + Context: testcontext.Get(t), + }, dest) + require.NoError(t, err) + require.NotEqual(t, common.HexToAddress("0x0"), onRamp, "expected onRamp to be set") + + // Transfer ownership so that we can set new candidate configs + // and set new config digest on the offramp. + _, err = commonchangeset.ApplyChangesets(t, tenv.Env, tenv.TimelockContracts(t), []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.TransferToMCMSWithTimelock), + Config: testhelpers.GenTestTransferOwnershipConfig(tenv, allChains, state), + }, + }) + require.NoError(t, err) + testhelpers.AssertTimelockOwnership(t, tenv, allChains, state) + + sendMsg := func() { + latesthdr, err := tenv.Env.Chains[dest].Client.HeaderByNumber(testcontext.Get(t), nil) + require.NoError(t, err) + block := latesthdr.Number.Uint64() + msgSentEvent := testhelpers.TestSendRequest(t, tenv.Env, state, source, dest, false, router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(state.Chains[dest].Receiver.Address().Bytes(), 32), + Data: []byte("hello world"), + TokenAmounts: nil, + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: nil, + }) + + var ( + startBlocks = map[uint64]*uint64{ + dest: &block, + } + expectedSeqNum = map[testhelpers.SourceDestPair]uint64{ + { + SourceChainSelector: source, + DestChainSelector: dest, + }: msgSentEvent.SequenceNumber, + } + expectedSeqNumExec = map[testhelpers.SourceDestPair][]uint64{ + { + SourceChainSelector: source, + DestChainSelector: dest, + }: {msgSentEvent.SequenceNumber}, + } + ) + + // Confirm execution of the message + testhelpers.ConfirmCommitForAllWithExpectedSeqNums(t, tenv.Env, state, expectedSeqNum, startBlocks) + testhelpers.ConfirmExecWithSeqNrsForAll(t, tenv.Env, state, expectedSeqNumExec, startBlocks) + } + + // send a message from source to dest and ensure that it gets executed + sendMsg() + + var ( + capReg = state.Chains[tenv.HomeChainSel].CapabilityRegistry + ccipHome = state.Chains[tenv.HomeChainSel].CCIPHome + ) + donID, err := internal.DonIDForChain(capReg, ccipHome, dest) + require.NoError(t, err) + candidateDigestCommitBefore, err := ccipHome.GetCandidateDigest(&bind.CallOpts{ + Context: testcontext.Get(t), + }, donID, uint8(types.PluginTypeCCIPCommit)) + require.NoError(t, err) + require.Equal(t, [32]byte{}, candidateDigestCommitBefore) + candidateDigestExecBefore, err := ccipHome.GetCandidateDigest(&bind.CallOpts{ + Context: testcontext.Get(t), + }, donID, uint8(types.PluginTypeCCIPExec)) + require.NoError(t, err) + require.Equal(t, [32]byte{}, candidateDigestExecBefore) + + // Now we can add a candidate config, send another request, and observe behavior. + // The candidate config should not be able to execute messages. + tokenConfig := changeset.NewTestTokenConfig(state.Chains[tenv.FeedChainSel].USDFeeds) + _, err = commonchangeset.ApplyChangesets(t, tenv.Env, tenv.TimelockContracts(t), []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(changeset.SetCandidateChangeset), + Config: changeset.SetCandidateChangesetConfig{ + SetCandidateConfigBase: changeset.SetCandidateConfigBase{ + HomeChainSelector: tenv.HomeChainSel, + FeedChainSelector: tenv.FeedChainSel, + MCMS: &changeset.MCMSConfig{ + MinDelay: 0, + }, + }, + PluginInfo: []changeset.SetCandidatePluginInfo{ + { + // NOTE: this is technically not a new chain, but needed for validation. + OCRConfigPerRemoteChainSelector: map[uint64]changeset.CCIPOCRParams{ + dest: changeset.DeriveCCIPOCRParams( + changeset.WithDefaultCommitOffChainConfig(tenv.FeedChainSel, tokenConfig.GetTokenInfo(logger.TestLogger(t), state.Chains[dest].LinkToken, state.Chains[dest].Weth9)), + ), + }, + PluginType: types.PluginTypeCCIPCommit, + }, + { + // NOTE: this is technically not a new chain, but needed for validation. + OCRConfigPerRemoteChainSelector: map[uint64]changeset.CCIPOCRParams{ + dest: changeset.DeriveCCIPOCRParams( + changeset.WithDefaultExecuteOffChainConfig(nil), + ), + }, + PluginType: types.PluginTypeCCIPExec, + }, + }, + }, + }, + }) + require.NoError(t, err) + + // check that CCIPHome state is updated with the new candidate configs + // for the dest chain DON. + candidateDigestCommit, err := ccipHome.GetCandidateDigest(&bind.CallOpts{ + Context: testcontext.Get(t), + }, donID, uint8(types.PluginTypeCCIPCommit)) + require.NoError(t, err) + require.NotEqual(t, candidateDigestCommit, candidateDigestCommitBefore) + candidateDigestExec, err := ccipHome.GetCandidateDigest(&bind.CallOpts{ + Context: testcontext.Get(t), + }, donID, uint8(types.PluginTypeCCIPExec)) + require.NoError(t, err) + require.NotEqual(t, candidateDigestExec, candidateDigestExecBefore) + + // send a message from source to dest and ensure that it gets executed after the candidate config is set + sendMsg() +} diff --git a/deployment/ccip/changeset/cs_add_chain.go b/deployment/ccip/changeset/cs_add_chain.go deleted file mode 100644 index ddb6e61d5ba..00000000000 --- a/deployment/ccip/changeset/cs_add_chain.go +++ /dev/null @@ -1,173 +0,0 @@ -package changeset - -import ( - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/common" - - "github.com/smartcontractkit/chainlink-ccip/chainconfig" - "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - - "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" -) - -var _ deployment.ChangeSet[ChainInboundChangesetConfig] = NewChainInboundChangeset - -type ChainInboundChangesetConfig struct { - HomeChainSelector uint64 - NewChainSelector uint64 - SourceChainSelectors []uint64 -} - -func (c ChainInboundChangesetConfig) Validate() error { - if c.HomeChainSelector == 0 { - return fmt.Errorf("HomeChainSelector must be set") - } - if c.NewChainSelector == 0 { - return fmt.Errorf("NewChainSelector must be set") - } - if len(c.SourceChainSelectors) == 0 { - return fmt.Errorf("SourceChainSelectors must be set") - } - return nil -} - -// NewChainInboundChangeset generates a proposal -// to connect the new chain to the existing chains. -func NewChainInboundChangeset( - e deployment.Environment, - cfg ChainInboundChangesetConfig, -) (deployment.ChangesetOutput, error) { - if err := cfg.Validate(); err != nil { - return deployment.ChangesetOutput{}, err - } - - state, err := LoadOnchainState(e) - if err != nil { - return deployment.ChangesetOutput{}, err - } - // Generate proposal which enables new destination (from test router) on all source chains. - var batches []timelock.BatchChainOperation - for _, source := range cfg.SourceChainSelectors { - enableOnRampDest, err := state.Chains[source].OnRamp.ApplyDestChainConfigUpdates(deployment.SimTransactOpts(), []onramp.OnRampDestChainConfigArgs{ - { - DestChainSelector: cfg.NewChainSelector, - Router: state.Chains[source].TestRouter.Address(), - }, - }) - if err != nil { - return deployment.ChangesetOutput{}, err - } - enableFeeQuoterDest, err := state.Chains[source].FeeQuoter.ApplyDestChainConfigUpdates( - deployment.SimTransactOpts(), - []fee_quoter.FeeQuoterDestChainConfigArgs{ - { - DestChainSelector: cfg.NewChainSelector, - DestChainConfig: DefaultFeeQuoterDestChainConfig(), - }, - }) - if err != nil { - return deployment.ChangesetOutput{}, err - } - batches = append(batches, timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(source), - Batch: []mcms.Operation{ - { - // Enable the source in on ramp - To: state.Chains[source].OnRamp.Address(), - Data: enableOnRampDest.Data(), - Value: big.NewInt(0), - }, - { - To: state.Chains[source].FeeQuoter.Address(), - Data: enableFeeQuoterDest.Data(), - Value: big.NewInt(0), - }, - }, - }) - } - - addChainOp, err := applyChainConfigUpdatesOp(e, state, cfg.HomeChainSelector, []uint64{cfg.NewChainSelector}) - if err != nil { - return deployment.ChangesetOutput{}, err - } - - batches = append(batches, timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(cfg.HomeChainSelector), - Batch: []mcms.Operation{ - addChainOp, - }, - }) - - var ( - timelocksPerChain = make(map[uint64]common.Address) - proposerMCMSes = make(map[uint64]*gethwrappers.ManyChainMultiSig) - ) - for _, chain := range append(cfg.SourceChainSelectors, cfg.HomeChainSelector) { - timelocksPerChain[chain] = state.Chains[chain].Timelock.Address() - proposerMCMSes[chain] = state.Chains[chain].ProposerMcm - } - prop, err := proposalutils.BuildProposalFromBatches( - timelocksPerChain, - proposerMCMSes, - batches, - "proposal to set new chains", - 0, - ) - if err != nil { - return deployment.ChangesetOutput{}, err - } - - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{*prop}, - }, nil -} - -func applyChainConfigUpdatesOp( - e deployment.Environment, - state CCIPOnChainState, - homeChainSel uint64, - chains []uint64, -) (mcms.Operation, error) { - nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) - if err != nil { - return mcms.Operation{}, err - } - encodedExtraChainConfig, err := chainconfig.EncodeChainConfig(chainconfig.ChainConfig{ - GasPriceDeviationPPB: ccipocr3.NewBigIntFromInt64(1000), - DAGasPriceDeviationPPB: ccipocr3.NewBigIntFromInt64(0), - OptimisticConfirmations: 1, - }) - if err != nil { - return mcms.Operation{}, err - } - var chainConfigUpdates []ccip_home.CCIPHomeChainConfigArgs - for _, chainSel := range chains { - chainConfig := setupConfigInfo(chainSel, nodes.NonBootstraps().PeerIDs(), - nodes.DefaultF(), encodedExtraChainConfig) - chainConfigUpdates = append(chainConfigUpdates, chainConfig) - } - - addChain, err := state.Chains[homeChainSel].CCIPHome.ApplyChainConfigUpdates( - deployment.SimTransactOpts(), - nil, - chainConfigUpdates, - ) - if err != nil { - return mcms.Operation{}, err - } - return mcms.Operation{ - To: state.Chains[homeChainSel].CCIPHome.Address(), - Data: addChain.Data(), - Value: big.NewInt(0), - }, nil -} diff --git a/deployment/ccip/changeset/cs_add_chain_test.go b/deployment/ccip/changeset/cs_add_chain_test.go deleted file mode 100644 index a70ea814881..00000000000 --- a/deployment/ccip/changeset/cs_add_chain_test.go +++ /dev/null @@ -1,335 +0,0 @@ -package changeset - -import ( - "testing" - "time" - - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" - commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - - "github.com/ethereum/go-ethereum/common" - - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils" - - "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" - - "github.com/smartcontractkit/chainlink/deployment" - - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -func TestAddChainInbound(t *testing.T) { - t.Skipf("Skipping test as it is running into timeout issues, move the test into integration in-memory tests") - t.Parallel() - // 4 chains where the 4th is added after initial deployment. - e := NewMemoryEnvironment(t, - WithChains(4), - WithJobsOnly(), - ) - state, err := LoadOnchainState(e.Env) - require.NoError(t, err) - // Take first non-home chain as the new chain. - newChain := e.Env.AllChainSelectorsExcluding([]uint64{e.HomeChainSel})[0] - // We deploy to the rest. - initialDeploy := e.Env.AllChainSelectorsExcluding([]uint64{newChain}) - newAddresses := deployment.NewMemoryAddressBook() - err = deployPrerequisiteChainContracts(e.Env, newAddresses, initialDeploy, nil) - require.NoError(t, err) - require.NoError(t, e.Env.ExistingAddresses.Merge(newAddresses)) - - cfg := proposalutils.SingleGroupTimelockConfig(t) - e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, nil, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployLinkToken), - Config: initialDeploy, - }, - { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock), - Config: map[uint64]commontypes.MCMSWithTimelockConfig{ - initialDeploy[0]: cfg, - initialDeploy[1]: cfg, - initialDeploy[2]: cfg, - }, - }, - }) - require.NoError(t, err) - newAddresses = deployment.NewMemoryAddressBook() - tokenConfig := NewTestTokenConfig(state.Chains[e.FeedChainSel].USDFeeds) - - chainConfig := make(map[uint64]CCIPOCRParams) - for _, chain := range initialDeploy { - chainConfig[chain] = DefaultOCRParams(e.FeedChainSel, nil, nil) - } - newChainCfg := NewChainsConfig{ - HomeChainSel: e.HomeChainSel, - FeedChainSel: e.FeedChainSel, - ChainConfigByChain: chainConfig, - } - e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, nil, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(DeployChainContracts), - Config: DeployChainContractsConfig{ - ChainSelectors: newChainCfg.Chains(), - HomeChainSelector: newChainCfg.HomeChainSel, - }, - }, - { - Changeset: commonchangeset.WrapChangeSet(ConfigureNewChains), - Config: newChainCfg, - }, - }) - require.NoError(t, err) - - state, err = LoadOnchainState(e.Env) - require.NoError(t, err) - - // Connect all the existing lanes. - for _, source := range initialDeploy { - for _, dest := range initialDeploy { - if source != dest { - require.NoError(t, AddLaneWithDefaultPricesAndFeeQuoterConfig(e.Env, state, source, dest, false)) - } - } - } - - rmnHomeAddress, err := deployment.SearchAddressBook(e.Env.ExistingAddresses, e.HomeChainSel, RMNHome) - require.NoError(t, err) - require.True(t, common.IsHexAddress(rmnHomeAddress)) - rmnHome, err := rmn_home.NewRMNHome(common.HexToAddress(rmnHomeAddress), e.Env.Chains[e.HomeChainSel].Client) - require.NoError(t, err) - - // Deploy contracts to new chain - e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, nil, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployLinkToken), - Config: []uint64{newChain}, - }, - { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock), - Config: map[uint64]commontypes.MCMSWithTimelockConfig{ - newChain: cfg, - }, - }, - }) - require.NoError(t, err) - newAddresses = deployment.NewMemoryAddressBook() - - err = deployPrerequisiteChainContracts(e.Env, newAddresses, []uint64{newChain}, nil) - require.NoError(t, err) - require.NoError(t, e.Env.ExistingAddresses.Merge(newAddresses)) - newAddresses = deployment.NewMemoryAddressBook() - err = deployChainContracts(e.Env, - e.Env.Chains[newChain], newAddresses, rmnHome) - require.NoError(t, err) - require.NoError(t, e.Env.ExistingAddresses.Merge(newAddresses)) - state, err = LoadOnchainState(e.Env) - require.NoError(t, err) - - // configure the testrouter appropriately on each chain - for _, source := range initialDeploy { - tx, err := state.Chains[source].TestRouter.ApplyRampUpdates(e.Env.Chains[source].DeployerKey, []router.RouterOnRamp{ - { - DestChainSelector: newChain, - OnRamp: state.Chains[source].OnRamp.Address(), - }, - }, nil, nil) - _, err = deployment.ConfirmIfNoError(e.Env.Chains[source], tx, err) - require.NoError(t, err) - } - - // transfer ownership to timelock - _, err = commonchangeset.ApplyChangesets(t, e.Env, map[uint64]*proposalutils.TimelockExecutionContracts{ - initialDeploy[0]: { - Timelock: state.Chains[initialDeploy[0]].Timelock, - CallProxy: state.Chains[initialDeploy[0]].CallProxy, - }, - initialDeploy[1]: { - Timelock: state.Chains[initialDeploy[1]].Timelock, - CallProxy: state.Chains[initialDeploy[1]].CallProxy, - }, - initialDeploy[2]: { - Timelock: state.Chains[initialDeploy[2]].Timelock, - CallProxy: state.Chains[initialDeploy[2]].CallProxy, - }, - }, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.TransferToMCMSWithTimelock), - Config: genTestTransferOwnershipConfig(e, initialDeploy, state), - }, - { - Changeset: commonchangeset.WrapChangeSet(NewChainInboundChangeset), - Config: ChainInboundChangesetConfig{ - HomeChainSelector: e.HomeChainSel, - NewChainSelector: newChain, - SourceChainSelectors: initialDeploy, - }, - }, - }) - require.NoError(t, err) - - assertTimelockOwnership(t, e, initialDeploy, state) - - // TODO This currently is not working - Able to send the request here but request gets stuck in execution - // Send a new message and expect that this is delivered once the chain is completely set up as inbound - //TestSendRequest(t, e.Env, state, initialDeploy[0], newChain, true) - - _, err = commonchangeset.ApplyChangesets(t, e.Env, map[uint64]*proposalutils.TimelockExecutionContracts{ - e.HomeChainSel: { - Timelock: state.Chains[e.HomeChainSel].Timelock, - CallProxy: state.Chains[e.HomeChainSel].CallProxy, - }, - newChain: { - Timelock: state.Chains[newChain].Timelock, - CallProxy: state.Chains[newChain].CallProxy, - }, - }, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(AddDonAndSetCandidateChangeset), - Config: AddDonAndSetCandidateChangesetConfig{ - SetCandidateConfigBase: SetCandidateConfigBase{ - HomeChainSelector: e.HomeChainSel, - FeedChainSelector: e.FeedChainSel, - DONChainSelector: newChain, - PluginType: types.PluginTypeCCIPCommit, - CCIPOCRParams: DefaultOCRParams( - e.FeedChainSel, - tokenConfig.GetTokenInfo(logger.TestLogger(t), state.Chains[newChain].LinkToken, state.Chains[newChain].Weth9), - nil, - ), - MCMS: &MCMSConfig{ - MinDelay: 0, - }, - }, - }, - }, - { - Changeset: commonchangeset.WrapChangeSet(SetCandidateChangeset), - Config: SetCandidateChangesetConfig{ - SetCandidateConfigBase: SetCandidateConfigBase{ - HomeChainSelector: e.HomeChainSel, - FeedChainSelector: e.FeedChainSel, - DONChainSelector: newChain, - PluginType: types.PluginTypeCCIPExec, - CCIPOCRParams: DefaultOCRParams( - e.FeedChainSel, - tokenConfig.GetTokenInfo(logger.TestLogger(t), state.Chains[newChain].LinkToken, state.Chains[newChain].Weth9), - nil, - ), - MCMS: &MCMSConfig{ - MinDelay: 0, - }, - }, - }, - }, - { - Changeset: commonchangeset.WrapChangeSet(PromoteAllCandidatesChangeset), - Config: PromoteAllCandidatesChangesetConfig{ - HomeChainSelector: e.HomeChainSel, - DONChainSelector: newChain, - MCMS: &MCMSConfig{ - MinDelay: 0, - }, - }, - }, - }) - require.NoError(t, err) - - // verify if the configs are updated - require.NoError(t, ValidateCCIPHomeConfigSetUp( - e.Env.Logger, - state.Chains[e.HomeChainSel].CapabilityRegistry, - state.Chains[e.HomeChainSel].CCIPHome, - newChain, - )) - replayBlocks, err := LatestBlocksByChain(testcontext.Get(t), e.Env.Chains) - require.NoError(t, err) - - // Now configure the new chain using deployer key (not transferred to timelock yet). - var offRampEnables []offramp.OffRampSourceChainConfigArgs - for _, source := range initialDeploy { - offRampEnables = append(offRampEnables, offramp.OffRampSourceChainConfigArgs{ - Router: state.Chains[newChain].Router.Address(), - SourceChainSelector: source, - IsEnabled: true, - OnRamp: common.LeftPadBytes(state.Chains[source].OnRamp.Address().Bytes(), 32), - }) - } - tx, err := state.Chains[newChain].OffRamp.ApplySourceChainConfigUpdates(e.Env.Chains[newChain].DeployerKey, offRampEnables) - require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(e.Env.Chains[newChain], tx, err) - require.NoError(t, err) - // Set the OCR3 config on new 4th chain to enable the plugin. - latestDON, err := internal.LatestCCIPDON(state.Chains[e.HomeChainSel].CapabilityRegistry) - require.NoError(t, err) - ocrConfigs, err := internal.BuildSetOCR3ConfigArgs(latestDON.Id, state.Chains[e.HomeChainSel].CCIPHome, newChain) - require.NoError(t, err) - tx, err = state.Chains[newChain].OffRamp.SetOCR3Configs(e.Env.Chains[newChain].DeployerKey, ocrConfigs) - require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(e.Env.Chains[newChain], tx, err) - require.NoError(t, err) - - // Assert the inbound lanes to the new chain are wired correctly. - state, err = LoadOnchainState(e.Env) - require.NoError(t, err) - for _, chain := range initialDeploy { - cfg, err2 := state.Chains[chain].OnRamp.GetDestChainConfig(nil, newChain) - require.NoError(t, err2) - assert.Equal(t, cfg.Router, state.Chains[chain].TestRouter.Address()) - fqCfg, err2 := state.Chains[chain].FeeQuoter.GetDestChainConfig(nil, newChain) - require.NoError(t, err2) - assert.True(t, fqCfg.IsEnabled) - s, err2 := state.Chains[newChain].OffRamp.GetSourceChainConfig(nil, chain) - require.NoError(t, err2) - assert.Equal(t, common.LeftPadBytes(state.Chains[chain].OnRamp.Address().Bytes(), 32), s.OnRamp) - } - // Ensure job related logs are up to date. - time.Sleep(30 * time.Second) - ReplayLogs(t, e.Env.Offchain, replayBlocks) - - // TODO: Send via all inbound lanes and use parallel helper - // Now that the proposal has been executed we expect to be able to send traffic to this new 4th chain. - latesthdr, err := e.Env.Chains[newChain].Client.HeaderByNumber(testcontext.Get(t), nil) - require.NoError(t, err) - startBlock := latesthdr.Number.Uint64() - msgSentEvent := TestSendRequest(t, e.Env, state, initialDeploy[0], newChain, true, router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(state.Chains[newChain].Receiver.Address().Bytes(), 32), - Data: []byte("hello world"), - TokenAmounts: nil, - FeeToken: common.HexToAddress("0x0"), - ExtraArgs: nil, - }) - require.NoError(t, - commonutils.JustError(ConfirmCommitWithExpectedSeqNumRange(t, e.Env.Chains[initialDeploy[0]], e.Env.Chains[newChain], state.Chains[newChain].OffRamp, &startBlock, cciptypes.SeqNumRange{ - cciptypes.SeqNum(1), - cciptypes.SeqNum(msgSentEvent.SequenceNumber), - }, true))) - require.NoError(t, - commonutils.JustError( - ConfirmExecWithSeqNrs( - t, - e.Env.Chains[initialDeploy[0]], - e.Env.Chains[newChain], - state.Chains[newChain].OffRamp, - &startBlock, - []uint64{msgSentEvent.SequenceNumber}, - ), - ), - ) - - linkAddress := state.Chains[newChain].LinkToken.Address() - feeQuoter := state.Chains[newChain].FeeQuoter - timestampedPrice, err := feeQuoter.GetTokenPrice(nil, linkAddress) - require.NoError(t, err) - require.Equal(t, MockLinkPrice, timestampedPrice.Value) -} diff --git a/deployment/ccip/changeset/cs_add_lane.go b/deployment/ccip/changeset/cs_add_lane.go deleted file mode 100644 index 0bd03b56559..00000000000 --- a/deployment/ccip/changeset/cs_add_lane.go +++ /dev/null @@ -1,227 +0,0 @@ -package changeset - -import ( - "encoding/hex" - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" -) - -var _ deployment.ChangeSet[AddLanesConfig] = AddLanes - -type InitialPrices struct { - LinkPrice *big.Int // USD to the power of 18 (e18) per LINK - WethPrice *big.Int // USD to the power of 18 (e18) per WETH - GasPrice *big.Int // uint224 packed gas price in USD (112 for exec // 112 for da) -} - -func (p InitialPrices) Validate() error { - if p.LinkPrice == nil { - return fmt.Errorf("missing link price") - } - if p.WethPrice == nil { - return fmt.Errorf("missing weth price") - } - if p.GasPrice == nil { - return fmt.Errorf("missing gas price") - } - return nil -} - -type LaneConfig struct { - SourceSelector uint64 - DestSelector uint64 - InitialPricesBySource InitialPrices - FeeQuoterDestChain fee_quoter.FeeQuoterDestChainConfig - TestRouter bool -} - -type AddLanesConfig struct { - LaneConfigs []LaneConfig -} - -func (c AddLanesConfig) Validate() error { - for _, pair := range c.LaneConfigs { - if pair.SourceSelector == pair.DestSelector { - return fmt.Errorf("cannot add lane to the same chain") - } - if err := pair.InitialPricesBySource.Validate(); err != nil { - return fmt.Errorf("error in validating initial prices for chain %d : %w", pair.SourceSelector, err) - } - // TODO: add more FeeQuoterDestChainConfigArgs validation - if pair.FeeQuoterDestChain == (fee_quoter.FeeQuoterDestChainConfig{}) { - return fmt.Errorf("missing fee quoter dest chain config") - } - } - return nil -} - -// AddLanes adds lanes between chains. -// AddLanes is run while the contracts are still owned by the deployer. -// This is useful to test the initial deployment to enable lanes between chains. -// If the testrouter is enabled, the lanes can be used to send messages between chains with testrouter. -// On successful verification with testrouter, the lanes can be enabled with the main router with different addLane ChangeSet. -func AddLanes(e deployment.Environment, cfg AddLanesConfig) (deployment.ChangesetOutput, error) { - if err := cfg.Validate(); err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("invalid AddLanesConfig: %w", err) - } - newAddresses := deployment.NewMemoryAddressBook() - err := addLanes(e, cfg) - if err != nil { - e.Logger.Errorw("Failed to add lanes", "err", err) - return deployment.ChangesetOutput{}, err - } - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{}, - AddressBook: newAddresses, - JobSpecs: nil, - }, nil -} - -var DefaultInitialPrices = InitialPrices{ - LinkPrice: deployment.E18Mult(20), - WethPrice: deployment.E18Mult(4000), - GasPrice: ToPackedFee(big.NewInt(8e14), big.NewInt(0)), -} - -func addLanes(e deployment.Environment, cfg AddLanesConfig) error { - state, err := LoadOnchainState(e) - if err != nil { - return fmt.Errorf("failed to load onchain state: %w", err) - } - for _, laneCfg := range cfg.LaneConfigs { - e.Logger.Infow("Enabling lane with test router", "from", laneCfg.SourceSelector, "to", laneCfg.DestSelector) - if err := addLane(e, state, laneCfg, laneCfg.TestRouter); err != nil { - return err - } - } - return nil -} - -func addLane(e deployment.Environment, state CCIPOnChainState, config LaneConfig, isTestRouter bool) error { - // TODO: Batch - var fromRouter *router.Router - var toRouter *router.Router - from := config.SourceSelector - to := config.DestSelector - feeQuoterDestChainConfig := config.FeeQuoterDestChain - initialPrices := config.InitialPricesBySource - if isTestRouter { - fromRouter = state.Chains[from].TestRouter - toRouter = state.Chains[to].TestRouter - } else { - fromRouter = state.Chains[from].Router - toRouter = state.Chains[to].Router - } - tx, err := fromRouter.ApplyRampUpdates(e.Chains[from].DeployerKey, []router.RouterOnRamp{ - { - DestChainSelector: to, - OnRamp: state.Chains[from].OnRamp.Address(), - }, - }, []router.RouterOffRamp{}, []router.RouterOffRamp{}) - if _, err := deployment.ConfirmIfNoError(e.Chains[from], tx, err); err != nil { - return err - } - tx, err = state.Chains[from].OnRamp.ApplyDestChainConfigUpdates(e.Chains[from].DeployerKey, - []onramp.OnRampDestChainConfigArgs{ - { - DestChainSelector: to, - Router: fromRouter.Address(), - }, - }) - if _, err := deployment.ConfirmIfNoError(e.Chains[from], tx, err); err != nil { - return err - } - - _, err = state.Chains[from].FeeQuoter.UpdatePrices( - e.Chains[from].DeployerKey, fee_quoter.InternalPriceUpdates{ - TokenPriceUpdates: []fee_quoter.InternalTokenPriceUpdate{ - { - SourceToken: state.Chains[from].LinkToken.Address(), - UsdPerToken: initialPrices.LinkPrice, - }, - { - SourceToken: state.Chains[from].Weth9.Address(), - UsdPerToken: initialPrices.WethPrice, - }, - }, - GasPriceUpdates: []fee_quoter.InternalGasPriceUpdate{ - { - DestChainSelector: to, - UsdPerUnitGas: initialPrices.GasPrice, - }, - }}) - if _, err := deployment.ConfirmIfNoError(e.Chains[from], tx, err); err != nil { - return err - } - - // Enable dest in fee quoter - tx, err = state.Chains[from].FeeQuoter.ApplyDestChainConfigUpdates(e.Chains[from].DeployerKey, - []fee_quoter.FeeQuoterDestChainConfigArgs{ - { - DestChainSelector: to, - DestChainConfig: feeQuoterDestChainConfig, - }, - }) - if _, err := deployment.ConfirmIfNoError(e.Chains[from], tx, err); err != nil { - return err - } - - tx, err = state.Chains[to].OffRamp.ApplySourceChainConfigUpdates(e.Chains[to].DeployerKey, - []offramp.OffRampSourceChainConfigArgs{ - { - Router: toRouter.Address(), - SourceChainSelector: from, - IsEnabled: true, - OnRamp: common.LeftPadBytes(state.Chains[from].OnRamp.Address().Bytes(), 32), - }, - }) - if _, err := deployment.ConfirmIfNoError(e.Chains[to], tx, err); err != nil { - return err - } - tx, err = toRouter.ApplyRampUpdates(e.Chains[to].DeployerKey, []router.RouterOnRamp{}, []router.RouterOffRamp{}, []router.RouterOffRamp{ - { - SourceChainSelector: from, - OffRamp: state.Chains[to].OffRamp.Address(), - }, - }) - _, err = deployment.ConfirmIfNoError(e.Chains[to], tx, err) - return err -} - -func DefaultFeeQuoterDestChainConfig() fee_quoter.FeeQuoterDestChainConfig { - // https://github.com/smartcontractkit/ccip/blob/c4856b64bd766f1ddbaf5d13b42d3c4b12efde3a/contracts/src/v0.8/ccip/libraries/Internal.sol#L337-L337 - /* - ```Solidity - // bytes4(keccak256("CCIP ChainFamilySelector EVM")) - bytes4 public constant CHAIN_FAMILY_SELECTOR_EVM = 0x2812d52c; - ``` - */ - evmFamilySelector, _ := hex.DecodeString("2812d52c") - return fee_quoter.FeeQuoterDestChainConfig{ - IsEnabled: true, - MaxNumberOfTokensPerMsg: 10, - MaxDataBytes: 256, - MaxPerMsgGasLimit: 3_000_000, - DestGasOverhead: ccipevm.DestGasOverhead, - DefaultTokenFeeUSDCents: 1, - DestGasPerPayloadByte: ccipevm.CalldataGasPerByte, - DestDataAvailabilityOverheadGas: 100, - DestGasPerDataAvailabilityByte: 100, - DestDataAvailabilityMultiplierBps: 1, - DefaultTokenDestGasOverhead: 125_000, - DefaultTxGasLimit: 200_000, - GasMultiplierWeiPerEth: 11e17, // Gas multiplier in wei per eth is scaled by 1e18, so 11e17 is 1.1 = 110% - NetworkFeeUSDCents: 1, - ChainFamilySelector: [4]byte(evmFamilySelector), - } -} diff --git a/deployment/ccip/changeset/cs_add_lane_test.go b/deployment/ccip/changeset/cs_add_lane_test.go index 5c324c975ef..18f86d98a68 100644 --- a/deployment/ccip/changeset/cs_add_lane_test.go +++ b/deployment/ccip/changeset/cs_add_lane_test.go @@ -1,199 +1,46 @@ -package changeset +package changeset_test import ( "testing" - "time" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" - commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" ) func TestAddLanesWithTestRouter(t *testing.T) { t.Parallel() - e := NewMemoryEnvironment(t) + e, _ := testhelpers.NewMemoryEnvironment(t) // Here we have CR + nodes set up, but no CCIP contracts deployed. - state, err := LoadOnchainState(e.Env) + state, err := changeset.LoadOnchainState(e.Env) require.NoError(t, err) selectors := e.Env.AllChainSelectors() chain1, chain2 := selectors[0], selectors[1] - - _, err = AddLanes(e.Env, AddLanesConfig{ - LaneConfigs: []LaneConfig{ - { - SourceSelector: chain1, - DestSelector: chain2, - InitialPricesBySource: DefaultInitialPrices, - FeeQuoterDestChain: DefaultFeeQuoterDestChainConfig(), - TestRouter: true, - }, - }, - }) - require.NoError(t, err) + testhelpers.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &e, state, chain1, chain2, true) // Need to keep track of the block number for each chain so that event subscription can be done from that block. startBlocks := make(map[uint64]*uint64) // Send a message from each chain to every other chain. - expectedSeqNumExec := make(map[SourceDestPair][]uint64) + expectedSeqNumExec := make(map[testhelpers.SourceDestPair][]uint64) latesthdr, err := e.Env.Chains[chain2].Client.HeaderByNumber(testcontext.Get(t), nil) require.NoError(t, err) block := latesthdr.Number.Uint64() startBlocks[chain2] = &block - msgSentEvent := TestSendRequest(t, e.Env, state, chain1, chain2, true, router.ClientEVM2AnyMessage{ + msgSentEvent := testhelpers.TestSendRequest(t, e.Env, state, chain1, chain2, true, router.ClientEVM2AnyMessage{ Receiver: common.LeftPadBytes(state.Chains[chain2].Receiver.Address().Bytes(), 32), Data: []byte("hello"), TokenAmounts: nil, FeeToken: common.HexToAddress("0x0"), ExtraArgs: nil, }) - expectedSeqNumExec[SourceDestPair{ + expectedSeqNumExec[testhelpers.SourceDestPair{ SourceChainSelector: chain1, DestChainSelector: chain2, }] = []uint64{msgSentEvent.SequenceNumber} - ConfirmExecWithSeqNrsForAll(t, e.Env, state, expectedSeqNumExec, startBlocks) -} - -// TestAddLane covers the workflow of adding a lane between two chains and enabling it. -// It also covers the case where the onRamp is disabled on the OffRamp contract initially and then enabled. -func TestAddLane(t *testing.T) { - t.Skip("This test is flaky and needs to be fixed: reverted," + - "error reason: 0x07da6ee6 InsufficientFeeTokenAmount: Replace time.sleep() with polling") - - t.Parallel() - // We add more chains to the chainlink nodes than the number of chains where CCIP is deployed. - e := NewMemoryEnvironment(t) - // Here we have CR + nodes set up, but no CCIP contracts deployed. - state, err := LoadOnchainState(e.Env) - require.NoError(t, err) - - selectors := e.Env.AllChainSelectors() - chain1, chain2 := selectors[0], selectors[1] - - // We expect no lanes available on any chain. - for _, sel := range []uint64{chain1, chain2} { - chain := state.Chains[sel] - offRamps, err := chain.Router.GetOffRamps(nil) - require.NoError(t, err) - require.Len(t, offRamps, 0) - } - - replayBlocks, err := LatestBlocksByChain(testcontext.Get(t), e.Env.Chains) - require.NoError(t, err) - - // Add one lane from chain1 to chain 2 and send traffic. - require.NoError(t, AddLaneWithDefaultPricesAndFeeQuoterConfig(e.Env, state, chain1, chain2, false)) - - ReplayLogs(t, e.Env.Offchain, replayBlocks) - time.Sleep(30 * time.Second) - // disable the onRamp initially on OffRamp - disableRampTx, err := state.Chains[chain2].OffRamp.ApplySourceChainConfigUpdates(e.Env.Chains[chain2].DeployerKey, []offramp.OffRampSourceChainConfigArgs{ - { - Router: state.Chains[chain2].Router.Address(), - SourceChainSelector: chain1, - IsEnabled: false, - OnRamp: common.LeftPadBytes(state.Chains[chain1].OnRamp.Address().Bytes(), 32), - }, - }) - _, err = deployment.ConfirmIfNoError(e.Env.Chains[chain2], disableRampTx, err) - require.NoError(t, err) - - for _, sel := range []uint64{chain1, chain2} { - chain := state.Chains[sel] - offRamps, err := chain.Router.GetOffRamps(nil) - require.NoError(t, err) - if sel == chain2 { - require.Len(t, offRamps, 1) - srcCfg, err := chain.OffRamp.GetSourceChainConfig(nil, chain1) - require.NoError(t, err) - require.Equal(t, common.LeftPadBytes(state.Chains[chain1].OnRamp.Address().Bytes(), 32), srcCfg.OnRamp) - require.False(t, srcCfg.IsEnabled) - } else { - require.Len(t, offRamps, 0) - } - } - - latesthdr, err := e.Env.Chains[chain2].Client.HeaderByNumber(testcontext.Get(t), nil) - require.NoError(t, err) - startBlock := latesthdr.Number.Uint64() - // Send traffic on the first lane and it should not be processed by the plugin as onRamp is disabled - // we will check this by confirming that the message is not executed by the end of the test - msgSentEvent1 := TestSendRequest(t, e.Env, state, chain1, chain2, false, router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(state.Chains[chain2].Receiver.Address().Bytes(), 32), - Data: []byte("hello world"), - TokenAmounts: nil, - FeeToken: common.HexToAddress("0x0"), - ExtraArgs: nil, - }) - require.Equal(t, uint64(1), msgSentEvent1.SequenceNumber) - - // Add another lane - require.NoError(t, AddLaneWithDefaultPricesAndFeeQuoterConfig(e.Env, state, chain2, chain1, false)) - - // Send traffic on the second lane and it should succeed - latesthdr, err = e.Env.Chains[chain1].Client.HeaderByNumber(testcontext.Get(t), nil) - require.NoError(t, err) - startBlock2 := latesthdr.Number.Uint64() - msgSentEvent2 := TestSendRequest(t, e.Env, state, chain2, chain1, false, router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(state.Chains[chain2].Receiver.Address().Bytes(), 32), - Data: []byte("hello world"), - TokenAmounts: nil, - FeeToken: common.HexToAddress("0x0"), - ExtraArgs: nil, - }) - require.Equal(t, uint64(1), msgSentEvent2.SequenceNumber) - require.NoError(t, - commonutils.JustError( - ConfirmExecWithSeqNrs( - t, - e.Env.Chains[chain2], - e.Env.Chains[chain1], - state.Chains[chain1].OffRamp, - &startBlock2, - []uint64{msgSentEvent2.SequenceNumber}, - ), - ), - ) - - // now check for the previous message from chain 1 to chain 2 that it has not been executed till now as the onRamp was disabled - ConfirmNoExecConsistentlyWithSeqNr(t, e.Env.Chains[chain1], e.Env.Chains[chain2], state.Chains[chain2].OffRamp, msgSentEvent1.SequenceNumber, 30*time.Second) - - // enable the onRamp on OffRamp - enableRampTx, err := state.Chains[chain2].OffRamp.ApplySourceChainConfigUpdates(e.Env.Chains[chain2].DeployerKey, []offramp.OffRampSourceChainConfigArgs{ - { - Router: state.Chains[chain2].Router.Address(), - SourceChainSelector: chain1, - IsEnabled: true, - OnRamp: common.LeftPadBytes(state.Chains[chain1].OnRamp.Address().Bytes(), 32), - }, - }) - _, err = deployment.ConfirmIfNoError(e.Env.Chains[chain2], enableRampTx, err) - require.NoError(t, err) - - srcCfg, err := state.Chains[chain2].OffRamp.GetSourceChainConfig(nil, chain1) - require.NoError(t, err) - require.Equal(t, common.LeftPadBytes(state.Chains[chain1].OnRamp.Address().Bytes(), 32), srcCfg.OnRamp) - require.True(t, srcCfg.IsEnabled) - - // we need the replay here otherwise plugin is not able to locate the message - ReplayLogs(t, e.Env.Offchain, replayBlocks) - time.Sleep(30 * time.Second) - // Now that the onRamp is enabled, the request should be processed - require.NoError(t, - commonutils.JustError( - ConfirmExecWithSeqNrs( - t, - e.Env.Chains[chain1], - e.Env.Chains[chain2], - state.Chains[chain2].OffRamp, - &startBlock, - []uint64{msgSentEvent1.SequenceNumber}, - ), - ), - ) + testhelpers.ConfirmExecWithSeqNrsForAll(t, e.Env, state, expectedSeqNumExec, startBlocks) } diff --git a/deployment/ccip/changeset/cs_ccip_home.go b/deployment/ccip/changeset/cs_ccip_home.go index f1e860d9d28..ffd353e7d59 100644 --- a/deployment/ccip/changeset/cs_ccip_home.go +++ b/deployment/ccip/changeset/cs_ccip_home.go @@ -1,123 +1,372 @@ package changeset import ( - "context" + "bytes" + "encoding/hex" + "errors" "fmt" "math/big" + "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + "golang.org/x/exp/maps" + + "github.com/smartcontractkit/chainlink-ccip/chainconfig" + "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink-ccip/pluginconfig" + "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/merklemulti" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" + commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" + commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" ) var ( _ deployment.ChangeSet[AddDonAndSetCandidateChangesetConfig] = AddDonAndSetCandidateChangeset - _ deployment.ChangeSet[PromoteAllCandidatesChangesetConfig] = PromoteAllCandidatesChangeset + _ deployment.ChangeSet[PromoteCandidateChangesetConfig] = PromoteCandidateChangeset _ deployment.ChangeSet[SetCandidateChangesetConfig] = SetCandidateChangeset _ deployment.ChangeSet[RevokeCandidateChangesetConfig] = RevokeCandidateChangeset + _ deployment.ChangeSet[UpdateChainConfigConfig] = UpdateChainConfigChangeset ) -type PromoteAllCandidatesChangesetConfig struct { - HomeChainSelector uint64 +type tokenInfo interface { + Address() common.Address + Symbol(opts *bind.CallOpts) (string, error) + Decimals(opts *bind.CallOpts) (uint8, error) +} - // DONChainSelector is the chain selector of the DON that we want to promote the candidate config of. - // Note that each (chain, ccip capability version) pair has a unique DON ID. - DONChainSelector uint64 +func findTokenInfo(tokens []tokenInfo, address common.Address) (string, uint8, error) { + for _, token := range tokens { + if token.Address() == address { + tokenSymbol, err := token.Symbol(nil) + if err != nil { + return "", 0, fmt.Errorf("fetch token symbol for token %s: %w", address, err) + } + tokenDecimals, err := token.Decimals(nil) + if err != nil { + return "", 0, fmt.Errorf("fetch token decimals for token %s: %w", address, err) + } + return tokenSymbol, tokenDecimals, nil + } + } + return "", 0, fmt.Errorf("token %s not found in available tokens", address) +} - // MCMS is optional MCMS configuration, if provided the changeset will generate an MCMS proposal. - // If nil, the changeset will execute the commands directly using the deployer key - // of the provided environment. - MCMS *MCMSConfig +func validateCommitOffchainConfig(c *pluginconfig.CommitOffchainConfig, selector uint64, feedChainSel uint64, state CCIPOnChainState) error { + if err := c.Validate(); err != nil { + return fmt.Errorf("invalid commit off-chain config: %w", err) + } + for tokenAddr, tokenConfig := range c.TokenInfo { + tokenUnknownAddr, err := ccipocr3.NewUnknownAddressFromHex(string(tokenAddr)) + if err != nil { + return fmt.Errorf("invalid token address %s: %w", tokenAddr, err) + } + + aggregatorAddr := common.HexToAddress(string(tokenConfig.AggregatorAddress)) + token := common.HexToAddress(tokenUnknownAddr.String()) + tokenInfos := make([]tokenInfo, 0) + onchainState := state.Chains[selector] + for _, tk := range onchainState.BurnMintTokens677 { + tokenInfos = append(tokenInfos, tk) + } + for _, tk := range onchainState.ERC20Tokens { + tokenInfos = append(tokenInfos, tk) + } + for _, tk := range onchainState.ERC677Tokens { + tokenInfos = append(tokenInfos, tk) + } + var linkTokenInfo tokenInfo + linkTokenInfo = onchainState.LinkToken + if onchainState.LinkToken == nil { + linkTokenInfo = onchainState.StaticLinkToken + } + tokenInfos = append(tokenInfos, linkTokenInfo) + tokenInfos = append(tokenInfos, onchainState.Weth9) + symbol, decimal, err := findTokenInfo(tokenInfos, token) + if err != nil { + return err + } + if decimal != tokenConfig.Decimals { + return fmt.Errorf("token %s -address %s has %d decimals in provided token config, expected %d", + symbol, token.String(), tokenConfig.Decimals, decimal) + } + feedChainState := state.Chains[feedChainSel] + aggregatorInState := feedChainState.USDFeeds[TokenSymbol(symbol)] + if aggregatorAddr == (common.Address{}) { + return fmt.Errorf("token %s -address %s has no aggregator in provided token config", symbol, token.String()) + } + if aggregatorInState == nil { + return fmt.Errorf("token %s -address %s has no aggregator in state,"+ + " but the aggregator %s is provided in token config", symbol, token.String(), aggregatorAddr.String()) + } + if aggregatorAddr != aggregatorInState.Address() { + return fmt.Errorf("token %s -address %s has aggregator %s in provided token config, expected %s", + symbol, token.String(), aggregatorAddr.String(), aggregatorInState.Address().String()) + } + } + return nil } -func (p PromoteAllCandidatesChangesetConfig) Validate(e deployment.Environment, state CCIPOnChainState) (donID uint32, err error) { - if err := deployment.IsValidChainSelector(p.HomeChainSelector); err != nil { - return 0, fmt.Errorf("home chain selector invalid: %w", err) +func validateUSDCConfig(usdcConfig *pluginconfig.USDCCCTPObserverConfig, state CCIPOnChainState) error { + for sel, token := range usdcConfig.Tokens { + onchainState, ok := state.Chains[uint64(sel)] + if !ok { + return fmt.Errorf("chain %d does not exist in state but provided in USDCCCTPObserverConfig", sel) + } + if onchainState.USDCTokenPool == nil { + return fmt.Errorf("chain %d does not have USDC token pool deployed", sel) + } + if common.HexToAddress(token.SourcePoolAddress) != onchainState.USDCTokenPool.Address() { + return fmt.Errorf("chain %d has USDC token pool deployed at %s, "+ + "but SourcePoolAddress %s is provided in USDCCCTPObserverConfig", + sel, onchainState.USDCTokenPool.Address().String(), token.SourcePoolAddress) + } } - if err := deployment.IsValidChainSelector(p.DONChainSelector); err != nil { - return 0, fmt.Errorf("don chain selector invalid: %w", err) + return nil +} + +type CCIPOCRParams struct { + OCRParameters commontypes.OCRParameters + // Note contains pointers to Arb feeds for prices + CommitOffChainConfig *pluginconfig.CommitOffchainConfig + // Note contains USDC config + ExecuteOffChainConfig *pluginconfig.ExecuteOffchainConfig +} + +func (c CCIPOCRParams) Validate(selector uint64, feedChainSel uint64, state CCIPOnChainState) error { + if err := c.OCRParameters.Validate(); err != nil { + return fmt.Errorf("invalid OCR parameters: %w", err) } - if len(e.NodeIDs) == 0 { - return 0, fmt.Errorf("NodeIDs must be set") + if c.CommitOffChainConfig == nil && c.ExecuteOffChainConfig == nil { + return errors.New("at least one of CommitOffChainConfig or ExecuteOffChainConfig must be set") } - if state.Chains[p.HomeChainSelector].CCIPHome == nil { - return 0, fmt.Errorf("CCIPHome contract does not exist") + if c.CommitOffChainConfig != nil { + if err := validateCommitOffchainConfig(c.CommitOffChainConfig, selector, feedChainSel, state); err != nil { + return fmt.Errorf("invalid commit off-chain config: %w", err) + } } - if state.Chains[p.HomeChainSelector].CapabilityRegistry == nil { - return 0, fmt.Errorf("CapabilityRegistry contract does not exist") + if c.ExecuteOffChainConfig != nil { + if err := c.ExecuteOffChainConfig.Validate(); err != nil { + return fmt.Errorf("invalid execute off-chain config: %w", err) + } + for _, observerConfig := range c.ExecuteOffChainConfig.TokenDataObservers { + switch observerConfig.Type { + case pluginconfig.USDCCCTPHandlerType: + if err := validateUSDCConfig(observerConfig.USDCCCTPObserverConfig, state); err != nil { + return fmt.Errorf("invalid USDC config: %w", err) + } + default: + return fmt.Errorf("unknown token observer config type: %s", observerConfig.Type) + } + } } - if state.Chains[p.DONChainSelector].OffRamp == nil { - // should not be possible, but a defensive check. - return 0, fmt.Errorf("OffRamp contract does not exist") + return nil +} + +type CCIPOCROpts func(params *CCIPOCRParams) + +// WithOCRParamOverride can be used if you want to override the default OCR parameters with your custom function. +func WithOCRParamOverride(override func(params *CCIPOCRParams)) CCIPOCROpts { + return func(params *CCIPOCRParams) { + if override != nil { + override(params) + } } +} - donID, err = internal.DonIDForChain( - state.Chains[p.HomeChainSelector].CapabilityRegistry, - state.Chains[p.HomeChainSelector].CCIPHome, - p.DONChainSelector, - ) - if err != nil { - return 0, fmt.Errorf("fetch don id for chain: %w", err) +// WithDefaultCommitOffChainConfig can be used to add token info to the existing commit off-chain config. If no commit off-chain config is set, it will be created with default values. +func WithDefaultCommitOffChainConfig(feedChainSel uint64, tokenInfo map[ccipocr3.UnknownEncodedAddress]pluginconfig.TokenInfo) CCIPOCROpts { + return func(params *CCIPOCRParams) { + if params.CommitOffChainConfig == nil { + params.CommitOffChainConfig = &pluginconfig.CommitOffchainConfig{ + RemoteGasPriceBatchWriteFrequency: *config.MustNewDuration(internal.RemoteGasPriceBatchWriteFrequency), + TokenPriceBatchWriteFrequency: *config.MustNewDuration(internal.TokenPriceBatchWriteFrequency), + TokenInfo: tokenInfo, + PriceFeedChainSelector: ccipocr3.ChainSelector(feedChainSel), + NewMsgScanBatchSize: merklemulti.MaxNumberTreeLeaves, + MaxReportTransmissionCheckAttempts: 5, + RMNEnabled: false, + RMNSignaturesTimeout: 30 * time.Minute, + MaxMerkleTreeSize: merklemulti.MaxNumberTreeLeaves, + SignObservationPrefix: "chainlink ccip 1.6 rmn observation", + } + } else { + if params.CommitOffChainConfig.TokenInfo == nil { + params.CommitOffChainConfig.TokenInfo = make(map[ccipocr3.UnknownEncodedAddress]pluginconfig.TokenInfo) + } + for k, v := range tokenInfo { + params.CommitOffChainConfig.TokenInfo[k] = v + } + } } - if donID == 0 { - return 0, fmt.Errorf("don doesn't exist in CR for chain %d", p.DONChainSelector) +} + +// WithDefaultExecuteOffChainConfig can be used to add token data observers to the execute off-chain config. If no execute off-chain config is set, it will be created with default values. +func WithDefaultExecuteOffChainConfig(tokenDataObservers []pluginconfig.TokenDataObserverConfig) CCIPOCROpts { + return func(params *CCIPOCRParams) { + if params.ExecuteOffChainConfig == nil { + params.ExecuteOffChainConfig = &pluginconfig.ExecuteOffchainConfig{ + BatchGasLimit: internal.BatchGasLimit, + RelativeBoostPerWaitHour: internal.RelativeBoostPerWaitHour, + InflightCacheExpiry: *config.MustNewDuration(internal.InflightCacheExpiry), + RootSnoozeTime: *config.MustNewDuration(internal.RootSnoozeTime), + MessageVisibilityInterval: *config.MustNewDuration(internal.FirstBlockAge), + BatchingStrategyID: internal.BatchingStrategyID, + TokenDataObservers: tokenDataObservers, + } + } else if tokenDataObservers != nil { + params.ExecuteOffChainConfig.TokenDataObservers = append(params.ExecuteOffChainConfig.TokenDataObservers, tokenDataObservers...) + } } +} - // Check that candidate digest and active digest are not both zero - this is enforced onchain. - commitConfigs, err := state.Chains[p.HomeChainSelector].CCIPHome.GetAllConfigs(&bind.CallOpts{ - Context: context.Background(), - }, donID, uint8(cctypes.PluginTypeCCIPCommit)) - if err != nil { - return 0, fmt.Errorf("fetching commit configs from cciphome: %w", err) +// DeriveCCIPOCRParams derives the default OCR parameters for a chain, with the option to override them. +func DeriveCCIPOCRParams( + opts ...CCIPOCROpts, +) CCIPOCRParams { + params := CCIPOCRParams{ + OCRParameters: commontypes.OCRParameters{ + DeltaProgress: internal.DeltaProgress, + DeltaResend: internal.DeltaResend, + DeltaInitial: internal.DeltaInitial, + DeltaRound: internal.DeltaRound, + DeltaGrace: internal.DeltaGrace, + DeltaCertifiedCommitRequest: internal.DeltaCertifiedCommitRequest, + DeltaStage: internal.DeltaStage, + Rmax: internal.Rmax, + MaxDurationQuery: internal.MaxDurationQuery, + MaxDurationObservation: internal.MaxDurationObservation, + MaxDurationShouldAcceptAttestedReport: internal.MaxDurationShouldAcceptAttestedReport, + MaxDurationShouldTransmitAcceptedReport: internal.MaxDurationShouldTransmitAcceptedReport, + }, + } + for _, opt := range opts { + opt(¶ms) } + return params +} + +type PromoteCandidatePluginInfo struct { + // RemoteChainSelectors is the chain selector of the DONs that we want to promote the candidate config of. + // Note that each (chain, ccip capability version) pair has a unique DON ID. + RemoteChainSelectors []uint64 + PluginType types.PluginType +} + +type PromoteCandidateChangesetConfig struct { + HomeChainSelector uint64 + + PluginInfo []PromoteCandidatePluginInfo + // MCMS is optional MCMS configuration, if provided the changeset will generate an MCMS proposal. + // If nil, the changeset will execute the commands directly using the deployer key + // of the provided environment. + MCMS *MCMSConfig +} - execConfigs, err := state.Chains[p.HomeChainSelector].CCIPHome.GetAllConfigs(&bind.CallOpts{ - Context: context.Background(), - }, donID, uint8(cctypes.PluginTypeCCIPExec)) +func (p PromoteCandidateChangesetConfig) Validate(e deployment.Environment) (map[uint64]uint32, error) { + state, err := LoadOnchainState(e) if err != nil { - return 0, fmt.Errorf("fetching exec configs from cciphome: %w", err) + return nil, err } - - if commitConfigs.ActiveConfig.ConfigDigest == [32]byte{} && - commitConfigs.CandidateConfig.ConfigDigest == [32]byte{} { - return 0, fmt.Errorf("commit active and candidate config digests are both zero") + if err := deployment.IsValidChainSelector(p.HomeChainSelector); err != nil { + return nil, fmt.Errorf("home chain selector invalid: %w", err) + } + homeChainState, exists := state.Chains[p.HomeChainSelector] + if !exists { + return nil, fmt.Errorf("home chain %d does not exist", p.HomeChainSelector) + } + if err := commoncs.ValidateOwnership(e.GetContext(), p.MCMS != nil, e.Chains[p.HomeChainSelector].DeployerKey.From, homeChainState.Timelock.Address(), homeChainState.CapabilityRegistry); err != nil { + return nil, err } - if execConfigs.ActiveConfig.ConfigDigest == [32]byte{} && - execConfigs.CandidateConfig.ConfigDigest == [32]byte{} { - return 0, fmt.Errorf("exec active and candidate config digests are both zero") + donIDs := make(map[uint64]uint32) + for _, plugin := range p.PluginInfo { + if plugin.PluginType != types.PluginTypeCCIPCommit && + plugin.PluginType != types.PluginTypeCCIPExec { + return nil, errors.New("PluginType must be set to either CCIPCommit or CCIPExec") + } + for _, chainSelector := range plugin.RemoteChainSelectors { + if err := deployment.IsValidChainSelector(chainSelector); err != nil { + return nil, fmt.Errorf("don chain selector invalid: %w", err) + } + chainState, exists := state.Chains[chainSelector] + if !exists { + return nil, fmt.Errorf("chain %d does not exist", chainSelector) + } + if chainState.OffRamp == nil { + // should not be possible, but a defensive check. + return nil, errors.New("OffRamp contract does not exist") + } + + donID, err := internal.DonIDForChain( + state.Chains[p.HomeChainSelector].CapabilityRegistry, + state.Chains[p.HomeChainSelector].CCIPHome, + chainSelector, + ) + if err != nil { + return nil, fmt.Errorf("fetch don id for chain: %w", err) + } + if donID == 0 { + return nil, fmt.Errorf("don doesn't exist in CR for chain %d", chainSelector) + } + // Check that candidate digest and active digest are not both zero - this is enforced onchain. + pluginConfigs, err := state.Chains[p.HomeChainSelector].CCIPHome.GetAllConfigs(&bind.CallOpts{ + Context: e.GetContext(), + }, donID, uint8(plugin.PluginType)) + if err != nil { + return nil, fmt.Errorf("fetching %s configs from cciphome: %w", plugin.PluginType.String(), err) + } + + if pluginConfigs.ActiveConfig.ConfigDigest == [32]byte{} && + pluginConfigs.CandidateConfig.ConfigDigest == [32]byte{} { + return nil, fmt.Errorf("%s active and candidate config digests are both zero", plugin.PluginType.String()) + } + donIDs[chainSelector] = donID + } + } + if len(e.NodeIDs) == 0 { + return nil, errors.New("NodeIDs must be set") + } + if state.Chains[p.HomeChainSelector].CCIPHome == nil { + return nil, errors.New("CCIPHome contract does not exist") + } + if state.Chains[p.HomeChainSelector].CapabilityRegistry == nil { + return nil, errors.New("CapabilityRegistry contract does not exist") } - return donID, nil + return donIDs, nil } -// PromoteAllCandidatesChangeset generates a proposal to call promoteCandidate on the CCIPHome through CapReg. +// PromoteCandidateChangeset generates a proposal to call promoteCandidate on the CCIPHome through CapReg. // Note that a DON must exist prior to being able to use this changeset effectively, // i.e AddDonAndSetCandidateChangeset must be called first. // This can also be used to promote a 0x0 candidate config to be the active, effectively shutting down the DON. // At that point you can call the RemoveDON changeset to remove the DON entirely from the capability registry. -func PromoteAllCandidatesChangeset( +// PromoteCandidateChangeset is NOT idempotent, once candidate config is promoted to active, if it's called again, +// It might promote empty candidate config to active, which is not desired. +func PromoteCandidateChangeset( e deployment.Environment, - cfg PromoteAllCandidatesChangesetConfig, + cfg PromoteCandidateChangesetConfig, ) (deployment.ChangesetOutput, error) { - state, err := LoadOnchainState(e) + donIDs, err := cfg.Validate(e) if err != nil { - return deployment.ChangesetOutput{}, err + return deployment.ChangesetOutput{}, fmt.Errorf("%w: %w", deployment.ErrInvalidConfig, err) } - - donID, err := cfg.Validate(e, state) + state, err := LoadOnchainState(e) if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("%w: %w", deployment.ErrInvalidConfig, err) + return deployment.ChangesetOutput{}, err } nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) @@ -132,17 +381,24 @@ func PromoteAllCandidatesChangeset( homeChain := e.Chains[cfg.HomeChainSelector] - promoteCandidateOps, err := promoteAllCandidatesForChainOps( - txOpts, - homeChain, - state.Chains[cfg.HomeChainSelector].CapabilityRegistry, - state.Chains[cfg.HomeChainSelector].CCIPHome, - nodes.NonBootstraps(), - donID, - cfg.MCMS != nil, - ) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("generating promote candidate ops: %w", err) + var ops []mcms.Operation + for _, plugin := range cfg.PluginInfo { + for _, donID := range donIDs { + promoteCandidateOps, err := promoteCandidateForChainOps( + txOpts, + homeChain, + state.Chains[cfg.HomeChainSelector].CapabilityRegistry, + state.Chains[cfg.HomeChainSelector].CCIPHome, + nodes.NonBootstraps(), + donID, + plugin.PluginType, + cfg.MCMS != nil, + ) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("generating promote candidate ops: %w", err) + } + ops = append(ops, promoteCandidateOps) + } } // Disabled MCMS means that we already executed the txes, so just return early w/out the proposals. @@ -159,9 +415,9 @@ func PromoteAllCandidatesChangeset( }, []timelock.BatchChainOperation{{ ChainIdentifier: mcms.ChainIdentifier(cfg.HomeChainSelector), - Batch: promoteCandidateOps, + Batch: ops, }}, - "promoteCandidate for commit and execution", + "promoteCandidate", cfg.MCMS.MinDelay, ) if err != nil { @@ -174,6 +430,60 @@ func PromoteAllCandidatesChangeset( }, nil } +type SetCandidatePluginInfo struct { + // OCRConfigPerRemoteChainSelector is the chain selector of the chain where the DON will be added. + OCRConfigPerRemoteChainSelector map[uint64]CCIPOCRParams + PluginType types.PluginType +} + +func (p SetCandidatePluginInfo) String() string { + allchains := maps.Keys(p.OCRConfigPerRemoteChainSelector) + return fmt.Sprintf("PluginType: %s, Chains: %v", p.PluginType.String(), allchains) +} + +func (p SetCandidatePluginInfo) Validate(state CCIPOnChainState, homeChain uint64, feedChain uint64) error { + if p.PluginType != types.PluginTypeCCIPCommit && + p.PluginType != types.PluginTypeCCIPExec { + return errors.New("PluginType must be set to either CCIPCommit or CCIPExec") + } + for chainSelector, params := range p.OCRConfigPerRemoteChainSelector { + _, ok := state.Chains[chainSelector] + if !ok { + return fmt.Errorf("chain %d does not exist in state", chainSelector) + } + if err := deployment.IsValidChainSelector(chainSelector); err != nil { + return fmt.Errorf("don chain selector invalid: %w", err) + } + if state.Chains[chainSelector].OffRamp == nil { + // should not be possible, but a defensive check. + return fmt.Errorf("OffRamp contract does not exist on don chain selector %d", chainSelector) + } + if p.PluginType == types.PluginTypeCCIPCommit && params.CommitOffChainConfig == nil { + return errors.New("commit off-chain config must be set") + } + if p.PluginType == types.PluginTypeCCIPExec && params.ExecuteOffChainConfig == nil { + return errors.New("execute off-chain config must be set") + } + + chainConfig, err := state.Chains[homeChain].CCIPHome.GetChainConfig(nil, chainSelector) + if err != nil { + return fmt.Errorf("get all chain configs: %w", err) + } + // FChain should never be zero if a chain config is set in CCIPHome + if chainConfig.FChain == 0 { + return fmt.Errorf("chain config not set up for new chain %d", chainSelector) + } + if len(chainConfig.Readers) == 0 { + return errors.New("readers must be set") + } + err = params.Validate(chainSelector, feedChain, state) + if err != nil { + return fmt.Errorf("invalid ccip ocr params: %w", err) + } + } + return nil +} + // SetCandidateConfigBase is a common base config struct for AddDonAndSetCandidateChangesetConfig and SetCandidateChangesetConfig. // This is extracted to deduplicate most of the validation logic. // Remaining validation logic is done in the specific config structs that inherit from this. @@ -181,13 +491,6 @@ type SetCandidateConfigBase struct { HomeChainSelector uint64 FeedChainSelector uint64 - // DONChainSelector is the chain selector of the chain where the DON will be added. - DONChainSelector uint64 - - PluginType types.PluginType - // Note that the PluginType field is used to determine which field in CCIPOCRParams is used. - CCIPOCRParams CCIPOCRParams - // MCMS is optional MCMS configuration, if provided the changeset will generate an MCMS proposal. // If nil, the changeset will execute the commands directly using the deployer key // of the provided environment. @@ -201,52 +504,26 @@ func (s SetCandidateConfigBase) Validate(e deployment.Environment, state CCIPOnC if err := deployment.IsValidChainSelector(s.FeedChainSelector); err != nil { return fmt.Errorf("feed chain selector invalid: %w", err) } - if err := deployment.IsValidChainSelector(s.DONChainSelector); err != nil { - return fmt.Errorf("don chain selector invalid: %w", err) + homeChainState, exists := state.Chains[s.HomeChainSelector] + if !exists { + return fmt.Errorf("home chain %d does not exist", s.HomeChainSelector) + } + if err := commoncs.ValidateOwnership(e.GetContext(), s.MCMS != nil, e.Chains[s.HomeChainSelector].DeployerKey.From, homeChainState.Timelock.Address(), homeChainState.CapabilityRegistry); err != nil { + return err } + if len(e.NodeIDs) == 0 { - return fmt.Errorf("nodeIDs must be set") + return errors.New("nodeIDs must be set") } if state.Chains[s.HomeChainSelector].CCIPHome == nil { - return fmt.Errorf("CCIPHome contract does not exist") + return errors.New("CCIPHome contract does not exist") } if state.Chains[s.HomeChainSelector].CapabilityRegistry == nil { - return fmt.Errorf("CapabilityRegistry contract does not exist") - } - if state.Chains[s.DONChainSelector].OffRamp == nil { - // should not be possible, but a defensive check. - return fmt.Errorf("OffRamp contract does not exist on don chain selector %d", s.DONChainSelector) - } - if s.PluginType != types.PluginTypeCCIPCommit && - s.PluginType != types.PluginTypeCCIPExec { - return fmt.Errorf("PluginType must be set to either CCIPCommit or CCIPExec") - } - - // no donID check since this config is used for both adding a new DON and updating an existing one. - // see AddDonAndSetCandidateChangesetConfig.Validate and SetCandidateChangesetConfig.Validate - // for these checks. - - // check that chain config is set up for the new chain - chainConfig, err := state.Chains[s.HomeChainSelector].CCIPHome.GetChainConfig(nil, s.DONChainSelector) - if err != nil { - return fmt.Errorf("get all chain configs: %w", err) - } - - // FChain should never be zero if a chain config is set in CCIPHome - if chainConfig.FChain == 0 { - return fmt.Errorf("chain config not set up for new chain %d", s.DONChainSelector) + return errors.New("CapabilityRegistry contract does not exist") } - err = s.CCIPOCRParams.Validate() - if err != nil { - return fmt.Errorf("invalid ccip ocr params: %w", err) - } - - // TODO: validate token config in the commit config, if commit is the plugin. - // TODO: validate gas config in the chain config in cciphome for this DONChainSelector. - if e.OCRSecrets.IsEmpty() { - return fmt.Errorf("OCR secrets must be set") + return errors.New("OCR secrets must be set") } return nil @@ -257,25 +534,34 @@ func (s SetCandidateConfigBase) Validate(e deployment.Environment, state CCIPOnC // In particular, we check to make sure we don't already have a DON for the chain. type AddDonAndSetCandidateChangesetConfig struct { SetCandidateConfigBase + + // Only set one plugin at a time while you are adding the DON for the first time. + // For subsequent SetCandidate call use SetCandidateChangeset as that fetches the already added DONID and sets the candidate. + PluginInfo SetCandidatePluginInfo } func (a AddDonAndSetCandidateChangesetConfig) Validate(e deployment.Environment, state CCIPOnChainState) error { - err := a.SetCandidateConfigBase.Validate(e, state) - if err != nil { + if err := a.SetCandidateConfigBase.Validate(e, state); err != nil { return err } - // check if a DON already exists for this chain - donID, err := internal.DonIDForChain( - state.Chains[a.HomeChainSelector].CapabilityRegistry, - state.Chains[a.HomeChainSelector].CCIPHome, - a.DONChainSelector, - ) - if err != nil { - return fmt.Errorf("fetch don id for chain: %w", err) + if err := a.PluginInfo.Validate(state, a.HomeChainSelector, a.FeedChainSelector); err != nil { + return fmt.Errorf("validate plugin info %s: %w", a.PluginInfo.String(), err) } - if donID != 0 { - return fmt.Errorf("don already exists in CR for chain %d, it has id %d", a.DONChainSelector, donID) + for chainSelector := range a.PluginInfo.OCRConfigPerRemoteChainSelector { + // check if a DON already exists for this chain + donID, err := internal.DonIDForChain( + state.Chains[a.HomeChainSelector].CapabilityRegistry, + state.Chains[a.HomeChainSelector].CCIPHome, + chainSelector, + ) + if err != nil { + return fmt.Errorf("fetch don id for chain: %w", err) + } + // if don already exists use SetCandidateChangeset instead + if donID != 0 { + return fmt.Errorf("don already exists in CR for chain %d, it has id %d", chainSelector, donID) + } } return nil @@ -285,12 +571,14 @@ func (a AddDonAndSetCandidateChangesetConfig) Validate(e deployment.Environment, // and sets the plugin config as candidateConfig for the don. // // This is the first step to creating a CCIP DON and must be executed before any -// other changesets (SetCandidateChangeset, PromoteAllCandidatesChangeset) +// other changesets (SetCandidateChangeset, PromoteCandidateChangeset) // can be executed. // // Note that these operations must be done together because the createDON call // in the capability registry calls the capability config contract, so we must // provide suitable calldata for CCIPHome. +// AddDonAndSetCandidateChangeset is not idempotent, if AddDON is called more than once for the same chain, +// it will throw an error because the DON would already exist for that chain. func AddDonAndSetCandidateChangeset( e deployment.Environment, cfg AddDonAndSetCandidateChangesetConfig, @@ -314,43 +602,48 @@ func AddDonAndSetCandidateChangeset( if cfg.MCMS != nil { txOpts = deployment.SimTransactOpts() } + var donOps []mcms.Operation + + for chainSelector, params := range cfg.PluginInfo.OCRConfigPerRemoteChainSelector { + newDONArgs, err := internal.BuildOCR3ConfigForCCIPHome( + e.OCRSecrets, + state.Chains[chainSelector].OffRamp, + e.Chains[chainSelector], + nodes.NonBootstraps(), + state.Chains[cfg.HomeChainSelector].RMNHome.Address(), + params.OCRParameters, + params.CommitOffChainConfig, + params.ExecuteOffChainConfig, + ) + if err != nil { + return deployment.ChangesetOutput{}, err + } - newDONArgs, err := internal.BuildOCR3ConfigForCCIPHome( - e.OCRSecrets, - state.Chains[cfg.DONChainSelector].OffRamp, - e.Chains[cfg.DONChainSelector], - nodes.NonBootstraps(), - state.Chains[cfg.HomeChainSelector].RMNHome.Address(), - cfg.CCIPOCRParams.OCRParameters, - cfg.CCIPOCRParams.CommitOffChainConfig, - cfg.CCIPOCRParams.ExecuteOffChainConfig, - ) - if err != nil { - return deployment.ChangesetOutput{}, err - } - - latestDon, err := internal.LatestCCIPDON(state.Chains[cfg.HomeChainSelector].CapabilityRegistry) - if err != nil { - return deployment.ChangesetOutput{}, err - } + latestDon, err := internal.LatestCCIPDON(state.Chains[cfg.HomeChainSelector].CapabilityRegistry) + if err != nil { + return deployment.ChangesetOutput{}, err + } - pluginOCR3Config, ok := newDONArgs[cfg.PluginType] - if !ok { - return deployment.ChangesetOutput{}, fmt.Errorf("missing commit plugin in ocr3Configs") - } + pluginOCR3Config, ok := newDONArgs[cfg.PluginInfo.PluginType] + if !ok { + return deployment.ChangesetOutput{}, fmt.Errorf("missing plugin %s in ocr3Configs", + cfg.PluginInfo.PluginType.String()) + } - expectedDonID := latestDon.Id + 1 - addDonOp, err := newDonWithCandidateOp( - txOpts, - e.Chains[cfg.HomeChainSelector], - expectedDonID, - pluginOCR3Config, - state.Chains[cfg.HomeChainSelector].CapabilityRegistry, - nodes.NonBootstraps(), - cfg.MCMS != nil, - ) - if err != nil { - return deployment.ChangesetOutput{}, err + expectedDonID := latestDon.Id + 1 + addDonOp, err := newDonWithCandidateOp( + txOpts, + e.Chains[cfg.HomeChainSelector], + expectedDonID, + pluginOCR3Config, + state.Chains[cfg.HomeChainSelector].CapabilityRegistry, + nodes.NonBootstraps(), + cfg.MCMS != nil, + ) + if err != nil { + return deployment.ChangesetOutput{}, err + } + donOps = append(donOps, addDonOp) } if cfg.MCMS == nil { return deployment.ChangesetOutput{}, nil @@ -365,9 +658,9 @@ func AddDonAndSetCandidateChangeset( }, []timelock.BatchChainOperation{{ ChainIdentifier: mcms.ChainIdentifier(cfg.HomeChainSelector), - Batch: []mcms.Operation{addDonOp}, + Batch: donOps, }}, - fmt.Sprintf("addDON on new Chain && setCandidate for plugin %s", cfg.PluginType.String()), + "addDON on new Chain && setCandidate for plugin "+cfg.PluginInfo.PluginType.String(), cfg.MCMS.MinDelay, ) if err != nil { @@ -416,7 +709,8 @@ func newDonWithCandidateOp( nodes.DefaultF(), ) if err != nil { - return mcms.Operation{}, fmt.Errorf("could not generate add don tx w/ commit config: %w", err) + return mcms.Operation{}, fmt.Errorf("could not generate add don tx w/ %s config: %w", + types.PluginType(pluginConfig.PluginType).String(), err) } if !mcmsEnabled { _, err = deployment.ConfirmIfNoError(homeChain, addDonTx, err) @@ -434,27 +728,38 @@ func newDonWithCandidateOp( type SetCandidateChangesetConfig struct { SetCandidateConfigBase + + PluginInfo []SetCandidatePluginInfo } -func (s SetCandidateChangesetConfig) Validate(e deployment.Environment, state CCIPOnChainState) (donID uint32, err error) { - err = s.SetCandidateConfigBase.Validate(e, state) +func (s SetCandidateChangesetConfig) Validate(e deployment.Environment, state CCIPOnChainState) (map[uint64]uint32, error) { + err := s.SetCandidateConfigBase.Validate(e, state) if err != nil { - return 0, err + return nil, err } - donID, err = internal.DonIDForChain( - state.Chains[s.HomeChainSelector].CapabilityRegistry, - state.Chains[s.HomeChainSelector].CCIPHome, - s.DONChainSelector, - ) - if err != nil { - return 0, fmt.Errorf("fetch don id for chain: %w", err) - } - if donID == 0 { - return 0, fmt.Errorf("don doesn't exist in CR for chain %d", s.DONChainSelector) + chainToDonIDs := make(map[uint64]uint32) + for _, plugin := range s.PluginInfo { + if err := plugin.Validate(state, s.HomeChainSelector, s.FeedChainSelector); err != nil { + return nil, fmt.Errorf("validate plugin info %s: %w", plugin.String(), err) + } + for chainSelector := range plugin.OCRConfigPerRemoteChainSelector { + donID, err := internal.DonIDForChain( + state.Chains[s.HomeChainSelector].CapabilityRegistry, + state.Chains[s.HomeChainSelector].CCIPHome, + chainSelector, + ) + if err != nil { + return nil, fmt.Errorf("fetch don id for chain: %w", err) + } + // if don doesn't exist use AddDonAndSetCandidateChangeset instead + if donID == 0 { + return nil, fmt.Errorf("don doesn't exist in CR for chain %d", chainSelector) + } + chainToDonIDs[chainSelector] = donID + } } - - return donID, nil + return chainToDonIDs, nil } // SetCandidateChangeset generates a proposal to call setCandidate on the CCIPHome through the capability registry. @@ -468,7 +773,7 @@ func SetCandidateChangeset( return deployment.ChangesetOutput{}, err } - donID, err := cfg.Validate(e, state) + chainToDonIDs, err := cfg.Validate(e, state) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("%w: %w", deployment.ErrInvalidConfig, err) } @@ -482,39 +787,45 @@ func SetCandidateChangeset( if cfg.MCMS != nil { txOpts = deployment.SimTransactOpts() } - - newDONArgs, err := internal.BuildOCR3ConfigForCCIPHome( - e.OCRSecrets, - state.Chains[cfg.DONChainSelector].OffRamp, - e.Chains[cfg.DONChainSelector], - nodes.NonBootstraps(), - state.Chains[cfg.HomeChainSelector].RMNHome.Address(), - cfg.CCIPOCRParams.OCRParameters, - cfg.CCIPOCRParams.CommitOffChainConfig, - cfg.CCIPOCRParams.ExecuteOffChainConfig, - ) - if err != nil { - return deployment.ChangesetOutput{}, err - } - - config, ok := newDONArgs[cfg.PluginType] - if !ok { - return deployment.ChangesetOutput{}, fmt.Errorf("missing %s plugin in ocr3Configs", cfg.PluginType.String()) - } - - setCandidateMCMSOps, err := setCandidateOnExistingDon( - txOpts, - e.Chains[cfg.HomeChainSelector], - state.Chains[cfg.HomeChainSelector].CapabilityRegistry, - nodes.NonBootstraps(), - donID, - config, - cfg.MCMS != nil, - ) - if err != nil { - return deployment.ChangesetOutput{}, err + var setCandidateOps []mcms.Operation + pluginInfos := make([]string, 0) + for _, plugin := range cfg.PluginInfo { + pluginInfos = append(pluginInfos, plugin.String()) + for chainSelector, params := range plugin.OCRConfigPerRemoteChainSelector { + newDONArgs, err := internal.BuildOCR3ConfigForCCIPHome( + e.OCRSecrets, + state.Chains[chainSelector].OffRamp, + e.Chains[chainSelector], + nodes.NonBootstraps(), + state.Chains[cfg.HomeChainSelector].RMNHome.Address(), + params.OCRParameters, + params.CommitOffChainConfig, + params.ExecuteOffChainConfig, + ) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + config, ok := newDONArgs[plugin.PluginType] + if !ok { + return deployment.ChangesetOutput{}, fmt.Errorf("missing %s plugin in ocr3Configs", plugin.PluginType.String()) + } + + setCandidateMCMSOps, err := setCandidateOnExistingDon( + txOpts, + e.Chains[cfg.HomeChainSelector], + state.Chains[cfg.HomeChainSelector].CapabilityRegistry, + nodes.NonBootstraps(), + chainToDonIDs[chainSelector], + config, + cfg.MCMS != nil, + ) + if err != nil { + return deployment.ChangesetOutput{}, err + } + setCandidateOps = append(setCandidateOps, setCandidateMCMSOps...) + } } - if cfg.MCMS == nil { return deployment.ChangesetOutput{}, nil } @@ -528,9 +839,9 @@ func SetCandidateChangeset( }, []timelock.BatchChainOperation{{ ChainIdentifier: mcms.ChainIdentifier(cfg.HomeChainSelector), - Batch: setCandidateMCMSOps, + Batch: setCandidateOps, }}, - fmt.Sprintf("SetCandidate for %s plugin", cfg.PluginType.String()), + fmt.Sprintf("SetCandidate for plugin details %v", pluginInfos), cfg.MCMS.MinDelay, ) if err != nil { @@ -555,7 +866,7 @@ func setCandidateOnExistingDon( mcmsEnabled bool, ) ([]mcms.Operation, error) { if donID == 0 { - return nil, fmt.Errorf("donID is zero") + return nil, errors.New("donID is zero") } encodedSetCandidateCall, err := internal.CCIPHomeABI.Pack( @@ -647,7 +958,8 @@ func promoteCandidateOp( nodes.DefaultF(), ) if err != nil { - return mcms.Operation{}, fmt.Errorf("error creating updateDon op for donID(%d) and plugin type (%d): %w", donID, pluginType, err) + return mcms.Operation{}, fmt.Errorf("error creating updateDon op for donID(%d) and plugin type (%s): %w", + donID, types.PluginType(pluginType).String(), err) } if !mcmsEnabled { _, err = deployment.ConfirmIfNoError(homeChain, updateDonTx, err) @@ -663,60 +975,47 @@ func promoteCandidateOp( }, nil } -// promoteAllCandidatesForChainOps promotes the candidate commit and exec configs to active by calling promoteCandidateAndRevokeActive on CCIPHome through the UpdateDON call on CapReg contract -func promoteAllCandidatesForChainOps( +// promoteCandidateForChainOps promotes the candidate commit and exec configs to active by calling promoteCandidateAndRevokeActive on CCIPHome through the UpdateDON call on CapReg contract +func promoteCandidateForChainOps( txOpts *bind.TransactOpts, homeChain deployment.Chain, capReg *capabilities_registry.CapabilitiesRegistry, ccipHome *ccip_home.CCIPHome, nodes deployment.Nodes, donID uint32, + pluginType cctypes.PluginType, mcmsEnabled bool, -) ([]mcms.Operation, error) { +) (mcms.Operation, error) { if donID == 0 { - return nil, fmt.Errorf("donID is zero") + return mcms.Operation{}, errors.New("donID is zero") } - - var mcmsOps []mcms.Operation - updateCommitOp, err := promoteCandidateOp( - txOpts, - homeChain, - capReg, - ccipHome, - nodes, - donID, - uint8(cctypes.PluginTypeCCIPCommit), - mcmsEnabled, - ) + digest, err := ccipHome.GetCandidateDigest(nil, donID, uint8(pluginType)) if err != nil { - return nil, fmt.Errorf("promote candidate op: %w", err) + return mcms.Operation{}, err } - mcmsOps = append(mcmsOps, updateCommitOp) - - updateExecOp, err := promoteCandidateOp( + fmt.Println("Promoting candidate for plugin", pluginType.String(), "with digest", digest) + updatePluginOp, err := promoteCandidateOp( txOpts, homeChain, capReg, ccipHome, nodes, donID, - uint8(cctypes.PluginTypeCCIPExec), + uint8(pluginType), mcmsEnabled, ) if err != nil { - return nil, fmt.Errorf("promote candidate op: %w", err) + return mcms.Operation{}, fmt.Errorf("promote candidate op for plugin %s: %w", pluginType.String(), err) } - mcmsOps = append(mcmsOps, updateExecOp) - - return mcmsOps, nil + return updatePluginOp, nil } type RevokeCandidateChangesetConfig struct { HomeChainSelector uint64 - // DONChainSelector is the chain selector whose candidate config we want to revoke. - DONChainSelector uint64 - PluginType types.PluginType + // RemoteChainSelector is the chain selector whose candidate config we want to revoke. + RemoteChainSelector uint64 + PluginType types.PluginType // MCMS is optional MCMS configuration, if provided the changeset will generate an MCMS proposal. // If nil, the changeset will execute the commands directly using the deployer key @@ -728,30 +1027,37 @@ func (r RevokeCandidateChangesetConfig) Validate(e deployment.Environment, state if err := deployment.IsValidChainSelector(r.HomeChainSelector); err != nil { return 0, fmt.Errorf("home chain selector invalid: %w", err) } - if err := deployment.IsValidChainSelector(r.DONChainSelector); err != nil { + if err := deployment.IsValidChainSelector(r.RemoteChainSelector); err != nil { return 0, fmt.Errorf("don chain selector invalid: %w", err) } if len(e.NodeIDs) == 0 { - return 0, fmt.Errorf("NodeIDs must be set") + return 0, errors.New("NodeIDs must be set") } if state.Chains[r.HomeChainSelector].CCIPHome == nil { - return 0, fmt.Errorf("CCIPHome contract does not exist") + return 0, errors.New("CCIPHome contract does not exist") } if state.Chains[r.HomeChainSelector].CapabilityRegistry == nil { - return 0, fmt.Errorf("CapabilityRegistry contract does not exist") + return 0, errors.New("CapabilityRegistry contract does not exist") + } + homeChainState, exists := state.Chains[r.HomeChainSelector] + if !exists { + return 0, fmt.Errorf("home chain %d does not exist", r.HomeChainSelector) + } + if err := commoncs.ValidateOwnership(e.GetContext(), r.MCMS != nil, e.Chains[r.HomeChainSelector].DeployerKey.From, homeChainState.Timelock.Address(), homeChainState.CapabilityRegistry); err != nil { + return 0, err } // check that the don exists for this chain donID, err = internal.DonIDForChain( state.Chains[r.HomeChainSelector].CapabilityRegistry, state.Chains[r.HomeChainSelector].CCIPHome, - r.DONChainSelector, + r.RemoteChainSelector, ) if err != nil { return 0, fmt.Errorf("fetch don id for chain: %w", err) } if donID == 0 { - return 0, fmt.Errorf("don doesn't exist in CR for chain %d", r.DONChainSelector) + return 0, fmt.Errorf("don doesn't exist in CR for chain %d", r.RemoteChainSelector) } // check that candidate digest is not zero - this is enforced onchain. @@ -760,7 +1066,7 @@ func (r RevokeCandidateChangesetConfig) Validate(e deployment.Environment, state return 0, fmt.Errorf("fetching candidate digest from cciphome: %w", err) } if candidateDigest == [32]byte{} { - return 0, fmt.Errorf("candidate config digest is zero, can't revoke it") + return 0, errors.New("candidate config digest is zero, can't revoke it") } return donID, nil @@ -816,7 +1122,7 @@ func RevokeCandidateChangeset(e deployment.Environment, cfg RevokeCandidateChang ChainIdentifier: mcms.ChainIdentifier(cfg.HomeChainSelector), Batch: ops, }}, - fmt.Sprintf("revokeCandidate for don %d", cfg.DONChainSelector), + fmt.Sprintf("revokeCandidate for don %d", cfg.RemoteChainSelector), cfg.MCMS.MinDelay, ) if err != nil { @@ -841,7 +1147,7 @@ func revokeCandidateOps( mcmsEnabled bool, ) ([]mcms.Operation, error) { if donID == 0 { - return nil, fmt.Errorf("donID is zero") + return nil, errors.New("donID is zero") } candidateDigest, err := ccipHome.GetCandidateDigest(nil, donID, pluginType) @@ -888,3 +1194,219 @@ func revokeCandidateOps( Value: big.NewInt(0), }}, nil } + +type ChainConfig struct { + Readers [][32]byte + FChain uint8 + EncodableChainConfig chainconfig.ChainConfig +} + +type UpdateChainConfigConfig struct { + HomeChainSelector uint64 + RemoteChainRemoves []uint64 + RemoteChainAdds map[uint64]ChainConfig + MCMS *MCMSConfig +} + +func (c UpdateChainConfigConfig) Validate(e deployment.Environment) error { + state, err := LoadOnchainState(e) + if err != nil { + return err + } + if err := deployment.IsValidChainSelector(c.HomeChainSelector); err != nil { + return fmt.Errorf("home chain selector invalid: %w", err) + } + if len(c.RemoteChainRemoves) == 0 && len(c.RemoteChainAdds) == 0 { + return errors.New("no chain adds or removes") + } + homeChainState, exists := state.Chains[c.HomeChainSelector] + if !exists { + return fmt.Errorf("home chain %d does not exist", c.HomeChainSelector) + } + if err := commoncs.ValidateOwnership(e.GetContext(), c.MCMS != nil, e.Chains[c.HomeChainSelector].DeployerKey.From, homeChainState.Timelock.Address(), homeChainState.CCIPHome); err != nil { + return err + } + for _, remove := range c.RemoteChainRemoves { + if err := deployment.IsValidChainSelector(remove); err != nil { + return fmt.Errorf("chain remove selector invalid: %w", err) + } + if _, ok := state.SupportedChains()[remove]; !ok { + return fmt.Errorf("chain to remove %d is not supported", remove) + } + } + for add, ccfg := range c.RemoteChainAdds { + if err := deployment.IsValidChainSelector(add); err != nil { + return fmt.Errorf("chain remove selector invalid: %w", err) + } + if _, ok := state.SupportedChains()[add]; !ok { + return fmt.Errorf("chain to add %d is not supported", add) + } + if ccfg.FChain == 0 { + return errors.New("FChain must be set") + } + if len(ccfg.Readers) == 0 { + return errors.New("Readers must be set") + } + } + return nil +} + +func UpdateChainConfigChangeset(e deployment.Environment, cfg UpdateChainConfigConfig) (deployment.ChangesetOutput, error) { + if err := cfg.Validate(e); err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("%w: %w", deployment.ErrInvalidConfig, err) + } + state, err := LoadOnchainState(e) + if err != nil { + return deployment.ChangesetOutput{}, err + } + txOpts := e.Chains[cfg.HomeChainSelector].DeployerKey + txOpts.Context = e.GetContext() + if cfg.MCMS != nil { + txOpts = deployment.SimTransactOpts() + } + var adds []ccip_home.CCIPHomeChainConfigArgs + for chain, ccfg := range cfg.RemoteChainAdds { + encodedChainConfig, err := chainconfig.EncodeChainConfig(chainconfig.ChainConfig{ + GasPriceDeviationPPB: ccfg.EncodableChainConfig.GasPriceDeviationPPB, + DAGasPriceDeviationPPB: ccfg.EncodableChainConfig.DAGasPriceDeviationPPB, + OptimisticConfirmations: ccfg.EncodableChainConfig.OptimisticConfirmations, + }) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("encoding chain config: %w", err) + } + chainConfig := ccip_home.CCIPHomeChainConfig{ + Readers: ccfg.Readers, + FChain: ccfg.FChain, + Config: encodedChainConfig, + } + existingCfg, err := state.Chains[cfg.HomeChainSelector].CCIPHome.GetChainConfig(nil, chain) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("get chain config for selector %d: %w", chain, err) + } + if isChainConfigEqual(existingCfg, chainConfig) { + e.Logger.Infow("Chain config already exists, not applying again", + "addedChain", chain, + "chainConfig", chainConfig, + ) + continue + } + adds = append(adds, ccip_home.CCIPHomeChainConfigArgs{ + ChainSelector: chain, + ChainConfig: chainConfig, + }) + } + + tx, err := state.Chains[cfg.HomeChainSelector].CCIPHome.ApplyChainConfigUpdates(txOpts, cfg.RemoteChainRemoves, adds) + if cfg.MCMS == nil { + _, err = deployment.ConfirmIfNoError(e.Chains[cfg.HomeChainSelector], tx, err) + if err != nil { + return deployment.ChangesetOutput{}, err + } + e.Logger.Infof("Updated chain config on chain %d removes %v, adds %v", cfg.HomeChainSelector, cfg.RemoteChainRemoves, cfg.RemoteChainAdds) + return deployment.ChangesetOutput{}, nil + } + + p, err := proposalutils.BuildProposalFromBatches( + map[uint64]common.Address{ + cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].Timelock.Address(), + }, + map[uint64]*gethwrappers.ManyChainMultiSig{ + cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].ProposerMcm, + }, + []timelock.BatchChainOperation{{ + ChainIdentifier: mcms.ChainIdentifier(cfg.HomeChainSelector), + Batch: []mcms.Operation{ + { + To: state.Chains[cfg.HomeChainSelector].CCIPHome.Address(), + Data: tx.Data(), + Value: big.NewInt(0), + }, + }, + }}, + "Update chain config", + cfg.MCMS.MinDelay, + ) + if err != nil { + return deployment.ChangesetOutput{}, err + } + e.Logger.Infof("Proposed chain config update on chain %d removes %v, adds %v", cfg.HomeChainSelector, cfg.RemoteChainRemoves, cfg.RemoteChainAdds) + return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{ + *p, + }}, nil +} + +func isChainConfigEqual(a, b ccip_home.CCIPHomeChainConfig) bool { + mapReader := make(map[[32]byte]struct{}) + for i := range a.Readers { + mapReader[a.Readers[i]] = struct{}{} + } + for i := range b.Readers { + if _, ok := mapReader[b.Readers[i]]; !ok { + return false + } + } + return bytes.Equal(a.Config, b.Config) && + a.FChain == b.FChain +} + +// ValidateCCIPHomeConfigSetUp checks that the commit and exec active and candidate configs are set up correctly +// TODO: Utilize this +func ValidateCCIPHomeConfigSetUp( + lggr logger.Logger, + capReg *capabilities_registry.CapabilitiesRegistry, + ccipHome *ccip_home.CCIPHome, + chainSel uint64, +) error { + // fetch DONID + donID, err := internal.DonIDForChain(capReg, ccipHome, chainSel) + if err != nil { + return fmt.Errorf("fetch don id for chain: %w", err) + } + if donID == 0 { + return fmt.Errorf("don id for chain (%d) does not exist", chainSel) + } + + // final sanity checks on configs. + commitConfigs, err := ccipHome.GetAllConfigs(&bind.CallOpts{ + //Pending: true, + }, donID, uint8(cctypes.PluginTypeCCIPCommit)) + if err != nil { + return fmt.Errorf("get all commit configs: %w", err) + } + commitActiveDigest, err := ccipHome.GetActiveDigest(nil, donID, uint8(cctypes.PluginTypeCCIPCommit)) + if err != nil { + return fmt.Errorf("get active commit digest: %w", err) + } + lggr.Debugw("Fetched active commit digest", "commitActiveDigest", hex.EncodeToString(commitActiveDigest[:])) + commitCandidateDigest, err := ccipHome.GetCandidateDigest(nil, donID, uint8(cctypes.PluginTypeCCIPCommit)) + if err != nil { + return fmt.Errorf("get commit candidate digest: %w", err) + } + lggr.Debugw("Fetched candidate commit digest", "commitCandidateDigest", hex.EncodeToString(commitCandidateDigest[:])) + if commitConfigs.ActiveConfig.ConfigDigest == [32]byte{} { + return fmt.Errorf( + "active config digest is empty for commit, expected nonempty, donID: %d, cfg: %+v, config digest from GetActiveDigest call: %x, config digest from GetCandidateDigest call: %x", + donID, commitConfigs.ActiveConfig, commitActiveDigest, commitCandidateDigest) + } + if commitConfigs.CandidateConfig.ConfigDigest != [32]byte{} { + return fmt.Errorf( + "candidate config digest is nonempty for commit, expected empty, donID: %d, cfg: %+v, config digest from GetCandidateDigest call: %x, config digest from GetActiveDigest call: %x", + donID, commitConfigs.CandidateConfig, commitCandidateDigest, commitActiveDigest) + } + + execConfigs, err := ccipHome.GetAllConfigs(nil, donID, uint8(cctypes.PluginTypeCCIPExec)) + if err != nil { + return fmt.Errorf("get all exec configs: %w", err) + } + lggr.Debugw("Fetched exec configs", + "ActiveConfig.ConfigDigest", hex.EncodeToString(execConfigs.ActiveConfig.ConfigDigest[:]), + "CandidateConfig.ConfigDigest", hex.EncodeToString(execConfigs.CandidateConfig.ConfigDigest[:]), + ) + if execConfigs.ActiveConfig.ConfigDigest == [32]byte{} { + return fmt.Errorf("active config digest is empty for exec, expected nonempty, cfg: %v", execConfigs.ActiveConfig) + } + if execConfigs.CandidateConfig.ConfigDigest != [32]byte{} { + return fmt.Errorf("candidate config digest is nonempty for exec, expected empty, cfg: %v", execConfigs.CandidateConfig) + } + return nil +} diff --git a/deployment/ccip/changeset/cs_ccip_home_test.go b/deployment/ccip/changeset/cs_ccip_home_test.go index b728e7b0c1d..73fd921d503 100644 --- a/deployment/ccip/changeset/cs_ccip_home_test.go +++ b/deployment/ccip/changeset/cs_ccip_home_test.go @@ -1,14 +1,23 @@ -package changeset +package changeset_test import ( + "math/big" + "regexp" "testing" + "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/stretchr/testify/assert" "golang.org/x/exp/maps" + "github.com/smartcontractkit/chainlink-ccip/chainconfig" + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -18,6 +27,65 @@ import ( "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" ) +func TestInvalidOCR3Params(t *testing.T) { + e, _ := testhelpers.NewMemoryEnvironment(t, + testhelpers.WithPrerequisiteDeploymentOnly(nil)) + chain1 := e.Env.AllChainSelectors()[0] + envNodes, err := deployment.NodeInfo(e.Env.NodeIDs, e.Env.Offchain) + require.NoError(t, err) + // Need to deploy prerequisites first so that we can form the USDC config + // no proposals to be made, timelock can be passed as nil here + e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, nil, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(changeset.DeployHomeChainChangeset), + Config: changeset.DeployHomeChainConfig{ + HomeChainSel: e.HomeChainSel, + RMNDynamicConfig: testhelpers.NewTestRMNDynamicConfig(), + RMNStaticConfig: testhelpers.NewTestRMNStaticConfig(), + NodeOperators: testhelpers.NewTestNodeOperator(e.Env.Chains[e.HomeChainSel].DeployerKey.From), + NodeP2PIDsPerNodeOpAdmin: map[string][][32]byte{ + testhelpers.TestNodeOperator: envNodes.NonBootstraps().PeerIDs(), + }, + }, + }, + { + Changeset: commonchangeset.WrapChangeSet(changeset.DeployChainContractsChangeset), + Config: changeset.DeployChainContractsConfig{ + ChainSelectors: []uint64{chain1}, + HomeChainSelector: e.HomeChainSel, + }, + }, + }) + require.NoError(t, err) + + state, err := changeset.LoadOnchainState(e.Env) + require.NoError(t, err) + nodes, err := deployment.NodeInfo(e.Env.NodeIDs, e.Env.Offchain) + require.NoError(t, err) + params := changeset.DeriveCCIPOCRParams( + changeset.WithDefaultCommitOffChainConfig(e.FeedChainSel, nil), + changeset.WithDefaultExecuteOffChainConfig(nil), + ) + // tweak params to have invalid config + // make DeltaRound greater than DeltaProgress + params.OCRParameters.DeltaRound = params.OCRParameters.DeltaProgress + time.Duration(1) + _, err = internal.BuildOCR3ConfigForCCIPHome( + e.Env.OCRSecrets, + state.Chains[chain1].OffRamp, + e.Env.Chains[chain1], + nodes.NonBootstraps(), + state.Chains[e.HomeChainSel].RMNHome.Address(), + params.OCRParameters, + params.CommitOffChainConfig, + params.ExecuteOffChainConfig, + ) + require.Errorf(t, err, "expected error") + pattern := `DeltaRound \(\d+\.\d+s\) must be less than DeltaProgress \(\d+s\)` + matched, err1 := regexp.MatchString(pattern, err.Error()) + require.NoError(t, err1) + require.True(t, matched) +} + func Test_PromoteCandidate(t *testing.T) { for _, tc := range []struct { name string @@ -34,10 +102,10 @@ func Test_PromoteCandidate(t *testing.T) { } { t.Run(tc.name, func(t *testing.T) { ctx := testcontext.Get(t) - tenv := NewMemoryEnvironment(t, - WithChains(2), - WithNodes(4)) - state, err := LoadOnchainState(tenv.Env) + tenv, _ := testhelpers.NewMemoryEnvironment(t, + testhelpers.WithNumOfChains(2), + testhelpers.WithNumOfNodes(4)) + state, err := changeset.LoadOnchainState(tenv.Env) require.NoError(t, err) // Deploy to all chains. @@ -57,23 +125,25 @@ func Test_PromoteCandidate(t *testing.T) { donID, err := internal.DonIDForChain(capReg, ccipHome, dest) require.NoError(t, err) require.NotEqual(t, uint32(0), donID) + t.Logf("donID: %d", donID) candidateDigestCommitBefore, err := ccipHome.GetCandidateDigest(&bind.CallOpts{ Context: ctx, }, donID, uint8(types.PluginTypeCCIPCommit)) require.NoError(t, err) require.Equal(t, [32]byte{}, candidateDigestCommitBefore) - candidateDigestExecBefore, err := ccipHome.GetCandidateDigest(&bind.CallOpts{ + ActiveDigestExecBefore, err := ccipHome.GetActiveDigest(&bind.CallOpts{ Context: ctx, }, donID, uint8(types.PluginTypeCCIPExec)) require.NoError(t, err) - require.Equal(t, [32]byte{}, candidateDigestExecBefore) + require.NotEqual(t, [32]byte{}, ActiveDigestExecBefore) - var mcmsConfig *MCMSConfig + var mcmsConfig *changeset.MCMSConfig if tc.mcmsEnabled { - mcmsConfig = &MCMSConfig{ + mcmsConfig = &changeset.MCMSConfig{ MinDelay: 0, } } + // promotes zero digest on commit and ensure exec is not affected _, err = commonchangeset.ApplyChangesets(t, tenv.Env, map[uint64]*proposalutils.TimelockExecutionContracts{ tenv.HomeChainSel: { Timelock: state.Chains[tenv.HomeChainSel].Timelock, @@ -81,11 +151,16 @@ func Test_PromoteCandidate(t *testing.T) { }, }, []commonchangeset.ChangesetApplication{ { - Changeset: commonchangeset.WrapChangeSet(PromoteAllCandidatesChangeset), - Config: PromoteAllCandidatesChangesetConfig{ + Changeset: commonchangeset.WrapChangeSet(changeset.PromoteCandidateChangeset), + Config: changeset.PromoteCandidateChangesetConfig{ HomeChainSelector: tenv.HomeChainSel, - DONChainSelector: dest, - MCMS: mcmsConfig, + PluginInfo: []changeset.PromoteCandidatePluginInfo{ + { + RemoteChainSelectors: []uint64{dest}, + PluginType: types.PluginTypeCCIPCommit, + }, + }, + MCMS: mcmsConfig, }, }, }) @@ -102,7 +177,7 @@ func Test_PromoteCandidate(t *testing.T) { Context: ctx, }, donID, uint8(types.PluginTypeCCIPExec)) require.NoError(t, err) - require.Equal(t, [32]byte{}, activeDigestExec) + require.Equal(t, ActiveDigestExecBefore, activeDigestExec) }) } } @@ -123,10 +198,10 @@ func Test_SetCandidate(t *testing.T) { } { t.Run(tc.name, func(t *testing.T) { ctx := testcontext.Get(t) - tenv := NewMemoryEnvironment(t, - WithChains(2), - WithNodes(4)) - state, err := LoadOnchainState(tenv.Env) + tenv, _ := testhelpers.NewMemoryEnvironment(t, + testhelpers.WithNumOfChains(2), + testhelpers.WithNumOfNodes(4)) + state, err := changeset.LoadOnchainState(tenv.Env) require.NoError(t, err) // Deploy to all chains. @@ -157,13 +232,13 @@ func Test_SetCandidate(t *testing.T) { require.NoError(t, err) require.Equal(t, [32]byte{}, candidateDigestExecBefore) - var mcmsConfig *MCMSConfig + var mcmsConfig *changeset.MCMSConfig if tc.mcmsEnabled { - mcmsConfig = &MCMSConfig{ + mcmsConfig = &changeset.MCMSConfig{ MinDelay: 0, } } - tokenConfig := NewTestTokenConfig(state.Chains[tenv.FeedChainSel].USDFeeds) + tokenConfig := changeset.NewTestTokenConfig(state.Chains[tenv.FeedChainSel].USDFeeds) _, err = commonchangeset.ApplyChangesets(t, tenv.Env, map[uint64]*proposalutils.TimelockExecutionContracts{ tenv.HomeChainSel: { Timelock: state.Chains[tenv.HomeChainSel].Timelock, @@ -171,36 +246,30 @@ func Test_SetCandidate(t *testing.T) { }, }, []commonchangeset.ChangesetApplication{ { - Changeset: commonchangeset.WrapChangeSet(SetCandidateChangeset), - Config: SetCandidateChangesetConfig{ - SetCandidateConfigBase: SetCandidateConfigBase{ + Changeset: commonchangeset.WrapChangeSet(changeset.SetCandidateChangeset), + Config: changeset.SetCandidateChangesetConfig{ + SetCandidateConfigBase: changeset.SetCandidateConfigBase{ HomeChainSelector: tenv.HomeChainSel, FeedChainSelector: tenv.FeedChainSel, - DONChainSelector: dest, - PluginType: types.PluginTypeCCIPCommit, - CCIPOCRParams: DefaultOCRParams( - tenv.FeedChainSel, - tokenConfig.GetTokenInfo(logger.TestLogger(t), state.Chains[dest].LinkToken, state.Chains[dest].Weth9), - nil, - ), - MCMS: mcmsConfig, + MCMS: mcmsConfig, }, - }, - }, - { - Changeset: commonchangeset.WrapChangeSet(SetCandidateChangeset), - Config: SetCandidateChangesetConfig{ - SetCandidateConfigBase: SetCandidateConfigBase{ - HomeChainSelector: tenv.HomeChainSel, - FeedChainSelector: tenv.FeedChainSel, - DONChainSelector: dest, - PluginType: types.PluginTypeCCIPExec, - CCIPOCRParams: DefaultOCRParams( - tenv.FeedChainSel, - tokenConfig.GetTokenInfo(logger.TestLogger(t), state.Chains[dest].LinkToken, state.Chains[dest].Weth9), - nil, - ), - MCMS: mcmsConfig, + PluginInfo: []changeset.SetCandidatePluginInfo{ + { + OCRConfigPerRemoteChainSelector: map[uint64]changeset.CCIPOCRParams{ + dest: changeset.DeriveCCIPOCRParams( + changeset.WithDefaultCommitOffChainConfig(tenv.FeedChainSel, tokenConfig.GetTokenInfo(logger.TestLogger(t), state.Chains[dest].LinkToken, state.Chains[dest].Weth9)), + ), + }, + PluginType: types.PluginTypeCCIPCommit, + }, + { + OCRConfigPerRemoteChainSelector: map[uint64]changeset.CCIPOCRParams{ + dest: changeset.DeriveCCIPOCRParams( + changeset.WithDefaultExecuteOffChainConfig(nil), + ), + }, + PluginType: types.PluginTypeCCIPExec, + }, }, }, }, @@ -242,10 +311,10 @@ func Test_RevokeCandidate(t *testing.T) { } { t.Run(tc.name, func(t *testing.T) { ctx := testcontext.Get(t) - tenv := NewMemoryEnvironment(t, - WithChains(2), - WithNodes(4)) - state, err := LoadOnchainState(tenv.Env) + tenv, _ := testhelpers.NewMemoryEnvironment(t, + testhelpers.WithNumOfChains(2), + testhelpers.WithNumOfNodes(4)) + state, err := changeset.LoadOnchainState(tenv.Env) require.NoError(t, err) // Deploy to all chains. @@ -276,13 +345,13 @@ func Test_RevokeCandidate(t *testing.T) { require.NoError(t, err) require.Equal(t, [32]byte{}, candidateDigestExecBefore) - var mcmsConfig *MCMSConfig + var mcmsConfig *changeset.MCMSConfig if tc.mcmsEnabled { - mcmsConfig = &MCMSConfig{ + mcmsConfig = &changeset.MCMSConfig{ MinDelay: 0, } } - tokenConfig := NewTestTokenConfig(state.Chains[tenv.FeedChainSel].USDFeeds) + tokenConfig := changeset.NewTestTokenConfig(state.Chains[tenv.FeedChainSel].USDFeeds) _, err = commonchangeset.ApplyChangesets(t, tenv.Env, map[uint64]*proposalutils.TimelockExecutionContracts{ tenv.HomeChainSel: { Timelock: state.Chains[tenv.HomeChainSel].Timelock, @@ -290,36 +359,30 @@ func Test_RevokeCandidate(t *testing.T) { }, }, []commonchangeset.ChangesetApplication{ { - Changeset: commonchangeset.WrapChangeSet(SetCandidateChangeset), - Config: SetCandidateChangesetConfig{ - SetCandidateConfigBase: SetCandidateConfigBase{ + Changeset: commonchangeset.WrapChangeSet(changeset.SetCandidateChangeset), + Config: changeset.SetCandidateChangesetConfig{ + SetCandidateConfigBase: changeset.SetCandidateConfigBase{ HomeChainSelector: tenv.HomeChainSel, FeedChainSelector: tenv.FeedChainSel, - DONChainSelector: dest, - PluginType: types.PluginTypeCCIPCommit, - CCIPOCRParams: DefaultOCRParams( - tenv.FeedChainSel, - tokenConfig.GetTokenInfo(logger.TestLogger(t), state.Chains[dest].LinkToken, state.Chains[dest].Weth9), - nil, - ), - MCMS: mcmsConfig, + MCMS: mcmsConfig, }, - }, - }, - { - Changeset: commonchangeset.WrapChangeSet(SetCandidateChangeset), - Config: SetCandidateChangesetConfig{ - SetCandidateConfigBase: SetCandidateConfigBase{ - HomeChainSelector: tenv.HomeChainSel, - FeedChainSelector: tenv.FeedChainSel, - DONChainSelector: dest, - PluginType: types.PluginTypeCCIPExec, - CCIPOCRParams: DefaultOCRParams( - tenv.FeedChainSel, - tokenConfig.GetTokenInfo(logger.TestLogger(t), state.Chains[dest].LinkToken, state.Chains[dest].Weth9), - nil, - ), - MCMS: mcmsConfig, + PluginInfo: []changeset.SetCandidatePluginInfo{ + { + OCRConfigPerRemoteChainSelector: map[uint64]changeset.CCIPOCRParams{ + dest: changeset.DeriveCCIPOCRParams( + changeset.WithDefaultCommitOffChainConfig(tenv.FeedChainSel, tokenConfig.GetTokenInfo(logger.TestLogger(t), state.Chains[dest].LinkToken, state.Chains[dest].Weth9)), + ), + }, + PluginType: types.PluginTypeCCIPCommit, + }, + { + OCRConfigPerRemoteChainSelector: map[uint64]changeset.CCIPOCRParams{ + dest: changeset.DeriveCCIPOCRParams( + changeset.WithDefaultExecuteOffChainConfig(nil), + ), + }, + PluginType: types.PluginTypeCCIPExec, + }, }, }, }, @@ -350,21 +413,21 @@ func Test_RevokeCandidate(t *testing.T) { }, }, []commonchangeset.ChangesetApplication{ { - Changeset: commonchangeset.WrapChangeSet(RevokeCandidateChangeset), - Config: RevokeCandidateChangesetConfig{ - HomeChainSelector: tenv.HomeChainSel, - DONChainSelector: dest, - PluginType: types.PluginTypeCCIPCommit, - MCMS: mcmsConfig, + Changeset: commonchangeset.WrapChangeSet(changeset.RevokeCandidateChangeset), + Config: changeset.RevokeCandidateChangesetConfig{ + HomeChainSelector: tenv.HomeChainSel, + RemoteChainSelector: dest, + PluginType: types.PluginTypeCCIPCommit, + MCMS: mcmsConfig, }, }, { - Changeset: commonchangeset.WrapChangeSet(RevokeCandidateChangeset), - Config: RevokeCandidateChangesetConfig{ - HomeChainSelector: tenv.HomeChainSel, - DONChainSelector: dest, - PluginType: types.PluginTypeCCIPExec, - MCMS: mcmsConfig, + Changeset: commonchangeset.WrapChangeSet(changeset.RevokeCandidateChangeset), + Config: changeset.RevokeCandidateChangesetConfig{ + HomeChainSelector: tenv.HomeChainSel, + RemoteChainSelector: dest, + PluginType: types.PluginTypeCCIPExec, + MCMS: mcmsConfig, }, }, }) @@ -388,8 +451,8 @@ func Test_RevokeCandidate(t *testing.T) { func transferToTimelock( t *testing.T, - tenv DeployedEnv, - state CCIPOnChainState, + tenv testhelpers.DeployedEnv, + state changeset.CCIPOnChainState, source, dest uint64) { // Transfer ownership to timelock so that we can promote the zero digest later down the line. @@ -409,9 +472,110 @@ func transferToTimelock( }, []commonchangeset.ChangesetApplication{ { Changeset: commonchangeset.WrapChangeSet(commonchangeset.TransferToMCMSWithTimelock), - Config: genTestTransferOwnershipConfig(tenv, []uint64{source, dest}, state), + Config: testhelpers.GenTestTransferOwnershipConfig(tenv, []uint64{source, dest}, state), }, }) require.NoError(t, err) - assertTimelockOwnership(t, tenv, []uint64{source, dest}, state) + testhelpers.AssertTimelockOwnership(t, tenv, []uint64{source, dest}, state) +} + +func Test_UpdateChainConfigs(t *testing.T) { + for _, tc := range []struct { + name string + mcmsEnabled bool + }{ + { + name: "MCMS enabled", + mcmsEnabled: true, + }, + { + name: "MCMS disabled", + mcmsEnabled: false, + }, + } { + t.Run(tc.name, func(t *testing.T) { + tenv, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithNumOfChains(3)) + state, err := changeset.LoadOnchainState(tenv.Env) + require.NoError(t, err) + + allChains := maps.Keys(tenv.Env.Chains) + source := allChains[0] + dest := allChains[1] + otherChain := allChains[2] + + if tc.mcmsEnabled { + // Transfer ownership to timelock so that we can promote the zero digest later down the line. + transferToTimelock(t, tenv, state, source, dest) + } + + ccipHome := state.Chains[tenv.HomeChainSel].CCIPHome + otherChainConfig, err := ccipHome.GetChainConfig(nil, otherChain) + require.NoError(t, err) + assert.NotZero(t, otherChainConfig.FChain) + + var mcmsConfig *changeset.MCMSConfig + if tc.mcmsEnabled { + mcmsConfig = &changeset.MCMSConfig{ + MinDelay: 0, + } + } + _, err = commonchangeset.ApplyChangesets(t, tenv.Env, map[uint64]*proposalutils.TimelockExecutionContracts{ + tenv.HomeChainSel: { + Timelock: state.Chains[tenv.HomeChainSel].Timelock, + CallProxy: state.Chains[tenv.HomeChainSel].CallProxy, + }, + }, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(changeset.UpdateChainConfigChangeset), + Config: changeset.UpdateChainConfigConfig{ + HomeChainSelector: tenv.HomeChainSel, + RemoteChainRemoves: []uint64{otherChain}, + RemoteChainAdds: make(map[uint64]changeset.ChainConfig), + MCMS: mcmsConfig, + }, + }, + }) + require.NoError(t, err) + + // other chain should be gone + chainConfigAfter, err := ccipHome.GetChainConfig(nil, otherChain) + require.NoError(t, err) + assert.Zero(t, chainConfigAfter.FChain) + + // Lets add it back now. + _, err = commonchangeset.ApplyChangesets(t, tenv.Env, map[uint64]*proposalutils.TimelockExecutionContracts{ + tenv.HomeChainSel: { + Timelock: state.Chains[tenv.HomeChainSel].Timelock, + CallProxy: state.Chains[tenv.HomeChainSel].CallProxy, + }, + }, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(changeset.UpdateChainConfigChangeset), + Config: changeset.UpdateChainConfigConfig{ + HomeChainSelector: tenv.HomeChainSel, + RemoteChainRemoves: []uint64{}, + RemoteChainAdds: map[uint64]changeset.ChainConfig{ + otherChain: { + EncodableChainConfig: chainconfig.ChainConfig{ + GasPriceDeviationPPB: cciptypes.BigInt{Int: big.NewInt(internal.GasPriceDeviationPPB)}, + DAGasPriceDeviationPPB: cciptypes.BigInt{Int: big.NewInt(internal.DAGasPriceDeviationPPB)}, + OptimisticConfirmations: internal.OptimisticConfirmations, + }, + FChain: otherChainConfig.FChain, + Readers: otherChainConfig.Readers, + }, + }, + MCMS: mcmsConfig, + }, + }, + }) + require.NoError(t, err) + + chainConfigAfter2, err := ccipHome.GetChainConfig(nil, otherChain) + require.NoError(t, err) + assert.Equal(t, chainConfigAfter2.FChain, otherChainConfig.FChain) + assert.Equal(t, chainConfigAfter2.Readers, otherChainConfig.Readers) + assert.Equal(t, chainConfigAfter2.Config, otherChainConfig.Config) + }) + } } diff --git a/deployment/ccip/changeset/cs_chain_contracts.go b/deployment/ccip/changeset/cs_chain_contracts.go new file mode 100644 index 00000000000..e52c2f2a603 --- /dev/null +++ b/deployment/ccip/changeset/cs_chain_contracts.go @@ -0,0 +1,1139 @@ +package changeset + +import ( + "bytes" + "context" + "encoding/hex" + "errors" + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" + commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" + cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/nonce_manager" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" +) + +var ( + _ deployment.ChangeSet[UpdateOnRampDestsConfig] = UpdateOnRampsDestsChangeset + _ deployment.ChangeSet[UpdateOffRampSourcesConfig] = UpdateOffRampSourcesChangeset + _ deployment.ChangeSet[UpdateRouterRampsConfig] = UpdateRouterRampsChangeset + _ deployment.ChangeSet[UpdateFeeQuoterDestsConfig] = UpdateFeeQuoterDestsChangeset + _ deployment.ChangeSet[SetOCR3OffRampConfig] = SetOCR3OffRampChangeset + _ deployment.ChangeSet[UpdateFeeQuoterPricesConfig] = UpdateFeeQuoterPricesChangeset + _ deployment.ChangeSet[UpdateNonceManagerConfig] = UpdateNonceManagersChangeset +) + +type UpdateNonceManagerConfig struct { + UpdatesByChain map[uint64]NonceManagerUpdate // source -> dest -> update + MCMS *MCMSConfig +} + +type NonceManagerUpdate struct { + AddedAuthCallers []common.Address + RemovedAuthCallers []common.Address + PreviousRampsArgs []PreviousRampCfg +} + +type PreviousRampCfg struct { + RemoteChainSelector uint64 + OverrideExisting bool + EnableOnRamp bool + EnableOffRamp bool +} + +func (cfg UpdateNonceManagerConfig) Validate(e deployment.Environment) error { + state, err := LoadOnchainState(e) + if err != nil { + return err + } + for sourceSel, update := range cfg.UpdatesByChain { + sourceChainState, ok := state.Chains[sourceSel] + if !ok { + return fmt.Errorf("chain %d not found in onchain state", sourceSel) + } + if sourceChainState.NonceManager == nil { + return fmt.Errorf("missing nonce manager for chain %d", sourceSel) + } + sourceChain, ok := e.Chains[sourceSel] + if !ok { + return fmt.Errorf("missing chain %d in environment", sourceSel) + } + if err := commoncs.ValidateOwnership(e.GetContext(), cfg.MCMS != nil, sourceChain.DeployerKey.From, sourceChainState.Timelock.Address(), sourceChainState.OnRamp); err != nil { + return fmt.Errorf("chain %s: %w", sourceChain.String(), err) + } + for _, prevRamp := range update.PreviousRampsArgs { + if prevRamp.RemoteChainSelector == sourceSel { + return errors.New("source and dest chain cannot be the same") + } + if _, ok := state.Chains[prevRamp.RemoteChainSelector]; !ok { + return fmt.Errorf("dest chain %d not found in onchain state for chain %d", prevRamp.RemoteChainSelector, sourceSel) + } + if !prevRamp.EnableOnRamp && !prevRamp.EnableOffRamp { + return errors.New("must specify either onramp or offramp") + } + if prevRamp.EnableOnRamp { + if prevOnRamp := state.Chains[sourceSel].EVM2EVMOnRamp; prevOnRamp == nil { + return fmt.Errorf("no previous onramp for source chain %d", sourceSel) + } else if prevOnRamp[prevRamp.RemoteChainSelector] == nil { + return fmt.Errorf("no previous onramp for source chain %d and dest chain %d", sourceSel, prevRamp.RemoteChainSelector) + } + } + if prevRamp.EnableOffRamp { + if prevOffRamp := state.Chains[sourceSel].EVM2EVMOffRamp; prevOffRamp == nil { + return fmt.Errorf("missing previous offramps for chain %d", sourceSel) + } else if prevOffRamp[prevRamp.RemoteChainSelector] == nil { + return fmt.Errorf("no previous offramp for source chain %d and dest chain %d", prevRamp.RemoteChainSelector, sourceSel) + } + } + } + } + return nil +} + +func UpdateNonceManagersChangeset(e deployment.Environment, cfg UpdateNonceManagerConfig) (deployment.ChangesetOutput, error) { + if err := cfg.Validate(e); err != nil { + return deployment.ChangesetOutput{}, err + } + s, err := LoadOnchainState(e) + if err != nil { + return deployment.ChangesetOutput{}, err + } + var batches []timelock.BatchChainOperation + timelocks := make(map[uint64]common.Address) + proposers := make(map[uint64]*gethwrappers.ManyChainMultiSig) + for chainSel, updates := range cfg.UpdatesByChain { + txOpts := e.Chains[chainSel].DeployerKey + if cfg.MCMS != nil { + txOpts = deployment.SimTransactOpts() + } + nm := s.Chains[chainSel].NonceManager + var authTx, prevRampsTx *types.Transaction + if len(updates.AddedAuthCallers) > 0 || len(updates.RemovedAuthCallers) > 0 { + authTx, err = nm.ApplyAuthorizedCallerUpdates(txOpts, nonce_manager.AuthorizedCallersAuthorizedCallerArgs{ + AddedCallers: updates.AddedAuthCallers, + RemovedCallers: updates.RemovedAuthCallers, + }) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("error updating authorized callers for chain %s: %w", e.Chains[chainSel].String(), err) + } + } + if len(updates.PreviousRampsArgs) > 0 { + previousRampsArgs := make([]nonce_manager.NonceManagerPreviousRampsArgs, 0) + for _, prevRamp := range updates.PreviousRampsArgs { + var onRamp, offRamp common.Address + if prevRamp.EnableOnRamp { + onRamp = s.Chains[chainSel].EVM2EVMOnRamp[prevRamp.RemoteChainSelector].Address() + } + if prevRamp.EnableOffRamp { + offRamp = s.Chains[chainSel].EVM2EVMOffRamp[prevRamp.RemoteChainSelector].Address() + } + previousRampsArgs = append(previousRampsArgs, nonce_manager.NonceManagerPreviousRampsArgs{ + RemoteChainSelector: prevRamp.RemoteChainSelector, + OverrideExistingRamps: prevRamp.OverrideExisting, + PrevRamps: nonce_manager.NonceManagerPreviousRamps{ + PrevOnRamp: onRamp, + PrevOffRamp: offRamp, + }, + }) + } + prevRampsTx, err = nm.ApplyPreviousRampsUpdates(txOpts, previousRampsArgs) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("error updating previous ramps for chain %s: %w", e.Chains[chainSel].String(), err) + } + } + if cfg.MCMS == nil { + if authTx != nil { + if _, err := deployment.ConfirmIfNoError(e.Chains[chainSel], authTx, err); err != nil { + return deployment.ChangesetOutput{}, err + } + } + if prevRampsTx != nil { + if _, err := deployment.ConfirmIfNoError(e.Chains[chainSel], prevRampsTx, err); err != nil { + return deployment.ChangesetOutput{}, err + } + } + } else { + ops := make([]mcms.Operation, 0) + if authTx != nil { + ops = append(ops, mcms.Operation{ + To: nm.Address(), + Data: authTx.Data(), + Value: big.NewInt(0), + }) + } + if prevRampsTx != nil { + ops = append(ops, mcms.Operation{ + To: nm.Address(), + Data: prevRampsTx.Data(), + Value: big.NewInt(0), + }) + } + if len(ops) == 0 { + return deployment.ChangesetOutput{}, errors.New("no operations to batch") + } + batches = append(batches, timelock.BatchChainOperation{ + ChainIdentifier: mcms.ChainIdentifier(chainSel), + Batch: ops, + }) + timelocks[chainSel] = s.Chains[chainSel].Timelock.Address() + proposers[chainSel] = s.Chains[chainSel].ProposerMcm + } + } + if cfg.MCMS == nil { + return deployment.ChangesetOutput{}, nil + } + + p, err := proposalutils.BuildProposalFromBatches( + timelocks, + proposers, + batches, + "Update nonce manager for previous ramps and authorized callers", + cfg.MCMS.MinDelay, + ) + if err != nil { + return deployment.ChangesetOutput{}, err + } + return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{ + *p, + }}, nil +} + +type UpdateOnRampDestsConfig struct { + // UpdatesByChain is a mapping of source -> dest -> update. + UpdatesByChain map[uint64]map[uint64]OnRampDestinationUpdate + // Disallow mixing MCMS/non-MCMS per chain for simplicity. + // (can still be achieved by calling this function multiple times) + MCMS *MCMSConfig +} + +type OnRampDestinationUpdate struct { + IsEnabled bool // If false, disables the destination by setting router to 0x0. + TestRouter bool // Flag for safety only allow specifying either router or testRouter. + AllowListEnabled bool +} + +func (cfg UpdateOnRampDestsConfig) Validate(e deployment.Environment) error { + state, err := LoadOnchainState(e) + if err != nil { + return err + } + supportedChains := state.SupportedChains() + for chainSel, updates := range cfg.UpdatesByChain { + chainState, ok := state.Chains[chainSel] + if !ok { + return fmt.Errorf("chain %d not found in onchain state", chainSel) + } + if chainState.TestRouter == nil { + return fmt.Errorf("missing test router for chain %d", chainSel) + } + if chainState.Router == nil { + return fmt.Errorf("missing router for chain %d", chainSel) + } + if chainState.OnRamp == nil { + return fmt.Errorf("missing onramp onramp for chain %d", chainSel) + } + if err := commoncs.ValidateOwnership(e.GetContext(), cfg.MCMS != nil, e.Chains[chainSel].DeployerKey.From, chainState.Timelock.Address(), chainState.OnRamp); err != nil { + return err + } + + for destination := range updates { + // Destination cannot be an unknown destination. + if _, ok := supportedChains[destination]; !ok { + return fmt.Errorf("destination chain %d is not a supported %s", destination, chainState.OnRamp.Address()) + } + sc, err := chainState.OnRamp.GetStaticConfig(&bind.CallOpts{Context: e.GetContext()}) + if err != nil { + return fmt.Errorf("failed to get onramp static config %s: %w", chainState.OnRamp.Address(), err) + } + if destination == sc.ChainSelector { + return errors.New("cannot update onramp destination to the same chain") + } + } + } + return nil +} + +// UpdateOnRampsDestsChangeset updates the onramp destinations for each onramp +// in the chains specified. Multichain support is important - consider when we add a new chain +// and need to update the onramp destinations for all chains to support the new chain. +func UpdateOnRampsDestsChangeset(e deployment.Environment, cfg UpdateOnRampDestsConfig) (deployment.ChangesetOutput, error) { + if err := cfg.Validate(e); err != nil { + return deployment.ChangesetOutput{}, err + } + s, err := LoadOnchainState(e) + if err != nil { + return deployment.ChangesetOutput{}, err + } + var batches []timelock.BatchChainOperation + timelocks := make(map[uint64]common.Address) + proposers := make(map[uint64]*gethwrappers.ManyChainMultiSig) + for chainSel, updates := range cfg.UpdatesByChain { + txOpts := e.Chains[chainSel].DeployerKey + txOpts.Context = e.GetContext() + if cfg.MCMS != nil { + txOpts = deployment.SimTransactOpts() + } + onRamp := s.Chains[chainSel].OnRamp + var args []onramp.OnRampDestChainConfigArgs + for destination, update := range updates { + router := common.HexToAddress("0x0") + // If not enabled, set router to 0x0. + if update.IsEnabled { + if update.TestRouter { + router = s.Chains[chainSel].TestRouter.Address() + } else { + router = s.Chains[chainSel].Router.Address() + } + } + args = append(args, onramp.OnRampDestChainConfigArgs{ + DestChainSelector: destination, + Router: router, + AllowlistEnabled: update.AllowListEnabled, + }) + } + tx, err := onRamp.ApplyDestChainConfigUpdates(txOpts, args) + if err != nil { + return deployment.ChangesetOutput{}, err + } + if cfg.MCMS == nil { + if _, err := deployment.ConfirmIfNoError(e.Chains[chainSel], tx, err); err != nil { + return deployment.ChangesetOutput{}, err + } + } else { + batches = append(batches, timelock.BatchChainOperation{ + ChainIdentifier: mcms.ChainIdentifier(chainSel), + Batch: []mcms.Operation{ + { + To: onRamp.Address(), + Data: tx.Data(), + Value: big.NewInt(0), + }, + }, + }) + timelocks[chainSel] = s.Chains[chainSel].Timelock.Address() + proposers[chainSel] = s.Chains[chainSel].ProposerMcm + } + } + if cfg.MCMS == nil { + return deployment.ChangesetOutput{}, nil + } + + p, err := proposalutils.BuildProposalFromBatches( + timelocks, + proposers, + batches, + "Update onramp destinations", + cfg.MCMS.MinDelay, + ) + if err != nil { + return deployment.ChangesetOutput{}, err + } + return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{ + *p, + }}, nil +} + +type UpdateFeeQuoterPricesConfig struct { + PricesByChain map[uint64]FeeQuoterPriceUpdatePerSource // source -> PriceDetails + MCMS *MCMSConfig +} + +type FeeQuoterPriceUpdatePerSource struct { + TokenPrices map[common.Address]*big.Int // token address -> price + GasPrices map[uint64]*big.Int // dest chain -> gas price +} + +func (cfg UpdateFeeQuoterPricesConfig) Validate(e deployment.Environment) error { + state, err := LoadOnchainState(e) + if err != nil { + return err + } + for chainSel, initialPrice := range cfg.PricesByChain { + if err := deployment.IsValidChainSelector(chainSel); err != nil { + return fmt.Errorf("invalid chain selector: %w", err) + } + chainState, ok := state.Chains[chainSel] + if !ok { + return fmt.Errorf("chain %d not found in onchain state", chainSel) + } + fq := chainState.FeeQuoter + if fq == nil { + return fmt.Errorf("missing fee quoter for chain %d", chainSel) + } + if err := commoncs.ValidateOwnership(e.GetContext(), cfg.MCMS != nil, e.Chains[chainSel].DeployerKey.From, chainState.Timelock.Address(), chainState.FeeQuoter); err != nil { + return err + } + // check that whether price updaters are set + authCallers, err := fq.GetAllAuthorizedCallers(&bind.CallOpts{Context: e.GetContext()}) + if err != nil { + return fmt.Errorf("failed to get authorized callers for chain %d: %w", chainSel, err) + } + if len(authCallers) == 0 { + return fmt.Errorf("no authorized callers for chain %d", chainSel) + } + expectedAuthCaller := e.Chains[chainSel].DeployerKey.From + if cfg.MCMS != nil { + expectedAuthCaller = chainState.Timelock.Address() + } + foundCaller := false + for _, authCaller := range authCallers { + if authCaller.Cmp(expectedAuthCaller) == 0 { + foundCaller = true + } + } + if !foundCaller { + return fmt.Errorf("expected authorized caller %s not found for chain %d", expectedAuthCaller.String(), chainSel) + } + for token, price := range initialPrice.TokenPrices { + if price == nil { + return fmt.Errorf("token price for chain %d is nil", chainSel) + } + if token == (common.Address{}) { + return fmt.Errorf("token address for chain %d is empty", chainSel) + } + contains, err := deployment.AddressBookContains(e.ExistingAddresses, chainSel, token.String()) + if err != nil { + return fmt.Errorf("error checking address book for token %s: %w", token.String(), err) + } + if !contains { + return fmt.Errorf("token %s not found in address book for chain %d", token.String(), chainSel) + } + } + for dest, price := range initialPrice.GasPrices { + if chainSel == dest { + return errors.New("source and dest chain cannot be the same") + } + if err := deployment.IsValidChainSelector(dest); err != nil { + return fmt.Errorf("invalid dest chain selector: %w", err) + } + if price == nil { + return fmt.Errorf("gas price for chain %d is nil", chainSel) + } + if _, ok := state.Chains[dest]; !ok { + return fmt.Errorf("dest chain %d not found in onchain state for chain %d", dest, chainSel) + } + } + } + + return nil +} + +func UpdateFeeQuoterPricesChangeset(e deployment.Environment, cfg UpdateFeeQuoterPricesConfig) (deployment.ChangesetOutput, error) { + if err := cfg.Validate(e); err != nil { + return deployment.ChangesetOutput{}, err + } + s, err := LoadOnchainState(e) + if err != nil { + return deployment.ChangesetOutput{}, err + } + var batches []timelock.BatchChainOperation + timelocks := make(map[uint64]common.Address) + proposers := make(map[uint64]*gethwrappers.ManyChainMultiSig) + for chainSel, initialPrice := range cfg.PricesByChain { + txOpts := e.Chains[chainSel].DeployerKey + if cfg.MCMS != nil { + txOpts = deployment.SimTransactOpts() + } + fq := s.Chains[chainSel].FeeQuoter + var tokenPricesArgs []fee_quoter.InternalTokenPriceUpdate + for token, price := range initialPrice.TokenPrices { + tokenPricesArgs = append(tokenPricesArgs, fee_quoter.InternalTokenPriceUpdate{ + SourceToken: token, + UsdPerToken: price, + }) + } + var gasPricesArgs []fee_quoter.InternalGasPriceUpdate + for dest, price := range initialPrice.GasPrices { + gasPricesArgs = append(gasPricesArgs, fee_quoter.InternalGasPriceUpdate{ + DestChainSelector: dest, + UsdPerUnitGas: price, + }) + } + tx, err := fq.UpdatePrices(txOpts, fee_quoter.InternalPriceUpdates{ + TokenPriceUpdates: tokenPricesArgs, + GasPriceUpdates: gasPricesArgs, + }) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("error updating prices for chain %s: %w", e.Chains[chainSel].String(), err) + } + if cfg.MCMS == nil { + if _, err := deployment.ConfirmIfNoError(e.Chains[chainSel], tx, err); err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("error confirming transaction for chain %s: %w", e.Chains[chainSel].String(), err) + } + } else { + batches = append(batches, timelock.BatchChainOperation{ + ChainIdentifier: mcms.ChainIdentifier(chainSel), + Batch: []mcms.Operation{ + { + To: fq.Address(), + Data: tx.Data(), + Value: big.NewInt(0), + }, + }, + }) + timelocks[chainSel] = s.Chains[chainSel].Timelock.Address() + proposers[chainSel] = s.Chains[chainSel].ProposerMcm + } + } + if cfg.MCMS == nil { + return deployment.ChangesetOutput{}, nil + } + + p, err := proposalutils.BuildProposalFromBatches( + timelocks, + proposers, + batches, + "Update fq prices", + cfg.MCMS.MinDelay, + ) + if err != nil { + return deployment.ChangesetOutput{}, err + } + return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{ + *p, + }}, nil +} + +type UpdateFeeQuoterDestsConfig struct { + // UpdatesByChain is a mapping from source -> dest -> config update. + UpdatesByChain map[uint64]map[uint64]fee_quoter.FeeQuoterDestChainConfig + // Disallow mixing MCMS/non-MCMS per chain for simplicity. + // (can still be achieved by calling this function multiple times) + MCMS *MCMSConfig +} + +func (cfg UpdateFeeQuoterDestsConfig) Validate(e deployment.Environment) error { + state, err := LoadOnchainState(e) + if err != nil { + return err + } + supportedChains := state.SupportedChains() + for chainSel, updates := range cfg.UpdatesByChain { + chainState, ok := state.Chains[chainSel] + if !ok { + return fmt.Errorf("chain %d not found in onchain state", chainSel) + } + if chainState.TestRouter == nil { + return fmt.Errorf("missing test router for chain %d", chainSel) + } + if chainState.Router == nil { + return fmt.Errorf("missing router for chain %d", chainSel) + } + if chainState.OnRamp == nil { + return fmt.Errorf("missing onramp onramp for chain %d", chainSel) + } + if err := commoncs.ValidateOwnership(e.GetContext(), cfg.MCMS != nil, e.Chains[chainSel].DeployerKey.From, chainState.Timelock.Address(), chainState.FeeQuoter); err != nil { + return err + } + + for destination := range updates { + // Destination cannot be an unknown destination. + if _, ok := supportedChains[destination]; !ok { + return fmt.Errorf("destination chain %d is not a supported %s", destination, chainState.OnRamp.Address()) + } + sc, err := chainState.OnRamp.GetStaticConfig(&bind.CallOpts{Context: e.GetContext()}) + if err != nil { + return fmt.Errorf("failed to get onramp static config %s: %w", chainState.OnRamp.Address(), err) + } + if destination == sc.ChainSelector { + return errors.New("source and destination chain cannot be the same") + } + } + } + return nil +} + +func UpdateFeeQuoterDestsChangeset(e deployment.Environment, cfg UpdateFeeQuoterDestsConfig) (deployment.ChangesetOutput, error) { + if err := cfg.Validate(e); err != nil { + return deployment.ChangesetOutput{}, err + } + s, err := LoadOnchainState(e) + if err != nil { + return deployment.ChangesetOutput{}, err + } + var batches []timelock.BatchChainOperation + timelocks := make(map[uint64]common.Address) + proposers := make(map[uint64]*gethwrappers.ManyChainMultiSig) + for chainSel, updates := range cfg.UpdatesByChain { + txOpts := e.Chains[chainSel].DeployerKey + txOpts.Context = e.GetContext() + if cfg.MCMS != nil { + txOpts = deployment.SimTransactOpts() + } + fq := s.Chains[chainSel].FeeQuoter + var args []fee_quoter.FeeQuoterDestChainConfigArgs + for destination, dc := range updates { + args = append(args, fee_quoter.FeeQuoterDestChainConfigArgs{ + DestChainSelector: destination, + DestChainConfig: dc, + }) + } + tx, err := fq.ApplyDestChainConfigUpdates(txOpts, args) + if err != nil { + return deployment.ChangesetOutput{}, err + } + if cfg.MCMS == nil { + if _, err := deployment.ConfirmIfNoError(e.Chains[chainSel], tx, err); err != nil { + return deployment.ChangesetOutput{}, err + } + } else { + batches = append(batches, timelock.BatchChainOperation{ + ChainIdentifier: mcms.ChainIdentifier(chainSel), + Batch: []mcms.Operation{ + { + To: fq.Address(), + Data: tx.Data(), + Value: big.NewInt(0), + }, + }, + }) + timelocks[chainSel] = s.Chains[chainSel].Timelock.Address() + proposers[chainSel] = s.Chains[chainSel].ProposerMcm + } + } + if cfg.MCMS == nil { + return deployment.ChangesetOutput{}, nil + } + + p, err := proposalutils.BuildProposalFromBatches( + timelocks, + proposers, + batches, + "Update fq destinations", + cfg.MCMS.MinDelay, + ) + if err != nil { + return deployment.ChangesetOutput{}, err + } + return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{ + *p, + }}, nil +} + +type UpdateOffRampSourcesConfig struct { + // UpdatesByChain is a mapping from dest chain -> source chain -> source chain + // update on the dest chain offramp. + UpdatesByChain map[uint64]map[uint64]OffRampSourceUpdate + MCMS *MCMSConfig +} + +type OffRampSourceUpdate struct { + IsEnabled bool // If false, disables the source by setting router to 0x0. + TestRouter bool // Flag for safety only allow specifying either router or testRouter. +} + +func (cfg UpdateOffRampSourcesConfig) Validate(e deployment.Environment) error { + state, err := LoadOnchainState(e) + if err != nil { + return err + } + supportedChains := state.SupportedChains() + for chainSel, updates := range cfg.UpdatesByChain { + chainState, ok := state.Chains[chainSel] + if !ok { + return fmt.Errorf("chain %d not found in onchain state", chainSel) + } + if chainState.TestRouter == nil { + return fmt.Errorf("missing test router for chain %d", chainSel) + } + if chainState.Router == nil { + return fmt.Errorf("missing router for chain %d", chainSel) + } + if chainState.OffRamp == nil { + return fmt.Errorf("missing onramp onramp for chain %d", chainSel) + } + if err := commoncs.ValidateOwnership(e.GetContext(), cfg.MCMS != nil, e.Chains[chainSel].DeployerKey.From, chainState.Timelock.Address(), chainState.OffRamp); err != nil { + return err + } + + for source := range updates { + // Source cannot be an unknown + if _, ok := supportedChains[source]; !ok { + return fmt.Errorf("source chain %d is not a supported chain %s", source, chainState.OffRamp.Address()) + } + + if source == chainSel { + return fmt.Errorf("cannot update offramp source to the same chain %d", source) + } + sourceChain := state.Chains[source] + // Source chain must have the onramp deployed. + // Note this also validates the specified source selector. + if sourceChain.OnRamp == nil { + return fmt.Errorf("missing onramp for source %d", source) + } + } + } + return nil +} + +// UpdateOffRampSourcesChangeset updates the offramp sources for each offramp. +func UpdateOffRampSourcesChangeset(e deployment.Environment, cfg UpdateOffRampSourcesConfig) (deployment.ChangesetOutput, error) { + if err := cfg.Validate(e); err != nil { + return deployment.ChangesetOutput{}, err + } + s, err := LoadOnchainState(e) + if err != nil { + return deployment.ChangesetOutput{}, err + } + var batches []timelock.BatchChainOperation + timelocks := make(map[uint64]common.Address) + proposers := make(map[uint64]*gethwrappers.ManyChainMultiSig) + for chainSel, updates := range cfg.UpdatesByChain { + txOpts := e.Chains[chainSel].DeployerKey + txOpts.Context = e.GetContext() + if cfg.MCMS != nil { + txOpts = deployment.SimTransactOpts() + } + offRamp := s.Chains[chainSel].OffRamp + var args []offramp.OffRampSourceChainConfigArgs + for source, update := range updates { + router := common.HexToAddress("0x0") + if update.IsEnabled { + if update.TestRouter { + router = s.Chains[chainSel].TestRouter.Address() + } else { + router = s.Chains[chainSel].Router.Address() + } + } + onRamp := s.Chains[source].OnRamp + args = append(args, offramp.OffRampSourceChainConfigArgs{ + SourceChainSelector: source, + Router: router, + IsEnabled: update.IsEnabled, + OnRamp: common.LeftPadBytes(onRamp.Address().Bytes(), 32), + }) + } + tx, err := offRamp.ApplySourceChainConfigUpdates(txOpts, args) + if err != nil { + return deployment.ChangesetOutput{}, err + } + if cfg.MCMS == nil { + if _, err := deployment.ConfirmIfNoError(e.Chains[chainSel], tx, err); err != nil { + return deployment.ChangesetOutput{}, err + } + } else { + batches = append(batches, timelock.BatchChainOperation{ + ChainIdentifier: mcms.ChainIdentifier(chainSel), + Batch: []mcms.Operation{ + { + To: offRamp.Address(), + Data: tx.Data(), + Value: big.NewInt(0), + }, + }, + }) + timelocks[chainSel] = s.Chains[chainSel].Timelock.Address() + proposers[chainSel] = s.Chains[chainSel].ProposerMcm + } + } + if cfg.MCMS == nil { + return deployment.ChangesetOutput{}, nil + } + + p, err := proposalutils.BuildProposalFromBatches( + timelocks, + proposers, + batches, + "Update offramp sources", + cfg.MCMS.MinDelay, + ) + if err != nil { + return deployment.ChangesetOutput{}, err + } + return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{ + *p, + }}, nil +} + +type UpdateRouterRampsConfig struct { + // TestRouter means the updates will be applied to the test router + // on all chains. Disallow mixing test router/non-test router per chain for simplicity. + TestRouter bool + UpdatesByChain map[uint64]RouterUpdates + MCMS *MCMSConfig +} + +type RouterUpdates struct { + OffRampUpdates map[uint64]bool + OnRampUpdates map[uint64]bool +} + +func (cfg UpdateRouterRampsConfig) Validate(e deployment.Environment) error { + state, err := LoadOnchainState(e) + if err != nil { + return err + } + supportedChains := state.SupportedChains() + for chainSel, update := range cfg.UpdatesByChain { + chainState, ok := state.Chains[chainSel] + if !ok { + return fmt.Errorf("chain %d not found in onchain state", chainSel) + } + if chainState.TestRouter == nil { + return fmt.Errorf("missing test router for chain %d", chainSel) + } + if chainState.Router == nil { + return fmt.Errorf("missing router for chain %d", chainSel) + } + if chainState.OffRamp == nil { + return fmt.Errorf("missing onramp onramp for chain %d", chainSel) + } + if cfg.TestRouter { + if err := commoncs.ValidateOwnership(e.GetContext(), cfg.MCMS != nil, e.Chains[chainSel].DeployerKey.From, chainState.Timelock.Address(), chainState.TestRouter); err != nil { + return err + } + } else { + if err := commoncs.ValidateOwnership(e.GetContext(), cfg.MCMS != nil, e.Chains[chainSel].DeployerKey.From, chainState.Timelock.Address(), chainState.Router); err != nil { + return err + } + } + + for source := range update.OffRampUpdates { + // Source cannot be an unknown + if _, ok := supportedChains[source]; !ok { + return fmt.Errorf("source chain %d is not a supported chain %s", source, chainState.OffRamp.Address()) + } + if source == chainSel { + return fmt.Errorf("cannot update offramp source to the same chain %d", source) + } + sourceChain := state.Chains[source] + // Source chain must have the onramp deployed. + // Note this also validates the specified source selector. + if sourceChain.OnRamp == nil { + return fmt.Errorf("missing onramp for source %d", source) + } + } + for destination := range update.OnRampUpdates { + // Source cannot be an unknown + if _, ok := supportedChains[destination]; !ok { + return fmt.Errorf("dest chain %d is not a supported chain %s", destination, chainState.OffRamp.Address()) + } + if destination == chainSel { + return fmt.Errorf("cannot update onRamp dest to the same chain %d", destination) + } + destChain := state.Chains[destination] + if destChain.OffRamp == nil { + return fmt.Errorf("missing offramp for dest %d", destination) + } + } + } + return nil +} + +// UpdateRouterRampsChangeset updates the on/offramps +// in either the router or test router for a series of chains. Use cases include: +// - Ramp upgrade. After deploying new ramps you can enable them on the test router and +// ensure it works e2e. Then enable the ramps on the real router. +// - New chain support. When adding a new chain, you can enable the new destination +// on all chains to support the new chain through the test router first. Once tested, +// Enable the new destination on the real router. +func UpdateRouterRampsChangeset(e deployment.Environment, cfg UpdateRouterRampsConfig) (deployment.ChangesetOutput, error) { + if err := cfg.Validate(e); err != nil { + return deployment.ChangesetOutput{}, err + } + s, err := LoadOnchainState(e) + if err != nil { + return deployment.ChangesetOutput{}, err + } + var batches []timelock.BatchChainOperation + timelocks := make(map[uint64]common.Address) + proposers := make(map[uint64]*gethwrappers.ManyChainMultiSig) + for chainSel, update := range cfg.UpdatesByChain { + txOpts := e.Chains[chainSel].DeployerKey + txOpts.Context = e.GetContext() + if cfg.MCMS != nil { + txOpts = deployment.SimTransactOpts() + } + routerC := s.Chains[chainSel].Router + if cfg.TestRouter { + routerC = s.Chains[chainSel].TestRouter + } + // Note if we add distinct offramps per source to the state, + // we'll need to add support here for looking them up. + // For now its simple, all sources use the same offramp. + offRamp := s.Chains[chainSel].OffRamp + var removes, adds []router.RouterOffRamp + for source, enabled := range update.OffRampUpdates { + if enabled { + adds = append(adds, router.RouterOffRamp{ + SourceChainSelector: source, + OffRamp: offRamp.Address(), + }) + } else { + removes = append(removes, router.RouterOffRamp{ + SourceChainSelector: source, + OffRamp: offRamp.Address(), + }) + } + } + // Ditto here, only one onramp expected until 1.7. + onRamp := s.Chains[chainSel].OnRamp + var onRampUpdates []router.RouterOnRamp + for dest, enabled := range update.OnRampUpdates { + if enabled { + onRampUpdates = append(onRampUpdates, router.RouterOnRamp{ + DestChainSelector: dest, + OnRamp: onRamp.Address(), + }) + } else { + onRampUpdates = append(onRampUpdates, router.RouterOnRamp{ + DestChainSelector: dest, + OnRamp: common.HexToAddress("0x0"), + }) + } + } + tx, err := routerC.ApplyRampUpdates(txOpts, onRampUpdates, removes, adds) + if err != nil { + return deployment.ChangesetOutput{}, err + } + if cfg.MCMS == nil { + if _, err := deployment.ConfirmIfNoError(e.Chains[chainSel], tx, err); err != nil { + return deployment.ChangesetOutput{}, err + } + } else { + batches = append(batches, timelock.BatchChainOperation{ + ChainIdentifier: mcms.ChainIdentifier(chainSel), + Batch: []mcms.Operation{ + { + To: routerC.Address(), + Data: tx.Data(), + Value: big.NewInt(0), + }, + }, + }) + timelocks[chainSel] = s.Chains[chainSel].Timelock.Address() + proposers[chainSel] = s.Chains[chainSel].ProposerMcm + } + } + if cfg.MCMS == nil { + return deployment.ChangesetOutput{}, nil + } + + p, err := proposalutils.BuildProposalFromBatches( + timelocks, + proposers, + batches, + "Update router offramps", + cfg.MCMS.MinDelay, + ) + if err != nil { + return deployment.ChangesetOutput{}, err + } + return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{ + *p, + }}, nil +} + +type SetOCR3OffRampConfig struct { + HomeChainSel uint64 + RemoteChainSels []uint64 + MCMS *MCMSConfig +} + +func (c SetOCR3OffRampConfig) Validate(e deployment.Environment) error { + state, err := LoadOnchainState(e) + if err != nil { + return err + } + if _, ok := state.Chains[c.HomeChainSel]; !ok { + return fmt.Errorf("home chain %d not found in onchain state", c.HomeChainSel) + } + for _, remote := range c.RemoteChainSels { + chainState, ok := state.Chains[remote] + if !ok { + return fmt.Errorf("remote chain %d not found in onchain state", remote) + } + if err := commoncs.ValidateOwnership(e.GetContext(), c.MCMS != nil, e.Chains[remote].DeployerKey.From, chainState.Timelock.Address(), chainState.OffRamp); err != nil { + return err + } + } + return nil +} + +// SetOCR3OffRampChangeset will set the OCR3 offramp for the given chain. +// to the active configuration on CCIPHome. This +// is used to complete the candidate->active promotion cycle, it's +// run after the candidate is confirmed to be working correctly. +// Multichain is especially helpful for NOP rotations where we have +// to touch all the chain to change signers. +func SetOCR3OffRampChangeset(e deployment.Environment, cfg SetOCR3OffRampConfig) (deployment.ChangesetOutput, error) { + if err := cfg.Validate(e); err != nil { + return deployment.ChangesetOutput{}, err + } + state, err := LoadOnchainState(e) + if err != nil { + return deployment.ChangesetOutput{}, err + } + var batches []timelock.BatchChainOperation + timelocks := make(map[uint64]common.Address) + proposers := make(map[uint64]*gethwrappers.ManyChainMultiSig) + for _, remote := range cfg.RemoteChainSels { + donID, err := internal.DonIDForChain( + state.Chains[cfg.HomeChainSel].CapabilityRegistry, + state.Chains[cfg.HomeChainSel].CCIPHome, + remote) + args, err := internal.BuildSetOCR3ConfigArgs(donID, state.Chains[cfg.HomeChainSel].CCIPHome, remote) + if err != nil { + return deployment.ChangesetOutput{}, err + } + set, err := isOCR3ConfigSetOnOffRamp(e.Logger, e.Chains[remote], state.Chains[remote].OffRamp, args) + if err != nil { + return deployment.ChangesetOutput{}, err + } + if set { + e.Logger.Infof("OCR3 config already set on offramp for chain %d", remote) + continue + } + txOpts := e.Chains[remote].DeployerKey + if cfg.MCMS != nil { + txOpts = deployment.SimTransactOpts() + } + offRamp := state.Chains[remote].OffRamp + tx, err := offRamp.SetOCR3Configs(txOpts, args) + if err != nil { + return deployment.ChangesetOutput{}, err + } + if cfg.MCMS == nil { + if _, err := deployment.ConfirmIfNoError(e.Chains[remote], tx, err); err != nil { + return deployment.ChangesetOutput{}, err + } + } else { + batches = append(batches, timelock.BatchChainOperation{ + ChainIdentifier: mcms.ChainIdentifier(remote), + Batch: []mcms.Operation{ + { + To: offRamp.Address(), + Data: tx.Data(), + Value: big.NewInt(0), + }, + }, + }) + timelocks[remote] = state.Chains[remote].Timelock.Address() + proposers[remote] = state.Chains[remote].ProposerMcm + } + } + if cfg.MCMS == nil { + return deployment.ChangesetOutput{}, nil + } + p, err := proposalutils.BuildProposalFromBatches( + timelocks, + proposers, + batches, + "Update OCR3 config", + cfg.MCMS.MinDelay, + ) + if err != nil { + return deployment.ChangesetOutput{}, err + } + e.Logger.Infof("Proposing OCR3 config update for", cfg.RemoteChainSels) + return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{ + *p, + }}, nil +} + +func isOCR3ConfigSetOnOffRamp( + lggr logger.Logger, + chain deployment.Chain, + offRamp *offramp.OffRamp, + offrampOCR3Configs []offramp.MultiOCR3BaseOCRConfigArgs, +) (bool, error) { + mapOfframpOCR3Configs := make(map[cctypes.PluginType]offramp.MultiOCR3BaseOCRConfigArgs) + for _, config := range offrampOCR3Configs { + mapOfframpOCR3Configs[cctypes.PluginType(config.OcrPluginType)] = config + } + + for _, pluginType := range []cctypes.PluginType{cctypes.PluginTypeCCIPCommit, cctypes.PluginTypeCCIPExec} { + ocrConfig, err := offRamp.LatestConfigDetails(&bind.CallOpts{ + Context: context.Background(), + }, uint8(pluginType)) + if err != nil { + return false, fmt.Errorf("error fetching OCR3 config for plugin %s chain %s: %w", pluginType.String(), chain.String(), err) + } + lggr.Debugw("Fetched OCR3 Configs", + "MultiOCR3BaseOCRConfig.F", ocrConfig.ConfigInfo.F, + "MultiOCR3BaseOCRConfig.N", ocrConfig.ConfigInfo.N, + "MultiOCR3BaseOCRConfig.IsSignatureVerificationEnabled", ocrConfig.ConfigInfo.IsSignatureVerificationEnabled, + "Signers", ocrConfig.Signers, + "Transmitters", ocrConfig.Transmitters, + "configDigest", hex.EncodeToString(ocrConfig.ConfigInfo.ConfigDigest[:]), + "chain", chain.String(), + ) + // TODO: assertions to be done as part of full state + // resprentation validation CCIP-3047 + if mapOfframpOCR3Configs[pluginType].ConfigDigest != ocrConfig.ConfigInfo.ConfigDigest { + lggr.Infow("OCR3 config digest mismatch", "pluginType", pluginType.String()) + return false, nil + } + if mapOfframpOCR3Configs[pluginType].F != ocrConfig.ConfigInfo.F { + lggr.Infow("OCR3 config F mismatch", "pluginType", pluginType.String()) + return false, nil + } + if mapOfframpOCR3Configs[pluginType].IsSignatureVerificationEnabled != ocrConfig.ConfigInfo.IsSignatureVerificationEnabled { + lggr.Infow("OCR3 config signature verification mismatch", "pluginType", pluginType.String()) + return false, nil + } + if pluginType == cctypes.PluginTypeCCIPCommit { + // only commit will set signers, exec doesn't need them. + for i, signer := range mapOfframpOCR3Configs[pluginType].Signers { + if !bytes.Equal(signer.Bytes(), ocrConfig.Signers[i].Bytes()) { + lggr.Infow("OCR3 config signer mismatch", "pluginType", pluginType.String()) + return false, nil + } + } + } + for i, transmitter := range mapOfframpOCR3Configs[pluginType].Transmitters { + if !bytes.Equal(transmitter.Bytes(), ocrConfig.Transmitters[i].Bytes()) { + lggr.Infow("OCR3 config transmitter mismatch", "pluginType", pluginType.String()) + return false, nil + } + } + } + return true, nil +} + +func DefaultFeeQuoterDestChainConfig() fee_quoter.FeeQuoterDestChainConfig { + // https://github.com/smartcontractkit/ccip/blob/c4856b64bd766f1ddbaf5d13b42d3c4b12efde3a/contracts/src/v0.8/ccip/libraries/Internal.sol#L337-L337 + /* + ```Solidity + // bytes4(keccak256("CCIP ChainFamilySelector EVM")) + bytes4 public constant CHAIN_FAMILY_SELECTOR_EVM = 0x2812d52c; + ``` + */ + evmFamilySelector, _ := hex.DecodeString("2812d52c") + return fee_quoter.FeeQuoterDestChainConfig{ + IsEnabled: true, + MaxNumberOfTokensPerMsg: 10, + MaxDataBytes: 256, + MaxPerMsgGasLimit: 3_000_000, + DestGasOverhead: ccipevm.DestGasOverhead, + DefaultTokenFeeUSDCents: 1, + DestGasPerPayloadByteBase: ccipevm.CalldataGasPerByteBase, + DestGasPerPayloadByteHigh: ccipevm.CalldataGasPerByteHigh, + DestGasPerPayloadByteThreshold: ccipevm.CalldataGasPerByteThreshold, + DestDataAvailabilityOverheadGas: 100, + DestGasPerDataAvailabilityByte: 100, + DestDataAvailabilityMultiplierBps: 1, + DefaultTokenDestGasOverhead: 125_000, + DefaultTxGasLimit: 200_000, + GasMultiplierWeiPerEth: 11e17, // Gas multiplier in wei per eth is scaled by 1e18, so 11e17 is 1.1 = 110% + NetworkFeeUSDCents: 1, + ChainFamilySelector: [4]byte(evmFamilySelector), + } +} diff --git a/deployment/ccip/changeset/cs_chain_contracts_test.go b/deployment/ccip/changeset/cs_chain_contracts_test.go new file mode 100644 index 00000000000..7b7f420e531 --- /dev/null +++ b/deployment/ccip/changeset/cs_chain_contracts_test.go @@ -0,0 +1,366 @@ +package changeset_test + +import ( + "testing" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + "golang.org/x/exp/maps" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" + + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" +) + +func TestUpdateOnRampsDests(t *testing.T) { + for _, tc := range []struct { + name string + mcmsEnabled bool + }{ + { + name: "MCMS enabled", + mcmsEnabled: true, + }, + { + name: "MCMS disabled", + mcmsEnabled: false, + }, + } { + t.Run(tc.name, func(t *testing.T) { + ctx := testcontext.Get(t) + // Default env just has 2 chains with all contracts + // deployed but no lanes. + tenv, _ := testhelpers.NewMemoryEnvironment(t) + state, err := changeset.LoadOnchainState(tenv.Env) + require.NoError(t, err) + + allChains := maps.Keys(tenv.Env.Chains) + source := allChains[0] + dest := allChains[1] + + if tc.mcmsEnabled { + // Transfer ownership to timelock so that we can promote the zero digest later down the line. + transferToTimelock(t, tenv, state, source, dest) + } + + var mcmsConfig *changeset.MCMSConfig + if tc.mcmsEnabled { + mcmsConfig = &changeset.MCMSConfig{ + MinDelay: 0, + } + } + _, err = commonchangeset.ApplyChangesets(t, tenv.Env, tenv.TimelockContracts(t), []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(changeset.UpdateOnRampsDestsChangeset), + Config: changeset.UpdateOnRampDestsConfig{ + UpdatesByChain: map[uint64]map[uint64]changeset.OnRampDestinationUpdate{ + source: { + dest: { + IsEnabled: true, + TestRouter: true, + AllowListEnabled: false, + }, + }, + dest: { + source: { + IsEnabled: true, + TestRouter: false, + AllowListEnabled: true, + }, + }, + }, + MCMS: mcmsConfig, + }, + }, + }) + require.NoError(t, err) + + // Assert the onramp configuration is as we expect. + sourceCfg, err := state.Chains[source].OnRamp.GetDestChainConfig(&bind.CallOpts{Context: ctx}, dest) + require.NoError(t, err) + require.Equal(t, state.Chains[source].TestRouter.Address(), sourceCfg.Router) + require.False(t, sourceCfg.AllowlistEnabled) + destCfg, err := state.Chains[dest].OnRamp.GetDestChainConfig(&bind.CallOpts{Context: ctx}, source) + require.NoError(t, err) + require.Equal(t, state.Chains[dest].Router.Address(), destCfg.Router) + require.True(t, destCfg.AllowlistEnabled) + }) + } +} + +func TestUpdateOffRampsSources(t *testing.T) { + for _, tc := range []struct { + name string + mcmsEnabled bool + }{ + { + name: "MCMS enabled", + mcmsEnabled: true, + }, + { + name: "MCMS disabled", + mcmsEnabled: false, + }, + } { + t.Run(tc.name, func(t *testing.T) { + ctx := testcontext.Get(t) + tenv, _ := testhelpers.NewMemoryEnvironment(t) + state, err := changeset.LoadOnchainState(tenv.Env) + require.NoError(t, err) + + allChains := maps.Keys(tenv.Env.Chains) + source := allChains[0] + dest := allChains[1] + + if tc.mcmsEnabled { + // Transfer ownership to timelock so that we can promote the zero digest later down the line. + transferToTimelock(t, tenv, state, source, dest) + } + + var mcmsConfig *changeset.MCMSConfig + if tc.mcmsEnabled { + mcmsConfig = &changeset.MCMSConfig{ + MinDelay: 0, + } + } + _, err = commonchangeset.ApplyChangesets(t, tenv.Env, tenv.TimelockContracts(t), []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(changeset.UpdateOffRampSourcesChangeset), + Config: changeset.UpdateOffRampSourcesConfig{ + UpdatesByChain: map[uint64]map[uint64]changeset.OffRampSourceUpdate{ + source: { + dest: { + IsEnabled: true, + TestRouter: true, + }, + }, + dest: { + source: { + IsEnabled: true, + TestRouter: false, + }, + }, + }, + MCMS: mcmsConfig, + }, + }, + }) + require.NoError(t, err) + + // Assert the offramp configuration is as we expect. + sourceCfg, err := state.Chains[source].OffRamp.GetSourceChainConfig(&bind.CallOpts{Context: ctx}, dest) + require.NoError(t, err) + require.Equal(t, state.Chains[source].TestRouter.Address(), sourceCfg.Router) + destCfg, err := state.Chains[dest].OffRamp.GetSourceChainConfig(&bind.CallOpts{Context: ctx}, source) + require.NoError(t, err) + require.Equal(t, state.Chains[dest].Router.Address(), destCfg.Router) + }) + } +} + +func TestUpdateFQDests(t *testing.T) { + for _, tc := range []struct { + name string + mcmsEnabled bool + }{ + { + name: "MCMS enabled", + mcmsEnabled: true, + }, + { + name: "MCMS disabled", + mcmsEnabled: false, + }, + } { + t.Run(tc.name, func(t *testing.T) { + ctx := testcontext.Get(t) + tenv, _ := testhelpers.NewMemoryEnvironment(t) + state, err := changeset.LoadOnchainState(tenv.Env) + require.NoError(t, err) + + allChains := maps.Keys(tenv.Env.Chains) + source := allChains[0] + dest := allChains[1] + + if tc.mcmsEnabled { + // Transfer ownership to timelock so that we can promote the zero digest later down the line. + transferToTimelock(t, tenv, state, source, dest) + } + + var mcmsConfig *changeset.MCMSConfig + if tc.mcmsEnabled { + mcmsConfig = &changeset.MCMSConfig{ + MinDelay: 0, + } + } + + fqCfg1 := changeset.DefaultFeeQuoterDestChainConfig() + fqCfg2 := changeset.DefaultFeeQuoterDestChainConfig() + fqCfg2.DestGasOverhead = 1000 + _, err = commonchangeset.ApplyChangesets(t, tenv.Env, tenv.TimelockContracts(t), []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(changeset.UpdateFeeQuoterDestsChangeset), + Config: changeset.UpdateFeeQuoterDestsConfig{ + UpdatesByChain: map[uint64]map[uint64]fee_quoter.FeeQuoterDestChainConfig{ + source: { + dest: fqCfg1, + }, + dest: { + source: fqCfg2, + }, + }, + MCMS: mcmsConfig, + }, + }, + }) + require.NoError(t, err) + + // Assert the fq configuration is as we expect. + source2destCfg, err := state.Chains[source].FeeQuoter.GetDestChainConfig(&bind.CallOpts{Context: ctx}, dest) + require.NoError(t, err) + testhelpers.AssertEqualFeeConfig(t, fqCfg1, source2destCfg) + dest2sourceCfg, err := state.Chains[dest].FeeQuoter.GetDestChainConfig(&bind.CallOpts{Context: ctx}, source) + require.NoError(t, err) + testhelpers.AssertEqualFeeConfig(t, fqCfg2, dest2sourceCfg) + }) + } +} + +func TestUpdateRouterRamps(t *testing.T) { + for _, tc := range []struct { + name string + mcmsEnabled bool + }{ + { + name: "MCMS enabled", + mcmsEnabled: true, + }, + { + name: "MCMS disabled", + mcmsEnabled: false, + }, + } { + t.Run(tc.name, func(t *testing.T) { + ctx := testcontext.Get(t) + tenv, _ := testhelpers.NewMemoryEnvironment(t) + state, err := changeset.LoadOnchainState(tenv.Env) + require.NoError(t, err) + + allChains := maps.Keys(tenv.Env.Chains) + source := allChains[0] + dest := allChains[1] + + if tc.mcmsEnabled { + // Transfer ownership to timelock so that we can promote the zero digest later down the line. + transferToTimelock(t, tenv, state, source, dest) + } + + var mcmsConfig *changeset.MCMSConfig + if tc.mcmsEnabled { + mcmsConfig = &changeset.MCMSConfig{ + MinDelay: 0, + } + } + + // Updates test router. + _, err = commonchangeset.ApplyChangesets(t, tenv.Env, tenv.TimelockContracts(t), []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(changeset.UpdateRouterRampsChangeset), + Config: changeset.UpdateRouterRampsConfig{ + TestRouter: true, + UpdatesByChain: map[uint64]changeset.RouterUpdates{ + source: { + OffRampUpdates: map[uint64]bool{ + dest: true, + }, + OnRampUpdates: map[uint64]bool{ + dest: true, + }, + }, + dest: { + OffRampUpdates: map[uint64]bool{ + source: true, + }, + OnRampUpdates: map[uint64]bool{ + source: true, + }, + }, + }, + MCMS: mcmsConfig, + }, + }, + }) + require.NoError(t, err) + + // Assert the router configuration is as we expect. + source2destOnRampTest, err := state.Chains[source].TestRouter.GetOnRamp(&bind.CallOpts{Context: ctx}, dest) + require.NoError(t, err) + require.Equal(t, state.Chains[source].OnRamp.Address(), source2destOnRampTest) + source2destOnRampReal, err := state.Chains[source].Router.GetOnRamp(&bind.CallOpts{Context: ctx}, dest) + require.NoError(t, err) + require.Equal(t, common.HexToAddress("0x0"), source2destOnRampReal) + }) + } +} + +func TestUpdateNonceManagersCS(t *testing.T) { + for _, tc := range []struct { + name string + mcmsEnabled bool + }{ + { + name: "MCMS enabled", + mcmsEnabled: true, + }, + { + name: "MCMS disabled", + mcmsEnabled: false, + }, + } { + t.Run(tc.name, func(t *testing.T) { + tenv, _ := testhelpers.NewMemoryEnvironment(t) + state, err := changeset.LoadOnchainState(tenv.Env) + require.NoError(t, err) + + allChains := maps.Keys(tenv.Env.Chains) + source := allChains[0] + dest := allChains[1] + + if tc.mcmsEnabled { + // Transfer ownership to timelock so that we can promote the zero digest later down the line. + transferToTimelock(t, tenv, state, source, dest) + } + + var mcmsConfig *changeset.MCMSConfig + if tc.mcmsEnabled { + mcmsConfig = &changeset.MCMSConfig{ + MinDelay: 0, + } + } + + _, err = commonchangeset.ApplyChangesets(t, tenv.Env, tenv.TimelockContracts(t), []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(changeset.UpdateNonceManagersChangeset), + Config: changeset.UpdateNonceManagerConfig{ + UpdatesByChain: map[uint64]changeset.NonceManagerUpdate{ + source: { + RemovedAuthCallers: []common.Address{state.Chains[source].OnRamp.Address()}, + }, + }, + MCMS: mcmsConfig, + }, + }, + }) + require.NoError(t, err) + // Assert the nonce manager configuration is as we expect. + callers, err := state.Chains[source].NonceManager.GetAllAuthorizedCallers(nil) + require.NoError(t, err) + require.NotContains(t, callers, state.Chains[source].OnRamp.Address()) + require.Contains(t, callers, state.Chains[source].OffRamp.Address()) + }) + } +} diff --git a/deployment/ccip/changeset/cs_deploy_chain.go b/deployment/ccip/changeset/cs_deploy_chain.go index 065c29755b6..28a4702df0b 100644 --- a/deployment/ccip/changeset/cs_deploy_chain.go +++ b/deployment/ccip/changeset/cs_deploy_chain.go @@ -1,6 +1,7 @@ package changeset import ( + "errors" "fmt" "math/big" @@ -14,7 +15,6 @@ import ( "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/maybe_revert_message_receiver" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/nonce_manager" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" @@ -23,18 +23,18 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" ) -var _ deployment.ChangeSet[DeployChainContractsConfig] = DeployChainContracts +var _ deployment.ChangeSet[DeployChainContractsConfig] = DeployChainContractsChangeset -// DeployChainContracts deploys all new CCIP v1.6 or later contracts for the given chains. +// DeployChainContractsChangeset deploys all new CCIP v1.6 or later contracts for the given chains. // It returns the new addresses for the contracts. -// DeployChainContracts is idempotent. If there is an error, it will return the successfully deployed addresses and the error so that the caller can call the +// DeployChainContractsChangeset is idempotent. If there is an error, it will return the successfully deployed addresses and the error so that the caller can call the // changeset again with the same input to retry the failed deployment. // Caller should update the environment's address book with the returned addresses. // Points to note : // In case of migrating from legacy ccip to 1.6, the previous RMN address should be set while deploying RMNRemote. // if there is no existing RMN address found, RMNRemote will be deployed with 0x0 address for previous RMN address // which will set RMN to 0x0 address immutably in RMNRemote. -func DeployChainContracts(env deployment.Environment, c DeployChainContractsConfig) (deployment.ChangesetOutput, error) { +func DeployChainContractsChangeset(env deployment.Environment, c DeployChainContractsConfig) (deployment.ChangesetOutput, error) { if err := c.Validate(); err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("invalid DeployChainContractsConfig: %w", err) } @@ -82,7 +82,7 @@ func deployChainContractsForChains( capReg := existingState.Chains[homeChainSel].CapabilityRegistry if capReg == nil { e.Logger.Errorw("Failed to get capability registry") - return fmt.Errorf("capability registry not found") + return errors.New("capability registry not found") } cr, err := capReg.GetHashedCapabilityId( &bind.CallOpts{}, internal.CapabilityLabelledName, internal.CapabilityVersion) @@ -106,12 +106,12 @@ func deployChainContractsForChains( return err } if ccipHome.Address() != existingState.Chains[homeChainSel].CCIPHome.Address() { - return fmt.Errorf("ccip home address mismatch") + return errors.New("ccip home address mismatch") } rmnHome := existingState.Chains[homeChainSel].RMNHome if rmnHome == nil { e.Logger.Errorw("Failed to get rmn home", "err", err) - return fmt.Errorf("rmn home not found") + return errors.New("rmn home not found") } deployGrp := errgroup.Group{} for _, chainSel := range chainsToDeploy { @@ -119,8 +119,14 @@ func deployChainContractsForChains( if !ok { return fmt.Errorf("chain %d not found", chainSel) } - if existingState.Chains[chainSel].LinkToken == nil || existingState.Chains[chainSel].Weth9 == nil { - return fmt.Errorf("fee tokens not found for chain %d", chainSel) + + staticLinkExists := existingState.Chains[chainSel].StaticLinkToken != nil + linkExists := existingState.Chains[chainSel].LinkToken != nil + weth9Exists := existingState.Chains[chainSel].Weth9 != nil + feeTokensAreValid := weth9Exists && (linkExists != staticLinkExists) + + if !feeTokensAreValid { + return fmt.Errorf("fee tokens not valid for chain %d, staticLinkExists: %t, linkExists: %t, weth9Exists: %t", chainSel, staticLinkExists, linkExists, weth9Exists) } deployGrp.Go( func() error { @@ -162,10 +168,10 @@ func deployChainContracts( return fmt.Errorf("timelock not found for chain %s, deploy the mcms contracts first", chain.String()) } weth9Contract := chainState.Weth9 - if chainState.LinkToken == nil { - return fmt.Errorf("link token not found for chain %s, deploy the prerequisites first", chain.String()) + linkTokenContractAddr, err := chainState.LinkTokenAddress() + if err != nil { + return fmt.Errorf("failed to get link token address for chain %s: %w", chain.String(), err) } - linkTokenContract := chainState.LinkToken if chainState.TokenAdminRegistry == nil { return fmt.Errorf("token admin registry not found for chain %s, deploy the prerequisites first", chain.String()) } @@ -176,34 +182,19 @@ func deployChainContracts( if chainState.Router == nil { return fmt.Errorf("router not found for chain %s, deploy the prerequisites first", chain.String()) } - rmnProxyContract := chainState.RMNProxy + RMNProxy := chainState.RMNProxy if chainState.RMNProxy == nil { + e.Logger.Errorw("RMNProxy not found", "chain", chain.String()) return fmt.Errorf("rmn proxy not found for chain %s, deploy the prerequisites first", chain.String()) } - if chainState.Receiver == nil { - _, err := deployment.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*maybe_revert_message_receiver.MaybeRevertMessageReceiver] { - receiverAddr, tx, receiver, err2 := maybe_revert_message_receiver.DeployMaybeRevertMessageReceiver( - chain.DeployerKey, - chain.Client, - false, - ) - return deployment.ContractDeploy[*maybe_revert_message_receiver.MaybeRevertMessageReceiver]{ - receiverAddr, receiver, tx, deployment.NewTypeAndVersion(CCIPReceiver, deployment.Version1_0_0), err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy receiver", "err", err) - return err - } - } else { - e.Logger.Infow("receiver already deployed", "addr", chainState.Receiver.Address, "chain", chain.String()) - } var rmnLegacyAddr common.Address if chainState.MockRMN != nil { rmnLegacyAddr = chainState.MockRMN.Address() } - // TODO add legacy RMN here when 1.5 contracts are available + // If RMN is deployed, set rmnLegacyAddr to the RMN address + if chainState.RMN != nil { + rmnLegacyAddr = chainState.RMN.Address() + } if rmnLegacyAddr == (common.Address{}) { e.Logger.Warnf("No legacy RMN contract found for chain %s, will not setRMN in RMNRemote", chain.String()) } @@ -219,7 +210,7 @@ func deployChainContracts( rmnLegacyAddr, ) return deployment.ContractDeploy[*rmn_remote.RMNRemote]{ - rmnRemoteAddr, rmnRemote, tx, deployment.NewTypeAndVersion(RMNRemote, deployment.Version1_6_0_dev), err2, + Address: rmnRemoteAddr, Contract: rmnRemote, Tx: tx, Tv: deployment.NewTypeAndVersion(RMNRemote, deployment.Version1_6_0_dev), Err: err2, } }) if err != nil { @@ -243,7 +234,7 @@ func deployChainContracts( Signers: []rmn_remote.RMNRemoteSigner{ {NodeIndex: 0, OnchainPublicKey: common.Address{1}}, }, - F: 0, // TODO: update when we have signers + FSign: 0, // TODO: update when we have signers }) if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { e.Logger.Errorw("Failed to confirm RMNRemote config", "chain", chain.String(), "err", err) @@ -256,10 +247,10 @@ func deployChainContracts( chain.DeployerKey, chain.Client, weth9Contract.Address(), - rmnProxyContract.Address(), + RMNProxy.Address(), ) return deployment.ContractDeploy[*router.Router]{ - routerAddr, routerC, tx2, deployment.NewTypeAndVersion(TestRouter, deployment.Version1_2_0), err2, + Address: routerAddr, Contract: routerC, Tx: tx2, Tv: deployment.NewTypeAndVersion(TestRouter, deployment.Version1_2_0), Err: err2, } }) if err != nil { @@ -280,7 +271,7 @@ func deployChainContracts( []common.Address{}, // Need to add onRamp after ) return deployment.ContractDeploy[*nonce_manager.NonceManager]{ - nonceManagerAddr, nonceManager, tx2, deployment.NewTypeAndVersion(NonceManager, deployment.Version1_6_0_dev), err2, + Address: nonceManagerAddr, Contract: nonceManager, Tx: tx2, Tv: deployment.NewTypeAndVersion(NonceManager, deployment.Version1_6_0_dev), Err: err2, } }) if err != nil { @@ -300,17 +291,17 @@ func deployChainContracts( chain.Client, fee_quoter.FeeQuoterStaticConfig{ MaxFeeJuelsPerMsg: big.NewInt(0).Mul(big.NewInt(2e2), big.NewInt(1e18)), - LinkToken: linkTokenContract.Address(), + LinkToken: linkTokenContractAddr, TokenPriceStalenessThreshold: uint32(24 * 60 * 60), }, - []common.Address{state.Chains[chain.Selector].Timelock.Address()}, // timelock should be able to update, ramps added after - []common.Address{weth9Contract.Address(), linkTokenContract.Address()}, // fee tokens + []common.Address{state.Chains[chain.Selector].Timelock.Address()}, // timelock should be able to update, ramps added after + []common.Address{weth9Contract.Address(), linkTokenContractAddr}, // fee tokens []fee_quoter.FeeQuoterTokenPriceFeedUpdate{}, []fee_quoter.FeeQuoterTokenTransferFeeConfigArgs{}, // TODO: tokens []fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthArgs{ { PremiumMultiplierWeiPerEth: 9e17, // 0.9 ETH - Token: linkTokenContract.Address(), + Token: linkTokenContractAddr, }, { PremiumMultiplierWeiPerEth: 1e18, @@ -320,7 +311,7 @@ func deployChainContracts( []fee_quoter.FeeQuoterDestChainConfigArgs{}, ) return deployment.ContractDeploy[*fee_quoter.FeeQuoter]{ - prAddr, pr, tx2, deployment.NewTypeAndVersion(FeeQuoter, deployment.Version1_6_0_dev), err2, + Address: prAddr, Contract: pr, Tx: tx2, Tv: deployment.NewTypeAndVersion(FeeQuoter, deployment.Version1_6_0_dev), Err: err2, } }) if err != nil { @@ -340,18 +331,18 @@ func deployChainContracts( chain.Client, onramp.OnRampStaticConfig{ ChainSelector: chain.Selector, - RmnRemote: rmnProxyContract.Address(), + RmnRemote: RMNProxy.Address(), NonceManager: nmContract.Address(), TokenAdminRegistry: tokenAdminReg.Address(), }, onramp.OnRampDynamicConfig{ FeeQuoter: feeQuoterContract.Address(), - FeeAggregator: common.HexToAddress("0x1"), // TODO real fee aggregator + FeeAggregator: chain.DeployerKey.From, // TODO real fee aggregator, using deployer key for now }, []onramp.OnRampDestChainConfigArgs{}, ) return deployment.ContractDeploy[*onramp.OnRamp]{ - onRampAddr, onRamp, tx2, deployment.NewTypeAndVersion(OnRamp, deployment.Version1_6_0_dev), err2, + Address: onRampAddr, Contract: onRamp, Tx: tx2, Tv: deployment.NewTypeAndVersion(OnRamp, deployment.Version1_6_0_dev), Err: err2, } }) if err != nil { @@ -372,7 +363,7 @@ func deployChainContracts( offramp.OffRampStaticConfig{ ChainSelector: chain.Selector, GasForCallExactCheck: 5_000, - RmnRemote: rmnProxyContract.Address(), + RmnRemote: RMNProxy.Address(), NonceManager: nmContract.Address(), TokenAdminRegistry: tokenAdminReg.Address(), }, diff --git a/deployment/ccip/changeset/cs_deploy_chain_test.go b/deployment/ccip/changeset/cs_deploy_chain_test.go index 9e1a581112d..c579b075b70 100644 --- a/deployment/ccip/changeset/cs_deploy_chain_test.go +++ b/deployment/ccip/changeset/cs_deploy_chain_test.go @@ -1,4 +1,4 @@ -package changeset +package changeset_test import ( "encoding/json" @@ -9,6 +9,8 @@ import ( "go.uber.org/zap/zapcore" "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" @@ -33,14 +35,20 @@ func TestDeployChainContractsChangeset(t *testing.T) { for _, chain := range e.AllChainSelectors() { cfg[chain] = proposalutils.SingleGroupTimelockConfig(t) } + prereqCfg := make([]changeset.DeployPrerequisiteConfigPerChain, 0) + for _, chain := range e.AllChainSelectors() { + prereqCfg = append(prereqCfg, changeset.DeployPrerequisiteConfigPerChain{ + ChainSelector: chain, + }) + } e, err = commonchangeset.ApplyChangesets(t, e, nil, []commonchangeset.ChangesetApplication{ { - Changeset: commonchangeset.WrapChangeSet(DeployHomeChain), - Config: DeployHomeChainConfig{ + Changeset: commonchangeset.WrapChangeSet(changeset.DeployHomeChainChangeset), + Config: changeset.DeployHomeChainConfig{ HomeChainSel: homeChainSel, - RMNStaticConfig: NewTestRMNStaticConfig(), - RMNDynamicConfig: NewTestRMNDynamicConfig(), - NodeOperators: NewTestNodeOperator(e.Chains[homeChainSel].DeployerKey.From), + RMNStaticConfig: testhelpers.NewTestRMNStaticConfig(), + RMNDynamicConfig: testhelpers.NewTestRMNDynamicConfig(), + NodeOperators: testhelpers.NewTestNodeOperator(e.Chains[homeChainSel].DeployerKey.From), NodeP2PIDsPerNodeOpAdmin: map[string][][32]byte{ "NodeOperator": p2pIds, }, @@ -55,14 +63,14 @@ func TestDeployChainContractsChangeset(t *testing.T) { Config: cfg, }, { - Changeset: commonchangeset.WrapChangeSet(DeployPrerequisites), - Config: DeployPrerequisiteConfig{ - ChainSelectors: selectors, + Changeset: commonchangeset.WrapChangeSet(changeset.DeployPrerequisitesChangeset), + Config: changeset.DeployPrerequisiteConfig{ + Configs: prereqCfg, }, }, { - Changeset: commonchangeset.WrapChangeSet(DeployChainContracts), - Config: DeployChainContractsConfig{ + Changeset: commonchangeset.WrapChangeSet(changeset.DeployChainContractsChangeset), + Config: changeset.DeployChainContractsConfig{ ChainSelectors: selectors, HomeChainSelector: homeChainSel, }, @@ -71,7 +79,7 @@ func TestDeployChainContractsChangeset(t *testing.T) { require.NoError(t, err) // load onchain state - state, err := LoadOnchainState(e) + state, err := changeset.LoadOnchainState(e) require.NoError(t, err) // verify all contracts populated @@ -95,9 +103,9 @@ func TestDeployChainContractsChangeset(t *testing.T) { func TestDeployCCIPContracts(t *testing.T) { t.Parallel() - e := NewMemoryEnvironment(t) + e, _ := testhelpers.NewMemoryEnvironment(t) // Deploy all the CCIP contracts. - state, err := LoadOnchainState(e.Env) + state, err := changeset.LoadOnchainState(e.Env) require.NoError(t, err) snap, err := state.View(e.Env.AllChainSelectors()) require.NoError(t, err) diff --git a/deployment/ccip/changeset/cs_home_chain.go b/deployment/ccip/changeset/cs_home_chain.go index 44658d41016..cc234a45e49 100644 --- a/deployment/ccip/changeset/cs_home_chain.go +++ b/deployment/ccip/changeset/cs_home_chain.go @@ -16,20 +16,21 @@ import ( "golang.org/x/exp/maps" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" ) -var _ deployment.ChangeSet[DeployHomeChainConfig] = DeployHomeChain +var _ deployment.ChangeSet[DeployHomeChainConfig] = DeployHomeChainChangeset -// DeployHomeChain is a separate changeset because it is a standalone deployment performed once in home chain for the entire CCIP deployment. -func DeployHomeChain(env deployment.Environment, cfg DeployHomeChainConfig) (deployment.ChangesetOutput, error) { +// DeployHomeChainChangeset is a separate changeset because it is a standalone deployment performed once in home chain for the entire CCIP deployment. +func DeployHomeChainChangeset(env deployment.Environment, cfg DeployHomeChainConfig) (deployment.ChangesetOutput, error) { err := cfg.Validate() if err != nil { return deployment.ChangesetOutput{}, errors.Wrapf(deployment.ErrInvalidConfig, "%v", err) @@ -61,23 +62,23 @@ type DeployHomeChainConfig struct { func (c DeployHomeChainConfig) Validate() error { if c.HomeChainSel == 0 { - return fmt.Errorf("home chain selector must be set") + return errors.New("home chain selector must be set") } if c.RMNDynamicConfig.OffchainConfig == nil { - return fmt.Errorf("offchain config for RMNHomeDynamicConfig must be set") + return errors.New("offchain config for RMNHomeDynamicConfig must be set") } if c.RMNStaticConfig.OffchainConfig == nil { - return fmt.Errorf("offchain config for RMNHomeStaticConfig must be set") + return errors.New("offchain config for RMNHomeStaticConfig must be set") } if len(c.NodeOperators) == 0 { - return fmt.Errorf("node operators must be set") + return errors.New("node operators must be set") } for _, nop := range c.NodeOperators { if nop.Admin == (common.Address{}) { - return fmt.Errorf("node operator admin address must be set") + return errors.New("node operator admin address must be set") } if nop.Name == "" { - return fmt.Errorf("node operator name must be set") + return errors.New("node operator name must be set") } if len(c.NodeP2PIDsPerNodeOpAdmin[nop.Name]) == 0 { return fmt.Errorf("node operator %s must have node p2p ids provided", nop.Name) @@ -338,14 +339,14 @@ func (c RemoveDONsConfig) Validate(homeChain CCIPChainState) error { return fmt.Errorf("home chain selector must be set %w", err) } if len(c.DonIDs) == 0 { - return fmt.Errorf("don ids must be set") + return errors.New("don ids must be set") } // Cap reg must exist if homeChain.CapabilityRegistry == nil { - return fmt.Errorf("cap reg does not exist") + return errors.New("cap reg does not exist") } if homeChain.CCIPHome == nil { - return fmt.Errorf("ccip home does not exist") + return errors.New("ccip home does not exist") } if err := internal.DONIdExists(homeChain.CapabilityRegistry, c.DonIDs); err != nil { return err diff --git a/deployment/ccip/changeset/cs_home_chain_test.go b/deployment/ccip/changeset/cs_home_chain_test.go index 8a2d4f87709..0dbdb866d9b 100644 --- a/deployment/ccip/changeset/cs_home_chain_test.go +++ b/deployment/ccip/changeset/cs_home_chain_test.go @@ -1,4 +1,4 @@ -package changeset +package changeset_test import ( "testing" @@ -8,6 +8,8 @@ import ( "go.uber.org/zap/zapcore" "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/common/view/v1_0" @@ -27,19 +29,19 @@ func TestDeployHomeChain(t *testing.T) { nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) require.NoError(t, err) p2pIds := nodes.NonBootstraps().PeerIDs() - homeChainCfg := DeployHomeChainConfig{ + homeChainCfg := changeset.DeployHomeChainConfig{ HomeChainSel: homeChainSel, - RMNStaticConfig: NewTestRMNStaticConfig(), - RMNDynamicConfig: NewTestRMNDynamicConfig(), - NodeOperators: NewTestNodeOperator(e.Chains[homeChainSel].DeployerKey.From), + RMNStaticConfig: testhelpers.NewTestRMNStaticConfig(), + RMNDynamicConfig: testhelpers.NewTestRMNDynamicConfig(), + NodeOperators: testhelpers.NewTestNodeOperator(e.Chains[homeChainSel].DeployerKey.From), NodeP2PIDsPerNodeOpAdmin: map[string][][32]byte{ "NodeOperator": p2pIds, }, } - output, err := DeployHomeChain(e, homeChainCfg) + output, err := changeset.DeployHomeChainChangeset(e, homeChainCfg) require.NoError(t, err) require.NoError(t, e.ExistingAddresses.Merge(output.AddressBook)) - state, err := LoadOnchainState(e) + state, err := changeset.LoadOnchainState(e) require.NoError(t, err) require.NotNil(t, state.Chains[homeChainSel].CapabilityRegistry) require.NotNil(t, state.Chains[homeChainSel].CCIPHome) @@ -52,28 +54,28 @@ func TestDeployHomeChain(t *testing.T) { capRegSnap, ok := snap[chainName].CapabilityRegistry[state.Chains[homeChainSel].CapabilityRegistry.Address().String()] require.True(t, ok) require.NotNil(t, capRegSnap) - require.Equal(t, capRegSnap.Nops, []v1_0.NopView{ + require.Equal(t, []v1_0.NopView{ { Admin: e.Chains[homeChainSel].DeployerKey.From, Name: "NodeOperator", }, - }) + }, capRegSnap.Nops) require.Len(t, capRegSnap.Nodes, len(p2pIds)) } func TestRemoveDonsValidate(t *testing.T) { - e := NewMemoryEnvironment(t) - s, err := LoadOnchainState(e.Env) + e, _ := testhelpers.NewMemoryEnvironment(t) + s, err := changeset.LoadOnchainState(e.Env) require.NoError(t, err) homeChain := s.Chains[e.HomeChainSel] var tt = []struct { name string - config RemoveDONsConfig + config changeset.RemoveDONsConfig expectErr bool }{ { name: "invalid home", - config: RemoveDONsConfig{ + config: changeset.RemoveDONsConfig{ HomeChainSel: 0, DonIDs: []uint32{1}, }, @@ -81,7 +83,7 @@ func TestRemoveDonsValidate(t *testing.T) { }, { name: "invalid dons", - config: RemoveDONsConfig{ + config: changeset.RemoveDONsConfig{ HomeChainSel: e.HomeChainSel, DonIDs: []uint32{1377}, }, @@ -89,7 +91,7 @@ func TestRemoveDonsValidate(t *testing.T) { }, { name: "no dons", - config: RemoveDONsConfig{ + config: changeset.RemoveDONsConfig{ HomeChainSel: e.HomeChainSel, DonIDs: []uint32{}, }, @@ -97,7 +99,7 @@ func TestRemoveDonsValidate(t *testing.T) { }, { name: "success", - config: RemoveDONsConfig{ + config: changeset.RemoveDONsConfig{ HomeChainSel: e.HomeChainSel, DonIDs: []uint32{1}, }, @@ -117,8 +119,8 @@ func TestRemoveDonsValidate(t *testing.T) { } func TestRemoveDons(t *testing.T) { - e := NewMemoryEnvironment(t) - s, err := LoadOnchainState(e.Env) + e, _ := testhelpers.NewMemoryEnvironment(t) + s, err := changeset.LoadOnchainState(e.Env) require.NoError(t, err) homeChain := s.Chains[e.HomeChainSel] @@ -127,8 +129,8 @@ func TestRemoveDons(t *testing.T) { require.NoError(t, err) e.Env, err = commoncs.ApplyChangesets(t, e.Env, nil, []commoncs.ChangesetApplication{ { - Changeset: commoncs.WrapChangeSet(RemoveDONs), - Config: RemoveDONsConfig{ + Changeset: commoncs.WrapChangeSet(changeset.RemoveDONs), + Config: changeset.RemoveDONsConfig{ HomeChainSel: e.HomeChainSel, DonIDs: []uint32{donsBefore[0].Id}, }, @@ -158,11 +160,11 @@ func TestRemoveDons(t *testing.T) { }, }, { - Changeset: commoncs.WrapChangeSet(RemoveDONs), - Config: RemoveDONsConfig{ + Changeset: commoncs.WrapChangeSet(changeset.RemoveDONs), + Config: changeset.RemoveDONsConfig{ HomeChainSel: e.HomeChainSel, DonIDs: []uint32{donsBefore[0].Id}, - MCMS: &MCMSConfig{MinDelay: 0}, + MCMS: &changeset.MCMSConfig{MinDelay: 0}, }, }, }) diff --git a/deployment/ccip/changeset/cs_initial_add_chain.go b/deployment/ccip/changeset/cs_initial_add_chain.go deleted file mode 100644 index 4f8b2ac2722..00000000000 --- a/deployment/ccip/changeset/cs_initial_add_chain.go +++ /dev/null @@ -1,532 +0,0 @@ -package changeset - -import ( - "bytes" - "context" - "encoding/hex" - "fmt" - "os" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - - "github.com/smartcontractkit/chainlink-ccip/chainconfig" - "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink-ccip/pluginconfig" - "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/merklemulti" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" - "github.com/smartcontractkit/chainlink/deployment/common/types" - cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" -) - -var _ deployment.ChangeSet[NewChainsConfig] = ConfigureNewChains - -// ConfigureNewChains enables new chains as destination(s) for CCIP -// It performs the following steps per chain: -// - addChainConfig + AddDON (candidate->primary promotion i.e. init) on the home chain -// - SetOCR3Config on the remote chain -// ConfigureNewChains assumes that the home chain is already enabled and all CCIP contracts are already deployed. -func ConfigureNewChains(env deployment.Environment, c NewChainsConfig) (deployment.ChangesetOutput, error) { - if err := c.Validate(); err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("invalid NewChainsConfig: %w", err) - } - err := configureChain(env, c) - if err != nil { - env.Logger.Errorw("Failed to configure chain", "err", err) - return deployment.ChangesetOutput{}, deployment.MaybeDataErr(err) - } - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{}, - AddressBook: nil, - JobSpecs: nil, - }, nil -} - -type CCIPOCRParams struct { - OCRParameters types.OCRParameters - // Note contains pointers to Arb feeds for prices - CommitOffChainConfig pluginconfig.CommitOffchainConfig - // Note ontains USDC config - ExecuteOffChainConfig pluginconfig.ExecuteOffchainConfig -} - -func (c CCIPOCRParams) Validate() error { - if err := c.OCRParameters.Validate(); err != nil { - return fmt.Errorf("invalid OCR parameters: %w", err) - } - if err := c.CommitOffChainConfig.Validate(); err != nil { - return fmt.Errorf("invalid commit off-chain config: %w", err) - } - if err := c.ExecuteOffChainConfig.Validate(); err != nil { - return fmt.Errorf("invalid execute off-chain config: %w", err) - } - return nil -} - -type NewChainsConfig struct { - // Common to all chains - HomeChainSel uint64 - FeedChainSel uint64 - // Per chain config - ChainConfigByChain map[uint64]CCIPOCRParams -} - -func (c NewChainsConfig) Chains() []uint64 { - chains := make([]uint64, 0, len(c.ChainConfigByChain)) - for chain := range c.ChainConfigByChain { - chains = append(chains, chain) - } - return chains -} - -func (c NewChainsConfig) Validate() error { - if err := deployment.IsValidChainSelector(c.HomeChainSel); err != nil { - return fmt.Errorf("invalid home chain selector: %d - %w", c.HomeChainSel, err) - } - if err := deployment.IsValidChainSelector(c.FeedChainSel); err != nil { - return fmt.Errorf("invalid feed chain selector: %d - %w", c.FeedChainSel, err) - } - // Validate chain config - for chain, cfg := range c.ChainConfigByChain { - if err := cfg.Validate(); err != nil { - return fmt.Errorf("invalid OCR params for chain %d: %w", chain, err) - } - if cfg.CommitOffChainConfig.PriceFeedChainSelector != ccipocr3.ChainSelector(c.FeedChainSel) { - return fmt.Errorf("chain %d has invalid feed chain selector", chain) - } - } - return nil -} - -// DefaultOCRParams returns the default OCR parameters for a chain, -// except for a few values which must be parameterized (passed as arguments). -func DefaultOCRParams( - feedChainSel uint64, - tokenInfo map[ccipocr3.UnknownEncodedAddress]pluginconfig.TokenInfo, - tokenDataObservers []pluginconfig.TokenDataObserverConfig, -) CCIPOCRParams { - return CCIPOCRParams{ - OCRParameters: types.OCRParameters{ - DeltaProgress: internal.DeltaProgress, - DeltaResend: internal.DeltaResend, - DeltaInitial: internal.DeltaInitial, - DeltaRound: internal.DeltaRound, - DeltaGrace: internal.DeltaGrace, - DeltaCertifiedCommitRequest: internal.DeltaCertifiedCommitRequest, - DeltaStage: internal.DeltaStage, - Rmax: internal.Rmax, - MaxDurationQuery: internal.MaxDurationQuery, - MaxDurationObservation: internal.MaxDurationObservation, - MaxDurationShouldAcceptAttestedReport: internal.MaxDurationShouldAcceptAttestedReport, - MaxDurationShouldTransmitAcceptedReport: internal.MaxDurationShouldTransmitAcceptedReport, - }, - ExecuteOffChainConfig: pluginconfig.ExecuteOffchainConfig{ - BatchGasLimit: internal.BatchGasLimit, - RelativeBoostPerWaitHour: internal.RelativeBoostPerWaitHour, - InflightCacheExpiry: *config.MustNewDuration(internal.InflightCacheExpiry), - RootSnoozeTime: *config.MustNewDuration(internal.RootSnoozeTime), - MessageVisibilityInterval: *config.MustNewDuration(internal.FirstBlockAge), - BatchingStrategyID: internal.BatchingStrategyID, - TokenDataObservers: tokenDataObservers, - }, - CommitOffChainConfig: pluginconfig.CommitOffchainConfig{ - RemoteGasPriceBatchWriteFrequency: *config.MustNewDuration(internal.RemoteGasPriceBatchWriteFrequency), - TokenPriceBatchWriteFrequency: *config.MustNewDuration(internal.TokenPriceBatchWriteFrequency), - TokenInfo: tokenInfo, - PriceFeedChainSelector: ccipocr3.ChainSelector(feedChainSel), - NewMsgScanBatchSize: merklemulti.MaxNumberTreeLeaves, - MaxReportTransmissionCheckAttempts: 5, - RMNEnabled: os.Getenv("ENABLE_RMN") == "true", // only enabled in manual test - RMNSignaturesTimeout: 30 * time.Minute, - MaxMerkleTreeSize: merklemulti.MaxNumberTreeLeaves, - SignObservationPrefix: "chainlink ccip 1.6 rmn observation", - }, - } -} - -// configureChain assumes the all the Home chain contracts and CCIP contracts are deployed -// It does - -// 1. addChainConfig for each chain in CCIPHome -// 2. Registers the nodes with the capability registry -// 3. SetOCR3Config on the remote chain -func configureChain( - e deployment.Environment, - c NewChainsConfig, -) error { - if e.OCRSecrets.IsEmpty() { - return fmt.Errorf("OCR secrets are empty") - } - nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) - if err != nil || len(nodes) == 0 { - e.Logger.Errorw("Failed to get node info", "err", err) - return err - } - existingState, err := LoadOnchainState(e) - if err != nil { - e.Logger.Errorw("Failed to load existing onchain state", "err") - return err - } - homeChain := e.Chains[c.HomeChainSel] - capReg := existingState.Chains[c.HomeChainSel].CapabilityRegistry - if capReg == nil { - e.Logger.Errorw("Failed to get capability registry", "chain", homeChain.String()) - return fmt.Errorf("capability registry not found") - } - ccipHome := existingState.Chains[c.HomeChainSel].CCIPHome - if ccipHome == nil { - e.Logger.Errorw("Failed to get ccip home", "chain", homeChain.String(), "err", err) - return fmt.Errorf("ccip home not found") - } - rmnHome := existingState.Chains[c.HomeChainSel].RMNHome - if rmnHome == nil { - e.Logger.Errorw("Failed to get rmn home", "chain", homeChain.String(), "err", err) - return fmt.Errorf("rmn home not found") - } - - for chainSel, chainConfig := range c.ChainConfigByChain { - chain, _ := e.Chains[chainSel] - chainState, ok := existingState.Chains[chain.Selector] - if !ok { - return fmt.Errorf("chain state not found for chain %d", chain.Selector) - } - if chainState.OffRamp == nil { - return fmt.Errorf("off ramp not found for chain %d", chain.Selector) - } - _, err = addChainConfig( - e.Logger, - e.Chains[c.HomeChainSel], - ccipHome, - chain.Selector, - nodes.NonBootstraps().PeerIDs()) - if err != nil { - return err - } - // For each chain, we create a DON on the home chain (2 OCR instances) - if err := addDON( - e.Logger, - e.OCRSecrets, - capReg, - ccipHome, - rmnHome.Address(), - chainState.OffRamp, - chain, - e.Chains[c.HomeChainSel], - nodes.NonBootstraps(), - chainConfig, - ); err != nil { - e.Logger.Errorw("Failed to add DON", "err", err) - return err - } - } - - return nil -} - -func setupConfigInfo(chainSelector uint64, readers [][32]byte, fChain uint8, cfg []byte) ccip_home.CCIPHomeChainConfigArgs { - return ccip_home.CCIPHomeChainConfigArgs{ - ChainSelector: chainSelector, - ChainConfig: ccip_home.CCIPHomeChainConfig{ - Readers: readers, - FChain: fChain, - Config: cfg, - }, - } -} - -func isChainConfigEqual(a, b ccip_home.CCIPHomeChainConfig) bool { - mapReader := make(map[[32]byte]struct{}) - for i := range a.Readers { - mapReader[a.Readers[i]] = struct{}{} - } - for i := range b.Readers { - if _, ok := mapReader[b.Readers[i]]; !ok { - return false - } - } - return bytes.Equal(a.Config, b.Config) && - a.FChain == b.FChain -} - -func addChainConfig( - lggr logger.Logger, - h deployment.Chain, - ccipConfig *ccip_home.CCIPHome, - chainSelector uint64, - p2pIDs [][32]byte, -) (ccip_home.CCIPHomeChainConfigArgs, error) { - // First Add CCIPOCRParams that includes all p2pIDs as readers - encodedExtraChainConfig, err := chainconfig.EncodeChainConfig(chainconfig.ChainConfig{ - GasPriceDeviationPPB: ccipocr3.NewBigIntFromInt64(1000), - DAGasPriceDeviationPPB: ccipocr3.NewBigIntFromInt64(0), - OptimisticConfirmations: 1, - }) - if err != nil { - return ccip_home.CCIPHomeChainConfigArgs{}, err - } - chainConfig := setupConfigInfo(chainSelector, p2pIDs, uint8(len(p2pIDs)/3), encodedExtraChainConfig) - existingCfg, err := ccipConfig.GetChainConfig(nil, chainSelector) - if err != nil { - return ccip_home.CCIPHomeChainConfigArgs{}, fmt.Errorf("get chain config for selector %d: %w", chainSelector, err) - } - if isChainConfigEqual(existingCfg, chainConfig.ChainConfig) { - lggr.Infow("Chain config already exists, not applying again", - "homeChain", h.String(), - "addedChain", chainSelector, - "chainConfig", chainConfig, - ) - return chainConfig, nil - } - tx, err := ccipConfig.ApplyChainConfigUpdates(h.DeployerKey, nil, []ccip_home.CCIPHomeChainConfigArgs{ - chainConfig, - }) - if _, err := deployment.ConfirmIfNoError(h, tx, err); err != nil { - return ccip_home.CCIPHomeChainConfigArgs{}, err - } - lggr.Infow("Applied chain config updates", "homeChain", h.String(), "addedChain", chainSelector, "chainConfig", chainConfig) - return chainConfig, nil -} - -// createDON creates one DON with 2 plugins (commit and exec) -// It first set a new candidate for the DON with the first plugin type and AddDON on capReg -// Then for subsequent operations it uses UpdateDON to promote the first plugin to the active deployment -// and to set candidate and promote it for the second plugin -func createDON( - lggr logger.Logger, - capReg *capabilities_registry.CapabilitiesRegistry, - ccipHome *ccip_home.CCIPHome, - ocr3Configs map[cctypes.PluginType]ccip_home.CCIPHomeOCR3Config, - home deployment.Chain, - newChainSel uint64, - nodes deployment.Nodes, -) error { - donID, err := internal.DonIDForChain(capReg, ccipHome, newChainSel) - if err != nil { - return fmt.Errorf("fetch don id for chain: %w", err) - } - if donID != 0 { - lggr.Infow("DON already exists not adding it again", "donID", donID, "chain", newChainSel) - return ValidateCCIPHomeConfigSetUp(lggr, capReg, ccipHome, newChainSel) - } - - commitConfig, ok := ocr3Configs[cctypes.PluginTypeCCIPCommit] - if !ok { - return fmt.Errorf("missing commit plugin in ocr3Configs") - } - - execConfig, ok := ocr3Configs[cctypes.PluginTypeCCIPExec] - if !ok { - return fmt.Errorf("missing exec plugin in ocr3Configs") - } - - latestDon, err := internal.LatestCCIPDON(capReg) - if err != nil { - return err - } - - donID = latestDon.Id + 1 - - err = internal.SetupCommitDON(lggr, donID, commitConfig, capReg, home, nodes, ccipHome) - if err != nil { - return fmt.Errorf("setup commit don: %w", err) - } - - // TODO: bug in contract causing this to not work as expected. - err = internal.SetupExecDON(lggr, donID, execConfig, capReg, home, nodes, ccipHome) - if err != nil { - return fmt.Errorf("setup exec don: %w", err) - } - return ValidateCCIPHomeConfigSetUp(lggr, capReg, ccipHome, newChainSel) -} - -func addDON( - lggr logger.Logger, - ocrSecrets deployment.OCRSecrets, - capReg *capabilities_registry.CapabilitiesRegistry, - ccipHome *ccip_home.CCIPHome, - rmnHomeAddress common.Address, - offRamp *offramp.OffRamp, - dest deployment.Chain, - home deployment.Chain, - nodes deployment.Nodes, - ocrParams CCIPOCRParams, -) error { - ocrConfigs, err := internal.BuildOCR3ConfigForCCIPHome( - ocrSecrets, offRamp, dest, nodes, rmnHomeAddress, ocrParams.OCRParameters, ocrParams.CommitOffChainConfig, ocrParams.ExecuteOffChainConfig) - if err != nil { - return err - } - err = createDON(lggr, capReg, ccipHome, ocrConfigs, home, dest.Selector, nodes) - if err != nil { - return err - } - don, err := internal.LatestCCIPDON(capReg) - if err != nil { - return err - } - lggr.Infow("Added DON", "donID", don.Id) - - offrampOCR3Configs, err := internal.BuildSetOCR3ConfigArgs(don.Id, ccipHome, dest.Selector) - if err != nil { - return err - } - lggr.Infow("Setting OCR3 Configs", - "offrampOCR3Configs", offrampOCR3Configs, - "configDigestCommit", hex.EncodeToString(offrampOCR3Configs[cctypes.PluginTypeCCIPCommit].ConfigDigest[:]), - "configDigestExec", hex.EncodeToString(offrampOCR3Configs[cctypes.PluginTypeCCIPExec].ConfigDigest[:]), - "chainSelector", dest.Selector, - ) - - // check if OCR3 config is already set on offramp - ocr3ConfigSet, err := isOCR3ConfigSetOnOffRamp(lggr, dest, offRamp, offrampOCR3Configs) - if err != nil { - return fmt.Errorf("error checking if OCR3 config is set on offramp: %w", err) - } - if ocr3ConfigSet { - lggr.Infow("OCR3 config already set on offramp, not applying again", "chain", dest.String()) - return nil - } - tx, err := offRamp.SetOCR3Configs(dest.DeployerKey, offrampOCR3Configs) - if _, err := deployment.ConfirmIfNoError(dest, tx, err); err != nil { - return err - } - lggr.Infow("Set OCR3 Configs", "chain", dest.String()) - // now check if OCR3 config is set on offramp - ocr3ConfigSet, err = isOCR3ConfigSetOnOffRamp(lggr, dest, offRamp, offrampOCR3Configs) - if err != nil { - return fmt.Errorf("error checking if OCR3 config is set on offramp: %w", err) - } - if !ocr3ConfigSet { - return fmt.Errorf("OCR3 config not set on offramp properly, check logs, chain %s", dest.String()) - } - return nil -} - -func isOCR3ConfigSetOnOffRamp( - lggr logger.Logger, - chain deployment.Chain, - offRamp *offramp.OffRamp, - offrampOCR3Configs []offramp.MultiOCR3BaseOCRConfigArgs, -) (bool, error) { - mapOfframpOCR3Configs := make(map[cctypes.PluginType]offramp.MultiOCR3BaseOCRConfigArgs) - for _, config := range offrampOCR3Configs { - mapOfframpOCR3Configs[cctypes.PluginType(config.OcrPluginType)] = config - } - - for _, pluginType := range []cctypes.PluginType{cctypes.PluginTypeCCIPCommit, cctypes.PluginTypeCCIPExec} { - ocrConfig, err := offRamp.LatestConfigDetails(&bind.CallOpts{ - Context: context.Background(), - }, uint8(pluginType)) - if err != nil { - return false, fmt.Errorf("error fetching OCR3 config for plugin %s chain %s: %w", pluginType.String(), chain.String(), err) - } - lggr.Debugw("Fetched OCR3 Configs", - "MultiOCR3BaseOCRConfig.F", ocrConfig.ConfigInfo.F, - "MultiOCR3BaseOCRConfig.N", ocrConfig.ConfigInfo.N, - "MultiOCR3BaseOCRConfig.IsSignatureVerificationEnabled", ocrConfig.ConfigInfo.IsSignatureVerificationEnabled, - "Signers", ocrConfig.Signers, - "Transmitters", ocrConfig.Transmitters, - "configDigest", hex.EncodeToString(ocrConfig.ConfigInfo.ConfigDigest[:]), - "chain", chain.String(), - ) - // TODO: assertions to be done as part of full state - // resprentation validation CCIP-3047 - if mapOfframpOCR3Configs[pluginType].ConfigDigest != ocrConfig.ConfigInfo.ConfigDigest { - lggr.Infow("OCR3 config digest mismatch", "pluginType", pluginType.String()) - return false, nil - } - if mapOfframpOCR3Configs[pluginType].F != ocrConfig.ConfigInfo.F { - lggr.Infow("OCR3 config F mismatch", "pluginType", pluginType.String()) - return false, nil - } - if mapOfframpOCR3Configs[pluginType].IsSignatureVerificationEnabled != ocrConfig.ConfigInfo.IsSignatureVerificationEnabled { - lggr.Infow("OCR3 config signature verification mismatch", "pluginType", pluginType.String()) - return false, nil - } - if pluginType == cctypes.PluginTypeCCIPCommit { - // only commit will set signers, exec doesn't need them. - for i, signer := range mapOfframpOCR3Configs[pluginType].Signers { - if !bytes.Equal(signer.Bytes(), ocrConfig.Signers[i].Bytes()) { - lggr.Infow("OCR3 config signer mismatch", "pluginType", pluginType.String()) - return false, nil - } - } - } - for i, transmitter := range mapOfframpOCR3Configs[pluginType].Transmitters { - if !bytes.Equal(transmitter.Bytes(), ocrConfig.Transmitters[i].Bytes()) { - lggr.Infow("OCR3 config transmitter mismatch", "pluginType", pluginType.String()) - return false, nil - } - } - } - return true, nil -} - -// ValidateCCIPHomeConfigSetUp checks that the commit and exec active and candidate configs are set up correctly -func ValidateCCIPHomeConfigSetUp( - lggr logger.Logger, - capReg *capabilities_registry.CapabilitiesRegistry, - ccipHome *ccip_home.CCIPHome, - chainSel uint64, -) error { - // fetch DONID - donID, err := internal.DonIDForChain(capReg, ccipHome, chainSel) - if err != nil { - return fmt.Errorf("fetch don id for chain: %w", err) - } - if donID == 0 { - return fmt.Errorf("don id for chain (%d) does not exist", chainSel) - } - - // final sanity checks on configs. - commitConfigs, err := ccipHome.GetAllConfigs(&bind.CallOpts{ - //Pending: true, - }, donID, uint8(cctypes.PluginTypeCCIPCommit)) - if err != nil { - return fmt.Errorf("get all commit configs: %w", err) - } - commitActiveDigest, err := ccipHome.GetActiveDigest(nil, donID, uint8(cctypes.PluginTypeCCIPCommit)) - if err != nil { - return fmt.Errorf("get active commit digest: %w", err) - } - lggr.Debugw("Fetched active commit digest", "commitActiveDigest", hex.EncodeToString(commitActiveDigest[:])) - commitCandidateDigest, err := ccipHome.GetCandidateDigest(nil, donID, uint8(cctypes.PluginTypeCCIPCommit)) - if err != nil { - return fmt.Errorf("get commit candidate digest: %w", err) - } - lggr.Debugw("Fetched candidate commit digest", "commitCandidateDigest", hex.EncodeToString(commitCandidateDigest[:])) - if commitConfigs.ActiveConfig.ConfigDigest == [32]byte{} { - return fmt.Errorf( - "active config digest is empty for commit, expected nonempty, donID: %d, cfg: %+v, config digest from GetActiveDigest call: %x, config digest from GetCandidateDigest call: %x", - donID, commitConfigs.ActiveConfig, commitActiveDigest, commitCandidateDigest) - } - if commitConfigs.CandidateConfig.ConfigDigest != [32]byte{} { - return fmt.Errorf( - "candidate config digest is nonempty for commit, expected empty, donID: %d, cfg: %+v, config digest from GetCandidateDigest call: %x, config digest from GetActiveDigest call: %x", - donID, commitConfigs.CandidateConfig, commitCandidateDigest, commitActiveDigest) - } - - execConfigs, err := ccipHome.GetAllConfigs(nil, donID, uint8(cctypes.PluginTypeCCIPExec)) - if err != nil { - return fmt.Errorf("get all exec configs: %w", err) - } - lggr.Debugw("Fetched exec configs", - "ActiveConfig.ConfigDigest", hex.EncodeToString(execConfigs.ActiveConfig.ConfigDigest[:]), - "CandidateConfig.ConfigDigest", hex.EncodeToString(execConfigs.CandidateConfig.ConfigDigest[:]), - ) - if execConfigs.ActiveConfig.ConfigDigest == [32]byte{} { - return fmt.Errorf("active config digest is empty for exec, expected nonempty, cfg: %v", execConfigs.ActiveConfig) - } - if execConfigs.CandidateConfig.ConfigDigest != [32]byte{} { - return fmt.Errorf("candidate config digest is nonempty for exec, expected empty, cfg: %v", execConfigs.CandidateConfig) - } - return nil -} diff --git a/deployment/ccip/changeset/cs_initial_add_chain_test.go b/deployment/ccip/changeset/cs_initial_add_chain_test.go deleted file mode 100644 index 7e155b82ed1..00000000000 --- a/deployment/ccip/changeset/cs_initial_add_chain_test.go +++ /dev/null @@ -1,93 +0,0 @@ -package changeset - -import ( - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/chainlink-ccip/pluginconfig" - "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" - "github.com/stretchr/testify/require" - - commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" -) - -func TestInitialAddChainAppliedTwice(t *testing.T) { - t.Parallel() - // This already applies the initial add chain changeset. - e := NewMemoryEnvironment(t) - - state, err := LoadOnchainState(e.Env) - require.NoError(t, err) - - // now try to apply it again for the second time - // Build the per chain config. - allChains := e.Env.AllChainSelectors() - tokenConfig := NewTestTokenConfig(state.Chains[e.FeedChainSel].USDFeeds) - chainConfigs := make(map[uint64]CCIPOCRParams) - timelockContractsPerChain := make(map[uint64]*proposalutils.TimelockExecutionContracts) - - for _, chain := range allChains { - timelockContractsPerChain[chain] = &proposalutils.TimelockExecutionContracts{ - Timelock: state.Chains[chain].Timelock, - CallProxy: state.Chains[chain].CallProxy, - } - tokenInfo := tokenConfig.GetTokenInfo(e.Env.Logger, state.Chains[chain].LinkToken, state.Chains[chain].Weth9) - ocrParams := DefaultOCRParams(e.FeedChainSel, tokenInfo, []pluginconfig.TokenDataObserverConfig{}) - chainConfigs[chain] = ocrParams - } - e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, timelockContractsPerChain, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(ConfigureNewChains), - Config: NewChainsConfig{ - HomeChainSel: e.HomeChainSel, - FeedChainSel: e.FeedChainSel, - ChainConfigByChain: chainConfigs, - }, - }, - }) - require.NoError(t, err) - // send requests - chain1, chain2 := allChains[0], allChains[1] - _, err = AddLanes(e.Env, AddLanesConfig{ - LaneConfigs: []LaneConfig{ - { - SourceSelector: chain1, - DestSelector: chain2, - InitialPricesBySource: DefaultInitialPrices, - FeeQuoterDestChain: DefaultFeeQuoterDestChainConfig(), - TestRouter: true, - }, - }, - }) - require.NoError(t, err) - ReplayLogs(t, e.Env.Offchain, e.ReplayBlocks) - // Need to keep track of the block number for each chain so that event subscription can be done from that block. - startBlocks := make(map[uint64]*uint64) - // Send a message from each chain to every other chain. - expectedSeqNumExec := make(map[SourceDestPair][]uint64) - expectedSeqNum := make(map[SourceDestPair]uint64) - latesthdr, err := e.Env.Chains[chain2].Client.HeaderByNumber(testcontext.Get(t), nil) - require.NoError(t, err) - block := latesthdr.Number.Uint64() - startBlocks[chain2] = &block - msgSentEvent := TestSendRequest(t, e.Env, state, chain1, chain2, true, router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(state.Chains[chain2].Receiver.Address().Bytes(), 32), - Data: []byte("hello"), - TokenAmounts: nil, - FeeToken: common.HexToAddress("0x0"), - ExtraArgs: nil, - }) - - expectedSeqNum[SourceDestPair{ - SourceChainSelector: chain1, - DestChainSelector: chain2, - }] = msgSentEvent.SequenceNumber - expectedSeqNumExec[SourceDestPair{ - SourceChainSelector: chain1, - DestChainSelector: chain2, - }] = []uint64{msgSentEvent.SequenceNumber} - ConfirmCommitForAllWithExpectedSeqNums(t, e.Env, state, expectedSeqNum, startBlocks) - ConfirmExecWithSeqNrsForAll(t, e.Env, state, expectedSeqNumExec, startBlocks) -} diff --git a/deployment/ccip/changeset/cs_jobspec.go b/deployment/ccip/changeset/cs_jobspec.go index 2551f193f47..e29578a516a 100644 --- a/deployment/ccip/changeset/cs_jobspec.go +++ b/deployment/ccip/changeset/cs_jobspec.go @@ -9,11 +9,11 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/relay" ) -var _ deployment.ChangeSet[any] = CCIPCapabilityJobspec +var _ deployment.ChangeSet[any] = CCIPCapabilityJobspecChangeset -// CCIPCapabilityJobspec returns the job specs for the CCIP capability. +// CCIPCapabilityJobspecChangeset returns the job specs for the CCIP capability. // The caller needs to propose these job specs to the offchain system. -func CCIPCapabilityJobspec(env deployment.Environment, _ any) (deployment.ChangesetOutput, error) { +func CCIPCapabilityJobspecChangeset(env deployment.Environment, _ any) (deployment.ChangesetOutput, error) { nodes, err := deployment.NodeInfo(env.NodeIDs, env.Offchain) if err != nil { return deployment.ChangesetOutput{}, err diff --git a/deployment/ccip/changeset/cs_jobspec_test.go b/deployment/ccip/changeset/cs_jobspec_test.go index a0445b0d5ee..b79dfc47387 100644 --- a/deployment/ccip/changeset/cs_jobspec_test.go +++ b/deployment/ccip/changeset/cs_jobspec_test.go @@ -1,4 +1,4 @@ -package changeset +package changeset_test import ( "testing" @@ -7,6 +7,7 @@ import ( "go.uber.org/zap/zapcore" "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/environment/memory" ccip "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/validate" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -19,7 +20,7 @@ func TestJobSpecChangeset(t *testing.T) { Chains: 1, Nodes: 4, }) - output, err := CCIPCapabilityJobspec(e, nil) + output, err := changeset.CCIPCapabilityJobspecChangeset(e, nil) require.NoError(t, err) require.NotNil(t, output.JobSpecs) nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) diff --git a/deployment/ccip/changeset/cs_prerequisites.go b/deployment/ccip/changeset/cs_prerequisites.go index 95ef923df83..da4f59c3eb6 100644 --- a/deployment/ccip/changeset/cs_prerequisites.go +++ b/deployment/ccip/changeset/cs_prerequisites.go @@ -2,37 +2,47 @@ package changeset import ( "fmt" + "math/big" "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + "github.com/smartcontractkit/chainlink-ccip/pkg/reader" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "golang.org/x/sync/errgroup" "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/maybe_revert_message_receiver" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_rmn_contract" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_usdc_token_messenger" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_usdc_token_transmitter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry_1_2_0" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/registry_module_owner_custom" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_contract" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_proxy_contract" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_admin_registry" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/usdc_token_pool" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/weth9" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/multicall3" ) var ( - _ deployment.ChangeSet[DeployPrerequisiteConfig] = DeployPrerequisites + _ deployment.ChangeSet[DeployPrerequisiteConfig] = DeployPrerequisitesChangeset ) -// DeployPrerequisites deploys the pre-requisite contracts for CCIP +// DeployPrerequisitesChangeset deploys the pre-requisite contracts for CCIP // pre-requisite contracts are the contracts which can be reused from previous versions of CCIP // Or the contracts which are already deployed on the chain ( for example, tokens, feeds, etc) // Caller should update the environment's address book with the returned addresses. -func DeployPrerequisites(env deployment.Environment, cfg DeployPrerequisiteConfig) (deployment.ChangesetOutput, error) { +func DeployPrerequisitesChangeset(env deployment.Environment, cfg DeployPrerequisiteConfig) (deployment.ChangesetOutput, error) { err := cfg.Validate() if err != nil { return deployment.ChangesetOutput{}, errors.Wrapf(deployment.ErrInvalidConfig, "%v", err) } ab := deployment.NewMemoryAddressBook() - err = deployPrerequisiteChainContracts(env, ab, cfg.ChainSelectors, cfg.Opts...) + err = deployPrerequisiteChainContracts(env, ab, cfg) if err != nil { env.Logger.Errorw("Failed to deploy prerequisite contracts", "err", err, "addressBook", ab) return deployment.ChangesetOutput{ @@ -47,13 +57,23 @@ func DeployPrerequisites(env deployment.Environment, cfg DeployPrerequisiteConfi } type DeployPrerequisiteContractsOpts struct { - USDCEnabledChains []uint64 - Multicall3Enabled bool + USDCEnabled bool + Multicall3Enabled bool + LegacyDeploymentCfg *V1_5DeploymentConfig +} + +type V1_5DeploymentConfig struct { + RMNConfig *rmn_contract.RMNConfig + PriceRegStalenessThreshold uint32 } type DeployPrerequisiteConfig struct { - ChainSelectors []uint64 - Opts []PrerequisiteOpt + Configs []DeployPrerequisiteConfigPerChain +} + +type DeployPrerequisiteConfigPerChain struct { + ChainSelector uint64 + Opts []PrerequisiteOpt // TODO handle tokens and feeds in prerequisite config Tokens map[TokenSymbol]common.Address Feeds map[TokenSymbol]common.Address @@ -61,7 +81,8 @@ type DeployPrerequisiteConfig struct { func (c DeployPrerequisiteConfig) Validate() error { mapAllChainSelectors := make(map[uint64]struct{}) - for _, cs := range c.ChainSelectors { + for _, cfg := range c.Configs { + cs := cfg.ChainSelector mapAllChainSelectors[cs] = struct{}{} if err := deployment.IsValidChainSelector(cs); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", cs, err) @@ -72,31 +93,41 @@ func (c DeployPrerequisiteConfig) Validate() error { type PrerequisiteOpt func(o *DeployPrerequisiteContractsOpts) -func WithUSDCChains(chains []uint64) PrerequisiteOpt { +func WithUSDCEnabled() PrerequisiteOpt { + return func(o *DeployPrerequisiteContractsOpts) { + o.USDCEnabled = true + } +} + +func WithMultiCall3Enabled() PrerequisiteOpt { return func(o *DeployPrerequisiteContractsOpts) { - o.USDCEnabledChains = chains + o.Multicall3Enabled = true } } -func WithMulticall3(enabled bool) PrerequisiteOpt { +func WithLegacyDeploymentEnabled(cfg V1_5DeploymentConfig) PrerequisiteOpt { return func(o *DeployPrerequisiteContractsOpts) { - o.Multicall3Enabled = enabled + if cfg.PriceRegStalenessThreshold == 0 { + panic("PriceRegStalenessThreshold must be set") + } + // TODO validate RMNConfig + o.LegacyDeploymentCfg = &cfg } } -func deployPrerequisiteChainContracts(e deployment.Environment, ab deployment.AddressBook, selectors []uint64, opts ...PrerequisiteOpt) error { +func deployPrerequisiteChainContracts(e deployment.Environment, ab deployment.AddressBook, cfg DeployPrerequisiteConfig) error { state, err := LoadOnchainState(e) if err != nil { e.Logger.Errorw("Failed to load existing onchain state", "err") return err } deployGrp := errgroup.Group{} - for _, sel := range selectors { - chain := e.Chains[sel] + for _, c := range cfg.Configs { + chain := e.Chains[c.ChainSelector] deployGrp.Go(func() error { - err := deployPrerequisiteContracts(e, ab, state, chain, opts...) + err := deployPrerequisiteContracts(e, ab, state, chain, c.Opts...) if err != nil { - e.Logger.Errorw("Failed to deploy prerequisite contracts", "chain", sel, "err", err) + e.Logger.Errorw("Failed to deploy prerequisite contracts", "chain", chain.String(), "err", err) return err } return nil @@ -114,19 +145,12 @@ func deployPrerequisiteContracts(e deployment.Environment, ab deployment.Address opt(deployOpts) } } - var isUSDC bool - for _, sel := range deployOpts.USDCEnabledChains { - if sel == chain.Selector { - isUSDC = true - break - } - } lggr := e.Logger chainState, chainExists := state.Chains[chain.Selector] var weth9Contract *weth9.WETH9 var tokenAdminReg *token_admin_registry.TokenAdminRegistry var registryModule *registry_module_owner_custom.RegistryModuleOwnerCustom - var rmnProxy *rmn_proxy_contract.RMNProxyContract + var rmnProxy *rmn_proxy_contract.RMNProxy var r *router.Router var mc3 *multicall3.Multicall3 if chainExists { @@ -137,37 +161,103 @@ func deployPrerequisiteContracts(e deployment.Environment, ab deployment.Address r = chainState.Router mc3 = chainState.Multicall3 } + var rmnAddr common.Address + // if we are setting up 1.5 version, deploy RMN contract based on the config provided + // else deploy the mock RMN contract + if deployOpts.LegacyDeploymentCfg != nil && deployOpts.LegacyDeploymentCfg.RMNConfig != nil { + if chainState.RMN == nil { + rmn, err := deployment.DeployContract(lggr, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*rmn_contract.RMNContract] { + rmnAddress, tx2, rmnC, err2 := rmn_contract.DeployRMNContract( + chain.DeployerKey, + chain.Client, + *deployOpts.LegacyDeploymentCfg.RMNConfig, + ) + return deployment.ContractDeploy[*rmn_contract.RMNContract]{ + Address: rmnAddress, Contract: rmnC, Tx: tx2, Tv: deployment.NewTypeAndVersion(RMN, deployment.Version1_5_0), Err: err2, + } + }) + if err != nil { + lggr.Errorw("Failed to deploy RMN", "chain", chain.String(), "err", deployment.MaybeDataErr(err)) + return err + } + rmnAddr = rmn.Address + } else { + lggr.Infow("RMN already deployed", "chain", chain.String(), "address", chainState.RMN.Address) + rmnAddr = chainState.RMN.Address() + } + } else { + if chainState.MockRMN == nil { + rmn, err := deployment.DeployContract(lggr, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*mock_rmn_contract.MockRMNContract] { + rmnAddress, tx2, rmnC, err2 := mock_rmn_contract.DeployMockRMNContract( + chain.DeployerKey, + chain.Client, + ) + return deployment.ContractDeploy[*mock_rmn_contract.MockRMNContract]{ + Address: rmnAddress, Contract: rmnC, Tx: tx2, Tv: deployment.NewTypeAndVersion(MockRMN, deployment.Version1_0_0), Err: err2, + } + }) + if err != nil { + lggr.Errorw("Failed to deploy mock RMN", "chain", chain.String(), "err", err) + return err + } + rmnAddr = rmn.Address + } else { + lggr.Infow("Mock RMN already deployed", "chain", chain.String(), "addr", chainState.MockRMN.Address) + rmnAddr = chainState.MockRMN.Address() + } + } if rmnProxy == nil { - rmn, err := deployment.DeployContract(lggr, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*mock_rmn_contract.MockRMNContract] { - rmnAddr, tx2, rmn, err2 := mock_rmn_contract.DeployMockRMNContract( + RMNProxy, err := deployment.DeployContract(lggr, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*rmn_proxy_contract.RMNProxy] { + rmnProxyAddr, tx2, rmnProxy2, err2 := rmn_proxy_contract.DeployRMNProxy( chain.DeployerKey, chain.Client, + rmnAddr, ) - return deployment.ContractDeploy[*mock_rmn_contract.MockRMNContract]{ - Address: rmnAddr, Contract: rmn, Tx: tx2, Tv: deployment.NewTypeAndVersion(MockRMN, deployment.Version1_0_0), Err: err2, + return deployment.ContractDeploy[*rmn_proxy_contract.RMNProxy]{ + Address: rmnProxyAddr, Contract: rmnProxy2, Tx: tx2, Tv: deployment.NewTypeAndVersion(ARMProxy, deployment.Version1_0_0), Err: err2, } }) if err != nil { - lggr.Errorw("Failed to deploy mock RMN", "chain", chain.String(), "err", err) + lggr.Errorw("Failed to deploy RMNProxy", "chain", chain.String(), "err", err) return err } - rmnProxyContract, err := deployment.DeployContract(lggr, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*rmn_proxy_contract.RMNProxyContract] { - rmnProxyAddr, tx2, rmnProxy, err2 := rmn_proxy_contract.DeployRMNProxyContract( - chain.DeployerKey, - chain.Client, - rmn.Address, - ) - return deployment.ContractDeploy[*rmn_proxy_contract.RMNProxyContract]{ - rmnProxyAddr, rmnProxy, tx2, deployment.NewTypeAndVersion(ARMProxy, deployment.Version1_0_0), err2, - } - }) + rmnProxy = RMNProxy.Contract + } else { + lggr.Infow("RMNProxy already deployed", "chain", chain.String(), "addr", rmnProxy.Address) + // check if the RMNProxy is pointing to the correct RMN contract + currentRMNAddr, err := rmnProxy.GetARM(nil) if err != nil { - lggr.Errorw("Failed to deploy RMNProxyExisting", "chain", chain.String(), "err", err) + lggr.Errorw("Failed to get RMN from RMNProxy", "chain", chain.String(), "err", err) return err } - rmnProxy = rmnProxyContract.Contract + if currentRMNAddr != rmnAddr { + lggr.Infow("RMNProxy is not pointing to the correct RMN contract, updating RMN", "chain", chain.String(), "currentRMN", currentRMNAddr, "expectedRMN", rmnAddr) + rmnOwner, err := rmnProxy.Owner(nil) + if err != nil { + lggr.Errorw("Failed to get owner of RMNProxy", "chain", chain.String(), "err", err) + return err + } + if rmnOwner != chain.DeployerKey.From { + lggr.Warnw( + "RMNProxy is not owned by the deployer and RMNProxy is not pointing to the correct RMN contract, "+ + "run SetRMNRemoteOnRMNProxyChangeset to update RMN with a proposal", + "chain", chain.String(), "owner", rmnOwner, "currentRMN", currentRMNAddr, "expectedRMN", rmnAddr) + } else { + tx, err := rmnProxy.SetARM(chain.DeployerKey, rmnAddr) + if err != nil { + lggr.Errorw("Failed to set RMN on RMNProxy", "chain", chain.String(), "err", err) + return err + } + _, err = chain.Confirm(tx) + if err != nil { + lggr.Errorw("Failed to confirm setRMN on RMNProxy", "chain", chain.String(), "err", err) + return err + } + } + } } if tokenAdminReg == nil { tokenAdminRegistry, err := deployment.DeployContract(e.Logger, chain, ab, @@ -176,7 +266,7 @@ func deployPrerequisiteContracts(e deployment.Environment, ab deployment.Address chain.DeployerKey, chain.Client) return deployment.ContractDeploy[*token_admin_registry.TokenAdminRegistry]{ - tokenAdminRegistryAddr, tokenAdminRegistry, tx2, deployment.NewTypeAndVersion(TokenAdminRegistry, deployment.Version1_5_0), err2, + Address: tokenAdminRegistryAddr, Contract: tokenAdminRegistry, Tx: tx2, Tv: deployment.NewTypeAndVersion(TokenAdminRegistry, deployment.Version1_5_0), Err: err2, } }) if err != nil { @@ -195,7 +285,7 @@ func deployPrerequisiteContracts(e deployment.Environment, ab deployment.Address chain.Client, tokenAdminReg.Address()) return deployment.ContractDeploy[*registry_module_owner_custom.RegistryModuleOwnerCustom]{ - regModAddr, regMod, tx2, deployment.NewTypeAndVersion(RegistryModule, deployment.Version1_5_0), err2, + Address: regModAddr, Contract: regMod, Tx: tx2, Tv: deployment.NewTypeAndVersion(RegistryModule, deployment.Version1_5_0), Err: err2, } }) if err != nil { @@ -233,7 +323,7 @@ func deployPrerequisiteContracts(e deployment.Environment, ab deployment.Address chain.Client, ) return deployment.ContractDeploy[*weth9.WETH9]{ - weth9Addr, weth9c, tx2, deployment.NewTypeAndVersion(WETH9, deployment.Version1_0_0), err2, + Address: weth9Addr, Contract: weth9c, Tx: tx2, Tv: deployment.NewTypeAndVersion(WETH9, deployment.Version1_0_0), Err: err2, } }) if err != nil { @@ -242,8 +332,10 @@ func deployPrerequisiteContracts(e deployment.Environment, ab deployment.Address } weth9Contract = weth.Contract } else { - lggr.Infow("weth9 already deployed", "addr", weth9Contract.Address) + lggr.Infow("weth9 already deployed", "chain", chain.String(), "addr", weth9Contract.Address) + weth9Contract = chainState.Weth9 } + // if router is not already deployed, we deploy it if r == nil { routerContract, err := deployment.DeployContract(e.Logger, chain, ab, @@ -255,7 +347,7 @@ func deployPrerequisiteContracts(e deployment.Environment, ab deployment.Address rmnProxy.Address(), ) return deployment.ContractDeploy[*router.Router]{ - routerAddr, routerC, tx2, deployment.NewTypeAndVersion(Router, deployment.Version1_2_0), err2, + Address: routerAddr, Contract: routerC, Tx: tx2, Tv: deployment.NewTypeAndVersion(Router, deployment.Version1_2_0), Err: err2, } }) if err != nil { @@ -275,7 +367,7 @@ func deployPrerequisiteContracts(e deployment.Environment, ab deployment.Address chain.Client, ) return deployment.ContractDeploy[*multicall3.Multicall3]{ - multicall3Addr, multicall3Wrapper, tx2, deployment.NewTypeAndVersion(Multicall3, deployment.Version1_0_0), err2, + Address: multicall3Addr, Contract: multicall3Wrapper, Tx: tx2, Tv: deployment.NewTypeAndVersion(Multicall3, deployment.Version1_0_0), Err: err2, } }) if err != nil { @@ -287,8 +379,8 @@ func deployPrerequisiteContracts(e deployment.Environment, ab deployment.Address e.Logger.Info("ccip multicall already deployed", "chain", chain.String(), "addr", mc3.Address) } } - if isUSDC { - token, pool, messenger, transmitter, err1 := DeployUSDC(e.Logger, chain, ab, rmnProxy.Address(), r.Address()) + if deployOpts.USDCEnabled { + token, pool, messenger, transmitter, err1 := deployUSDC(e.Logger, chain, ab, rmnProxy.Address(), r.Address()) if err1 != nil { return err1 } @@ -300,5 +392,169 @@ func deployPrerequisiteContracts(e deployment.Environment, ab deployment.Address "messenger", messenger.Address(), ) } + if chainState.Receiver == nil { + _, err := deployment.DeployContract(e.Logger, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*maybe_revert_message_receiver.MaybeRevertMessageReceiver] { + receiverAddr, tx, receiver, err2 := maybe_revert_message_receiver.DeployMaybeRevertMessageReceiver( + chain.DeployerKey, + chain.Client, + false, + ) + return deployment.ContractDeploy[*maybe_revert_message_receiver.MaybeRevertMessageReceiver]{ + Address: receiverAddr, Contract: receiver, Tx: tx, Tv: deployment.NewTypeAndVersion(CCIPReceiver, deployment.Version1_0_0), Err: err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy receiver", "chain", chain.String(), "err", err) + return err + } + } else { + e.Logger.Infow("receiver already deployed", "addr", chainState.Receiver.Address, "chain", chain.String()) + } + // Only applicable if setting up for 1.5 version, remove this once we have fully migrated to 1.6 + if deployOpts.LegacyDeploymentCfg != nil { + if chainState.PriceRegistry == nil { + linkAddr, err1 := chainState.LinkTokenAddress() + if err1 != nil { + return fmt.Errorf("failed to get link token address for chain %s: %w", chain.String(), err1) + } + _, err := deployment.DeployContract(lggr, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*price_registry_1_2_0.PriceRegistry] { + priceRegAddr, tx2, priceRegAddrC, err2 := price_registry_1_2_0.DeployPriceRegistry( + chain.DeployerKey, + chain.Client, + nil, + []common.Address{weth9Contract.Address(), linkAddr}, + deployOpts.LegacyDeploymentCfg.PriceRegStalenessThreshold, + ) + return deployment.ContractDeploy[*price_registry_1_2_0.PriceRegistry]{ + Address: priceRegAddr, Contract: priceRegAddrC, Tx: tx2, + Tv: deployment.NewTypeAndVersion(PriceRegistry, deployment.Version1_2_0), Err: err2, + } + }) + if err != nil { + lggr.Errorw("Failed to deploy PriceRegistry", "chain", chain.String(), "err", err) + return err + } + } else { + lggr.Infow("PriceRegistry already deployed", "chain", chain.String(), "addr", chainState.PriceRegistry.Address) + } + } return nil } + +func deployUSDC( + lggr logger.Logger, + chain deployment.Chain, + addresses deployment.AddressBook, + rmnProxy common.Address, + router common.Address, +) ( + *burn_mint_erc677.BurnMintERC677, + *usdc_token_pool.USDCTokenPool, + *mock_usdc_token_messenger.MockE2EUSDCTokenMessenger, + *mock_usdc_token_transmitter.MockE2EUSDCTransmitter, + error, +) { + token, err := deployment.DeployContract(lggr, chain, addresses, + func(chain deployment.Chain) deployment.ContractDeploy[*burn_mint_erc677.BurnMintERC677] { + tokenAddress, tx, tokenContract, err2 := burn_mint_erc677.DeployBurnMintERC677( + chain.DeployerKey, + chain.Client, + USDCName, + string(USDCSymbol), + UsdcDecimals, + big.NewInt(0), + ) + return deployment.ContractDeploy[*burn_mint_erc677.BurnMintERC677]{ + Address: tokenAddress, + Contract: tokenContract, + Tx: tx, + Tv: deployment.NewTypeAndVersion(USDCToken, deployment.Version1_0_0), + Err: err2, + } + }) + if err != nil { + lggr.Errorw("Failed to deploy USDC token", "chain", chain.String(), "err", err) + return nil, nil, nil, nil, err + } + + tx, err := token.Contract.GrantMintRole(chain.DeployerKey, chain.DeployerKey.From) + if err != nil { + lggr.Errorw("Failed to grant mint role", "chain", chain.String(), "token", token.Contract.Address(), "err", err) + return nil, nil, nil, nil, err + } + _, err = chain.Confirm(tx) + if err != nil { + return nil, nil, nil, nil, err + } + + transmitter, err := deployment.DeployContract(lggr, chain, addresses, + func(chain deployment.Chain) deployment.ContractDeploy[*mock_usdc_token_transmitter.MockE2EUSDCTransmitter] { + transmitterAddress, tx, transmitterContract, err2 := mock_usdc_token_transmitter.DeployMockE2EUSDCTransmitter( + chain.DeployerKey, + chain.Client, + 0, + reader.AllAvailableDomains()[chain.Selector], + token.Address, + ) + return deployment.ContractDeploy[*mock_usdc_token_transmitter.MockE2EUSDCTransmitter]{ + Address: transmitterAddress, + Contract: transmitterContract, + Tx: tx, + Tv: deployment.NewTypeAndVersion(USDCMockTransmitter, deployment.Version1_0_0), + Err: err2, + } + }) + if err != nil { + lggr.Errorw("Failed to deploy mock USDC transmitter", "chain", chain.String(), "err", err) + return nil, nil, nil, nil, err + } + + messenger, err := deployment.DeployContract(lggr, chain, addresses, + func(chain deployment.Chain) deployment.ContractDeploy[*mock_usdc_token_messenger.MockE2EUSDCTokenMessenger] { + messengerAddress, tx, messengerContract, err2 := mock_usdc_token_messenger.DeployMockE2EUSDCTokenMessenger( + chain.DeployerKey, + chain.Client, + 0, + transmitter.Address, + ) + return deployment.ContractDeploy[*mock_usdc_token_messenger.MockE2EUSDCTokenMessenger]{ + Address: messengerAddress, + Contract: messengerContract, + Tx: tx, + Tv: deployment.NewTypeAndVersion(USDCTokenMessenger, deployment.Version1_0_0), + Err: err2, + } + }) + if err != nil { + lggr.Errorw("Failed to deploy USDC token messenger", "chain", chain.String(), "err", err) + return nil, nil, nil, nil, err + } + + tokenPool, err := deployment.DeployContract(lggr, chain, addresses, + func(chain deployment.Chain) deployment.ContractDeploy[*usdc_token_pool.USDCTokenPool] { + tokenPoolAddress, tx, tokenPoolContract, err2 := usdc_token_pool.DeployUSDCTokenPool( + chain.DeployerKey, + chain.Client, + messenger.Address, + token.Address, + []common.Address{}, + rmnProxy, + router, + ) + return deployment.ContractDeploy[*usdc_token_pool.USDCTokenPool]{ + Address: tokenPoolAddress, + Contract: tokenPoolContract, + Tx: tx, + Tv: deployment.NewTypeAndVersion(USDCTokenPool, deployment.Version1_0_0), + Err: err2, + } + }) + if err != nil { + lggr.Errorw("Failed to deploy USDC token pool", "chain", chain.String(), "err", err) + return nil, nil, nil, nil, err + } + + return token.Contract, tokenPool.Contract, messenger.Contract, transmitter.Contract, nil +} diff --git a/deployment/ccip/changeset/cs_prerequisites_test.go b/deployment/ccip/changeset/cs_prerequisites_test.go index da1ff9c83a9..c9c20757e92 100644 --- a/deployment/ccip/changeset/cs_prerequisites_test.go +++ b/deployment/ccip/changeset/cs_prerequisites_test.go @@ -1,4 +1,4 @@ -package changeset +package changeset_test import ( "testing" @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -19,14 +20,18 @@ func TestDeployPrerequisites(t *testing.T) { Nodes: 4, }) newChain := e.AllChainSelectors()[0] - cfg := DeployPrerequisiteConfig{ - ChainSelectors: []uint64{newChain}, + cfg := changeset.DeployPrerequisiteConfig{ + Configs: []changeset.DeployPrerequisiteConfigPerChain{ + { + ChainSelector: newChain, + }, + }, } - output, err := DeployPrerequisites(e, cfg) + output, err := changeset.DeployPrerequisitesChangeset(e, cfg) require.NoError(t, err) err = e.ExistingAddresses.Merge(output.AddressBook) require.NoError(t, err) - state, err := LoadOnchainState(e) + state, err := changeset.LoadOnchainState(e) require.NoError(t, err) require.NotNil(t, state.Chains[newChain].Weth9) require.NotNil(t, state.Chains[newChain].TokenAdminRegistry) diff --git a/deployment/ccip/changeset/cs_rmn_curse_uncurse.go b/deployment/ccip/changeset/cs_rmn_curse_uncurse.go new file mode 100644 index 00000000000..b6125638143 --- /dev/null +++ b/deployment/ccip/changeset/cs_rmn_curse_uncurse.go @@ -0,0 +1,339 @@ +package changeset + +import ( + "encoding/binary" + "errors" + "fmt" + + "github.com/smartcontractkit/chainlink/deployment" + commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" +) + +var ( + _ deployment.ChangeSet[RMNCurseConfig] = RMNCurseChangeset + _ deployment.ChangeSet[RMNCurseConfig] = RMNUncurseChangeset +) + +// GlobalCurseSubject as defined here: https://github.com/smartcontractkit/chainlink/blob/new-rmn-curse-changeset/contracts/src/v0.8/ccip/rmn/RMNRemote.sol#L15 +func GlobalCurseSubject() Subject { + return Subject{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01} +} + +// RMNCurseAction represent a curse action to be applied on a chain (ChainSelector) with a specific subject (SubjectToCurse) +// The curse action will by applied by calling the Curse method on the RMNRemote contract on the chain (ChainSelector) +type RMNCurseAction struct { + ChainSelector uint64 + SubjectToCurse Subject +} + +// CurseAction is a function that returns a list of RMNCurseAction to be applied on a chain +// CurseChain, CurseLane, CurseGloballyOnlyOnSource are examples of function implementing CurseAction +type CurseAction func(e deployment.Environment) []RMNCurseAction + +type RMNCurseConfig struct { + MCMS *MCMSConfig + CurseActions []CurseAction + Reason string +} + +func (c RMNCurseConfig) Validate(e deployment.Environment) error { + state, err := LoadOnchainState(e) + + if err != nil { + return fmt.Errorf("failed to load onchain state: %w", err) + } + + if len(c.CurseActions) == 0 { + return errors.New("curse actions are required") + } + + if c.Reason == "" { + return errors.New("reason is required") + } + + validSubjects := map[Subject]struct{}{ + GlobalCurseSubject(): {}, + } + for _, selector := range e.AllChainSelectors() { + validSubjects[SelectorToSubject(selector)] = struct{}{} + } + + for _, curseAction := range c.CurseActions { + result := curseAction(e) + for _, action := range result { + targetChain := e.Chains[action.ChainSelector] + targetChainState, ok := state.Chains[action.ChainSelector] + if !ok { + return fmt.Errorf("chain %s not found in onchain state", targetChain.String()) + } + + if err := commoncs.ValidateOwnership(e.GetContext(), c.MCMS != nil, targetChain.DeployerKey.From, targetChainState.Timelock.Address(), targetChainState.RMNRemote); err != nil { + return fmt.Errorf("chain %s: %w", targetChain.String(), err) + } + + if err = deployment.IsValidChainSelector(action.ChainSelector); err != nil { + return fmt.Errorf("invalid chain selector %d for chain %s", action.ChainSelector, targetChain.String()) + } + + if _, ok := validSubjects[action.SubjectToCurse]; !ok { + return fmt.Errorf("invalid subject %x for chain %s", action.SubjectToCurse, targetChain.String()) + } + } + } + + return nil +} + +type Subject = [16]byte + +func SelectorToSubject(selector uint64) Subject { + var b Subject + binary.BigEndian.PutUint64(b[8:], selector) + return b +} + +// CurseLaneOnlyOnSource curses a lane only on the source chain +// This will prevent message from source to destination to be initiated +// One noteworthy behaviour is that this means that message can be sent from destination to source but will not be executed on the source +// Given 3 chains A, B, C +// CurseLaneOnlyOnSource(A, B) will curse A with the curse subject of B +func CurseLaneOnlyOnSource(sourceSelector uint64, destinationSelector uint64) CurseAction { + // Curse from source to destination + return func(e deployment.Environment) []RMNCurseAction { + return []RMNCurseAction{ + { + ChainSelector: sourceSelector, + SubjectToCurse: SelectorToSubject(destinationSelector), + }, + } + } +} + +// CurseGloballyOnlyOnChain curses a chain globally only on the source chain +// Given 3 chains A, B, C +// CurseGloballyOnlyOnChain(A) will curse a with the global curse subject only +func CurseGloballyOnlyOnChain(selector uint64) CurseAction { + return func(e deployment.Environment) []RMNCurseAction { + return []RMNCurseAction{ + { + ChainSelector: selector, + SubjectToCurse: GlobalCurseSubject(), + }, + } + } +} + +// Call Curse on both RMNRemote from source and destination to prevent message from source to destination and vice versa +// Given 3 chains A, B, C +// CurseLaneBidirectionally(A, B) will curse A with the curse subject of B and B with the curse subject of A +func CurseLaneBidirectionally(sourceSelector uint64, destinationSelector uint64) CurseAction { + // Bidirectional curse between two chains + return func(e deployment.Environment) []RMNCurseAction { + return append( + CurseLaneOnlyOnSource(sourceSelector, destinationSelector)(e), + CurseLaneOnlyOnSource(destinationSelector, sourceSelector)(e)..., + ) + } +} + +// CurseChain do a global curse on chainSelector and curse chainSelector on all other chains +// Given 3 chains A, B, C +// CurseChain(A) will curse A with the global curse subject and curse B and C with the curse subject of A +func CurseChain(chainSelector uint64) CurseAction { + return func(e deployment.Environment) []RMNCurseAction { + chainSelectors := e.AllChainSelectors() + + // Curse all other chains to prevent onramp from sending message to the cursed chain + var curseActions []RMNCurseAction + for _, otherChainSelector := range chainSelectors { + if otherChainSelector != chainSelector { + curseActions = append(curseActions, RMNCurseAction{ + ChainSelector: otherChainSelector, + SubjectToCurse: SelectorToSubject(chainSelector), + }) + } + } + + // Curse the chain with a global curse to prevent any onramp or offramp message from send message in and out of the chain + curseActions = append(curseActions, CurseGloballyOnlyOnChain(chainSelector)(e)...) + + return curseActions + } +} + +func groupRMNSubjectBySelector(rmnSubjects []RMNCurseAction, avoidCursingSelf bool, onlyKeepGlobal bool) map[uint64][]Subject { + grouped := make(map[uint64][]Subject) + for _, s := range rmnSubjects { + // Skip self-curse if needed + if s.SubjectToCurse == SelectorToSubject(s.ChainSelector) && avoidCursingSelf { + continue + } + // Initialize slice for this chain if needed + if _, ok := grouped[s.ChainSelector]; !ok { + grouped[s.ChainSelector] = []Subject{} + } + // If global is already set and we only keep global, skip + if onlyKeepGlobal && len(grouped[s.ChainSelector]) == 1 && grouped[s.ChainSelector][0] == GlobalCurseSubject() { + continue + } + // If subject is global and we only keep global, reset immediately + if s.SubjectToCurse == GlobalCurseSubject() && onlyKeepGlobal { + grouped[s.ChainSelector] = []Subject{GlobalCurseSubject()} + continue + } + // Ensure uniqueness + duplicate := false + for _, added := range grouped[s.ChainSelector] { + if added == s.SubjectToCurse { + duplicate = true + break + } + } + if !duplicate { + grouped[s.ChainSelector] = append(grouped[s.ChainSelector], s.SubjectToCurse) + } + } + + return grouped +} + +// RMNCurseChangeset creates a new changeset for cursing chains or lanes on RMNRemote contracts. +// Example usage: +// +// cfg := RMNCurseConfig{ +// CurseActions: []CurseAction{ +// CurseChain(SEPOLIA_CHAIN_SELECTOR), +// CurseLane(SEPOLIA_CHAIN_SELECTOR, AVAX_FUJI_CHAIN_SELECTOR), +// }, +// CurseReason: "test curse", +// MCMS: &MCMSConfig{MinDelay: 0}, +// } +// output, err := RMNCurseChangeset(env, cfg) +func RMNCurseChangeset(e deployment.Environment, cfg RMNCurseConfig) (deployment.ChangesetOutput, error) { + err := cfg.Validate(e) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + state, err := LoadOnchainState(e) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) + } + deployerGroup := NewDeployerGroup(e, state, cfg.MCMS) + + // Generate curse actions + var curseActions []RMNCurseAction + for _, curseAction := range cfg.CurseActions { + curseActions = append(curseActions, curseAction(e)...) + } + // Group curse actions by chain selector + grouped := groupRMNSubjectBySelector(curseActions, true, true) + // For each chain in the environment get the RMNRemote contract and call curse + for selector, chain := range state.Chains { + deployer, err := deployerGroup.GetDeployer(selector) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to get deployer for chain %d: %w", selector, err) + } + if curseSubjects, ok := grouped[selector]; ok { + // Only curse the subjects that are not actually cursed + notAlreadyCursedSubjects := make([]Subject, 0) + for _, subject := range curseSubjects { + cursed, err := chain.RMNRemote.IsCursed(nil, subject) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to check if chain %d is cursed: %w", selector, err) + } + + if !cursed { + notAlreadyCursedSubjects = append(notAlreadyCursedSubjects, subject) + } else { + e.Logger.Warnf("chain %s subject %x is already cursed, ignoring it while cursing", e.Chains[selector].Name(), subject) + } + } + + if len(notAlreadyCursedSubjects) == 0 { + e.Logger.Infof("chain %s is already cursed with all the subjects, skipping", e.Chains[selector].Name()) + continue + } + + _, err := chain.RMNRemote.Curse0(deployer, notAlreadyCursedSubjects) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to curse chain %d: %w", selector, err) + } + e.Logger.Infof("Cursed chain %d with subjects %v", selector, notAlreadyCursedSubjects) + } + } + + return deployerGroup.Enact("proposal to curse RMNs: " + cfg.Reason) +} + +// RMNUncurseChangeset creates a new changeset for uncursing chains or lanes on RMNRemote contracts. +// Example usage: +// +// cfg := RMNCurseConfig{ +// CurseActions: []CurseAction{ +// CurseChain(SEPOLIA_CHAIN_SELECTOR), +// CurseLane(SEPOLIA_CHAIN_SELECTOR, AVAX_FUJI_CHAIN_SELECTOR), +// }, +// MCMS: &MCMSConfig{MinDelay: 0}, +// } +// output, err := RMNUncurseChangeset(env, cfg) +// +// Curse actions are reused and reverted instead of applied in this changeset +func RMNUncurseChangeset(e deployment.Environment, cfg RMNCurseConfig) (deployment.ChangesetOutput, error) { + err := cfg.Validate(e) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + state, err := LoadOnchainState(e) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) + } + deployerGroup := NewDeployerGroup(e, state, cfg.MCMS) + + // Generate curse actions + var curseActions []RMNCurseAction + for _, curseAction := range cfg.CurseActions { + curseActions = append(curseActions, curseAction(e)...) + } + // Group curse actions by chain selector + grouped := groupRMNSubjectBySelector(curseActions, false, false) + + // For each chain in the environement get the RMNRemote contract and call uncurse + for selector, chain := range state.Chains { + deployer, err := deployerGroup.GetDeployer(selector) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to get deployer for chain %d: %w", selector, err) + } + + if curseSubjects, ok := grouped[selector]; ok { + // Only keep the subject that are actually cursed + actuallyCursedSubjects := make([]Subject, 0) + for _, subject := range curseSubjects { + cursed, err := chain.RMNRemote.IsCursed(nil, subject) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to check if chain %d is cursed: %w", selector, err) + } + + if cursed { + actuallyCursedSubjects = append(actuallyCursedSubjects, subject) + } else { + e.Logger.Warnf("chain %s subject %x is not cursed, ignoring it while uncursing", e.Chains[selector].Name(), subject) + } + } + + if len(actuallyCursedSubjects) == 0 { + e.Logger.Infof("chain %s is not cursed with any of the subjects, skipping", e.Chains[selector].Name()) + continue + } + + _, err := chain.RMNRemote.Uncurse0(deployer, actuallyCursedSubjects) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to uncurse chain %d: %w", selector, err) + } + e.Logger.Infof("Uncursed chain %d with subjects %v", selector, actuallyCursedSubjects) + } + } + + return deployerGroup.Enact("proposal to uncurse RMNs: %s" + cfg.Reason) +} diff --git a/deployment/ccip/changeset/cs_rmn_curse_uncurse_test.go b/deployment/ccip/changeset/cs_rmn_curse_uncurse_test.go new file mode 100644 index 00000000000..7a043b36645 --- /dev/null +++ b/deployment/ccip/changeset/cs_rmn_curse_uncurse_test.go @@ -0,0 +1,383 @@ +package changeset_test + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" +) + +type curseAssertion struct { + chainID uint64 + subject uint64 + globalCurse bool + cursed bool +} + +type CurseTestCase struct { + name string + curseActionsBuilder func(mapIDToSelectorFunc) []changeset.CurseAction + curseAssertions []curseAssertion +} + +type mapIDToSelectorFunc func(uint64) uint64 + +var testCases = []CurseTestCase{ + { + name: "lane", + curseActionsBuilder: func(mapIDToSelector mapIDToSelectorFunc) []changeset.CurseAction { + return []changeset.CurseAction{changeset.CurseLaneBidirectionally(mapIDToSelector(0), mapIDToSelector(1))} + }, + curseAssertions: []curseAssertion{ + {chainID: 0, subject: 1, cursed: true}, + {chainID: 0, subject: 2, cursed: false}, + {chainID: 1, subject: 0, cursed: true}, + {chainID: 1, subject: 2, cursed: false}, + {chainID: 2, subject: 0, cursed: false}, + {chainID: 2, subject: 1, cursed: false}, + }, + }, + { + name: "lane duplicate", + curseActionsBuilder: func(mapIDToSelector mapIDToSelectorFunc) []changeset.CurseAction { + return []changeset.CurseAction{ + changeset.CurseLaneBidirectionally(mapIDToSelector(0), mapIDToSelector(1)), + changeset.CurseLaneBidirectionally(mapIDToSelector(0), mapIDToSelector(1))} + }, + curseAssertions: []curseAssertion{ + {chainID: 0, subject: 1, cursed: true}, + {chainID: 0, subject: 2, cursed: false}, + {chainID: 1, subject: 0, cursed: true}, + {chainID: 1, subject: 2, cursed: false}, + {chainID: 2, subject: 0, cursed: false}, + {chainID: 2, subject: 1, cursed: false}, + }, + }, + { + name: "chain", + curseActionsBuilder: func(mapIDToSelector mapIDToSelectorFunc) []changeset.CurseAction { + return []changeset.CurseAction{changeset.CurseChain(mapIDToSelector(0))} + }, + curseAssertions: []curseAssertion{ + {chainID: 0, globalCurse: true, cursed: true}, + {chainID: 1, subject: 0, cursed: true}, + {chainID: 1, subject: 2, cursed: false}, + {chainID: 2, subject: 0, cursed: true}, + {chainID: 2, subject: 1, cursed: false}, + }, + }, + { + name: "chain duplicate", + curseActionsBuilder: func(mapIDToSelector mapIDToSelectorFunc) []changeset.CurseAction { + return []changeset.CurseAction{changeset.CurseChain(mapIDToSelector(0)), changeset.CurseChain(mapIDToSelector(0))} + }, + curseAssertions: []curseAssertion{ + {chainID: 0, globalCurse: true, cursed: true}, + {chainID: 1, subject: 0, cursed: true}, + {chainID: 1, subject: 2, cursed: false}, + {chainID: 2, subject: 0, cursed: true}, + {chainID: 2, subject: 1, cursed: false}, + }, + }, + { + name: "chain and lanes", + curseActionsBuilder: func(mapIDToSelector mapIDToSelectorFunc) []changeset.CurseAction { + return []changeset.CurseAction{changeset.CurseChain(mapIDToSelector(0)), changeset.CurseLaneBidirectionally(mapIDToSelector(1), mapIDToSelector(2))} + }, + curseAssertions: []curseAssertion{ + {chainID: 0, globalCurse: true, cursed: true}, + {chainID: 1, subject: 0, cursed: true}, + {chainID: 1, subject: 2, cursed: true}, + {chainID: 2, subject: 0, cursed: true}, + {chainID: 2, subject: 1, cursed: true}, + }, + }, +} + +func TestRMNCurse(t *testing.T) { + for _, tc := range testCases { + t.Run(tc.name+"_NO_MCMS", func(t *testing.T) { + runRmnCurseTest(t, tc) + }) + t.Run(tc.name+"_MCMS", func(t *testing.T) { + runRmnCurseMCMSTest(t, tc) + }) + } +} + +func TestRMNCurseIdempotent(t *testing.T) { + for _, tc := range testCases { + t.Run(tc.name+"_CURSE_IDEMPOTENT_NO_MCMS", func(t *testing.T) { + runRmnCurseIdempotentTest(t, tc) + }) + } +} + +func TestRMNUncurseIdempotent(t *testing.T) { + for _, tc := range testCases { + t.Run(tc.name+"_UNCURESE_IDEMPOTENT_NO_MCMS", func(t *testing.T) { + runRmnUncurseIdempotentTest(t, tc) + }) + } +} + +func TestRMNUncurse(t *testing.T) { + for _, tc := range testCases { + t.Run(tc.name+"_UNCURSE", func(t *testing.T) { + runRmnUncurseTest(t, tc) + }) + t.Run(tc.name+"_UNCURSE_MCMS", func(t *testing.T) { + runRmnUncurseMCMSTest(t, tc) + }) + } +} + +func TestRMNCurseConfigValidate(t *testing.T) { + for _, tc := range testCases { + t.Run(tc.name+"_VALIDATE", func(t *testing.T) { + runRmnCurseConfigValidateTest(t, tc) + }) + } +} + +func runRmnUncurseTest(t *testing.T, tc CurseTestCase) { + e, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithNumOfChains(3)) + + mapIDToSelector := func(id uint64) uint64 { + return e.Env.AllChainSelectors()[id] + } + + verifyNoActiveCurseOnAllChains(t, &e) + + config := changeset.RMNCurseConfig{ + CurseActions: tc.curseActionsBuilder(mapIDToSelector), + Reason: "test curse", + } + + _, err := changeset.RMNCurseChangeset(e.Env, config) + require.NoError(t, err) + + verifyTestCaseAssertions(t, &e, tc, mapIDToSelector) + + _, err = changeset.RMNUncurseChangeset(e.Env, config) + require.NoError(t, err) + + verifyNoActiveCurseOnAllChains(t, &e) +} + +func transferRMNContractToMCMS(t *testing.T, e *testhelpers.DeployedEnv, state changeset.CCIPOnChainState, timelocksPerChain map[uint64]*proposalutils.TimelockExecutionContracts) { + contractsByChain := make(map[uint64][]common.Address) + rmnRemoteAddressesByChain := buildRMNRemoteAddressPerChain(e.Env, state) + for chainSelector, rmnRemoteAddress := range rmnRemoteAddressesByChain { + contractsByChain[chainSelector] = []common.Address{rmnRemoteAddress} + } + + contractsByChain[e.HomeChainSel] = append(contractsByChain[e.HomeChainSel], state.Chains[e.HomeChainSel].RMNHome.Address()) + + // This is required because RMN Contracts is initially owned by the deployer + _, err := commonchangeset.ApplyChangesets(t, e.Env, timelocksPerChain, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.TransferToMCMSWithTimelock), + Config: commonchangeset.TransferToMCMSWithTimelockConfig{ + ContractsByChain: contractsByChain, + MinDelay: 0, + }, + }, + }) + require.NoError(t, err) +} + +func runRmnUncurseMCMSTest(t *testing.T, tc CurseTestCase) { + e, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithNumOfChains(3)) + + mapIDToSelector := func(id uint64) uint64 { + return e.Env.AllChainSelectors()[id] + } + + config := changeset.RMNCurseConfig{ + CurseActions: tc.curseActionsBuilder(mapIDToSelector), + Reason: "test curse", + MCMS: &changeset.MCMSConfig{MinDelay: 0}, + } + + state, err := changeset.LoadOnchainState(e.Env) + require.NoError(t, err) + + verifyNoActiveCurseOnAllChains(t, &e) + + timelocksPerChain := changeset.BuildTimelockPerChain(e.Env, state) + + transferRMNContractToMCMS(t, &e, state, timelocksPerChain) + + _, err = commonchangeset.ApplyChangesets(t, e.Env, timelocksPerChain, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(changeset.RMNCurseChangeset), + Config: config, + }, + }) + require.NoError(t, err) + + verifyTestCaseAssertions(t, &e, tc, mapIDToSelector) + + _, err = commonchangeset.ApplyChangesets(t, e.Env, timelocksPerChain, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(changeset.RMNUncurseChangeset), + Config: config, + }, + }) + require.NoError(t, err) + + verifyNoActiveCurseOnAllChains(t, &e) +} + +func runRmnCurseConfigValidateTest(t *testing.T, tc CurseTestCase) { + e, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithNumOfChains(3)) + + mapIDToSelector := func(id uint64) uint64 { + return e.Env.AllChainSelectors()[id] + } + + config := changeset.RMNCurseConfig{ + CurseActions: tc.curseActionsBuilder(mapIDToSelector), + Reason: "test curse", + } + + err := config.Validate(e.Env) + require.NoError(t, err) +} + +func runRmnCurseTest(t *testing.T, tc CurseTestCase) { + e, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithNumOfChains(3)) + + mapIDToSelector := func(id uint64) uint64 { + return e.Env.AllChainSelectors()[id] + } + + verifyNoActiveCurseOnAllChains(t, &e) + + config := changeset.RMNCurseConfig{ + CurseActions: tc.curseActionsBuilder(mapIDToSelector), + Reason: "test curse", + } + + _, err := changeset.RMNCurseChangeset(e.Env, config) + require.NoError(t, err) + + verifyTestCaseAssertions(t, &e, tc, mapIDToSelector) +} + +func runRmnCurseIdempotentTest(t *testing.T, tc CurseTestCase) { + e, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithNumOfChains(3)) + + mapIDToSelector := func(id uint64) uint64 { + return e.Env.AllChainSelectors()[id] + } + + verifyNoActiveCurseOnAllChains(t, &e) + + config := changeset.RMNCurseConfig{ + CurseActions: tc.curseActionsBuilder(mapIDToSelector), + Reason: "test curse", + } + + _, err := changeset.RMNCurseChangeset(e.Env, config) + require.NoError(t, err) + + _, err = changeset.RMNCurseChangeset(e.Env, config) + require.NoError(t, err) + + verifyTestCaseAssertions(t, &e, tc, mapIDToSelector) +} + +func runRmnUncurseIdempotentTest(t *testing.T, tc CurseTestCase) { + e, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithNumOfChains(3)) + + mapIDToSelector := func(id uint64) uint64 { + return e.Env.AllChainSelectors()[id] + } + + verifyNoActiveCurseOnAllChains(t, &e) + + config := changeset.RMNCurseConfig{ + CurseActions: tc.curseActionsBuilder(mapIDToSelector), + Reason: "test curse", + } + + _, err := changeset.RMNCurseChangeset(e.Env, config) + require.NoError(t, err) + + verifyTestCaseAssertions(t, &e, tc, mapIDToSelector) + + _, err = changeset.RMNUncurseChangeset(e.Env, config) + require.NoError(t, err) + + _, err = changeset.RMNUncurseChangeset(e.Env, config) + require.NoError(t, err) + + verifyNoActiveCurseOnAllChains(t, &e) +} + +func runRmnCurseMCMSTest(t *testing.T, tc CurseTestCase) { + e, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithNumOfChains(3)) + + mapIDToSelector := func(id uint64) uint64 { + return e.Env.AllChainSelectors()[id] + } + + config := changeset.RMNCurseConfig{ + CurseActions: tc.curseActionsBuilder(mapIDToSelector), + Reason: "test curse", + MCMS: &changeset.MCMSConfig{MinDelay: 0}, + } + + state, err := changeset.LoadOnchainState(e.Env) + require.NoError(t, err) + + verifyNoActiveCurseOnAllChains(t, &e) + + timelocksPerChain := changeset.BuildTimelockPerChain(e.Env, state) + + transferRMNContractToMCMS(t, &e, state, timelocksPerChain) + + _, err = commonchangeset.ApplyChangesets(t, e.Env, timelocksPerChain, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(changeset.RMNCurseChangeset), + Config: config, + }, + }) + require.NoError(t, err) + + verifyTestCaseAssertions(t, &e, tc, mapIDToSelector) +} + +func verifyTestCaseAssertions(t *testing.T, e *testhelpers.DeployedEnv, tc CurseTestCase, mapIDToSelector mapIDToSelectorFunc) { + state, err := changeset.LoadOnchainState(e.Env) + require.NoError(t, err) + + for _, assertion := range tc.curseAssertions { + cursedSubject := changeset.SelectorToSubject(mapIDToSelector(assertion.subject)) + if assertion.globalCurse { + cursedSubject = changeset.GlobalCurseSubject() + } + + isCursed, err := state.Chains[mapIDToSelector(assertion.chainID)].RMNRemote.IsCursed(nil, cursedSubject) + require.NoError(t, err) + require.Equal(t, assertion.cursed, isCursed, "chain %d subject %d", assertion.chainID, assertion.subject) + } +} + +func verifyNoActiveCurseOnAllChains(t *testing.T, e *testhelpers.DeployedEnv) { + state, err := changeset.LoadOnchainState(e.Env) + require.NoError(t, err) + + for _, chain := range e.Env.Chains { + isCursed, err := state.Chains[chain.Selector].RMNRemote.IsCursed0(nil) + require.NoError(t, err) + require.False(t, isCursed, "chain %d", chain.Selector) + } +} diff --git a/deployment/ccip/changeset/cs_update_rmn_config.go b/deployment/ccip/changeset/cs_update_rmn_config.go index 96f8eacb4cc..e220ca50998 100644 --- a/deployment/ccip/changeset/cs_update_rmn_config.go +++ b/deployment/ccip/changeset/cs_update_rmn_config.go @@ -1,6 +1,7 @@ package changeset import ( + "errors" "fmt" "math/big" "reflect" @@ -8,7 +9,6 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" @@ -19,6 +19,13 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) +var ( + _ deployment.ChangeSet[SetRMNRemoteOnRMNProxyConfig] = SetRMNRemoteOnRMNProxyChangeset + _ deployment.ChangeSet[SetRMNHomeCandidateConfig] = SetRMNHomeCandidateConfigChangeset + _ deployment.ChangeSet[PromoteRMNHomeCandidateConfig] = PromoteRMNHomeCandidateConfigChangeset + _ deployment.ChangeSet[SetRMNRemoteConfig] = SetRMNRemoteConfigChangeset +) + type SetRMNRemoteOnRMNProxyConfig struct { ChainSelectors []uint64 MCMSConfig *MCMSConfig @@ -44,7 +51,7 @@ func (c SetRMNRemoteOnRMNProxyConfig) Validate(state CCIPOnChainState) error { return nil } -func SetRMNRemoteOnRMNProxy(e deployment.Environment, cfg SetRMNRemoteOnRMNProxyConfig) (deployment.ChangesetOutput, error) { +func SetRMNRemoteOnRMNProxyChangeset(e deployment.Environment, cfg SetRMNRemoteOnRMNProxyConfig) (deployment.ChangesetOutput, error) { state, err := LoadOnchainState(e) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) @@ -178,14 +185,14 @@ func (c SetRMNHomeCandidateConfig) Validate(state CCIPOnChainState) error { } if len(c.RMNDynamicConfig.OffchainConfig) != 0 { - return fmt.Errorf("RMNDynamicConfig.OffchainConfig must be empty") + return errors.New("RMNDynamicConfig.OffchainConfig must be empty") } if len(c.RMNStaticConfig.OffchainConfig) != 0 { - return fmt.Errorf("RMNStaticConfig.OffchainConfig must be empty") + return errors.New("RMNStaticConfig.OffchainConfig must be empty") } if len(c.RMNStaticConfig.Nodes) > 256 { - return fmt.Errorf("RMNStaticConfig.Nodes must be less than 256") + return errors.New("RMNStaticConfig.Nodes must be less than 256") } var ( @@ -251,12 +258,12 @@ func (c PromoteRMNHomeCandidateConfig) Validate(state CCIPOnChainState) error { return nil } -// NewSetRMNHomeCandidateConfigChangeset creates a changeset to set the RMNHome candidate config +// SetRMNHomeCandidateConfigChangeset creates a changeset to set the RMNHome candidate config // DigestToOverride is the digest of the current candidate config that the new config will override // StaticConfig contains the list of nodes with their peerIDs (found in their rageproxy keystore) and offchain public keys (found in the RMN keystore) // DynamicConfig contains the list of source chains with their chain selectors, f value and the bitmap of the nodes that are oberver for each source chain // The bitmap is a 256 bit array where each bit represents a node. If the bit matching the index of the node in the static config is set it means that the node is an observer -func NewSetRMNHomeCandidateConfigChangeset(e deployment.Environment, config SetRMNHomeCandidateConfig) (deployment.ChangesetOutput, error) { +func SetRMNHomeCandidateConfigChangeset(e deployment.Environment, config SetRMNHomeCandidateConfig) (deployment.ChangesetOutput, error) { state, err := LoadOnchainState(e) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) @@ -307,9 +314,9 @@ func NewSetRMNHomeCandidateConfigChangeset(e deployment.Environment, config SetR }, } - timelocksPerChain := buildTimelockAddressPerChain(e, state) + timelocksPerChain := BuildTimelockAddressPerChain(e, state) - proposerMCMSes := buildProposerPerChain(e, state) + proposerMCMSes := BuildProposerPerChain(e, state) prop, err := proposalutils.BuildProposalFromBatches( timelocksPerChain, @@ -324,7 +331,7 @@ func NewSetRMNHomeCandidateConfigChangeset(e deployment.Environment, config SetR }, nil } -func NewPromoteCandidateConfigChangeset(e deployment.Environment, config PromoteRMNHomeCandidateConfig) (deployment.ChangesetOutput, error) { +func PromoteRMNHomeCandidateConfigChangeset(e deployment.Environment, config PromoteRMNHomeCandidateConfig) (deployment.ChangesetOutput, error) { state, err := LoadOnchainState(e) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) @@ -386,9 +393,9 @@ func NewPromoteCandidateConfigChangeset(e deployment.Environment, config Promote }, } - timelocksPerChain := buildTimelockAddressPerChain(e, state) + timelocksPerChain := BuildTimelockAddressPerChain(e, state) - proposerMCMSes := buildProposerPerChain(e, state) + proposerMCMSes := BuildProposerPerChain(e, state) prop, err := proposalutils.BuildProposalFromBatches( timelocksPerChain, @@ -407,35 +414,7 @@ func NewPromoteCandidateConfigChangeset(e deployment.Environment, config Promote }, nil } -func buildTimelockPerChain(e deployment.Environment, state CCIPOnChainState) map[uint64]*proposalutils.TimelockExecutionContracts { - timelocksPerChain := make(map[uint64]*proposalutils.TimelockExecutionContracts) - for _, chain := range e.Chains { - timelocksPerChain[chain.Selector] = &proposalutils.TimelockExecutionContracts{ - Timelock: state.Chains[chain.Selector].Timelock, - CallProxy: state.Chains[chain.Selector].CallProxy, - } - } - return timelocksPerChain -} - -func buildTimelockAddressPerChain(e deployment.Environment, state CCIPOnChainState) map[uint64]common.Address { - timelocksPerChain := buildTimelockPerChain(e, state) - timelockAddressPerChain := make(map[uint64]common.Address) - for chain, timelock := range timelocksPerChain { - timelockAddressPerChain[chain] = timelock.Timelock.Address() - } - return timelockAddressPerChain -} - -func buildProposerPerChain(e deployment.Environment, state CCIPOnChainState) map[uint64]*gethwrappers.ManyChainMultiSig { - proposerPerChain := make(map[uint64]*gethwrappers.ManyChainMultiSig) - for _, chain := range e.Chains { - proposerPerChain[chain.Selector] = state.Chains[chain.Selector].ProposerMcm - } - return proposerPerChain -} - -func buildRMNRemotePerChain(e deployment.Environment, state CCIPOnChainState) map[uint64]*rmn_remote.RMNRemote { +func BuildRMNRemotePerChain(e deployment.Environment, state CCIPOnChainState) map[uint64]*rmn_remote.RMNRemote { timelocksPerChain := make(map[uint64]*rmn_remote.RMNRemote) for _, chain := range e.Chains { timelocksPerChain[chain.Selector] = state.Chains[chain.Selector].RMNRemote @@ -480,7 +459,7 @@ func (c SetRMNRemoteConfig) Validate() error { return nil } -func NewSetRMNRemoteConfigChangeset(e deployment.Environment, config SetRMNRemoteConfig) (deployment.ChangesetOutput, error) { +func SetRMNRemoteConfigChangeset(e deployment.Environment, config SetRMNRemoteConfig) (deployment.ChangesetOutput, error) { state, err := LoadOnchainState(e) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) @@ -509,7 +488,7 @@ func NewSetRMNRemoteConfigChangeset(e deployment.Environment, config SetRMNRemot return deployment.ChangesetOutput{}, fmt.Errorf("failed to get RMNHome active digest for chain %s: %w", homeChain.String(), err) } - rmnRemotePerChain := buildRMNRemotePerChain(e, state) + rmnRemotePerChain := BuildRMNRemotePerChain(e, state) batches := make([]timelock.BatchChainOperation, 0) for chain, remoteConfig := range config.RMNRemoteConfigs { remote, ok := rmnRemotePerChain[chain] @@ -525,7 +504,7 @@ func NewSetRMNRemoteConfigChangeset(e deployment.Environment, config SetRMNRemot newConfig := rmn_remote.RMNRemoteConfig{ RmnHomeContractConfigDigest: activeConfig, Signers: remoteConfig.Signers, - F: remoteConfig.F, + FSign: remoteConfig.F, } if reflect.DeepEqual(currentVersionConfig.Config, newConfig) { @@ -566,9 +545,9 @@ func NewSetRMNRemoteConfigChangeset(e deployment.Environment, config SetRMNRemot return deployment.ChangesetOutput{}, nil } - timelocksPerChain := buildTimelockAddressPerChain(e, state) + timelocksPerChain := BuildTimelockAddressPerChain(e, state) - proposerMCMSes := buildProposerPerChain(e, state) + proposerMCMSes := BuildProposerPerChain(e, state) prop, err := proposalutils.BuildProposalFromBatches( timelocksPerChain, diff --git a/deployment/ccip/changeset/cs_update_rmn_config_test.go b/deployment/ccip/changeset/cs_update_rmn_config_test.go index 07bf22720c2..1db80197b15 100644 --- a/deployment/ccip/changeset/cs_update_rmn_config_test.go +++ b/deployment/ccip/changeset/cs_update_rmn_config_test.go @@ -1,4 +1,4 @@ -package changeset +package changeset_test import ( "testing" @@ -7,6 +7,8 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" @@ -15,19 +17,19 @@ import ( ) var ( - rmn_staging_1 = RMNNopConfig{ + rmnStaging1 = changeset.RMNNopConfig{ NodeIndex: 0, PeerId: deployment.MustPeerIDFromString("p2p_12D3KooWRXxZq3pd4a3ZGkKj7Nt1SQQrnB8CuvbPnnV9KVeMeWqg"), OffchainPublicKey: [32]byte(common.FromHex("0xb34944857a42444d1b285d7940d6e06682309e0781e43a69676ee9f85c73c2d1")), EVMOnChainPublicKey: common.HexToAddress("0x5af8ee32316a6427f169a45fdc1b3a91a85ac459e3c1cb91c69e1c51f0c1fc21"), } - rmn_staging_2 = RMNNopConfig{ + rmnStaging2 = changeset.RMNNopConfig{ NodeIndex: 1, PeerId: deployment.MustPeerIDFromString("p2p_12D3KooWEmdxYQFsRbD9aFczF32zA3CcUwuSiWCk2CrmACo4v9RL"), OffchainPublicKey: [32]byte(common.FromHex("0x68d9f3f274e3985528a923a9bace3d39c55dd778b187b4120b384cc48c892859")), EVMOnChainPublicKey: common.HexToAddress("0x858589216956f482a0f68b282a7050af4cd48ed2"), } - rmn_staging_3 = RMNNopConfig{ + rmnStaging3 = changeset.RMNNopConfig{ NodeIndex: 2, PeerId: deployment.MustPeerIDFromString("p2p_12D3KooWJS42cNXKJvj6DeZnxEX7aGxhEuap6uNFrz554AbUDw6Q"), OffchainPublicKey: [32]byte(common.FromHex("0x5af8ee32316a6427f169a45fdc1b3a91a85ac459e3c1cb91c69e1c51f0c1fc21")), @@ -38,7 +40,7 @@ var ( type updateRMNConfigTestCase struct { useMCMS bool name string - nops []RMNNopConfig + nops []changeset.RMNNopConfig } func TestUpdateRMNConfig(t *testing.T) { @@ -47,12 +49,12 @@ func TestUpdateRMNConfig(t *testing.T) { { useMCMS: true, name: "with MCMS", - nops: []RMNNopConfig{rmn_staging_1, rmn_staging_2, rmn_staging_3}, + nops: []changeset.RMNNopConfig{rmnStaging1, rmnStaging2, rmnStaging3}, }, { useMCMS: false, name: "without MCMS", - nops: []RMNNopConfig{rmn_staging_1, rmn_staging_2, rmn_staging_3}, + nops: []changeset.RMNNopConfig{rmnStaging1, rmnStaging2, rmnStaging3}, }, } @@ -65,9 +67,9 @@ func TestUpdateRMNConfig(t *testing.T) { } func updateRMNConfig(t *testing.T, tc updateRMNConfigTestCase) { - e := NewMemoryEnvironment(t) + e, _ := testhelpers.NewMemoryEnvironment(t) - state, err := LoadOnchainState(e.Env) + state, err := changeset.LoadOnchainState(e.Env) require.NoError(t, err) contractsByChain := make(map[uint64][]common.Address) @@ -78,7 +80,7 @@ func updateRMNConfig(t *testing.T, tc updateRMNConfigTestCase) { contractsByChain[e.HomeChainSel] = append(contractsByChain[e.HomeChainSel], state.Chains[e.HomeChainSel].RMNHome.Address()) - timelocksPerChain := buildTimelockPerChain(e.Env, state) + timelocksPerChain := changeset.BuildTimelockPerChain(e.Env, state) if tc.useMCMS { // This is required because RMNHome is initially owned by the deployer _, err = commonchangeset.ApplyChangesets(t, e.Env, timelocksPerChain, []commonchangeset.ChangesetApplication{ @@ -99,10 +101,10 @@ func updateRMNConfig(t *testing.T, tc updateRMNConfigTestCase) { previousActiveDigest, err := rmnHome.GetActiveDigest(nil) require.NoError(t, err) - var mcmsConfig *MCMSConfig = nil + var mcmsConfig *changeset.MCMSConfig if tc.useMCMS { - mcmsConfig = &MCMSConfig{ + mcmsConfig = &changeset.MCMSConfig{ MinDelay: 0, } } @@ -112,7 +114,7 @@ func updateRMNConfig(t *testing.T, tc updateRMNConfigTestCase) { nodes = append(nodes, nop.ToRMNHomeNode()) } - setRMNHomeCandidateConfig := SetRMNHomeCandidateConfig{ + setRMNHomeCandidateConfig := changeset.SetRMNHomeCandidateConfig{ HomeChainSelector: e.HomeChainSel, RMNStaticConfig: rmn_home.RMNHomeStaticConfig{ Nodes: nodes, @@ -127,14 +129,14 @@ func updateRMNConfig(t *testing.T, tc updateRMNConfigTestCase) { _, err = commonchangeset.ApplyChangesets(t, e.Env, timelocksPerChain, []commonchangeset.ChangesetApplication{ { - Changeset: commonchangeset.WrapChangeSet(NewSetRMNHomeCandidateConfigChangeset), + Changeset: commonchangeset.WrapChangeSet(changeset.SetRMNHomeCandidateConfigChangeset), Config: setRMNHomeCandidateConfig, }, }) require.NoError(t, err) - state, err = LoadOnchainState(e.Env) + state, err = changeset.LoadOnchainState(e.Env) require.NoError(t, err) currentCandidateDigest, err := rmnHome.GetCandidateDigest(nil) @@ -145,7 +147,7 @@ func updateRMNConfig(t *testing.T, tc updateRMNConfigTestCase) { require.NotEqual(t, previousCandidateDigest, currentCandidateDigest) require.Equal(t, previousActiveDigest, currentActiveDigest) - promoteConfig := PromoteRMNHomeCandidateConfig{ + promoteConfig := changeset.PromoteRMNHomeCandidateConfig{ HomeChainSelector: e.HomeChainSel, DigestToPromote: currentCandidateDigest, MCMSConfig: mcmsConfig, @@ -153,7 +155,7 @@ func updateRMNConfig(t *testing.T, tc updateRMNConfigTestCase) { _, err = commonchangeset.ApplyChangesets(t, e.Env, timelocksPerChain, []commonchangeset.ChangesetApplication{ { - Changeset: commonchangeset.WrapChangeSet(NewPromoteCandidateConfigChangeset), + Changeset: commonchangeset.WrapChangeSet(changeset.PromoteRMNHomeCandidateConfigChangeset), Config: promoteConfig, }, }) @@ -169,9 +171,9 @@ func updateRMNConfig(t *testing.T, tc updateRMNConfigTestCase) { signers = append(signers, nop.ToRMNRemoteSigner()) } - remoteConfigs := make(map[uint64]RMNRemoteConfig, len(e.Env.Chains)) + remoteConfigs := make(map[uint64]changeset.RMNRemoteConfig, len(e.Env.Chains)) for _, chain := range e.Env.Chains { - remoteConfig := RMNRemoteConfig{ + remoteConfig := changeset.RMNRemoteConfig{ Signers: signers, F: 0, } @@ -179,7 +181,7 @@ func updateRMNConfig(t *testing.T, tc updateRMNConfigTestCase) { remoteConfigs[chain.Selector] = remoteConfig } - setRemoteConfig := SetRMNRemoteConfig{ + setRemoteConfig := changeset.SetRMNRemoteConfig{ HomeChainSelector: e.HomeChainSel, RMNRemoteConfigs: remoteConfigs, MCMSConfig: mcmsConfig, @@ -187,13 +189,13 @@ func updateRMNConfig(t *testing.T, tc updateRMNConfigTestCase) { _, err = commonchangeset.ApplyChangesets(t, e.Env, timelocksPerChain, []commonchangeset.ChangesetApplication{ { - Changeset: commonchangeset.WrapChangeSet(NewSetRMNRemoteConfigChangeset), + Changeset: commonchangeset.WrapChangeSet(changeset.SetRMNRemoteConfigChangeset), Config: setRemoteConfig, }, }) require.NoError(t, err) - rmnRemotePerChain := buildRMNRemotePerChain(e.Env, state) + rmnRemotePerChain := changeset.BuildRMNRemotePerChain(e.Env, state) for _, rmnRemote := range rmnRemotePerChain { remoteConfigSetEvents, err := rmnRemote.FilterConfigSet(nil, nil) require.NoError(t, err) @@ -206,8 +208,8 @@ func updateRMNConfig(t *testing.T, tc updateRMNConfigTestCase) { } } -func buildRMNRemoteAddressPerChain(e deployment.Environment, state CCIPOnChainState) map[uint64]common.Address { - rmnRemotePerChain := buildRMNRemotePerChain(e, state) +func buildRMNRemoteAddressPerChain(e deployment.Environment, state changeset.CCIPOnChainState) map[uint64]common.Address { + rmnRemotePerChain := changeset.BuildRMNRemotePerChain(e, state) rmnRemoteAddressPerChain := make(map[uint64]common.Address) for chain, remote := range rmnRemotePerChain { if remote == nil { @@ -220,12 +222,16 @@ func buildRMNRemoteAddressPerChain(e deployment.Environment, state CCIPOnChainSt func TestSetRMNRemoteOnRMNProxy(t *testing.T) { t.Parallel() - e := NewMemoryEnvironment(t, WithNoJobsAndContracts()) + e, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithNoJobsAndContracts()) allChains := e.Env.AllChainSelectors() mcmsCfg := make(map[uint64]commontypes.MCMSWithTimelockConfig) var err error + prereqCfgs := make([]changeset.DeployPrerequisiteConfigPerChain, 0) for _, c := range e.Env.AllChainSelectors() { mcmsCfg[c] = proposalutils.SingleGroupTimelockConfig(t) + prereqCfgs = append(prereqCfgs, changeset.DeployPrerequisiteConfigPerChain{ + ChainSelector: c, + }) } // Need to deploy prerequisites first so that we can form the USDC config // no proposals to be made, timelock can be passed as nil here @@ -235,9 +241,9 @@ func TestSetRMNRemoteOnRMNProxy(t *testing.T) { Config: allChains, }, { - Changeset: commonchangeset.WrapChangeSet(DeployPrerequisites), - Config: DeployPrerequisiteConfig{ - ChainSelectors: allChains, + Changeset: commonchangeset.WrapChangeSet(changeset.DeployPrerequisitesChangeset), + Config: changeset.DeployPrerequisiteConfig{ + Configs: prereqCfgs, }, }, { @@ -247,7 +253,7 @@ func TestSetRMNRemoteOnRMNProxy(t *testing.T) { }) require.NoError(t, err) contractsByChain := make(map[uint64][]common.Address) - state, err := LoadOnchainState(e.Env) + state, err := changeset.LoadOnchainState(e.Env) require.NoError(t, err) for _, chain := range allChains { rmnProxy := state.Chains[chain].RMNProxy @@ -261,6 +267,8 @@ func TestSetRMNRemoteOnRMNProxy(t *testing.T) { CallProxy: state.Chains[chain].CallProxy, } } + envNodes, err := deployment.NodeInfo(e.Env.NodeIDs, e.Env.Offchain) + require.NoError(t, err) e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, timelockContractsPerChain, []commonchangeset.ChangesetApplication{ // transfer ownership of RMNProxy to timelock { @@ -270,25 +278,38 @@ func TestSetRMNRemoteOnRMNProxy(t *testing.T) { MinDelay: 0, }, }, + + { + Changeset: commonchangeset.WrapChangeSet(changeset.DeployHomeChainChangeset), + Config: changeset.DeployHomeChainConfig{ + HomeChainSel: e.HomeChainSel, + RMNDynamicConfig: testhelpers.NewTestRMNDynamicConfig(), + RMNStaticConfig: testhelpers.NewTestRMNStaticConfig(), + NodeOperators: testhelpers.NewTestNodeOperator(e.Env.Chains[e.HomeChainSel].DeployerKey.From), + NodeP2PIDsPerNodeOpAdmin: map[string][][32]byte{ + "NodeOperator": envNodes.NonBootstraps().PeerIDs(), + }, + }, + }, { - Changeset: commonchangeset.WrapChangeSet(DeployChainContracts), - Config: DeployChainContractsConfig{ + Changeset: commonchangeset.WrapChangeSet(changeset.DeployChainContractsChangeset), + Config: changeset.DeployChainContractsConfig{ ChainSelectors: allChains, HomeChainSelector: e.HomeChainSel, }, }, { - Changeset: commonchangeset.WrapChangeSet(SetRMNRemoteOnRMNProxy), - Config: SetRMNRemoteOnRMNProxyConfig{ + Changeset: commonchangeset.WrapChangeSet(changeset.SetRMNRemoteOnRMNProxyChangeset), + Config: changeset.SetRMNRemoteOnRMNProxyConfig{ ChainSelectors: allChains, - MCMSConfig: &MCMSConfig{ + MCMSConfig: &changeset.MCMSConfig{ MinDelay: 0, }, }, }, }) require.NoError(t, err) - state, err = LoadOnchainState(e.Env) + state, err = changeset.LoadOnchainState(e.Env) require.NoError(t, err) for _, chain := range allChains { rmnProxy := state.Chains[chain].RMNProxy diff --git a/deployment/ccip/changeset/deployer_group.go b/deployment/ccip/changeset/deployer_group.go new file mode 100644 index 00000000000..5f7c7e52da2 --- /dev/null +++ b/deployment/ccip/changeset/deployer_group.go @@ -0,0 +1,194 @@ +package changeset + +import ( + "context" + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" +) + +type DeployerGroup struct { + e deployment.Environment + state CCIPOnChainState + mcmConfig *MCMSConfig + transactions map[uint64][]*types.Transaction +} + +// DeployerGroup is an abstraction that lets developers write their changeset +// without needing to know if it's executed using a DeployerKey or an MCMS proposal. +// +// Example usage: +// +// deployerGroup := NewDeployerGroup(e, state, mcmConfig) +// selector := 0 +// # Get the right deployer key for the chain +// deployer := deployerGroup.GetDeployer(selector) +// state.Chains[selector].RMNRemote.Curse() +// # Execute the transaction or create the proposal +// deployerGroup.Enact("Curse RMNRemote") +func NewDeployerGroup(e deployment.Environment, state CCIPOnChainState, mcmConfig *MCMSConfig) *DeployerGroup { + return &DeployerGroup{ + e: e, + mcmConfig: mcmConfig, + state: state, + transactions: make(map[uint64][]*types.Transaction), + } +} + +func (d *DeployerGroup) GetDeployer(chain uint64) (*bind.TransactOpts, error) { + txOpts := d.e.Chains[chain].DeployerKey + if d.mcmConfig != nil { + txOpts = deployment.SimTransactOpts() + txOpts = &bind.TransactOpts{ + From: d.state.Chains[chain].Timelock.Address(), + Signer: txOpts.Signer, + GasLimit: txOpts.GasLimit, + GasPrice: txOpts.GasPrice, + Nonce: txOpts.Nonce, + Value: txOpts.Value, + GasFeeCap: txOpts.GasFeeCap, + GasTipCap: txOpts.GasTipCap, + Context: txOpts.Context, + AccessList: txOpts.AccessList, + NoSend: txOpts.NoSend, + } + } + sim := &bind.TransactOpts{ + From: txOpts.From, + Signer: txOpts.Signer, + GasLimit: txOpts.GasLimit, + GasPrice: txOpts.GasPrice, + Nonce: txOpts.Nonce, + Value: txOpts.Value, + GasFeeCap: txOpts.GasFeeCap, + GasTipCap: txOpts.GasTipCap, + Context: txOpts.Context, + AccessList: txOpts.AccessList, + NoSend: true, + } + oldSigner := sim.Signer + + var startingNonce *big.Int + if txOpts.Nonce != nil { + startingNonce = new(big.Int).Set(txOpts.Nonce) + } else { + nonce, err := d.e.Chains[chain].Client.PendingNonceAt(context.Background(), txOpts.From) + if err != nil { + return nil, fmt.Errorf("could not get nonce for deployer: %w", err) + } + startingNonce = new(big.Int).SetUint64(nonce) + } + + sim.Signer = func(a common.Address, t *types.Transaction) (*types.Transaction, error) { + // Update the nonce to consider the transactions that have been sent + sim.Nonce = big.NewInt(0).Add(startingNonce, big.NewInt(int64(len(d.transactions[chain]))+1)) + + tx, err := oldSigner(a, t) + if err != nil { + return nil, err + } + d.transactions[chain] = append(d.transactions[chain], tx) + return tx, nil + } + return sim, nil +} + +func (d *DeployerGroup) Enact(deploymentDescription string) (deployment.ChangesetOutput, error) { + if d.mcmConfig != nil { + return d.enactMcms(deploymentDescription) + } + + return d.enactDeployer() +} + +func (d *DeployerGroup) enactMcms(deploymentDescription string) (deployment.ChangesetOutput, error) { + batches := make([]timelock.BatchChainOperation, 0) + for selector, txs := range d.transactions { + mcmOps := make([]mcms.Operation, len(txs)) + for i, tx := range txs { + mcmOps[i] = mcms.Operation{ + To: *tx.To(), + Data: tx.Data(), + Value: tx.Value(), + } + } + batches = append(batches, timelock.BatchChainOperation{ + ChainIdentifier: mcms.ChainIdentifier(selector), + Batch: mcmOps, + }) + } + + timelocksPerChain := BuildTimelockAddressPerChain(d.e, d.state) + + proposerMCMSes := BuildProposerPerChain(d.e, d.state) + + prop, err := proposalutils.BuildProposalFromBatches( + timelocksPerChain, + proposerMCMSes, + batches, + deploymentDescription, + d.mcmConfig.MinDelay, + ) + + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to build proposal %w", err) + } + + return deployment.ChangesetOutput{ + Proposals: []timelock.MCMSWithTimelockProposal{*prop}, + }, nil +} + +func (d *DeployerGroup) enactDeployer() (deployment.ChangesetOutput, error) { + for selector, txs := range d.transactions { + for _, tx := range txs { + err := d.e.Chains[selector].Client.SendTransaction(context.Background(), tx) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to send transaction: %w", err) + } + + _, err = d.e.Chains[selector].Confirm(tx) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("waiting for tx to be mined failed: %w", err) + } + } + } + return deployment.ChangesetOutput{}, nil +} + +func BuildTimelockPerChain(e deployment.Environment, state CCIPOnChainState) map[uint64]*proposalutils.TimelockExecutionContracts { + timelocksPerChain := make(map[uint64]*proposalutils.TimelockExecutionContracts) + for _, chain := range e.Chains { + timelocksPerChain[chain.Selector] = &proposalutils.TimelockExecutionContracts{ + Timelock: state.Chains[chain.Selector].Timelock, + CallProxy: state.Chains[chain.Selector].CallProxy, + } + } + return timelocksPerChain +} + +func BuildTimelockAddressPerChain(e deployment.Environment, state CCIPOnChainState) map[uint64]common.Address { + timelocksPerChain := BuildTimelockPerChain(e, state) + timelockAddressPerChain := make(map[uint64]common.Address) + for chain, timelock := range timelocksPerChain { + timelockAddressPerChain[chain] = timelock.Timelock.Address() + } + return timelockAddressPerChain +} + +func BuildProposerPerChain(e deployment.Environment, state CCIPOnChainState) map[uint64]*gethwrappers.ManyChainMultiSig { + proposerPerChain := make(map[uint64]*gethwrappers.ManyChainMultiSig) + for _, chain := range e.Chains { + proposerPerChain[chain.Selector] = state.Chains[chain.Selector].ProposerMcm + } + return proposerPerChain +} diff --git a/deployment/ccip/changeset/deployer_group_test.go b/deployment/ccip/changeset/deployer_group_test.go new file mode 100644 index 00000000000..ba598ec74e8 --- /dev/null +++ b/deployment/ccip/changeset/deployer_group_test.go @@ -0,0 +1,193 @@ +package changeset_test + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" +) + +type dummyDeployerGroupChangesetConfig struct { + selector uint64 + address common.Address + mints []*big.Int + MCMS *changeset.MCMSConfig +} + +func dummyDeployerGroupGrantMintChangeset(e deployment.Environment, cfg dummyDeployerGroupChangesetConfig) (deployment.ChangesetOutput, error) { + state, err := changeset.LoadOnchainState(e) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + token := state.Chains[cfg.selector].LinkToken + + group := changeset.NewDeployerGroup(e, state, cfg.MCMS) + deployer, err := group.GetDeployer(cfg.selector) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + _, err = token.GrantMintRole(deployer, deployer.From) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + return group.Enact("Grant mint role") +} + +func dummyDeployerGroupMintChangeset(e deployment.Environment, cfg dummyDeployerGroupChangesetConfig) (deployment.ChangesetOutput, error) { + state, err := changeset.LoadOnchainState(e) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + token := state.Chains[cfg.selector].LinkToken + + group := changeset.NewDeployerGroup(e, state, cfg.MCMS) + deployer, err := group.GetDeployer(cfg.selector) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + for _, mint := range cfg.mints { + _, err = token.Mint(deployer, cfg.address, mint) + if err != nil { + return deployment.ChangesetOutput{}, err + } + } + + return group.Enact("Mint tokens") +} + +type deployerGroupTestCase struct { + name string + cfg dummyDeployerGroupChangesetConfig + expectError bool +} + +var deployerGroupTestCases = []deployerGroupTestCase{ + { + name: "happy path", + cfg: dummyDeployerGroupChangesetConfig{ + mints: []*big.Int{big.NewInt(1), big.NewInt(2)}, + address: common.HexToAddress("0x455E5AA18469bC6ccEF49594645666C587A3a71B"), + }, + }, + { + name: "error", + cfg: dummyDeployerGroupChangesetConfig{ + mints: []*big.Int{big.NewInt(-1)}, + address: common.HexToAddress("0x455E5AA18469bC6ccEF49594645666C587A3a71B"), + }, + expectError: true, + }, +} + +func TestDeployerGroup(t *testing.T) { + for _, tc := range deployerGroupTestCases { + t.Run(tc.name, func(t *testing.T) { + e, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithNumOfChains(2)) + + tc.cfg.selector = e.HomeChainSel + tc.cfg.MCMS = nil + + _, err := dummyDeployerGroupGrantMintChangeset(e.Env, tc.cfg) + require.NoError(t, err) + + _, err = dummyDeployerGroupMintChangeset(e.Env, tc.cfg) + if tc.expectError { + require.Error(t, err) + } else { + require.NoError(t, err) + + state, err := changeset.LoadOnchainState(e.Env) + require.NoError(t, err) + + token := state.Chains[e.HomeChainSel].LinkToken + + amount, err := token.BalanceOf(nil, tc.cfg.address) + require.NoError(t, err) + + sumOfMints := big.NewInt(0) + for _, mint := range tc.cfg.mints { + sumOfMints = sumOfMints.Add(sumOfMints, mint) + } + + require.Equal(t, sumOfMints, amount) + } + }) + } +} + +func TestDeployerGroupMCMS(t *testing.T) { + for _, tc := range deployerGroupTestCases { + t.Run(tc.name, func(t *testing.T) { + if tc.expectError { + t.Skip("skipping test because it's not possible to verify error when using MCMS since we are explicitly failing the test in ApplyChangesets") + } + + e, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithNumOfChains(2)) + + tc.cfg.selector = e.HomeChainSel + tc.cfg.MCMS = &changeset.MCMSConfig{ + MinDelay: 0, + } + state, err := changeset.LoadOnchainState(e.Env) + require.NoError(t, err) + + timelocksPerChain := changeset.BuildTimelockPerChain(e.Env, state) + + contractsByChain := make(map[uint64][]common.Address) + contractsByChain[e.HomeChainSel] = []common.Address{state.Chains[e.HomeChainSel].LinkToken.Address()} + + _, err = commonchangeset.ApplyChangesets(t, e.Env, timelocksPerChain, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.TransferToMCMSWithTimelock), + Config: commonchangeset.TransferToMCMSWithTimelockConfig{ + ContractsByChain: contractsByChain, + MinDelay: 0, + }, + }, + }) + require.NoError(t, err) + + _, err = commonchangeset.ApplyChangesets(t, e.Env, timelocksPerChain, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(dummyDeployerGroupGrantMintChangeset), + Config: tc.cfg, + }, + }) + require.NoError(t, err) + + _, err = commonchangeset.ApplyChangesets(t, e.Env, timelocksPerChain, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(dummyDeployerGroupMintChangeset), + Config: tc.cfg, + }, + }) + require.NoError(t, err) + + state, err = changeset.LoadOnchainState(e.Env) + require.NoError(t, err) + + token := state.Chains[e.HomeChainSel].LinkToken + + amount, err := token.BalanceOf(nil, tc.cfg.address) + require.NoError(t, err) + + sumOfMints := big.NewInt(0) + for _, mint := range tc.cfg.mints { + sumOfMints = sumOfMints.Add(sumOfMints, mint) + } + + require.Equal(t, sumOfMints, amount) + }) + } +} diff --git a/deployment/ccip/changeset/internal/deploy_home_chain.go b/deployment/ccip/changeset/internal/deploy_home_chain.go index e4c97cae326..8c829bab473 100644 --- a/deployment/ccip/changeset/internal/deploy_home_chain.go +++ b/deployment/ccip/changeset/internal/deploy_home_chain.go @@ -2,16 +2,17 @@ package internal import ( "context" + "errors" "fmt" "time" "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/common/hexutil" "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/smartcontractkit/chainlink-ccip/pluginconfig" @@ -21,7 +22,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" ) const ( @@ -32,7 +33,7 @@ const ( RemoteGasPriceBatchWriteFrequency = 30 * time.Minute TokenPriceBatchWriteFrequency = 30 * time.Minute BatchGasLimit = 6_500_000 - RelativeBoostPerWaitHour = 10000.5 + RelativeBoostPerWaitHour = 0.5 InflightCacheExpiry = 10 * time.Minute RootSnoozeTime = 30 * time.Minute BatchingStrategyID = 0 @@ -48,6 +49,10 @@ const ( MaxDurationObservation = 5 * time.Second MaxDurationShouldAcceptAttestedReport = 10 * time.Second MaxDurationShouldTransmitAcceptedReport = 10 * time.Second + + GasPriceDeviationPPB = 1000 + DAGasPriceDeviationPPB = 0 + OptimisticConfirmations = 1 ) var ( @@ -124,6 +129,12 @@ func DonIDForChain(registry *capabilities_registry.CapabilitiesRegistry, ccipHom if err != nil { return 0, fmt.Errorf("get all commit configs from cciphome: %w", err) } + if configs.ActiveConfig.ConfigDigest == [32]byte{} && configs.CandidateConfig.ConfigDigest == [32]byte{} { + configs, err = ccipHome.GetAllConfigs(nil, don.Id, uint8(types.PluginTypeCCIPExec)) + if err != nil { + return 0, fmt.Errorf("get all exec configs from cciphome: %w", err) + } + } if configs.ActiveConfig.Config.ChainSelector == chainSelector || configs.CandidateConfig.Config.ChainSelector == chainSelector { donIDs = append(donIDs, don.Id) } @@ -165,7 +176,8 @@ func BuildSetOCR3ConfigArgs( // we expect only an active config and no candidate config. if ocrConfig.ActiveConfig.ConfigDigest == [32]byte{} || ocrConfig.CandidateConfig.ConfigDigest != [32]byte{} { - return nil, fmt.Errorf("invalid OCR3 config state, expected active config and no candidate config, donID: %d", donID) + return nil, fmt.Errorf("invalid OCR3 config state, expected active config and no candidate config, donID: %d, activeConfig: %v, candidateConfig: %v", + donID, hexutil.Encode(ocrConfig.ActiveConfig.ConfigDigest[:]), hexutil.Encode(ocrConfig.CandidateConfig.ConfigDigest[:])) } activeConfig := ocrConfig.ActiveConfig @@ -188,255 +200,6 @@ func BuildSetOCR3ConfigArgs( return offrampOCR3Configs, nil } -func SetupExecDON( - lggr logger.Logger, - donID uint32, - execConfig ccip_home.CCIPHomeOCR3Config, - capReg *capabilities_registry.CapabilitiesRegistry, - home deployment.Chain, - nodes deployment.Nodes, - ccipHome *ccip_home.CCIPHome, -) error { - encodedSetCandidateCall, err := CCIPHomeABI.Pack( - "setCandidate", - donID, - execConfig.PluginType, - execConfig, - [32]byte{}, - ) - if err != nil { - return fmt.Errorf("pack set candidate call: %w", err) - } - - // set candidate call - tx, err := capReg.UpdateDON( - home.DeployerKey, - donID, - nodes.PeerIDs(), - []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: CCIPCapabilityID, - Config: encodedSetCandidateCall, - }, - }, - false, - nodes.DefaultF(), - ) - if err != nil { - return fmt.Errorf("update don w/ exec config: %w", err) - } - - if _, err := deployment.ConfirmIfNoError(home, tx, err); err != nil { - return fmt.Errorf("confirm update don w/ exec config: %w", err) - } - lggr.Infow("Updated DON with exec config", "chain", home.String(), "donID", donID, "txHash", tx.Hash().Hex(), "setCandidateCall", encodedSetCandidateCall) - - execCandidateDigest, err := ccipHome.GetCandidateDigest(nil, donID, execConfig.PluginType) - if err != nil { - return fmt.Errorf("get exec candidate digest 1st time: %w", err) - } - - if execCandidateDigest == [32]byte{} { - return fmt.Errorf("candidate digest is empty, expected nonempty") - } - lggr.Infow("Got exec candidate digest", "chain", home.String(), "donID", donID, "execCandidateDigest", execCandidateDigest) - // promote candidate call - encodedPromotionCall, err := CCIPHomeABI.Pack( - "promoteCandidateAndRevokeActive", - donID, - execConfig.PluginType, - execCandidateDigest, - [32]byte{}, - ) - if err != nil { - return fmt.Errorf("pack promotion call: %w", err) - } - - tx, err = capReg.UpdateDON( - home.DeployerKey, - donID, - nodes.PeerIDs(), - []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: CCIPCapabilityID, - Config: encodedPromotionCall, - }, - }, - false, - nodes.DefaultF(), - ) - if err != nil { - return fmt.Errorf("update don w/ exec config: %w", err) - } - bn, err := deployment.ConfirmIfNoError(home, tx, err) - if err != nil { - return fmt.Errorf("confirm update don w/ exec config: %w", err) - } - if bn == 0 { - return fmt.Errorf("UpdateDON tx not confirmed") - } - lggr.Infow("Promoted exec candidate", "chain", home.String(), "donID", donID, "txHash", tx.Hash().Hex(), "promotionCall", encodedPromotionCall) - // check if candidate digest is promoted - pEvent, err := ccipHome.FilterConfigPromoted(&bind.FilterOpts{ - Context: context.Background(), - Start: bn, - }, [][32]byte{execCandidateDigest}) - if err != nil { - return fmt.Errorf("filter exec config promoted: %w", err) - } - if !pEvent.Next() { - return fmt.Errorf("exec config not promoted") - } - // check that candidate digest is empty. - execCandidateDigest, err = ccipHome.GetCandidateDigest(nil, donID, execConfig.PluginType) - if err != nil { - return fmt.Errorf("get exec candidate digest 2nd time: %w", err) - } - - if execCandidateDigest != [32]byte{} { - return fmt.Errorf("candidate digest is nonempty after promotion, expected empty") - } - - // check that active digest is non-empty. - execActiveDigest, err := ccipHome.GetActiveDigest(nil, donID, uint8(types.PluginTypeCCIPExec)) - if err != nil { - return fmt.Errorf("get active exec digest: %w", err) - } - - if execActiveDigest == [32]byte{} { - return fmt.Errorf("active exec digest is empty, expected nonempty") - } - - execConfigs, err := ccipHome.GetAllConfigs(nil, donID, uint8(types.PluginTypeCCIPExec)) - if err != nil { - return fmt.Errorf("get all exec configs 2nd time: %w", err) - } - - // log the above info - lggr.Infow("completed exec DON creation and promotion", - "donID", donID, - "execCandidateDigest", execCandidateDigest, - "execActiveDigest", execActiveDigest, - "execCandidateDigestFromGetAllConfigs", execConfigs.CandidateConfig.ConfigDigest, - "execActiveDigestFromGetAllConfigs", execConfigs.ActiveConfig.ConfigDigest, - ) - - return nil -} - -func SetupCommitDON( - lggr logger.Logger, - donID uint32, - commitConfig ccip_home.CCIPHomeOCR3Config, - capReg *capabilities_registry.CapabilitiesRegistry, - home deployment.Chain, - nodes deployment.Nodes, - ccipHome *ccip_home.CCIPHome, -) error { - encodedSetCandidateCall, err := CCIPHomeABI.Pack( - "setCandidate", - donID, - commitConfig.PluginType, - commitConfig, - [32]byte{}, - ) - if err != nil { - return fmt.Errorf("pack set candidate call: %w", err) - } - tx, err := capReg.AddDON(home.DeployerKey, nodes.PeerIDs(), []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: CCIPCapabilityID, - Config: encodedSetCandidateCall, - }, - }, false, false, nodes.DefaultF()) - if err != nil { - return fmt.Errorf("add don w/ commit config: %w", err) - } - - if _, err := deployment.ConfirmIfNoError(home, tx, err); err != nil { - return fmt.Errorf("confirm add don w/ commit config: %w", err) - } - lggr.Debugw("Added DON with commit config", "chain", home.String(), "donID", donID, "txHash", tx.Hash().Hex(), "setCandidateCall", encodedSetCandidateCall) - commitCandidateDigest, err := ccipHome.GetCandidateDigest(nil, donID, commitConfig.PluginType) - if err != nil { - return fmt.Errorf("get commit candidate digest: %w", err) - } - - if commitCandidateDigest == [32]byte{} { - return fmt.Errorf("candidate digest is empty, expected nonempty") - } - lggr.Debugw("Got commit candidate digest", "chain", home.String(), "donID", donID, "commitCandidateDigest", commitCandidateDigest) - - encodedPromotionCall, err := CCIPHomeABI.Pack( - "promoteCandidateAndRevokeActive", - donID, - commitConfig.PluginType, - commitCandidateDigest, - [32]byte{}, - ) - if err != nil { - return fmt.Errorf("pack promotion call: %w", err) - } - - tx, err = capReg.UpdateDON( - home.DeployerKey, - donID, - nodes.PeerIDs(), - []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: CCIPCapabilityID, - Config: encodedPromotionCall, - }, - }, - false, - nodes.DefaultF(), - ) - if err != nil { - return fmt.Errorf("update don w/ commit config: %w", err) - } - - if _, err := deployment.ConfirmIfNoError(home, tx, err); err != nil { - return fmt.Errorf("confirm update don w/ commit config: %w", err) - } - lggr.Debugw("Promoted commit candidate", "chain", home.String(), "donID", donID, "txHash", tx.Hash().Hex(), "promotionCall", encodedPromotionCall) - - // check that candidate digest is empty. - commitCandidateDigest, err = ccipHome.GetCandidateDigest(nil, donID, commitConfig.PluginType) - if err != nil { - return fmt.Errorf("get commit candidate digest 2nd time: %w", err) - } - - if commitCandidateDigest != [32]byte{} { - return fmt.Errorf("candidate digest is nonempty after promotion, expected empty") - } - - // check that active digest is non-empty. - commitActiveDigest, err := ccipHome.GetActiveDigest(nil, donID, uint8(types.PluginTypeCCIPCommit)) - if err != nil { - return fmt.Errorf("get active commit digest: %w", err) - } - - if commitActiveDigest == [32]byte{} { - return fmt.Errorf("active commit digest is empty, expected nonempty") - } - - commitConfigs, err := ccipHome.GetAllConfigs(nil, donID, uint8(types.PluginTypeCCIPCommit)) - if err != nil { - return fmt.Errorf("get all commit configs 2nd time: %w", err) - } - - // log the above information - lggr.Infow("completed commit DON creation and promotion", - "donID", donID, - "commitCandidateDigest", commitCandidateDigest, - "commitActiveDigest", commitActiveDigest, - "commitCandidateDigestFromGetAllConfigs", commitConfigs.CandidateConfig.ConfigDigest, - "commitActiveDigestFromGetAllConfigs", commitConfigs.ActiveConfig.ConfigDigest, - ) - - return nil -} - func BuildOCR3ConfigForCCIPHome( ocrSecrets deployment.OCRSecrets, offRamp *offramp.OffRamp, @@ -444,8 +207,8 @@ func BuildOCR3ConfigForCCIPHome( nodes deployment.Nodes, rmnHomeAddress common.Address, ocrParams types2.OCRParameters, - commitOffchainCfg pluginconfig.CommitOffchainConfig, - execOffchainCfg pluginconfig.ExecuteOffchainConfig, + commitOffchainCfg *pluginconfig.CommitOffchainConfig, + execOffchainCfg *pluginconfig.ExecuteOffchainConfig, ) (map[types.PluginType]ccip_home.CCIPHomeOCR3Config, error) { p2pIDs := nodes.PeerIDs() // Get OCR3 Config from helper @@ -469,10 +232,20 @@ func BuildOCR3ConfigForCCIPHome( // Add DON on capability registry contract ocr3Configs := make(map[types.PluginType]ccip_home.CCIPHomeOCR3Config) - for _, pluginType := range []types.PluginType{types.PluginTypeCCIPCommit, types.PluginTypeCCIPExec} { + pluginTypes := make([]types.PluginType, 0) + if commitOffchainCfg != nil { + pluginTypes = append(pluginTypes, types.PluginTypeCCIPCommit) + } + if execOffchainCfg != nil { + pluginTypes = append(pluginTypes, types.PluginTypeCCIPExec) + } + for _, pluginType := range pluginTypes { var encodedOffchainConfig []byte var err2 error if pluginType == types.PluginTypeCCIPCommit { + if commitOffchainCfg == nil { + return nil, errors.New("commitOffchainCfg is nil") + } encodedOffchainConfig, err2 = pluginconfig.EncodeCommitOffchainConfig(pluginconfig.CommitOffchainConfig{ RemoteGasPriceBatchWriteFrequency: commitOffchainCfg.RemoteGasPriceBatchWriteFrequency, TokenPriceBatchWriteFrequency: commitOffchainCfg.TokenPriceBatchWriteFrequency, @@ -486,6 +259,9 @@ func BuildOCR3ConfigForCCIPHome( RMNSignaturesTimeout: commitOffchainCfg.RMNSignaturesTimeout, }) } else { + if execOffchainCfg == nil { + return nil, errors.New("execOffchainCfg is nil") + } encodedOffchainConfig, err2 = pluginconfig.EncodeExecuteOffchainConfig(pluginconfig.ExecuteOffchainConfig{ BatchGasLimit: execOffchainCfg.BatchGasLimit, RelativeBoostPerWaitHour: execOffchainCfg.RelativeBoostPerWaitHour, @@ -499,7 +275,7 @@ func BuildOCR3ConfigForCCIPHome( if err2 != nil { return nil, err2 } - signers, transmitters, configF, _, offchainConfigVersion, offchainConfig, err2 := ocr3confighelper.ContractSetConfigArgsDeterministic( + signers, transmitters, configF, onchainConfig, offchainConfigVersion, offchainConfig, err2 := ocr3confighelper.ContractSetConfigArgsDeterministic( ocrSecrets.EphemeralSk, ocrSecrets.SharedSecret, ocrParams.DeltaProgress, @@ -538,7 +314,18 @@ func BuildOCR3ConfigForCCIPHome( } transmittersBytes[i] = parsed } - + // validate ocr3 params correctness + _, err := ocr3confighelper.PublicConfigFromContractConfig(false, ocrtypes.ContractConfig{ + Signers: signers, + Transmitters: transmitters, + F: configF, + OnchainConfig: onchainConfig, + OffchainConfigVersion: offchainConfigVersion, + OffchainConfig: offchainConfig, + }) + if err != nil { + return nil, fmt.Errorf("failed to validate ocr3 params: %w", err) + } var ocrNodes []ccip_home.CCIPHomeOCR3Node for i := range nodes { ocrNodes = append(ocrNodes, ccip_home.CCIPHomeOCR3Node{ diff --git a/deployment/ccip/changeset/save_existing_test.go b/deployment/ccip/changeset/save_existing_test.go index 080ed80481a..f575bc005f2 100644 --- a/deployment/ccip/changeset/save_existing_test.go +++ b/deployment/ccip/changeset/save_existing_test.go @@ -1,4 +1,4 @@ -package changeset +package changeset_test import ( "math/big" @@ -9,6 +9,7 @@ import ( "go.uber.org/zap/zapcore" "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" "github.com/smartcontractkit/chainlink/deployment/environment/memory" @@ -35,32 +36,32 @@ func TestSaveExistingCCIP(t *testing.T) { }, { Address: common.BigToAddress(big.NewInt(2)), - TypeAndVersion: deployment.NewTypeAndVersion(WETH9, deployment.Version1_0_0), + TypeAndVersion: deployment.NewTypeAndVersion(changeset.WETH9, deployment.Version1_0_0), ChainSelector: chain1, }, { Address: common.BigToAddress(big.NewInt(3)), - TypeAndVersion: deployment.NewTypeAndVersion(TokenAdminRegistry, deployment.Version1_5_0), + TypeAndVersion: deployment.NewTypeAndVersion(changeset.TokenAdminRegistry, deployment.Version1_5_0), ChainSelector: chain1, }, { Address: common.BigToAddress(big.NewInt(4)), - TypeAndVersion: deployment.NewTypeAndVersion(RegistryModule, deployment.Version1_5_0), + TypeAndVersion: deployment.NewTypeAndVersion(changeset.RegistryModule, deployment.Version1_5_0), ChainSelector: chain2, }, { Address: common.BigToAddress(big.NewInt(5)), - TypeAndVersion: deployment.NewTypeAndVersion(Router, deployment.Version1_2_0), + TypeAndVersion: deployment.NewTypeAndVersion(changeset.Router, deployment.Version1_2_0), ChainSelector: chain2, }, }, } - output, err := commonchangeset.SaveExistingContracts(e, cfg) + output, err := commonchangeset.SaveExistingContractsChangeset(e, cfg) require.NoError(t, err) err = e.ExistingAddresses.Merge(output.AddressBook) require.NoError(t, err) - state, err := LoadOnchainState(e) + state, err := changeset.LoadOnchainState(e) require.NoError(t, err) require.Equal(t, state.Chains[chain1].LinkToken.Address(), common.BigToAddress(big.NewInt(1))) require.Equal(t, state.Chains[chain1].Weth9.Address(), common.BigToAddress(big.NewInt(2))) diff --git a/deployment/ccip/changeset/state.go b/deployment/ccip/changeset/state.go index 2403f3f7cc2..323226c6a4a 100644 --- a/deployment/ccip/changeset/state.go +++ b/deployment/ccip/changeset/state.go @@ -2,11 +2,18 @@ package changeset import ( "fmt" + "strconv" "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" burn_mint_token_pool "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/burn_mint_token_pool_1_4_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_offramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry_1_2_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_contract" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/erc20" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/erc677" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_usdc_token_messenger" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_usdc_token_transmitter" @@ -25,7 +32,7 @@ import ( commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" common_v1_0 "github.com/smartcontractkit/chainlink/deployment/common/view/v1_0" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_rmn_contract" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/registry_module_owner_custom" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" @@ -34,7 +41,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/maybe_revert_message_receiver" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/nonce_manager" @@ -45,12 +52,14 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_admin_registry" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/weth9" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/aggregator_v3_interface" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/aggregator_v3_interface" ) var ( - // Legacy - CommitStore deployment.ContractType = "CommitStore" + // Legacy + CommitStore deployment.ContractType = "CommitStore" + PriceRegistry deployment.ContractType = "PriceRegistry" + RMN deployment.ContractType = "RMN" // Not legacy MockRMN deployment.ContractType = "MockRMN" @@ -77,6 +86,8 @@ var ( // Pools BurnMintToken deployment.ContractType = "BurnMintToken" + ERC20Token deployment.ContractType = "ERC20Token" + ERC677Token deployment.ContractType = "ERC677Token" BurnMintTokenPool deployment.ContractType = "BurnMintTokenPool" USDCToken deployment.ContractType = "USDCToken" USDCTokenMessenger deployment.ContractType = "USDCTokenMessenger" @@ -92,19 +103,17 @@ type CCIPChainState struct { OnRamp *onramp.OnRamp OffRamp *offramp.OffRamp FeeQuoter *fee_quoter.FeeQuoter - RMNProxy *rmn_proxy_contract.RMNProxyContract + RMNProxy *rmn_proxy_contract.RMNProxy NonceManager *nonce_manager.NonceManager TokenAdminRegistry *token_admin_registry.TokenAdminRegistry RegistryModule *registry_module_owner_custom.RegistryModuleOwnerCustom Router *router.Router - CommitStore *commit_store.CommitStore Weth9 *weth9.WETH9 RMNRemote *rmn_remote.RMNRemote - MockRMN *mock_rmn_contract.MockRMNContract // Map between token Descriptor (e.g. LinkSymbol, WethSymbol) // and the respective token contract - // This is more of an illustration of how we'll have tokens, and it might need some work later to work properly. - // Not all tokens will be burn and mint tokens. + ERC20Tokens map[TokenSymbol]*erc20.ERC20 + ERC677Tokens map[TokenSymbol]*erc677.ERC677 BurnMintTokens677 map[TokenSymbol]*burn_mint_erc677.BurnMintERC677 BurnMintTokenPools map[TokenSymbol]*burn_mint_token_pool.BurnMintTokenPool // Map between token Symbol (e.g. LinkSymbol, WethSymbol) @@ -123,6 +132,24 @@ type CCIPChainState struct { MockUSDCTransmitter *mock_usdc_token_transmitter.MockE2EUSDCTransmitter MockUSDCTokenMessenger *mock_usdc_token_messenger.MockE2EUSDCTokenMessenger Multicall3 *multicall3.Multicall3 + + // Legacy contracts + EVM2EVMOnRamp map[uint64]*evm_2_evm_onramp.EVM2EVMOnRamp // mapping of dest chain selector -> EVM2EVMOnRamp + CommitStore map[uint64]*commit_store.CommitStore // mapping of source chain selector -> CommitStore + EVM2EVMOffRamp map[uint64]*evm_2_evm_offramp.EVM2EVMOffRamp // mapping of source chain selector -> EVM2EVMOffRamp + MockRMN *mock_rmn_contract.MockRMNContract + PriceRegistry *price_registry_1_2_0.PriceRegistry + RMN *rmn_contract.RMNContract +} + +func (c CCIPChainState) LinkTokenAddress() (common.Address, error) { + if c.LinkToken != nil { + return c.LinkToken.Address(), nil + } + if c.StaticLinkToken != nil { + return c.StaticLinkToken.Address(), nil + } + return common.Address{}, errors.New("no link token found in the state") } func (c CCIPChainState) GenerateView() (view.ChainView, error) { @@ -153,7 +180,7 @@ func (c CCIPChainState) GenerateView() (view.ChainView, error) { if err != nil { return chainView, errors.Wrapf(err, "failed to generate rmn remote view for rmn remote %s", c.RMNRemote.Address().String()) } - chainView.RMN[c.RMNRemote.Address().Hex()] = rmnView + chainView.RMNRemote[c.RMNRemote.Address().Hex()] = rmnView } if c.RMNHome != nil { @@ -195,14 +222,6 @@ func (c CCIPChainState) GenerateView() (view.ChainView, error) { chainView.OffRamp[c.OffRamp.Address().Hex()] = offRampView } - if c.CommitStore != nil { - commitStoreView, err := v1_5.GenerateCommitStoreView(c.CommitStore) - if err != nil { - return chainView, errors.Wrapf(err, "failed to generate commit store view for commit store %s", c.CommitStore.Address().String()) - } - chainView.CommitStore[c.CommitStore.Address().Hex()] = commitStoreView - } - if c.RMNProxy != nil { rmnProxyView, err := v1_0.GenerateRMNProxyView(c.RMNProxy) if err != nil { @@ -245,6 +264,53 @@ func (c CCIPChainState) GenerateView() (view.ChainView, error) { } chainView.StaticLinkToken = staticLinkTokenView } + // Legacy contracts + if c.CommitStore != nil { + for source, commitStore := range c.CommitStore { + commitStoreView, err := v1_5.GenerateCommitStoreView(commitStore) + if err != nil { + return chainView, errors.Wrapf(err, "failed to generate commit store view for commit store %s for source %d", commitStore.Address().String(), source) + } + chainView.CommitStore[commitStore.Address().Hex()] = commitStoreView + } + } + + if c.PriceRegistry != nil { + priceRegistryView, err := v1_2.GeneratePriceRegistryView(c.PriceRegistry) + if err != nil { + return chainView, errors.Wrapf(err, "failed to generate price registry view for price registry %s", c.PriceRegistry.Address().String()) + } + chainView.PriceRegistry[c.PriceRegistry.Address().String()] = priceRegistryView + } + + if c.RMN != nil { + rmnView, err := v1_5.GenerateRMNView(c.RMN) + if err != nil { + return chainView, errors.Wrapf(err, "failed to generate rmn view for rmn %s", c.RMN.Address().String()) + } + chainView.RMN[c.RMN.Address().Hex()] = rmnView + } + + if c.EVM2EVMOffRamp != nil { + for source, offRamp := range c.EVM2EVMOffRamp { + offRampView, err := v1_5.GenerateOffRampView(offRamp) + if err != nil { + return chainView, errors.Wrapf(err, "failed to generate off ramp view for off ramp %s for source %d", offRamp.Address().String(), source) + } + chainView.EVM2EVMOffRamp[offRamp.Address().Hex()] = offRampView + } + } + + if c.EVM2EVMOnRamp != nil { + for dest, onRamp := range c.EVM2EVMOnRamp { + onRampView, err := v1_5.GenerateOnRampView(onRamp) + if err != nil { + return chainView, errors.Wrapf(err, "failed to generate on ramp view for on ramp %s for dest %d", onRamp.Address().String(), dest) + } + chainView.EVM2EVMOnRamp[onRamp.Address().Hex()] = onRampView + } + } + return chainView, nil } @@ -259,6 +325,16 @@ type CCIPOnChainState struct { SolChains map[uint64]SolCCIPChainState } +func (s CCIPOnChainState) Validate() error { + for sel, chain := range s.Chains { + // cannot have static link and link together + if chain.LinkToken != nil && chain.StaticLinkToken != nil { + return fmt.Errorf("cannot have both link and static link token on the same chain %d", sel) + } + } + return nil +} + func (s CCIPOnChainState) GetAllProposerMCMSForChains(chains []uint64) (map[uint64]*gethwrappers.ManyChainMultiSig, error) { multiSigs := make(map[uint64]*gethwrappers.ManyChainMultiSig) for _, chain := range chains { @@ -289,6 +365,14 @@ func (s CCIPOnChainState) GetAllTimeLocksForChains(chains []uint64) (map[uint64] return timelocks, nil } +func (s CCIPOnChainState) SupportedChains() map[uint64]struct{} { + chains := make(map[uint64]struct{}) + for chain := range s.Chains { + chains[chain] = struct{}{} + } + return chains +} + func (s CCIPOnChainState) View(chains []uint64) (map[string]view.ChainView, error) { m := make(map[string]view.ChainView) for _, chainSelector := range chains { @@ -304,7 +388,11 @@ func (s CCIPOnChainState) View(chains []uint64) (map[string]view.ChainView, erro if err != nil { return m, err } - m[chainInfo.ChainName] = chainView + name := chainInfo.ChainName + if chainInfo.ChainName == "" { + name = strconv.FormatUint(chainSelector, 10) + } + m[name] = chainView } return m, nil } @@ -329,7 +417,7 @@ func LoadOnchainState(e deployment.Environment) (CCIPOnChainState, error) { } state.Chains[chainSelector] = chainState } - return state, nil + return state, state.Validate() } // LoadChainState Loads all state for a chain into state @@ -381,17 +469,11 @@ func LoadChainState(chain deployment.Chain, addresses map[string]deployment.Type } state.OffRamp = offRamp case deployment.NewTypeAndVersion(ARMProxy, deployment.Version1_0_0).String(): - armProxy, err := rmn_proxy_contract.NewRMNProxyContract(common.HexToAddress(address), chain.Client) + armProxy, err := rmn_proxy_contract.NewRMNProxy(common.HexToAddress(address), chain.Client) if err != nil { return state, err } state.RMNProxy = armProxy - case deployment.NewTypeAndVersion(MockRMN, deployment.Version1_0_0).String(): - mockRMN, err := mock_rmn_contract.NewMockRMNContract(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.MockRMN = mockRMN case deployment.NewTypeAndVersion(RMNRemote, deployment.Version1_6_0_dev).String(): rmnRemote, err := rmn_remote.NewRMNRemote(common.HexToAddress(address), chain.Client) if err != nil { @@ -416,12 +498,6 @@ func LoadChainState(chain deployment.Chain, addresses map[string]deployment.Type return state, err } state.NonceManager = nm - case deployment.NewTypeAndVersion(CommitStore, deployment.Version1_5_0).String(): - cs, err := commit_store.NewCommitStore(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.CommitStore = cs case deployment.NewTypeAndVersion(TokenAdminRegistry, deployment.Version1_5_0).String(): tm, err := token_admin_registry.NewTokenAdminRegistry(common.HexToAddress(address), chain.Client) if err != nil { @@ -508,7 +584,7 @@ func LoadChainState(chain deployment.Chain, addresses map[string]deployment.Type if err != nil { return state, err } - key, ok := MockDescriptionToTokenSymbol[desc] + key, ok := DescriptionToTokenSymbol[desc] if !ok { return state, fmt.Errorf("unknown feed description %s", desc) } @@ -547,6 +623,90 @@ func LoadChainState(chain deployment.Chain, addresses map[string]deployment.Type return state, fmt.Errorf("failed to get token symbol of token at %s: %w", address, err) } state.BurnMintTokens677[TokenSymbol(symbol)] = tok + case deployment.NewTypeAndVersion(ERC20Token, deployment.Version1_0_0).String(): + tok, err := erc20.NewERC20(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + if state.ERC20Tokens == nil { + state.ERC20Tokens = make(map[TokenSymbol]*erc20.ERC20) + } + symbol, err := tok.Symbol(nil) + if err != nil { + return state, fmt.Errorf("failed to get token symbol of token at %s: %w", address, err) + } + state.ERC20Tokens[TokenSymbol(symbol)] = tok + case deployment.NewTypeAndVersion(ERC677Token, deployment.Version1_0_0).String(): + tok, err := erc677.NewERC677(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + if state.ERC677Tokens == nil { + state.ERC677Tokens = make(map[TokenSymbol]*erc677.ERC677) + } + symbol, err := tok.Symbol(nil) + if err != nil { + return state, fmt.Errorf("failed to get token symbol of token at %s: %w", address, err) + } + state.ERC677Tokens[TokenSymbol(symbol)] = tok + // legacy addresses below + case deployment.NewTypeAndVersion(OnRamp, deployment.Version1_5_0).String(): + onRampC, err := evm_2_evm_onramp.NewEVM2EVMOnRamp(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + sCfg, err := onRampC.GetStaticConfig(nil) + if err != nil { + return state, fmt.Errorf("failed to get static config chain %s: %w", chain.String(), err) + } + if state.EVM2EVMOnRamp == nil { + state.EVM2EVMOnRamp = make(map[uint64]*evm_2_evm_onramp.EVM2EVMOnRamp) + } + state.EVM2EVMOnRamp[sCfg.DestChainSelector] = onRampC + case deployment.NewTypeAndVersion(OffRamp, deployment.Version1_5_0).String(): + offRamp, err := evm_2_evm_offramp.NewEVM2EVMOffRamp(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + sCfg, err := offRamp.GetStaticConfig(nil) + if err != nil { + return state, err + } + if state.EVM2EVMOffRamp == nil { + state.EVM2EVMOffRamp = make(map[uint64]*evm_2_evm_offramp.EVM2EVMOffRamp) + } + state.EVM2EVMOffRamp[sCfg.SourceChainSelector] = offRamp + case deployment.NewTypeAndVersion(CommitStore, deployment.Version1_5_0).String(): + commitStore, err := commit_store.NewCommitStore(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + sCfg, err := commitStore.GetStaticConfig(nil) + if err != nil { + return state, err + } + if state.CommitStore == nil { + state.CommitStore = make(map[uint64]*commit_store.CommitStore) + } + state.CommitStore[sCfg.SourceChainSelector] = commitStore + case deployment.NewTypeAndVersion(PriceRegistry, deployment.Version1_2_0).String(): + pr, err := price_registry_1_2_0.NewPriceRegistry(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.PriceRegistry = pr + case deployment.NewTypeAndVersion(RMN, deployment.Version1_5_0).String(): + rmnC, err := rmn_contract.NewRMNContract(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.RMN = rmnC + case deployment.NewTypeAndVersion(MockRMN, deployment.Version1_0_0).String(): + mockRMN, err := mock_rmn_contract.NewMockRMNContract(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.MockRMN = mockRMN default: return state, fmt.Errorf("unknown contract %s", tvStr) } diff --git a/deployment/ccip/changeset/state_test.go b/deployment/ccip/changeset/state_test.go index 3587332fff2..c46df8b1dc7 100644 --- a/deployment/ccip/changeset/state_test.go +++ b/deployment/ccip/changeset/state_test.go @@ -1,14 +1,17 @@ -package changeset +package changeset_test import ( "testing" "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" ) func TestSmokeState(t *testing.T) { - tenv := NewMemoryEnvironment(t, WithChains(3)) - state, err := LoadOnchainState(tenv.Env) + tenv, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithNumOfChains(3)) + state, err := changeset.LoadOnchainState(tenv.Env) require.NoError(t, err) _, err = state.View(tenv.Env.AllChainSelectors()) require.NoError(t, err) diff --git a/deployment/ccip/changeset/test_environment.go b/deployment/ccip/changeset/test_environment.go deleted file mode 100644 index cb0760cee1c..00000000000 --- a/deployment/ccip/changeset/test_environment.go +++ /dev/null @@ -1,445 +0,0 @@ -package changeset - -import ( - "context" - "fmt" - "math/big" - "os" - "testing" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink-ccip/pluginconfig" - commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink-common/pkg/logger" - jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" - "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/chainlink/deployment" - commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" - "github.com/smartcontractkit/chainlink/deployment/environment/memory" -) - -type EnvType string - -const ( - Memory EnvType = "in-memory" - Docker EnvType = "docker" - ENVTESTTYPE = "CCIP_V16_TEST_ENV" -) - -type TestConfigs struct { - Type EnvType // set by env var CCIP_V16_TEST_ENV, defaults to Memory - CreateJob bool - CreateJobAndContracts bool - Chains int // only used in memory mode, for docker mode, this is determined by the integration-test config toml input - NumOfUsersPerChain int // only used in memory mode, for docker mode, this is determined by the integration-test config toml input - Nodes int // only used in memory mode, for docker mode, this is determined by the integration-test config toml input - Bootstraps int // only used in memory mode, for docker mode, this is determined by the integration-test config toml input - IsUSDC bool - IsUSDCAttestationMissing bool - IsMultiCall3 bool - OCRConfigOverride func(CCIPOCRParams) CCIPOCRParams - RMNEnabled bool - NumOfRMNNodes int - LinkPrice *big.Int - WethPrice *big.Int -} - -func (tc *TestConfigs) Validate() error { - if tc.Chains < 2 { - return fmt.Errorf("chains must be at least 2") - } - if tc.Nodes < 4 { - return fmt.Errorf("nodes must be at least 4") - } - if tc.Bootstraps < 1 { - return fmt.Errorf("bootstraps must be at least 1") - } - if tc.Type == Memory && tc.RMNEnabled { - return fmt.Errorf("cannot run RMN tests in memory mode") - } - return nil -} - -func (tc *TestConfigs) MustSetEnvTypeOrDefault(t *testing.T) { - envType := os.Getenv(ENVTESTTYPE) - if envType == "" || envType == string(Memory) { - tc.Type = Memory - } else if envType == string(Docker) { - tc.Type = Docker - } else { - t.Fatalf("env var CCIP_V16_TEST_ENV must be either %s or %s, defaults to %s if unset, got: %s", Memory, Docker, Memory, envType) - } -} - -func DefaultTestConfigs() *TestConfigs { - return &TestConfigs{ - Chains: 2, - NumOfUsersPerChain: 1, - Nodes: 4, - Bootstraps: 1, - LinkPrice: MockLinkPrice, - WethPrice: MockWethPrice, - CreateJobAndContracts: true, - } -} - -type TestOps func(testCfg *TestConfigs) - -func WithMultiCall3() TestOps { - return func(testCfg *TestConfigs) { - testCfg.IsMultiCall3 = true - } -} - -func WithJobsOnly() TestOps { - return func(testCfg *TestConfigs) { - testCfg.CreateJobAndContracts = false - testCfg.CreateJob = true - } -} - -func WithNoJobsAndContracts() TestOps { - return func(testCfg *TestConfigs) { - testCfg.CreateJobAndContracts = false - testCfg.CreateJob = false - } -} - -func WithRMNEnabled(numOfNode int) TestOps { - return func(testCfg *TestConfigs) { - testCfg.RMNEnabled = true - testCfg.NumOfRMNNodes = numOfNode - } -} - -func WithOCRConfigOverride(override func(CCIPOCRParams) CCIPOCRParams) TestOps { - return func(testCfg *TestConfigs) { - testCfg.OCRConfigOverride = override - } -} - -func WithUSDCAttestationMissing() TestOps { - return func(testCfg *TestConfigs) { - testCfg.IsUSDCAttestationMissing = true - } -} - -func WithUSDC() TestOps { - return func(testCfg *TestConfigs) { - testCfg.IsUSDC = true - } -} - -func WithChains(numChains int) TestOps { - return func(testCfg *TestConfigs) { - testCfg.Chains = numChains - } -} - -func WithUsersPerChain(numUsers int) TestOps { - return func(testCfg *TestConfigs) { - testCfg.NumOfUsersPerChain = numUsers - } -} - -func WithNodes(numNodes int) TestOps { - return func(testCfg *TestConfigs) { - testCfg.Nodes = numNodes - } -} - -func WithBootstraps(numBootstraps int) TestOps { - return func(testCfg *TestConfigs) { - testCfg.Bootstraps = numBootstraps - } -} - -type TestEnvironment interface { - SetupJobs(t *testing.T) - StartNodes(t *testing.T, tc *TestConfigs, crConfig deployment.CapabilityRegistryConfig) - StartChains(t *testing.T, tc *TestConfigs) - DeployedEnvironment() DeployedEnv - MockUSDCAttestationServer(t *testing.T, isUSDCAttestationMissing bool) string -} - -type DeployedEnv struct { - Env deployment.Environment - HomeChainSel uint64 - FeedChainSel uint64 - ReplayBlocks map[uint64]uint64 - Users map[uint64][]*bind.TransactOpts -} - -func (d *DeployedEnv) SetupJobs(t *testing.T) { - ctx := testcontext.Get(t) - out, err := CCIPCapabilityJobspec(d.Env, struct{}{}) - require.NoError(t, err) - for nodeID, jobs := range out.JobSpecs { - for _, job := range jobs { - // Note these auto-accept - _, err := d.Env.Offchain.ProposeJob(ctx, - &jobv1.ProposeJobRequest{ - NodeId: nodeID, - Spec: job, - }) - require.NoError(t, err) - } - } - // Wait for plugins to register filters? - // TODO: Investigate how to avoid. - time.Sleep(30 * time.Second) - ReplayLogs(t, d.Env.Offchain, d.ReplayBlocks) -} - -type MemoryEnvironment struct { - DeployedEnv - chains map[uint64]deployment.Chain -} - -func (m *MemoryEnvironment) DeployedEnvironment() DeployedEnv { - return m.DeployedEnv -} - -func (m *MemoryEnvironment) StartChains(t *testing.T, tc *TestConfigs) { - ctx := testcontext.Get(t) - chains, users := memory.NewMemoryChains(t, tc.Chains, tc.NumOfUsersPerChain) - m.chains = chains - homeChainSel, feedSel := allocateCCIPChainSelectors(chains) - replayBlocks, err := LatestBlocksByChain(ctx, chains) - require.NoError(t, err) - m.DeployedEnv = DeployedEnv{ - Env: deployment.Environment{ - Chains: m.chains, - }, - HomeChainSel: homeChainSel, - FeedChainSel: feedSel, - ReplayBlocks: replayBlocks, - Users: users, - } -} - -func (m *MemoryEnvironment) StartNodes(t *testing.T, tc *TestConfigs, crConfig deployment.CapabilityRegistryConfig) { - require.NotNil(t, m.chains, "start chains first, chains are empty") - require.NotNil(t, m.DeployedEnv, "start chains and initiate deployed env first before starting nodes") - nodes := memory.NewNodes(t, zapcore.InfoLevel, m.chains, tc.Nodes, tc.Bootstraps, crConfig) - ctx := testcontext.Get(t) - lggr := logger.Test(t) - for _, node := range nodes { - require.NoError(t, node.App.Start(ctx)) - t.Cleanup(func() { - require.NoError(t, node.App.Stop()) - }) - } - m.DeployedEnv.Env = memory.NewMemoryEnvironmentFromChainsNodes(func() context.Context { return ctx }, lggr, m.chains, nodes) -} - -func (m *MemoryEnvironment) MockUSDCAttestationServer(t *testing.T, isUSDCAttestationMissing bool) string { - server := mockAttestationResponse(isUSDCAttestationMissing) - endpoint := server.URL - t.Cleanup(func() { - server.Close() - }) - return endpoint -} - -// NewMemoryEnvironment creates an in-memory environment based on the testconfig requested -func NewMemoryEnvironment(t *testing.T, opts ...TestOps) DeployedEnv { - testCfg := DefaultTestConfigs() - for _, opt := range opts { - opt(testCfg) - } - require.NoError(t, testCfg.Validate(), "invalid test config") - env := &MemoryEnvironment{} - if testCfg.CreateJobAndContracts { - return NewEnvironmentWithJobsAndContracts(t, testCfg, env) - } - if testCfg.CreateJob { - return NewEnvironmentWithJobs(t, testCfg, env) - } - return NewEnvironment(t, testCfg, env) -} - -func NewEnvironment(t *testing.T, tc *TestConfigs, tEnv TestEnvironment) DeployedEnv { - lggr := logger.Test(t) - tEnv.StartChains(t, tc) - dEnv := tEnv.DeployedEnvironment() - require.NotEmpty(t, dEnv.FeedChainSel) - require.NotEmpty(t, dEnv.HomeChainSel) - require.NotEmpty(t, dEnv.Env.Chains) - ab := deployment.NewMemoryAddressBook() - crConfig := DeployTestContracts(t, lggr, ab, dEnv.HomeChainSel, dEnv.FeedChainSel, dEnv.Env.Chains, tc.LinkPrice, tc.WethPrice) - tEnv.StartNodes(t, tc, crConfig) - dEnv = tEnv.DeployedEnvironment() - envNodes, err := deployment.NodeInfo(dEnv.Env.NodeIDs, dEnv.Env.Offchain) - require.NoError(t, err) - dEnv.Env.ExistingAddresses = ab - _, err = deployHomeChain(lggr, dEnv.Env, dEnv.Env.ExistingAddresses, dEnv.Env.Chains[dEnv.HomeChainSel], - NewTestRMNStaticConfig(), - NewTestRMNDynamicConfig(), - NewTestNodeOperator(dEnv.Env.Chains[dEnv.HomeChainSel].DeployerKey.From), - map[string][][32]byte{ - "NodeOperator": envNodes.NonBootstraps().PeerIDs(), - }, - ) - require.NoError(t, err) - - return dEnv -} - -func NewEnvironmentWithJobsAndContracts(t *testing.T, tc *TestConfigs, tEnv TestEnvironment) DeployedEnv { - var err error - e := NewEnvironment(t, tc, tEnv) - allChains := e.Env.AllChainSelectors() - mcmsCfg := make(map[uint64]commontypes.MCMSWithTimelockConfig) - - for _, c := range e.Env.AllChainSelectors() { - mcmsCfg[c] = proposalutils.SingleGroupTimelockConfig(t) - } - var ( - usdcChains []uint64 - isMulticall3 bool - ) - if tc != nil { - if tc.IsUSDC { - usdcChains = allChains - } - isMulticall3 = tc.IsMultiCall3 - } - // Need to deploy prerequisites first so that we can form the USDC config - // no proposals to be made, timelock can be passed as nil here - e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, nil, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployLinkToken), - Config: allChains, - }, - { - Changeset: commonchangeset.WrapChangeSet(DeployPrerequisites), - Config: DeployPrerequisiteConfig{ - ChainSelectors: allChains, - Opts: []PrerequisiteOpt{ - WithUSDCChains(usdcChains), - WithMulticall3(isMulticall3), - }, - }, - }, - { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock), - Config: mcmsCfg, - }, - { - Changeset: commonchangeset.WrapChangeSet(DeployChainContracts), - Config: DeployChainContractsConfig{ - ChainSelectors: allChains, - HomeChainSelector: e.HomeChainSel, - }, - }, - { - Changeset: commonchangeset.WrapChangeSet(SetRMNRemoteOnRMNProxy), - Config: SetRMNRemoteOnRMNProxyConfig{ - ChainSelectors: allChains, - }, - }, - }) - require.NoError(t, err) - - state, err := LoadOnchainState(e.Env) - require.NoError(t, err) - // Assert USDC set up as expected. - for _, chain := range usdcChains { - require.NotNil(t, state.Chains[chain].MockUSDCTokenMessenger) - require.NotNil(t, state.Chains[chain].MockUSDCTransmitter) - require.NotNil(t, state.Chains[chain].USDCTokenPool) - } - // Assert link present - require.NotNil(t, state.Chains[e.FeedChainSel].LinkToken) - require.NotNil(t, state.Chains[e.FeedChainSel].Weth9) - - tokenConfig := NewTestTokenConfig(state.Chains[e.FeedChainSel].USDFeeds) - var tokenDataProviders []pluginconfig.TokenDataObserverConfig - if len(usdcChains) > 0 { - endpoint := tEnv.MockUSDCAttestationServer(t, tc.IsUSDCAttestationMissing) - cctpContracts := make(map[cciptypes.ChainSelector]pluginconfig.USDCCCTPTokenConfig) - for _, usdcChain := range usdcChains { - cctpContracts[cciptypes.ChainSelector(usdcChain)] = pluginconfig.USDCCCTPTokenConfig{ - SourcePoolAddress: state.Chains[usdcChain].USDCTokenPool.Address().String(), - SourceMessageTransmitterAddr: state.Chains[usdcChain].MockUSDCTransmitter.Address().String(), - } - } - tokenDataProviders = append(tokenDataProviders, pluginconfig.TokenDataObserverConfig{ - Type: pluginconfig.USDCCCTPHandlerType, - Version: "1.0", - USDCCCTPObserverConfig: &pluginconfig.USDCCCTPObserverConfig{ - Tokens: cctpContracts, - AttestationAPI: endpoint, - AttestationAPITimeout: commonconfig.MustNewDuration(time.Second), - AttestationAPIInterval: commonconfig.MustNewDuration(500 * time.Millisecond), - }}) - } - // Build the per chain config. - chainConfigs := make(map[uint64]CCIPOCRParams) - timelockContractsPerChain := make(map[uint64]*proposalutils.TimelockExecutionContracts) - for _, chain := range allChains { - timelockContractsPerChain[chain] = &proposalutils.TimelockExecutionContracts{ - Timelock: state.Chains[chain].Timelock, - CallProxy: state.Chains[chain].CallProxy, - } - tokenInfo := tokenConfig.GetTokenInfo(e.Env.Logger, state.Chains[chain].LinkToken, state.Chains[chain].Weth9) - ocrParams := DefaultOCRParams(e.FeedChainSel, tokenInfo, tokenDataProviders) - if tc.OCRConfigOverride != nil { - ocrParams = tc.OCRConfigOverride(ocrParams) - } - chainConfigs[chain] = ocrParams - } - // Deploy second set of changesets to deploy and configure the CCIP contracts. - e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, timelockContractsPerChain, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(ConfigureNewChains), - Config: NewChainsConfig{ - HomeChainSel: e.HomeChainSel, - FeedChainSel: e.FeedChainSel, - ChainConfigByChain: chainConfigs, - }, - }, - { - Changeset: commonchangeset.WrapChangeSet(CCIPCapabilityJobspec), - }, - }) - require.NoError(t, err) - - ReplayLogs(t, e.Env.Offchain, e.ReplayBlocks) - - state, err = LoadOnchainState(e.Env) - require.NoError(t, err) - require.NotNil(t, state.Chains[e.HomeChainSel].CapabilityRegistry) - require.NotNil(t, state.Chains[e.HomeChainSel].CCIPHome) - require.NotNil(t, state.Chains[e.HomeChainSel].RMNHome) - for _, chain := range allChains { - require.NotNil(t, state.Chains[chain].LinkToken) - require.NotNil(t, state.Chains[chain].Weth9) - require.NotNil(t, state.Chains[chain].TokenAdminRegistry) - require.NotNil(t, state.Chains[chain].RegistryModule) - require.NotNil(t, state.Chains[chain].Router) - require.NotNil(t, state.Chains[chain].RMNRemote) - require.NotNil(t, state.Chains[chain].TestRouter) - require.NotNil(t, state.Chains[chain].NonceManager) - require.NotNil(t, state.Chains[chain].FeeQuoter) - require.NotNil(t, state.Chains[chain].OffRamp) - require.NotNil(t, state.Chains[chain].OnRamp) - } - return e -} - -// NewEnvironmentWithJobs creates a new CCIP environment -// with capreg, fee tokens, feeds, nodes and jobs set up. -func NewEnvironmentWithJobs(t *testing.T, tc *TestConfigs, tEnv TestEnvironment) DeployedEnv { - e := NewEnvironment(t, tc, tEnv) - e.SetupJobs(t) - return e -} diff --git a/deployment/ccip/changeset/test_usdc_helpers.go b/deployment/ccip/changeset/test_usdc_helpers.go deleted file mode 100644 index 55f1bd25a36..00000000000 --- a/deployment/ccip/changeset/test_usdc_helpers.go +++ /dev/null @@ -1,260 +0,0 @@ -package changeset - -import ( - "math/big" - - "golang.org/x/sync/errgroup" - - "github.com/ethereum/go-ethereum/common" - - "github.com/smartcontractkit/chainlink-ccip/pkg/reader" - "github.com/smartcontractkit/chainlink-common/pkg/logger" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_usdc_token_messenger" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_usdc_token_transmitter" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/usdc_token_pool" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" -) - -func ConfigureUSDCTokenPools( - lggr logger.Logger, - chains map[uint64]deployment.Chain, - src, dst uint64, - state CCIPOnChainState, -) (*burn_mint_erc677.BurnMintERC677, *burn_mint_erc677.BurnMintERC677, error) { - srcToken := state.Chains[src].BurnMintTokens677[USDCSymbol] - dstToken := state.Chains[dst].BurnMintTokens677[USDCSymbol] - srcPool := state.Chains[src].USDCTokenPool - dstPool := state.Chains[dst].USDCTokenPool - - args := []struct { - sourceChain deployment.Chain - dstChainSel uint64 - state CCIPChainState - srcToken *burn_mint_erc677.BurnMintERC677 - srcPool *usdc_token_pool.USDCTokenPool - dstToken *burn_mint_erc677.BurnMintERC677 - dstPool *usdc_token_pool.USDCTokenPool - }{ - { - chains[src], - dst, - state.Chains[src], - srcToken, - srcPool, - dstToken, - dstPool, - }, - { - chains[dst], - src, - state.Chains[dst], - dstToken, - dstPool, - srcToken, - srcPool, - }, - } - - configurePoolGrp := errgroup.Group{} - for _, arg := range args { - configurePoolGrp.Go(configureSingleChain(lggr, arg.sourceChain, arg.dstChainSel, arg.state, arg.srcToken, arg.srcPool, arg.dstToken, arg.dstPool)) - } - if err := configurePoolGrp.Wait(); err != nil { - return nil, nil, err - } - return srcToken, dstToken, nil -} - -func configureSingleChain( - lggr logger.Logger, - sourceChain deployment.Chain, - dstChainSel uint64, - state CCIPChainState, - srcToken *burn_mint_erc677.BurnMintERC677, - srcPool *usdc_token_pool.USDCTokenPool, - dstToken *burn_mint_erc677.BurnMintERC677, - dstPool *usdc_token_pool.USDCTokenPool, -) func() error { - return func() error { - if err := attachTokenToTheRegistry(sourceChain, state, sourceChain.DeployerKey, srcToken.Address(), srcPool.Address()); err != nil { - lggr.Errorw("Failed to attach token to the registry", "err", err, "token", srcToken.Address(), "pool", srcPool.Address()) - return err - } - - if err := setUSDCTokenPoolCounterPart(sourceChain, srcPool, dstChainSel, sourceChain.DeployerKey, dstToken.Address(), dstPool.Address()); err != nil { - lggr.Errorw("Failed to set counter part", "err", err, "srcPool", srcPool.Address(), "dstPool", dstPool.Address()) - return err - } - - for _, addr := range []common.Address{ - srcPool.Address(), - state.MockUSDCTokenMessenger.Address(), - state.MockUSDCTransmitter.Address(), - } { - if err := grantMintBurnPermissions(lggr, sourceChain, srcToken, sourceChain.DeployerKey, addr); err != nil { - lggr.Errorw("Failed to grant mint/burn permissions", "err", err, "token", srcToken.Address(), "address", addr) - return err - } - } - return nil - } -} - -func UpdateFeeQuoterForUSDC( - lggr logger.Logger, - chain deployment.Chain, - state CCIPChainState, - dstChain uint64, - usdcToken *burn_mint_erc677.BurnMintERC677, -) error { - config := []fee_quoter.FeeQuoterTokenTransferFeeConfigArgs{ - { - DestChainSelector: dstChain, - TokenTransferFeeConfigs: []fee_quoter.FeeQuoterTokenTransferFeeConfigSingleTokenArgs{ - { - usdcToken.Address(), - fee_quoter.FeeQuoterTokenTransferFeeConfig{ - MinFeeUSDCents: 50, - MaxFeeUSDCents: 50_000, - DeciBps: 0, - DestGasOverhead: 180_000, - DestBytesOverhead: 640, - IsEnabled: true, - }, - }, - }, - }, - } - - tx, err := state.FeeQuoter.ApplyTokenTransferFeeConfigUpdates( - chain.DeployerKey, - config, - []fee_quoter.FeeQuoterTokenTransferFeeConfigRemoveArgs{}, - ) - if err != nil { - lggr.Errorw("Failed to apply token transfer fee config updates", "err", err, "config", config) - return err - } - - _, err = chain.Confirm(tx) - return err -} - -func DeployUSDC( - lggr logger.Logger, - chain deployment.Chain, - addresses deployment.AddressBook, - rmnProxy common.Address, - router common.Address, -) ( - *burn_mint_erc677.BurnMintERC677, - *usdc_token_pool.USDCTokenPool, - *mock_usdc_token_messenger.MockE2EUSDCTokenMessenger, - *mock_usdc_token_transmitter.MockE2EUSDCTransmitter, - error, -) { - token, err := deployment.DeployContract(lggr, chain, addresses, - func(chain deployment.Chain) deployment.ContractDeploy[*burn_mint_erc677.BurnMintERC677] { - tokenAddress, tx, tokenContract, err2 := burn_mint_erc677.DeployBurnMintERC677( - chain.DeployerKey, - chain.Client, - USDCName, - string(USDCSymbol), - UsdcDecimals, - big.NewInt(0), - ) - return deployment.ContractDeploy[*burn_mint_erc677.BurnMintERC677]{ - Address: tokenAddress, - Contract: tokenContract, - Tx: tx, - Tv: deployment.NewTypeAndVersion(USDCToken, deployment.Version1_0_0), - Err: err2, - } - }) - if err != nil { - lggr.Errorw("Failed to deploy USDC token", "chain", chain.String(), "err", err) - return nil, nil, nil, nil, err - } - - tx, err := token.Contract.GrantMintRole(chain.DeployerKey, chain.DeployerKey.From) - if err != nil { - lggr.Errorw("Failed to grant mint role", "chain", chain.String(), "token", token.Contract.Address(), "err", err) - return nil, nil, nil, nil, err - } - _, err = chain.Confirm(tx) - if err != nil { - return nil, nil, nil, nil, err - } - - transmitter, err := deployment.DeployContract(lggr, chain, addresses, - func(chain deployment.Chain) deployment.ContractDeploy[*mock_usdc_token_transmitter.MockE2EUSDCTransmitter] { - transmitterAddress, tx, transmitterContract, err2 := mock_usdc_token_transmitter.DeployMockE2EUSDCTransmitter( - chain.DeployerKey, - chain.Client, - 0, - reader.AllAvailableDomains()[chain.Selector], - token.Address, - ) - return deployment.ContractDeploy[*mock_usdc_token_transmitter.MockE2EUSDCTransmitter]{ - Address: transmitterAddress, - Contract: transmitterContract, - Tx: tx, - Tv: deployment.NewTypeAndVersion(USDCMockTransmitter, deployment.Version1_0_0), - Err: err2, - } - }) - if err != nil { - lggr.Errorw("Failed to deploy mock USDC transmitter", "chain", chain.String(), "err", err) - return nil, nil, nil, nil, err - } - - messenger, err := deployment.DeployContract(lggr, chain, addresses, - func(chain deployment.Chain) deployment.ContractDeploy[*mock_usdc_token_messenger.MockE2EUSDCTokenMessenger] { - messengerAddress, tx, messengerContract, err2 := mock_usdc_token_messenger.DeployMockE2EUSDCTokenMessenger( - chain.DeployerKey, - chain.Client, - 0, - transmitter.Address, - ) - return deployment.ContractDeploy[*mock_usdc_token_messenger.MockE2EUSDCTokenMessenger]{ - Address: messengerAddress, - Contract: messengerContract, - Tx: tx, - Tv: deployment.NewTypeAndVersion(USDCTokenMessenger, deployment.Version1_0_0), - Err: err2, - } - }) - if err != nil { - lggr.Errorw("Failed to deploy USDC token messenger", "chain", chain.String(), "err", err) - return nil, nil, nil, nil, err - } - - tokenPool, err := deployment.DeployContract(lggr, chain, addresses, - func(chain deployment.Chain) deployment.ContractDeploy[*usdc_token_pool.USDCTokenPool] { - tokenPoolAddress, tx, tokenPoolContract, err2 := usdc_token_pool.DeployUSDCTokenPool( - chain.DeployerKey, - chain.Client, - messenger.Address, - token.Address, - []common.Address{}, - rmnProxy, - router, - ) - return deployment.ContractDeploy[*usdc_token_pool.USDCTokenPool]{ - Address: tokenPoolAddress, - Contract: tokenPoolContract, - Tx: tx, - Tv: deployment.NewTypeAndVersion(USDCTokenPool, deployment.Version1_0_0), - Err: err2, - } - }) - if err != nil { - lggr.Errorw("Failed to deploy USDC token pool", "chain", chain.String(), "err", err) - return nil, nil, nil, nil, err - } - - return token.Contract, tokenPool.Contract, messenger.Contract, transmitter.Contract, nil -} diff --git a/deployment/ccip/changeset/test_assertions.go b/deployment/ccip/changeset/testhelpers/test_assertions.go similarity index 85% rename from deployment/ccip/changeset/test_assertions.go rename to deployment/ccip/changeset/testhelpers/test_assertions.go index a114e52b361..768788cef1a 100644 --- a/deployment/ccip/changeset/test_assertions.go +++ b/deployment/ccip/changeset/testhelpers/test_assertions.go @@ -1,7 +1,8 @@ -package changeset +package testhelpers import ( "context" + "errors" "fmt" "math/big" "sync" @@ -10,6 +11,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" @@ -17,6 +19,8 @@ import ( commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/deployment" @@ -27,7 +31,7 @@ import ( func ConfirmGasPriceUpdatedForAll( t *testing.T, e deployment.Environment, - state CCIPOnChainState, + state changeset.CCIPOnChainState, startBlocks map[uint64]*uint64, gasPrice *big.Int, ) { @@ -80,7 +84,7 @@ func ConfirmGasPriceUpdated( func ConfirmTokenPriceUpdatedForAll( t *testing.T, e deployment.Environment, - state CCIPOnChainState, + state changeset.CCIPOnChainState, startBlocks map[uint64]*uint64, linkPrice *big.Int, wethPrice *big.Int, @@ -165,7 +169,7 @@ type SourceDestPair struct { func ConfirmCommitForAllWithExpectedSeqNums( t *testing.T, e deployment.Environment, - state CCIPOnChainState, + state changeset.CCIPOnChainState, expectedSeqNums map[SourceDestPair]uint64, startBlocks map[uint64]*uint64, ) { @@ -265,7 +269,7 @@ func (c *commitReportTracker) allCommited(sourceChainSelector uint64) bool { func ConfirmMultipleCommits( t *testing.T, chains map[uint64]deployment.Chain, - state map[uint64]CCIPChainState, + state map[uint64]changeset.CCIPChainState, startBlocks map[uint64]*uint64, enforceSingleCommit bool, expectedSeqNums map[SourceDestPair]ccipocr3.SeqNumRange, @@ -359,12 +363,12 @@ func ConfirmCommitWithExpectedSeqNumRange( if mr.SourceChainSelector == src.Selector && uint64(expectedSeqNumRange.Start()) >= mr.MinSeqNr && uint64(expectedSeqNumRange.End()) <= mr.MaxSeqNr { - t.Logf("All sequence numbers commited in a single report [%d, %d]", expectedSeqNumRange.Start(), expectedSeqNumRange.End()) + t.Logf("All sequence numbers committed in a single report [%d, %d]", expectedSeqNumRange.Start(), expectedSeqNumRange.End()) return event, nil } if !enforceSingleCommit && seenMessages.allCommited(src.Selector) { - t.Logf("All sequence numbers already commited from range [%d, %d]", expectedSeqNumRange.Start(), expectedSeqNumRange.End()) + t.Logf("All sequence numbers already committed from range [%d, %d]", expectedSeqNumRange.Start(), expectedSeqNumRange.End()) return event, nil } } @@ -388,12 +392,12 @@ func ConfirmCommitWithExpectedSeqNumRange( if mr.SourceChainSelector == src.Selector && uint64(expectedSeqNumRange.Start()) >= mr.MinSeqNr && uint64(expectedSeqNumRange.End()) <= mr.MaxSeqNr { - t.Logf("All sequence numbers commited in a single report [%d, %d]", expectedSeqNumRange.Start(), expectedSeqNumRange.End()) + t.Logf("All sequence numbers committed in a single report [%d, %d]", expectedSeqNumRange.Start(), expectedSeqNumRange.End()) return report, nil } if !enforceSingleCommit && seenMessages.allCommited(src.Selector) { - t.Logf("All sequence numbers already commited from range [%d, %d]", expectedSeqNumRange.Start(), expectedSeqNumRange.End()) + t.Logf("All sequence numbers already committed from range [%d, %d]", expectedSeqNumRange.Start(), expectedSeqNumRange.End()) return report, nil } } @@ -411,7 +415,7 @@ func ConfirmCommitWithExpectedSeqNumRange( func ConfirmExecWithSeqNrsForAll( t *testing.T, e deployment.Environment, - state CCIPOnChainState, + state changeset.CCIPOnChainState, expectedSeqNums map[SourceDestPair][]uint64, startBlocks map[uint64]*uint64, ) (executionStates map[SourceDestPair]map[uint64]int) { @@ -481,10 +485,10 @@ func ConfirmExecWithSeqNrs( expectedSeqNrs []uint64, ) (executionStates map[uint64]int, err error) { if len(expectedSeqNrs) == 0 { - return nil, fmt.Errorf("no expected sequence numbers provided") + return nil, errors.New("no expected sequence numbers provided") } - timer := time.NewTimer(8 * time.Minute) + timer := time.NewTimer(tests.WaitTimeout(t)) defer timer.Stop() tick := time.NewTicker(3 * time.Second) defer tick.Stop() @@ -636,3 +640,57 @@ func executionStateToString(state uint8) string { return "UNKNOWN" } } + +func AssertEqualFeeConfig(t *testing.T, want, have fee_quoter.FeeQuoterDestChainConfig) { + assert.Equal(t, want.DestGasOverhead, have.DestGasOverhead) + assert.Equal(t, want.IsEnabled, have.IsEnabled) + assert.Equal(t, want.ChainFamilySelector, have.ChainFamilySelector) + assert.Equal(t, want.DefaultTokenDestGasOverhead, have.DefaultTokenDestGasOverhead) + assert.Equal(t, want.DefaultTokenFeeUSDCents, have.DefaultTokenFeeUSDCents) + assert.Equal(t, want.DefaultTxGasLimit, have.DefaultTxGasLimit) + assert.Equal(t, want.DestGasPerPayloadByteBase, have.DestGasPerPayloadByteBase) + assert.Equal(t, want.DestGasPerPayloadByteHigh, have.DestGasPerPayloadByteHigh) + assert.Equal(t, want.DestGasPerPayloadByteThreshold, have.DestGasPerPayloadByteThreshold) + assert.Equal(t, want.DestGasPerDataAvailabilityByte, have.DestGasPerDataAvailabilityByte) + assert.Equal(t, want.DestDataAvailabilityMultiplierBps, have.DestDataAvailabilityMultiplierBps) + assert.Equal(t, want.DestDataAvailabilityOverheadGas, have.DestDataAvailabilityOverheadGas) + assert.Equal(t, want.MaxDataBytes, have.MaxDataBytes) + assert.Equal(t, want.MaxNumberOfTokensPerMsg, have.MaxNumberOfTokensPerMsg) + assert.Equal(t, want.MaxPerMsgGasLimit, have.MaxPerMsgGasLimit) +} + +// AssertTimelockOwnership asserts that the ownership of the contracts has been transferred +// to the appropriate timelock contract on each chain. +func AssertTimelockOwnership( + t *testing.T, + e DeployedEnv, + chains []uint64, + state changeset.CCIPOnChainState, +) { + // check that the ownership has been transferred correctly + for _, chain := range chains { + for _, contract := range []common.Address{ + state.Chains[chain].OnRamp.Address(), + state.Chains[chain].OffRamp.Address(), + state.Chains[chain].FeeQuoter.Address(), + state.Chains[chain].NonceManager.Address(), + state.Chains[chain].RMNRemote.Address(), + } { + owner, _, err := commonchangeset.LoadOwnableContract(contract, e.Env.Chains[chain].Client) + require.NoError(t, err) + require.Equal(t, state.Chains[chain].Timelock.Address(), owner) + } + } + + // check home chain contracts ownership + homeChainTimelockAddress := state.Chains[e.HomeChainSel].Timelock.Address() + for _, contract := range []common.Address{ + state.Chains[e.HomeChainSel].CapabilityRegistry.Address(), + state.Chains[e.HomeChainSel].CCIPHome.Address(), + state.Chains[e.HomeChainSel].RMNHome.Address(), + } { + owner, _, err := commonchangeset.LoadOwnableContract(contract, e.Env.Chains[e.HomeChainSel].Client) + require.NoError(t, err) + require.Equal(t, homeChainTimelockAddress, owner) + } +} diff --git a/deployment/ccip/changeset/testhelpers/test_environment.go b/deployment/ccip/changeset/testhelpers/test_environment.go new file mode 100644 index 00000000000..ca58a067667 --- /dev/null +++ b/deployment/ccip/changeset/testhelpers/test_environment.go @@ -0,0 +1,694 @@ +package testhelpers + +import ( + "context" + "errors" + "math/big" + "os" + "testing" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + + "github.com/smartcontractkit/chainlink-ccip/chainconfig" + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink-ccip/pluginconfig" + commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" + + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" + + "github.com/smartcontractkit/chainlink/deployment" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" + commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" +) + +type EnvType string + +const ( + Memory EnvType = "in-memory" + Docker EnvType = "docker" + ENVTESTTYPE = "CCIP_V16_TEST_ENV" +) + +type TestConfigs struct { + Type EnvType // set by env var CCIP_V16_TEST_ENV, defaults to Memory + CreateJob bool + // TODO: This should be CreateContracts so the booleans make sense? + CreateJobAndContracts bool + PrerequisiteDeploymentOnly bool + V1_5Cfg changeset.V1_5DeploymentConfig + Chains int // only used in memory mode, for docker mode, this is determined by the integration-test config toml input + ChainIDs []uint64 // only used in memory mode, for docker mode, this is determined by the integration-test config toml input + NumOfUsersPerChain int // only used in memory mode, for docker mode, this is determined by the integration-test config toml input + Nodes int // only used in memory mode, for docker mode, this is determined by the integration-test config toml input + Bootstraps int // only used in memory mode, for docker mode, this is determined by the integration-test config toml input + IsUSDC bool + IsUSDCAttestationMissing bool + IsMultiCall3 bool + OCRConfigOverride func(*changeset.CCIPOCRParams) + RMNEnabled bool + NumOfRMNNodes int + LinkPrice *big.Int + WethPrice *big.Int +} + +func (tc *TestConfigs) Validate() error { + if tc.Chains < 2 { + return errors.New("chains must be at least 2") + } + if tc.Nodes < 4 { + return errors.New("nodes must be at least 4") + } + if tc.Bootstraps < 1 { + return errors.New("bootstraps must be at least 1") + } + if tc.Type == Memory && tc.RMNEnabled { + return errors.New("cannot run RMN tests in memory mode") + } + return nil +} + +func (tc *TestConfigs) MustSetEnvTypeOrDefault(t *testing.T) { + envType := os.Getenv(ENVTESTTYPE) + if envType == "" || envType == string(Memory) { + tc.Type = Memory + } else if envType == string(Docker) { + tc.Type = Docker + } else { + t.Fatalf("env var CCIP_V16_TEST_ENV must be either %s or %s, defaults to %s if unset, got: %s", Memory, Docker, Memory, envType) + } +} + +func DefaultTestConfigs() *TestConfigs { + return &TestConfigs{ + Chains: 2, + NumOfUsersPerChain: 1, + Nodes: 4, + Bootstraps: 1, + LinkPrice: changeset.MockLinkPrice, + WethPrice: changeset.MockWethPrice, + CreateJobAndContracts: true, + } +} + +type TestOps func(testCfg *TestConfigs) + +func WithMultiCall3() TestOps { + return func(testCfg *TestConfigs) { + testCfg.IsMultiCall3 = true + } +} + +func WithPrerequisiteDeploymentOnly(v1_5Cfg *changeset.V1_5DeploymentConfig) TestOps { + return func(testCfg *TestConfigs) { + testCfg.PrerequisiteDeploymentOnly = true + if v1_5Cfg != nil { + testCfg.V1_5Cfg = *v1_5Cfg + } + } +} + +func WithChainIDs(chainIDs []uint64) TestOps { + return func(testCfg *TestConfigs) { + testCfg.ChainIDs = chainIDs + } +} + +func WithJobsOnly() TestOps { + return func(testCfg *TestConfigs) { + testCfg.CreateJobAndContracts = false + testCfg.CreateJob = true + } +} + +func WithNoJobsAndContracts() TestOps { + return func(testCfg *TestConfigs) { + testCfg.CreateJobAndContracts = false + testCfg.CreateJob = false + } +} + +func WithRMNEnabled(numOfNode int) TestOps { + return func(testCfg *TestConfigs) { + testCfg.RMNEnabled = true + testCfg.NumOfRMNNodes = numOfNode + } +} + +func WithOCRConfigOverride(override func(*changeset.CCIPOCRParams)) TestOps { + return func(testCfg *TestConfigs) { + testCfg.OCRConfigOverride = override + } +} + +func WithUSDCAttestationMissing() TestOps { + return func(testCfg *TestConfigs) { + testCfg.IsUSDCAttestationMissing = true + } +} + +func WithUSDC() TestOps { + return func(testCfg *TestConfigs) { + testCfg.IsUSDC = true + } +} + +func WithNumOfChains(numChains int) TestOps { + return func(testCfg *TestConfigs) { + testCfg.Chains = numChains + } +} + +func WithNumOfUsersPerChain(numUsers int) TestOps { + return func(testCfg *TestConfigs) { + testCfg.NumOfUsersPerChain = numUsers + } +} + +func WithNumOfNodes(numNodes int) TestOps { + return func(testCfg *TestConfigs) { + testCfg.Nodes = numNodes + } +} + +func WithNumOfBootstrapNodes(numBootstraps int) TestOps { + return func(testCfg *TestConfigs) { + testCfg.Bootstraps = numBootstraps + } +} + +type TestEnvironment interface { + SetupJobs(t *testing.T) + StartNodes(t *testing.T, crConfig deployment.CapabilityRegistryConfig) + StartChains(t *testing.T) + TestConfigs() *TestConfigs + DeployedEnvironment() DeployedEnv + UpdateDeployedEnvironment(env DeployedEnv) + MockUSDCAttestationServer(t *testing.T, isUSDCAttestationMissing bool) string +} + +type DeployedEnv struct { + Env deployment.Environment + HomeChainSel uint64 + FeedChainSel uint64 + ReplayBlocks map[uint64]uint64 + Users map[uint64][]*bind.TransactOpts +} + +func (d *DeployedEnv) TimelockContracts(t *testing.T) map[uint64]*proposalutils.TimelockExecutionContracts { + timelocks := make(map[uint64]*proposalutils.TimelockExecutionContracts) + state, err := changeset.LoadOnchainState(d.Env) + require.NoError(t, err) + for chain, chainState := range state.Chains { + timelocks[chain] = &proposalutils.TimelockExecutionContracts{ + Timelock: chainState.Timelock, + CallProxy: chainState.CallProxy, + } + } + return timelocks +} + +func (d *DeployedEnv) SetupJobs(t *testing.T) { + ctx := testcontext.Get(t) + out, err := changeset.CCIPCapabilityJobspecChangeset(d.Env, struct{}{}) + require.NoError(t, err) + for nodeID, jobs := range out.JobSpecs { + for _, job := range jobs { + // Note these auto-accept + _, err := d.Env.Offchain.ProposeJob(ctx, + &jobv1.ProposeJobRequest{ + NodeId: nodeID, + Spec: job, + }) + require.NoError(t, err) + } + } + // Wait for plugins to register filters? + // TODO: Investigate how to avoid. + time.Sleep(30 * time.Second) + ReplayLogs(t, d.Env.Offchain, d.ReplayBlocks) +} + +type MemoryEnvironment struct { + DeployedEnv + TestConfig *TestConfigs + Chains map[uint64]deployment.Chain +} + +func (m *MemoryEnvironment) TestConfigs() *TestConfigs { + return m.TestConfig +} + +func (m *MemoryEnvironment) DeployedEnvironment() DeployedEnv { + return m.DeployedEnv +} + +func (m *MemoryEnvironment) UpdateDeployedEnvironment(env DeployedEnv) { + m.DeployedEnv = env +} + +func (m *MemoryEnvironment) StartChains(t *testing.T) { + ctx := testcontext.Get(t) + tc := m.TestConfig + var chains map[uint64]deployment.Chain + var users map[uint64][]*bind.TransactOpts + if len(tc.ChainIDs) > 0 { + chains, users = memory.NewMemoryChainsWithChainIDs(t, tc.ChainIDs, tc.NumOfUsersPerChain) + if tc.Chains > len(tc.ChainIDs) { + additionalChains, additionalUsers := memory.NewMemoryChains(t, tc.Chains-len(tc.ChainIDs), tc.NumOfUsersPerChain) + for k, v := range additionalChains { + chains[k] = v + } + for k, v := range additionalUsers { + users[k] = v + } + } + } else { + chains, users = memory.NewMemoryChains(t, tc.Chains, tc.NumOfUsersPerChain) + } + m.Chains = chains + homeChainSel, feedSel := allocateCCIPChainSelectors(chains) + replayBlocks, err := LatestBlocksByChain(ctx, chains) + require.NoError(t, err) + m.DeployedEnv = DeployedEnv{ + Env: deployment.Environment{ + Chains: m.Chains, + }, + HomeChainSel: homeChainSel, + FeedChainSel: feedSel, + ReplayBlocks: replayBlocks, + Users: users, + } +} + +func (m *MemoryEnvironment) StartNodes(t *testing.T, crConfig deployment.CapabilityRegistryConfig) { + require.NotNil(t, m.Chains, "start chains first, chains are empty") + require.NotNil(t, m.DeployedEnv, "start chains and initiate deployed env first before starting nodes") + tc := m.TestConfig + nodes := memory.NewNodes(t, zapcore.InfoLevel, m.Chains, tc.Nodes, tc.Bootstraps, crConfig) + ctx := testcontext.Get(t) + lggr := logger.Test(t) + for _, node := range nodes { + require.NoError(t, node.App.Start(ctx)) + t.Cleanup(func() { + require.NoError(t, node.App.Stop()) + }) + } + m.DeployedEnv.Env = memory.NewMemoryEnvironmentFromChainsNodes(func() context.Context { return ctx }, lggr, m.Chains, nodes) +} + +func (m *MemoryEnvironment) MockUSDCAttestationServer(t *testing.T, isUSDCAttestationMissing bool) string { + server := mockAttestationResponse(isUSDCAttestationMissing) + endpoint := server.URL + t.Cleanup(func() { + server.Close() + }) + return endpoint +} + +// NewMemoryEnvironment creates an in-memory environment based on the testconfig requested +func NewMemoryEnvironment(t *testing.T, opts ...TestOps) (DeployedEnv, TestEnvironment) { + testCfg := DefaultTestConfigs() + for _, opt := range opts { + opt(testCfg) + } + require.NoError(t, testCfg.Validate(), "invalid test config") + env := &MemoryEnvironment{ + TestConfig: testCfg, + } + if testCfg.PrerequisiteDeploymentOnly { + dEnv := NewEnvironmentWithPrerequisitesContracts(t, env) + env.UpdateDeployedEnvironment(dEnv) + return dEnv, env + } + if testCfg.CreateJobAndContracts { + dEnv := NewEnvironmentWithJobsAndContracts(t, env) + env.UpdateDeployedEnvironment(dEnv) + return dEnv, env + } + if testCfg.CreateJob { + dEnv := NewEnvironmentWithJobs(t, env) + env.UpdateDeployedEnvironment(dEnv) + return dEnv, env + } + dEnv := NewEnvironment(t, env) + env.UpdateDeployedEnvironment(dEnv) + return dEnv, env +} + +func NewEnvironmentWithPrerequisitesContracts(t *testing.T, tEnv TestEnvironment) DeployedEnv { + var err error + tc := tEnv.TestConfigs() + e := NewEnvironment(t, tEnv) + allChains := e.Env.AllChainSelectors() + + mcmsCfg := make(map[uint64]commontypes.MCMSWithTimelockConfig) + for _, c := range e.Env.AllChainSelectors() { + mcmsCfg[c] = proposalutils.SingleGroupTimelockConfig(t) + } + prereqCfg := make([]changeset.DeployPrerequisiteConfigPerChain, 0) + for _, chain := range allChains { + var opts []changeset.PrerequisiteOpt + if tc != nil { + if tc.IsUSDC { + opts = append(opts, changeset.WithUSDCEnabled()) + } + if tc.IsMultiCall3 { + opts = append(opts, changeset.WithMultiCall3Enabled()) + } + } + if tc.V1_5Cfg != (changeset.V1_5DeploymentConfig{}) { + opts = append(opts, changeset.WithLegacyDeploymentEnabled(tc.V1_5Cfg)) + } + prereqCfg = append(prereqCfg, changeset.DeployPrerequisiteConfigPerChain{ + ChainSelector: chain, + Opts: opts, + }) + } + + e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, nil, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployLinkToken), + Config: allChains, + }, + { + Changeset: commonchangeset.WrapChangeSet(changeset.DeployPrerequisitesChangeset), + Config: changeset.DeployPrerequisiteConfig{ + Configs: prereqCfg, + }, + }, + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock), + Config: mcmsCfg, + }, + }) + require.NoError(t, err) + tEnv.UpdateDeployedEnvironment(e) + return e +} + +func NewEnvironment(t *testing.T, tEnv TestEnvironment) DeployedEnv { + lggr := logger.Test(t) + tc := tEnv.TestConfigs() + tEnv.StartChains(t) + dEnv := tEnv.DeployedEnvironment() + require.NotEmpty(t, dEnv.FeedChainSel) + require.NotEmpty(t, dEnv.HomeChainSel) + require.NotEmpty(t, dEnv.Env.Chains) + ab := deployment.NewMemoryAddressBook() + crConfig := DeployTestContracts(t, lggr, ab, dEnv.HomeChainSel, dEnv.FeedChainSel, dEnv.Env.Chains, tc.LinkPrice, tc.WethPrice) + tEnv.StartNodes(t, crConfig) + dEnv = tEnv.DeployedEnvironment() + dEnv.Env.ExistingAddresses = ab + return dEnv +} + +func NewEnvironmentWithJobsAndContracts(t *testing.T, tEnv TestEnvironment) DeployedEnv { + var err error + tc := tEnv.TestConfigs() + e := NewEnvironment(t, tEnv) + allChains := e.Env.AllChainSelectors() + mcmsCfg := make(map[uint64]commontypes.MCMSWithTimelockConfig) + + for _, c := range e.Env.AllChainSelectors() { + mcmsCfg[c] = proposalutils.SingleGroupTimelockConfig(t) + } + + prereqCfg := make([]changeset.DeployPrerequisiteConfigPerChain, 0) + for _, chain := range allChains { + var opts []changeset.PrerequisiteOpt + if tc != nil { + if tc.IsUSDC { + opts = append(opts, changeset.WithUSDCEnabled()) + } + if tc.IsMultiCall3 { + opts = append(opts, changeset.WithMultiCall3Enabled()) + } + } + prereqCfg = append(prereqCfg, changeset.DeployPrerequisiteConfigPerChain{ + ChainSelector: chain, + Opts: opts, + }) + } + // Need to deploy prerequisites first so that we can form the USDC config + // no proposals to be made, timelock can be passed as nil here + e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, nil, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployLinkToken), + Config: allChains, + }, + { + Changeset: commonchangeset.WrapChangeSet(changeset.DeployPrerequisitesChangeset), + Config: changeset.DeployPrerequisiteConfig{ + Configs: prereqCfg, + }, + }, + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock), + Config: mcmsCfg, + }, + }) + require.NoError(t, err) + tEnv.UpdateDeployedEnvironment(e) + e = AddCCIPContractsToEnvironment(t, e.Env.AllChainSelectors(), tEnv, true, true, false) + // now we update RMNProxy to point to RMNRemote + e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, nil, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(changeset.SetRMNRemoteOnRMNProxyChangeset), + Config: changeset.SetRMNRemoteOnRMNProxyConfig{ + ChainSelectors: allChains, + }, + }, + }) + require.NoError(t, err) + return e +} + +func AddCCIPContractsToEnvironment(t *testing.T, allChains []uint64, tEnv TestEnvironment, deployJobs, deployHomeChain, mcmsEnabled bool) DeployedEnv { + tc := tEnv.TestConfigs() + e := tEnv.DeployedEnvironment() + envNodes, err := deployment.NodeInfo(e.Env.NodeIDs, e.Env.Offchain) + require.NoError(t, err) + + // Need to deploy prerequisites first so that we can form the USDC config + // no proposals to be made, timelock can be passed as nil here + var apps []commonchangeset.ChangesetApplication + if deployHomeChain { + apps = append(apps, commonchangeset.ChangesetApplication{ + Changeset: commonchangeset.WrapChangeSet(changeset.DeployHomeChainChangeset), + Config: changeset.DeployHomeChainConfig{ + HomeChainSel: e.HomeChainSel, + RMNDynamicConfig: NewTestRMNDynamicConfig(), + RMNStaticConfig: NewTestRMNStaticConfig(), + NodeOperators: NewTestNodeOperator(e.Env.Chains[e.HomeChainSel].DeployerKey.From), + NodeP2PIDsPerNodeOpAdmin: map[string][][32]byte{ + TestNodeOperator: envNodes.NonBootstraps().PeerIDs(), + }, + }, + }) + } + apps = append(apps, commonchangeset.ChangesetApplication{ + Changeset: commonchangeset.WrapChangeSet(changeset.DeployChainContractsChangeset), + Config: changeset.DeployChainContractsConfig{ + ChainSelectors: allChains, + HomeChainSelector: e.HomeChainSel, + }, + }) + e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, nil, apps) + require.NoError(t, err) + + state, err := changeset.LoadOnchainState(e.Env) + require.NoError(t, err) + // Assert link present + require.NotNil(t, state.Chains[e.FeedChainSel].LinkToken) + require.NotNil(t, state.Chains[e.FeedChainSel].Weth9) + + tokenConfig := changeset.NewTestTokenConfig(state.Chains[e.FeedChainSel].USDFeeds) + var tokenDataProviders []pluginconfig.TokenDataObserverConfig + if tc.IsUSDC { + endpoint := tEnv.MockUSDCAttestationServer(t, tc.IsUSDCAttestationMissing) + cctpContracts := make(map[cciptypes.ChainSelector]pluginconfig.USDCCCTPTokenConfig) + for _, usdcChain := range allChains { + require.NotNil(t, state.Chains[usdcChain].MockUSDCTokenMessenger) + require.NotNil(t, state.Chains[usdcChain].MockUSDCTransmitter) + require.NotNil(t, state.Chains[usdcChain].USDCTokenPool) + cctpContracts[cciptypes.ChainSelector(usdcChain)] = pluginconfig.USDCCCTPTokenConfig{ + SourcePoolAddress: state.Chains[usdcChain].USDCTokenPool.Address().String(), + SourceMessageTransmitterAddr: state.Chains[usdcChain].MockUSDCTransmitter.Address().String(), + } + } + tokenDataProviders = append(tokenDataProviders, pluginconfig.TokenDataObserverConfig{ + Type: pluginconfig.USDCCCTPHandlerType, + Version: "1.0", + USDCCCTPObserverConfig: &pluginconfig.USDCCCTPObserverConfig{ + Tokens: cctpContracts, + AttestationAPI: endpoint, + AttestationAPITimeout: commonconfig.MustNewDuration(time.Second), + AttestationAPIInterval: commonconfig.MustNewDuration(500 * time.Millisecond), + }}) + } + // Build the per chain config. + ocrConfigs := make(map[uint64]changeset.CCIPOCRParams) + chainConfigs := make(map[uint64]changeset.ChainConfig) + timelockContractsPerChain := make(map[uint64]*proposalutils.TimelockExecutionContracts) + nodeInfo, err := deployment.NodeInfo(e.Env.NodeIDs, e.Env.Offchain) + require.NoError(t, err) + for _, chain := range allChains { + timelockContractsPerChain[chain] = &proposalutils.TimelockExecutionContracts{ + Timelock: state.Chains[chain].Timelock, + CallProxy: state.Chains[chain].CallProxy, + } + tokenInfo := tokenConfig.GetTokenInfo(e.Env.Logger, state.Chains[chain].LinkToken, state.Chains[chain].Weth9) + ocrOverride := tc.OCRConfigOverride + if tc.RMNEnabled { + ocrOverride = func(ocrParams *changeset.CCIPOCRParams) { + if tc.OCRConfigOverride != nil { + tc.OCRConfigOverride(ocrParams) + } + ocrParams.CommitOffChainConfig.RMNEnabled = true + } + } + ocrParams := changeset.DeriveCCIPOCRParams( + changeset.WithDefaultCommitOffChainConfig(e.FeedChainSel, tokenInfo), + changeset.WithDefaultExecuteOffChainConfig(tokenDataProviders), + changeset.WithOCRParamOverride(ocrOverride), + ) + ocrConfigs[chain] = ocrParams + chainConfigs[chain] = changeset.ChainConfig{ + Readers: nodeInfo.NonBootstraps().PeerIDs(), + FChain: uint8(len(nodeInfo.NonBootstraps().PeerIDs()) / 3), + EncodableChainConfig: chainconfig.ChainConfig{ + GasPriceDeviationPPB: cciptypes.BigInt{Int: big.NewInt(internal.GasPriceDeviationPPB)}, + DAGasPriceDeviationPPB: cciptypes.BigInt{Int: big.NewInt(internal.DAGasPriceDeviationPPB)}, + OptimisticConfirmations: internal.OptimisticConfirmations, + }, + } + } + timelockContractsPerChain[e.HomeChainSel] = &proposalutils.TimelockExecutionContracts{ + Timelock: state.Chains[e.HomeChainSel].Timelock, + CallProxy: state.Chains[e.HomeChainSel].CallProxy, + } + // Apply second set of changesets to configure the CCIP contracts. + var mcmsConfig *changeset.MCMSConfig + if mcmsEnabled { + mcmsConfig = &changeset.MCMSConfig{ + MinDelay: 0, + } + } + apps = []commonchangeset.ChangesetApplication{ + { + // Add the chain configs for the new chains. + Changeset: commonchangeset.WrapChangeSet(changeset.UpdateChainConfigChangeset), + Config: changeset.UpdateChainConfigConfig{ + HomeChainSelector: e.HomeChainSel, + RemoteChainAdds: chainConfigs, + MCMS: mcmsConfig, + }, + }, + { + // Add the DONs and candidate commit OCR instances for the chain. + Changeset: commonchangeset.WrapChangeSet(changeset.AddDonAndSetCandidateChangeset), + Config: changeset.AddDonAndSetCandidateChangesetConfig{ + SetCandidateConfigBase: changeset.SetCandidateConfigBase{ + HomeChainSelector: e.HomeChainSel, + FeedChainSelector: e.FeedChainSel, + MCMS: mcmsConfig, + }, + PluginInfo: changeset.SetCandidatePluginInfo{ + OCRConfigPerRemoteChainSelector: ocrConfigs, + PluginType: types.PluginTypeCCIPCommit, + }, + }, + }, + { + // Add the exec OCR instances for the new chains. + Changeset: commonchangeset.WrapChangeSet(changeset.SetCandidateChangeset), + Config: changeset.SetCandidateChangesetConfig{ + SetCandidateConfigBase: changeset.SetCandidateConfigBase{ + HomeChainSelector: e.HomeChainSel, + FeedChainSelector: e.FeedChainSel, + MCMS: mcmsConfig, + }, + PluginInfo: []changeset.SetCandidatePluginInfo{ + { + OCRConfigPerRemoteChainSelector: ocrConfigs, + PluginType: types.PluginTypeCCIPExec, + }, + }, + }, + }, + { + // Promote everything + Changeset: commonchangeset.WrapChangeSet(changeset.PromoteCandidateChangeset), + Config: changeset.PromoteCandidateChangesetConfig{ + HomeChainSelector: e.HomeChainSel, + PluginInfo: []changeset.PromoteCandidatePluginInfo{ + { + PluginType: types.PluginTypeCCIPCommit, + RemoteChainSelectors: allChains, + }, + { + PluginType: types.PluginTypeCCIPExec, + RemoteChainSelectors: allChains, + }, + }, + MCMS: mcmsConfig, + }, + }, + { + // Enable the OCR config on the remote chains. + Changeset: commonchangeset.WrapChangeSet(changeset.SetOCR3OffRampChangeset), + Config: changeset.SetOCR3OffRampConfig{ + HomeChainSel: e.HomeChainSel, + RemoteChainSels: allChains, + }, + }, + } + if deployJobs { + apps = append(apps, commonchangeset.ChangesetApplication{ + Changeset: commonchangeset.WrapChangeSet(changeset.CCIPCapabilityJobspecChangeset), + }) + } + e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, timelockContractsPerChain, apps) + require.NoError(t, err) + + ReplayLogs(t, e.Env.Offchain, e.ReplayBlocks) + + state, err = changeset.LoadOnchainState(e.Env) + require.NoError(t, err) + require.NotNil(t, state.Chains[e.HomeChainSel].CapabilityRegistry) + require.NotNil(t, state.Chains[e.HomeChainSel].CCIPHome) + require.NotNil(t, state.Chains[e.HomeChainSel].RMNHome) + for _, chain := range allChains { + require.NotNil(t, state.Chains[chain].LinkToken) + require.NotNil(t, state.Chains[chain].Weth9) + require.NotNil(t, state.Chains[chain].TokenAdminRegistry) + require.NotNil(t, state.Chains[chain].RegistryModule) + require.NotNil(t, state.Chains[chain].Router) + require.NotNil(t, state.Chains[chain].RMNRemote) + require.NotNil(t, state.Chains[chain].TestRouter) + require.NotNil(t, state.Chains[chain].NonceManager) + require.NotNil(t, state.Chains[chain].FeeQuoter) + require.NotNil(t, state.Chains[chain].OffRamp) + require.NotNil(t, state.Chains[chain].OnRamp) + } + tEnv.UpdateDeployedEnvironment(e) + return e +} + +// NewEnvironmentWithJobs creates a new CCIP environment +// with capreg, fee tokens, feeds, nodes and jobs set up. +func NewEnvironmentWithJobs(t *testing.T, tEnv TestEnvironment) DeployedEnv { + e := NewEnvironment(t, tEnv) + e.SetupJobs(t) + return e +} diff --git a/deployment/ccip/changeset/test_helpers.go b/deployment/ccip/changeset/testhelpers/test_helpers.go similarity index 83% rename from deployment/ccip/changeset/test_helpers.go rename to deployment/ccip/changeset/testhelpers/test_helpers.go index 75801d99cff..dcfba1fad9e 100644 --- a/deployment/ccip/changeset/test_helpers.go +++ b/deployment/ccip/changeset/testhelpers/test_helpers.go @@ -1,4 +1,4 @@ -package changeset +package testhelpers import ( "context" @@ -18,6 +18,10 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/pkg/errors" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/ethereum/go-ethereum/common" @@ -40,13 +44,13 @@ import ( "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/burn_mint_token_pool" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_v3_aggregator_contract" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/usdc_token_pool" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/aggregator_v3_interface" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_ethusd_aggregator_wrapper" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/aggregator_v3_interface" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/mock_v3_aggregator_contract" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" ) @@ -60,6 +64,10 @@ var ( evmExtraArgsV2Tag = hexutil.MustDecode("0x181dcf10") routerABI = abihelpers.MustParseABI(router.RouterABI) + + DefaultLinkPrice = deployment.E18Mult(20) + DefaultWethPrice = deployment.E18Mult(4000) + DefaultGasPrice = ToPackedFee(big.NewInt(8e14), big.NewInt(0)) ) // Context returns a context with the test's deadline, if available. @@ -99,11 +107,16 @@ func DeployTestContracts(t *testing.T, linkPrice *big.Int, wethPrice *big.Int, ) deployment.CapabilityRegistryConfig { - capReg, err := deployCapReg(lggr, - // deploying cap reg for the first time on a blank chain state - CCIPOnChainState{ - Chains: make(map[uint64]CCIPChainState), - }, ab, chains[homeChainSel]) + capReg, err := deployment.DeployContract(lggr, chains[homeChainSel], ab, + func(chain deployment.Chain) deployment.ContractDeploy[*capabilities_registry.CapabilitiesRegistry] { + crAddr, tx, cr, err2 := capabilities_registry.DeployCapabilitiesRegistry( + chain.DeployerKey, + chain.Client, + ) + return deployment.ContractDeploy[*capabilities_registry.CapabilitiesRegistry]{ + Address: crAddr, Contract: cr, Tv: deployment.NewTypeAndVersion(changeset.CapabilitiesRegistry, deployment.Version1_0_0), Tx: tx, Err: err2, + } + }) require.NoError(t, err) _, err = DeployFeeds(lggr, ab, chains[feedChainSel], linkPrice, wethPrice) @@ -172,7 +185,7 @@ func mockAttestationResponse(isFaulty bool) *httptest.Server { func CCIPSendRequest( e deployment.Environment, - state CCIPOnChainState, + state changeset.CCIPOnChainState, cfg *CCIPSendReqConfig, ) (*types.Transaction, uint64, error) { msg := router.ClientEVM2AnyMessage{ @@ -260,7 +273,7 @@ func CCIPSendCalldata( func TestSendRequest( t *testing.T, e deployment.Environment, - state CCIPOnChainState, + state changeset.CCIPOnChainState, src, dest uint64, testRouter bool, evm2AnyMessage router.ClientEVM2AnyMessage, @@ -319,7 +332,7 @@ func WithDestChain(destChain uint64) SendReqOpts { func DoSendRequest( t *testing.T, e deployment.Environment, - state CCIPOnChainState, + state changeset.CCIPOnChainState, opts ...SendReqOpts, ) (*onramp.OnRampCCIPMessageSent, error) { cfg := &CCIPSendReqConfig{} @@ -347,7 +360,7 @@ func DoSendRequest( } require.True(t, it.Next()) - t.Logf("CCIP message (id %x) sent from chain selector %d to chain selector %d tx %s seqNum %d nonce %d sender %s", + t.Logf("CCIP message (id %x) sent from chain selector %d to chain selector %d tx %s seqNum %d nonce %d sender %s testRouterEnabled %t", it.Event.Message.Header.MessageId[:], cfg.SourceChain, cfg.DestChain, @@ -355,6 +368,7 @@ func DoSendRequest( it.Event.SequenceNumber, it.Event.Message.Header.Nonce, it.Event.Message.Sender.String(), + cfg.IsTestRouter, ) return it.Event, nil } @@ -384,30 +398,114 @@ func MakeEVMExtraArgsV2(gasLimit uint64, allowOOO bool) []byte { return extraArgs } -func AddLaneWithDefaultPricesAndFeeQuoterConfig(e deployment.Environment, state CCIPOnChainState, from, to uint64, isTestRouter bool) error { - cfg := LaneConfig{ - SourceSelector: from, - DestSelector: to, - InitialPricesBySource: DefaultInitialPrices, - FeeQuoterDestChain: DefaultFeeQuoterDestChainConfig(), - } - return addLane(e, state, cfg, isTestRouter) +func AddLane( + t *testing.T, + e *DeployedEnv, + from, to uint64, + isTestRouter bool, + gasprice map[uint64]*big.Int, + tokenPrices map[common.Address]*big.Int, + fqCfg fee_quoter.FeeQuoterDestChainConfig, +) { + var err error + e.Env, err = commoncs.ApplyChangesets(t, e.Env, e.TimelockContracts(t), []commoncs.ChangesetApplication{ + { + Changeset: commoncs.WrapChangeSet(changeset.UpdateOnRampsDestsChangeset), + Config: changeset.UpdateOnRampDestsConfig{ + UpdatesByChain: map[uint64]map[uint64]changeset.OnRampDestinationUpdate{ + from: { + to: { + IsEnabled: true, + TestRouter: isTestRouter, + AllowListEnabled: false, + }, + }, + }, + }, + }, + { + Changeset: commoncs.WrapChangeSet(changeset.UpdateFeeQuoterPricesChangeset), + Config: changeset.UpdateFeeQuoterPricesConfig{ + PricesByChain: map[uint64]changeset.FeeQuoterPriceUpdatePerSource{ + from: { + TokenPrices: tokenPrices, + GasPrices: gasprice, + }, + }, + }, + }, + { + Changeset: commoncs.WrapChangeSet(changeset.UpdateFeeQuoterDestsChangeset), + Config: changeset.UpdateFeeQuoterDestsConfig{ + UpdatesByChain: map[uint64]map[uint64]fee_quoter.FeeQuoterDestChainConfig{ + from: { + to: fqCfg, + }, + }, + }, + }, + { + Changeset: commoncs.WrapChangeSet(changeset.UpdateOffRampSourcesChangeset), + Config: changeset.UpdateOffRampSourcesConfig{ + UpdatesByChain: map[uint64]map[uint64]changeset.OffRampSourceUpdate{ + to: { + from: { + IsEnabled: true, + TestRouter: isTestRouter, + }, + }, + }, + }, + }, + { + Changeset: commoncs.WrapChangeSet(changeset.UpdateRouterRampsChangeset), + Config: changeset.UpdateRouterRampsConfig{ + TestRouter: isTestRouter, + UpdatesByChain: map[uint64]changeset.RouterUpdates{ + // onRamp update on source chain + from: { + OnRampUpdates: map[uint64]bool{ + to: true, + }, + }, + // offramp update on dest chain + to: { + OffRampUpdates: map[uint64]bool{ + from: true, + }, + }, + }, + }, + }, + }) + require.NoError(t, err) +} + +func AddLaneWithDefaultPricesAndFeeQuoterConfig(t *testing.T, e *DeployedEnv, state changeset.CCIPOnChainState, from, to uint64, isTestRouter bool) { + stateChainFrom := state.Chains[from] + AddLane( + t, + e, + from, to, + isTestRouter, + map[uint64]*big.Int{ + to: DefaultGasPrice, + }, map[common.Address]*big.Int{ + stateChainFrom.LinkToken.Address(): DefaultLinkPrice, + stateChainFrom.Weth9.Address(): DefaultWethPrice, + }, changeset.DefaultFeeQuoterDestChainConfig()) } // AddLanesForAll adds densely connected lanes for all chains in the environment so that each chain // is connected to every other chain except itself. -func AddLanesForAll(e deployment.Environment, state CCIPOnChainState) error { - for source := range e.Chains { - for dest := range e.Chains { +func AddLanesForAll(t *testing.T, e *DeployedEnv, state changeset.CCIPOnChainState) { + for source := range e.Env.Chains { + for dest := range e.Env.Chains { if source != dest { - err := AddLaneWithDefaultPricesAndFeeQuoterConfig(e, state, source, dest, false) - if err != nil { - return err - } + AddLaneWithDefaultPricesAndFeeQuoterConfig(t, e, state, source, dest, false) } } } - return nil } func ToPackedFee(execFee, daFee *big.Int) *big.Int { @@ -415,35 +513,6 @@ func ToPackedFee(execFee, daFee *big.Int) *big.Int { return new(big.Int).Or(daShifted, execFee) } -const ( - // MockLinkAggregatorDescription This is the description of the MockV3Aggregator.sol contract - //nolint:lll - // https://github.com/smartcontractkit/chainlink/blob/a348b98e90527520049c580000a86fb8ceff7fa7/contracts/src/v0.8/tests/MockV3Aggregator.sol#L76-L76 - MockLinkAggregatorDescription = "v0.8/tests/MockV3Aggregator.sol" - // MockWETHAggregatorDescription WETH use description from MockETHUSDAggregator.sol - //nolint:lll - // https://github.com/smartcontractkit/chainlink/blob/a348b98e90527520049c580000a86fb8ceff7fa7/contracts/src/v0.8/automation/testhelpers/MockETHUSDAggregator.sol#L19-L19 - MockWETHAggregatorDescription = "MockETHUSDAggregator" -) - -var ( - MockLinkPrice = deployment.E18Mult(500) - MockWethPrice = big.NewInt(9e8) - // MockDescriptionToTokenSymbol maps a mock feed description to token descriptor - MockDescriptionToTokenSymbol = map[string]TokenSymbol{ - MockLinkAggregatorDescription: LinkSymbol, - MockWETHAggregatorDescription: WethSymbol, - } - MockSymbolToDescription = map[TokenSymbol]string{ - LinkSymbol: MockLinkAggregatorDescription, - WethSymbol: MockWETHAggregatorDescription, - } - MockSymbolToDecimals = map[TokenSymbol]uint8{ - LinkSymbol: LinkDecimals, - WethSymbol: WethDecimals, - } -) - func DeployFeeds( lggr logger.Logger, ab deployment.AddressBook, @@ -451,13 +520,13 @@ func DeployFeeds( linkPrice *big.Int, wethPrice *big.Int, ) (map[string]common.Address, error) { - linkTV := deployment.NewTypeAndVersion(PriceFeed, deployment.Version1_0_0) + linkTV := deployment.NewTypeAndVersion(changeset.PriceFeed, deployment.Version1_0_0) mockLinkFeed := func(chain deployment.Chain) deployment.ContractDeploy[*aggregator_v3_interface.AggregatorV3Interface] { linkFeed, tx, _, err1 := mock_v3_aggregator_contract.DeployMockV3Aggregator( chain.DeployerKey, chain.Client, - LinkDecimals, // decimals - linkPrice, // initialAnswer + changeset.LinkDecimals, // decimals + linkPrice, // initialAnswer ) aggregatorCr, err2 := aggregator_v3_interface.NewAggregatorV3Interface(linkFeed, chain.Client) @@ -479,12 +548,12 @@ func DeployFeeds( } } - linkFeedAddress, linkFeedDescription, err := deploySingleFeed(lggr, ab, chain, mockLinkFeed, LinkSymbol) + linkFeedAddress, linkFeedDescription, err := deploySingleFeed(lggr, ab, chain, mockLinkFeed, changeset.LinkSymbol) if err != nil { return nil, err } - wethFeedAddress, wethFeedDescription, err := deploySingleFeed(lggr, ab, chain, mockWethFeed, WethSymbol) + wethFeedAddress, wethFeedDescription, err := deploySingleFeed(lggr, ab, chain, mockWethFeed, changeset.WethSymbol) if err != nil { return nil, err } @@ -502,9 +571,9 @@ func deploySingleFeed( ab deployment.AddressBook, chain deployment.Chain, deployFunc func(deployment.Chain) deployment.ContractDeploy[*aggregator_v3_interface.AggregatorV3Interface], - symbol TokenSymbol, + symbol changeset.TokenSymbol, ) (common.Address, string, error) { - //tokenTV := deployment.NewTypeAndVersion(PriceFeed, deployment.Version1_0_0) + // tokenTV := deployment.NewTypeAndVersion(PriceFeed, deployment.Version1_0_0) mockTokenFeed, err := deployment.DeployContract(lggr, chain, ab, deployFunc) if err != nil { lggr.Errorw("Failed to deploy token feed", "err", err, "symbol", symbol) @@ -519,7 +588,7 @@ func deploySingleFeed( return common.Address{}, "", err } - if desc != MockSymbolToDescription[symbol] { + if desc != changeset.MockSymbolToDescription[symbol] { lggr.Errorw("Unexpected description for token", "symbol", symbol, "desc", desc) return common.Address{}, "", fmt.Errorf("unexpected description: %s", desc) } @@ -527,7 +596,7 @@ func deploySingleFeed( return mockTokenFeed.Address, desc, nil } -func ConfirmRequestOnSourceAndDest(t *testing.T, env deployment.Environment, state CCIPOnChainState, sourceCS, destCS, expectedSeqNr uint64) error { +func ConfirmRequestOnSourceAndDest(t *testing.T, env deployment.Environment, state changeset.CCIPOnChainState, sourceCS, destCS, expectedSeqNr uint64) error { latesthdr, err := env.Chains[destCS].Client.HeaderByNumber(testcontext.Get(t), nil) require.NoError(t, err) startBlock := latesthdr.Number.Uint64() @@ -571,7 +640,7 @@ func DeployTransferableToken( chains map[uint64]deployment.Chain, src, dst uint64, srcActor, dstActor *bind.TransactOpts, - state CCIPOnChainState, + state changeset.CCIPOnChainState, addresses deployment.AddressBook, token string, ) (*burn_mint_erc677.BurnMintERC677, *burn_mint_token_pool.BurnMintTokenPool, *burn_mint_erc677.BurnMintERC677, *burn_mint_token_pool.BurnMintTokenPool, error) { @@ -615,7 +684,7 @@ func deployTokenPoolsInParallel( chains map[uint64]deployment.Chain, src, dst uint64, srcActor, dstActor *bind.TransactOpts, - state CCIPOnChainState, + state changeset.CCIPOnChainState, addresses deployment.AddressBook, token string, ) ( @@ -658,7 +727,7 @@ func deployTokenPoolsInParallel( return nil, nil, nil, nil, err } if srcToken == nil || srcPool == nil || dstToken == nil || dstPool == nil { - return nil, nil, nil, nil, fmt.Errorf("failed to deploy token and pool") + return nil, nil, nil, nil, errors.New("failed to deploy token and pool") } return srcToken, srcPool, dstToken, dstPool, nil } @@ -685,7 +754,7 @@ func setUSDCTokenPoolCounterPart( var fixedAddr [32]byte copy(fixedAddr[:], allowedCaller[:32]) - domain, _ := reader.AllAvailableDomains()[destChainSelector] + domain := reader.AllAvailableDomains()[destChainSelector] domains := []usdc_token_pool.USDCTokenPoolDomainUpdate{ { @@ -759,7 +828,7 @@ func setTokenPoolCounterPart(chain deployment.Chain, tokenPool *burn_mint_token_ func attachTokenToTheRegistry( chain deployment.Chain, - state CCIPChainState, + state changeset.CCIPChainState, owner *bind.TransactOpts, token common.Address, tokenPool common.Address, @@ -815,10 +884,10 @@ func deployTransferTokenOneEnd( return nil, nil, err } for address, v := range chainAddresses { - if deployment.NewTypeAndVersion(ARMProxy, deployment.Version1_0_0) == v { + if deployment.NewTypeAndVersion(changeset.ARMProxy, deployment.Version1_0_0) == v { rmnAddress = address } - if deployment.NewTypeAndVersion(Router, deployment.Version1_2_0) == v { + if deployment.NewTypeAndVersion(changeset.Router, deployment.Version1_2_0) == v { routerAddress = address } if rmnAddress != "" && routerAddress != "" { @@ -839,7 +908,7 @@ func deployTransferTokenOneEnd( big.NewInt(0).Mul(big.NewInt(1e9), big.NewInt(1e18)), ) return deployment.ContractDeploy[*burn_mint_erc677.BurnMintERC677]{ - tokenAddress, token, tx, deployment.NewTypeAndVersion(BurnMintToken, deployment.Version1_0_0), err2, + Address: tokenAddress, Contract: token, Tx: tx, Tv: deployment.NewTypeAndVersion(changeset.BurnMintToken, deployment.Version1_0_0), Err: err2, } }) if err != nil { @@ -868,7 +937,7 @@ func deployTransferTokenOneEnd( common.HexToAddress(routerAddress), ) return deployment.ContractDeploy[*burn_mint_token_pool.BurnMintTokenPool]{ - tokenPoolAddress, tokenPoolContract, tx, deployment.NewTypeAndVersion(BurnMintTokenPool, deployment.Version1_5_1), err2, + Address: tokenPoolAddress, Contract: tokenPoolContract, Tx: tx, Tv: deployment.NewTypeAndVersion(changeset.BurnMintTokenPool, deployment.Version1_5_1), Err: err2, } }) if err != nil { @@ -897,7 +966,7 @@ func NewMintTokenWithCustomSender(auth *bind.TransactOpts, sender *bind.Transact func MintAndAllow( t *testing.T, e deployment.Environment, - state CCIPOnChainState, + state changeset.CCIPOnChainState, tokenMap map[uint64][]MintTokenInfo, ) { configurePoolGrp := errgroup.Group{} @@ -940,7 +1009,7 @@ func Transfer( ctx context.Context, t *testing.T, env deployment.Environment, - state CCIPOnChainState, + state changeset.CCIPOnChainState, sourceChain, destChain uint64, tokens []router.ClientEVMTokenAmount, receiver common.Address, @@ -986,7 +1055,7 @@ func TransferMultiple( ctx context.Context, t *testing.T, env deployment.Environment, - state CCIPOnChainState, + state changeset.CCIPOnChainState, requests []TestTransferRequest, ) ( map[uint64]*uint64, @@ -1040,7 +1109,7 @@ func TransferAndWaitForSuccess( ctx context.Context, t *testing.T, env deployment.Environment, - state CCIPOnChainState, + state changeset.CCIPOnChainState, sourceChain, destChain uint64, tokens []router.ClientEVMTokenAmount, receiver common.Address, @@ -1179,3 +1248,41 @@ func DefaultRouterMessage(receiverAddress common.Address) router.ClientEVM2AnyMe ExtraArgs: nil, } } + +func GenTestTransferOwnershipConfig( + e DeployedEnv, + chains []uint64, + state changeset.CCIPOnChainState, +) commoncs.TransferToMCMSWithTimelockConfig { + var ( + timelocksPerChain = make(map[uint64]common.Address) + contracts = make(map[uint64][]common.Address) + ) + + // chain contracts + for _, chain := range chains { + timelocksPerChain[chain] = state.Chains[chain].Timelock.Address() + contracts[chain] = []common.Address{ + state.Chains[chain].OnRamp.Address(), + state.Chains[chain].OffRamp.Address(), + state.Chains[chain].FeeQuoter.Address(), + state.Chains[chain].NonceManager.Address(), + state.Chains[chain].RMNRemote.Address(), + state.Chains[chain].TestRouter.Address(), + state.Chains[chain].Router.Address(), + } + } + + // home chain + homeChainTimelockAddress := state.Chains[e.HomeChainSel].Timelock.Address() + timelocksPerChain[e.HomeChainSel] = homeChainTimelockAddress + contracts[e.HomeChainSel] = append(contracts[e.HomeChainSel], + state.Chains[e.HomeChainSel].CapabilityRegistry.Address(), + state.Chains[e.HomeChainSel].CCIPHome.Address(), + state.Chains[e.HomeChainSel].RMNHome.Address(), + ) + + return commoncs.TransferToMCMSWithTimelockConfig{ + ContractsByChain: contracts, + } +} diff --git a/deployment/ccip/changeset/test_params.go b/deployment/ccip/changeset/testhelpers/test_params.go similarity index 85% rename from deployment/ccip/changeset/test_params.go rename to deployment/ccip/changeset/testhelpers/test_params.go index eea0f8eb183..8e43c08919f 100644 --- a/deployment/ccip/changeset/test_params.go +++ b/deployment/ccip/changeset/testhelpers/test_params.go @@ -1,10 +1,14 @@ -package changeset +package testhelpers import ( "github.com/ethereum/go-ethereum/common" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" +) + +const ( + TestNodeOperator = "NodeOperator" ) func NewTestRMNStaticConfig() rmn_home.RMNHomeStaticConfig { @@ -25,7 +29,7 @@ func NewTestNodeOperator(admin common.Address) []capabilities_registry.Capabilit return []capabilities_registry.CapabilitiesRegistryNodeOperator{ { Admin: admin, - Name: "NodeOperator", + Name: TestNodeOperator, }, } } diff --git a/deployment/ccip/changeset/testhelpers/test_usdc_helpers.go b/deployment/ccip/changeset/testhelpers/test_usdc_helpers.go new file mode 100644 index 00000000000..ebaa3b8ec37 --- /dev/null +++ b/deployment/ccip/changeset/testhelpers/test_usdc_helpers.go @@ -0,0 +1,140 @@ +package testhelpers + +import ( + "golang.org/x/sync/errgroup" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/usdc_token_pool" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" +) + +func ConfigureUSDCTokenPools( + lggr logger.Logger, + chains map[uint64]deployment.Chain, + src, dst uint64, + state changeset.CCIPOnChainState, +) (*burn_mint_erc677.BurnMintERC677, *burn_mint_erc677.BurnMintERC677, error) { + srcToken := state.Chains[src].BurnMintTokens677[changeset.USDCSymbol] + dstToken := state.Chains[dst].BurnMintTokens677[changeset.USDCSymbol] + srcPool := state.Chains[src].USDCTokenPool + dstPool := state.Chains[dst].USDCTokenPool + + args := []struct { + sourceChain deployment.Chain + dstChainSel uint64 + state changeset.CCIPChainState + srcToken *burn_mint_erc677.BurnMintERC677 + srcPool *usdc_token_pool.USDCTokenPool + dstToken *burn_mint_erc677.BurnMintERC677 + dstPool *usdc_token_pool.USDCTokenPool + }{ + { + chains[src], + dst, + state.Chains[src], + srcToken, + srcPool, + dstToken, + dstPool, + }, + { + chains[dst], + src, + state.Chains[dst], + dstToken, + dstPool, + srcToken, + srcPool, + }, + } + + configurePoolGrp := errgroup.Group{} + for _, arg := range args { + configurePoolGrp.Go(configureSingleChain(lggr, arg.sourceChain, arg.dstChainSel, arg.state, arg.srcToken, arg.srcPool, arg.dstToken, arg.dstPool)) + } + if err := configurePoolGrp.Wait(); err != nil { + return nil, nil, err + } + return srcToken, dstToken, nil +} + +func configureSingleChain( + lggr logger.Logger, + sourceChain deployment.Chain, + dstChainSel uint64, + state changeset.CCIPChainState, + srcToken *burn_mint_erc677.BurnMintERC677, + srcPool *usdc_token_pool.USDCTokenPool, + dstToken *burn_mint_erc677.BurnMintERC677, + dstPool *usdc_token_pool.USDCTokenPool, +) func() error { + return func() error { + if err := attachTokenToTheRegistry(sourceChain, state, sourceChain.DeployerKey, srcToken.Address(), srcPool.Address()); err != nil { + lggr.Errorw("Failed to attach token to the registry", "err", err, "token", srcToken.Address(), "pool", srcPool.Address()) + return err + } + + if err := setUSDCTokenPoolCounterPart(sourceChain, srcPool, dstChainSel, sourceChain.DeployerKey, dstToken.Address(), dstPool.Address()); err != nil { + lggr.Errorw("Failed to set counter part", "err", err, "srcPool", srcPool.Address(), "dstPool", dstPool.Address()) + return err + } + + for _, addr := range []common.Address{ + srcPool.Address(), + state.MockUSDCTokenMessenger.Address(), + state.MockUSDCTransmitter.Address(), + } { + if err := grantMintBurnPermissions(lggr, sourceChain, srcToken, sourceChain.DeployerKey, addr); err != nil { + lggr.Errorw("Failed to grant mint/burn permissions", "err", err, "token", srcToken.Address(), "address", addr) + return err + } + } + return nil + } +} + +func UpdateFeeQuoterForUSDC( + lggr logger.Logger, + chain deployment.Chain, + state changeset.CCIPChainState, + dstChain uint64, + usdcToken *burn_mint_erc677.BurnMintERC677, +) error { + config := []fee_quoter.FeeQuoterTokenTransferFeeConfigArgs{ + { + DestChainSelector: dstChain, + TokenTransferFeeConfigs: []fee_quoter.FeeQuoterTokenTransferFeeConfigSingleTokenArgs{ + { + Token: usdcToken.Address(), + TokenTransferFeeConfig: fee_quoter.FeeQuoterTokenTransferFeeConfig{ + MinFeeUSDCents: 50, + MaxFeeUSDCents: 50_000, + DeciBps: 0, + DestGasOverhead: 180_000, + DestBytesOverhead: 640, + IsEnabled: true, + }, + }, + }, + }, + } + + tx, err := state.FeeQuoter.ApplyTokenTransferFeeConfigUpdates( + chain.DeployerKey, + config, + []fee_quoter.FeeQuoterTokenTransferFeeConfigRemoveArgs{}, + ) + if err != nil { + lggr.Errorw("Failed to apply token transfer fee config updates", "err", err, "config", config) + return err + } + + _, err = chain.Confirm(tx) + return err +} diff --git a/deployment/ccip/changeset/testhelpers/v1_5/test_helpers.go b/deployment/ccip/changeset/testhelpers/v1_5/test_helpers.go new file mode 100644 index 00000000000..be2804c6527 --- /dev/null +++ b/deployment/ccip/changeset/testhelpers/v1_5/test_helpers.go @@ -0,0 +1,391 @@ +package v1_5 + +import ( + "context" + "fmt" + "math/big" + "net/http" + "net/http/httptest" + "strconv" + "testing" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + chain_selectors "github.com/smartcontractkit/chain-selectors" + "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/config" + cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" + v1_5changeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_5" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_offramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry_1_2_0" + plugintesthelpers "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers" +) + +func AddLanes(t *testing.T, e deployment.Environment, state changeset.CCIPOnChainState, pairs []testhelpers.SourceDestPair) deployment.Environment { + addLanesCfg, commitOCR2Configs, execOCR2Configs, jobspecs := LaneConfigsForChains(t, e, state, pairs) + var err error + e, err = commonchangeset.ApplyChangesets(t, e, nil, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(v1_5changeset.DeployLanesChangeset), + Config: v1_5changeset.DeployLanesConfig{ + Configs: addLanesCfg, + }, + }, + { + Changeset: commonchangeset.WrapChangeSet(v1_5changeset.SetOCR2ConfigForTestChangeset), + Config: v1_5changeset.OCR2Config{ + CommitConfigs: commitOCR2Configs, + ExecConfigs: execOCR2Configs, + }, + }, + { + Changeset: commonchangeset.WrapChangeSet(v1_5changeset.JobSpecsForLanesChangeset), + Config: v1_5changeset.JobSpecsForLanesConfig{ + Configs: jobspecs, + }, + }, + }) + require.NoError(t, err) + return e +} + +func LaneConfigsForChains(t *testing.T, env deployment.Environment, state changeset.CCIPOnChainState, pairs []testhelpers.SourceDestPair) ( + []v1_5changeset.DeployLaneConfig, + []v1_5changeset.CommitOCR2ConfigParams, + []v1_5changeset.ExecuteOCR2ConfigParams, + []v1_5changeset.JobSpecInput, +) { + addLanesCfg := make([]v1_5changeset.DeployLaneConfig, 0) + commitOCR2Configs := make([]v1_5changeset.CommitOCR2ConfigParams, 0) + execOCR2Configs := make([]v1_5changeset.ExecuteOCR2ConfigParams, 0) + jobSpecs := make([]v1_5changeset.JobSpecInput, 0) + for _, pair := range pairs { + dest := pair.DestChainSelector + src := pair.SourceChainSelector + sourceChainState := state.Chains[src] + destChainState := state.Chains[dest] + _, err := sourceChainState.LinkTokenAddress() + require.NoError(t, err) + require.NotNil(t, sourceChainState.RMNProxy) + require.NotNil(t, sourceChainState.TokenAdminRegistry) + require.NotNil(t, sourceChainState.Router) + require.NotNil(t, sourceChainState.PriceRegistry) + require.NotNil(t, sourceChainState.Weth9) + _, err = destChainState.LinkTokenAddress() + require.NoError(t, err) + require.NotNil(t, destChainState.RMNProxy) + require.NotNil(t, destChainState.TokenAdminRegistry) + tokenPrice, _, _ := CreatePricesPipeline(t, state, src, dest) + block, err := env.Chains[dest].Client.HeaderByNumber(context.Background(), nil) + require.NoError(t, err) + destEVMChainIdStr, err := chain_selectors.GetChainIDFromSelector(dest) + require.NoError(t, err) + destEVMChainId, err := strconv.ParseUint(destEVMChainIdStr, 10, 64) + require.NoError(t, err) + jobSpecs = append(jobSpecs, v1_5changeset.JobSpecInput{ + SourceChainSelector: src, + DestinationChainSelector: dest, + DestEVMChainID: destEVMChainId, + TokenPricesUSDPipeline: tokenPrice, + DestinationStartBlock: block.Number.Uint64(), + }) + srcLinkTokenAddr, err := sourceChainState.LinkTokenAddress() + require.NoError(t, err) + addLanesCfg = append(addLanesCfg, v1_5changeset.DeployLaneConfig{ + SourceChainSelector: src, + DestinationChainSelector: dest, + OnRampStaticCfg: evm_2_evm_onramp.EVM2EVMOnRampStaticConfig{ + LinkToken: srcLinkTokenAddr, + ChainSelector: src, + DestChainSelector: dest, + DefaultTxGasLimit: 200_000, + MaxNopFeesJuels: big.NewInt(0).Mul(big.NewInt(100_000_000), big.NewInt(1e18)), + PrevOnRamp: common.Address{}, + RmnProxy: sourceChainState.RMNProxy.Address(), + TokenAdminRegistry: sourceChainState.TokenAdminRegistry.Address(), + }, + OnRampDynamicCfg: evm_2_evm_onramp.EVM2EVMOnRampDynamicConfig{ + Router: sourceChainState.Router.Address(), + MaxNumberOfTokensPerMsg: 5, + DestGasOverhead: 350_000, + DestGasPerPayloadByte: 16, + DestDataAvailabilityOverheadGas: 33_596, + DestGasPerDataAvailabilityByte: 16, + DestDataAvailabilityMultiplierBps: 6840, + PriceRegistry: sourceChainState.PriceRegistry.Address(), + MaxDataBytes: 1e5, + MaxPerMsgGasLimit: 4_000_000, + DefaultTokenFeeUSDCents: 50, + DefaultTokenDestGasOverhead: 125_000, + }, + OnRampFeeTokenArgs: []evm_2_evm_onramp.EVM2EVMOnRampFeeTokenConfigArgs{ + { + Token: srcLinkTokenAddr, + NetworkFeeUSDCents: 1_00, + GasMultiplierWeiPerEth: 1e18, + PremiumMultiplierWeiPerEth: 9e17, + Enabled: true, + }, + { + Token: sourceChainState.Weth9.Address(), + NetworkFeeUSDCents: 1_00, + GasMultiplierWeiPerEth: 1e18, + PremiumMultiplierWeiPerEth: 1e18, + Enabled: true, + }, + }, + OnRampTransferTokenCfgs: []evm_2_evm_onramp.EVM2EVMOnRampTokenTransferFeeConfigArgs{ + { + Token: srcLinkTokenAddr, + MinFeeUSDCents: 50, // $0.5 + MaxFeeUSDCents: 1_000_000_00, // $ 1 million + DeciBps: 5_0, // 5 bps + DestGasOverhead: 350_000, + DestBytesOverhead: 32, + AggregateRateLimitEnabled: true, + }, + }, + OnRampNopsAndWeight: []evm_2_evm_onramp.EVM2EVMOnRampNopAndWeight{}, + OnRampRateLimiterCfg: evm_2_evm_onramp.RateLimiterConfig{ + IsEnabled: true, + Capacity: plugintesthelpers.LinkUSDValue(100), + Rate: plugintesthelpers.LinkUSDValue(1), + }, + OffRampRateLimiterCfg: evm_2_evm_offramp.RateLimiterConfig{ + IsEnabled: true, + Capacity: plugintesthelpers.LinkUSDValue(100), + Rate: plugintesthelpers.LinkUSDValue(1), + }, + InitialTokenPrices: []price_registry_1_2_0.InternalTokenPriceUpdate{ + { + SourceToken: srcLinkTokenAddr, + UsdPerToken: new(big.Int).Mul(big.NewInt(1e18), big.NewInt(20)), + }, + { + SourceToken: sourceChainState.Weth9.Address(), + UsdPerToken: new(big.Int).Mul(big.NewInt(1e18), big.NewInt(2000)), + }, + }, + GasPriceUpdates: []price_registry_1_2_0.InternalGasPriceUpdate{ + { + DestChainSelector: dest, + UsdPerUnitGas: big.NewInt(20000e9), + }, + }, + }) + commitOCR2Configs = append(commitOCR2Configs, v1_5changeset.CommitOCR2ConfigParams{ + SourceChainSelector: src, + DestinationChainSelector: dest, + OCR2ConfigParams: DefaultOCRParams(), + GasPriceHeartBeat: *config.MustNewDuration(10 * time.Second), + DAGasPriceDeviationPPB: 1, + ExecGasPriceDeviationPPB: 1, + TokenPriceHeartBeat: *config.MustNewDuration(10 * time.Second), + TokenPriceDeviationPPB: 1, + InflightCacheExpiry: *config.MustNewDuration(5 * time.Second), + PriceReportingDisabled: false, + }) + execOCR2Configs = append(execOCR2Configs, v1_5changeset.ExecuteOCR2ConfigParams{ + DestinationChainSelector: dest, + SourceChainSelector: src, + DestOptimisticConfirmations: 1, + BatchGasLimit: 5_000_000, + RelativeBoostPerWaitHour: 0.07, + InflightCacheExpiry: *config.MustNewDuration(1 * time.Minute), + RootSnoozeTime: *config.MustNewDuration(1 * time.Minute), + BatchingStrategyID: 0, + MessageVisibilityInterval: config.Duration{}, + ExecOnchainConfig: evm_2_evm_offramp.EVM2EVMOffRampDynamicConfig{ + PermissionLessExecutionThresholdSeconds: uint32(24 * time.Hour.Seconds()), + MaxDataBytes: 1e5, + MaxNumberOfTokensPerMsg: 5, + }, + OCR2ConfigParams: DefaultOCRParams(), + }) + } + return addLanesCfg, commitOCR2Configs, execOCR2Configs, jobSpecs +} + +func CreatePricesPipeline(t *testing.T, state changeset.CCIPOnChainState, source, dest uint64) (string, *httptest.Server, *httptest.Server) { + sourceRouter := state.Chains[source].Router + destRouter := state.Chains[dest].Router + destLinkAddr, err := state.Chains[dest].LinkTokenAddress() + require.NoError(t, err) + linkUSD := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + _, err := w.Write([]byte(`{"UsdPerLink": "8000000000000000000"}`)) + require.NoError(t, err) + })) + t.Cleanup(linkUSD.Close) + + ethUSD := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + _, err := w.Write([]byte(`{"UsdPerETH": "1700000000000000000000"}`)) + require.NoError(t, err) + })) + t.Cleanup(ethUSD.Close) + + sourceWrappedNative, err := sourceRouter.GetWrappedNative(nil) + require.NoError(t, err) + destWrappedNative, err := destRouter.GetWrappedNative(nil) + require.NoError(t, err) + tokenPricesUSDPipeline := fmt.Sprintf(` +// Price 1 +link [type=http method=GET url="%s"]; +link_parse [type=jsonparse path="UsdPerLink"]; +link->link_parse; +eth [type=http method=GET url="%s"]; +eth_parse [type=jsonparse path="UsdPerETH"]; +eth->eth_parse; +merge [type=merge left="{}" right="{\\\"%s\\\":$(link_parse), \\\"%s\\\":$(eth_parse), \\\"%s\\\":$(eth_parse)}"];`, + linkUSD.URL, ethUSD.URL, destLinkAddr, sourceWrappedNative, destWrappedNative) + + return tokenPricesUSDPipeline, linkUSD, ethUSD +} + +func DefaultOCRParams() confighelper.PublicConfig { + return confighelper.PublicConfig{ + DeltaProgress: 2 * time.Second, + DeltaResend: 1 * time.Second, + DeltaRound: 1 * time.Second, + DeltaGrace: 500 * time.Millisecond, + DeltaStage: 2 * time.Second, + RMax: 3, + MaxDurationInitialization: nil, + MaxDurationQuery: 50 * time.Millisecond, + MaxDurationObservation: 1 * time.Second, + MaxDurationReport: 100 * time.Millisecond, + MaxDurationShouldAcceptFinalizedReport: 100 * time.Millisecond, + MaxDurationShouldTransmitAcceptedReport: 100 * time.Millisecond, + } +} + +func SendRequest( + t *testing.T, + e deployment.Environment, + state changeset.CCIPOnChainState, + opts ...testhelpers.SendReqOpts, +) (*evm_2_evm_onramp.EVM2EVMOnRampCCIPSendRequested, error) { + cfg := &testhelpers.CCIPSendReqConfig{} + for _, opt := range opts { + opt(cfg) + } + // Set default sender if not provided + if cfg.Sender == nil { + cfg.Sender = e.Chains[cfg.SourceChain].DeployerKey + } + t.Logf("Sending CCIP request from chain selector %d to chain selector %d from sender %s", + cfg.SourceChain, cfg.DestChain, cfg.Sender.From.String()) + tx, blockNum, err := testhelpers.CCIPSendRequest(e, state, cfg) + if err != nil { + return nil, err + } + + onRamp := state.Chains[cfg.SourceChain].EVM2EVMOnRamp[cfg.DestChain] + + it, err := onRamp.FilterCCIPSendRequested(&bind.FilterOpts{ + Start: blockNum, + End: &blockNum, + Context: context.Background(), + }) + if err != nil { + return nil, err + } + + require.True(t, it.Next()) + t.Logf("CCIP message (id %x) sent from chain selector %d to chain selector %d tx %s seqNum %d sender %s", + it.Event.Message.MessageId[:], + cfg.SourceChain, + cfg.DestChain, + tx.Hash().String(), + it.Event.Message.SequenceNumber, + it.Event.Message.Sender.String(), + ) + return it.Event, nil +} + +func WaitForCommit( + t *testing.T, + src deployment.Chain, + dest deployment.Chain, + commitStore *commit_store.CommitStore, + seqNr uint64, +) { + timer := time.NewTimer(5 * time.Minute) + defer timer.Stop() + ticker := time.NewTicker(2 * time.Second) + defer ticker.Stop() + for { + select { + case <-ticker.C: + if backend, ok := src.Client.(*memory.Backend); ok { + backend.Commit() + } + if backend, ok := dest.Client.(*memory.Backend); ok { + backend.Commit() + } + minSeqNr, err := commitStore.GetExpectedNextSequenceNumber(nil) + require.NoError(t, err) + t.Logf("Waiting for commit for sequence number %d, current min sequence number %d", seqNr, minSeqNr) + if minSeqNr > seqNr { + t.Logf("Commit for sequence number %d found", seqNr) + return + } + case <-timer.C: + t.Fatalf("timed out waiting for commit for sequence number %d for commit store %s ", seqNr, commitStore.Address().String()) + return + } + } +} + +func WaitForExecute( + t *testing.T, + src deployment.Chain, + dest deployment.Chain, + offRamp *evm_2_evm_offramp.EVM2EVMOffRamp, + seqNrs []uint64, + blockNum uint64, +) { + timer := time.NewTimer(5 * time.Minute) + defer timer.Stop() + ticker := time.NewTicker(2 * time.Second) + defer ticker.Stop() + for { + select { + case <-ticker.C: + if backend, ok := src.Client.(*memory.Backend); ok { + backend.Commit() + } + if backend, ok := dest.Client.(*memory.Backend); ok { + backend.Commit() + } + t.Logf("Waiting for execute for sequence numbers %v", seqNrs) + it, err := offRamp.FilterExecutionStateChanged( + &bind.FilterOpts{ + Start: blockNum, + }, seqNrs, [][32]byte{}) + require.NoError(t, err) + for it.Next() { + t.Logf("Execution state changed for sequence number=%d current state=%d", it.Event.SequenceNumber, it.Event.State) + if cciptypes.MessageExecutionState(it.Event.State) == cciptypes.ExecutionStateSuccess { + t.Logf("Execution for sequence number %d found", it.Event.SequenceNumber) + return + } + t.Logf("Execution for sequence number %d resulted in status %d", it.Event.SequenceNumber, it.Event.State) + t.Fail() + } + case <-timer.C: + t.Fatalf("timed out waiting for execute for sequence numbers %v for offramp %s ", seqNrs, offRamp.Address().String()) + return + } + } +} diff --git a/deployment/ccip/changeset/token_info.go b/deployment/ccip/changeset/token_info.go index 7c008a8a884..cecc3070ab8 100644 --- a/deployment/ccip/changeset/token_info.go +++ b/deployment/ccip/changeset/token_info.go @@ -1,13 +1,18 @@ package changeset import ( + "math/big" + "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink-ccip/pluginconfig" + + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/link_token" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/weth9" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/aggregator_v3_interface" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/aggregator_v3_interface" ) type TokenSymbol string @@ -15,14 +20,41 @@ type TokenSymbol string const ( LinkSymbol TokenSymbol = "LINK" WethSymbol TokenSymbol = "WETH" + WAVAXSymbol TokenSymbol = "WAVAX" USDCSymbol TokenSymbol = "USDC" USDCName string = "USD Coin" LinkDecimals = 18 WethDecimals = 18 UsdcDecimals = 6 + + // Price Feed Descriptions + AvaxUSD = "AVAX / USD" + LinkUSD = "LINK / USD" + EthUSD = "ETH / USD" + + // MockLinkAggregatorDescription is the description of the MockV3Aggregator.sol contract + // https://github.com/smartcontractkit/chainlink/blob/a348b98e90527520049c580000a86fb8ceff7fa7/contracts/src/v0.8/tests/MockV3Aggregator.sol#L76-L76 + MockLinkAggregatorDescription = "v0.8/tests/MockV3Aggregator.sol" + // MockWETHAggregatorDescription is the description from MockETHUSDAggregator.sol + // https://github.com/smartcontractkit/chainlink/blob/a348b98e90527520049c580000a86fb8ceff7fa7/contracts/src/v0.8/automation/testhelpers/MockETHUSDAggregator.sol#L19-L19 + MockWETHAggregatorDescription = "MockETHUSDAggregator" ) var ( + MockLinkPrice = deployment.E18Mult(500) + MockWethPrice = big.NewInt(9e8) + // DescriptionToTokenSymbol maps price feed description to token descriptor + DescriptionToTokenSymbol = map[string]TokenSymbol{ + MockLinkAggregatorDescription: LinkSymbol, + MockWETHAggregatorDescription: WethSymbol, + LinkUSD: LinkSymbol, + AvaxUSD: WAVAXSymbol, + EthUSD: WethSymbol, + } + MockSymbolToDescription = map[TokenSymbol]string{ + LinkSymbol: MockLinkAggregatorDescription, + WethSymbol: MockWETHAggregatorDescription, + } TestDeviationPPB = ccipocr3.NewBigIntFromInt64(1e9) ) diff --git a/deployment/ccip/changeset/v1_5/cs_jobspec.go b/deployment/ccip/changeset/v1_5/cs_jobspec.go new file mode 100644 index 00000000000..fd80a392136 --- /dev/null +++ b/deployment/ccip/changeset/v1_5/cs_jobspec.go @@ -0,0 +1,152 @@ +package v1_5 + +import ( + "errors" + "fmt" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" + integrationtesthelpers "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers/integration" +) + +var _ deployment.ChangeSet[JobSpecsForLanesConfig] = JobSpecsForLanesChangeset + +type JobSpecsForLanesConfig struct { + Configs []JobSpecInput +} + +func (c JobSpecsForLanesConfig) Validate() error { + for _, cfg := range c.Configs { + if err := cfg.Validate(); err != nil { + return fmt.Errorf("invalid JobSpecInput: %w", err) + } + } + return nil +} + +type JobSpecInput struct { + SourceChainSelector uint64 + DestinationChainSelector uint64 + DestEVMChainID uint64 + DestinationStartBlock uint64 + TokenPricesUSDPipeline string + PriceGetterConfigJson string + USDCAttestationAPI string + USDCCfg *config.USDCConfig +} + +func (j JobSpecInput) Validate() error { + if err := deployment.IsValidChainSelector(j.SourceChainSelector); err != nil { + return fmt.Errorf("SourceChainSelector is invalid: %w", err) + } + if err := deployment.IsValidChainSelector(j.DestinationChainSelector); err != nil { + return fmt.Errorf("DestinationChainSelector is invalid: %w", err) + } + if j.TokenPricesUSDPipeline == "" && j.PriceGetterConfigJson == "" { + return errors.New("TokenPricesUSDPipeline or PriceGetterConfigJson is required") + } + if j.USDCCfg != nil { + if err := j.USDCCfg.ValidateUSDCConfig(); err != nil { + return fmt.Errorf("USDCCfg is invalid: %w", err) + } + if j.USDCAttestationAPI == "" { + return errors.New("USDCAttestationAPI is required") + } + } + return nil +} + +func JobSpecsForLanesChangeset(env deployment.Environment, c JobSpecsForLanesConfig) (deployment.ChangesetOutput, error) { + if err := c.Validate(); err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("invalid JobSpecsForLanesConfig: %w", err) + } + state, err := changeset.LoadOnchainState(env) + if err != nil { + return deployment.ChangesetOutput{}, err + } + nodesToJobSpecs, err := jobSpecsForLane(env, state, c) + if err != nil { + return deployment.ChangesetOutput{}, err + } + return deployment.ChangesetOutput{ + JobSpecs: nodesToJobSpecs, + }, nil +} + +func jobSpecsForLane( + env deployment.Environment, + state changeset.CCIPOnChainState, + lanesCfg JobSpecsForLanesConfig, +) (map[string][]string, error) { + nodes, err := deployment.NodeInfo(env.NodeIDs, env.Offchain) + if err != nil { + return nil, err + } + nodesToJobSpecs := make(map[string][]string) + for _, node := range nodes { + var specs []string + for _, cfg := range lanesCfg.Configs { + destChainState := state.Chains[cfg.DestinationChainSelector] + sourceChain := env.Chains[cfg.SourceChainSelector] + destChain := env.Chains[cfg.DestinationChainSelector] + + ccipJobParam := integrationtesthelpers.CCIPJobSpecParams{ + OffRamp: destChainState.EVM2EVMOffRamp[cfg.SourceChainSelector].Address(), + CommitStore: destChainState.CommitStore[cfg.SourceChainSelector].Address(), + SourceChainName: sourceChain.Name(), + DestChainName: destChain.Name(), + DestEvmChainId: cfg.DestEVMChainID, + TokenPricesUSDPipeline: cfg.TokenPricesUSDPipeline, + PriceGetterConfig: cfg.PriceGetterConfigJson, + DestStartBlock: cfg.DestinationStartBlock, + USDCAttestationAPI: cfg.USDCAttestationAPI, + USDCConfig: cfg.USDCCfg, + P2PV2Bootstrappers: nodes.BootstrapLocators(), + } + if !node.IsBootstrap { + ocrCfg, found := node.OCRConfigForChainSelector(cfg.DestinationChainSelector) + if !found { + return nil, fmt.Errorf("OCR config not found for chain %s", destChain.String()) + } + ocrKeyBundleID := ocrCfg.KeyBundleID + transmitterID := ocrCfg.TransmitAccount + commitSpec, err := ccipJobParam.CommitJobSpec() + if err != nil { + return nil, fmt.Errorf("failed to generate commit job spec for source %s and destination %s: %w", + sourceChain.String(), destChain.String(), err) + } + commitSpec.OCR2OracleSpec.OCRKeyBundleID.SetValid(ocrKeyBundleID) + commitSpec.OCR2OracleSpec.TransmitterID.SetValid(string(transmitterID)) + commitSpecStr, err := commitSpec.String() + if err != nil { + return nil, fmt.Errorf("failed to convert commit job spec to string for source %s and destination %s: %w", + sourceChain.String(), destChain.String(), err) + } + execSpec, err := ccipJobParam.ExecutionJobSpec() + if err != nil { + return nil, fmt.Errorf("failed to generate execution job spec for source %s and destination %s: %w", + sourceChain.String(), destChain.String(), err) + } + execSpec.OCR2OracleSpec.OCRKeyBundleID.SetValid(ocrKeyBundleID) + execSpec.OCR2OracleSpec.TransmitterID.SetValid(string(transmitterID)) + execSpecStr, err := execSpec.String() + if err != nil { + return nil, fmt.Errorf("failed to convert execution job spec to string for source %s and destination %s: %w", + sourceChain.String(), destChain.String(), err) + } + specs = append(specs, commitSpecStr, execSpecStr) + } else { + bootstrapSpec := ccipJobParam.BootstrapJob(destChainState.CommitStore[cfg.SourceChainSelector].Address().String()) + bootstrapSpecStr, err := bootstrapSpec.String() + if err != nil { + return nil, fmt.Errorf("failed to convert bootstrap job spec to string for source %s and destination %s: %w", + sourceChain.String(), destChain.String(), err) + } + specs = append(specs, bootstrapSpecStr) + } + } + nodesToJobSpecs[node.NodeID] = append(nodesToJobSpecs[node.NodeID], specs...) + } + return nodesToJobSpecs, nil +} diff --git a/deployment/ccip/changeset/v1_5/cs_lane_contracts.go b/deployment/ccip/changeset/v1_5/cs_lane_contracts.go new file mode 100644 index 00000000000..6f6f0d54a69 --- /dev/null +++ b/deployment/ccip/changeset/v1_5/cs_lane_contracts.go @@ -0,0 +1,309 @@ +package v1_5 + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_offramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry_1_2_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" +) + +var _ deployment.ChangeSet[DeployLanesConfig] = DeployLanesChangeset + +type DeployLanesConfig struct { + Configs []DeployLaneConfig +} + +func (c *DeployLanesConfig) Validate(e deployment.Environment, state changeset.CCIPOnChainState) error { + for _, cfg := range c.Configs { + if err := cfg.Validate(e, state); err != nil { + return err + } + } + return nil +} + +type DeployLaneConfig struct { + SourceChainSelector uint64 + DestinationChainSelector uint64 + + // onRamp specific configuration + OnRampStaticCfg evm_2_evm_onramp.EVM2EVMOnRampStaticConfig + OnRampDynamicCfg evm_2_evm_onramp.EVM2EVMOnRampDynamicConfig + OnRampFeeTokenArgs []evm_2_evm_onramp.EVM2EVMOnRampFeeTokenConfigArgs + OnRampTransferTokenCfgs []evm_2_evm_onramp.EVM2EVMOnRampTokenTransferFeeConfigArgs + OnRampNopsAndWeight []evm_2_evm_onramp.EVM2EVMOnRampNopAndWeight + OnRampRateLimiterCfg evm_2_evm_onramp.RateLimiterConfig + + // offRamp specific configuration + OffRampRateLimiterCfg evm_2_evm_offramp.RateLimiterConfig + + // Price Registry specific configuration + InitialTokenPrices []price_registry_1_2_0.InternalTokenPriceUpdate + GasPriceUpdates []price_registry_1_2_0.InternalGasPriceUpdate +} + +func (c *DeployLaneConfig) Validate(e deployment.Environment, state changeset.CCIPOnChainState) error { + if err := deployment.IsValidChainSelector(c.SourceChainSelector); err != nil { + return err + } + if err := deployment.IsValidChainSelector(c.DestinationChainSelector); err != nil { + return err + } + sourceChain, exists := e.Chains[c.SourceChainSelector] + if !exists { + return fmt.Errorf("source chain %d not found in environment", c.SourceChainSelector) + } + destChain, exists := e.Chains[c.DestinationChainSelector] + if !exists { + return fmt.Errorf("destination chain %d not found in environment", c.DestinationChainSelector) + } + sourceChainState, exists := state.Chains[c.SourceChainSelector] + if !exists { + return fmt.Errorf("source chain %d not found in state", c.SourceChainSelector) + } + destChainState, exists := state.Chains[c.DestinationChainSelector] + if !exists { + return fmt.Errorf("destination chain %d not found in state", c.DestinationChainSelector) + } + // check for existing chain contracts on both source and destination chains + if err := arePrerequisitesMet(sourceChainState, sourceChain); err != nil { + return err + } + if err := arePrerequisitesMet(destChainState, destChain); err != nil { + return err + } + // TODO: Add rest of the config validation + return nil +} + +func (c *DeployLaneConfig) populateAddresses(state changeset.CCIPOnChainState) error { + sourceChainState := state.Chains[c.SourceChainSelector] + srcLink, err := sourceChainState.LinkTokenAddress() + if err != nil { + return fmt.Errorf("failed to get LINK token address for source chain %d: %w", c.SourceChainSelector, err) + } + c.OnRampStaticCfg.LinkToken = srcLink + c.OnRampStaticCfg.RmnProxy = sourceChainState.RMNProxy.Address() + c.OnRampStaticCfg.TokenAdminRegistry = sourceChainState.TokenAdminRegistry.Address() + + c.OnRampDynamicCfg.Router = sourceChainState.Router.Address() + c.OnRampDynamicCfg.PriceRegistry = sourceChainState.PriceRegistry.Address() + return nil +} + +func DeployLanesChangeset(env deployment.Environment, c DeployLanesConfig) (deployment.ChangesetOutput, error) { + state, err := changeset.LoadOnchainState(env) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to load CCIP onchain state: %w", err) + } + if err := c.Validate(env, state); err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("invalid DeployChainContractsConfig: %w", err) + } + // populate addresses from the state + for i := range c.Configs { + if err := c.Configs[i].populateAddresses(state); err != nil { + return deployment.ChangesetOutput{}, err + } + } + newAddresses := deployment.NewMemoryAddressBook() + for _, cfg := range c.Configs { + if err := deployLane(env, state, newAddresses, cfg); err != nil { + return deployment.ChangesetOutput{ + AddressBook: newAddresses, + }, err + } + } + return deployment.ChangesetOutput{ + AddressBook: newAddresses, + }, nil +} + +func deployLane(e deployment.Environment, state changeset.CCIPOnChainState, ab deployment.AddressBook, cfg DeployLaneConfig) error { + // update prices on the source price registry + sourceChainState := state.Chains[cfg.SourceChainSelector] + destChainState := state.Chains[cfg.DestinationChainSelector] + sourceChain := e.Chains[cfg.SourceChainSelector] + destChain := e.Chains[cfg.DestinationChainSelector] + sourcePriceReg := sourceChainState.PriceRegistry + tx, err := sourcePriceReg.UpdatePrices(sourceChain.DeployerKey, price_registry_1_2_0.InternalPriceUpdates{ + TokenPriceUpdates: cfg.InitialTokenPrices, + GasPriceUpdates: cfg.GasPriceUpdates, + }) + if err != nil { + return err + } + _, err = sourceChain.Confirm(tx) + if err != nil { + return fmt.Errorf("failed to confirm price update tx for chain %s: %w", sourceChain.String(), deployment.MaybeDataErr(err)) + } + // ================================================================ + // │ Deploy Lane │ + // ================================================================ + // Deploy onRamp on source chain + onRamp, onRampExists := sourceChainState.EVM2EVMOnRamp[cfg.DestinationChainSelector] + if !onRampExists { + onRampC, err := deployment.DeployContract(e.Logger, sourceChain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*evm_2_evm_onramp.EVM2EVMOnRamp] { + onRampAddress, tx2, onRampC, err2 := evm_2_evm_onramp.DeployEVM2EVMOnRamp( + sourceChain.DeployerKey, + sourceChain.Client, + cfg.OnRampStaticCfg, + cfg.OnRampDynamicCfg, + cfg.OnRampRateLimiterCfg, + cfg.OnRampFeeTokenArgs, + cfg.OnRampTransferTokenCfgs, + cfg.OnRampNopsAndWeight, + ) + return deployment.ContractDeploy[*evm_2_evm_onramp.EVM2EVMOnRamp]{ + Address: onRampAddress, Contract: onRampC, Tx: tx2, + Tv: deployment.NewTypeAndVersion(changeset.OnRamp, deployment.Version1_5_0), Err: err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy EVM2EVMOnRamp", "chain", sourceChain.String(), "err", err) + return err + } + onRamp = onRampC.Contract + } else { + e.Logger.Infow("EVM2EVMOnRamp already exists", + "source chain", sourceChain.String(), "destination chain", destChain.String(), + "address", onRamp.Address().String()) + } + + // Deploy commit store on source chain + commitStore, commitStoreExists := destChainState.CommitStore[cfg.SourceChainSelector] + if !commitStoreExists { + commitStoreC, err := deployment.DeployContract(e.Logger, destChain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*commit_store.CommitStore] { + commitStoreAddress, tx2, commitStoreC, err2 := commit_store.DeployCommitStore( + destChain.DeployerKey, + destChain.Client, + commit_store.CommitStoreStaticConfig{ + ChainSelector: destChain.Selector, + SourceChainSelector: sourceChain.Selector, + OnRamp: onRamp.Address(), + RmnProxy: destChainState.RMNProxy.Address(), + }, + ) + return deployment.ContractDeploy[*commit_store.CommitStore]{ + Address: commitStoreAddress, Contract: commitStoreC, Tx: tx2, + Tv: deployment.NewTypeAndVersion(changeset.CommitStore, deployment.Version1_5_0), Err: err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy CommitStore", "chain", sourceChain.String(), "err", err) + return err + } + commitStore = commitStoreC.Contract + } else { + e.Logger.Infow("CommitStore already exists", + "source chain", sourceChain.String(), "destination chain", destChain.String(), + "address", commitStore.Address().String()) + } + + // Deploy offRamp on destination chain + offRamp, offRampExists := destChainState.EVM2EVMOffRamp[cfg.SourceChainSelector] + if !offRampExists { + offRampC, err := deployment.DeployContract(e.Logger, destChain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*evm_2_evm_offramp.EVM2EVMOffRamp] { + offRampAddress, tx2, offRampC, err2 := evm_2_evm_offramp.DeployEVM2EVMOffRamp( + destChain.DeployerKey, + destChain.Client, + evm_2_evm_offramp.EVM2EVMOffRampStaticConfig{ + CommitStore: commitStore.Address(), + ChainSelector: destChain.Selector, + SourceChainSelector: sourceChain.Selector, + OnRamp: onRamp.Address(), + PrevOffRamp: common.HexToAddress(""), + RmnProxy: destChainState.RMNProxy.Address(), // RMN, formerly ARM + TokenAdminRegistry: destChainState.TokenAdminRegistry.Address(), + }, + cfg.OffRampRateLimiterCfg, + ) + return deployment.ContractDeploy[*evm_2_evm_offramp.EVM2EVMOffRamp]{ + Address: offRampAddress, Contract: offRampC, Tx: tx2, + Tv: deployment.NewTypeAndVersion(changeset.OffRamp, deployment.Version1_5_0), Err: err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy EVM2EVMOffRamp", "chain", sourceChain.String(), "err", err) + return err + } + offRamp = offRampC.Contract + } else { + e.Logger.Infow("EVM2EVMOffRamp already exists", + "source chain", sourceChain.String(), "destination chain", destChain.String(), + "address", offRamp.Address().String()) + } + + // Apply Router updates + tx, err = sourceChainState.Router.ApplyRampUpdates(sourceChain.DeployerKey, + []router.RouterOnRamp{{DestChainSelector: destChain.Selector, OnRamp: onRamp.Address()}}, nil, nil) + if err != nil { + return fmt.Errorf("failed to apply router updates for source chain %s: %w", sourceChain.String(), deployment.MaybeDataErr(err)) + } + _, err = sourceChain.Confirm(tx) + if err != nil { + return fmt.Errorf("failed to confirm router updates tx %s for source chain %s: %w", tx.Hash().String(), sourceChain.String(), deployment.MaybeDataErr(err)) + } + + tx, err = destChainState.Router.ApplyRampUpdates(destChain.DeployerKey, + nil, + nil, + []router.RouterOffRamp{{SourceChainSelector: sourceChain.Selector, OffRamp: offRamp.Address()}}, + ) + if err != nil { + return fmt.Errorf("failed to apply router updates for destination chain %s: %w", destChain.String(), deployment.MaybeDataErr(err)) + } + _, err = destChain.Confirm(tx) + if err != nil { + return fmt.Errorf("failed to confirm router updates tx %s for destination chain %s: %w", tx.Hash().String(), destChain.String(), deployment.MaybeDataErr(err)) + } + + // price registry updates + _, err = destChainState.PriceRegistry.ApplyPriceUpdatersUpdates( + destChain.DeployerKey, + []common.Address{commitStore.Address()}, + []common.Address{}, + ) + if err != nil { + return fmt.Errorf("failed to apply price registry updates for destination chain %s: %w", destChain.String(), deployment.MaybeDataErr(err)) + } + _, err = destChain.Confirm(tx) + if err != nil { + return fmt.Errorf("failed to confirm price registry updates tx %s for destination chain %s: %w", tx.Hash().String(), destChain.String(), deployment.MaybeDataErr(err)) + } + return nil +} + +func arePrerequisitesMet(chainState changeset.CCIPChainState, chain deployment.Chain) error { + if chainState.Router == nil { + return fmt.Errorf("router not found for chain %s", chain.String()) + } + if chainState.PriceRegistry == nil { + return fmt.Errorf("price registry not found for chain %s", chain.String()) + } + if chainState.RMN == nil && chainState.MockRMN == nil { + return fmt.Errorf("neither RMN nor mockRMN found for chain %s", chain.String()) + } + if chainState.Weth9 == nil { + return fmt.Errorf("WETH9 not found for chain %s", chain.String()) + } + if _, err := chainState.LinkTokenAddress(); err != nil { + return fmt.Errorf("LINK token not found for chain %s", chain.String()) + } + if chainState.TokenAdminRegistry == nil { + return fmt.Errorf("token admin registry not found for chain %s", chain.String()) + } + if chainState.RMNProxy == nil { + return fmt.Errorf("RMNProxy not found for chain %s", chain.String()) + } + return nil +} diff --git a/deployment/ccip/changeset/v1_5/cs_ocr2_config.go b/deployment/ccip/changeset/v1_5/cs_ocr2_config.go new file mode 100644 index 00000000000..2babf666da2 --- /dev/null +++ b/deployment/ccip/changeset/v1_5/cs_ocr2_config.go @@ -0,0 +1,331 @@ +package v1_5 + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/pkg/errors" + "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" + + "github.com/smartcontractkit/chainlink-common/pkg/config" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_offramp" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers" +) + +var _ deployment.ChangeSet[OCR2Config] = SetOCR2ConfigForTestChangeset + +type FinalOCR2Config struct { + Signers []common.Address + Transmitters []common.Address + F uint8 + OnchainConfig []byte + OffchainConfigVersion uint64 + OffchainConfig []byte +} + +type CommitOCR2ConfigParams struct { + DestinationChainSelector uint64 + SourceChainSelector uint64 + OCR2ConfigParams confighelper.PublicConfig + GasPriceHeartBeat config.Duration + DAGasPriceDeviationPPB uint32 + ExecGasPriceDeviationPPB uint32 + TokenPriceHeartBeat config.Duration + TokenPriceDeviationPPB uint32 + InflightCacheExpiry config.Duration + PriceReportingDisabled bool +} + +func (c *CommitOCR2ConfigParams) PopulateOffChainAndOnChainCfg(priceReg common.Address) error { + var err error + c.OCR2ConfigParams.ReportingPluginConfig, err = testhelpers.NewCommitOffchainConfig( + c.GasPriceHeartBeat, + c.DAGasPriceDeviationPPB, + c.ExecGasPriceDeviationPPB, + c.TokenPriceHeartBeat, + c.TokenPriceDeviationPPB, + c.InflightCacheExpiry, + c.PriceReportingDisabled, + ).Encode() + if err != nil { + return errors.Wrapf(err, "failed to encode offchain config for source chain %d and destination chain %d", + c.SourceChainSelector, c.DestinationChainSelector) + } + c.OCR2ConfigParams.OnchainConfig, err = abihelpers.EncodeAbiStruct(testhelpers.NewCommitOnchainConfig(priceReg)) + if err != nil { + return fmt.Errorf("failed to encode onchain config for source chain %d and destination chain %d: %w", + c.SourceChainSelector, c.DestinationChainSelector, err) + } + return nil +} + +func (c *CommitOCR2ConfigParams) Validate(state changeset.CCIPOnChainState) error { + if err := deployment.IsValidChainSelector(c.DestinationChainSelector); err != nil { + return fmt.Errorf("invalid DestinationChainSelector: %w", err) + } + if err := deployment.IsValidChainSelector(c.SourceChainSelector); err != nil { + return fmt.Errorf("invalid SourceChainSelector: %w", err) + } + + chain, exists := state.Chains[c.DestinationChainSelector] + if !exists { + return fmt.Errorf("chain %d does not exist in state", c.DestinationChainSelector) + } + if chain.CommitStore == nil { + return fmt.Errorf("chain %d does not have a commit store", c.DestinationChainSelector) + } + _, exists = chain.CommitStore[c.SourceChainSelector] + if !exists { + return fmt.Errorf("chain %d does not have a commit store for source chain %d", c.DestinationChainSelector, c.SourceChainSelector) + } + if chain.PriceRegistry == nil { + return fmt.Errorf("chain %d does not have a price registry", c.DestinationChainSelector) + } + return nil +} + +type ExecuteOCR2ConfigParams struct { + DestinationChainSelector uint64 + SourceChainSelector uint64 + DestOptimisticConfirmations uint32 + BatchGasLimit uint32 + RelativeBoostPerWaitHour float64 + InflightCacheExpiry config.Duration + RootSnoozeTime config.Duration + BatchingStrategyID uint32 + MessageVisibilityInterval config.Duration + ExecOnchainConfig evm_2_evm_offramp.EVM2EVMOffRampDynamicConfig + OCR2ConfigParams confighelper.PublicConfig +} + +func (e *ExecuteOCR2ConfigParams) PopulateOffChainAndOnChainCfg(router, priceReg common.Address) error { + var err error + e.OCR2ConfigParams.ReportingPluginConfig, err = testhelpers.NewExecOffchainConfig( + e.DestOptimisticConfirmations, + e.BatchGasLimit, + e.RelativeBoostPerWaitHour, + e.InflightCacheExpiry, + e.RootSnoozeTime, + e.BatchingStrategyID, + ).Encode() + if err != nil { + return fmt.Errorf("failed to encode offchain config for exec plugin, source chain %d dest chain %d :%w", + e.SourceChainSelector, e.DestinationChainSelector, err) + } + e.OCR2ConfigParams.OnchainConfig, err = abihelpers.EncodeAbiStruct(testhelpers.NewExecOnchainConfig( + e.ExecOnchainConfig.PermissionLessExecutionThresholdSeconds, + router, + priceReg, + e.ExecOnchainConfig.MaxNumberOfTokensPerMsg, + e.ExecOnchainConfig.MaxDataBytes, + )) + if err != nil { + return fmt.Errorf("failed to encode onchain config for exec plugin, source chain %d dest chain %d :%w", + e.SourceChainSelector, e.DestinationChainSelector, err) + } + return nil +} + +func (e *ExecuteOCR2ConfigParams) Validate(state changeset.CCIPOnChainState) error { + if err := deployment.IsValidChainSelector(e.SourceChainSelector); err != nil { + return fmt.Errorf("invalid SourceChainSelector: %w", err) + } + if err := deployment.IsValidChainSelector(e.DestinationChainSelector); err != nil { + return fmt.Errorf("invalid DestinationChainSelector: %w", err) + } + chain, exists := state.Chains[e.DestinationChainSelector] + if !exists { + return fmt.Errorf("chain %d does not exist in state", e.DestinationChainSelector) + } + if chain.EVM2EVMOffRamp == nil { + return fmt.Errorf("chain %d does not have an EVM2EVMOffRamp", e.DestinationChainSelector) + } + _, exists = chain.EVM2EVMOffRamp[e.SourceChainSelector] + if !exists { + return fmt.Errorf("chain %d does not have an EVM2EVMOffRamp for source chain %d", e.DestinationChainSelector, e.SourceChainSelector) + } + if chain.PriceRegistry == nil { + return fmt.Errorf("chain %d does not have a price registry", e.DestinationChainSelector) + } + if chain.Router == nil { + return fmt.Errorf("chain %d does not have a router", e.DestinationChainSelector) + } + return nil +} + +type OCR2Config struct { + CommitConfigs []CommitOCR2ConfigParams + ExecConfigs []ExecuteOCR2ConfigParams +} + +func (o OCR2Config) Validate(state changeset.CCIPOnChainState) error { + for _, c := range o.CommitConfigs { + if err := c.Validate(state); err != nil { + return err + } + } + for _, e := range o.ExecConfigs { + if err := e.Validate(state); err != nil { + return err + } + } + return nil +} + +// SetOCR2ConfigForTestChangeset sets the OCR2 config on the chain for commit and offramp +// This is currently not suitable for prod environments it's only for testing +func SetOCR2ConfigForTestChangeset(env deployment.Environment, c OCR2Config) (deployment.ChangesetOutput, error) { + state, err := changeset.LoadOnchainState(env) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to load CCIP onchain state: %w", err) + } + if err := c.Validate(state); err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("invalid OCR2 config: %w", err) + } + for _, commit := range c.CommitConfigs { + if err := commit.PopulateOffChainAndOnChainCfg(state.Chains[commit.DestinationChainSelector].PriceRegistry.Address()); err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to populate offchain and onchain config for commit: %w", err) + } + finalCfg, err := deriveOCR2Config(env, commit.DestinationChainSelector, commit.OCR2ConfigParams) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to derive OCR2 config for commit: %w", err) + } + commitStore := state.Chains[commit.DestinationChainSelector].CommitStore[commit.SourceChainSelector] + chain := env.Chains[commit.DestinationChainSelector] + tx, err := commitStore.SetOCR2Config( + chain.DeployerKey, + finalCfg.Signers, + finalCfg.Transmitters, + finalCfg.F, + finalCfg.OnchainConfig, + finalCfg.OffchainConfigVersion, + finalCfg.OffchainConfig, + ) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to set OCR2 config for commit store %s on chain %s: %w", + commitStore.Address().String(), chain.String(), deployment.MaybeDataErr(err)) + } + _, err = chain.Confirm(tx) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to confirm OCR2 for commit store %s config on chain %s: %w", + commitStore.Address().String(), chain.String(), err) + } + } + for _, exec := range c.ExecConfigs { + if err := exec.PopulateOffChainAndOnChainCfg( + state.Chains[exec.DestinationChainSelector].Router.Address(), + state.Chains[exec.DestinationChainSelector].PriceRegistry.Address()); err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to populate offchain and onchain config for offramp: %w", err) + } + finalCfg, err := deriveOCR2Config(env, exec.DestinationChainSelector, exec.OCR2ConfigParams) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to derive OCR2 config for offramp: %w", err) + } + offRamp := state.Chains[exec.DestinationChainSelector].EVM2EVMOffRamp[exec.SourceChainSelector] + chain := env.Chains[exec.DestinationChainSelector] + tx, err := offRamp.SetOCR2Config( + chain.DeployerKey, + finalCfg.Signers, + finalCfg.Transmitters, + finalCfg.F, + finalCfg.OnchainConfig, + finalCfg.OffchainConfigVersion, + finalCfg.OffchainConfig, + ) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to set OCR2 config for offramp %s on chain %s: %w", + offRamp.Address().String(), chain.String(), err) + } + _, err = chain.Confirm(tx) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to confirm OCR2 for offramp %s config on chain %s: %w", + offRamp.Address().String(), chain.String(), err) + } + } + return deployment.ChangesetOutput{}, nil +} + +func deriveOCR2Config( + env deployment.Environment, + chainSel uint64, + ocrParams confighelper.PublicConfig, +) (FinalOCR2Config, error) { + nodeInfo, err := deployment.NodeInfo(env.NodeIDs, env.Offchain) + if err != nil { + return FinalOCR2Config{}, fmt.Errorf("failed to get node info: %w", err) + } + nodes := nodeInfo.NonBootstraps() + // Get OCR3 Config from helper + var schedule []int + var oracles []confighelper.OracleIdentityExtra + for _, node := range nodes { + schedule = append(schedule, 1) + cfg, exists := node.OCRConfigForChainSelector(chainSel) + if !exists { + return FinalOCR2Config{}, fmt.Errorf("no OCR config for chain %d", chainSel) + } + oracles = append(oracles, confighelper.OracleIdentityExtra{ + OracleIdentity: confighelper.OracleIdentity{ + OnchainPublicKey: cfg.OnchainPublicKey, + TransmitAccount: cfg.TransmitAccount, + OffchainPublicKey: cfg.OffchainPublicKey, + PeerID: cfg.PeerID.Raw(), + }, + ConfigEncryptionPublicKey: cfg.ConfigEncryptionPublicKey, + }) + } + + signers, transmitters, threshold, onchainConfig, offchainConfigVersion, offchainConfig, err := confighelper.ContractSetConfigArgsForTests( + ocrParams.DeltaProgress, + ocrParams.DeltaResend, + ocrParams.DeltaRound, + ocrParams.DeltaGrace, + ocrParams.DeltaStage, + ocrParams.RMax, + schedule, + oracles, + ocrParams.ReportingPluginConfig, + nil, + ocrParams.MaxDurationQuery, + ocrParams.MaxDurationObservation, + ocrParams.MaxDurationReport, + ocrParams.MaxDurationShouldAcceptFinalizedReport, + ocrParams.MaxDurationShouldTransmitAcceptedReport, + int(nodes.DefaultF()), + ocrParams.OnchainConfig, + ) + if err != nil { + return FinalOCR2Config{}, fmt.Errorf("failed to derive OCR2 config: %w", err) + } + var signersAddresses []common.Address + for _, signer := range signers { + if len(signer) != 20 { + return FinalOCR2Config{}, fmt.Errorf("address is not 20 bytes %s", signer) + } + signersAddresses = append(signersAddresses, common.BytesToAddress(signer)) + } + var transmittersAddresses []common.Address + for _, transmitter := range transmitters { + bytes, err := hexutil.Decode(string(transmitter)) + if err != nil { + return FinalOCR2Config{}, errors.Wrap(err, fmt.Sprintf("given address is not valid %s", transmitter)) + } + if len(bytes) != 20 { + return FinalOCR2Config{}, errors.Errorf("address is not 20 bytes %s", transmitter) + } + transmittersAddresses = append(transmittersAddresses, common.BytesToAddress(bytes)) + } + return FinalOCR2Config{ + Signers: signersAddresses, + Transmitters: transmittersAddresses, + F: threshold, + OnchainConfig: onchainConfig, + OffchainConfigVersion: offchainConfigVersion, + OffchainConfig: offchainConfig, + }, nil +} diff --git a/deployment/ccip/changeset/v1_5/cs_rmn.go b/deployment/ccip/changeset/v1_5/cs_rmn.go new file mode 100644 index 00000000000..ffe20294873 --- /dev/null +++ b/deployment/ccip/changeset/v1_5/cs_rmn.go @@ -0,0 +1,169 @@ +package v1_5 + +import ( + "context" + "fmt" + "math/big" + "slices" + + "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" +) + +var _ deployment.ChangeSet[PermaBlessCommitStoreConfig] = PermaBlessCommitStoreChangeset + +type PermaBlessConfigPerSourceChain struct { + SourceChainSelector uint64 + PermaBless bool // if true, the commit store will be included in adds and if false it will be included in removes list, + // https://github.com/smartcontractkit/ccip/blob/ccip-develop/contracts/src/v0.8/ccip/RMN.sol#L699C30-L699C54 +} + +func (p PermaBlessConfigPerSourceChain) Validate(destChain uint64, state changeset.CCIPOnChainState, permaBlessedCommitStores []common.Address) error { + if err := deployment.IsValidChainSelector(p.SourceChainSelector); err != nil { + return fmt.Errorf("invalid SourceChainSelector: %w", err) + } + _, ok := state.Chains[p.SourceChainSelector] + if !ok { + return fmt.Errorf("source chain state not found for chain selector %d", p.SourceChainSelector) + } + destState := state.Chains[destChain] + if destState.CommitStore[p.SourceChainSelector] == nil { + return fmt.Errorf("dest chain %d does not have a commit store for source chain %d", destChain, p.SourceChainSelector) + } + + if p.PermaBless { + if slices.Contains(permaBlessedCommitStores, destState.CommitStore[p.SourceChainSelector].Address()) { + return fmt.Errorf("commit store for source chain %d is already permablessed", p.SourceChainSelector) + } + } else { + if !slices.Contains(permaBlessedCommitStores, destState.CommitStore[p.SourceChainSelector].Address()) { + return fmt.Errorf("commit store for source chain %d is not permablessed, cannot be removed", p.SourceChainSelector) + } + } + return nil +} + +type PermaBlessCommitStoreConfigPerDest struct { + Sources []PermaBlessConfigPerSourceChain +} + +type PermaBlessCommitStoreConfig struct { + Configs map[uint64]PermaBlessCommitStoreConfigPerDest + MCMSConfig *changeset.MCMSConfig +} + +func (c PermaBlessCommitStoreConfig) Validate(env deployment.Environment) error { + state, err := changeset.LoadOnchainState(env) + if err != nil { + return fmt.Errorf("failed to load onchain state: %w", err) + } + for destChain, pCfg := range c.Configs { + if err := deployment.IsValidChainSelector(destChain); err != nil { + return fmt.Errorf("invalid DestChainSelector: %w", err) + } + destState, ok := state.Chains[destChain] + if !ok { + return fmt.Errorf("dest chain state not found for chain selector %d", destChain) + } + if destState.RMN == nil { + return fmt.Errorf("dest chain %d does not have an RMN", destChain) + } + if destState.CommitStore == nil { + return fmt.Errorf("dest chain %d does not have any commit store", destChain) + } + // get all permablessed commit stores + permaBlessedCommitStores, err := destState.RMN.GetPermaBlessedCommitStores(nil) + if err != nil { + return fmt.Errorf("failed to get perma blessed commit stores: %w", err) + } + for _, sourceCfg := range pCfg.Sources { + if err := sourceCfg.Validate(destChain, state, permaBlessedCommitStores); err != nil { + return fmt.Errorf("invalid PermaBlessConfig for source chain %d and dest chain %d : %w", sourceCfg.SourceChainSelector, destChain, err) + } + } + + if err := commoncs.ValidateOwnership(context.Background(), c.MCMSConfig != nil, env.Chains[destChain].DeployerKey.From, destState.Timelock.Address(), destState.RMN); err != nil { + return fmt.Errorf("failed to validate ownership: %w", err) + } + } + return nil +} + +// PermaBlessCommitStoreChangeset permablesses the commit stores on the RMN contract +// If commit store addresses are added to the permaBlessed list, those will be considered automatically blessed. +// This changeset can add to or remove from the existing permaBlessed list. +func PermaBlessCommitStoreChangeset(env deployment.Environment, c PermaBlessCommitStoreConfig) (deployment.ChangesetOutput, error) { + if err := c.Validate(env); err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("invalid PermaBlessCommitStoreConfig: %w", err) + } + state, err := changeset.LoadOnchainState(env) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) + } + ops := make([]timelock.BatchChainOperation, 0) + timelocks := make(map[uint64]common.Address) + proposerMCM := make(map[uint64]*gethwrappers.ManyChainMultiSig) + for destChain, cfg := range c.Configs { + destState := state.Chains[destChain] + RMN := destState.RMN + var removes []common.Address + var adds []common.Address + for _, sourceCfg := range cfg.Sources { + commitStore := destState.CommitStore[sourceCfg.SourceChainSelector] + if sourceCfg.PermaBless { + adds = append(adds, commitStore.Address()) + } else { + removes = append(removes, commitStore.Address()) + } + } + txOpts := env.Chains[destChain].DeployerKey + if c.MCMSConfig != nil { + txOpts = deployment.SimTransactOpts() + } + tx, err := RMN.OwnerRemoveThenAddPermaBlessedCommitStores(txOpts, removes, adds) + if c.MCMSConfig == nil { + _, err = deployment.ConfirmIfNoError(env.Chains[destChain], tx, err) + if err != nil { + return deployment.ChangesetOutput{}, err + } + env.Logger.Infof("PermaBlessed commit stores on chain %d removed %v, added %v", destChain, removes, adds) + continue + } + timelocks[destChain] = destState.Timelock.Address() + proposerMCM[destChain] = destState.ProposerMcm + ops = append(ops, timelock.BatchChainOperation{ + ChainIdentifier: mcms.ChainIdentifier(destChain), + Batch: []mcms.Operation{ + { + To: RMN.Address(), + Data: tx.Data(), + Value: big.NewInt(0), + }, + }, + }) + } + if c.MCMSConfig == nil { + return deployment.ChangesetOutput{}, nil + } + p, err := proposalutils.BuildProposalFromBatches( + timelocks, + proposerMCM, + ops, + "PermaBless commit stores on RMN", + c.MCMSConfig.MinDelay, + ) + if err != nil { + return deployment.ChangesetOutput{}, err + } + env.Logger.Infof("perma bless commit stores proposal created with %d operations", len(ops)) + return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{ + *p, + }}, nil +} diff --git a/deployment/ccip/changeset/v1_5/e2e_test.go b/deployment/ccip/changeset/v1_5/e2e_test.go new file mode 100644 index 00000000000..8911dcc8bf4 --- /dev/null +++ b/deployment/ccip/changeset/v1_5/e2e_test.go @@ -0,0 +1,96 @@ +package v1_5_test + +import ( + "context" + "testing" + + "github.com/ethereum/go-ethereum/common" + chainselectors "github.com/smartcontractkit/chain-selectors" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers/v1_5" + v1_5changeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_5" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_contract" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" +) + +// This test only works if the destination chain id is 1337 +// Otherwise it shows error for offchain and onchain config digest mismatch +func TestE2ELegacy(t *testing.T) { + e, _ := testhelpers.NewMemoryEnvironment( + t, + testhelpers.WithPrerequisiteDeploymentOnly(&changeset.V1_5DeploymentConfig{ + PriceRegStalenessThreshold: 60 * 60 * 24 * 14, // two weeks + RMNConfig: &rmn_contract.RMNConfig{ + BlessWeightThreshold: 2, + CurseWeightThreshold: 2, + // setting dummy voters, we will permabless this later + Voters: []rmn_contract.RMNVoter{ + { + BlessWeight: 2, + CurseWeight: 2, + BlessVoteAddr: utils.RandomAddress(), + CurseVoteAddr: utils.RandomAddress(), + }, + }, + }, + }), + testhelpers.WithNumOfChains(3), + testhelpers.WithChainIDs([]uint64{chainselectors.GETH_TESTNET.EvmChainID})) + state, err := changeset.LoadOnchainState(e.Env) + require.NoError(t, err) + allChains := e.Env.AllChainSelectorsExcluding([]uint64{chainselectors.GETH_TESTNET.Selector}) + require.Contains(t, e.Env.AllChainSelectors(), chainselectors.GETH_TESTNET.Selector) + require.Len(t, allChains, 2) + src, dest := allChains[1], chainselectors.GETH_TESTNET.Selector + srcChain := e.Env.Chains[src] + destChain := e.Env.Chains[dest] + pairs := []testhelpers.SourceDestPair{ + {SourceChainSelector: src, DestChainSelector: dest}, + } + e.Env = v1_5.AddLanes(t, e.Env, state, pairs) + // permabless the commit stores + e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, e.TimelockContracts(t), []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(v1_5changeset.PermaBlessCommitStoreChangeset), + Config: v1_5changeset.PermaBlessCommitStoreConfig{ + Configs: map[uint64]v1_5changeset.PermaBlessCommitStoreConfigPerDest{ + dest: { + Sources: []v1_5changeset.PermaBlessConfigPerSourceChain{ + { + SourceChainSelector: src, + PermaBless: true, + }, + }, + }, + }, + }, + }, + }) + require.NoError(t, err) + // reload state after adding lanes + state, err = changeset.LoadOnchainState(e.Env) + require.NoError(t, err) + sentEvent, err := v1_5.SendRequest(t, e.Env, state, + testhelpers.WithSourceChain(src), + testhelpers.WithDestChain(dest), + testhelpers.WithTestRouter(false), + testhelpers.WithEvm2AnyMessage(router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(state.Chains[dest].Receiver.Address().Bytes(), 32), + Data: []byte("hello"), + TokenAmounts: nil, + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: nil, + }), + ) + require.NoError(t, err) + require.NotNil(t, sentEvent) + destStartBlock, err := destChain.Client.HeaderByNumber(context.Background(), nil) + require.NoError(t, err) + v1_5.WaitForCommit(t, srcChain, destChain, state.Chains[dest].CommitStore[src], sentEvent.Message.SequenceNumber) + v1_5.WaitForExecute(t, srcChain, destChain, state.Chains[dest].EVM2EVMOffRamp[src], []uint64{sentEvent.Message.SequenceNumber}, destStartBlock.Number.Uint64()) +} diff --git a/deployment/ccip/changeset/view_test.go b/deployment/ccip/changeset/view_test.go index 35193979849..cb798835cd7 100644 --- a/deployment/ccip/changeset/view_test.go +++ b/deployment/ccip/changeset/view_test.go @@ -1,14 +1,17 @@ -package changeset +package changeset_test import ( "testing" "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" ) func TestSmokeView(t *testing.T) { t.Parallel() - tenv := NewMemoryEnvironment(t, WithChains(3)) - _, err := ViewCCIP(tenv.Env) + tenv, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithNumOfChains(3)) + _, err := changeset.ViewCCIP(tenv.Env) require.NoError(t, err) } diff --git a/deployment/ccip/view/v1_0/rmn_proxy_contract.go b/deployment/ccip/view/v1_0/rmn_proxy_contract.go index 6c628281399..5a2ea2807f6 100644 --- a/deployment/ccip/view/v1_0/rmn_proxy_contract.go +++ b/deployment/ccip/view/v1_0/rmn_proxy_contract.go @@ -1,6 +1,7 @@ package v1_0 import ( + "errors" "fmt" "github.com/ethereum/go-ethereum/common" @@ -14,9 +15,9 @@ type RMNProxyView struct { RMN common.Address `json:"rmn"` } -func GenerateRMNProxyView(r *rmn_proxy_contract.RMNProxyContract) (RMNProxyView, error) { +func GenerateRMNProxyView(r *rmn_proxy_contract.RMNProxy) (RMNProxyView, error) { if r == nil { - return RMNProxyView{}, fmt.Errorf("cannot generate view for nil RMNProxy") + return RMNProxyView{}, errors.New("cannot generate view for nil RMNProxy") } meta, err := types.NewContractMetaData(r, r.Address()) if err != nil { diff --git a/deployment/ccip/view/v1_2/price_registry.go b/deployment/ccip/view/v1_2/price_registry.go index ee0f1067b6c..269c48fccaf 100644 --- a/deployment/ccip/view/v1_2/price_registry.go +++ b/deployment/ccip/view/v1_2/price_registry.go @@ -1,6 +1,7 @@ package v1_2 import ( + "errors" "fmt" "github.com/ethereum/go-ethereum/common" @@ -18,7 +19,7 @@ type PriceRegistryView struct { func GeneratePriceRegistryView(pr *price_registry_1_2_0.PriceRegistry) (PriceRegistryView, error) { if pr == nil { - return PriceRegistryView{}, fmt.Errorf("cannot generate view for nil PriceRegistry") + return PriceRegistryView{}, errors.New("cannot generate view for nil PriceRegistry") } meta, err := types.NewContractMetaData(pr, pr.Address()) if err != nil { diff --git a/deployment/ccip/view/v1_2/price_registry_test.go b/deployment/ccip/view/v1_2/price_registry_test.go index cbcdbe253ce..8248f55335b 100644 --- a/deployment/ccip/view/v1_2/price_registry_test.go +++ b/deployment/ccip/view/v1_2/price_registry_test.go @@ -29,10 +29,10 @@ func TestGeneratePriceRegistryView(t *testing.T) { v, err := GeneratePriceRegistryView(c) require.NoError(t, err) assert.Equal(t, v.Owner, chain.DeployerKey.From) - assert.Equal(t, v.TypeAndVersion, "PriceRegistry 1.2.0") - assert.Equal(t, v.FeeTokens, []common.Address{f1, f2}) - assert.Equal(t, v.StalenessThreshold, "10") - assert.Equal(t, v.Updaters, []common.Address{chain.DeployerKey.From}) + assert.Equal(t, "PriceRegistry 1.2.0", v.TypeAndVersion) + assert.Equal(t, []common.Address{f1, f2}, v.FeeTokens) + assert.Equal(t, "10", v.StalenessThreshold) + assert.Equal(t, []common.Address{chain.DeployerKey.From}, v.Updaters) _, err = json.MarshalIndent(v, "", " ") require.NoError(t, err) } diff --git a/deployment/ccip/view/v1_5/commit_store.go b/deployment/ccip/view/v1_5/commit_store.go index ffea3b61f5f..396aa8b737a 100644 --- a/deployment/ccip/view/v1_5/commit_store.go +++ b/deployment/ccip/view/v1_5/commit_store.go @@ -1,6 +1,7 @@ package v1_5 import ( + "errors" "fmt" "github.com/ethereum/go-ethereum/common" @@ -24,7 +25,7 @@ type CommitStoreView struct { func GenerateCommitStoreView(c *commit_store.CommitStore) (CommitStoreView, error) { if c == nil { - return CommitStoreView{}, fmt.Errorf("cannot generate view for nil CommitStore") + return CommitStoreView{}, errors.New("cannot generate view for nil CommitStore") } meta, err := types.NewContractMetaData(c, c.Address()) if err != nil { diff --git a/deployment/ccip/view/v1_5/offramp.go b/deployment/ccip/view/v1_5/offramp.go index 95e40d9da27..95d92c445e4 100644 --- a/deployment/ccip/view/v1_5/offramp.go +++ b/deployment/ccip/view/v1_5/offramp.go @@ -1,6 +1,7 @@ package v1_5 import ( + "errors" "fmt" "github.com/smartcontractkit/chainlink/deployment/common/view/types" @@ -15,7 +16,7 @@ type OffRampView struct { func GenerateOffRampView(r *evm_2_evm_offramp.EVM2EVMOffRamp) (OffRampView, error) { if r == nil { - return OffRampView{}, fmt.Errorf("cannot generate view for nil OffRamp") + return OffRampView{}, errors.New("cannot generate view for nil OffRamp") } meta, err := types.NewContractMetaData(r, r.Address()) if err != nil { diff --git a/deployment/ccip/view/v1_5/offramp_test.go b/deployment/ccip/view/v1_5/offramp_test.go index d6539fe2ba5..47370501424 100644 --- a/deployment/ccip/view/v1_5/offramp_test.go +++ b/deployment/ccip/view/v1_5/offramp_test.go @@ -54,7 +54,7 @@ func TestOffRampView(t *testing.T) { v, err := GenerateOffRampView(c2) require.NoError(t, err) assert.Equal(t, v.StaticConfig, sc) - assert.Equal(t, v.TypeAndVersion, "EVM2EVMOffRamp 1.5.0") + assert.Equal(t, "EVM2EVMOffRamp 1.5.0", v.TypeAndVersion) _, err = json.MarshalIndent(v, "", " ") require.NoError(t, err) } diff --git a/deployment/ccip/view/v1_5/onramp.go b/deployment/ccip/view/v1_5/onramp.go index d679f6c14c0..c211c493cbc 100644 --- a/deployment/ccip/view/v1_5/onramp.go +++ b/deployment/ccip/view/v1_5/onramp.go @@ -1,6 +1,7 @@ package v1_5 import ( + "errors" "fmt" "github.com/smartcontractkit/chainlink/deployment/common/view/types" @@ -15,7 +16,7 @@ type OnRampView struct { func GenerateOnRampView(r *evm_2_evm_onramp.EVM2EVMOnRamp) (OnRampView, error) { if r == nil { - return OnRampView{}, fmt.Errorf("cannot generate view for nil OnRamp") + return OnRampView{}, errors.New("cannot generate view for nil OnRamp") } meta, err := types.NewContractMetaData(r, r.Address()) if err != nil { diff --git a/deployment/ccip/view/v1_5/onramp_test.go b/deployment/ccip/view/v1_5/onramp_test.go index 4d7ef0225a6..6ce21c9f032 100644 --- a/deployment/ccip/view/v1_5/onramp_test.go +++ b/deployment/ccip/view/v1_5/onramp_test.go @@ -64,8 +64,7 @@ func TestOnRampView(t *testing.T) { // Check a few fields. assert.Equal(t, v.StaticConfig.ChainSelector, chain.Selector) assert.Equal(t, v.DynamicConfig.Router, common.HexToAddress("0x4")) - assert.Equal(t, v.TypeAndVersion, "EVM2EVMOnRamp 1.5.0") + assert.Equal(t, "EVM2EVMOnRamp 1.5.0", v.TypeAndVersion) _, err = json.MarshalIndent(v, "", " ") require.NoError(t, err) - } diff --git a/deployment/ccip/view/v1_5/rmn.go b/deployment/ccip/view/v1_5/rmn.go index cef55460446..19535cf508e 100644 --- a/deployment/ccip/view/v1_5/rmn.go +++ b/deployment/ccip/view/v1_5/rmn.go @@ -1,6 +1,7 @@ package v1_5 import ( + "errors" "fmt" "github.com/smartcontractkit/chainlink/deployment/common/view/types" @@ -14,7 +15,7 @@ type RMNView struct { func GenerateRMNView(r *rmn_contract.RMNContract) (RMNView, error) { if r == nil { - return RMNView{}, fmt.Errorf("cannot generate view for nil RMN") + return RMNView{}, errors.New("cannot generate view for nil RMN") } meta, err := types.NewContractMetaData(r, r.Address()) if err != nil { diff --git a/deployment/ccip/view/v1_5/rmn_test.go b/deployment/ccip/view/v1_5/rmn_test.go index 3ec7d7a9cc9..f4ea35a116f 100644 --- a/deployment/ccip/view/v1_5/rmn_test.go +++ b/deployment/ccip/view/v1_5/rmn_test.go @@ -45,8 +45,8 @@ func TestGenerateRMNView(t *testing.T) { v, err := GenerateRMNView(c) require.NoError(t, err) assert.Equal(t, v.Owner, chain.DeployerKey.From) - assert.Equal(t, v.TypeAndVersion, "RMN 1.5.0") - assert.Equal(t, v.ConfigDetails.Version, uint32(1)) + assert.Equal(t, "RMN 1.5.0", v.TypeAndVersion) + assert.Equal(t, uint32(1), v.ConfigDetails.Version) assert.Equal(t, v.ConfigDetails.Config, cfg) _, err = json.MarshalIndent(v, "", " ") require.NoError(t, err) diff --git a/deployment/ccip/view/v1_5/tokenadminregistry.go b/deployment/ccip/view/v1_5/tokenadminregistry.go index 2fd36615bcd..e4a88996247 100644 --- a/deployment/ccip/view/v1_5/tokenadminregistry.go +++ b/deployment/ccip/view/v1_5/tokenadminregistry.go @@ -1,6 +1,7 @@ package v1_5 import ( + "errors" "fmt" "github.com/ethereum/go-ethereum/common" @@ -20,7 +21,7 @@ type TokenAdminRegistryView struct { func GenerateTokenAdminRegistryView(taContract *token_admin_registry.TokenAdminRegistry) (TokenAdminRegistryView, error) { if taContract == nil { - return TokenAdminRegistryView{}, fmt.Errorf("token admin registry contract is nil") + return TokenAdminRegistryView{}, errors.New("token admin registry contract is nil") } tokens, err := getAllConfiguredTokensPaginated(taContract) if err != nil { diff --git a/deployment/ccip/view/v1_6/ccip_home.go b/deployment/ccip/view/v1_6/ccip_home.go index ac1e23179c4..04b7dc8c1af 100644 --- a/deployment/ccip/view/v1_6/ccip_home.go +++ b/deployment/ccip/view/v1_6/ccip_home.go @@ -1,6 +1,7 @@ package v1_6 import ( + "errors" "fmt" "math/big" @@ -8,7 +9,7 @@ import ( "github.com/smartcontractkit/chainlink/deployment/common/view/types" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" ) // https://github.com/smartcontractkit/chainlink/blob/develop/contracts/src/v0.8/ccip/libraries/Internal.sol#L190 @@ -33,7 +34,7 @@ type CCIPHomeView struct { func GenerateCCIPHomeView(cr *capabilities_registry.CapabilitiesRegistry, ch *ccip_home.CCIPHome) (CCIPHomeView, error) { if ch == nil { - return CCIPHomeView{}, fmt.Errorf("cannot generate view for nil CCIPHome") + return CCIPHomeView{}, errors.New("cannot generate view for nil CCIPHome") } meta, err := types.NewContractMetaData(ch, ch.Address()) if err != nil { diff --git a/deployment/ccip/view/v1_6/ccip_home_test.go b/deployment/ccip/view/v1_6/ccip_home_test.go index 26f6f50aed5..3d4701d705a 100644 --- a/deployment/ccip/view/v1_6/ccip_home_test.go +++ b/deployment/ccip/view/v1_6/ccip_home_test.go @@ -11,7 +11,7 @@ import ( "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -33,7 +33,7 @@ func TestCCIPHomeView(t *testing.T) { v, err := GenerateCCIPHomeView(cr, ch) require.NoError(t, err) - assert.Equal(t, v.TypeAndVersion, "CCIPHome 1.6.0-dev") + assert.Equal(t, "CCIPHome 1.6.0-dev", v.TypeAndVersion) _, err = json.MarshalIndent(v, "", " ") require.NoError(t, err) diff --git a/deployment/ccip/view/v1_6/feequoter.go b/deployment/ccip/view/v1_6/feequoter.go index ed85f84ac2f..1fd10b3fb63 100644 --- a/deployment/ccip/view/v1_6/feequoter.go +++ b/deployment/ccip/view/v1_6/feequoter.go @@ -33,7 +33,9 @@ type FeeQuoterDestChainConfig struct { MaxDataBytes uint32 `json:"maxDataBytes,omitempty"` MaxPerMsgGasLimit uint32 `json:"maxPerMsgGasLimit,omitempty"` DestGasOverhead uint32 `json:"destGasOverhead,omitempty"` - DestGasPerPayloadByte uint16 `json:"destGasPerPayloadByte,omitempty"` + DestGasPerPayloadByteBase uint8 `json:"destGasPerPayloadByteBase,omitempty"` + DestGasPerPayloadByteHigh uint8 `json:"destGasPerPayloadByteHigh,omitempty"` + DestGasPerPayloadByteThreshold uint16 `json:"destGasPerPayloadByteThreshold,omitempty"` DestDataAvailabilityOverheadGas uint32 `json:"destDataAvailabilityOverheadGas,omitempty"` DestGasPerDataAvailabilityByte uint16 `json:"destGasPerDataAvailabilityByte,omitempty"` DestDataAvailabilityMultiplierBps uint16 `json:"destDataAvailabilityMultiplierBps,omitempty"` @@ -99,7 +101,9 @@ func GenerateFeeQuoterView(fqContract *fee_quoter.FeeQuoter, router *router1_2.R MaxDataBytes: destChainConfig.MaxDataBytes, MaxPerMsgGasLimit: destChainConfig.MaxPerMsgGasLimit, DestGasOverhead: destChainConfig.DestGasOverhead, - DestGasPerPayloadByte: destChainConfig.DestGasPerPayloadByte, + DestGasPerPayloadByteBase: destChainConfig.DestGasPerPayloadByteBase, + DestGasPerPayloadByteHigh: destChainConfig.DestGasPerPayloadByteHigh, + DestGasPerPayloadByteThreshold: destChainConfig.DestGasPerPayloadByteThreshold, DestDataAvailabilityOverheadGas: destChainConfig.DestDataAvailabilityOverheadGas, DestGasPerDataAvailabilityByte: destChainConfig.DestGasPerDataAvailabilityByte, DestDataAvailabilityMultiplierBps: destChainConfig.DestDataAvailabilityMultiplierBps, diff --git a/deployment/ccip/view/v1_6/rmnhome.go b/deployment/ccip/view/v1_6/rmnhome.go index 82d39074d6f..5a99c5d752c 100644 --- a/deployment/ccip/view/v1_6/rmnhome.go +++ b/deployment/ccip/view/v1_6/rmnhome.go @@ -7,6 +7,7 @@ import ( "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/smartcontractkit/chainlink/deployment/common/view/types" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" ) @@ -77,7 +78,7 @@ type RMNHomeDynamicConfig struct { type RMNHomeSourceChain struct { ChainSelector uint64 `json:"selector"` - F uint64 `json:"f"` + FObserve uint64 `json:"fObserve"` ObserverNodesBitmap *big.Int `json:"observerNodesBitmap"` } @@ -145,7 +146,7 @@ func mapSourceChains(chains []rmn_home.RMNHomeSourceChain) []RMNHomeSourceChain for i, chain := range chains { result[i] = RMNHomeSourceChain{ ChainSelector: chain.ChainSelector, - F: chain.F, + FObserve: chain.FObserve, ObserverNodesBitmap: chain.ObserverNodesBitmap, } } diff --git a/deployment/ccip/view/v1_6/rmnremote.go b/deployment/ccip/view/v1_6/rmnremote.go index c3708e0611a..e05754c2f0d 100644 --- a/deployment/ccip/view/v1_6/rmnremote.go +++ b/deployment/ccip/view/v1_6/rmnremote.go @@ -14,7 +14,7 @@ type RMNRemoteView struct { type RMNRemoteVersionedConfig struct { Version uint32 `json:"version"` Signers []RMNRemoteSigner `json:"signers"` - F uint64 `json:"f"` + Fsign uint64 `json:"fSign"` } type RMNRemoteSigner struct { @@ -34,7 +34,7 @@ func GenerateRMNRemoteView(rmnReader *rmn_remote.RMNRemote) (RMNRemoteView, erro rmnConfig := RMNRemoteVersionedConfig{ Version: config.Version, Signers: make([]RMNRemoteSigner, 0, len(config.Config.Signers)), - F: config.Config.F, + Fsign: config.Config.FSign, } for _, signer := range config.Config.Signers { rmnConfig.Signers = append(rmnConfig.Signers, RMNRemoteSigner{ diff --git a/deployment/ccip/view/view.go b/deployment/ccip/view/view.go index 4f216d13008..8f698ba2277 100644 --- a/deployment/ccip/view/view.go +++ b/deployment/ccip/view/view.go @@ -19,11 +19,16 @@ type ChainView struct { // v1.5 TokenAdminRegistry map[string]v1_5.TokenAdminRegistryView `json:"tokenAdminRegistry,omitempty"` CommitStore map[string]v1_5.CommitStoreView `json:"commitStore,omitempty"` + PriceRegistry map[string]v1_2.PriceRegistryView `json:"priceRegistry,omitempty"` + EVM2EVMOnRamp map[string]v1_5.OnRampView `json:"evm2evmOnRamp,omitempty"` + EVM2EVMOffRamp map[string]v1_5.OffRampView `json:"evm2evmOffRamp,omitempty"` + RMN map[string]v1_5.RMNView `json:"rmn,omitempty"` + // v1.6 FeeQuoter map[string]v1_6.FeeQuoterView `json:"feeQuoter,omitempty"` NonceManager map[string]v1_6.NonceManagerView `json:"nonceManager,omitempty"` + RMNRemote map[string]v1_6.RMNRemoteView `json:"rmnRemote,omitempty"` RMNHome map[string]v1_6.RMNHomeView `json:"rmnHome,omitempty"` - RMN map[string]v1_6.RMNRemoteView `json:"rmn,omitempty"` OnRamp map[string]v1_6.OnRampView `json:"onRamp,omitempty"` OffRamp map[string]v1_6.OffRampView `json:"offRamp,omitempty"` // TODO: Perhaps restrict to one CCIPHome/CR? Shouldn't @@ -40,15 +45,19 @@ func NewChain() ChainView { // v1.0 RMNProxy: make(map[string]v1_0.RMNProxyView), // v1.2 - Router: make(map[string]v1_2.RouterView), + Router: make(map[string]v1_2.RouterView), + PriceRegistry: make(map[string]v1_2.PriceRegistryView), // v1.5 TokenAdminRegistry: make(map[string]v1_5.TokenAdminRegistryView), CommitStore: make(map[string]v1_5.CommitStoreView), + EVM2EVMOnRamp: make(map[string]v1_5.OnRampView), + EVM2EVMOffRamp: make(map[string]v1_5.OffRampView), + RMN: make(map[string]v1_5.RMNView), // v1.6 FeeQuoter: make(map[string]v1_6.FeeQuoterView), NonceManager: make(map[string]v1_6.NonceManagerView), + RMNRemote: make(map[string]v1_6.RMNRemoteView), RMNHome: make(map[string]v1_6.RMNHomeView), - RMN: make(map[string]v1_6.RMNRemoteView), OnRamp: make(map[string]v1_6.OnRampView), OffRamp: make(map[string]v1_6.OffRampView), CapabilityRegistry: make(map[string]common_v1_0.CapabilityRegistryView), diff --git a/deployment/common/changeset/deploy_link_token.go b/deployment/common/changeset/deploy_link_token.go index c115a7ee083..607c33fbeaa 100644 --- a/deployment/common/changeset/deploy_link_token.go +++ b/deployment/common/changeset/deploy_link_token.go @@ -1,10 +1,17 @@ package changeset import ( + "context" "fmt" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/gagliardetto/solana-go" + solRpc "github.com/gagliardetto/solana-go/rpc" + chainsel "github.com/smartcontractkit/chain-selectors" + + solCommomUtil "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/common" + solTokenUtil "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/tokens" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/types" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/link_token" @@ -12,27 +19,48 @@ import ( var _ deployment.ChangeSet[[]uint64] = DeployLinkToken +const ( + TokenDecimalsSolana = 9 +) + // DeployLinkToken deploys a link token contract to the chain identified by the ChainSelector. func DeployLinkToken(e deployment.Environment, chains []uint64) (deployment.ChangesetOutput, error) { for _, chain := range chains { - _, ok := e.Chains[chain] - if !ok { - return deployment.ChangesetOutput{}, fmt.Errorf("chain not found in environment") + _, evmOk := e.Chains[chain] + _, solOk := e.SolChains[chain] + if !evmOk && !solOk { + return deployment.ChangesetOutput{}, fmt.Errorf("chain %d not found in environment", chain) } } newAddresses := deployment.NewMemoryAddressBook() for _, chain := range chains { - _, err := deployLinkTokenContract( - e.Logger, e.Chains[chain], newAddresses, - ) + family, err := chainsel.GetSelectorFamily(chain) if err != nil { return deployment.ChangesetOutput{AddressBook: newAddresses}, err } + switch family { + case chainsel.FamilyEVM: + // Deploy EVM LINK token + _, err := deployLinkTokenContractEVM( + e.Logger, e.Chains[chain], newAddresses, + ) + if err != nil { + return deployment.ChangesetOutput{AddressBook: newAddresses}, err + } + case chainsel.FamilySolana: + // Deploy Solana LINK token + err := deployLinkTokenContractSolana( + e.Logger, e.SolChains[chain], newAddresses, + ) + if err != nil { + return deployment.ChangesetOutput{AddressBook: newAddresses}, err + } + } } return deployment.ChangesetOutput{AddressBook: newAddresses}, nil } -func deployLinkTokenContract( +func deployLinkTokenContractEVM( lggr logger.Logger, chain deployment.Chain, ab deployment.AddressBook, @@ -57,3 +85,35 @@ func deployLinkTokenContract( } return linkToken, nil } + +func deployLinkTokenContractSolana( + lggr logger.Logger, + chain deployment.SolChain, + ab deployment.AddressBook, +) error { + adminPublicKey := chain.DeployerKey.PublicKey() + mint, _ := solana.NewRandomPrivateKey() + // this is the token address + mintPublicKey := mint.PublicKey() + instructions, err := solTokenUtil.CreateToken( + context.Background(), solana.Token2022ProgramID, mintPublicKey, adminPublicKey, TokenDecimalsSolana, chain.Client, solRpc.CommitmentConfirmed, + ) + if err != nil { + lggr.Errorw("Failed to generate instructions for link token deployment", "chain", chain.String(), "err", err) + return err + } + err = chain.Confirm(instructions, solCommomUtil.AddSigners(mint)) + if err != nil { + lggr.Errorw("Failed to confirm instructions for link token deployment", "chain", chain.String(), "err", err) + return err + } + tv := deployment.NewTypeAndVersion(types.LinkToken, deployment.Version1_0_0) + lggr.Infow("Deployed contract", "Contract", tv.String(), "addr", mintPublicKey.String(), "chain", chain.String()) + err = ab.Save(chain.Selector, mintPublicKey.String(), tv) + if err != nil { + lggr.Errorw("Failed to save link token", "chain", chain.String(), "err", err) + return err + } + + return nil +} diff --git a/deployment/common/changeset/deploy_link_token_test.go b/deployment/common/changeset/deploy_link_token_test.go index bc472d2a247..ddaca52c2d5 100644 --- a/deployment/common/changeset/deploy_link_token_test.go +++ b/deployment/common/changeset/deploy_link_token_test.go @@ -15,13 +15,15 @@ func TestDeployLinkToken(t *testing.T) { t.Parallel() lggr := logger.TestLogger(t) e := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ - Chains: 1, + Chains: 1, + SolChains: 1, }) chain1 := e.AllChainSelectors()[0] + solChain1 := e.AllChainSelectorsSolana()[0] e, err := changeset.ApplyChangesets(t, e, nil, []changeset.ChangesetApplication{ { Changeset: changeset.WrapChangeSet(changeset.DeployLinkToken), - Config: []uint64{chain1}, + Config: []uint64{chain1, solChain1}, }, }) require.NoError(t, err) @@ -32,4 +34,10 @@ func TestDeployLinkToken(t *testing.T) { // View itself already unit tested _, err = state.GenerateLinkView() require.NoError(t, err) + + // solana test + addrs, err = e.ExistingAddresses.AddressesForChain(solChain1) + require.NoError(t, err) + require.NotEmpty(t, addrs) + } diff --git a/deployment/common/changeset/deploy_mcms_with_timelock.go b/deployment/common/changeset/deploy_mcms_with_timelock.go index c36e1f1575b..06f9aba6164 100644 --- a/deployment/common/changeset/deploy_mcms_with_timelock.go +++ b/deployment/common/changeset/deploy_mcms_with_timelock.go @@ -1,6 +1,12 @@ package changeset import ( + "context" + "fmt" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/changeset/internal" "github.com/smartcontractkit/chainlink/deployment/common/types" @@ -18,3 +24,16 @@ func DeployMCMSWithTimelock(e deployment.Environment, cfgByChain map[uint64]type } return deployment.ChangesetOutput{AddressBook: newAddresses}, nil } + +func ValidateOwnership(ctx context.Context, mcms bool, deployerKey, timelock common.Address, contract Ownable) error { + owner, err := contract.Owner(&bind.CallOpts{Context: ctx}) + if err != nil { + return fmt.Errorf("failed to get owner: %w", err) + } + if mcms && owner != timelock { + return fmt.Errorf("%s not owned by deployer key", contract.Address()) + } else if !mcms && owner != deployerKey { + return fmt.Errorf("%s not owned by deployer key", contract.Address()) + } + return nil +} diff --git a/deployment/common/changeset/example/add_mint_burners_link.go b/deployment/common/changeset/example/add_mint_burners_link.go index 7322f99dd60..d41734519d7 100644 --- a/deployment/common/changeset/example/add_mint_burners_link.go +++ b/deployment/common/changeset/example/add_mint_burners_link.go @@ -18,7 +18,6 @@ var _ deployment.ChangeSet[*AddMintersBurnersLinkConfig] = AddMintersBurnersLink // AddMintersBurnersLink grants the minter / burner role to the provided addresses. func AddMintersBurnersLink(e deployment.Environment, cfg *AddMintersBurnersLinkConfig) (deployment.ChangesetOutput, error) { - chain := e.Chains[cfg.ChainSelector] addresses, err := e.ExistingAddresses.AddressesForChain(cfg.ChainSelector) if err != nil { @@ -66,5 +65,4 @@ func AddMintersBurnersLink(e deployment.Environment, cfg *AddMintersBurnersLinkC } } return deployment.ChangesetOutput{}, nil - } diff --git a/deployment/common/changeset/example/link_transfer.go b/deployment/common/changeset/example/link_transfer.go index 2e3be48a4d1..6253be187c0 100644 --- a/deployment/common/changeset/example/link_transfer.go +++ b/deployment/common/changeset/example/link_transfer.go @@ -135,7 +135,6 @@ func initStatePerChain(cfg *LinkTransferConfig, e deployment.Environment) ( mcmsStatePerChain, err = changeset.MaybeLoadMCMSWithTimelockState(e, chainSelectors) if err != nil { return nil, nil, err - } return linkStatePerChain, mcmsStatePerChain, nil } @@ -160,12 +159,10 @@ func transferOrBuildTx( } } return tx, nil - } // LinkTransfer takes the given link transfers and executes them or creates an MCMS proposal for them. func LinkTransfer(e deployment.Environment, cfg *LinkTransferConfig) (deployment.ChangesetOutput, error) { - err := cfg.Validate(e) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("invalid LinkTransferConfig: %w", err) diff --git a/deployment/common/changeset/example/link_transfer_test.go b/deployment/common/changeset/example/link_transfer_test.go index eecfbd37c95..4cc2bd0880b 100644 --- a/deployment/common/changeset/example/link_transfer_test.go +++ b/deployment/common/changeset/example/link_transfer_test.go @@ -25,7 +25,6 @@ import ( // setupLinkTransferContracts deploys all required contracts for the link transfer tests and returns the updated env. func setupLinkTransferTestEnv(t *testing.T) deployment.Environment { - lggr := logger.TestLogger(t) cfg := memory.MemoryEnvironmentConfig{ Nodes: 1, diff --git a/deployment/common/changeset/example/mint_link.go b/deployment/common/changeset/example/mint_link.go index dc50f8a1a27..8a71555928e 100644 --- a/deployment/common/changeset/example/mint_link.go +++ b/deployment/common/changeset/example/mint_link.go @@ -19,7 +19,6 @@ var _ deployment.ChangeSet[*MintLinkConfig] = MintLink // MintLink mints LINK to the provided contract. func MintLink(e deployment.Environment, cfg *MintLinkConfig) (deployment.ChangesetOutput, error) { - chain := e.Chains[cfg.ChainSelector] addresses, err := e.ExistingAddresses.AddressesForChain(cfg.ChainSelector) if err != nil { @@ -39,5 +38,4 @@ func MintLink(e deployment.Environment, cfg *MintLinkConfig) (deployment.Changes return deployment.ChangesetOutput{}, err } return deployment.ChangesetOutput{}, nil - } diff --git a/deployment/common/changeset/internal/mcms.go b/deployment/common/changeset/internal/mcms.go index baa82d77c8f..61808e1cbbd 100644 --- a/deployment/common/changeset/internal/mcms.go +++ b/deployment/common/changeset/internal/mcms.go @@ -27,7 +27,7 @@ func DeployMCMSWithConfig( chain.Client, ) return deployment.ContractDeploy[*owner_helpers.ManyChainMultiSig]{ - mcmAddr, mcm, tx, deployment.NewTypeAndVersion(contractType, deployment.Version1_0_0), err2, + Address: mcmAddr, Contract: mcm, Tx: tx, Tv: deployment.NewTypeAndVersion(contractType, deployment.Version1_0_0), Err: err2, } }) if err != nil { @@ -115,7 +115,7 @@ func DeployMCMSWithTimelockContracts( []common.Address{bypasser.Address}, // bypassers ) return deployment.ContractDeploy[*owner_helpers.RBACTimelock]{ - timelock, cc, tx2, deployment.NewTypeAndVersion(types.RBACTimelock, deployment.Version1_0_0), err2, + Address: timelock, Contract: cc, Tx: tx2, Tv: deployment.NewTypeAndVersion(types.RBACTimelock, deployment.Version1_0_0), Err: err2, } }) if err != nil { @@ -131,7 +131,7 @@ func DeployMCMSWithTimelockContracts( timelock.Address, ) return deployment.ContractDeploy[*owner_helpers.CallProxy]{ - callProxy, cc, tx2, deployment.NewTypeAndVersion(types.CallProxy, deployment.Version1_0_0), err2, + Address: callProxy, Contract: cc, Tx: tx2, Tv: deployment.NewTypeAndVersion(types.CallProxy, deployment.Version1_0_0), Err: err2, } }) if err != nil { diff --git a/deployment/common/changeset/internal/mcms_test.go b/deployment/common/changeset/internal/mcms_test.go index ff013717d30..92822422daa 100644 --- a/deployment/common/changeset/internal/mcms_test.go +++ b/deployment/common/changeset/internal/mcms_test.go @@ -18,9 +18,9 @@ import ( func TestDeployMCMSWithConfig(t *testing.T) { lggr := logger.TestLogger(t) - chains := memory.NewMemoryChainsWithChainIDs(t, []uint64{ + chains, _ := memory.NewMemoryChainsWithChainIDs(t, []uint64{ chainsel.TEST_90000001.EvmChainID, - }) + }, 1) ab := deployment.NewMemoryAddressBook() _, err := internal.DeployMCMSWithConfig(types.ProposerManyChainMultisig, lggr, chains[chainsel.TEST_90000001.Selector], ab, proposalutils.SingleGroupMCMS(t)) @@ -29,9 +29,9 @@ func TestDeployMCMSWithConfig(t *testing.T) { func TestDeployMCMSWithTimelockContracts(t *testing.T) { lggr := logger.TestLogger(t) - chains := memory.NewMemoryChainsWithChainIDs(t, []uint64{ + chains, _ := memory.NewMemoryChainsWithChainIDs(t, []uint64{ chainsel.TEST_90000001.EvmChainID, - }) + }, 1) ab := deployment.NewMemoryAddressBook() _, err := internal.DeployMCMSWithTimelockContracts(lggr, chains[chainsel.TEST_90000001.Selector], diff --git a/deployment/common/changeset/save_existing.go b/deployment/common/changeset/save_existing.go index a5177c8e49b..17fdc0a8025 100644 --- a/deployment/common/changeset/save_existing.go +++ b/deployment/common/changeset/save_existing.go @@ -11,7 +11,7 @@ import ( ) var ( - _ deployment.ChangeSet[ExistingContractsConfig] = SaveExistingContracts + _ deployment.ChangeSet[ExistingContractsConfig] = SaveExistingContractsChangeset ) type Contract struct { @@ -30,21 +30,21 @@ func (cfg ExistingContractsConfig) Validate() error { return fmt.Errorf("invalid chain selector: %d - %w", ec.ChainSelector, err) } if ec.Address == (common.Address{}) { - return fmt.Errorf("address must be set") + return errors.New("address must be set") } if ec.TypeAndVersion.Type == "" { - return fmt.Errorf("type must be set") + return errors.New("type must be set") } if val, err := ec.TypeAndVersion.Version.Value(); err != nil || val == "" { - return fmt.Errorf("version must be set") + return errors.New("version must be set") } } return nil } -// SaveExistingContracts saves the existing contracts to the address book. +// SaveExistingContractsChangeset saves the existing contracts to the address book. // Caller should update the environment's address book with the returned addresses. -func SaveExistingContracts(env deployment.Environment, cfg ExistingContractsConfig) (deployment.ChangesetOutput, error) { +func SaveExistingContractsChangeset(env deployment.Environment, cfg ExistingContractsConfig) (deployment.ChangesetOutput, error) { err := cfg.Validate() if err != nil { return deployment.ChangesetOutput{}, errors.Wrapf(deployment.ErrInvalidConfig, "%v", err) diff --git a/deployment/common/changeset/save_existing_test.go b/deployment/common/changeset/save_existing_test.go index 2a2618c8f54..a7e8c9068f3 100644 --- a/deployment/common/changeset/save_existing_test.go +++ b/deployment/common/changeset/save_existing_test.go @@ -43,7 +43,7 @@ func TestSaveExisting(t *testing.T) { }, } - output, err := SaveExistingContracts(dummyEnv, ExistingContracts) + output, err := SaveExistingContractsChangeset(dummyEnv, ExistingContracts) require.NoError(t, err) require.NoError(t, dummyEnv.ExistingAddresses.Merge(output.AddressBook)) addresses, err := dummyEnv.ExistingAddresses.Addresses() diff --git a/deployment/common/changeset/set_config_mcms.go b/deployment/common/changeset/set_config_mcms.go new file mode 100644 index 00000000000..5e2dc718b95 --- /dev/null +++ b/deployment/common/changeset/set_config_mcms.go @@ -0,0 +1,208 @@ +package changeset + +import ( + "context" + "errors" + "fmt" + "math/big" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/config" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + chain_selectors "github.com/smartcontractkit/chain-selectors" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" + commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" +) + +type ConfigPerRole struct { + Proposer config.Config + Canceller config.Config + Bypasser config.Config +} +type TimelockConfig struct { + MinDelay time.Duration // delay for timelock worker to execute the transfers. +} + +type MCMSConfig struct { + ConfigsPerChain map[uint64]ConfigPerRole + ProposalConfig *TimelockConfig +} + +var _ deployment.ChangeSet[MCMSConfig] = SetConfigMCMS + +// Validate checks that the MCMSConfig is valid +func (cfg MCMSConfig) Validate(e deployment.Environment, selectors []uint64) error { + if len(cfg.ConfigsPerChain) == 0 { + return errors.New("no chain configs provided") + } + // configs should have at least one chain + state, err := MaybeLoadMCMSWithTimelockState(e, selectors) + if err != nil { + return err + } + for chainSelector, c := range cfg.ConfigsPerChain { + family, err := chain_selectors.GetSelectorFamily(chainSelector) + if err != nil { + return err + } + if family != chain_selectors.FamilyEVM { + return fmt.Errorf("chain selector: %d is not an ethereum chain", chainSelector) + } + _, ok := e.Chains[chainSelector] + if !ok { + return fmt.Errorf("chain selector: %d not found in environment", chainSelector) + } + _, ok = state[chainSelector] + if !ok { + return fmt.Errorf("chain selector: %d not found for MCMS state", chainSelector) + } + if err := c.Proposer.Validate(); err != nil { + return err + } + if err := c.Canceller.Validate(); err != nil { + return err + } + if err := c.Bypasser.Validate(); err != nil { + return err + } + } + return nil +} + +// setConfigOrTxData executes set config tx or gets the tx data for the MCMS proposal +func setConfigOrTxData(ctx context.Context, lggr logger.Logger, chain deployment.Chain, cfg config.Config, contract *gethwrappers.ManyChainMultiSig, useMCMS bool) (*types.Transaction, error) { + groupQuorums, groupParents, signerAddresses, signerGroups := cfg.ExtractSetConfigInputs() + opts := deployment.SimTransactOpts() + if !useMCMS { + opts = chain.DeployerKey + } + opts.Context = ctx + tx, err := contract.SetConfig(opts, signerAddresses, signerGroups, groupQuorums, groupParents, false) + if err != nil { + return nil, err + } + if !useMCMS { + _, err = deployment.ConfirmIfNoError(chain, tx, err) + if err != nil { + return nil, err + } + lggr.Infow("SetConfigMCMS tx confirmed", "txHash", tx.Hash().Hex()) + } + return tx, nil +} + +type setConfigTxs struct { + proposerTx *types.Transaction + cancellerTx *types.Transaction + bypasserTx *types.Transaction +} + +// setConfigPerRole sets the configuration for each of the MCMS contract roles on the mcmsState. +func setConfigPerRole(ctx context.Context, lggr logger.Logger, chain deployment.Chain, cfg ConfigPerRole, mcmsState *MCMSWithTimelockState, useMCMS bool) (setConfigTxs, error) { + // Proposer set config + proposerTx, err := setConfigOrTxData(ctx, lggr, chain, cfg.Proposer, mcmsState.ProposerMcm, useMCMS) + if err != nil { + return setConfigTxs{}, err + } + // Canceller set config + cancellerTx, err := setConfigOrTxData(ctx, lggr, chain, cfg.Canceller, mcmsState.CancellerMcm, useMCMS) + if err != nil { + return setConfigTxs{}, err + } + // Bypasser set config + bypasserTx, err := setConfigOrTxData(ctx, lggr, chain, cfg.Bypasser, mcmsState.BypasserMcm, useMCMS) + if err != nil { + return setConfigTxs{}, err + } + + return setConfigTxs{ + proposerTx: proposerTx, + cancellerTx: cancellerTx, + bypasserTx: bypasserTx, + }, nil +} + +func addTxsToProposalBatch(setConfigTxsChain setConfigTxs, chainSelector uint64, state MCMSWithTimelockState) timelock.BatchChainOperation { + result := timelock.BatchChainOperation{ + ChainIdentifier: mcms.ChainIdentifier(chainSelector), + Batch: []mcms.Operation{}, + } + result.Batch = append(result.Batch, mcms.Operation{ + To: state.ProposerMcm.Address(), + Data: setConfigTxsChain.proposerTx.Data(), + Value: big.NewInt(0), + ContractType: string(commontypes.ProposerManyChainMultisig), + }) + result.Batch = append(result.Batch, mcms.Operation{ + To: state.CancellerMcm.Address(), + Data: setConfigTxsChain.cancellerTx.Data(), + Value: big.NewInt(0), + ContractType: string(commontypes.CancellerManyChainMultisig), + }) + result.Batch = append(result.Batch, mcms.Operation{ + To: state.BypasserMcm.Address(), + Data: setConfigTxsChain.bypasserTx.Data(), + Value: big.NewInt(0), + ContractType: string(commontypes.BypasserManyChainMultisig), + }) + return result +} + +// SetConfigMCMS sets the configuration of the MCMS contract on the chain identified by the chainSelector. +func SetConfigMCMS(e deployment.Environment, cfg MCMSConfig) (deployment.ChangesetOutput, error) { + selectors := []uint64{} + lggr := e.Logger + ctx := e.GetContext() + for chainSelector := range cfg.ConfigsPerChain { + selectors = append(selectors, chainSelector) + } + useMCMS := cfg.ProposalConfig != nil + err := cfg.Validate(e, selectors) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + batches := []timelock.BatchChainOperation{} + timelocksPerChain := map[uint64]common.Address{} + proposerMcmsPerChain := map[uint64]*gethwrappers.ManyChainMultiSig{} + + mcmsStatePerChain, err := MaybeLoadMCMSWithTimelockState(e, selectors) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + for chainSelector, c := range cfg.ConfigsPerChain { + chain := e.Chains[chainSelector] + state := mcmsStatePerChain[chainSelector] + timelocksPerChain[chainSelector] = state.Timelock.Address() + proposerMcmsPerChain[chainSelector] = state.ProposerMcm + setConfigTxsChain, err := setConfigPerRole(ctx, lggr, chain, c, state, useMCMS) + if err != nil { + return deployment.ChangesetOutput{}, err + } + if useMCMS { + batch := addTxsToProposalBatch(setConfigTxsChain, chainSelector, *state) + batches = append(batches, batch) + } + } + + if useMCMS { + // Create MCMS with timelock proposal + proposal, err := proposalutils.BuildProposalFromBatches(timelocksPerChain, proposerMcmsPerChain, batches, "Set config proposal", cfg.ProposalConfig.MinDelay) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to build proposal from batch: %w", err) + } + lggr.Infow("SetConfigMCMS proposal created", "proposal", proposal) + return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{*proposal}}, nil + } + + return deployment.ChangesetOutput{}, nil +} diff --git a/deployment/common/changeset/set_config_mcms_test.go b/deployment/common/changeset/set_config_mcms_test.go new file mode 100644 index 00000000000..207b37c00f3 --- /dev/null +++ b/deployment/common/changeset/set_config_mcms_test.go @@ -0,0 +1,311 @@ +package changeset_test + +import ( + "testing" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/config" + chain_selectors "github.com/smartcontractkit/chain-selectors" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" + "github.com/smartcontractkit/chainlink/v2/core/logger" + + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + + "github.com/smartcontractkit/chainlink/deployment" + + "github.com/smartcontractkit/chainlink/deployment/common/types" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" +) + +// setupSetConfigTestEnv deploys all required contracts for the setConfig MCMS contract call. +func setupSetConfigTestEnv(t *testing.T) deployment.Environment { + lggr := logger.TestLogger(t) + cfg := memory.MemoryEnvironmentConfig{ + Nodes: 1, + Chains: 2, + } + env := memory.NewMemoryEnvironment(t, lggr, zapcore.DebugLevel, cfg) + chainSelector := env.AllChainSelectors()[0] + + config := proposalutils.SingleGroupTimelockConfig(t) + // Deploy MCMS and Timelock + env, err := commonchangeset.ApplyChangesets(t, env, nil, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployLinkToken), + Config: []uint64{chainSelector}, + }, + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock), + Config: map[uint64]types.MCMSWithTimelockConfig{ + chainSelector: config, + }, + }, + }) + require.NoError(t, err) + return env +} + +// TestSetConfigMCMSVariants tests the SetConfigMCMS changeset variants. +func TestSetConfigMCMSVariants(t *testing.T) { + // Add the timelock as a signer to check state changes + for _, tc := range []struct { + name string + changeSets func(mcmsState *commonchangeset.MCMSWithTimelockState, chainSel uint64, cfgProp, cfgCancel, cfgBypass config.Config) []commonchangeset.ChangesetApplication + }{ + { + name: "MCMS disabled", + changeSets: func(mcmsState *commonchangeset.MCMSWithTimelockState, chainSel uint64, cfgProp, cfgCancel, cfgBypass config.Config) []commonchangeset.ChangesetApplication { + return []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.SetConfigMCMS), + Config: commonchangeset.MCMSConfig{ + ConfigsPerChain: map[uint64]commonchangeset.ConfigPerRole{ + chainSel: { + Proposer: cfgProp, + Canceller: cfgCancel, + Bypasser: cfgBypass, + }, + }, + }, + }, + } + }, + }, + { + name: "MCMS enabled", + changeSets: func(mcmsState *commonchangeset.MCMSWithTimelockState, chainSel uint64, cfgProp, cfgCancel, cfgBypass config.Config) []commonchangeset.ChangesetApplication { + return []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.TransferToMCMSWithTimelock), + Config: commonchangeset.TransferToMCMSWithTimelockConfig{ + ContractsByChain: map[uint64][]common.Address{ + chainSel: {mcmsState.ProposerMcm.Address(), mcmsState.BypasserMcm.Address(), mcmsState.CancellerMcm.Address()}, + }, + }, + }, + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.SetConfigMCMS), + Config: commonchangeset.MCMSConfig{ + ProposalConfig: &commonchangeset.TimelockConfig{ + MinDelay: 0, + }, + ConfigsPerChain: map[uint64]commonchangeset.ConfigPerRole{ + chainSel: { + Proposer: cfgProp, + Canceller: cfgCancel, + Bypasser: cfgBypass, + }, + }, + }, + }, + } + }, + }, + } { + t.Run(tc.name, func(t *testing.T) { + ctx := tests.Context(t) + + env := setupSetConfigTestEnv(t) + chainSelector := env.AllChainSelectors()[0] + chain := env.Chains[chainSelector] + addrs, err := env.ExistingAddresses.AddressesForChain(chainSelector) + require.NoError(t, err) + require.Len(t, addrs, 6) + + mcmsState, err := commonchangeset.MaybeLoadMCMSWithTimelockChainState(chain, addrs) + require.NoError(t, err) + timelockAddress := mcmsState.Timelock.Address() + cfgProposer := proposalutils.SingleGroupMCMS(t) + cfgProposer.Signers = append(cfgProposer.Signers, timelockAddress) + cfgProposer.Quorum = 2 // quorum should change to 2 out of 2 signers + timelockMap := map[uint64]*proposalutils.TimelockExecutionContracts{ + chainSelector: { + Timelock: mcmsState.Timelock, + CallProxy: mcmsState.CallProxy, + }, + } + cfgCanceller := proposalutils.SingleGroupMCMS(t) + cfgBypasser := proposalutils.SingleGroupMCMS(t) + cfgBypasser.Signers = append(cfgBypasser.Signers, timelockAddress) + cfgBypasser.Signers = append(cfgBypasser.Signers, mcmsState.ProposerMcm.Address()) + cfgBypasser.Quorum = 3 // quorum should change to 3 out of 3 signers + + // Set config on all 3 MCMS contracts + changesetsToApply := tc.changeSets(mcmsState, chainSelector, cfgProposer, cfgCanceller, cfgBypasser) + _, err = commonchangeset.ApplyChangesets(t, env, timelockMap, changesetsToApply) + require.NoError(t, err) + + // Check new State + expected := cfgProposer.ToRawConfig() + opts := &bind.CallOpts{Context: ctx} + newConf, err := mcmsState.ProposerMcm.GetConfig(opts) + require.NoError(t, err) + require.Equal(t, expected, newConf) + + expected = cfgBypasser.ToRawConfig() + newConf, err = mcmsState.BypasserMcm.GetConfig(opts) + require.NoError(t, err) + require.Equal(t, expected, newConf) + + expected = cfgCanceller.ToRawConfig() + newConf, err = mcmsState.CancellerMcm.GetConfig(opts) + require.NoError(t, err) + require.Equal(t, expected, newConf) + }) + } +} + +func TestValidate(t *testing.T) { + env := setupSetConfigTestEnv(t) + + chainSelector := env.AllChainSelectors()[0] + chain := env.Chains[chainSelector] + addrs, err := env.ExistingAddresses.AddressesForChain(chainSelector) + require.NoError(t, err) + require.Len(t, addrs, 6) + mcmsState, err := commonchangeset.MaybeLoadMCMSWithTimelockChainState(chain, addrs) + require.NoError(t, err) + cfg := proposalutils.SingleGroupMCMS(t) + timelockAddress := mcmsState.Timelock.Address() + // Add the timelock as a signer to check state changes + cfg.Signers = append(cfg.Signers, timelockAddress) + cfg.Quorum = 2 // quorum + + cfgInvalid := proposalutils.SingleGroupMCMS(t) + cfgInvalid.Quorum = 0 + require.NoError(t, err) + tests := []struct { + name string + cfg commonchangeset.MCMSConfig + errorMsg string + }{ + { + name: "valid config", + cfg: commonchangeset.MCMSConfig{ + ProposalConfig: &commonchangeset.TimelockConfig{ + MinDelay: 0, + }, + ConfigsPerChain: map[uint64]commonchangeset.ConfigPerRole{ + chainSelector: { + Proposer: cfg, + Canceller: cfg, + Bypasser: cfg, + }, + }, + }, + }, + { + name: "valid non mcms config", + cfg: commonchangeset.MCMSConfig{ + ConfigsPerChain: map[uint64]commonchangeset.ConfigPerRole{ + chainSelector: { + Proposer: cfg, + Canceller: cfg, + Bypasser: cfg, + }, + }, + }, + }, + { + name: "no chain configurations", + cfg: commonchangeset.MCMSConfig{ + ConfigsPerChain: map[uint64]commonchangeset.ConfigPerRole{}, + }, + errorMsg: "no chain configs provided", + }, + { + name: "non evm chain", + cfg: commonchangeset.MCMSConfig{ + ConfigsPerChain: map[uint64]commonchangeset.ConfigPerRole{ + chain_selectors.APTOS_MAINNET.Selector: { + Proposer: cfg, + Canceller: cfg, + Bypasser: cfg, + }, + }, + }, + errorMsg: "chain selector: 4741433654826277614 is not an ethereum chain", + }, + { + name: "chain selector not found in environment", + cfg: commonchangeset.MCMSConfig{ + ConfigsPerChain: map[uint64]commonchangeset.ConfigPerRole{ + 123: { + Proposer: cfg, + Canceller: cfg, + Bypasser: cfg, + }, + }, + }, + errorMsg: "unknown chain selector 123", + }, + { + name: "invalid proposer config", + cfg: commonchangeset.MCMSConfig{ + ProposalConfig: &commonchangeset.TimelockConfig{ + MinDelay: 0, + }, + ConfigsPerChain: map[uint64]commonchangeset.ConfigPerRole{ + chainSelector: { + Proposer: cfgInvalid, + Canceller: cfg, + Bypasser: cfg, + }, + }, + }, + errorMsg: "invalid MCMS config: Quorum must be greater than 0", + }, + { + name: "invalid canceller config", + cfg: commonchangeset.MCMSConfig{ + ProposalConfig: &commonchangeset.TimelockConfig{ + MinDelay: 0, + }, + ConfigsPerChain: map[uint64]commonchangeset.ConfigPerRole{ + chainSelector: { + Proposer: cfg, + Canceller: cfgInvalid, + Bypasser: cfg, + }, + }, + }, + errorMsg: "invalid MCMS config: Quorum must be greater than 0", + }, + { + name: "invalid bypasser config", + cfg: commonchangeset.MCMSConfig{ + ProposalConfig: &commonchangeset.TimelockConfig{ + MinDelay: 0, + }, + ConfigsPerChain: map[uint64]commonchangeset.ConfigPerRole{ + chainSelector: { + Proposer: cfg, + Canceller: cfg, + Bypasser: cfgInvalid, + }, + }, + }, + errorMsg: "invalid MCMS config: Quorum must be greater than 0", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + selectors := []uint64{chainSelector} + + err := tt.cfg.Validate(env, selectors) + if tt.errorMsg != "" { + require.Error(t, err) + require.Contains(t, err.Error(), tt.errorMsg) + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/deployment/common/changeset/test_helpers.go b/deployment/common/changeset/test_helpers.go index e92b36e5b55..a8105b26561 100644 --- a/deployment/common/changeset/test_helpers.go +++ b/deployment/common/changeset/test_helpers.go @@ -5,6 +5,7 @@ import ( "testing" mapset "github.com/deckarep/golang-set/v2" + jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" @@ -89,6 +90,7 @@ func ApplyChangesets(t *testing.T, e deployment.Environment, timelockContractsPe Logger: e.Logger, ExistingAddresses: addresses, Chains: e.Chains, + SolChains: e.SolChains, NodeIDs: e.NodeIDs, Offchain: e.Offchain, OCRSecrets: e.OCRSecrets, diff --git a/deployment/common/changeset/transfer_to_mcms_with_timelock.go b/deployment/common/changeset/transfer_to_mcms_with_timelock.go index afba1afa48b..da932a95b01 100644 --- a/deployment/common/changeset/transfer_to_mcms_with_timelock.go +++ b/deployment/common/changeset/transfer_to_mcms_with_timelock.go @@ -36,11 +36,11 @@ func LoadOwnableContract(addr common.Address, client bind.ContractBackend) (comm // Just using the ownership interface from here. c, err := burn_mint_erc677.NewBurnMintERC677(addr, client) if err != nil { - return common.Address{}, nil, fmt.Errorf("failed to create contract: %v", err) + return common.Address{}, nil, fmt.Errorf("failed to create contract: %w", err) } owner, err := c.Owner(nil) if err != nil { - return common.Address{}, nil, fmt.Errorf("failed to get owner of contract: %v", err) + return common.Address{}, nil, fmt.Errorf("failed to get owner of contract %s: %w", c.Address(), err) } return owner, c, nil } @@ -52,13 +52,13 @@ func (t TransferToMCMSWithTimelockConfig) Validate(e deployment.Environment) err // Note this also assures non-zero addresses. if exists, err := deployment.AddressBookContains(e.ExistingAddresses, chainSelector, contract.String()); err != nil || !exists { if err != nil { - return fmt.Errorf("failed to check address book: %v", err) + return fmt.Errorf("failed to check address book: %w", err) } return fmt.Errorf("contract %s not found in address book", contract) } owner, _, err := LoadOwnableContract(contract, e.Chains[chainSelector].Client) if err != nil { - return fmt.Errorf("failed to load ownable: %v", err) + return fmt.Errorf("failed to load ownable: %w", err) } if owner != e.Chains[chainSelector].DeployerKey.From { return fmt.Errorf("contract %s is not owned by the deployer key", contract) @@ -66,10 +66,10 @@ func (t TransferToMCMSWithTimelockConfig) Validate(e deployment.Environment) err } // If there is no timelock and mcms proposer on the chain, the transfer will fail. if _, err := deployment.SearchAddressBook(e.ExistingAddresses, chainSelector, types.RBACTimelock); err != nil { - return fmt.Errorf("timelock not present on the chain %v", err) + return fmt.Errorf("timelock not present on the chain %w", err) } if _, err := deployment.SearchAddressBook(e.ExistingAddresses, chainSelector, types.ProposerManyChainMultisig); err != nil { - return fmt.Errorf("mcms proposer not present on the chain %v", err) + return fmt.Errorf("mcms proposer not present on the chain %w", err) } } @@ -101,7 +101,7 @@ func TransferToMCMSWithTimelock( timelocksByChain[chainSelector] = common.HexToAddress(timelockAddr) proposer, err := owner_helpers.NewManyChainMultiSig(common.HexToAddress(proposerAddr), e.Chains[chainSelector].Client) if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to create proposer mcms: %v", err) + return deployment.ChangesetOutput{}, fmt.Errorf("failed to create proposer mcms: %w", err) } proposersByChain[chainSelector] = proposer @@ -118,7 +118,7 @@ func TransferToMCMSWithTimelock( tx, err := c.TransferOwnership(e.Chains[chainSelector].DeployerKey, common.HexToAddress(timelockAddr)) _, err = deployment.ConfirmIfNoError(e.Chains[chainSelector], tx, err) if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to transfer ownership of contract %T: %v", contract, err) + return deployment.ChangesetOutput{}, fmt.Errorf("failed to transfer ownership of contract %T: %w", contract, err) } tx, err = c.AcceptOwnership(deployment.SimTransactOpts()) if err != nil { @@ -218,25 +218,55 @@ type RenounceTimelockDeployerConfig struct { ChainSel uint64 } +func (cfg RenounceTimelockDeployerConfig) Validate(e deployment.Environment) error { + if err := deployment.IsValidChainSelector(cfg.ChainSel); err != nil { + return fmt.Errorf("invalid chain selector: %w", err) + } + + _, ok := e.Chains[cfg.ChainSel] + if !ok { + return fmt.Errorf("chain selector: %d not found in environment", cfg.ChainSel) + } + + // MCMS should already exists + state, err := MaybeLoadMCMSWithTimelockState(e, []uint64{cfg.ChainSel}) + if err != nil { + return err + } + + contract, ok := state[cfg.ChainSel] + if !ok { + return fmt.Errorf("mcms contracts not found on chain %d", cfg.ChainSel) + } + if contract.Timelock == nil { + return fmt.Errorf("timelock not found on chain %d", cfg.ChainSel) + } + + return nil +} + // RenounceTimelockDeployer revokes the deployer key from administering the contract. func RenounceTimelockDeployer(e deployment.Environment, cfg RenounceTimelockDeployerConfig) (deployment.ChangesetOutput, error) { + if err := cfg.Validate(e); err != nil { + return deployment.ChangesetOutput{}, err + } + contracts, err := MaybeLoadMCMSWithTimelockState(e, []uint64{cfg.ChainSel}) if err != nil { return deployment.ChangesetOutput{}, err } tl := contracts[cfg.ChainSel].Timelock - if tl == nil { - return deployment.ChangesetOutput{}, fmt.Errorf("timelock not found on chain %d", cfg.ChainSel) - } - admin, err := tl.ADMINROLE(&bind.CallOpts{}) + admin, err := tl.ADMINROLE(&bind.CallOpts{Context: e.GetContext()}) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to get admin role: %w", err) } - tx, err := tl.RenounceRole(e.Chains[cfg.ChainSel].DeployerKey, admin, e.Chains[cfg.ChainSel].DeployerKey.From) + + chain := e.Chains[cfg.ChainSel] + tx, err := tl.RenounceRole(chain.DeployerKey, admin, chain.DeployerKey.From) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to revoke deployer key: %w", err) } - if _, err := deployment.ConfirmIfNoError(e.Chains[cfg.ChainSel], tx, err); err != nil { + if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { return deployment.ChangesetOutput{}, err } e.Logger.Infof("revoked deployer key from owning contract %s", tl.Address().Hex()) diff --git a/deployment/common/changeset/transfer_to_mcms_with_timelock_test.go b/deployment/common/changeset/transfer_to_mcms_with_timelock_test.go index 49c46aab5f0..c8c0f462811 100644 --- a/deployment/common/changeset/transfer_to_mcms_with_timelock_test.go +++ b/deployment/common/changeset/transfer_to_mcms_with_timelock_test.go @@ -6,8 +6,10 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" + chain_selectors "github.com/smartcontractkit/chain-selectors" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/common/types" "github.com/smartcontractkit/chainlink/deployment/environment/memory" @@ -81,6 +83,81 @@ func TestTransferToMCMSWithTimelock(t *testing.T) { require.Equal(t, e.Chains[chain1].DeployerKey.From, o) } +func TestRenounceTimelockDeployerConfigValidate(t *testing.T) { + t.Parallel() + lggr := logger.TestLogger(t) + e := memory.NewMemoryEnvironment(t, lggr, 0, memory.MemoryEnvironmentConfig{ + Chains: 1, + Nodes: 1, + }) + chain1 := e.AllChainSelectors()[0] + e, err := ApplyChangesets(t, e, nil, []ChangesetApplication{ + { + Changeset: WrapChangeSet(DeployMCMSWithTimelock), + Config: map[uint64]types.MCMSWithTimelockConfig{ + chain1: proposalutils.SingleGroupTimelockConfig(t), + }, + }, + }) + require.NoError(t, err) + + envWithNoMCMS := memory.NewMemoryEnvironment(t, lggr, 0, memory.MemoryEnvironmentConfig{ + Chains: 1, + Nodes: 1, + }) + chain2 := envWithNoMCMS.AllChainSelectors()[0] + + for _, test := range []struct { + name string + config RenounceTimelockDeployerConfig + env deployment.Environment + err string + }{ + { + name: "valid config", + env: e, + config: RenounceTimelockDeployerConfig{ + ChainSel: chain1, + }, + }, + { + name: "invalid chain selector", + env: e, + config: RenounceTimelockDeployerConfig{ + ChainSel: 0, + }, + err: "invalid chain selector: chain selector must be set", + }, + { + name: "chain does not exists on env", + env: e, + config: RenounceTimelockDeployerConfig{ + ChainSel: chain_selectors.ETHEREUM_TESTNET_SEPOLIA.Selector, + }, + err: "chain selector: 16015286601757825753 not found in environment", + }, + { + name: "no MCMS deployed", + env: envWithNoMCMS, + config: RenounceTimelockDeployerConfig{ + ChainSel: chain2, + }, + // chain does not match any existing addresses + err: "chain selector 909606746561742123: chain not found", + }, + } { + t.Run(test.name, func(t *testing.T) { + t.Parallel() + err := test.config.Validate(test.env) + if test.err != "" { + require.EqualError(t, err, test.err) + } else { + require.NoError(t, err) + } + }) + } +} + func TestRenounceTimelockDeployer(t *testing.T) { lggr := logger.TestLogger(t) e := memory.NewMemoryEnvironment(t, lggr, 0, memory.MemoryEnvironmentConfig{ diff --git a/deployment/common/proposalutils/mcms_helpers.go b/deployment/common/proposalutils/mcms_helpers.go index 51a720a4389..8b7153e526b 100644 --- a/deployment/common/proposalutils/mcms_helpers.go +++ b/deployment/common/proposalutils/mcms_helpers.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum/common" owner_helpers "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/types" @@ -76,21 +77,21 @@ type RunTimelockExecutorConfig struct { func (cfg RunTimelockExecutorConfig) Validate() error { if cfg.Executor == nil { - return fmt.Errorf("executor is nil") + return errors.New("executor is nil") } if cfg.TimelockContracts == nil { - return fmt.Errorf("timelock contracts is nil") + return errors.New("timelock contracts is nil") } if cfg.ChainSelector == 0 { - return fmt.Errorf("chain selector is 0") + return errors.New("chain selector is 0") } if cfg.BlockStart != nil && cfg.BlockEnd == nil { if *cfg.BlockStart > *cfg.BlockEnd { - return fmt.Errorf("block start is greater than block end") + return errors.New("block start is greater than block end") } } if cfg.BlockStart == nil && cfg.BlockEnd != nil { - return fmt.Errorf("block start must not be nil when block end is not nil") + return errors.New("block start must not be nil when block end is not nil") } if len(cfg.Executor.Operations[mcms.ChainIdentifier(cfg.ChainSelector)]) == 0 { diff --git a/deployment/common/proposalutils/propose.go b/deployment/common/proposalutils/propose.go index 32a5bcdfda2..874bbecbdb8 100644 --- a/deployment/common/proposalutils/propose.go +++ b/deployment/common/proposalutils/propose.go @@ -1,6 +1,7 @@ package proposalutils import ( + "errors" "fmt" "time" @@ -15,7 +16,6 @@ const ( DefaultValidUntil = 72 * time.Hour ) - func BuildProposalMetadata( chainSelectors []uint64, proposerMcmsesPerChain map[uint64]*gethwrappers.ManyChainMultiSig, @@ -40,7 +40,13 @@ func BuildProposalMetadata( } // BuildProposalFromBatches Given batches of operations, we build the metadata and timelock addresses of those opartions -// We then return a proposal that can be executed and signed +// We then return a proposal that can be executed and signed. +// You can specify multiple batches for the same chain, but the only +// usecase to do that would be you have a batch that can't fit in a single +// transaction due to gas or calldata constraints of the chain. +// The batches are specified separately because we eventually intend +// to support user-specified cross chain ordering of batch execution by the tooling itself. +// TODO: Can/should merge timelocks and proposers into a single map for the chain. func BuildProposalFromBatches( timelocksPerChain map[uint64]common.Address, proposerMcmsesPerChain map[uint64]*gethwrappers.ManyChainMultiSig, @@ -49,7 +55,7 @@ func BuildProposalFromBatches( minDelay time.Duration, ) (*timelock.MCMSWithTimelockProposal, error) { if len(batches) == 0 { - return nil, fmt.Errorf("no operations in batch") + return nil, errors.New("no operations in batch") } chains := mapset.NewSet[uint64]() diff --git a/deployment/common/types/types.go b/deployment/common/types/types.go index 0f04421af43..c86fb3e9887 100644 --- a/deployment/common/types/types.go +++ b/deployment/common/types/types.go @@ -1,7 +1,7 @@ package types import ( - "fmt" + "errors" "math/big" "time" @@ -52,40 +52,40 @@ type OCRParameters struct { func (params OCRParameters) Validate() error { if params.DeltaProgress <= 0 { - return fmt.Errorf("deltaProgress must be positive") + return errors.New("deltaProgress must be positive") } if params.DeltaResend <= 0 { - return fmt.Errorf("deltaResend must be positive") + return errors.New("deltaResend must be positive") } if params.DeltaInitial <= 0 { - return fmt.Errorf("deltaInitial must be positive") + return errors.New("deltaInitial must be positive") } if params.DeltaRound <= 0 { - return fmt.Errorf("deltaRound must be positive") + return errors.New("deltaRound must be positive") } if params.DeltaGrace <= 0 { - return fmt.Errorf("deltaGrace must be positive") + return errors.New("deltaGrace must be positive") } if params.DeltaCertifiedCommitRequest <= 0 { - return fmt.Errorf("deltaCertifiedCommitRequest must be positive") + return errors.New("deltaCertifiedCommitRequest must be positive") } if params.DeltaStage <= 0 { - return fmt.Errorf("deltaStage must be positive") + return errors.New("deltaStage must be positive") } if params.Rmax <= 0 { - return fmt.Errorf("rmax must be positive") + return errors.New("rmax must be positive") } if params.MaxDurationQuery <= 0 { - return fmt.Errorf("maxDurationQuery must be positive") + return errors.New("maxDurationQuery must be positive") } if params.MaxDurationObservation <= 0 { - return fmt.Errorf("maxDurationObservation must be positive") + return errors.New("maxDurationObservation must be positive") } if params.MaxDurationShouldAcceptAttestedReport <= 0 { - return fmt.Errorf("maxDurationShouldAcceptAttestedReport must be positive") + return errors.New("maxDurationShouldAcceptAttestedReport must be positive") } if params.MaxDurationShouldTransmitAcceptedReport <= 0 { - return fmt.Errorf("maxDurationShouldTransmitAcceptedReport must be positive") + return errors.New("maxDurationShouldTransmitAcceptedReport must be positive") } return nil } diff --git a/deployment/common/view/nops.go b/deployment/common/view/nops.go index 61e16d59145..74f011dfe44 100644 --- a/deployment/common/view/nops.go +++ b/deployment/common/view/nops.go @@ -2,9 +2,11 @@ package view import ( "context" + "encoding/hex" "fmt" "github.com/pkg/errors" + nodev1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" "github.com/smartcontractkit/chainlink/deployment" @@ -62,11 +64,11 @@ func GenerateNopsView(nodeIds []string, oc deployment.OffchainClient) (map[strin } for details, ocrConfig := range node.SelToOCRConfig { nop.OCRKeys[details.ChainName] = OCRKeyView{ - OffchainPublicKey: fmt.Sprintf("%x", ocrConfig.OffchainPublicKey[:]), + OffchainPublicKey: hex.EncodeToString(ocrConfig.OffchainPublicKey[:]), OnchainPublicKey: fmt.Sprintf("%x", ocrConfig.OnchainPublicKey[:]), PeerID: ocrConfig.PeerID.String(), TransmitAccount: string(ocrConfig.TransmitAccount), - ConfigEncryptionPublicKey: fmt.Sprintf("%x", ocrConfig.ConfigEncryptionPublicKey[:]), + ConfigEncryptionPublicKey: hex.EncodeToString(ocrConfig.ConfigEncryptionPublicKey[:]), KeyBundleID: ocrConfig.KeyBundleID, } } diff --git a/deployment/common/view/v1_0/capreg.go b/deployment/common/view/v1_0/capreg.go index 3274cc4e97f..1d3ea485cf1 100644 --- a/deployment/common/view/v1_0/capreg.go +++ b/deployment/common/view/v1_0/capreg.go @@ -11,7 +11,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/smartcontractkit/chainlink/deployment/common/view/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) diff --git a/deployment/common/view/v1_0/capreg_test.go b/deployment/common/view/v1_0/capreg_test.go index 2f58034a619..eb7c8a83bd4 100644 --- a/deployment/common/view/v1_0/capreg_test.go +++ b/deployment/common/view/v1_0/capreg_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/smartcontractkit/chainlink/deployment/common/view/types" - cr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + cr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" ) func TestCapRegView_Denormalize(t *testing.T) { @@ -149,7 +149,7 @@ func TestCapRegView_Denormalize(t *testing.T) { {Name: "third nop"}, }, Capabilities: []CapabilityView{ - //capabilities for don1 + // capabilities for don1 NewCapabilityView(cr.CapabilitiesRegistryCapabilityInfo{ HashedId: [32]byte{0: 1}, LabelledName: "cap1", @@ -161,7 +161,7 @@ func TestCapRegView_Denormalize(t *testing.T) { Version: "1.0.0", }), - //capabilities for don2 + // capabilities for don2 NewCapabilityView(cr.CapabilitiesRegistryCapabilityInfo{ HashedId: [32]byte{2: 2}, // matches don ID 2, capabitility ID 1 LabelledName: "other cap", diff --git a/deployment/common/view/v1_0/link_token.go b/deployment/common/view/v1_0/link_token.go index 6dd1a00be3b..2d345f1fd3c 100644 --- a/deployment/common/view/v1_0/link_token.go +++ b/deployment/common/view/v1_0/link_token.go @@ -44,8 +44,8 @@ func GenerateLinkTokenView(lt *link_token.LinkToken) (LinkTokenView, error) { return LinkTokenView{ ContractMetaData: types.ContractMetaData{ TypeAndVersion: deployment.TypeAndVersion{ - commontypes.LinkToken, - deployment.Version1_0_0, + Type: commontypes.LinkToken, + Version: deployment.Version1_0_0, }.String(), Address: lt.Address(), Owner: owner, diff --git a/deployment/common/view/v1_0/link_token_test.go b/deployment/common/view/v1_0/link_token_test.go index c83c0b3e3c2..735d7789169 100644 --- a/deployment/common/view/v1_0/link_token_test.go +++ b/deployment/common/view/v1_0/link_token_test.go @@ -26,12 +26,12 @@ func TestLinkTokenView(t *testing.T) { require.NoError(t, err) assert.Equal(t, v.Owner, chain.DeployerKey.From) - assert.Equal(t, v.TypeAndVersion, "LinkToken 1.0.0") - assert.Equal(t, v.Decimals, uint8(18)) + assert.Equal(t, "LinkToken 1.0.0", v.TypeAndVersion) + assert.Equal(t, uint8(18), v.Decimals) // Initially nothing minted and no minters/burners. - assert.Equal(t, v.Supply.String(), "0") - require.Len(t, v.Minters, 0) - require.Len(t, v.Burners, 0) + assert.Equal(t, "0", v.Supply.String()) + require.Empty(t, v.Minters) + require.Empty(t, v.Burners) // Add some minters tx, err = lt.GrantMintAndBurnRoles(chain.DeployerKey, chain.DeployerKey.From) @@ -45,7 +45,7 @@ func TestLinkTokenView(t *testing.T) { v, err = GenerateLinkTokenView(lt) require.NoError(t, err) - assert.Equal(t, v.Supply.String(), "100") + assert.Equal(t, "100", v.Supply.String()) require.Len(t, v.Minters, 1) require.Equal(t, v.Minters[0].String(), chain.DeployerKey.From.String()) require.Len(t, v.Burners, 1) diff --git a/deployment/common/view/v1_0/static_link_token.go b/deployment/common/view/v1_0/static_link_token.go index 525f1a9f0c5..2c9c60531b2 100644 --- a/deployment/common/view/v1_0/static_link_token.go +++ b/deployment/common/view/v1_0/static_link_token.go @@ -28,8 +28,8 @@ func GenerateStaticLinkTokenView(lt *link_token_interface.LinkToken) (StaticLink return StaticLinkTokenView{ ContractMetaData: types.ContractMetaData{ TypeAndVersion: deployment.TypeAndVersion{ - commontypes.StaticLinkToken, - deployment.Version1_0_0, + Type: commontypes.StaticLinkToken, + Version: deployment.Version1_0_0, }.String(), Address: lt.Address(), // No owner. diff --git a/deployment/common/view/v1_0/static_link_token_test.go b/deployment/common/view/v1_0/static_link_token_test.go index 517efac9438..b276a80fb2e 100644 --- a/deployment/common/view/v1_0/static_link_token_test.go +++ b/deployment/common/view/v1_0/static_link_token_test.go @@ -26,7 +26,7 @@ func TestStaticLinkTokenView(t *testing.T) { require.NoError(t, err) assert.Equal(t, v.Owner, common.HexToAddress("0x0")) // Ownerless - assert.Equal(t, v.TypeAndVersion, "StaticLinkToken 1.0.0") - assert.Equal(t, v.Decimals, uint8(18)) - assert.Equal(t, v.Supply.String(), "1000000000000000000000000000") + assert.Equal(t, "StaticLinkToken 1.0.0", v.TypeAndVersion) + assert.Equal(t, uint8(18), v.Decimals) + assert.Equal(t, "1000000000000000000000000000", v.Supply.String()) } diff --git a/deployment/environment.go b/deployment/environment.go index 0823404da2d..a37622dc3ac 100644 --- a/deployment/environment.go +++ b/deployment/environment.go @@ -7,6 +7,7 @@ import ( "fmt" "math/big" "sort" + "strconv" "strings" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -74,6 +75,9 @@ func (c Chain) Name() string { // we should never get here, if the selector is invalid it should not be in the environment panic(err) } + if chainInfo.ChainName == "" { + return strconv.FormatUint(c.Selector, 10) + } return chainInfo.ChainName } @@ -107,6 +111,7 @@ func NewEnvironment( logger logger.Logger, existingAddrs AddressBook, chains map[uint64]Chain, + solChains map[uint64]SolChain, nodeIDs []string, offchain OffchainClient, ctx func() context.Context, @@ -117,6 +122,7 @@ func NewEnvironment( Logger: logger, ExistingAddresses: existingAddrs, Chains: chains, + SolChains: solChains, NodeIDs: nodeIDs, Offchain: offchain, GetContext: ctx, @@ -155,6 +161,17 @@ func (e Environment) AllChainSelectorsExcluding(excluding []uint64) []uint64 { return selectors } +func (e Environment) AllChainSelectorsSolana() []uint64 { + selectors := make([]uint64, 0, len(e.SolChains)) + for sel := range e.SolChains { + selectors = append(selectors, sel) + } + sort.Slice(selectors, func(i, j int) bool { + return selectors[i] < selectors[j] + }) + return selectors +} + func (e Environment) AllDeployerKeys() []common.Address { var deployerKeys []common.Address for sel := range e.Chains { diff --git a/deployment/environment/clo/don_nodeset.go b/deployment/environment/clo/don_nodeset.go deleted file mode 100644 index c4cfa212c0b..00000000000 --- a/deployment/environment/clo/don_nodeset.go +++ /dev/null @@ -1,67 +0,0 @@ -package clo - -import ( - "strings" - - "github.com/smartcontractkit/chainlink/deployment/environment/clo/models" -) - -// CapabilityNodeSets groups nodes by a given filter function, resulting in a map of don name to nodes. -func CapabilityNodeSets(nops []*models.NodeOperator, donFilters map[string]FilterFuncT[*models.Node]) map[string][]*models.NodeOperator { - // first drop bootstraps if they exist because they do not serve capabilities - nonBootstrapNops := FilterNopNodes(nops, func(n *models.Node) bool { - for _, chain := range n.ChainConfigs { - if chain.Ocr2Config.IsBootstrap { - return false - } - } - return true - }) - // apply given filters to non-bootstrap nodes - out := make(map[string][]*models.NodeOperator) - for name, f := range donFilters { - out[name] = FilterNopNodes(nonBootstrapNops, f) - } - return out -} - -// FilterNopNodes filters the nodes of each nop by the provided filter function. -// if a nop has no nodes after filtering, it is not included in the output. -func FilterNopNodes(nops []*models.NodeOperator, f FilterFuncT[*models.Node]) []*models.NodeOperator { - var out []*models.NodeOperator - for _, nop := range nops { - var res []*models.Node - for _, n := range nop.Nodes { - node := n - if f(n) { - res = append(res, node) - } - } - if len(res) > 0 { - filterNop := *nop - filterNop.Nodes = res - out = append(out, &filterNop) - } - } - return out -} - -type FilterFuncT[T any] func(n T) bool - -func ProductFilterGenerator(p models.ProductType) FilterFuncT[*models.Node] { - return func(n *models.Node) bool { - for _, prod := range n.SupportedProducts { - if prod == p { - return true - } - } - return false - } -} - -// this could be generalized to a regex filter -func NodeNameFilterGenerator(contains string) FilterFuncT[*models.Node] { - return func(n *models.Node) bool { - return strings.Contains(n.Name, contains) - } -} diff --git a/deployment/environment/clo/don_nodeset_test.go b/deployment/environment/clo/don_nodeset_test.go deleted file mode 100644 index fab9a81690b..00000000000 --- a/deployment/environment/clo/don_nodeset_test.go +++ /dev/null @@ -1,104 +0,0 @@ -package clo_test - -import ( - "encoding/json" - "os" - "path/filepath" - "sort" - "strings" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/test-go/testify/require" - - "github.com/smartcontractkit/chainlink/deployment/environment/clo" - "github.com/smartcontractkit/chainlink/deployment/environment/clo/models" -) - -// this is hacky, but there is no first class concept of a chain writer node in CLO -// in prod, probably better to make an explicit list of pubkeys if we can't add a category or product type -// sufficient for testing -var ( - writerFilter = func(n *models.Node) bool { - return strings.Contains(n.Name, "Prod Keystone Cap One") && !strings.Contains(n.Name, "Boot") - } - - assetFilter = func(n *models.Node) bool { - return strings.Contains(n.Name, "Prod Keystone Asset") && !strings.Contains(n.Name, "Bootstrap") - } - - wfFilter = func(n *models.Node) bool { - return strings.Contains(n.Name, "Prod Keystone One") && !strings.Contains(n.Name, "Boot") - } -) - -func TestGenerateNopNodesData(t *testing.T) { - t.Skipf("this test is for generating test data only") - // use for generating keystone deployment test data - // `./bin/fmscli --config ~/.fmsclient/prod.yaml login` - // `./bin/fmscli --config ~/.fmsclient/prod.yaml get nodeOperators > /tmp/all-clo-nops.json` - - regenerateFromCLO := false - if regenerateFromCLO { - path := "/tmp/all-clo-nops.json" - f, err := os.ReadFile(path) - require.NoError(t, err) - type cloData struct { - Nops []*models.NodeOperator `json:"nodeOperators"` - } - var d cloData - require.NoError(t, json.Unmarshal(f, &d)) - require.NotEmpty(t, d.Nops) - allNops := d.Nops - sort.Slice(allNops, func(i, j int) bool { - return allNops[i].ID < allNops[j].ID - }) - - ksFilter := func(n *models.Node) bool { - return writerFilter(n) || assetFilter(n) || wfFilter(n) - } - ksNops := clo.FilterNopNodes(allNops, ksFilter) - require.NotEmpty(t, ksNops) - b, err := json.MarshalIndent(ksNops, "", " ") - require.NoError(t, err) - require.NoError(t, os.WriteFile("testdata/keystone_nops.json", b, 0644)) //nolint:gosec - } - keystoneNops := loadTestNops(t, "testdata/keystone_nops.json") - - m := clo.CapabilityNodeSets(keystoneNops, map[string]clo.FilterFuncT[*models.Node]{ - "workflow": wfFilter, - "chainWriter": writerFilter, - "asset": assetFilter, - }) - assert.Len(t, m, 3) - assert.Len(t, m["workflow"], 10) - assert.Len(t, m["chainWriter"], 10) - assert.Len(t, m["asset"], 16) - - // can be used to derive the test data for the keystone deployment - updateTestData := true - if updateTestData { - d := "/tmp" // change this to the path where you want to write the test, "../deployment/keystone/testdata" - b, err := json.MarshalIndent(m["workflow"], "", " ") - require.NoError(t, err) - require.NoError(t, os.WriteFile(filepath.Join(d, "workflow_nodes.json"), b, 0600)) - - b, err = json.MarshalIndent(m["chainWriter"], "", " ") - require.NoError(t, err) - require.NoError(t, os.WriteFile(filepath.Join(d, "chain_writer_nodes.json"), b, 0600)) - b, err = json.MarshalIndent(m["asset"], "", " ") - require.NoError(t, err) - require.NoError(t, os.WriteFile(filepath.Join(d, "asset_nodes.json"), b, 0600)) - } -} - -func loadTestNops(t *testing.T, path string) []*models.NodeOperator { - f, err := os.ReadFile(path) - require.NoError(t, err) - var nodes []*models.NodeOperator - require.NoError(t, json.Unmarshal(f, &nodes)) - sort.Slice(nodes, func(i, j int) bool { - return nodes[i].ID < nodes[j].ID - }) - return nodes -} diff --git a/deployment/environment/clo/models/models.go b/deployment/environment/clo/models/models.go deleted file mode 100644 index 1d33cff84d5..00000000000 --- a/deployment/environment/clo/models/models.go +++ /dev/null @@ -1,28 +0,0 @@ -// TODO: KS-455: Refactor this package to use chainlink-common -// Fork from: https://github.com/smartcontractkit/feeds-manager/tree/develop/api/models -// until it can be refactored in cahinlink-common. - -// Package models provides generated go types that reflect the GraphQL types -// defined in the API schemas. -// -// To maintain compatibility with the default JSON interfaces, any necessary model -// overrides can be defined this package. -package models - -import "go/types" - -// Generic Error model to override existing GQL Error types and allow unmarshaling of GQL Error unions -type Error struct { - Typename string `json:"__typename,omitempty"` - Message string `json:"message,omitempty"` - Path *[]string `json:"path,omitempty"` -} - -func (e *Error) Underlying() types.Type { return e } -func (e *Error) String() string { return "Error" } - -// Unmarshal GQL Time fields into go strings because by default, time.Time results in zero-value -// timestamps being present in the CLI output, e.g. "createdAt": "0001-01-01T00:00:00Z". -// This is because the default JSON interfaces don't recognize it as an empty value for Time.time -// and fail to omit it when using `json:"omitempty"` tags. -type Time string diff --git a/deployment/environment/clo/models/models_gen.go b/deployment/environment/clo/models/models_gen.go deleted file mode 100644 index 8d8f57c3b56..00000000000 --- a/deployment/environment/clo/models/models_gen.go +++ /dev/null @@ -1,3653 +0,0 @@ -// Forked from https://github.com/smartcontractkit/feeds-manager/blob/afc24439ee1dffd3781b53c9419ccd1eb44f4163/api/models/models_gen.go#L1 -// TODO: KS-455: Refactor this package to use chainlink-common -// Code generated by github.com/99designs/gqlgen, DO NOT EDIT. - -package models - -import ( - "fmt" - "io" - "strconv" -) - -type AggregatorConfig interface { - IsAggregatorConfig() -} - -type AggregatorSpecConfig interface { - IsAggregatorSpecConfig() -} - -type JobConfig interface { - IsJobConfig() -} - -type Action struct { - Name string `json:"name,omitempty"` - ActionType ActionType `json:"actionType,omitempty"` - Run *ActionRun `json:"run,omitempty"` - Tasks []*Task `json:"tasks,omitempty"` -} - -type ActionRun struct { - ID string `json:"id,omitempty"` - Network *Network `json:"network,omitempty"` - ActionType ActionType `json:"actionType,omitempty"` - Status ActionRunStatus `json:"status,omitempty"` - Tasks []*Task `json:"tasks,omitempty"` - TaskRuns []*TaskRun `json:"taskRuns,omitempty"` - CreatedAt Time `json:"createdAt,omitempty"` -} - -type ActivateBootstrapNodeInput struct { - ID string `json:"id,omitempty"` - ContractType ContractType `json:"contractType,omitempty"` -} - -type ActivateBootstrapNodePayload struct { - Node *Node `json:"node,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type AddAggregatorInput struct { - Name string `json:"name,omitempty"` - Template string `json:"template,omitempty"` - CategoryID string `json:"categoryID,omitempty"` -} - -type AddChainInput struct { - NetworkID string `json:"networkID,omitempty"` - Template string `json:"template,omitempty"` - // The Display String lets a user differentiate multiple CCIP chains on the same network. It is not unique and used for display purposes only. - DisplayName *string `json:"displayName,omitempty"` -} - -type AddChainPayload struct { - Errors []Error `json:"errors,omitempty"` - Chain *CCIPChain `json:"chain,omitempty"` -} - -type AddChainTestContractsInput struct { - ChainID string `json:"chainID,omitempty"` -} - -type AddChainTestContractsPayload struct { - Chain *CCIPChain `json:"chain,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type AddFeedAggregatorInput struct { - FeedID string `json:"feedID,omitempty"` - Aggregator *AddAggregatorInput `json:"aggregator,omitempty"` -} - -type AddFeedAggregatorPayload struct { - Aggregator *Aggregator `json:"aggregator,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type AddFeedInput struct { - Name string `json:"name,omitempty"` - NetworkID string `json:"networkID,omitempty"` - Proxy *AddProxyInput `json:"proxy,omitempty"` - Aggregator *AddAggregatorInput `json:"aggregator,omitempty"` -} - -type AddFeedPayload struct { - Feed *Feed `json:"feed,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type AddLaneInput struct { - ChainAid string `json:"chainAID,omitempty"` - ChainBid string `json:"chainBID,omitempty"` - Template string `json:"template,omitempty"` - // The Display String lets a user differentiate multiple CCIP chains on the same network. It is not unique and used for display purposes only. - DisplayName *string `json:"displayName,omitempty"` -} - -type AddLanePayload struct { - Errors []Error `json:"errors,omitempty"` - Lane *CCIPLane `json:"lane,omitempty"` -} - -type AddLaneUpgradeInput struct { - LaneID string `json:"laneID,omitempty"` - Template string `json:"template,omitempty"` -} - -type AddLaneUpgradePayload struct { - Lane *CCIPLane `json:"lane,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type AddMercuryV03NetworkStackInput struct { - NetworkID string `json:"networkID,omitempty"` - MercuryServerURL string `json:"mercuryServerURL,omitempty"` - MercuryServerPubKey string `json:"mercuryServerPubKey,omitempty"` - ReadAccessController *ReadAccessController `json:"readAccessController,omitempty"` - NativeSurcharge *string `json:"nativeSurcharge,omitempty"` - Servers *string `json:"servers,omitempty"` -} - -type AddMercuryV03NetworkStackPayload struct { - NetworkStack *MercuryV03NetworkStack `json:"networkStack,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type AddProxyInput struct { - AccessControllerAddress *string `json:"accessControllerAddress,omitempty"` -} - -type AddStorageContractInput struct { - NetworkID string `json:"networkID,omitempty"` - Template string `json:"template,omitempty"` - DisplayName *string `json:"displayName,omitempty"` -} - -type AddStorageContractPayload struct { - StorageContract *StorageContract `json:"storageContract,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type AddTokenInput struct { - Template string `json:"template,omitempty"` -} - -type AddTokenPayload struct { - Token *CCIPToken `json:"token,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type AddTokenPoolInput struct { - ID string `json:"id,omitempty"` - Template string `json:"template,omitempty"` -} - -type AddTokenPoolPayload struct { - Errors []Error `json:"errors,omitempty"` - Chain *CCIPChain `json:"chain,omitempty"` -} - -type AddVerificationProviderInput struct { - FeedID string `json:"feedID,omitempty"` - NetworkStackID string `json:"networkStackID,omitempty"` -} - -type AddVerificationProviderPayload struct { - Feed *MercuryV03Feed `json:"feed,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type Aggregator struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - ContractAddress *string `json:"contractAddress,omitempty"` - ContractType ContractType `json:"contractType,omitempty"` - DeploymentStatus DeploymentStatus `json:"deploymentStatus,omitempty"` - OwnerAddress *string `json:"ownerAddress,omitempty"` - OwnerAddressType *ContractOwnerType `json:"ownerAddressType,omitempty"` - PendingOwnerAddress *string `json:"pendingOwnerAddress,omitempty"` - PendingOwnerType *ContractOwnerType `json:"pendingOwnerType,omitempty"` - TransferOwnershipStatus TransferOwnershipStatus `json:"transferOwnershipStatus,omitempty"` - Don *Don `json:"don,omitempty"` - BootstrapMultiaddrs []string `json:"bootstrapMultiaddrs,omitempty"` - SpecConfig AggregatorSpecConfig `json:"specConfig,omitempty"` - Config AggregatorConfig `json:"config,omitempty"` - Feed *Feed `json:"feed,omitempty"` - Network *Network `json:"network,omitempty"` - Category *Category `json:"category,omitempty"` - CreatedAt Time `json:"createdAt,omitempty"` -} - -type AggregatorBilling struct { - MaximumGasPrice string `json:"maximumGasPrice,omitempty"` - ReasonableGasPrice string `json:"reasonableGasPrice,omitempty"` - MicroLinkPerEth string `json:"microLinkPerEth,omitempty"` - LinkGweiPerObservation string `json:"linkGweiPerObservation,omitempty"` - LinkGewiPerTransmission string `json:"linkGewiPerTransmission,omitempty"` -} - -type AggregatorConfigOcr1 struct { - Description string `json:"description,omitempty"` - ReasonableGasPrice string `json:"reasonableGasPrice,omitempty"` - MaximumGasPrice string `json:"maximumGasPrice,omitempty"` - MicroLinkPerEth string `json:"microLinkPerEth,omitempty"` - LinkGweiPerObservation string `json:"linkGweiPerObservation,omitempty"` - LinkGweiPerTransmission string `json:"linkGweiPerTransmission,omitempty"` - MinimumAnswer string `json:"minimumAnswer,omitempty"` - MaximumAnswer string `json:"maximumAnswer,omitempty"` - Decimals string `json:"decimals,omitempty"` - DeltaProgress string `json:"deltaProgress,omitempty"` - DeltaResend string `json:"deltaResend,omitempty"` - DeltaRound string `json:"deltaRound,omitempty"` - DeltaGrace string `json:"deltaGrace,omitempty"` - DeltaC string `json:"deltaC,omitempty"` - AlphaPpb string `json:"alphaPPB,omitempty"` - DeltaStage string `json:"deltaStage,omitempty"` - RMax string `json:"rMax,omitempty"` - S []int `json:"s,omitempty"` - F string `json:"f,omitempty"` -} - -func (AggregatorConfigOcr1) IsAggregatorConfig() {} - -type AggregatorConfigOcr2 struct { - MinimumAnswer string `json:"minimumAnswer,omitempty"` - MaximumAnswer string `json:"maximumAnswer,omitempty"` - Description string `json:"description,omitempty"` - Decimals string `json:"decimals,omitempty"` - DeltaGrace string `json:"deltaGrace,omitempty"` - DeltaProgress string `json:"deltaProgress,omitempty"` - DeltaResend string `json:"deltaResend,omitempty"` - DeltaRound string `json:"deltaRound,omitempty"` - DeltaStage string `json:"deltaStage,omitempty"` - F string `json:"f,omitempty"` - MaxDurationObservation string `json:"maxDurationObservation,omitempty"` - MaxDurationQuery string `json:"maxDurationQuery,omitempty"` - MaxDurationReport string `json:"maxDurationReport,omitempty"` - MaxDurationShouldAcceptFinalizedReport string `json:"maxDurationShouldAcceptFinalizedReport,omitempty"` - MaxDurationShouldTransmitAcceptedReport string `json:"maxDurationShouldTransmitAcceptedReport,omitempty"` - RMax string `json:"rMax,omitempty"` - S []int `json:"s,omitempty"` - AlphaAcceptInfinite bool `json:"alphaAcceptInfinite,omitempty"` - AlphaAcceptPpb string `json:"alphaAcceptPPB,omitempty"` - AlphaReportInfinite bool `json:"alphaReportInfinite,omitempty"` - AlphaReportPpb string `json:"alphaReportPPB,omitempty"` - DeltaC string `json:"deltaC,omitempty"` - ObservationPaymentGjuels string `json:"observationPaymentGjuels,omitempty"` - TransmissionPaymentGjuels string `json:"transmissionPaymentGjuels,omitempty"` - MaximumGasPriceGwei *string `json:"maximumGasPriceGwei,omitempty"` - ReasonableGasPriceGwei *string `json:"reasonableGasPriceGwei,omitempty"` - AccountingGas *string `json:"accountingGas,omitempty"` -} - -func (AggregatorConfigOcr2) IsAggregatorConfig() {} - -type AggregatorOnChainConfig struct { - ConfigCount string `json:"configCount,omitempty"` - BlockNumber string `json:"blockNumber,omitempty"` - ConfigDigest []string `json:"configDigest,omitempty"` -} - -type AggregatorOnChainState struct { - Billing *AggregatorBilling `json:"billing,omitempty"` - Config *AggregatorOnChainConfig `json:"config,omitempty"` - OwnerAddress string `json:"ownerAddress,omitempty"` -} - -type AggregatorProxy struct { - ID string `json:"id,omitempty"` - ContractAddress *string `json:"contractAddress,omitempty"` - TransferOwnershipStatus TransferOwnershipStatus `json:"transferOwnershipStatus,omitempty"` - OwnerAddress *string `json:"ownerAddress,omitempty"` - OwnerAddressType *ContractOwnerType `json:"ownerAddressType,omitempty"` - PendingOwnerAddress *string `json:"pendingOwnerAddress,omitempty"` - PendingOwnerType *ContractOwnerType `json:"pendingOwnerType,omitempty"` - Aggregator *Aggregator `json:"aggregator,omitempty"` - AccessControllerAddress *string `json:"accessControllerAddress,omitempty"` - Feed *Feed `json:"feed,omitempty"` - Network *Network `json:"network,omitempty"` - CreatedAt Time `json:"createdAt,omitempty"` -} - -type ArchiveChainPayload struct { - Chain *CCIPChain `json:"chain,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type ArchiveContractInput struct { - ChainID string `json:"chainID,omitempty"` - ContractID string `json:"contractID,omitempty"` -} - -type ArchiveContractPayload struct { - Contract *Contract `json:"contract,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type ArchiveFeedPayload struct { - Feed *MercuryV03Feed `json:"feed,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type ArchiveLanePayload struct { - Lane *CCIPLane `json:"lane,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type ArchiveNetworkInput struct { - ID string `json:"id,omitempty"` -} - -type ArchiveNetworkPayload struct { - Network *Network `json:"network,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type ArchiveNetworkStackPayload struct { - NetworkStack *MercuryV03NetworkStack `json:"networkStack,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type AssignNodeToJobInput struct { - JobID string `json:"jobID,omitempty"` - NodeID string `json:"nodeID,omitempty"` -} - -type AssignNodeToJobPayload struct { - Job *Job `json:"job,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type BuildInfo struct { - Version string `json:"version,omitempty"` -} - -type CCIPChain struct { - ID string `json:"id,omitempty"` - Network *Network `json:"network,omitempty"` - Contracts []*Contract `json:"contracts,omitempty"` - WorkflowRuns []*WorkflowRun `json:"workflowRuns,omitempty"` - SupportedTokens []*EVMBridgedToken `json:"supportedTokens,omitempty"` - FeeTokens []string `json:"feeTokens,omitempty"` - WrappedNativeToken string `json:"wrappedNativeToken,omitempty"` - ArchivedAt *Time `json:"archivedAt,omitempty"` - // The Display String lets a user differentiate multiple CCIP chains on the same network. It is not unique and used for display purposes only. - DisplayName *string `json:"displayName,omitempty"` - DeployedTemplate map[string]interface{} `json:"deployedTemplate,omitempty"` - Labels map[string]interface{} `json:"labels,omitempty"` -} - -type CCIPChainBasic struct { - ID string `json:"id,omitempty"` - ChainID string `json:"chainID,omitempty"` - Contracts []*ContractBasic `json:"contracts,omitempty"` -} - -type CCIPChainFilter struct { - IsArchived *bool `json:"isArchived,omitempty"` - Selectors []*CCIPChainSelector `json:"selectors,omitempty"` -} - -type CCIPChainSelector struct { - Key string `json:"key,omitempty"` - Op SelectorOp `json:"op,omitempty"` - Value *string `json:"value,omitempty"` -} - -type CCIPEndpoint struct { - Chain *CCIPChain `json:"chain,omitempty"` - Contracts []*Contract `json:"contracts,omitempty"` -} - -type CCIPEndpointBasic struct { - Chain *CCIPChainBasic `json:"chain,omitempty"` - Contracts []*ContractBasic `json:"contracts,omitempty"` -} - -type CCIPLane struct { - ID string `json:"id,omitempty"` - ChainA *CCIPChain `json:"chainA,omitempty"` - ChainB *CCIPChain `json:"chainB,omitempty"` - LegA *CCIPLaneLeg `json:"legA,omitempty"` - LegB *CCIPLaneLeg `json:"legB,omitempty"` - LegAProvisional *CCIPLaneLeg `json:"legAProvisional,omitempty"` - LegBProvisional *CCIPLaneLeg `json:"legBProvisional,omitempty"` - Dons []*Don `json:"dons,omitempty"` - WorkflowRuns []*WorkflowRun `json:"workflowRuns,omitempty"` - Status CCIPLaneLegStatus `json:"status,omitempty"` - ArchivedAt *Time `json:"archivedAt,omitempty"` - DisplayName *string `json:"displayName,omitempty"` - DeployedTemplate map[string]interface{} `json:"deployedTemplate,omitempty"` - DeployedProvisionalTemplate map[string]interface{} `json:"deployedProvisionalTemplate,omitempty"` -} - -type CCIPLaneChainUpdateInput struct { - ID string `json:"id,omitempty"` -} - -type CCIPLaneLeg struct { - ID string `json:"id,omitempty"` - Tag CCIPLaneLegTag `json:"tag,omitempty"` - Source *CCIPEndpoint `json:"source,omitempty"` - Destination *CCIPEndpoint `json:"destination,omitempty"` - WorkflowRuns []*WorkflowRun `json:"workflowRuns,omitempty"` - Dons []*Don `json:"dons,omitempty"` - Status CCIPLaneLegStatus `json:"status,omitempty"` - ArchivedAt *Time `json:"archivedAt,omitempty"` - SupportedTokens []string `json:"supportedTokens,omitempty"` -} - -type CCIPLaneLegBasic struct { - ID string `json:"id,omitempty"` - Source *CCIPEndpointBasic `json:"source,omitempty"` - Destination *CCIPEndpointBasic `json:"destination,omitempty"` - Dons []*DONBasic `json:"dons,omitempty"` - Status CCIPLaneLegStatus `json:"status,omitempty"` - SupportedTokens []string `json:"supportedTokens,omitempty"` -} - -type CCIPLaneLegsFilter struct { - ContractAddress string `json:"contractAddress,omitempty"` - NetworkNameKey string `json:"networkNameKey,omitempty"` -} - -type CCIPLanesFilter struct { - IsArchived *bool `json:"isArchived,omitempty"` -} - -type CCIPMutations struct { - AddChain *AddChainPayload `json:"addChain,omitempty"` - ImportChain *ImportChainPayload `json:"importChain,omitempty"` - AddChainTestContracts *AddChainTestContractsPayload `json:"addChainTestContracts,omitempty"` - AddTokenPool *AddTokenPoolPayload `json:"addTokenPool,omitempty"` - ImportTokenPool *ImportTokenPoolPayload `json:"importTokenPool,omitempty"` - AddToken *AddTokenPayload `json:"addToken,omitempty"` - DeployContract *DeployContractPayload `json:"deployContract,omitempty"` - DeleteContract *DeleteContractPayload `json:"deleteContract,omitempty"` - ArchiveContract *ArchiveContractPayload `json:"archiveContract,omitempty"` - // Deploys the contracts for a chain - DeployChain *CcipDeployChainPayload `json:"deployChain,omitempty"` - DeployChainTestContracts *CcipDeployChainTestContractsPayload `json:"deployChainTestContracts,omitempty"` - DeployToken *DeployTokenPayload `json:"deployToken,omitempty"` - DeregisterTestToken *DeregisterTestTokenPayload `json:"deregisterTestToken,omitempty"` - AddLane *AddLanePayload `json:"addLane,omitempty"` - ImportLane *ImportLanePayload `json:"importLane,omitempty"` - AddLaneUpgrade *AddLaneUpgradePayload `json:"addLaneUpgrade,omitempty"` - UpdateLane *UpdateLanePayload `json:"updateLane,omitempty"` - ArchiveLane *ArchiveLanePayload `json:"archiveLane,omitempty"` - ArchiveChain *ArchiveChainPayload `json:"archiveChain,omitempty"` - CancelLaneUpgrade *CancelLaneUpgradePayload `json:"cancelLaneUpgrade,omitempty"` - ConfirmLaneUpgrade *ConfirmLaneUpgradePayload `json:"confirmLaneUpgrade,omitempty"` - DeployLaneLeg *CcipDeployLaneLegPayload `json:"deployLaneLeg,omitempty"` - SetAllowListTokenPool *SetAllowListTokenPoolPayload `json:"setAllowListTokenPool,omitempty"` - // SetConfigLaneLeg sets the on chain configuration for the Commit Store and Off Ramp contracts of the lane leg. - // - // The configuration values passed as arguments to the contract call are provided by the most recently inserted - // RDD template. - SetConfigLaneLeg *CcipSetConfigLaneLegPayload `json:"setConfigLaneLeg,omitempty"` - TransferOwnership *TransferOwnershipPayload `json:"transferOwnership,omitempty"` - TransferAdminRole *TransferAdminRolePayload `json:"transferAdminRole,omitempty"` - UpdateChain *UpdateCCIPChainPayload `json:"updateChain,omitempty"` - RemoveLiquidity *RemoveLiquidityPayload `json:"removeLiquidity,omitempty"` - SyncChain *SyncChainPayload `json:"syncChain,omitempty"` - SyncLane *SyncLanePayload `json:"syncLane,omitempty"` - SyncContracts *SyncContractsPayload `json:"syncContracts,omitempty"` -} - -type CCIPQueries struct { - Chains []*CCIPChain `json:"chains,omitempty"` - Lanes []*CCIPLane `json:"lanes,omitempty"` - LaneLegs []*CCIPLaneLegBasic `json:"laneLegs,omitempty"` - Chain *CCIPChain `json:"chain,omitempty"` - Lane *CCIPLane `json:"lane,omitempty"` - Tokens []*CCIPToken `json:"tokens,omitempty"` - Token *CCIPToken `json:"token,omitempty"` -} - -type CCIPToken struct { - ID string `json:"id,omitempty"` - Symbol string `json:"symbol,omitempty"` - TokenPools []*CCIPTokenPool `json:"tokenPools,omitempty"` -} - -type CCIPTokenPool struct { - ID string `json:"id,omitempty"` - Contract *Contract `json:"contract,omitempty"` - Address *string `json:"address,omitempty"` - TokenAddress string `json:"tokenAddress,omitempty"` - TokenSymbol string `json:"tokenSymbol,omitempty"` - Chain *CCIPChain `json:"chain,omitempty"` - WorkflowRuns []*WorkflowRun `json:"workflowRuns,omitempty"` -} - -type CcipDeployChainInput struct { - ChainID string `json:"chainID,omitempty"` -} - -type CcipDeployChainPayload struct { - WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type CcipDeployChainTestContractsInput struct { - ChainID string `json:"chainID,omitempty"` -} - -type CcipDeployChainTestContractsPayload struct { - WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type CcipDeployLaneLegInput struct { - LegID string `json:"legID,omitempty"` -} - -type CcipDeployLaneLegPayload struct { - WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type CcipSetConfigLaneLegInput struct { - LegID string `json:"legID,omitempty"` -} - -type CcipSetConfigLaneLegPayload struct { - WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type CSAKeypair struct { - ID string `json:"id,omitempty"` - PublicKey string `json:"publicKey,omitempty"` - CreatedAt Time `json:"createdAt,omitempty"` -} - -type CancelLaneUpgradeInput struct { - LaneID string `json:"laneID,omitempty"` -} - -type CancelLaneUpgradePayload struct { - Errors []Error `json:"errors,omitempty"` - Lane *CCIPLane `json:"lane,omitempty"` -} - -type Category struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - Color string `json:"color,omitempty"` - CreatedAt Time `json:"createdAt,omitempty"` -} - -type ConfirmLaneUpgradeInput struct { - LaneID string `json:"laneID,omitempty"` -} - -type ConfirmLaneUpgradePayload struct { - Errors []Error `json:"errors,omitempty"` - Lane *CCIPLane `json:"lane,omitempty"` -} - -type Contract struct { - ID string `json:"id,omitempty"` - Network *Network `json:"network,omitempty"` - Name string `json:"name,omitempty"` - Version int `json:"version,omitempty"` - Semver *string `json:"semver,omitempty"` - Tag ContractTag `json:"tag,omitempty"` - Address *string `json:"address,omitempty"` - Metadata map[string]interface{} `json:"metadata,omitempty"` - OwnerAddress *string `json:"ownerAddress,omitempty"` - OwnerType ContractOwnerType `json:"ownerType,omitempty"` - PendingOwnerAddress *string `json:"pendingOwnerAddress,omitempty"` - PendingOwnerType *ContractOwnerType `json:"pendingOwnerType,omitempty"` - TransferOwnershipStatus TransferOwnershipStatus `json:"transferOwnershipStatus,omitempty"` - VerificationStatus VerificationStatus `json:"verificationStatus,omitempty"` - SourceCodeHash string `json:"sourceCodeHash,omitempty"` - DeployedAt *Time `json:"deployedAt,omitempty"` - Imported bool `json:"imported,omitempty"` - ArchivedAt *Time `json:"archivedAt,omitempty"` -} - -type ContractBasic struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - Version int `json:"version,omitempty"` - Semver *string `json:"semver,omitempty"` - Address *string `json:"address,omitempty"` - Metadata map[string]interface{} `json:"metadata,omitempty"` -} - -type CreateBootstrapJobInput struct { - DonID string `json:"donID,omitempty"` - NodeID string `json:"nodeID,omitempty"` -} - -type CreateBootstrapJobPayload struct { - Job *Job `json:"job,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type CreateCSAKeypairPayload struct { - CsaKeypair *CSAKeypair `json:"csaKeypair,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type CreateCategoryInput struct { - Name string `json:"name,omitempty"` - Color *string `json:"color,omitempty"` -} - -type CreateCategoryPayload struct { - Category *Category `json:"category,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type CreateJobInput struct { - Type JobType `json:"type,omitempty"` - Ocr2PluginType *OCR2PluginType `json:"ocr2PluginType,omitempty"` - Config *JobConfigInput `json:"config,omitempty"` - DonID string `json:"donID,omitempty"` - NodeOperatorID string `json:"nodeOperatorID,omitempty"` -} - -type CreateJobPayload struct { - Job *Job `json:"job,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type CreateMercuryNetworkStackInput struct { - NetworkID string `json:"networkID,omitempty"` - VerifierAddress string `json:"verifierAddress,omitempty"` - VerifierProxyAddress string `json:"verifierProxyAddress,omitempty"` - ServerURL string `json:"serverURL,omitempty"` - ServerPublicKey string `json:"serverPublicKey,omitempty"` - Servers *string `json:"servers,omitempty"` -} - -type CreateMercuryNetworkStackPayload struct { - NetworkStack *MercuryNetworkStack `json:"networkStack,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type CreateNetworkInput struct { - ChainID string `json:"chainID,omitempty"` - ChainType ChainType `json:"chainType,omitempty"` - Name string `json:"name,omitempty"` - NativeToken string `json:"nativeToken,omitempty"` - NativeTokenContractAddress *string `json:"nativeTokenContractAddress,omitempty"` - ConfigContractAddress *string `json:"configContractAddress,omitempty"` - LinkUSDProxyAddress *string `json:"linkUSDProxyAddress,omitempty"` - NativeUSDProxyAddress *string `json:"nativeUSDProxyAddress,omitempty"` - LinkContractAddress *string `json:"linkContractAddress,omitempty"` - FlagsContractAddress *string `json:"flagsContractAddress,omitempty"` - LinkFunding *string `json:"linkFunding,omitempty"` - BillingAdminAccessControllerAddress *string `json:"billingAdminAccessControllerAddress,omitempty"` - RequesterAdminAccessControllerAddress *string `json:"requesterAdminAccessControllerAddress,omitempty"` - ExplorerAPIKey *string `json:"explorerAPIKey,omitempty"` - ExplorerAPIURL *string `json:"explorerAPIURL,omitempty"` -} - -type CreateNetworkPayload struct { - Network *Network `json:"network,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type CreateNodeInput struct { - Name string `json:"name,omitempty"` - PublicKey string `json:"publicKey,omitempty"` - NodeOperatorID string `json:"nodeOperatorID,omitempty"` - SupportedCategoryIDs []string `json:"supportedCategoryIDs,omitempty"` - SupportedProducts []ProductType `json:"supportedProducts,omitempty"` -} - -type CreateNodeOperatorInput struct { - Keys []string `json:"keys,omitempty"` - Name string `json:"name,omitempty"` - Email *string `json:"email,omitempty"` - Website *string `json:"website,omitempty"` -} - -type CreateNodeOperatorPayload struct { - NodeOperator *NodeOperator `json:"nodeOperator,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type CreateNodePayload struct { - Node *Node `json:"node,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type CreateRelayerAccountInput struct { - RelayerID string `json:"relayerID,omitempty"` -} - -type CreateRelayerAccountPayload struct { - RelayerAccount *RelayerAccount `json:"relayerAccount,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type CreateRelayerInput struct { - Name string `json:"name,omitempty"` - NetworkID string `json:"networkID,omitempty"` - Config string `json:"config,omitempty"` - URL *RelayerURL `json:"url,omitempty"` -} - -type CreateRelayerPayload struct { - Relayer *Relayer `json:"relayer,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type CreateUserInput struct { - Email string `json:"email,omitempty"` - Name string `json:"name,omitempty"` - Password string `json:"password,omitempty"` - Role UserRole `json:"role,omitempty"` -} - -type CreateUserPayload struct { - User *User `json:"user,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type CreateVaultInput struct { - Name string `json:"name,omitempty"` - Address string `json:"address,omitempty"` - VaultType VaultType `json:"vaultType,omitempty"` - SupportedProducts []ProductType `json:"supportedProducts,omitempty"` - NetworkID string `json:"networkID,omitempty"` -} - -type CreateVaultPayload struct { - Vault *Vault `json:"vault,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type CreateWebhookInput struct { - Name string `json:"name,omitempty"` - EndpointURL string `json:"endpointURL,omitempty"` -} - -type CreateWebhookPayload struct { - Webhook *Webhook `json:"webhook,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type Don struct { - ID string `json:"id,omitempty"` - Network *Network `json:"network,omitempty"` - ExecutionType DONExecutionType `json:"executionType,omitempty"` - Jobs []*Job `json:"jobs,omitempty"` -} - -type DONBasic struct { - ID string `json:"id,omitempty"` - ExecutionType DONExecutionType `json:"executionType,omitempty"` - Jobs []*JobBasic `json:"jobs,omitempty"` -} - -type DeactivateBootstrapNodeInput struct { - ID string `json:"id,omitempty"` - ContractType ContractType `json:"contractType,omitempty"` -} - -type DeactivateBootstrapNodePayload struct { - Node *Node `json:"node,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type DeleteContractInput struct { - ChainID string `json:"chainID,omitempty"` - ContractID string `json:"contractID,omitempty"` -} - -type DeleteContractPayload struct { - Errors []Error `json:"errors,omitempty"` -} - -type DeleteFeedInput struct { - ID string `json:"id,omitempty"` -} - -type DeleteFeedPayload struct { - Feed *Feed `json:"feed,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type DeleteJobInput struct { - ID string `json:"id,omitempty"` -} - -type DeleteJobPayload struct { - Job *Job `json:"job,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type DeleteNodeInput struct { - ID string `json:"id,omitempty"` -} - -type DeleteNodePayload struct { - Node *Node `json:"node,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type DeleteVaultInput struct { - ID string `json:"id,omitempty"` -} - -type DeleteVaultPayload struct { - Vault *Vault `json:"vault,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type DeleteWebhookInput struct { - ID string `json:"id,omitempty"` -} - -type DeleteWebhookPayload struct { - Webhook *Webhook `json:"webhook,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type DeleteWorkflowRunInput struct { - WorkflowRunID string `json:"workflowRunID,omitempty"` -} - -type DeleteWorkflowRunPayload struct { - WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type DeployContractInput struct { - ChainID string `json:"chainID,omitempty"` - ContractID string `json:"contractID,omitempty"` -} - -type DeployContractPayload struct { - Errors []Error `json:"errors,omitempty"` - WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` -} - -type DeployMercuryV03NetworkStackInput struct { - NetworkStackID string `json:"networkStackID,omitempty"` -} - -type DeployMercuryV03NetworkStackPayload struct { - WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type DeploySetStorageContractInput struct { - StorageID string `json:"storageID,omitempty"` -} - -type DeploySetStorageContractPayload struct { - WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type DeployTokenInput struct { - Symbol string `json:"symbol,omitempty"` -} - -type DeployTokenPayload struct { - WorkflowRunsAndContracts []*WorkflowRunAndContract `json:"workflowRunsAndContracts,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type DeregisterTestTokenInput struct { - LaneLegID string `json:"laneLegID,omitempty"` -} - -type DeregisterTestTokenPayload struct { - WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type DisableNodeInput struct { - ID string `json:"id,omitempty"` -} - -type DisableNodePayload struct { - Node *Node `json:"node,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type DisableRelayerInput struct { - ID string `json:"id,omitempty"` -} - -type DisableRelayerPayload struct { - Relayer *Relayer `json:"relayer,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type DisableUserInput struct { - ID string `json:"id,omitempty"` -} - -type DisableUserPayload struct { - User *User `json:"user,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type EVMBridgedToken struct { - Token string `json:"token,omitempty"` - Address string `json:"address,omitempty"` - TokenPoolType TokenPoolType `json:"tokenPoolType,omitempty"` - PriceType TokenPriceType `json:"priceType,omitempty"` - Price *string `json:"price,omitempty"` - PriceFeed *PriceFeed `json:"priceFeed,omitempty"` -} - -type EnableNodeInput struct { - ID string `json:"id,omitempty"` -} - -type EnableNodePayload struct { - Node *Node `json:"node,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type EnableRelayerInput struct { - ID string `json:"id,omitempty"` -} - -type EnableRelayerPayload struct { - Relayer *Relayer `json:"relayer,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type Feed struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - Status FeedStatus `json:"status,omitempty"` - Network *Network `json:"network,omitempty"` - Proxy *AggregatorProxy `json:"proxy,omitempty"` - Aggregators []*Aggregator `json:"aggregators,omitempty"` - WorkflowRuns []*WorkflowRun `json:"workflowRuns,omitempty"` - CreatedAt Time `json:"createdAt,omitempty"` -} - -type FeedsFilters struct { - ChainID *string `json:"chainID,omitempty"` - ChainType *ChainType `json:"chainType,omitempty"` - Name *string `json:"name,omitempty"` - NetworkID *string `json:"networkID,omitempty"` - ProxyAddress *string `json:"proxyAddress,omitempty"` - Limit *string `json:"limit,omitempty"` - Offset *string `json:"offset,omitempty"` -} - -type FeedsInput struct { - Filter *FeedsFilters `json:"filter,omitempty"` -} - -type GauntletReport struct { - ID string `json:"id,omitempty"` - TraceID string `json:"traceID,omitempty"` - WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` - TransactionHash *string `json:"transactionHash,omitempty"` - ReportID string `json:"reportID,omitempty"` - Timestamp Time `json:"timestamp,omitempty"` - Op string `json:"op,omitempty"` - Input string `json:"input,omitempty"` - Output *string `json:"output,omitempty"` - Requirements *string `json:"requirements,omitempty"` - Config string `json:"config,omitempty"` - Subops *string `json:"subops,omitempty"` - Events *string `json:"events,omitempty"` - Snapshot *string `json:"snapshot,omitempty"` - Error *string `json:"error,omitempty"` - TraceExtra *string `json:"traceExtra,omitempty"` -} - -type GauntletReportsInput struct { - TraceID *string `json:"traceID,omitempty"` - WorkflowRunID *int `json:"workflowRunID,omitempty"` - TransactionHash *string `json:"transactionHash,omitempty"` -} - -type ImportAggregatorInput struct { - Name string `json:"name,omitempty"` - ContractAddress string `json:"contractAddress,omitempty"` - Template string `json:"template,omitempty"` - CategoryID string `json:"categoryID,omitempty"` -} - -type ImportChainInput struct { - NetworkID string `json:"networkID,omitempty"` - Template string `json:"template,omitempty"` - // The Display String lets a user differentiate multiple CCIP chains on the same network. It is not unique and used for display purposes only. - DisplayName *string `json:"displayName,omitempty"` -} - -type ImportChainPayload struct { - Errors []Error `json:"errors,omitempty"` - Chain *CCIPChain `json:"chain,omitempty"` -} - -type ImportFeedAggregatorInput struct { - FeedID string `json:"feedID,omitempty"` - Aggregator *ImportAggregatorInput `json:"aggregator,omitempty"` -} - -type ImportFeedAggregatorPayload struct { - Aggregator *Aggregator `json:"aggregator,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type ImportFeedInput struct { - Name string `json:"name,omitempty"` - NetworkID string `json:"networkID,omitempty"` - Proxy *ImportProxyInput `json:"proxy,omitempty"` - Aggregators []*ImportAggregatorInput `json:"aggregators,omitempty"` -} - -type ImportFeedPayload struct { - Feed *Feed `json:"feed,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type ImportKeystoneWorkflowInput struct { - CategoryID string `json:"categoryID,omitempty"` - NetworkID string `json:"networkID,omitempty"` - Template string `json:"template,omitempty"` -} - -type ImportKeystoneWorkflowPayload struct { - Workflow *KeystoneWorkflow `json:"workflow,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type ImportLaneInput struct { - ChainAid string `json:"chainAID,omitempty"` - ChainBid string `json:"chainBID,omitempty"` - Template string `json:"template,omitempty"` - // The Display String lets a user differentiate multiple CCIP chains on the same network. It is not unique and used for display purposes only. - DisplayName *string `json:"displayName,omitempty"` -} - -type ImportLanePayload struct { - Errors []Error `json:"errors,omitempty"` - Lane *CCIPLane `json:"lane,omitempty"` -} - -type ImportMercuryFeedInput struct { - Name string `json:"name,omitempty"` - ExternalFeedID string `json:"externalFeedID,omitempty"` - NetworkStackID string `json:"networkStackID,omitempty"` - FromBlock string `json:"fromBlock,omitempty"` - Template string `json:"template,omitempty"` -} - -type ImportMercuryFeedPayload struct { - Feed *MercuryFeed `json:"feed,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type ImportMercuryV03FeedInput struct { - Name string `json:"name,omitempty"` - ExternalFeedID string `json:"externalFeedID,omitempty"` - Template string `json:"template,omitempty"` - CategoryID string `json:"categoryID,omitempty"` -} - -type ImportMercuryV03FeedPayload struct { - Feed *MercuryV03Feed `json:"feed,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type ImportMercuryV03NetworkStackInput struct { - NetworkID string `json:"networkID,omitempty"` - VerifierAddress string `json:"verifierAddress,omitempty"` - VerifierProxyAddress string `json:"verifierProxyAddress,omitempty"` - RewardBankAddress string `json:"rewardBankAddress,omitempty"` - FeeManagerAddress string `json:"feeManagerAddress,omitempty"` - MercuryServerURL string `json:"mercuryServerURL,omitempty"` - MercuryServerPubKey string `json:"mercuryServerPubKey,omitempty"` - Servers *string `json:"servers,omitempty"` -} - -type ImportMercuryV03NetworkStackPayload struct { - NetworkStack *MercuryV03NetworkStack `json:"networkStack,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type ImportOCR3CapabilityInput struct { - CategoryID string `json:"categoryID,omitempty"` - NetworkID string `json:"networkID,omitempty"` - Template string `json:"template,omitempty"` -} - -type ImportOCR3CapabilityPayload struct { - Ocr3Capability *OCR3Capability `json:"ocr3Capability,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type ImportProxyInput struct { - ContractAddress string `json:"contractAddress,omitempty"` - AccessControllerAddress *string `json:"accessControllerAddress,omitempty"` - AggregatorAddress string `json:"aggregatorAddress,omitempty"` -} - -type ImportTokenPoolInput struct { - ID string `json:"id,omitempty"` - Template string `json:"template,omitempty"` -} - -type ImportTokenPoolPayload struct { - Errors []Error `json:"errors,omitempty"` - Chain *CCIPChain `json:"chain,omitempty"` -} - -type Job struct { - ID string `json:"id,omitempty"` - UUID string `json:"uuid,omitempty"` - Type JobType `json:"type,omitempty"` - Ocr2PluginType *OCR2PluginType `json:"ocr2PluginType,omitempty"` - Status JobStatus `json:"status,omitempty"` - NodeOperator *NodeOperator `json:"nodeOperator,omitempty"` - Node *Node `json:"node,omitempty"` - IsBootstrap bool `json:"isBootstrap,omitempty"` - Config JobConfig `json:"config,omitempty"` - Spec *string `json:"spec,omitempty"` - ProposalChanged bool `json:"proposalChanged,omitempty"` - AssignableNodes []*Node `json:"assignableNodes,omitempty"` - CanPropose bool `json:"canPropose,omitempty"` - CanRevoke bool `json:"canRevoke,omitempty"` - Proposals []*JobProposal `json:"proposals,omitempty"` - CreatedAt Time `json:"createdAt,omitempty"` -} - -type JobBasic struct { - ID string `json:"id,omitempty"` - UUID string `json:"uuid,omitempty"` - Type JobType `json:"type,omitempty"` - Ocr2PluginType *OCR2PluginType `json:"ocr2PluginType,omitempty"` - Status JobStatus `json:"status,omitempty"` - IsBootstrap bool `json:"isBootstrap,omitempty"` -} - -type JobConfigEmpty struct { - Empty bool `json:"_empty,omitempty"` -} - -func (JobConfigEmpty) IsJobConfig() {} - -type JobConfigEmptyInput struct { - Empty *bool `json:"_empty,omitempty"` -} - -type JobConfigInput struct { - Ocr1 *JobConfigOCR1Input `json:"ocr1,omitempty"` - Ocr2Median *JobConfigOCR2MedianInput `json:"ocr2Median,omitempty"` - Ocr2Mercury *JobConfigOCR2MercuryInput `json:"ocr2Mercury,omitempty"` - Ocr2CCIPCommit *JobConfigEmptyInput `json:"ocr2CCIPCommit,omitempty"` - Ocr2CCIPExecution *JobConfigEmptyInput `json:"ocr2CCIPExecution,omitempty"` - Ocr2CCIPRebalancer *JobConfigEmptyInput `json:"ocr2CCIPRebalancer,omitempty"` -} - -type JobConfigOcr1 struct { - Apis []string `json:"apis,omitempty"` -} - -func (JobConfigOcr1) IsJobConfig() {} - -type JobConfigOCR1Input struct { - Apis []string `json:"apis,omitempty"` -} - -type JobConfigOCR2Median struct { - Apis []string `json:"apis,omitempty"` -} - -func (JobConfigOCR2Median) IsJobConfig() {} - -type JobConfigOCR2MedianInput struct { - Apis []string `json:"apis,omitempty"` -} - -type JobConfigOCR2Mercury struct { - Apis []string `json:"apis,omitempty"` -} - -func (JobConfigOCR2Mercury) IsJobConfig() {} - -type JobConfigOCR2MercuryInput struct { - Apis []string `json:"apis,omitempty"` - CrossApis []string `json:"crossApis,omitempty"` -} - -type JobProposal struct { - ID string `json:"id,omitempty"` - Version string `json:"version,omitempty"` - Status JobProposalStatus `json:"status,omitempty"` - Spec string `json:"spec,omitempty"` - Job *Job `json:"job,omitempty"` - CreatedAt Time `json:"createdAt,omitempty"` - UpdatedAt Time `json:"updatedAt,omitempty"` - ProposedAt *Time `json:"proposedAt,omitempty"` - ResponseReceivedAt *Time `json:"responseReceivedAt,omitempty"` -} - -type KeystoneWorkflow struct { - ID string `json:"id,omitempty"` - WorkflowSpec string `json:"workflowSpec,omitempty"` - WorkflowOwner string `json:"workflowOwner,omitempty"` - ExternalWorkflowID string `json:"externalWorkflowID,omitempty"` - Don *Don `json:"don,omitempty"` - Name string `json:"name,omitempty"` - Category *Category `json:"category,omitempty"` -} - -type KeystoneWorkflowMutations struct { - ImportWorkflow *ImportKeystoneWorkflowPayload `json:"importWorkflow,omitempty"` - UpdateWorkflow *UpdateKeystoneWorkflowPayload `json:"updateWorkflow,omitempty"` -} - -type KeystoneWorkflowQueries struct { - Workflow *KeystoneWorkflow `json:"workflow,omitempty"` - Workflows []*KeystoneWorkflow `json:"workflows,omitempty"` -} - -type ListAggregatorsFilter struct { - NetworkID *string `json:"networkID,omitempty"` - ContractAddress *string `json:"contractAddress,omitempty"` -} - -type ListRelayersFilter struct { - Enabled *bool `json:"enabled,omitempty"` -} - -type ListWebhookCallsFilter struct { - State *WebhookCallState `json:"state,omitempty"` -} - -type LoginInput struct { - Email string `json:"email,omitempty"` - Password string `json:"password,omitempty"` -} - -type LoginPayload struct { - Session *Session `json:"session,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type LogoutPayload struct { - Session *Session `json:"session,omitempty"` -} - -type MarkStaleJobsInput struct { - Ids []string `json:"ids,omitempty"` -} - -type MarkStaleJobsPayload struct { - Jobs []*Job `json:"jobs,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type MercuryFeed struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - ExternalFeedID string `json:"externalFeedID,omitempty"` - NetworkStack *MercuryNetworkStack `json:"networkStack,omitempty"` - FromBlock string `json:"fromBlock,omitempty"` - Template string `json:"template,omitempty"` - Don *Don `json:"don,omitempty"` - CreatedAt Time `json:"createdAt,omitempty"` - UpdatedAt Time `json:"updatedAt,omitempty"` -} - -type MercuryFeedsFilters struct { - Name *string `json:"name,omitempty"` - NetworkID *string `json:"networkID,omitempty"` - VerifierProxyAddress *string `json:"verifierProxyAddress,omitempty"` - Limit *string `json:"limit,omitempty"` - Offset *string `json:"offset,omitempty"` -} - -type MercuryFeedsInput struct { - Filter *MercuryFeedsFilters `json:"filter,omitempty"` -} - -type MercuryMutations struct { - CreateNetworkStack *CreateMercuryNetworkStackPayload `json:"createNetworkStack,omitempty"` - ImportFeed *ImportMercuryFeedPayload `json:"importFeed,omitempty"` - UpdateFeed *UpdateMercuryFeedPayload `json:"updateFeed,omitempty"` - UpdateNetworkStack *UpdateMercuryNetworkStackPayload `json:"updateNetworkStack,omitempty"` -} - -type MercuryNetworkStack struct { - ID string `json:"id,omitempty"` - Network *Network `json:"network,omitempty"` - VerifierAddress string `json:"verifierAddress,omitempty"` - VerifierProxyAddress string `json:"verifierProxyAddress,omitempty"` - ServerURL string `json:"serverURL,omitempty"` - ServerPublicKey string `json:"serverPublicKey,omitempty"` - CreatedAt Time `json:"createdAt,omitempty"` - UpdatedAt Time `json:"updatedAt,omitempty"` - Servers []*MercuryServer `json:"servers,omitempty"` -} - -type MercuryQueries struct { - NetworkStacks []*MercuryNetworkStack `json:"networkStacks,omitempty"` - NetworkStack *MercuryNetworkStack `json:"networkStack,omitempty"` - Feed *MercuryFeed `json:"feed,omitempty"` - Feeds []*MercuryFeed `json:"feeds,omitempty"` -} - -type MercuryServer struct { - URL string `json:"url,omitempty"` - PublicKey string `json:"publicKey,omitempty"` -} - -type MercuryV03Feed struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - ExternalFeedID string `json:"externalFeedID,omitempty"` - Verifiers []*MercuryV03Verifier `json:"verifiers,omitempty"` - ReportSchemaVersion ReportSchemaVersion `json:"reportSchemaVersion,omitempty"` - Template string `json:"template,omitempty"` - Don *Don `json:"don,omitempty"` - CreatedAt Time `json:"createdAt,omitempty"` - UpdatedAt Time `json:"updatedAt,omitempty"` - ArchivedAt *Time `json:"archivedAt,omitempty"` - Category *Category `json:"category,omitempty"` -} - -type MercuryV03FeedFilter struct { - IsArchived *bool `json:"isArchived,omitempty"` - TransmitToServer *bool `json:"transmitToServer,omitempty"` -} - -type MercuryV03Mutations struct { - ArchiveFeed *ArchiveFeedPayload `json:"archiveFeed,omitempty"` - ArchiveNetworkStack *ArchiveNetworkStackPayload `json:"archiveNetworkStack,omitempty"` - AddVerificationProvider *AddVerificationProviderPayload `json:"addVerificationProvider,omitempty"` - RemoveVerificationProvider *RemoveVerificationProviderPayload `json:"removeVerificationProvider,omitempty"` - AddNetworkStack *AddMercuryV03NetworkStackPayload `json:"addNetworkStack,omitempty"` - DeployNetworkStack *DeployMercuryV03NetworkStackPayload `json:"deployNetworkStack,omitempty"` - ImportFeed *ImportMercuryV03FeedPayload `json:"importFeed,omitempty"` - ImportNetworkStack *ImportMercuryV03NetworkStackPayload `json:"importNetworkStack,omitempty"` - TransferOwnership *TransferOwnershipPayload `json:"transferOwnership,omitempty"` - UpdateNetworkStack *UpdateMercuryV03NetworkStackPayload `json:"updateNetworkStack,omitempty"` - UpdateFeed *UpdateMercuryV03FeedPayload `json:"updateFeed,omitempty"` - VerifyContract *VerifyMercuryV03ContractPayload `json:"verifyContract,omitempty"` -} - -type MercuryV03NetworkStack struct { - ID string `json:"id,omitempty"` - Network *Network `json:"network,omitempty"` - Status NetworkStackStatus `json:"status,omitempty"` - VerifierAddress *string `json:"verifierAddress,omitempty"` - VerifierProxyAddress *string `json:"verifierProxyAddress,omitempty"` - RewardBankAddress *string `json:"rewardBankAddress,omitempty"` - FeeManagerAddress *string `json:"feeManagerAddress,omitempty"` - MercuryServerURL string `json:"mercuryServerURL,omitempty"` - MercuryServerPubKey string `json:"mercuryServerPubKey,omitempty"` - Contracts []*Contract `json:"contracts,omitempty"` - WorkflowRuns []*WorkflowRun `json:"workflowRuns,omitempty"` - CreatedAt Time `json:"createdAt,omitempty"` - UpdatedAt Time `json:"updatedAt,omitempty"` - ArchivedAt *Time `json:"archivedAt,omitempty"` - Servers []*MercuryServer `json:"servers,omitempty"` -} - -type MercuryV03NetworkStackFilter struct { - IsArchived *bool `json:"isArchived,omitempty"` -} - -type MercuryV03Queries struct { - NetworkStack *MercuryV03NetworkStack `json:"networkStack,omitempty"` - NetworkStacks []*MercuryV03NetworkStack `json:"networkStacks,omitempty"` - Feed *MercuryV03Feed `json:"feed,omitempty"` - Feeds []*MercuryV03Feed `json:"feeds,omitempty"` -} - -type MercuryV03Verifier struct { - ID string `json:"id,omitempty"` - NetworkStack *MercuryV03NetworkStack `json:"networkStack,omitempty"` - NetworkStackType NetworkStackType `json:"networkStackType,omitempty"` -} - -type Mutation struct { -} - -type Network struct { - ID string `json:"id,omitempty"` - ChainID string `json:"chainID,omitempty"` - ChainType ChainType `json:"chainType,omitempty"` - Name string `json:"name,omitempty"` - NativeToken string `json:"nativeToken,omitempty"` - Archived bool `json:"archived,omitempty"` - NativeTokenContractAddress *string `json:"nativeTokenContractAddress,omitempty"` - ConfigContractAddress *string `json:"configContractAddress,omitempty"` - LinkUSDProxyAddress *string `json:"linkUSDProxyAddress,omitempty"` - NativeUSDProxyAddress *string `json:"nativeUSDProxyAddress,omitempty"` - LinkContractAddress *string `json:"linkContractAddress,omitempty"` - FlagsContractAddress *string `json:"flagsContractAddress,omitempty"` - LinkFunding string `json:"linkFunding,omitempty"` - BillingAdminAccessControllerAddress *string `json:"billingAdminAccessControllerAddress,omitempty"` - RequesterAdminAccessControllerAddress *string `json:"requesterAdminAccessControllerAddress,omitempty"` - IconName *string `json:"iconName,omitempty"` - ExplorerURL *string `json:"explorerURL,omitempty"` - Relayers []*Relayer `json:"relayers,omitempty"` - Vaults []*Vault `json:"vaults,omitempty"` - ExplorerAPIKey *string `json:"explorerAPIKey,omitempty"` - ExplorerAPIURL *string `json:"explorerAPIURL,omitempty"` -} - -type NetworksFilters struct { - Archived *bool `json:"archived,omitempty"` - ChainID *string `json:"chainID,omitempty"` - ChainType *ChainType `json:"chainType,omitempty"` - Name *string `json:"name,omitempty"` -} - -type NetworksInput struct { - Filter *NetworksFilters `json:"filter,omitempty"` -} - -type Node struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - PublicKey *string `json:"publicKey,omitempty"` - ChainConfigs []*NodeChainConfig `json:"chainConfigs,omitempty"` - Connected bool `json:"connected,omitempty"` - Enabled bool `json:"enabled,omitempty"` - Metadata *NodeMetadata `json:"metadata,omitempty"` - NodeOperator *NodeOperator `json:"nodeOperator,omitempty"` - Version *string `json:"version,omitempty"` - SupportedProducts []ProductType `json:"supportedProducts,omitempty"` - Categories []*Category `json:"categories,omitempty"` - CreatedAt Time `json:"createdAt,omitempty"` -} - -type NodeChainConfig struct { - ID string `json:"id,omitempty"` - Network *Network `json:"network,omitempty"` - AccountAddress string `json:"accountAddress,omitempty"` - AdminAddress string `json:"adminAddress,omitempty"` - Ocr1Config *NodeOCR1Config `json:"ocr1Config,omitempty"` - Ocr1BootstrapVerified bool `json:"ocr1BootstrapVerified,omitempty"` - Ocr2Config *NodeOCR2Config `json:"ocr2Config,omitempty"` - Ocr2BootstrapVerified bool `json:"ocr2BootstrapVerified,omitempty"` - CreatedAt Time `json:"createdAt,omitempty"` -} - -type NodeConnectionInfo struct { - PublicKey string `json:"publicKey,omitempty"` - RPCURL string `json:"rpcURL,omitempty"` -} - -type NodeMetadata struct { - JobCount int `json:"jobCount,omitempty"` -} - -type NodeOCR1Config struct { - Enabled bool `json:"enabled,omitempty"` - IsBootstrap bool `json:"isBootstrap,omitempty"` - Multiaddr *string `json:"multiaddr,omitempty"` - P2pKeyBundle *NodeOCR1ConfigP2PKeyBundle `json:"p2pKeyBundle,omitempty"` - OcrKeyBundle *NodeOCR1ConfigOCRKeyBundle `json:"ocrKeyBundle,omitempty"` -} - -type NodeOCR1ConfigOCRKeyBundle struct { - BundleID string `json:"bundleID,omitempty"` - ConfigPublicKey string `json:"configPublicKey,omitempty"` - OffchainPublicKey string `json:"offchainPublicKey,omitempty"` - OnchainSigningAddress string `json:"onchainSigningAddress,omitempty"` -} - -type NodeOCR1ConfigP2PKeyBundle struct { - PeerID string `json:"peerID,omitempty"` - PublicKey string `json:"publicKey,omitempty"` -} - -type NodeOCR2Config struct { - Enabled bool `json:"enabled,omitempty"` - IsBootstrap bool `json:"isBootstrap,omitempty"` - Multiaddr *string `json:"multiaddr,omitempty"` - ForwarderAddress *string `json:"forwarderAddress,omitempty"` - P2pKeyBundle *NodeOCR2ConfigP2PKeyBundle `json:"p2pKeyBundle,omitempty"` - OcrKeyBundle *NodeOCR2ConfigOCRKeyBundle `json:"ocrKeyBundle,omitempty"` - Plugins *NodeOCR2ConfigPlugins `json:"plugins,omitempty"` -} - -type NodeOCR2ConfigOCRKeyBundle struct { - BundleID string `json:"bundleID,omitempty"` - ConfigPublicKey string `json:"configPublicKey,omitempty"` - OffchainPublicKey string `json:"offchainPublicKey,omitempty"` - OnchainSigningAddress string `json:"onchainSigningAddress,omitempty"` -} - -type NodeOCR2ConfigP2PKeyBundle struct { - PeerID string `json:"peerID,omitempty"` - PublicKey string `json:"publicKey,omitempty"` -} - -type NodeOCR2ConfigPlugins struct { - CcipCommit bool `json:"ccipCommit,omitempty"` - CcipExecution bool `json:"ccipExecution,omitempty"` - CcipRebalancer bool `json:"ccipRebalancer,omitempty"` - Median bool `json:"median,omitempty"` - Mercury bool `json:"mercury,omitempty"` -} - -type NodeOperator struct { - ID string `json:"id,omitempty"` - Keys []string `json:"keys,omitempty"` - Name string `json:"name,omitempty"` - Email string `json:"email,omitempty"` - Website string `json:"website,omitempty"` - Metadata *NodeOperatorMetadata `json:"metadata,omitempty"` - Nodes []*Node `json:"nodes,omitempty"` - CreatedAt Time `json:"createdAt,omitempty"` -} - -type NodeOperatorMetadata struct { - NodeCount int `json:"nodeCount,omitempty"` - JobCount int `json:"jobCount,omitempty"` -} - -type NodesFilters struct { - NetworkID *string `json:"networkID,omitempty"` -} - -type NodesInput struct { - Filter *NodesFilters `json:"filter,omitempty"` -} - -type OCR3Capability struct { - ID string `json:"id,omitempty"` - ContractAddress string `json:"contractAddress,omitempty"` - Name string `json:"name,omitempty"` - BootstrapMultiaddrs []string `json:"bootstrapMultiaddrs,omitempty"` - Template string `json:"template,omitempty"` - Category *Category `json:"category,omitempty"` - Don *Don `json:"don,omitempty"` -} - -type OCR3CapabilityMutations struct { - ImportOCR3Capability *ImportOCR3CapabilityPayload `json:"importOCR3Capability,omitempty"` - UpdateOCR3Capability *UpdateOCR3CapabilityPayload `json:"updateOCR3Capability,omitempty"` -} - -type OCR3CapabilityQueries struct { - Ocr3Capability *OCR3Capability `json:"ocr3Capability,omitempty"` - Ocr3Capabilities []*OCR3Capability `json:"ocr3Capabilities,omitempty"` -} - -type PriceFeed struct { - AggregatorAddress string `json:"aggregatorAddress,omitempty"` - Multiplier string `json:"multiplier,omitempty"` -} - -type Profile struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - Email string `json:"email,omitempty"` - Role UserRole `json:"role,omitempty"` - Permits []string `json:"permits,omitempty"` - CreatedAt Time `json:"createdAt,omitempty"` -} - -type ProposeJobInput struct { - ID string `json:"id,omitempty"` -} - -type ProposeJobPayload struct { - Job *Job `json:"job,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type Query struct { -} - -type ReadAccessController struct { - Address string `json:"address,omitempty"` -} - -type Relayer struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - URL *URL `json:"url,omitempty"` - Config string `json:"config,omitempty"` - IsEnabled bool `json:"isEnabled,omitempty"` - Network *Network `json:"network,omitempty"` - Accounts []*RelayerAccount `json:"accounts,omitempty"` -} - -type RelayerAccount struct { - ID string `json:"id,omitempty"` - Relayer *Relayer `json:"relayer,omitempty"` - Address string `json:"address,omitempty"` - NativeBalance string `json:"nativeBalance,omitempty"` - LinkBalance string `json:"linkBalance,omitempty"` -} - -type RelayerURL struct { - Websocket string `json:"websocket,omitempty"` - HTTP string `json:"http,omitempty"` -} - -type RemoveLiquidityInput struct { - ChainID string `json:"chainID,omitempty"` - TokenPoolContractID string `json:"tokenPoolContractID,omitempty"` - Amount string `json:"amount,omitempty"` -} - -type RemoveLiquidityPayload struct { - Errors []Error `json:"errors,omitempty"` - WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` -} - -type RemoveVerificationProviderInput struct { - FeedID string `json:"feedID,omitempty"` - NetworkStackID string `json:"networkStackID,omitempty"` -} - -type RemoveVerificationProviderPayload struct { - Feed *MercuryV03Feed `json:"feed,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type RetryActionRunInput struct { - ActionRunID string `json:"actionRunID,omitempty"` -} - -type RetryActionRunPayload struct { - Status ActionRunStatus `json:"status,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type RetryWebhookCallInput struct { - WebhookCallID string `json:"webhookCallID,omitempty"` -} - -type RetryWebhookCallPayload struct { - WebhookCall *WebhookCall `json:"webhookCall,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type RevokeJobInput struct { - ID string `json:"id,omitempty"` -} - -type RevokeJobPayload struct { - Job *Job `json:"job,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type Role struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - Permits []string `json:"permits,omitempty"` -} - -type RunCCIPCommandInput struct { - Command CCIPCommand `json:"command,omitempty"` - LaneLegID string `json:"laneLegID,omitempty"` - Upgrade *bool `json:"upgrade,omitempty"` -} - -type RunCCIPCommandPayload struct { - Errors []Error `json:"errors,omitempty"` - WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` -} - -type SendTestWebhookEventInput struct { - WebhookID string `json:"webhookID,omitempty"` -} - -type SendTestWebhookEventPayload struct { - WebhookCall *WebhookCall `json:"webhookCall,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type Session struct { - ID string `json:"id,omitempty"` - Token string `json:"token,omitempty"` - ExpiresAt Time `json:"expiresAt,omitempty"` - Revoked bool `json:"revoked,omitempty"` - Permits []string `json:"permits,omitempty"` -} - -type SetAllowListTokenPoolInput struct { - ChainID string `json:"chainID,omitempty"` - TokenPoolContractID string `json:"tokenPoolContractID,omitempty"` - AllowList []string `json:"allowList,omitempty"` -} - -type SetAllowListTokenPoolPayload struct { - Errors []Error `json:"errors,omitempty"` - WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` -} - -type SetPasswordInput struct { - UserID string `json:"userID,omitempty"` - Password string `json:"password,omitempty"` -} - -type SetPasswordPayload struct { - Errors []Error `json:"errors,omitempty"` -} - -type SetupAppInput struct { - Token string `json:"token,omitempty"` - Email string `json:"email,omitempty"` - Name string `json:"name,omitempty"` - Password string `json:"password,omitempty"` -} - -type SetupAppPayload struct { - Errors []Error `json:"errors,omitempty"` -} - -type SpecConfigOffChainReporting1 struct { - Decimals int `json:"decimals,omitempty"` -} - -func (SpecConfigOffChainReporting1) IsAggregatorSpecConfig() {} - -type SpecConfigOffChainReporting2 struct { - Decimals int `json:"decimals,omitempty"` -} - -func (SpecConfigOffChainReporting2) IsAggregatorSpecConfig() {} - -type StorageContract struct { - ID string `json:"id,omitempty"` - Network *Network `json:"network,omitempty"` - DisplayName *string `json:"displayName,omitempty"` - Template string `json:"template,omitempty"` - Contract *Contract `json:"contract,omitempty"` - WorkflowRuns []*WorkflowRun `json:"workflowRuns,omitempty"` -} - -type StorageContractFilter struct { - NetworkID *string `json:"networkID,omitempty"` -} - -// Grouping of all mutations related to the Storage contract resource. -type StorageMutations struct { - // addStorageContract adds a new storage contract to the database and creates - // a single new resource. - AddStorageContract *AddStorageContractPayload `json:"addStorageContract,omitempty"` - // deploySetStorageContract deploys a new storage contract to the network and - // sets the value on chain to the value provided from the template of the storage. - DeploySetStorageContract *DeploySetStorageContractPayload `json:"deploySetStorageContract,omitempty"` -} - -// Grouping of all queries related to the Storage contract resource. -type StorageQueries struct { - StorageContracts []*StorageContract `json:"storageContracts,omitempty"` - StorageContract *StorageContract `json:"storageContract,omitempty"` -} - -type SyncAggregatorInput struct { - ID string `json:"id,omitempty"` -} - -type SyncAggregatorPayload struct { - Aggregator *Aggregator `json:"aggregator,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type SyncAggregatorProxyInput struct { - ID string `json:"id,omitempty"` -} - -type SyncAggregatorProxyPayload struct { - AggregatorProxy *AggregatorProxy `json:"aggregatorProxy,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type SyncChainInput struct { - ChainID string `json:"chainID,omitempty"` -} - -type SyncChainPayload struct { - Chain *CCIPChain `json:"chain,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type SyncContractsInput struct { - ContractIDs []string `json:"contractIDs,omitempty"` -} - -type SyncContractsPayload struct { - Contracts []*Contract `json:"contracts,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type SyncLaneInput struct { - LaneID string `json:"laneID,omitempty"` -} - -type SyncLanePayload struct { - Lane *CCIPLane `json:"lane,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type Task struct { - Name string `json:"name,omitempty"` - Run *TaskRun `json:"run,omitempty"` -} - -type TaskRun struct { - ID string `json:"id,omitempty"` - Input string `json:"input,omitempty"` - Output string `json:"output,omitempty"` - Status TaskRunStatus `json:"status,omitempty"` - Error *string `json:"error,omitempty"` - TxHash *string `json:"txHash,omitempty"` -} - -type Token struct { - Symbol string `json:"symbol,omitempty"` - Address string `json:"address,omitempty"` -} - -type TransferAdminRoleInput struct { - TokenAdminRegistryID string `json:"tokenAdminRegistryID,omitempty"` - TokenPoolID string `json:"tokenPoolID,omitempty"` - VaultID string `json:"vaultID,omitempty"` -} - -type TransferAdminRolePayload struct { - Errors []Error `json:"errors,omitempty"` - WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` -} - -type TransferOwnershipInput struct { - ContractIDs []string `json:"contractIDs,omitempty"` - VaultID string `json:"vaultID,omitempty"` -} - -type TransferOwnershipPayload struct { - Errors []Error `json:"errors,omitempty"` - WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` -} - -type URL struct { - Websocket string `json:"websocket,omitempty"` - HTTP *string `json:"http,omitempty"` -} - -type UnarchiveNetworkInput struct { - ID string `json:"id,omitempty"` -} - -type UnarchiveNetworkPayload struct { - Network *Network `json:"network,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type UpdateAggregatorDetailsInput struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - CategoryID string `json:"categoryID,omitempty"` -} - -type UpdateAggregatorDetailsPayload struct { - Aggregator *Aggregator `json:"aggregator,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type UpdateAggregatorInput struct { - ID string `json:"id,omitempty"` - AggregatorTemplate *string `json:"aggregatorTemplate,omitempty"` -} - -type UpdateAggregatorPayload struct { - Aggregator *Aggregator `json:"aggregator,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type UpdateAggregatorProxyInput struct { - ID string `json:"id,omitempty"` - ContractAddress string `json:"contractAddress,omitempty"` -} - -type UpdateAggregatorProxyPayload struct { - ID string `json:"id,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type UpdateCCIPChainInput struct { - ID string `json:"id,omitempty"` - Template string `json:"template,omitempty"` -} - -type UpdateCCIPChainPayload struct { - Chain *CCIPChain `json:"chain,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type UpdateCategoryInput struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - Color *string `json:"color,omitempty"` -} - -type UpdateCategoryPayload struct { - Category *Category `json:"category,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type UpdateFeedInput struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` -} - -type UpdateFeedPayload struct { - Feed *Feed `json:"feed,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type UpdateKeystoneWorkflowInput struct { - ID string `json:"id,omitempty"` - Template string `json:"template,omitempty"` - CategoryID string `json:"categoryID,omitempty"` -} - -type UpdateKeystoneWorkflowPayload struct { - Workflow *KeystoneWorkflow `json:"workflow,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type UpdateLaneInput struct { - Template *string `json:"template,omitempty"` - UpdateStartBlocks *bool `json:"updateStartBlocks,omitempty"` - LegA *CCIPLaneChainUpdateInput `json:"legA,omitempty"` - LegB *CCIPLaneChainUpdateInput `json:"legB,omitempty"` -} - -type UpdateLanePayload struct { - Errors []Error `json:"errors,omitempty"` - Lane *CCIPLane `json:"lane,omitempty"` -} - -type UpdateMercuryFeedInput struct { - ID string `json:"id,omitempty"` - FromBlock string `json:"fromBlock,omitempty"` - Template *string `json:"template,omitempty"` -} - -type UpdateMercuryFeedPayload struct { - Feed *MercuryFeed `json:"feed,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type UpdateMercuryNetworkStackInput struct { - ID string `json:"id,omitempty"` - VerifierAddress string `json:"verifierAddress,omitempty"` - VerifierProxyAddress string `json:"verifierProxyAddress,omitempty"` - ServerURL string `json:"serverURL,omitempty"` - ServerPublicKey string `json:"serverPublicKey,omitempty"` - Servers *string `json:"servers,omitempty"` -} - -type UpdateMercuryNetworkStackPayload struct { - NetworkStack *MercuryNetworkStack `json:"networkStack,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type UpdateMercuryV03FeedInput struct { - ID string `json:"id,omitempty"` - Template string `json:"template,omitempty"` - CategoryID string `json:"categoryID,omitempty"` -} - -type UpdateMercuryV03FeedPayload struct { - Feed *MercuryV03Feed `json:"feed,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type UpdateMercuryV03NetworkStackInput struct { - ID string `json:"id,omitempty"` - VerifierAddress string `json:"verifierAddress,omitempty"` - VerifierProxyAddress string `json:"verifierProxyAddress,omitempty"` - RewardBankAddress string `json:"rewardBankAddress,omitempty"` - FeeManagerAddress string `json:"feeManagerAddress,omitempty"` - MercuryServerURL string `json:"mercuryServerURL,omitempty"` - MercuryServerPubKey string `json:"mercuryServerPubKey,omitempty"` - Servers *string `json:"servers,omitempty"` -} - -type UpdateMercuryV03NetworkStackPayload struct { - NetworkStack *MercuryV03NetworkStack `json:"networkStack,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type UpdateNetworkInput struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - NativeToken string `json:"nativeToken,omitempty"` - NativeTokenContractAddress *string `json:"nativeTokenContractAddress,omitempty"` - ConfigContractAddress *string `json:"configContractAddress,omitempty"` - LinkUSDProxyAddress *string `json:"linkUSDProxyAddress,omitempty"` - NativeUSDProxyAddress *string `json:"nativeUSDProxyAddress,omitempty"` - LinkContractAddress *string `json:"linkContractAddress,omitempty"` - FlagsContractAddress *string `json:"flagsContractAddress,omitempty"` - LinkFunding *string `json:"linkFunding,omitempty"` - BillingAdminAccessControllerAddress *string `json:"billingAdminAccessControllerAddress,omitempty"` - RequesterAdminAccessControllerAddress *string `json:"requesterAdminAccessControllerAddress,omitempty"` - ExplorerAPIKey *string `json:"explorerAPIKey,omitempty"` - ExplorerAPIURL *string `json:"explorerAPIURL,omitempty"` -} - -type UpdateNetworkPayload struct { - Network *Network `json:"network,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type UpdateNodeInput struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - PublicKey string `json:"publicKey,omitempty"` - SupportedCategoryIDs []string `json:"supportedCategoryIDs,omitempty"` - SupportedProducts []ProductType `json:"supportedProducts,omitempty"` -} - -type UpdateNodeOperatorInput struct { - ID string `json:"id,omitempty"` - Keys []string `json:"keys,omitempty"` - Name string `json:"name,omitempty"` - Email string `json:"email,omitempty"` - Website string `json:"website,omitempty"` -} - -type UpdateNodeOperatorPayload struct { - NodeOperator *NodeOperator `json:"nodeOperator,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type UpdateNodePayload struct { - Node *Node `json:"node,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type UpdateOCR3CapabilityInput struct { - ID string `json:"id,omitempty"` - Template string `json:"template,omitempty"` - CategoryID string `json:"categoryID,omitempty"` -} - -type UpdateOCR3CapabilityPayload struct { - Ocr3Capability *OCR3Capability `json:"ocr3Capability,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type UpdatePasswordInput struct { - OldPassword string `json:"oldPassword,omitempty"` - NewPassword string `json:"newPassword,omitempty"` -} - -type UpdatePasswordPayload struct { - Errors []Error `json:"errors,omitempty"` -} - -type UpdateProfileInput struct { - Name string `json:"name,omitempty"` -} - -type UpdateProfilePayload struct { - Profile *Profile `json:"profile,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type UpdateRelayerInput struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - URL *RelayerURL `json:"url,omitempty"` - Config string `json:"config,omitempty"` -} - -type UpdateRelayerPayload struct { - Relayer *Relayer `json:"relayer,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type UpdateUserInput struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - Email string `json:"email,omitempty"` - Role UserRole `json:"role,omitempty"` -} - -type UpdateUserPayload struct { - User *User `json:"user,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type UpdateVaultInput struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - Address string `json:"address,omitempty"` - SupportedProducts []ProductType `json:"supportedProducts,omitempty"` -} - -type UpdateVaultPayload struct { - Vault *Vault `json:"vault,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type UpdateWebhookInput struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - EndpointURL string `json:"endpointURL,omitempty"` - Enabled bool `json:"enabled,omitempty"` -} - -type UpdateWebhookPayload struct { - Webhook *Webhook `json:"webhook,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type User struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - Email string `json:"email,omitempty"` - Role UserRole `json:"role,omitempty"` - Disabled bool `json:"disabled,omitempty"` - CreatedAt Time `json:"createdAt,omitempty"` -} - -type Vault struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - Address string `json:"address,omitempty"` - Type VaultType `json:"type,omitempty"` - SupportedProducts []ProductType `json:"supportedProducts,omitempty"` - Network *Network `json:"network,omitempty"` - CreatedAt Time `json:"createdAt,omitempty"` - UpdatedAt Time `json:"updatedAt,omitempty"` -} - -type VaultsFilters struct { - Type *VaultType `json:"type,omitempty"` -} - -type VaultsInput struct { - Filter *VaultsFilters `json:"filter,omitempty"` -} - -type VerifyMercuryV03ContractInput struct { - ContractIDs []string `json:"contractIDs,omitempty"` -} - -type VerifyMercuryV03ContractPayload struct { - WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` - Errors []Error `json:"errors,omitempty"` -} - -type Webhook struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - EndpointURL string `json:"endpointURL,omitempty"` - SecretKey string `json:"secretKey,omitempty"` - Enabled bool `json:"enabled,omitempty"` - CreatedAt Time `json:"createdAt,omitempty"` - UpdatedAt Time `json:"updatedAt,omitempty"` -} - -type WebhookCall struct { - ID string `json:"id,omitempty"` - UUID string `json:"uuid,omitempty"` - Type string `json:"type,omitempty"` - State string `json:"state,omitempty"` - Payload string `json:"payload,omitempty"` - Attempts []*WebhookCallAttempt `json:"attempts,omitempty"` - CreatedAt Time `json:"createdAt,omitempty"` - DeliveredAt *Time `json:"deliveredAt,omitempty"` -} - -type WebhookCallAttempt struct { - ID string `json:"id,omitempty"` - StatusCode int `json:"statusCode,omitempty"` - Timestamp Time `json:"timestamp,omitempty"` -} - -type WorkflowRun struct { - ID string `json:"id,omitempty"` - WorkflowType WorkflowType `json:"workflowType,omitempty"` - Status WorkflowRunStatus `json:"status,omitempty"` - User *User `json:"user,omitempty"` - AccountAddress *string `json:"accountAddress,omitempty"` - Actions []*Action `json:"actions,omitempty"` - CreatedAt Time `json:"createdAt,omitempty"` - Name *string `json:"name,omitempty"` - DeletedAt *Time `json:"deletedAt,omitempty"` -} - -type WorkflowRunAndContract struct { - WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` - Contract *Contract `json:"contract,omitempty"` -} - -type WorkflowRunsFilters struct { - UserID *string `json:"userID,omitempty"` -} - -type WorkflowRunsInput struct { - Filter *WorkflowRunsFilters `json:"filter,omitempty"` -} - -type ActionRunStatus string - -const ( - ActionRunStatusPending ActionRunStatus = "PENDING" - ActionRunStatusInProgress ActionRunStatus = "IN_PROGRESS" - ActionRunStatusCompleted ActionRunStatus = "COMPLETED" - ActionRunStatusErrored ActionRunStatus = "ERRORED" -) - -var AllActionRunStatus = []ActionRunStatus{ - ActionRunStatusPending, - ActionRunStatusInProgress, - ActionRunStatusCompleted, - ActionRunStatusErrored, -} - -func (e ActionRunStatus) IsValid() bool { - switch e { - case ActionRunStatusPending, ActionRunStatusInProgress, ActionRunStatusCompleted, ActionRunStatusErrored: - return true - } - return false -} - -func (e ActionRunStatus) String() string { - return string(e) -} - -func (e *ActionRunStatus) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = ActionRunStatus(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid ActionRunStatus", str) - } - return nil -} - -func (e ActionRunStatus) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -type ActionType string - -const ( - ActionTypeGeneric ActionType = "GENERIC" -) - -var AllActionType = []ActionType{ - ActionTypeGeneric, -} - -func (e ActionType) IsValid() bool { - switch e { - case ActionTypeGeneric: - return true - } - return false -} - -func (e ActionType) String() string { - return string(e) -} - -func (e *ActionType) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = ActionType(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid ActionType", str) - } - return nil -} - -func (e ActionType) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -type CCIPCommand string - -const ( - CCIPCommandSetConfig CCIPCommand = "SET_CONFIG" -) - -var AllCCIPCommand = []CCIPCommand{ - CCIPCommandSetConfig, -} - -func (e CCIPCommand) IsValid() bool { - switch e { - case CCIPCommandSetConfig: - return true - } - return false -} - -func (e CCIPCommand) String() string { - return string(e) -} - -func (e *CCIPCommand) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = CCIPCommand(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid CCIPCommand", str) - } - return nil -} - -func (e CCIPCommand) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -type CCIPJobType string - -const ( - CCIPJobTypeCommit CCIPJobType = "COMMIT" - CCIPJobTypeExecute CCIPJobType = "EXECUTE" - CCIPJobTypeBootstrap CCIPJobType = "BOOTSTRAP" -) - -var AllCCIPJobType = []CCIPJobType{ - CCIPJobTypeCommit, - CCIPJobTypeExecute, - CCIPJobTypeBootstrap, -} - -func (e CCIPJobType) IsValid() bool { - switch e { - case CCIPJobTypeCommit, CCIPJobTypeExecute, CCIPJobTypeBootstrap: - return true - } - return false -} - -func (e CCIPJobType) String() string { - return string(e) -} - -func (e *CCIPJobType) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = CCIPJobType(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid CCIPJobType", str) - } - return nil -} - -func (e CCIPJobType) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -type CCIPLaneLegStatus string - -const ( - CCIPLaneLegStatusDraft CCIPLaneLegStatus = "DRAFT" - CCIPLaneLegStatusReady CCIPLaneLegStatus = "READY" -) - -var AllCCIPLaneLegStatus = []CCIPLaneLegStatus{ - CCIPLaneLegStatusDraft, - CCIPLaneLegStatusReady, -} - -func (e CCIPLaneLegStatus) IsValid() bool { - switch e { - case CCIPLaneLegStatusDraft, CCIPLaneLegStatusReady: - return true - } - return false -} - -func (e CCIPLaneLegStatus) String() string { - return string(e) -} - -func (e *CCIPLaneLegStatus) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = CCIPLaneLegStatus(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid CCIPLaneLegStatus", str) - } - return nil -} - -func (e CCIPLaneLegStatus) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -type CCIPLaneLegTag string - -const ( - CCIPLaneLegTagMain CCIPLaneLegTag = "MAIN" - CCIPLaneLegTagProvisional CCIPLaneLegTag = "PROVISIONAL" - CCIPLaneLegTagDead CCIPLaneLegTag = "DEAD" -) - -var AllCCIPLaneLegTag = []CCIPLaneLegTag{ - CCIPLaneLegTagMain, - CCIPLaneLegTagProvisional, - CCIPLaneLegTagDead, -} - -func (e CCIPLaneLegTag) IsValid() bool { - switch e { - case CCIPLaneLegTagMain, CCIPLaneLegTagProvisional, CCIPLaneLegTagDead: - return true - } - return false -} - -func (e CCIPLaneLegTag) String() string { - return string(e) -} - -func (e *CCIPLaneLegTag) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = CCIPLaneLegTag(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid CCIPLaneLegTag", str) - } - return nil -} - -func (e CCIPLaneLegTag) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -type ChainType string - -const ( - ChainTypeEvm ChainType = "EVM" - ChainTypeSolana ChainType = "SOLANA" - ChainTypeStarknet ChainType = "STARKNET" - ChainTypeAptos ChainType = "APTOS" - -) - -var AllChainType = []ChainType{ - ChainTypeEvm, - ChainTypeSolana, - ChainTypeStarknet, - ChainTypeAptos, -} - -func (e ChainType) IsValid() bool { - switch e { - case ChainTypeEvm, ChainTypeSolana, ChainTypeStarknet, ChainTypeAptos: - return true - } - return false -} - -func (e ChainType) String() string { - return string(e) -} - -func (e *ChainType) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = ChainType(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid ChainType", str) - } - return nil -} - -func (e ChainType) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -type ContractOwnerType string - -const ( - ContractOwnerTypeSystem ContractOwnerType = "SYSTEM" - ContractOwnerTypeExternal ContractOwnerType = "EXTERNAL" - ContractOwnerTypeVault ContractOwnerType = "VAULT" - ContractOwnerTypeNotOwnable ContractOwnerType = "NOT_OWNABLE" -) - -var AllContractOwnerType = []ContractOwnerType{ - ContractOwnerTypeSystem, - ContractOwnerTypeExternal, - ContractOwnerTypeVault, - ContractOwnerTypeNotOwnable, -} - -func (e ContractOwnerType) IsValid() bool { - switch e { - case ContractOwnerTypeSystem, ContractOwnerTypeExternal, ContractOwnerTypeVault, ContractOwnerTypeNotOwnable: - return true - } - return false -} - -func (e ContractOwnerType) String() string { - return string(e) -} - -func (e *ContractOwnerType) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = ContractOwnerType(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid ContractOwnerType", str) - } - return nil -} - -func (e ContractOwnerType) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -type ContractTag string - -const ( - ContractTagMain ContractTag = "MAIN" - ContractTagTest ContractTag = "TEST" - ContractTagUpgrade ContractTag = "UPGRADE" - ContractTagDead ContractTag = "DEAD" -) - -var AllContractTag = []ContractTag{ - ContractTagMain, - ContractTagTest, - ContractTagUpgrade, - ContractTagDead, -} - -func (e ContractTag) IsValid() bool { - switch e { - case ContractTagMain, ContractTagTest, ContractTagUpgrade, ContractTagDead: - return true - } - return false -} - -func (e ContractTag) String() string { - return string(e) -} - -func (e *ContractTag) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = ContractTag(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid ContractTag", str) - } - return nil -} - -func (e ContractTag) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -type ContractType string - -const ( - ContractTypeOcr1 ContractType = "OCR1" - ContractTypeOcr2 ContractType = "OCR2" -) - -var AllContractType = []ContractType{ - ContractTypeOcr1, - ContractTypeOcr2, -} - -func (e ContractType) IsValid() bool { - switch e { - case ContractTypeOcr1, ContractTypeOcr2: - return true - } - return false -} - -func (e ContractType) String() string { - return string(e) -} - -func (e *ContractType) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = ContractType(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid ContractType", str) - } - return nil -} - -func (e ContractType) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -type DONExecutionType string - -const ( - DONExecutionTypeMercury DONExecutionType = "MERCURY" - DONExecutionTypeMercuryV03 DONExecutionType = "MERCURY_V03" - DONExecutionTypeAggregator DONExecutionType = "AGGREGATOR" - DONExecutionTypeCcipCommit DONExecutionType = "CCIP_COMMIT" - DONExecutionTypeCcipExecute DONExecutionType = "CCIP_EXECUTE" - DONExecutionTypeKeystoneWorkflow DONExecutionType = "KEYSTONE_WORKFLOW" -) - -var AllDONExecutionType = []DONExecutionType{ - DONExecutionTypeMercury, - DONExecutionTypeMercuryV03, - DONExecutionTypeAggregator, - DONExecutionTypeCcipCommit, - DONExecutionTypeCcipExecute, - DONExecutionTypeKeystoneWorkflow, -} - -func (e DONExecutionType) IsValid() bool { - switch e { - case DONExecutionTypeMercury, DONExecutionTypeMercuryV03, DONExecutionTypeAggregator, DONExecutionTypeCcipCommit, DONExecutionTypeCcipExecute, DONExecutionTypeKeystoneWorkflow: - return true - } - return false -} - -func (e DONExecutionType) String() string { - return string(e) -} - -func (e *DONExecutionType) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = DONExecutionType(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid DONExecutionType", str) - } - return nil -} - -func (e DONExecutionType) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -type DeploymentStatus string - -const ( - DeploymentStatusPending DeploymentStatus = "PENDING" - DeploymentStatusQueued DeploymentStatus = "QUEUED" - DeploymentStatusInProgress DeploymentStatus = "IN_PROGRESS" - DeploymentStatusCompleted DeploymentStatus = "COMPLETED" - DeploymentStatusErrored DeploymentStatus = "ERRORED" -) - -var AllDeploymentStatus = []DeploymentStatus{ - DeploymentStatusPending, - DeploymentStatusQueued, - DeploymentStatusInProgress, - DeploymentStatusCompleted, - DeploymentStatusErrored, -} - -func (e DeploymentStatus) IsValid() bool { - switch e { - case DeploymentStatusPending, DeploymentStatusQueued, DeploymentStatusInProgress, DeploymentStatusCompleted, DeploymentStatusErrored: - return true - } - return false -} - -func (e DeploymentStatus) String() string { - return string(e) -} - -func (e *DeploymentStatus) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = DeploymentStatus(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid DeploymentStatus", str) - } - return nil -} - -func (e DeploymentStatus) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -type FeedStatus string - -const ( - FeedStatusDraft FeedStatus = "DRAFT" - FeedStatusReady FeedStatus = "READY" -) - -var AllFeedStatus = []FeedStatus{ - FeedStatusDraft, - FeedStatusReady, -} - -func (e FeedStatus) IsValid() bool { - switch e { - case FeedStatusDraft, FeedStatusReady: - return true - } - return false -} - -func (e FeedStatus) String() string { - return string(e) -} - -func (e *FeedStatus) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = FeedStatus(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid FeedStatus", str) - } - return nil -} - -func (e FeedStatus) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -type JobProposalStatus string - -const ( - JobProposalStatusProposed JobProposalStatus = "PROPOSED" - JobProposalStatusApproved JobProposalStatus = "APPROVED" - JobProposalStatusRejected JobProposalStatus = "REJECTED" - JobProposalStatusAccepted JobProposalStatus = "ACCEPTED" - JobProposalStatusPending JobProposalStatus = "PENDING" -) - -var AllJobProposalStatus = []JobProposalStatus{ - JobProposalStatusProposed, - JobProposalStatusApproved, - JobProposalStatusRejected, - JobProposalStatusAccepted, - JobProposalStatusPending, -} - -func (e JobProposalStatus) IsValid() bool { - switch e { - case JobProposalStatusProposed, JobProposalStatusApproved, JobProposalStatusRejected, JobProposalStatusAccepted, JobProposalStatusPending: - return true - } - return false -} - -func (e JobProposalStatus) String() string { - return string(e) -} - -func (e *JobProposalStatus) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = JobProposalStatus(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid JobProposalStatus", str) - } - return nil -} - -func (e JobProposalStatus) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -type JobStatus string - -const ( - JobStatusDraft JobStatus = "DRAFT" - JobStatusProposed JobStatus = "PROPOSED" - JobStatusApproved JobStatus = "APPROVED" - JobStatusRejected JobStatus = "REJECTED" - JobStatusCancelled JobStatus = "CANCELLED" - JobStatusDisabled JobStatus = "DISABLED" - JobStatusDeleted JobStatus = "DELETED" - JobStatusRevoked JobStatus = "REVOKED" -) - -var AllJobStatus = []JobStatus{ - JobStatusDraft, - JobStatusProposed, - JobStatusApproved, - JobStatusRejected, - JobStatusCancelled, - JobStatusDisabled, - JobStatusDeleted, - JobStatusRevoked, -} - -func (e JobStatus) IsValid() bool { - switch e { - case JobStatusDraft, JobStatusProposed, JobStatusApproved, JobStatusRejected, JobStatusCancelled, JobStatusDisabled, JobStatusDeleted, JobStatusRevoked: - return true - } - return false -} - -func (e JobStatus) String() string { - return string(e) -} - -func (e *JobStatus) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = JobStatus(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid JobStatus", str) - } - return nil -} - -func (e JobStatus) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -type JobType string - -const ( - JobTypeOffchainreporting JobType = "OFFCHAINREPORTING" - JobTypeOffchainreporting2 JobType = "OFFCHAINREPORTING2" - JobTypeBootstrap JobType = "BOOTSTRAP" - JobTypeWorkflow JobType = "WORKFLOW" -) - -var AllJobType = []JobType{ - JobTypeOffchainreporting, - JobTypeOffchainreporting2, - JobTypeBootstrap, - JobTypeWorkflow, -} - -func (e JobType) IsValid() bool { - switch e { - case JobTypeOffchainreporting, JobTypeOffchainreporting2, JobTypeBootstrap, JobTypeWorkflow: - return true - } - return false -} - -func (e JobType) String() string { - return string(e) -} - -func (e *JobType) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = JobType(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid JobType", str) - } - return nil -} - -func (e JobType) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -type NetworkStackStatus string - -const ( - NetworkStackStatusReady NetworkStackStatus = "READY" - NetworkStackStatusInProgress NetworkStackStatus = "IN_PROGRESS" -) - -var AllNetworkStackStatus = []NetworkStackStatus{ - NetworkStackStatusReady, - NetworkStackStatusInProgress, -} - -func (e NetworkStackStatus) IsValid() bool { - switch e { - case NetworkStackStatusReady, NetworkStackStatusInProgress: - return true - } - return false -} - -func (e NetworkStackStatus) String() string { - return string(e) -} - -func (e *NetworkStackStatus) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = NetworkStackStatus(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid NetworkStackStatus", str) - } - return nil -} - -func (e NetworkStackStatus) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -type NetworkStackType string - -const ( - NetworkStackTypeMain NetworkStackType = "MAIN" - NetworkStackTypeAdditional NetworkStackType = "ADDITIONAL" -) - -var AllNetworkStackType = []NetworkStackType{ - NetworkStackTypeMain, - NetworkStackTypeAdditional, -} - -func (e NetworkStackType) IsValid() bool { - switch e { - case NetworkStackTypeMain, NetworkStackTypeAdditional: - return true - } - return false -} - -func (e NetworkStackType) String() string { - return string(e) -} - -func (e *NetworkStackType) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = NetworkStackType(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid NetworkStackType", str) - } - return nil -} - -func (e NetworkStackType) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -type OCR2PluginType string - -const ( - OCR2PluginTypeMedian OCR2PluginType = "MEDIAN" - OCR2PluginTypeCcipCommit OCR2PluginType = "CCIP_COMMIT" - OCR2PluginTypeCcipExecute OCR2PluginType = "CCIP_EXECUTE" - OCR2PluginTypeCcipRebalancer OCR2PluginType = "CCIP_REBALANCER" - OCR2PluginTypeMercury OCR2PluginType = "MERCURY" -) - -var AllOCR2PluginType = []OCR2PluginType{ - OCR2PluginTypeMedian, - OCR2PluginTypeCcipCommit, - OCR2PluginTypeCcipExecute, - OCR2PluginTypeCcipRebalancer, - OCR2PluginTypeMercury, -} - -func (e OCR2PluginType) IsValid() bool { - switch e { - case OCR2PluginTypeMedian, OCR2PluginTypeCcipCommit, OCR2PluginTypeCcipExecute, OCR2PluginTypeCcipRebalancer, OCR2PluginTypeMercury: - return true - } - return false -} - -func (e OCR2PluginType) String() string { - return string(e) -} - -func (e *OCR2PluginType) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = OCR2PluginType(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid OCR2PluginType", str) - } - return nil -} - -func (e OCR2PluginType) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -type ProductType string - -const ( - ProductTypeDataFeeds ProductType = "DATA_FEEDS" - ProductTypeDataStreamsV02 ProductType = "DATA_STREAMS_V02" - ProductTypeDataStreamsV03 ProductType = "DATA_STREAMS_V03" - ProductTypeCcip ProductType = "CCIP" - ProductTypeWorkflow ProductType = "WORKFLOW" - ProductTypeOcr3Capability ProductType = "OCR3_CAPABILITY" -) - -var AllProductType = []ProductType{ - ProductTypeDataFeeds, - ProductTypeDataStreamsV02, - ProductTypeDataStreamsV03, - ProductTypeCcip, - ProductTypeWorkflow, - ProductTypeOcr3Capability, -} - -func (e ProductType) IsValid() bool { - switch e { - case ProductTypeDataFeeds, ProductTypeDataStreamsV02, ProductTypeDataStreamsV03, ProductTypeCcip, ProductTypeWorkflow, ProductTypeOcr3Capability: - return true - } - return false -} - -func (e ProductType) String() string { - return string(e) -} - -func (e *ProductType) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = ProductType(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid ProductType", str) - } - return nil -} - -func (e ProductType) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -type ReportSchemaVersion string - -const ( - ReportSchemaVersionBasic ReportSchemaVersion = "BASIC" - ReportSchemaVersionPremium ReportSchemaVersion = "PREMIUM" - ReportSchemaVersionBlockBased ReportSchemaVersion = "BLOCK_BASED" -) - -var AllReportSchemaVersion = []ReportSchemaVersion{ - ReportSchemaVersionBasic, - ReportSchemaVersionPremium, - ReportSchemaVersionBlockBased, -} - -func (e ReportSchemaVersion) IsValid() bool { - switch e { - case ReportSchemaVersionBasic, ReportSchemaVersionPremium, ReportSchemaVersionBlockBased: - return true - } - return false -} - -func (e ReportSchemaVersion) String() string { - return string(e) -} - -func (e *ReportSchemaVersion) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = ReportSchemaVersion(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid ReportSchemaVersion", str) - } - return nil -} - -func (e ReportSchemaVersion) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -type SelectorOp string - -const ( - SelectorOpEq SelectorOp = "EQ" - SelectorOpNotEq SelectorOp = "NOT_EQ" - SelectorOpIn SelectorOp = "IN" - SelectorOpNotIn SelectorOp = "NOT_IN" - SelectorOpExist SelectorOp = "EXIST" - SelectorOpNotExist SelectorOp = "NOT_EXIST" -) - -var AllSelectorOp = []SelectorOp{ - SelectorOpEq, - SelectorOpNotEq, - SelectorOpIn, - SelectorOpNotIn, - SelectorOpExist, - SelectorOpNotExist, -} - -func (e SelectorOp) IsValid() bool { - switch e { - case SelectorOpEq, SelectorOpNotEq, SelectorOpIn, SelectorOpNotIn, SelectorOpExist, SelectorOpNotExist: - return true - } - return false -} - -func (e SelectorOp) String() string { - return string(e) -} - -func (e *SelectorOp) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = SelectorOp(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid SelectorOp", str) - } - return nil -} - -func (e SelectorOp) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -type TaskRunStatus string - -const ( - TaskRunStatusInProgress TaskRunStatus = "IN_PROGRESS" - TaskRunStatusCompleted TaskRunStatus = "COMPLETED" - TaskRunStatusErrored TaskRunStatus = "ERRORED" -) - -var AllTaskRunStatus = []TaskRunStatus{ - TaskRunStatusInProgress, - TaskRunStatusCompleted, - TaskRunStatusErrored, -} - -func (e TaskRunStatus) IsValid() bool { - switch e { - case TaskRunStatusInProgress, TaskRunStatusCompleted, TaskRunStatusErrored: - return true - } - return false -} - -func (e TaskRunStatus) String() string { - return string(e) -} - -func (e *TaskRunStatus) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = TaskRunStatus(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid TaskRunStatus", str) - } - return nil -} - -func (e TaskRunStatus) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -type TokenPoolType string - -const ( - TokenPoolTypeLockRelease TokenPoolType = "LOCK_RELEASE" - TokenPoolTypeLockReleaseAndProxy TokenPoolType = "LOCK_RELEASE_AND_PROXY" - TokenPoolTypeBurnMint TokenPoolType = "BURN_MINT" - TokenPoolTypeBurnMintAndProxy TokenPoolType = "BURN_MINT_AND_PROXY" - TokenPoolTypeBurnFromMint TokenPoolType = "BURN_FROM_MINT" - TokenPoolTypeBurnWithFromMint TokenPoolType = "BURN_WITH_FROM_MINT" - TokenPoolTypeBurnWithFromMintAndProxy TokenPoolType = "BURN_WITH_FROM_MINT_AND_PROXY" - TokenPoolTypeUsdc TokenPoolType = "USDC" - TokenPoolTypeFeeTokenOnly TokenPoolType = "FEE_TOKEN_ONLY" -) - -var AllTokenPoolType = []TokenPoolType{ - TokenPoolTypeLockRelease, - TokenPoolTypeLockReleaseAndProxy, - TokenPoolTypeBurnMint, - TokenPoolTypeBurnMintAndProxy, - TokenPoolTypeBurnFromMint, - TokenPoolTypeBurnWithFromMint, - TokenPoolTypeBurnWithFromMintAndProxy, - TokenPoolTypeUsdc, - TokenPoolTypeFeeTokenOnly, -} - -func (e TokenPoolType) IsValid() bool { - switch e { - case TokenPoolTypeLockRelease, TokenPoolTypeLockReleaseAndProxy, TokenPoolTypeBurnMint, TokenPoolTypeBurnMintAndProxy, TokenPoolTypeBurnFromMint, TokenPoolTypeBurnWithFromMint, TokenPoolTypeBurnWithFromMintAndProxy, TokenPoolTypeUsdc, TokenPoolTypeFeeTokenOnly: - return true - } - return false -} - -func (e TokenPoolType) String() string { - return string(e) -} - -func (e *TokenPoolType) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = TokenPoolType(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid TokenPoolType", str) - } - return nil -} - -func (e TokenPoolType) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -type TokenPriceType string - -const ( - TokenPriceTypeFixed TokenPriceType = "FIXED" - TokenPriceTypeFeed TokenPriceType = "FEED" -) - -var AllTokenPriceType = []TokenPriceType{ - TokenPriceTypeFixed, - TokenPriceTypeFeed, -} - -func (e TokenPriceType) IsValid() bool { - switch e { - case TokenPriceTypeFixed, TokenPriceTypeFeed: - return true - } - return false -} - -func (e TokenPriceType) String() string { - return string(e) -} - -func (e *TokenPriceType) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = TokenPriceType(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid TokenPriceType", str) - } - return nil -} - -func (e TokenPriceType) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -type TransferOwnershipStatus string - -const ( - TransferOwnershipStatusNone TransferOwnershipStatus = "NONE" - TransferOwnershipStatusProcessingTransaction TransferOwnershipStatus = "PROCESSING_TRANSACTION" - TransferOwnershipStatusAwaitingConfirmation TransferOwnershipStatus = "AWAITING_CONFIRMATION" - TransferOwnershipStatusError TransferOwnershipStatus = "ERROR" -) - -var AllTransferOwnershipStatus = []TransferOwnershipStatus{ - TransferOwnershipStatusNone, - TransferOwnershipStatusProcessingTransaction, - TransferOwnershipStatusAwaitingConfirmation, - TransferOwnershipStatusError, -} - -func (e TransferOwnershipStatus) IsValid() bool { - switch e { - case TransferOwnershipStatusNone, TransferOwnershipStatusProcessingTransaction, TransferOwnershipStatusAwaitingConfirmation, TransferOwnershipStatusError: - return true - } - return false -} - -func (e TransferOwnershipStatus) String() string { - return string(e) -} - -func (e *TransferOwnershipStatus) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = TransferOwnershipStatus(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid TransferOwnershipStatus", str) - } - return nil -} - -func (e TransferOwnershipStatus) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -type UserRole string - -const ( - UserRoleViewer UserRole = "VIEWER" - UserRoleOps UserRole = "OPS" - UserRoleMaintainer UserRole = "MAINTAINER" - UserRoleAdmin UserRole = "ADMIN" - UserRoleFoundation UserRole = "FOUNDATION" - UserRoleDataProvider UserRole = "DATA_PROVIDER" - UserRoleCcipValidator UserRole = "CCIP_VALIDATOR" - UserRoleDataStreamsOps UserRole = "DATA_STREAMS_OPS" -) - -var AllUserRole = []UserRole{ - UserRoleViewer, - UserRoleOps, - UserRoleMaintainer, - UserRoleAdmin, - UserRoleFoundation, - UserRoleDataProvider, - UserRoleCcipValidator, - UserRoleDataStreamsOps, -} - -func (e UserRole) IsValid() bool { - switch e { - case UserRoleViewer, UserRoleOps, UserRoleMaintainer, UserRoleAdmin, UserRoleFoundation, UserRoleDataProvider, UserRoleCcipValidator, UserRoleDataStreamsOps: - return true - } - return false -} - -func (e UserRole) String() string { - return string(e) -} - -func (e *UserRole) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = UserRole(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid UserRole", str) - } - return nil -} - -func (e UserRole) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -type VaultType string - -const ( - VaultTypeEoa VaultType = "EOA" - VaultTypeSafe VaultType = "SAFE" - VaultTypeTimelock VaultType = "TIMELOCK" -) - -var AllVaultType = []VaultType{ - VaultTypeEoa, - VaultTypeSafe, - VaultTypeTimelock, -} - -func (e VaultType) IsValid() bool { - switch e { - case VaultTypeEoa, VaultTypeSafe, VaultTypeTimelock: - return true - } - return false -} - -func (e VaultType) String() string { - return string(e) -} - -func (e *VaultType) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = VaultType(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid VaultType", str) - } - return nil -} - -func (e VaultType) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -type VerificationStatus string - -const ( - VerificationStatusUnknown VerificationStatus = "UNKNOWN" - VerificationStatusSuccess VerificationStatus = "SUCCESS" - VerificationStatusPending VerificationStatus = "PENDING" - VerificationStatusError VerificationStatus = "ERROR" -) - -var AllVerificationStatus = []VerificationStatus{ - VerificationStatusUnknown, - VerificationStatusSuccess, - VerificationStatusPending, - VerificationStatusError, -} - -func (e VerificationStatus) IsValid() bool { - switch e { - case VerificationStatusUnknown, VerificationStatusSuccess, VerificationStatusPending, VerificationStatusError: - return true - } - return false -} - -func (e VerificationStatus) String() string { - return string(e) -} - -func (e *VerificationStatus) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = VerificationStatus(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid VerificationStatus", str) - } - return nil -} - -func (e VerificationStatus) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -type WebhookCallState string - -const ( - WebhookCallStatePending WebhookCallState = "PENDING" - WebhookCallStateSuccess WebhookCallState = "SUCCESS" - WebhookCallStateError WebhookCallState = "ERROR" - WebhookCallStateFailed WebhookCallState = "FAILED" -) - -var AllWebhookCallState = []WebhookCallState{ - WebhookCallStatePending, - WebhookCallStateSuccess, - WebhookCallStateError, - WebhookCallStateFailed, -} - -func (e WebhookCallState) IsValid() bool { - switch e { - case WebhookCallStatePending, WebhookCallStateSuccess, WebhookCallStateError, WebhookCallStateFailed: - return true - } - return false -} - -func (e WebhookCallState) String() string { - return string(e) -} - -func (e *WebhookCallState) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = WebhookCallState(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid WebhookCallState", str) - } - return nil -} - -func (e WebhookCallState) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -type WorkflowRunStatus string - -const ( - WorkflowRunStatusPending WorkflowRunStatus = "PENDING" - WorkflowRunStatusInProgress WorkflowRunStatus = "IN_PROGRESS" - WorkflowRunStatusCompleted WorkflowRunStatus = "COMPLETED" - WorkflowRunStatusErrored WorkflowRunStatus = "ERRORED" -) - -var AllWorkflowRunStatus = []WorkflowRunStatus{ - WorkflowRunStatusPending, - WorkflowRunStatusInProgress, - WorkflowRunStatusCompleted, - WorkflowRunStatusErrored, -} - -func (e WorkflowRunStatus) IsValid() bool { - switch e { - case WorkflowRunStatusPending, WorkflowRunStatusInProgress, WorkflowRunStatusCompleted, WorkflowRunStatusErrored: - return true - } - return false -} - -func (e WorkflowRunStatus) String() string { - return string(e) -} - -func (e *WorkflowRunStatus) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = WorkflowRunStatus(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid WorkflowRunStatus", str) - } - return nil -} - -func (e WorkflowRunStatus) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -type WorkflowType string - -const ( - WorkflowTypeGeneric WorkflowType = "GENERIC" -) - -var AllWorkflowType = []WorkflowType{ - WorkflowTypeGeneric, -} - -func (e WorkflowType) IsValid() bool { - switch e { - case WorkflowTypeGeneric: - return true - } - return false -} - -func (e WorkflowType) String() string { - return string(e) -} - -func (e *WorkflowType) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = WorkflowType(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid WorkflowType", str) - } - return nil -} - -func (e WorkflowType) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} diff --git a/deployment/environment/clo/offchain_client_impl.go b/deployment/environment/clo/offchain_client_impl.go deleted file mode 100644 index 2046a32f810..00000000000 --- a/deployment/environment/clo/offchain_client_impl.go +++ /dev/null @@ -1,271 +0,0 @@ -package clo - -import ( - "context" - "fmt" - "slices" - "strings" - - "go.uber.org/zap" - "google.golang.org/grpc" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - csav1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/csa" - jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" - nodev1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" - "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/shared/ptypes" - - "github.com/smartcontractkit/chainlink/deployment/environment/clo/models" -) - -type JobClient struct { - NodeOperators []*models.NodeOperator `json:"nodeOperators"` - nodesByID map[string]*models.Node - lggr logger.Logger -} - -func (j JobClient) BatchProposeJob(ctx context.Context, in *jobv1.BatchProposeJobRequest, opts ...grpc.CallOption) (*jobv1.BatchProposeJobResponse, error) { - //TODO implement me - panic("implement me") -} - -func (j JobClient) UpdateJob(ctx context.Context, in *jobv1.UpdateJobRequest, opts ...grpc.CallOption) (*jobv1.UpdateJobResponse, error) { - //TODO CCIP-3108 implement me - panic("implement me") -} - -func (j JobClient) DisableNode(ctx context.Context, in *nodev1.DisableNodeRequest, opts ...grpc.CallOption) (*nodev1.DisableNodeResponse, error) { - //TODO CCIP-3108 implement me - panic("implement me") -} - -func (j JobClient) EnableNode(ctx context.Context, in *nodev1.EnableNodeRequest, opts ...grpc.CallOption) (*nodev1.EnableNodeResponse, error) { - //TODO CCIP-3108 implement me - panic("implement me") -} - -func (j JobClient) RegisterNode(ctx context.Context, in *nodev1.RegisterNodeRequest, opts ...grpc.CallOption) (*nodev1.RegisterNodeResponse, error) { - //TODO implement me - panic("implement me") -} - -func (j JobClient) UpdateNode(ctx context.Context, in *nodev1.UpdateNodeRequest, opts ...grpc.CallOption) (*nodev1.UpdateNodeResponse, error) { - //TODO CCIP-3108 implement me - panic("implement me") -} - -func (j JobClient) GetKeypair(ctx context.Context, in *csav1.GetKeypairRequest, opts ...grpc.CallOption) (*csav1.GetKeypairResponse, error) { - //TODO implement me - panic("implement me") -} - -func (j JobClient) ListKeypairs(ctx context.Context, in *csav1.ListKeypairsRequest, opts ...grpc.CallOption) (*csav1.ListKeypairsResponse, error) { - //TODO CCIP-3108 implement me - panic("implement me") -} - -func (j JobClient) GetNode(ctx context.Context, in *nodev1.GetNodeRequest, opts ...grpc.CallOption) (*nodev1.GetNodeResponse, error) { - //TODO CCIP-3108 implement me - panic("implement me") -} - -func (j JobClient) ListNodes(ctx context.Context, in *nodev1.ListNodesRequest, opts ...grpc.CallOption) (*nodev1.ListNodesResponse, error) { - include := func(node *nodev1.Node) bool { - if in.Filter == nil { - return true - } - if len(in.Filter.Ids) > 0 { - idx := slices.IndexFunc(in.Filter.Ids, func(id string) bool { - return node.Id == id - }) - if idx < 0 { - return false - } - } - for _, selector := range in.Filter.Selectors { - idx := slices.IndexFunc(node.Labels, func(label *ptypes.Label) bool { - return label.Key == selector.Key - }) - if idx < 0 { - return false - } - label := node.Labels[idx] - - switch selector.Op { - case ptypes.SelectorOp_IN: - values := strings.Split(*selector.Value, ",") - found := slices.Contains(values, *label.Value) - if !found { - return false - } - default: - panic("unimplemented selector") - } - } - return true - } - var nodes []*nodev1.Node - for _, nop := range j.NodeOperators { - for _, n := range nop.Nodes { - p2pId, err := NodeP2PId(n) - if err != nil { - return nil, fmt.Errorf("failed to get p2p id for node %s: %w", n.ID, err) - } - node := &nodev1.Node{ - Id: n.ID, - Name: n.Name, - PublicKey: *n.PublicKey, - IsEnabled: n.Enabled, - IsConnected: n.Connected, - Labels: []*ptypes.Label{ - { - Key: "p2p_id", - Value: &p2pId, // here n.ID is also peer ID - }, - }, - } - if include(node) { - nodes = append(nodes, node) - } - } - } - return &nodev1.ListNodesResponse{ - Nodes: nodes, - }, nil -} - -func (j JobClient) ListNodeChainConfigs(ctx context.Context, in *nodev1.ListNodeChainConfigsRequest, opts ...grpc.CallOption) (*nodev1.ListNodeChainConfigsResponse, error) { - - resp := &nodev1.ListNodeChainConfigsResponse{ - ChainConfigs: make([]*nodev1.ChainConfig, 0), - } - // no filter, return all - if in.Filter == nil || len(in.Filter.NodeIds) == 0 { - for _, n := range j.nodesByID { - ccfg := cloNodeToChainConfigs(n) - resp.ChainConfigs = append(resp.ChainConfigs, ccfg...) - } - } else { - for _, want := range in.Filter.NodeIds { - n, ok := j.nodesByID[want] - if !ok { - j.lggr.Warn("node not found", zap.String("node_id", want)) - continue - } - ccfg := cloNodeToChainConfigs(n) - resp.ChainConfigs = append(resp.ChainConfigs, ccfg...) - } - } - return resp, nil - -} - -func (j JobClient) GetJob(ctx context.Context, in *jobv1.GetJobRequest, opts ...grpc.CallOption) (*jobv1.GetJobResponse, error) { - //TODO CCIP-3108 implement me - panic("implement me") -} - -func (j JobClient) GetProposal(ctx context.Context, in *jobv1.GetProposalRequest, opts ...grpc.CallOption) (*jobv1.GetProposalResponse, error) { - //TODO CCIP-3108 implement me - panic("implement me") -} - -func (j JobClient) ListJobs(ctx context.Context, in *jobv1.ListJobsRequest, opts ...grpc.CallOption) (*jobv1.ListJobsResponse, error) { - //TODO CCIP-3108 implement me - panic("implement me") -} - -func (j JobClient) ListProposals(ctx context.Context, in *jobv1.ListProposalsRequest, opts ...grpc.CallOption) (*jobv1.ListProposalsResponse, error) { - //TODO CCIP-3108 implement me - panic("implement me") -} - -func (j JobClient) ProposeJob(ctx context.Context, in *jobv1.ProposeJobRequest, opts ...grpc.CallOption) (*jobv1.ProposeJobResponse, error) { - panic("implement me") - -} - -func (j JobClient) RevokeJob(ctx context.Context, in *jobv1.RevokeJobRequest, opts ...grpc.CallOption) (*jobv1.RevokeJobResponse, error) { - //TODO CCIP-3108 implement me - panic("implement me") -} - -func (j JobClient) DeleteJob(ctx context.Context, in *jobv1.DeleteJobRequest, opts ...grpc.CallOption) (*jobv1.DeleteJobResponse, error) { - //TODO CCIP-3108 implement me - panic("implement me") -} - -type GetNodeOperatorsResponse struct { - NodeOperators []*models.NodeOperator `json:"nodeOperators"` -} - -type JobClientConfig struct { - Nops []*models.NodeOperator -} - -func NewJobClient(lggr logger.Logger, cfg JobClientConfig) *JobClient { - - c := &JobClient{ - NodeOperators: cfg.Nops, - nodesByID: make(map[string]*models.Node), - lggr: lggr, - } - for _, nop := range c.NodeOperators { - for _, n := range nop.Nodes { - node := n - c.nodesByID[n.ID] = node // maybe should use the public key instead? - } - } - return c -} - -func cloNodeToChainConfigs(n *models.Node) []*nodev1.ChainConfig { - out := make([]*nodev1.ChainConfig, 0) - for _, ccfg := range n.ChainConfigs { - out = append(out, cloChainCfgToJDChainCfg(ccfg)) - } - return out -} - -func cloChainCfgToJDChainCfg(ccfg *models.NodeChainConfig) *nodev1.ChainConfig { - var ctype nodev1.ChainType - switch ccfg.Network.ChainType { - case models.ChainTypeEvm: - ctype = nodev1.ChainType_CHAIN_TYPE_EVM - case models.ChainTypeSolana: - ctype = nodev1.ChainType_CHAIN_TYPE_SOLANA - case models.ChainTypeStarknet: - ctype = nodev1.ChainType_CHAIN_TYPE_STARKNET - case models.ChainTypeAptos: - ctype = nodev1.ChainType_CHAIN_TYPE_APTOS - default: - panic(fmt.Sprintf("Unsupported chain family %v", ccfg.Network.ChainType)) - } - - return &nodev1.ChainConfig{ - Chain: &nodev1.Chain{ - Id: ccfg.Network.ChainID, - Type: ctype, - }, - AccountAddress: ccfg.AccountAddress, - AdminAddress: ccfg.AdminAddress, - // only care about ocr2 for now - Ocr2Config: &nodev1.OCR2Config{ - Enabled: ccfg.Ocr2Config.Enabled, - IsBootstrap: ccfg.Ocr2Config.IsBootstrap, - P2PKeyBundle: &nodev1.OCR2Config_P2PKeyBundle{ - PeerId: ccfg.Ocr2Config.P2pKeyBundle.PeerID, - PublicKey: ccfg.Ocr2Config.P2pKeyBundle.PublicKey, - }, - OcrKeyBundle: &nodev1.OCR2Config_OCRKeyBundle{ - BundleId: ccfg.Ocr2Config.OcrKeyBundle.BundleID, - ConfigPublicKey: ccfg.Ocr2Config.OcrKeyBundle.ConfigPublicKey, - OffchainPublicKey: ccfg.Ocr2Config.OcrKeyBundle.OffchainPublicKey, - OnchainSigningAddress: ccfg.Ocr2Config.OcrKeyBundle.OnchainSigningAddress, - }, - // TODO: the clo cli does not serialize this field, so it will always be nil - //Multiaddr: *ccfg.Ocr2Config.Multiaddr, - //ForwarderAddress: ccfg.Ocr2Config.ForwarderAddress, - }, - } -} diff --git a/deployment/environment/clo/offchain_client_impl_test.go b/deployment/environment/clo/offchain_client_impl_test.go deleted file mode 100644 index f2d6fcf6f41..00000000000 --- a/deployment/environment/clo/offchain_client_impl_test.go +++ /dev/null @@ -1,677 +0,0 @@ -package clo_test - -import ( - "context" - "encoding/json" - "reflect" - "testing" - - "github.com/test-go/testify/require" - "google.golang.org/grpc" - - nodev1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" - "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/shared/ptypes" - "github.com/smartcontractkit/chainlink/deployment/environment/clo" - "github.com/smartcontractkit/chainlink/deployment/environment/clo/models" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -var ( - p2pid_1 = "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE7807807807" - p2pid_2 = "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE6868686868" - p2pid_3 = "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE9999999999" - p2pid_4 = "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE1000000000" -) - -var testNops = ` -[ - { - "id": "67", - "name": "Chainlink Keystone Node Operator 9", - "nodes": [ - { - "id": "780", - "name": "Chainlink Sepolia Prod Keystone One 9", - "publicKey": "412dc6fe48ea4e34baaa77da2e3b032d39b938597b6f3d61fe7ed183a827a431", - "connected": true, - "chainConfigs": [ - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM" - }, - "ocr2Config": { - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE7807807807" - } - } - } - ], - "supportedProducts": [ - "WORKFLOW", - "OCR3_CAPABILITY" - ] - } - ], - "createdAt": "2024-08-14T19:00:07.113658Z" - }, - { - "id": "68", - "name": "Chainlink Keystone Node Operator 8", - "nodes": [ - { - "id": "781", - "name": "Chainlink Sepolia Prod Keystone One 8", - "publicKey": "1141dd1e46797ced9b0fbad49115f18507f6f6e6e3cc86e7e5ba169e58645adc", - "connected": true, - "chainConfigs": [ - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM" - }, - "ocr2Config": { - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE6868686868" - } - } - } - ], - "supportedProducts": [ - "WORKFLOW", - "OCR3_CAPABILITY" - ] - } - ], - "createdAt": "2024-08-14T20:26:37.622463Z" - }, - { - "id": "999", - "name": "Chainlink Keystone Node Operator 100", - "nodes": [ - { - "id": "999", - "name": "Chainlink Sepolia Prod Keystone One 999", - "publicKey": "9991dd1e46797ced9b0fbad49115f18507f6f6e6e3cc86e7e5ba169e58999999", - "connected": true, - "chainConfigs": [ - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM" - }, - "ocr2Config": { - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE9999999999" - } - } - } - ], - "supportedProducts": [ - "WORKFLOW", - "OCR3_CAPABILITY" - ] - }, - { - "id": "1000", - "name": "Chainlink Sepolia Prod Keystone One 1000", - "publicKey": "1000101e46797ced9b0fbad49115f18507f6f6e6e3cc86e7e5ba169e58641000", - "connected": true, - "chainConfigs": [ - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM" - }, - "ocr2Config": { - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE1000000000" - } - } - } - ], - "supportedProducts": [ - "WORKFLOW", - "OCR3_CAPABILITY" - ] - } - ], - "createdAt": "2024-08-14T20:26:37.622463Z" - } -] -` - -func parseTestNops(t *testing.T) []*models.NodeOperator { - t.Helper() - var out []*models.NodeOperator - err := json.Unmarshal([]byte(testNops), &out) - require.NoError(t, err) - require.Len(t, out, 3, "wrong number of nops") - return out -} -func TestJobClient_ListNodes(t *testing.T) { - lggr := logger.TestLogger(t) - nops := parseTestNops(t) - - type fields struct { - NodeOperators []*models.NodeOperator - RemapNodeIDsToPeerIDs bool - } - type args struct { - ctx context.Context - in *nodev1.ListNodesRequest - opts []grpc.CallOption - } - tests := []struct { - name string - fields fields - args args - want *nodev1.ListNodesResponse - wantErr bool - }{ - { - name: "empty", - fields: fields{ - NodeOperators: make([]*models.NodeOperator, 0), - }, - args: args{ - ctx: context.Background(), - in: &nodev1.ListNodesRequest{}, - }, - want: &nodev1.ListNodesResponse{}, - }, - { - name: "one node from one nop", - fields: fields{ - NodeOperators: nops[0:1], - }, - args: args{ - ctx: context.Background(), - in: &nodev1.ListNodesRequest{}, - }, - want: &nodev1.ListNodesResponse{ - Nodes: []*nodev1.Node{ - { - Id: "780", - Name: "Chainlink Sepolia Prod Keystone One 9", - PublicKey: "412dc6fe48ea4e34baaa77da2e3b032d39b938597b6f3d61fe7ed183a827a431", - IsConnected: true, - Labels: []*ptypes.Label{ - { - Key: "p2p_id", - Value: &p2pid_1, - }, - }, - }, - }, - }, - }, - { - name: "two nops each with one node", - fields: fields{ - NodeOperators: nops[0:2], - }, - args: args{ - ctx: context.Background(), - in: &nodev1.ListNodesRequest{}, - }, - want: &nodev1.ListNodesResponse{ - Nodes: []*nodev1.Node{ - { - Id: "780", - Name: "Chainlink Sepolia Prod Keystone One 9", - PublicKey: "412dc6fe48ea4e34baaa77da2e3b032d39b938597b6f3d61fe7ed183a827a431", - IsConnected: true, - Labels: []*ptypes.Label{ - { - Key: "p2p_id", - Value: &p2pid_1, - }, - }, - }, - { - Id: "781", - Name: "Chainlink Sepolia Prod Keystone One 8", - PublicKey: "1141dd1e46797ced9b0fbad49115f18507f6f6e6e3cc86e7e5ba169e58645adc", - IsConnected: true, - Labels: []*ptypes.Label{ - { - Key: "p2p_id", - Value: &p2pid_2, - }, - }, - }, - }, - }, - }, - { - name: "two nodes from one nop", - fields: fields{ - NodeOperators: nops[2:3], - }, - args: args{ - ctx: context.Background(), - in: &nodev1.ListNodesRequest{}, - }, - want: &nodev1.ListNodesResponse{ - Nodes: []*nodev1.Node{ - { - Id: "999", - Name: "Chainlink Sepolia Prod Keystone One 999", - PublicKey: "9991dd1e46797ced9b0fbad49115f18507f6f6e6e3cc86e7e5ba169e58999999", - IsConnected: true, - Labels: []*ptypes.Label{ - { - Key: "p2p_id", - Value: &p2pid_3, - }, - }, - }, - { - Id: "1000", - Name: "Chainlink Sepolia Prod Keystone One 1000", - PublicKey: "1000101e46797ced9b0fbad49115f18507f6f6e6e3cc86e7e5ba169e58641000", - IsConnected: true, - Labels: []*ptypes.Label{ - { - Key: "p2p_id", - Value: &p2pid_4, - }, - }, - }, - }, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - j := clo.NewJobClient(lggr, clo.JobClientConfig{Nops: tt.fields.NodeOperators}) - - got, err := j.ListNodes(tt.args.ctx, tt.args.in, tt.args.opts...) - if (err != nil) != tt.wantErr { - t.Errorf("JobClient.ListNodes() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("JobClient.ListNodes() = %v, want %v", got, tt.want) - } - }) - } -} - -var testNopsWithChainConfigs = ` -[ - { - "id": "67", - "keys": [ - "keystone-09" - ], - "name": "Chainlink Keystone Node Operator 9", - "metadata": { - "nodeCount": 1, - "jobCount": 4 - }, - "nodes": [ - { - "id": "780", - "name": "Chainlink Sepolia Prod Keystone One 9", - "publicKey": "412dc6fe48ea4e34baaa77da2e3b032d39b938597b6f3d61fe7ed183a827a431", - "chainConfigs": [ - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0xbA8E21dFaa0501fCD43146d0b5F21c2B8E0eEdfB", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE8TxNr5dM4U", - "publicKey": "147d5cc651819b093cd2fdff9760f0f0f77b7ef7798d9e24fc6a350b7300e5d9" - }, - "ocrKeyBundle": { - "bundleID": "1c28e76d180d1ed1524e61845fa58a384415de7e51017edf1f8c553e28357772", - "configPublicKey": "09fced0207611ed618bf0759ab128d9797e15b18e46436be1a56a91e4043ec0e", - "offchainPublicKey": "c805572b813a072067eab2087ddbee8aa719090e12890b15c01094f0d3f74a5f", - "onchainSigningAddress": "679296b7c1eb4948efcc87efc550940a182e610c" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x0b04cE574E80Da73191Ec141c0016a54A6404056", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE8TxNr5dM4U", - "publicKey": "147d5cc651819b093cd2fdff9760f0f0f77b7ef7798d9e24fc6a350b7300e5d9" - }, - "ocrKeyBundle": { - "bundleID": "1c28e76d180d1ed1524e61845fa58a384415de7e51017edf1f8c553e28357772", - "configPublicKey": "09fced0207611ed618bf0759ab128d9797e15b18e46436be1a56a91e4043ec0e", - "offchainPublicKey": "c805572b813a072067eab2087ddbee8aa719090e12890b15c01094f0d3f74a5f", - "onchainSigningAddress": "679296b7c1eb4948efcc87efc550940a182e610c" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "WORKFLOW", - "OCR3_CAPABILITY" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T19:00:07.113658Z" - }, - { - "id": "68", - "keys": [ - "keystone-08" - ], - "name": "Chainlink Keystone Node Operator 8", - "metadata": { - "nodeCount": 1, - "jobCount": 4 - }, - "nodes": [ - { - "id": "781", - "name": "Chainlink Sepolia Prod Keystone One 8", - "publicKey": "1141dd1e46797ced9b0fbad49115f18507f6f6e6e3cc86e7e5ba169e58645adc", - "chainConfigs": [ - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0xEa4bC3638660D78Da56f39f6680dCDD0cEAaD2c6", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWAUagqMycsro27kFznSQRHbhfCBLx8nKD4ptTiUGDe38c", - "publicKey": "09ca39cd924653c72fbb0e458b629c3efebdad3e29e7cd0b5760754d919ed829" - }, - "ocrKeyBundle": { - "bundleID": "be0d639de3ae3cbeaa31ca369514f748ba1d271145cba6796bcc12aace2f64c3", - "configPublicKey": "e3d4d7a7372a3b1110db0290ab3649eb5fbb0daf6cf3ae02cfe5f367700d9264", - "offchainPublicKey": "ad08c2a5878cada53521f4e2bb449f191ccca7899246721a0deeea19f7b83f70", - "onchainSigningAddress": "8c2aa1e6fad88a6006dfb116eb866cbad2910314" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x31B179dcF8f9036C30f04bE578793e51bF14A39E", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWAUagqMycsro27kFznSQRHbhfCBLx8nKD4ptTiUGDe38c", - "publicKey": "09ca39cd924653c72fbb0e458b629c3efebdad3e29e7cd0b5760754d919ed829" - }, - "ocrKeyBundle": { - "bundleID": "be0d639de3ae3cbeaa31ca369514f748ba1d271145cba6796bcc12aace2f64c3", - "configPublicKey": "e3d4d7a7372a3b1110db0290ab3649eb5fbb0daf6cf3ae02cfe5f367700d9264", - "offchainPublicKey": "ad08c2a5878cada53521f4e2bb449f191ccca7899246721a0deeea19f7b83f70", - "onchainSigningAddress": "8c2aa1e6fad88a6006dfb116eb866cbad2910314" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "WORKFLOW", - "OCR3_CAPABILITY" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T20:26:37.622463Z" - } -]` - -func TestJobClient_ListNodeChainConfigs(t *testing.T) { - nops := parseTestNopsWithChainConfigs(t) - lggr := logger.TestLogger(t) - type fields struct { - NodeOperators []*models.NodeOperator - } - type args struct { - ctx context.Context - in *nodev1.ListNodeChainConfigsRequest - opts []grpc.CallOption - } - tests := []struct { - name string - fields fields - args args - want *nodev1.ListNodeChainConfigsResponse - wantErr bool - }{ - { - name: "empty", - fields: fields{ - NodeOperators: make([]*models.NodeOperator, 0), - }, - args: args{ - ctx: context.Background(), - in: &nodev1.ListNodeChainConfigsRequest{}, - }, - want: &nodev1.ListNodeChainConfigsResponse{ - ChainConfigs: make([]*nodev1.ChainConfig, 0), - }, - }, - - { - name: "no matching nodes", - fields: fields{ - NodeOperators: nops, - }, - args: args{ - ctx: context.Background(), - in: &nodev1.ListNodeChainConfigsRequest{ - Filter: &nodev1.ListNodeChainConfigsRequest_Filter{ - NodeIds: []string{"not-a-node-id"}, - }, - }, - }, - want: &nodev1.ListNodeChainConfigsResponse{ - ChainConfigs: make([]*nodev1.ChainConfig, 0), - }, - }, - - { - name: "one nop with one node that has two chain configs", - fields: fields{ - NodeOperators: nops[0:1], - }, - args: args{ - ctx: context.Background(), - in: &nodev1.ListNodeChainConfigsRequest{}, - }, - want: &nodev1.ListNodeChainConfigsResponse{ - ChainConfigs: []*nodev1.ChainConfig{ - { - Chain: &nodev1.Chain{ - Id: "421614", - Type: nodev1.ChainType_CHAIN_TYPE_EVM, - }, - AccountAddress: "0xbA8E21dFaa0501fCD43146d0b5F21c2B8E0eEdfB", - AdminAddress: "0x0000000000000000000000000000000000000000", - Ocr2Config: &nodev1.OCR2Config{ - Enabled: true, - P2PKeyBundle: &nodev1.OCR2Config_P2PKeyBundle{ - PeerId: "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE8TxNr5dM4U", - PublicKey: "147d5cc651819b093cd2fdff9760f0f0f77b7ef7798d9e24fc6a350b7300e5d9", - }, - OcrKeyBundle: &nodev1.OCR2Config_OCRKeyBundle{ - BundleId: "1c28e76d180d1ed1524e61845fa58a384415de7e51017edf1f8c553e28357772", - ConfigPublicKey: "09fced0207611ed618bf0759ab128d9797e15b18e46436be1a56a91e4043ec0e", - OffchainPublicKey: "c805572b813a072067eab2087ddbee8aa719090e12890b15c01094f0d3f74a5f", - OnchainSigningAddress: "679296b7c1eb4948efcc87efc550940a182e610c", - }, - }, - }, - { - Chain: &nodev1.Chain{ - Id: "11155111", - Type: nodev1.ChainType_CHAIN_TYPE_EVM, - }, - AccountAddress: "0x0b04cE574E80Da73191Ec141c0016a54A6404056", - AdminAddress: "0x0000000000000000000000000000000000000000", - Ocr2Config: &nodev1.OCR2Config{ - Enabled: true, - P2PKeyBundle: &nodev1.OCR2Config_P2PKeyBundle{ - PeerId: "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE8TxNr5dM4U", - PublicKey: "147d5cc651819b093cd2fdff9760f0f0f77b7ef7798d9e24fc6a350b7300e5d9", - }, - OcrKeyBundle: &nodev1.OCR2Config_OCRKeyBundle{ - BundleId: "1c28e76d180d1ed1524e61845fa58a384415de7e51017edf1f8c553e28357772", - ConfigPublicKey: "09fced0207611ed618bf0759ab128d9797e15b18e46436be1a56a91e4043ec0e", - OffchainPublicKey: "c805572b813a072067eab2087ddbee8aa719090e12890b15c01094f0d3f74a5f", - OnchainSigningAddress: "679296b7c1eb4948efcc87efc550940a182e610c", - }, - }, - }, - }, - }, - }, - - { - name: "one nop with one node that has two chain configs matching the filter", - fields: fields{ - NodeOperators: nops, - }, - args: args{ - ctx: context.Background(), - in: &nodev1.ListNodeChainConfigsRequest{ - Filter: &nodev1.ListNodeChainConfigsRequest_Filter{ - NodeIds: []string{"780"}, - }, - }, - }, - want: &nodev1.ListNodeChainConfigsResponse{ - ChainConfigs: []*nodev1.ChainConfig{ - { - Chain: &nodev1.Chain{ - Id: "421614", - Type: nodev1.ChainType_CHAIN_TYPE_EVM, - }, - AccountAddress: "0xbA8E21dFaa0501fCD43146d0b5F21c2B8E0eEdfB", - AdminAddress: "0x0000000000000000000000000000000000000000", - Ocr2Config: &nodev1.OCR2Config{ - Enabled: true, - P2PKeyBundle: &nodev1.OCR2Config_P2PKeyBundle{ - PeerId: "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE8TxNr5dM4U", - PublicKey: "147d5cc651819b093cd2fdff9760f0f0f77b7ef7798d9e24fc6a350b7300e5d9", - }, - OcrKeyBundle: &nodev1.OCR2Config_OCRKeyBundle{ - BundleId: "1c28e76d180d1ed1524e61845fa58a384415de7e51017edf1f8c553e28357772", - ConfigPublicKey: "09fced0207611ed618bf0759ab128d9797e15b18e46436be1a56a91e4043ec0e", - OffchainPublicKey: "c805572b813a072067eab2087ddbee8aa719090e12890b15c01094f0d3f74a5f", - OnchainSigningAddress: "679296b7c1eb4948efcc87efc550940a182e610c", - }, - }, - }, - { - Chain: &nodev1.Chain{ - Id: "11155111", - Type: nodev1.ChainType_CHAIN_TYPE_EVM, - }, - AccountAddress: "0x0b04cE574E80Da73191Ec141c0016a54A6404056", - AdminAddress: "0x0000000000000000000000000000000000000000", - Ocr2Config: &nodev1.OCR2Config{ - Enabled: true, - P2PKeyBundle: &nodev1.OCR2Config_P2PKeyBundle{ - PeerId: "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE8TxNr5dM4U", - PublicKey: "147d5cc651819b093cd2fdff9760f0f0f77b7ef7798d9e24fc6a350b7300e5d9", - }, - OcrKeyBundle: &nodev1.OCR2Config_OCRKeyBundle{ - BundleId: "1c28e76d180d1ed1524e61845fa58a384415de7e51017edf1f8c553e28357772", - ConfigPublicKey: "09fced0207611ed618bf0759ab128d9797e15b18e46436be1a56a91e4043ec0e", - OffchainPublicKey: "c805572b813a072067eab2087ddbee8aa719090e12890b15c01094f0d3f74a5f", - OnchainSigningAddress: "679296b7c1eb4948efcc87efc550940a182e610c", - }, - }, - }, - }, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - j := clo.NewJobClient(lggr, clo.JobClientConfig{Nops: tt.fields.NodeOperators}) - - got, err := j.ListNodeChainConfigs(tt.args.ctx, tt.args.in, tt.args.opts...) - if (err != nil) != tt.wantErr { - t.Errorf("JobClient.ListNodeChainConfigs() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("JobClient.ListNodeChainConfigs() = %v, want %v", got, tt.want) - } - }) - } -} - -func parseTestNopsWithChainConfigs(t *testing.T) []*models.NodeOperator { - t.Helper() - var out []*models.NodeOperator - err := json.Unmarshal([]byte(testNopsWithChainConfigs), &out) - require.NoError(t, err) - require.Len(t, out, 2, "wrong number of nops") - return out -} diff --git a/deployment/environment/clo/testdata/keystone_nops.json b/deployment/environment/clo/testdata/keystone_nops.json deleted file mode 100644 index 679a85935a4..00000000000 --- a/deployment/environment/clo/testdata/keystone_nops.json +++ /dev/null @@ -1,3162 +0,0 @@ -[ - { - "id": "67", - "keys": [ - "keystone-09" - ], - "name": "Chainlink Keystone Node Operator 9", - "metadata": { - "nodeCount": 2, - "jobCount": 4 - }, - "nodes": [ - { - "id": "780", - "name": "Chainlink Sepolia Prod Keystone One 9", - "publicKey": "412dc6fe48ea4e34baaa77da2e3b032d39b938597b6f3d61fe7ed183a827a431", - "chainConfigs": [ - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0xbA8E21dFaa0501fCD43146d0b5F21c2B8E0eEdfB", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE8TxNr5dM4U", - "publicKey": "147d5cc651819b093cd2fdff9760f0f0f77b7ef7798d9e24fc6a350b7300e5d9" - }, - "ocrKeyBundle": { - "bundleID": "1c28e76d180d1ed1524e61845fa58a384415de7e51017edf1f8c553e28357772", - "configPublicKey": "09fced0207611ed618bf0759ab128d9797e15b18e46436be1a56a91e4043ec0e", - "offchainPublicKey": "c805572b813a072067eab2087ddbee8aa719090e12890b15c01094f0d3f74a5f", - "onchainSigningAddress": "679296b7c1eb4948efcc87efc550940a182e610c" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x0b04cE574E80Da73191Ec141c0016a54A6404056", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE8TxNr5dM4U", - "publicKey": "147d5cc651819b093cd2fdff9760f0f0f77b7ef7798d9e24fc6a350b7300e5d9" - }, - "ocrKeyBundle": { - "bundleID": "1c28e76d180d1ed1524e61845fa58a384415de7e51017edf1f8c553e28357772", - "configPublicKey": "09fced0207611ed618bf0759ab128d9797e15b18e46436be1a56a91e4043ec0e", - "offchainPublicKey": "c805572b813a072067eab2087ddbee8aa719090e12890b15c01094f0d3f74a5f", - "onchainSigningAddress": "679296b7c1eb4948efcc87efc550940a182e610c" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "WORKFLOW", - "OCR3_CAPABILITY" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - }, - { - "id": "818", - "name": "Chainlink Sepolia Prod Keystone Cap One 9", - "publicKey": "3f5bbcb4b0409e6ea39d824f1837787484475fffb12e5e4a70509756ef6c7f9a", - "chainConfigs": [ - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0x9b74f08bD7269919C0597C0E00e70ef2A66829db", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWPG6X2RgqoSWtM3kvETV6kK4ki8FftaBkwvFWk8yKRBkz", - "publicKey": "c7bf55cf625a55470b0c56c3e51ad175c9dd0d42ca48246c205c715b7495937f" - }, - "ocrKeyBundle": { - "bundleID": "aa717effd7d28374c5980dbd9583dcff5e0800e7100051c6c8418899648dffbf", - "configPublicKey": "3fd95a3839f15adcdff573e6fbf07d06d78fbfeac5eb683f67e70226c1983c44", - "offchainPublicKey": "2b8b8d091c6f4446365f463e6132d699206bbddd38284e8e14ae0443382f297c", - "onchainSigningAddress": "b05b138a987fceffa68f79bdbb36a1faf8d3d964" - }, - "plugins": {} - } - }, - { - "network": { - "id": "10", - "chainID": "43113", - "chainType": "EVM", - "name": "Avalanche Testnet (Fuji)" - }, - "accountAddress": "0x662B6B119f7fc9Dc2A526395A9EA88AE79A1192F", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWPG6X2RgqoSWtM3kvETV6kK4ki8FftaBkwvFWk8yKRBkz", - "publicKey": "c7bf55cf625a55470b0c56c3e51ad175c9dd0d42ca48246c205c715b7495937f" - }, - "ocrKeyBundle": { - "bundleID": "aa717effd7d28374c5980dbd9583dcff5e0800e7100051c6c8418899648dffbf", - "configPublicKey": "3fd95a3839f15adcdff573e6fbf07d06d78fbfeac5eb683f67e70226c1983c44", - "offchainPublicKey": "2b8b8d091c6f4446365f463e6132d699206bbddd38284e8e14ae0443382f297c", - "onchainSigningAddress": "b05b138a987fceffa68f79bdbb36a1faf8d3d964" - }, - "plugins": {} - } - }, - { - "network": { - "id": "147", - "chainID": "84532", - "chainType": "EVM", - "name": "Base Testnet (Sepolia)" - }, - "accountAddress": "0x34431021e0E07c75816226697Af6Ef02725e36af", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWPG6X2RgqoSWtM3kvETV6kK4ki8FftaBkwvFWk8yKRBkz", - "publicKey": "c7bf55cf625a55470b0c56c3e51ad175c9dd0d42ca48246c205c715b7495937f" - }, - "ocrKeyBundle": { - "bundleID": "aa717effd7d28374c5980dbd9583dcff5e0800e7100051c6c8418899648dffbf", - "configPublicKey": "3fd95a3839f15adcdff573e6fbf07d06d78fbfeac5eb683f67e70226c1983c44", - "offchainPublicKey": "2b8b8d091c6f4446365f463e6132d699206bbddd38284e8e14ae0443382f297c", - "onchainSigningAddress": "b05b138a987fceffa68f79bdbb36a1faf8d3d964" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0xB5988d5d9ADd3d98CF45211bE37cf9b3372054C9", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWPG6X2RgqoSWtM3kvETV6kK4ki8FftaBkwvFWk8yKRBkz", - "publicKey": "c7bf55cf625a55470b0c56c3e51ad175c9dd0d42ca48246c205c715b7495937f" - }, - "ocrKeyBundle": { - "bundleID": "aa717effd7d28374c5980dbd9583dcff5e0800e7100051c6c8418899648dffbf", - "configPublicKey": "3fd95a3839f15adcdff573e6fbf07d06d78fbfeac5eb683f67e70226c1983c44", - "offchainPublicKey": "2b8b8d091c6f4446365f463e6132d699206bbddd38284e8e14ae0443382f297c", - "onchainSigningAddress": "b05b138a987fceffa68f79bdbb36a1faf8d3d964" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "OCR3_CAPABILITY", - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T19:00:07.113658Z" - }, - { - "id": "68", - "keys": [ - "keystone-08" - ], - "name": "Chainlink Keystone Node Operator 8", - "metadata": { - "nodeCount": 2, - "jobCount": 4 - }, - "nodes": [ - { - "id": "781", - "name": "Chainlink Sepolia Prod Keystone One 8", - "publicKey": "1141dd1e46797ced9b0fbad49115f18507f6f6e6e3cc86e7e5ba169e58645adc", - "chainConfigs": [ - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0xEa4bC3638660D78Da56f39f6680dCDD0cEAaD2c6", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWAUagqMycsro27kFznSQRHbhfCBLx8nKD4ptTiUGDe38c", - "publicKey": "09ca39cd924653c72fbb0e458b629c3efebdad3e29e7cd0b5760754d919ed829" - }, - "ocrKeyBundle": { - "bundleID": "be0d639de3ae3cbeaa31ca369514f748ba1d271145cba6796bcc12aace2f64c3", - "configPublicKey": "e3d4d7a7372a3b1110db0290ab3649eb5fbb0daf6cf3ae02cfe5f367700d9264", - "offchainPublicKey": "ad08c2a5878cada53521f4e2bb449f191ccca7899246721a0deeea19f7b83f70", - "onchainSigningAddress": "8c2aa1e6fad88a6006dfb116eb866cbad2910314" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x31B179dcF8f9036C30f04bE578793e51bF14A39E", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWAUagqMycsro27kFznSQRHbhfCBLx8nKD4ptTiUGDe38c", - "publicKey": "09ca39cd924653c72fbb0e458b629c3efebdad3e29e7cd0b5760754d919ed829" - }, - "ocrKeyBundle": { - "bundleID": "be0d639de3ae3cbeaa31ca369514f748ba1d271145cba6796bcc12aace2f64c3", - "configPublicKey": "e3d4d7a7372a3b1110db0290ab3649eb5fbb0daf6cf3ae02cfe5f367700d9264", - "offchainPublicKey": "ad08c2a5878cada53521f4e2bb449f191ccca7899246721a0deeea19f7b83f70", - "onchainSigningAddress": "8c2aa1e6fad88a6006dfb116eb866cbad2910314" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "WORKFLOW", - "OCR3_CAPABILITY" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - }, - { - "id": "817", - "name": "Chainlink Sepolia Prod Keystone Cap One 8", - "publicKey": "2346da196a82c88fe6c315d2e4d0dddacf4590a172b20adb6f27a8601ca0540d", - "chainConfigs": [ - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0xa5C7133aBD35F9d742bD2997D693A507c5eBf4Ac", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWNfg9cYxEri1zGbdCZ87DekmruYY6J1wUobEwNNVewMpT", - "publicKey": "beee088bccea272eb6473fcc1cd3e22f2fc8d3a253a6398b69f5aab94070e690" - }, - "ocrKeyBundle": { - "bundleID": "9fba2d29874bb06b07272bd9141f096c1987d790bb0f81c3ffaf66d11cdac4f2", - "configPublicKey": "66dec87065de79e64ed4edd2478ec40a66f955af56e7b837729f464f8487d713", - "offchainPublicKey": "a0f59d50078c77812da8d3077f552209adfb58e76b635e008b6b0f872ce52139", - "onchainSigningAddress": "ed25406f1ef2e1381f6e1e04341f1a6e8b4eacea" - }, - "plugins": {} - } - }, - { - "network": { - "id": "10", - "chainID": "43113", - "chainType": "EVM", - "name": "Avalanche Testnet (Fuji)" - }, - "accountAddress": "0x9fd869f5baADb79F9b7C58c0855fcAc0384e1d4B", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWNfg9cYxEri1zGbdCZ87DekmruYY6J1wUobEwNNVewMpT", - "publicKey": "beee088bccea272eb6473fcc1cd3e22f2fc8d3a253a6398b69f5aab94070e690" - }, - "ocrKeyBundle": { - "bundleID": "9fba2d29874bb06b07272bd9141f096c1987d790bb0f81c3ffaf66d11cdac4f2", - "configPublicKey": "66dec87065de79e64ed4edd2478ec40a66f955af56e7b837729f464f8487d713", - "offchainPublicKey": "a0f59d50078c77812da8d3077f552209adfb58e76b635e008b6b0f872ce52139", - "onchainSigningAddress": "ed25406f1ef2e1381f6e1e04341f1a6e8b4eacea" - }, - "plugins": {} - } - }, - { - "network": { - "id": "147", - "chainID": "84532", - "chainType": "EVM", - "name": "Base Testnet (Sepolia)" - }, - "accountAddress": "0xe477E4C2e335E9b839665d710dE77CFECa9C43A7", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWNfg9cYxEri1zGbdCZ87DekmruYY6J1wUobEwNNVewMpT", - "publicKey": "beee088bccea272eb6473fcc1cd3e22f2fc8d3a253a6398b69f5aab94070e690" - }, - "ocrKeyBundle": { - "bundleID": "9fba2d29874bb06b07272bd9141f096c1987d790bb0f81c3ffaf66d11cdac4f2", - "configPublicKey": "66dec87065de79e64ed4edd2478ec40a66f955af56e7b837729f464f8487d713", - "offchainPublicKey": "a0f59d50078c77812da8d3077f552209adfb58e76b635e008b6b0f872ce52139", - "onchainSigningAddress": "ed25406f1ef2e1381f6e1e04341f1a6e8b4eacea" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x056A1275DD670205aba10D8fC9bB597777a65030", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWNfg9cYxEri1zGbdCZ87DekmruYY6J1wUobEwNNVewMpT", - "publicKey": "beee088bccea272eb6473fcc1cd3e22f2fc8d3a253a6398b69f5aab94070e690" - }, - "ocrKeyBundle": { - "bundleID": "9fba2d29874bb06b07272bd9141f096c1987d790bb0f81c3ffaf66d11cdac4f2", - "configPublicKey": "66dec87065de79e64ed4edd2478ec40a66f955af56e7b837729f464f8487d713", - "offchainPublicKey": "a0f59d50078c77812da8d3077f552209adfb58e76b635e008b6b0f872ce52139", - "onchainSigningAddress": "ed25406f1ef2e1381f6e1e04341f1a6e8b4eacea" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "OCR3_CAPABILITY", - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T20:26:37.622463Z" - }, - { - "id": "69", - "keys": [ - "keystone-07" - ], - "name": "Chainlink Keystone Node Operator 7", - "metadata": { - "nodeCount": 2, - "jobCount": 4 - }, - "nodes": [ - { - "id": "782", - "name": "Chainlink Sepolia Prod Keystone One 7", - "publicKey": "b473091fe1d4dbbc26ad71c67b4432f8f4280e06bab5e2122a92f4ab8b6ff2f5", - "chainConfigs": [ - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0x65bE4739E187a39b859766C143b569acd5BE234d", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWQMCj73V5xmCd6C5VsJr7rbFG2TF9LwVcLiiBqXps9MgC", - "publicKey": "d7e9f2252b09edf0802a65b60bc9956691747894cb3ab9fefd072adf742eb9f1" - }, - "ocrKeyBundle": { - "bundleID": "e6d6ffec6cff01ac20d57bc42626c8e955293f232d383bf468351d867a7b8213", - "configPublicKey": "4d2f75f98b911c20fe7808384312d8b913e6b7a98c34d05c6e461434c92b4502", - "offchainPublicKey": "01496edce35663071d74472e02119432ba059b3904d205e4358014410e4f2be3", - "onchainSigningAddress": "213803bb9f9715379aaf11aadb0212369701dc0a" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x9ad9f3AD49e5aB0F28bD694d211a90297bD90D7f", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWQMCj73V5xmCd6C5VsJr7rbFG2TF9LwVcLiiBqXps9MgC", - "publicKey": "d7e9f2252b09edf0802a65b60bc9956691747894cb3ab9fefd072adf742eb9f1" - }, - "ocrKeyBundle": { - "bundleID": "e6d6ffec6cff01ac20d57bc42626c8e955293f232d383bf468351d867a7b8213", - "configPublicKey": "4d2f75f98b911c20fe7808384312d8b913e6b7a98c34d05c6e461434c92b4502", - "offchainPublicKey": "01496edce35663071d74472e02119432ba059b3904d205e4358014410e4f2be3", - "onchainSigningAddress": "213803bb9f9715379aaf11aadb0212369701dc0a" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "WORKFLOW", - "OCR3_CAPABILITY" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - }, - { - "id": "816", - "name": "Chainlink Sepolia Prod Keystone Cap One 7", - "publicKey": "50d4e3393516d1998e5c39874d7c0da2291e4e3727f8baac4380e9f5573cc648", - "chainConfigs": [ - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0x0ba7c1096B701A862bBCe7F13E9D33eED7e33c1D", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWQswQr8fxJG5ieMrayptGV4rvCjDWPCFtfkqm4L6NZbbb", - "publicKey": "dfc9a26dc022bd244c13d62ca88bbe62ca996065bd23224e1f1b77128914d84e" - }, - "ocrKeyBundle": { - "bundleID": "d4566a0c2f256e59733ad2a6dff9f388a1e00b2e65ec1cff7590cb59028888cd", - "configPublicKey": "58db0da621471e616615b8c1c1658ee3b7afbfa64662ce28b38272a95964052c", - "offchainPublicKey": "262fee9de8dd0c8758ba78de8873fdb6705c45ce331bc16ac81dc5b5f0b9680f", - "onchainSigningAddress": "516a9990d3a202b25c2cdd2f6316f4d066543e5d" - }, - "plugins": {} - } - }, - { - "network": { - "id": "10", - "chainID": "43113", - "chainType": "EVM", - "name": "Avalanche Testnet (Fuji)" - }, - "accountAddress": "0xcC44eD47023Bd88B82092A708c38609e8Fc2D197", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWQswQr8fxJG5ieMrayptGV4rvCjDWPCFtfkqm4L6NZbbb", - "publicKey": "dfc9a26dc022bd244c13d62ca88bbe62ca996065bd23224e1f1b77128914d84e" - }, - "ocrKeyBundle": { - "bundleID": "d4566a0c2f256e59733ad2a6dff9f388a1e00b2e65ec1cff7590cb59028888cd", - "configPublicKey": "58db0da621471e616615b8c1c1658ee3b7afbfa64662ce28b38272a95964052c", - "offchainPublicKey": "262fee9de8dd0c8758ba78de8873fdb6705c45ce331bc16ac81dc5b5f0b9680f", - "onchainSigningAddress": "516a9990d3a202b25c2cdd2f6316f4d066543e5d" - }, - "plugins": {} - } - }, - { - "network": { - "id": "147", - "chainID": "84532", - "chainType": "EVM", - "name": "Base Testnet (Sepolia)" - }, - "accountAddress": "0x0E8F4E699cd331022FaA2Ad75E500e70303C8767", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWQswQr8fxJG5ieMrayptGV4rvCjDWPCFtfkqm4L6NZbbb", - "publicKey": "dfc9a26dc022bd244c13d62ca88bbe62ca996065bd23224e1f1b77128914d84e" - }, - "ocrKeyBundle": { - "bundleID": "d4566a0c2f256e59733ad2a6dff9f388a1e00b2e65ec1cff7590cb59028888cd", - "configPublicKey": "58db0da621471e616615b8c1c1658ee3b7afbfa64662ce28b38272a95964052c", - "offchainPublicKey": "262fee9de8dd0c8758ba78de8873fdb6705c45ce331bc16ac81dc5b5f0b9680f", - "onchainSigningAddress": "516a9990d3a202b25c2cdd2f6316f4d066543e5d" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x49c36b3BEc6b6e0e77305273FAFC68f479630535", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWQswQr8fxJG5ieMrayptGV4rvCjDWPCFtfkqm4L6NZbbb", - "publicKey": "dfc9a26dc022bd244c13d62ca88bbe62ca996065bd23224e1f1b77128914d84e" - }, - "ocrKeyBundle": { - "bundleID": "d4566a0c2f256e59733ad2a6dff9f388a1e00b2e65ec1cff7590cb59028888cd", - "configPublicKey": "58db0da621471e616615b8c1c1658ee3b7afbfa64662ce28b38272a95964052c", - "offchainPublicKey": "262fee9de8dd0c8758ba78de8873fdb6705c45ce331bc16ac81dc5b5f0b9680f", - "onchainSigningAddress": "516a9990d3a202b25c2cdd2f6316f4d066543e5d" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "OCR3_CAPABILITY", - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T20:30:51.07624Z" - }, - { - "id": "70", - "keys": [ - "keystone-06" - ], - "name": "Chainlink Keystone Node Operator 6", - "metadata": { - "nodeCount": 2, - "jobCount": 4 - }, - "nodes": [ - { - "id": "783", - "name": "Chainlink Sepolia Prod Keystone One 6", - "publicKey": "75ac63fc97a31e31168084e0de8ccd2bea90059b609d962f3e43fc296cdba28d", - "chainConfigs": [ - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0x8706E716fc1ee972F3E4D42D42711Aa175Aa654A", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWNJ8de3PUURZ2oucrVTpnRTqNBTUYwHLQjK9LzN3E6Mfn", - "publicKey": "b96933429b1a81c811e1195389d7733e936b03e8086e75ea1fa92c61564b6c31" - }, - "ocrKeyBundle": { - "bundleID": "62d36269d916b4834b17dc6d637c1c39b0895396249a0845764c898e83f63525", - "configPublicKey": "8c6c7d889ac6cc9e663ae48073bbf130fae105d6a3689636db27752e3e3e6816", - "offchainPublicKey": "aa3419628ea3536783742d17d8adf05681aa6a6bd2b206fbde78c7e5aa38586d", - "onchainSigningAddress": "4885973b2fcf061d5cdfb8f74c5139bd3056e9da" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x19e10B063a62B1574AE19020A64fDe6419892dA6", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWNJ8de3PUURZ2oucrVTpnRTqNBTUYwHLQjK9LzN3E6Mfn", - "publicKey": "b96933429b1a81c811e1195389d7733e936b03e8086e75ea1fa92c61564b6c31" - }, - "ocrKeyBundle": { - "bundleID": "62d36269d916b4834b17dc6d637c1c39b0895396249a0845764c898e83f63525", - "configPublicKey": "8c6c7d889ac6cc9e663ae48073bbf130fae105d6a3689636db27752e3e3e6816", - "offchainPublicKey": "aa3419628ea3536783742d17d8adf05681aa6a6bd2b206fbde78c7e5aa38586d", - "onchainSigningAddress": "4885973b2fcf061d5cdfb8f74c5139bd3056e9da" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "WORKFLOW", - "OCR3_CAPABILITY" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - }, - { - "id": "815", - "name": "Chainlink Sepolia Prod Keystone Cap One 6", - "publicKey": "2669981add3071fae5dfd760fe97e7d2b90157f86b40227f306f1f3906099fc3", - "chainConfigs": [ - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0x405eE4ad3E79786f899810ff6de16a83A920Db5D", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWHB1ucYgRqrocS6t834wL5XaB11JSPgKwzB6QwRPzRayu", - "publicKey": "6d4c18afa813bf7eec73e98a260294bce4b0b26eb9f6efceb2c9402eead56c98" - }, - "ocrKeyBundle": { - "bundleID": "d55283594d4e2c3e507f81ea9ad96261ebec1b1e8579bb1392ca22f7dc9b471b", - "configPublicKey": "32d5b6d38147fa23ec1dc4eeb240e2e70ea768b9a5182676075acd5a2ab2794c", - "offchainPublicKey": "9922cb5c0ae08f0b917979593824bde7ddad0935950e2835914acc34f6cd62f3", - "onchainSigningAddress": "bca900017893ea1366c110941d698d078c2b93ca" - }, - "plugins": {} - } - }, - { - "network": { - "id": "10", - "chainID": "43113", - "chainType": "EVM", - "name": "Avalanche Testnet (Fuji)" - }, - "accountAddress": "0x58D39d629ae9f904b0Ae509179b9e7c9B0184cee", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWHB1ucYgRqrocS6t834wL5XaB11JSPgKwzB6QwRPzRayu", - "publicKey": "6d4c18afa813bf7eec73e98a260294bce4b0b26eb9f6efceb2c9402eead56c98" - }, - "ocrKeyBundle": { - "bundleID": "d55283594d4e2c3e507f81ea9ad96261ebec1b1e8579bb1392ca22f7dc9b471b", - "configPublicKey": "32d5b6d38147fa23ec1dc4eeb240e2e70ea768b9a5182676075acd5a2ab2794c", - "offchainPublicKey": "9922cb5c0ae08f0b917979593824bde7ddad0935950e2835914acc34f6cd62f3", - "onchainSigningAddress": "bca900017893ea1366c110941d698d078c2b93ca" - }, - "plugins": {} - } - }, - { - "network": { - "id": "147", - "chainID": "84532", - "chainType": "EVM", - "name": "Base Testnet (Sepolia)" - }, - "accountAddress": "0x34bFe10F4f4e1101b019639ABd5E5eE5186B80E6", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWHB1ucYgRqrocS6t834wL5XaB11JSPgKwzB6QwRPzRayu", - "publicKey": "6d4c18afa813bf7eec73e98a260294bce4b0b26eb9f6efceb2c9402eead56c98" - }, - "ocrKeyBundle": { - "bundleID": "d55283594d4e2c3e507f81ea9ad96261ebec1b1e8579bb1392ca22f7dc9b471b", - "configPublicKey": "32d5b6d38147fa23ec1dc4eeb240e2e70ea768b9a5182676075acd5a2ab2794c", - "offchainPublicKey": "9922cb5c0ae08f0b917979593824bde7ddad0935950e2835914acc34f6cd62f3", - "onchainSigningAddress": "bca900017893ea1366c110941d698d078c2b93ca" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x1741EB7468A490b4A9BA6f4CC7A47B82EcD65c4c", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWHB1ucYgRqrocS6t834wL5XaB11JSPgKwzB6QwRPzRayu", - "publicKey": "6d4c18afa813bf7eec73e98a260294bce4b0b26eb9f6efceb2c9402eead56c98" - }, - "ocrKeyBundle": { - "bundleID": "d55283594d4e2c3e507f81ea9ad96261ebec1b1e8579bb1392ca22f7dc9b471b", - "configPublicKey": "32d5b6d38147fa23ec1dc4eeb240e2e70ea768b9a5182676075acd5a2ab2794c", - "offchainPublicKey": "9922cb5c0ae08f0b917979593824bde7ddad0935950e2835914acc34f6cd62f3", - "onchainSigningAddress": "bca900017893ea1366c110941d698d078c2b93ca" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "OCR3_CAPABILITY", - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T20:32:14.024795Z" - }, - { - "id": "71", - "keys": [ - "keystone-05" - ], - "name": "Chainlink Keystone Node Operator 5", - "metadata": { - "nodeCount": 2, - "jobCount": 4 - }, - "nodes": [ - { - "id": "784", - "name": "Chainlink Sepolia Prod Keystone One 5", - "publicKey": "4542f4fd2ed150c8c976b39802fe3d994aec3ac94fd11e7817f693b1c9a1dabb", - "chainConfigs": [ - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0xcea9f5C042130dD35Eff5B5a6E2361A0276570e3", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWR8d5kbZb7YiQWKpT1J1PfMqNaGAmb4jBFx9DWag4hpSZ", - "publicKey": "e38c9f2760db006f070e9cc1bc1c2269ad033751adaa85d022fb760cbc5b5ef6" - }, - "ocrKeyBundle": { - "bundleID": "99fad0362cc8dc8a57a8e616e68133a6d5a8834e08a1b4819710f0e912df5abc", - "configPublicKey": "36de4924cf11938b4461aea1ce99cb640e9603d9a7c294ab6c54acd51d575a49", - "offchainPublicKey": "283471ed66d61fbe11f64eff65d738b59a0301c9a4f846280db26c64c9fdd3f8", - "onchainSigningAddress": "657587eb55cecd6f90b97297b611c3024e488cc0" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0xdAd1F3F8ec690cf335D46c50EdA5547CeF875161", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWR8d5kbZb7YiQWKpT1J1PfMqNaGAmb4jBFx9DWag4hpSZ", - "publicKey": "e38c9f2760db006f070e9cc1bc1c2269ad033751adaa85d022fb760cbc5b5ef6" - }, - "ocrKeyBundle": { - "bundleID": "99fad0362cc8dc8a57a8e616e68133a6d5a8834e08a1b4819710f0e912df5abc", - "configPublicKey": "36de4924cf11938b4461aea1ce99cb640e9603d9a7c294ab6c54acd51d575a49", - "offchainPublicKey": "283471ed66d61fbe11f64eff65d738b59a0301c9a4f846280db26c64c9fdd3f8", - "onchainSigningAddress": "657587eb55cecd6f90b97297b611c3024e488cc0" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "WORKFLOW", - "OCR3_CAPABILITY" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - }, - { - "id": "814", - "name": "Chainlink Sepolia Prod Keystone Cap One 5", - "publicKey": "94e9ee398547f1564b8b5f72c6148e511919ed0e59b94ae848d63685108f2ab4", - "chainConfigs": [ - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0xbd1ee3165178D3A3E38458a9Fb1d6BF7fb5C443e", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWCiwWc97Q3Z9YUGZcAf46TMLg1uMvrEDa4gT6HZUFFCB1", - "publicKey": "2b2f46bf3b7ab2f39a7fec18166a6ebbc0a72209e920c33933f9adf07b101cc0" - }, - "ocrKeyBundle": { - "bundleID": "bf1736a09452daa0923f2c680f3fa6362ae652294e80ce72d923b304b0dcbb13", - "configPublicKey": "4ebd2a563c458485d2698d06142daa37ea2bee706b4a1a71c8435f2ec254506a", - "offchainPublicKey": "8577b96b270b36e74eb5d411caa14353cdadea599d6d6aa9cccf534ce31f1ef5", - "onchainSigningAddress": "b6727a31772b71d15e3120bfd618545292e1f9df" - }, - "plugins": {} - } - }, - { - "network": { - "id": "10", - "chainID": "43113", - "chainType": "EVM", - "name": "Avalanche Testnet (Fuji)" - }, - "accountAddress": "0x9b6284B5775E46fB02C1a589596EF07c35b55377", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWCiwWc97Q3Z9YUGZcAf46TMLg1uMvrEDa4gT6HZUFFCB1", - "publicKey": "2b2f46bf3b7ab2f39a7fec18166a6ebbc0a72209e920c33933f9adf07b101cc0" - }, - "ocrKeyBundle": { - "bundleID": "bf1736a09452daa0923f2c680f3fa6362ae652294e80ce72d923b304b0dcbb13", - "configPublicKey": "4ebd2a563c458485d2698d06142daa37ea2bee706b4a1a71c8435f2ec254506a", - "offchainPublicKey": "8577b96b270b36e74eb5d411caa14353cdadea599d6d6aa9cccf534ce31f1ef5", - "onchainSigningAddress": "b6727a31772b71d15e3120bfd618545292e1f9df" - }, - "plugins": {} - } - }, - { - "network": { - "id": "147", - "chainID": "84532", - "chainType": "EVM", - "name": "Base Testnet (Sepolia)" - }, - "accountAddress": "0xD83DCED517E4df64e913B97b3d0A906e4CA63d43", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWCiwWc97Q3Z9YUGZcAf46TMLg1uMvrEDa4gT6HZUFFCB1", - "publicKey": "2b2f46bf3b7ab2f39a7fec18166a6ebbc0a72209e920c33933f9adf07b101cc0" - }, - "ocrKeyBundle": { - "bundleID": "bf1736a09452daa0923f2c680f3fa6362ae652294e80ce72d923b304b0dcbb13", - "configPublicKey": "4ebd2a563c458485d2698d06142daa37ea2bee706b4a1a71c8435f2ec254506a", - "offchainPublicKey": "8577b96b270b36e74eb5d411caa14353cdadea599d6d6aa9cccf534ce31f1ef5", - "onchainSigningAddress": "b6727a31772b71d15e3120bfd618545292e1f9df" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0xFF1218066b4b5Cd9dE2A73639862082bcC98bf0D", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWCiwWc97Q3Z9YUGZcAf46TMLg1uMvrEDa4gT6HZUFFCB1", - "publicKey": "2b2f46bf3b7ab2f39a7fec18166a6ebbc0a72209e920c33933f9adf07b101cc0" - }, - "ocrKeyBundle": { - "bundleID": "bf1736a09452daa0923f2c680f3fa6362ae652294e80ce72d923b304b0dcbb13", - "configPublicKey": "4ebd2a563c458485d2698d06142daa37ea2bee706b4a1a71c8435f2ec254506a", - "offchainPublicKey": "8577b96b270b36e74eb5d411caa14353cdadea599d6d6aa9cccf534ce31f1ef5", - "onchainSigningAddress": "b6727a31772b71d15e3120bfd618545292e1f9df" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "OCR3_CAPABILITY", - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T20:38:35.588611Z" - }, - { - "id": "72", - "keys": [ - "keystone-04" - ], - "name": "Chainlink Keystone Node Operator 4", - "metadata": { - "nodeCount": 2, - "jobCount": 4 - }, - "nodes": [ - { - "id": "785", - "name": "Chainlink Sepolia Prod Keystone One 4", - "publicKey": "07e0ffc57b6263604df517b94bd986169451a3c90600a855bb19212dc575de54", - "chainConfigs": [ - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0x0be7Df958604166D9Bf0F727F0AC7A4Fb0f5B8a1", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWHqR1w26yHatTSZQW3xbRct9SxWzVj9X4SpU916Hy8jYg", - "publicKey": "77224be9d052343b1d17156a1e463625c0d746468d4f5a44cddd452365b1d4ed" - }, - "ocrKeyBundle": { - "bundleID": "8e563a16ec5a802345b162d0f31149e8d5055014a31847d7b20d6de500aa48bd", - "configPublicKey": "c812eab2415f45cc1d2afdb2be2e3ea419bb7851acfc30c07b4df42c856e8f74", - "offchainPublicKey": "2a4c7dec127fdd8145e48c5edb9467225098bd8c8ad1dade868325b787affbde", - "onchainSigningAddress": "a6f35436cb7bffd615cc47a0a04aa0a78696a144" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x6F5cAb24Fb7412bB516b3468b9F3a9c471d25fE5", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWHqR1w26yHatTSZQW3xbRct9SxWzVj9X4SpU916Hy8jYg", - "publicKey": "77224be9d052343b1d17156a1e463625c0d746468d4f5a44cddd452365b1d4ed" - }, - "ocrKeyBundle": { - "bundleID": "8e563a16ec5a802345b162d0f31149e8d5055014a31847d7b20d6de500aa48bd", - "configPublicKey": "c812eab2415f45cc1d2afdb2be2e3ea419bb7851acfc30c07b4df42c856e8f74", - "offchainPublicKey": "2a4c7dec127fdd8145e48c5edb9467225098bd8c8ad1dade868325b787affbde", - "onchainSigningAddress": "a6f35436cb7bffd615cc47a0a04aa0a78696a144" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "WORKFLOW", - "OCR3_CAPABILITY" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - }, - { - "id": "813", - "name": "Chainlink Sepolia Prod Keystone Cap One 4", - "publicKey": "a618fe2d3260151957d105d2dd593dddaad20c45dc6ae8eab265504e6585a02c", - "chainConfigs": [ - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0xE73E4D047DA32De40C7008075aEb9F60C8AF3C90", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWPMfQRpMy3wYzSMe3BLS8GFuC3fauk7FhTtgfbtp6T6jT", - "publicKey": "c92c6c81f3dff17c05577b9f87177d735d797a3ceedc0fa1395682dfbb66a8d2" - }, - "ocrKeyBundle": { - "bundleID": "fbcfd8420c2ebc450c81fcf72c6673fdd786702c881467e69817c20350bf819b", - "configPublicKey": "282a47a24fd976134f25a99f6370e072f228098010d2594d849d0a4c2788f878", - "offchainPublicKey": "1a7902a01e27818cda034637fdce603a265bc380934324b6f48cf23873234ec6", - "onchainSigningAddress": "7e799378dda3dcdc503233735f09150f0684be19" - }, - "plugins": {} - } - }, - { - "network": { - "id": "10", - "chainID": "43113", - "chainType": "EVM", - "name": "Avalanche Testnet (Fuji)" - }, - "accountAddress": "0x7501ff3462fd2133f2E1F93DB7Ec514988B43E56", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWPMfQRpMy3wYzSMe3BLS8GFuC3fauk7FhTtgfbtp6T6jT", - "publicKey": "c92c6c81f3dff17c05577b9f87177d735d797a3ceedc0fa1395682dfbb66a8d2" - }, - "ocrKeyBundle": { - "bundleID": "fbcfd8420c2ebc450c81fcf72c6673fdd786702c881467e69817c20350bf819b", - "configPublicKey": "282a47a24fd976134f25a99f6370e072f228098010d2594d849d0a4c2788f878", - "offchainPublicKey": "1a7902a01e27818cda034637fdce603a265bc380934324b6f48cf23873234ec6", - "onchainSigningAddress": "7e799378dda3dcdc503233735f09150f0684be19" - }, - "plugins": {} - } - }, - { - "network": { - "id": "147", - "chainID": "84532", - "chainType": "EVM", - "name": "Base Testnet (Sepolia)" - }, - "accountAddress": "0xef080765890a3F697C4920609621fe301Dd34A70", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWPMfQRpMy3wYzSMe3BLS8GFuC3fauk7FhTtgfbtp6T6jT", - "publicKey": "c92c6c81f3dff17c05577b9f87177d735d797a3ceedc0fa1395682dfbb66a8d2" - }, - "ocrKeyBundle": { - "bundleID": "fbcfd8420c2ebc450c81fcf72c6673fdd786702c881467e69817c20350bf819b", - "configPublicKey": "282a47a24fd976134f25a99f6370e072f228098010d2594d849d0a4c2788f878", - "offchainPublicKey": "1a7902a01e27818cda034637fdce603a265bc380934324b6f48cf23873234ec6", - "onchainSigningAddress": "7e799378dda3dcdc503233735f09150f0684be19" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x860235D5Db42eF568665900BBD6bA3DB2fA4f33f", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWPMfQRpMy3wYzSMe3BLS8GFuC3fauk7FhTtgfbtp6T6jT", - "publicKey": "c92c6c81f3dff17c05577b9f87177d735d797a3ceedc0fa1395682dfbb66a8d2" - }, - "ocrKeyBundle": { - "bundleID": "fbcfd8420c2ebc450c81fcf72c6673fdd786702c881467e69817c20350bf819b", - "configPublicKey": "282a47a24fd976134f25a99f6370e072f228098010d2594d849d0a4c2788f878", - "offchainPublicKey": "1a7902a01e27818cda034637fdce603a265bc380934324b6f48cf23873234ec6", - "onchainSigningAddress": "7e799378dda3dcdc503233735f09150f0684be19" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "OCR3_CAPABILITY", - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T20:39:26.24249Z" - }, - { - "id": "73", - "keys": [ - "keystone-03", - "keystone-bt-03" - ], - "name": "Chainlink Keystone Node Operator 3", - "metadata": { - "nodeCount": 3, - "jobCount": 5 - }, - "nodes": [ - { - "id": "786", - "name": "\tChainlink Sepolia Prod Keystone One 3", - "publicKey": "487901e0c0a9d3c66e7cfc50f3a9e3cdbfdf1b0107273d73d94a91d278545516", - "chainConfigs": [ - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0x3Be73A57a36E5ab00DcceD755B4bfF8bb99e52b2", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWCcVLytqinD8xMn27NvomcQhj2mqMVzyGemz6oPwv1SMT", - "publicKey": "298834a041a056df58c839cb53d99b78558693042e54dff238f504f16d18d4b6" - }, - "ocrKeyBundle": { - "bundleID": "8843b5db0608f92dac38ca56775766a08db9ee82224a19595d04bd6c58b38fbd", - "configPublicKey": "63375a3d175364bd299e7cecf352cb3e469dd30116cf1418f2b7571fb46c4a4b", - "offchainPublicKey": "b4c4993d6c15fee63800db901a8b35fa419057610962caab1c1d7bed55709127", - "onchainSigningAddress": "6607c140e558631407f33bafbabd103863cee876" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0xA9eFB53c513E413762b2Be5299D161d8E6e7278e", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWCcVLytqinD8xMn27NvomcQhj2mqMVzyGemz6oPwv1SMT", - "publicKey": "298834a041a056df58c839cb53d99b78558693042e54dff238f504f16d18d4b6" - }, - "ocrKeyBundle": { - "bundleID": "8843b5db0608f92dac38ca56775766a08db9ee82224a19595d04bd6c58b38fbd", - "configPublicKey": "63375a3d175364bd299e7cecf352cb3e469dd30116cf1418f2b7571fb46c4a4b", - "offchainPublicKey": "b4c4993d6c15fee63800db901a8b35fa419057610962caab1c1d7bed55709127", - "onchainSigningAddress": "6607c140e558631407f33bafbabd103863cee876" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "WORKFLOW", - "OCR3_CAPABILITY" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - }, - { - "id": "812", - "name": "Chainlink Sepolia Prod Keystone Cap One 3", - "publicKey": "f4cf97438c3ad86003e5c0368ab52c70f7fbb7f39ae0d7bf6dacbe16807e8a36", - "chainConfigs": [ - { - "network": { - "id": "147", - "chainID": "84532", - "chainType": "EVM", - "name": "Base Testnet (Sepolia)" - }, - "accountAddress": "0x646665317aF70313B3E83Ea1369A91de389DaCAe", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWAvLkcnc8Zttykk6gGeTWFiT6TqgovRHnb6Ym6QqjnLVM", - "publicKey": "1063921b717c3e32210d2803fe684cd818ea2a4a96e405373e5786c8a13c7600" - }, - "ocrKeyBundle": { - "bundleID": "5b46ab201ba66bd93bae6f41afc59c2e578e0f5682fbdf76e1b647fde6d6e8dd", - "configPublicKey": "a01d7d13f3e67ff84ff208cc44c923fe245d02d6029c91dc38422ef44f2bb26e", - "offchainPublicKey": "64eded06a47efc5e311799c1e1fa833cf78d17f079b2f6019c3247debe490439", - "onchainSigningAddress": "afca74e3b850a9435b2dc479ca8bc8e1b45dd0b2" - }, - "plugins": {} - } - }, - { - "network": { - "id": "10", - "chainID": "43113", - "chainType": "EVM", - "name": "Avalanche Testnet (Fuji)" - }, - "accountAddress": "0x3Ab2A4e4765A0374F727a9a9eCE893734e2928ec", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWAvLkcnc8Zttykk6gGeTWFiT6TqgovRHnb6Ym6QqjnLVM", - "publicKey": "1063921b717c3e32210d2803fe684cd818ea2a4a96e405373e5786c8a13c7600" - }, - "ocrKeyBundle": { - "bundleID": "5b46ab201ba66bd93bae6f41afc59c2e578e0f5682fbdf76e1b647fde6d6e8dd", - "configPublicKey": "a01d7d13f3e67ff84ff208cc44c923fe245d02d6029c91dc38422ef44f2bb26e", - "offchainPublicKey": "64eded06a47efc5e311799c1e1fa833cf78d17f079b2f6019c3247debe490439", - "onchainSigningAddress": "afca74e3b850a9435b2dc479ca8bc8e1b45dd0b2" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x9905E8C3A4f82037170a8c411CD8b11D4894066f", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWAvLkcnc8Zttykk6gGeTWFiT6TqgovRHnb6Ym6QqjnLVM", - "publicKey": "1063921b717c3e32210d2803fe684cd818ea2a4a96e405373e5786c8a13c7600" - }, - "ocrKeyBundle": { - "bundleID": "5b46ab201ba66bd93bae6f41afc59c2e578e0f5682fbdf76e1b647fde6d6e8dd", - "configPublicKey": "a01d7d13f3e67ff84ff208cc44c923fe245d02d6029c91dc38422ef44f2bb26e", - "offchainPublicKey": "64eded06a47efc5e311799c1e1fa833cf78d17f079b2f6019c3247debe490439", - "onchainSigningAddress": "afca74e3b850a9435b2dc479ca8bc8e1b45dd0b2" - }, - "plugins": {} - } - }, - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0x762354eC86ea2253F5da27FF8b952Cb7Dec52B6D", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWAvLkcnc8Zttykk6gGeTWFiT6TqgovRHnb6Ym6QqjnLVM", - "publicKey": "1063921b717c3e32210d2803fe684cd818ea2a4a96e405373e5786c8a13c7600" - }, - "ocrKeyBundle": { - "bundleID": "5b46ab201ba66bd93bae6f41afc59c2e578e0f5682fbdf76e1b647fde6d6e8dd", - "configPublicKey": "a01d7d13f3e67ff84ff208cc44c923fe245d02d6029c91dc38422ef44f2bb26e", - "offchainPublicKey": "64eded06a47efc5e311799c1e1fa833cf78d17f079b2f6019c3247debe490439", - "onchainSigningAddress": "afca74e3b850a9435b2dc479ca8bc8e1b45dd0b2" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "OCR3_CAPABILITY", - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T20:40:30.499914Z" - }, - { - "id": "74", - "keys": [ - "keystone-02", - "keystone-bt-02" - ], - "name": "Chainlink Keystone Node Operator 2", - "metadata": { - "nodeCount": 3, - "jobCount": 5 - }, - "nodes": [ - { - "id": "787", - "name": "Chainlink Sepolia Prod Keystone One 2", - "publicKey": "7a166fbc816eb4a4dcb620d11c3ccac5c085d56b1972374100116f87619debb8", - "chainConfigs": [ - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0x693bf95A3ef46E5dABe17d1A89dB1E83948aeD88", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWGDmBKZ7B3PynGrvfHTJMEecpjfHts9YK5NWk8oJuxcAo", - "publicKey": "5f247f61a6d5bfdd1d5064db0bd25fe443648133c6131975edb23481424e3d9c" - }, - "ocrKeyBundle": { - "bundleID": "1d20490fe469dd6af3d418cc310a6e835181fa13e8dc80156bcbe302b7afcd34", - "configPublicKey": "ee466234b3b2f65b13c848b17aa6a8d4e0aa0311d3bf8e77a64f20b04ed48d39", - "offchainPublicKey": "dba3c61e5f8bec594be481bcaf67ecea0d1c2950edb15b158ce3dbc77877def3", - "onchainSigningAddress": "d4dcc573e9d24a8b27a07bba670ba3a2ab36e5bb" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0xCea84bC1881F3cE14BA13Dc3a00DC1Ff3D553fF0", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWGDmBKZ7B3PynGrvfHTJMEecpjfHts9YK5NWk8oJuxcAo", - "publicKey": "5f247f61a6d5bfdd1d5064db0bd25fe443648133c6131975edb23481424e3d9c" - }, - "ocrKeyBundle": { - "bundleID": "1d20490fe469dd6af3d418cc310a6e835181fa13e8dc80156bcbe302b7afcd34", - "configPublicKey": "ee466234b3b2f65b13c848b17aa6a8d4e0aa0311d3bf8e77a64f20b04ed48d39", - "offchainPublicKey": "dba3c61e5f8bec594be481bcaf67ecea0d1c2950edb15b158ce3dbc77877def3", - "onchainSigningAddress": "d4dcc573e9d24a8b27a07bba670ba3a2ab36e5bb" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "WORKFLOW", - "OCR3_CAPABILITY" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - }, - { - "id": "811", - "name": "Chainlink Sepolia Prod Keystone Cap One 2", - "publicKey": "a1f112923513f13ede1ca8f982ea0ab6221d584b40cd57f0c82307ab79c0e69f", - "chainConfigs": [ - { - "network": { - "id": "10", - "chainID": "43113", - "chainType": "EVM", - "name": "Avalanche Testnet (Fuji)" - }, - "accountAddress": "0xbF1Ad47D99A65e230235537b47C8D1Dddb22FD53", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWQhLYuAxx4WDKafnuhZUTix8Y24gtB92vEUpAC4EdH4VA", - "publicKey": "dd1268a3e7ed4b9c83b1227e5bf2558e6b77af585c66e88a06f1164a1a94f8ed" - }, - "ocrKeyBundle": { - "bundleID": "a11d9438035564bfe84fcfb513b579edbe173fa26c00331e71a010d00b856037", - "configPublicKey": "407cab2a04fa868f645c6848a53abdb8136b08441c50b191651c4f1a348ee700", - "offchainPublicKey": "64a3215839e5630f12ae66b4363f40d82e9c981118c304ca0c4ca5fc2c6e1f37", - "onchainSigningAddress": "6579d77791ee8f8116495dbe6fa6586980177230" - }, - "plugins": {} - } - }, - { - "network": { - "id": "147", - "chainID": "84532", - "chainType": "EVM", - "name": "Base Testnet (Sepolia)" - }, - "accountAddress": "0xa8d4698f74a0A427c1b8ec4575d9dFdD17Be288c", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWQhLYuAxx4WDKafnuhZUTix8Y24gtB92vEUpAC4EdH4VA", - "publicKey": "dd1268a3e7ed4b9c83b1227e5bf2558e6b77af585c66e88a06f1164a1a94f8ed" - }, - "ocrKeyBundle": { - "bundleID": "a11d9438035564bfe84fcfb513b579edbe173fa26c00331e71a010d00b856037", - "configPublicKey": "407cab2a04fa868f645c6848a53abdb8136b08441c50b191651c4f1a348ee700", - "offchainPublicKey": "64a3215839e5630f12ae66b4363f40d82e9c981118c304ca0c4ca5fc2c6e1f37", - "onchainSigningAddress": "6579d77791ee8f8116495dbe6fa6586980177230" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0xf286c79b4a613a1fE480C8e4fB17B837E7D8ba03", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWQhLYuAxx4WDKafnuhZUTix8Y24gtB92vEUpAC4EdH4VA", - "publicKey": "dd1268a3e7ed4b9c83b1227e5bf2558e6b77af585c66e88a06f1164a1a94f8ed" - }, - "ocrKeyBundle": { - "bundleID": "a11d9438035564bfe84fcfb513b579edbe173fa26c00331e71a010d00b856037", - "configPublicKey": "407cab2a04fa868f645c6848a53abdb8136b08441c50b191651c4f1a348ee700", - "offchainPublicKey": "64a3215839e5630f12ae66b4363f40d82e9c981118c304ca0c4ca5fc2c6e1f37", - "onchainSigningAddress": "6579d77791ee8f8116495dbe6fa6586980177230" - }, - "plugins": {} - } - }, - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0xfe85A25cE2CB58b280CC0316305fC678Bf570f5e", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWQhLYuAxx4WDKafnuhZUTix8Y24gtB92vEUpAC4EdH4VA", - "publicKey": "dd1268a3e7ed4b9c83b1227e5bf2558e6b77af585c66e88a06f1164a1a94f8ed" - }, - "ocrKeyBundle": { - "bundleID": "a11d9438035564bfe84fcfb513b579edbe173fa26c00331e71a010d00b856037", - "configPublicKey": "407cab2a04fa868f645c6848a53abdb8136b08441c50b191651c4f1a348ee700", - "offchainPublicKey": "64a3215839e5630f12ae66b4363f40d82e9c981118c304ca0c4ca5fc2c6e1f37", - "onchainSigningAddress": "6579d77791ee8f8116495dbe6fa6586980177230" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "OCR3_CAPABILITY", - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T20:41:33.205484Z" - }, - { - "id": "75", - "keys": [ - "keystone-01", - "keystone-bt-01" - ], - "name": "Chainlink Keystone Node Operator 1", - "metadata": { - "nodeCount": 3, - "jobCount": 5 - }, - "nodes": [ - { - "id": "788", - "name": "Chainlink Sepolia Prod Keystone One 1", - "publicKey": "28b91143ec9111796a7d63e14c1cf6bb01b4ed59667ab54f5bc72ebe49c881be", - "chainConfigs": [ - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0xe45a754B30FdE9852A826F58c6bd94Fa6554CE96", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWCbDiL7sP9BVby5KaZqPpaVP1RBokoa9ShzH5WhkYX46v", - "publicKey": "2934f31f278e5c60618f85861bd6add54a4525d79a642019bdc87d75d26372c3" - }, - "ocrKeyBundle": { - "bundleID": "7a9b75510b8d09932b98142419bef52436ff725dd9395469473b487ef87fdfb0", - "configPublicKey": "2c45fec2320f6bcd36444529a86d9f8b4439499a5d8272dec9bcbbebb5e1bf01", - "offchainPublicKey": "255096a3b7ade10e29c648e0b407fc486180464f713446b1da04f013df6179c8", - "onchainSigningAddress": "8258f4c4761cc445333017608044a204fd0c006a" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x415aa1E9a1bcB3929ed92bFa1F9735Dc0D45AD31", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWCbDiL7sP9BVby5KaZqPpaVP1RBokoa9ShzH5WhkYX46v", - "publicKey": "2934f31f278e5c60618f85861bd6add54a4525d79a642019bdc87d75d26372c3" - }, - "ocrKeyBundle": { - "bundleID": "7a9b75510b8d09932b98142419bef52436ff725dd9395469473b487ef87fdfb0", - "configPublicKey": "2c45fec2320f6bcd36444529a86d9f8b4439499a5d8272dec9bcbbebb5e1bf01", - "offchainPublicKey": "255096a3b7ade10e29c648e0b407fc486180464f713446b1da04f013df6179c8", - "onchainSigningAddress": "8258f4c4761cc445333017608044a204fd0c006a" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "WORKFLOW", - "OCR3_CAPABILITY" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - }, - { - "id": "810", - "name": "Chainlink Sepolia Prod Keystone Cap One 1", - "publicKey": "9ef27cd1855a0ed6932be33c80d7cd9c178307e5a240dbeb9055946359dc5d7f", - "chainConfigs": [ - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0xBB465BCa1b289269F2a95a36f5B6fD006Af56ede", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWMNg1a7HvNWuHAPMdveWr1J6NNCVBU1Z4w5swzepT5Wvf", - "publicKey": "abb750e04bee21d830c6ce0f08180853466139fc6055c6737614797c0704d59c" - }, - "ocrKeyBundle": { - "bundleID": "0d176a4c2d68c619d237e419c31a030e5b2162ee031baa8ebc8472623da9b067", - "configPublicKey": "43e4dbf80a9c818a7d35c080f61b6f8f9b175fa1217b1d01168140da75322d5c", - "offchainPublicKey": "707db88237aaaaddc22bf0fe914540ea7b8bbfbe5cf88349cabb26e34762237c", - "onchainSigningAddress": "ac08f52ec257ddbb493e7b9e299dd2c166a7f090" - }, - "plugins": {} - } - }, - { - "network": { - "id": "10", - "chainID": "43113", - "chainType": "EVM", - "name": "Avalanche Testnet (Fuji)" - }, - "accountAddress": "0x5e3618cFF8Ab337b3c73c2775d1a2EC65e5abEF0", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWMNg1a7HvNWuHAPMdveWr1J6NNCVBU1Z4w5swzepT5Wvf", - "publicKey": "abb750e04bee21d830c6ce0f08180853466139fc6055c6737614797c0704d59c" - }, - "ocrKeyBundle": { - "bundleID": "0d176a4c2d68c619d237e419c31a030e5b2162ee031baa8ebc8472623da9b067", - "configPublicKey": "43e4dbf80a9c818a7d35c080f61b6f8f9b175fa1217b1d01168140da75322d5c", - "offchainPublicKey": "707db88237aaaaddc22bf0fe914540ea7b8bbfbe5cf88349cabb26e34762237c", - "onchainSigningAddress": "ac08f52ec257ddbb493e7b9e299dd2c166a7f090" - }, - "plugins": {} - } - }, - { - "network": { - "id": "147", - "chainID": "84532", - "chainType": "EVM", - "name": "Base Testnet (Sepolia)" - }, - "accountAddress": "0x1796BbC2AbbAd5660C8a7812b313E1f48A99f1D1", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWMNg1a7HvNWuHAPMdveWr1J6NNCVBU1Z4w5swzepT5Wvf", - "publicKey": "abb750e04bee21d830c6ce0f08180853466139fc6055c6737614797c0704d59c" - }, - "ocrKeyBundle": { - "bundleID": "0d176a4c2d68c619d237e419c31a030e5b2162ee031baa8ebc8472623da9b067", - "configPublicKey": "43e4dbf80a9c818a7d35c080f61b6f8f9b175fa1217b1d01168140da75322d5c", - "offchainPublicKey": "707db88237aaaaddc22bf0fe914540ea7b8bbfbe5cf88349cabb26e34762237c", - "onchainSigningAddress": "ac08f52ec257ddbb493e7b9e299dd2c166a7f090" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0xA2bfAc45e6878fbE04525C23dFbb11fFb224Ea60", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWMNg1a7HvNWuHAPMdveWr1J6NNCVBU1Z4w5swzepT5Wvf", - "publicKey": "abb750e04bee21d830c6ce0f08180853466139fc6055c6737614797c0704d59c" - }, - "ocrKeyBundle": { - "bundleID": "0d176a4c2d68c619d237e419c31a030e5b2162ee031baa8ebc8472623da9b067", - "configPublicKey": "43e4dbf80a9c818a7d35c080f61b6f8f9b175fa1217b1d01168140da75322d5c", - "offchainPublicKey": "707db88237aaaaddc22bf0fe914540ea7b8bbfbe5cf88349cabb26e34762237c", - "onchainSigningAddress": "ac08f52ec257ddbb493e7b9e299dd2c166a7f090" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "OCR3_CAPABILITY", - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T20:42:05.709664Z" - }, - { - "id": "76", - "keys": [ - "keystone-00", - "keystone-bt-00" - ], - "name": "Chainlink Keystone Node Operator 0", - "metadata": { - "nodeCount": 3, - "jobCount": 5 - }, - "nodes": [ - { - "id": "789", - "name": "Chainlink Sepolia Prod Keystone One 0", - "publicKey": "403b72f0b1b3b5f5a91bcfedb7f28599767502a04b5b7e067fcf3782e23eeb9c", - "chainConfigs": [ - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0x1a04C6b4b1A45D20356F93DcE7931F765955BAa7", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWMWUKdoAc2ruZf9f55p7NVFj7AFiPm67xjQ8BZBwkqyYv", - "publicKey": "adb6bf005cdb23f21e11b82d66b9f62628c2939640ed93028bf0dad3923c5a8b" - }, - "ocrKeyBundle": { - "bundleID": "665a101d79d310cb0a5ebf695b06e8fc8082b5cbe62d7d362d80d47447a31fea", - "configPublicKey": "5193f72fc7b4323a86088fb0acb4e4494ae351920b3944bd726a59e8dbcdd45f", - "offchainPublicKey": "03dacd15fc96c965c648e3623180de002b71a97cf6eeca9affb91f461dcd6ce1", - "onchainSigningAddress": "b35409a8d4f9a18da55c5b2bb08a3f5f68d44442" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x2877F08d9c5Cc9F401F730Fa418fAE563A9a2FF3", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWMWUKdoAc2ruZf9f55p7NVFj7AFiPm67xjQ8BZBwkqyYv", - "publicKey": "adb6bf005cdb23f21e11b82d66b9f62628c2939640ed93028bf0dad3923c5a8b" - }, - "ocrKeyBundle": { - "bundleID": "665a101d79d310cb0a5ebf695b06e8fc8082b5cbe62d7d362d80d47447a31fea", - "configPublicKey": "5193f72fc7b4323a86088fb0acb4e4494ae351920b3944bd726a59e8dbcdd45f", - "offchainPublicKey": "03dacd15fc96c965c648e3623180de002b71a97cf6eeca9affb91f461dcd6ce1", - "onchainSigningAddress": "b35409a8d4f9a18da55c5b2bb08a3f5f68d44442" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "WORKFLOW", - "OCR3_CAPABILITY" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - }, - { - "id": "809", - "name": "Chainlink Sepolia Prod Keystone Cap One 0", - "publicKey": "545197637db59b96b22528ff90960b9e7cdcea81c8a5a9f06ae6b728bcba35cb", - "chainConfigs": [ - { - "network": { - "id": "10", - "chainID": "43113", - "chainType": "EVM", - "name": "Avalanche Testnet (Fuji)" - }, - "accountAddress": "0x66a88b0a23D8351e8F5e228eEe8439e65F423842", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWFux8Vvs8CPfUSKitXwQsq81ZBhQYcbKRH5L5jkFbQ6nH", - "publicKey": "5a946cfec8e3c33f6c88961dcab2bbd8bb9d05538c8f931bb62d59b1d7fd782e" - }, - "ocrKeyBundle": { - "bundleID": "d9a3c3afdb310ba11b058afd6ee3159edfbc740df4daefd65c257a7ed46ed9ef", - "configPublicKey": "64fd95e7bcbb33e3dd548247352bb7be5ea6577a840e5e3b66336f710b5b272e", - "offchainPublicKey": "216b1e3dc51ad21be806c010397cc2e0bf59b2a06ade89bc7d0c0a7299a4e01e", - "onchainSigningAddress": "a4f0acbe902443aa842db278f421da99cdc47a8b" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x36a46774A3743641D4C274b385608Cb455B5B6b8", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWFux8Vvs8CPfUSKitXwQsq81ZBhQYcbKRH5L5jkFbQ6nH", - "publicKey": "5a946cfec8e3c33f6c88961dcab2bbd8bb9d05538c8f931bb62d59b1d7fd782e" - }, - "ocrKeyBundle": { - "bundleID": "d9a3c3afdb310ba11b058afd6ee3159edfbc740df4daefd65c257a7ed46ed9ef", - "configPublicKey": "64fd95e7bcbb33e3dd548247352bb7be5ea6577a840e5e3b66336f710b5b272e", - "offchainPublicKey": "216b1e3dc51ad21be806c010397cc2e0bf59b2a06ade89bc7d0c0a7299a4e01e", - "onchainSigningAddress": "a4f0acbe902443aa842db278f421da99cdc47a8b" - }, - "plugins": {} - } - }, - { - "network": { - "id": "147", - "chainID": "84532", - "chainType": "EVM", - "name": "Base Testnet (Sepolia)" - }, - "accountAddress": "0x868ab67c00fF7e21aFf470C066798e5bE4240305", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWFux8Vvs8CPfUSKitXwQsq81ZBhQYcbKRH5L5jkFbQ6nH", - "publicKey": "5a946cfec8e3c33f6c88961dcab2bbd8bb9d05538c8f931bb62d59b1d7fd782e" - }, - "ocrKeyBundle": { - "bundleID": "d9a3c3afdb310ba11b058afd6ee3159edfbc740df4daefd65c257a7ed46ed9ef", - "configPublicKey": "64fd95e7bcbb33e3dd548247352bb7be5ea6577a840e5e3b66336f710b5b272e", - "offchainPublicKey": "216b1e3dc51ad21be806c010397cc2e0bf59b2a06ade89bc7d0c0a7299a4e01e", - "onchainSigningAddress": "a4f0acbe902443aa842db278f421da99cdc47a8b" - }, - "plugins": {} - } - }, - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0xa60bC482fCfcd12B752541a00555E4e448Bc1d16", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWFux8Vvs8CPfUSKitXwQsq81ZBhQYcbKRH5L5jkFbQ6nH", - "publicKey": "5a946cfec8e3c33f6c88961dcab2bbd8bb9d05538c8f931bb62d59b1d7fd782e" - }, - "ocrKeyBundle": { - "bundleID": "d9a3c3afdb310ba11b058afd6ee3159edfbc740df4daefd65c257a7ed46ed9ef", - "configPublicKey": "64fd95e7bcbb33e3dd548247352bb7be5ea6577a840e5e3b66336f710b5b272e", - "offchainPublicKey": "216b1e3dc51ad21be806c010397cc2e0bf59b2a06ade89bc7d0c0a7299a4e01e", - "onchainSigningAddress": "a4f0acbe902443aa842db278f421da99cdc47a8b" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "OCR3_CAPABILITY", - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T20:42:49.446864Z" - }, - { - "id": "81", - "keys": [ - "cl-df-asset-don-testnet-0" - ], - "name": "Chainlink Keystone Asset DON Node Operator 0", - "metadata": { - "nodeCount": 2, - "jobCount": 18 - }, - "nodes": [ - { - "id": "831", - "name": "Chainlink Sepolia Prod Keystone Asset Node 0", - "publicKey": "d791dad33f1aeff811f3364088993053d5d08fa595ba48f73aecd4ee2d5035a1", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0xe826b8D7f57b1c08E2d0C9477006244AECB280c3", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWDh47EiK5TzG4yApEEwLecgRkqZKQif3fcnsztfhQNzNh", - "publicKey": "398f42d12c7f3445341e42ce4ea555c87d84db68c808c76a0655e5d993d7a2a6" - }, - "ocrKeyBundle": { - "bundleID": "c8dee638c00194cf38bd0c30306fffd14b561601828085ceaaf0ab5fe451ec23", - "configPublicKey": "dbd5d1f5aa4921fd1e7b16f26dc75aff5cc08fee6e74324e947654ba78791e7e", - "offchainPublicKey": "66a599cda37e6fb5dc50e16d7c81e6967e010a25bbeaabf20752e228a26f5bc3", - "onchainSigningAddress": "9184c1c20da57f2f747a60909d0152c289e8518f" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:19:34.127102Z" - }, - { - "id": "82", - "keys": [ - "cl-df-asset-don-testnet-1" - ], - "name": "Chainlink Keystone Asset DON Node Operator 1", - "metadata": { - "nodeCount": 1, - "jobCount": 9 - }, - "nodes": [ - { - "id": "832", - "name": "Chainlink Sepolia Prod Keystone Asset Node 1", - "publicKey": "eb410038ba7847a729c4e40c1d4afdbcce9ad33cc71e459883cd98f0883a5366", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0xCE154165b0d60D1efA9b3c7a172ED77712Cb82f9", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWG7WEsQjxXQdn5WAEQSDh77qxjMoWxz3rGYrRC9pPB7qx", - "publicKey": "5d8a1f11ecd0cd2cdd95fec35b8ea6386af567bc96aa2c2ea47e91d22b1f12bf" - }, - "ocrKeyBundle": { - "bundleID": "a6dda044db7fa1fa652ec9ff60a44fb31ee99d33db35599848b21e34ce33c343", - "configPublicKey": "586fb9935401e8907ead91e7a3423a0c0676d4669bac619f71c99913e14b362a", - "offchainPublicKey": "9557c0c4c6c8aeb41ecaa84f0aa7d0e1be7ffa9e4a08da27b23bd64b2d0c0fe9", - "onchainSigningAddress": "bd3e16dda612f543c0f79fafc03fa35f3f300e30" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:19:48.159926Z" - }, - { - "id": "83", - "keys": [ - "cl-df-asset-don-testnet-2" - ], - "name": "Chainlink Keystone Asset DON Node Operator 2", - "metadata": { - "nodeCount": 1, - "jobCount": 9 - }, - "nodes": [ - { - "id": "833", - "name": "Chainlink Sepolia Prod Keystone Asset Node 2", - "publicKey": "daf14b79caa585c3dacf550688aeed5371f8fd39cbfb6e33add2fb82538626b0", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0xbb16a69A7bb8778dc52a2D081EE1B2Dde0237F3b", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWBWms38viHaptUHTXXNdN4Qm2ZxDWtuaZviZtq1WzWWcq", - "publicKey": "1935b60309f79e7fd1bfd4736df5729b7532bcd435be2a707dd28519e9ae6e6a" - }, - "ocrKeyBundle": { - "bundleID": "9c63a332ff254cd2cda8bcf2c3f0e46ee95d4991595019619a0c60907437d98c", - "configPublicKey": "29b9b6f61db8e72df13e17e274bdf5450987953079b9dee2745f2d288dc7e86d", - "offchainPublicKey": "c3b08d0b68baf68da2c8446f6a9dc552af3ab2014b900d75ca9e2122b6fc9eb0", - "onchainSigningAddress": "cb66494d66922ad00708bce7c83ada133ddb8994" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:20:01.151494Z" - }, - { - "id": "84", - "keys": [ - "cl-df-asset-don-testnet-3" - ], - "name": "Chainlink Keystone Asset DON Node Operator 3", - "metadata": { - "nodeCount": 1, - "jobCount": 9 - }, - "nodes": [ - { - "id": "834", - "name": "Chainlink Sepolia Prod Keystone Asset Node 3", - "publicKey": "0e1f9462a8b326d746fde2d5016faa9f2e017f7e6e5969aaf3281519d2e31dbc", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0xA64f65e0c12ab015792c34867BE5b80b4D4C551A", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWMhHZTVHz23gCQAEzFyeBLxR9ghVqMQHk18VND4TbAc1U", - "publicKey": "b07bf77b2b1d8964915d4871b4cd0173e13bc1d0590731a8969393a6e80aef8f" - }, - "ocrKeyBundle": { - "bundleID": "87770ad41d54661a6dee424612f4338b49cd4fd20bdab1f11c308c76efeb56f8", - "configPublicKey": "dd0edc91d1476a0a4c554e8fe8050dadba679ba42f53973bf181d85eed1b6821", - "offchainPublicKey": "2ba2cc779c8e1460d9ff823d594708a344bb7a9d84aa3aa3833d539852511a88", - "onchainSigningAddress": "5e5b1a602c5a79ec6cdeb67e6f855d58061f785f" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:20:10.382565Z" - }, - { - "id": "85", - "keys": [ - "cl-df-asset-don-testnet-4" - ], - "name": "Chainlink Keystone Asset DON Node Operator 4", - "metadata": { - "nodeCount": 1, - "jobCount": 9 - }, - "nodes": [ - { - "id": "835", - "name": "Chainlink Sepolia Prod Keystone Asset Node 4", - "publicKey": "1d5f6ef3443e48bd471efdb47a5b9c6c900a14f35253c2b562908186f5b8b457", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x7284bBa5C8090Ac99d55b14db015a291C017275c", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWMrkkbkFYJydLhcYKr8AnxNcNGmwfVXMQGdn8uoSpYoJs", - "publicKey": "b2e8f0b25c7334e8082cb82eee29bc4f48ae086b8fe4a2fd5eb4e08195a0e06c" - }, - "ocrKeyBundle": { - "bundleID": "1ceac31d893d21e95a62419d94b1a88805fa4f056b1636ccd79ab0ca8b4fe68c", - "configPublicKey": "4c94f49461fd0fd9d4da5cda4590a2cf80fba2ea27c422b92ee18a3aaaa51321", - "offchainPublicKey": "d1649b393614e01811979340d2726280f9ea57fd7a1ee28958adbbaf71b41bf5", - "onchainSigningAddress": "e47d17607054e9899d3fb7fa5b4b3e01b85b8fc9" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:20:21.050174Z" - }, - { - "id": "86", - "keys": [ - "cl-df-asset-don-testnet-5" - ], - "name": "Chainlink Keystone Asset DON Node Operator 5", - "metadata": { - "nodeCount": 1, - "jobCount": 9 - }, - "nodes": [ - { - "id": "837", - "name": "Chainlink Sepolia Prod Keystone Asset Node 5", - "publicKey": "d87dfbb7444036e0654578afdb11864e31a0de1824ca2780f24b16116a85463d", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x6c75DB65540ca889803a092d4C1497D3337cDE30", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWH8q69DtEqahJdwKfYXnkRHHH6E4jTqevZSAZzGsrnsTB", - "publicKey": "6cbcb3cc0a48ec9d94bb1424beea5e1b7cf57fda2dbfc519afd9221cbeac3b8e" - }, - "ocrKeyBundle": { - "bundleID": "6e088c00e61fea95a5a808a56e7e55c58ec0d61c3207383a2c63abc705bd120c", - "configPublicKey": "0728ce40c95155853ecd31bc213ed2b39d4ecf2e62dc95334f008181ad010848", - "offchainPublicKey": "521d4c291fe8ef245b2e497982b0a07127cd3c65439a10784d914e03ba24328d", - "onchainSigningAddress": "d32a6ed4be6656fd988a0e43e71ce43fab3faba4" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:21:21.831183Z" - }, - { - "id": "87", - "keys": [ - "cl-df-asset-don-testnet-6" - ], - "name": "Chainlink Keystone Asset DON Node Operator 6", - "metadata": { - "nodeCount": 1, - "jobCount": 9 - }, - "nodes": [ - { - "id": "838", - "name": "Chainlink Sepolia Prod Keystone Asset Node 6", - "publicKey": "294f58723d4049af0dcd63eedfcda957287401a10070db509ede7a799bb70654", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0xa2788731913cc2deBC061F8594AEaa8e99B4FCCE", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWD7URmTzSeotMvEzkJTiFrwUHhcGMBeaS9GY8763Sqqnf", - "publicKey": "30f502f9fb19b54e8644f038f57f9a43582f76b86bace61759fff12886ccf1a8" - }, - "ocrKeyBundle": { - "bundleID": "57bc2a8a62ed96e6aa7b9bbe56f93abeef938a1766cb8a6d18e42ebf71101646", - "configPublicKey": "36c882b0cdcec84aa85f00ea43cd31254406cec84d31f6dded69b4fbb3f17449", - "offchainPublicKey": "46951e1e18cee25cd417b3fa7feb25fb53623a249e1c09491bb978dccc2ea76e", - "onchainSigningAddress": "abcd8be3952a84fb10947dbeb768a255ead58ca2" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:21:34.93501Z" - }, - { - "id": "88", - "keys": [ - "cl-df-asset-don-testnet-7" - ], - "name": "Chainlink Keystone Asset DON Node Operator 7", - "metadata": { - "nodeCount": 1, - "jobCount": 9 - }, - "nodes": [ - { - "id": "839", - "name": "Chainlink Sepolia Prod Keystone Asset Node 7", - "publicKey": "55b0ec5d90de973c00efce233334a9d3c5a94062ea010575bb248eb6804a9cfe", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x14dAF00DaD855089A6586690d5C1fD2779302736", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWBbo44H5CLACV3yGyDWrtMuSWRdN5sQcDsnPC4WfLr6Jo", - "publicKey": "1a7ef5e7420434fcf06de3d15a0191f7499e00e15427679616ce800779ceb514" - }, - "ocrKeyBundle": { - "bundleID": "f87acde2c1c21e8859d84813034d84a3f3bb1d49596e13ac66731d50750b9436", - "configPublicKey": "e75f21bc1dc6eac12358277caf18a216ed54f8dc84285941ef1f5fb1047f8d5b", - "offchainPublicKey": "c7b86dfbdf31a3b13c44305cd6fc88c402653198201006083414223ffc36950d", - "onchainSigningAddress": "93fbb113f191959f8ab5e052395676e0038f2f1f" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:21:45.063449Z" - }, - { - "id": "89", - "keys": [ - "cl-df-asset-don-testnet-8" - ], - "name": "Chainlink Keystone Asset DON Node Operator 8", - "metadata": { - "nodeCount": 1, - "jobCount": 9 - }, - "nodes": [ - { - "id": "840", - "name": "Chainlink Sepolia Prod Keystone Asset Node 8", - "publicKey": "8f9f327ac7ad823a0f3297f3505591bcd40adc8fb1309f99874c26663cbd5914", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0xb0C0168905C07F00A141494eaeFc0bD9F153fc16", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWGVroAehJh33SBns9MohmctNPZSDh89KRQM1J6TSCnT1v", - "publicKey": "63442493270891409900afd3bb868d03fd07c775bb38c56e56a624b674a68b35" - }, - "ocrKeyBundle": { - "bundleID": "4413e0a3080c3dfa7709b16c3ee68c04359e2dd66d107fd3be6ba7c615c4b3b6", - "configPublicKey": "8f3975b19fc6f02e241119b2132331ed9ed0d19221bd0cfd6f54b5859090a741", - "offchainPublicKey": "f4f182c889668d8951932c49e1ffb1252b8a33a9875d3f19aea7bb805b65c7a6", - "onchainSigningAddress": "b257e9efe637f38b5462a170737571ea0f0e2e05" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:21:55.09098Z" - }, - { - "id": "90", - "keys": [ - "cl-df-asset-don-testnet-9" - ], - "name": "Chainlink Keystone Asset DON Node Operator 9", - "metadata": { - "nodeCount": 1, - "jobCount": 9 - }, - "nodes": [ - { - "id": "841", - "name": "Chainlink Sepolia Prod Keystone Asset Node 9", - "publicKey": "1d79884071dfec1f39dc62f4868f4a143ae39cb03ad9d14142b184686c2b5a93", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x2F5E08a5b9D893e9dA2d68Ef605fBa6f8Ebfd0cB", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWEBn9tWmMWrSxRZe2VQ56RcSHRUPdcFoD3Ep88wqTT9zP", - "publicKey": "40eb109d9f28e8754dfff419a9175d6714405907413d2f77657355721c3b2bd0" - }, - "ocrKeyBundle": { - "bundleID": "6d4da72b1daad0b9ea47a7daa6cde81c1608b7bd199c05b18b989d10c5d7b99e", - "configPublicKey": "7e1c66bfa23c270770401d0dd739adad5a52827ecb40a0668f7e014d53f38059", - "offchainPublicKey": "712561a10b1f7dd96f0ae0f0d3e6cdf83fdd0837d333cf9bbae0090126ae7f39", - "onchainSigningAddress": "2ef8cea7dae7bd1e876a59a44ca59b89adf8abb4" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:22:09.476108Z" - }, - { - "id": "91", - "keys": [ - "cl-df-asset-don-testnet-10" - ], - "name": "Chainlink Keystone Asset DON Node Operator 10", - "metadata": { - "nodeCount": 1, - "jobCount": 9 - }, - "nodes": [ - { - "id": "842", - "name": "Chainlink Sepolia Prod Keystone Asset Node 10", - "publicKey": "cf6c47ad934518f5947ce8f1a48c2df8c93bd585788a3a82229fd4d723efa706", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x4794743bB8f159954Efa31642609ebfD4D2b9EdC", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWNXZCbQe4Ao7KEciJGY6Ec4oZLZNGcMTPyZ7XpFhLPyLo", - "publicKey": "bcd987b3b2b20d9effe30598850ddfd33023339dab012c4aee4cdc4246111bfc" - }, - "ocrKeyBundle": { - "bundleID": "a8d9929327d89cfabd8c583d250dfddbc14e947e9253f7471191886ca5197786", - "configPublicKey": "a1a390e756bce818d1786dca6ba3e45013085087e5a3be6253d8bbbd6479255a", - "offchainPublicKey": "76522fec251ce6130c03a816025f2054eb3ac83b7d30347f42b73a77e7b9a511", - "onchainSigningAddress": "179d48901e5e9c3c11dd947c001f8a2ee887c8eb" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:22:30.732346Z" - }, - { - "id": "92", - "keys": [ - "cl-df-asset-don-testnet-11" - ], - "name": "Chainlink Keystone Asset DON Node Operator 11", - "metadata": { - "nodeCount": 1, - "jobCount": 9 - }, - "nodes": [ - { - "id": "843", - "name": "Chainlink Sepolia Prod Keystone Asset Node 11", - "publicKey": "c239c23670224558a64ea3165eae8d67a17b75b1874fbccf8a4dd98e953820ad", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x27AFd92F391dFD7BA1bbC89e3bd13ceC9A667c11", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWSSzLfwq7QSdJcpDLFiBznA1XR58dwg1xre4b88SbP7VF", - "publicKey": "f71ccc7f7b73f1499f72987679a94a11e8564f01415acdb958c008c5bfe21eae" - }, - "ocrKeyBundle": { - "bundleID": "3e691b13aa702631fba25f6e128a566bdff3982cc3438af29acc2a819b9d6e02", - "configPublicKey": "149d81dce137d0874b477ad6c19dc72801f335200622fa34f1c660623febed22", - "offchainPublicKey": "b0d0d8e3c62abc7236e6539413ef82e568dd24f0c39ff6e8e2babe513590a522", - "onchainSigningAddress": "a0f2feab4d03899eb2e830bd4abc3fd5babef3e1" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:22:42.314654Z" - }, - { - "id": "93", - "keys": [ - "cl-df-asset-don-testnet-12" - ], - "name": "Chainlink Keystone Asset DON Node Operator 12", - "metadata": { - "nodeCount": 1, - "jobCount": 9 - }, - "nodes": [ - { - "id": "844", - "name": "Chainlink Sepolia Prod Keystone Asset Node 12", - "publicKey": "71b29eb63daa6ac2e48b46669936eff5606879b102bae78afc929554c435dd0b", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x13d5b27d71B4C4697874177Ff43DEB1884Cff49e", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWT1LMqEW51UfxBynzjYjuybQzVkmf4rH9js9e16QAbU3X", - "publicKey": "ff66057a6c96779134a6527364cddcce43b69e3d1820f59dde5e6b38d1d32fde" - }, - "ocrKeyBundle": { - "bundleID": "4854ee3fc7ac4591eea33c5d0d1cefd4ad819d2c374a2f86267a9999228a967a", - "configPublicKey": "470225644f274147b5b80c862a3f3cd7a19fed4ff915e9c18ac80e06003ecc6a", - "offchainPublicKey": "e7d89e196f5f6d92f4c42ab34f9a2f21f3201314be65b819872c4609b87866c7", - "onchainSigningAddress": "c84f2f60ccb1d7e6c6e4ae4bc3cab8bb85db8977" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:22:52.838595Z" - }, - { - "id": "94", - "keys": [ - "cl-df-asset-don-testnet-13" - ], - "name": "Chainlink Keystone Asset DON Node Operator 13", - "metadata": { - "nodeCount": 1, - "jobCount": 9 - }, - "nodes": [ - { - "id": "845", - "name": "Chainlink Sepolia Prod Keystone Asset Node 13", - "publicKey": "c098264a552125355804b903de06400621f2d1de357c2bed94586727fe8a3502", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x5647A091F2a09915c1C0F6ac95630Be87114881F", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWRjg2KoP6jKVWU2BczeduWsdnfN69tHN2YGEAGtETvc9P", - "publicKey": "ec87467a512f8218bb63f7fcf46cf0b8fd8ebb14bd5f3b670908d505a5af801a" - }, - "ocrKeyBundle": { - "bundleID": "20626049a1e24912a14d186645ba70fea4860efcc987b3ec7c9ddc881b5057db", - "configPublicKey": "d84d4653db0caca062d4058e9937ae618a53bbd1b41a673c5f13bebc24e7aa3a", - "offchainPublicKey": "156c8ab52099386377fe27bbd50dafa368ff2790245f1407579f590b0bae7a1e", - "onchainSigningAddress": "4f4b7bff5d32d62326b575d8c951d34e54888e31" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:23:19.587619Z" - }, - { - "id": "95", - "keys": [ - "cl-df-asset-don-testnet-14" - ], - "name": "Chainlink Keystone Asset DON Node Operator 14", - "metadata": { - "nodeCount": 1, - "jobCount": 9 - }, - "nodes": [ - { - "id": "846", - "name": "Chainlink Sepolia Prod Keystone Asset Node 14", - "publicKey": "12681ec137cd2d25e7c71638f564404dd764061921c870bbcddf683d048eed21", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x0419E70d32c3972930c99aaaDF20dCB473c56d22", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWCdEG68z5kwYuD1xp1aJsFBtpw2HYh1K3ffVM6keVrJnT", - "publicKey": "29b8bafebdef5e11ec3556fbcacdfb626d2f80cf178406e38664775e8b1ace78" - }, - "ocrKeyBundle": { - "bundleID": "80b1304898d5cea3c684790a0f01158468c7fa7770675edef33e4b137232ddc9", - "configPublicKey": "15552ecb6ff10103a534f02594a7b7cbab686d76d5e7b32a9c67059e8c856861", - "offchainPublicKey": "b561b7df3bdfe70f1af9395dbc00ef796774aa352c9a30d9c7e2f7e74d438073", - "onchainSigningAddress": "fb1ca65bf473b4443d7359becc0de67a2d96228d" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:23:44.73219Z" - }, - { - "id": "96", - "keys": [ - "cl-df-asset-don-testnet-15" - ], - "name": "Chainlink Keystone Asset DON Node Operator 15", - "metadata": { - "nodeCount": 1, - "jobCount": 9 - }, - "nodes": [ - { - "id": "847", - "name": "Chainlink Sepolia Prod Keystone Asset Node 15", - "publicKey": "a9a5d084f9cbbbd291eb43c33dd137cd6140e33c53cebb260463bf52795ec579", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x931900764a585D7a01e500976B630B4747216c8c", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWQyZ9A9ScBpcoRww1gJVBNB2brNkjJhaqze6ehuv6bmfQ", - "publicKey": "e139f020ae4bc9efaa77da9cfd54339d36176479028f849b9e64ad2cf29acba3" - }, - "ocrKeyBundle": { - "bundleID": "5c1c69eb1d6619b2c9b93bdfdd9c1b87c28101d6fc88bf7979ad52ceda459908", - "configPublicKey": "33f2107ab22b3dd5c19d5de0c5b1e6e038f2275ba455eed7997485caec421925", - "offchainPublicKey": "bb91b077c135cbdd1f4422c6021cf56d78326710c8bb8c4a87b3e7415e48915f", - "onchainSigningAddress": "b94e3de607033d03e3f0cc3ef1f09edd2592b440" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:24:01.875231Z" - } -] \ No newline at end of file diff --git a/deployment/environment/clo/utils.go b/deployment/environment/clo/utils.go deleted file mode 100644 index 67be141a6db..00000000000 --- a/deployment/environment/clo/utils.go +++ /dev/null @@ -1,101 +0,0 @@ -package clo - -import ( - "fmt" - - jd "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" - "github.com/smartcontractkit/chainlink/deployment/environment/clo/models" -) - -// NewChainConfig creates a new JobDistributor ChainConfig from a clo model NodeChainConfig -func NewChainConfig(chain *models.NodeChainConfig) *jd.ChainConfig { - return &jd.ChainConfig{ - Chain: &jd.Chain{ - Id: chain.Network.ChainID, - Type: jd.ChainType_CHAIN_TYPE_EVM, // TODO: support other chain types - }, - - AccountAddress: chain.AccountAddress, - AdminAddress: chain.AdminAddress, - Ocr2Config: &jd.OCR2Config{ - Enabled: chain.Ocr2Config.Enabled, - P2PKeyBundle: &jd.OCR2Config_P2PKeyBundle{ - PeerId: chain.Ocr2Config.P2pKeyBundle.PeerID, - PublicKey: chain.Ocr2Config.P2pKeyBundle.PublicKey, - }, - OcrKeyBundle: &jd.OCR2Config_OCRKeyBundle{ - BundleId: chain.Ocr2Config.OcrKeyBundle.BundleID, - OnchainSigningAddress: chain.Ocr2Config.OcrKeyBundle.OnchainSigningAddress, - OffchainPublicKey: chain.Ocr2Config.OcrKeyBundle.OffchainPublicKey, - ConfigPublicKey: chain.Ocr2Config.OcrKeyBundle.ConfigPublicKey, - }, - }, - } -} - -func NodeP2PId(n *models.Node) (string, error) { - p2pIds := make(map[string]struct{}) - for _, cc := range n.ChainConfigs { - if cc.Ocr2Config != nil && cc.Ocr2Config.P2pKeyBundle != nil { - p2pIds[cc.Ocr2Config.P2pKeyBundle.PeerID] = struct{}{} - } - } - if len(p2pIds) == 0 { - return "", fmt.Errorf("no p2p id found for node %s", n.ID) - } - if len(p2pIds) > 1 { - return "", fmt.Errorf("multiple p2p ids found for node %s", n.ID) - } - var p2pId string - for k := range p2pIds { - p2pId = k - break - } - return p2pId, nil -} - -func NodesToPeerIDs(nodes []*models.Node) ([]string, error) { - var p2pIds []string - for _, node := range nodes { - p2pId, err := NodeP2PId(node) - if err != nil { - return nil, err - } - p2pIds = append(p2pIds, p2pId) - } - return p2pIds, nil -} - -func NopsToNodes(nops []*models.NodeOperator) []*models.Node { - var nodes []*models.Node - for _, nop := range nops { - nodes = append(nodes, nop.Nodes...) - } - return nodes -} - -func NopsToPeerIds(nops []*models.NodeOperator) ([]string, error) { - return NodesToPeerIDs(NopsToNodes(nops)) -} - -func SetIdToPeerId(n *models.Node) error { - p2pId, err := NodeP2PId(n) - if err != nil { - return err - } - n.ID = p2pId - return nil -} - -// SetNodeIdsToPeerIds sets the ID of each node in the NOPs to the P2P ID of the node -// It mutates the input NOPs -func SetNodeIdsToPeerIds(nops []*models.NodeOperator) error { - for _, nop := range nops { - for _, n := range nop.Nodes { - if err := SetIdToPeerId(n); err != nil { - return err - } - } - } - return nil -} diff --git a/deployment/environment/clo/utils_test.go b/deployment/environment/clo/utils_test.go deleted file mode 100644 index e2202d4e14f..00000000000 --- a/deployment/environment/clo/utils_test.go +++ /dev/null @@ -1,168 +0,0 @@ -package clo - -import ( - "testing" - - "github.com/smartcontractkit/chainlink/deployment/environment/clo/models" - "github.com/stretchr/testify/assert" -) - -func TestSetNodeIdsToPeerIds(t *testing.T) { - type args struct { - nops []*models.NodeOperator - } - tests := []struct { - name string - args args - want []*models.NodeOperator - wantErr bool - }{ - { - name: "no nodes", - args: args{ - nops: []*models.NodeOperator{ - { - ID: "nop1", - }, - }, - }, - want: []*models.NodeOperator{ - { - ID: "nop1", - }, - }, - }, - { - name: "error no p2p key bundle", - args: args{ - nops: []*models.NodeOperator{ - { - ID: "nop1", - Nodes: []*models.Node{ - { - ID: "node1", - ChainConfigs: []*models.NodeChainConfig{ - { - Ocr2Config: &models.NodeOCR2Config{}, - }, - }, - }, - }, - }, - }, - }, - wantErr: true, - }, - { - name: "error multiple p2p key bundle", - args: args{ - nops: []*models.NodeOperator{ - { - ID: "nop1", - Nodes: []*models.Node{ - { - ID: "node1", - ChainConfigs: []*models.NodeChainConfig{ - { - Ocr2Config: &models.NodeOCR2Config{ - P2pKeyBundle: &models.NodeOCR2ConfigP2PKeyBundle{ - PeerID: "peer1", - }, - }, - }, - { - Ocr2Config: &models.NodeOCR2Config{ - P2pKeyBundle: &models.NodeOCR2ConfigP2PKeyBundle{ - PeerID: "peer2", - }, - }, - }, - }, - }, - }, - }, - }, - }, - wantErr: true, - }, - { - name: "multiple nodes", - args: args{ - nops: []*models.NodeOperator{ - { - ID: "nop1", - Nodes: []*models.Node{ - { - ID: "node1", - ChainConfigs: []*models.NodeChainConfig{ - { - Ocr2Config: &models.NodeOCR2Config{ - P2pKeyBundle: &models.NodeOCR2ConfigP2PKeyBundle{ - PeerID: "peer1", - }, - }, - }, - }, - }, - { - ID: "node2", - ChainConfigs: []*models.NodeChainConfig{ - { - Ocr2Config: &models.NodeOCR2Config{ - P2pKeyBundle: &models.NodeOCR2ConfigP2PKeyBundle{ - PeerID: "another peer id", - }, - }, - }, - }, - }, - }, - }, - }, - }, - want: []*models.NodeOperator{ - { - ID: "nop1", - Nodes: []*models.Node{ - { - ID: "peer1", - ChainConfigs: []*models.NodeChainConfig{ - { - Ocr2Config: &models.NodeOCR2Config{ - P2pKeyBundle: &models.NodeOCR2ConfigP2PKeyBundle{ - PeerID: "peer1", - }, - }, - }, - }, - }, - { - ID: "another peer id", - ChainConfigs: []*models.NodeChainConfig{ - { - Ocr2Config: &models.NodeOCR2Config{ - P2pKeyBundle: &models.NodeOCR2ConfigP2PKeyBundle{ - PeerID: "another peer id", - }, - }, - }, - }, - }, - }, - }, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - err := SetNodeIdsToPeerIds(tt.args.nops) - if (err != nil) != tt.wantErr { - t.Errorf("SetNodeIdsToPeerIds() error = %v, wantErr %v", err, tt.wantErr) - } - if err != nil { - return - } - assert.EqualValues(t, tt.args.nops, tt.want) - }) - } -} diff --git a/deployment/environment/crib/ccip_deployer.go b/deployment/environment/crib/ccip_deployer.go index aea7ad0cb8f..9aa7972585d 100644 --- a/deployment/environment/crib/ccip_deployer.go +++ b/deployment/environment/crib/ccip_deployer.go @@ -4,22 +4,28 @@ import ( "context" "errors" "fmt" + "math/big" + "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/config" - commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" - commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" - "github.com/smartcontractkit/chainlink/deployment/environment/devenv" - "github.com/smartcontractkit/chainlink/v2/core/services/relay" - "math/big" + + "github.com/smartcontractkit/chainlink-ccip/chainconfig" + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" + "github.com/smartcontractkit/chainlink/deployment/environment/devenv" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" ) -// DeployHomeChainContracts deploys the home chain contracts so that the chainlink nodes can be started with the CR address in Capabilities.ExternalRegistry -// DeployHomeChainContracts is to 1. Set up crib with chains and chainlink nodes ( cap reg is not known yet so not setting the config with capreg address) -// Call DeployHomeChain changeset with nodeinfo ( the peer id and all) +// DeployHomeChainContracts deploys the home chain contracts so that the chainlink nodes can use the CR address in Capabilities.ExternalRegistry +// Afterwards, we call DeployHomeChainChangeset changeset with nodeinfo ( the peer id and all) func DeployHomeChainContracts(ctx context.Context, lggr logger.Logger, envConfig devenv.EnvironmentConfig, homeChainSel uint64, feedChainSel uint64) (deployment.CapabilityRegistryConfig, deployment.AddressBook, error) { e, _, err := devenv.NewEnvironment(func() context.Context { return ctx }, lggr, envConfig) if err != nil { @@ -36,12 +42,12 @@ func DeployHomeChainContracts(ctx context.Context, lggr logger.Logger, envConfig p2pIds := nodes.NonBootstraps().PeerIDs() *e, err = commonchangeset.ApplyChangesets(nil, *e, nil, []commonchangeset.ChangesetApplication{ { - Changeset: commonchangeset.WrapChangeSet(changeset.DeployHomeChain), + Changeset: commonchangeset.WrapChangeSet(changeset.DeployHomeChainChangeset), Config: changeset.DeployHomeChainConfig{ HomeChainSel: homeChainSel, - RMNStaticConfig: changeset.NewTestRMNStaticConfig(), - RMNDynamicConfig: changeset.NewTestRMNDynamicConfig(), - NodeOperators: changeset.NewTestNodeOperator(e.Chains[homeChainSel].DeployerKey.From), + RMNStaticConfig: testhelpers.NewTestRMNStaticConfig(), + RMNDynamicConfig: testhelpers.NewTestRMNDynamicConfig(), + NodeOperators: testhelpers.NewTestNodeOperator(e.Chains[homeChainSel].DeployerKey.From), NodeP2PIDsPerNodeOpAdmin: map[string][][32]byte{ "NodeOperator": p2pIds, }, @@ -65,14 +71,16 @@ func DeployHomeChainContracts(ctx context.Context, lggr logger.Logger, envConfig return capRegConfig, e.ExistingAddresses, nil } +// DeployCCIPAndAddLanes is the actual ccip setup once the nodes are initialized. func DeployCCIPAndAddLanes(ctx context.Context, lggr logger.Logger, envConfig devenv.EnvironmentConfig, homeChainSel, feedChainSel uint64, ab deployment.AddressBook) (DeployCCIPOutput, error) { e, _, err := devenv.NewEnvironment(func() context.Context { return ctx }, lggr, envConfig) if err != nil { return DeployCCIPOutput{}, fmt.Errorf("failed to initiate new environment: %w", err) } e.ExistingAddresses = ab - allChainIds := e.AllChainSelectors() + chainSelectors := e.AllChainSelectors() cfg := make(map[uint64]commontypes.MCMSWithTimelockConfig) + var prereqCfgs []changeset.DeployPrerequisiteConfigPerChain for _, chain := range e.AllChainSelectors() { mcmsConfig, err := config.NewConfig(1, []common.Address{e.Chains[chain].DeployerKey.From}, []config.Config{}) if err != nil { @@ -84,19 +92,46 @@ func DeployCCIPAndAddLanes(ctx context.Context, lggr logger.Logger, envConfig de Proposer: *mcmsConfig, TimelockMinDelay: big.NewInt(0), } + prereqCfgs = append(prereqCfgs, changeset.DeployPrerequisiteConfigPerChain{ + ChainSelector: chain, + }) } - // This will not apply any proposals because we pass nil to testing. - // However, setup is ok because we only need to deploy the contracts and distribute job specs + // set up chains + chainConfigs := make(map[uint64]changeset.ChainConfig) + nodeInfo, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) + if err != nil { + return DeployCCIPOutput{}, fmt.Errorf("failed to get node info from env: %w", err) + } + for _, chain := range chainSelectors { + chainConfigs[chain] = changeset.ChainConfig{ + Readers: nodeInfo.NonBootstraps().PeerIDs(), + FChain: 1, + EncodableChainConfig: chainconfig.ChainConfig{ + GasPriceDeviationPPB: cciptypes.BigInt{Int: big.NewInt(1000)}, + DAGasPriceDeviationPPB: cciptypes.BigInt{Int: big.NewInt(1_000_000)}, + OptimisticConfirmations: 1, + }, + } + } + + // Setup because we only need to deploy the contracts and distribute job specs *e, err = commonchangeset.ApplyChangesets(nil, *e, nil, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(changeset.UpdateChainConfigChangeset), + Config: changeset.UpdateChainConfigConfig{ + HomeChainSelector: homeChainSel, + RemoteChainAdds: chainConfigs, + }, + }, { Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployLinkToken), - Config: allChainIds, + Config: chainSelectors, }, { - Changeset: commonchangeset.WrapChangeSet(changeset.DeployPrerequisites), + Changeset: commonchangeset.WrapChangeSet(changeset.DeployPrerequisitesChangeset), Config: changeset.DeployPrerequisiteConfig{ - ChainSelectors: allChainIds, + Configs: prereqCfgs, }, }, { @@ -104,14 +139,14 @@ func DeployCCIPAndAddLanes(ctx context.Context, lggr logger.Logger, envConfig de Config: cfg, }, { - Changeset: commonchangeset.WrapChangeSet(changeset.DeployChainContracts), + Changeset: commonchangeset.WrapChangeSet(changeset.DeployChainContractsChangeset), Config: changeset.DeployChainContractsConfig{ - ChainSelectors: allChainIds, + ChainSelectors: chainSelectors, HomeChainSelector: homeChainSel, }, }, { - Changeset: commonchangeset.WrapChangeSet(changeset.CCIPCapabilityJobspec), + Changeset: commonchangeset.WrapChangeSet(changeset.CCIPCapabilityJobspecChangeset), Config: struct{}{}, }, }) @@ -120,9 +155,91 @@ func DeployCCIPAndAddLanes(ctx context.Context, lggr logger.Logger, envConfig de return DeployCCIPOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } // Add all lanes - err = changeset.AddLanesForAll(*e, state) - if err != nil { - return DeployCCIPOutput{}, fmt.Errorf("failed to add lanes: %w", err) + for from := range e.Chains { + for to := range e.Chains { + if from != to { + stateChain1 := state.Chains[from] + newEnv, err := commonchangeset.ApplyChangesets(nil, *e, nil, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(changeset.UpdateOnRampsDestsChangeset), + Config: changeset.UpdateOnRampDestsConfig{ + UpdatesByChain: map[uint64]map[uint64]changeset.OnRampDestinationUpdate{ + from: { + to: { + IsEnabled: true, + TestRouter: false, + AllowListEnabled: false, + }, + }, + }, + }, + }, + { + Changeset: commonchangeset.WrapChangeSet(changeset.UpdateFeeQuoterPricesChangeset), + Config: changeset.UpdateFeeQuoterPricesConfig{ + PricesByChain: map[uint64]changeset.FeeQuoterPriceUpdatePerSource{ + from: { + TokenPrices: map[common.Address]*big.Int{ + stateChain1.LinkToken.Address(): testhelpers.DefaultLinkPrice, + stateChain1.Weth9.Address(): testhelpers.DefaultWethPrice, + }, + GasPrices: map[uint64]*big.Int{ + to: testhelpers.DefaultGasPrice, + }, + }, + }, + }, + }, + { + Changeset: commonchangeset.WrapChangeSet(changeset.UpdateFeeQuoterDestsChangeset), + Config: changeset.UpdateFeeQuoterDestsConfig{ + UpdatesByChain: map[uint64]map[uint64]fee_quoter.FeeQuoterDestChainConfig{ + from: { + to: changeset.DefaultFeeQuoterDestChainConfig(), + }, + }, + }, + }, + { + Changeset: commonchangeset.WrapChangeSet(changeset.UpdateOffRampSourcesChangeset), + Config: changeset.UpdateOffRampSourcesConfig{ + UpdatesByChain: map[uint64]map[uint64]changeset.OffRampSourceUpdate{ + to: { + from: { + IsEnabled: true, + TestRouter: true, + }, + }, + }, + }, + }, + { + Changeset: commonchangeset.WrapChangeSet(changeset.UpdateRouterRampsChangeset), + Config: changeset.UpdateRouterRampsConfig{ + TestRouter: true, + UpdatesByChain: map[uint64]changeset.RouterUpdates{ + // onRamp update on source chain + from: { + OnRampUpdates: map[uint64]bool{ + to: true, + }, + }, + // off + from: { + OffRampUpdates: map[uint64]bool{ + to: true, + }, + }, + }, + }, + }, + }) + if err != nil { + return DeployCCIPOutput{}, fmt.Errorf("failed to apply changesets: %w", err) + } + e = &newEnv + } + } } addresses, err := e.ExistingAddresses.Addresses() diff --git a/deployment/environment/crib/types.go b/deployment/environment/crib/types.go index d19c8424443..771880053f9 100644 --- a/deployment/environment/crib/types.go +++ b/deployment/environment/crib/types.go @@ -2,6 +2,7 @@ package crib import ( "context" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/environment/devenv" @@ -32,6 +33,7 @@ func NewDeployEnvironmentFromCribOutput(lggr logger.Logger, output DeployOutput) lggr, output.AddressBook, chains, + nil, // nil for solana chains, can use memory solana chain example when required output.NodeIDs, nil, // todo: populate the offchain client using output.DON func() context.Context { return context.Background() }, deployment.XXXGenerateTestOCRSecrets(), diff --git a/deployment/environment/devenv/chain.go b/deployment/environment/devenv/chain.go index 5c6c4336ed7..265a6647050 100644 --- a/deployment/environment/devenv/chain.go +++ b/deployment/environment/devenv/chain.go @@ -2,6 +2,7 @@ package devenv import ( "context" + "errors" "fmt" "math/big" "time" @@ -39,7 +40,7 @@ func (c *ChainConfig) SetUsers(pvtkeys []string) error { c.Users = []*bind.TransactOpts{c.DeployerKey} return nil } else { - return fmt.Errorf("no private keys provided for users, deployer key is also not set") + return errors.New("no private keys provided for users, deployer key is also not set") } } for _, pvtKeyStr := range pvtkeys { diff --git a/deployment/environment/devenv/don.go b/deployment/environment/devenv/don.go index 76f6ee92b68..a8912254d1d 100644 --- a/deployment/environment/devenv/don.go +++ b/deployment/environment/devenv/don.go @@ -4,15 +4,18 @@ import ( "context" "errors" "fmt" - chainsel "github.com/smartcontractkit/chain-selectors" "strconv" "strings" "time" + chainsel "github.com/smartcontractkit/chain-selectors" + "github.com/hashicorp/go-multierror" "github.com/rs/zerolog" "github.com/sethvargo/go-retry" + nodev1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" + clclient "github.com/smartcontractkit/chainlink/deployment/environment/nodeclient" "github.com/smartcontractkit/chainlink/deployment/environment/web/sdk/client" @@ -167,7 +170,7 @@ type Node struct { NodeId string // node id returned by job distributor after node is registered with it JDId string // job distributor id returned by node after Job distributor is created in node Name string // name of the node - AccountAddr map[uint64]string // chain selector to node's account address mapping for supported chains + AccountAddr map[uint64]string // chain id to node's account address mapping for supported chains gqlClient client.Client // graphql client to interact with the node restClient *clclient.ChainlinkClient // rest client to interact with the node labels []*ptypes.Label // labels with which the node is registered with the job distributor @@ -395,7 +398,7 @@ func (n *Node) CreateJobDistributor(ctx context.Context, jd JobDistributor) (str // create the job distributor in the node with the csa key resp, err := n.gqlClient.ListJobDistributors(ctx) if err != nil { - return "", fmt.Errorf("could not list job distrubutors: %w", err) + return "", fmt.Errorf("could not list job distributors: %w", err) } if len(resp.FeedsManagers.Results) > 0 { for _, fm := range resp.FeedsManagers.Results { diff --git a/deployment/environment/devenv/don_test.go b/deployment/environment/devenv/don_test.go index f93436f72f5..0e0578f8275 100644 --- a/deployment/environment/devenv/don_test.go +++ b/deployment/environment/devenv/don_test.go @@ -7,7 +7,6 @@ import ( ) func TestPtrVal(t *testing.T) { - x := "hello" xptr := ptr(x) got := value(xptr) diff --git a/deployment/environment/devenv/environment.go b/deployment/environment/devenv/environment.go index 121caea43bb..b6b5198f8fb 100644 --- a/deployment/environment/devenv/environment.go +++ b/deployment/environment/devenv/environment.go @@ -2,6 +2,7 @@ package devenv import ( "context" + "errors" "fmt" "github.com/smartcontractkit/chainlink-common/pkg/logger" @@ -30,10 +31,10 @@ func NewEnvironment(ctx func() context.Context, lggr logger.Logger, config Envir jd, ok := offChain.(*JobDistributor) if !ok { - return nil, nil, fmt.Errorf("offchain client does not implement JobDistributor") + return nil, nil, errors.New("offchain client does not implement JobDistributor") } if jd == nil { - return nil, nil, fmt.Errorf("offchain client is not set up") + return nil, nil, errors.New("offchain client is not set up") } var nodeIDs []string if jd.don != nil { @@ -49,6 +50,7 @@ func NewEnvironment(ctx func() context.Context, lggr logger.Logger, config Envir lggr, deployment.NewMemoryAddressBook(), chains, + nil, // sending nil for solana chains right now, we can build this when we need it nodeIDs, offChain, ctx, diff --git a/deployment/environment/devenv/jd.go b/deployment/environment/devenv/jd.go index 818f9b09400..844068e50da 100644 --- a/deployment/environment/devenv/jd.go +++ b/deployment/environment/devenv/jd.go @@ -2,6 +2,7 @@ package devenv import ( "context" + "errors" "fmt" "golang.org/x/oauth2" @@ -121,7 +122,7 @@ func (jd JobDistributor) GetCSAPublicKey(ctx context.Context) (string, error) { return "", err } if keypairs == nil || len(keypairs.Keypairs) == 0 { - return "", fmt.Errorf("no keypairs found") + return "", errors.New("no keypairs found") } csakey := keypairs.Keypairs[0].PublicKey return csakey, nil @@ -138,7 +139,7 @@ func (jd JobDistributor) ProposeJob(ctx context.Context, in *jobv1.ProposeJobReq return nil, fmt.Errorf("failed to propose job. err: %w", err) } if res.Proposal == nil { - return nil, fmt.Errorf("failed to propose job. err: proposal is nil") + return nil, errors.New("failed to propose job. err: proposal is nil") } if jd.don == nil || len(jd.don.Nodes) == 0 { return res, nil diff --git a/deployment/environment/memory/chain.go b/deployment/environment/memory/chain.go index 40a20a02416..d3aa3a614f4 100644 --- a/deployment/environment/memory/chain.go +++ b/deployment/environment/memory/chain.go @@ -1,19 +1,36 @@ package memory import ( + "encoding/json" "math/big" + "os" + "path" + "strconv" + "sync" "testing" + "time" "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/crypto" "github.com/ethereum/go-ethereum/ethclient/simulated" + "github.com/gagliardetto/solana-go" + solRpc "github.com/gagliardetto/solana-go/rpc" + "github.com/hashicorp/consul/sdk/freeport" "github.com/stretchr/testify/require" + "github.com/testcontainers/testcontainers-go" + + solTestUtil "github.com/smartcontractkit/chainlink-ccip/chains/solana/contracts/tests/testutils" chainsel "github.com/smartcontractkit/chain-selectors" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + + chainselectors "github.com/smartcontractkit/chain-selectors" + + "github.com/smartcontractkit/chainlink-testing-framework/framework" + "github.com/smartcontractkit/chainlink-testing-framework/framework/components/blockchain" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" ) @@ -23,6 +40,13 @@ type EVMChain struct { Users []*bind.TransactOpts } +type SolanaChain struct { + Client *solRpc.Client + URL string + WSURL string + DeployerKey solana.PrivateKey +} + func fundAddress(t *testing.T, from *bind.TransactOpts, to common.Address, amount *big.Int, backend *simulated.Backend) { ctx := tests.Context(t) nonce, err := backend.Client().PendingNonceAt(ctx, from.From) @@ -52,10 +76,39 @@ func GenerateChains(t *testing.T, numChains int, numUsers int) map[uint64]EVMCha return chains } -func GenerateChainsWithIds(t *testing.T, chainIDs []uint64) map[uint64]EVMChain { +func getTestSolanaChainSelectors() []uint64 { + result := []uint64{} + for _, x := range chainsel.SolanaALL { + if x.Name == x.ChainID { + result = append(result, x.Selector) + } + } + return result +} + +func GenerateChainsSol(t *testing.T, numChains int) map[uint64]SolanaChain { + testSolanaChainSelectors := getTestSolanaChainSelectors() + if len(testSolanaChainSelectors) < numChains { + t.Fatalf("not enough test solana chain selectors available") + } + chains := make(map[uint64]SolanaChain) + for i := 0; i < numChains; i++ { + chainID := testSolanaChainSelectors[i] + solChain := solChain(t) + admin := solChain.DeployerKey + solTestUtil.FundTestAccounts(t, []solana.PublicKey{admin.PublicKey()}, solChain.URL) + chains[chainID] = SolanaChain{ + Client: solChain.Client, + DeployerKey: solChain.DeployerKey, + } + } + return chains +} + +func GenerateChainsWithIds(t *testing.T, chainIDs []uint64, numUsers int) map[uint64]EVMChain { chains := make(map[uint64]EVMChain) for _, chainID := range chainIDs { - chains[chainID] = evmChain(t, 1) + chains[chainID] = evmChain(t, numUsers) } return chains } @@ -86,3 +139,66 @@ func evmChain(t *testing.T, numUsers int) EVMChain { Users: users, } } + +var once = &sync.Once{} + +func solChain(t *testing.T) SolanaChain { + t.Helper() + + // initialize the docker network used by CTF + err := framework.DefaultNetwork(once) + require.NoError(t, err) + + deployerKey, err := solana.NewRandomPrivateKey() + require.NoError(t, err) + + t.TempDir() + // store the generated keypair somewhere + bytes, err := json.Marshal([]byte(deployerKey)) + require.NoError(t, err) + keypairPath := path.Join(t.TempDir(), "solana-keypair.json") + err = os.WriteFile(keypairPath, bytes, 0600) + require.NoError(t, err) + + port := freeport.GetOne(t) + + bcInput := &blockchain.Input{ + Type: "solana", + ChainID: chainselectors.SOLANA_DEVNET.ChainID, + PublicKey: deployerKey.PublicKey().String(), + Port: strconv.Itoa(port), + // TODO: ContractsDir & SolanaPrograms via env vars + } + output, err := blockchain.NewBlockchainNetwork(bcInput) + require.NoError(t, err) + testcontainers.CleanupContainer(t, output.Container) + + url := output.Nodes[0].HostHTTPUrl + wsURL := output.Nodes[0].HostWSUrl + + // Wait for api server to boot + client := solRpc.New(url) + var ready bool + for i := 0; i < 30; i++ { + time.Sleep(time.Second) + out, err := client.GetHealth(tests.Context(t)) + if err != nil || out != solRpc.HealthOk { + t.Logf("API server not ready yet (attempt %d)\n", i+1) + continue + } + ready = true + break + } + if !ready { + t.Logf("solana-test-validator is not ready after 30 attempts") + } + require.True(t, ready) + t.Logf("solana-test-validator is ready at %s", url) + + return SolanaChain{ + Client: client, + URL: url, + WSURL: wsURL, + DeployerKey: deployerKey, + } +} diff --git a/deployment/environment/memory/environment.go b/deployment/environment/memory/environment.go index d6c80a92a44..c9044792834 100644 --- a/deployment/environment/memory/environment.go +++ b/deployment/environment/memory/environment.go @@ -5,9 +5,11 @@ import ( "fmt" "strconv" "testing" + "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/core/types" + "github.com/gagliardetto/solana-go" "github.com/hashicorp/consul/sdk/freeport" "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" @@ -18,6 +20,9 @@ import ( "github.com/smartcontractkit/chainlink/deployment" + solRpc "github.com/gagliardetto/solana-go/rpc" + + solCommomUtil "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/common" "github.com/smartcontractkit/chainlink-common/pkg/logger" ) @@ -27,6 +32,7 @@ const ( type MemoryEnvironmentConfig struct { Chains int + SolChains int NumOfUsersPerChain int Nodes int Bootstraps int @@ -58,9 +64,20 @@ func NewMemoryChains(t *testing.T, numChains int, numUsers int) (map[uint64]depl return generateMemoryChain(t, mchains), users } -func NewMemoryChainsWithChainIDs(t *testing.T, chainIDs []uint64) map[uint64]deployment.Chain { - mchains := GenerateChainsWithIds(t, chainIDs) - return generateMemoryChain(t, mchains) +func NewMemoryChainsSol(t *testing.T, numChains int) map[uint64]deployment.SolChain { + mchains := GenerateChainsSol(t, numChains) + return generateMemoryChainSol(t, mchains) +} + +func NewMemoryChainsWithChainIDs(t *testing.T, chainIDs []uint64, numUsers int) (map[uint64]deployment.Chain, map[uint64][]*bind.TransactOpts) { + mchains := GenerateChainsWithIds(t, chainIDs, numUsers) + users := make(map[uint64][]*bind.TransactOpts) + for id, chain := range mchains { + sel, err := chainsel.SelectorFromChainId(id) + require.NoError(t, err) + users[sel] = chain.Users + } + return generateMemoryChain(t, mchains), users } func generateMemoryChain(t *testing.T, inputs map[uint64]EVMChain) map[uint64]deployment.Chain { @@ -80,10 +97,13 @@ func generateMemoryChain(t *testing.T, inputs map[uint64]EVMChain) map[uint64]de } for { backend.Commit() - receipt, err := backend.TransactionReceipt(context.Background(), tx.Hash()) + receipt, err := func() (*types.Receipt, error) { + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) + defer cancel() + return bind.WaitMined(ctx, backend, tx) + }() if err != nil { - t.Log("failed to get receipt", "chain", chainInfo.ChainName, err) - continue + return 0, fmt.Errorf("tx %s failed to confirm: %w, chain %d", tx.Hash().Hex(), err, chainInfo.ChainSelector) } if receipt.Status == 0 { errReason, err := deployment.GetErrorReasonFromTx(chain.Backend.Client(), chain.DeployerKey.From, tx, receipt) @@ -101,6 +121,28 @@ func generateMemoryChain(t *testing.T, inputs map[uint64]EVMChain) map[uint64]de return chains } +func generateMemoryChainSol(t *testing.T, inputs map[uint64]SolanaChain) map[uint64]deployment.SolChain { + chains := make(map[uint64]deployment.SolChain) + for cid, chain := range inputs { + chain := chain + chains[cid] = deployment.SolChain{ + Selector: cid, + Client: chain.Client, + DeployerKey: &chain.DeployerKey, + Confirm: func(instructions []solana.Instruction, opts ...solCommomUtil.TxModifier) error { + _, err := solCommomUtil.SendAndConfirm( + context.Background(), chain.Client, instructions, chain.DeployerKey, solRpc.CommitmentConfirmed, opts..., + ) + if err != nil { + return err + } + return nil + }, + } + } + return chains +} + func NewNodes(t *testing.T, logLevel zapcore.Level, chains map[uint64]deployment.Chain, numNodes, numBootstraps int, registryConfig deployment.CapabilityRegistryConfig) map[string]Node { nodesByPeerID := make(map[string]Node) if numNodes+numBootstraps == 0 { @@ -111,13 +153,13 @@ func NewNodes(t *testing.T, logLevel zapcore.Level, chains map[uint64]deployment // since we won't run a bootstrapper and a plugin oracle on the same // chainlink node in production. for i := 0; i < numBootstraps; i++ { - node := NewNode(t, ports[i], chains, logLevel, true /* bootstrap */, registryConfig) + node := NewNode(t, ports[i], chains, nil, logLevel, true /* bootstrap */, registryConfig) nodesByPeerID[node.Keys.PeerID.String()] = *node // Note in real env, this ID is allocated by JD. } for i := 0; i < numNodes; i++ { // grab port offset by numBootstraps, since above loop also takes some ports. - node := NewNode(t, ports[numBootstraps+i], chains, logLevel, false /* bootstrap */, registryConfig) + node := NewNode(t, ports[numBootstraps+i], chains, nil, logLevel, false /* bootstrap */, registryConfig) nodesByPeerID[node.Keys.PeerID.String()] = *node // Note in real env, this ID is allocated by JD. } @@ -139,6 +181,7 @@ func NewMemoryEnvironmentFromChainsNodes( lggr, deployment.NewMemoryAddressBook(), chains, + nil, nodeIDs, // Note these have the p2p_ prefix. NewMemoryJobClient(nodes), ctx, @@ -149,6 +192,7 @@ func NewMemoryEnvironmentFromChainsNodes( // To be used by tests and any kind of deployment logic. func NewMemoryEnvironment(t *testing.T, lggr logger.Logger, logLevel zapcore.Level, config MemoryEnvironmentConfig) deployment.Environment { chains, _ := NewMemoryChains(t, config.Chains, config.NumOfUsersPerChain) + solChains := NewMemoryChainsSol(t, config.SolChains) nodes := NewNodes(t, logLevel, chains, config.Nodes, config.Bootstraps, config.RegistryConfig) var nodeIDs []string for id := range nodes { @@ -159,6 +203,7 @@ func NewMemoryEnvironment(t *testing.T, lggr logger.Logger, logLevel zapcore.Lev lggr, deployment.NewMemoryAddressBook(), chains, + solChains, nodeIDs, NewMemoryJobClient(nodes), func() context.Context { return tests.Context(t) }, diff --git a/deployment/environment/memory/job_client.go b/deployment/environment/memory/job_client.go index 98fb90ceffa..e025ea18fda 100644 --- a/deployment/environment/memory/job_client.go +++ b/deployment/environment/memory/job_client.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "slices" - "strconv" "strings" "github.com/ethereum/go-ethereum/common" @@ -20,6 +19,8 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/validate" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" + ocr2validate "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" + "github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap" ) type JobClient struct { @@ -27,42 +28,42 @@ type JobClient struct { } func (j JobClient) BatchProposeJob(ctx context.Context, in *jobv1.BatchProposeJobRequest, opts ...grpc.CallOption) (*jobv1.BatchProposeJobResponse, error) { - //TODO CCIP-3108 implement me + // TODO CCIP-3108 implement me panic("implement me") } func (j JobClient) UpdateJob(ctx context.Context, in *jobv1.UpdateJobRequest, opts ...grpc.CallOption) (*jobv1.UpdateJobResponse, error) { - //TODO CCIP-3108 implement me + // TODO CCIP-3108 implement me panic("implement me") } func (j JobClient) DisableNode(ctx context.Context, in *nodev1.DisableNodeRequest, opts ...grpc.CallOption) (*nodev1.DisableNodeResponse, error) { - //TODO CCIP-3108 implement me + // TODO CCIP-3108 implement me panic("implement me") } func (j JobClient) EnableNode(ctx context.Context, in *nodev1.EnableNodeRequest, opts ...grpc.CallOption) (*nodev1.EnableNodeResponse, error) { - //TODO CCIP-3108 implement me + // TODO CCIP-3108 implement me panic("implement me") } func (j JobClient) RegisterNode(ctx context.Context, in *nodev1.RegisterNodeRequest, opts ...grpc.CallOption) (*nodev1.RegisterNodeResponse, error) { - //TODO implement me + // TODO implement me panic("implement me") } func (j JobClient) UpdateNode(ctx context.Context, in *nodev1.UpdateNodeRequest, opts ...grpc.CallOption) (*nodev1.UpdateNodeResponse, error) { - //TODO CCIP-3108 implement me + // TODO CCIP-3108 implement me panic("implement me") } func (j JobClient) GetKeypair(ctx context.Context, in *csav1.GetKeypairRequest, opts ...grpc.CallOption) (*csav1.GetKeypairResponse, error) { - //TODO implement me + // TODO implement me panic("implement me") } func (j JobClient) ListKeypairs(ctx context.Context, in *csav1.ListKeypairsRequest, opts ...grpc.CallOption) (*csav1.ListKeypairsResponse, error) { - //TODO CCIP-3108 implement me + // TODO CCIP-3108 implement me panic("implement me") } @@ -82,7 +83,7 @@ func (j JobClient) GetNode(ctx context.Context, in *nodev1.GetNodeRequest, opts } func (j JobClient) ListNodes(ctx context.Context, in *nodev1.ListNodesRequest, opts ...grpc.CallOption) (*nodev1.ListNodesResponse, error) { - //TODO CCIP-3108 + // TODO CCIP-3108 include := func(node *nodev1.Node) bool { if in.Filter == nil { return true @@ -151,49 +152,12 @@ func (j JobClient) ListNodeChainConfigs(ctx context.Context, in *nodev1.ListNode if !ok { return nil, fmt.Errorf("node id not found: %s", in.Filter.NodeIds[0]) } - evmBundle := n.Keys.OCRKeyBundles[chaintype.EVM] - offpk := evmBundle.OffchainPublicKey() - cpk := evmBundle.ConfigEncryptionPublicKey() - - evmKeyBundle := &nodev1.OCR2Config_OCRKeyBundle{ - BundleId: evmBundle.ID(), - ConfigPublicKey: common.Bytes2Hex(cpk[:]), - OffchainPublicKey: common.Bytes2Hex(offpk[:]), - OnchainSigningAddress: evmBundle.OnChainPublicKey(), - } - var chainConfigs []*nodev1.ChainConfig - for evmChainID, transmitter := range n.Keys.TransmittersByEVMChainID { - chainConfigs = append(chainConfigs, &nodev1.ChainConfig{ - Chain: &nodev1.Chain{ - Id: strconv.Itoa(int(evmChainID)), - Type: nodev1.ChainType_CHAIN_TYPE_EVM, - }, - AccountAddress: transmitter.String(), - AdminAddress: transmitter.String(), // TODO: custom address - Ocr1Config: nil, - Ocr2Config: &nodev1.OCR2Config{ - Enabled: true, - IsBootstrap: n.IsBoostrap, - P2PKeyBundle: &nodev1.OCR2Config_P2PKeyBundle{ - PeerId: n.Keys.PeerID.String(), - }, - OcrKeyBundle: evmKeyBundle, - Multiaddr: n.Addr.String(), - Plugins: nil, - ForwarderAddress: ptr(""), - }, - }) - } for _, selector := range n.Chains { family, err := chainsel.GetSelectorFamily(selector) if err != nil { return nil, err } - if family == chainsel.FamilyEVM { - // already handled above - continue - } // NOTE: this supports non-EVM too chainID, err := chainsel.GetChainIDFromSelector(selector) @@ -218,7 +182,6 @@ func (j JobClient) ListNodeChainConfigs(ctx context.Context, in *nodev1.ListNode } bundle := n.Keys.OCRKeyBundles[ocrtype] - offpk := bundle.OffchainPublicKey() cpk := bundle.ConfigEncryptionPublicKey() @@ -243,13 +206,15 @@ func (j JobClient) ListNodeChainConfigs(ctx context.Context, in *nodev1.ListNode panic(fmt.Sprintf("Unsupported chain family %v", family)) } + transmitter := n.Keys.Transmitters[selector] + chainConfigs = append(chainConfigs, &nodev1.ChainConfig{ Chain: &nodev1.Chain{ Id: chainID, Type: ctype, }, - AccountAddress: "", // TODO: support AccountAddress - AdminAddress: "", + AccountAddress: transmitter, + AdminAddress: transmitter, Ocr1Config: nil, Ocr2Config: &nodev1.OCR2Config{ Enabled: true, @@ -264,29 +229,28 @@ func (j JobClient) ListNodeChainConfigs(ctx context.Context, in *nodev1.ListNode }, }) } - // TODO: I think we can pull it from the feeds manager. return &nodev1.ListNodeChainConfigsResponse{ ChainConfigs: chainConfigs, }, nil } func (j JobClient) GetJob(ctx context.Context, in *jobv1.GetJobRequest, opts ...grpc.CallOption) (*jobv1.GetJobResponse, error) { - //TODO CCIP-3108 implement me + // TODO CCIP-3108 implement me panic("implement me") } func (j JobClient) GetProposal(ctx context.Context, in *jobv1.GetProposalRequest, opts ...grpc.CallOption) (*jobv1.GetProposalResponse, error) { - //TODO CCIP-3108 implement me + // TODO CCIP-3108 implement me panic("implement me") } func (j JobClient) ListJobs(ctx context.Context, in *jobv1.ListJobsRequest, opts ...grpc.CallOption) (*jobv1.ListJobsResponse, error) { - //TODO CCIP-3108 implement me + // TODO CCIP-3108 implement me panic("implement me") } func (j JobClient) ListProposals(ctx context.Context, in *jobv1.ListProposalsRequest, opts ...grpc.CallOption) (*jobv1.ListProposalsResponse, error) { - //TODO CCIP-3108 implement me + // TODO CCIP-3108 implement me panic("implement me") } @@ -295,7 +259,27 @@ func (j JobClient) ProposeJob(ctx context.Context, in *jobv1.ProposeJobRequest, // TODO: Use FMS jb, err := validate.ValidatedCCIPSpec(in.Spec) if err != nil { - return nil, err + if !strings.Contains(err.Error(), "the only supported type is currently 'ccip'") { + return nil, err + } + // check if it's offchainreporting2 job + jb, err = ocr2validate.ValidatedOracleSpecToml( + ctx, + n.App.GetConfig().OCR2(), + n.App.GetConfig().Insecure(), + in.Spec, + nil, // not required for validation + ) + if err != nil { + if !strings.Contains(err.Error(), "the only supported type is currently 'offchainreporting2'") { + return nil, err + } + // check if it's bootstrap job + jb, err = ocrbootstrap.ValidatedBootstrapSpecToml(in.Spec) + if err != nil { + return nil, fmt.Errorf("failed to validate job spec only ccip, bootstrap and offchainreporting2 are supported: %w", err) + } + } } err = n.App.AddJobV2(ctx, &jb) if err != nil { @@ -316,12 +300,12 @@ func (j JobClient) ProposeJob(ctx context.Context, in *jobv1.ProposeJobRequest, } func (j JobClient) RevokeJob(ctx context.Context, in *jobv1.RevokeJobRequest, opts ...grpc.CallOption) (*jobv1.RevokeJobResponse, error) { - //TODO CCIP-3108 implement me + // TODO CCIP-3108 implement me panic("implement me") } func (j JobClient) DeleteJob(ctx context.Context, in *jobv1.DeleteJobRequest, opts ...grpc.CallOption) (*jobv1.DeleteJobResponse, error) { - //TODO CCIP-3108 implement me + // TODO CCIP-3108 implement me panic("implement me") } diff --git a/deployment/environment/memory/node.go b/deployment/environment/memory/node.go index 84f0d2e443f..606c080be94 100644 --- a/deployment/environment/memory/node.go +++ b/deployment/environment/memory/node.go @@ -6,6 +6,7 @@ import ( "math/big" "net" "net/http" + "slices" "strconv" "testing" "time" @@ -22,6 +23,8 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/v2/core/capabilities" @@ -72,14 +75,19 @@ func NewNode( t *testing.T, port int, // Port for the P2P V2 listener. chains map[uint64]deployment.Chain, + solchains map[uint64]deployment.SolChain, logLevel zapcore.Level, bootstrap bool, registryConfig deployment.CapabilityRegistryConfig, ) *Node { evmchains := make(map[uint64]EVMChain) for _, chain := range chains { - // we're only mapping evm chains here - if family, err := chainsel.GetSelectorFamily(chain.Selector); err != nil || family != chainsel.FamilyEVM { + family, err := chainsel.GetSelectorFamily(chain.Selector) + if err != nil { + t.Fatal(err) + } + // we're only mapping evm chains here, currently this list could also contain non-EVMs, e.g. Aptos + if family != chainsel.FamilyEVM { continue } evmChainID, err := chainsel.ChainIdFromSelector(chain.Selector) @@ -120,11 +128,21 @@ func NewNode( c.Log.Level = ptr(configv2.LogLevel(logLevel)) - var chainConfigs v2toml.EVMConfigs + var evmConfigs v2toml.EVMConfigs for chainID := range evmchains { - chainConfigs = append(chainConfigs, createConfigV2Chain(chainID)) + evmConfigs = append(evmConfigs, createConfigV2Chain(chainID)) } - c.EVM = chainConfigs + c.EVM = evmConfigs + + var solConfigs solcfg.TOMLConfigs + for chainID, chain := range solchains { + solanaChainID, err := chainsel.GetChainIDFromSelector(chainID) + if err != nil { + t.Fatal(err) + } + solConfigs = append(solConfigs, createSolanaChainConfig(solanaChainID, chain)) + } + c.Solana = solConfigs }) // Set logging. @@ -164,6 +182,12 @@ func NewNode( CSAETHKeystore: kStore, } + solanaOpts := chainlink.SolanaFactoryConfig{ + Keystore: master.Solana(), + TOMLConfigs: cfg.SolanaConfigs(), + DS: db, + } + // Build Beholder auth ctx := tests.Context(t) require.NoError(t, master.Unlock(ctx, "password")) @@ -171,14 +195,19 @@ func NewNode( beholderAuthHeaders, csaPubKeyHex, err := keystore.BuildBeholderAuth(master) require.NoError(t, err) - // Build relayer factory with EVM. + loopRegistry := plugins.NewLoopRegistry(lggr.Named("LoopRegistry"), cfg.Tracing(), cfg.Telemetry(), beholderAuthHeaders, csaPubKeyHex) + + // Build relayer factory relayerFactory := chainlink.RelayerFactory{ Logger: lggr, - LoopRegistry: plugins.NewLoopRegistry(lggr.Named("LoopRegistry"), cfg.Tracing(), cfg.Telemetry(), beholderAuthHeaders, csaPubKeyHex), + LoopRegistry: loopRegistry, GRPCOpts: loop.GRPCOpts{}, CapabilitiesRegistry: capabilities.NewRegistry(lggr), } - initOps := []chainlink.CoreRelayerChainInitFunc{chainlink.InitEVM(context.Background(), relayerFactory, evmOpts)} + initOps := []chainlink.CoreRelayerChainInitFunc{ + chainlink.InitEVM(context.Background(), relayerFactory, evmOpts), + chainlink.InitSolana(context.Background(), relayerFactory, solanaOpts), + } rci, err := chainlink.NewCoreRelayerChainInteroperators(initOps...) require.NoError(t, err) @@ -194,17 +223,20 @@ func NewNode( RestrictedHTTPClient: &http.Client{}, AuditLogger: audit.NoopLogger, MailMon: mailMon, - LoopRegistry: plugins.NewLoopRegistry(lggr, cfg.Tracing(), cfg.Telemetry(), beholderAuthHeaders, csaPubKeyHex), + LoopRegistry: loopRegistry, }) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, db.Close()) }) - keys := CreateKeys(t, app, chains) + keys := CreateKeys(t, app, chains, solchains) return &Node{ - App: app, - Chains: maps.Keys(chains), + App: app, + Chains: slices.Concat( + maps.Keys(chains), + maps.Keys(solchains), + ), Keys: keys, Addr: net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: port}, IsBoostrap: bootstrap, @@ -212,14 +244,17 @@ func NewNode( } type Keys struct { - PeerID p2pkey.PeerID - CSA csakey.KeyV2 - TransmittersByEVMChainID map[uint64]common.Address - OCRKeyBundles map[chaintype.ChainType]ocr2key.KeyBundle + PeerID p2pkey.PeerID + CSA csakey.KeyV2 + Transmitters map[uint64]string // chainSelector => address + OCRKeyBundles map[chaintype.ChainType]ocr2key.KeyBundle } func CreateKeys(t *testing.T, - app chainlink.Application, chains map[uint64]deployment.Chain) Keys { + app chainlink.Application, + chains map[uint64]deployment.Chain, + solchains map[uint64]deployment.SolChain, +) Keys { ctx := tests.Context(t) _, err := app.GetKeyStore().P2P().Create(ctx) require.NoError(t, err) @@ -235,7 +270,7 @@ func CreateKeys(t *testing.T, require.Len(t, p2pIDs, 1) peerID := p2pIDs[0].PeerID() // create a transmitter for each chain - transmitters := make(map[uint64]common.Address) + transmitters := make(map[uint64]string) keybundles := make(map[chaintype.ChainType]ocr2key.KeyBundle) for _, chain := range chains { family, err := chainsel.GetSelectorFamily(chain.Selector) @@ -257,44 +292,100 @@ func CreateKeys(t *testing.T, panic(fmt.Sprintf("Unsupported chain family %v", family)) } - keybundle, err := app.GetKeyStore().OCR2().Create(ctx, ctype) + err = app.GetKeyStore().OCR2().EnsureKeys(ctx, ctype) + require.NoError(t, err) + keys, err := app.GetKeyStore().OCR2().GetAllOfType(ctype) require.NoError(t, err) + require.Len(t, keys, 1) + keybundle := keys[0] + keybundles[ctype] = keybundle - if family != chainsel.FamilyEVM { - // TODO: only support EVM transmission keys for now - continue + switch family { + case chainsel.FamilyEVM: + evmChainID, err := chainsel.ChainIdFromSelector(chain.Selector) + require.NoError(t, err) + + cid := new(big.Int).SetUint64(evmChainID) + addrs, err2 := app.GetKeyStore().Eth().EnabledAddressesForChain(ctx, cid) + require.NoError(t, err2) + var transmitter common.Address + if len(addrs) == 1 { + // just fund the address + transmitter = addrs[0] + } else { + // create key and fund it + _, err3 := app.GetKeyStore().Eth().Create(ctx, cid) + require.NoError(t, err3, "failed to create key for chain", evmChainID) + sendingKeys, err3 := app.GetKeyStore().Eth().EnabledAddressesForChain(ctx, cid) + require.NoError(t, err3) + require.Len(t, sendingKeys, 1) + transmitter = sendingKeys[0] + } + transmitters[chain.Selector] = transmitter.String() + + backend := chain.Client.(*Backend).Sim + fundAddress(t, chain.DeployerKey, transmitter, assets.Ether(1000).ToInt(), backend) + // need to look more into it, but it seems like with sim chains nodes are sending txs with 0x from address + fundAddress(t, chain.DeployerKey, common.Address{}, assets.Ether(1000).ToInt(), backend) + case chainsel.FamilyAptos: + err = app.GetKeyStore().Aptos().EnsureKey(ctx) + require.NoError(t, err, "failed to create key for aptos") + + keys, err := app.GetKeyStore().Aptos().GetAll() + require.NoError(t, err) + require.Len(t, keys, 1) + + transmitter := keys[0] + transmitters[chain.Selector] = transmitter.ID() + + // TODO: funding + case chainsel.FamilyStarknet: + err = app.GetKeyStore().StarkNet().EnsureKey(ctx) + require.NoError(t, err, "failed to create key for starknet") + + keys, err := app.GetKeyStore().StarkNet().GetAll() + require.NoError(t, err) + require.Len(t, keys, 1) + + transmitter := keys[0] + transmitters[chain.Selector] = transmitter.ID() + + // TODO: funding + default: + // TODO: other transmission keys unsupported for now } + } - evmChainID, err := chainsel.ChainIdFromSelector(chain.Selector) + for chain := range solchains { + ctype := chaintype.Solana + err = app.GetKeyStore().OCR2().EnsureKeys(ctx, ctype) + require.NoError(t, err) + keys, err := app.GetKeyStore().OCR2().GetAllOfType(ctype) require.NoError(t, err) + require.Len(t, keys, 1) + keybundle := keys[0] - cid := big.NewInt(int64(evmChainID)) - addrs, err2 := app.GetKeyStore().Eth().EnabledAddressesForChain(ctx, cid) - require.NoError(t, err2) - if len(addrs) == 1 { - // just fund the address - transmitters[evmChainID] = addrs[0] - } else { - // create key and fund it - _, err3 := app.GetKeyStore().Eth().Create(ctx, cid) - require.NoError(t, err3, "failed to create key for chain", evmChainID) - sendingKeys, err3 := app.GetKeyStore().Eth().EnabledAddressesForChain(ctx, cid) - require.NoError(t, err3) - require.Len(t, sendingKeys, 1) - transmitters[evmChainID] = sendingKeys[0] - } - backend := chain.Client.(*Backend).Sim - fundAddress(t, chain.DeployerKey, transmitters[evmChainID], assets.Ether(1000).ToInt(), backend) - // need to look more into it, but it seems like with sim chains nodes are sending txs with 0x from address - fundAddress(t, chain.DeployerKey, common.Address{}, assets.Ether(1000).ToInt(), backend) + keybundles[ctype] = keybundle + + err = app.GetKeyStore().Solana().EnsureKey(ctx) + require.NoError(t, err, "failed to create key for solana") + + solkeys, err := app.GetKeyStore().Solana().GetAll() + require.NoError(t, err) + require.Len(t, solkeys, 1) + + transmitter := solkeys[0] + transmitters[chain] = transmitter.ID() + + // TODO: funding } return Keys{ - PeerID: peerID, - CSA: csaKey, - TransmittersByEVMChainID: transmitters, - OCRKeyBundles: keybundles, + PeerID: peerID, + CSA: csaKey, + Transmitters: transmitters, + OCRKeyBundles: keybundles, } } @@ -313,6 +404,28 @@ func createConfigV2Chain(chainID uint64) *v2toml.EVMConfig { } } +func createSolanaChainConfig(chainID string, chain deployment.SolChain) *solcfg.TOMLConfig { + chainConfig := solcfg.Chain{} + chainConfig.SetDefaults() + + url, err := config.ParseURL(chain.URL) + if err != nil { + panic(err) + } + + return &solcfg.TOMLConfig{ + ChainID: &chainID, + Enabled: ptr(true), + Chain: chainConfig, + MultiNode: solcfg.MultiNodeConfig{}, + Nodes: []*solcfg.Node{{ + Name: ptr("primary"), + URL: url, + SendOnly: false, + }}, + } +} + func ptr[T any](v T) *T { return &v } var _ keystore.Eth = &EthKeystoreSim{} diff --git a/deployment/environment/memory/node_test.go b/deployment/environment/memory/node_test.go index 78bc2db90e5..b9562f0290a 100644 --- a/deployment/environment/memory/node_test.go +++ b/deployment/environment/memory/node_test.go @@ -15,7 +15,7 @@ import ( func TestNode(t *testing.T) { chains, _ := NewMemoryChains(t, 3, 5) ports := freeport.GetN(t, 1) - node := NewNode(t, ports[0], chains, zapcore.DebugLevel, false, deployment.CapabilityRegistryConfig{}) + node := NewNode(t, ports[0], chains, nil, zapcore.DebugLevel, false, deployment.CapabilityRegistryConfig{}) // We expect 3 transmitter keys keys, err := node.App.GetKeyStore().Eth().GetAll(tests.Context(t)) require.NoError(t, err) diff --git a/deployment/environment/nodeclient/chainlink.go b/deployment/environment/nodeclient/chainlink.go index 9b92dd12759..0fb3eca2659 100644 --- a/deployment/environment/nodeclient/chainlink.go +++ b/deployment/environment/nodeclient/chainlink.go @@ -7,6 +7,7 @@ import ( "math/big" "net/http" "os" + "strconv" "strings" "sync" "time" @@ -93,6 +94,11 @@ func (c *ChainlinkClient) URL() string { return c.Config.URL } +func (c *ChainlinkClient) WithRetryCount(retryCount int) *ChainlinkClient { + c.APIClient.SetRetryCount(retryCount) + return c +} + // Health returns all statuses health info func (c *ChainlinkClient) Health() (*HealthResponse, *http.Response, error) { respBody := &HealthResponse{} @@ -492,7 +498,7 @@ func (c *ChainlinkClient) DeleteP2PKey(id int) (*http.Response, error) { c.l.Info().Str(NodeURL, c.Config.URL).Int("ID", id).Msg("Deleting P2P Key") resp, err := c.APIClient.R(). SetPathParams(map[string]string{ - "id": fmt.Sprint(id), + "id": strconv.Itoa(id), }). Delete("/v2/keys/p2p/{id}") if err != nil { @@ -528,7 +534,7 @@ func (c *ChainlinkClient) UpdateEthKeyMaxGasPriceGWei(keyId string, gWei int) (* "keyId": keyId, }). SetQueryParams(map[string]string{ - "maxGasPriceGWei": fmt.Sprint(gWei), + "maxGasPriceGWei": strconv.Itoa(gWei), }). SetResult(ethKey). Put("/v2/keys/eth/{keyId}") @@ -1005,6 +1011,34 @@ func (c *ChainlinkClient) CreateStarkNetNode(node *StarkNetNodeAttributes) (*Sta return &response, resp.RawResponse, err } +// CreateTronChain creates a tron chain +func (c *ChainlinkClient) CreateTronChain(chain *TronChainAttributes) (*TronChainCreate, *http.Response, error) { + response := TronChainCreate{} + c.l.Info().Str(NodeURL, c.Config.URL).Str("Chain ID", chain.ChainID).Msg("Creating Tron Chain") + resp, err := c.APIClient.R(). + SetBody(chain). + SetResult(&response). + Post("/v2/chains/tron") + if err != nil { + return nil, nil, err + } + return &response, resp.RawResponse, err +} + +// CreateTronNode creates a tron node +func (c *ChainlinkClient) CreateTronNode(node *TronNodeAttributes) (*TronNodeCreate, *http.Response, error) { + response := TronNodeCreate{} + c.l.Info().Str(NodeURL, c.Config.URL).Str("Name", node.Name).Msg("Creating Tron Node") + resp, err := c.APIClient.R(). + SetBody(node). + SetResult(&response). + Post("/v2/nodes/tron") + if err != nil { + return nil, nil, err + } + return &response, resp.RawResponse, err +} + // InternalIP retrieves the inter-cluster IP of the Chainlink node, for use with inter-node communications func (c *ChainlinkClient) InternalIP() string { return c.Config.InternalIP @@ -1031,7 +1065,7 @@ func (c *ChainlinkClient) Profile(profileTime time.Duration, profileFunction fun "reportType": profileReport.Type, }). SetQueryParams(map[string]string{ - "seconds": fmt.Sprint(profileSeconds), + "seconds": strconv.Itoa(profileSeconds), }). Get("/v2/debug/pprof/{reportType}") if err != nil { @@ -1222,10 +1256,10 @@ func (c *ChainlinkClient) ReplayLogPollerFromBlock(fromBlock, evmChainID int64) resp, err := c.APIClient.R(). SetResult(&specObj). SetQueryParams(map[string]string{ - "evmChainID": fmt.Sprint(evmChainID), + "evmChainID": strconv.FormatInt(evmChainID, 10), }). SetPathParams(map[string]string{ - "fromBlock": fmt.Sprint(fromBlock), + "fromBlock": strconv.FormatInt(fromBlock, 10), }). Post("/v2/replay_from_block/{fromBlock}") if err != nil { diff --git a/deployment/environment/nodeclient/chainlink_models.go b/deployment/environment/nodeclient/chainlink_models.go index 84bea9cec31..1f4bbe4ebd0 100644 --- a/deployment/environment/nodeclient/chainlink_models.go +++ b/deployment/environment/nodeclient/chainlink_models.go @@ -520,6 +520,48 @@ type StarkNetNodeCreate struct { Data StarkNetNode `json:"data"` } +type TronChainConfig struct { + OCR2CachePollPeriod null.String + OCR2CacheTTL null.String + RequestTimeout null.String + TxTimeout null.Bool + TxSendFrequency null.String + TxMaxBatchSize null.String +} + +// TronChainAttributes is the model that represents the tron chain +type TronChainAttributes struct { + ChainID string `json:"chainID"` + Config TronChainConfig `json:"config"` +} + +// TronChain is the model that represents the tron chain when read +type TronChain struct { + Attributes TronChainAttributes `json:"attributes"` +} + +// TronChainCreate is the model that represents the tron chain when created +type TronChainCreate struct { + Data TronChain `json:"data"` +} + +// TronNodeAttributes is the model that represents the tron node +type TronNodeAttributes struct { + Name string `json:"name"` + ChainID string `json:"chainId"` + URL string `json:"url"` +} + +// TronNode is the model that represents the tron node when read +type TronNode struct { + Attributes TronNodeAttributes `json:"attributes"` +} + +// TronNodeCreate is the model that represents the tron node when created +type TronNodeCreate struct { + Data TronNode `json:"data"` +} + // SpecForm is the form used when creating a v2 job spec, containing the TOML of the v2 job type SpecForm struct { TOML string `json:"toml"` diff --git a/deployment/environment/web/sdk/client/client.go b/deployment/environment/web/sdk/client/client.go index e0a56b9e642..331376b2e9f 100644 --- a/deployment/environment/web/sdk/client/client.go +++ b/deployment/environment/web/sdk/client/client.go @@ -3,13 +3,15 @@ package client import ( "context" "encoding/json" + "errors" "fmt" - "github.com/Khan/genqlient/graphql" - "github.com/sethvargo/go-retry" "net/http" "strings" "time" + "github.com/Khan/genqlient/graphql" + "github.com/sethvargo/go-retry" + "github.com/smartcontractkit/chainlink/deployment/environment/web/sdk/client/doer" "github.com/smartcontractkit/chainlink/deployment/environment/web/sdk/internal/generated" ) @@ -61,7 +63,7 @@ func New(baseURI string, creds Credentials) (Client, error) { endpoints: ep, credentials: creds, } - + err := retry.Do(context.Background(), retry.WithMaxDuration(10*time.Second, retry.NewFibonacci(2*time.Second)), func(ctx context.Context) error { err := c.login() if err != nil { @@ -87,7 +89,7 @@ func (c *client) FetchCSAPublicKey(ctx context.Context) (*string, error) { return nil, err } if keys == nil || len(keys.CsaKeys.GetResults()) == 0 { - return nil, fmt.Errorf("no CSA keys found") + return nil, errors.New("no CSA keys found") } return &keys.CsaKeys.GetResults()[0].PublicKey, nil } @@ -98,7 +100,7 @@ func (c *client) FetchP2PPeerID(ctx context.Context) (*string, error) { return nil, err } if keys == nil || len(keys.P2pKeys.GetResults()) == 0 { - return nil, fmt.Errorf("no P2P keys found") + return nil, errors.New("no P2P keys found") } return &keys.P2pKeys.GetResults()[0].PeerID, nil } @@ -109,7 +111,7 @@ func (c *client) FetchOCR2KeyBundleID(ctx context.Context, chainType string) (st return "", err } if keyBundles == nil || len(keyBundles.GetOcr2KeyBundles().Results) == 0 { - return "", fmt.Errorf("no ocr2 keybundle found, check if ocr2 is enabled") + return "", errors.New("no ocr2 keybundle found, check if ocr2 is enabled") } for _, keyBundle := range keyBundles.GetOcr2KeyBundles().Results { if keyBundle.ChainType == generated.OCR2ChainType(chainType) { @@ -125,7 +127,7 @@ func (c *client) FetchAccountAddress(ctx context.Context, chainID string) (*stri return nil, err } if keys == nil || len(keys.EthKeys.GetResults()) == 0 { - return nil, fmt.Errorf("no accounts found") + return nil, errors.New("no accounts found") } for _, keyDetail := range keys.EthKeys.GetResults() { if keyDetail.GetChain().Enabled && keyDetail.GetChain().Id == chainID { @@ -141,7 +143,7 @@ func (c *client) FetchKeys(ctx context.Context, chainType string) ([]string, err return nil, err } if keys == nil { - return nil, fmt.Errorf("no accounts found") + return nil, errors.New("no accounts found") } switch generated.OCR2ChainType(chainType) { case generated.OCR2ChainTypeAptos: @@ -183,12 +185,12 @@ func (c *client) GetJobDistributor(ctx context.Context, id string) (generated.Fe return generated.FeedsManagerParts{}, err } if res == nil { - return generated.FeedsManagerParts{}, fmt.Errorf("no feeds manager found") + return generated.FeedsManagerParts{}, errors.New("no feeds manager found") } if success, ok := res.GetFeedsManager().(*generated.GetFeedsManagerFeedsManager); ok { return success.FeedsManagerParts, nil } - return generated.FeedsManagerParts{}, fmt.Errorf("failed to get feeds manager") + return generated.FeedsManagerParts{}, errors.New("failed to get feeds manager") } func (c *client) ListJobDistributors(ctx context.Context) (*generated.ListFeedsManagersResponse, error) { @@ -238,12 +240,12 @@ func (c *client) CreateJobDistributorChainConfig(ctx context.Context, in JobDist return "", err } if res == nil { - return "", fmt.Errorf("failed to create feeds manager chain config") + return "", errors.New("failed to create feeds manager chain config") } if success, ok := res.GetCreateFeedsManagerChainConfig().(*generated.CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccess); ok { return success.ChainConfig.Id, nil } - return "", fmt.Errorf("failed to create feeds manager chain config") + return "", errors.New("failed to create feeds manager chain config") } func (c *client) DeleteJobDistributorChainConfig(ctx context.Context, id string) error { @@ -252,12 +254,12 @@ func (c *client) DeleteJobDistributorChainConfig(ctx context.Context, id string) return err } if res == nil { - return fmt.Errorf("failed to delete feeds manager chain config") + return errors.New("failed to delete feeds manager chain config") } if _, ok := res.GetDeleteFeedsManagerChainConfig().(*generated.DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess); ok { return nil } - return fmt.Errorf("failed to delete feeds manager chain config") + return errors.New("failed to delete feeds manager chain config") } func (c *client) GetJobProposal(ctx context.Context, id string) (*generated.GetJobProposalJobProposal, error) { @@ -266,12 +268,12 @@ func (c *client) GetJobProposal(ctx context.Context, id string) (*generated.GetJ return nil, err } if proposal == nil { - return nil, fmt.Errorf("no job proposal found") + return nil, errors.New("no job proposal found") } if success, ok := proposal.GetJobProposal().(*generated.GetJobProposalJobProposal); ok { return success, nil } - return nil, fmt.Errorf("failed to get job proposal") + return nil, errors.New("failed to get job proposal") } func (c *client) ApproveJobProposalSpec(ctx context.Context, id string, force bool) (*JobProposalApprovalSuccessSpec, error) { @@ -289,7 +291,7 @@ func (c *client) ApproveJobProposalSpec(ctx context.Context, id string, force bo return &cmd, nil } } - return nil, fmt.Errorf("failed to approve job proposal spec") + return nil, errors.New("failed to approve job proposal spec") } func (c *client) CancelJobProposalSpec(ctx context.Context, id string) (*generated.CancelJobProposalSpecResponse, error) { @@ -327,7 +329,7 @@ func (c *client) login() error { cookieHeader := res.Header.Get("Set-Cookie") if cookieHeader == "" { - return fmt.Errorf("no cookie found in header") + return errors.New("no cookie found in header") } c.cookie = strings.Split(cookieHeader, ";")[0] diff --git a/deployment/environment/web/sdk/client/types.go b/deployment/environment/web/sdk/client/types.go index d213ee161c6..9ecc2cc72ea 100644 --- a/deployment/environment/web/sdk/client/types.go +++ b/deployment/environment/web/sdk/client/types.go @@ -3,7 +3,7 @@ package client import ( "bytes" "encoding/json" - "fmt" + "errors" "reflect" ) @@ -47,7 +47,7 @@ type JobProposalApprovalSuccessSpec struct { func DecodeInput(in, out any) error { if reflect.TypeOf(out).Kind() != reflect.Ptr || reflect.ValueOf(out).IsNil() { - return fmt.Errorf("out type must be a non-nil pointer") + return errors.New("out type must be a non-nil pointer") } jsonBytes, err := json.Marshal(in) if err != nil { diff --git a/deployment/environment_test.go b/deployment/environment_test.go index 37a7e3baeae..5ebbe0be1ce 100644 --- a/deployment/environment_test.go +++ b/deployment/environment_test.go @@ -9,16 +9,16 @@ import ( func TestNode_OCRConfigForChainSelector(t *testing.T) { var m = map[chain_selectors.ChainDetails]OCRConfig{ - chain_selectors.ChainDetails{ + { ChainSelector: chain_selectors.APTOS_TESTNET.Selector, ChainName: chain_selectors.APTOS_TESTNET.Name, - }: OCRConfig{ + }: { KeyBundleID: "aptos bundle 1", }, - chain_selectors.ChainDetails{ + { ChainSelector: chain_selectors.ETHEREUM_MAINNET_ARBITRUM_1.Selector, ChainName: chain_selectors.ETHEREUM_MAINNET_ARBITRUM_1.Name, - }: OCRConfig{ + }: { KeyBundleID: "arb bundle 1", }, } diff --git a/deployment/evm_kmsclient.go b/deployment/evm_kmsclient.go index b28a3842930..811125827af 100644 --- a/deployment/evm_kmsclient.go +++ b/deployment/evm_kmsclient.go @@ -11,6 +11,7 @@ import ( "os" "github.com/aws/aws-sdk-go/aws/session" + "github.com/pkg/errors" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/kms" @@ -59,10 +60,10 @@ type KMS struct { func NewKMSClient(config KMS) (KMSClient, error) { if config.KmsDeployerKeyId == "" { - return nil, fmt.Errorf("KMS key ID is required") + return nil, errors.New("KMS key ID is required") } if config.KmsDeployerKeyRegion == "" { - return nil, fmt.Errorf("KMS key region is required") + return nil, errors.New("KMS key region is required") } var awsSessionFn AwsSessionFn if config.AwsProfileName != "" { @@ -94,7 +95,7 @@ func (c *EVMKMSClient) GetKMSTransactOpts(ctx context.Context, chainID *big.Int) pubKeyBytes := secp256k1.S256().Marshal(ecdsaPublicKey.X, ecdsaPublicKey.Y) keyAddr := crypto.PubkeyToAddress(*ecdsaPublicKey) if chainID == nil { - return nil, fmt.Errorf("chainID is required") + return nil, errors.New("chainID is required") } signer := types.LatestSignerForChainID(chainID) @@ -195,7 +196,7 @@ func recoverEthSignature(expectedPublicKeyBytes, txHash, r, s []byte) ([]byte, e } if hex.EncodeToString(recoveredPublicKeyBytes) != hex.EncodeToString(expectedPublicKeyBytes) { - return nil, fmt.Errorf("can not reconstruct public key from sig") + return nil, errors.New("can not reconstruct public key from sig") } } @@ -238,15 +239,15 @@ func KMSConfigFromEnvVars() (KMS, error) { var exists bool config.KmsDeployerKeyId, exists = os.LookupEnv("KMS_DEPLOYER_KEY_ID") if !exists { - return config, fmt.Errorf("KMS_DEPLOYER_KEY_ID is required") + return config, errors.New("KMS_DEPLOYER_KEY_ID is required") } config.KmsDeployerKeyRegion, exists = os.LookupEnv("KMS_DEPLOYER_KEY_REGION") if !exists { - return config, fmt.Errorf("KMS_DEPLOYER_KEY_REGION is required") + return config, errors.New("KMS_DEPLOYER_KEY_REGION is required") } config.AwsProfileName, exists = os.LookupEnv("AWS_PROFILE") if !exists { - return config, fmt.Errorf("AWS_PROFILE is required") + return config, errors.New("AWS_PROFILE is required") } return config, nil } diff --git a/deployment/go.mod b/deployment/go.mod index e5307c9da60..f40142f2232 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -9,7 +9,7 @@ replace github.com/smartcontractkit/chainlink/v2 => ../ // Using a separate inline `require` here to avoid surrounding line changes // creating potential merge conflicts. -require github.com/smartcontractkit/chainlink/v2 v2.0.0-20241206210521-125d98cdaf66 +require github.com/smartcontractkit/chainlink/v2 v2.0.0-20241212011003-de1a8f5e5b42 require ( github.com/Khan/genqlient v0.7.0 @@ -18,6 +18,7 @@ require ( github.com/aws/aws-sdk-go v1.54.19 github.com/deckarep/golang-set/v2 v2.6.0 github.com/ethereum/go-ethereum v1.14.11 + github.com/gagliardetto/solana-go v1.12.0 github.com/go-resty/resty/v2 v2.15.3 github.com/google/uuid v1.6.0 github.com/hashicorp/consul/sdk v0.16.1 @@ -27,18 +28,21 @@ require ( github.com/rs/zerolog v1.33.0 github.com/sethvargo/go-retry v0.2.4 github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix - github.com/smartcontractkit/chain-selectors v1.0.34 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241213122413-5e8f65dd6b1b - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241214155818-b403079b2805 + github.com/smartcontractkit/chain-selectors v1.0.36 + github.com/smartcontractkit/chainlink-ccip v0.0.0-20250120130359-cc025272bbff + github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250103152858-8973fd0c912b + github.com/smartcontractkit/chainlink-common v0.4.2-0.20250116214855-f49c5c27db51 github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 + github.com/smartcontractkit/chainlink-solana v1.1.1-0.20250117143722-fb6416c087a5 + github.com/smartcontractkit/chainlink-testing-framework/framework v0.4.2-0.20250110073248-456673e8eea2 github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 - github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 - github.com/stretchr/testify v1.9.0 + github.com/smartcontractkit/libocr v0.0.0-20241223215956-e5b78d8e3919 + github.com/stretchr/testify v1.10.0 github.com/test-go/testify v1.1.4 github.com/testcontainers/testcontainers-go v0.34.0 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.27.0 - golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c + golang.org/x/exp v0.0.0-20241210194714-1829a127f884 golang.org/x/oauth2 v0.23.0 golang.org/x/sync v0.10.0 google.golang.org/grpc v1.67.1 @@ -48,7 +52,6 @@ require ( ) require ( - contrib.go.opencensus.io/exporter/stackdriver v0.13.5 // indirect cosmossdk.io/api v0.3.1 // indirect cosmossdk.io/core v0.5.1 // indirect cosmossdk.io/depinject v1.0.0-alpha.4 // indirect @@ -104,6 +107,7 @@ require ( github.com/aws/constructs-go/constructs/v10 v10.4.2 // indirect github.com/aws/jsii-runtime-go v1.104.0 // indirect github.com/aws/smithy-go v1.22.0 // indirect + github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3 // indirect github.com/benbjohnson/clock v1.3.5 // indirect @@ -114,10 +118,11 @@ require ( github.com/blendle/zapdriver v1.3.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect + github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129 // indirect github.com/buger/jsonparser v1.1.1 // indirect github.com/bytecodealliance/wasmtime-go/v23 v23.0.0 // indirect - github.com/bytedance/sonic v1.11.6 // indirect - github.com/bytedance/sonic/loader v0.1.1 // indirect + github.com/bytedance/sonic v1.12.3 // indirect + github.com/bytedance/sonic/loader v0.2.0 // indirect github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b // indirect github.com/c9s/goprocinfo v0.0.0-20210130143923-c95fcf8c64a8 // indirect github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5 // indirect @@ -160,9 +165,8 @@ require ( github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect github.com/dennwc/varint v1.0.0 // indirect - github.com/dfuse-io/logging v0.0.0-20210109005628-b97a57253f70 // indirect github.com/dgraph-io/badger/v2 v2.2007.4 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect @@ -173,6 +177,7 @@ require ( github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dominikbraun/graph v0.23.0 // indirect + github.com/doyensec/safeurl v0.2.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.7.0 // indirect github.com/edsrzf/mmap-go v1.1.0 // indirect @@ -188,10 +193,10 @@ require ( github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect - github.com/gabriel-vasile/mimetype v1.4.3 // indirect - github.com/gagliardetto/binary v0.7.7 // indirect - github.com/gagliardetto/solana-go v1.8.4 // indirect + github.com/gabriel-vasile/mimetype v1.4.6 // indirect + github.com/gagliardetto/binary v0.8.0 // indirect github.com/gagliardetto/treeout v0.1.4 // indirect + github.com/gagliardetto/utilz v0.1.1 // indirect github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/getsentry/sentry-go v0.27.0 // indirect github.com/gin-contrib/sessions v0.0.5 // indirect @@ -218,7 +223,7 @@ require ( github.com/go-openapi/validate v0.23.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.22.0 // indirect + github.com/go-playground/validator/v10 v10.22.1 // indirect github.com/go-redis/redis/v8 v8.11.5 // indirect github.com/go-viper/mapstructure/v2 v2.1.0 // indirect github.com/go-webauthn/webauthn v0.9.4 // indirect @@ -268,6 +273,7 @@ require ( github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/gtank/merlin v0.1.1 // indirect github.com/gtank/ristretto255 v0.1.2 // indirect + github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026 // indirect github.com/hashicorp/consul/api v1.29.2 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-bexpr v0.1.10 // indirect @@ -332,7 +338,7 @@ require ( github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.14 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect github.com/miekg/dns v1.1.61 // indirect github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect @@ -364,6 +370,7 @@ require ( github.com/oklog/run v1.1.0 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/onsi/gomega v1.34.2 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/opentracing-contrib/go-grpc v0.0.0-20210225150812-73cb765af46e // indirect @@ -374,29 +381,30 @@ require ( github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect - github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect + github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/prometheus/alertmanager v0.27.0 // indirect github.com/prometheus/client_golang v1.20.5 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.60.0 // indirect + github.com/prometheus/common v0.60.1 // indirect github.com/prometheus/common/sigv4 v0.1.0 // indirect github.com/prometheus/exporter-toolkit v0.11.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/prometheus/prometheus v0.54.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect - github.com/rivo/uniseg v0.4.4 // indirect + github.com/rivo/uniseg v0.4.7 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect github.com/rogpeppe/go-internal v1.13.1 // indirect github.com/rs/cors v1.10.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/ryanuber/go-glob v1.0.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sanity-io/litter v1.5.5 // indirect github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect - github.com/sasha-s/go-deadlock v0.3.1 // indirect + github.com/sasha-s/go-deadlock v0.3.5 // indirect github.com/scylladb/go-reflectx v1.0.1 // indirect github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect github.com/sercand/kuberesolver/v5 v5.1.1 // indirect @@ -407,11 +415,11 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e // indirect - github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3 // indirect + github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250115135646-ac859d85e7e3 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.1 // indirect + github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250115203616-a2ea5e50b260 // indirect github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241210172617-6fd1891d0fbc // indirect - github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 // indirect + github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20250117171710-b6481e9fcb34 // indirect github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 // indirect github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.5 // indirect github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2 // indirect @@ -428,13 +436,12 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.19.0 // indirect github.com/status-im/keycard-go v0.2.0 // indirect - github.com/streamingfast/logging v0.0.0-20220405224725-2755dab2ce75 // indirect + github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/supranational/blst v0.3.13 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tendermint/go-amino v0.16.0 // indirect - github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 // indirect github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a // indirect github.com/tidwall/btree v1.6.0 // indirect github.com/tidwall/gjson v1.17.0 // indirect @@ -463,7 +470,6 @@ require ( go.etcd.io/etcd/client/pkg/v3 v3.5.14 // indirect go.etcd.io/etcd/client/v3 v3.5.14 // indirect go.mongodb.org/mongo-driver v1.15.0 // indirect - go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/collector/pdata v1.12.0 // indirect go.opentelemetry.io/collector/semconv v0.105.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 // indirect @@ -493,13 +499,13 @@ require ( go4.org/netipx v0.0.0-20230125063823-8449b0a6169f // indirect golang.org/x/arch v0.11.0 // indirect golang.org/x/crypto v0.31.0 // indirect - golang.org/x/mod v0.21.0 // indirect - golang.org/x/net v0.30.0 // indirect + golang.org/x/mod v0.22.0 // indirect + golang.org/x/net v0.32.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/term v0.27.0 // indirect golang.org/x/text v0.21.0 // indirect golang.org/x/time v0.7.0 // indirect - golang.org/x/tools v0.26.0 // indirect + golang.org/x/tools v0.28.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect gonum.org/v1/gonum v0.15.1 // indirect diff --git a/deployment/go.sum b/deployment/go.sum index f988f4f37bc..4cc20b9b4e3 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -3,7 +3,6 @@ cel.dev/expr v0.17.0/go.mod h1:HCwbrn+qQoHPXgfz6cl2J0hDybnX2N1sQQkl9EggXx8= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= @@ -54,10 +53,6 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.45.0 h1:5av0QcIVj77t+44mV4gffFC/LscFRUhto6UBMB5SimM= cloud.google.com/go/storage v1.45.0/go.mod h1:wpPblkIuMP5jCB/E48Pz9zIo2S/zD8g+ITmxKkPCITE= -contrib.go.opencensus.io/exporter/stackdriver v0.12.6/go.mod h1:8x999/OcIPy5ivx/wDiV7Gx4D+VUPODf0mWRGRc5kSk= -contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= -contrib.go.opencensus.io/exporter/stackdriver v0.13.5 h1:TNaexHK16gPUoc7uzELKOU7JULqccn1NDuqUxmxSqfo= -contrib.go.opencensus.io/exporter/stackdriver v0.13.5/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= cosmossdk.io/api v0.3.1 h1:NNiOclKRR0AOlO4KIqeaG6PS6kswOMhHD0ir0SscNXE= cosmossdk.io/api v0.3.1/go.mod h1:DfHfMkiNA2Uhy8fj0JJlOCYOBp4eWUUJ1te5zBGNyIw= cosmossdk.io/core v0.5.1 h1:vQVtFrIYOQJDV3f7rw4pjjVqc1id4+mE0L9hHP66pyI= @@ -75,7 +70,6 @@ cosmossdk.io/tools/rosetta v0.2.1/go.mod h1:Pqdc1FdvkNV3LcNIkYWt2RQY6IP1ge6YWZk8 dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -118,8 +112,6 @@ github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/Depado/ginprom v1.8.0 h1:zaaibRLNI1dMiiuj1MKzatm8qrcHzikMlCc1anqOdyo= github.com/Depado/ginprom v1.8.0/go.mod h1:XBaKzeNBqPF4vxJpNLincSQZeMDnZp1tIbU0FU0UKgg= -github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0= -github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.3 h1:cb3br57K508pQEFgBxn9GDhPS9HefpyMPK1RzmtMNzk= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.3/go.mod h1:itPGVDKf9cC/ov4MdvJ2QZ0khw4bfoo9jzwTJlaxy2k= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.3 h1:xir5X8TS8UBVPWg2jHL+cSTf0jZgqYQSA54TscSt1/0= @@ -159,7 +151,6 @@ github.com/XSAM/otelsql v0.27.0 h1:i9xtxtdcqXV768a5C6SoT/RkG+ue3JTOgkYInzlTOqs= github.com/XSAM/otelsql v0.27.0/go.mod h1:0mFB3TvLa7NCuhm/2nU7/b2wEtsczkj8Rey8ygO7V+A= github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8= github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= -github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -181,7 +172,6 @@ github.com/alicebob/miniredis/v2 v2.30.4/go.mod h1:b25qWj4fCEsBeAAR2mlb0ufImGC6u github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129/go.mod h1:rFgpPQZYZ8vdbc+48xibu8ALc3yeyd64IhHS+PU6Yyg= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA= @@ -210,8 +200,6 @@ github.com/avast/retry-go/v4 v4.6.0 h1:K9xNA+KeB8HHc2aWFuLb25Offp+0iVRXEvFx8IinR github.com/avast/retry-go/v4 v4.6.0/go.mod h1:gvWlPhBVsvBbLkVGDg/KwvBv0bEkCOLRRSHKIr2PyOE= github.com/awalterschulze/gographviz v2.0.3+incompatible h1:9sVEXJBJLwGX7EQVhLm2elIKCm7P2YHFC8v6096G09E= github.com/awalterschulze/gographviz v2.0.3+incompatible/go.mod h1:GEV5wmg4YquNw7v1kkyoX9etIk8yVmXj+AkDHuuETHs= -github.com/aws/aws-sdk-go v1.22.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.54.19 h1:tyWV+07jagrNiCcGRzRhdtVjQs7Vy41NwsuOcl0IbVI= github.com/aws/aws-sdk-go v1.54.19/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= @@ -247,6 +235,8 @@ github.com/aws/jsii-runtime-go v1.104.0 h1:651Sh6J2FtatfnVzlOQ3/Ye1WWPAseZ6E/tSQ github.com/aws/jsii-runtime-go v1.104.0/go.mod h1:7ZmQXxV0AAhhvv/GaHX4n6zbgA1tSRVdnQYAJbIhXHk= github.com/aws/smithy-go v1.22.0 h1:uunKnWlcoL3zO7q+gG2Pk53joueEOsnNB28QdMsmiMM= github.com/aws/smithy-go v1.22.0/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= +github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 h1:WWB576BN5zNSZc/M9d/10pqEx5VHNhaQ/yOVAkmj5Yo= +github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df h1:GSoSVRLoBaFpOOds6QyY1L8AX7uoY+Ln3BHc22W40X0= @@ -267,7 +257,6 @@ github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 h1:41iFGWnSlI2 github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= @@ -284,16 +273,19 @@ github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6 github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= +github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129 h1:gfAMKE626QEuKG3si0pdTRcr/YEbBoxY+3GOH3gWvl4= +github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129/go.mod h1:u9UyCz2eTrSGy6fbupqJ54eY5c4IC8gREQ1053dK12U= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/bxcodec/faker v2.0.1+incompatible h1:P0KUpUw5w6WJXwrPfv35oc91i4d8nf40Nwln+M/+faA= github.com/bxcodec/faker v2.0.1+incompatible/go.mod h1:BNzfpVdTwnFJ6GtfYTcQu6l6rHShT+veBxNCnjCx5XM= github.com/bytecodealliance/wasmtime-go/v23 v23.0.0 h1:NJvU4S8KEk1GnF6+FvlnzMD/8wXTj/mYJSG6Q4yu3Pw= github.com/bytecodealliance/wasmtime-go/v23 v23.0.0/go.mod h1:5YIL+Ouiww2zpO7u+iZ1U1G5NvmwQYaXdmCZQGjQM0U= -github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= -github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= -github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= +github.com/bytedance/sonic v1.12.3 h1:W2MGa7RCU1QTeYRTPE3+88mVC0yXmsRQRChiyVocVjU= +github.com/bytedance/sonic v1.12.3/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/bytedance/sonic/loader v0.2.0 h1:zNprn+lsIP06C/IqCHs3gPQIvnvpKbbxyXQP1iU4kWM= +github.com/bytedance/sonic/loader v0.2.0/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b h1:6+ZFm0flnudZzdSE0JxlhR2hKnGPcNB35BjQf4RYQDY= github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M= github.com/c9s/goprocinfo v0.0.0-20210130143923-c95fcf8c64a8 h1:SjZ2GvvOononHOpK84APFuMvxqsk3tEIaKH/z4Rpu3g= @@ -372,9 +364,7 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -385,7 +375,6 @@ github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7 github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= @@ -424,9 +413,8 @@ github.com/creachadair/taskgroup v0.4.2 h1:jsBLdAJE42asreGss2xZGZ8fJra7WtwnHWeJF github.com/creachadair/taskgroup v0.4.2/go.mod h1:qiXUOSrbwAY3u0JPGTzObbE3yf9hcXHDKBZ2ZjpCbgM= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= -github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E= +github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0= +github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= github.com/danielkov/gin-helmet v0.0.0-20171108135313-1387e224435e h1:5jVSh2l/ho6ajWhSPNN84eHEdq3dp0T7+f6r3Tc6hsk= @@ -440,27 +428,22 @@ github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80N github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/dennwc/varint v1.0.0 h1:kGNFFSSw8ToIy3obO/kKr8U9GZYUAxQEVuix4zfDWzE= github.com/dennwc/varint v1.0.0/go.mod h1:hnItb35rvZvJrbTALZtY/iQfDs48JKRG1RPpgziApxA= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= -github.com/dfuse-io/logging v0.0.0-20201110202154-26697de88c79/go.mod h1:V+ED4kT/t/lKtH99JQmKIb0v9WL3VaYkJ36CfHlVECI= -github.com/dfuse-io/logging v0.0.0-20210109005628-b97a57253f70 h1:CuJS05R9jmNlUK8GOxrEELPbfXm0EuGh/30LjkjN5vo= -github.com/dfuse-io/logging v0.0.0-20210109005628-b97a57253f70/go.mod h1:EoK/8RFbMEteaCaz89uessDTnCWjbbcr+DXcBh4el5o= github.com/dgraph-io/badger/v2 v2.2007.4 h1:TRWBQg8UrlUhaFdco01nO2uXwzKS7zd+HVdwV/GHc4o= github.com/dgraph-io/badger/v2 v2.2007.4/go.mod h1:vSw/ax2qojzbN6eXHIx6KPKtCSHJN/Uz0X0VPruTIhk= github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+UbP35JkH8yB7MYb4q/qhBarqZE6g= github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= github.com/digitalocean/godo v1.118.0 h1:lkzGFQmACrVCp7UqH1sAi4JK/PWwlc5aaxubgorKmC4= @@ -477,6 +460,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dominikbraun/graph v0.23.0 h1:TdZB4pPqCLFxYhdyMFb1TBdFxp8XLcJfTTBQucVPgCo= github.com/dominikbraun/graph v0.23.0/go.mod h1:yOjYyogZLY1LSG9E33JWZJiq5k83Qy2C6POAuiViluc= +github.com/doyensec/safeurl v0.2.1 h1:DY15JorEfQsnpBWhBkVQIkaif2jfxCC14PIuGDsjDVs= +github.com/doyensec/safeurl v0.2.1/go.mod h1:wzSXqC/6Z410qHz23jtBWT+wQ8yTxcY0p8bZH/4EZIg= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= @@ -533,16 +518,19 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= -github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= -github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= -github.com/gagliardetto/binary v0.7.7 h1:QZpT38+sgoPg+TIQjH94sLbl/vX+nlIRA37pEyOsjfY= -github.com/gagliardetto/binary v0.7.7/go.mod h1:mUuay5LL8wFVnIlecHakSZMvcdqfs+CsotR5n77kyjM= +github.com/gabriel-vasile/mimetype v1.4.6 h1:3+PzJTKLkvgjeTbts6msPJt4DixhT4YtFNf1gtGe3zc= +github.com/gabriel-vasile/mimetype v1.4.6/go.mod h1:JX1qVKqZd40hUPpAfiNTe0Sne7hdfKSbOqqmkq8GCXc= +github.com/gagliardetto/binary v0.8.0 h1:U9ahc45v9HW0d15LoN++vIXSJyqR/pWw8DDlhd7zvxg= +github.com/gagliardetto/binary v0.8.0/go.mod h1:2tfj51g5o9dnvsc+fL3Jxr22MuWzYXwx9wEoN0XQ7/c= github.com/gagliardetto/gofuzz v1.2.2 h1:XL/8qDMzcgvR4+CyRQW9UGdwPRPMHVJfqQ/uMvSUuQw= github.com/gagliardetto/gofuzz v1.2.2/go.mod h1:bkH/3hYLZrMLbfYWA0pWzXmi5TTRZnu4pMGZBkqMKvY= -github.com/gagliardetto/solana-go v1.8.4 h1:vmD/JmTlonyXGy39bAo0inMhmbdAwV7rXZtLDMZeodE= -github.com/gagliardetto/solana-go v1.8.4/go.mod h1:i+7aAyNDTHG0jK8GZIBSI4OVvDqkt2Qx+LklYclRNG8= +github.com/gagliardetto/hashsearch v0.0.0-20191005111333-09dd671e19f9/go.mod h1:513DXpQPzeRo7d4dsCP3xO3XI8hgvruMl9njxyQeraQ= +github.com/gagliardetto/solana-go v1.12.0 h1:rzsbilDPj6p+/DOPXBMLhwMZeBgeRuXjm5zQFCoXgsg= +github.com/gagliardetto/solana-go v1.12.0/go.mod h1:l/qqqIN6qJJPtxW/G1PF4JtcE3Zg2vD2EliZrr9Gn5k= github.com/gagliardetto/treeout v0.1.4 h1:ozeYerrLCmCubo1TcIjFiOWTTGteOOHND1twdFpgwaw= github.com/gagliardetto/treeout v0.1.4/go.mod h1:loUefvXTrlRG5rYmJmExNryyBRh8f89VZhmMOyCyqok= +github.com/gagliardetto/utilz v0.1.1 h1:/etW4hl607emKg6R6Lj9jRJ9d6ue2AQOyjhuAwjzs1U= +github.com/gagliardetto/utilz v0.1.1/go.mod h1:b+rGFkRHz3HWJD0RYMzat47JyvbTtpE0iEcYTRJTLLA= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813 h1:Uc+IZ7gYqAf/rSGFplbWBSHaGolEQlNLgMgSE3ccnIQ= @@ -619,8 +607,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao= -github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA= +github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/go-resty/resty/v2 v2.15.3 h1:bqff+hcqAflpiF591hhJzNdkRsFhlB96CYfBwSFvql8= @@ -664,7 +652,6 @@ github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVI github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -700,7 +687,6 @@ github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= @@ -784,12 +770,10 @@ github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/rpc v1.2.0/go.mod h1:V4h9r+4sF5HnzqbwIez0fKSpANP0zlYd3qR7p36jkTQ= github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY= github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/grafana/dskit v0.0.0-20231120170505-765e343eda4f h1:gyojr97YeWZ70pKNakWv5/tKwBHuLy3icnIeCo9gQr4= @@ -814,15 +798,12 @@ github.com/graph-gophers/graphql-go v1.5.0 h1:fDqblo50TEpD0LY7RXk/LFVYEVqo3+tXMN github.com/graph-gophers/graphql-go v1.5.0/go.mod h1:YtmJZDLbF1YYNrlNAuiO5zAStUWc3XZT07iGsVqe1Os= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= @@ -835,6 +816,8 @@ github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is= github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc= github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o= +github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026 h1:BpJ2o0OR5FV7vrkDYfXYVJQeMNWa8RhklZOpW2ITAIQ= +github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026/go.mod h1:5Scbynm8dF1XAPwIwkGPqzkM/shndPm79Jd1003hTjE= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/api v1.29.2 h1:aYyRn8EdE2mSfG14S1+L9Qkjtz8RzmaWh6AcNGRNwPw= github.com/hashicorp/consul/api v1.29.2/go.mod h1:0YObcaLNDSbtlgzIRtmRXI1ZkeuK0trCBxwZQ4MYnIk= @@ -893,7 +876,6 @@ github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09 github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru v0.6.0 h1:uL2shRDx7RTrOrTCUZEGP/wJUFiUI8QT6E7z5o8jga4= github.com/hashicorp/golang-lru v0.6.0/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= @@ -996,10 +978,8 @@ github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0f github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= @@ -1010,7 +990,6 @@ github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4= github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -1035,7 +1014,6 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= @@ -1085,7 +1063,6 @@ github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/z github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= @@ -1117,8 +1094,8 @@ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= -github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= @@ -1127,6 +1104,7 @@ github.com/mfridman/interpolate v0.0.2 h1:pnuTK7MQIxxFz1Gr+rjSIx9u7qVjf5VOoM/u6B github.com/mfridman/interpolate v0.0.2/go.mod h1:p+7uk6oE07mpE/Ik1b8EckO0O4ZXiGAfshKBWLUM9Xg= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs= github.com/miekg/dns v1.1.61/go.mod h1:mnAarhS3nWaW+NVP2wTkYVIZyHNJ098SJZUki3eykwQ= @@ -1186,7 +1164,6 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= -github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= @@ -1207,7 +1184,6 @@ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+ github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1 h1:dOYG7LS/WK00RWZc8XGgcUTlTxpp3mKhdR2Q9z9HbXM= github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1/go.mod h1:mpRZBD8SJ55OIICQ3iWH0Yz3cjzA61JdqMLoWXeB2+8= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= @@ -1225,8 +1201,8 @@ github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vv github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= -github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= +github.com/onsi/ginkgo/v2 v2.20.1 h1:YlVIbqct+ZmnEph770q9Q7NVAz4wwIiVNahee6JyUzo= +github.com/onsi/ginkgo/v2 v2.20.1/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= @@ -1265,9 +1241,8 @@ github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNH github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= -github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 h1:hDSdbBuw3Lefr6R18ax0tZ2BJeNB3NehB3trOwYBsdU= -github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 h1:Dx7Ovyv/SFnMFw3fD4oEoeorXc6saIiQ23LrGLth0Gw= +github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= @@ -1295,7 +1270,6 @@ github.com/pressly/goose/v3 v3.21.1/go.mod h1:sqthmzV8PitchEkjecFJII//l43dLOCzfW github.com/prometheus/alertmanager v0.27.0 h1:V6nTa2J5V4s8TG4C4HtrBP/WNSebCCTYGGv4qecA/+I= github.com/prometheus/alertmanager v0.27.0/go.mod h1:8Ia/R3urPmbzJ8OsdvmZvIprDwvwmYCmUbwBL+jlPOE= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= @@ -1308,21 +1282,18 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1: github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= -github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= +github.com/prometheus/common v0.60.1 h1:FUas6GcOw66yB/73KC+BOZoFJmbo/1pojoILArPAaSc= +github.com/prometheus/common v0.60.1/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/common/sigv4 v0.1.0 h1:qoVebwtwwEhS85Czm2dSROY5fTo2PAPEVdDeppTwGX4= github.com/prometheus/common/sigv4 v0.1.0/go.mod h1:2Jkxxk9yYvCkE5G1sQT7GuEXm57JrvHu9k5YwTjsNtI= github.com/prometheus/exporter-toolkit v0.11.0 h1:yNTsuZ0aNCNFQ3aFTD2uhPOvr4iD7fdBvKPAEGkNf+g= github.com/prometheus/exporter-toolkit v0.11.0/go.mod h1:BVnENhnNecpwoTLiABx7mrPB/OLRIgN74qlQbV+FK1Q= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= @@ -1331,7 +1302,6 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/prometheus v0.54.1 h1:vKuwQNjnYN2/mDoWfHXDhAsz/68q/dQDb+YbcEqU7MQ= github.com/prometheus/prometheus v0.54.1/go.mod h1:xlLByHhk2g3ycakQGrMaU8K7OySZx98BzeCR99991NY= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= @@ -1339,11 +1309,10 @@ github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqn github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4= github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC5sZ4OhQ3+NtdbZ6oBDKQwq5Ou+FI= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= @@ -1362,6 +1331,8 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= +github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= @@ -1370,8 +1341,8 @@ github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQ github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= -github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= -github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= +github.com/sasha-s/go-deadlock v0.3.5 h1:tNCOEEDG6tBqrNDOX35j/7hL5FcFViG6awUGROb2NsU= +github.com/sasha-s/go-deadlock v0.3.5/go.mod h1:bugP6EGbdGYObIlx7pUZtWqlvo8k9H6vCBBsiChJQ5U= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/scaleway/scaleway-sdk-go v1.0.0-beta.29 h1:BkTk4gynLjguayxrYxZoMZjBnAOh7ntQvUkOFmkMqPU= github.com/scaleway/scaleway-sdk-go v1.0.0-beta.29/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg= @@ -1411,28 +1382,34 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix h1:DPJD++yKLSx0EfT+U14P8vLVxjXFmoIETiCO9lVwQo8= github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= -github.com/smartcontractkit/chain-selectors v1.0.34 h1:MJ17OGu8+jjl426pcKrJkCf3fePb3eCreuAnUA3RBj4= -github.com/smartcontractkit/chain-selectors v1.0.34/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= +github.com/smartcontractkit/chain-selectors v1.0.36 h1:KSpO8I+JOiuyN4FuXsV471sPorGF//PAqwq2Cm4gRK0= +github.com/smartcontractkit/chain-selectors v1.0.36/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241213122413-5e8f65dd6b1b h1:iSQJ6ng4FhEswf8SXunGkaJlVP3E3JlgLB8Oo2f3Ud4= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241213122413-5e8f65dd6b1b/go.mod h1:F8xQAIW0ymb2BZhqn89sWZLXreJhM5KDVF6Qb4y44N0= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241214155818-b403079b2805 h1:Pz8jB/6qe10xT10h2S3LFYJrnebNpG5rJ/w16HZGwPQ= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241214155818-b403079b2805/go.mod h1:yti7e1+G9hhkYhj+L5sVUULn9Bn3bBL5/AxaNqdJ5YQ= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250120130359-cc025272bbff h1:ZEOlcleVdT0/y9V5yjgFJF0j7MpvdrFmKis/xmFNIgE= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250120130359-cc025272bbff/go.mod h1:JJZMCB75aVSAiPNW032F9WUKTlLztTd8bbQB5MEaZa4= +github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250103152858-8973fd0c912b h1:UBXi9Yj8YSMHDDaxQLu273x1fWjyEL9xP58nuJsqZfg= +github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250103152858-8973fd0c912b/go.mod h1:Bmwq4lNb5tE47sydN0TKetcLEGbgl+VxHEWp4S0LI60= +github.com/smartcontractkit/chainlink-common v0.4.2-0.20250116214855-f49c5c27db51 h1:YdjQiEu5uHWM1ApwdV+nLyJmu1+tt3IeiwPKNGoXwBI= +github.com/smartcontractkit/chainlink-common v0.4.2-0.20250116214855-f49c5c27db51/go.mod h1:yti7e1+G9hhkYhj+L5sVUULn9Bn3bBL5/AxaNqdJ5YQ= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3 h1:aeiBdBHGY8QNftps+VqrIk6OnfeeOD5z4jrAabW4ZSc= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3/go.mod h1:AS6zY2BkcRwfiGzNabGbHhfrLSrXrcI/GmjnT4jQ5/s= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250115135646-ac859d85e7e3 h1:GcPYNVFYjB065CNq0h8nK/VeU08nUkHgBX0cJIEpuHY= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250115135646-ac859d85e7e3/go.mod h1:pDZagSGjs9U+l4YIFhveDznMHqxuuz+5vRxvVgpbdr8= github.com/smartcontractkit/chainlink-feeds v0.1.1 h1:JzvUOM/OgGQA1sOqTXXl52R6AnNt+Wg64sVG+XSA49c= github.com/smartcontractkit/chainlink-feeds v0.1.1/go.mod h1:55EZ94HlKCfAsUiKUTNI7QlE/3d3IwTlsU3YNa/nBb4= +github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250115203616-a2ea5e50b260 h1:See2isL6KdrTJDlVKWv8qiyYqWhYUcubU2e5yKXV1oY= +github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250115203616-a2ea5e50b260/go.mod h1:4JqpgFy01LaqG1yM2iFTzwX3ZgcAvW9WdstBZQgPHzU= github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 h1:0ewLMbAz3rZrovdRUCgd028yOXX8KigB4FndAUdI2kM= github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0/go.mod h1:/dVVLXrsp+V0AbcYGJo3XMzKg3CkELsweA/TTopCsKE= github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0 h1:ZBat8EBvE2LpSQR9U1gEbRV6PfAkiFdINmQ8nVnXIAQ= github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241210172617-6fd1891d0fbc h1:dssRwJhmzJkUN/OajaDj2GsxBn+Tupk3bI1BkPEoJg0= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241210172617-6fd1891d0fbc/go.mod h1:p8aUDfJeley6oer7y+Ucd3edOtRlMTnWg3mN6rhaLWo= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 h1:tNS7U9lrxkFvEuyxQv11HHOiV9LPDGC9wYEy+yM/Jv4= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8/go.mod h1:EBrEgcdIbwepqguClkv8Ohy7CbyWSJaE4EC9aBJlQK0= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20250117143722-fb6416c087a5 h1:kDW6Ab8vGRK2y+DPEvvhU2It8UCS9FK5ZQqIVjDfpK4= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20250117143722-fb6416c087a5/go.mod h1:uHVnYLMgJ1rTcNoVxhBpy38t69gXq0j+LN3TkcIVE3U= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20250117171710-b6481e9fcb34 h1:tQCjnIjY88AClWXApaTS+/ihQYM1GVCrbD9W00eh11E= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20250117171710-b6481e9fcb34/go.mod h1:lgG9JT2P19KnYuBheKIis5ZeCO+AaSta+RfzvwDQS2Y= +github.com/smartcontractkit/chainlink-testing-framework/framework v0.4.2-0.20250110073248-456673e8eea2 h1:nTUoe7GZLw17nPLV5t3Vgf4U4pf+VW0Uko5xpNiKdKU= +github.com/smartcontractkit/chainlink-testing-framework/framework v0.4.2-0.20250110073248-456673e8eea2/go.mod h1:mMUqvS3BZfvN1OfK4OFTYf1+T0X6nwmSXJM2keaPsSM= github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 h1:T0kbw07Vb6xUyA9MIJZfErMgWseWi1zf7cYvRpoq7ug= github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13/go.mod h1:1CKUOzoK+Ga19WuhRH9pxZ+qUUnrlIx108VEA6qSzeQ= github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 h1:VIxK8u0Jd0Q/VuhmsNm6Bls6Tb31H/sA3A/rbc5hnhg= @@ -1443,8 +1420,8 @@ github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2 h1:7bCdbTUW github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2/go.mod h1:MltlNu3jcXm/DyLN98I5TFNtu/o1NNAcaPAFKMXWk70= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA= -github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 h1:NzZGjaqez21I3DU7objl3xExTH4fxYvzTqar8DC6360= -github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= +github.com/smartcontractkit/libocr v0.0.0-20241223215956-e5b78d8e3919 h1:IpGoPTXpvllN38kT2z2j13sifJMz4nbHglidvop7mfg= +github.com/smartcontractkit/libocr v0.0.0-20241223215956-e5b78d8e3919/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de h1:n0w0rKF+SVM+S3WNlup6uabXj2zFlFNfrlsKCMMb/co= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:Sl2MF/Fp3fgJIVzhdGhmZZX2BlnM0oUUyBP4s4xYb6o= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de h1:66VQxXx3lvTaAZrMBkIcdH9VEjujUEvmBQdnyOJnkOc= @@ -1455,7 +1432,6 @@ github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/sony/gobreaker v0.5.0 h1:dRCvqm0P490vZPmy7ppEk2qCnCieBooFJ+YoXGYB+yg= @@ -1474,7 +1450,6 @@ github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= @@ -1484,15 +1459,13 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= -github.com/streamingfast/logging v0.0.0-20220405224725-2755dab2ce75 h1:ZqpS7rAhhKD7S7DnrpEdrnW1/gZcv82ytpMviovkli4= -github.com/streamingfast/logging v0.0.0-20220405224725-2755dab2ce75/go.mod h1:VlduQ80JcGJSargkRU4Sg9Xo63wZD/l8A5NC/Uo1/uU= +github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 h1:RN5mrigyirb8anBEtdjtHFIufXdacyTi6i4KBfeNXeo= +github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091/go.mod h1:VlduQ80JcGJSargkRU4Sg9Xo63wZD/l8A5NC/Uo1/uU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= @@ -1512,8 +1485,9 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= @@ -1523,9 +1497,6 @@ github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDd github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= -github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0= -github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 h1:3SNcvBmEPE1YlB1JpVZouslJpI3GBNoiqW7+wb0Rz7w= -github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0= github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE= github.com/test-go/testify v1.1.4/go.mod h1:rH7cfJo/47vWGdi4GPj16x3/t1xGOj2YxzmNQzk2ghU= github.com/testcontainers/testcontainers-go v0.34.0 h1:5fbgF0vIN5u+nD3IWabQwRybuB4GY8G2HHgCkbMzMHo= @@ -1534,12 +1505,10 @@ github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a h1:YuO+afVc3eqrj github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a/go.mod h1:/sfW47zCZp9FrtGcWyo1VjbgDaodxX9ovZvgLb/MxaA= github.com/tidwall/btree v1.6.0 h1:LDZfKfQIBHGHWSwckhXI0RPSXzlo+KYdjK7FWSqOzzg= github.com/tidwall/btree v1.6.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= -github.com/tidwall/gjson v1.9.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM= github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= -github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= @@ -1547,7 +1516,6 @@ github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFA github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= @@ -1574,10 +1542,8 @@ github.com/urfave/cli v1.22.14 h1:ebbhrRiGK2i4naQJr+1Xj92HXZCrK7MsyTS/ob3HnAk= github.com/urfave/cli v1.22.14/go.mod h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA= github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fastjson v1.4.1 h1:hrltpHpIpkaxll8QltMU8c3QZ5+qIiCL8yKqPFJI/yE= github.com/valyala/fastjson v1.4.1/go.mod h1:nV6MsjxL2IMJQUoHDIrjEI7oLyeqK6aBD7EFWPsvP8o= -github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/vektah/gqlparser/v2 v2.5.11 h1:JJxLtXIoN7+3x6MBdtIP59TP1RANnY7pXOaDnADQSf8= github.com/vektah/gqlparser/v2 v2.5.11/go.mod h1:1rCcfwB2ekJofmluGWXMSEnPMZgbxzwj6FaZ/4OT8Cc= github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs= @@ -1586,10 +1552,6 @@ github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/ github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= -github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= -github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= @@ -1597,7 +1559,6 @@ github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGC github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= -github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -1624,7 +1585,6 @@ go.dedis.ch/kyber/v3 v3.1.0/go.mod h1:kXy7p3STAurkADD+/aZcsznZGKVHEqbtmdIzvPfrs1 go.dedis.ch/protobuf v1.0.5/go.mod h1:eIV4wicvi6JK0q/QnfIEGeSFNG0ZeB24kzut5+HaRLo= go.dedis.ch/protobuf v1.0.7/go.mod h1:pv5ysfkDX/EawiPqcW3ikOxsL5t+BqnV6xHSmE79KI4= go.dedis.ch/protobuf v1.0.11/go.mod h1:97QR256dnkimeNdfmURz0wAMNVbd1VmLXhG1CrTYrJ4= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= @@ -1636,12 +1596,10 @@ go.etcd.io/etcd/client/pkg/v3 v3.5.14/go.mod h1:8uMgAokyG1czCtIdsq+AGyYQMvpIKnSv go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= go.etcd.io/etcd/client/v3 v3.5.14 h1:CWfRs4FDaDoSz81giL7zPpZH2Z35tbOrAJkkjMqOupg= go.etcd.io/etcd/client/v3 v3.5.14/go.mod h1:k3XfdV/VIHy/97rqWjoUzrj9tk7GgJGH9J8L4dNXmAk= -go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= go.mongodb.org/mongo-driver v1.15.0 h1:rJCKC8eEliewXjZGf0ddURtl7tTVy1TK3bfl0gkUSLc= go.mongodb.org/mongo-driver v1.15.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -1715,22 +1673,18 @@ go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKY go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/ratelimit v0.2.0/go.mod h1:YYBV4e4naJvhpitQrWJu1vCpgB7CboMe0qhltKt6mUg= go.uber.org/ratelimit v0.3.1 h1:K4qVE+byfv/B3tC+4nYWP7v/6SimcO7HzHekoMNBma0= go.uber.org/ratelimit v0.3.1/go.mod h1:6euWsTB6U/Nb3X++xEUXA8ciPJvr19Q/0h1+oDcJhRk= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go4.org/netipx v0.0.0-20230125063823-8449b0a6169f h1:ketMxHg+vWm3yccyYiq+uK8D3fRmna2Fcj+awpQp84s= go4.org/netipx v0.0.0-20230125063823-8449b0a6169f/go.mod h1:tgPU4N2u9RByaTN3NC2p9xOzyFpte4jYwsIIRF7XlSc= -golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.11.0 h1:KXV8WWKCXm6tRpLirl2szsO5j/oOODwZf4hATmGVNs4= golang.org/x/arch v0.11.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1748,12 +1702,12 @@ golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= @@ -1768,8 +1722,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY= -golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= +golang.org/x/exp v0.0.0-20241210194714-1829a127f884 h1:Y/Mj/94zIQQGHVSv1tTtQBDaQaJe62U9bkDZKKyhPCU= +golang.org/x/exp v0.0.0-20241210194714-1829a127f884/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1798,15 +1752,14 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= +golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -1857,8 +1810,8 @@ golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= -golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= +golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= +golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1894,7 +1847,6 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1910,7 +1862,6 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1986,7 +1937,6 @@ golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -2035,7 +1985,6 @@ golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -2081,8 +2030,8 @@ golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= -golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= -golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= +golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8= +golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -2100,7 +2049,6 @@ google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEt google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.10.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= @@ -2125,7 +2073,6 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= @@ -2136,7 +2083,6 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -2186,7 +2132,6 @@ google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmE google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -2239,16 +2184,13 @@ gopkg.in/guregu/null.v4 v4.0.0/go.mod h1:YoQhUrADuG3i9WqesrCmpNRwm1ypAgSHYqoOcTu gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -2298,7 +2240,6 @@ nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYm pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw= pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= diff --git a/deployment/helpers.go b/deployment/helpers.go index dfbbccc2698..d8e15d0200d 100644 --- a/deployment/helpers.go +++ b/deployment/helpers.go @@ -14,6 +14,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/rpc" "github.com/pkg/errors" chain_selectors "github.com/smartcontractkit/chain-selectors" @@ -87,7 +88,7 @@ func parseError(txError error) (string, error) { return callErr.Data, nil } -func ParseErrorFromABI(errorString string, contractABI string) (string, error) { +func parseErrorFromABI(errorString string, contractABI string) (string, error) { parsedAbi, err := abi.JSON(strings.NewReader(contractABI)) if err != nil { return "", errors.Wrap(err, "error loading ABI") @@ -112,6 +113,29 @@ func ParseErrorFromABI(errorString string, contractABI string) (string, error) { return "", errors.New("error not found in ABI") } +// DecodeErr decodes an error from a contract call using the contract's ABI. +// If the error is not decodable, it returns the original error. +func DecodeErr(encodedABI string, err error) error { + if err == nil { + return nil + } + //revive:disable + var d rpc.DataError + ok := errors.As(err, &d) + if ok { + encErr, ok := d.ErrorData().(string) + if !ok { + return fmt.Errorf("error without error data: %s", d.Error()) + } + errStr, parseErr := parseErrorFromABI(encErr, encodedABI) + if parseErr != nil { + return fmt.Errorf("failed to decode error '%s' with abi: %w", encErr, parseErr) + } + return fmt.Errorf("contract error: %s", errStr) + } + return fmt.Errorf("cannot decode error with abi: %w", err) +} + // ContractDeploy represents the result of an EVM contract deployment // via an abigen Go binding. It contains all the return values // as they are useful in different ways. @@ -157,7 +181,7 @@ func DeployContract[C any]( func IsValidChainSelector(cs uint64) error { if cs == 0 { - return fmt.Errorf("chain selector must be set") + return errors.New("chain selector must be set") } _, err := chain_selectors.GetSelectorFamily(cs) if err != nil { diff --git a/deployment/keystone/changeset/accept_ownership.go b/deployment/keystone/changeset/accept_ownership.go index 662a4c2dcfa..dd709523bc2 100644 --- a/deployment/keystone/changeset/accept_ownership.go +++ b/deployment/keystone/changeset/accept_ownership.go @@ -5,7 +5,7 @@ import ( "github.com/ethereum/go-ethereum/common" - kslib "github.com/smartcontractkit/chainlink/deployment/keystone" + kslib "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/changeset" diff --git a/deployment/keystone/changeset/accept_ownership_test.go b/deployment/keystone/changeset/accept_ownership_test.go index d949e63c7aa..4007fde4f79 100644 --- a/deployment/keystone/changeset/accept_ownership_test.go +++ b/deployment/keystone/changeset/accept_ownership_test.go @@ -35,7 +35,7 @@ func TestAcceptAllOwnership(t *testing.T) { }, { Changeset: commonchangeset.WrapChangeSet(changeset.DeployForwarder), - Config: registrySel, + Config: changeset.DeployForwarderRequest{}, }, { Changeset: commonchangeset.WrapChangeSet(changeset.DeployFeedsConsumer), diff --git a/deployment/keystone/changeset/addrbook_utils.go b/deployment/keystone/changeset/addrbook_utils.go index 4b6d6d151b1..fa4dd27ca18 100644 --- a/deployment/keystone/changeset/addrbook_utils.go +++ b/deployment/keystone/changeset/addrbook_utils.go @@ -8,11 +8,12 @@ import ( ccipowner "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/keystone" - capReg "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/feeds_consumer" - keystoneForwarder "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder" - ocr3Capability "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability" + + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" + capReg "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + feeds_consumer "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/feeds_consumer_1_0_0" + keystoneForwarder "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder_1_0_0" + ocr3Capability "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability_1_0_0" ) // contractConstructor is a function type that takes an address and a client, @@ -56,7 +57,7 @@ func capRegistriesFromAddrBook(addrBook deployment.AddressBook, chain deployment return getContractsFromAddrBook[capReg.CapabilitiesRegistry]( addrBook, chain, - keystone.CapabilitiesRegistry, + internal.CapabilitiesRegistry, capReg.NewCapabilitiesRegistry, ) } @@ -66,7 +67,7 @@ func ocr3FromAddrBook(addrBook deployment.AddressBook, chain deployment.Chain) ( return getContractsFromAddrBook[ocr3Capability.OCR3Capability]( addrBook, chain, - keystone.OCR3Capability, + internal.OCR3Capability, ocr3Capability.NewOCR3Capability, ) } @@ -76,7 +77,7 @@ func forwardersFromAddrBook(addrBook deployment.AddressBook, chain deployment.Ch return getContractsFromAddrBook[keystoneForwarder.KeystoneForwarder]( addrBook, chain, - keystone.KeystoneForwarder, + internal.KeystoneForwarder, keystoneForwarder.NewKeystoneForwarder, ) } @@ -86,7 +87,7 @@ func feedsConsumersFromAddrBook(addrBook deployment.AddressBook, chain deploymen return getContractsFromAddrBook[feeds_consumer.KeystoneFeedsConsumer]( addrBook, chain, - keystone.FeedConsumer, + internal.FeedConsumer, feeds_consumer.NewKeystoneFeedsConsumer, ) } @@ -96,7 +97,7 @@ func proposersFromAddrBook(addrBook deployment.AddressBook, chain deployment.Cha return getContractsFromAddrBook[ccipowner.ManyChainMultiSig]( addrBook, chain, - keystone.ProposerManyChainMultiSig, + internal.ProposerManyChainMultiSig, ccipowner.NewManyChainMultiSig, ) } @@ -106,7 +107,7 @@ func timelocksFromAddrBook(addrBook deployment.AddressBook, chain deployment.Cha return getContractsFromAddrBook[ccipowner.RBACTimelock]( addrBook, chain, - keystone.RBACTimelock, + internal.RBACTimelock, ccipowner.NewRBACTimelock, ) } diff --git a/deployment/keystone/changeset/append_node_capabilities.go b/deployment/keystone/changeset/append_node_capabilities.go index 688d4fd8d2f..9ae1923d270 100644 --- a/deployment/keystone/changeset/append_node_capabilities.go +++ b/deployment/keystone/changeset/append_node_capabilities.go @@ -1,14 +1,15 @@ package changeset import ( + "errors" "fmt" "github.com/ethereum/go-ethereum/common" "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - kslib "github.com/smartcontractkit/chainlink/deployment/keystone" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" ) @@ -31,7 +32,7 @@ func AppendNodeCapabilities(env deployment.Environment, req *AppendNodeCapabilit out := deployment.ChangesetOutput{} if req.UseMCMS() { if r.Ops == nil { - return out, fmt.Errorf("expected MCMS operation to be non-nil") + return out, errors.New("expected MCMS operation to be non-nil") } timelocksPerChain := map[uint64]common.Address{ c.Chain.Selector: c.ContractSet.Timelock.Address(), @@ -63,7 +64,7 @@ func (req *AppendNodeCapabilitiesRequest) convert(e deployment.Environment) (*in if !ok { return nil, fmt.Errorf("registry chain selector %d does not exist in environment", req.RegistryChainSel) } - resp, err := kslib.GetContractSets(e.Logger, &kslib.GetContractSetsRequest{ + resp, err := internal.GetContractSets(e.Logger, &internal.GetContractSetsRequest{ Chains: map[uint64]deployment.Chain{req.RegistryChainSel: registryChain}, AddressBook: e.ExistingAddresses, }) diff --git a/deployment/keystone/changeset/append_node_capabilities_test.go b/deployment/keystone/changeset/append_node_capabilities_test.go index bfc01b309f5..3cf6081e966 100644 --- a/deployment/keystone/changeset/append_node_capabilities_test.go +++ b/deployment/keystone/changeset/append_node_capabilities_test.go @@ -10,7 +10,8 @@ import ( commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/test" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) @@ -29,15 +30,15 @@ func TestAppendNodeCapabilities(t *testing.T) { caps = []kcr.CapabilitiesRegistryCapability{capA, capB} ) t.Run("no mcms", func(t *testing.T) { - te := SetupTestEnv(t, TestConfig{ - WFDonConfig: DonConfig{N: 4}, - AssetDonConfig: DonConfig{N: 4}, - WriterDonConfig: DonConfig{N: 4}, + te := test.SetupTestEnv(t, test.TestConfig{ + WFDonConfig: test.DonConfig{N: 4}, + AssetDonConfig: test.DonConfig{N: 4}, + WriterDonConfig: test.DonConfig{N: 4}, NumChains: 1, }) newCapabilities := make(map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability) - for id, _ := range te.WFNodes { + for id := range te.WFNodes { k, err := p2pkey.MakePeerID(id) require.NoError(t, err) newCapabilities[k] = caps @@ -51,23 +52,23 @@ func TestAppendNodeCapabilities(t *testing.T) { csOut, err := changeset.AppendNodeCapabilities(te.Env, &cfg) require.NoError(t, err) - require.Len(t, csOut.Proposals, 0) + require.Empty(t, csOut.Proposals) require.Nil(t, csOut.AddressBook) validateCapabilityAppends(t, te, newCapabilities) }) }) t.Run("with mcms", func(t *testing.T) { - te := SetupTestEnv(t, TestConfig{ - WFDonConfig: DonConfig{N: 4}, - AssetDonConfig: DonConfig{N: 4}, - WriterDonConfig: DonConfig{N: 4}, + te := test.SetupTestEnv(t, test.TestConfig{ + WFDonConfig: test.DonConfig{N: 4}, + AssetDonConfig: test.DonConfig{N: 4}, + WriterDonConfig: test.DonConfig{N: 4}, NumChains: 1, UseMCMS: true, }) newCapabilities := make(map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability) - for id, _ := range te.WFNodes { + for id := range te.WFNodes { k, err := p2pkey.MakePeerID(id) require.NoError(t, err) newCapabilities[k] = caps @@ -104,11 +105,10 @@ func TestAppendNodeCapabilities(t *testing.T) { require.NoError(t, err) validateCapabilityAppends(t, te, newCapabilities) }) - } // validateUpdate checks reads nodes from the registry and checks they have the expected updates -func validateCapabilityAppends(t *testing.T, te TestEnv, appended map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability) { +func validateCapabilityAppends(t *testing.T, te test.TestEnv, appended map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability) { registry := te.ContractSets()[te.RegistrySelector].CapabilitiesRegistry wfP2PIDs := p2pIDs(t, maps.Keys(te.WFNodes)) nodes, err := registry.GetNodesByP2PIds(nil, wfP2PIDs) diff --git a/deployment/keystone/changeset/compatiblity.go b/deployment/keystone/changeset/compatiblity.go new file mode 100644 index 00000000000..7f80b6ab53d --- /dev/null +++ b/deployment/keystone/changeset/compatiblity.go @@ -0,0 +1,95 @@ +package changeset + +import "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" + +//TODO: KS-673 refactor internal package to reduce and remove the duplication + +// OracleConfig is the configuration for an oracle +type OracleConfig = internal.OracleConfig + +// OCR3OnchainConfig is the onchain configuration of an OCR2 contract +type OCR3OnchainConfig = internal.OCR2OracleConfig + +// NodeKeys is a set of public keys for a node +type NodeKeys = internal.NodeKeys + +// TopLevelConfigSource is the top level configuration source +type TopLevelConfigSource = internal.TopLevelConfigSource + +// GenerateOCR3Config generates an OCR3 config +var GenerateOCR3Config = internal.GenerateOCR3Config + +// FeedConsumer is a feed consumer contract type +var FeedConsumer = internal.FeedConsumer + +// KeystoneForwarder is a keystone forwarder contract type +var KeystoneForwarder = internal.KeystoneForwarder + +// GetContractSetsRequest is a request to get contract sets +type GetContractSetsRequest = internal.GetContractSetsRequest + +// GetContractSetsResponse is a response to get contract sets +type GetContractSetsResponse = internal.GetContractSetsResponse + +// GetContractSets gets contract sets +var GetContractSets = internal.GetContractSets + +// RegisterCapabilitiesRequest is a request to register capabilities +type RegisterCapabilitiesRequest = internal.RegisterCapabilitiesRequest + +// RegisterCapabilitiesResponse is a response to register capabilities +type RegisterCapabilitiesResponse = internal.RegisterCapabilitiesResponse + +// RegisterCapabilities registers capabilities +var RegisterCapabilities = internal.RegisterCapabilities + +// RegisterNOPSRequest is a request to register NOPS +type RegisterNOPSRequest = internal.RegisterNOPSRequest + +// RegisterNOPSResponse is a response to register NOPS +type RegisterNOPSResponse = internal.RegisterNOPSResponse + +// RegisterNOPS registers NOPS +var RegisterNOPS = internal.RegisterNOPS + +// RegisterNodesRequest is a request to register nodes with the capabilities registry +type RegisterNodesRequest = internal.RegisterNodesRequest + +// RegisterNodesResponse is a response to register nodes with the capabilities registry +type RegisterNodesResponse = internal.RegisterNodesResponse + +// RegisterNodes registers nodes with the capabilities registry +var RegisterNodes = internal.RegisterNodes + +// RegisteredCapability is a wrapper of a capability and its ID +type RegisteredCapability = internal.RegisteredCapability + +// FromCapabilitiesRegistryCapability converts a capabilities registry capability to a registered capability +var FromCapabilitiesRegistryCapability = internal.FromCapabilitiesRegistryCapability + +// RegisterDonsRequest is a request to register Dons with the capabilities registry +type RegisterDonsRequest = internal.RegisterDonsRequest + +// RegisterDonsResponse is a response to register Dons with the capabilities registry +type RegisterDonsResponse = internal.RegisterDonsResponse + +// RegisterDons registers Dons with the capabilities registry +var RegisterDons = internal.RegisterDons + +// DONToRegister is the minimal information needed to register a DON with the capabilities registry +type DONToRegister = internal.DONToRegister + +// ConfigureContractsRequest is a request to configure ALL the contracts +type ConfigureContractsRequest = internal.ConfigureContractsRequest + +// ConfigureContractsResponse is a response to configure ALL the contracts +type ConfigureContractsResponse = internal.ConfigureContractsResponse + +// DonCapabilities is a set of capabilities hosted by a set of node operators +// in is in a convenient form to handle the CLO representation of the nop data +type DonCapabilities = internal.DonCapabilities + +type DeployRequest = internal.DeployRequest +type DeployResponse = internal.DeployResponse + +type ContractSet = internal.ContractSet diff --git a/deployment/keystone/changeset/configure_contracts.go b/deployment/keystone/changeset/configure_contracts.go index 3a92782e12b..b57ebb0ed52 100644 --- a/deployment/keystone/changeset/configure_contracts.go +++ b/deployment/keystone/changeset/configure_contracts.go @@ -7,7 +7,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/deployment" - kslib "github.com/smartcontractkit/chainlink/deployment/keystone" + kslib "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" ) var _ deployment.ChangeSet[InitialContractsCfg] = ConfigureInitialContractsChangeset diff --git a/deployment/keystone/changeset/deploy_consumer.go b/deployment/keystone/changeset/deploy_consumer.go index fc7992e2a7d..5442a21576a 100644 --- a/deployment/keystone/changeset/deploy_consumer.go +++ b/deployment/keystone/changeset/deploy_consumer.go @@ -1,10 +1,11 @@ package changeset import ( + "errors" "fmt" "github.com/smartcontractkit/chainlink/deployment" - kslib "github.com/smartcontractkit/chainlink/deployment/keystone" + kslib "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" ) type DeployFeedsConsumerRequest struct { @@ -19,7 +20,7 @@ func DeployFeedsConsumer(env deployment.Environment, req *DeployFeedsConsumerReq lggr := env.Logger chain, ok := env.Chains[chainSelector] if !ok { - return deployment.ChangesetOutput{}, fmt.Errorf("chain not found in environment") + return deployment.ChangesetOutput{}, errors.New("chain not found in environment") } ab := deployment.NewMemoryAddressBook() deployResp, err := kslib.DeployFeedsConsumer(chain, ab) diff --git a/deployment/keystone/changeset/deploy_consumer_test.go b/deployment/keystone/changeset/deploy_consumer_test.go index 9a1e8f57da7..e73986b6ecf 100644 --- a/deployment/keystone/changeset/deploy_consumer_test.go +++ b/deployment/keystone/changeset/deploy_consumer_test.go @@ -36,5 +36,5 @@ func TestDeployFeedsConsumer(t *testing.T) { // no feeds consumer registry on chain 1 require.NotEqual(t, registrySel, env.AllChainSelectors()[1]) oaddrs, _ := resp.AddressBook.AddressesForChain(env.AllChainSelectors()[1]) - require.Len(t, oaddrs, 0) + require.Empty(t, oaddrs) } diff --git a/deployment/keystone/changeset/deploy_forwarder.go b/deployment/keystone/changeset/deploy_forwarder.go index 1e4066770bd..8a9cdf4d681 100644 --- a/deployment/keystone/changeset/deploy_forwarder.go +++ b/deployment/keystone/changeset/deploy_forwarder.go @@ -1,27 +1,43 @@ package changeset import ( + "errors" "fmt" + "maps" + "slices" "github.com/ethereum/go-ethereum/common" "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - kslib "github.com/smartcontractkit/chainlink/deployment/keystone" + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" ) -var _ deployment.ChangeSet[uint64] = DeployForwarder +var _ deployment.ChangeSet[DeployForwarderRequest] = DeployForwarder + +type DeployForwarderRequest struct { + ChainSelectors []uint64 // filter to only deploy to these chains; if empty, deploy to all chains +} // DeployForwarder deploys the KeystoneForwarder contract to all chains in the environment // callers must merge the output addressbook with the existing one // TODO: add selectors to deploy only to specific chains -func DeployForwarder(env deployment.Environment, _ uint64) (deployment.ChangesetOutput, error) { +func DeployForwarder(env deployment.Environment, cfg DeployForwarderRequest) (deployment.ChangesetOutput, error) { lggr := env.Logger ab := deployment.NewMemoryAddressBook() - for _, chain := range env.Chains { + selectors := cfg.ChainSelectors + if len(selectors) == 0 { + selectors = slices.Collect(maps.Keys(env.Chains)) + } + for _, sel := range selectors { + chain, ok := env.Chains[sel] + if !ok { + return deployment.ChangesetOutput{}, fmt.Errorf("chain with selector %d not found", sel) + } lggr.Infow("deploying forwarder", "chainSelector", chain.Selector) - forwarderResp, err := kslib.DeployForwarder(chain, ab) + forwarderResp, err := internal.DeployForwarder(chain, ab) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to deploy KeystoneForwarder to chain selector %d: %w", chain.Selector, err) } @@ -45,7 +61,7 @@ type ConfigureForwardContractsRequest struct { func (r ConfigureForwardContractsRequest) Validate() error { if len(r.WFNodeIDs) == 0 { - return fmt.Errorf("WFNodeIDs must not be empty") + return errors.New("WFNodeIDs must not be empty") } return nil } @@ -55,7 +71,7 @@ func (r ConfigureForwardContractsRequest) UseMCMS() bool { } func ConfigureForwardContracts(env deployment.Environment, req ConfigureForwardContractsRequest) (deployment.ChangesetOutput, error) { - wfDon, err := kslib.NewRegisteredDon(env, kslib.RegisteredDonConfig{ + wfDon, err := internal.NewRegisteredDon(env, internal.RegisteredDonConfig{ NodeIDs: req.WFNodeIDs, Name: req.WFDonName, RegistryChainSel: req.RegistryChainSel, @@ -63,15 +79,15 @@ func ConfigureForwardContracts(env deployment.Environment, req ConfigureForwardC if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to create registered don: %w", err) } - r, err := kslib.ConfigureForwardContracts(&env, kslib.ConfigureForwarderContractsRequest{ - Dons: []kslib.RegisteredDon{*wfDon}, + r, err := internal.ConfigureForwardContracts(&env, internal.ConfigureForwarderContractsRequest{ + Dons: []internal.RegisteredDon{*wfDon}, UseMCMS: req.UseMCMS(), }) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to configure forward contracts: %w", err) } - cresp, err := kslib.GetContractSets(env.Logger, &kslib.GetContractSetsRequest{ + cresp, err := internal.GetContractSets(env.Logger, &internal.GetContractSetsRequest{ Chains: env.Chains, AddressBook: env.ExistingAddresses, }) @@ -82,7 +98,7 @@ func ConfigureForwardContracts(env deployment.Environment, req ConfigureForwardC var out deployment.ChangesetOutput if req.UseMCMS() { if len(r.OpsPerChain) == 0 { - return out, fmt.Errorf("expected MCMS operation to be non-nil") + return out, errors.New("expected MCMS operation to be non-nil") } for chainSelector, op := range r.OpsPerChain { contracts := cresp.ContractSets[chainSelector] @@ -97,7 +113,7 @@ func ConfigureForwardContracts(env deployment.Environment, req ConfigureForwardC timelocksPerChain, proposerMCMSes, []timelock.BatchChainOperation{op}, - "proposal to set update nodes", + "proposal to set forwarder config", req.MCMSConfig.MinDuration, ) if err != nil { diff --git a/deployment/keystone/changeset/deploy_forwarder_test.go b/deployment/keystone/changeset/deploy_forwarder_test.go index e04bac6d264..40ef0c02aeb 100644 --- a/deployment/keystone/changeset/deploy_forwarder_test.go +++ b/deployment/keystone/changeset/deploy_forwarder_test.go @@ -4,9 +4,8 @@ import ( "fmt" "testing" - "go.uber.org/zap/zapcore" - "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/deployment" @@ -14,6 +13,7 @@ import ( "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/test" ) func TestDeployForwarder(t *testing.T) { @@ -33,7 +33,7 @@ func TestDeployForwarder(t *testing.T) { // deploy forwarder env.ExistingAddresses = ab - resp, err := changeset.DeployForwarder(env, registrySel) + resp, err := changeset.DeployForwarder(env, changeset.DeployForwarderRequest{}) require.NoError(t, err) require.NotNil(t, resp) // registry, ocr3, forwarder should be deployed on registry chain @@ -56,15 +56,15 @@ func TestConfigureForwarders(t *testing.T) { for _, nChains := range []int{1, 3} { name := fmt.Sprintf("nChains=%d", nChains) t.Run(name, func(t *testing.T) { - te := SetupTestEnv(t, TestConfig{ - WFDonConfig: DonConfig{N: 4}, - AssetDonConfig: DonConfig{N: 4}, - WriterDonConfig: DonConfig{N: 4}, + te := test.SetupTestEnv(t, test.TestConfig{ + WFDonConfig: test.DonConfig{N: 4}, + AssetDonConfig: test.DonConfig{N: 4}, + WriterDonConfig: test.DonConfig{N: 4}, NumChains: nChains, }) var wfNodes []string - for id, _ := range te.WFNodes { + for id := range te.WFNodes { wfNodes = append(wfNodes, id) } @@ -76,7 +76,7 @@ func TestConfigureForwarders(t *testing.T) { csOut, err := changeset.ConfigureForwardContracts(te.Env, cfg) require.NoError(t, err) require.Nil(t, csOut.AddressBook) - require.Len(t, csOut.Proposals, 0) + require.Empty(t, csOut.Proposals) // check that forwarder // TODO set up a listener to check that the forwarder is configured contractSet := te.ContractSets() @@ -93,16 +93,16 @@ func TestConfigureForwarders(t *testing.T) { for _, nChains := range []int{1, 3} { name := fmt.Sprintf("nChains=%d", nChains) t.Run(name, func(t *testing.T) { - te := SetupTestEnv(t, TestConfig{ - WFDonConfig: DonConfig{N: 4}, - AssetDonConfig: DonConfig{N: 4}, - WriterDonConfig: DonConfig{N: 4}, + te := test.SetupTestEnv(t, test.TestConfig{ + WFDonConfig: test.DonConfig{N: 4}, + AssetDonConfig: test.DonConfig{N: 4}, + WriterDonConfig: test.DonConfig{N: 4}, NumChains: nChains, UseMCMS: true, }) var wfNodes []string - for id, _ := range te.WFNodes { + for id := range te.WFNodes { wfNodes = append(wfNodes, id) } @@ -133,9 +133,7 @@ func TestConfigureForwarders(t *testing.T) { }, }) require.NoError(t, err) - }) } }) - } diff --git a/deployment/keystone/changeset/deploy_ocr3.go b/deployment/keystone/changeset/deploy_ocr3.go index 4dfed1e292c..75f9b75ecd1 100644 --- a/deployment/keystone/changeset/deploy_ocr3.go +++ b/deployment/keystone/changeset/deploy_ocr3.go @@ -2,16 +2,18 @@ package changeset import ( "encoding/json" + "errors" "fmt" "io" "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - kslib "github.com/smartcontractkit/chainlink/deployment/keystone" + kslib "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" ) var _ deployment.ChangeSet[uint64] = DeployOCR3 @@ -22,7 +24,7 @@ func DeployOCR3(env deployment.Environment, registryChainSel uint64) (deployment // ocr3 only deployed on registry chain c, ok := env.Chains[registryChainSel] if !ok { - return deployment.ChangesetOutput{}, fmt.Errorf("chain not found in environment") + return deployment.ChangesetOutput{}, errors.New("chain not found in environment") } ocr3Resp, err := kslib.DeployOCR3(c, ab) if err != nil { @@ -37,6 +39,7 @@ var _ deployment.ChangeSet[ConfigureOCR3Config] = ConfigureOCR3Contract type ConfigureOCR3Config struct { ChainSel uint64 NodeIDs []string + Address *common.Address // address of the OCR3 contract to configure OCR3Config *kslib.OracleConfig DryRun bool WriteGeneratedConfig io.Writer // if not nil, write the generated config to this writer as JSON [OCR2OracleConfig] @@ -54,6 +57,7 @@ func ConfigureOCR3Contract(env deployment.Environment, cfg ConfigureOCR3Config) ChainSel: cfg.ChainSel, NodeIDs: cfg.NodeIDs, OCR3Config: cfg.OCR3Config, + Address: cfg.Address, DryRun: cfg.DryRun, UseMCMS: cfg.UseMCMS(), }) @@ -71,14 +75,14 @@ func ConfigureOCR3Contract(env deployment.Environment, cfg ConfigureOCR3Config) return deployment.ChangesetOutput{}, fmt.Errorf("failed to write response output: %w", err) } if n != len(b) { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to write all bytes") + return deployment.ChangesetOutput{}, errors.New("failed to write all bytes") } } // does not create any new addresses var out deployment.ChangesetOutput if cfg.UseMCMS() { if resp.Ops == nil { - return out, fmt.Errorf("expected MCMS operation to be non-nil") + return out, errors.New("expected MCMS operation to be non-nil") } r, err := kslib.GetContractSets(env.Logger, &kslib.GetContractSetsRequest{ Chains: env.Chains, @@ -99,14 +103,13 @@ func ConfigureOCR3Contract(env deployment.Environment, cfg ConfigureOCR3Config) timelocksPerChain, proposerMCMSes, []timelock.BatchChainOperation{*resp.Ops}, - "proposal to set update nodes", + "proposal to set OCR3 config", cfg.MCMSConfig.MinDuration, ) if err != nil { return out, fmt.Errorf("failed to build proposal: %w", err) } out.Proposals = []timelock.MCMSWithTimelockProposal{*proposal} - } return out, nil } diff --git a/deployment/keystone/changeset/deploy_ocr3_test.go b/deployment/keystone/changeset/deploy_ocr3_test.go index 7a276886242..5ede6c5e6c7 100644 --- a/deployment/keystone/changeset/deploy_ocr3_test.go +++ b/deployment/keystone/changeset/deploy_ocr3_test.go @@ -5,18 +5,19 @@ import ( "encoding/json" "testing" - "go.uber.org/zap/zapcore" - + "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" "github.com/smartcontractkit/chainlink-common/pkg/logger" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/environment/memory" - kslib "github.com/smartcontractkit/chainlink/deployment/keystone" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/test" ) func TestDeployOCR3(t *testing.T) { @@ -41,42 +42,109 @@ func TestDeployOCR3(t *testing.T) { // nothing on chain 1 require.NotEqual(t, registrySel, env.AllChainSelectors()[1]) oaddrs, _ := resp.AddressBook.AddressesForChain(env.AllChainSelectors()[1]) - assert.Len(t, oaddrs, 0) + assert.Empty(t, oaddrs) } func TestConfigureOCR3(t *testing.T) { t.Parallel() - c := kslib.OracleConfig{ + c := internal.OracleConfig{ MaxFaultyOracles: 1, DeltaProgressMillis: 12345, } t.Run("no mcms", func(t *testing.T) { + te := test.SetupTestEnv(t, test.TestConfig{ + WFDonConfig: test.DonConfig{N: 4}, + AssetDonConfig: test.DonConfig{N: 4}, + WriterDonConfig: test.DonConfig{N: 4}, + NumChains: 1, + }) + + var wfNodes []string + for id := range te.WFNodes { + wfNodes = append(wfNodes, id) + } + + w := &bytes.Buffer{} + cfg := changeset.ConfigureOCR3Config{ + ChainSel: te.RegistrySelector, + NodeIDs: wfNodes, + OCR3Config: &c, + WriteGeneratedConfig: w, + } - te := SetupTestEnv(t, TestConfig{ - WFDonConfig: DonConfig{N: 4}, - AssetDonConfig: DonConfig{N: 4}, - WriterDonConfig: DonConfig{N: 4}, + csOut, err := changeset.ConfigureOCR3Contract(te.Env, cfg) + require.NoError(t, err) + var got internal.OCR2OracleConfig + err = json.Unmarshal(w.Bytes(), &got) + require.NoError(t, err) + assert.Len(t, got.Signers, 4) + assert.Len(t, got.Transmitters, 4) + assert.Nil(t, csOut.Proposals) + }) + + t.Run("success multiple OCR3 contracts", func(t *testing.T) { + te := test.SetupTestEnv(t, test.TestConfig{ + WFDonConfig: test.DonConfig{N: 4}, + AssetDonConfig: test.DonConfig{N: 4}, + WriterDonConfig: test.DonConfig{N: 4}, NumChains: 1, }) + registrySel := te.Env.AllChainSelectors()[0] + + existingContracts, err := te.Env.ExistingAddresses.AddressesForChain(registrySel) + require.NoError(t, err) + require.Len(t, existingContracts, 4) + + // Find existing OCR3 contract + var existingOCR3Addr string + for addr, tv := range existingContracts { + if tv.Type == internal.OCR3Capability { + existingOCR3Addr = addr + break + } + } + + // Deploy a new OCR3 contract + resp, err := changeset.DeployOCR3(te.Env, registrySel) + require.NoError(t, err) + require.NotNil(t, resp) + require.NoError(t, te.Env.ExistingAddresses.Merge(resp.AddressBook)) + + // Verify after merge there are three original contracts plus one new one + addrs, err := te.Env.ExistingAddresses.AddressesForChain(registrySel) + require.NoError(t, err) + require.Len(t, addrs, 5) + + // Find new OCR3 contract + var newOCR3Addr string + for addr, tv := range addrs { + if tv.Type == internal.OCR3Capability && addr != existingOCR3Addr { + newOCR3Addr = addr + break + } + } + var wfNodes []string - for id, _ := range te.WFNodes { + for id := range te.WFNodes { wfNodes = append(wfNodes, id) } + na := common.HexToAddress(newOCR3Addr) w := &bytes.Buffer{} cfg := changeset.ConfigureOCR3Config{ ChainSel: te.RegistrySelector, NodeIDs: wfNodes, + Address: &na, // Use the new OCR3 contract to configure OCR3Config: &c, WriteGeneratedConfig: w, } csOut, err := changeset.ConfigureOCR3Contract(te.Env, cfg) require.NoError(t, err) - var got kslib.OCR2OracleConfig + var got internal.OCR2OracleConfig err = json.Unmarshal(w.Bytes(), &got) require.NoError(t, err) assert.Len(t, got.Signers, 4) @@ -84,17 +152,105 @@ func TestConfigureOCR3(t *testing.T) { assert.Nil(t, csOut.Proposals) }) + t.Run("fails multiple OCR3 contracts but unspecified address", func(t *testing.T) { + te := test.SetupTestEnv(t, test.TestConfig{ + WFDonConfig: test.DonConfig{N: 4}, + AssetDonConfig: test.DonConfig{N: 4}, + WriterDonConfig: test.DonConfig{N: 4}, + NumChains: 1, + }) + + registrySel := te.Env.AllChainSelectors()[0] + + existingContracts, err := te.Env.ExistingAddresses.AddressesForChain(registrySel) + require.NoError(t, err) + require.Len(t, existingContracts, 4) + + // Deploy a new OCR3 contract + resp, err := changeset.DeployOCR3(te.Env, registrySel) + require.NoError(t, err) + require.NotNil(t, resp) + require.NoError(t, te.Env.ExistingAddresses.Merge(resp.AddressBook)) + + // Verify after merge there are original contracts plus one new one + addrs, err := te.Env.ExistingAddresses.AddressesForChain(registrySel) + require.NoError(t, err) + require.Len(t, addrs, 5) + + var wfNodes []string + for id := range te.WFNodes { + wfNodes = append(wfNodes, id) + } + + w := &bytes.Buffer{} + cfg := changeset.ConfigureOCR3Config{ + ChainSel: te.RegistrySelector, + NodeIDs: wfNodes, + OCR3Config: &c, + WriteGeneratedConfig: w, + } + + _, err = changeset.ConfigureOCR3Contract(te.Env, cfg) + require.Error(t, err) + require.ErrorContains(t, err, "OCR contract address is unspecified") + }) + + t.Run("fails multiple OCR3 contracts but address not found", func(t *testing.T) { + te := test.SetupTestEnv(t, test.TestConfig{ + WFDonConfig: test.DonConfig{N: 4}, + AssetDonConfig: test.DonConfig{N: 4}, + WriterDonConfig: test.DonConfig{N: 4}, + NumChains: 1, + }) + + registrySel := te.Env.AllChainSelectors()[0] + + existingContracts, err := te.Env.ExistingAddresses.AddressesForChain(registrySel) + require.NoError(t, err) + require.Len(t, existingContracts, 4) + + // Deploy a new OCR3 contract + resp, err := changeset.DeployOCR3(te.Env, registrySel) + require.NoError(t, err) + require.NotNil(t, resp) + require.NoError(t, te.Env.ExistingAddresses.Merge(resp.AddressBook)) + + // Verify after merge there are original contracts plus one new one + addrs, err := te.Env.ExistingAddresses.AddressesForChain(registrySel) + require.NoError(t, err) + require.Len(t, addrs, 5) + + var wfNodes []string + for id := range te.WFNodes { + wfNodes = append(wfNodes, id) + } + + nfa := common.HexToAddress("0x1234567890123456789012345678901234567890") + w := &bytes.Buffer{} + cfg := changeset.ConfigureOCR3Config{ + ChainSel: te.RegistrySelector, + NodeIDs: wfNodes, + OCR3Config: &c, + Address: &nfa, + WriteGeneratedConfig: w, + } + + _, err = changeset.ConfigureOCR3Contract(te.Env, cfg) + require.Error(t, err) + require.ErrorContains(t, err, "not found in contract set") + }) + t.Run("mcms", func(t *testing.T) { - te := SetupTestEnv(t, TestConfig{ - WFDonConfig: DonConfig{N: 4}, - AssetDonConfig: DonConfig{N: 4}, - WriterDonConfig: DonConfig{N: 4}, + te := test.SetupTestEnv(t, test.TestConfig{ + WFDonConfig: test.DonConfig{N: 4}, + AssetDonConfig: test.DonConfig{N: 4}, + WriterDonConfig: test.DonConfig{N: 4}, NumChains: 1, UseMCMS: true, }) var wfNodes []string - for id, _ := range te.WFNodes { + for id := range te.WFNodes { wfNodes = append(wfNodes, id) } @@ -109,7 +265,7 @@ func TestConfigureOCR3(t *testing.T) { csOut, err := changeset.ConfigureOCR3Contract(te.Env, cfg) require.NoError(t, err) - var got kslib.OCR2OracleConfig + var got internal.OCR2OracleConfig err = json.Unmarshal(w.Bytes(), &got) require.NoError(t, err) assert.Len(t, got.Signers, 4) @@ -137,5 +293,4 @@ func TestConfigureOCR3(t *testing.T) { }) require.NoError(t, err) }) - } diff --git a/deployment/keystone/changeset/deploy_registry.go b/deployment/keystone/changeset/deploy_registry.go index d07e2728282..f78b6762f9e 100644 --- a/deployment/keystone/changeset/deploy_registry.go +++ b/deployment/keystone/changeset/deploy_registry.go @@ -1,10 +1,11 @@ package changeset import ( + "errors" "fmt" "github.com/smartcontractkit/chainlink/deployment" - kslib "github.com/smartcontractkit/chainlink/deployment/keystone" + kslib "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" ) var _ deployment.ChangeSet[uint64] = DeployCapabilityRegistry @@ -13,7 +14,7 @@ func DeployCapabilityRegistry(env deployment.Environment, registrySelector uint6 lggr := env.Logger chain, ok := env.Chains[registrySelector] if !ok { - return deployment.ChangesetOutput{}, fmt.Errorf("chain not found in environment") + return deployment.ChangesetOutput{}, errors.New("chain not found in environment") } ab := deployment.NewMemoryAddressBook() capabilitiesRegistryResp, err := kslib.DeployCapabilitiesRegistry(chain, ab) diff --git a/deployment/keystone/changeset/deploy_registry_test.go b/deployment/keystone/changeset/deploy_registry_test.go index 9abf357f2a8..713ef897197 100644 --- a/deployment/keystone/changeset/deploy_registry_test.go +++ b/deployment/keystone/changeset/deploy_registry_test.go @@ -34,5 +34,5 @@ func TestDeployCapabilityRegistry(t *testing.T) { // no capabilities registry on chain 1 require.NotEqual(t, registrySel, env.AllChainSelectors()[1]) oaddrs, _ := resp.AddressBook.AddressesForChain(env.AllChainSelectors()[1]) - require.Len(t, oaddrs, 0) + require.Empty(t, oaddrs) } diff --git a/deployment/keystone/changeset/internal/append_node_capabilities.go b/deployment/keystone/changeset/internal/append_node_capabilities.go index 892aa4c1e16..a87688b5427 100644 --- a/deployment/keystone/changeset/internal/append_node_capabilities.go +++ b/deployment/keystone/changeset/internal/append_node_capabilities.go @@ -1,18 +1,19 @@ package internal import ( + "errors" "fmt" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/deployment" - kslib "github.com/smartcontractkit/chainlink/deployment/keystone" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) type AppendNodeCapabilitiesRequest struct { Chain deployment.Chain - ContractSet *kslib.ContractSet + ContractSet *ContractSet P2pToCapabilities map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability UseMCMS bool @@ -20,10 +21,10 @@ type AppendNodeCapabilitiesRequest struct { func (req *AppendNodeCapabilitiesRequest) Validate() error { if len(req.P2pToCapabilities) == 0 { - return fmt.Errorf("p2pToCapabilities is empty") + return errors.New("p2pToCapabilities is empty") } if req.ContractSet.CapabilitiesRegistry == nil { - return fmt.Errorf("registry is nil") + return errors.New("registry is nil") } return nil } @@ -48,7 +49,7 @@ func AppendNodeCapabilitiesImpl(lggr logger.Logger, req *AppendNodeCapabilitiesR for _, cap := range req.P2pToCapabilities { capabilities = append(capabilities, cap...) } - op, err := kslib.AddCapabilities(lggr, req.ContractSet, req.Chain, capabilities, req.UseMCMS) + op, err := AddCapabilities(lggr, req.ContractSet.CapabilitiesRegistry, req.Chain, capabilities, req.UseMCMS) if err != nil { return nil, fmt.Errorf("failed to add capabilities: %w", err) } diff --git a/deployment/keystone/changeset/internal/append_node_capabilities_test.go b/deployment/keystone/changeset/internal/append_node_capabilities_test.go index f2ec2bf5c8f..6d26133195d 100644 --- a/deployment/keystone/changeset/internal/append_node_capabilities_test.go +++ b/deployment/keystone/changeset/internal/append_node_capabilities_test.go @@ -11,7 +11,7 @@ import ( "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" kstest "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal/test" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) diff --git a/deployment/keystone/capability_definitions.go b/deployment/keystone/changeset/internal/capability_definitions.go similarity index 93% rename from deployment/keystone/capability_definitions.go rename to deployment/keystone/changeset/internal/capability_definitions.go index 61f129a939a..21c2b4fce01 100644 --- a/deployment/keystone/capability_definitions.go +++ b/deployment/keystone/changeset/internal/capability_definitions.go @@ -1,6 +1,6 @@ -package keystone +package internal -import kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" +import kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" // TODO: KS-457 configuration management for capabilities from external sources var StreamTriggerCap = kcr.CapabilitiesRegistryCapability{ diff --git a/deployment/keystone/capability_management.go b/deployment/keystone/changeset/internal/capability_management.go similarity index 63% rename from deployment/keystone/capability_management.go rename to deployment/keystone/changeset/internal/capability_management.go index 7e502d4f8ea..04f5a153482 100644 --- a/deployment/keystone/capability_management.go +++ b/deployment/keystone/changeset/internal/capability_management.go @@ -1,4 +1,4 @@ -package keystone +package internal import ( "fmt" @@ -6,50 +6,58 @@ import ( "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/deployment" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" ) // AddCapabilities adds the capabilities to the registry -func AddCapabilities(lggr logger.Logger, contractSet *ContractSet, chain deployment.Chain, capabilities []kcr.CapabilitiesRegistryCapability, useMCMS bool) (*timelock.BatchChainOperation, error) { +func AddCapabilities(lggr logger.Logger, registry *kcr.CapabilitiesRegistry, chain deployment.Chain, capabilities []kcr.CapabilitiesRegistryCapability, useMCMS bool) (*timelock.BatchChainOperation, error) { if len(capabilities) == 0 { return nil, nil } - registry := contractSet.CapabilitiesRegistry deduped, err := dedupCapabilities(registry, capabilities) if err != nil { return nil, fmt.Errorf("failed to dedup capabilities: %w", err) } - txOpts := chain.DeployerKey + if useMCMS { - txOpts = deployment.SimTransactOpts() + return addCapabilitiesMCMSProposal(registry, deduped, chain) } - tx, err := registry.AddCapabilities(txOpts, deduped) + + tx, err := registry.AddCapabilities(chain.DeployerKey, deduped) if err != nil { - err = DecodeErr(kcr.CapabilitiesRegistryABI, err) + err = deployment.DecodeErr(kcr.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to add capabilities: %w", err) } - var batch *timelock.BatchChainOperation - if !useMCMS { - _, err = chain.Confirm(tx) - if err != nil { - return nil, fmt.Errorf("failed to confirm AddCapabilities confirm transaction %s: %w", tx.Hash().String(), err) - } - lggr.Info("registered capabilities", "capabilities", deduped) - } else { - batch = &timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(chain.Selector), - Batch: []mcms.Operation{ - { - To: registry.Address(), - Data: tx.Data(), - Value: big.NewInt(0), - }, - }, - } + + _, err = chain.Confirm(tx) + if err != nil { + return nil, fmt.Errorf("failed to confirm AddCapabilities confirm transaction %s: %w", tx.Hash().String(), err) + } + lggr.Info("registered capabilities", "capabilities", deduped) + + return nil, nil +} + +func addCapabilitiesMCMSProposal(registry *kcr.CapabilitiesRegistry, caps []kcr.CapabilitiesRegistryCapability, regChain deployment.Chain) (*timelock.BatchChainOperation, error) { + tx, err := registry.AddCapabilities(deployment.SimTransactOpts(), caps) + if err != nil { + err = deployment.DecodeErr(kcr.CapabilitiesRegistryABI, err) + return nil, fmt.Errorf("failed to call AddNodeOperators: %w", err) } - return batch, nil + + return &timelock.BatchChainOperation{ + ChainIdentifier: mcms.ChainIdentifier(regChain.Selector), + Batch: []mcms.Operation{ + { + To: registry.Address(), + Data: tx.Data(), + Value: big.NewInt(0), + }, + }, + }, nil } // CapabilityID returns a unique id for the capability diff --git a/deployment/keystone/capability_registry_deployer.go b/deployment/keystone/changeset/internal/capability_registry_deployer.go similarity index 97% rename from deployment/keystone/capability_registry_deployer.go rename to deployment/keystone/changeset/internal/capability_registry_deployer.go index 11c85453927..492ba168c9d 100644 --- a/deployment/keystone/capability_registry_deployer.go +++ b/deployment/keystone/changeset/internal/capability_registry_deployer.go @@ -1,4 +1,4 @@ -package keystone +package internal import ( "context" @@ -11,7 +11,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" ) type CapabilitiesRegistryDeployer struct { diff --git a/deployment/keystone/consumer_deployer.go b/deployment/keystone/changeset/internal/consumer_deployer.go similarity index 90% rename from deployment/keystone/consumer_deployer.go rename to deployment/keystone/changeset/internal/consumer_deployer.go index 12d148144b5..3c2de539ccb 100644 --- a/deployment/keystone/consumer_deployer.go +++ b/deployment/keystone/changeset/internal/consumer_deployer.go @@ -1,4 +1,4 @@ -package keystone +package internal import ( "fmt" @@ -6,7 +6,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/feeds_consumer" + feeds_consumer "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/feeds_consumer_1_0_0" ) type KeystoneFeedsConsumerDeployer struct { diff --git a/deployment/keystone/contract_set.go b/deployment/keystone/changeset/internal/contract_set.go similarity index 99% rename from deployment/keystone/contract_set.go rename to deployment/keystone/changeset/internal/contract_set.go index ee503a54b4d..540ab80097b 100644 --- a/deployment/keystone/contract_set.go +++ b/deployment/keystone/changeset/internal/contract_set.go @@ -1,4 +1,4 @@ -package keystone +package internal import ( "fmt" @@ -108,7 +108,6 @@ func DeployFeedsConsumer(chain deployment.Chain, ab deployment.AddressBook) (*De } err = ab.Save(chain.Selector, consumerResp.Address.String(), consumerResp.Tv) if err != nil { - return nil, fmt.Errorf("failed to save FeedsConsumer: %w", err) } return consumerResp, nil diff --git a/deployment/keystone/deploy.go b/deployment/keystone/changeset/internal/deploy.go similarity index 80% rename from deployment/keystone/deploy.go rename to deployment/keystone/changeset/internal/deploy.go index cb7804d0051..e785b6dc161 100644 --- a/deployment/keystone/deploy.go +++ b/deployment/keystone/changeset/internal/deploy.go @@ -1,4 +1,4 @@ -package keystone +package internal import ( "bytes" @@ -14,11 +14,12 @@ import ( "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum/go-ethereum/common" "golang.org/x/exp/maps" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + "github.com/smartcontractkit/chainlink/deployment" "google.golang.org/protobuf/proto" @@ -29,9 +30,8 @@ import ( capabilitiespb "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" "github.com/smartcontractkit/chainlink-common/pkg/values" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" - kf "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder" + capabilities_registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + kf "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder_1_0_0" "github.com/smartcontractkit/chainlink-common/pkg/logger" ) @@ -68,7 +68,7 @@ func (r ConfigureContractsRequest) Validate() error { type ConfigureContractsResponse struct { Changeset *deployment.ChangesetOutput - DonInfos map[string]kcr.CapabilitiesRegistryDONInfo + DonInfos map[string]capabilities_registry.CapabilitiesRegistryDONInfo } // ConfigureContracts configures contracts them with the given DONS and their capabilities. It optionally deploys the contracts @@ -142,7 +142,7 @@ type DonInfo struct { Name string F uint8 Nodes []deployment.Node - Capabilities []kcr.CapabilitiesRegistryCapability // every capability is hosted on each node + Capabilities []capabilities_registry.CapabilitiesRegistryCapability // every capability is hosted on each node } func DonInfos(dons []DonCapabilities, jd deployment.OffchainClient) ([]DonInfo, error) { @@ -166,7 +166,7 @@ func DonInfos(dons []DonCapabilities, jd deployment.OffchainClient) ([]DonInfo, return donInfos, nil } -func GetRegistryContract(e *deployment.Environment, registryChainSel uint64) (*kcr.CapabilitiesRegistry, deployment.Chain, error) { +func GetRegistryContract(e *deployment.Environment, registryChainSel uint64) (*capabilities_registry.CapabilitiesRegistry, deployment.Chain, error) { registryChain, ok := e.Chains[registryChainSel] if !ok { return nil, deployment.Chain{}, fmt.Errorf("chain %d not found in environment", registryChainSel) @@ -181,14 +181,14 @@ func GetRegistryContract(e *deployment.Environment, registryChainSel uint64) (*k } // ensure registry is deployed and get the registry contract and chain - var registry *kcr.CapabilitiesRegistry + var registry *capabilities_registry.CapabilitiesRegistry registryChainContracts, ok := contractSetsResp.ContractSets[registryChainSel] if !ok { return nil, deployment.Chain{}, fmt.Errorf("failed to deploy registry chain contracts. expected chain %d", registryChainSel) } registry = registryChainContracts.CapabilitiesRegistry if registry == nil { - return nil, deployment.Chain{}, fmt.Errorf("no registry contract found") + return nil, deployment.Chain{}, errors.New("no registry contract found") } e.Logger.Debugf("registry contract address: %s, chain %d", registry.Address().String(), registryChainSel) return registry, registryChain, nil @@ -323,12 +323,14 @@ func ConfigureOCR3Contract(env *deployment.Environment, chainSel uint64, dons [] if !ok { return fmt.Errorf("failed to get contract set for chain %d", chainSel) } - contract := contracts.OCR3 - if contract == nil { - return fmt.Errorf("no ocr3 contract found for chain %d", chainSel) + + contract, err := contracts.GetOCR3Contract(nil) + if err != nil { + env.Logger.Errorf("failed to get OCR3 contract: %s", err) + return fmt.Errorf("failed to get OCR3 contract: %w", err) } - _, err := configureOCR3contract(configureOCR3Request{ + _, err = configureOCR3contract(configureOCR3Request{ cfg: cfg, chain: registryChain, contract: contract, @@ -351,6 +353,7 @@ type ConfigureOCR3Resp struct { type ConfigureOCR3Config struct { ChainSel uint64 NodeIDs []string + Address *common.Address // address of the OCR3 contract to configure OCR3Config *OracleConfig DryRun bool @@ -379,10 +382,13 @@ func ConfigureOCR3ContractFromJD(env *deployment.Environment, cfg ConfigureOCR3C if !ok { return nil, fmt.Errorf("failed to get contract set for chain %d", cfg.ChainSel) } - contract := contracts.OCR3 - if contract == nil { - return nil, fmt.Errorf("no ocr3 contract found for chain %d", cfg.ChainSel) + + contract, err := contracts.GetOCR3Contract(cfg.Address) + if err != nil { + env.Logger.Errorf("%sfailed to get OCR3 contract at %s : %s", prefix, cfg.Address, err) + return nil, fmt.Errorf("failed to get OCR3 contract: %w", err) } + nodes, err := deployment.NodeInfo(cfg.NodeIDs, env.Offchain) if err != nil { return nil, err @@ -404,25 +410,28 @@ func ConfigureOCR3ContractFromJD(env *deployment.Environment, cfg ConfigureOCR3C OCR2OracleConfig: r.ocrConfig, Ops: r.ops, }, nil - } type RegisterCapabilitiesRequest struct { Env *deployment.Environment RegistryChainSelector uint64 - DonToCapabilities map[string][]kcr.CapabilitiesRegistryCapability + DonToCapabilities map[string][]capabilities_registry.CapabilitiesRegistryCapability + + // if UseMCMS is true, a batch proposal is returned and no transaction is confirmed on chain. + UseMCMS bool } type RegisterCapabilitiesResponse struct { DonToCapabilities map[string][]RegisteredCapability + Ops *timelock.BatchChainOperation } type RegisteredCapability struct { - kcr.CapabilitiesRegistryCapability + capabilities_registry.CapabilitiesRegistryCapability ID [32]byte } -func FromCapabilitiesRegistryCapability(cap *kcr.CapabilitiesRegistryCapability, e deployment.Environment, registryChainSelector uint64) (*RegisteredCapability, error) { +func FromCapabilitiesRegistryCapability(cap *capabilities_registry.CapabilitiesRegistryCapability, e deployment.Environment, registryChainSelector uint64) (*RegisteredCapability, error) { registry, _, err := GetRegistryContract(&e, registryChainSelector) if err != nil { return nil, fmt.Errorf("failed to get registry: %w", err) @@ -440,7 +449,7 @@ func FromCapabilitiesRegistryCapability(cap *kcr.CapabilitiesRegistryCapability, // RegisterCapabilities add computes the capability id, adds it to the registry and associates the registered capabilities with appropriate don(s) func RegisterCapabilities(lggr logger.Logger, req RegisterCapabilitiesRequest) (*RegisterCapabilitiesResponse, error) { if len(req.DonToCapabilities) == 0 { - return nil, fmt.Errorf("no capabilities to register") + return nil, errors.New("no capabilities to register") } cresp, err := GetContractSets(req.Env.Logger, &GetContractSetsRequest{ Chains: req.Env.Chains, @@ -456,7 +465,7 @@ func RegisterCapabilities(lggr logger.Logger, req RegisterCapabilitiesRequest) ( } // capability could be hosted on multiple dons. need to deduplicate - uniqueCaps := make(map[kcr.CapabilitiesRegistryCapability][32]byte) + uniqueCaps := make(map[capabilities_registry.CapabilitiesRegistryCapability][32]byte) for don, caps := range req.DonToCapabilities { var registerCaps []RegisteredCapability for _, cap := range caps { @@ -479,7 +488,7 @@ func RegisterCapabilities(lggr logger.Logger, req RegisterCapabilitiesRequest) ( resp.DonToCapabilities[don] = registerCaps } - var capabilities []kcr.CapabilitiesRegistryCapability + var capabilities []capabilities_registry.CapabilitiesRegistryCapability for cap := range uniqueCaps { capabilities = append(capabilities, cap) } @@ -487,22 +496,27 @@ func RegisterCapabilities(lggr logger.Logger, req RegisterCapabilitiesRequest) ( lggr.Warn("no new capabilities to register") return &RegisterCapabilitiesResponse{}, nil } - // not using mcms; ignore proposals - _, err = AddCapabilities(lggr, &contracts, registryChain, capabilities, false) + + ops, err := AddCapabilities(lggr, contracts.CapabilitiesRegistry, registryChain, capabilities, req.UseMCMS) if err != nil { return nil, fmt.Errorf("failed to add capabilities: %w", err) } + + resp.Ops = ops + return resp, nil } type RegisterNOPSRequest struct { Env *deployment.Environment RegistryChainSelector uint64 - Nops []kcr.CapabilitiesRegistryNodeOperator + Nops []capabilities_registry.CapabilitiesRegistryNodeOperator + UseMCMS bool } type RegisterNOPSResponse struct { - Nops []*kcr.CapabilitiesRegistryNodeOperatorAdded + Nops []*capabilities_registry.CapabilitiesRegistryNodeOperatorAdded + Ops *timelock.BatchChainOperation } func RegisterNOPS(ctx context.Context, lggr logger.Logger, req RegisterNOPSRequest) (*RegisterNOPSResponse, error) { @@ -521,15 +535,15 @@ func RegisterNOPS(ctx context.Context, lggr logger.Logger, req RegisterNOPSReque } lggr.Infow("fetched existing node operators", "len", len(existingNopsAddrToID)) resp := &RegisterNOPSResponse{ - Nops: []*kcr.CapabilitiesRegistryNodeOperatorAdded{}, + Nops: []*capabilities_registry.CapabilitiesRegistryNodeOperatorAdded{}, } - nops := []kcr.CapabilitiesRegistryNodeOperator{} + nops := []capabilities_registry.CapabilitiesRegistryNodeOperator{} for _, nop := range req.Nops { if id, ok := existingNopsAddrToID[nop]; !ok { nops = append(nops, nop) } else { lggr.Debugw("node operator already exists", "name", nop.Name, "admin", nop.Admin.String(), "id", id) - resp.Nops = append(resp.Nops, &kcr.CapabilitiesRegistryNodeOperatorAdded{ + resp.Nops = append(resp.Nops, &capabilities_registry.CapabilitiesRegistryNodeOperatorAdded{ NodeOperatorId: id, Name: nop.Name, Admin: nop.Admin, @@ -540,11 +554,23 @@ func RegisterNOPS(ctx context.Context, lggr logger.Logger, req RegisterNOPSReque lggr.Debug("no new node operators to register") return resp, nil } + + if req.UseMCMS { + ops, err := addNOPsMCMSProposal(registry, nops, registryChain) + if err != nil { + return nil, fmt.Errorf("failed to generate proposal to add node operators: %w", err) + } + + resp.Ops = ops + return resp, nil + } + tx, err := registry.AddNodeOperators(registryChain.DeployerKey, nops) if err != nil { - err = DecodeErr(kcr.CapabilitiesRegistryABI, err) + err = deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to call AddNodeOperators: %w", err) } + // for some reason that i don't understand, the confirm must be called before the WaitMined or the latter will hang // (at least for a simulated backend chain) _, err = registryChain.Confirm(tx) @@ -570,6 +596,25 @@ func RegisterNOPS(ctx context.Context, lggr logger.Logger, req RegisterNOPSReque return resp, nil } +func addNOPsMCMSProposal(registry *capabilities_registry.CapabilitiesRegistry, nops []capabilities_registry.CapabilitiesRegistryNodeOperator, regChain deployment.Chain) (*timelock.BatchChainOperation, error) { + tx, err := registry.AddNodeOperators(deployment.SimTransactOpts(), nops) + if err != nil { + err = deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) + return nil, fmt.Errorf("failed to call AddNodeOperators: %w", err) + } + + return &timelock.BatchChainOperation{ + ChainIdentifier: mcms.ChainIdentifier(regChain.Selector), + Batch: []mcms.Operation{ + { + To: registry.Address(), + Data: tx.Data(), + Value: big.NewInt(0), + }, + }, + }, nil +} + func DefaultCapConfig(capType uint8, nNodes int) *capabilitiespb.CapabilityConfig { switch capType { // TODO: use the enum defined in ?? @@ -605,45 +650,23 @@ func DefaultCapConfig(capType uint8, nNodes int) *capabilitiespb.CapabilityConfi } } -func DecodeErr(encodedABI string, err error) error { - if err == nil { - return nil - } - - //revive:disable - var d rpc.DataError - ok := errors.As(err, &d) - if ok { - encErr, ok := d.ErrorData().(string) - if !ok { - return fmt.Errorf("error without error data: %s", d.Error()) - } - errStr, parseErr := deployment.ParseErrorFromABI(encErr, encodedABI) - if parseErr != nil { - return fmt.Errorf("failed to decode error '%s' with abi: %w", encErr, parseErr) - } - return fmt.Errorf("contract error: %s", errStr) - - } - return fmt.Errorf("cannot decode error with abi: %w", err) -} - // register nodes type RegisterNodesRequest struct { Env *deployment.Environment RegistryChainSelector uint64 - NopToNodeIDs map[kcr.CapabilitiesRegistryNodeOperator][]string + NopToNodeIDs map[capabilities_registry.CapabilitiesRegistryNodeOperator][]string DonToNodes map[string][]deployment.Node DonToCapabilities map[string][]RegisteredCapability - Nops []*kcr.CapabilitiesRegistryNodeOperatorAdded + Nops []*capabilities_registry.CapabilitiesRegistryNodeOperatorAdded + UseMCMS bool } type RegisterNodesResponse struct { - nodeIDToParams map[string]kcr.CapabilitiesRegistryNodeParams + nodeIDToParams map[string]capabilities_registry.CapabilitiesRegistryNodeParams + Ops *timelock.BatchChainOperation } // registerNodes registers the nodes with the registry. it assumes that the deployer key in the Chain // can sign the transactions update the contract state -// TODO: 467 refactor to support MCMS. Specifically need to separate the call data generation from the actual contract call func RegisterNodes(lggr logger.Logger, req *RegisterNodesRequest) (*RegisterNodesResponse, error) { registry, registryChain, err := GetRegistryContract(req.Env, req.RegistryChainSelector) if err != nil { @@ -655,9 +678,9 @@ func RegisterNodes(lggr logger.Logger, req *RegisterNodesRequest) (*RegisterNode count += len(nodes) } lggr.Infow("registering nodes...", "len", count) - nodeToRegisterNop := make(map[string]*kcr.CapabilitiesRegistryNodeOperatorAdded) + nodeToRegisterNop := make(map[string]*capabilities_registry.CapabilitiesRegistryNodeOperatorAdded) for _, nop := range req.Nops { - n := kcr.CapabilitiesRegistryNodeOperator{ + n := capabilities_registry.CapabilitiesRegistryNodeOperator{ Name: nop.Name, Admin: nop.Admin, } @@ -680,7 +703,7 @@ func RegisterNodes(lggr logger.Logger, req *RegisterNodesRequest) (*RegisterNode return nil, err } - nodeIDToParams := make(map[string]kcr.CapabilitiesRegistryNodeParams) + nodeIDToParams := make(map[string]capabilities_registry.CapabilitiesRegistryNodeParams) for don, nodes := range req.DonToNodes { caps, ok := req.DonToCapabilities[don] if !ok { @@ -711,7 +734,7 @@ func RegisterNodes(lggr logger.Logger, req *RegisterNodesRequest) (*RegisterNode copy(signer[:], evmCC.OnchainPublicKey) var csakey [32]byte copy(csakey[:], evmCC.ConfigEncryptionPublicKey[:]) - params = kcr.CapabilitiesRegistryNodeParams{ + params = capabilities_registry.CapabilitiesRegistryNodeParams{ NodeOperatorId: nop.NodeOperatorId, Signer: signer, P2pId: n.PeerID, @@ -739,14 +762,27 @@ func RegisterNodes(lggr logger.Logger, req *RegisterNodesRequest) (*RegisterNode } } - var uniqueNodeParams []kcr.CapabilitiesRegistryNodeParams + var uniqueNodeParams []capabilities_registry.CapabilitiesRegistryNodeParams for _, v := range nodeIDToParams { uniqueNodeParams = append(uniqueNodeParams, v) } lggr.Debugw("unique node params to add", "count", len(uniqueNodeParams), "params", uniqueNodeParams) + + if req.UseMCMS { + ops, err := addNodesMCMSProposal(registry, uniqueNodeParams, registryChain) + if err != nil { + return nil, fmt.Errorf("failed to generate proposal to add nodes: %w", err) + } + + return &RegisterNodesResponse{ + nodeIDToParams: nodeIDToParams, + Ops: ops, + }, nil + } + tx, err := registry.AddNodes(registryChain.DeployerKey, uniqueNodeParams) if err != nil { - err = DecodeErr(kcr.CapabilitiesRegistryABI, err) + err = deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) // no typed errors in the abi, so we have to do string matching // try to add all nodes in one go, if that fails, fall back to 1-by-1 if !strings.Contains(err.Error(), "NodeAlreadyExists") { @@ -754,9 +790,9 @@ func RegisterNodes(lggr logger.Logger, req *RegisterNodesRequest) (*RegisterNode } lggr.Warn("nodes already exist, falling back to 1-by-1") for _, singleNodeParams := range uniqueNodeParams { - tx, err = registry.AddNodes(registryChain.DeployerKey, []kcr.CapabilitiesRegistryNodeParams{singleNodeParams}) + tx, err = registry.AddNodes(registryChain.DeployerKey, []capabilities_registry.CapabilitiesRegistryNodeParams{singleNodeParams}) if err != nil { - err = DecodeErr(kcr.CapabilitiesRegistryABI, err) + err = deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) if strings.Contains(err.Error(), "NodeAlreadyExists") { lggr.Warnw("node already exists, skipping", "p2pid", hex.EncodeToString(singleNodeParams.P2pId[:])) continue @@ -777,11 +813,32 @@ func RegisterNodes(lggr logger.Logger, req *RegisterNodesRequest) (*RegisterNode return nil, fmt.Errorf("failed to confirm AddNode confirm transaction %s: %w", tx.Hash().String(), err) } } + return &RegisterNodesResponse{ nodeIDToParams: nodeIDToParams, }, nil } +// addNodesMCMSProposal generates a single call to AddNodes for all the node params at once. +func addNodesMCMSProposal(registry *capabilities_registry.CapabilitiesRegistry, params []capabilities_registry.CapabilitiesRegistryNodeParams, regChain deployment.Chain) (*timelock.BatchChainOperation, error) { + tx, err := registry.AddNodes(deployment.SimTransactOpts(), params) + if err != nil { + err = deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) + return nil, fmt.Errorf("failed to simulate call to AddNodes: %w", err) + } + + return &timelock.BatchChainOperation{ + ChainIdentifier: mcms.ChainIdentifier(regChain.Selector), + Batch: []mcms.Operation{ + { + To: registry.Address(), + Data: tx.Data(), + Value: big.NewInt(0), + }, + }, + }, nil +} + type DONToRegister struct { Name string F uint8 @@ -795,10 +852,12 @@ type RegisterDonsRequest struct { NodeIDToP2PID map[string][32]byte DonToCapabilities map[string][]RegisteredCapability DonsToRegister []DONToRegister + UseMCMS bool } type RegisterDonsResponse struct { - DonInfos map[string]kcr.CapabilitiesRegistryDONInfo + DonInfos map[string]capabilities_registry.CapabilitiesRegistryDONInfo + Ops *timelock.BatchChainOperation } func sortedHash(p2pids [][32]byte) string { @@ -825,7 +884,7 @@ func RegisterDons(lggr logger.Logger, req RegisterDonsRequest) (*RegisterDonsRes donInfos, err := registry.GetDONs(&bind.CallOpts{}) if err != nil { - err = DecodeErr(kcr.CapabilitiesRegistryABI, err) + err = deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to call GetDONs: %w", err) } existingDONs := make(map[string]struct{}) @@ -834,6 +893,7 @@ func RegisterDons(lggr logger.Logger, req RegisterDonsRequest) (*RegisterDonsRes } lggr.Infow("fetched existing DONs...", "len", len(donInfos), "lenByNodesHash", len(existingDONs)) + mcmsOps := make([]mcms.Operation, 0, len(req.DonsToRegister)) for _, don := range req.DonsToRegister { var p2pIds [][32]byte for _, n := range don.Nodes { @@ -851,16 +911,18 @@ func RegisterDons(lggr logger.Logger, req RegisterDonsRequest) (*RegisterDonsRes p2pIdsToDon[p2pSortedHash] = don.Name if _, ok := existingDONs[p2pSortedHash]; ok { - lggr.Debugw("don already exists, ignoring", "don", don, "p2p sorted hash", p2pSortedHash) + lggr.Debugw("don already exists, ignoring", "don", don.Name, "p2p sorted hash", p2pSortedHash) continue } + lggr.Debugw("registering DON", "don", don.Name, "p2p sorted hash", p2pSortedHash) + caps, ok := req.DonToCapabilities[don.Name] if !ok { return nil, fmt.Errorf("capabilities not found for DON %s", don.Name) } wfSupported := false - var cfgs []kcr.CapabilitiesRegistryCapabilityConfiguration + var cfgs []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration for _, cap := range caps { if cap.CapabilityType == 2 { // OCR3 capability => WF supported wfSupported = true @@ -871,17 +933,34 @@ func RegisterDons(lggr logger.Logger, req RegisterDonsRequest) (*RegisterDonsRes if err != nil { return nil, fmt.Errorf("failed to marshal capability config for %v: %w", cap, err) } - cfgs = append(cfgs, kcr.CapabilitiesRegistryCapabilityConfiguration{ + cfgs = append(cfgs, capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ CapabilityId: cap.ID, Config: cfgb, }) } - tx, err := registry.AddDON(registryChain.DeployerKey, p2pIds, cfgs, true, wfSupported, don.F) + txOpts := registryChain.DeployerKey + if req.UseMCMS { + txOpts = deployment.SimTransactOpts() + } + + tx, err := registry.AddDON(txOpts, p2pIds, cfgs, true, wfSupported, don.F) if err != nil { - err = DecodeErr(kcr.CapabilitiesRegistryABI, err) + err = deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to call AddDON for don '%s' p2p2Id hash %s capability %v: %w", don.Name, p2pSortedHash, cfgs, err) } + + if req.UseMCMS { + lggr.Debugw("adding mcms op for DON", "don", don.Name) + op := mcms.Operation{ + To: registry.Address(), + Data: tx.Data(), + Value: big.NewInt(0), + } + mcmsOps = append(mcmsOps, op) + continue + } + _, err = registryChain.Confirm(tx) if err != nil { return nil, fmt.Errorf("failed to confirm AddDON transaction %s for don %s: %w", tx.Hash().String(), don.Name, err) @@ -889,6 +968,16 @@ func RegisterDons(lggr logger.Logger, req RegisterDonsRequest) (*RegisterDonsRes lggr.Debugw("registered DON", "don", don.Name, "p2p sorted hash", p2pSortedHash, "cgs", cfgs, "wfSupported", wfSupported, "f", don.F) addedDons++ } + + if req.UseMCMS { + return &RegisterDonsResponse{ + Ops: &timelock.BatchChainOperation{ + ChainIdentifier: mcms.ChainIdentifier(registryChain.Selector), + Batch: mcmsOps, + }, + }, nil + } + lggr.Debugf("Registered all DONs (new=%d), waiting for registry to update", addedDons) // occasionally the registry does not return the expected number of DONS immediately after the txns above @@ -906,15 +995,15 @@ func RegisterDons(lggr logger.Logger, req RegisterDonsRequest) (*RegisterDonsRes } } if err != nil { - err = DecodeErr(kcr.CapabilitiesRegistryABI, err) + err = deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to call GetDONs: %w", err) } if !foundAll { - return nil, fmt.Errorf("did not find all desired DONS") + return nil, errors.New("did not find all desired DONS") } resp := RegisterDonsResponse{ - DonInfos: make(map[string]kcr.CapabilitiesRegistryDONInfo), + DonInfos: make(map[string]capabilities_registry.CapabilitiesRegistryDONInfo), } for i, donInfo := range donInfos { donName, ok := p2pIdsToDon[sortedHash(donInfo.NodeP2PIds)] @@ -922,14 +1011,15 @@ func RegisterDons(lggr logger.Logger, req RegisterDonsRequest) (*RegisterDonsRes lggr.Debugw("irrelevant DON found in the registry, ignoring", "p2p sorted hash", sortedHash(donInfo.NodeP2PIds)) continue } - lggr.Debugw("adding don info to the reponse (keyed by DON name)", "don", donName) + lggr.Debugw("adding don info to the response (keyed by DON name)", "don", donName) resp.DonInfos[donName] = donInfos[i] } + return &resp, nil } // are all DONs from p2pIdsToDon in donInfos -func containsAllDONs(donInfos []kcr.CapabilitiesRegistryDONInfo, p2pIdsToDon map[string]string) bool { +func containsAllDONs(donInfos []capabilities_registry.CapabilitiesRegistryDONInfo, p2pIdsToDon map[string]string) bool { found := make(map[string]struct{}) for _, donInfo := range donInfos { hash := sortedHash(donInfo.NodeP2PIds) @@ -962,13 +1052,13 @@ func configureForwarder(lggr logger.Logger, chain deployment.Chain, contractSet } tx, err := fwdr.SetConfig(txOpts, dn.Info.Id, ver, dn.Info.F, signers) if err != nil { - err = DecodeErr(kf.KeystoneForwarderABI, err) + err = deployment.DecodeErr(kf.KeystoneForwarderABI, err) return nil, fmt.Errorf("failed to call SetConfig for forwarder %s on chain %d: %w", fwdr.Address().String(), chain.Selector, err) } if !useMCMS { _, err = chain.Confirm(tx) if err != nil { - err = DecodeErr(kf.KeystoneForwarderABI, err) + err = deployment.DecodeErr(kf.KeystoneForwarderABI, err) return nil, fmt.Errorf("failed to confirm SetConfig for forwarder %s: %w", fwdr.Address().String(), err) } } else { diff --git a/deployment/keystone/changeset/internal/deploy_test.go b/deployment/keystone/changeset/internal/deploy_test.go new file mode 100644 index 00000000000..b8a98207ea0 --- /dev/null +++ b/deployment/keystone/changeset/internal/deploy_test.go @@ -0,0 +1,203 @@ +package internal_test + +import ( + "context" + "testing" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" + kstest "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal/test" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + + "github.com/stretchr/testify/require" +) + +func Test_RegisterNOPS(t *testing.T) { + var ( + useMCMS bool + lggr = logger.Test(t) + setupResp = kstest.SetupTestRegistry(t, lggr, &kstest.SetupTestRegistryRequest{}) + registry = setupResp.Registry + chain = setupResp.Chain + nops = make([]kcr.CapabilitiesRegistryNodeOperator, 0) + ) + t.Run("success create add NOPs mcms proposal", func(t *testing.T) { + nops = append(nops, kcr.CapabilitiesRegistryNodeOperator{ + Name: "test-nop", + }) + useMCMS = true + env := &deployment.Environment{ + Logger: lggr, + Chains: map[uint64]deployment.Chain{ + chain.Selector: chain, + }, + ExistingAddresses: deployment.NewMemoryAddressBookFromMap(map[uint64]map[string]deployment.TypeAndVersion{ + chain.Selector: { + registry.Address().String(): deployment.TypeAndVersion{ + Type: internal.CapabilitiesRegistry, + Version: deployment.Version1_0_0, + }, + }, + }), + } + resp, err := internal.RegisterNOPS(context.TODO(), lggr, internal.RegisterNOPSRequest{ + Env: env, + RegistryChainSelector: chain.Selector, + Nops: nops, + UseMCMS: useMCMS, + }) + require.NoError(t, err) + require.NotNil(t, resp.Ops) + require.Len(t, resp.Ops.Batch, 1) + }) +} + +func Test_AddCapabilities(t *testing.T) { + var ( + useMCMS bool + lggr = logger.Test(t) + setupResp = kstest.SetupTestRegistry(t, lggr, &kstest.SetupTestRegistryRequest{}) + registry = setupResp.Registry + chain = setupResp.Chain + capabilities = make([]kcr.CapabilitiesRegistryCapability, 0) + ) + + t.Run("successfully create mcms proposal", func(t *testing.T) { + useMCMS = true + capabilities = append(capabilities, kcr.CapabilitiesRegistryCapability{ + LabelledName: "cap1", + Version: "1.0.0", + CapabilityType: 0, + }) + ops, err := internal.AddCapabilities(lggr, registry, chain, capabilities, useMCMS) + require.NoError(t, err) + require.NotNil(t, ops) + require.Len(t, ops.Batch, 1) + }) + + t.Run("does nothing if no capabilities", func(t *testing.T) { + ops, err := internal.AddCapabilities(lggr, registry, chain, nil, useMCMS) + require.NoError(t, err) + require.Nil(t, ops) + }) +} + +func Test_RegisterNodes(t *testing.T) { + var ( + useMCMS bool + lggr = logger.Test(t) + setupResp = kstest.SetupTestRegistry(t, lggr, &kstest.SetupTestRegistryRequest{}) + registry = setupResp.Registry + chain = setupResp.Chain + ) + t.Run("success create add nodes mcms proposal", func(t *testing.T) { + useMCMS = true + env := &deployment.Environment{ + Logger: lggr, + Chains: map[uint64]deployment.Chain{ + chain.Selector: chain, + }, + ExistingAddresses: deployment.NewMemoryAddressBookFromMap(map[uint64]map[string]deployment.TypeAndVersion{ + chain.Selector: { + registry.Address().String(): deployment.TypeAndVersion{ + Type: internal.CapabilitiesRegistry, + Version: deployment.Version1_0_0, + }, + }, + }), + } + resp, err := internal.RegisterNodes(lggr, &internal.RegisterNodesRequest{ + Env: env, + RegistryChainSelector: chain.Selector, + UseMCMS: useMCMS, + }) + require.NoError(t, err) + require.NotNil(t, resp.Ops) + require.Len(t, resp.Ops.Batch, 1) + }) +} + +func Test_RegisterDons(t *testing.T) { + var ( + useMCMS bool + lggr = logger.Test(t) + setupResp = kstest.SetupTestRegistry(t, lggr, &kstest.SetupTestRegistryRequest{}) + registry = setupResp.Registry + chain = setupResp.Chain + ) + t.Run("success create add DONs mcms proposal", func(t *testing.T) { + useMCMS = true + env := &deployment.Environment{ + Logger: lggr, + Chains: map[uint64]deployment.Chain{ + chain.Selector: chain, + }, + ExistingAddresses: deployment.NewMemoryAddressBookFromMap(map[uint64]map[string]deployment.TypeAndVersion{ + chain.Selector: { + registry.Address().String(): deployment.TypeAndVersion{ + Type: internal.CapabilitiesRegistry, + Version: deployment.Version1_0_0, + }, + }, + }), + } + resp, err := internal.RegisterDons(lggr, internal.RegisterDonsRequest{ + Env: env, + RegistryChainSelector: chain.Selector, + DonToCapabilities: map[string][]internal.RegisteredCapability{ + "test-don": {}, + }, + DonsToRegister: []internal.DONToRegister{ + { + Name: "test-don", + F: 2, + }, + }, + UseMCMS: useMCMS, + }) + require.NoError(t, err) + require.NotNil(t, resp.Ops) + require.Len(t, resp.Ops.Batch, 1) + }) + + t.Run("success create add DONs mcms proposal with multiple DONs", func(t *testing.T) { + useMCMS = true + env := &deployment.Environment{ + Logger: lggr, + Chains: map[uint64]deployment.Chain{ + chain.Selector: chain, + }, + ExistingAddresses: deployment.NewMemoryAddressBookFromMap(map[uint64]map[string]deployment.TypeAndVersion{ + chain.Selector: { + registry.Address().String(): deployment.TypeAndVersion{ + Type: internal.CapabilitiesRegistry, + Version: deployment.Version1_0_0, + }, + }, + }), + } + resp, err := internal.RegisterDons(lggr, internal.RegisterDonsRequest{ + Env: env, + RegistryChainSelector: chain.Selector, + DonToCapabilities: map[string][]internal.RegisteredCapability{ + "test-don-1": {}, + "test-don-2": {}, + }, + DonsToRegister: []internal.DONToRegister{ + { + Name: "test-don-1", + F: 2, + }, + { + Name: "test-don-2", + F: 2, + }, + }, + UseMCMS: useMCMS, + }) + require.NoError(t, err) + require.NotNil(t, resp.Ops) + require.Len(t, resp.Ops.Batch, 2) + }) +} diff --git a/deployment/keystone/forwarder_deployer.go b/deployment/keystone/changeset/internal/forwarder_deployer.go similarity index 96% rename from deployment/keystone/forwarder_deployer.go rename to deployment/keystone/changeset/internal/forwarder_deployer.go index 7c7b3a1ed93..6e374e200d7 100644 --- a/deployment/keystone/forwarder_deployer.go +++ b/deployment/keystone/changeset/internal/forwarder_deployer.go @@ -1,14 +1,15 @@ -package keystone +package internal import ( "fmt" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder" + forwarder "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder_1_0_0" ) type KeystoneForwarderDeployer struct { diff --git a/deployment/keystone/ocr3_deployer.go b/deployment/keystone/changeset/internal/ocr3_deployer.go similarity index 91% rename from deployment/keystone/ocr3_deployer.go rename to deployment/keystone/changeset/internal/ocr3_deployer.go index 227894f7c67..35e75b5ec43 100644 --- a/deployment/keystone/ocr3_deployer.go +++ b/deployment/keystone/changeset/internal/ocr3_deployer.go @@ -1,13 +1,14 @@ -package keystone +package internal import ( "fmt" "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability" + ocr3_capability "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability_1_0_0" ) type OCR3Deployer struct { diff --git a/deployment/keystone/ocr3config.go b/deployment/keystone/changeset/internal/ocr3config.go similarity index 97% rename from deployment/keystone/ocr3config.go rename to deployment/keystone/changeset/internal/ocr3config.go index d80c4930df4..d1d2e337efb 100644 --- a/deployment/keystone/ocr3config.go +++ b/deployment/keystone/changeset/internal/ocr3config.go @@ -1,6 +1,6 @@ // TODO: KS-458 copied from https://github.com/smartcontractkit/chainlink/blob/65924811dc53a211613927c814d7f04fd85439a4/core/scripts/keystone/src/88_gen_ocr3_config.go#L1 // to unblock go mod issues when trying to import the scripts package -package keystone +package internal import ( "crypto/ed25519" @@ -22,7 +22,7 @@ import ( "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" "github.com/smartcontractkit/chainlink/deployment" - kocr3 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability" + kocr3 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability_1_0_0" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" @@ -222,7 +222,7 @@ func GenerateOCR3Config(cfg OracleConfig, nca []NodeKeys, secrets deployment.OCR for index := range nca { identities = append(identities, confighelper.OracleIdentityExtra{ OracleIdentity: confighelper.OracleIdentity{ - OnchainPublicKey: onchainPubKeys[index][:], + OnchainPublicKey: onchainPubKeys[index], OffchainPublicKey: offchainPubKeysBytes[index], PeerID: nca[index].P2PPeerID, TransmitAccount: types.Account(nca[index].EthAddress), @@ -303,7 +303,7 @@ type configureOCR3Response struct { func configureOCR3contract(req configureOCR3Request) (*configureOCR3Response, error) { if req.contract == nil { - return nil, fmt.Errorf("OCR3 contract is nil") + return nil, errors.New("OCR3 contract is nil") } ocrConfig, err := req.generateOCR3Config() if err != nil { @@ -327,15 +327,15 @@ func configureOCR3contract(req configureOCR3Request) (*configureOCR3Response, er ocrConfig.OffchainConfig, ) if err != nil { - err = DecodeErr(kocr3.OCR3CapabilityABI, err) - return nil, fmt.Errorf("failed to call SetConfig for OCR3 contract %s using mcms: %t: %w", req.contract.Address().String(), req.useMCMS, err) + err = deployment.DecodeErr(kocr3.OCR3CapabilityABI, err) + return nil, fmt.Errorf("failed to call SetConfig for OCR3 contract %s using mcms: %T: %w", req.contract.Address().String(), req.useMCMS, err) } var ops *timelock.BatchChainOperation if !req.useMCMS { _, err = req.chain.Confirm(tx) if err != nil { - err = DecodeErr(kocr3.OCR3CapabilityABI, err) + err = deployment.DecodeErr(kocr3.OCR3CapabilityABI, err) return nil, fmt.Errorf("failed to confirm SetConfig for OCR3 contract %s: %w", req.contract.Address().String(), err) } } else { diff --git a/deployment/keystone/ocr3config_test.go b/deployment/keystone/changeset/internal/ocr3config_test.go similarity index 99% rename from deployment/keystone/ocr3config_test.go rename to deployment/keystone/changeset/internal/ocr3config_test.go index 55fa16af68c..55769fdaece 100644 --- a/deployment/keystone/ocr3config_test.go +++ b/deployment/keystone/changeset/internal/ocr3config_test.go @@ -1,6 +1,6 @@ // TODO: KS-458 copied from https://github.com/smartcontractkit/chainlink/blob/65924811dc53a211613927c814d7f04fd85439a4/core/scripts/keystone/src/88_gen_ocr3_config.go#L1 // to unblock go mod issues when trying to import the scripts package -package keystone +package internal import ( "encoding/json" @@ -115,7 +115,7 @@ func loadTestData(t *testing.T, path string) []deployment.Node { // in general we can map from the view to the node, but we know the test data var nodes []deployment.Node - //for _, nv := range nodeViews { + // for _, nv := range nodeViews { for _, name := range names { nv := nodeViews[name] node := deployment.Node{ diff --git a/deployment/keystone/state.go b/deployment/keystone/changeset/internal/state.go similarity index 56% rename from deployment/keystone/state.go rename to deployment/keystone/changeset/internal/state.go index 0ac7cdc89ed..3253acaf4e4 100644 --- a/deployment/keystone/state.go +++ b/deployment/keystone/changeset/internal/state.go @@ -1,6 +1,7 @@ -package keystone +package internal import ( + "errors" "fmt" "github.com/ethereum/go-ethereum/common" @@ -11,9 +12,10 @@ import ( commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" common_v1_0 "github.com/smartcontractkit/chainlink/deployment/common/view/v1_0" "github.com/smartcontractkit/chainlink/deployment/keystone/view" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability" + capabilities_registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + forwarder "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder_1_0_0" + ocr3_capability "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability_1_0_0" + workflow_registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/workflow/generated/workflow_registry_wrapper" ) type GetContractSetsRequest struct { @@ -27,15 +29,18 @@ type GetContractSetsResponse struct { type ContractSet struct { commonchangeset.MCMSWithTimelockState - OCR3 *ocr3_capability.OCR3Capability + OCR3 map[common.Address]*ocr3_capability.OCR3Capability Forwarder *forwarder.KeystoneForwarder CapabilitiesRegistry *capabilities_registry.CapabilitiesRegistry + WorkflowRegistry *workflow_registry.WorkflowRegistry } func (cs ContractSet) TransferableContracts() []common.Address { var out []common.Address if cs.OCR3 != nil { - out = append(out, cs.OCR3.Address()) + for _, ocr := range cs.OCR3 { + out = append(out, ocr.Address()) + } } if cs.Forwarder != nil { out = append(out, cs.Forwarder.Address()) @@ -43,6 +48,9 @@ func (cs ContractSet) TransferableContracts() []common.Address { if cs.CapabilitiesRegistry != nil { out = append(out, cs.CapabilitiesRegistry.Address()) } + if cs.WorkflowRegistry != nil { + out = append(out, cs.WorkflowRegistry.Address()) + } return out } @@ -58,6 +66,10 @@ func (cs ContractSet) View() (view.KeystoneChainView, error) { return out, nil } +func (cs ContractSet) GetOCR3Contract(addr *common.Address) (*ocr3_capability.OCR3Capability, error) { + return getOCR3Contract(cs.OCR3, addr) +} + func GetContractSets(lggr logger.Logger, req *GetContractSetsRequest) (*GetContractSetsResponse, error) { resp := &GetContractSetsResponse{ ContractSets: make(map[uint64]ContractSet), @@ -104,7 +116,16 @@ func loadContractSet(lggr logger.Logger, chain deployment.Chain, addresses map[s if err != nil { return nil, fmt.Errorf("failed to create OCR3Capability contract from address %s: %w", addr, err) } - out.OCR3 = c + if out.OCR3 == nil { + out.OCR3 = make(map[common.Address]*ocr3_capability.OCR3Capability) + } + out.OCR3[common.HexToAddress(addr)] = c + case WorkflowRegistry: + c, err := workflow_registry.NewWorkflowRegistry(common.HexToAddress(addr), chain.Client) + if err != nil { + return nil, fmt.Errorf("failed to create OCR3Capability contract from address %s: %w", addr, err) + } + out.WorkflowRegistry = c default: lggr.Warnw("unknown contract type", "type", tv.Type) // ignore unknown contract types @@ -112,3 +133,35 @@ func loadContractSet(lggr logger.Logger, chain deployment.Chain, addresses map[s } return &out, nil } + +// getOCR3Contract returns the OCR3 contract from the contract set. By default, it returns the only +// contract in the set if there is no address specified. If an address is specified, it returns the +// contract with that address. If the address is specified but not found in the contract set, it returns +// an error. +func getOCR3Contract(contracts map[common.Address]*ocr3_capability.OCR3Capability, addr *common.Address) (*ocr3_capability.OCR3Capability, error) { + // Fail if the OCR3 contract address is unspecified and there are multiple OCR3 contracts + if addr == nil && len(contracts) > 1 { + return nil, errors.New("OCR contract address is unspecified") + } + + // Use the first OCR3 contract if the address is unspecified + if addr == nil && len(contracts) == 1 { + // use the first OCR3 contract + for _, c := range contracts { + return c, nil + } + } + + // Select the OCR3 contract by address + if contract, ok := contracts[*addr]; ok { + return contract, nil + } + + addrSet := make([]string, 0, len(contracts)) + for a := range contracts { + addrSet = append(addrSet, a.String()) + } + + // Fail if the OCR3 contract address is specified but not found in the contract set + return nil, fmt.Errorf("OCR3 contract address %s not found in contract set %v", *addr, addrSet) +} diff --git a/deployment/keystone/changeset/internal/test/utils.go b/deployment/keystone/changeset/internal/test/utils.go index 0a23f7e60a7..cc7e3b27160 100644 --- a/deployment/keystone/changeset/internal/test/utils.go +++ b/deployment/keystone/changeset/internal/test/utils.go @@ -17,10 +17,8 @@ import ( "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/environment/memory" - kslib "github.com/smartcontractkit/chainlink/deployment/keystone" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + capabilities_registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) @@ -29,18 +27,19 @@ type Don struct { P2PIDs []p2pkey.PeerID CapabilityConfigs []internal.CapabilityConfig } + type SetupTestRegistryRequest struct { - P2pToCapabilities map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability - NopToNodes map[kcr.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc + P2pToCapabilities map[p2pkey.PeerID][]capabilities_registry.CapabilitiesRegistryCapability + NopToNodes map[capabilities_registry.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc Dons []Don // TODO maybe add support for MCMS at this level } type SetupTestRegistryResponse struct { - Registry *kcr.CapabilitiesRegistry + Registry *capabilities_registry.CapabilitiesRegistry Chain deployment.Chain RegistrySelector uint64 - ContractSet *kslib.ContractSet + ContractSet *internal.ContractSet } func SetupTestRegistry(t *testing.T, lggr logger.Logger, req *SetupTestRegistryRequest) *SetupTestRegistryResponse { @@ -48,7 +47,7 @@ func SetupTestRegistry(t *testing.T, lggr logger.Logger, req *SetupTestRegistryR // deploy the registry registry := deployCapReg(t, chain) // convert req to nodeoperators - nops := make([]kcr.CapabilitiesRegistryNodeOperator, 0) + nops := make([]capabilities_registry.CapabilitiesRegistryNodeOperator, 0) for nop := range req.NopToNodes { nops = append(nops, nop) } @@ -60,19 +59,19 @@ func SetupTestRegistry(t *testing.T, lggr logger.Logger, req *SetupTestRegistryR // add capabilities to registry capCache := NewCapabiltyCache(t) - var capabilities []kcr.CapabilitiesRegistryCapability + var capabilities []capabilities_registry.CapabilitiesRegistryCapability for _, caps := range req.P2pToCapabilities { capabilities = append(capabilities, caps...) } registeredCapabilities := capCache.AddCapabilities(lggr, chain, registry, capabilities) - expectedDeduped := make(map[kcr.CapabilitiesRegistryCapability]struct{}) + expectedDeduped := make(map[capabilities_registry.CapabilitiesRegistryCapability]struct{}) for _, cap := range capabilities { expectedDeduped[cap] = struct{}{} } require.Len(t, registeredCapabilities, len(expectedDeduped)) // make the nodes and register node - var nodeParams []kcr.CapabilitiesRegistryNodeParams + var nodeParams []capabilities_registry.CapabilitiesRegistryNodeParams initialp2pToCapabilities := make(map[p2pkey.PeerID][][32]byte) for p2pID := range req.P2pToCapabilities { initialp2pToCapabilities[p2pID] = mustCapabilityIds(t, registry, registeredCapabilities) @@ -83,7 +82,7 @@ func SetupTestRegistry(t *testing.T, lggr logger.Logger, req *SetupTestRegistryR require.Fail(t, "missing nopToNodes for %s", nop.Name) } for _, p2pSignerEnc := range req.NopToNodes[nop] { - nodeParams = append(nodeParams, kcr.CapabilitiesRegistryNodeParams{ + nodeParams = append(nodeParams, capabilities_registry.CapabilitiesRegistryNodeParams{ Signer: p2pSignerEnc.Signer, P2pId: p2pSignerEnc.P2PKey, EncryptionPublicKey: p2pSignerEnc.EncryptionPublicKey, @@ -101,21 +100,21 @@ func SetupTestRegistry(t *testing.T, lggr logger.Logger, req *SetupTestRegistryR Registry: registry, Chain: chain, RegistrySelector: chain.Selector, - ContractSet: &kslib.ContractSet{ + ContractSet: &internal.ContractSet{ CapabilitiesRegistry: registry, }, } } -func deployCapReg(t *testing.T, chain deployment.Chain) *kcr.CapabilitiesRegistry { - capabilitiesRegistryDeployer, err := kslib.NewCapabilitiesRegistryDeployer() +func deployCapReg(t *testing.T, chain deployment.Chain) *capabilities_registry.CapabilitiesRegistry { + capabilitiesRegistryDeployer, err := internal.NewCapabilitiesRegistryDeployer() require.NoError(t, err) - _, err = capabilitiesRegistryDeployer.Deploy(kslib.DeployRequest{Chain: chain}) + _, err = capabilitiesRegistryDeployer.Deploy(internal.DeployRequest{Chain: chain}) require.NoError(t, err) return capabilitiesRegistryDeployer.Contract() } -func addNops(t *testing.T, lggr logger.Logger, chain deployment.Chain, registry *kcr.CapabilitiesRegistry, nops []kcr.CapabilitiesRegistryNodeOperator) *kslib.RegisterNOPSResponse { +func addNops(t *testing.T, lggr logger.Logger, chain deployment.Chain, registry *capabilities_registry.CapabilitiesRegistry, nops []capabilities_registry.CapabilitiesRegistryNodeOperator) *internal.RegisterNOPSResponse { env := &deployment.Environment{ Logger: lggr, Chains: map[uint64]deployment.Chain{ @@ -124,13 +123,13 @@ func addNops(t *testing.T, lggr logger.Logger, chain deployment.Chain, registry ExistingAddresses: deployment.NewMemoryAddressBookFromMap(map[uint64]map[string]deployment.TypeAndVersion{ chain.Selector: { registry.Address().String(): deployment.TypeAndVersion{ - Type: kslib.CapabilitiesRegistry, + Type: internal.CapabilitiesRegistry, Version: deployment.Version1_0_0, }, }, }), } - resp, err := kslib.RegisterNOPS(context.TODO(), lggr, kslib.RegisterNOPSRequest{ + resp, err := internal.RegisterNOPS(context.TODO(), lggr, internal.RegisterNOPSRequest{ Env: env, RegistryChainSelector: chain.Selector, Nops: nops, @@ -139,23 +138,23 @@ func addNops(t *testing.T, lggr logger.Logger, chain deployment.Chain, registry return resp } -func addNodes(t *testing.T, lggr logger.Logger, chain deployment.Chain, registry *kcr.CapabilitiesRegistry, nodes []kcr.CapabilitiesRegistryNodeParams) { +func addNodes(t *testing.T, lggr logger.Logger, chain deployment.Chain, registry *capabilities_registry.CapabilitiesRegistry, nodes []capabilities_registry.CapabilitiesRegistryNodeParams) { tx, err := registry.AddNodes(chain.DeployerKey, nodes) if err != nil { - err2 := kslib.DecodeErr(kcr.CapabilitiesRegistryABI, err) + err2 := deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) require.Fail(t, fmt.Sprintf("failed to call AddNodes: %s: %s", err, err2)) } _, err = chain.Confirm(tx) require.NoError(t, err) } -func addDons(t *testing.T, lggr logger.Logger, chain deployment.Chain, registry *kcr.CapabilitiesRegistry, capCache *CapabilityCache, dons []Don) { +func addDons(t *testing.T, lggr logger.Logger, chain deployment.Chain, registry *capabilities_registry.CapabilitiesRegistry, capCache *CapabilityCache, dons []Don) { for _, don := range dons { acceptsWorkflows := false // lookup the capabilities - var capConfigs []kcr.CapabilitiesRegistryCapabilityConfiguration + var capConfigs []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration for _, ccfg := range don.CapabilityConfigs { - var cc = kcr.CapabilitiesRegistryCapabilityConfiguration{ + var cc = capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ CapabilityId: [32]byte{}, Config: ccfg.Config, } @@ -175,7 +174,7 @@ func addDons(t *testing.T, lggr logger.Logger, chain deployment.Chain, registry f := len(don.P2PIDs)/3 + 1 tx, err := registry.AddDON(chain.DeployerKey, internal.PeerIDsToBytes(don.P2PIDs), capConfigs, isPublic, acceptsWorkflows, uint8(f)) if err != nil { - err2 := kslib.DecodeErr(kcr.CapabilitiesRegistryABI, err) + err2 := deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) require.Fail(t, fmt.Sprintf("failed to call AddDON: %s: %s", err, err2)) } _, err = chain.Confirm(tx) @@ -183,7 +182,7 @@ func addDons(t *testing.T, lggr logger.Logger, chain deployment.Chain, registry } } -func defaultCapConfig(t *testing.T, cap kcr.CapabilitiesRegistryCapability) []byte { +func defaultCapConfig(t *testing.T, cap capabilities_registry.CapabilitiesRegistryCapability) []byte { empty := &capabilitiespb.CapabilityConfig{ DefaultConfig: values.Proto(values.EmptyMap()).GetMapValue(), } @@ -204,24 +203,24 @@ func NewCapabiltyCache(t *testing.T) *CapabilityCache { nameToId: make(map[string][32]byte), } } -func (cc *CapabilityCache) Get(cap kcr.CapabilitiesRegistryCapability) ([32]byte, bool) { - id, exists := cc.nameToId[kslib.CapabilityID(cap)] +func (cc *CapabilityCache) Get(cap capabilities_registry.CapabilitiesRegistryCapability) ([32]byte, bool) { + id, exists := cc.nameToId[internal.CapabilityID(cap)] return id, exists } // AddCapabilities adds the capabilities to the registry and returns the registered capabilities // if the capability is already registered, it will not be re-registered // if duplicate capabilities are passed, they will be deduped -func (cc *CapabilityCache) AddCapabilities(lggr logger.Logger, chain deployment.Chain, registry *kcr.CapabilitiesRegistry, capabilities []kcr.CapabilitiesRegistryCapability) []kslib.RegisteredCapability { +func (cc *CapabilityCache) AddCapabilities(lggr logger.Logger, chain deployment.Chain, registry *capabilities_registry.CapabilitiesRegistry, capabilities []capabilities_registry.CapabilitiesRegistryCapability) []internal.RegisteredCapability { t := cc.t - var out []kslib.RegisteredCapability + var out []internal.RegisteredCapability // get the registered capabilities & dedup - seen := make(map[kcr.CapabilitiesRegistryCapability]struct{}) - var toRegister []kcr.CapabilitiesRegistryCapability + seen := make(map[capabilities_registry.CapabilitiesRegistryCapability]struct{}) + var toRegister []capabilities_registry.CapabilitiesRegistryCapability for _, cap := range capabilities { - id, cached := cc.nameToId[kslib.CapabilityID(cap)] + id, cached := cc.nameToId[internal.CapabilityID(cap)] if cached { - out = append(out, kslib.RegisteredCapability{ + out = append(out, internal.RegisteredCapability{ CapabilitiesRegistryCapability: cap, ID: id, }) @@ -238,7 +237,7 @@ func (cc *CapabilityCache) AddCapabilities(lggr logger.Logger, chain deployment. } tx, err := registry.AddCapabilities(chain.DeployerKey, toRegister) if err != nil { - err2 := kslib.DecodeErr(kcr.CapabilitiesRegistryABI, err) + err2 := deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) require.Fail(t, fmt.Sprintf("failed to call AddCapabilities: %s: %s", err, err2)) } _, err = chain.Confirm(tx) @@ -249,12 +248,12 @@ func (cc *CapabilityCache) AddCapabilities(lggr logger.Logger, chain deployment. capb := capb id, err := registry.GetHashedCapabilityId(&bind.CallOpts{}, capb.LabelledName, capb.Version) require.NoError(t, err) - out = append(out, kslib.RegisteredCapability{ + out = append(out, internal.RegisteredCapability{ CapabilitiesRegistryCapability: capb, ID: id, }) // cache the id - cc.nameToId[kslib.CapabilityID(capb)] = id + cc.nameToId[internal.CapabilityID(capb)] = id } return out } @@ -270,7 +269,7 @@ func testChain(t *testing.T) deployment.Chain { return chain } -func capabilityIds(registry *capabilities_registry.CapabilitiesRegistry, rcs []kslib.RegisteredCapability) ([][32]byte, error) { +func capabilityIds(registry *capabilities_registry.CapabilitiesRegistry, rcs []internal.RegisteredCapability) ([][32]byte, error) { out := make([][32]byte, len(rcs)) for i := range rcs { id, err := registry.GetHashedCapabilityId(&bind.CallOpts{}, rcs[i].LabelledName, rcs[i].Version) @@ -282,7 +281,7 @@ func capabilityIds(registry *capabilities_registry.CapabilitiesRegistry, rcs []k return out, nil } -func mustCapabilityIds(t *testing.T, registry *capabilities_registry.CapabilitiesRegistry, rcs []kslib.RegisteredCapability) [][32]byte { +func mustCapabilityIds(t *testing.T, registry *capabilities_registry.CapabilitiesRegistry, rcs []internal.RegisteredCapability) [][32]byte { t.Helper() out, err := capabilityIds(registry, rcs) require.NoError(t, err) diff --git a/deployment/keystone/testdata/testnet_wf_view.json b/deployment/keystone/changeset/internal/testdata/testnet_wf_view.json similarity index 100% rename from deployment/keystone/testdata/testnet_wf_view.json rename to deployment/keystone/changeset/internal/testdata/testnet_wf_view.json diff --git a/deployment/keystone/types.go b/deployment/keystone/changeset/internal/types.go similarity index 94% rename from deployment/keystone/types.go rename to deployment/keystone/changeset/internal/types.go index d406487043c..cffd69f85e6 100644 --- a/deployment/keystone/types.go +++ b/deployment/keystone/changeset/internal/types.go @@ -1,6 +1,7 @@ -package keystone +package internal import ( + "encoding/hex" "errors" "fmt" "slices" @@ -14,13 +15,14 @@ import ( "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + capabilities_registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) var ( CapabilitiesRegistry deployment.ContractType = "CapabilitiesRegistry" // https://github.com/smartcontractkit/chainlink/blob/50c1b3dbf31bd145b312739b08967600a5c67f30/contracts/src/v0.8/keystone/CapabilitiesRegistry.sol#L392 + WorkflowRegistry deployment.ContractType = "WorkflowRegistry" // https://github.com/smartcontractkit/chainlink/blob/develop/contracts/src/v0.8/workflow/dev/WorkflowRegistry.sol KeystoneForwarder deployment.ContractType = "KeystoneForwarder" // https://github.com/smartcontractkit/chainlink/blob/50c1b3dbf31bd145b312739b08967600a5c67f30/contracts/src/v0.8/keystone/KeystoneForwarder.sol#L90 OCR3Capability deployment.ContractType = "OCR3Capability" // https://github.com/smartcontractkit/chainlink/blob/50c1b3dbf31bd145b312739b08967600a5c67f30/contracts/src/v0.8/keystone/OCR3Capability.sol#L12 FeedConsumer deployment.ContractType = "FeedConsumer" // no type and a version in contract https://github.com/smartcontractkit/chainlink/blob/89183a8a5d22b1aeca0ade3b76d16aa84067aa57/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol#L1 @@ -80,9 +82,9 @@ func toNodeKeys(o *deployment.Node, registryChainSel uint64) NodeKeys { EthAddress: string(evmCC.TransmitAccount), P2PPeerID: strings.TrimPrefix(o.PeerID.String(), "p2p_"), OCR2BundleID: evmCC.KeyBundleID, - OCR2OffchainPublicKey: fmt.Sprintf("%x", evmCC.OffchainPublicKey[:]), + OCR2OffchainPublicKey: hex.EncodeToString(evmCC.OffchainPublicKey[:]), OCR2OnchainPublicKey: fmt.Sprintf("%x", evmCC.OnchainPublicKey[:]), - OCR2ConfigPublicKey: fmt.Sprintf("%x", evmCC.ConfigEncryptionPublicKey[:]), + OCR2ConfigPublicKey: hex.EncodeToString(evmCC.ConfigEncryptionPublicKey[:]), CSAPublicKey: o.CSAKey, // default value of encryption public key is the CSA public key // TODO: DEVSVCS-760 @@ -265,7 +267,7 @@ func NewRegisteredDon(env deployment.Environment, cfg RegisteredDonConfig) (*Reg } } if don == nil { - return nil, fmt.Errorf("don not found in registry") + return nil, errors.New("don not found in registry") } return &RegisteredDon{ Name: cfg.Name, @@ -285,11 +287,10 @@ func (d RegisteredDon) Signers(chainFamily string) []common.Address { } var found bool var registryChainDetails chainsel.ChainDetails - for details, _ := range n.SelToOCRConfig { + for details := range n.SelToOCRConfig { if family, err := chainsel.GetSelectorFamily(details.ChainSelector); err == nil && family == chainFamily { found = true registryChainDetails = details - } } if !found { @@ -318,7 +319,6 @@ func joinInfoAndNodes(donInfos map[string]kcr.CapabilitiesRegistryDONInfo, dons } var out []RegisteredDon for donName, info := range donInfos { - ocr2nodes, ok := nodes[donName] if !ok { return nil, fmt.Errorf("nodes not found for don %s", donName) diff --git a/deployment/keystone/types_test.go b/deployment/keystone/changeset/internal/types_test.go similarity index 97% rename from deployment/keystone/types_test.go rename to deployment/keystone/changeset/internal/types_test.go index ea122837aa6..e8d02f51df0 100644 --- a/deployment/keystone/types_test.go +++ b/deployment/keystone/changeset/internal/types_test.go @@ -1,4 +1,4 @@ -package keystone +package internal import ( "encoding/hex" @@ -10,10 +10,11 @@ import ( "github.com/ethereum/go-ethereum/common" chainsel "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) func Test_toNodeKeys(t *testing.T) { @@ -49,7 +50,7 @@ func Test_toNodeKeys(t *testing.T) { SelToOCRConfig: map[chainsel.ChainDetails]deployment.OCRConfig{ registryChainDetails: { OffchainPublicKey: types.OffchainPublicKey(common.FromHex("1111111111111111111111111111111111111111111111111111111111111111")), - OnchainPublicKey: signing_1[:], + OnchainPublicKey: signing_1, PeerID: p2pID.PeerID(), TransmitAccount: types.Account(admin_1.String()), ConfigEncryptionPublicKey: encryptionpubkey, diff --git a/deployment/keystone/changeset/internal/update_don.go b/deployment/keystone/changeset/internal/update_don.go index fc7e410e540..aa3e203e5e4 100644 --- a/deployment/keystone/changeset/internal/update_don.go +++ b/deployment/keystone/changeset/internal/update_don.go @@ -5,6 +5,7 @@ import ( "crypto/sha256" "encoding/hex" "encoding/json" + "errors" "fmt" "math/big" "sort" @@ -12,14 +13,13 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + "google.golang.org/protobuf/proto" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" - "google.golang.org/protobuf/proto" - - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" - kslib "github.com/smartcontractkit/chainlink/deployment/keystone" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" ) // CapabilityConfig is a struct that holds a capability and its configuration @@ -30,7 +30,7 @@ type CapabilityConfig struct { type UpdateDonRequest struct { Chain deployment.Chain - ContractSet *kslib.ContractSet // contract set for the given chain + ContractSet *ContractSet // contract set for the given chain P2PIDs []p2pkey.PeerID // this is the unique identifier for the don CapabilityConfigs []CapabilityConfig // if Config subfield is nil, a default config is used @@ -58,10 +58,10 @@ func (r *UpdateDonRequest) AppendNodeCapabilitiesRequest() *AppendNodeCapabiliti func (r *UpdateDonRequest) Validate() error { if r.ContractSet.CapabilitiesRegistry == nil { - return fmt.Errorf("registry is required") + return errors.New("registry is required") } if len(r.P2PIDs) == 0 { - return fmt.Errorf("p2pIDs is required") + return errors.New("p2pIDs is required") } return nil } @@ -97,7 +97,7 @@ func UpdateDon(lggr logger.Logger, req *UpdateDonRequest) (*UpdateDonResponse, e } tx, err := registry.UpdateDON(txOpts, don.Id, don.NodeP2PIds, cfgs, don.IsPublic, don.F) if err != nil { - err = kslib.DecodeErr(kcr.CapabilitiesRegistryABI, err) + err = deployment.DecodeErr(kcr.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to call UpdateDON: %w", err) } var ops *timelock.BatchChainOperation @@ -150,7 +150,7 @@ func computeConfigs(registry *kcr.CapabilitiesRegistry, caps []CapabilityConfig, } out[i].CapabilityId = id if out[i].Config == nil { - c := kslib.DefaultCapConfig(cap.Capability.CapabilityType, int(donInfo.F)) + c := DefaultCapConfig(cap.Capability.CapabilityType, int(donInfo.F)) cb, err := proto.Marshal(c) if err != nil { return nil, fmt.Errorf("failed to marshal capability config for %v: %w", c, err) diff --git a/deployment/keystone/changeset/internal/update_don_test.go b/deployment/keystone/changeset/internal/update_don_test.go index 93857b26f78..bf9ab96fecb 100644 --- a/deployment/keystone/changeset/internal/update_don_test.go +++ b/deployment/keystone/changeset/internal/update_don_test.go @@ -11,17 +11,16 @@ import ( "github.com/ethereum/go-ethereum/common" chainsel "github.com/smartcontractkit/chain-selectors" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/keystone" - kslib "github.com/smartcontractkit/chainlink/deployment/keystone" kscs "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" kstest "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal/test" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) var ( @@ -100,14 +99,14 @@ func TestUpdateDon(t *testing.T) { t.Run("empty", func(t *testing.T) { cfg := setupUpdateDonTestConfig{ - dons: []kslib.DonInfo{ + dons: []internal.DonInfo{ { Name: "don 1", Nodes: []deployment.Node{node_1, node_2, node_3, node_4}, Capabilities: []kcr.CapabilitiesRegistryCapability{initialCap}, }, }, - nops: []keystone.NOP{ + nops: []internal.NOP{ { Name: "nop 1", Nodes: []string{node_1.NodeID, node_2.NodeID, node_3.NodeID, node_4.NodeID}, @@ -155,7 +154,6 @@ func TestUpdateDon(t *testing.T) { assert.Equal(t, want.DonInfo.ConfigCount, got.DonInfo.ConfigCount) assert.Equal(t, sortedP2Pids(want.DonInfo.NodeP2PIds), sortedP2Pids(got.DonInfo.NodeP2PIds)) assert.Equal(t, capIds(want.DonInfo.CapabilityConfigurations), capIds(got.DonInfo.CapabilityConfigurations)) - }) } @@ -223,8 +221,8 @@ func newNode(t *testing.T, cfg minimalNodeCfg) deployment.Node { } type setupUpdateDonTestConfig struct { - dons []kslib.DonInfo - nops []keystone.NOP + dons []internal.DonInfo + nops []internal.NOP } type setupUpdateDonTestResult struct { @@ -236,10 +234,9 @@ func registerTestDon(t *testing.T, lggr logger.Logger, cfg setupUpdateDonTestCon t.Helper() req := newSetupTestRegistryRequest(t, cfg.dons, cfg.nops) return kstest.SetupTestRegistry(t, lggr, req) - } -func newSetupTestRegistryRequest(t *testing.T, dons []kslib.DonInfo, nops []keystone.NOP) *kstest.SetupTestRegistryRequest { +func newSetupTestRegistryRequest(t *testing.T, dons []internal.DonInfo, nops []internal.NOP) *kstest.SetupTestRegistryRequest { t.Helper() nodes := make(map[string]deployment.Node) for _, don := range dons { @@ -258,7 +255,7 @@ func newSetupTestRegistryRequest(t *testing.T, dons []kslib.DonInfo, nops []keys return req } -func makeNopToNodes(t *testing.T, nops []keystone.NOP, nodes map[string]deployment.Node) map[kcr.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc { +func makeNopToNodes(t *testing.T, nops []internal.NOP, nodes map[string]deployment.Node) map[kcr.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc { nopToNodes := make(map[kcr.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc) for _, nop := range nops { @@ -282,7 +279,7 @@ func makeNopToNodes(t *testing.T, nops []keystone.NOP, nodes map[string]deployme return nopToNodes } -func makeP2PToCapabilities(t *testing.T, dons []kslib.DonInfo) map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability { +func makeP2PToCapabilities(t *testing.T, dons []internal.DonInfo) map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability { p2pToCapabilities := make(map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability) for _, don := range dons { for _, node := range don.Nodes { @@ -296,7 +293,7 @@ func makeP2PToCapabilities(t *testing.T, dons []kslib.DonInfo) map[p2pkey.PeerID return p2pToCapabilities } -func makeTestDon(t *testing.T, dons []kslib.DonInfo) []kstest.Don { +func makeTestDon(t *testing.T, dons []internal.DonInfo) []kstest.Don { out := make([]kstest.Don, len(dons)) for i, don := range dons { out[i] = testDon(t, don) @@ -304,7 +301,7 @@ func makeTestDon(t *testing.T, dons []kslib.DonInfo) []kstest.Don { return out } -func testDon(t *testing.T, don kslib.DonInfo) kstest.Don { +func testDon(t *testing.T, don internal.DonInfo) kstest.Don { var p2pids []p2pkey.PeerID for _, node := range don.Nodes { // all chain configs are the same wrt admin address & node keys diff --git a/deployment/keystone/changeset/internal/update_node_capabilities.go b/deployment/keystone/changeset/internal/update_node_capabilities.go index fe101c90296..34fb5346d5c 100644 --- a/deployment/keystone/changeset/internal/update_node_capabilities.go +++ b/deployment/keystone/changeset/internal/update_node_capabilities.go @@ -1,18 +1,18 @@ package internal import ( + "errors" "fmt" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/deployment" - kslib "github.com/smartcontractkit/chainlink/deployment/keystone" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) type UpdateNodeCapabilitiesImplRequest struct { Chain deployment.Chain - ContractSet *kslib.ContractSet + ContractSet *ContractSet P2pToCapabilities map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability UseMCMS bool @@ -20,10 +20,10 @@ type UpdateNodeCapabilitiesImplRequest struct { func (req *UpdateNodeCapabilitiesImplRequest) Validate() error { if len(req.P2pToCapabilities) == 0 { - return fmt.Errorf("p2pToCapabilities is empty") + return errors.New("p2pToCapabilities is empty") } if req.ContractSet == nil { - return fmt.Errorf("registry is nil") + return errors.New("registry is nil") } return nil @@ -38,7 +38,7 @@ func UpdateNodeCapabilitiesImpl(lggr logger.Logger, req *UpdateNodeCapabilitiesI for _, cap := range req.P2pToCapabilities { capabilities = append(capabilities, cap...) } - op, err := kslib.AddCapabilities(lggr, req.ContractSet, req.Chain, capabilities, req.UseMCMS) + op, err := AddCapabilities(lggr, req.ContractSet.CapabilitiesRegistry, req.Chain, capabilities, req.UseMCMS) if err != nil { return nil, fmt.Errorf("failed to add capabilities: %w", err) } diff --git a/deployment/keystone/changeset/internal/update_node_capabilities_test.go b/deployment/keystone/changeset/internal/update_node_capabilities_test.go index ac39e57b32d..65da264dd01 100644 --- a/deployment/keystone/changeset/internal/update_node_capabilities_test.go +++ b/deployment/keystone/changeset/internal/update_node_capabilities_test.go @@ -8,9 +8,9 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/deployment" - kslib "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" kstest "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal/test" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) @@ -25,9 +25,9 @@ func TestUpdateNodeCapabilities(t *testing.T) { }, }, } - nopToNodes = map[kcr.CapabilitiesRegistryNodeOperator][]*kslib.P2PSignerEnc{ - testNop(t, "testNop"): []*kslib.P2PSignerEnc{ - &kslib.P2PSignerEnc{ + nopToNodes = map[kcr.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc{ + testNop(t, "testNop"): []*internal.P2PSignerEnc{ + &internal.P2PSignerEnc{ Signer: [32]byte{0: 1}, P2PKey: testPeerID(t, "0x1"), EncryptionPublicKey: [32]byte{3: 16, 4: 2}, @@ -40,7 +40,7 @@ func TestUpdateNodeCapabilities(t *testing.T) { type args struct { lggr logger.Logger - req *kslib.UpdateNodeCapabilitiesImplRequest // chain and registry are set in the test setup + req *internal.UpdateNodeCapabilitiesImplRequest // chain and registry are set in the test setup initialState *kstest.SetupTestRegistryRequest } tests := []struct { @@ -53,7 +53,7 @@ func TestUpdateNodeCapabilities(t *testing.T) { name: "invalid request", args: args{ lggr: lggr, - req: &kslib.UpdateNodeCapabilitiesImplRequest{ + req: &internal.UpdateNodeCapabilitiesImplRequest{ Chain: deployment.Chain{}, }, initialState: &kstest.SetupTestRegistryRequest{}, @@ -68,7 +68,7 @@ func TestUpdateNodeCapabilities(t *testing.T) { P2pToCapabilities: initialp2pToCapabilities, NopToNodes: nopToNodes, }, - req: &kslib.UpdateNodeCapabilitiesImplRequest{ + req: &internal.UpdateNodeCapabilitiesImplRequest{ P2pToCapabilities: map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability{ testPeerID(t, "0x1"): []kcr.CapabilitiesRegistryCapability{ { @@ -95,7 +95,7 @@ func TestUpdateNodeCapabilities(t *testing.T) { tt.args.req.Chain = setupResp.Chain tt.args.req.ContractSet = setupResp.ContractSet - got, err := kslib.UpdateNodeCapabilitiesImpl(tt.args.lggr, tt.args.req) + got, err := internal.UpdateNodeCapabilitiesImpl(tt.args.lggr, tt.args.req) if (err != nil) != tt.wantErr { t.Errorf("UpdateNodeCapabilities() error = %v, wantErr %v", err, tt.wantErr) return diff --git a/deployment/keystone/changeset/internal/update_nodes.go b/deployment/keystone/changeset/internal/update_nodes.go index 3480f39b084..976125e582d 100644 --- a/deployment/keystone/changeset/internal/update_nodes.go +++ b/deployment/keystone/changeset/internal/update_nodes.go @@ -12,12 +12,12 @@ import ( "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + "github.com/smartcontractkit/chainlink-common/pkg/logger" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" "github.com/smartcontractkit/chainlink/deployment" - kslib "github.com/smartcontractkit/chainlink/deployment/keystone" ) type NodeUpdate struct { @@ -30,7 +30,7 @@ type NodeUpdate struct { type UpdateNodesRequest struct { Chain deployment.Chain - ContractSet *kslib.ContractSet // contract set for the given chain + ContractSet *ContractSet // contract set for the given chain P2pToUpdates map[p2pkey.PeerID]NodeUpdate @@ -60,7 +60,7 @@ func (req *UpdateNodesRequest) Validate() error { for peer, updates := range req.P2pToUpdates { seen := make(map[string]struct{}) for _, cap := range updates.Capabilities { - id := kslib.CapabilityID(cap) + id := CapabilityID(cap) if _, exists := seen[id]; exists { return fmt.Errorf("duplicate capability %s for %s", id, peer) } @@ -103,7 +103,7 @@ func UpdateNodes(lggr logger.Logger, req *UpdateNodesRequest) (*UpdateNodesRespo params, err := req.NodeParams() if err != nil { - err = kslib.DecodeErr(kcr.CapabilitiesRegistryABI, err) + err = deployment.DecodeErr(kcr.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to make node params: %w", err) } txOpts := req.Chain.DeployerKey @@ -113,7 +113,7 @@ func UpdateNodes(lggr logger.Logger, req *UpdateNodesRequest) (*UpdateNodesRespo registry := req.ContractSet.CapabilitiesRegistry tx, err := registry.UpdateNodes(txOpts, params) if err != nil { - err = kslib.DecodeErr(kcr.CapabilitiesRegistryABI, err) + err = deployment.DecodeErr(kcr.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to call UpdateNodes: %w", err) } @@ -183,8 +183,8 @@ func AppendCapabilities(lggr logger.Logger, registry *kcr.CapabilitiesRegistry, var deduped []kcr.CapabilitiesRegistryCapability seen := make(map[string]struct{}) for _, cap := range mergedCaps { - if _, ok := seen[kslib.CapabilityID(cap)]; !ok { - seen[kslib.CapabilityID(cap)] = struct{}{} + if _, ok := seen[CapabilityID(cap)]; !ok { + seen[CapabilityID(cap)] = struct{}{} deduped = append(deduped, cap) } } @@ -195,7 +195,6 @@ func AppendCapabilities(lggr logger.Logger, registry *kcr.CapabilitiesRegistry, func makeNodeParams(registry *kcr.CapabilitiesRegistry, p2pToUpdates map[p2pkey.PeerID]NodeUpdate) ([]kcr.CapabilitiesRegistryNodeParams, error) { - var out []kcr.CapabilitiesRegistryNodeParams var p2pIds []p2pkey.PeerID for p2pID := range p2pToUpdates { @@ -204,7 +203,7 @@ func makeNodeParams(registry *kcr.CapabilitiesRegistry, nodes, err := registry.GetNodesByP2PIds(&bind.CallOpts{}, PeerIDsToBytes(p2pIds)) if err != nil { - err = kslib.DecodeErr(kcr.CapabilitiesRegistryABI, err) + err = deployment.DecodeErr(kcr.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to get nodes by p2p ids: %w", err) } for _, node := range nodes { @@ -258,14 +257,13 @@ func makeNodeParams(registry *kcr.CapabilitiesRegistry, }) return out, nil - } -// fetchkslib.CapabilityIDs fetches the capability ids for the given capabilities +// fetchCapabilityIDs fetches the capability ids for the given capabilities func fetchCapabilityIDs(registry *kcr.CapabilitiesRegistry, caps []kcr.CapabilitiesRegistryCapability) (map[string][32]byte, error) { out := make(map[string][32]byte) for _, cap := range caps { - name := kslib.CapabilityID(cap) + name := CapabilityID(cap) if _, exists := out[name]; exists { continue } diff --git a/deployment/keystone/changeset/internal/update_nodes_test.go b/deployment/keystone/changeset/internal/update_nodes_test.go index e730668f806..1b532129e48 100644 --- a/deployment/keystone/changeset/internal/update_nodes_test.go +++ b/deployment/keystone/changeset/internal/update_nodes_test.go @@ -16,12 +16,11 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/deployment" - kslib "github.com/smartcontractkit/chainlink/deployment/keystone" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" kstest "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal/test" "github.com/smartcontractkit/chainlink/deployment/environment/memory" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) @@ -30,7 +29,7 @@ func Test_UpdateNodesRequest_validate(t *testing.T) { p2pToUpdates map[p2pkey.PeerID]internal.NodeUpdate nopToNodes map[kcr.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc chain deployment.Chain - contractSet *kslib.ContractSet + contractSet *internal.ContractSet } tests := []struct { name string @@ -465,14 +464,14 @@ func TestUpdateNodes(t *testing.T) { require.NoError(t, err) // register the capabilities that the Update will use - expectedUpdatedCaps := make(map[p2pkey.PeerID][]kslib.RegisteredCapability) + expectedUpdatedCaps := make(map[p2pkey.PeerID][]internal.RegisteredCapability) capCache := kstest.NewCapabiltyCache(t) for p2p, update := range tt.args.req.P2pToUpdates { if len(update.Capabilities) > 0 { expectedCaps := capCache.AddCapabilities(tt.args.lggr, tt.args.req.Chain, registry, update.Capabilities) expectedUpdatedCaps[p2p] = expectedCaps } else { - expectedUpdatedCaps[p2p] = []kslib.RegisteredCapability{ + expectedUpdatedCaps[p2p] = []internal.RegisteredCapability{ {CapabilitiesRegistryCapability: phonyCap, ID: id}, } } @@ -564,7 +563,7 @@ func TestUpdateNodes(t *testing.T) { toRegister := p2pToCapabilitiesUpdated[testPeerID(t, "peerID_1")] tx, err := registry.AddCapabilities(chain.DeployerKey, toRegister) if err != nil { - err2 := kslib.DecodeErr(kcr.CapabilitiesRegistryABI, err) + err2 := deployment.DecodeErr(kcr.CapabilitiesRegistryABI, err) require.Fail(t, fmt.Sprintf("failed to call AddCapabilities: %s: %s", err, err2)) } _, err = chain.Confirm(tx) @@ -598,7 +597,6 @@ func TestUpdateNodes(t *testing.T) { } func TestAppendCapabilities(t *testing.T) { - var ( capMap = map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability{ testPeerID(t, "peerID_1"): []kcr.CapabilitiesRegistryCapability{ @@ -654,7 +652,7 @@ func TestAppendCapabilities(t *testing.T) { wantCaps = append(wantCaps, newCaps...) for i, got := range gotCaps { - assert.Equal(t, kslib.CapabilityID(wantCaps[i]), kslib.CapabilityID(got)) + assert.Equal(t, internal.CapabilityID(wantCaps[i]), internal.CapabilityID(got)) } // trying to append an existing capability should not change the result @@ -664,7 +662,6 @@ func TestAppendCapabilities(t *testing.T) { gotCaps2 := appendedResp2[testPeerID(t, "peerID_1")] require.Len(t, gotCaps2, 3) require.EqualValues(t, gotCaps, gotCaps2) - } func testPeerID(t *testing.T, s string) p2pkey.PeerID { diff --git a/deployment/keystone/changeset/helpers_test.go b/deployment/keystone/changeset/test/helpers.go similarity index 84% rename from deployment/keystone/changeset/helpers_test.go rename to deployment/keystone/changeset/test/helpers.go index f51a4ed610c..5ddaeda524e 100644 --- a/deployment/keystone/changeset/helpers_test.go +++ b/deployment/keystone/changeset/test/helpers.go @@ -1,4 +1,4 @@ -package changeset_test +package test import ( "bytes" @@ -6,53 +6,29 @@ import ( "crypto/sha256" "encoding/hex" "errors" - "fmt" "math" "sort" "testing" - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" "golang.org/x/exp/maps" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink/deployment" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" "github.com/smartcontractkit/chainlink/deployment/environment/memory" - "github.com/smartcontractkit/chainlink/deployment/keystone" - kslib "github.com/smartcontractkit/chainlink/deployment/keystone" kschangeset "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/workflowregistry" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) -func TestSetupTestEnv(t *testing.T) { - t.Parallel() - ctx := tests.Context(t) - for _, useMCMS := range []bool{true, false} { - te := SetupTestEnv(t, TestConfig{ - WFDonConfig: DonConfig{N: 4}, - AssetDonConfig: DonConfig{N: 4}, - WriterDonConfig: DonConfig{N: 4}, - NumChains: 3, - UseMCMS: useMCMS, - }) - t.Run(fmt.Sprintf("set up test env using MCMS: %t", useMCMS), func(t *testing.T) { - require.NotNil(t, te.Env.ExistingAddresses) - require.Len(t, te.Env.Chains, 3) - require.NotEmpty(t, te.RegistrySelector) - require.NotNil(t, te.Env.Offchain) - r, err := te.Env.Offchain.ListNodes(ctx, &node.ListNodesRequest{}) - require.NoError(t, err) - require.Len(t, r.Nodes, 12) - }) - } -} - type DonConfig struct { N int } @@ -104,8 +80,8 @@ type TestEnv struct { AssetNodes map[string]memory.Node } -func (te TestEnv) ContractSets() map[uint64]kslib.ContractSet { - r, err := kslib.GetContractSets(te.Env.Logger, &kslib.GetContractSetsRequest{ +func (te TestEnv) ContractSets() map[uint64]internal.ContractSet { + r, err := internal.GetContractSets(te.Env.Logger, &internal.GetContractSetsRequest{ Chains: te.Env.Chains, AddressBook: te.Env.ExistingAddresses, }) @@ -141,6 +117,10 @@ func SetupTestEnv(t *testing.T, c TestConfig) TestEnv { }, { Changeset: commonchangeset.WrapChangeSet(kschangeset.DeployForwarder), + Config: kschangeset.DeployForwarderRequest{}, + }, + { + Changeset: commonchangeset.WrapChangeSet(workflowregistry.Deploy), Config: registryChainSel, }, }) @@ -172,35 +152,35 @@ func SetupTestEnv(t *testing.T, c TestConfig) TestEnv { // TODO: partition nodes into multiple nops - wfDon := keystone.DonCapabilities{ - Name: keystone.WFDonName, - Nops: []keystone.NOP{ + wfDon := internal.DonCapabilities{ + Name: internal.WFDonName, + Nops: []internal.NOP{ { Name: "nop 1", Nodes: maps.Keys(wfNodes), }, }, - Capabilities: []kcr.CapabilitiesRegistryCapability{keystone.OCR3Cap}, + Capabilities: []kcr.CapabilitiesRegistryCapability{internal.OCR3Cap}, } - cwDon := keystone.DonCapabilities{ - Name: keystone.TargetDonName, - Nops: []keystone.NOP{ + cwDon := internal.DonCapabilities{ + Name: internal.TargetDonName, + Nops: []internal.NOP{ { Name: "nop 2", Nodes: maps.Keys(cwNodes), }, }, - Capabilities: []kcr.CapabilitiesRegistryCapability{keystone.WriteChainCap}, + Capabilities: []kcr.CapabilitiesRegistryCapability{internal.WriteChainCap}, } - assetDon := keystone.DonCapabilities{ - Name: keystone.StreamDonName, - Nops: []keystone.NOP{ + assetDon := internal.DonCapabilities{ + Name: internal.StreamDonName, + Nops: []internal.NOP{ { Name: "nop 3", Nodes: maps.Keys(assetNodes), }, }, - Capabilities: []kcr.CapabilitiesRegistryCapability{keystone.StreamTriggerCap}, + Capabilities: []kcr.CapabilitiesRegistryCapability{internal.StreamTriggerCap}, } allChains := make(map[uint64]deployment.Chain) @@ -215,10 +195,10 @@ func SetupTestEnv(t *testing.T, c TestConfig) TestEnv { err = env.ExistingAddresses.Merge(e.ExistingAddresses) require.NoError(t, err) - var ocr3Config = keystone.OracleConfig{ + var ocr3Config = internal.OracleConfig{ MaxFaultyOracles: len(wfNodes) / 3, } - var allDons = []keystone.DonCapabilities{wfDon, cwDon, assetDon} + var allDons = []internal.DonCapabilities{wfDon, cwDon, assetDon} csOut, err := kschangeset.ConfigureInitialContractsChangeset(env, kschangeset.InitialContractsCfg{ RegistryChainSel: registryChainSel, @@ -228,12 +208,12 @@ func SetupTestEnv(t *testing.T, c TestConfig) TestEnv { require.NoError(t, err) require.Nil(t, csOut.AddressBook, "no new addresses should be created in configure initial contracts") - req := &keystone.GetContractSetsRequest{ + req := &internal.GetContractSetsRequest{ Chains: env.Chains, AddressBook: env.ExistingAddresses, } - contractSetsResp, err := keystone.GetContractSets(lggr, req) + contractSetsResp, err := internal.GetContractSets(lggr, req) require.NoError(t, err) require.Len(t, contractSetsResp.ContractSets, len(env.Chains)) // check the registry @@ -268,7 +248,7 @@ func SetupTestEnv(t *testing.T, c TestConfig) TestEnv { }) require.NoError(t, err) // extract the MCMS address - r, err := kslib.GetContractSets(lggr, &kslib.GetContractSetsRequest{ + r, err := internal.GetContractSets(lggr, &internal.GetContractSetsRequest{ Chains: env.Chains, AddressBook: env.ExistingAddresses, }) @@ -318,7 +298,7 @@ func validateInitialChainState(t *testing.T, env deployment.Environment, registr // all contracts on registry chain registryChainAddrs, err := ad.AddressesForChain(registryChainSel) require.NoError(t, err) - require.Len(t, registryChainAddrs, 3) // registry, ocr3, forwarder + require.Len(t, registryChainAddrs, 4) // registry, ocr3, forwarder, workflowRegistry // only forwarder on non-home chain for sel := range env.Chains { chainAddrs, err := ad.AddressesForChain(sel) @@ -326,11 +306,11 @@ func validateInitialChainState(t *testing.T, env deployment.Environment, registr if sel != registryChainSel { require.Len(t, chainAddrs, 1) } else { - require.Len(t, chainAddrs, 3) + require.Len(t, chainAddrs, 4) } containsForwarder := false for _, tv := range chainAddrs { - if tv.Type == keystone.KeystoneForwarder { + if tv.Type == internal.KeystoneForwarder { containsForwarder = true break } @@ -350,7 +330,7 @@ func validateNodes(t *testing.T, gotRegistry *kcr.CapabilitiesRegistry, nodes ma } // validateDon checks that the don exists and has the expected capabilities -func validateDon(t *testing.T, gotRegistry *kcr.CapabilitiesRegistry, nodes map[string]memory.Node, don kslib.DonCapabilities) { +func validateDon(t *testing.T, gotRegistry *kcr.CapabilitiesRegistry, nodes map[string]memory.Node, don internal.DonCapabilities) { gotDons, err := gotRegistry.GetDONs(nil) require.NoError(t, err) wantP2PID := sortedHash(p2pIDs(t, maps.Keys(nodes))) @@ -389,7 +369,7 @@ func p2pIDs(t *testing.T, vals []string) [][32]byte { return out } -func expectedHashedCapabilities(t *testing.T, registry *kcr.CapabilitiesRegistry, don kslib.DonCapabilities) [][32]byte { +func expectedHashedCapabilities(t *testing.T, registry *kcr.CapabilitiesRegistry, don internal.DonCapabilities) [][32]byte { out := make([][32]byte, len(don.Capabilities)) var err error for i, cap := range don.Capabilities { diff --git a/deployment/keystone/changeset/test/helpers_test.go b/deployment/keystone/changeset/test/helpers_test.go new file mode 100644 index 00000000000..2d06e087db0 --- /dev/null +++ b/deployment/keystone/changeset/test/helpers_test.go @@ -0,0 +1,34 @@ +package test + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" +) + +func TestSetupTestEnv(t *testing.T) { + t.Parallel() + ctx := tests.Context(t) + for _, useMCMS := range []bool{true, false} { + te := SetupTestEnv(t, TestConfig{ + WFDonConfig: DonConfig{N: 4}, + AssetDonConfig: DonConfig{N: 4}, + WriterDonConfig: DonConfig{N: 4}, + NumChains: 3, + UseMCMS: useMCMS, + }) + t.Run(fmt.Sprintf("set up test env using MCMS: %t", useMCMS), func(t *testing.T) { + require.NotNil(t, te.Env.ExistingAddresses) + require.Len(t, te.Env.Chains, 3) + require.NotEmpty(t, te.RegistrySelector) + require.NotNil(t, te.Env.Offchain) + r, err := te.Env.Offchain.ListNodes(ctx, &node.ListNodesRequest{}) + require.NoError(t, err) + require.Len(t, r.Nodes, 12) + }) + } +} diff --git a/deployment/keystone/changeset/update_don.go b/deployment/keystone/changeset/update_don.go index 3f43ea513be..47cb7c82507 100644 --- a/deployment/keystone/changeset/update_don.go +++ b/deployment/keystone/changeset/update_don.go @@ -1,13 +1,13 @@ package changeset import ( + "errors" "fmt" "github.com/smartcontractkit/chainlink/deployment" - kslib "github.com/smartcontractkit/chainlink/deployment/keystone" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) @@ -27,10 +27,10 @@ type UpdateDonRequest struct { func (r *UpdateDonRequest) Validate() error { if len(r.P2PIDs) == 0 { - return fmt.Errorf("p2pIDs is required") + return errors.New("p2pIDs is required") } if len(r.CapabilityConfigs) == 0 { - return fmt.Errorf("capabilityConfigs is required") + return errors.New("capabilityConfigs is required") } return nil } @@ -64,10 +64,10 @@ func UpdateDon(env deployment.Environment, req *UpdateDonRequest) (deployment.Ch out := deployment.ChangesetOutput{} if req.UseMCMS() { if updateResult.Ops == nil { - return out, fmt.Errorf("expected MCMS operation to be non-nil") + return out, errors.New("expected MCMS operation to be non-nil") } if len(appendResult.Proposals) == 0 { - return out, fmt.Errorf("expected append node capabilities to return proposals") + return out, errors.New("expected append node capabilities to return proposals") } out.Proposals = appendResult.Proposals @@ -76,10 +76,8 @@ func UpdateDon(env deployment.Environment, req *UpdateDonRequest) (deployment.Ch // this makes the proposal all-or-nothing because all the operations are in the same batch, there is only one tr // transaction and only one proposal out.Proposals[0].Transactions[0].Batch = append(out.Proposals[0].Transactions[0].Batch, updateResult.Ops.Batch...) - } return out, nil - } func appendRequest(r *UpdateDonRequest) *AppendNodeCapabilitiesRequest { @@ -100,7 +98,7 @@ func appendRequest(r *UpdateDonRequest) *AppendNodeCapabilitiesRequest { } func updateDonRequest(env deployment.Environment, r *UpdateDonRequest) (*internal.UpdateDonRequest, error) { - resp, err := kslib.GetContractSets(env.Logger, &kslib.GetContractSetsRequest{ + resp, err := internal.GetContractSets(env.Logger, &internal.GetContractSetsRequest{ Chains: env.Chains, AddressBook: env.ExistingAddresses, }) diff --git a/deployment/keystone/changeset/update_don_test.go b/deployment/keystone/changeset/update_don_test.go index 012111c4e62..74e2609b0a1 100644 --- a/deployment/keystone/changeset/update_don_test.go +++ b/deployment/keystone/changeset/update_don_test.go @@ -10,7 +10,8 @@ import ( "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/test" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) @@ -29,10 +30,10 @@ func TestUpdateDon(t *testing.T) { caps = []kcr.CapabilitiesRegistryCapability{capA, capB} ) t.Run("no mcms", func(t *testing.T) { - te := SetupTestEnv(t, TestConfig{ - WFDonConfig: DonConfig{N: 4}, - AssetDonConfig: DonConfig{N: 4}, - WriterDonConfig: DonConfig{N: 4}, + te := test.SetupTestEnv(t, test.TestConfig{ + WFDonConfig: test.DonConfig{N: 4}, + AssetDonConfig: test.DonConfig{N: 4}, + WriterDonConfig: test.DonConfig{N: 4}, NumChains: 1, }) @@ -40,7 +41,7 @@ func TestUpdateDon(t *testing.T) { // we have to keep track of the existing capabilities to add to the new ones var p2pIDs []p2pkey.PeerID newCapabilities := make(map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability) - for id, _ := range te.WFNodes { + for id := range te.WFNodes { k, err := p2pkey.MakePeerID(id) require.NoError(t, err) p2pIDs = append(p2pIDs, k) @@ -63,17 +64,17 @@ func TestUpdateDon(t *testing.T) { csOut, err := changeset.UpdateDon(te.Env, &cfg) require.NoError(t, err) - require.Len(t, csOut.Proposals, 0) + require.Empty(t, csOut.Proposals) require.Nil(t, csOut.AddressBook) assertDonContainsCapabilities(t, te.ContractSets()[te.RegistrySelector].CapabilitiesRegistry, caps, p2pIDs) }) }) t.Run("with mcms", func(t *testing.T) { - te := SetupTestEnv(t, TestConfig{ - WFDonConfig: DonConfig{N: 4}, - AssetDonConfig: DonConfig{N: 4}, - WriterDonConfig: DonConfig{N: 4}, + te := test.SetupTestEnv(t, test.TestConfig{ + WFDonConfig: test.DonConfig{N: 4}, + AssetDonConfig: test.DonConfig{N: 4}, + WriterDonConfig: test.DonConfig{N: 4}, NumChains: 1, UseMCMS: true, }) @@ -81,7 +82,7 @@ func TestUpdateDon(t *testing.T) { // contract set is already deployed with capabilities // we have to keep track of the existing capabilities to add to the new ones var p2pIDs []p2pkey.PeerID - for id, _ := range te.WFNodes { + for id := range te.WFNodes { k, err := p2pkey.MakePeerID(id) require.NoError(t, err) p2pIDs = append(p2pIDs, k) diff --git a/deployment/keystone/changeset/update_node_capabilities.go b/deployment/keystone/changeset/update_node_capabilities.go index 9c9d5585fc2..c96393328db 100644 --- a/deployment/keystone/changeset/update_node_capabilities.go +++ b/deployment/keystone/changeset/update_node_capabilities.go @@ -1,6 +1,7 @@ package changeset import ( + "errors" "fmt" "strconv" @@ -9,12 +10,12 @@ import ( "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - kslib "github.com/smartcontractkit/chainlink/deployment/keystone" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) @@ -62,7 +63,7 @@ type MutateNodeCapabilitiesRequest struct { func (req *MutateNodeCapabilitiesRequest) Validate() error { if len(req.P2pToCapabilities) == 0 { - return fmt.Errorf("p2pToCapabilities is empty") + return errors.New("p2pToCapabilities is empty") } _, exists := chainsel.ChainBySelector(req.RegistryChainSel) if !exists { @@ -84,7 +85,7 @@ func (req *MutateNodeCapabilitiesRequest) updateNodeCapabilitiesImplRequest(e de if !ok { return nil, fmt.Errorf("registry chain selector %d does not exist in environment", req.RegistryChainSel) } - resp, err := kslib.GetContractSets(e.Logger, &kslib.GetContractSetsRequest{ + resp, err := internal.GetContractSets(e.Logger, &internal.GetContractSetsRequest{ Chains: map[uint64]deployment.Chain{req.RegistryChainSel: registryChain}, AddressBook: e.ExistingAddresses, }) @@ -119,7 +120,7 @@ func UpdateNodeCapabilities(env deployment.Environment, req *UpdateNodeCapabilit out := deployment.ChangesetOutput{} if req.UseMCMS() { if r.Ops == nil { - return out, fmt.Errorf("expected MCMS operation to be non-nil") + return out, errors.New("expected MCMS operation to be non-nil") } timelocksPerChain := map[uint64]common.Address{ c.Chain.Selector: c.ContractSet.Timelock.Address(), diff --git a/deployment/keystone/changeset/update_node_capabilities_test.go b/deployment/keystone/changeset/update_node_capabilities_test.go index 87b49acf614..8962dfc389d 100644 --- a/deployment/keystone/changeset/update_node_capabilities_test.go +++ b/deployment/keystone/changeset/update_node_capabilities_test.go @@ -10,7 +10,8 @@ import ( commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/test" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) @@ -29,10 +30,10 @@ func TestUpdateNodeCapabilities(t *testing.T) { caps = []kcr.CapabilitiesRegistryCapability{capA, capB} ) t.Run("no mcms", func(t *testing.T) { - te := SetupTestEnv(t, TestConfig{ - WFDonConfig: DonConfig{N: 4}, - AssetDonConfig: DonConfig{N: 4}, - WriterDonConfig: DonConfig{N: 4}, + te := test.SetupTestEnv(t, test.TestConfig{ + WFDonConfig: test.DonConfig{N: 4}, + AssetDonConfig: test.DonConfig{N: 4}, + WriterDonConfig: test.DonConfig{N: 4}, NumChains: 1, }) @@ -40,7 +41,7 @@ func TestUpdateNodeCapabilities(t *testing.T) { // we have to keep track of the existing capabilities to add to the new ones var p2pIDs []p2pkey.PeerID newCapabilities := make(map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability) - for id, _ := range te.WFNodes { + for id := range te.WFNodes { k, err := p2pkey.MakePeerID(id) require.NoError(t, err) p2pIDs = append(p2pIDs, k) @@ -48,7 +49,6 @@ func TestUpdateNodeCapabilities(t *testing.T) { } t.Run("fails if update drops existing capabilities", func(t *testing.T) { - cfg := changeset.UpdateNodeCapabilitiesRequest{ RegistryChainSel: te.RegistrySelector, P2pToCapabilities: newCapabilities, @@ -72,17 +72,17 @@ func TestUpdateNodeCapabilities(t *testing.T) { csOut, err := changeset.UpdateNodeCapabilities(te.Env, &cfg) require.NoError(t, err) - require.Len(t, csOut.Proposals, 0) + require.Empty(t, csOut.Proposals) require.Nil(t, csOut.AddressBook) validateCapabilityUpdates(t, te, capabiltiesToSet) }) }) t.Run("with mcms", func(t *testing.T) { - te := SetupTestEnv(t, TestConfig{ - WFDonConfig: DonConfig{N: 4}, - AssetDonConfig: DonConfig{N: 4}, - WriterDonConfig: DonConfig{N: 4}, + te := test.SetupTestEnv(t, test.TestConfig{ + WFDonConfig: test.DonConfig{N: 4}, + AssetDonConfig: test.DonConfig{N: 4}, + WriterDonConfig: test.DonConfig{N: 4}, NumChains: 1, UseMCMS: true, }) @@ -91,7 +91,7 @@ func TestUpdateNodeCapabilities(t *testing.T) { // we have to keep track of the existing capabilities to add to the new ones var p2pIDs []p2pkey.PeerID newCapabilities := make(map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability) - for id, _ := range te.WFNodes { + for id := range te.WFNodes { k, err := p2pkey.MakePeerID(id) require.NoError(t, err) p2pIDs = append(p2pIDs, k) @@ -134,13 +134,11 @@ func TestUpdateNodeCapabilities(t *testing.T) { }) require.NoError(t, err) validateCapabilityUpdates(t, te, capabiltiesToSet) - }) - } // validateUpdate checks reads nodes from the registry and checks they have the expected updates -func validateCapabilityUpdates(t *testing.T, te TestEnv, expected map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability) { +func validateCapabilityUpdates(t *testing.T, te test.TestEnv, expected map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability) { registry := te.ContractSets()[te.RegistrySelector].CapabilitiesRegistry wfP2PIDs := p2pIDs(t, maps.Keys(te.WFNodes)) nodes, err := registry.GetNodesByP2PIds(nil, wfP2PIDs) diff --git a/deployment/keystone/changeset/update_nodes.go b/deployment/keystone/changeset/update_nodes.go index bb12f32cb94..4a98f8b06e9 100644 --- a/deployment/keystone/changeset/update_nodes.go +++ b/deployment/keystone/changeset/update_nodes.go @@ -1,16 +1,17 @@ package changeset import ( + "errors" "fmt" "time" "github.com/ethereum/go-ethereum/common" "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - kslib "github.com/smartcontractkit/chainlink/deployment/keystone" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) @@ -31,7 +32,7 @@ type UpdateNodesRequest struct { func (r *UpdateNodesRequest) Validate() error { if r.P2pToUpdates == nil { - return fmt.Errorf("P2pToUpdates must be non-nil") + return errors.New("P2pToUpdates must be non-nil") } return nil } @@ -50,7 +51,7 @@ func UpdateNodes(env deployment.Environment, req *UpdateNodesRequest) (deploymen if !ok { return deployment.ChangesetOutput{}, fmt.Errorf("registry chain selector %d does not exist in environment", req.RegistryChainSel) } - cresp, err := kslib.GetContractSets(env.Logger, &kslib.GetContractSetsRequest{ + cresp, err := internal.GetContractSets(env.Logger, &internal.GetContractSetsRequest{ Chains: env.Chains, AddressBook: env.ExistingAddresses, }) @@ -75,7 +76,7 @@ func UpdateNodes(env deployment.Environment, req *UpdateNodesRequest) (deploymen out := deployment.ChangesetOutput{} if req.UseMCMS() { if resp.Ops == nil { - return out, fmt.Errorf("expected MCMS operation to be non-nil") + return out, errors.New("expected MCMS operation to be non-nil") } timelocksPerChain := map[uint64]common.Address{ req.RegistryChainSel: contracts.Timelock.Address(), diff --git a/deployment/keystone/changeset/update_nodes_test.go b/deployment/keystone/changeset/update_nodes_test.go index 31f71cd9603..5709482ddb3 100644 --- a/deployment/keystone/changeset/update_nodes_test.go +++ b/deployment/keystone/changeset/update_nodes_test.go @@ -11,6 +11,7 @@ import ( commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/test" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) @@ -18,16 +19,16 @@ func TestUpdateNodes(t *testing.T) { t.Parallel() t.Run("no mcms", func(t *testing.T) { - te := SetupTestEnv(t, TestConfig{ - WFDonConfig: DonConfig{N: 4}, - AssetDonConfig: DonConfig{N: 4}, - WriterDonConfig: DonConfig{N: 4}, + te := test.SetupTestEnv(t, test.TestConfig{ + WFDonConfig: test.DonConfig{N: 4}, + AssetDonConfig: test.DonConfig{N: 4}, + WriterDonConfig: test.DonConfig{N: 4}, NumChains: 1, }) updates := make(map[p2pkey.PeerID]changeset.NodeUpdate) i := uint8(0) - for id, _ := range te.WFNodes { + for id := range te.WFNodes { k, err := p2pkey.MakePeerID(id) require.NoError(t, err) pubKey := [32]byte{31: i + 1} @@ -47,24 +48,24 @@ func TestUpdateNodes(t *testing.T) { csOut, err := changeset.UpdateNodes(te.Env, &cfg) require.NoError(t, err) - require.Len(t, csOut.Proposals, 0) + require.Empty(t, csOut.Proposals) require.Nil(t, csOut.AddressBook) validateUpdate(t, te, updates) }) t.Run("with mcms", func(t *testing.T) { - te := SetupTestEnv(t, TestConfig{ - WFDonConfig: DonConfig{N: 4}, - AssetDonConfig: DonConfig{N: 4}, - WriterDonConfig: DonConfig{N: 4}, + te := test.SetupTestEnv(t, test.TestConfig{ + WFDonConfig: test.DonConfig{N: 4}, + AssetDonConfig: test.DonConfig{N: 4}, + WriterDonConfig: test.DonConfig{N: 4}, NumChains: 1, UseMCMS: true, }) updates := make(map[p2pkey.PeerID]changeset.NodeUpdate) i := uint8(0) - for id, _ := range te.WFNodes { + for id := range te.WFNodes { k, err := p2pkey.MakePeerID(id) require.NoError(t, err) pubKey := [32]byte{31: i + 1} @@ -110,11 +111,10 @@ func TestUpdateNodes(t *testing.T) { validateUpdate(t, te, updates) }) - } // validateUpdate checks reads nodes from the registry and checks they have the expected updates -func validateUpdate(t *testing.T, te TestEnv, expected map[p2pkey.PeerID]changeset.NodeUpdate) { +func validateUpdate(t *testing.T, te test.TestEnv, expected map[p2pkey.PeerID]changeset.NodeUpdate) { registry := te.ContractSets()[te.RegistrySelector].CapabilitiesRegistry wfP2PIDs := p2pIDs(t, maps.Keys(te.WFNodes)) nodes, err := registry.GetNodesByP2PIds(nil, wfP2PIDs) @@ -126,3 +126,13 @@ func validateUpdate(t *testing.T, te TestEnv, expected map[p2pkey.PeerID]changes assert.Equal(t, expected[node.P2pId].Signer, node.Signer) } } + +func p2pIDs(t *testing.T, vals []string) [][32]byte { + var out [][32]byte + for _, v := range vals { + id, err := p2pkey.MakePeerID(v) + require.NoError(t, err) + out = append(out, id) + } + return out +} diff --git a/deployment/keystone/changeset/view.go b/deployment/keystone/changeset/view.go index 417484ed6aa..f6f495fd30b 100644 --- a/deployment/keystone/changeset/view.go +++ b/deployment/keystone/changeset/view.go @@ -8,14 +8,14 @@ import ( "github.com/smartcontractkit/chainlink/deployment" commonview "github.com/smartcontractkit/chainlink/deployment/common/view" - "github.com/smartcontractkit/chainlink/deployment/keystone" + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" "github.com/smartcontractkit/chainlink/deployment/keystone/view" ) var _ deployment.ViewState = ViewKeystone func ViewKeystone(e deployment.Environment) (json.Marshaler, error) { - state, err := keystone.GetContractSets(e.Logger, &keystone.GetContractSetsRequest{ + state, err := internal.GetContractSets(e.Logger, &internal.GetContractSetsRequest{ Chains: e.Chains, AddressBook: e.ExistingAddresses, }) @@ -37,7 +37,6 @@ func ViewKeystone(e deployment.Environment) (json.Marshaler, error) { return nil, fmt.Errorf("failed to view contract set: %w", err) } chainViews[chainName] = v - } nopsView, err := commonview.GenerateNopsView(e.NodeIDs, e.Offchain) if err != nil { diff --git a/deployment/keystone/changeset/view_test.go b/deployment/keystone/changeset/view_test.go index 023b4462549..5b32699fd89 100644 --- a/deployment/keystone/changeset/view_test.go +++ b/deployment/keystone/changeset/view_test.go @@ -26,7 +26,7 @@ func TestKeystoneView(t *testing.T) { require.NoError(t, err) require.NotNil(t, resp) require.NoError(t, env.ExistingAddresses.Merge(resp.AddressBook)) - resp, err = DeployForwarder(env, registryChain) + resp, err = DeployForwarder(env, DeployForwarderRequest{}) require.NoError(t, err) require.NotNil(t, resp) require.NoError(t, env.ExistingAddresses.Merge(resp.AddressBook)) diff --git a/deployment/keystone/changeset/workflowregistry/deploy.go b/deployment/keystone/changeset/workflowregistry/deploy.go new file mode 100644 index 00000000000..3bead5cdc6c --- /dev/null +++ b/deployment/keystone/changeset/workflowregistry/deploy.go @@ -0,0 +1,26 @@ +package workflowregistry + +import ( + "errors" + "fmt" + + "github.com/smartcontractkit/chainlink/deployment" +) + +var _ deployment.ChangeSet[uint64] = Deploy + +func Deploy(env deployment.Environment, registrySelector uint64) (deployment.ChangesetOutput, error) { + lggr := env.Logger + chain, ok := env.Chains[registrySelector] + if !ok { + return deployment.ChangesetOutput{}, errors.New("chain not found in environment") + } + ab := deployment.NewMemoryAddressBook() + wrResp, err := deployWorkflowRegistry(chain, ab) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to deploy WorkflowRegistry: %w", err) + } + lggr.Infof("Deployed %s chain selector %d addr %s", wrResp.Tv.String(), chain.Selector, wrResp.Address.String()) + + return deployment.ChangesetOutput{AddressBook: ab}, nil +} diff --git a/deployment/keystone/changeset/workflowregistry/deploy_test.go b/deployment/keystone/changeset/workflowregistry/deploy_test.go new file mode 100644 index 00000000000..733f47d6a15 --- /dev/null +++ b/deployment/keystone/changeset/workflowregistry/deploy_test.go @@ -0,0 +1,38 @@ +package workflowregistry + +import ( + "testing" + + "go.uber.org/zap/zapcore" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" +) + +func Test_Deploy(t *testing.T) { + t.Parallel() + lggr := logger.Test(t) + cfg := memory.MemoryEnvironmentConfig{ + Nodes: 1, // nodes unused but required in config + Chains: 2, + } + env := memory.NewMemoryEnvironment(t, lggr, zapcore.DebugLevel, cfg) + + registrySel := env.AllChainSelectors()[0] + + resp, err := Deploy(env, registrySel) + require.NoError(t, err) + require.NotNil(t, resp) + // workflow registry should be deployed on chain 0 + addrs, err := resp.AddressBook.AddressesForChain(registrySel) + require.NoError(t, err) + require.Len(t, addrs, 1) + + // assert nothing on chain 1 + require.NotEqual(t, registrySel, env.AllChainSelectors()[1]) + oaddrs, _ := resp.AddressBook.AddressesForChain(env.AllChainSelectors()[1]) + assert.Empty(t, oaddrs) +} diff --git a/deployment/keystone/changeset/workflowregistry/setup_test.go b/deployment/keystone/changeset/workflowregistry/setup_test.go new file mode 100644 index 00000000000..ec4d448b93c --- /dev/null +++ b/deployment/keystone/changeset/workflowregistry/setup_test.go @@ -0,0 +1,55 @@ +package workflowregistry + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" + workflow_registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/workflow/generated/workflow_registry_wrapper" +) + +type SetupTestWorkflowRegistryResponse struct { + Registry *workflow_registry.WorkflowRegistry + Chain deployment.Chain + RegistrySelector uint64 + AddressBook deployment.AddressBook +} + +func SetupTestWorkflowRegistry(t *testing.T, lggr logger.Logger, chainSel uint64) *SetupTestWorkflowRegistryResponse { + chain := testChain(t) + + deployer, err := newWorkflowRegistryDeployer() + require.NoError(t, err) + resp, err := deployer.Deploy(changeset.DeployRequest{Chain: chain}) + require.NoError(t, err) + + addressBook := deployment.NewMemoryAddressBookFromMap( + map[uint64]map[string]deployment.TypeAndVersion{ + chainSel: map[string]deployment.TypeAndVersion{ + resp.Address.Hex(): resp.Tv, + }, + }, + ) + + return &SetupTestWorkflowRegistryResponse{ + Registry: deployer.Contract(), + Chain: chain, + RegistrySelector: chain.Selector, + AddressBook: addressBook, + } +} + +func testChain(t *testing.T) deployment.Chain { + chains, _ := memory.NewMemoryChains(t, 1, 5) + var chain deployment.Chain + for _, c := range chains { + chain = c + break + } + require.NotEmpty(t, chain) + return chain +} diff --git a/deployment/keystone/changeset/workflowregistry/strategies.go b/deployment/keystone/changeset/workflowregistry/strategies.go new file mode 100644 index 00000000000..617d6e6e8dc --- /dev/null +++ b/deployment/keystone/changeset/workflowregistry/strategies.go @@ -0,0 +1,85 @@ +package workflowregistry + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + + "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" +) + +type strategy interface { + Apply(callFn func(opts *bind.TransactOpts) (*types.Transaction, error)) (deployment.ChangesetOutput, error) +} + +type simpleTransaction struct { + chain deployment.Chain +} + +func (s *simpleTransaction) Apply(callFn func(opts *bind.TransactOpts) (*types.Transaction, error)) (deployment.ChangesetOutput, error) { + tx, err := callFn(s.chain.DeployerKey) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + _, err = s.chain.Confirm(tx) + return deployment.ChangesetOutput{}, err +} + +type mcmsTransaction struct { + Config *changeset.MCMSConfig + Description string + Address common.Address + ChainSel uint64 + ContractSet *changeset.ContractSet +} + +func (m *mcmsTransaction) Apply(callFn func(opts *bind.TransactOpts) (*types.Transaction, error)) (deployment.ChangesetOutput, error) { + opts := deployment.SimTransactOpts() + + tx, err := callFn(opts) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + op := timelock.BatchChainOperation{ + ChainIdentifier: mcms.ChainIdentifier(m.ChainSel), + Batch: []mcms.Operation{ + { + Data: tx.Data(), + To: m.Address, + Value: big.NewInt(0), + }, + }, + } + + timelocksPerChain := map[uint64]common.Address{ + m.ChainSel: m.ContractSet.Timelock.Address(), + } + proposerMCMSes := map[uint64]*gethwrappers.ManyChainMultiSig{ + m.ChainSel: m.ContractSet.ProposerMcm, + } + + proposal, err := proposalutils.BuildProposalFromBatches( + timelocksPerChain, + proposerMCMSes, + []timelock.BatchChainOperation{op}, + m.Description, + m.Config.MinDuration, + ) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + return deployment.ChangesetOutput{ + Proposals: []timelock.MCMSWithTimelockProposal{*proposal}, + }, nil +} diff --git a/deployment/keystone/changeset/workflowregistry/update_allowed_dons.go b/deployment/keystone/changeset/workflowregistry/update_allowed_dons.go new file mode 100644 index 00000000000..5001370b552 --- /dev/null +++ b/deployment/keystone/changeset/workflowregistry/update_allowed_dons.go @@ -0,0 +1,80 @@ +package workflowregistry + +import ( + "errors" + "fmt" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/core/types" + + "github.com/smartcontractkit/chainlink/deployment" + + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" + workflow_registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/workflow/generated/workflow_registry_wrapper" +) + +var _ deployment.ChangeSet[*UpdateAllowedDonsRequest] = UpdateAllowedDons + +type UpdateAllowedDonsRequest struct { + RegistryChainSel uint64 + DonIDs []uint32 + Allowed bool + + MCMSConfig *changeset.MCMSConfig +} + +func (r *UpdateAllowedDonsRequest) Validate() error { + if len(r.DonIDs) == 0 { + return errors.New("Must provide at least one DonID") + } + return nil +} + +// UpdateAllowedDons updates the list of DONs that workflows can be sent to. +func UpdateAllowedDons(env deployment.Environment, req *UpdateAllowedDonsRequest) (deployment.ChangesetOutput, error) { + if err := req.Validate(); err != nil { + return deployment.ChangesetOutput{}, err + } + + resp, err := changeset.GetContractSets(env.Logger, &changeset.GetContractSetsRequest{ + Chains: env.Chains, + AddressBook: env.ExistingAddresses, + }) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to get contract sets: %w", err) + } + + cs := resp.ContractSets[req.RegistryChainSel] + if cs.WorkflowRegistry == nil { + return deployment.ChangesetOutput{}, errors.New("could not find workflow registry") + } + registry := cs.WorkflowRegistry + + chain, ok := env.Chains[req.RegistryChainSel] + if !ok { + return deployment.ChangesetOutput{}, fmt.Errorf("registry chain selector %d does not exist in environment", req.RegistryChainSel) + } + + var s strategy + if req.MCMSConfig != nil { + s = &mcmsTransaction{ + Config: req.MCMSConfig, + Description: "proposal to update allowed dons", + Address: registry.Address(), + ChainSel: req.RegistryChainSel, + ContractSet: &cs, + } + } else { + s = &simpleTransaction{ + chain: chain, + } + } + + return s.Apply(func(opts *bind.TransactOpts) (*types.Transaction, error) { + tx, err := registry.UpdateAllowedDONs(opts, req.DonIDs, req.Allowed) + if err != nil { + err = deployment.DecodeErr(workflow_registry.WorkflowRegistryABI, err) + } + return tx, err + }) +} diff --git a/deployment/keystone/changeset/workflowregistry/update_allowed_dons_test.go b/deployment/keystone/changeset/workflowregistry/update_allowed_dons_test.go new file mode 100644 index 00000000000..aa869ce1517 --- /dev/null +++ b/deployment/keystone/changeset/workflowregistry/update_allowed_dons_test.go @@ -0,0 +1,110 @@ +package workflowregistry_test + +import ( + "testing" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + + chain_selectors "github.com/smartcontractkit/chain-selectors" + + "github.com/smartcontractkit/chainlink/deployment" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/test" + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/workflowregistry" +) + +func TestUpdateAllowedDons(t *testing.T) { + lggr := logger.Test(t) + + chainSel := chain_selectors.ETHEREUM_TESTNET_SEPOLIA.Selector + resp := workflowregistry.SetupTestWorkflowRegistry(t, lggr, chainSel) + registry := resp.Registry + + dons, err := registry.GetAllAllowedDONs(&bind.CallOpts{}) + require.NoError(t, err) + + assert.Empty(t, dons) + + env := deployment.Environment{ + Logger: lggr, + Chains: map[uint64]deployment.Chain{ + chainSel: resp.Chain, + }, + ExistingAddresses: resp.AddressBook, + } + + _, err = workflowregistry.UpdateAllowedDons( + env, + &workflowregistry.UpdateAllowedDonsRequest{ + RegistryChainSel: chainSel, + DonIDs: []uint32{1}, + Allowed: true, + }, + ) + require.NoError(t, err) + + dons, err = registry.GetAllAllowedDONs(&bind.CallOpts{}) + require.NoError(t, err) + + assert.Len(t, dons, 1) + assert.Equal(t, uint32(1), dons[0]) + + _, err = workflowregistry.UpdateAllowedDons( + env, + &workflowregistry.UpdateAllowedDonsRequest{ + RegistryChainSel: chainSel, + DonIDs: []uint32{1}, + Allowed: false, + }, + ) + require.NoError(t, err) + + dons, err = registry.GetAllAllowedDONs(&bind.CallOpts{}) + require.NoError(t, err) + + assert.Empty(t, dons) +} + +func Test_UpdateAllowedDons_WithMCMS(t *testing.T) { + te := test.SetupTestEnv(t, test.TestConfig{ + WFDonConfig: test.DonConfig{N: 4}, + AssetDonConfig: test.DonConfig{N: 4}, + WriterDonConfig: test.DonConfig{N: 4}, + NumChains: 1, + UseMCMS: true, + }) + + req := &workflowregistry.UpdateAllowedDonsRequest{ + RegistryChainSel: te.RegistrySelector, + DonIDs: []uint32{1}, + Allowed: true, + MCMSConfig: &changeset.MCMSConfig{MinDuration: 0}, + } + + out, err := workflowregistry.UpdateAllowedDons(te.Env, req) + require.NoError(t, err) + require.Len(t, out.Proposals, 1) + require.Nil(t, out.AddressBook) + + contracts := te.ContractSets()[te.RegistrySelector] + timelockContracts := map[uint64]*proposalutils.TimelockExecutionContracts{ + te.RegistrySelector: { + Timelock: contracts.Timelock, + CallProxy: contracts.CallProxy, + }, + } + + _, err = commonchangeset.ApplyChangesets(t, te.Env, timelockContracts, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(workflowregistry.UpdateAllowedDons), + Config: req, + }, + }) + require.NoError(t, err) +} diff --git a/deployment/keystone/changeset/workflowregistry/update_authorized_addresses.go b/deployment/keystone/changeset/workflowregistry/update_authorized_addresses.go new file mode 100644 index 00000000000..b2d5ffcce1e --- /dev/null +++ b/deployment/keystone/changeset/workflowregistry/update_authorized_addresses.go @@ -0,0 +1,105 @@ +package workflowregistry + +import ( + "errors" + "fmt" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + + "github.com/smartcontractkit/chainlink/deployment" + + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" + workflow_registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/workflow/generated/workflow_registry_wrapper" +) + +var _ deployment.ChangeSet[*UpdateAuthorizedAddressesRequest] = UpdateAuthorizedAddresses + +type UpdateAuthorizedAddressesRequest struct { + RegistryChainSel uint64 + + Addresses []string + Allowed bool + + MCMSConfig *changeset.MCMSConfig +} + +func (r *UpdateAuthorizedAddressesRequest) Validate() error { + if len(r.Addresses) == 0 { + return errors.New("Must provide at least 1 address") + } + + return nil +} + +func getWorkflowRegistry(env deployment.Environment, chainSel uint64) (*workflow_registry.WorkflowRegistry, error) { + resp, err := changeset.GetContractSets(env.Logger, &changeset.GetContractSetsRequest{ + Chains: env.Chains, + AddressBook: env.ExistingAddresses, + }) + if err != nil { + return nil, fmt.Errorf("failed to get contract sets: %w", err) + } + + cs := resp.ContractSets[chainSel] + if cs.WorkflowRegistry == nil { + return nil, errors.New("could not find workflow registry") + } + + return cs.WorkflowRegistry, nil +} + +// UpdateAuthorizedAddresses updates the list of DONs that workflows can be sent to. +func UpdateAuthorizedAddresses(env deployment.Environment, req *UpdateAuthorizedAddressesRequest) (deployment.ChangesetOutput, error) { + if err := req.Validate(); err != nil { + return deployment.ChangesetOutput{}, err + } + + resp, err := changeset.GetContractSets(env.Logger, &changeset.GetContractSetsRequest{ + Chains: env.Chains, + AddressBook: env.ExistingAddresses, + }) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to get contract sets: %w", err) + } + + cs := resp.ContractSets[req.RegistryChainSel] + if cs.WorkflowRegistry == nil { + return deployment.ChangesetOutput{}, errors.New("could not find workflow registry") + } + registry := cs.WorkflowRegistry + + chain, ok := env.Chains[req.RegistryChainSel] + if !ok { + return deployment.ChangesetOutput{}, fmt.Errorf("registry chain selector %d does not exist in environment", req.RegistryChainSel) + } + + var addr []common.Address + for _, a := range req.Addresses { + addr = append(addr, common.HexToAddress(a)) + } + + var s strategy + if req.MCMSConfig != nil { + s = &mcmsTransaction{ + Config: req.MCMSConfig, + Description: "proposal to update authorized addresses", + Address: registry.Address(), + ChainSel: chain.Selector, + ContractSet: &cs, + } + } else { + s = &simpleTransaction{ + chain: chain, + } + } + + return s.Apply(func(opts *bind.TransactOpts) (*types.Transaction, error) { + tx, err := registry.UpdateAuthorizedAddresses(opts, addr, req.Allowed) + if err != nil { + err = deployment.DecodeErr(workflow_registry.WorkflowRegistryABI, err) + } + return tx, err + }) +} diff --git a/deployment/keystone/changeset/workflowregistry/update_authorized_addresses_test.go b/deployment/keystone/changeset/workflowregistry/update_authorized_addresses_test.go new file mode 100644 index 00000000000..20dbf9895d4 --- /dev/null +++ b/deployment/keystone/changeset/workflowregistry/update_authorized_addresses_test.go @@ -0,0 +1,113 @@ +package workflowregistry_test + +import ( + "testing" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + chain_selectors "github.com/smartcontractkit/chain-selectors" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + + "github.com/smartcontractkit/chainlink/deployment" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/test" + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/workflowregistry" +) + +func TestUpdateAuthorizedAddresses(t *testing.T) { + lggr := logger.Test(t) + + chainSel := chain_selectors.ETHEREUM_TESTNET_SEPOLIA.Selector + resp := workflowregistry.SetupTestWorkflowRegistry(t, lggr, chainSel) + registry := resp.Registry + + authorizedAddresses, err := registry.GetAllAuthorizedAddresses(&bind.CallOpts{}) + require.NoError(t, err) + + assert.Empty(t, authorizedAddresses) + + env := deployment.Environment{ + Logger: lggr, + Chains: map[uint64]deployment.Chain{ + chainSel: resp.Chain, + }, + ExistingAddresses: resp.AddressBook, + } + + addr := "0xc0ffee254729296a45a3885639AC7E10F9d54979" + _, err = workflowregistry.UpdateAuthorizedAddresses( + env, + &workflowregistry.UpdateAuthorizedAddressesRequest{ + RegistryChainSel: chainSel, + Addresses: []string{addr}, + Allowed: true, + }, + ) + require.NoError(t, err) + + authorizedAddresses, err = registry.GetAllAuthorizedAddresses(&bind.CallOpts{}) + require.NoError(t, err) + + assert.Len(t, authorizedAddresses, 1) + assert.Equal(t, authorizedAddresses[0], common.HexToAddress(addr)) + + _, err = workflowregistry.UpdateAuthorizedAddresses( + env, + &workflowregistry.UpdateAuthorizedAddressesRequest{ + RegistryChainSel: chainSel, + Addresses: []string{addr}, + Allowed: false, + }, + ) + require.NoError(t, err) + + authorizedAddresses, err = registry.GetAllAuthorizedAddresses(&bind.CallOpts{}) + require.NoError(t, err) + + assert.Empty(t, authorizedAddresses) +} + +func Test_UpdateAuthorizedAddresses_WithMCMS(t *testing.T) { + te := test.SetupTestEnv(t, test.TestConfig{ + WFDonConfig: test.DonConfig{N: 4}, + AssetDonConfig: test.DonConfig{N: 4}, + WriterDonConfig: test.DonConfig{N: 4}, + NumChains: 1, + UseMCMS: true, + }) + + addr := "0xc0ffee254729296a45a3885639AC7E10F9d54979" + req := &workflowregistry.UpdateAuthorizedAddressesRequest{ + RegistryChainSel: te.RegistrySelector, + Addresses: []string{addr}, + Allowed: true, + MCMSConfig: &changeset.MCMSConfig{MinDuration: 0}, + } + + out, err := workflowregistry.UpdateAuthorizedAddresses(te.Env, req) + require.NoError(t, err) + require.Len(t, out.Proposals, 1) + require.Nil(t, out.AddressBook) + + contracts := te.ContractSets()[te.RegistrySelector] + timelockContracts := map[uint64]*proposalutils.TimelockExecutionContracts{ + te.RegistrySelector: { + Timelock: contracts.Timelock, + CallProxy: contracts.CallProxy, + }, + } + + _, err = commonchangeset.ApplyChangesets(t, te.Env, timelockContracts, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(workflowregistry.UpdateAuthorizedAddresses), + Config: req, + }, + }) + require.NoError(t, err) +} diff --git a/deployment/keystone/changeset/workflowregistry/workflow_registry_deployer.go b/deployment/keystone/changeset/workflowregistry/workflow_registry_deployer.go new file mode 100644 index 00000000000..6ebe6693482 --- /dev/null +++ b/deployment/keystone/changeset/workflowregistry/workflow_registry_deployer.go @@ -0,0 +1,75 @@ +package workflowregistry + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" + workflow_registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/workflow/generated/workflow_registry_wrapper" +) + +type workflowRegistryDeployer struct { + lggr logger.Logger + contract *workflow_registry.WorkflowRegistry +} + +func newWorkflowRegistryDeployer() (*workflowRegistryDeployer, error) { + lggr, err := logger.New() + if err != nil { + return nil, err + } + return &workflowRegistryDeployer{lggr: lggr}, nil +} + +func (c *workflowRegistryDeployer) Contract() *workflow_registry.WorkflowRegistry { + return c.contract +} + +func (c *workflowRegistryDeployer) Deploy(req changeset.DeployRequest) (*changeset.DeployResponse, error) { + addr, tx, wr, err := workflow_registry.DeployWorkflowRegistry( + req.Chain.DeployerKey, + req.Chain.Client) + if err != nil { + return nil, deployment.DecodeErr(workflow_registry.WorkflowRegistryABI, err) + } + + _, err = req.Chain.Confirm(tx) + if err != nil { + return nil, fmt.Errorf("failed to confirm and save WorkflowRegistry: %w", err) + } + tvStr, err := wr.TypeAndVersion(&bind.CallOpts{}) + if err != nil { + return nil, fmt.Errorf("failed to get type and version: %w", err) + } + + tv, err := deployment.TypeAndVersionFromString(tvStr) + if err != nil { + return nil, fmt.Errorf("failed to parse type and version from %s: %w", tvStr, err) + } + resp := &changeset.DeployResponse{ + Address: addr, + Tx: tx.Hash(), + Tv: tv, + } + c.contract = wr + return resp, nil +} + +// deployWorkflowRegistry deploys the WorkflowRegistry contract to the chain +// and saves the address in the address book. This mutates the address book. +func deployWorkflowRegistry(chain deployment.Chain, ab deployment.AddressBook) (*changeset.DeployResponse, error) { + deployer, err := newWorkflowRegistryDeployer() + resp, err := deployer.Deploy(changeset.DeployRequest{Chain: chain}) + if err != nil { + return nil, fmt.Errorf("failed to deploy WorkflowRegistry: %w", err) + } + err = ab.Save(chain.Selector, resp.Address.String(), resp.Tv) + if err != nil { + return nil, fmt.Errorf("failed to save WorkflowRegistry: %w", err) + } + return resp, nil +} diff --git a/deployment/keystone/deploy_test.go b/deployment/keystone/deploy_test.go deleted file mode 100644 index eb167ed60fb..00000000000 --- a/deployment/keystone/deploy_test.go +++ /dev/null @@ -1,252 +0,0 @@ -package keystone_test - -import ( - "encoding/json" - "fmt" - "os" - "strconv" - "testing" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - chainsel "github.com/smartcontractkit/chain-selectors" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/environment/clo" - "github.com/smartcontractkit/chainlink/deployment/environment/clo/models" - "github.com/smartcontractkit/chainlink/deployment/environment/memory" - "github.com/smartcontractkit/chainlink/deployment/keystone" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -// TODO: Deprecated, remove everything below that leverages CLO - -func nodeOperatorsToIDs(t *testing.T, nops []*models.NodeOperator) (nodeIDs []keystone.NOP) { - for _, nop := range nops { - nodeOperator := keystone.NOP{ - Name: nop.Name, - } - for _, node := range nop.Nodes { - p2pID, err := clo.NodeP2PId(node) - require.NoError(t, err) - - nodeOperator.Nodes = append(nodeOperator.Nodes, p2pID) - } - nodeIDs = append(nodeIDs, nodeOperator) - } - return nodeIDs -} - -func TestDeployCLO(t *testing.T) { - lggr := logger.Test(t) - - wfNops := loadTestNops(t, "testdata/workflow_nodes.json") - cwNops := loadTestNops(t, "testdata/chain_writer_nodes.json") - assetNops := loadTestNops(t, "testdata/asset_nodes.json") - require.Len(t, wfNops, 10) - requireChains(t, wfNops, []models.ChainType{models.ChainTypeEvm, models.ChainTypeAptos}) - require.Len(t, cwNops, 10) - requireChains(t, cwNops, []models.ChainType{models.ChainTypeEvm, models.ChainTypeEvm}) - require.Len(t, assetNops, 16) - requireChains(t, assetNops, []models.ChainType{models.ChainTypeEvm}) - - wfNodes := nodeOperatorsToIDs(t, wfNops) - cwNodes := nodeOperatorsToIDs(t, cwNops) - assetNodes := nodeOperatorsToIDs(t, assetNops) - - wfDon := keystone.DonCapabilities{ - Name: keystone.WFDonName, - Nops: wfNodes, - Capabilities: []kcr.CapabilitiesRegistryCapability{keystone.OCR3Cap}, - } - cwDon := keystone.DonCapabilities{ - Name: keystone.TargetDonName, - Nops: cwNodes, - Capabilities: []kcr.CapabilitiesRegistryCapability{keystone.WriteChainCap}, - } - assetDon := keystone.DonCapabilities{ - Name: keystone.StreamDonName, - Nops: assetNodes, - Capabilities: []kcr.CapabilitiesRegistryCapability{keystone.StreamTriggerCap}, - } - - var allNops []*models.NodeOperator - allNops = append(allNops, wfNops...) - allNops = append(allNops, cwNops...) - allNops = append(allNops, assetNops...) - - chains := make(map[uint64]struct{}) - for _, nop := range allNops { - for _, node := range nop.Nodes { - for _, chain := range node.ChainConfigs { - // chain selector lib doesn't support chain id 2 and we don't use it in tests - // because it's not an evm chain - if chain.Network.ChainID == "2" { // aptos chain - continue - } - id, err := strconv.ParseUint(chain.Network.ChainID, 10, 64) - require.NoError(t, err, "failed to parse chain id to uint64") - chains[id] = struct{}{} - } - } - } - var chainIDs []uint64 - for c := range chains { - chainIDs = append(chainIDs, c) - } - allChains := memory.NewMemoryChainsWithChainIDs(t, chainIDs) - - env := &deployment.Environment{ - Name: "CLO", - ExistingAddresses: deployment.NewMemoryAddressBook(), - Offchain: clo.NewJobClient(lggr, clo.JobClientConfig{Nops: allNops}), - Chains: allChains, - Logger: lggr, - OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), - } - // assume that all the nodes in the provided input nops are part of the don - for _, nop := range allNops { - for _, node := range nop.Nodes { - env.NodeIDs = append(env.NodeIDs, node.ID) - } - } - - // sepolia; all nodes are on the this chain - registryChainSel, err := chainsel.SelectorFromChainId(11155111) - require.NoError(t, err) - - var ocr3Config = keystone.OracleConfig{ - MaxFaultyOracles: len(wfNops) / 3, - } - - ctx := tests.Context(t) - // explicitly deploy the contracts - cs, err := keystone.DeployContracts(env, registryChainSel) - require.NoError(t, err) - // Deploy successful these are now part of our env. - require.NoError(t, env.ExistingAddresses.Merge(cs.AddressBook)) - - deployReq := keystone.ConfigureContractsRequest{ - RegistryChainSel: registryChainSel, - Env: env, - OCR3Config: &ocr3Config, - Dons: []keystone.DonCapabilities{wfDon, cwDon, assetDon}, - DoContractDeploy: false, - } - deployResp, err := keystone.ConfigureContracts(ctx, lggr, deployReq) - require.NoError(t, err) - ad := env.ExistingAddresses - - // all contracts on home chain - homeChainAddrs, err := ad.AddressesForChain(registryChainSel) - require.NoError(t, err) - require.Len(t, homeChainAddrs, 3) - // only forwarder on non-home chain - for sel := range env.Chains { - chainAddrs, err := ad.AddressesForChain(sel) - require.NoError(t, err) - if sel != registryChainSel { - require.Len(t, chainAddrs, 1) - } else { - require.Len(t, chainAddrs, 3) - } - containsForwarder := false - for _, tv := range chainAddrs { - if tv.Type == keystone.KeystoneForwarder { - containsForwarder = true - break - } - } - require.True(t, containsForwarder, "no forwarder found in %v on chain %d for target don", chainAddrs, sel) - } - req := &keystone.GetContractSetsRequest{ - Chains: env.Chains, - AddressBook: ad, - } - - contractSetsResp, err := keystone.GetContractSets(lggr, req) - require.NoError(t, err) - require.Len(t, contractSetsResp.ContractSets, len(env.Chains)) - // check the registry - regChainContracts, ok := contractSetsResp.ContractSets[registryChainSel] - require.True(t, ok) - gotRegistry := regChainContracts.CapabilitiesRegistry - require.NotNil(t, gotRegistry) - // check DONs - gotDons, err := gotRegistry.GetDONs(&bind.CallOpts{}) - if err != nil { - err = keystone.DecodeErr(kcr.CapabilitiesRegistryABI, err) - require.Fail(t, fmt.Sprintf("failed to get DONs from registry at %s: %s", gotRegistry.Address().String(), err)) - } - require.NoError(t, err) - assert.Len(t, gotDons, len(deployReq.Dons)) - // check NOPs - nops, err := gotRegistry.GetNodeOperators(&bind.CallOpts{}) - if err != nil { - err = keystone.DecodeErr(kcr.CapabilitiesRegistryABI, err) - require.Fail(t, fmt.Sprintf("failed to get NOPs from registry at %s: %s", gotRegistry.Address().String(), err)) - } - require.NoError(t, err) - assert.Len(t, nops, 26) // 10 NOPs owning workflow & writer DONs + 16 NOPs owning Asset DON - - for n, info := range deployResp.DonInfos { - found := false - for _, gdon := range gotDons { - if gdon.Id == info.Id { - found = true - assert.EqualValues(t, info, gdon) - break - } - } - require.True(t, found, "don %s not found in registry", n) - } - // check the forwarder - for _, cs := range contractSetsResp.ContractSets { - forwarder := cs.Forwarder - require.NotNil(t, forwarder) - // any read to ensure that the contract is deployed correctly - _, err := forwarder.Owner(&bind.CallOpts{}) - require.NoError(t, err) - // TODO expand this test; there is no get method on the forwarder so unclear how to test it - } - // check the ocr3 contract - for chainSel, cs := range contractSetsResp.ContractSets { - if chainSel != registryChainSel { - require.Nil(t, cs.OCR3) - continue - } - require.NotNil(t, cs.OCR3) - // any read to ensure that the contract is deployed correctly - _, err := cs.OCR3.LatestConfigDetails(&bind.CallOpts{}) - require.NoError(t, err) - } -} - -func requireChains(t *testing.T, donNops []*models.NodeOperator, cs []models.ChainType) { - got := make(map[models.ChainType]struct{}) - want := make(map[models.ChainType]struct{}) - for _, c := range cs { - want[c] = struct{}{} - } - for _, nop := range donNops { - for _, node := range nop.Nodes { - for _, cc := range node.ChainConfigs { - got[cc.Network.ChainType] = struct{}{} - } - } - require.EqualValues(t, want, got, "did not find all chains in node %s", nop.Name) - } -} - -func loadTestNops(t *testing.T, pth string) []*models.NodeOperator { - f, err := os.ReadFile(pth) - require.NoError(t, err) - var nops []*models.NodeOperator - require.NoError(t, json.Unmarshal(f, &nops)) - return nops -} diff --git a/deployment/keystone/deprecated.go b/deployment/keystone/deprecated.go new file mode 100644 index 00000000000..0e85cbedb17 --- /dev/null +++ b/deployment/keystone/deprecated.go @@ -0,0 +1,127 @@ +package keystone + +import "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" + +//TODO: delete this after the downstream migration is done + +// DEPRECATED: Use changeset package instead +// OracleConfig is the configuration for an oracle +type OracleConfig = changeset.OracleConfig + +// DEPRECATED: Use changeset package instead +// OCR3OnchainConfig is the onchain configuration of an OCR2 contract +type OCR2OracleConfig = changeset.OCR3OnchainConfig + +// DEPRECATED: Use changeset package instead +// NodeKeys is a set of public keys for a node +type NodeKeys = changeset.NodeKeys + +// DEPRECATED: Use changeset package instead +// TopLevelConfigSource is the top level configuration source +type TopLevelConfigSource = changeset.TopLevelConfigSource + +// DEPRECATED: Use changeset package instead +// GenerateOCR3Config generates an OCR3 config +var GenerateOCR3Config = changeset.GenerateOCR3Config + +// DEPRECATED: Use changeset package instead +// FeedConsumer is a feed consumer contract type +var FeedConsumer = changeset.FeedConsumer + +// DEPRECATED: Use changeset package instead +// KeystoneForwarder is a keystone forwarder contract type +var KeystoneForwarder = changeset.KeystoneForwarder + +// DEPRECATED: Use changeset package instead +// GetContractSetsRequest is a request to get contract sets +type GetContractSetsRequest = changeset.GetContractSetsRequest + +// DEPRECATED: Use changeset package instead +// GetContractSetsResponse is a response to get contract sets +type GetContractSetsResponse = changeset.GetContractSetsResponse + +// DEPRECATED: Use changeset package instead +// GetContractSets gets contract sets +var GetContractSets = changeset.GetContractSets + +// DEPRECATED: Use changeset package instead +// RegisterCapabilitiesRequest is a request to register capabilities +type RegisterCapabilitiesRequest = changeset.RegisterCapabilitiesRequest + +// DEPRECATED: Use changeset package instead +// RegisterCapabilitiesResponse is a response to register capabilities +type RegisterCapabilitiesResponse = changeset.RegisterCapabilitiesResponse + +// DEPRECATED: Use changeset package instead +// RegisterCapabilities registers capabilities +var RegisterCapabilities = changeset.RegisterCapabilities + +// DEPRECATED: Use changeset package instead +// RegisterNOPSRequest is a request to register NOPS +type RegisterNOPSRequest = changeset.RegisterNOPSRequest + +// DEPRECATED: Use changeset package instead +// RegisterNOPSResponse is a response to register NOPS +type RegisterNOPSResponse = changeset.RegisterNOPSResponse + +// DEPRECATED: Use changeset package instead +// RegisterNOPS registers NOPS +var RegisterNOPS = changeset.RegisterNOPS + +// DEPRECATED: Use changeset package instead +// RegisterNodesRequest is a request to register nodes with the capabilities registry +type RegisterNodesRequest = changeset.RegisterNodesRequest + +// DEPRECATED: Use changeset package instead +// RegisterNodesResponse is a response to register nodes with the capabilities registry +type RegisterNodesResponse = changeset.RegisterNodesResponse + +// DEPRECATED: Use changeset package instead +// RegisterNodes registers nodes with the capabilities registry +var RegisterNodes = changeset.RegisterNodes + +// DEPRECATED: Use changeset package instead +// RegisteredCapability is a wrapper of a capability and its ID +type RegisteredCapability = changeset.RegisteredCapability + +// DEPRECATED: Use changeset package instead +// FromCapabilitiesRegistryCapability converts a capabilities registry capability to a registered capability +var FromCapabilitiesRegistryCapability = changeset.FromCapabilitiesRegistryCapability + +// DEPRECATED: Use changeset package instead +// RegisterDonsRequest is a request to register Dons with the capabilities registry +type RegisterDonsRequest = changeset.RegisterDonsRequest + +// DEPRECATED: Use changeset package instead +// RegisterDonsResponse is a response to register Dons with the capabilities registry +type RegisterDonsResponse = changeset.RegisterDonsResponse + +// DEPRECATED: Use changeset package instead +// RegisterDons registers Dons with the capabilities registry +var RegisterDons = changeset.RegisterDons + +// DEPRECATED: Use changeset package instead +// DONToRegister is the minimal information needed to register a DON with the capabilities registry +type DONToRegister = changeset.DONToRegister + +// DEPRECATED: Use changeset package instead +// ConfigureContractsRequest is a request to configure ALL the contracts +type ConfigureContractsRequest = changeset.ConfigureContractsRequest + +// DEPRECATED: Use changeset package instead +// ConfigureContractsResponse is a response to configure ALL the contracts +type ConfigureContractsResponse = changeset.ConfigureContractsResponse + +// DEPRECATED: Use changeset package instead +// DonCapabilities is a set of capabilities hosted by a set of node operators +// in is in a convenient form to handle the CLO representation of the nop data +type DonCapabilities = changeset.DonCapabilities + +// DEPRECATED: Use changeset package instead +type DeployRequest = changeset.DeployRequest + +// DEPRECATED: Use changeset package instead +type DeployResponse = changeset.DeployResponse + +// DEPRECATED: Use changeset package instead +type ContractSet = changeset.ContractSet diff --git a/deployment/keystone/test/changeset/capability_registry.go b/deployment/keystone/test/changeset/capability_registry.go index 28ee711dc75..98f1e752f5a 100644 --- a/deployment/keystone/test/changeset/capability_registry.go +++ b/deployment/keystone/test/changeset/capability_registry.go @@ -7,10 +7,11 @@ import ( chainsel "github.com/smartcontractkit/chain-selectors" "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/view/v1_0" - "github.com/smartcontractkit/chainlink/deployment/keystone" + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" ) type HydrateConfig struct { @@ -33,7 +34,7 @@ func HydrateCapabilityRegistry(t *testing.T, v v1_0.CapabilityRegistryView, env return nil, fmt.Errorf("failed to deploy contract: %w", err) } - resp, err := keystone.GetContractSets(env.Logger, &keystone.GetContractSetsRequest{ + resp, err := changeset.GetContractSets(env.Logger, &changeset.GetContractSetsRequest{ Chains: env.Chains, AddressBook: changesetOutput.AddressBook, }) @@ -49,13 +50,13 @@ func HydrateCapabilityRegistry(t *testing.T, v v1_0.CapabilityRegistryView, env nopsParams := v.NopsToNopsParams() tx, err := deployedContract.AddNodeOperators(chain.DeployerKey, nopsParams) - if _, err = deployment.ConfirmIfNoError(chain, tx, keystone.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err)); err != nil { + if _, err = deployment.ConfirmIfNoError(chain, tx, deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err)); err != nil { return nil, fmt.Errorf("failed to add node operators: %w", err) } capabilitiesParams := v.CapabilitiesToCapabilitiesParams() tx, err = deployedContract.AddCapabilities(chain.DeployerKey, capabilitiesParams) - if _, err = deployment.ConfirmIfNoError(chain, tx, keystone.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err)); err != nil { + if _, err = deployment.ConfirmIfNoError(chain, tx, deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err)); err != nil { return nil, fmt.Errorf("failed to add capabilities: %w", err) } @@ -64,7 +65,7 @@ func HydrateCapabilityRegistry(t *testing.T, v v1_0.CapabilityRegistryView, env return nil, fmt.Errorf("failed to convert nodes to nodes params: %w", err) } tx, err = deployedContract.AddNodes(chain.DeployerKey, nodesParams) - if _, err = deployment.ConfirmIfNoError(chain, tx, keystone.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err)); err != nil { + if _, err = deployment.ConfirmIfNoError(chain, tx, deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err)); err != nil { return nil, fmt.Errorf("failed to add nodes: %w", err) } @@ -78,7 +79,7 @@ func HydrateCapabilityRegistry(t *testing.T, v v1_0.CapabilityRegistryView, env peerIds = append(peerIds, id) } tx, err = deployedContract.AddDON(chain.DeployerKey, peerIds, cfgs, don.IsPublic, don.AcceptsWorkflows, don.F) - if _, err = deployment.ConfirmIfNoError(chain, tx, keystone.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err)); err != nil { + if _, err = deployment.ConfirmIfNoError(chain, tx, deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err)); err != nil { return nil, fmt.Errorf("failed to add don: %w", err) } } diff --git a/deployment/keystone/testdata/asset_nodes.json b/deployment/keystone/testdata/asset_nodes.json deleted file mode 100644 index 9ad2ba4e0e8..00000000000 --- a/deployment/keystone/testdata/asset_nodes.json +++ /dev/null @@ -1,978 +0,0 @@ -[ - { - "id": "81", - "keys": [ - "cl-df-asset-don-testnet-0" - ], - "name": "Chainlink Keystone Asset DON Node Operator 0", - "metadata": { - "nodeCount": 2, - "jobCount": 18 - }, - "nodes": [ - { - "id": "831", - "name": "Chainlink Sepolia Prod Keystone Asset Node 0", - "publicKey": "d791dad33f1aeff811f3364088993053d5d08fa595ba48f73aecd4ee2d5035a1", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0xe826b8D7f57b1c08E2d0C9477006244AECB280c3", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWDh47EiK5TzG4yApEEwLecgRkqZKQif3fcnsztfhQNzNh", - "publicKey": "398f42d12c7f3445341e42ce4ea555c87d84db68c808c76a0655e5d993d7a2a6" - }, - "ocrKeyBundle": { - "bundleID": "c8dee638c00194cf38bd0c30306fffd14b561601828085ceaaf0ab5fe451ec23", - "configPublicKey": "dbd5d1f5aa4921fd1e7b16f26dc75aff5cc08fee6e74324e947654ba78791e7e", - "offchainPublicKey": "66a599cda37e6fb5dc50e16d7c81e6967e010a25bbeaabf20752e228a26f5bc3", - "onchainSigningAddress": "9184c1c20da57f2f747a60909d0152c289e8518f" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:19:34.127102Z" - }, - { - "id": "82", - "keys": [ - "cl-df-asset-don-testnet-1" - ], - "name": "Chainlink Keystone Asset DON Node Operator 1", - "metadata": { - "nodeCount": 1, - "jobCount": 9 - }, - "nodes": [ - { - "id": "832", - "name": "Chainlink Sepolia Prod Keystone Asset Node 1", - "publicKey": "eb410038ba7847a729c4e40c1d4afdbcce9ad33cc71e459883cd98f0883a5366", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0xCE154165b0d60D1efA9b3c7a172ED77712Cb82f9", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWG7WEsQjxXQdn5WAEQSDh77qxjMoWxz3rGYrRC9pPB7qx", - "publicKey": "5d8a1f11ecd0cd2cdd95fec35b8ea6386af567bc96aa2c2ea47e91d22b1f12bf" - }, - "ocrKeyBundle": { - "bundleID": "a6dda044db7fa1fa652ec9ff60a44fb31ee99d33db35599848b21e34ce33c343", - "configPublicKey": "586fb9935401e8907ead91e7a3423a0c0676d4669bac619f71c99913e14b362a", - "offchainPublicKey": "9557c0c4c6c8aeb41ecaa84f0aa7d0e1be7ffa9e4a08da27b23bd64b2d0c0fe9", - "onchainSigningAddress": "bd3e16dda612f543c0f79fafc03fa35f3f300e30" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:19:48.159926Z" - }, - { - "id": "83", - "keys": [ - "cl-df-asset-don-testnet-2" - ], - "name": "Chainlink Keystone Asset DON Node Operator 2", - "metadata": { - "nodeCount": 1, - "jobCount": 9 - }, - "nodes": [ - { - "id": "833", - "name": "Chainlink Sepolia Prod Keystone Asset Node 2", - "publicKey": "daf14b79caa585c3dacf550688aeed5371f8fd39cbfb6e33add2fb82538626b0", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0xbb16a69A7bb8778dc52a2D081EE1B2Dde0237F3b", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWBWms38viHaptUHTXXNdN4Qm2ZxDWtuaZviZtq1WzWWcq", - "publicKey": "1935b60309f79e7fd1bfd4736df5729b7532bcd435be2a707dd28519e9ae6e6a" - }, - "ocrKeyBundle": { - "bundleID": "9c63a332ff254cd2cda8bcf2c3f0e46ee95d4991595019619a0c60907437d98c", - "configPublicKey": "29b9b6f61db8e72df13e17e274bdf5450987953079b9dee2745f2d288dc7e86d", - "offchainPublicKey": "c3b08d0b68baf68da2c8446f6a9dc552af3ab2014b900d75ca9e2122b6fc9eb0", - "onchainSigningAddress": "cb66494d66922ad00708bce7c83ada133ddb8994" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:20:01.151494Z" - }, - { - "id": "84", - "keys": [ - "cl-df-asset-don-testnet-3" - ], - "name": "Chainlink Keystone Asset DON Node Operator 3", - "metadata": { - "nodeCount": 1, - "jobCount": 9 - }, - "nodes": [ - { - "id": "834", - "name": "Chainlink Sepolia Prod Keystone Asset Node 3", - "publicKey": "0e1f9462a8b326d746fde2d5016faa9f2e017f7e6e5969aaf3281519d2e31dbc", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0xA64f65e0c12ab015792c34867BE5b80b4D4C551A", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWMhHZTVHz23gCQAEzFyeBLxR9ghVqMQHk18VND4TbAc1U", - "publicKey": "b07bf77b2b1d8964915d4871b4cd0173e13bc1d0590731a8969393a6e80aef8f" - }, - "ocrKeyBundle": { - "bundleID": "87770ad41d54661a6dee424612f4338b49cd4fd20bdab1f11c308c76efeb56f8", - "configPublicKey": "dd0edc91d1476a0a4c554e8fe8050dadba679ba42f53973bf181d85eed1b6821", - "offchainPublicKey": "2ba2cc779c8e1460d9ff823d594708a344bb7a9d84aa3aa3833d539852511a88", - "onchainSigningAddress": "5e5b1a602c5a79ec6cdeb67e6f855d58061f785f" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:20:10.382565Z" - }, - { - "id": "85", - "keys": [ - "cl-df-asset-don-testnet-4" - ], - "name": "Chainlink Keystone Asset DON Node Operator 4", - "metadata": { - "nodeCount": 1, - "jobCount": 9 - }, - "nodes": [ - { - "id": "835", - "name": "Chainlink Sepolia Prod Keystone Asset Node 4", - "publicKey": "1d5f6ef3443e48bd471efdb47a5b9c6c900a14f35253c2b562908186f5b8b457", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x7284bBa5C8090Ac99d55b14db015a291C017275c", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWMrkkbkFYJydLhcYKr8AnxNcNGmwfVXMQGdn8uoSpYoJs", - "publicKey": "b2e8f0b25c7334e8082cb82eee29bc4f48ae086b8fe4a2fd5eb4e08195a0e06c" - }, - "ocrKeyBundle": { - "bundleID": "1ceac31d893d21e95a62419d94b1a88805fa4f056b1636ccd79ab0ca8b4fe68c", - "configPublicKey": "4c94f49461fd0fd9d4da5cda4590a2cf80fba2ea27c422b92ee18a3aaaa51321", - "offchainPublicKey": "d1649b393614e01811979340d2726280f9ea57fd7a1ee28958adbbaf71b41bf5", - "onchainSigningAddress": "e47d17607054e9899d3fb7fa5b4b3e01b85b8fc9" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:20:21.050174Z" - }, - { - "id": "86", - "keys": [ - "cl-df-asset-don-testnet-5" - ], - "name": "Chainlink Keystone Asset DON Node Operator 5", - "metadata": { - "nodeCount": 1, - "jobCount": 9 - }, - "nodes": [ - { - "id": "837", - "name": "Chainlink Sepolia Prod Keystone Asset Node 5", - "publicKey": "d87dfbb7444036e0654578afdb11864e31a0de1824ca2780f24b16116a85463d", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x6c75DB65540ca889803a092d4C1497D3337cDE30", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWH8q69DtEqahJdwKfYXnkRHHH6E4jTqevZSAZzGsrnsTB", - "publicKey": "6cbcb3cc0a48ec9d94bb1424beea5e1b7cf57fda2dbfc519afd9221cbeac3b8e" - }, - "ocrKeyBundle": { - "bundleID": "6e088c00e61fea95a5a808a56e7e55c58ec0d61c3207383a2c63abc705bd120c", - "configPublicKey": "0728ce40c95155853ecd31bc213ed2b39d4ecf2e62dc95334f008181ad010848", - "offchainPublicKey": "521d4c291fe8ef245b2e497982b0a07127cd3c65439a10784d914e03ba24328d", - "onchainSigningAddress": "d32a6ed4be6656fd988a0e43e71ce43fab3faba4" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:21:21.831183Z" - }, - { - "id": "87", - "keys": [ - "cl-df-asset-don-testnet-6" - ], - "name": "Chainlink Keystone Asset DON Node Operator 6", - "metadata": { - "nodeCount": 1, - "jobCount": 9 - }, - "nodes": [ - { - "id": "838", - "name": "Chainlink Sepolia Prod Keystone Asset Node 6", - "publicKey": "294f58723d4049af0dcd63eedfcda957287401a10070db509ede7a799bb70654", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0xa2788731913cc2deBC061F8594AEaa8e99B4FCCE", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWD7URmTzSeotMvEzkJTiFrwUHhcGMBeaS9GY8763Sqqnf", - "publicKey": "30f502f9fb19b54e8644f038f57f9a43582f76b86bace61759fff12886ccf1a8" - }, - "ocrKeyBundle": { - "bundleID": "57bc2a8a62ed96e6aa7b9bbe56f93abeef938a1766cb8a6d18e42ebf71101646", - "configPublicKey": "36c882b0cdcec84aa85f00ea43cd31254406cec84d31f6dded69b4fbb3f17449", - "offchainPublicKey": "46951e1e18cee25cd417b3fa7feb25fb53623a249e1c09491bb978dccc2ea76e", - "onchainSigningAddress": "abcd8be3952a84fb10947dbeb768a255ead58ca2" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:21:34.93501Z" - }, - { - "id": "88", - "keys": [ - "cl-df-asset-don-testnet-7" - ], - "name": "Chainlink Keystone Asset DON Node Operator 7", - "metadata": { - "nodeCount": 1, - "jobCount": 9 - }, - "nodes": [ - { - "id": "839", - "name": "Chainlink Sepolia Prod Keystone Asset Node 7", - "publicKey": "55b0ec5d90de973c00efce233334a9d3c5a94062ea010575bb248eb6804a9cfe", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x14dAF00DaD855089A6586690d5C1fD2779302736", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWBbo44H5CLACV3yGyDWrtMuSWRdN5sQcDsnPC4WfLr6Jo", - "publicKey": "1a7ef5e7420434fcf06de3d15a0191f7499e00e15427679616ce800779ceb514" - }, - "ocrKeyBundle": { - "bundleID": "f87acde2c1c21e8859d84813034d84a3f3bb1d49596e13ac66731d50750b9436", - "configPublicKey": "e75f21bc1dc6eac12358277caf18a216ed54f8dc84285941ef1f5fb1047f8d5b", - "offchainPublicKey": "c7b86dfbdf31a3b13c44305cd6fc88c402653198201006083414223ffc36950d", - "onchainSigningAddress": "93fbb113f191959f8ab5e052395676e0038f2f1f" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:21:45.063449Z" - }, - { - "id": "89", - "keys": [ - "cl-df-asset-don-testnet-8" - ], - "name": "Chainlink Keystone Asset DON Node Operator 8", - "metadata": { - "nodeCount": 1, - "jobCount": 9 - }, - "nodes": [ - { - "id": "840", - "name": "Chainlink Sepolia Prod Keystone Asset Node 8", - "publicKey": "8f9f327ac7ad823a0f3297f3505591bcd40adc8fb1309f99874c26663cbd5914", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0xb0C0168905C07F00A141494eaeFc0bD9F153fc16", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWGVroAehJh33SBns9MohmctNPZSDh89KRQM1J6TSCnT1v", - "publicKey": "63442493270891409900afd3bb868d03fd07c775bb38c56e56a624b674a68b35" - }, - "ocrKeyBundle": { - "bundleID": "4413e0a3080c3dfa7709b16c3ee68c04359e2dd66d107fd3be6ba7c615c4b3b6", - "configPublicKey": "8f3975b19fc6f02e241119b2132331ed9ed0d19221bd0cfd6f54b5859090a741", - "offchainPublicKey": "f4f182c889668d8951932c49e1ffb1252b8a33a9875d3f19aea7bb805b65c7a6", - "onchainSigningAddress": "b257e9efe637f38b5462a170737571ea0f0e2e05" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:21:55.09098Z" - }, - { - "id": "90", - "keys": [ - "cl-df-asset-don-testnet-9" - ], - "name": "Chainlink Keystone Asset DON Node Operator 9", - "metadata": { - "nodeCount": 1, - "jobCount": 9 - }, - "nodes": [ - { - "id": "841", - "name": "Chainlink Sepolia Prod Keystone Asset Node 9", - "publicKey": "1d79884071dfec1f39dc62f4868f4a143ae39cb03ad9d14142b184686c2b5a93", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x2F5E08a5b9D893e9dA2d68Ef605fBa6f8Ebfd0cB", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWEBn9tWmMWrSxRZe2VQ56RcSHRUPdcFoD3Ep88wqTT9zP", - "publicKey": "40eb109d9f28e8754dfff419a9175d6714405907413d2f77657355721c3b2bd0" - }, - "ocrKeyBundle": { - "bundleID": "6d4da72b1daad0b9ea47a7daa6cde81c1608b7bd199c05b18b989d10c5d7b99e", - "configPublicKey": "7e1c66bfa23c270770401d0dd739adad5a52827ecb40a0668f7e014d53f38059", - "offchainPublicKey": "712561a10b1f7dd96f0ae0f0d3e6cdf83fdd0837d333cf9bbae0090126ae7f39", - "onchainSigningAddress": "2ef8cea7dae7bd1e876a59a44ca59b89adf8abb4" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:22:09.476108Z" - }, - { - "id": "91", - "keys": [ - "cl-df-asset-don-testnet-10" - ], - "name": "Chainlink Keystone Asset DON Node Operator 10", - "metadata": { - "nodeCount": 1, - "jobCount": 9 - }, - "nodes": [ - { - "id": "842", - "name": "Chainlink Sepolia Prod Keystone Asset Node 10", - "publicKey": "cf6c47ad934518f5947ce8f1a48c2df8c93bd585788a3a82229fd4d723efa706", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x4794743bB8f159954Efa31642609ebfD4D2b9EdC", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWNXZCbQe4Ao7KEciJGY6Ec4oZLZNGcMTPyZ7XpFhLPyLo", - "publicKey": "bcd987b3b2b20d9effe30598850ddfd33023339dab012c4aee4cdc4246111bfc" - }, - "ocrKeyBundle": { - "bundleID": "a8d9929327d89cfabd8c583d250dfddbc14e947e9253f7471191886ca5197786", - "configPublicKey": "a1a390e756bce818d1786dca6ba3e45013085087e5a3be6253d8bbbd6479255a", - "offchainPublicKey": "76522fec251ce6130c03a816025f2054eb3ac83b7d30347f42b73a77e7b9a511", - "onchainSigningAddress": "179d48901e5e9c3c11dd947c001f8a2ee887c8eb" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:22:30.732346Z" - }, - { - "id": "92", - "keys": [ - "cl-df-asset-don-testnet-11" - ], - "name": "Chainlink Keystone Asset DON Node Operator 11", - "metadata": { - "nodeCount": 1, - "jobCount": 9 - }, - "nodes": [ - { - "id": "843", - "name": "Chainlink Sepolia Prod Keystone Asset Node 11", - "publicKey": "c239c23670224558a64ea3165eae8d67a17b75b1874fbccf8a4dd98e953820ad", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x27AFd92F391dFD7BA1bbC89e3bd13ceC9A667c11", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWSSzLfwq7QSdJcpDLFiBznA1XR58dwg1xre4b88SbP7VF", - "publicKey": "f71ccc7f7b73f1499f72987679a94a11e8564f01415acdb958c008c5bfe21eae" - }, - "ocrKeyBundle": { - "bundleID": "3e691b13aa702631fba25f6e128a566bdff3982cc3438af29acc2a819b9d6e02", - "configPublicKey": "149d81dce137d0874b477ad6c19dc72801f335200622fa34f1c660623febed22", - "offchainPublicKey": "b0d0d8e3c62abc7236e6539413ef82e568dd24f0c39ff6e8e2babe513590a522", - "onchainSigningAddress": "a0f2feab4d03899eb2e830bd4abc3fd5babef3e1" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:22:42.314654Z" - }, - { - "id": "93", - "keys": [ - "cl-df-asset-don-testnet-12" - ], - "name": "Chainlink Keystone Asset DON Node Operator 12", - "metadata": { - "nodeCount": 1, - "jobCount": 9 - }, - "nodes": [ - { - "id": "844", - "name": "Chainlink Sepolia Prod Keystone Asset Node 12", - "publicKey": "71b29eb63daa6ac2e48b46669936eff5606879b102bae78afc929554c435dd0b", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x13d5b27d71B4C4697874177Ff43DEB1884Cff49e", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWT1LMqEW51UfxBynzjYjuybQzVkmf4rH9js9e16QAbU3X", - "publicKey": "ff66057a6c96779134a6527364cddcce43b69e3d1820f59dde5e6b38d1d32fde" - }, - "ocrKeyBundle": { - "bundleID": "4854ee3fc7ac4591eea33c5d0d1cefd4ad819d2c374a2f86267a9999228a967a", - "configPublicKey": "470225644f274147b5b80c862a3f3cd7a19fed4ff915e9c18ac80e06003ecc6a", - "offchainPublicKey": "e7d89e196f5f6d92f4c42ab34f9a2f21f3201314be65b819872c4609b87866c7", - "onchainSigningAddress": "c84f2f60ccb1d7e6c6e4ae4bc3cab8bb85db8977" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:22:52.838595Z" - }, - { - "id": "94", - "keys": [ - "cl-df-asset-don-testnet-13" - ], - "name": "Chainlink Keystone Asset DON Node Operator 13", - "metadata": { - "nodeCount": 1, - "jobCount": 9 - }, - "nodes": [ - { - "id": "845", - "name": "Chainlink Sepolia Prod Keystone Asset Node 13", - "publicKey": "c098264a552125355804b903de06400621f2d1de357c2bed94586727fe8a3502", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x5647A091F2a09915c1C0F6ac95630Be87114881F", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWRjg2KoP6jKVWU2BczeduWsdnfN69tHN2YGEAGtETvc9P", - "publicKey": "ec87467a512f8218bb63f7fcf46cf0b8fd8ebb14bd5f3b670908d505a5af801a" - }, - "ocrKeyBundle": { - "bundleID": "20626049a1e24912a14d186645ba70fea4860efcc987b3ec7c9ddc881b5057db", - "configPublicKey": "d84d4653db0caca062d4058e9937ae618a53bbd1b41a673c5f13bebc24e7aa3a", - "offchainPublicKey": "156c8ab52099386377fe27bbd50dafa368ff2790245f1407579f590b0bae7a1e", - "onchainSigningAddress": "4f4b7bff5d32d62326b575d8c951d34e54888e31" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:23:19.587619Z" - }, - { - "id": "95", - "keys": [ - "cl-df-asset-don-testnet-14" - ], - "name": "Chainlink Keystone Asset DON Node Operator 14", - "metadata": { - "nodeCount": 1, - "jobCount": 9 - }, - "nodes": [ - { - "id": "846", - "name": "Chainlink Sepolia Prod Keystone Asset Node 14", - "publicKey": "12681ec137cd2d25e7c71638f564404dd764061921c870bbcddf683d048eed21", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x0419E70d32c3972930c99aaaDF20dCB473c56d22", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWCdEG68z5kwYuD1xp1aJsFBtpw2HYh1K3ffVM6keVrJnT", - "publicKey": "29b8bafebdef5e11ec3556fbcacdfb626d2f80cf178406e38664775e8b1ace78" - }, - "ocrKeyBundle": { - "bundleID": "80b1304898d5cea3c684790a0f01158468c7fa7770675edef33e4b137232ddc9", - "configPublicKey": "15552ecb6ff10103a534f02594a7b7cbab686d76d5e7b32a9c67059e8c856861", - "offchainPublicKey": "b561b7df3bdfe70f1af9395dbc00ef796774aa352c9a30d9c7e2f7e74d438073", - "onchainSigningAddress": "fb1ca65bf473b4443d7359becc0de67a2d96228d" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:23:44.73219Z" - }, - { - "id": "96", - "keys": [ - "cl-df-asset-don-testnet-15" - ], - "name": "Chainlink Keystone Asset DON Node Operator 15", - "metadata": { - "nodeCount": 1, - "jobCount": 9 - }, - "nodes": [ - { - "id": "847", - "name": "Chainlink Sepolia Prod Keystone Asset Node 15", - "publicKey": "a9a5d084f9cbbbd291eb43c33dd137cd6140e33c53cebb260463bf52795ec579", - "chainConfigs": [ - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x931900764a585D7a01e500976B630B4747216c8c", - "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWQyZ9A9ScBpcoRww1gJVBNB2brNkjJhaqze6ehuv6bmfQ", - "publicKey": "e139f020ae4bc9efaa77da9cfd54339d36176479028f849b9e64ad2cf29acba3" - }, - "ocrKeyBundle": { - "bundleID": "5c1c69eb1d6619b2c9b93bdfdd9c1b87c28101d6fc88bf7979ad52ceda459908", - "configPublicKey": "33f2107ab22b3dd5c19d5de0c5b1e6e038f2275ba455eed7997485caec421925", - "offchainPublicKey": "bb91b077c135cbdd1f4422c6021cf56d78326710c8bb8c4a87b3e7415e48915f", - "onchainSigningAddress": "b94e3de607033d03e3f0cc3ef1f09edd2592b440" - }, - "plugins": { - "mercury": true - } - } - } - ], - "connected": true, - "supportedProducts": [ - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-09-18T19:24:01.875231Z" - } -] diff --git a/deployment/keystone/testdata/chain_writer_nodes.json b/deployment/keystone/testdata/chain_writer_nodes.json deleted file mode 100644 index 807730451ad..00000000000 --- a/deployment/keystone/testdata/chain_writer_nodes.json +++ /dev/null @@ -1,1447 +0,0 @@ - -[ - { - "id": "67", - "keys": [ - "keystone-09" - ], - "name": "Chainlink Keystone Node Operator 9", - "metadata": { - "nodeCount": 2, - "jobCount": 4 - }, - "nodes": [ - { - "id": "818", - "name": "Chainlink Sepolia Prod Keystone Cap One 9", - "publicKey": "3f5bbcb4b0409e6ea39d824f1837787484475fffb12e5e4a70509756ef6c7f9a", - "chainConfigs": [ - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0x9b74f08bD7269919C0597C0E00e70ef2A66829db", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWPG6X2RgqoSWtM3kvETV6kK4ki8FftaBkwvFWk8yKRBkz", - "publicKey": "c7bf55cf625a55470b0c56c3e51ad175c9dd0d42ca48246c205c715b7495937f" - }, - "ocrKeyBundle": { - "bundleID": "aa717effd7d28374c5980dbd9583dcff5e0800e7100051c6c8418899648dffbf", - "configPublicKey": "3fd95a3839f15adcdff573e6fbf07d06d78fbfeac5eb683f67e70226c1983c44", - "offchainPublicKey": "2b8b8d091c6f4446365f463e6132d699206bbddd38284e8e14ae0443382f297c", - "onchainSigningAddress": "b05b138a987fceffa68f79bdbb36a1faf8d3d964" - }, - "plugins": {} - } - }, - { - "network": { - "id": "10", - "chainID": "43113", - "chainType": "EVM", - "name": "Avalanche Testnet (Fuji)" - }, - "accountAddress": "0x662B6B119f7fc9Dc2A526395A9EA88AE79A1192F", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWPG6X2RgqoSWtM3kvETV6kK4ki8FftaBkwvFWk8yKRBkz", - "publicKey": "c7bf55cf625a55470b0c56c3e51ad175c9dd0d42ca48246c205c715b7495937f" - }, - "ocrKeyBundle": { - "bundleID": "aa717effd7d28374c5980dbd9583dcff5e0800e7100051c6c8418899648dffbf", - "configPublicKey": "3fd95a3839f15adcdff573e6fbf07d06d78fbfeac5eb683f67e70226c1983c44", - "offchainPublicKey": "2b8b8d091c6f4446365f463e6132d699206bbddd38284e8e14ae0443382f297c", - "onchainSigningAddress": "b05b138a987fceffa68f79bdbb36a1faf8d3d964" - }, - "plugins": {} - } - }, - { - "network": { - "id": "147", - "chainID": "84532", - "chainType": "EVM", - "name": "Base Testnet (Sepolia)" - }, - "accountAddress": "0x34431021e0E07c75816226697Af6Ef02725e36af", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWPG6X2RgqoSWtM3kvETV6kK4ki8FftaBkwvFWk8yKRBkz", - "publicKey": "c7bf55cf625a55470b0c56c3e51ad175c9dd0d42ca48246c205c715b7495937f" - }, - "ocrKeyBundle": { - "bundleID": "aa717effd7d28374c5980dbd9583dcff5e0800e7100051c6c8418899648dffbf", - "configPublicKey": "3fd95a3839f15adcdff573e6fbf07d06d78fbfeac5eb683f67e70226c1983c44", - "offchainPublicKey": "2b8b8d091c6f4446365f463e6132d699206bbddd38284e8e14ae0443382f297c", - "onchainSigningAddress": "b05b138a987fceffa68f79bdbb36a1faf8d3d964" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0xB5988d5d9ADd3d98CF45211bE37cf9b3372054C9", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWPG6X2RgqoSWtM3kvETV6kK4ki8FftaBkwvFWk8yKRBkz", - "publicKey": "c7bf55cf625a55470b0c56c3e51ad175c9dd0d42ca48246c205c715b7495937f" - }, - "ocrKeyBundle": { - "bundleID": "aa717effd7d28374c5980dbd9583dcff5e0800e7100051c6c8418899648dffbf", - "configPublicKey": "3fd95a3839f15adcdff573e6fbf07d06d78fbfeac5eb683f67e70226c1983c44", - "offchainPublicKey": "2b8b8d091c6f4446365f463e6132d699206bbddd38284e8e14ae0443382f297c", - "onchainSigningAddress": "b05b138a987fceffa68f79bdbb36a1faf8d3d964" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "OCR3_CAPABILITY", - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T19:00:07.113658Z" - }, - { - "id": "68", - "keys": [ - "keystone-08" - ], - "name": "Chainlink Keystone Node Operator 8", - "metadata": { - "nodeCount": 2, - "jobCount": 4 - }, - "nodes": [ - { - "id": "817", - "name": "Chainlink Sepolia Prod Keystone Cap One 8", - "publicKey": "2346da196a82c88fe6c315d2e4d0dddacf4590a172b20adb6f27a8601ca0540d", - "chainConfigs": [ - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0xa5C7133aBD35F9d742bD2997D693A507c5eBf4Ac", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWNfg9cYxEri1zGbdCZ87DekmruYY6J1wUobEwNNVewMpT", - "publicKey": "beee088bccea272eb6473fcc1cd3e22f2fc8d3a253a6398b69f5aab94070e690" - }, - "ocrKeyBundle": { - "bundleID": "9fba2d29874bb06b07272bd9141f096c1987d790bb0f81c3ffaf66d11cdac4f2", - "configPublicKey": "66dec87065de79e64ed4edd2478ec40a66f955af56e7b837729f464f8487d713", - "offchainPublicKey": "a0f59d50078c77812da8d3077f552209adfb58e76b635e008b6b0f872ce52139", - "onchainSigningAddress": "ed25406f1ef2e1381f6e1e04341f1a6e8b4eacea" - }, - "plugins": {} - } - }, - { - "network": { - "id": "10", - "chainID": "43113", - "chainType": "EVM", - "name": "Avalanche Testnet (Fuji)" - }, - "accountAddress": "0x9fd869f5baADb79F9b7C58c0855fcAc0384e1d4B", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWNfg9cYxEri1zGbdCZ87DekmruYY6J1wUobEwNNVewMpT", - "publicKey": "beee088bccea272eb6473fcc1cd3e22f2fc8d3a253a6398b69f5aab94070e690" - }, - "ocrKeyBundle": { - "bundleID": "9fba2d29874bb06b07272bd9141f096c1987d790bb0f81c3ffaf66d11cdac4f2", - "configPublicKey": "66dec87065de79e64ed4edd2478ec40a66f955af56e7b837729f464f8487d713", - "offchainPublicKey": "a0f59d50078c77812da8d3077f552209adfb58e76b635e008b6b0f872ce52139", - "onchainSigningAddress": "ed25406f1ef2e1381f6e1e04341f1a6e8b4eacea" - }, - "plugins": {} - } - }, - { - "network": { - "id": "147", - "chainID": "84532", - "chainType": "EVM", - "name": "Base Testnet (Sepolia)" - }, - "accountAddress": "0xe477E4C2e335E9b839665d710dE77CFECa9C43A7", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWNfg9cYxEri1zGbdCZ87DekmruYY6J1wUobEwNNVewMpT", - "publicKey": "beee088bccea272eb6473fcc1cd3e22f2fc8d3a253a6398b69f5aab94070e690" - }, - "ocrKeyBundle": { - "bundleID": "9fba2d29874bb06b07272bd9141f096c1987d790bb0f81c3ffaf66d11cdac4f2", - "configPublicKey": "66dec87065de79e64ed4edd2478ec40a66f955af56e7b837729f464f8487d713", - "offchainPublicKey": "a0f59d50078c77812da8d3077f552209adfb58e76b635e008b6b0f872ce52139", - "onchainSigningAddress": "ed25406f1ef2e1381f6e1e04341f1a6e8b4eacea" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x056A1275DD670205aba10D8fC9bB597777a65030", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWNfg9cYxEri1zGbdCZ87DekmruYY6J1wUobEwNNVewMpT", - "publicKey": "beee088bccea272eb6473fcc1cd3e22f2fc8d3a253a6398b69f5aab94070e690" - }, - "ocrKeyBundle": { - "bundleID": "9fba2d29874bb06b07272bd9141f096c1987d790bb0f81c3ffaf66d11cdac4f2", - "configPublicKey": "66dec87065de79e64ed4edd2478ec40a66f955af56e7b837729f464f8487d713", - "offchainPublicKey": "a0f59d50078c77812da8d3077f552209adfb58e76b635e008b6b0f872ce52139", - "onchainSigningAddress": "ed25406f1ef2e1381f6e1e04341f1a6e8b4eacea" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "OCR3_CAPABILITY", - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T20:26:37.622463Z" - }, - { - "id": "69", - "keys": [ - "keystone-07" - ], - "name": "Chainlink Keystone Node Operator 7", - "metadata": { - "nodeCount": 2, - "jobCount": 4 - }, - "nodes": [ - { - "id": "816", - "name": "Chainlink Sepolia Prod Keystone Cap One 7", - "publicKey": "50d4e3393516d1998e5c39874d7c0da2291e4e3727f8baac4380e9f5573cc648", - "chainConfigs": [ - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0x0ba7c1096B701A862bBCe7F13E9D33eED7e33c1D", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWQswQr8fxJG5ieMrayptGV4rvCjDWPCFtfkqm4L6NZbbb", - "publicKey": "dfc9a26dc022bd244c13d62ca88bbe62ca996065bd23224e1f1b77128914d84e" - }, - "ocrKeyBundle": { - "bundleID": "d4566a0c2f256e59733ad2a6dff9f388a1e00b2e65ec1cff7590cb59028888cd", - "configPublicKey": "58db0da621471e616615b8c1c1658ee3b7afbfa64662ce28b38272a95964052c", - "offchainPublicKey": "262fee9de8dd0c8758ba78de8873fdb6705c45ce331bc16ac81dc5b5f0b9680f", - "onchainSigningAddress": "516a9990d3a202b25c2cdd2f6316f4d066543e5d" - }, - "plugins": {} - } - }, - { - "network": { - "id": "10", - "chainID": "43113", - "chainType": "EVM", - "name": "Avalanche Testnet (Fuji)" - }, - "accountAddress": "0xcC44eD47023Bd88B82092A708c38609e8Fc2D197", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWQswQr8fxJG5ieMrayptGV4rvCjDWPCFtfkqm4L6NZbbb", - "publicKey": "dfc9a26dc022bd244c13d62ca88bbe62ca996065bd23224e1f1b77128914d84e" - }, - "ocrKeyBundle": { - "bundleID": "d4566a0c2f256e59733ad2a6dff9f388a1e00b2e65ec1cff7590cb59028888cd", - "configPublicKey": "58db0da621471e616615b8c1c1658ee3b7afbfa64662ce28b38272a95964052c", - "offchainPublicKey": "262fee9de8dd0c8758ba78de8873fdb6705c45ce331bc16ac81dc5b5f0b9680f", - "onchainSigningAddress": "516a9990d3a202b25c2cdd2f6316f4d066543e5d" - }, - "plugins": {} - } - }, - { - "network": { - "id": "147", - "chainID": "84532", - "chainType": "EVM", - "name": "Base Testnet (Sepolia)" - }, - "accountAddress": "0x0E8F4E699cd331022FaA2Ad75E500e70303C8767", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWQswQr8fxJG5ieMrayptGV4rvCjDWPCFtfkqm4L6NZbbb", - "publicKey": "dfc9a26dc022bd244c13d62ca88bbe62ca996065bd23224e1f1b77128914d84e" - }, - "ocrKeyBundle": { - "bundleID": "d4566a0c2f256e59733ad2a6dff9f388a1e00b2e65ec1cff7590cb59028888cd", - "configPublicKey": "58db0da621471e616615b8c1c1658ee3b7afbfa64662ce28b38272a95964052c", - "offchainPublicKey": "262fee9de8dd0c8758ba78de8873fdb6705c45ce331bc16ac81dc5b5f0b9680f", - "onchainSigningAddress": "516a9990d3a202b25c2cdd2f6316f4d066543e5d" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x49c36b3BEc6b6e0e77305273FAFC68f479630535", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWQswQr8fxJG5ieMrayptGV4rvCjDWPCFtfkqm4L6NZbbb", - "publicKey": "dfc9a26dc022bd244c13d62ca88bbe62ca996065bd23224e1f1b77128914d84e" - }, - "ocrKeyBundle": { - "bundleID": "d4566a0c2f256e59733ad2a6dff9f388a1e00b2e65ec1cff7590cb59028888cd", - "configPublicKey": "58db0da621471e616615b8c1c1658ee3b7afbfa64662ce28b38272a95964052c", - "offchainPublicKey": "262fee9de8dd0c8758ba78de8873fdb6705c45ce331bc16ac81dc5b5f0b9680f", - "onchainSigningAddress": "516a9990d3a202b25c2cdd2f6316f4d066543e5d" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "OCR3_CAPABILITY", - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T20:30:51.07624Z" - }, - { - "id": "70", - "keys": [ - "keystone-06" - ], - "name": "Chainlink Keystone Node Operator 6", - "metadata": { - "nodeCount": 2, - "jobCount": 4 - }, - "nodes": [ - { - "id": "815", - "name": "Chainlink Sepolia Prod Keystone Cap One 6", - "publicKey": "2669981add3071fae5dfd760fe97e7d2b90157f86b40227f306f1f3906099fc3", - "chainConfigs": [ - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0x405eE4ad3E79786f899810ff6de16a83A920Db5D", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWHB1ucYgRqrocS6t834wL5XaB11JSPgKwzB6QwRPzRayu", - "publicKey": "6d4c18afa813bf7eec73e98a260294bce4b0b26eb9f6efceb2c9402eead56c98" - }, - "ocrKeyBundle": { - "bundleID": "d55283594d4e2c3e507f81ea9ad96261ebec1b1e8579bb1392ca22f7dc9b471b", - "configPublicKey": "32d5b6d38147fa23ec1dc4eeb240e2e70ea768b9a5182676075acd5a2ab2794c", - "offchainPublicKey": "9922cb5c0ae08f0b917979593824bde7ddad0935950e2835914acc34f6cd62f3", - "onchainSigningAddress": "bca900017893ea1366c110941d698d078c2b93ca" - }, - "plugins": {} - } - }, - { - "network": { - "id": "10", - "chainID": "43113", - "chainType": "EVM", - "name": "Avalanche Testnet (Fuji)" - }, - "accountAddress": "0x58D39d629ae9f904b0Ae509179b9e7c9B0184cee", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWHB1ucYgRqrocS6t834wL5XaB11JSPgKwzB6QwRPzRayu", - "publicKey": "6d4c18afa813bf7eec73e98a260294bce4b0b26eb9f6efceb2c9402eead56c98" - }, - "ocrKeyBundle": { - "bundleID": "d55283594d4e2c3e507f81ea9ad96261ebec1b1e8579bb1392ca22f7dc9b471b", - "configPublicKey": "32d5b6d38147fa23ec1dc4eeb240e2e70ea768b9a5182676075acd5a2ab2794c", - "offchainPublicKey": "9922cb5c0ae08f0b917979593824bde7ddad0935950e2835914acc34f6cd62f3", - "onchainSigningAddress": "bca900017893ea1366c110941d698d078c2b93ca" - }, - "plugins": {} - } - }, - { - "network": { - "id": "147", - "chainID": "84532", - "chainType": "EVM", - "name": "Base Testnet (Sepolia)" - }, - "accountAddress": "0x34bFe10F4f4e1101b019639ABd5E5eE5186B80E6", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWHB1ucYgRqrocS6t834wL5XaB11JSPgKwzB6QwRPzRayu", - "publicKey": "6d4c18afa813bf7eec73e98a260294bce4b0b26eb9f6efceb2c9402eead56c98" - }, - "ocrKeyBundle": { - "bundleID": "d55283594d4e2c3e507f81ea9ad96261ebec1b1e8579bb1392ca22f7dc9b471b", - "configPublicKey": "32d5b6d38147fa23ec1dc4eeb240e2e70ea768b9a5182676075acd5a2ab2794c", - "offchainPublicKey": "9922cb5c0ae08f0b917979593824bde7ddad0935950e2835914acc34f6cd62f3", - "onchainSigningAddress": "bca900017893ea1366c110941d698d078c2b93ca" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x1741EB7468A490b4A9BA6f4CC7A47B82EcD65c4c", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWHB1ucYgRqrocS6t834wL5XaB11JSPgKwzB6QwRPzRayu", - "publicKey": "6d4c18afa813bf7eec73e98a260294bce4b0b26eb9f6efceb2c9402eead56c98" - }, - "ocrKeyBundle": { - "bundleID": "d55283594d4e2c3e507f81ea9ad96261ebec1b1e8579bb1392ca22f7dc9b471b", - "configPublicKey": "32d5b6d38147fa23ec1dc4eeb240e2e70ea768b9a5182676075acd5a2ab2794c", - "offchainPublicKey": "9922cb5c0ae08f0b917979593824bde7ddad0935950e2835914acc34f6cd62f3", - "onchainSigningAddress": "bca900017893ea1366c110941d698d078c2b93ca" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "OCR3_CAPABILITY", - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T20:32:14.024795Z" - }, - { - "id": "71", - "keys": [ - "keystone-05" - ], - "name": "Chainlink Keystone Node Operator 5", - "metadata": { - "nodeCount": 2, - "jobCount": 4 - }, - "nodes": [ - { - "id": "814", - "name": "Chainlink Sepolia Prod Keystone Cap One 5", - "publicKey": "94e9ee398547f1564b8b5f72c6148e511919ed0e59b94ae848d63685108f2ab4", - "chainConfigs": [ - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0xbd1ee3165178D3A3E38458a9Fb1d6BF7fb5C443e", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWCiwWc97Q3Z9YUGZcAf46TMLg1uMvrEDa4gT6HZUFFCB1", - "publicKey": "2b2f46bf3b7ab2f39a7fec18166a6ebbc0a72209e920c33933f9adf07b101cc0" - }, - "ocrKeyBundle": { - "bundleID": "bf1736a09452daa0923f2c680f3fa6362ae652294e80ce72d923b304b0dcbb13", - "configPublicKey": "4ebd2a563c458485d2698d06142daa37ea2bee706b4a1a71c8435f2ec254506a", - "offchainPublicKey": "8577b96b270b36e74eb5d411caa14353cdadea599d6d6aa9cccf534ce31f1ef5", - "onchainSigningAddress": "b6727a31772b71d15e3120bfd618545292e1f9df" - }, - "plugins": {} - } - }, - { - "network": { - "id": "10", - "chainID": "43113", - "chainType": "EVM", - "name": "Avalanche Testnet (Fuji)" - }, - "accountAddress": "0x9b6284B5775E46fB02C1a589596EF07c35b55377", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWCiwWc97Q3Z9YUGZcAf46TMLg1uMvrEDa4gT6HZUFFCB1", - "publicKey": "2b2f46bf3b7ab2f39a7fec18166a6ebbc0a72209e920c33933f9adf07b101cc0" - }, - "ocrKeyBundle": { - "bundleID": "bf1736a09452daa0923f2c680f3fa6362ae652294e80ce72d923b304b0dcbb13", - "configPublicKey": "4ebd2a563c458485d2698d06142daa37ea2bee706b4a1a71c8435f2ec254506a", - "offchainPublicKey": "8577b96b270b36e74eb5d411caa14353cdadea599d6d6aa9cccf534ce31f1ef5", - "onchainSigningAddress": "b6727a31772b71d15e3120bfd618545292e1f9df" - }, - "plugins": {} - } - }, - { - "network": { - "id": "147", - "chainID": "84532", - "chainType": "EVM", - "name": "Base Testnet (Sepolia)" - }, - "accountAddress": "0xD83DCED517E4df64e913B97b3d0A906e4CA63d43", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWCiwWc97Q3Z9YUGZcAf46TMLg1uMvrEDa4gT6HZUFFCB1", - "publicKey": "2b2f46bf3b7ab2f39a7fec18166a6ebbc0a72209e920c33933f9adf07b101cc0" - }, - "ocrKeyBundle": { - "bundleID": "bf1736a09452daa0923f2c680f3fa6362ae652294e80ce72d923b304b0dcbb13", - "configPublicKey": "4ebd2a563c458485d2698d06142daa37ea2bee706b4a1a71c8435f2ec254506a", - "offchainPublicKey": "8577b96b270b36e74eb5d411caa14353cdadea599d6d6aa9cccf534ce31f1ef5", - "onchainSigningAddress": "b6727a31772b71d15e3120bfd618545292e1f9df" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0xFF1218066b4b5Cd9dE2A73639862082bcC98bf0D", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWCiwWc97Q3Z9YUGZcAf46TMLg1uMvrEDa4gT6HZUFFCB1", - "publicKey": "2b2f46bf3b7ab2f39a7fec18166a6ebbc0a72209e920c33933f9adf07b101cc0" - }, - "ocrKeyBundle": { - "bundleID": "bf1736a09452daa0923f2c680f3fa6362ae652294e80ce72d923b304b0dcbb13", - "configPublicKey": "4ebd2a563c458485d2698d06142daa37ea2bee706b4a1a71c8435f2ec254506a", - "offchainPublicKey": "8577b96b270b36e74eb5d411caa14353cdadea599d6d6aa9cccf534ce31f1ef5", - "onchainSigningAddress": "b6727a31772b71d15e3120bfd618545292e1f9df" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "OCR3_CAPABILITY", - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T20:38:35.588611Z" - }, - { - "id": "72", - "keys": [ - "keystone-04" - ], - "name": "Chainlink Keystone Node Operator 4", - "metadata": { - "nodeCount": 2, - "jobCount": 4 - }, - "nodes": [ - { - "id": "813", - "name": "Chainlink Sepolia Prod Keystone Cap One 4", - "publicKey": "a618fe2d3260151957d105d2dd593dddaad20c45dc6ae8eab265504e6585a02c", - "chainConfigs": [ - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0xE73E4D047DA32De40C7008075aEb9F60C8AF3C90", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWPMfQRpMy3wYzSMe3BLS8GFuC3fauk7FhTtgfbtp6T6jT", - "publicKey": "c92c6c81f3dff17c05577b9f87177d735d797a3ceedc0fa1395682dfbb66a8d2" - }, - "ocrKeyBundle": { - "bundleID": "fbcfd8420c2ebc450c81fcf72c6673fdd786702c881467e69817c20350bf819b", - "configPublicKey": "282a47a24fd976134f25a99f6370e072f228098010d2594d849d0a4c2788f878", - "offchainPublicKey": "1a7902a01e27818cda034637fdce603a265bc380934324b6f48cf23873234ec6", - "onchainSigningAddress": "7e799378dda3dcdc503233735f09150f0684be19" - }, - "plugins": {} - } - }, - { - "network": { - "id": "10", - "chainID": "43113", - "chainType": "EVM", - "name": "Avalanche Testnet (Fuji)" - }, - "accountAddress": "0x7501ff3462fd2133f2E1F93DB7Ec514988B43E56", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWPMfQRpMy3wYzSMe3BLS8GFuC3fauk7FhTtgfbtp6T6jT", - "publicKey": "c92c6c81f3dff17c05577b9f87177d735d797a3ceedc0fa1395682dfbb66a8d2" - }, - "ocrKeyBundle": { - "bundleID": "fbcfd8420c2ebc450c81fcf72c6673fdd786702c881467e69817c20350bf819b", - "configPublicKey": "282a47a24fd976134f25a99f6370e072f228098010d2594d849d0a4c2788f878", - "offchainPublicKey": "1a7902a01e27818cda034637fdce603a265bc380934324b6f48cf23873234ec6", - "onchainSigningAddress": "7e799378dda3dcdc503233735f09150f0684be19" - }, - "plugins": {} - } - }, - { - "network": { - "id": "147", - "chainID": "84532", - "chainType": "EVM", - "name": "Base Testnet (Sepolia)" - }, - "accountAddress": "0xef080765890a3F697C4920609621fe301Dd34A70", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWPMfQRpMy3wYzSMe3BLS8GFuC3fauk7FhTtgfbtp6T6jT", - "publicKey": "c92c6c81f3dff17c05577b9f87177d735d797a3ceedc0fa1395682dfbb66a8d2" - }, - "ocrKeyBundle": { - "bundleID": "fbcfd8420c2ebc450c81fcf72c6673fdd786702c881467e69817c20350bf819b", - "configPublicKey": "282a47a24fd976134f25a99f6370e072f228098010d2594d849d0a4c2788f878", - "offchainPublicKey": "1a7902a01e27818cda034637fdce603a265bc380934324b6f48cf23873234ec6", - "onchainSigningAddress": "7e799378dda3dcdc503233735f09150f0684be19" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x860235D5Db42eF568665900BBD6bA3DB2fA4f33f", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWPMfQRpMy3wYzSMe3BLS8GFuC3fauk7FhTtgfbtp6T6jT", - "publicKey": "c92c6c81f3dff17c05577b9f87177d735d797a3ceedc0fa1395682dfbb66a8d2" - }, - "ocrKeyBundle": { - "bundleID": "fbcfd8420c2ebc450c81fcf72c6673fdd786702c881467e69817c20350bf819b", - "configPublicKey": "282a47a24fd976134f25a99f6370e072f228098010d2594d849d0a4c2788f878", - "offchainPublicKey": "1a7902a01e27818cda034637fdce603a265bc380934324b6f48cf23873234ec6", - "onchainSigningAddress": "7e799378dda3dcdc503233735f09150f0684be19" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "OCR3_CAPABILITY", - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T20:39:26.24249Z" - }, - { - "id": "73", - "keys": [ - "keystone-03", - "keystone-bt-03" - ], - "name": "Chainlink Keystone Node Operator 3", - "metadata": { - "nodeCount": 3, - "jobCount": 5 - }, - "nodes": [ - { - "id": "812", - "name": "Chainlink Sepolia Prod Keystone Cap One 3", - "publicKey": "f4cf97438c3ad86003e5c0368ab52c70f7fbb7f39ae0d7bf6dacbe16807e8a36", - "chainConfigs": [ - { - "network": { - "id": "147", - "chainID": "84532", - "chainType": "EVM", - "name": "Base Testnet (Sepolia)" - }, - "accountAddress": "0x646665317aF70313B3E83Ea1369A91de389DaCAe", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWAvLkcnc8Zttykk6gGeTWFiT6TqgovRHnb6Ym6QqjnLVM", - "publicKey": "1063921b717c3e32210d2803fe684cd818ea2a4a96e405373e5786c8a13c7600" - }, - "ocrKeyBundle": { - "bundleID": "5b46ab201ba66bd93bae6f41afc59c2e578e0f5682fbdf76e1b647fde6d6e8dd", - "configPublicKey": "a01d7d13f3e67ff84ff208cc44c923fe245d02d6029c91dc38422ef44f2bb26e", - "offchainPublicKey": "64eded06a47efc5e311799c1e1fa833cf78d17f079b2f6019c3247debe490439", - "onchainSigningAddress": "afca74e3b850a9435b2dc479ca8bc8e1b45dd0b2" - }, - "plugins": {} - } - }, - { - "network": { - "id": "10", - "chainID": "43113", - "chainType": "EVM", - "name": "Avalanche Testnet (Fuji)" - }, - "accountAddress": "0x3Ab2A4e4765A0374F727a9a9eCE893734e2928ec", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWAvLkcnc8Zttykk6gGeTWFiT6TqgovRHnb6Ym6QqjnLVM", - "publicKey": "1063921b717c3e32210d2803fe684cd818ea2a4a96e405373e5786c8a13c7600" - }, - "ocrKeyBundle": { - "bundleID": "5b46ab201ba66bd93bae6f41afc59c2e578e0f5682fbdf76e1b647fde6d6e8dd", - "configPublicKey": "a01d7d13f3e67ff84ff208cc44c923fe245d02d6029c91dc38422ef44f2bb26e", - "offchainPublicKey": "64eded06a47efc5e311799c1e1fa833cf78d17f079b2f6019c3247debe490439", - "onchainSigningAddress": "afca74e3b850a9435b2dc479ca8bc8e1b45dd0b2" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x9905E8C3A4f82037170a8c411CD8b11D4894066f", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWAvLkcnc8Zttykk6gGeTWFiT6TqgovRHnb6Ym6QqjnLVM", - "publicKey": "1063921b717c3e32210d2803fe684cd818ea2a4a96e405373e5786c8a13c7600" - }, - "ocrKeyBundle": { - "bundleID": "5b46ab201ba66bd93bae6f41afc59c2e578e0f5682fbdf76e1b647fde6d6e8dd", - "configPublicKey": "a01d7d13f3e67ff84ff208cc44c923fe245d02d6029c91dc38422ef44f2bb26e", - "offchainPublicKey": "64eded06a47efc5e311799c1e1fa833cf78d17f079b2f6019c3247debe490439", - "onchainSigningAddress": "afca74e3b850a9435b2dc479ca8bc8e1b45dd0b2" - }, - "plugins": {} - } - }, - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0x762354eC86ea2253F5da27FF8b952Cb7Dec52B6D", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWAvLkcnc8Zttykk6gGeTWFiT6TqgovRHnb6Ym6QqjnLVM", - "publicKey": "1063921b717c3e32210d2803fe684cd818ea2a4a96e405373e5786c8a13c7600" - }, - "ocrKeyBundle": { - "bundleID": "5b46ab201ba66bd93bae6f41afc59c2e578e0f5682fbdf76e1b647fde6d6e8dd", - "configPublicKey": "a01d7d13f3e67ff84ff208cc44c923fe245d02d6029c91dc38422ef44f2bb26e", - "offchainPublicKey": "64eded06a47efc5e311799c1e1fa833cf78d17f079b2f6019c3247debe490439", - "onchainSigningAddress": "afca74e3b850a9435b2dc479ca8bc8e1b45dd0b2" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "OCR3_CAPABILITY", - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T20:40:30.499914Z" - }, - { - "id": "74", - "keys": [ - "keystone-02", - "keystone-bt-02" - ], - "name": "Chainlink Keystone Node Operator 2", - "metadata": { - "nodeCount": 3, - "jobCount": 5 - }, - "nodes": [ - { - "id": "811", - "name": "Chainlink Sepolia Prod Keystone Cap One 2", - "publicKey": "a1f112923513f13ede1ca8f982ea0ab6221d584b40cd57f0c82307ab79c0e69f", - "chainConfigs": [ - { - "network": { - "id": "10", - "chainID": "43113", - "chainType": "EVM", - "name": "Avalanche Testnet (Fuji)" - }, - "accountAddress": "0xbF1Ad47D99A65e230235537b47C8D1Dddb22FD53", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWQhLYuAxx4WDKafnuhZUTix8Y24gtB92vEUpAC4EdH4VA", - "publicKey": "dd1268a3e7ed4b9c83b1227e5bf2558e6b77af585c66e88a06f1164a1a94f8ed" - }, - "ocrKeyBundle": { - "bundleID": "a11d9438035564bfe84fcfb513b579edbe173fa26c00331e71a010d00b856037", - "configPublicKey": "407cab2a04fa868f645c6848a53abdb8136b08441c50b191651c4f1a348ee700", - "offchainPublicKey": "64a3215839e5630f12ae66b4363f40d82e9c981118c304ca0c4ca5fc2c6e1f37", - "onchainSigningAddress": "6579d77791ee8f8116495dbe6fa6586980177230" - }, - "plugins": {} - } - }, - { - "network": { - "id": "147", - "chainID": "84532", - "chainType": "EVM", - "name": "Base Testnet (Sepolia)" - }, - "accountAddress": "0xa8d4698f74a0A427c1b8ec4575d9dFdD17Be288c", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWQhLYuAxx4WDKafnuhZUTix8Y24gtB92vEUpAC4EdH4VA", - "publicKey": "dd1268a3e7ed4b9c83b1227e5bf2558e6b77af585c66e88a06f1164a1a94f8ed" - }, - "ocrKeyBundle": { - "bundleID": "a11d9438035564bfe84fcfb513b579edbe173fa26c00331e71a010d00b856037", - "configPublicKey": "407cab2a04fa868f645c6848a53abdb8136b08441c50b191651c4f1a348ee700", - "offchainPublicKey": "64a3215839e5630f12ae66b4363f40d82e9c981118c304ca0c4ca5fc2c6e1f37", - "onchainSigningAddress": "6579d77791ee8f8116495dbe6fa6586980177230" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0xf286c79b4a613a1fE480C8e4fB17B837E7D8ba03", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWQhLYuAxx4WDKafnuhZUTix8Y24gtB92vEUpAC4EdH4VA", - "publicKey": "dd1268a3e7ed4b9c83b1227e5bf2558e6b77af585c66e88a06f1164a1a94f8ed" - }, - "ocrKeyBundle": { - "bundleID": "a11d9438035564bfe84fcfb513b579edbe173fa26c00331e71a010d00b856037", - "configPublicKey": "407cab2a04fa868f645c6848a53abdb8136b08441c50b191651c4f1a348ee700", - "offchainPublicKey": "64a3215839e5630f12ae66b4363f40d82e9c981118c304ca0c4ca5fc2c6e1f37", - "onchainSigningAddress": "6579d77791ee8f8116495dbe6fa6586980177230" - }, - "plugins": {} - } - }, - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0xfe85A25cE2CB58b280CC0316305fC678Bf570f5e", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWQhLYuAxx4WDKafnuhZUTix8Y24gtB92vEUpAC4EdH4VA", - "publicKey": "dd1268a3e7ed4b9c83b1227e5bf2558e6b77af585c66e88a06f1164a1a94f8ed" - }, - "ocrKeyBundle": { - "bundleID": "a11d9438035564bfe84fcfb513b579edbe173fa26c00331e71a010d00b856037", - "configPublicKey": "407cab2a04fa868f645c6848a53abdb8136b08441c50b191651c4f1a348ee700", - "offchainPublicKey": "64a3215839e5630f12ae66b4363f40d82e9c981118c304ca0c4ca5fc2c6e1f37", - "onchainSigningAddress": "6579d77791ee8f8116495dbe6fa6586980177230" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "OCR3_CAPABILITY", - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T20:41:33.205484Z" - }, - { - "id": "75", - "keys": [ - "keystone-01", - "keystone-bt-01" - ], - "name": "Chainlink Keystone Node Operator 1", - "metadata": { - "nodeCount": 3, - "jobCount": 5 - }, - "nodes": [ - { - "id": "810", - "name": "Chainlink Sepolia Prod Keystone Cap One 1", - "publicKey": "9ef27cd1855a0ed6932be33c80d7cd9c178307e5a240dbeb9055946359dc5d7f", - "chainConfigs": [ - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0xBB465BCa1b289269F2a95a36f5B6fD006Af56ede", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWMNg1a7HvNWuHAPMdveWr1J6NNCVBU1Z4w5swzepT5Wvf", - "publicKey": "abb750e04bee21d830c6ce0f08180853466139fc6055c6737614797c0704d59c" - }, - "ocrKeyBundle": { - "bundleID": "0d176a4c2d68c619d237e419c31a030e5b2162ee031baa8ebc8472623da9b067", - "configPublicKey": "43e4dbf80a9c818a7d35c080f61b6f8f9b175fa1217b1d01168140da75322d5c", - "offchainPublicKey": "707db88237aaaaddc22bf0fe914540ea7b8bbfbe5cf88349cabb26e34762237c", - "onchainSigningAddress": "ac08f52ec257ddbb493e7b9e299dd2c166a7f090" - }, - "plugins": {} - } - }, - { - "network": { - "id": "10", - "chainID": "43113", - "chainType": "EVM", - "name": "Avalanche Testnet (Fuji)" - }, - "accountAddress": "0x5e3618cFF8Ab337b3c73c2775d1a2EC65e5abEF0", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWMNg1a7HvNWuHAPMdveWr1J6NNCVBU1Z4w5swzepT5Wvf", - "publicKey": "abb750e04bee21d830c6ce0f08180853466139fc6055c6737614797c0704d59c" - }, - "ocrKeyBundle": { - "bundleID": "0d176a4c2d68c619d237e419c31a030e5b2162ee031baa8ebc8472623da9b067", - "configPublicKey": "43e4dbf80a9c818a7d35c080f61b6f8f9b175fa1217b1d01168140da75322d5c", - "offchainPublicKey": "707db88237aaaaddc22bf0fe914540ea7b8bbfbe5cf88349cabb26e34762237c", - "onchainSigningAddress": "ac08f52ec257ddbb493e7b9e299dd2c166a7f090" - }, - "plugins": {} - } - }, - { - "network": { - "id": "147", - "chainID": "84532", - "chainType": "EVM", - "name": "Base Testnet (Sepolia)" - }, - "accountAddress": "0x1796BbC2AbbAd5660C8a7812b313E1f48A99f1D1", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWMNg1a7HvNWuHAPMdveWr1J6NNCVBU1Z4w5swzepT5Wvf", - "publicKey": "abb750e04bee21d830c6ce0f08180853466139fc6055c6737614797c0704d59c" - }, - "ocrKeyBundle": { - "bundleID": "0d176a4c2d68c619d237e419c31a030e5b2162ee031baa8ebc8472623da9b067", - "configPublicKey": "43e4dbf80a9c818a7d35c080f61b6f8f9b175fa1217b1d01168140da75322d5c", - "offchainPublicKey": "707db88237aaaaddc22bf0fe914540ea7b8bbfbe5cf88349cabb26e34762237c", - "onchainSigningAddress": "ac08f52ec257ddbb493e7b9e299dd2c166a7f090" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0xA2bfAc45e6878fbE04525C23dFbb11fFb224Ea60", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWMNg1a7HvNWuHAPMdveWr1J6NNCVBU1Z4w5swzepT5Wvf", - "publicKey": "abb750e04bee21d830c6ce0f08180853466139fc6055c6737614797c0704d59c" - }, - "ocrKeyBundle": { - "bundleID": "0d176a4c2d68c619d237e419c31a030e5b2162ee031baa8ebc8472623da9b067", - "configPublicKey": "43e4dbf80a9c818a7d35c080f61b6f8f9b175fa1217b1d01168140da75322d5c", - "offchainPublicKey": "707db88237aaaaddc22bf0fe914540ea7b8bbfbe5cf88349cabb26e34762237c", - "onchainSigningAddress": "ac08f52ec257ddbb493e7b9e299dd2c166a7f090" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "OCR3_CAPABILITY", - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T20:42:05.709664Z" - }, - { - "id": "76", - "keys": [ - "keystone-00", - "keystone-bt-00" - ], - "name": "Chainlink Keystone Node Operator 0", - "metadata": { - "nodeCount": 3, - "jobCount": 5 - }, - "nodes": [ - { - "id": "809", - "name": "Chainlink Sepolia Prod Keystone Cap One 0", - "publicKey": "545197637db59b96b22528ff90960b9e7cdcea81c8a5a9f06ae6b728bcba35cb", - "chainConfigs": [ - { - "network": { - "id": "10", - "chainID": "43113", - "chainType": "EVM", - "name": "Avalanche Testnet (Fuji)" - }, - "accountAddress": "0x66a88b0a23D8351e8F5e228eEe8439e65F423842", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWFux8Vvs8CPfUSKitXwQsq81ZBhQYcbKRH5L5jkFbQ6nH", - "publicKey": "5a946cfec8e3c33f6c88961dcab2bbd8bb9d05538c8f931bb62d59b1d7fd782e" - }, - "ocrKeyBundle": { - "bundleID": "d9a3c3afdb310ba11b058afd6ee3159edfbc740df4daefd65c257a7ed46ed9ef", - "configPublicKey": "64fd95e7bcbb33e3dd548247352bb7be5ea6577a840e5e3b66336f710b5b272e", - "offchainPublicKey": "216b1e3dc51ad21be806c010397cc2e0bf59b2a06ade89bc7d0c0a7299a4e01e", - "onchainSigningAddress": "a4f0acbe902443aa842db278f421da99cdc47a8b" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x36a46774A3743641D4C274b385608Cb455B5B6b8", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWFux8Vvs8CPfUSKitXwQsq81ZBhQYcbKRH5L5jkFbQ6nH", - "publicKey": "5a946cfec8e3c33f6c88961dcab2bbd8bb9d05538c8f931bb62d59b1d7fd782e" - }, - "ocrKeyBundle": { - "bundleID": "d9a3c3afdb310ba11b058afd6ee3159edfbc740df4daefd65c257a7ed46ed9ef", - "configPublicKey": "64fd95e7bcbb33e3dd548247352bb7be5ea6577a840e5e3b66336f710b5b272e", - "offchainPublicKey": "216b1e3dc51ad21be806c010397cc2e0bf59b2a06ade89bc7d0c0a7299a4e01e", - "onchainSigningAddress": "a4f0acbe902443aa842db278f421da99cdc47a8b" - }, - "plugins": {} - } - }, - { - "network": { - "id": "147", - "chainID": "84532", - "chainType": "EVM", - "name": "Base Testnet (Sepolia)" - }, - "accountAddress": "0x868ab67c00fF7e21aFf470C066798e5bE4240305", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWFux8Vvs8CPfUSKitXwQsq81ZBhQYcbKRH5L5jkFbQ6nH", - "publicKey": "5a946cfec8e3c33f6c88961dcab2bbd8bb9d05538c8f931bb62d59b1d7fd782e" - }, - "ocrKeyBundle": { - "bundleID": "d9a3c3afdb310ba11b058afd6ee3159edfbc740df4daefd65c257a7ed46ed9ef", - "configPublicKey": "64fd95e7bcbb33e3dd548247352bb7be5ea6577a840e5e3b66336f710b5b272e", - "offchainPublicKey": "216b1e3dc51ad21be806c010397cc2e0bf59b2a06ade89bc7d0c0a7299a4e01e", - "onchainSigningAddress": "a4f0acbe902443aa842db278f421da99cdc47a8b" - }, - "plugins": {} - } - }, - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0xa60bC482fCfcd12B752541a00555E4e448Bc1d16", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWFux8Vvs8CPfUSKitXwQsq81ZBhQYcbKRH5L5jkFbQ6nH", - "publicKey": "5a946cfec8e3c33f6c88961dcab2bbd8bb9d05538c8f931bb62d59b1d7fd782e" - }, - "ocrKeyBundle": { - "bundleID": "d9a3c3afdb310ba11b058afd6ee3159edfbc740df4daefd65c257a7ed46ed9ef", - "configPublicKey": "64fd95e7bcbb33e3dd548247352bb7be5ea6577a840e5e3b66336f710b5b272e", - "offchainPublicKey": "216b1e3dc51ad21be806c010397cc2e0bf59b2a06ade89bc7d0c0a7299a4e01e", - "onchainSigningAddress": "a4f0acbe902443aa842db278f421da99cdc47a8b" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "OCR3_CAPABILITY", - "DATA_STREAMS_V03" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T20:42:49.446864Z" - } -] diff --git a/deployment/keystone/testdata/ocr3config.json b/deployment/keystone/testdata/ocr3config.json deleted file mode 100644 index 6835a4143f4..00000000000 --- a/deployment/keystone/testdata/ocr3config.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "OracleConfig": { - "MaxQueryLengthBytes": 1000000, - "MaxObservationLengthBytes": 1000000, - "MaxReportLengthBytes": 1000000, - "MaxRequestBatchSize": 1000, - "UniqueReports": true, - - "DeltaProgressMillis": 5000, - "DeltaResendMillis": 5000, - "DeltaInitialMillis": 5000, - "DeltaRoundMillis": 2000, - "DeltaGraceMillis": 500, - "DeltaCertifiedCommitRequestMillis": 1000, - "DeltaStageMillis": 30000, - "MaxRoundsPerEpoch": 10, - "TransmissionSchedule": [1, 1, 1, 1], - - "MaxDurationQueryMillis": 1000, - "MaxDurationObservationMillis": 1000, - "MaxDurationReportMillis": 1000, - "MaxDurationAcceptMillis": 1000, - "MaxDurationTransmitMillis": 1000, - - "MaxFaultyOracles": 1 - } -} diff --git a/deployment/keystone/testdata/workflow_nodes.json b/deployment/keystone/testdata/workflow_nodes.json deleted file mode 100644 index a5cf7de56fd..00000000000 --- a/deployment/keystone/testdata/workflow_nodes.json +++ /dev/null @@ -1,1107 +0,0 @@ - -[ - { - "id": "67", - "keys": [ - "keystone-09" - ], - "name": "Chainlink Keystone Node Operator 9", - "metadata": { - "nodeCount": 2, - "jobCount": 4 - }, - "nodes": [ - { - "id": "780", - "name": "Chainlink Sepolia Prod Keystone One 9", - "publicKey": "412dc6fe48ea4e34baaa77da2e3b032d39b938597b6f3d61fe7ed183a827a431", - "chainConfigs": [ - { - "network": { - "id": "1401", - "chainID": "2", - "chainType": "APTOS", - "name": "APTOS TEST" - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE8TxNr5dM4U", - "publicKey": "147d5cc651819b093cd2fdff9760f0f0f77b7ef7798d9e24fc6a350b7300e5d9" - }, - "ocrKeyBundle": { - "bundleID": "d834cf7c830df7510228b33b138c018ff16b4eecf82273ed3bcd862bbbc046d4", - "configPublicKey": "6a1f37f06833c55ecf46233439ea6179a835bac6f2b2dee725b747c121813149", - "offchainPublicKey": "ff1144bbf648e6f76c58d0ce53a9a2cbe9a284d52db8691a714cac8e3a96b8b4", - "onchainSigningAddress": "4fa557850e4d5c21b3963c97414c1f37792700c4d3b8abdb904b765fd47e39bf" - }, - "plugins": {} - } - }, - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0xbA8E21dFaa0501fCD43146d0b5F21c2B8E0eEdfB", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE8TxNr5dM4U", - "publicKey": "147d5cc651819b093cd2fdff9760f0f0f77b7ef7798d9e24fc6a350b7300e5d9" - }, - "ocrKeyBundle": { - "bundleID": "1c28e76d180d1ed1524e61845fa58a384415de7e51017edf1f8c553e28357772", - "configPublicKey": "09fced0207611ed618bf0759ab128d9797e15b18e46436be1a56a91e4043ec0e", - "offchainPublicKey": "c805572b813a072067eab2087ddbee8aa719090e12890b15c01094f0d3f74a5f", - "onchainSigningAddress": "679296b7c1eb4948efcc87efc550940a182e610c" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x0b04cE574E80Da73191Ec141c0016a54A6404056", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE8TxNr5dM4U", - "publicKey": "147d5cc651819b093cd2fdff9760f0f0f77b7ef7798d9e24fc6a350b7300e5d9" - }, - "ocrKeyBundle": { - "bundleID": "1c28e76d180d1ed1524e61845fa58a384415de7e51017edf1f8c553e28357772", - "configPublicKey": "09fced0207611ed618bf0759ab128d9797e15b18e46436be1a56a91e4043ec0e", - "offchainPublicKey": "c805572b813a072067eab2087ddbee8aa719090e12890b15c01094f0d3f74a5f", - "onchainSigningAddress": "679296b7c1eb4948efcc87efc550940a182e610c" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "WORKFLOW", - "OCR3_CAPABILITY" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T19:00:07.113658Z" - }, - { - "id": "68", - "keys": [ - "keystone-08" - ], - "name": "Chainlink Keystone Node Operator 8", - "metadata": { - "nodeCount": 2, - "jobCount": 4 - }, - "nodes": [ - { - "id": "781", - "name": "Chainlink Sepolia Prod Keystone One 8", - "publicKey": "1141dd1e46797ced9b0fbad49115f18507f6f6e6e3cc86e7e5ba169e58645adc", - "chainConfigs": [ - { - "network": { - "id": "1402", - "chainID": "2", - "chainType": "APTOS", - "name": "APTOS TEST" - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWAUagqMycsro27kFznSQRHbhfCBLx8nKD4ptTiUGDe38c", - "publicKey": "09ca39cd924653c72fbb0e458b629c3efebdad3e29e7cd0b5760754d919ed829" - }, - "ocrKeyBundle": { - "bundleID": "6726df46033038b724a4e6371807b6aa09efc829d0a3f7a5db4fd7df4b69fea7", - "configPublicKey": "0874e6cd5c8e651ab0ff564a474832ed9eaf2c5025b553f908d04921d9777d50", - "offchainPublicKey": "c791d2b9d3562f991af68ab7164a19734d551a9404d91c9571fdcdc5dcb237ca", - "onchainSigningAddress": "bddafb20cc50d89e0ae2f244908c27b1d639615d8186b28c357669de3359f208" - }, - "plugins": {} - } - }, - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0xEa4bC3638660D78Da56f39f6680dCDD0cEAaD2c6", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWAUagqMycsro27kFznSQRHbhfCBLx8nKD4ptTiUGDe38c", - "publicKey": "09ca39cd924653c72fbb0e458b629c3efebdad3e29e7cd0b5760754d919ed829" - }, - "ocrKeyBundle": { - "bundleID": "be0d639de3ae3cbeaa31ca369514f748ba1d271145cba6796bcc12aace2f64c3", - "configPublicKey": "e3d4d7a7372a3b1110db0290ab3649eb5fbb0daf6cf3ae02cfe5f367700d9264", - "offchainPublicKey": "ad08c2a5878cada53521f4e2bb449f191ccca7899246721a0deeea19f7b83f70", - "onchainSigningAddress": "8c2aa1e6fad88a6006dfb116eb866cbad2910314" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x31B179dcF8f9036C30f04bE578793e51bF14A39E", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWAUagqMycsro27kFznSQRHbhfCBLx8nKD4ptTiUGDe38c", - "publicKey": "09ca39cd924653c72fbb0e458b629c3efebdad3e29e7cd0b5760754d919ed829" - }, - "ocrKeyBundle": { - "bundleID": "be0d639de3ae3cbeaa31ca369514f748ba1d271145cba6796bcc12aace2f64c3", - "configPublicKey": "e3d4d7a7372a3b1110db0290ab3649eb5fbb0daf6cf3ae02cfe5f367700d9264", - "offchainPublicKey": "ad08c2a5878cada53521f4e2bb449f191ccca7899246721a0deeea19f7b83f70", - "onchainSigningAddress": "8c2aa1e6fad88a6006dfb116eb866cbad2910314" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "WORKFLOW", - "OCR3_CAPABILITY" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T20:26:37.622463Z" - }, - { - "id": "69", - "keys": [ - "keystone-07" - ], - "name": "Chainlink Keystone Node Operator 7", - "metadata": { - "nodeCount": 2, - "jobCount": 4 - }, - "nodes": [ - { - "id": "782", - "name": "Chainlink Sepolia Prod Keystone One 7", - "publicKey": "b473091fe1d4dbbc26ad71c67b4432f8f4280e06bab5e2122a92f4ab8b6ff2f5", - "chainConfigs": [ - { - "network": { - "id": "1403", - "chainID": "2", - "chainType": "APTOS", - "name": "APTOS TEST" - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWQMCj73V5xmCd6C5VsJr7rbFG2TF9LwVcLiiBqXps9MgC", - "publicKey": "d7e9f2252b09edf0802a65b60bc9956691747894cb3ab9fefd072adf742eb9f1" - }, - "ocrKeyBundle": { - "bundleID": "14082da0f33b4cec842bc1e1002e617a194ed4a81105603bd6c1edf784aa3743", - "configPublicKey": "209eea27e73b0ecc1c49b3ea274e4a18a1f5ed62fd79f443f0b5b9cc6019356e", - "offchainPublicKey": "cf0684a0e59399fe9b92cfc740d9696f925e78ee7d0273947e5f7b830070eaaa", - "onchainSigningAddress": "96dc85670c49caa986de4ad288e680e9afb0f5491160dcbb4868ca718e194fc8" - }, - "plugins": {} - } - }, - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0x65bE4739E187a39b859766C143b569acd5BE234d", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWQMCj73V5xmCd6C5VsJr7rbFG2TF9LwVcLiiBqXps9MgC", - "publicKey": "d7e9f2252b09edf0802a65b60bc9956691747894cb3ab9fefd072adf742eb9f1" - }, - "ocrKeyBundle": { - "bundleID": "e6d6ffec6cff01ac20d57bc42626c8e955293f232d383bf468351d867a7b8213", - "configPublicKey": "4d2f75f98b911c20fe7808384312d8b913e6b7a98c34d05c6e461434c92b4502", - "offchainPublicKey": "01496edce35663071d74472e02119432ba059b3904d205e4358014410e4f2be3", - "onchainSigningAddress": "213803bb9f9715379aaf11aadb0212369701dc0a" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x9ad9f3AD49e5aB0F28bD694d211a90297bD90D7f", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWQMCj73V5xmCd6C5VsJr7rbFG2TF9LwVcLiiBqXps9MgC", - "publicKey": "d7e9f2252b09edf0802a65b60bc9956691747894cb3ab9fefd072adf742eb9f1" - }, - "ocrKeyBundle": { - "bundleID": "e6d6ffec6cff01ac20d57bc42626c8e955293f232d383bf468351d867a7b8213", - "configPublicKey": "4d2f75f98b911c20fe7808384312d8b913e6b7a98c34d05c6e461434c92b4502", - "offchainPublicKey": "01496edce35663071d74472e02119432ba059b3904d205e4358014410e4f2be3", - "onchainSigningAddress": "213803bb9f9715379aaf11aadb0212369701dc0a" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "WORKFLOW", - "OCR3_CAPABILITY" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T20:30:51.07624Z" - }, - { - "id": "70", - "keys": [ - "keystone-06" - ], - "name": "Chainlink Keystone Node Operator 6", - "metadata": { - "nodeCount": 2, - "jobCount": 4 - }, - "nodes": [ - { - "id": "783", - "name": "Chainlink Sepolia Prod Keystone One 6", - "publicKey": "75ac63fc97a31e31168084e0de8ccd2bea90059b609d962f3e43fc296cdba28d", - "chainConfigs": [ - { - "network": { - "id": "1404", - "chainID": "2", - "chainType": "APTOS", - "name": "APTOS TEST" - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWNJ8de3PUURZ2oucrVTpnRTqNBTUYwHLQjK9LzN3E6Mfn", - "publicKey": "b96933429b1a81c811e1195389d7733e936b03e8086e75ea1fa92c61564b6c31" - }, - "ocrKeyBundle": { - "bundleID": "b419e9e3f1256aa2907a1a396bdf27ba5002a30eee440ab96cb60369429ce277", - "configPublicKey": "3ae1a1c713e4ad63f67191fd93620c9eebe44e1d5f3264036ec0fbcd59cf9664", - "offchainPublicKey": "6fc8c3fb55b39577abbab20028bee93d1d6d8a888dd298354b95d4af3ccb6009", - "onchainSigningAddress": "4a94c75cb9fe8b1fba86fd4b71ad130943281fdefad10216c46eb2285d60950f" - }, - "plugins": {} - } - }, - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0x8706E716fc1ee972F3E4D42D42711Aa175Aa654A", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWNJ8de3PUURZ2oucrVTpnRTqNBTUYwHLQjK9LzN3E6Mfn", - "publicKey": "b96933429b1a81c811e1195389d7733e936b03e8086e75ea1fa92c61564b6c31" - }, - "ocrKeyBundle": { - "bundleID": "62d36269d916b4834b17dc6d637c1c39b0895396249a0845764c898e83f63525", - "configPublicKey": "8c6c7d889ac6cc9e663ae48073bbf130fae105d6a3689636db27752e3e3e6816", - "offchainPublicKey": "aa3419628ea3536783742d17d8adf05681aa6a6bd2b206fbde78c7e5aa38586d", - "onchainSigningAddress": "4885973b2fcf061d5cdfb8f74c5139bd3056e9da" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x19e10B063a62B1574AE19020A64fDe6419892dA6", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWNJ8de3PUURZ2oucrVTpnRTqNBTUYwHLQjK9LzN3E6Mfn", - "publicKey": "b96933429b1a81c811e1195389d7733e936b03e8086e75ea1fa92c61564b6c31" - }, - "ocrKeyBundle": { - "bundleID": "62d36269d916b4834b17dc6d637c1c39b0895396249a0845764c898e83f63525", - "configPublicKey": "8c6c7d889ac6cc9e663ae48073bbf130fae105d6a3689636db27752e3e3e6816", - "offchainPublicKey": "aa3419628ea3536783742d17d8adf05681aa6a6bd2b206fbde78c7e5aa38586d", - "onchainSigningAddress": "4885973b2fcf061d5cdfb8f74c5139bd3056e9da" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "WORKFLOW", - "OCR3_CAPABILITY" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T20:32:14.024795Z" - }, - { - "id": "71", - "keys": [ - "keystone-05" - ], - "name": "Chainlink Keystone Node Operator 5", - "metadata": { - "nodeCount": 2, - "jobCount": 4 - }, - "nodes": [ - { - "id": "784", - "name": "Chainlink Sepolia Prod Keystone One 5", - "publicKey": "4542f4fd2ed150c8c976b39802fe3d994aec3ac94fd11e7817f693b1c9a1dabb", - "chainConfigs": [ - { - "network": { - "id": "14005", - "chainID": "2", - "chainType": "APTOS", - "name": "APTOS TEST" - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWR8d5kbZb7YiQWKpT1J1PfMqNaGAmb4jBFx9DWag4hpSZ", - "publicKey": "e38c9f2760db006f070e9cc1bc1c2269ad033751adaa85d022fb760cbc5b5ef6" - }, - "ocrKeyBundle": { - "bundleID": "44b5f46bfbb04d0984469298ec43c350ec6b2cd4556b18265ebac1b6cc329c7c", - "configPublicKey": "263bee0d09d90e0e618c4cdd630d1437f7377f2d544df57f39ddd47984970555", - "offchainPublicKey": "11674b98849d8e070ac69d37c284b3091fcd374913f52b2b83ce2d9a4a4e0213", - "onchainSigningAddress": "425d1354a7b8180252a221040c718cac0ba0251c7efe31a2acefbba578dc2153" - }, - "plugins": {} - } - }, - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0xcea9f5C042130dD35Eff5B5a6E2361A0276570e3", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWR8d5kbZb7YiQWKpT1J1PfMqNaGAmb4jBFx9DWag4hpSZ", - "publicKey": "e38c9f2760db006f070e9cc1bc1c2269ad033751adaa85d022fb760cbc5b5ef6" - }, - "ocrKeyBundle": { - "bundleID": "99fad0362cc8dc8a57a8e616e68133a6d5a8834e08a1b4819710f0e912df5abc", - "configPublicKey": "36de4924cf11938b4461aea1ce99cb640e9603d9a7c294ab6c54acd51d575a49", - "offchainPublicKey": "283471ed66d61fbe11f64eff65d738b59a0301c9a4f846280db26c64c9fdd3f8", - "onchainSigningAddress": "657587eb55cecd6f90b97297b611c3024e488cc0" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0xdAd1F3F8ec690cf335D46c50EdA5547CeF875161", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWR8d5kbZb7YiQWKpT1J1PfMqNaGAmb4jBFx9DWag4hpSZ", - "publicKey": "e38c9f2760db006f070e9cc1bc1c2269ad033751adaa85d022fb760cbc5b5ef6" - }, - "ocrKeyBundle": { - "bundleID": "99fad0362cc8dc8a57a8e616e68133a6d5a8834e08a1b4819710f0e912df5abc", - "configPublicKey": "36de4924cf11938b4461aea1ce99cb640e9603d9a7c294ab6c54acd51d575a49", - "offchainPublicKey": "283471ed66d61fbe11f64eff65d738b59a0301c9a4f846280db26c64c9fdd3f8", - "onchainSigningAddress": "657587eb55cecd6f90b97297b611c3024e488cc0" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "WORKFLOW", - "OCR3_CAPABILITY" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T20:38:35.588611Z" - }, - { - "id": "72", - "keys": [ - "keystone-04" - ], - "name": "Chainlink Keystone Node Operator 4", - "metadata": { - "nodeCount": 2, - "jobCount": 4 - }, - "nodes": [ - { - "id": "785", - "name": "Chainlink Sepolia Prod Keystone One 4", - "publicKey": "07e0ffc57b6263604df517b94bd986169451a3c90600a855bb19212dc575de54", - "chainConfigs": [ - { - "network": { - "id": "1406", - "chainID": "2", - "chainType": "APTOS", - "name": "APTOS TEST" - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWHqR1w26yHatTSZQW3xbRct9SxWzVj9X4SpU916Hy8jYg", - "publicKey": "77224be9d052343b1d17156a1e463625c0d746468d4f5a44cddd452365b1d4ed" - }, - "ocrKeyBundle": { - "bundleID": "b1ab478c1322bc4f8227be50898a8044efc70cf0156ec53cf132119db7e94dea", - "configPublicKey": "96ae354418e50dcd5b3dae62e8f0bc911bbce7f761220837aacdaa6f82bd0f29", - "offchainPublicKey": "b34bb49788541de8b6cfb321799a41927a391a4eb135c74f6cb14eec0531ee6f", - "onchainSigningAddress": "1221e131ef21014a6a99ed22376eb869746a3b5e30fd202cf79e44efaeb8c5c2" - }, - "plugins": {} - } - }, - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0x0be7Df958604166D9Bf0F727F0AC7A4Fb0f5B8a1", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWHqR1w26yHatTSZQW3xbRct9SxWzVj9X4SpU916Hy8jYg", - "publicKey": "77224be9d052343b1d17156a1e463625c0d746468d4f5a44cddd452365b1d4ed" - }, - "ocrKeyBundle": { - "bundleID": "8e563a16ec5a802345b162d0f31149e8d5055014a31847d7b20d6de500aa48bd", - "configPublicKey": "c812eab2415f45cc1d2afdb2be2e3ea419bb7851acfc30c07b4df42c856e8f74", - "offchainPublicKey": "2a4c7dec127fdd8145e48c5edb9467225098bd8c8ad1dade868325b787affbde", - "onchainSigningAddress": "a6f35436cb7bffd615cc47a0a04aa0a78696a144" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x6F5cAb24Fb7412bB516b3468b9F3a9c471d25fE5", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWHqR1w26yHatTSZQW3xbRct9SxWzVj9X4SpU916Hy8jYg", - "publicKey": "77224be9d052343b1d17156a1e463625c0d746468d4f5a44cddd452365b1d4ed" - }, - "ocrKeyBundle": { - "bundleID": "8e563a16ec5a802345b162d0f31149e8d5055014a31847d7b20d6de500aa48bd", - "configPublicKey": "c812eab2415f45cc1d2afdb2be2e3ea419bb7851acfc30c07b4df42c856e8f74", - "offchainPublicKey": "2a4c7dec127fdd8145e48c5edb9467225098bd8c8ad1dade868325b787affbde", - "onchainSigningAddress": "a6f35436cb7bffd615cc47a0a04aa0a78696a144" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "WORKFLOW", - "OCR3_CAPABILITY" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T20:39:26.24249Z" - }, - { - "id": "73", - "keys": [ - "keystone-03", - "keystone-bt-03" - ], - "name": "Chainlink Keystone Node Operator 3", - "metadata": { - "nodeCount": 3, - "jobCount": 5 - }, - "nodes": [ - { - "id": "786", - "name": "Chainlink Sepolia Prod Keystone One 3", - "publicKey": "487901e0c0a9d3c66e7cfc50f3a9e3cdbfdf1b0107273d73d94a91d278545516", - "chainConfigs": [ - { - "network": { - "id": "1417", - "chainID": "2", - "chainType": "APTOS", - "name": "APTOS TEST" - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWCcVLytqinD8xMn27NvomcQhj2mqMVzyGemz6oPwv1SMT", - "publicKey": "298834a041a056df58c839cb53d99b78558693042e54dff238f504f16d18d4b6" - }, - "ocrKeyBundle": { - "bundleID": "5811a96a0c3b5f5b52973eee10e5771cf5953d37d5616ea71f7ae76f09f6e332", - "configPublicKey": "a7f3435bfbaabebd1572142ff1aec9ed98758d9bb098f1fcc77262fcae7f4171", - "offchainPublicKey": "886044b333af681ab4bf3be663122524ece9725e110ac2a64cda8526cad6983e", - "onchainSigningAddress": "046faf34ebfe42510251e6098bc34fa3dd5f2de38ac07e47f2d1b34ac770639f" - }, - "plugins": {} - } - }, - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0x3Be73A57a36E5ab00DcceD755B4bfF8bb99e52b2", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWCcVLytqinD8xMn27NvomcQhj2mqMVzyGemz6oPwv1SMT", - "publicKey": "298834a041a056df58c839cb53d99b78558693042e54dff238f504f16d18d4b6" - }, - "ocrKeyBundle": { - "bundleID": "8843b5db0608f92dac38ca56775766a08db9ee82224a19595d04bd6c58b38fbd", - "configPublicKey": "63375a3d175364bd299e7cecf352cb3e469dd30116cf1418f2b7571fb46c4a4b", - "offchainPublicKey": "b4c4993d6c15fee63800db901a8b35fa419057610962caab1c1d7bed55709127", - "onchainSigningAddress": "6607c140e558631407f33bafbabd103863cee876" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0xA9eFB53c513E413762b2Be5299D161d8E6e7278e", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWCcVLytqinD8xMn27NvomcQhj2mqMVzyGemz6oPwv1SMT", - "publicKey": "298834a041a056df58c839cb53d99b78558693042e54dff238f504f16d18d4b6" - }, - "ocrKeyBundle": { - "bundleID": "8843b5db0608f92dac38ca56775766a08db9ee82224a19595d04bd6c58b38fbd", - "configPublicKey": "63375a3d175364bd299e7cecf352cb3e469dd30116cf1418f2b7571fb46c4a4b", - "offchainPublicKey": "b4c4993d6c15fee63800db901a8b35fa419057610962caab1c1d7bed55709127", - "onchainSigningAddress": "6607c140e558631407f33bafbabd103863cee876" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "WORKFLOW", - "OCR3_CAPABILITY" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T20:40:30.499914Z" - }, - { - "id": "74", - "keys": [ - "keystone-02", - "keystone-bt-02" - ], - "name": "Chainlink Keystone Node Operator 2", - "metadata": { - "nodeCount": 3, - "jobCount": 5 - }, - "nodes": [ - { - "id": "787", - "name": "Chainlink Sepolia Prod Keystone One 2", - "publicKey": "7a166fbc816eb4a4dcb620d11c3ccac5c085d56b1972374100116f87619debb8", - "chainConfigs": [ - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0x693bf95A3ef46E5dABe17d1A89dB1E83948aeD88", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWGDmBKZ7B3PynGrvfHTJMEecpjfHts9YK5NWk8oJuxcAo", - "publicKey": "5f247f61a6d5bfdd1d5064db0bd25fe443648133c6131975edb23481424e3d9c" - }, - "ocrKeyBundle": { - "bundleID": "1d20490fe469dd6af3d418cc310a6e835181fa13e8dc80156bcbe302b7afcd34", - "configPublicKey": "ee466234b3b2f65b13c848b17aa6a8d4e0aa0311d3bf8e77a64f20b04ed48d39", - "offchainPublicKey": "dba3c61e5f8bec594be481bcaf67ecea0d1c2950edb15b158ce3dbc77877def3", - "onchainSigningAddress": "d4dcc573e9d24a8b27a07bba670ba3a2ab36e5bb" - }, - "plugins": {} - } - }, - { - "network": { - "id": "1408", - "chainID": "2", - "chainType": "APTOS", - "name": "APTOS TEST" - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWGDmBKZ7B3PynGrvfHTJMEecpjfHts9YK5NWk8oJuxcAo", - "publicKey": "5f247f61a6d5bfdd1d5064db0bd25fe443648133c6131975edb23481424e3d9c" - }, - "ocrKeyBundle": { - "bundleID": "e57c608a899d80e510913d2c7ef55758ee81e9eb73eb531003af1564307fd133", - "configPublicKey": "412a4bed6b064c17168871d28dbb965cc0a898f7b19eb3fa7cd01d3e3d10b66c", - "offchainPublicKey": "450aa794c87198a595761a8c18f0f1590046c8092960036638d002256af95254", - "onchainSigningAddress": "ba20d3da9b07663f1e8039081a514649fd61a48be2d241bc63537ee47d028fcd" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0xCea84bC1881F3cE14BA13Dc3a00DC1Ff3D553fF0", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWGDmBKZ7B3PynGrvfHTJMEecpjfHts9YK5NWk8oJuxcAo", - "publicKey": "5f247f61a6d5bfdd1d5064db0bd25fe443648133c6131975edb23481424e3d9c" - }, - "ocrKeyBundle": { - "bundleID": "1d20490fe469dd6af3d418cc310a6e835181fa13e8dc80156bcbe302b7afcd34", - "configPublicKey": "ee466234b3b2f65b13c848b17aa6a8d4e0aa0311d3bf8e77a64f20b04ed48d39", - "offchainPublicKey": "dba3c61e5f8bec594be481bcaf67ecea0d1c2950edb15b158ce3dbc77877def3", - "onchainSigningAddress": "d4dcc573e9d24a8b27a07bba670ba3a2ab36e5bb" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "WORKFLOW", - "OCR3_CAPABILITY" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T20:41:33.205484Z" - }, - { - "id": "75", - "keys": [ - "keystone-01", - "keystone-bt-01" - ], - "name": "Chainlink Keystone Node Operator 1", - "metadata": { - "nodeCount": 3, - "jobCount": 5 - }, - "nodes": [ - { - "id": "788", - "name": "Chainlink Sepolia Prod Keystone One 1", - "publicKey": "28b91143ec9111796a7d63e14c1cf6bb01b4ed59667ab54f5bc72ebe49c881be", - "chainConfigs": [ - { - "network": { - "id": "1409", - "chainID": "2", - "chainType": "APTOS", - "name": "APTOS TEST" - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWCbDiL7sP9BVby5KaZqPpaVP1RBokoa9ShzH5WhkYX46v", - "publicKey": "2934f31f278e5c60618f85861bd6add54a4525d79a642019bdc87d75d26372c3" - }, - "ocrKeyBundle": { - "bundleID": "4b6418b8ab88ea1244c3c48eb5f4c86f9f0301aebffcac4fcfac5cdfb7cf6933", - "configPublicKey": "a38dbe521643479d78ab5477cae78161a5de0030c95098e3fbb09add6aca9508", - "offchainPublicKey": "7718dcbf40173dbd876720aa64028a6b18bf9a87543fc83a549515c4937962e3", - "onchainSigningAddress": "247d0189f65f58be83a4e7d87ff338aaf8956e9acb9fcc783f34f9edc29d1b40" - }, - "plugins": {} - } - }, - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0xe45a754B30FdE9852A826F58c6bd94Fa6554CE96", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWCbDiL7sP9BVby5KaZqPpaVP1RBokoa9ShzH5WhkYX46v", - "publicKey": "2934f31f278e5c60618f85861bd6add54a4525d79a642019bdc87d75d26372c3" - }, - "ocrKeyBundle": { - "bundleID": "7a9b75510b8d09932b98142419bef52436ff725dd9395469473b487ef87fdfb0", - "configPublicKey": "2c45fec2320f6bcd36444529a86d9f8b4439499a5d8272dec9bcbbebb5e1bf01", - "offchainPublicKey": "255096a3b7ade10e29c648e0b407fc486180464f713446b1da04f013df6179c8", - "onchainSigningAddress": "8258f4c4761cc445333017608044a204fd0c006a" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x415aa1E9a1bcB3929ed92bFa1F9735Dc0D45AD31", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWCbDiL7sP9BVby5KaZqPpaVP1RBokoa9ShzH5WhkYX46v", - "publicKey": "2934f31f278e5c60618f85861bd6add54a4525d79a642019bdc87d75d26372c3" - }, - "ocrKeyBundle": { - "bundleID": "7a9b75510b8d09932b98142419bef52436ff725dd9395469473b487ef87fdfb0", - "configPublicKey": "2c45fec2320f6bcd36444529a86d9f8b4439499a5d8272dec9bcbbebb5e1bf01", - "offchainPublicKey": "255096a3b7ade10e29c648e0b407fc486180464f713446b1da04f013df6179c8", - "onchainSigningAddress": "8258f4c4761cc445333017608044a204fd0c006a" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "WORKFLOW", - "OCR3_CAPABILITY" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T20:42:05.709664Z" - }, - { - "id": "76", - "keys": [ - "keystone-00", - "keystone-bt-00" - ], - "name": "Chainlink Keystone Node Operator 0", - "metadata": { - "nodeCount": 3, - "jobCount": 5 - }, - "nodes": [ - { - "id": "789", - "name": "Chainlink Sepolia Prod Keystone One 0", - "publicKey": "403b72f0b1b3b5f5a91bcfedb7f28599767502a04b5b7e067fcf3782e23eeb9c", - "chainConfigs": [ - { - "network": { - "id": "1411", - "chainID": "2", - "chainType": "APTOS", - "name": "APTOS TEST" - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWMWUKdoAc2ruZf9f55p7NVFj7AFiPm67xjQ8BZBwkqyYv", - "publicKey": "adb6bf005cdb23f21e11b82d66b9f62628c2939640ed93028bf0dad3923c5a8b" - }, - "ocrKeyBundle": { - "bundleID": "b4504e84ea307cc2afffca0206bd4bf8e98acc5a03c9bd47b2456e3845a5d1fa", - "configPublicKey": "559ea4ee5774a31d97914a4220d6a47094ae8e2cf0806e80e1eacd851f3e6757", - "offchainPublicKey": "4ec55bbe76a6b1fdc885c59da85a8fe44cf06afe1e4719f0824a731937526c52", - "onchainSigningAddress": "b8834eaa062f0df4ccfe7832253920071ec14dc4f78b13ecdda10b824e2dd3b6" - }, - "plugins": {} - } - }, - { - "network": { - "id": "140", - "chainID": "421614", - "chainType": "EVM", - "name": "Arbitrum Testnet (Sepolia)" - }, - "accountAddress": "0x1a04C6b4b1A45D20356F93DcE7931F765955BAa7", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWMWUKdoAc2ruZf9f55p7NVFj7AFiPm67xjQ8BZBwkqyYv", - "publicKey": "adb6bf005cdb23f21e11b82d66b9f62628c2939640ed93028bf0dad3923c5a8b" - }, - "ocrKeyBundle": { - "bundleID": "665a101d79d310cb0a5ebf695b06e8fc8082b5cbe62d7d362d80d47447a31fea", - "configPublicKey": "5193f72fc7b4323a86088fb0acb4e4494ae351920b3944bd726a59e8dbcdd45f", - "offchainPublicKey": "03dacd15fc96c965c648e3623180de002b71a97cf6eeca9affb91f461dcd6ce1", - "onchainSigningAddress": "b35409a8d4f9a18da55c5b2bb08a3f5f68d44442" - }, - "plugins": {} - } - }, - { - "network": { - "id": "129", - "chainID": "11155111", - "chainType": "EVM", - "name": "Ethereum Testnet (Sepolia)" - }, - "accountAddress": "0x2877F08d9c5Cc9F401F730Fa418fAE563A9a2FF3", - "adminAddress": "0x0000000000000000000000000000000000000000", - "ocr1Config": { - "p2pKeyBundle": {}, - "ocrKeyBundle": {} - }, - "ocr2Config": { - "enabled": true, - "p2pKeyBundle": { - "peerID": "p2p_12D3KooWMWUKdoAc2ruZf9f55p7NVFj7AFiPm67xjQ8BZBwkqyYv", - "publicKey": "adb6bf005cdb23f21e11b82d66b9f62628c2939640ed93028bf0dad3923c5a8b" - }, - "ocrKeyBundle": { - "bundleID": "665a101d79d310cb0a5ebf695b06e8fc8082b5cbe62d7d362d80d47447a31fea", - "configPublicKey": "5193f72fc7b4323a86088fb0acb4e4494ae351920b3944bd726a59e8dbcdd45f", - "offchainPublicKey": "03dacd15fc96c965c648e3623180de002b71a97cf6eeca9affb91f461dcd6ce1", - "onchainSigningAddress": "b35409a8d4f9a18da55c5b2bb08a3f5f68d44442" - }, - "plugins": {} - } - } - ], - "connected": true, - "supportedProducts": [ - "WORKFLOW", - "OCR3_CAPABILITY" - ], - "categories": [ - { - "id": "11", - "name": "Keystone" - } - ] - } - ], - "createdAt": "2024-08-14T20:42:49.446864Z" - } -] diff --git a/deployment/mocks/offchain_client_mock.go b/deployment/mocks/offchain_client_mock.go new file mode 100644 index 00000000000..f760cd1fda3 --- /dev/null +++ b/deployment/mocks/offchain_client_mock.go @@ -0,0 +1,1375 @@ +// Code generated by mockery v2.50.0. DO NOT EDIT. + +package deployment + +import ( + context "context" + + csa "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/csa" + grpc "google.golang.org/grpc" + + job "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" + + mock "github.com/stretchr/testify/mock" + + node "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" +) + +// MockOffchainClient is an autogenerated mock type for the OffchainClient type +type MockOffchainClient struct { + mock.Mock +} + +type MockOffchainClient_Expecter struct { + mock *mock.Mock +} + +func (_m *MockOffchainClient) EXPECT() *MockOffchainClient_Expecter { + return &MockOffchainClient_Expecter{mock: &_m.Mock} +} + +// BatchProposeJob provides a mock function with given fields: ctx, in, opts +func (_m *MockOffchainClient) BatchProposeJob(ctx context.Context, in *job.BatchProposeJobRequest, opts ...grpc.CallOption) (*job.BatchProposeJobResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for BatchProposeJob") + } + + var r0 *job.BatchProposeJobResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *job.BatchProposeJobRequest, ...grpc.CallOption) (*job.BatchProposeJobResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *job.BatchProposeJobRequest, ...grpc.CallOption) *job.BatchProposeJobResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*job.BatchProposeJobResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *job.BatchProposeJobRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockOffchainClient_BatchProposeJob_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BatchProposeJob' +type MockOffchainClient_BatchProposeJob_Call struct { + *mock.Call +} + +// BatchProposeJob is a helper method to define mock.On call +// - ctx context.Context +// - in *job.BatchProposeJobRequest +// - opts ...grpc.CallOption +func (_e *MockOffchainClient_Expecter) BatchProposeJob(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_BatchProposeJob_Call { + return &MockOffchainClient_BatchProposeJob_Call{Call: _e.mock.On("BatchProposeJob", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *MockOffchainClient_BatchProposeJob_Call) Run(run func(ctx context.Context, in *job.BatchProposeJobRequest, opts ...grpc.CallOption)) *MockOffchainClient_BatchProposeJob_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*job.BatchProposeJobRequest), variadicArgs...) + }) + return _c +} + +func (_c *MockOffchainClient_BatchProposeJob_Call) Return(_a0 *job.BatchProposeJobResponse, _a1 error) *MockOffchainClient_BatchProposeJob_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockOffchainClient_BatchProposeJob_Call) RunAndReturn(run func(context.Context, *job.BatchProposeJobRequest, ...grpc.CallOption) (*job.BatchProposeJobResponse, error)) *MockOffchainClient_BatchProposeJob_Call { + _c.Call.Return(run) + return _c +} + +// DeleteJob provides a mock function with given fields: ctx, in, opts +func (_m *MockOffchainClient) DeleteJob(ctx context.Context, in *job.DeleteJobRequest, opts ...grpc.CallOption) (*job.DeleteJobResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for DeleteJob") + } + + var r0 *job.DeleteJobResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *job.DeleteJobRequest, ...grpc.CallOption) (*job.DeleteJobResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *job.DeleteJobRequest, ...grpc.CallOption) *job.DeleteJobResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*job.DeleteJobResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *job.DeleteJobRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockOffchainClient_DeleteJob_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteJob' +type MockOffchainClient_DeleteJob_Call struct { + *mock.Call +} + +// DeleteJob is a helper method to define mock.On call +// - ctx context.Context +// - in *job.DeleteJobRequest +// - opts ...grpc.CallOption +func (_e *MockOffchainClient_Expecter) DeleteJob(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_DeleteJob_Call { + return &MockOffchainClient_DeleteJob_Call{Call: _e.mock.On("DeleteJob", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *MockOffchainClient_DeleteJob_Call) Run(run func(ctx context.Context, in *job.DeleteJobRequest, opts ...grpc.CallOption)) *MockOffchainClient_DeleteJob_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*job.DeleteJobRequest), variadicArgs...) + }) + return _c +} + +func (_c *MockOffchainClient_DeleteJob_Call) Return(_a0 *job.DeleteJobResponse, _a1 error) *MockOffchainClient_DeleteJob_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockOffchainClient_DeleteJob_Call) RunAndReturn(run func(context.Context, *job.DeleteJobRequest, ...grpc.CallOption) (*job.DeleteJobResponse, error)) *MockOffchainClient_DeleteJob_Call { + _c.Call.Return(run) + return _c +} + +// DisableNode provides a mock function with given fields: ctx, in, opts +func (_m *MockOffchainClient) DisableNode(ctx context.Context, in *node.DisableNodeRequest, opts ...grpc.CallOption) (*node.DisableNodeResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for DisableNode") + } + + var r0 *node.DisableNodeResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *node.DisableNodeRequest, ...grpc.CallOption) (*node.DisableNodeResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *node.DisableNodeRequest, ...grpc.CallOption) *node.DisableNodeResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*node.DisableNodeResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *node.DisableNodeRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockOffchainClient_DisableNode_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DisableNode' +type MockOffchainClient_DisableNode_Call struct { + *mock.Call +} + +// DisableNode is a helper method to define mock.On call +// - ctx context.Context +// - in *node.DisableNodeRequest +// - opts ...grpc.CallOption +func (_e *MockOffchainClient_Expecter) DisableNode(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_DisableNode_Call { + return &MockOffchainClient_DisableNode_Call{Call: _e.mock.On("DisableNode", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *MockOffchainClient_DisableNode_Call) Run(run func(ctx context.Context, in *node.DisableNodeRequest, opts ...grpc.CallOption)) *MockOffchainClient_DisableNode_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*node.DisableNodeRequest), variadicArgs...) + }) + return _c +} + +func (_c *MockOffchainClient_DisableNode_Call) Return(_a0 *node.DisableNodeResponse, _a1 error) *MockOffchainClient_DisableNode_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockOffchainClient_DisableNode_Call) RunAndReturn(run func(context.Context, *node.DisableNodeRequest, ...grpc.CallOption) (*node.DisableNodeResponse, error)) *MockOffchainClient_DisableNode_Call { + _c.Call.Return(run) + return _c +} + +// EnableNode provides a mock function with given fields: ctx, in, opts +func (_m *MockOffchainClient) EnableNode(ctx context.Context, in *node.EnableNodeRequest, opts ...grpc.CallOption) (*node.EnableNodeResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for EnableNode") + } + + var r0 *node.EnableNodeResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *node.EnableNodeRequest, ...grpc.CallOption) (*node.EnableNodeResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *node.EnableNodeRequest, ...grpc.CallOption) *node.EnableNodeResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*node.EnableNodeResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *node.EnableNodeRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockOffchainClient_EnableNode_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EnableNode' +type MockOffchainClient_EnableNode_Call struct { + *mock.Call +} + +// EnableNode is a helper method to define mock.On call +// - ctx context.Context +// - in *node.EnableNodeRequest +// - opts ...grpc.CallOption +func (_e *MockOffchainClient_Expecter) EnableNode(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_EnableNode_Call { + return &MockOffchainClient_EnableNode_Call{Call: _e.mock.On("EnableNode", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *MockOffchainClient_EnableNode_Call) Run(run func(ctx context.Context, in *node.EnableNodeRequest, opts ...grpc.CallOption)) *MockOffchainClient_EnableNode_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*node.EnableNodeRequest), variadicArgs...) + }) + return _c +} + +func (_c *MockOffchainClient_EnableNode_Call) Return(_a0 *node.EnableNodeResponse, _a1 error) *MockOffchainClient_EnableNode_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockOffchainClient_EnableNode_Call) RunAndReturn(run func(context.Context, *node.EnableNodeRequest, ...grpc.CallOption) (*node.EnableNodeResponse, error)) *MockOffchainClient_EnableNode_Call { + _c.Call.Return(run) + return _c +} + +// GetJob provides a mock function with given fields: ctx, in, opts +func (_m *MockOffchainClient) GetJob(ctx context.Context, in *job.GetJobRequest, opts ...grpc.CallOption) (*job.GetJobResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for GetJob") + } + + var r0 *job.GetJobResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *job.GetJobRequest, ...grpc.CallOption) (*job.GetJobResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *job.GetJobRequest, ...grpc.CallOption) *job.GetJobResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*job.GetJobResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *job.GetJobRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockOffchainClient_GetJob_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetJob' +type MockOffchainClient_GetJob_Call struct { + *mock.Call +} + +// GetJob is a helper method to define mock.On call +// - ctx context.Context +// - in *job.GetJobRequest +// - opts ...grpc.CallOption +func (_e *MockOffchainClient_Expecter) GetJob(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_GetJob_Call { + return &MockOffchainClient_GetJob_Call{Call: _e.mock.On("GetJob", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *MockOffchainClient_GetJob_Call) Run(run func(ctx context.Context, in *job.GetJobRequest, opts ...grpc.CallOption)) *MockOffchainClient_GetJob_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*job.GetJobRequest), variadicArgs...) + }) + return _c +} + +func (_c *MockOffchainClient_GetJob_Call) Return(_a0 *job.GetJobResponse, _a1 error) *MockOffchainClient_GetJob_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockOffchainClient_GetJob_Call) RunAndReturn(run func(context.Context, *job.GetJobRequest, ...grpc.CallOption) (*job.GetJobResponse, error)) *MockOffchainClient_GetJob_Call { + _c.Call.Return(run) + return _c +} + +// GetKeypair provides a mock function with given fields: ctx, in, opts +func (_m *MockOffchainClient) GetKeypair(ctx context.Context, in *csa.GetKeypairRequest, opts ...grpc.CallOption) (*csa.GetKeypairResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for GetKeypair") + } + + var r0 *csa.GetKeypairResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *csa.GetKeypairRequest, ...grpc.CallOption) (*csa.GetKeypairResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *csa.GetKeypairRequest, ...grpc.CallOption) *csa.GetKeypairResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*csa.GetKeypairResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *csa.GetKeypairRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockOffchainClient_GetKeypair_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetKeypair' +type MockOffchainClient_GetKeypair_Call struct { + *mock.Call +} + +// GetKeypair is a helper method to define mock.On call +// - ctx context.Context +// - in *csa.GetKeypairRequest +// - opts ...grpc.CallOption +func (_e *MockOffchainClient_Expecter) GetKeypair(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_GetKeypair_Call { + return &MockOffchainClient_GetKeypair_Call{Call: _e.mock.On("GetKeypair", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *MockOffchainClient_GetKeypair_Call) Run(run func(ctx context.Context, in *csa.GetKeypairRequest, opts ...grpc.CallOption)) *MockOffchainClient_GetKeypair_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*csa.GetKeypairRequest), variadicArgs...) + }) + return _c +} + +func (_c *MockOffchainClient_GetKeypair_Call) Return(_a0 *csa.GetKeypairResponse, _a1 error) *MockOffchainClient_GetKeypair_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockOffchainClient_GetKeypair_Call) RunAndReturn(run func(context.Context, *csa.GetKeypairRequest, ...grpc.CallOption) (*csa.GetKeypairResponse, error)) *MockOffchainClient_GetKeypair_Call { + _c.Call.Return(run) + return _c +} + +// GetNode provides a mock function with given fields: ctx, in, opts +func (_m *MockOffchainClient) GetNode(ctx context.Context, in *node.GetNodeRequest, opts ...grpc.CallOption) (*node.GetNodeResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for GetNode") + } + + var r0 *node.GetNodeResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *node.GetNodeRequest, ...grpc.CallOption) (*node.GetNodeResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *node.GetNodeRequest, ...grpc.CallOption) *node.GetNodeResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*node.GetNodeResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *node.GetNodeRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockOffchainClient_GetNode_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetNode' +type MockOffchainClient_GetNode_Call struct { + *mock.Call +} + +// GetNode is a helper method to define mock.On call +// - ctx context.Context +// - in *node.GetNodeRequest +// - opts ...grpc.CallOption +func (_e *MockOffchainClient_Expecter) GetNode(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_GetNode_Call { + return &MockOffchainClient_GetNode_Call{Call: _e.mock.On("GetNode", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *MockOffchainClient_GetNode_Call) Run(run func(ctx context.Context, in *node.GetNodeRequest, opts ...grpc.CallOption)) *MockOffchainClient_GetNode_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*node.GetNodeRequest), variadicArgs...) + }) + return _c +} + +func (_c *MockOffchainClient_GetNode_Call) Return(_a0 *node.GetNodeResponse, _a1 error) *MockOffchainClient_GetNode_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockOffchainClient_GetNode_Call) RunAndReturn(run func(context.Context, *node.GetNodeRequest, ...grpc.CallOption) (*node.GetNodeResponse, error)) *MockOffchainClient_GetNode_Call { + _c.Call.Return(run) + return _c +} + +// GetProposal provides a mock function with given fields: ctx, in, opts +func (_m *MockOffchainClient) GetProposal(ctx context.Context, in *job.GetProposalRequest, opts ...grpc.CallOption) (*job.GetProposalResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for GetProposal") + } + + var r0 *job.GetProposalResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *job.GetProposalRequest, ...grpc.CallOption) (*job.GetProposalResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *job.GetProposalRequest, ...grpc.CallOption) *job.GetProposalResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*job.GetProposalResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *job.GetProposalRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockOffchainClient_GetProposal_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetProposal' +type MockOffchainClient_GetProposal_Call struct { + *mock.Call +} + +// GetProposal is a helper method to define mock.On call +// - ctx context.Context +// - in *job.GetProposalRequest +// - opts ...grpc.CallOption +func (_e *MockOffchainClient_Expecter) GetProposal(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_GetProposal_Call { + return &MockOffchainClient_GetProposal_Call{Call: _e.mock.On("GetProposal", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *MockOffchainClient_GetProposal_Call) Run(run func(ctx context.Context, in *job.GetProposalRequest, opts ...grpc.CallOption)) *MockOffchainClient_GetProposal_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*job.GetProposalRequest), variadicArgs...) + }) + return _c +} + +func (_c *MockOffchainClient_GetProposal_Call) Return(_a0 *job.GetProposalResponse, _a1 error) *MockOffchainClient_GetProposal_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockOffchainClient_GetProposal_Call) RunAndReturn(run func(context.Context, *job.GetProposalRequest, ...grpc.CallOption) (*job.GetProposalResponse, error)) *MockOffchainClient_GetProposal_Call { + _c.Call.Return(run) + return _c +} + +// ListJobs provides a mock function with given fields: ctx, in, opts +func (_m *MockOffchainClient) ListJobs(ctx context.Context, in *job.ListJobsRequest, opts ...grpc.CallOption) (*job.ListJobsResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for ListJobs") + } + + var r0 *job.ListJobsResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *job.ListJobsRequest, ...grpc.CallOption) (*job.ListJobsResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *job.ListJobsRequest, ...grpc.CallOption) *job.ListJobsResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*job.ListJobsResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *job.ListJobsRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockOffchainClient_ListJobs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListJobs' +type MockOffchainClient_ListJobs_Call struct { + *mock.Call +} + +// ListJobs is a helper method to define mock.On call +// - ctx context.Context +// - in *job.ListJobsRequest +// - opts ...grpc.CallOption +func (_e *MockOffchainClient_Expecter) ListJobs(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_ListJobs_Call { + return &MockOffchainClient_ListJobs_Call{Call: _e.mock.On("ListJobs", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *MockOffchainClient_ListJobs_Call) Run(run func(ctx context.Context, in *job.ListJobsRequest, opts ...grpc.CallOption)) *MockOffchainClient_ListJobs_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*job.ListJobsRequest), variadicArgs...) + }) + return _c +} + +func (_c *MockOffchainClient_ListJobs_Call) Return(_a0 *job.ListJobsResponse, _a1 error) *MockOffchainClient_ListJobs_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockOffchainClient_ListJobs_Call) RunAndReturn(run func(context.Context, *job.ListJobsRequest, ...grpc.CallOption) (*job.ListJobsResponse, error)) *MockOffchainClient_ListJobs_Call { + _c.Call.Return(run) + return _c +} + +// ListKeypairs provides a mock function with given fields: ctx, in, opts +func (_m *MockOffchainClient) ListKeypairs(ctx context.Context, in *csa.ListKeypairsRequest, opts ...grpc.CallOption) (*csa.ListKeypairsResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for ListKeypairs") + } + + var r0 *csa.ListKeypairsResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *csa.ListKeypairsRequest, ...grpc.CallOption) (*csa.ListKeypairsResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *csa.ListKeypairsRequest, ...grpc.CallOption) *csa.ListKeypairsResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*csa.ListKeypairsResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *csa.ListKeypairsRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockOffchainClient_ListKeypairs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListKeypairs' +type MockOffchainClient_ListKeypairs_Call struct { + *mock.Call +} + +// ListKeypairs is a helper method to define mock.On call +// - ctx context.Context +// - in *csa.ListKeypairsRequest +// - opts ...grpc.CallOption +func (_e *MockOffchainClient_Expecter) ListKeypairs(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_ListKeypairs_Call { + return &MockOffchainClient_ListKeypairs_Call{Call: _e.mock.On("ListKeypairs", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *MockOffchainClient_ListKeypairs_Call) Run(run func(ctx context.Context, in *csa.ListKeypairsRequest, opts ...grpc.CallOption)) *MockOffchainClient_ListKeypairs_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*csa.ListKeypairsRequest), variadicArgs...) + }) + return _c +} + +func (_c *MockOffchainClient_ListKeypairs_Call) Return(_a0 *csa.ListKeypairsResponse, _a1 error) *MockOffchainClient_ListKeypairs_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockOffchainClient_ListKeypairs_Call) RunAndReturn(run func(context.Context, *csa.ListKeypairsRequest, ...grpc.CallOption) (*csa.ListKeypairsResponse, error)) *MockOffchainClient_ListKeypairs_Call { + _c.Call.Return(run) + return _c +} + +// ListNodeChainConfigs provides a mock function with given fields: ctx, in, opts +func (_m *MockOffchainClient) ListNodeChainConfigs(ctx context.Context, in *node.ListNodeChainConfigsRequest, opts ...grpc.CallOption) (*node.ListNodeChainConfigsResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for ListNodeChainConfigs") + } + + var r0 *node.ListNodeChainConfigsResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *node.ListNodeChainConfigsRequest, ...grpc.CallOption) (*node.ListNodeChainConfigsResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *node.ListNodeChainConfigsRequest, ...grpc.CallOption) *node.ListNodeChainConfigsResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*node.ListNodeChainConfigsResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *node.ListNodeChainConfigsRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockOffchainClient_ListNodeChainConfigs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListNodeChainConfigs' +type MockOffchainClient_ListNodeChainConfigs_Call struct { + *mock.Call +} + +// ListNodeChainConfigs is a helper method to define mock.On call +// - ctx context.Context +// - in *node.ListNodeChainConfigsRequest +// - opts ...grpc.CallOption +func (_e *MockOffchainClient_Expecter) ListNodeChainConfigs(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_ListNodeChainConfigs_Call { + return &MockOffchainClient_ListNodeChainConfigs_Call{Call: _e.mock.On("ListNodeChainConfigs", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *MockOffchainClient_ListNodeChainConfigs_Call) Run(run func(ctx context.Context, in *node.ListNodeChainConfigsRequest, opts ...grpc.CallOption)) *MockOffchainClient_ListNodeChainConfigs_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*node.ListNodeChainConfigsRequest), variadicArgs...) + }) + return _c +} + +func (_c *MockOffchainClient_ListNodeChainConfigs_Call) Return(_a0 *node.ListNodeChainConfigsResponse, _a1 error) *MockOffchainClient_ListNodeChainConfigs_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockOffchainClient_ListNodeChainConfigs_Call) RunAndReturn(run func(context.Context, *node.ListNodeChainConfigsRequest, ...grpc.CallOption) (*node.ListNodeChainConfigsResponse, error)) *MockOffchainClient_ListNodeChainConfigs_Call { + _c.Call.Return(run) + return _c +} + +// ListNodes provides a mock function with given fields: ctx, in, opts +func (_m *MockOffchainClient) ListNodes(ctx context.Context, in *node.ListNodesRequest, opts ...grpc.CallOption) (*node.ListNodesResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for ListNodes") + } + + var r0 *node.ListNodesResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *node.ListNodesRequest, ...grpc.CallOption) (*node.ListNodesResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *node.ListNodesRequest, ...grpc.CallOption) *node.ListNodesResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*node.ListNodesResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *node.ListNodesRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockOffchainClient_ListNodes_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListNodes' +type MockOffchainClient_ListNodes_Call struct { + *mock.Call +} + +// ListNodes is a helper method to define mock.On call +// - ctx context.Context +// - in *node.ListNodesRequest +// - opts ...grpc.CallOption +func (_e *MockOffchainClient_Expecter) ListNodes(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_ListNodes_Call { + return &MockOffchainClient_ListNodes_Call{Call: _e.mock.On("ListNodes", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *MockOffchainClient_ListNodes_Call) Run(run func(ctx context.Context, in *node.ListNodesRequest, opts ...grpc.CallOption)) *MockOffchainClient_ListNodes_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*node.ListNodesRequest), variadicArgs...) + }) + return _c +} + +func (_c *MockOffchainClient_ListNodes_Call) Return(_a0 *node.ListNodesResponse, _a1 error) *MockOffchainClient_ListNodes_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockOffchainClient_ListNodes_Call) RunAndReturn(run func(context.Context, *node.ListNodesRequest, ...grpc.CallOption) (*node.ListNodesResponse, error)) *MockOffchainClient_ListNodes_Call { + _c.Call.Return(run) + return _c +} + +// ListProposals provides a mock function with given fields: ctx, in, opts +func (_m *MockOffchainClient) ListProposals(ctx context.Context, in *job.ListProposalsRequest, opts ...grpc.CallOption) (*job.ListProposalsResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for ListProposals") + } + + var r0 *job.ListProposalsResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *job.ListProposalsRequest, ...grpc.CallOption) (*job.ListProposalsResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *job.ListProposalsRequest, ...grpc.CallOption) *job.ListProposalsResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*job.ListProposalsResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *job.ListProposalsRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockOffchainClient_ListProposals_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListProposals' +type MockOffchainClient_ListProposals_Call struct { + *mock.Call +} + +// ListProposals is a helper method to define mock.On call +// - ctx context.Context +// - in *job.ListProposalsRequest +// - opts ...grpc.CallOption +func (_e *MockOffchainClient_Expecter) ListProposals(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_ListProposals_Call { + return &MockOffchainClient_ListProposals_Call{Call: _e.mock.On("ListProposals", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *MockOffchainClient_ListProposals_Call) Run(run func(ctx context.Context, in *job.ListProposalsRequest, opts ...grpc.CallOption)) *MockOffchainClient_ListProposals_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*job.ListProposalsRequest), variadicArgs...) + }) + return _c +} + +func (_c *MockOffchainClient_ListProposals_Call) Return(_a0 *job.ListProposalsResponse, _a1 error) *MockOffchainClient_ListProposals_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockOffchainClient_ListProposals_Call) RunAndReturn(run func(context.Context, *job.ListProposalsRequest, ...grpc.CallOption) (*job.ListProposalsResponse, error)) *MockOffchainClient_ListProposals_Call { + _c.Call.Return(run) + return _c +} + +// ProposeJob provides a mock function with given fields: ctx, in, opts +func (_m *MockOffchainClient) ProposeJob(ctx context.Context, in *job.ProposeJobRequest, opts ...grpc.CallOption) (*job.ProposeJobResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for ProposeJob") + } + + var r0 *job.ProposeJobResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *job.ProposeJobRequest, ...grpc.CallOption) (*job.ProposeJobResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *job.ProposeJobRequest, ...grpc.CallOption) *job.ProposeJobResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*job.ProposeJobResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *job.ProposeJobRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockOffchainClient_ProposeJob_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ProposeJob' +type MockOffchainClient_ProposeJob_Call struct { + *mock.Call +} + +// ProposeJob is a helper method to define mock.On call +// - ctx context.Context +// - in *job.ProposeJobRequest +// - opts ...grpc.CallOption +func (_e *MockOffchainClient_Expecter) ProposeJob(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_ProposeJob_Call { + return &MockOffchainClient_ProposeJob_Call{Call: _e.mock.On("ProposeJob", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *MockOffchainClient_ProposeJob_Call) Run(run func(ctx context.Context, in *job.ProposeJobRequest, opts ...grpc.CallOption)) *MockOffchainClient_ProposeJob_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*job.ProposeJobRequest), variadicArgs...) + }) + return _c +} + +func (_c *MockOffchainClient_ProposeJob_Call) Return(_a0 *job.ProposeJobResponse, _a1 error) *MockOffchainClient_ProposeJob_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockOffchainClient_ProposeJob_Call) RunAndReturn(run func(context.Context, *job.ProposeJobRequest, ...grpc.CallOption) (*job.ProposeJobResponse, error)) *MockOffchainClient_ProposeJob_Call { + _c.Call.Return(run) + return _c +} + +// RegisterNode provides a mock function with given fields: ctx, in, opts +func (_m *MockOffchainClient) RegisterNode(ctx context.Context, in *node.RegisterNodeRequest, opts ...grpc.CallOption) (*node.RegisterNodeResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for RegisterNode") + } + + var r0 *node.RegisterNodeResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *node.RegisterNodeRequest, ...grpc.CallOption) (*node.RegisterNodeResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *node.RegisterNodeRequest, ...grpc.CallOption) *node.RegisterNodeResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*node.RegisterNodeResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *node.RegisterNodeRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockOffchainClient_RegisterNode_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RegisterNode' +type MockOffchainClient_RegisterNode_Call struct { + *mock.Call +} + +// RegisterNode is a helper method to define mock.On call +// - ctx context.Context +// - in *node.RegisterNodeRequest +// - opts ...grpc.CallOption +func (_e *MockOffchainClient_Expecter) RegisterNode(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_RegisterNode_Call { + return &MockOffchainClient_RegisterNode_Call{Call: _e.mock.On("RegisterNode", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *MockOffchainClient_RegisterNode_Call) Run(run func(ctx context.Context, in *node.RegisterNodeRequest, opts ...grpc.CallOption)) *MockOffchainClient_RegisterNode_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*node.RegisterNodeRequest), variadicArgs...) + }) + return _c +} + +func (_c *MockOffchainClient_RegisterNode_Call) Return(_a0 *node.RegisterNodeResponse, _a1 error) *MockOffchainClient_RegisterNode_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockOffchainClient_RegisterNode_Call) RunAndReturn(run func(context.Context, *node.RegisterNodeRequest, ...grpc.CallOption) (*node.RegisterNodeResponse, error)) *MockOffchainClient_RegisterNode_Call { + _c.Call.Return(run) + return _c +} + +// RevokeJob provides a mock function with given fields: ctx, in, opts +func (_m *MockOffchainClient) RevokeJob(ctx context.Context, in *job.RevokeJobRequest, opts ...grpc.CallOption) (*job.RevokeJobResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for RevokeJob") + } + + var r0 *job.RevokeJobResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *job.RevokeJobRequest, ...grpc.CallOption) (*job.RevokeJobResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *job.RevokeJobRequest, ...grpc.CallOption) *job.RevokeJobResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*job.RevokeJobResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *job.RevokeJobRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockOffchainClient_RevokeJob_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RevokeJob' +type MockOffchainClient_RevokeJob_Call struct { + *mock.Call +} + +// RevokeJob is a helper method to define mock.On call +// - ctx context.Context +// - in *job.RevokeJobRequest +// - opts ...grpc.CallOption +func (_e *MockOffchainClient_Expecter) RevokeJob(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_RevokeJob_Call { + return &MockOffchainClient_RevokeJob_Call{Call: _e.mock.On("RevokeJob", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *MockOffchainClient_RevokeJob_Call) Run(run func(ctx context.Context, in *job.RevokeJobRequest, opts ...grpc.CallOption)) *MockOffchainClient_RevokeJob_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*job.RevokeJobRequest), variadicArgs...) + }) + return _c +} + +func (_c *MockOffchainClient_RevokeJob_Call) Return(_a0 *job.RevokeJobResponse, _a1 error) *MockOffchainClient_RevokeJob_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockOffchainClient_RevokeJob_Call) RunAndReturn(run func(context.Context, *job.RevokeJobRequest, ...grpc.CallOption) (*job.RevokeJobResponse, error)) *MockOffchainClient_RevokeJob_Call { + _c.Call.Return(run) + return _c +} + +// UpdateJob provides a mock function with given fields: ctx, in, opts +func (_m *MockOffchainClient) UpdateJob(ctx context.Context, in *job.UpdateJobRequest, opts ...grpc.CallOption) (*job.UpdateJobResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for UpdateJob") + } + + var r0 *job.UpdateJobResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *job.UpdateJobRequest, ...grpc.CallOption) (*job.UpdateJobResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *job.UpdateJobRequest, ...grpc.CallOption) *job.UpdateJobResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*job.UpdateJobResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *job.UpdateJobRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockOffchainClient_UpdateJob_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateJob' +type MockOffchainClient_UpdateJob_Call struct { + *mock.Call +} + +// UpdateJob is a helper method to define mock.On call +// - ctx context.Context +// - in *job.UpdateJobRequest +// - opts ...grpc.CallOption +func (_e *MockOffchainClient_Expecter) UpdateJob(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_UpdateJob_Call { + return &MockOffchainClient_UpdateJob_Call{Call: _e.mock.On("UpdateJob", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *MockOffchainClient_UpdateJob_Call) Run(run func(ctx context.Context, in *job.UpdateJobRequest, opts ...grpc.CallOption)) *MockOffchainClient_UpdateJob_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*job.UpdateJobRequest), variadicArgs...) + }) + return _c +} + +func (_c *MockOffchainClient_UpdateJob_Call) Return(_a0 *job.UpdateJobResponse, _a1 error) *MockOffchainClient_UpdateJob_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockOffchainClient_UpdateJob_Call) RunAndReturn(run func(context.Context, *job.UpdateJobRequest, ...grpc.CallOption) (*job.UpdateJobResponse, error)) *MockOffchainClient_UpdateJob_Call { + _c.Call.Return(run) + return _c +} + +// UpdateNode provides a mock function with given fields: ctx, in, opts +func (_m *MockOffchainClient) UpdateNode(ctx context.Context, in *node.UpdateNodeRequest, opts ...grpc.CallOption) (*node.UpdateNodeResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for UpdateNode") + } + + var r0 *node.UpdateNodeResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *node.UpdateNodeRequest, ...grpc.CallOption) (*node.UpdateNodeResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *node.UpdateNodeRequest, ...grpc.CallOption) *node.UpdateNodeResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*node.UpdateNodeResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *node.UpdateNodeRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockOffchainClient_UpdateNode_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateNode' +type MockOffchainClient_UpdateNode_Call struct { + *mock.Call +} + +// UpdateNode is a helper method to define mock.On call +// - ctx context.Context +// - in *node.UpdateNodeRequest +// - opts ...grpc.CallOption +func (_e *MockOffchainClient_Expecter) UpdateNode(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_UpdateNode_Call { + return &MockOffchainClient_UpdateNode_Call{Call: _e.mock.On("UpdateNode", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *MockOffchainClient_UpdateNode_Call) Run(run func(ctx context.Context, in *node.UpdateNodeRequest, opts ...grpc.CallOption)) *MockOffchainClient_UpdateNode_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*node.UpdateNodeRequest), variadicArgs...) + }) + return _c +} + +func (_c *MockOffchainClient_UpdateNode_Call) Return(_a0 *node.UpdateNodeResponse, _a1 error) *MockOffchainClient_UpdateNode_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockOffchainClient_UpdateNode_Call) RunAndReturn(run func(context.Context, *node.UpdateNodeRequest, ...grpc.CallOption) (*node.UpdateNodeResponse, error)) *MockOffchainClient_UpdateNode_Call { + _c.Call.Return(run) + return _c +} + +// NewMockOffchainClient creates a new instance of MockOffchainClient. 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 NewMockOffchainClient(t interface { + mock.TestingT + Cleanup(func()) +}) *MockOffchainClient { + mock := &MockOffchainClient{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/deployment/multiclient.go b/deployment/multiclient.go index f1ac2f3c310..256de787b5e 100644 --- a/deployment/multiclient.go +++ b/deployment/multiclient.go @@ -7,6 +7,7 @@ import ( "time" "github.com/avast/retry-go/v4" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -88,6 +89,26 @@ func (mc *MultiClient) SendTransaction(ctx context.Context, tx *types.Transactio }) } +func (mc *MultiClient) CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) { + var result []byte + err := mc.retryWithBackups("CallContract", func(client *ethclient.Client) error { + var err error + result, err = client.CallContract(ctx, msg, blockNumber) + return err + }) + return result, err +} + +func (mc *MultiClient) CallContractAtHash(ctx context.Context, msg ethereum.CallMsg, blockHash common.Hash) ([]byte, error) { + var result []byte + err := mc.retryWithBackups("CallContractAtHash", func(client *ethclient.Client) error { + var err error + result, err = client.CallContractAtHash(ctx, msg, blockHash) + return err + }) + return result, err +} + func (mc *MultiClient) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error) { var code []byte err := mc.retryWithBackups("CodeAt", func(client *ethclient.Client) error { @@ -98,6 +119,16 @@ func (mc *MultiClient) CodeAt(ctx context.Context, account common.Address, block return code, err } +func (mc *MultiClient) CodeAtHash(ctx context.Context, account common.Address, blockHash common.Hash) ([]byte, error) { + var code []byte + err := mc.retryWithBackups("CodeAtHash", func(client *ethclient.Client) error { + var err error + code, err = client.CodeAtHash(ctx, account, blockHash) + return err + }) + return code, err +} + func (mc *MultiClient) NonceAt(ctx context.Context, account common.Address, block *big.Int) (uint64, error) { var count uint64 err := mc.retryWithBackups("NonceAt", func(client *ethclient.Client) error { @@ -108,17 +139,27 @@ func (mc *MultiClient) NonceAt(ctx context.Context, account common.Address, bloc return count, err } +func (mc *MultiClient) NonceAtHash(ctx context.Context, account common.Address, blockHash common.Hash) (uint64, error) { + var count uint64 + err := mc.retryWithBackups("NonceAtHash", func(client *ethclient.Client) error { + var err error + count, err = client.NonceAtHash(ctx, account, blockHash) + return err + }) + return count, err +} + func (mc *MultiClient) WaitMined(ctx context.Context, tx *types.Transaction) (*types.Receipt, error) { - mc.lggr.Debugf("Waiting for tx %s to be mined", tx.Hash().Hex()) + mc.lggr.Debugf("Waiting for tx %s to be mined for chain %s", tx.Hash().Hex(), mc.chainName) // no retries here because we want to wait for the tx to be mined resultCh := make(chan *types.Receipt) doneCh := make(chan struct{}) waitMined := func(client *ethclient.Client, tx *types.Transaction) { - mc.lggr.Debugf("Waiting for tx %s to be mined with client %v", tx.Hash().Hex(), client) + mc.lggr.Debugf("Waiting for tx %s to be mined with chain %s", tx.Hash().Hex(), mc.chainName) receipt, err := bind.WaitMined(ctx, client, tx) if err != nil { - mc.lggr.Warnf("WaitMined error %v with client %v", err, client) + mc.lggr.Warnf("WaitMined error %v with chain %s", err, mc.chainName) return } select { @@ -135,6 +176,7 @@ func (mc *MultiClient) WaitMined(ctx context.Context, tx *types.Transaction) (*t select { case receipt = <-resultCh: close(doneCh) + mc.lggr.Debugf("Tx %s mined with chain %s", tx.Hash().Hex(), mc.chainName) return receipt, nil case <-ctx.Done(): mc.lggr.Warnf("WaitMined context done %v", ctx.Err()) diff --git a/deployment/multiclient_test.go b/deployment/multiclient_test.go index 2e10c46e33f..152cdbc8d0e 100644 --- a/deployment/multiclient_test.go +++ b/deployment/multiclient_test.go @@ -38,7 +38,7 @@ func TestMultiClient(t *testing.T) { require.NoError(t, err) require.NotNil(t, mc) assert.Equal(t, mc.RetryConfig.Attempts, uint(RPC_DEFAULT_RETRY_ATTEMPTS)) - assert.Equal(t, mc.RetryConfig.Delay, RPC_DEFAULT_RETRY_DELAY) + assert.Equal(t, RPC_DEFAULT_RETRY_DELAY, mc.RetryConfig.Delay) _, err = NewMultiClient(lggr, []RPC{}) require.Error(t, err) @@ -49,5 +49,5 @@ func TestMultiClient(t *testing.T) { {WSURL: s.URL}, }) require.NoError(t, err) - require.Equal(t, len(mc.Backups), 1) + require.Len(t, mc.Backups, 1) } diff --git a/deployment/solana_chain.go b/deployment/solana_chain.go index 338642e3e32..34410c2d06a 100644 --- a/deployment/solana_chain.go +++ b/deployment/solana_chain.go @@ -1,5 +1,95 @@ package deployment +import ( + "bytes" + "fmt" + "os/exec" + "strconv" + "strings" + "time" + + "github.com/gagliardetto/solana-go" + solRpc "github.com/gagliardetto/solana-go/rpc" + "github.com/pkg/errors" + + solCommomUtil "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/common" +) + // SolChain represents a Solana chain. type SolChain struct { + // Selectors used as canonical chain identifier. + Selector uint64 + // RPC client + Client *solRpc.Client + URL string + WSURL string + // TODO: raw private key for now, need to replace with a more secure way + DeployerKey *solana.PrivateKey + // deploy uses the solana CLI which needs a keyfile + KeypairPath string + ProgramsPath string + Confirm func(instructions []solana.Instruction, opts ...solCommomUtil.TxModifier) error +} + +func (c SolChain) String() string { + chainInfo, err := ChainInfo(c.Selector) + if err != nil { + // we should never get here, if the selector is invalid it should not be in the environment + panic(err) + } + return fmt.Sprintf("%s (%d)", chainInfo.ChainName, chainInfo.ChainSelector) +} + +func (c SolChain) Name() string { + chainInfo, err := ChainInfo(c.Selector) + if err != nil { + // we should never get here, if the selector is invalid it should not be in the environment + panic(err) + } + if chainInfo.ChainName == "" { + return strconv.FormatUint(c.Selector, 10) + } + return chainInfo.ChainName +} + +func (c SolChain) DeployProgram(programName string) (string, error) { + programFile := fmt.Sprintf("%s/%s.so", c.ProgramsPath, programName) + programKeyPair := fmt.Sprintf("%s/%s-keypair.json", c.ProgramsPath, programName) + + // Construct the CLI command: solana program deploy + // TODO: @terry doing this on the fly + cmd := exec.Command("solana", "program", "deploy", programFile, "--keypair", c.KeypairPath, "--program-id", programKeyPair) + + // Capture the command output + var stdout, stderr bytes.Buffer + cmd.Stdout = &stdout + cmd.Stderr = &stderr + + // Run the command + if err := cmd.Run(); err != nil { + return "", fmt.Errorf("error deploying program: %s: %s", err.Error(), stderr.String()) + } + + // Parse and return the program ID + output := stdout.String() + + time.Sleep(5 * time.Second) // obviously need to do this better + return parseProgramID(output) +} + +// parseProgramID parses the program ID from the deploy output. +func parseProgramID(output string) (string, error) { + // Look for the program ID in the CLI output + // Example output: "Program Id: " + const prefix = "Program Id: " + startIdx := strings.Index(output, prefix) + if startIdx == -1 { + return "", errors.New("failed to find program ID in output") + } + startIdx += len(prefix) + endIdx := strings.Index(output[startIdx:], "\n") + if endIdx == -1 { + endIdx = len(output) + } + return output[startIdx : startIdx+endIdx], nil } diff --git a/docs/CONFIG.md b/docs/CONFIG.md index 946703695eb..e90b37d09c7 100644 --- a/docs/CONFIG.md +++ b/docs/CONFIG.md @@ -1900,15 +1900,26 @@ CertFile is the path to a PEM file of trusted root certificate authority certifi ## Mercury.Transmitter ```toml [Mercury.Transmitter] -TransmitQueueMaxSize = 10_000 # Default +Protocol = "wsrpc" # Default +TransmitQueueMaxSize = 100_000 # Default TransmitTimeout = "5s" # Default TransmitConcurrency = 100 # Default ``` Mercury.Transmitter controls settings for the mercury transmitter +### Protocol +```toml +Protocol = "wsrpc" # Default +``` +Protocol is the protocol to use for the transmitter. + +Options are either: +- "wsrpc" for the legacy websocket protocol +- "grpc" for the gRPC protocol + ### TransmitQueueMaxSize ```toml -TransmitQueueMaxSize = 10_000 # Default +TransmitQueueMaxSize = 100_000 # Default ``` TransmitQueueMaxSize controls the size of the transmit queue. This is scoped per OCR instance. If the queue is full, the transmitter will start dropping @@ -2034,6 +2045,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '9m0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -2044,6 +2056,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -2138,6 +2153,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -2148,6 +2164,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -2242,6 +2261,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -2252,6 +2272,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -2346,6 +2369,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -2356,6 +2380,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -2451,6 +2478,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '13m0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -2461,6 +2489,9 @@ ResendAfterThreshold = '30s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -2559,6 +2590,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -2569,6 +2601,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -2663,6 +2698,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -2673,6 +2709,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -2768,6 +2807,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -2778,6 +2818,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -2872,6 +2915,7 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '45s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -2882,6 +2926,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -2975,6 +3022,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -2985,6 +3033,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -3078,6 +3129,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -3088,6 +3140,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -3182,6 +3237,7 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '40s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -3192,6 +3248,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -3287,6 +3346,7 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '2m0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -3297,6 +3357,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -3391,6 +3454,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -3401,6 +3465,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -3495,6 +3562,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '6m0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 5000 @@ -3505,6 +3573,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -3574,6 +3645,113 @@ GasLimitDefault = 400000

+
Sonic Mainnet (146)

+ +```toml +AutoCreateKey = true +BlockBackfillDepth = 10 +BlockBackfillSkip = false +FinalityDepth = 10 +FinalityTagEnabled = false +LogBackfillBatchSize = 1000 +LogPollInterval = '1s' +LogKeepBlocksDepth = 100000 +LogPrunePageSize = 0 +BackupLogPollerBlockDelay = 100 +MinIncomingConfirmations = 5 +MinContractPayment = '0.00001 link' +NonceAutoSync = true +NoNewHeadsThreshold = '3m0s' +LogBroadcasterEnabled = true +RPCDefaultBatchSize = 100 +RPCBlockQueryDelay = 10 +FinalizedBlockOffset = 0 +NoNewFinalizedHeadsThreshold = '0s' + +[Transactions] +Enabled = true +ForwardersEnabled = false +MaxInFlight = 16 +MaxQueued = 500 +ReaperInterval = '1h0m0s' +ReaperThreshold = '168h0m0s' +ResendAfterThreshold = '1m0s' + +[Transactions.AutoPurge] +Enabled = false + +[Transactions.TransactionManagerV2] +Enabled = false + +[BalanceMonitor] +Enabled = true + +[GasEstimator] +Mode = 'FeeHistory' +PriceDefault = '20 gwei' +PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' +PriceMin = '1 gwei' +LimitDefault = 8000000 +LimitMax = 500000 +LimitMultiplier = '1' +LimitTransfer = 21000 +EstimateLimit = false +BumpMin = '5 gwei' +BumpPercent = 10 +BumpThreshold = 3 +EIP1559DynamicFees = true +FeeCapDefault = '100 gwei' +TipCapDefault = '1 wei' +TipCapMin = '1 wei' + +[GasEstimator.BlockHistory] +BatchSize = 25 +BlockHistorySize = 100 +CheckInclusionBlocks = 12 +CheckInclusionPercentile = 90 +TransactionPercentile = 60 + +[GasEstimator.FeeHistory] +CacheTimeout = '2s' + +[HeadTracker] +HistoryDepth = 50 +MaxBufferSize = 3 +SamplingInterval = '1s' +MaxAllowedFinalityDepth = 10000 +FinalityTagBypass = true +PersistenceEnabled = true + +[NodePool] +PollFailureThreshold = 5 +PollInterval = '10s' +SelectionMode = 'HighestHead' +SyncThreshold = 10 +LeaseDuration = '0s' +NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = true +DeathDeclarationDelay = '1m0s' +NewHeadsPollInterval = '0s' + +[OCR] +ContractConfirmations = 4 +ContractTransmitterTransmitTimeout = '10s' +DatabaseTimeout = '10s' +DeltaCOverride = '168h0m0s' +DeltaCJitterOverride = '1h0m0s' +ObservationGracePeriod = '1s' + +[OCR2] +[OCR2.Automation] +GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 +``` + +

+
XLayer Sepolia (195)

```toml @@ -3599,6 +3777,7 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -3610,6 +3789,9 @@ ResendAfterThreshold = '3m0s' Enabled = true MinAttempts = 3 +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -3704,6 +3886,7 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -3715,6 +3898,9 @@ ResendAfterThreshold = '3m0s' Enabled = true MinAttempts = 3 +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -3809,6 +3995,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '1h10m0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -3819,6 +4006,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -3917,6 +4107,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -3927,6 +4118,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -4021,6 +4215,7 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -4031,6 +4226,9 @@ ResendAfterThreshold = '30s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -4129,6 +4327,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -4139,6 +4338,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -4236,6 +4438,7 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -4246,6 +4449,9 @@ ResendAfterThreshold = '2m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -4340,6 +4546,7 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -4350,6 +4557,9 @@ ResendAfterThreshold = '2m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -4444,6 +4654,7 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -4454,6 +4665,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -4551,6 +4765,7 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -4561,6 +4776,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -4659,6 +4877,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -4669,6 +4888,9 @@ ResendAfterThreshold = '30s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -4767,6 +4989,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '1h30m0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -4777,6 +5000,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -4875,6 +5101,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -4885,6 +5112,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -4978,6 +5208,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -4988,6 +5219,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -5082,6 +5316,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -5092,6 +5327,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -5186,6 +5424,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -5197,6 +5436,9 @@ ResendAfterThreshold = '3m0s' Enabled = true MinAttempts = 3 +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -5291,6 +5533,7 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '40s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -5301,6 +5544,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -5395,6 +5641,7 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '40s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -5405,6 +5652,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -5499,6 +5749,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '1h10m0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -5509,6 +5760,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -5607,6 +5861,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '45m0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -5617,6 +5872,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -5714,6 +5972,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -5724,6 +5983,9 @@ ResendAfterThreshold = '0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -5793,7 +6055,7 @@ GasLimitDefault = 400000

-
Soneium Sepolia (1946)

+

Soneium Mainnet (1868)

```toml AutoCreateKey = true @@ -5819,6 +6081,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '2h0m0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -5829,6 +6092,9 @@ ResendAfterThreshold = '30s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -5902,65 +6168,70 @@ GasLimitDefault = 400000

-
Ronin Mainnet (2020)

+

Soneium Sepolia (1946)

```toml AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false -FinalityDepth = 50 +ChainType = 'optimismBedrock' +FinalityDepth = 200 FinalityTagEnabled = true -LinkContractAddress = '0x3902228D6A3d2Dc44731fD9d45FeE6a61c722D0b' +LinkContractAddress = '0x7ea13478Ea3961A0e8b538cb05a9DF0477c79Cd2' LogBackfillBatchSize = 1000 -LogPollInterval = '3s' +LogPollInterval = '2s' LogKeepBlocksDepth = 100000 LogPrunePageSize = 0 BackupLogPollerBlockDelay = 100 -MinIncomingConfirmations = 3 +MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true -NoNewHeadsThreshold = '3m0s' +NoNewHeadsThreshold = '40s' LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 -NoNewFinalizedHeadsThreshold = '0s' +NoNewFinalizedHeadsThreshold = '2h0m0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 ReaperInterval = '1h0m0s' ReaperThreshold = '168h0m0s' -ResendAfterThreshold = '1m0s' +ResendAfterThreshold = '30s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true [GasEstimator] -Mode = 'FeeHistory' +Mode = 'BlockHistory' PriceDefault = '20 gwei' -PriceMax = '1 micro' -PriceMin = '1 gwei' +PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' +PriceMin = '1 wei' LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 EstimateLimit = false -BumpMin = '5 gwei' +BumpMin = '1 mwei' BumpPercent = 20 BumpThreshold = 3 -EIP1559DynamicFees = false +EIP1559DynamicFees = true FeeCapDefault = '100 gwei' TipCapDefault = '1 wei' TipCapMin = '1 wei' [GasEstimator.BlockHistory] BatchSize = 25 -BlockHistorySize = 8 +BlockHistorySize = 60 CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 @@ -5968,8 +6239,120 @@ TransactionPercentile = 60 [GasEstimator.FeeHistory] CacheTimeout = '10s' +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x420000000000000000000000000000000000000F' + [HeadTracker] -HistoryDepth = 100 +HistoryDepth = 300 +MaxBufferSize = 3 +SamplingInterval = '1s' +MaxAllowedFinalityDepth = 10000 +FinalityTagBypass = true +PersistenceEnabled = true + +[NodePool] +PollFailureThreshold = 5 +PollInterval = '10s' +SelectionMode = 'HighestHead' +SyncThreshold = 10 +LeaseDuration = '0s' +NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = true +DeathDeclarationDelay = '1m0s' +NewHeadsPollInterval = '0s' + +[OCR] +ContractConfirmations = 1 +ContractTransmitterTransmitTimeout = '10s' +DatabaseTimeout = '10s' +DeltaCOverride = '168h0m0s' +DeltaCJitterOverride = '1h0m0s' +ObservationGracePeriod = '1s' + +[OCR2] +[OCR2.Automation] +GasLimit = 6500000 + +[Workflow] +GasLimitDefault = 400000 +``` + +

+ +
Ronin Mainnet (2020)

+ +```toml +AutoCreateKey = true +BlockBackfillDepth = 10 +BlockBackfillSkip = false +FinalityDepth = 50 +FinalityTagEnabled = true +LinkContractAddress = '0x3902228D6A3d2Dc44731fD9d45FeE6a61c722D0b' +LogBackfillBatchSize = 1000 +LogPollInterval = '3s' +LogKeepBlocksDepth = 100000 +LogPrunePageSize = 0 +BackupLogPollerBlockDelay = 100 +MinIncomingConfirmations = 3 +MinContractPayment = '0.00001 link' +NonceAutoSync = true +NoNewHeadsThreshold = '3m0s' +LogBroadcasterEnabled = true +RPCDefaultBatchSize = 250 +RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 +NoNewFinalizedHeadsThreshold = '0s' + +[Transactions] +Enabled = true +ForwardersEnabled = false +MaxInFlight = 16 +MaxQueued = 250 +ReaperInterval = '1h0m0s' +ReaperThreshold = '168h0m0s' +ResendAfterThreshold = '1m0s' + +[Transactions.AutoPurge] +Enabled = false + +[Transactions.TransactionManagerV2] +Enabled = false + +[BalanceMonitor] +Enabled = true + +[GasEstimator] +Mode = 'FeeHistory' +PriceDefault = '20 gwei' +PriceMax = '1 micro' +PriceMin = '1 gwei' +LimitDefault = 500000 +LimitMax = 500000 +LimitMultiplier = '1' +LimitTransfer = 21000 +EstimateLimit = false +BumpMin = '5 gwei' +BumpPercent = 20 +BumpThreshold = 3 +EIP1559DynamicFees = false +FeeCapDefault = '100 gwei' +TipCapDefault = '1 wei' +TipCapMin = '1 wei' + +[GasEstimator.BlockHistory] +BatchSize = 25 +BlockHistorySize = 8 +CheckInclusionBlocks = 12 +CheckInclusionPercentile = 90 +TransactionPercentile = 60 + +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + +[HeadTracker] +HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 @@ -6031,6 +6414,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -6041,6 +6425,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -6135,6 +6522,7 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -6145,6 +6533,9 @@ ResendAfterThreshold = '30s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -6243,6 +6634,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -6254,6 +6646,9 @@ ResendAfterThreshold = '3m0s' Enabled = true MinAttempts = 3 +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -6323,6 +6718,113 @@ GasLimitDefault = 400000

+
Botanix Testnet (3636)

+ +```toml +AutoCreateKey = true +BlockBackfillDepth = 10 +BlockBackfillSkip = false +FinalityDepth = 50 +FinalityTagEnabled = true +LogBackfillBatchSize = 1000 +LogPollInterval = '15s' +LogKeepBlocksDepth = 100000 +LogPrunePageSize = 0 +BackupLogPollerBlockDelay = 100 +MinIncomingConfirmations = 3 +MinContractPayment = '0.00001 link' +NonceAutoSync = true +NoNewHeadsThreshold = '3m0s' +LogBroadcasterEnabled = true +RPCDefaultBatchSize = 250 +RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 +NoNewFinalizedHeadsThreshold = '0s' + +[Transactions] +Enabled = true +ForwardersEnabled = false +MaxInFlight = 16 +MaxQueued = 250 +ReaperInterval = '1h0m0s' +ReaperThreshold = '168h0m0s' +ResendAfterThreshold = '1m0s' + +[Transactions.AutoPurge] +Enabled = false + +[Transactions.TransactionManagerV2] +Enabled = false + +[BalanceMonitor] +Enabled = true + +[GasEstimator] +Mode = 'BlockHistory' +PriceDefault = '20 gwei' +PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' +PriceMin = '1 gwei' +LimitDefault = 500000 +LimitMax = 500000 +LimitMultiplier = '1' +LimitTransfer = 21000 +EstimateLimit = false +BumpMin = '5 gwei' +BumpPercent = 20 +BumpThreshold = 3 +EIP1559DynamicFees = true +FeeCapDefault = '100 gwei' +TipCapDefault = '1 wei' +TipCapMin = '1 wei' + +[GasEstimator.BlockHistory] +BatchSize = 25 +BlockHistorySize = 4 +CheckInclusionBlocks = 12 +CheckInclusionPercentile = 90 +TransactionPercentile = 50 + +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + +[HeadTracker] +HistoryDepth = 100 +MaxBufferSize = 3 +SamplingInterval = '1s' +MaxAllowedFinalityDepth = 10000 +FinalityTagBypass = false +PersistenceEnabled = true + +[NodePool] +PollFailureThreshold = 5 +PollInterval = '10s' +SelectionMode = 'HighestHead' +SyncThreshold = 5 +LeaseDuration = '0s' +NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = true +DeathDeclarationDelay = '1m0s' +NewHeadsPollInterval = '0s' + +[OCR] +ContractConfirmations = 4 +ContractTransmitterTransmitTimeout = '10s' +DatabaseTimeout = '10s' +DeltaCOverride = '168h0m0s' +DeltaCJitterOverride = '1h0m0s' +ObservationGracePeriod = '1s' + +[OCR2] +[OCR2.Automation] +GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 +``` + +

+
Fantom Testnet (4002)

```toml @@ -6348,6 +6850,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -6358,6 +6861,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -6452,6 +6958,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '1h30m0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -6462,6 +6969,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -6535,6 +7045,232 @@ GasLimitDefault = 400000

+
Mantle Mainnet (5000)

+ +```toml +AutoCreateKey = true +BlockBackfillDepth = 10 +BlockBackfillSkip = false +ChainType = 'optimismBedrock' +FinalityDepth = 1200 +FinalityTagEnabled = true +LogBackfillBatchSize = 1000 +LogPollInterval = '2s' +LogKeepBlocksDepth = 100000 +LogPrunePageSize = 0 +BackupLogPollerBlockDelay = 100 +MinIncomingConfirmations = 1 +MinContractPayment = '0.00001 link' +NonceAutoSync = true +NoNewHeadsThreshold = '3m0s' +LogBroadcasterEnabled = true +RPCDefaultBatchSize = 250 +RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 +NoNewFinalizedHeadsThreshold = '40m0s' + +[Transactions] +Enabled = true +ForwardersEnabled = false +MaxInFlight = 16 +MaxQueued = 250 +ReaperInterval = '1h0m0s' +ReaperThreshold = '168h0m0s' +ResendAfterThreshold = '1m0s' + +[Transactions.AutoPurge] +Enabled = false + +[Transactions.TransactionManagerV2] +Enabled = false + +[BalanceMonitor] +Enabled = true + +[GasEstimator] +Mode = 'BlockHistory' +PriceDefault = '20 gwei' +PriceMax = '120 gwei' +PriceMin = '1 gwei' +LimitDefault = 80000000000 +LimitMax = 100000000000 +LimitMultiplier = '1' +LimitTransfer = 21000 +EstimateLimit = false +BumpMin = '100 wei' +BumpPercent = 20 +BumpThreshold = 60 +EIP1559DynamicFees = true +FeeCapDefault = '120 gwei' +TipCapDefault = '0' +TipCapMin = '0' + +[GasEstimator.BlockHistory] +BatchSize = 25 +BlockHistorySize = 200 +CheckInclusionBlocks = 12 +CheckInclusionPercentile = 90 +EIP1559FeeCapBufferBlocks = 0 +TransactionPercentile = 60 + +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x420000000000000000000000000000000000000F' + +[HeadTracker] +HistoryDepth = 1250 +MaxBufferSize = 3 +SamplingInterval = '1s' +MaxAllowedFinalityDepth = 10000 +FinalityTagBypass = true +PersistenceEnabled = true + +[NodePool] +PollFailureThreshold = 5 +PollInterval = '10s' +SelectionMode = 'HighestHead' +SyncThreshold = 5 +LeaseDuration = '0s' +NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = true +DeathDeclarationDelay = '1m0s' +NewHeadsPollInterval = '0s' + +[OCR] +ContractConfirmations = 4 +ContractTransmitterTransmitTimeout = '10s' +DatabaseTimeout = '10s' +DeltaCOverride = '168h0m0s' +DeltaCJitterOverride = '1h0m0s' +ObservationGracePeriod = '1s' + +[OCR2] +[OCR2.Automation] +GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 +``` + +

+ +
Mantle Sepolia (5003)

+ +```toml +AutoCreateKey = true +BlockBackfillDepth = 10 +BlockBackfillSkip = false +ChainType = 'optimismBedrock' +FinalityDepth = 1200 +FinalityTagEnabled = true +LogBackfillBatchSize = 1000 +LogPollInterval = '2s' +LogKeepBlocksDepth = 100000 +LogPrunePageSize = 0 +BackupLogPollerBlockDelay = 100 +MinIncomingConfirmations = 1 +MinContractPayment = '0.00001 link' +NonceAutoSync = true +NoNewHeadsThreshold = '3m0s' +LogBroadcasterEnabled = true +RPCDefaultBatchSize = 250 +RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 +NoNewFinalizedHeadsThreshold = '1h0m0s' + +[Transactions] +Enabled = true +ForwardersEnabled = false +MaxInFlight = 16 +MaxQueued = 250 +ReaperInterval = '1h0m0s' +ReaperThreshold = '168h0m0s' +ResendAfterThreshold = '1m0s' + +[Transactions.AutoPurge] +Enabled = false + +[Transactions.TransactionManagerV2] +Enabled = false + +[BalanceMonitor] +Enabled = true + +[GasEstimator] +Mode = 'BlockHistory' +PriceDefault = '20 gwei' +PriceMax = '120 gwei' +PriceMin = '1 gwei' +LimitDefault = 80000000000 +LimitMax = 100000000000 +LimitMultiplier = '1' +LimitTransfer = 21000 +EstimateLimit = false +BumpMin = '100 wei' +BumpPercent = 20 +BumpThreshold = 60 +EIP1559DynamicFees = true +FeeCapDefault = '120 gwei' +TipCapDefault = '0' +TipCapMin = '0' + +[GasEstimator.BlockHistory] +BatchSize = 25 +BlockHistorySize = 200 +CheckInclusionBlocks = 12 +CheckInclusionPercentile = 90 +EIP1559FeeCapBufferBlocks = 0 +TransactionPercentile = 60 + +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x420000000000000000000000000000000000000F' + +[HeadTracker] +HistoryDepth = 1250 +MaxBufferSize = 3 +SamplingInterval = '1s' +MaxAllowedFinalityDepth = 10000 +FinalityTagBypass = true +PersistenceEnabled = true + +[NodePool] +PollFailureThreshold = 5 +PollInterval = '10s' +SelectionMode = 'HighestHead' +SyncThreshold = 5 +LeaseDuration = '0s' +NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = true +DeathDeclarationDelay = '1m0s' +NewHeadsPollInterval = '0s' + +[OCR] +ContractConfirmations = 4 +ContractTransmitterTransmitTimeout = '10s' +DatabaseTimeout = '10s' +DeltaCOverride = '168h0m0s' +DeltaCJitterOverride = '1h0m0s' +ObservationGracePeriod = '1s' + +[OCR2] +[OCR2.Automation] +GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 +``` + +

+
Klaytn Mainnet (8217)

```toml @@ -6559,6 +7295,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -6569,6 +7306,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -6663,6 +7403,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '15m0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -6673,6 +7414,9 @@ ResendAfterThreshold = '30s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -6771,6 +7515,7 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '2m0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -6781,6 +7526,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -6876,6 +7624,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -6886,6 +7635,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -6984,6 +7736,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -6994,6 +7747,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -7092,6 +7848,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -7102,6 +7859,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -7199,6 +7959,7 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '1m0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -7209,6 +7970,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -7303,6 +8067,7 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '1m0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -7313,14 +8078,17 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true [GasEstimator] Mode = 'BlockHistory' -PriceDefault = '25 gwei' +PriceDefault = '1 gwei' PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' -PriceMin = '25 gwei' +PriceMin = '1 gwei' LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' @@ -7407,6 +8175,7 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '1m0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -7417,14 +8186,17 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true [GasEstimator] Mode = 'BlockHistory' -PriceDefault = '25 gwei' +PriceDefault = '1 gwei' PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' -PriceMin = '25 gwei' +PriceMin = '1 gwei' LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' @@ -7511,6 +8283,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '45m0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -7521,6 +8294,9 @@ ResendAfterThreshold = '30s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -7616,6 +8392,122 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '15m0s' [Transactions] +Enabled = true +ForwardersEnabled = false +MaxInFlight = 16 +MaxQueued = 250 +ReaperInterval = '1h0m0s' +ReaperThreshold = '168h0m0s' +ResendAfterThreshold = '30s' + +[Transactions.AutoPurge] +Enabled = true +Threshold = 90 +MinAttempts = 3 + +[Transactions.TransactionManagerV2] +Enabled = false + +[BalanceMonitor] +Enabled = true + +[GasEstimator] +Mode = 'BlockHistory' +PriceDefault = '20 gwei' +PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' +PriceMin = '1 wei' +LimitDefault = 500000 +LimitMax = 500000 +LimitMultiplier = '1' +LimitTransfer = 21000 +EstimateLimit = false +BumpMin = '100 wei' +BumpPercent = 20 +BumpThreshold = 3 +EIP1559DynamicFees = true +FeeCapDefault = '100 gwei' +TipCapDefault = '1 wei' +TipCapMin = '1 wei' + +[GasEstimator.BlockHistory] +BatchSize = 25 +BlockHistorySize = 60 +CheckInclusionBlocks = 12 +CheckInclusionPercentile = 90 +TransactionPercentile = 60 + +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x420000000000000000000000000000000000000F' + +[HeadTracker] +HistoryDepth = 2000 +MaxBufferSize = 3 +SamplingInterval = '1s' +MaxAllowedFinalityDepth = 10000 +FinalityTagBypass = true +PersistenceEnabled = true + +[NodePool] +PollFailureThreshold = 5 +PollInterval = '10s' +SelectionMode = 'HighestHead' +SyncThreshold = 10 +LeaseDuration = '0s' +NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = true +DeathDeclarationDelay = '1m0s' +NewHeadsPollInterval = '0s' + +[OCR] +ContractConfirmations = 1 +ContractTransmitterTransmitTimeout = '10s' +DatabaseTimeout = '10s' +DeltaCOverride = '168h0m0s' +DeltaCJitterOverride = '1h0m0s' +ObservationGracePeriod = '1s' + +[OCR2] +[OCR2.Automation] +GasLimit = 6500000 + +[Workflow] +GasLimitDefault = 400000 +``` + +

+ +
Zircuit Mainnet (48900)

+ +```toml +AutoCreateKey = true +BlockBackfillDepth = 10 +BlockBackfillSkip = false +ChainType = 'zircuit' +FinalityDepth = 1000 +FinalityTagEnabled = true +LinkContractAddress = '0x5D6d033B4FbD2190D99D930719fAbAcB64d2439a' +LogBackfillBatchSize = 1000 +LogPollInterval = '2s' +LogKeepBlocksDepth = 100000 +LogPrunePageSize = 0 +BackupLogPollerBlockDelay = 100 +MinIncomingConfirmations = 3 +MinContractPayment = '0.00001 link' +NonceAutoSync = true +NoNewHeadsThreshold = '40s' +LogBroadcasterEnabled = true +RPCDefaultBatchSize = 250 +RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 +NoNewFinalizedHeadsThreshold = '15m0s' + +[Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -7628,21 +8520,135 @@ Enabled = true Threshold = 90 MinAttempts = 3 +[Transactions.TransactionManagerV2] +Enabled = false + +[BalanceMonitor] +Enabled = true + +[GasEstimator] +Mode = 'BlockHistory' +PriceDefault = '20 gwei' +PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' +PriceMin = '1 wei' +LimitDefault = 500000 +LimitMax = 500000 +LimitMultiplier = '1' +LimitTransfer = 21000 +EstimateLimit = false +BumpMin = '100 wei' +BumpPercent = 20 +BumpThreshold = 3 +EIP1559DynamicFees = true +FeeCapDefault = '100 gwei' +TipCapDefault = '1 wei' +TipCapMin = '1 wei' + +[GasEstimator.BlockHistory] +BatchSize = 25 +BlockHistorySize = 24 +CheckInclusionBlocks = 12 +CheckInclusionPercentile = 90 +TransactionPercentile = 60 + +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x420000000000000000000000000000000000000F' + +[HeadTracker] +HistoryDepth = 2000 +MaxBufferSize = 3 +SamplingInterval = '1s' +MaxAllowedFinalityDepth = 10000 +FinalityTagBypass = true +PersistenceEnabled = true + +[NodePool] +PollFailureThreshold = 5 +PollInterval = '10s' +SelectionMode = 'HighestHead' +SyncThreshold = 10 +LeaseDuration = '0s' +NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = true +DeathDeclarationDelay = '1m0s' +NewHeadsPollInterval = '0s' + +[OCR] +ContractConfirmations = 1 +ContractTransmitterTransmitTimeout = '10s' +DatabaseTimeout = '10s' +DeltaCOverride = '168h0m0s' +DeltaCJitterOverride = '1h0m0s' +ObservationGracePeriod = '1s' + +[OCR2] +[OCR2.Automation] +GasLimit = 6500000 + +[Workflow] +GasLimitDefault = 400000 +``` + +

+ +
Sonic testnet (57054)

+ +```toml +AutoCreateKey = true +BlockBackfillDepth = 10 +BlockBackfillSkip = false +FinalityDepth = 10 +FinalityTagEnabled = false +LogBackfillBatchSize = 1000 +LogPollInterval = '1s' +LogKeepBlocksDepth = 100000 +LogPrunePageSize = 0 +BackupLogPollerBlockDelay = 100 +MinIncomingConfirmations = 5 +MinContractPayment = '0.00001 link' +NonceAutoSync = true +NoNewHeadsThreshold = '3m0s' +LogBroadcasterEnabled = true +RPCDefaultBatchSize = 100 +RPCBlockQueryDelay = 10 +FinalizedBlockOffset = 0 +NoNewFinalizedHeadsThreshold = '0s' + +[Transactions] +Enabled = true +ForwardersEnabled = false +MaxInFlight = 16 +MaxQueued = 500 +ReaperInterval = '1h0m0s' +ReaperThreshold = '168h0m0s' +ResendAfterThreshold = '1m0s' + +[Transactions.AutoPurge] +Enabled = false + +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true [GasEstimator] -Mode = 'BlockHistory' +Mode = 'FeeHistory' PriceDefault = '20 gwei' PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' -PriceMin = '1 wei' -LimitDefault = 500000 +PriceMin = '1 gwei' +LimitDefault = 8000000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 EstimateLimit = false -BumpMin = '100 wei' -BumpPercent = 20 +BumpMin = '5 gwei' +BumpPercent = 10 BumpThreshold = 3 EIP1559DynamicFees = true FeeCapDefault = '100 gwei' @@ -7651,20 +8657,16 @@ TipCapMin = '1 wei' [GasEstimator.BlockHistory] BatchSize = 25 -BlockHistorySize = 60 +BlockHistorySize = 100 CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 [GasEstimator.FeeHistory] -CacheTimeout = '10s' - -[GasEstimator.DAOracle] -OracleType = 'opstack' -OracleAddress = '0x420000000000000000000000000000000000000F' +CacheTimeout = '2s' [HeadTracker] -HistoryDepth = 2000 +HistoryDepth = 50 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 @@ -7684,7 +8686,7 @@ DeathDeclarationDelay = '1m0s' NewHeadsPollInterval = '0s' [OCR] -ContractConfirmations = 1 +ContractConfirmations = 4 ContractTransmitterTransmitTimeout = '10s' DatabaseTimeout = '10s' DeltaCOverride = '168h0m0s' @@ -7693,7 +8695,7 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] -GasLimit = 6500000 +GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 @@ -7701,16 +8703,15 @@ GasLimitDefault = 400000

-
Zircuit Mainnet (48900)

+

Ink Mainnet (57073)

```toml AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false -ChainType = 'zircuit' -FinalityDepth = 1000 +ChainType = 'optimismBedrock' +FinalityDepth = 3000 FinalityTagEnabled = true -LinkContractAddress = '0x5D6d033B4FbD2190D99D930719fAbAcB64d2439a' LogBackfillBatchSize = 1000 LogPollInterval = '2s' LogKeepBlocksDepth = 100000 @@ -7719,40 +8720,42 @@ BackupLogPollerBlockDelay = 100 MinIncomingConfirmations = 3 MinContractPayment = '0.00001 link' NonceAutoSync = true -NoNewHeadsThreshold = '40s' +NoNewHeadsThreshold = '3m0s' LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 -NoNewFinalizedHeadsThreshold = '15m0s' +NoNewFinalizedHeadsThreshold = '1h0m0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 ReaperInterval = '1h0m0s' ReaperThreshold = '168h0m0s' -ResendAfterThreshold = '30s' +ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] -Enabled = true -Threshold = 90 -MinAttempts = 3 +Enabled = false + +[Transactions.TransactionManagerV2] +Enabled = false [BalanceMonitor] Enabled = true [GasEstimator] -Mode = 'BlockHistory' +Mode = 'FeeHistory' PriceDefault = '20 gwei' PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' -PriceMin = '1 wei' +PriceMin = '1 gwei' LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 EstimateLimit = false -BumpMin = '100 wei' +BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 EIP1559DynamicFees = true @@ -7762,20 +8765,20 @@ TipCapMin = '1 wei' [GasEstimator.BlockHistory] BatchSize = 25 -BlockHistorySize = 24 +BlockHistorySize = 100 CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 [GasEstimator.FeeHistory] -CacheTimeout = '10s' +CacheTimeout = '2s' [GasEstimator.DAOracle] OracleType = 'opstack' OracleAddress = '0x420000000000000000000000000000000000000F' [HeadTracker] -HistoryDepth = 2000 +HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 @@ -7786,7 +8789,7 @@ PersistenceEnabled = true PollFailureThreshold = 5 PollInterval = '10s' SelectionMode = 'HighestHead' -SyncThreshold = 10 +SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' @@ -7795,7 +8798,7 @@ DeathDeclarationDelay = '1m0s' NewHeadsPollInterval = '0s' [OCR] -ContractConfirmations = 1 +ContractConfirmations = 4 ContractTransmitterTransmitTimeout = '10s' DatabaseTimeout = '10s' DeltaCOverride = '168h0m0s' @@ -7804,7 +8807,7 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] -GasLimit = 6500000 +GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 @@ -7836,6 +8839,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -7846,6 +8850,9 @@ ResendAfterThreshold = '3m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -7939,6 +8946,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -7951,6 +8959,9 @@ Enabled = true Threshold = 50 MinAttempts = 3 +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -8044,6 +9055,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -8056,6 +9068,9 @@ Enabled = true Threshold = 50 MinAttempts = 3 +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -8150,6 +9165,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -8160,6 +9176,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -8254,6 +9273,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '1h50m0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -8264,6 +9284,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -8362,6 +9385,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 5000 @@ -8372,6 +9396,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -8465,6 +9492,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '12m0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 5000 @@ -8475,6 +9503,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -8568,6 +9599,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '5m0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -8578,6 +9610,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -8672,6 +9707,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -8682,6 +9718,9 @@ ResendAfterThreshold = '30s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -8780,6 +9819,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '12m0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -8790,6 +9830,9 @@ ResendAfterThreshold = '30s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -8889,6 +9932,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -8899,6 +9943,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -8997,6 +10044,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -9007,6 +10055,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -9104,6 +10155,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -9114,6 +10166,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -9211,6 +10266,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -9222,6 +10278,9 @@ ResendAfterThreshold = '1m0s' Enabled = true DetectionApiUrl = 'https://sepolia-venus.scroll.io' +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -9320,6 +10379,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -9331,6 +10391,9 @@ ResendAfterThreshold = '1m0s' Enabled = true DetectionApiUrl = 'https://venus.scroll.io' +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -9404,6 +10467,118 @@ GasLimitDefault = 400000

+
Ink Testnet (763373)

+ +```toml +AutoCreateKey = true +BlockBackfillDepth = 10 +BlockBackfillSkip = false +ChainType = 'optimismBedrock' +FinalityDepth = 3000 +FinalityTagEnabled = true +LogBackfillBatchSize = 1000 +LogPollInterval = '2s' +LogKeepBlocksDepth = 100000 +LogPrunePageSize = 0 +BackupLogPollerBlockDelay = 100 +MinIncomingConfirmations = 3 +MinContractPayment = '0.00001 link' +NonceAutoSync = true +NoNewHeadsThreshold = '3m0s' +LogBroadcasterEnabled = true +RPCDefaultBatchSize = 250 +RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 +NoNewFinalizedHeadsThreshold = '1h0m0s' + +[Transactions] +Enabled = true +ForwardersEnabled = false +MaxInFlight = 16 +MaxQueued = 250 +ReaperInterval = '1h0m0s' +ReaperThreshold = '168h0m0s' +ResendAfterThreshold = '1m0s' + +[Transactions.AutoPurge] +Enabled = false + +[Transactions.TransactionManagerV2] +Enabled = false + +[BalanceMonitor] +Enabled = true + +[GasEstimator] +Mode = 'FeeHistory' +PriceDefault = '20 gwei' +PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' +PriceMin = '1 gwei' +LimitDefault = 500000 +LimitMax = 500000 +LimitMultiplier = '1' +LimitTransfer = 21000 +EstimateLimit = false +BumpMin = '5 gwei' +BumpPercent = 20 +BumpThreshold = 3 +EIP1559DynamicFees = true +FeeCapDefault = '100 gwei' +TipCapDefault = '1 wei' +TipCapMin = '1 wei' + +[GasEstimator.BlockHistory] +BatchSize = 25 +BlockHistorySize = 100 +CheckInclusionBlocks = 12 +CheckInclusionPercentile = 90 +TransactionPercentile = 60 + +[GasEstimator.FeeHistory] +CacheTimeout = '2s' + +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x420000000000000000000000000000000000000F' + +[HeadTracker] +HistoryDepth = 100 +MaxBufferSize = 3 +SamplingInterval = '1s' +MaxAllowedFinalityDepth = 10000 +FinalityTagBypass = true +PersistenceEnabled = true + +[NodePool] +PollFailureThreshold = 5 +PollInterval = '10s' +SelectionMode = 'HighestHead' +SyncThreshold = 5 +LeaseDuration = '0s' +NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = true +DeathDeclarationDelay = '1m0s' +NewHeadsPollInterval = '0s' + +[OCR] +ContractConfirmations = 4 +ContractTransmitterTransmitTimeout = '10s' +DatabaseTimeout = '10s' +DeltaCOverride = '168h0m0s' +DeltaCJitterOverride = '1h0m0s' +ObservationGracePeriod = '1s' + +[OCR2] +[OCR2.Automation] +GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 +``` + +

+
BOB Testnet (808813)

```toml @@ -9429,6 +10604,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '1h50m0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -9439,6 +10615,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -9537,6 +10716,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -9547,6 +10727,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -9641,6 +10824,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '15m0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -9651,6 +10835,9 @@ ResendAfterThreshold = '30s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -9749,6 +10936,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -9759,6 +10947,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -9853,6 +11044,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -9863,6 +11055,9 @@ ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] Enabled = false +[Transactions.TransactionManagerV2] +Enabled = false + [BalanceMonitor] Enabled = true @@ -10138,6 +11333,7 @@ Set to zero to disable. ## EVM.Transactions ```toml [EVM.Transactions] +Enabled = true # Default ForwardersEnabled = false # Default MaxInFlight = 16 # Default MaxQueued = 250 # Default @@ -10147,6 +11343,12 @@ ResendAfterThreshold = '1m' # Default ``` +### Enabled +```toml +Enabled = true # Default +``` +Enabled is a feature flag for the Transaction Manager. This flag also enables or disables the gas estimator since it is dependent on the TXM to start it. + ### ForwardersEnabled ```toml ForwardersEnabled = false # Default @@ -10227,6 +11429,40 @@ MinAttempts = 3 # Example ``` MinAttempts configures the minimum number of broadcasted attempts a transaction has to have before it is evaluated further for being terminally stuck. This threshold is only applied if there is no custom API to identify stuck transactions provided by the chain. Ensure the gas estimator configs take more bump attempts before reaching the configured max gas price. +## EVM.Transactions.TransactionManagerV2 +```toml +[EVM.Transactions.TransactionManagerV2] +Enabled = false # Default +BlockTime = '10s' # Example +CustomURL = 'https://example.api.io' # Example +DualBroadcast = false # Example +``` + + +### Enabled +```toml +Enabled = false # Default +``` +Enabled enables TransactionManagerV2. + +### BlockTime +```toml +BlockTime = '10s' # Example +``` +BlockTime controls the frequency of the backfill loop of TransactionManagerV2. + +### CustomURL +```toml +CustomURL = 'https://example.api.io' # Example +``` +CustomURL configures the base url of a custom endpoint used by the ChainDualBroadcast chain type. + +### DualBroadcast +```toml +DualBroadcast = false # Example +``` +DualBroadcast enables DualBroadcast functionality. + ## EVM.BalanceMonitor ```toml [EVM.BalanceMonitor] @@ -11182,6 +12418,7 @@ OCR2CacheTTL = '1m' # Default TxTimeout = '1m' # Default TxRetryTimeout = '10s' # Default TxConfirmTimeout = '30s' # Default +TxExpirationRebroadcast = false # Default TxRetentionTimeout = '0s' # Default SkipPreflight = true # Default Commitment = 'confirmed' # Default @@ -11252,6 +12489,13 @@ TxConfirmTimeout = '30s' # Default ``` TxConfirmTimeout is the duration to wait when confirming a tx signature, before discarding as unconfirmed. +### TxExpirationRebroadcast +```toml +TxExpirationRebroadcast = false # Default +``` +TxExpirationRebroadcast enables or disables transaction rebroadcast if expired. Expiration check is performed every `ConfirmPollPeriod` +A transaction is considered expired if the blockhash it was sent with is 150 blocks older than the latest blockhash. + ### TxRetentionTimeout ```toml TxRetentionTimeout = '0s' # Default diff --git a/go.md b/go.md index 9f51ecd4c81..5a9081747f2 100644 --- a/go.md +++ b/go.md @@ -37,6 +37,8 @@ flowchart LR click chainlink-data-streams href "https://github.com/smartcontractkit/chainlink-data-streams" chainlink-feeds --> chainlink-common click chainlink-feeds href "https://github.com/smartcontractkit/chainlink-feeds" + chainlink-framework/multinode --> chainlink-common + click chainlink-framework/multinode href "https://github.com/smartcontractkit/chainlink-framework" chainlink-protos/orchestrator --> wsrpc click chainlink-protos/orchestrator href "https://github.com/smartcontractkit/chainlink-protos" chainlink-solana --> chainlink-common @@ -48,6 +50,7 @@ flowchart LR chainlink/v2 --> chainlink-cosmos chainlink/v2 --> chainlink-data-streams chainlink/v2 --> chainlink-feeds + chainlink/v2 --> chainlink-framework/multinode chainlink/v2 --> chainlink-protos/orchestrator chainlink/v2 --> chainlink-solana chainlink/v2 --> chainlink-starknet/relayer @@ -105,6 +108,8 @@ flowchart LR chainlink-ccip --> chain-selectors chainlink-ccip --> chainlink-common click chainlink-ccip href "https://github.com/smartcontractkit/chainlink-ccip" + chainlink-ccip/chains/solana --> chainlink-common + click chainlink-ccip/chains/solana href "https://github.com/smartcontractkit/chainlink-ccip" chainlink-common --> grpc-proxy chainlink-common --> libocr click chainlink-common href "https://github.com/smartcontractkit/chainlink-common" @@ -114,6 +119,8 @@ flowchart LR click chainlink-data-streams href "https://github.com/smartcontractkit/chainlink-data-streams" chainlink-feeds --> chainlink-common click chainlink-feeds href "https://github.com/smartcontractkit/chainlink-feeds" + chainlink-framework/multinode --> chainlink-common + click chainlink-framework/multinode href "https://github.com/smartcontractkit/chainlink-framework" chainlink-protos/job-distributor click chainlink-protos/job-distributor href "https://github.com/smartcontractkit/chainlink-protos" chainlink-protos/orchestrator --> wsrpc @@ -122,6 +129,8 @@ flowchart LR click chainlink-solana href "https://github.com/smartcontractkit/chainlink-solana" chainlink-starknet/relayer --> chainlink-common click chainlink-starknet/relayer href "https://github.com/smartcontractkit/chainlink-starknet" + chainlink-testing-framework/framework + click chainlink-testing-framework/framework href "https://github.com/smartcontractkit/chainlink-testing-framework" chainlink-testing-framework/havoc --> chainlink-testing-framework/lib/grafana click chainlink-testing-framework/havoc href "https://github.com/smartcontractkit/chainlink-testing-framework" chainlink-testing-framework/lib --> chainlink-testing-framework/seth @@ -136,7 +145,9 @@ flowchart LR chainlink/core/scripts --> chainlink/deployment click chainlink/core/scripts href "https://github.com/smartcontractkit/chainlink" chainlink/deployment --> ccip-owner-contracts + chainlink/deployment --> chainlink-ccip/chains/solana chainlink/deployment --> chainlink-protos/job-distributor + chainlink/deployment --> chainlink-testing-framework/framework chainlink/deployment --> chainlink-testing-framework/lib chainlink/deployment --> chainlink/v2 click chainlink/deployment href "https://github.com/smartcontractkit/chainlink" @@ -150,6 +161,7 @@ flowchart LR chainlink/v2 --> chainlink-cosmos chainlink/v2 --> chainlink-data-streams chainlink/v2 --> chainlink-feeds + chainlink/v2 --> chainlink-framework/multinode chainlink/v2 --> chainlink-protos/orchestrator chainlink/v2 --> chainlink-solana chainlink/v2 --> chainlink-starknet/relayer @@ -178,6 +190,12 @@ flowchart LR end click chainlink-repo href "https://github.com/smartcontractkit/chainlink" + subgraph chainlink-ccip-repo[chainlink-ccip] + chainlink-ccip + chainlink-ccip/chains/solana + end + click chainlink-ccip-repo href "https://github.com/smartcontractkit/chainlink-ccip" + subgraph chainlink-protos-repo[chainlink-protos] chainlink-protos/job-distributor chainlink-protos/orchestrator @@ -185,6 +203,7 @@ flowchart LR click chainlink-protos-repo href "https://github.com/smartcontractkit/chainlink-protos" subgraph chainlink-testing-framework-repo[chainlink-testing-framework] + chainlink-testing-framework/framework chainlink-testing-framework/havoc chainlink-testing-framework/lib chainlink-testing-framework/lib/grafana @@ -200,5 +219,5 @@ flowchart LR click tdh2-repo href "https://github.com/smartcontractkit/tdh2" classDef outline stroke-dasharray:6,fill:none; - class chainlink-repo,chainlink-protos-repo,chainlink-testing-framework-repo,tdh2-repo outline + class chainlink-repo,chainlink-ccip-repo,chainlink-protos-repo,chainlink-testing-framework-repo,tdh2-repo outline ``` diff --git a/go.mod b/go.mod index 1767da64153..b0f817a5ca4 100644 --- a/go.mod +++ b/go.mod @@ -19,6 +19,7 @@ require ( github.com/danielkov/gin-helmet v0.0.0-20171108135313-1387e224435e github.com/deckarep/golang-set/v2 v2.6.0 github.com/dominikbraun/graph v0.23.0 + github.com/doyensec/safeurl v0.2.1 github.com/esote/minmaxheap v1.0.0 github.com/ethereum/go-ethereum v1.14.11 github.com/fatih/color v1.17.0 @@ -68,7 +69,7 @@ require ( github.com/pressly/goose/v3 v3.21.1 github.com/prometheus/client_golang v1.20.5 github.com/prometheus/client_model v0.6.1 - github.com/prometheus/common v0.60.0 + github.com/prometheus/common v0.60.1 github.com/prometheus/prometheus v0.54.1 github.com/robfig/cron/v3 v3.0.1 github.com/rogpeppe/go-internal v1.13.1 @@ -78,20 +79,21 @@ require ( github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chain-selectors v1.0.34 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241213122413-5e8f65dd6b1b - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241214155818-b403079b2805 + github.com/smartcontractkit/chainlink-ccip v0.0.0-20250120130359-cc025272bbff + github.com/smartcontractkit/chainlink-common v0.4.2-0.20250116214855-f49c5c27db51 github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e - github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3 + github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250115135646-ac859d85e7e3 github.com/smartcontractkit/chainlink-feeds v0.1.1 + github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250115203616-a2ea5e50b260 github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0 - github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241210172617-6fd1891d0fbc - github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 - github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 + github.com/smartcontractkit/chainlink-solana v1.1.1-0.20250117143722-fb6416c087a5 + github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20250117171710-b6481e9fcb34 + github.com/smartcontractkit/libocr v0.0.0-20241223215956-e5b78d8e3919 github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de - github.com/smartcontractkit/wsrpc v0.8.3 + github.com/smartcontractkit/wsrpc v0.8.2 github.com/spf13/cast v1.6.0 - github.com/stretchr/testify v1.9.0 + github.com/stretchr/testify v1.10.0 github.com/test-go/testify v1.1.4 github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a github.com/tidwall/gjson v1.17.0 @@ -108,6 +110,7 @@ require ( go.opentelemetry.io/otel/metric v1.31.0 go.opentelemetry.io/otel/sdk/metric v1.31.0 go.opentelemetry.io/otel/trace v1.31.0 + go.uber.org/atomic v1.11.0 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.27.0 golang.org/x/crypto v0.31.0 @@ -151,12 +154,14 @@ require ( github.com/apache/arrow-go/v18 v18.0.0 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c // indirect + github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect github.com/bits-and-blooms/bitset v1.13.0 // indirect github.com/blendle/zapdriver v1.3.1 // indirect + github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129 // indirect github.com/buger/jsonparser v1.1.1 // indirect github.com/bytecodealliance/wasmtime-go/v23 v23.0.0 // indirect github.com/bytedance/sonic v1.11.6 // indirect @@ -206,6 +211,7 @@ require ( github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/gagliardetto/binary v0.7.7 // indirect github.com/gagliardetto/treeout v0.1.4 // indirect + github.com/gagliardetto/utilz v0.1.1 // indirect github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813 // indirect github.com/gin-contrib/sse v0.1.0 // indirect @@ -248,6 +254,7 @@ require ( github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/gtank/merlin v0.1.1 // indirect github.com/gtank/ristretto255 v0.1.2 // indirect + github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026 // indirect github.com/hashicorp/go-bexpr v0.1.10 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-hclog v1.6.3 // indirect @@ -287,6 +294,7 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect github.com/mfridman/interpolate v0.0.2 // indirect + github.com/miekg/dns v1.1.61 // indirect github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect @@ -305,7 +313,7 @@ require ( github.com/opencontainers/image-spec v1.1.0 // indirect github.com/opencontainers/runc v1.1.10 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect - github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect + github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pierrec/lz4/v4 v4.1.21 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect @@ -314,11 +322,12 @@ require ( github.com/rivo/uniseg v0.4.4 // indirect github.com/rs/cors v1.9.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/ryanuber/go-glob v1.0.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sanity-io/litter v1.5.5 // indirect github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect - github.com/sasha-s/go-deadlock v0.3.1 // indirect + github.com/sasha-s/go-deadlock v0.3.5 // indirect github.com/sethvargo/go-retry v0.2.4 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect diff --git a/go.sum b/go.sum index 8c7327b4997..23ecaeca29d 100644 --- a/go.sum +++ b/go.sum @@ -167,6 +167,8 @@ github.com/aws/aws-sdk-go v1.22.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.54.19 h1:tyWV+07jagrNiCcGRzRhdtVjQs7Vy41NwsuOcl0IbVI= github.com/aws/aws-sdk-go v1.54.19/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= +github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 h1:WWB576BN5zNSZc/M9d/10pqEx5VHNhaQ/yOVAkmj5Yo= +github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -196,6 +198,8 @@ github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6 github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= +github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129 h1:gfAMKE626QEuKG3si0pdTRcr/YEbBoxY+3GOH3gWvl4= +github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129/go.mod h1:u9UyCz2eTrSGy6fbupqJ54eY5c4IC8gREQ1053dK12U= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/bytecodealliance/wasmtime-go/v23 v23.0.0 h1:NJvU4S8KEk1GnF6+FvlnzMD/8wXTj/mYJSG6Q4yu3Pw= @@ -354,6 +358,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dominikbraun/graph v0.23.0 h1:TdZB4pPqCLFxYhdyMFb1TBdFxp8XLcJfTTBQucVPgCo= github.com/dominikbraun/graph v0.23.0/go.mod h1:yOjYyogZLY1LSG9E33JWZJiq5k83Qy2C6POAuiViluc= +github.com/doyensec/safeurl v0.2.1 h1:DY15JorEfQsnpBWhBkVQIkaif2jfxCC14PIuGDsjDVs= +github.com/doyensec/safeurl v0.2.1/go.mod h1:wzSXqC/6Z410qHz23jtBWT+wQ8yTxcY0p8bZH/4EZIg= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= @@ -402,10 +408,13 @@ github.com/gagliardetto/binary v0.7.7 h1:QZpT38+sgoPg+TIQjH94sLbl/vX+nlIRA37pEyO github.com/gagliardetto/binary v0.7.7/go.mod h1:mUuay5LL8wFVnIlecHakSZMvcdqfs+CsotR5n77kyjM= github.com/gagliardetto/gofuzz v1.2.2 h1:XL/8qDMzcgvR4+CyRQW9UGdwPRPMHVJfqQ/uMvSUuQw= github.com/gagliardetto/gofuzz v1.2.2/go.mod h1:bkH/3hYLZrMLbfYWA0pWzXmi5TTRZnu4pMGZBkqMKvY= +github.com/gagliardetto/hashsearch v0.0.0-20191005111333-09dd671e19f9/go.mod h1:513DXpQPzeRo7d4dsCP3xO3XI8hgvruMl9njxyQeraQ= github.com/gagliardetto/solana-go v1.8.4 h1:vmD/JmTlonyXGy39bAo0inMhmbdAwV7rXZtLDMZeodE= github.com/gagliardetto/solana-go v1.8.4/go.mod h1:i+7aAyNDTHG0jK8GZIBSI4OVvDqkt2Qx+LklYclRNG8= github.com/gagliardetto/treeout v0.1.4 h1:ozeYerrLCmCubo1TcIjFiOWTTGteOOHND1twdFpgwaw= github.com/gagliardetto/treeout v0.1.4/go.mod h1:loUefvXTrlRG5rYmJmExNryyBRh8f89VZhmMOyCyqok= +github.com/gagliardetto/utilz v0.1.1 h1:/etW4hl607emKg6R6Lj9jRJ9d6ue2AQOyjhuAwjzs1U= +github.com/gagliardetto/utilz v0.1.1/go.mod h1:b+rGFkRHz3HWJD0RYMzat47JyvbTtpE0iEcYTRJTLLA= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813 h1:Uc+IZ7gYqAf/rSGFplbWBSHaGolEQlNLgMgSE3ccnIQ= @@ -654,6 +663,8 @@ github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is= github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc= github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o= +github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026 h1:BpJ2o0OR5FV7vrkDYfXYVJQeMNWa8RhklZOpW2ITAIQ= +github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026/go.mod h1:5Scbynm8dF1XAPwIwkGPqzkM/shndPm79Jd1003hTjE= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.16.0 h1:SE9m0W6DEfgIVCJX7xU+iv/hUl4m/nxqMTnCdMxDpJ8= @@ -905,6 +916,9 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5 github.com/mfridman/interpolate v0.0.2 h1:pnuTK7MQIxxFz1Gr+rjSIx9u7qVjf5VOoM/u6BbAxPY= github.com/mfridman/interpolate v0.0.2/go.mod h1:p+7uk6oE07mpE/Ik1b8EckO0O4ZXiGAfshKBWLUM9Xg= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= +github.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs= +github.com/miekg/dns v1.1.61/go.mod h1:mnAarhS3nWaW+NVP2wTkYVIZyHNJ098SJZUki3eykwQ= github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 h1:QRUSJEgZn2Snx0EmT/QLXibWjSUDjKWvXIT19NBVp94= github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= @@ -1011,9 +1025,8 @@ github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCko github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= -github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= -github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 h1:hDSdbBuw3Lefr6R18ax0tZ2BJeNB3NehB3trOwYBsdU= -github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 h1:Dx7Ovyv/SFnMFw3fD4oEoeorXc6saIiQ23LrGLth0Gw= +github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= @@ -1051,8 +1064,8 @@ github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7q github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= -github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= +github.com/prometheus/common v0.60.1 h1:FUas6GcOw66yB/73KC+BOZoFJmbo/1pojoILArPAaSc= +github.com/prometheus/common v0.60.1/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -1096,6 +1109,8 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= +github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= @@ -1104,8 +1119,8 @@ github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQ github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= -github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= -github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= +github.com/sasha-s/go-deadlock v0.3.5 h1:tNCOEEDG6tBqrNDOX35j/7hL5FcFViG6awUGROb2NsU= +github.com/sasha-s/go-deadlock v0.3.5/go.mod h1:bugP6EGbdGYObIlx7pUZtWqlvo8k9H6vCBBsiChJQ5U= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/scylladb/go-reflectx v1.0.1 h1:b917wZM7189pZdlND9PbIJ6NQxfDPfBvUaQ7cjj1iZQ= github.com/scylladb/go-reflectx v1.0.1/go.mod h1:rWnOfDIRWBGN0miMLIcoPt/Dhi2doCMZqwMCJ3KupFc= @@ -1137,32 +1152,34 @@ github.com/smartcontractkit/chain-selectors v1.0.34 h1:MJ17OGu8+jjl426pcKrJkCf3f github.com/smartcontractkit/chain-selectors v1.0.34/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241213122413-5e8f65dd6b1b h1:iSQJ6ng4FhEswf8SXunGkaJlVP3E3JlgLB8Oo2f3Ud4= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241213122413-5e8f65dd6b1b/go.mod h1:F8xQAIW0ymb2BZhqn89sWZLXreJhM5KDVF6Qb4y44N0= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241214155818-b403079b2805 h1:Pz8jB/6qe10xT10h2S3LFYJrnebNpG5rJ/w16HZGwPQ= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241214155818-b403079b2805/go.mod h1:yti7e1+G9hhkYhj+L5sVUULn9Bn3bBL5/AxaNqdJ5YQ= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250120130359-cc025272bbff h1:ZEOlcleVdT0/y9V5yjgFJF0j7MpvdrFmKis/xmFNIgE= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250120130359-cc025272bbff/go.mod h1:JJZMCB75aVSAiPNW032F9WUKTlLztTd8bbQB5MEaZa4= +github.com/smartcontractkit/chainlink-common v0.4.2-0.20250116214855-f49c5c27db51 h1:YdjQiEu5uHWM1ApwdV+nLyJmu1+tt3IeiwPKNGoXwBI= +github.com/smartcontractkit/chainlink-common v0.4.2-0.20250116214855-f49c5c27db51/go.mod h1:yti7e1+G9hhkYhj+L5sVUULn9Bn3bBL5/AxaNqdJ5YQ= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3 h1:aeiBdBHGY8QNftps+VqrIk6OnfeeOD5z4jrAabW4ZSc= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3/go.mod h1:AS6zY2BkcRwfiGzNabGbHhfrLSrXrcI/GmjnT4jQ5/s= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250115135646-ac859d85e7e3 h1:GcPYNVFYjB065CNq0h8nK/VeU08nUkHgBX0cJIEpuHY= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250115135646-ac859d85e7e3/go.mod h1:pDZagSGjs9U+l4YIFhveDznMHqxuuz+5vRxvVgpbdr8= github.com/smartcontractkit/chainlink-feeds v0.1.1 h1:JzvUOM/OgGQA1sOqTXXl52R6AnNt+Wg64sVG+XSA49c= github.com/smartcontractkit/chainlink-feeds v0.1.1/go.mod h1:55EZ94HlKCfAsUiKUTNI7QlE/3d3IwTlsU3YNa/nBb4= +github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250115203616-a2ea5e50b260 h1:See2isL6KdrTJDlVKWv8qiyYqWhYUcubU2e5yKXV1oY= +github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250115203616-a2ea5e50b260/go.mod h1:4JqpgFy01LaqG1yM2iFTzwX3ZgcAvW9WdstBZQgPHzU= github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0 h1:ZBat8EBvE2LpSQR9U1gEbRV6PfAkiFdINmQ8nVnXIAQ= github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241210172617-6fd1891d0fbc h1:dssRwJhmzJkUN/OajaDj2GsxBn+Tupk3bI1BkPEoJg0= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241210172617-6fd1891d0fbc/go.mod h1:p8aUDfJeley6oer7y+Ucd3edOtRlMTnWg3mN6rhaLWo= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 h1:tNS7U9lrxkFvEuyxQv11HHOiV9LPDGC9wYEy+yM/Jv4= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8/go.mod h1:EBrEgcdIbwepqguClkv8Ohy7CbyWSJaE4EC9aBJlQK0= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20250117143722-fb6416c087a5 h1:kDW6Ab8vGRK2y+DPEvvhU2It8UCS9FK5ZQqIVjDfpK4= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20250117143722-fb6416c087a5/go.mod h1:uHVnYLMgJ1rTcNoVxhBpy38t69gXq0j+LN3TkcIVE3U= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20250117171710-b6481e9fcb34 h1:tQCjnIjY88AClWXApaTS+/ihQYM1GVCrbD9W00eh11E= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20250117171710-b6481e9fcb34/go.mod h1:lgG9JT2P19KnYuBheKIis5ZeCO+AaSta+RfzvwDQS2Y= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA= -github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 h1:NzZGjaqez21I3DU7objl3xExTH4fxYvzTqar8DC6360= -github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= +github.com/smartcontractkit/libocr v0.0.0-20241223215956-e5b78d8e3919 h1:IpGoPTXpvllN38kT2z2j13sifJMz4nbHglidvop7mfg= +github.com/smartcontractkit/libocr v0.0.0-20241223215956-e5b78d8e3919/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de h1:n0w0rKF+SVM+S3WNlup6uabXj2zFlFNfrlsKCMMb/co= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:Sl2MF/Fp3fgJIVzhdGhmZZX2BlnM0oUUyBP4s4xYb6o= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de h1:66VQxXx3lvTaAZrMBkIcdH9VEjujUEvmBQdnyOJnkOc= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:NSc7hgOQbXG3DAwkOdWnZzLTZENXSwDJ7Va1nBp0YU0= -github.com/smartcontractkit/wsrpc v0.8.3 h1:9tDf7Ut61g36RJIyxV9iI73SqoOMasKPfURV9oMLrPg= -github.com/smartcontractkit/wsrpc v0.8.3/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= +github.com/smartcontractkit/wsrpc v0.8.2 h1:XB/xcn/MMseHW+8JE8+a/rceA86ck7Ur6cEa9LiUC8M= +github.com/smartcontractkit/wsrpc v0.8.2/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= @@ -1220,8 +1237,9 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= @@ -1598,6 +1616,7 @@ golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/integration-tests/.gitignore b/integration-tests/.gitignore new file mode 100644 index 00000000000..43803dd8728 --- /dev/null +++ b/integration-tests/.gitignore @@ -0,0 +1,4 @@ +vendor +# secret files in config +**/**/network_config.toml +**/**/secrets.toml \ No newline at end of file diff --git a/integration-tests/.golangci.yml b/integration-tests/.golangci.yml index 8969110d988..957d11e04ff 100644 --- a/integration-tests/.golangci.yml +++ b/integration-tests/.golangci.yml @@ -1,15 +1,32 @@ run: timeout: 15m + allow-parallel-runners: true linters: enable: + - containedctx + - depguard + - errname + - errorlint - exhaustive - - exportloopref - - revive + - fatcontext + - ginkgolinter + - gocritic - goimports - gosec + - loggercheck + - mirror - misspell + - noctx + - nolintlint + - perfsprint + - prealloc + - revive - rowserrcheck - - errorlint + - spancheck + - sqlclosecheck + - testifylint + - unconvert + - whitespace linters-settings: exhaustive: default-signifies-exhaustive: true @@ -23,6 +40,28 @@ linters-settings: govet: enable: - shadow + settings: + printf: + # Additionally check chainlink custom loggers + funcs: + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Tracef + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Debugf + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Infof + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Warnf + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Errorf + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Criticalf + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Panicf + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Fatalf + - (github.com/smartcontractkit/chainlink/v2/core/logger.SugaredLogger).AssumptionViolationf + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Debugf + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Infof + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Warnf + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Errorf + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Panicf + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Fatalf + - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).AssumptionViolationf + - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).Tracef + - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).Criticalf revive: confidence: 0.8 rules: @@ -33,9 +72,10 @@ linters-settings: - name: error-return - name: error-strings - name: error-naming + - name: exported - name: if-return - name: increment-decrement - # - name: var-naming // doesn't work with some generated names + - name: var-naming - name: var-declaration - name: package-comments - name: range @@ -46,7 +86,7 @@ linters-settings: - name: errorf - name: empty-block - name: superfluous-else - #- name: unused-parameter + # - name: unused-parameter - name: unreachable-code - name: redefines-builtin-id - name: waitgroup-by-value @@ -61,13 +101,69 @@ linters-settings: - name: identical-branches - name: get-return # - name: flag-parameter // probably one we should work on doing better at in the future - # - name: early-return // probably one we should work on doing better at in the future + - name: early-return - name: defer - name: constant-logical-expr - name: confusing-naming - name: confusing-results - name: bool-literal-in-expr - name: atomic + depguard: + rules: + main: + list-mode: lax + deny: + - pkg: cosmossdk.io/errors + desc: Use the standard library instead + - pkg: github.com/gofrs/uuid + desc: Use github.com/google/uuid instead + - pkg: github.com/jackc/pgx3 + desc: Use github.com/jackc/pgx4 instead + - pkg: github.com/jackc/pgx5 + desc: Use github.com/jackc/pgx4 instead + - pkg: github.com/satori/go.uuid + desc: Use github.com/google/uuid instead + - pkg: github.com/test-go/testify/assert + desc: Use github.com/stretchr/testify/assert instead + - pkg: github.com/test-go/testify/mock + desc: Use github.com/stretchr/testify/mock instead + - pkg: github.com/test-go/testify/require + desc: Use github.com/stretchr/testify/require instead + - pkg: go.uber.org/multierr + desc: Use the standard library instead, for example https://pkg.go.dev/errors#Join + - pkg: gopkg.in/guregu/null.v1 + desc: Use gopkg.in/guregu/null.v4 instead + - pkg: gopkg.in/guregu/null.v2 + desc: Use gopkg.in/guregu/null.v4 instead + - pkg: gopkg.in/guregu/null.v3 + desc: Use gopkg.in/guregu/null.v4 instead + - pkg: github.com/go-gorm/gorm + desc: Use github.com/jmoiron/sqlx directly instead + loggercheck: + # Check that *w logging functions have even number of args (i.e., well formed key-value pairs). + rules: + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Tracew + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Debugw + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Infow + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Warnw + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Errorw + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Criticalw + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Panicw + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Fatalw + - (github.com/smartcontractkit/chainlink/v2/core/logger.SugaredLogger).AssumptionViolationw + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Debugw + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Infow + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Warnw + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Errorw + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Panicw + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Fatalw + - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).AssumptionViolationw + - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).Tracew + - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).Criticalw + - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).With + nolintlint: + require-specific: true + require-explanation: true issues: exclude-rules: - text: "^G404: Use of weak random number generator" diff --git a/integration-tests/actions/actions.go b/integration-tests/actions/actions.go index 53283967976..5a3f0b6c70b 100644 --- a/integration-tests/actions/actions.go +++ b/integration-tests/actions/actions.go @@ -4,6 +4,7 @@ package actions import ( "context" "crypto/ecdsa" + "encoding/json" "fmt" "math" "math/big" @@ -13,6 +14,7 @@ import ( "testing" "time" + "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/pelletier/go-toml/v2" geth "github.com/ethereum/go-ethereum" @@ -697,6 +699,45 @@ func ConfigureOCRv2AggregatorContracts( return nil } +// ReturnFunds attempts to return all the funds from the chainlink nodes to the network's default address +// all from a remote, k8s style environment +// Remove this once ccip-tests are moved to seth client +func ReturnFunds(lggr zerolog.Logger, chainlinkNodes []*nodeclient.ChainlinkK8sClient, blockchainClient blockchain.EVMClient) error { + if blockchainClient == nil { + return errors.New("blockchain client is nil, unable to return funds from chainlink nodes") + } + lggr.Info().Msg("Attempting to return Chainlink node funds to default network wallets") + if blockchainClient.NetworkSimulated() { + lggr.Info().Str("Network Name", blockchainClient.GetNetworkName()). + Msg("Network is a simulated network. Skipping fund return.") + return nil + } + + for _, chainlinkNode := range chainlinkNodes { + fundedKeys, err := chainlinkNode.ExportEVMKeysForChain(blockchainClient.GetChainID().String()) + if err != nil { + return err + } + for _, key := range fundedKeys { + keyToDecrypt, err := json.Marshal(key) + if err != nil { + return err + } + // This can take up a good bit of RAM and time. When running on the remote-test-runner, this can lead to OOM + // issues. So we avoid running in parallel; slower, but safer. + decryptedKey, err := keystore.DecryptKey(keyToDecrypt, nodeclient.ChainlinkKeyPassword) + if err != nil { + return err + } + err = blockchainClient.ReturnFunds(decryptedKey.PrivateKey) + if err != nil { + lggr.Error().Err(err).Str("Address", fundedKeys[0].Address).Msg("Error returning funds from Chainlink node") + } + } + } + return blockchainClient.WaitForEvents() +} + // TeardownSuite tears down networks/clients and environment and creates a logs folder for failed tests in the // specified path. Can also accept a testreporter (if one was used) to log further results func TeardownSuite( @@ -707,6 +748,7 @@ func TeardownSuite( optionalTestReporter testreporters.TestReporter, // Optionally pass in a test reporter to log further metrics failingLogLevel zapcore.Level, // Examines logs after the test, and fails the test if any Chainlink logs are found at or above provided level grafnaUrlProvider testreporters.GrafanaURLProvider, + evmClients ...blockchain.EVMClient, ) error { l := logging.GetTestLogger(t) if err := testreporters.WriteTeardownLogs(t, env, optionalTestReporter, failingLogLevel, grafnaUrlProvider); err != nil { @@ -730,6 +772,28 @@ func TeardownSuite( } else { l.Info().Msg("Successfully returned funds from chainlink nodes to default network wallets") } + // The following is needed for tests using EVMClient, + // Remove this once ccip-tests are moved to seth client + for _, c := range evmClients { + if c != nil && chainlinkNodes != nil && len(chainlinkNodes) > 0 { + if err := ReturnFunds(l, chainlinkNodes, c); err != nil { + // This printed line is required for tests that use real funds to propagate the failure + // out to the system running the test. Do not remove + fmt.Println(environment.FAILED_FUND_RETURN) + l.Error().Err(err).Str("Namespace", env.Cfg.Namespace). + Msg("Error attempting to return funds from chainlink nodes to network's default wallet. " + + "Environment is left running so you can try manually!") + } + } else { + l.Info().Msg("Successfully returned funds from chainlink nodes to default network wallets") + } + if c != nil { + err := c.Close() + if err != nil { + return err + } + } + } return env.Shutdown() } diff --git a/integration-tests/ccip-tests/Makefile b/integration-tests/ccip-tests/Makefile index 2702c36b027..4aebd4c4608 100644 --- a/integration-tests/ccip-tests/Makefile +++ b/integration-tests/ccip-tests/Makefile @@ -1,5 +1,5 @@ ## To Override the default config: -# example usage: make set_config override_toml=../config/config.toml network_config_toml=../config/network.toml +# example usage: make set_config override_toml=../config/config.toml .PHONY: set_config set_config: if [ -s "$(override_toml)" ]; then \ @@ -12,10 +12,6 @@ set_config: echo "No override config found, using default config"; \ echo > ./testconfig/override/.env; \ fi - if [ -s "$(network_config_toml)" ]; then \ - echo "Overriding network config with $(network_config_toml)"; \ - echo "export BASE64_NETWORK_CONFIG=$$(base64 -i $(network_config_toml))" >> ./testconfig/override/.env; \ - fi @echo "Checking for test secrets file in ~/.testsecrets..."; @if [ ! -f ~/.testsecrets ]; then \ @@ -71,3 +67,10 @@ test_smoke_ccip_default: set_config .PHONY: build_ccip_image build_ccip_image: docker build -f ../../core/chainlink.Dockerfile --build-arg COMMIT_SHA=$(git rev-parse HEAD) --build-arg CHAINLINK_USER=chainlink -t $(image):$(tag) ../../ + +# image: the name for the chainlink image being built, example: image=chainlink +# tag: the tag for the chainlink image being built, example: tag=latest +# example usage: make build_ccip_image image=chainlink-ccip tag=latest +.PHONY: build_ccip_debug_image +build_ccip_debug_image: + docker build -f ../../core/chainlink.debug.Dockerfile --build-arg COMMIT_SHA=$(git rev-parse HEAD) --build-arg CHAINLINK_USER=chainlink -t $(image):$(tag) ../../ diff --git a/integration-tests/ccip-tests/README.md b/integration-tests/ccip-tests/README.md index a4255928949..855cfcde699 100644 --- a/integration-tests/ccip-tests/README.md +++ b/integration-tests/ccip-tests/README.md @@ -34,6 +34,16 @@ For example, if you want to override the `Network` input in test and want to run export BASE64_CONFIG_OVERRIDE=$(base64 -i ./testconfig/override/mainnet.toml) ``` +3. Secrets - You also need to set some secrets. This is a mandatory step needed to run the tests. Please refer to [.testsecrets.example](./examples/.testsecrets.example) for the list of secrets and instruction how to set them up. + - The chainlink image is a required secret for all tests + - If you are running tests in live networks like testnet and mainnet, you need to set the secrets (rpc urls and private keys) for the respective networks. + +**Please note that the secrets should NOT be checked in to the repo and should be kept locally.** + +======= + export BASE64_CONFIG_OVERRIDE=$(base64 -i ./testconfig/override/mainnet.toml) + ``` + 3. Secrets - You also need to set some secrets. This is a mandatory step needed to run the tests. Please refer to [.testsecrets.example](./examples/.testsecrets.example) for the list of secrets and instruction how to set them up. - The chainlink image and tag are required secrets for all the tests. - If you are running tests in live networks like testnet and mainnet, you need to set the secrets (rpc urls and private keys) for the respective networks. @@ -50,6 +60,7 @@ You can run this command to ignore any changes to the file. git update-index --skip-worktree ``` +>>>>>>> v2.17.0 ## Running the Tests There are two ways to run the tests: diff --git a/integration-tests/ccip-tests/actions/ccip_helpers.go b/integration-tests/ccip-tests/actions/ccip_helpers.go index 492ee2fd0fa..56a06021db2 100644 --- a/integration-tests/ccip-tests/actions/ccip_helpers.go +++ b/integration-tests/ccip-tests/actions/ccip_helpers.go @@ -4,6 +4,7 @@ import ( "context" crypto_rand "crypto/rand" "encoding/base64" + "encoding/hex" "encoding/json" "fmt" "math/big" @@ -31,8 +32,6 @@ import ( "golang.org/x/exp/rand" "golang.org/x/sync/errgroup" - "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" - chainselectors "github.com/smartcontractkit/chain-selectors" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" @@ -44,6 +43,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/mockserver" "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/reorg" "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" "github.com/smartcontractkit/chainlink/deployment/environment/nodeclient" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/contracts/laneconfig" @@ -61,6 +61,8 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_contract" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_pool" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/ccipexec" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers" integrationtesthelpers "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers/integration" @@ -87,6 +89,7 @@ const ( // DefaultResubscriptionTimeout denotes the max backoff duration for resubscription for various watch events // if the subscription keeps failing even after this duration, the test will fail DefaultResubscriptionTimeout = 2 * time.Hour + LBTCValidDestPoolData = "9b11457aa29d65e4940b67b7da16bd370d29bf6a3247a28066f93ac407b8b811" ) // TODO: These should be refactored along with the default CCIP test setup to use optional config functions @@ -175,6 +178,8 @@ type CCIPCommon struct { MulticallContract common.Address ExistingDeployment bool USDCMockDeployment *bool + LBTCMockDeployment *bool + LBTCDestPoolDataAs32Bytes *bool TokenMessenger *common.Address TokenTransmitter *contracts.TokenTransmitter IsConnectionRestoredRecently *atomic.Bool @@ -723,6 +728,10 @@ func (ccipModule *CCIPCommon) IsUSDCDeployment() bool { return pointer.GetBool(ccipModule.USDCMockDeployment) } +func (ccipModule *CCIPCommon) IsLBTCDeployment() bool { + return pointer.GetBool(ccipModule.LBTCMockDeployment) +} + func (ccipModule *CCIPCommon) WriteLaneConfig(conf *laneconfig.LaneConfig) { var btAddresses, btpAddresses []string priceAggrs := make(map[string]string) @@ -733,17 +742,16 @@ func (ccipModule *CCIPCommon) WriteLaneConfig(conf *laneconfig.LaneConfig) { for k, v := range ccipModule.PriceAggregators { priceAggrs[k.Hex()] = v.ContractAddress.Hex() } - conf.CommonContracts = laneconfig.CommonContracts{ - FeeToken: ccipModule.FeeToken.Address(), - BridgeTokens: btAddresses, - BridgeTokenPools: btpAddresses, - ARM: ccipModule.RMNContract.Hex(), - Router: ccipModule.Router.Address(), - PriceRegistry: ccipModule.PriceRegistry.Address(), - PriceAggregators: priceAggrs, - WrappedNative: ccipModule.WrappedNative.Hex(), - Multicall: ccipModule.MulticallContract.Hex(), - } + conf.CommonContracts.FeeToken = ccipModule.FeeToken.Address() + conf.CommonContracts.BridgeTokens = btAddresses + conf.CommonContracts.BridgeTokenPools = btpAddresses + conf.CommonContracts.ARM = ccipModule.RMNContract.Hex() + conf.CommonContracts.Router = ccipModule.Router.Address() + conf.CommonContracts.PriceRegistry = ccipModule.PriceRegistry.Address() + conf.CommonContracts.PriceAggregators = priceAggrs + conf.CommonContracts.WrappedNative = ccipModule.WrappedNative.Hex() + conf.CommonContracts.Multicall = ccipModule.MulticallContract.Hex() + if ccipModule.TokenAdminRegistry != nil { conf.CommonContracts.TokenAdminRegistry = ccipModule.TokenAdminRegistry.Address() } @@ -883,7 +891,6 @@ func (ccipModule *CCIPCommon) DeployContracts( // deploy bridge token. for i := len(ccipModule.BridgeTokens); i < noOfTokens; i++ { var token *contracts.ERC20Token - if len(tokenDeployerFns) != noOfTokens { if ccipModule.IsUSDCDeployment() && i == 0 { // if it's USDC deployment, we deploy the burn mint token 677 with decimal 6 and cast it to ERC20Token @@ -929,6 +936,16 @@ func (ccipModule *CCIPCommon) DeployContracts( if err != nil { return fmt.Errorf("granting minter role to token transmitter shouldn't fail %w", err) } + } else if ccipModule.IsLBTCDeployment() && i == 0 { + // if it's LBTC deployment, we deploy the burn mint token 677 with decimal 8 and cast it to ERC20Token + lbtcToken, err := ccipModule.tokenDeployer.DeployCustomBurnMintERC677Token("Lombard LBTC", "LBTC", uint8(8), new(big.Int).Mul(big.NewInt(1e6), big.NewInt(1e18))) + if err != nil { + return fmt.Errorf("deploying bridge lbtc token contract shouldn't fail %w", err) + } + token, err = ccipModule.tokenDeployer.NewERC20TokenContract(lbtcToken.ContractAddress) + if err != nil { + return fmt.Errorf("getting new bridge lbtc token contract shouldn't fail %w", err) + } } else { // otherwise we deploy link token and cast it to ERC20Token linkToken, err := ccipModule.tokenDeployer.DeployLinkTokenContract() @@ -993,6 +1010,43 @@ func (ccipModule *CCIPCommon) DeployContracts( } ccipModule.BridgeTokenPools = append(ccipModule.BridgeTokenPools, usdcPool) + } else if ccipModule.IsLBTCDeployment() && i == 0 { + if ccipModule.RMNContract == nil { + return errors.New("RMNContract is not initialized") + } + rmnContract := *ccipModule.RMNContract + + destPoolData, err := hex.DecodeString(LBTCValidDestPoolData) // valid 32 bytes should call attestation api + if err != nil { + return errors.Wrapf(err, "decoding dest pool data shouldn't fail") + } + if !pointer.GetBool(ccipModule.LBTCDestPoolDataAs32Bytes) { + // non 32 bytes data should not call attestation api and instead consider it as deposit payload. + // lombard has both attested and non-attested flow + destPoolData = []byte{0x12, 0x34, 0x56, 0x78} + } + lbtcPool, err := ccipModule.tokenDeployer.DeployMockLBTCTokenPoolContract(token.Address(), rmnContract, ccipModule.Router.Instance.Address(), destPoolData) + if err != nil { + return errors.Wrapf(err, "deploying mock lbtc bridge token pool shouldn't fail") + } + lbtcInstance, err := burn_mint_erc677.NewBurnMintERC677(token.ContractAddress, ccipModule.ChainClient.Backend()) + if err != nil { + return errors.Wrapf(err, "failed to get dest usdc token instance") + } + opts, err := ccipModule.tokenDeployer.Client().TransactionOpts(token.OwnerWallet) + if err != nil { + return errors.Wrapf(err, "failed to get transaction opts") + } + tx, err := lbtcInstance.GrantMintAndBurnRoles(opts, common.HexToAddress(lbtcPool.Address())) + if err != nil { + return errors.Wrapf(err, "granting minter role to owner shouldn't fail") + } + err = ccipModule.tokenDeployer.Client().ProcessTransaction(tx) + if err != nil { + return errors.Wrapf(err, "failed to process grant mint role") + } + + ccipModule.BridgeTokenPools = append(ccipModule.BridgeTokenPools, lbtcPool) } else { // deploy lock release token pool in case of non-usdc deployment btp, err := ccipModule.tokenDeployer.DeployLockReleaseTokenPoolContract(token.Address(), *ccipModule.RMNContract, ccipModule.Router.Instance.Address()) @@ -1291,6 +1345,8 @@ func DefaultCCIPModule( ExistingDeployment: pointer.GetBool(testGroupConf.ExistingDeployment), MulticallEnabled: pointer.GetBool(testGroupConf.MulticallInOneTx), USDCMockDeployment: testGroupConf.USDCMockDeployment, + LBTCMockDeployment: testGroupConf.LBTCMockDeployment, + LBTCDestPoolDataAs32Bytes: testGroupConf.LBTCDestPoolDataAs32Bytes, NoOfTokensNeedingDynamicPrice: pointer.GetInt(testGroupConf.TokenConfig.NoOfTokensWithDynamicPrice), poolFunds: testhelpers.Link(5), gasUpdateWatcherMu: &sync.Mutex{}, @@ -1652,7 +1708,10 @@ func (sourceCCIP *SourceCCIPModule) IsRequestTriggeredWithinTimeframe(timeframe // IsPastRequestTriggeredWithinTimeframe determines the average block time and calculates the block numbers // within the specified timeframe. It then uses FilterCCIPSendRequested to identify the past events. -func (sourceCCIP *SourceCCIPModule) IsPastRequestTriggeredWithinTimeframe(ctx context.Context, timeframe *commonconfig.Duration) (*time.Time, error) { +func (sourceCCIP *SourceCCIPModule) IsPastRequestTriggeredWithinTimeframe( + ctx context.Context, + timeframe *commonconfig.Duration, +) (*types.Log, error) { if timeframe == nil { return nil, nil } @@ -1683,17 +1742,21 @@ func (sourceCCIP *SourceCCIPModule) IsPastRequestTriggeredWithinTimeframe(ctx co return nil, fmt.Errorf("error while filtering CCIP send requested starting block number: %d. Error: %w", filterFromBlock, err) } defer func() { - _ = iterator.Close() + iterErr := iterator.Close() + if iterErr != nil { + sourceCCIP.Common.Logger.Error().Err(iterErr).Msg("Error closing iterator") + } }() - if iterator.Next() { - hdr, err := sourceCCIP.Common.ChainClient.HeaderByNumber(context.Background(), new(big.Int).SetUint64(iterator.Event.Raw.BlockNumber)) - if err != nil { - return nil, fmt.Errorf("error getting header for block: %d, Error: %w", iterator.Event.Raw.BlockNumber, err) + lastBlockNumber := uint64(0) + var latestEvent *types.Log + for iterator.Next() { + blockNum := iterator.Event.Raw.BlockNumber + if blockNum > lastBlockNumber { + lastBlockNumber = blockNum + latestEvent = &iterator.Event.Raw } - return pointer.ToTime(hdr.Timestamp), nil } - - return nil, nil + return latestEvent, nil } func (sourceCCIP *SourceCCIPModule) AssertEventCCIPSendRequested( @@ -3211,7 +3274,7 @@ func (lane *CCIPLane) ValidateRequestByTxHash(txHash common.Hash, opts validatio reqStats = append(reqStats, req.RequestStat) } - if opts.phaseExpectedToFail == testreporters.CCIPSendRe && opts.timeout != 0 { + if (opts.phaseExpectedToFail == testreporters.CCIPSendRe || opts.expectAnyPhaseToFail) && opts.timeout != 0 { timeout = opts.timeout } msgLogs, ccipSendReqGenAt, err := lane.Source.AssertEventCCIPSendRequested( @@ -3239,6 +3302,10 @@ func (lane *CCIPLane) ValidateRequestByTxHash(txHash common.Hash, opts validatio return fmt.Errorf("could not find request stat for seq number %d", seqNumber) } + if opts.expectAnyPhaseToFail && opts.timeout != 0 { + timeout = opts.timeout + } + if opts.phaseExpectedToFail == testreporters.Commit && opts.timeout != 0 { timeout = opts.timeout } @@ -3278,6 +3345,10 @@ func (lane *CCIPLane) ValidateRequestByTxHash(txHash common.Hash, opts validatio return phaseErr } } + if opts.expectAnyPhaseToFail { + return errors.New("expected at least any one phase to fail but no phase got failed") + } + return nil } @@ -3727,6 +3798,21 @@ func (lane *CCIPLane) DeployNewCCIPLane( AttestationAPITimeoutSeconds: 5, } } + if !lane.Source.Common.ExistingDeployment && lane.Source.Common.IsLBTCDeployment() { + api := "" + if killgrave != nil { + api = killgrave.InternalEndpoint + } + if env.MockServer != nil { + api = env.MockServer.Config.ClusterURL + } + // Only one LBTC allowed per chain + jobParams.LBTCConfig = &config.LBTCConfig{ + SourceTokenAddress: common.HexToAddress(lane.Source.Common.BridgeTokens[0].Address()), + AttestationAPI: api, + AttestationAPITimeoutSeconds: 5, + } + } if !bootstrapAdded.Load() { bootstrapAdded.Store(true) err := CreateBootstrapJob(jobParams, bootstrapCommit, bootstrapExec) @@ -3854,12 +3940,13 @@ func SetOCR2Config( if len(execNodes) > 0 { nodes = execNodes } + + // Use out of order batching strategy if we expect to be sending out of order messages + batchingStrategyID := ccipexec.BestEffortBatchingStrategyID + if pointer.GetBool(testConf.AllowOutOfOrder) { + batchingStrategyID = ccipexec.ZKOverflowBatchingStrategyID + } if destCCIP.OffRamp != nil { - // Use out of order batching strategy if we expect to be sending out of order messages - batchingStrategyID := uint32(0) - if pointer.GetBool(testConf.AllowOutOfOrder) { - batchingStrategyID = uint32(1) - } execOffchainCfg, err := contracts.NewExecOffchainConfig( 1, BatchGasLimit, @@ -4121,6 +4208,7 @@ func (c *CCIPTestEnv) ConnectToExistingNodes(envConfig *testconfig.Common) error if err != nil { return fmt.Errorf("failed to create chainlink client: %w for node %d config %v", err, i+1, cfg) } + clClient.ChainlinkClient.WithRetryCount(3) c.CLNodes = append(c.CLNodes, clClient) c.nodeMutexes = append(c.nodeMutexes, &sync.Mutex{}) } @@ -4134,7 +4222,7 @@ func (c *CCIPTestEnv) ConnectToDeployedNodes() error { for _, chainlinkNode := range c.LocalCluster.ClCluster.Nodes { c.nodeMutexes = append(c.nodeMutexes, &sync.Mutex{}) c.CLNodes = append(c.CLNodes, &nodeclient.ChainlinkK8sClient{ - ChainlinkClient: chainlinkNode.API, + ChainlinkClient: chainlinkNode.API.WithRetryCount(3), }) } } else { @@ -4422,6 +4510,48 @@ func SetMockServerWithUSDCAttestation( return nil } +// SetMockServerWithLBTCAttestation responds with a mock attestation for any msgHash +// The path is set with regex to match any path that starts with /v1/attestations +func SetMockServerWithLBTCAttestation( + killGrave *ctftestenv.Killgrave, + mockserver *ctfClient.MockserverClient, +) error { + path := "/bridge/v1/deposits/getByHash" + type attestation struct { + Status string `json:"status"` + Attestation string `json:"attestation"` + MessageHash string `json:"message_hash"` + } + response := struct { + Attestations []attestation `json:"attestations"` + }{ + Attestations: []attestation{ + { + MessageHash: "0x" + LBTCValidDestPoolData, // sample hash + Status: "NOTARIZATION_STATUS_SESSION_APPROVED", + Attestation: "0x0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000e45c70a5050000000000000000000000000000000000000000000000000000000000aa36a7000000000000000000000000845f8e3c214d8d0e4d83fc094f302aa26a12a0bc0000000000000000000000000000000000000000000000000000000000014a34000000000000000000000000845f8e3c214d8d0e4d83fc094f302aa26a12a0bc00000000000000000000000062f10ce5b727edf787ea45776bd050308a61150800000000000000000000000000000000000000000000000000000000000003e60000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000040277eeafba008d767c2636d9428f2ebb13ab29ac70337f4fc34b0f5606767cae546f9be3f12160de6d142e5b3c1c3ebd0bf4298662b32b597d0cc5970c7742fc10000000000000000000000000000000000000000000000000000000000000040bbcd60ecc9e06f2effe7c94161219498a1eb435b419387adadb86ec9a52dfb066ce027532517df7216404049d193a25b85c35edfa3e7c5aa4757bfe84887a3980000000000000000000000000000000000000000000000000000000000000040da4a6dc619b5ca2349783cabecc4efdbc910090d3e234d7b8d0430165f8fae532f9a965ceb85c18bb92e059adefa7ce5835850a705761ab9e026d2db4a13ef9a", + }, + }, + } + if killGrave == nil && mockserver == nil { + return errors.New("both killgrave and mockserver are nil") + } + log.Info().Str("path", path).Msg("setting attestation-api response for any msgHash") + if killGrave != nil { + err := killGrave.SetAnyValueResponse(path, []string{http.MethodPost}, response) + if err != nil { + return fmt.Errorf("failed to set killgrave server value: %w", err) + } + } + if mockserver != nil { + err := mockserver.SetAnyValueResponse(path, response) + if err != nil { + return fmt.Errorf("failed to set mockserver value: %w URL = %s", err, fmt.Sprintf("%s/%s/.*", mockserver.LocalURL(), path)) + } + } + return nil +} + // SetMockserverWithTokenPriceValue sets the mock responses in mockserver that are read by chainlink nodes // to simulate different price feed value. // it keeps updating the response every 15 seconds to simulate price feed updates diff --git a/integration-tests/ccip-tests/contracts/contract_deployer.go b/integration-tests/ccip-tests/contracts/contract_deployer.go index 1f2859ae0db..f564ab6244c 100644 --- a/integration-tests/ccip-tests/contracts/contract_deployer.go +++ b/integration-tests/ccip-tests/contracts/contract_deployer.go @@ -21,9 +21,8 @@ import ( ocrconfighelper2 "github.com/smartcontractkit/libocr/offchainreporting2/confighelper" ocrtypes2 "github.com/smartcontractkit/libocr/offchainreporting2/types" - "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" - "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" "github.com/smartcontractkit/chainlink/deployment/environment/nodeclient" "github.com/smartcontractkit/chainlink/integration-tests/contracts" @@ -37,10 +36,10 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/lock_release_token_pool" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/lock_release_token_pool_1_4_0" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/maybe_revert_message_receiver" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_lbtc_token_pool" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_rmn_contract" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_usdc_token_messenger" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_usdc_token_transmitter" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_v3_aggregator_contract" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry_1_2_0" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_contract" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" @@ -51,9 +50,10 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/usdc_token_pool_1_4_0" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/weth9" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" - type_and_version "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/type_and_version_interface_wrapper" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/erc20" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/mock_v3_aggregator_contract" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/type_and_version" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" ccipconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers" @@ -241,6 +241,43 @@ func (e *CCIPContractsDeployer) DeployBurnMintERC677(ownerMintingAmount *big.Int return token, err } +func (e *CCIPContractsDeployer) DeployCustomBurnMintERC677Token(name, symbol string, decimals uint8, ownerMintingAmount *big.Int) (*ERC677Token, error) { + address, _, instance, err := e.evmClient.DeployContract("Burn Mint ERC 677", func( + auth *bind.TransactOpts, + _ bind.ContractBackend, + ) (common.Address, *types.Transaction, interface{}, error) { + return burn_mint_erc677.DeployBurnMintERC677(auth, wrappers.MustNewWrappedContractBackend(e.evmClient, nil), name, symbol, decimals, new(big.Int).Mul(big.NewInt(1e18), big.NewInt(1e9))) + }) + if err != nil { + return nil, err + } + + token := &ERC677Token{ + client: e.evmClient, + logger: e.logger, + ContractAddress: *address, + instance: instance.(*burn_mint_erc677.BurnMintERC677), + OwnerAddress: common.HexToAddress(e.evmClient.GetDefaultWallet().Address()), + OwnerWallet: e.evmClient.GetDefaultWallet(), + } + if ownerMintingAmount != nil { + // grant minter role to owner and mint tokens + err = token.GrantMintRole(common.HexToAddress(e.evmClient.GetDefaultWallet().Address())) + if err != nil { + return token, fmt.Errorf("granting minter role to owner shouldn't fail %w", err) + } + err = e.evmClient.WaitForEvents() + if err != nil { + return token, fmt.Errorf("error in waiting for granting mint role %w", err) + } + err = token.Mint(common.HexToAddress(e.evmClient.GetDefaultWallet().Address()), ownerMintingAmount) + if err != nil { + return token, fmt.Errorf("minting tokens shouldn't fail %w", err) + } + } + return token, err +} + func (e *CCIPContractsDeployer) DeployERC20TokenContract(deployerFn blockchain.ContractDeployer) (*ERC20Token, error) { address, _, _, err := e.evmClient.DeployContract("Custom ERC20 Token", deployerFn) if err != nil { @@ -488,6 +525,81 @@ func (e *CCIPContractsDeployer) DeployUSDCTokenPoolContract(tokenAddr string, to } } +func (e *CCIPContractsDeployer) NewMockLBTCTokenPoolContract(addr common.Address) ( + *TokenPool, + error, +) { + version := VersionMap[TokenPoolContract] + e.logger.Info().Str("Version", version.String()).Msg("New Mock LBTC Token Pool") + switch version { + case Latest: + pool, err := mock_lbtc_token_pool.NewMockLBTCTokenPool(addr, wrappers.MustNewWrappedContractBackend(e.evmClient, nil)) + + if err != nil { + return nil, err + } + e.logger.Info(). + Str("Contract Address", addr.Hex()). + Str("Contract Name", "Mock LBTC Token Pool"). + Str("From", e.evmClient.GetDefaultWallet().Address()). + Str("Network Name", e.evmClient.GetNetworkConfig().Name). + Msg("New contract") + poolInterface, err := token_pool.NewTokenPool(addr, wrappers.MustNewWrappedContractBackend(e.evmClient, nil)) + if err != nil { + return nil, err + } + return &TokenPool{ + client: e.evmClient, + logger: e.logger, + Instance: &TokenPoolWrapper{ + Latest: &LatestPool{ + PoolInterface: poolInterface, + MockLBTCPool: pool, + }, + }, + EthAddress: addr, + OwnerAddress: common.HexToAddress(e.evmClient.GetDefaultWallet().Address()), + OwnerWallet: e.evmClient.GetDefaultWallet(), + }, err + default: + return nil, fmt.Errorf("version not supported: %s", version) + } +} + +func (e *CCIPContractsDeployer) DeployMockLBTCTokenPoolContract(tokenAddr string, rmnProxy common.Address, router common.Address, destPoolData []byte) ( + *TokenPool, + error, +) { + e.logger.Println("In DeployMockLBTCTokenPoolContract") + version := VersionMap[TokenPoolContract] + e.logger.Debug().Str("Token", tokenAddr).Msg("Deploying Mock LBTC token pool") + token := common.HexToAddress(tokenAddr) + switch version { + case Latest: + address, _, _, err := e.evmClient.DeployContract("Mock LBTC Token Pool", func( + auth *bind.TransactOpts, + _ bind.ContractBackend, + ) (common.Address, *types.Transaction, interface{}, error) { + return mock_lbtc_token_pool.DeployMockLBTCTokenPool( + auth, + wrappers.MustNewWrappedContractBackend(e.evmClient, nil), + token, + []common.Address{}, + rmnProxy, + router, + destPoolData, + ) + }) + + if err != nil { + return nil, err + } + return e.NewMockLBTCTokenPoolContract(*address) + default: + return nil, fmt.Errorf("version not supported: %s", version) + } +} + func (e *CCIPContractsDeployer) DeployLockReleaseTokenPoolContract(tokenAddr string, rmnProxy common.Address, router common.Address) ( *TokenPool, error, @@ -505,7 +617,7 @@ func (e *CCIPContractsDeployer) DeployLockReleaseTokenPoolContract(tokenAddr str auth, wrappers.MustNewWrappedContractBackend(e.evmClient, nil), token, - 18, + testhelpers.TokenDecimals, []common.Address{}, rmnProxy, true, @@ -1259,7 +1371,7 @@ func (e *CCIPContractsDeployer) NewMockAggregator(addr common.Address) (*MockAgg } func (e *CCIPContractsDeployer) TypeAndVersion(addr common.Address) (string, error) { - tv, err := type_and_version.NewTypeAndVersionInterface(addr, wrappers.MustNewWrappedContractBackend(e.evmClient, nil)) + tv, err := type_and_version.NewITypeAndVersion(addr, wrappers.MustNewWrappedContractBackend(e.evmClient, nil)) if err != nil { return "", err } diff --git a/integration-tests/ccip-tests/contracts/contract_models.go b/integration-tests/ccip-tests/contracts/contract_models.go index 257670dbaa1..01245daa966 100644 --- a/integration-tests/ccip-tests/contracts/contract_models.go +++ b/integration-tests/ccip-tests/contracts/contract_models.go @@ -18,6 +18,7 @@ import ( "golang.org/x/exp/rand" "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_lbtc_token_pool" "github.com/smartcontractkit/chainlink/integration-tests/wrappers" @@ -33,7 +34,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/maybe_revert_message_receiver" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_rmn_contract" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_usdc_token_transmitter" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_v3_aggregator_contract" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry_1_2_0" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_contract" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" @@ -45,6 +45,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/erc20" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/mock_v3_aggregator_contract" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" ) @@ -404,6 +405,7 @@ type LatestPool struct { PoolInterface *token_pool.TokenPool LockReleasePool *lock_release_token_pool.LockReleaseTokenPool USDCPool *usdc_token_pool.USDCTokenPool + MockLBTCPool *mock_lbtc_token_pool.MockLBTCTokenPool } type V1_4_0Pool struct { @@ -485,6 +487,7 @@ func (w TokenPoolWrapper) ApplyChainUpdates(opts *bind.TransactOpts, update []to for i, u := range update { V1_4_0Updates[i] = token_pool_1_4_0.TokenPoolChainUpdate{ RemoteChainSelector: u.RemoteChainSelector, + Allowed: true, InboundRateLimiterConfig: token_pool_1_4_0.RateLimiterConfig{ IsEnabled: u.InboundRateLimiterConfig.IsEnabled, Capacity: u.InboundRateLimiterConfig.Capacity, diff --git a/integration-tests/ccip-tests/contracts/lm_contracts.go b/integration-tests/ccip-tests/contracts/lm_contracts.go index 521324c11be..f51369ee977 100644 --- a/integration-tests/ccip-tests/contracts/lm_contracts.go +++ b/integration-tests/ccip-tests/contracts/lm_contracts.go @@ -25,7 +25,7 @@ import ( type ArmProxy struct { client blockchain.EVMClient - Instance *rmn_proxy_contract.RMNProxyContract + Instance *rmn_proxy_contract.RMNProxy EthAddress *common.Address } @@ -34,7 +34,7 @@ func (e *CCIPContractsDeployer) DeployArmProxy(arm common.Address) (*ArmProxy, e auth *bind.TransactOpts, _ bind.ContractBackend, ) (common.Address, *types.Transaction, interface{}, error) { - return rmn_proxy_contract.DeployRMNProxyContract( + return rmn_proxy_contract.DeployRMNProxy( auth, wrappers.MustNewWrappedContractBackend(e.evmClient, nil), arm, @@ -45,7 +45,7 @@ func (e *CCIPContractsDeployer) DeployArmProxy(arm common.Address) (*ArmProxy, e } return &ArmProxy{ client: e.evmClient, - Instance: instance.(*rmn_proxy_contract.RMNProxyContract), + Instance: instance.(*rmn_proxy_contract.RMNProxy), EthAddress: address, }, err } diff --git a/integration-tests/ccip-tests/load/ccip_loadgen.go b/integration-tests/ccip-tests/load/ccip_loadgen.go index d562cce88b2..198db0ef94b 100644 --- a/integration-tests/ccip-tests/load/ccip_loadgen.go +++ b/integration-tests/ccip-tests/load/ccip_loadgen.go @@ -10,28 +10,27 @@ import ( "testing" "time" - "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" - "github.com/AlekSi/pointer" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/rs/zerolog" - chain_selectors "github.com/smartcontractkit/chain-selectors" "github.com/stretchr/testify/require" "go.uber.org/atomic" + chain_selectors "github.com/smartcontractkit/chain-selectors" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink-testing-framework/wasp" "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/testconfig" + "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/testreporters" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers" - - "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/actions" - "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/testreporters" ) // CCIPLaneOptimized is a light-weight version of CCIPLane, It only contains elements which are used during load triggering and validation @@ -198,6 +197,7 @@ func (c *CCIPE2ELoad) CCIPMsg() (router.ClientEVM2AnyMessage, *testreporters.Req extraArgs []byte err error ) + // v1.5.0 and later starts using V2 extra args matchErr := contracts.MatchContractVersionsOrAbove(map[contracts.Name]contracts.Version{ contracts.OnRampContract: contracts.V1_5_0, }) @@ -225,13 +225,20 @@ func (c *CCIPE2ELoad) Call(_ *wasp.Generator) *wasp.Response { res := &wasp.Response{} sourceCCIP := c.Lane.Source var recentRequestFoundAt *time.Time + var latestEvent *types.Log var err error // Use IsPastRequestTriggeredWithinTimeframe to check for any historical CCIP send request events // within the specified timeframe for the first message. Subsequently, use the watcher method to monitor // and detect any new events as they occur. if c.CurrentMsgSerialNo.Load() == int64(1) { - recentRequestFoundAt, err = sourceCCIP.IsPastRequestTriggeredWithinTimeframe(testcontext.Get(c.t), c.SkipRequestIfAnotherRequestTriggeredWithin) + latestEvent, err = sourceCCIP.IsPastRequestTriggeredWithinTimeframe(testcontext.Get(c.t), c.SkipRequestIfAnotherRequestTriggeredWithin) require.NoError(c.t, err, "error while filtering past requests") + if latestEvent != nil { + //nolint:gosec // safe to cast + hdr, err := sourceCCIP.Common.ChainClient.HeaderByNumber(context.Background(), big.NewInt(int64(latestEvent.BlockNumber))) + require.NoError(c.t, err, "error while getting header by block number") + recentRequestFoundAt = pointer.ToTime(hdr.Timestamp) + } } else { recentRequestFoundAt = sourceCCIP.IsRequestTriggeredWithinTimeframe(c.SkipRequestIfAnotherRequestTriggeredWithin) } diff --git a/integration-tests/ccip-tests/load/ccip_multicall_loadgen.go b/integration-tests/ccip-tests/load/ccip_multicall_loadgen.go index 04fcffaa4b1..39e5388244e 100644 --- a/integration-tests/ccip-tests/load/ccip_multicall_loadgen.go +++ b/integration-tests/ccip-tests/load/ccip_multicall_loadgen.go @@ -91,7 +91,7 @@ func NewMultiCallLoadGenerator(testCfg *testsetups.CCIPTestConfig, lanes []*acti testCfg.Test, lane, testCfg.TestGroupInput.PhaseTimeout.Duration(), 100000, testCfg.TestGroupInput.LoadProfile.MsgProfile, 0, - testCfg.TestGroupInput.LoadProfile.SkipRequestIfAnotherRequestTriggeredWithin, + testCfg.TestGroupInput.SkipRequestIfAnotherRequestTriggeredWithin, ) ccipLoad.BeforeAllCall() m.E2ELoads[fmt.Sprintf("%s-%s", lane.SourceNetworkName, lane.DestNetworkName)] = ccipLoad diff --git a/integration-tests/ccip-tests/load/helper.go b/integration-tests/ccip-tests/load/helper.go index 34860c8871c..f89aadc2483 100644 --- a/integration-tests/ccip-tests/load/helper.go +++ b/integration-tests/ccip-tests/load/helper.go @@ -112,8 +112,15 @@ func (l *LoadArgs) scheduleForDest(destNetworkName string) []*wasp.Segment { // if found, use that frequency for the destination network // otherwise, use the default frequency if l.TestCfg.TestGroupInput.LoadProfile.FrequencyByDestination != nil { + l.lggr.Debug(). + Interface("FrequencyByDestination", l.TestCfg.TestGroupInput.LoadProfile.FrequencyByDestination). + Msg("LoadProfile provided") for networkName, freq := range l.TestCfg.TestGroupInput.LoadProfile.FrequencyByDestination { - if strings.Contains(destNetworkName, networkName) { + l.lggr.Debug().Str("Destination", destNetworkName).Str("NetworkName", networkName).Msg("Checking frequency for destination") + if strings.EqualFold(destNetworkName, networkName) { + l.lggr.Info().Str("Destination", destNetworkName). + Ints64("RequestPerUnitTime", freq.RequestPerUnitTime). + Msg("Using frequency for destination") return WaspSchedule( freq.RequestPerUnitTime, l.TestCfg.TestGroupInput.LoadProfile.TestDuration, @@ -269,7 +276,7 @@ func (l *LoadArgs) TriggerLoadByLane() { ccipLoad := NewCCIPLoad( l.TestCfg.Test, lane, l.TestCfg.TestGroupInput.PhaseTimeout.Duration(), 100000, l.TestCfg.TestGroupInput.LoadProfile.MsgProfile, sendMaxData, - l.TestCfg.TestGroupInput.LoadProfile.SkipRequestIfAnotherRequestTriggeredWithin, + l.TestCfg.TestGroupInput.SkipRequestIfAnotherRequestTriggeredWithin, ) ccipLoad.BeforeAllCall() // if it's not multicall set the tokens to nil to free up some space, diff --git a/integration-tests/ccip-tests/smoke/ccip_test.go b/integration-tests/ccip-tests/smoke/ccip_test.go index a74d404db18..344b920f852 100644 --- a/integration-tests/ccip-tests/smoke/ccip_test.go +++ b/integration-tests/ccip-tests/smoke/ccip_test.go @@ -4,16 +4,17 @@ import ( "fmt" "math" "math/big" + "strings" "testing" "time" - "github.com/rs/zerolog" - "github.com/stretchr/testify/assert" - "github.com/AlekSi/pointer" - "github.com/stretchr/testify/require" + "github.com/ethereum/go-ethereum/core/types" + "github.com/rs/zerolog" + "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/osutil" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp" @@ -21,10 +22,14 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_pool" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/actions" + "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/testsetups" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/testconfig" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/testreporters" - "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/testsetups" ) type testDefinition struct { @@ -245,7 +250,10 @@ func TestSmokeCCIPRateLimit(t *testing.T) { tc.lane.Source.Common.ChainClient.GetDefaultWallet(), src.Common.Router.Address(), src.TransferAmount[0]), ) require.NoError(t, tc.lane.Source.Common.ChainClient.WaitForEvents()) - failedTx, _, _, err := tc.lane.Source.SendRequest(tc.lane.Dest.ReceiverDapp.EthAddress, big.NewInt(actions.DefaultDestinationGasLimit)) + failedTx, _, _, err := tc.lane.Source.SendRequest( + tc.lane.Dest.ReceiverDapp.EthAddress, + big.NewInt(actions.DefaultDestinationGasLimit), + ) require.NoError(t, err) require.Error(t, tc.lane.Source.Common.ChainClient.WaitForEvents()) errReason, v, err := tc.lane.Source.Common.ChainClient.RevertReasonFromTx(failedTx, evm_2_evm_onramp.EVM2EVMOnRampABI) @@ -886,7 +894,7 @@ func TestSmokeCCIPReorgBelowFinality(t *testing.T) { // Test creates above finality reorg at destination and // expects ccip transactions in-flight and the one initiated after reorg -// doesn't go through and verifies f+1 nodes is able to detect reorg. +// doesn't go through and verifies f+1 nodes are able to detect reorg. // Note: LogPollInterval interval is set as 1s to detect the reorg immediately func TestSmokeCCIPReorgAboveFinalityAtDestination(t *testing.T) { utils.SkipFlakey(t, "https://smartcontract-it.atlassian.net/browse/CCIP-4401") @@ -898,7 +906,7 @@ func TestSmokeCCIPReorgAboveFinalityAtDestination(t *testing.T) { // Test creates above finality reorg at destination and // expects ccip transactions in-flight doesn't go through, the transaction initiated after reorg -// shouldn't even get initiated and verifies f+1 nodes is able to detect reorg. +// shouldn't even get initiated and verifies f+1 nodes are able to detect reorg. // Note: LogPollInterval interval is set as 1s to detect the reorg immediately func TestSmokeCCIPReorgAboveFinalityAtSource(t *testing.T) { utils.SkipFlakey(t, "https://smartcontract-it.atlassian.net/browse/CCIP-4401") @@ -908,6 +916,123 @@ func TestSmokeCCIPReorgAboveFinalityAtSource(t *testing.T) { }) } +// TestSmokeCCIPForGivenNetworkPairs is designed specifically for scheduled mainnet testing. This test checks for recent +// transaction and skip the lanes accordingly. This test also has capability to take override input on network pairs and phase timeout. +func TestSmokeCCIPForGivenNetworkPairs(t *testing.T) { + t.Parallel() + log := logging.GetTestLogger(t) + TestCfg := testsetups.NewCCIPTestConfig(t, log, testconfig.Smoke) + // override network pairs + var temp []testsetups.NetworkPair + overrideNetworkPairs, err := osutil.GetEnv("OVERRIDE_NETWORK_PAIRS") + require.NoError(t, err, "Error getting OVERRIDE_NETWORK_PAIRS environment variable") + if overrideNetworkPairs != "" { + networkPairs := strings.Split(overrideNetworkPairs, ";") + for _, networkPair := range networkPairs { + // check for any malformed inputs + if !strings.Contains(networkPair, ",") || len(strings.Split(networkPair, ",")) != 2 { + log.Error().Msgf("malformed OVERRIDE_NETWORK_PAIRS environment variable for network pair: %s ", networkPair) + return + } + networkPair = strings.ToUpper(strings.ReplaceAll(networkPair, "_", " ")) + for _, network := range TestCfg.NetworkPairs { + if strings.Contains(networkPair, strings.ToUpper(network.NetworkA.Name)) && strings.Contains(networkPair, strings.ToUpper(network.NetworkB.Name)) { + temp = append(temp, network) + break + } + } + } + log.Info().Int("Pairs", len(temp)).Msg("Number of lanes overridden in the test") + log.Info().Interface("Lanes", networkPairs).Msg("Lanes under test") + TestCfg.NetworkPairs = temp + } + + // phase timeout override + phaseTimeout, err := osutil.GetEnv("OVERRIDE_PHASE_TIMEOUT") + require.NoError(t, err, "Error getting OVERRIDE_PHASE_TIMEOUT environment variable") + if phaseTimeout != "" { + configDuration, err := config.ParseDuration(phaseTimeout) + require.NoError(t, err, "Error parsing phase timeout value") + TestCfg.TestGroupInput.PhaseTimeout = &configDuration + log.Info().Float64("Timeout in minutes", configDuration.Duration().Minutes()).Msg("Phase timeout is overridden") + } + + gasLimit := big.NewInt(*TestCfg.TestGroupInput.MsgDetails.DestGasLimit) + setUpOutput := testsetups.CCIPDefaultTestSetUp(t, &log, "smoke-ccip", nil, TestCfg) + if len(setUpOutput.Lanes) == 0 { + log.Error().Msg("No lanes found") + return + } + + t.Cleanup(func() { + // If we are running a test that is a token transfer, we need to verify the balance. + // skip the balance check for existing deployment, there can be multiple external requests in progress for existing deployments + // other than token transfer initiated by the test, which can affect the balance check + // therefore we check the balance only for the ccip environment created by the test + if TestCfg.TestGroupInput.MsgDetails.IsTokenTransfer() && + !pointer.GetBool(TestCfg.TestGroupInput.USDCMockDeployment) && + !pointer.GetBool(TestCfg.TestGroupInput.ExistingDeployment) { + setUpOutput.Balance.Verify(t) + } + require.NoError(t, setUpOutput.TearDown(), "error in tear down step") + }) + + var tests []testDefinition + lookBackDuration := TestCfg.TestGroupInput.SkipRequestIfAnotherRequestTriggeredWithin + var recentTxFound *types.Log + + addLanesToTest := func(lane *actions.CCIPLane) { + // Create test definitions for given lane if no previous request has been triggered within the specified timeframe. + // By default, the timeframe is set to nil. To define a timeframe, assign a duration to the variable + // SkipRequestIfAnotherRequestTriggeredWithin. + if lookBackDuration != nil { + recentTxFound, err = lane.Source.IsPastRequestTriggeredWithinTimeframe(lane.Context, lookBackDuration) + require.NoError(t, err, "error while finding recent request for lane network %s to network %s", + lane.SourceNetworkName, lane.DestNetworkName) + } + if recentTxFound == nil { + tests = append(tests, testDefinition{ + testName: fmt.Sprintf("CCIP message transfer from network %s to network %s", + lane.SourceNetworkName, lane.DestNetworkName), + lane: lane, + }) + } else { + log.Info(). + Str("TX", recentTxFound.TxHash.Hex()). + Uint64("Block Number", recentTxFound.BlockNumber). + Str("Source", lane.SourceNetworkName). + Str("Dest", lane.DestNetworkName). + Msgf("Lane Skipped. Recent request found within %v minutes.", lookBackDuration.Duration().Minutes()) + } + } + for _, lane := range setUpOutput.Lanes { + addLanesToTest(lane.ForwardLane) + if lane.ReverseLane != nil { + recentTxFound = nil + addLanesToTest(lane.ReverseLane) + } + } + + // Execute tests. + log.Info().Int("Total Lanes", len(tests)).Msg("Starting CCIP test") + for _, test := range tests { + tc := test + t.Run(tc.testName, func(t *testing.T) { + t.Parallel() + tc.lane.Test = t + log.Info(). + Str("Source", tc.lane.SourceNetworkName). + Str("Destination", tc.lane.DestNetworkName). + Msgf("Starting lane %s -> %s", tc.lane.SourceNetworkName, tc.lane.DestNetworkName) + + tc.lane.RecordStateBeforeTransfer() + err = tc.lane.SendRequests(1, gasLimit) + require.NoError(t, err, "error sending requests") + tc.lane.ValidateRequests() + }) + } +} + // performAboveFinalityReorgAndValidate is to perform the above finality reorg test func performAboveFinalityReorgAndValidate(t *testing.T, network string) { t.Helper() @@ -952,7 +1077,7 @@ func performAboveFinalityReorgAndValidate(t *testing.T, network string) { require.NoError(t, err) for _, d := range resp.Data { if d.Attributes.Name == logPollerName && d.Attributes.Output == "finality violated" && d.Attributes.Status == "failing" { - log.Debug().Msg("Finality violated is detected by node") + log.Debug().Str("Node", node.ChainlinkClient.URL()).Msg("Finality violated is detected by node") nodesDetectedViolation[node.ChainlinkClient.URL()] = true } } diff --git a/integration-tests/ccip-tests/testconfig/README.md b/integration-tests/ccip-tests/testconfig/README.md index d614ed62ea4..9a9fa5129b1 100644 --- a/integration-tests/ccip-tests/testconfig/README.md +++ b/integration-tests/ccip-tests/testconfig/README.md @@ -10,7 +10,7 @@ The test config is read in following order: - The config mentioned in this file will override the default config. - Example override file - [override.toml.example](./examples/override.toml.example) - If there are sensitive details like private keys, credentials in test config, they can be specified in a separate dotenv file as env vars - - The `~/.testsecrets` file in home directory is automatically loaded and should have all test secrets as env vars + - The `~/.testsecrets` file in home directory is automatically loaded and should have all test secrets as env vars. Learn more about it [here](https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/config/README.md#test-secrets) - Example secret file - [.testsecrets.example](./examples/.testsecrets.example) ## CCIP.ContractVersions @@ -110,7 +110,7 @@ Or, DataFile = '' ``` -## CCIP.Env +## CCIP.Env Specifies the environment details for the test to be run on. Mandatory fields are: @@ -119,14 +119,7 @@ Mandatory fields are: - **NewCLCluster**: [CCIP.Env.NewCLCluster](#ccipenvnewclcluster) - This is mandatory if the test needs to deploy Chainlink nodes. - **ExistingCLCluster**: [CCIP.Env.ExistingCLCluster](#ccipenvexistingclcluster) - This is mandatory if the test needs to run on existing Chainlink nodes to deploy ccip jobs. -Test needs network/chain details to be set through configuration. This configuration is mandatory for running the tests. -you have option to set the network details in two ways: - -1. Using [CCIP.Env.Networks](#ccipenvnetworks) -2. Using a separate network config file - - - refer to the example - [network_config.toml.example](./examples/network_config.toml.example) - - once all necessary values are set, encode the toml file content in base64 format, - - set the base64'ed string content in `BASE64_NETWORK_CONFIG` environment variable. +Test needs network/chain details to be set through configuration. Set network urls in ~/.testsecrets [see docs](https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/config/README.md#test-secrets). ### CCIP.Env.Networks @@ -146,7 +139,7 @@ If the network is not present in known_networks, then the network details can be #### CCIP.Env.Network.EVMNetworks -Specifies the network config to be used while creating blockchain EVMClient for test. +Specifies the network config to be used while creating blockchain EVMClient for test. It is a map of network name to EVMNetworks where key is network name specified under `CCIP.Env.Networks.selected_networks` and value is `EVMNetwork`. The EVMNetwork is imported from [EVMNetwork](https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/blockchain/config.go#L43) in chainlink-testing-framework. @@ -638,6 +631,13 @@ Specifies the OCR parameters for the execute job. This is only valid if the test Specifies the value for the `InflightExpiry` in commit job's offchain config. This is only valid if the test is not run on [existing deployments](#ccipgroupstestgroupexistingdeployment). +### CCIP.Groups.[testgroup].SkipRequestIfAnotherRequestTriggeredWithin + +If there is CCIP Send requested event present within this duration, the test will skip sending another +request during load run or avoid sending request in smoke test in that lane. For Example, +if `SkipRequestIfAnotherRequestTriggeredWithin` is set to `40m`, and a request is triggered at 0th second, the test will skip sending another request for another 40m. +This particular field is used to avoid sending transaction when there is traffic already in that lane. + ### CCIP.Groups.[testgroup].OffRampConfig Specifies the offramp configuration for the execution job. This is only valid if the test is not run on [existing deployments](#ccipgroupstestgroupexistingdeployment). @@ -717,11 +717,6 @@ Specifies the duration network delay used for `NetworkChaos` experiment. This is If there are multiple chaos experiments, this specifies the duration to wait between each chaos experiment. This is only valid if the test is run on k8s and not on [existing deployments](#ccipgroupstestgroupexistingdeployment). -#### CCIP.Groups.[testgroup].LoadProfile.SkipRequestIfAnotherRequestTriggeredWithin - -If a request is triggered within this duration, the test will skip sending another request during load run. For Example, if `SkipRequestIfAnotherRequestTriggeredWithin` is set to `40m`, and a request is triggered at 0th second, the test will skip sending another request for another 40m. -This particular field is used to avoid sending multiple requests in a short duration during load run. - #### CCIP.Groups.[testgroup].LoadProfile.OptimizeSpace This is used internally to optimize memory usage during load run. If set to true, after the initial lane set up is over the test will discard the lane config to save memory. @@ -802,4 +797,4 @@ DataLength = 10000 MsgType = 'Data' DestGasLimit = 2500000 DataLength = 10000 -``` \ No newline at end of file +``` diff --git a/integration-tests/ccip-tests/testconfig/ccip.go b/integration-tests/ccip-tests/testconfig/ccip.go index 0a53ee18732..c77b2c3a33e 100644 --- a/integration-tests/ccip-tests/testconfig/ccip.go +++ b/integration-tests/ccip-tests/testconfig/ccip.go @@ -1,6 +1,7 @@ package testconfig import ( + "errors" "fmt" "math/big" "os" @@ -211,19 +212,18 @@ type LoadFrequency struct { } type LoadProfile struct { - MsgProfile *MsgProfile `toml:",omitempty"` - FrequencyByDestination map[string]*LoadFrequency `toml:",omitempty"` - RequestPerUnitTime []int64 `toml:",omitempty"` - TimeUnit *config.Duration `toml:",omitempty"` - StepDuration []*config.Duration `toml:",omitempty"` - TestDuration *config.Duration `toml:",omitempty"` - NetworkChaosDelay *config.Duration `toml:",omitempty"` - WaitBetweenChaosDuringLoad *config.Duration `toml:",omitempty"` - SkipRequestIfAnotherRequestTriggeredWithin *config.Duration `toml:",omitempty"` - OptimizeSpace *bool `toml:",omitempty"` - FailOnFirstErrorInLoad *bool `toml:",omitempty"` - SendMaxDataInEveryMsgCount *int64 `toml:",omitempty"` - TestRunName string `toml:",omitempty"` + MsgProfile *MsgProfile `toml:",omitempty"` + FrequencyByDestination map[string]*LoadFrequency `toml:",omitempty"` + RequestPerUnitTime []int64 `toml:",omitempty"` + TimeUnit *config.Duration `toml:",omitempty"` + StepDuration []*config.Duration `toml:",omitempty"` + TestDuration *config.Duration `toml:",omitempty"` + NetworkChaosDelay *config.Duration `toml:",omitempty"` + WaitBetweenChaosDuringLoad *config.Duration `toml:",omitempty"` + OptimizeSpace *bool `toml:",omitempty"` + FailOnFirstErrorInLoad *bool `toml:",omitempty"` + SendMaxDataInEveryMsgCount *int64 `toml:",omitempty"` + TestRunName string `toml:",omitempty"` } func (l *LoadProfile) Validate() error { @@ -242,9 +242,6 @@ func (l *LoadProfile) Validate() error { if l.TestDuration == nil || l.TestDuration.Duration().Minutes() == 0 { return fmt.Errorf("test duration should be set") } - if l.SkipRequestIfAnotherRequestTriggeredWithin != nil && l.TimeUnit.Duration() < l.SkipRequestIfAnotherRequestTriggeredWithin.Duration() { - return fmt.Errorf("SkipRequestIfAnotherRequestTriggeredWithin should be set below the TimeUnit duration") - } return nil } @@ -265,35 +262,38 @@ func (gp *ReorgProfile) Validate() error { // CCIPTestGroupConfig defines configuration input to change how a particular CCIP test group should run type CCIPTestGroupConfig struct { - Type string `toml:",omitempty"` - KeepEnvAlive *bool `toml:",omitempty"` - BiDirectionalLane *bool `toml:",omitempty"` - CommitAndExecuteOnSameDON *bool `toml:",omitempty"` - AllowOutOfOrder *bool `toml:",omitempty"` // To set out of order execution globally - NoOfCommitNodes int `toml:",omitempty"` - MsgDetails *MsgDetails `toml:",omitempty"` - TokenConfig *TokenConfig `toml:",omitempty"` - MulticallInOneTx *bool `toml:",omitempty"` - NoOfSendsInMulticall int `toml:",omitempty"` - PhaseTimeout *config.Duration `toml:",omitempty"` - LocalCluster *bool `toml:",omitempty"` - ExistingDeployment *bool `toml:",omitempty"` - ReuseContracts *bool `toml:",omitempty"` - NodeFunding float64 `toml:",omitempty"` - NetworkPairs []string `toml:",omitempty"` - DenselyConnectedNetworkChainIds []string `toml:",omitempty"` - NoOfNetworks int `toml:",omitempty"` - NoOfRoutersPerPair int `toml:",omitempty"` - MaxNoOfLanes int `toml:",omitempty"` - ChaosDuration *config.Duration `toml:",omitempty"` - USDCMockDeployment *bool `toml:",omitempty"` - CommitOCRParams *contracts.OffChainAggregatorV2Config `toml:",omitempty"` - ExecOCRParams *contracts.OffChainAggregatorV2Config `toml:",omitempty"` - OffRampConfig *OffRampConfig `toml:",omitempty"` - CommitInflightExpiry *config.Duration `toml:",omitempty"` - StoreLaneConfig *bool `toml:",omitempty"` - LoadProfile *LoadProfile `toml:",omitempty"` - ReorgProfile *ReorgProfile `toml:",omitempty"` + Type string `toml:",omitempty"` + KeepEnvAlive *bool `toml:",omitempty"` + BiDirectionalLane *bool `toml:",omitempty"` + CommitAndExecuteOnSameDON *bool `toml:",omitempty"` + AllowOutOfOrder *bool `toml:",omitempty"` // To set out of order execution globally + NoOfCommitNodes int `toml:",omitempty"` + MsgDetails *MsgDetails `toml:",omitempty"` + TokenConfig *TokenConfig `toml:",omitempty"` + MulticallInOneTx *bool `toml:",omitempty"` + NoOfSendsInMulticall int `toml:",omitempty"` + PhaseTimeout *config.Duration `toml:",omitempty"` + LocalCluster *bool `toml:",omitempty"` + ExistingDeployment *bool `toml:",omitempty"` + ReuseContracts *bool `toml:",omitempty"` + NodeFunding float64 `toml:",omitempty"` + NetworkPairs []string `toml:",omitempty"` + DenselyConnectedNetworkChainIDs []string `toml:",omitempty"` + NoOfNetworks int `toml:",omitempty"` + NoOfRoutersPerPair int `toml:",omitempty"` + MaxNoOfLanes int `toml:",omitempty"` + ChaosDuration *config.Duration `toml:",omitempty"` + USDCMockDeployment *bool `toml:",omitempty"` + LBTCMockDeployment *bool `toml:",omitempty"` + LBTCDestPoolDataAs32Bytes *bool `toml:",omitempty"` + CommitOCRParams *contracts.OffChainAggregatorV2Config `toml:",omitempty"` + ExecOCRParams *contracts.OffChainAggregatorV2Config `toml:",omitempty"` + OffRampConfig *OffRampConfig `toml:",omitempty"` + CommitInflightExpiry *config.Duration `toml:",omitempty"` + StoreLaneConfig *bool `toml:",omitempty"` + LoadProfile *LoadProfile `toml:",omitempty"` + ReorgProfile *ReorgProfile `toml:",omitempty"` + SkipRequestIfAnotherRequestTriggeredWithin *config.Duration `toml:",omitempty"` } func (c *CCIPTestGroupConfig) Validate() error { @@ -310,6 +310,11 @@ func (c *CCIPTestGroupConfig) Validate() error { return fmt.Errorf("test run name should be set if existing deployment is true and test is running in k8s") } } + if c.ReorgProfile != nil { + if err := c.ReorgProfile.Validate(); err != nil { + return err + } + } } err := c.MsgDetails.Validate() if err != nil { @@ -336,6 +341,10 @@ func (c *CCIPTestGroupConfig) Validate() error { return fmt.Errorf("number of sends in multisend should be greater than 0 if multisend is true") } } + if c.SkipRequestIfAnotherRequestTriggeredWithin != nil && c.LoadProfile != nil && + c.LoadProfile.TimeUnit.Duration() < c.SkipRequestIfAnotherRequestTriggeredWithin.Duration() { + return errors.New("SkipRequestIfAnotherRequestTriggeredWithin should be set below the load TimeUnit duration") + } return nil } diff --git a/integration-tests/ccip-tests/testconfig/override/mainnet.toml b/integration-tests/ccip-tests/testconfig/override/mainnet.toml index f723411eafc..cb83da28cb3 100644 --- a/integration-tests/ccip-tests/testconfig/override/mainnet.toml +++ b/integration-tests/ccip-tests/testconfig/override/mainnet.toml @@ -1,10 +1,10 @@ [CCIP] [CCIP.ContractVersions] -PriceRegistry = '1.2.0' -OffRamp = '1.2.0' -OnRamp = '1.2.0' -TokenPool = '1.4.0' -CommitStore = '1.2.0' +PriceRegistry = 'latest' +OffRamp = 'latest' +OnRamp = 'latest' +TokenPool = 'latest' +CommitStore = 'latest' [CCIP.Deployments] Data = """ @@ -19,114 +19,114 @@ Data = """ "wrapped_native": "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1", "src_contracts": { "Avalanche Mainnet": { - "on_ramp": "0x05B723f3db92430FbE4395fD03E40Cc7e9D17988", + "on_ramp": "0xe80cC83B895ada027b722b78949b296Bd1fC5639", "deployed_at": 0 }, "BSC Mainnet": { - "on_ramp": "0x79f3ABeCe5A3AFFf32D47F4CFe45e7b65c9a2D91", + "on_ramp": "0x14bF7b1Ca6b843f386bfDfa76BFd439919b9378D", "deployed_at": 0 }, "Base Mainnet": { - "on_ramp": "0x77b60F85b25fD501E3ddED6C1fe7bF565C08A22A", + "on_ramp": "0xc1b6287A3292d6469F2D8545877E40A2f75CA9a6", "deployed_at": 0 }, "Blast Mainnet": { - "on_ramp": "0x54480425E9e24138fdF1644a1F70007F25abfB46", + "on_ramp": "0xc5490997680a39A1b4684ce2b668AE8A2eBEC7ee", "deployed_at": 0 }, "Ethereum Mainnet": { - "on_ramp": "0xCe11020D56e5FDbfE46D9FC3021641FfbBB5AdEE", + "on_ramp": "0x67761742ac8A21Ec4D76CA18cbd701e5A6F3Bef3", "deployed_at": 0 }, "Gnosis Mainnet": { - "on_ramp": "0x1216DC856Af47a833254a280A038185F51C1B5c4", + "on_ramp": "0xc7d6B885d8A4286E6311F79227430b7862311cd3", "deployed_at": 0 }, "Metis Andromeda": { - "on_ramp": "0x5b23A0a103fC9028363B3BC3577e8Bd45B8E819F", + "on_ramp": "0xF1e73c37CDa8E47768De2246AEf5eFD4d76330ae", "deployed_at": 0 }, "Mode Mainnet": { - "on_ramp": "0x3920BF474BB50fffb4B77c1e6e66F65210D1D722", + "on_ramp": "0xd236ea4DDE7de1e594021764E2f6Cd8e8cD7F047", "deployed_at": 0 }, "Optimism Mainnet": { - "on_ramp": "0xC09b72E8128620C40D89649019d995Cc79f030C3", + "on_ramp": "0xAFECc7b67c6a8e606e94ce4e2F70D83C2206C2cb", "deployed_at": 0 }, "Polygon Mainnet": { - "on_ramp": "0x122F05F49e90508F089eE8D0d868d1a4f3E5a809", + "on_ramp": "0x6087d6C33946670232DF09Fe93eECbaEa3D6864d", "deployed_at": 0 }, "WeMix Mainnet": { - "on_ramp": "0x66a0046ac9FA104eB38B04cfF391CcD0122E6FbC", + "on_ramp": "0x52e51f245e600C6A87Ef2090d607D2a0eAedA1a6", "deployed_at": 0 }, "ZKSync Mainnet": { - "on_ramp": "0x2C1016053d9873270d71613cA321aE97Fc89201d", + "on_ramp": "0xd67F6713Fa4448548c984a9a7DCFBD13B0fB78D6", "deployed_at": 0 } }, "dest_contracts": { "Avalanche Mainnet": { - "off_ramp": "0xe0109912157d5B75ea8b3181123Cf32c73bc9920", - "commit_store": "0xDaa61b8Cd85977820f92d1e749E1D9F55Da6CCEA", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x95095007d5Cc3E7517A1A03c9e228adA5D0bc376", + "commit_store": "0x46679C9E93B7312A9191A9aD12A73b0c86A33623", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "BSC Mainnet": { - "off_ramp": "0xB1b705c2315fced1B38baE463BE7DDef531e47fA", - "commit_store": "0x310cECbFf14Ad0307EfF762F461a487C1abb90bf", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x16B9709F8A23B9EB922E8Dde7EaB1Ede7C79F663", + "commit_store": "0x6c3fD63b9BdE38C414530727a5De858ca023cFc4", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Base Mainnet": { - "off_ramp": "0xdB19F77F87661f9be0F557cf9a1ebeCf7D8F206c", - "commit_store": "0x6e37f4c82d9A31cc42B445874dd3c3De97AB553f", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xb62178f8198905D0Fa6d640Bdb188E4E8143Ac4b", + "commit_store": "0x8F60C335a5d2BEC6B32867d3C05C377E88640AaF", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Blast Mainnet": { - "off_ramp": "0x449C59F4Ef3b1802DD054dd7837Eb2Ca91aFAB84", - "commit_store": "0x1E0e8B01693A248b3Aa1e5aca36336F9022Ceac0", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x40314FeC27C5FCc7AaA05e618802A3fEA8E23Ae3", + "commit_store": "0xe7C1904E00BAf5Ca61926da0d1d2B036f14A3ad8", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Ethereum Mainnet": { - "off_ramp": "0x542ba1902044069330e8c5b36A84EC503863722f", - "commit_store": "0x060331fEdA35691e54876D957B4F9e3b8Cb47d20", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x91e46cc5590A4B9182e47f40006140A7077Dec31", + "commit_store": "0x86be76A0FA2bD3ECB69330cBb4fd1f62c48F43E3", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Gnosis Mainnet": { - "off_ramp": "0x0C00414D9dcDB2DA7BF8AF26aE2deb617f09e756", - "commit_store": "0x1d464cd86c5C8358d56281aB31d2213534CCEA13", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xeE53872d1C695933B34cE0a11B58613CBBf37e20", + "commit_store": "0x5D88518a198b99F096d2893092a568A97F60B8d4", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Metis Andromeda": { - "off_ramp": "0xeF8dEb0c01f7389AD4ae05DAB30120dba915D53c", - "commit_store": "0xE594a09Aa8bCb55188758826A160615B95A6F3fE", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xF1A4DE22FF792b0457306C39f4CB5822Ab47bdAE", + "commit_store": "0x7F20F4374f8d99201F22434ad59f96bE898A9E0B", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Mode Mainnet": { - "off_ramp": "0xEDE7ADACFbD27DBEBbE2d6C3BaDf12a634a72Faa", - "commit_store": "0x032B209a6B7a00336047505b55a4cBFBd29eE2c1", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xa964355d8eBa62E9b043Eb27eEe6d999Ecc69429", + "commit_store": "0x72C3cdA94eCAC06f7605301dd7144815C2F05A03", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Optimism Mainnet": { - "off_ramp": "0xeeed4D86F3E0e6d32A6Ad29d8De6A0Dc91963A5f", - "commit_store": "0xbbB563c4d98020b9c0f3Cc34c2C0Ef9676806E35", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x27a971D482335d0f8d1917451390734f7372A4a3", + "commit_store": "0x6642E640321e1Ad01eef2fC2ad5427D84A2Ee269", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Polygon Mainnet": { - "off_ramp": "0x9bDA7c8DCda4E39aFeB483cc0B7E3C1f6E0D5AB1", - "commit_store": "0x63a0AeaadAe851b990bBD9dc41f5C1B08b32026d", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xcabc2D71dC3172a154A5A34cD706B050e0ef9b6f", + "commit_store": "0x78B15A57889200F246fc52790c4F3DfC37d82Aa2", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "WeMix Mainnet": { - "off_ramp": "0xEEf5Fb4c4953F9cA9ab1f25cE590776AfFc2c455", - "commit_store": "0xD268286A277095a9C3C90205110831a84505881c", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x893c14bA328A49336a188F972f997C0d7286B8E4", + "commit_store": "0xc986D260b096E8708D82063309fB98734481A045", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "ZKSync Mainnet": { - "off_ramp": "0x50Fc0de671c775301e1Bdf19C17E778D0f978f6F", - "commit_store": "0x87732C2647168818ED49268EdA8A98C2e62ed744", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x052CF0c46375287255c71B179b10a7BFFD97502F", + "commit_store": "0xE19E9765857A2371d849FDd26D62D2463fb7a0a9", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" } } }, @@ -135,82 +135,82 @@ Data = """ "fee_token": "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7", "arm": "0x4f6Ec25f06A114ADD3154DC17fb637F750AdaA31", "router": "0xF4c7E640EdA248ef95972845a62bdC74237805dB", - "price_registry": "0x2d3b38E0a4DFFDad2A613f7760bE1683F272eA18", + "price_registry": "0xfA4edD04eaAcDB07c8D73621bc1790eC50D8c489", "wrapped_native": "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7", "src_contracts": { "Arbitrum Mainnet": { - "on_ramp": "0x98f51B041e493fc4d72B8BD33218480bA0c66DDF", + "on_ramp": "0x4e910c8Bbe88DaDF90baa6c1B7850DbeA32c5B29", "deployed_at": 0 }, "BSC Mainnet": { - "on_ramp": "0x8eaae6462816CB4957184c48B86afA7642D8Bf2B", + "on_ramp": "0xe6e161d55019AA5960DcF0Af9bB6e4d574C69F99", "deployed_at": 0 }, "Base Mainnet": { - "on_ramp": "0x268fb4311D2c6CB2bbA01CCA9AC073Fb3bfd1C7c", + "on_ramp": "0x139D4108C23e66745Eda4ab47c25C83494b7C14d", "deployed_at": 0 }, "Ethereum Mainnet": { - "on_ramp": "0xD0701FcC7818c31935331B02Eb21e91eC71a1704", + "on_ramp": "0xe8784c29c583C52FA89144b9e5DD91Df2a1C2587", "deployed_at": 0 }, "Gnosis Mainnet": { - "on_ramp": "0xBd0B9317F6AaA1085993F7b4CD468dE7A6428722", + "on_ramp": "0x38fd0DF16F6fD0a2C3Ec6615c73e50F5d027b8bA", "deployed_at": 0 }, "Optimism Mainnet": { - "on_ramp": "0x8629008887E073260c5434D6CaCFc83C3001d211", + "on_ramp": "0x3e3b4Fba004E7824219e79aE9f676d9D41A216Fa", "deployed_at": 0 }, "Polygon Mainnet": { - "on_ramp": "0x97500490d9126f34cf9aA0126d64623E170319Ef", + "on_ramp": "0x5570a4E979d7460F13b84075ACEF69FAc73914b1", "deployed_at": 0 }, "WeMix Mainnet": { - "on_ramp": "0x9b1ed9De069Be4d50957464b359f98eD0Bf34dd5", + "on_ramp": "0x1DA12512f852DAaba7883340A4074FfB73FA8f21", "deployed_at": 0 } }, "dest_contracts": { "Arbitrum Mainnet": { - "off_ramp": "0x770b1375F86E7a9bf30DBe3F97bea67193dC9135", - "commit_store": "0x23E2b34Ce8e12c53f8a39AD4b3FFCa845f8E617C", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x508Ea280D46E4796Ce0f1Acf8BEDa610c4238dB3", + "commit_store": "0x20bEde74Da64C9aE47FFDf4B87613752CD13bE5D", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "BSC Mainnet": { - "off_ramp": "0x83F53Fc798FEbfFbdF84830AD403b9989187a06C", - "commit_store": "0xD8ceCE2D7794385E00Ce3EF94550E732b0A0B959", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x6CDAa2711BdF0B719911BF00588A79FA97bf9264", + "commit_store": "0x4c05E7AB694C602De3135e025aEc7F7de06E80F7", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Base Mainnet": { - "off_ramp": "0x4d6A796Bc85dcDF41ce9AaEB50B094C6b589748f", - "commit_store": "0xc4C4358FA01a04D6c6FE3b96a351946d4c2715C2", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x37879EBFCb807f8C397fCe2f42DC0F5329AD6823", + "commit_store": "0xDe615EEaD232BEECF6c9b71c293A387B97814E8D", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Ethereum Mainnet": { - "off_ramp": "0x5B833BD6456c604Eb396C0fBa477aD49e82B1A2a", - "commit_store": "0x23E23958D220B774680f91c2c91a6f2B2f610d7e", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xE5F21F43937199D4D57876A83077b3923F68EB76", + "commit_store": "0xf0F791901854fAb16adeBd60F0639b960B6ea0CF", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Gnosis Mainnet": { - "off_ramp": "0xDE7ebf1Dc753D916A9fbEC4ae521Ee74EC2d0B5f", - "commit_store": "0x2dbc917b4DD455532015949c3103B64fcDB891b2", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x1181A59FF0BAEd1E0EA77e919185cB8C3D5D3125", + "commit_store": "0x60b2Bc7858D6296D8c4370E35a930E5ddF13085E", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Optimism Mainnet": { - "off_ramp": "0xb68A3EE8bD0A09eE221cf1859Dd5a4d5765188Fe", - "commit_store": "0x83DCeeCf822981F9F8552925eEfd88CAc1905dEA", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x376C0AFC9E64efE0d9202E1F02c3d7f9Dc15e404", + "commit_store": "0xF8728f8Cd9C809287e6a97B71A2cdfD2c3C034cE", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Polygon Mainnet": { - "off_ramp": "0x19250aBE66B88F214d02B6f3BF80F4118290C619", - "commit_store": "0x87A0935cE6254dB1252bBac90d1D07D04846aDCA", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xFf49E35626Eba28Bee1d251782AB75A6cEd91c45", + "commit_store": "0xee2570De22C0D07d0FaBC1169dC5EcA342B838Da", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "WeMix Mainnet": { - "off_ramp": "0x317dE8bc5c3292E494b6496586696d4966A922B0", - "commit_store": "0x97Fbf3d6DEac16adC721aE9187CeEa1e610aC7Af", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xFA5CF1bBFe0Ba5c01e60513EF8960945A99B78A4", + "commit_store": "0x671c83B1Ebe798bfC625E99Be0FF7C48F6E4C491", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" } } }, @@ -219,100 +219,100 @@ Data = """ "fee_token": "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c", "arm": "0x56491A98199aD2e687Ea9D0cFB7b4AC57B4980Fc", "router": "0x34B03Cb9086d7D758AC55af71584F81A598759FE", - "price_registry": "0x18C3D917D55Bc1784a3d4729AA3e2C1ecd662fFd", + "price_registry": "0xd64aAbD70A71d9f0A00B99F6EFc1626aA2dD43C7", "wrapped_native": "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c", "src_contracts": { "Arbitrum Mainnet": { - "on_ramp": "0x2788b46BAcFF49BD89562e6bA5c5FBbbE5Fa92F7", + "on_ramp": "0x5577c19bD183e39a007ce4CE236f1D91e9132D5c", "deployed_at": 0 }, "Avalanche Mainnet": { - "on_ramp": "0x6aa72a998859eF93356c6521B72155D355D0Cfd2", + "on_ramp": "0x43F00dBf0Aa61A099c674A74FBdCb93786564950", "deployed_at": 0 }, "Base Mainnet": { - "on_ramp": "0x70bC7f7a6D936b289bBF5c0E19ECE35B437E2e36", + "on_ramp": "0xdABb6De5eC48dd2fcF28ac85CbEFe3F19E03F1BD", "deployed_at": 0 }, "Blast Mainnet": { - "on_ramp": "0x02082b23D35d2670B8a636A431F3C30AF9d21e07", + "on_ramp": "0x0b7Bfe549F26AF4B6aA5246CB3FD96C8a5c23a68", "deployed_at": 0 }, "Ethereum Mainnet": { - "on_ramp": "0x0Bf40b034872D0b364f3DCec04C7434a4Da1C8d9", + "on_ramp": "0x35C724666ba31632A56Bad4390eb69f206ab60C7", "deployed_at": 0 }, "Gnosis Mainnet": { - "on_ramp": "0xAc9fE4179816077674d769698306CE6A7C6A1096", + "on_ramp": "0x83AC865c2E18f2CDc1d10126987FfC465e11c0DF", "deployed_at": 0 }, "Mode Mainnet": { - "on_ramp": "0x4A83dA46c148AB5941a379b4cA49f42d14281C78", + "on_ramp": "0x9d4d125788A548C2f69fAC7f8C3A64FA21d18C9e", "deployed_at": 0 }, "Optimism Mainnet": { - "on_ramp": "0x4FEB11A454C9E8038A8d0aDF599Fe7612ce114bA", + "on_ramp": "0x3A3649852A518ab180f41f28288c6c9184563616", "deployed_at": 0 }, "Polygon Mainnet": { - "on_ramp": "0x6bD4754D86fc87FE5b463D368f26a3587a08347c", + "on_ramp": "0x1C88e3Fd2B0a8735D1b19A77AA6e2333555BB95c", "deployed_at": 0 }, "WeMix Mainnet": { - "on_ramp": "0x1467fF8f249f5bc604119Af26a47035886f856BE", + "on_ramp": "0x9BaFC5E78C0051c7Bcd1EF37FF02fcBd31B37a72", "deployed_at": 0 } }, "dest_contracts": { "Arbitrum Mainnet": { - "off_ramp": "0x3DA330fd8Ef10d93cFB7D4f8ecE7BC1F10811feC", - "commit_store": "0x86D55Ff492cfBBAf0c0D42D4EE615144E78b3D02", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x2A9C65afF39758CeAa24dBD1ACd1BeB3618e6780", + "commit_store": "0x99C7C97Ed175A3f0BFd4f52526E7B1310bB3fc16", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Avalanche Mainnet": { - "off_ramp": "0x37a6fa55fe61061Ae97bF7314Ae270eCF71c5ED3", - "commit_store": "0x1f558F6dcf0224Ef1F78A24814FED548B9602c80", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xc69a550470bEbC5c3Be98A4C3dD26C6AdD90C64b", + "commit_store": "0x49FeF2978569E8061a7CA5cC676d46970613e9D0", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Base Mainnet": { - "off_ramp": "0x574c697deab06B805D8780898B3F136a1F4892Dc", - "commit_store": "0x002B164b1dcf4E92F352DC625A01Be0E890EdEea", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x133672C0F0067573254dd7C8C9818a37d6208610", + "commit_store": "0xEc44EFcf3E0aC801C742e444B130918a5a3A87E9", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Blast Mainnet": { - "off_ramp": "0x6500EDFBD27d34b7B69D0D45865ddaC4A1ceafE1", - "commit_store": "0x3A328B3fA852409415c15271442EFE4c77C04992", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x38cA434FE65D540942A36c84FdFD4B7C7a9a4612", + "commit_store": "0xF70409dC69Bc50aA30b001d45C7F9E2C706Ad387", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Ethereum Mainnet": { - "off_ramp": "0x181Bb1E97b0bDD1D85E741ad0943552D3682cc35", - "commit_store": "0x3fF27A34fF0FA77921C3438e67f58da1a83e9Ce1", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xF616733641D420207b8F30db9C4cE39684768991", + "commit_store": "0x7aa39A9c9D539b5E7388872a193b3447D34bf11F", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Gnosis Mainnet": { - "off_ramp": "0xBE9b0cc569E970dAb953d336c670fc6b7c856c19", - "commit_store": "0xEe89CC6C2236d3b99C2D9c0b3b911690F757FadF", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x53AF5cE4534C39582E6a5E3fD77946E0c3BFe870", + "commit_store": "0xe7a0Ffc182E2330d19fF79adEEC637094c02dcA3", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Mode Mainnet": { - "off_ramp": "0x6C702159daA4DEbae32E294c584B1EaF2356cB1A", - "commit_store": "0x73C8d1E9e240331E3345c6fBe6CDFC71B742B69C", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xFc2278eBc27B9d205e3DC9F1b88D6D863D71190D", + "commit_store": "0x92eeb265F465Aff3AE708117ba7aE35279227845", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Optimism Mainnet": { - "off_ramp": "0xE7E080C8d62d595a223C577C7C8d1f75d9A5E664", - "commit_store": "0xF4d53346bDb6d393C74B0B72Aa7D6689a3eAad79", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x3c5E62cdFD08e23a0961ff2A3155CaBb96cbc89D", + "commit_store": "0xDC39E05264D0C17eD16F2Db363364B127Cf56d75", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Polygon Mainnet": { - "off_ramp": "0x26af2046Da85d7f6712D5edCa81B9E3b2e7A60Ab", - "commit_store": "0x4C1dA405a789AC2853A69D8290B8B9b47a0374F8", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x21159ebdA3E6A2437bCD6ef39853042ACC436D2D", + "commit_store": "0x018Bb120265672C699969a9e2193755d4CF1ca16", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "WeMix Mainnet": { - "off_ramp": "0xC027C5AEb230008c243Be463A73571e581F94c13", - "commit_store": "0x2EB426C8C54D740d1FC856eB3Ff96feA03957978", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x512CA54a0F6447AC41c07Da3336DFcA042D88A7B", + "commit_store": "0xae79C737801b04ECA277d50FDeaC4006C3725F62", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" } } }, @@ -321,91 +321,91 @@ Data = """ "fee_token": "0x4200000000000000000000000000000000000006", "arm": "0x91cB19E7c4Ba9B08CF544cDc9143042150B007C3", "router": "0x881e3A65B4d4a04dD529061dd0071cf975F58bCD", - "price_registry": "0x1bA15c57c8b74cD32443D7583E7f6d7c638aCf46", + "price_registry": "0x6337a58D4BD7Ba691B66341779e8f87d4679923a", "wrapped_native": "0x4200000000000000000000000000000000000006", "src_contracts": { "Arbitrum Mainnet": { - "on_ramp": "0x1E5Ca70d1e7A1B26061125738a880BBeA42FeB21", + "on_ramp": "0x9D0ffA76C7F82C34Be313b5bFc6d42A72dA8CA69", "deployed_at": 0 }, "Avalanche Mainnet": { - "on_ramp": "0xBE5a9E336D9614024B4Fa10D8112671fc9A42d96", + "on_ramp": "0x4be6E0F97EA849FF80773af7a317356E6c646FD7", "deployed_at": 0 }, "BSC Mainnet": { - "on_ramp": "0xdd4Fb402d41Beb0eEeF6CfB1bf445f50bDC8c981", + "on_ramp": "0xE5FD5A0ec3657Ad58E875518e73F6264E00Eb754", "deployed_at": 0 }, "Blast Mainnet": { - "on_ramp": "0xCCC32e2794EaD73f0a0a514Ac1c78D048968ab81", + "on_ramp": "0x9A59832b85217C20b17a990A45BD5d0F3de36266", "deployed_at": 0 }, "Ethereum Mainnet": { - "on_ramp": "0xDEA286dc0E01Cb4755650A6CF8d1076b454eA1cb", + "on_ramp": "0x56b30A0Dcd8dc87Ec08b80FA09502bAB801fa78e", "deployed_at": 0 }, "Gnosis Mainnet": { - "on_ramp": "0xcDD0e963E0708a4E936202396983E458cFA4A363", + "on_ramp": "0xDcFB24AEbcB9Edfb6746a045DDcae402381F984B", "deployed_at": 0 }, "Mode Mainnet": { - "on_ramp": "0x626aCCbDDD73532df1caEDb5628Fdc40C5f429Ba", + "on_ramp": "0xEB50Fc6F57AAc6bf060A2Dfc6479fED592e6e184", "deployed_at": 0 }, "Optimism Mainnet": { - "on_ramp": "0xd952FEAcDd5919Cc5E9454b53bF45d4E73dD6457", + "on_ramp": "0x362E6bE957c18e268ad91046CA6b47EB09AD98C1", "deployed_at": 0 }, "Polygon Mainnet": { - "on_ramp": "0x3DB8Bea142e41cA3633890d0e5640F99a895D6A5", + "on_ramp": "0xd3Bde678BB706Cf727A512515C254BcF021dD203", "deployed_at": 0 } }, "dest_contracts": { "Arbitrum Mainnet": { - "off_ramp": "0x8531E63aE9279a1f0D09eba566CD1b092b95f3D5", - "commit_store": "0x327E13f54c7871a2416006B33B4822eAAD357916", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x7D38c6363d5E4DFD500a691Bc34878b383F58d93", + "commit_store": "0x17891fe60a577c5E1e4a4Ddd78E642428A56039f", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Avalanche Mainnet": { - "off_ramp": "0x8345F2fF67e5A65e85dc955DE1414832608E00aD", - "commit_store": "0xd0b13be4c53A6262b47C5DDd36F0257aa714F562", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x61C3f6d72c80A3D1790b213c4cB58c3d4aaFccDF", + "commit_store": "0x700C6715734111a6D1Cf414F46D85627b298B5dd", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "BSC Mainnet": { - "off_ramp": "0x48a51f5D38BE630Ddd6417Ea2D9052B8efc91a18", - "commit_store": "0xF97127e77252284EC9D4bc13C247c9D1A99F72B0", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x45d524b6Fe99C005C52C65c578dc0e02d9751083", + "commit_store": "0x1ccD0D49e283789a73E882B0ED4B5b1163675c3C", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Blast Mainnet": { - "off_ramp": "0x15F54FDd37ccC8E5a0b64633C95Ef8209Fd86401", - "commit_store": "0x52b5b4f3Cc50E38f736f23897f192430E131ccB8", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x941F0E2E0556aCf60fE0f09972f599d9F8916F01", + "commit_store": "0x575F920e3ef294EA80efB1A4C815EF4B8a67878F", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Ethereum Mainnet": { - "off_ramp": "0xEC0cFe335a4d53dBA70CB650Ab56eEc32788F0BB", - "commit_store": "0x0ae3c2c7FB789bd05A450CD3075D11f6c2Ca4F77", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xCA04169671A81E4fB8768cfaD46c347ae65371F1", + "commit_store": "0xb40659aACb709D1D54c80FC0d38b15705358Ce0B", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Gnosis Mainnet": { - "off_ramp": "0xA24D3Bc3A59798a57AF58f69c89DC1C8aFD78F18", - "commit_store": "0x672dbdC3aF7eE37436fe101531D33266D85F33c9", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x300977dBA924af14E166B31F4926892B1f310661", + "commit_store": "0x932D6D5c6647e6495Ed3473ff0F4e31a6056D837", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Mode Mainnet": { - "off_ramp": "0xFC30bFe46b11D4E25C6f7492fd064A70FbF18848", - "commit_store": "0xaeDBe55633F74A291F0A43Daa0Fd719615b78363", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x639Dc04368006544eba7CbC959f3e4361bfEAB0d", + "commit_store": "0x2D3FC7f8b03718157359266ac06AF6373aFee2f1", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Optimism Mainnet": { - "off_ramp": "0xf50c0d2a8B6Db60f1D93E60f03d0413D56153E4F", - "commit_store": "0x16f72C15165f7C9d74c12fDF188E399d4d3724e4", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x18095fbD53184A50C2BB3929a6c62Ca328732062", + "commit_store": "0xa8FA8aE51dB9661e7D1c21141d967d07110036cb", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Polygon Mainnet": { - "off_ramp": "0x75F29f058b31106F99caFdc17c9b26ADfcC7b5D7", - "commit_store": "0xb719616E732581B570232DfB13Ca49D27667Af9f", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x74d574D11977fC8D40f8590C419504cbE178ADB7", + "commit_store": "0x565f70396Ff82C23d25Dd3E57A9A66367dccdF3B", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" } } }, @@ -418,42 +418,42 @@ Data = """ "wrapped_native": "0x4300000000000000000000000000000000000004", "src_contracts": { "Arbitrum Mainnet": { - "on_ramp": "0x42E1f5f5ACCe6e4971D9B9468D7A9Abed8D69DdD", + "on_ramp": "0x28f7E57cEE31241B4B8B72e6b710c4dC2e9bEb28", "deployed_at": 0 }, "BSC Mainnet": { - "on_ramp": "0x9c98d7aE731b0A53bedffBc1a12d9d43501Ea464", + "on_ramp": "0x01D1A2Ed2053e410177f8E762aF635ee78b7a581", "deployed_at": 0 }, "Base Mainnet": { - "on_ramp": "0x955f139225F5d7021EB911ED2787a795f71E5eb6", + "on_ramp": "0xAbBC1fC0C919ecFb0220e90749111e0619abf79A", "deployed_at": 0 }, "Ethereum Mainnet": { - "on_ramp": "0xBD9bf9AA79adF083BB7100848Eb15F4e8282E27e", + "on_ramp": "0xEa8112530cA10945C2aA976f8F615582Af9B70fa", "deployed_at": 0 } }, "dest_contracts": { "Arbitrum Mainnet": { - "off_ramp": "0x01A38cd2da195C704bA192fCCDddd8986cb7EdE9", - "commit_store": "0xab6D69db1C1E9B97a26eB3983b0878AdeD248200", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x8e4E966a3f6b3aB56185800a2afFe75CCf7B4DfD", + "commit_store": "0x4a577dC79BfeF5C84a55EF6Df30400083F16AE8d", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "BSC Mainnet": { - "off_ramp": "0xabC7Dffb2590c44a201EC7532382e1fc01Cd9eEb", - "commit_store": "0xA3086bf1D609d8e8028E8339e4aa4362C7da339D", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x9A9f3714b517231869b97F3b49E2ba1009499d9b", + "commit_store": "0xAB0eCFDE9E681B1CD04D6C5536BafdBada180716", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Base Mainnet": { - "off_ramp": "0x0406F8f66C10Da99ff518bc2242e0Ec486a2c787", - "commit_store": "0xc6A97d753a3001e0B893e5FA2b0ec3d623af6C20", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x5837622b622D3c88Faf5491324575f5c0BB40001", + "commit_store": "0x9fAE0d8F4A15Fb96B999aad81a1C0e39deFDF49e", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Ethereum Mainnet": { - "off_ramp": "0x4e0092bBC8EfAb6Eca295caB66986193b90a1Bb9", - "commit_store": "0xd7cA96B58EE33FdB3aa1392c30eD02645b1F28e2", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xFf094AC08B0AA8Ab3d29e034a51199a0ddE3d8C8", + "commit_store": "0x544f068b14e4FAc004579f158ccCE14225264c71", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" } } }, @@ -466,15 +466,15 @@ Data = """ "wrapped_native": "0x2021B12D8138e2D63cF0895eccABC0DFc92416c6", "src_contracts": { "Ethereum Mainnet": { - "on_ramp": "0x27C96A8a2f70a8408aD6c620717a3bDaA54bb10b", + "on_ramp": "0xc319484eF6cdA3a7f4D470e660b343FB569e9A1e", "deployed_at": 0 } }, "dest_contracts": { "Ethereum Mainnet": { - "off_ramp": "0x90902C0AEE857F3A42f2beBEa38724cE7b7a0cff", - "commit_store": "0x25adA90B241143DD5Df04Fb06C1fF6E7f7624ad9", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x1B12D218280DD1767304A00070101a91f7A61470", + "commit_store": "0x8Ad3FEFf222e2200CbC79cC3AdbaE3b64a37d1F8", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" } } }, @@ -483,127 +483,127 @@ Data = """ "fee_token": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "arm": "0xdCD48419bD5Cd9d1b097695F2af4Ee125aADF84F", "router": "0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D", - "price_registry": "0x020082A7a9c2510e1921116001152DEE4da81985", + "price_registry": "0x8c9b2Efb7c64C394119270bfecE7f54763b958Ad", "wrapped_native": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "src_contracts": { "Arbitrum Mainnet": { - "on_ramp": "0x925228D7B82d883Dde340A55Fe8e6dA56244A22C", + "on_ramp": "0x69eCC4E2D8ea56E2d0a05bF57f4Fd6aEE7f2c284", "deployed_at": 0 }, "Avalanche Mainnet": { - "on_ramp": "0x3df8dAe2d123081c4D5E946E655F7c109B9Dd630", + "on_ramp": "0xaFd31C0C78785aDF53E4c185670bfd5376249d8A", "deployed_at": 0 }, "BSC Mainnet": { - "on_ramp": "0x91D25A56Db77aD5147437d8B83Eb563D46eBFa69", + "on_ramp": "0x948306C220Ac325fa9392A6E601042A3CD0b480d", "deployed_at": 0 }, "Base Mainnet": { - "on_ramp": "0xe2c2AB221AA0b957805f229d2AA57fBE2f4dADf7", + "on_ramp": "0xb8a882f3B88bd52D1Ff56A873bfDB84b70431937", "deployed_at": 0 }, "Blast Mainnet": { - "on_ramp": "0x4545F9a17DA50110632C14704a15d893BF9CBD27", + "on_ramp": "0x6751cA96b769129dFE6eB8E349c310deCEDb4e36", "deployed_at": 0 }, "Celo": { - "on_ramp": "0xEd5bE9508ae56531cc0EDe6A3bD588Eb9E2e3cfa", + "on_ramp": "0x741599d9a5a1bfC40A22f530fbCd85E2718e9F90", "deployed_at": 0 }, "Gnosis Mainnet": { - "on_ramp": "0xF538dA6c673A30338269655f4e019B71ba58CFd4", + "on_ramp": "0xf50B9A46C394bD98491ce163d420222d8030F6F0", "deployed_at": 0 }, "Metis Andromeda": { - "on_ramp": "0xa5ef33B57dD8B653F9A9EA7114f46376d18264aC", + "on_ramp": "0x75d536eED32f4c8Bb39F4B0c992163f5BA49B84e", "deployed_at": 0 }, "Mode Mainnet": { - "on_ramp": "0x466a078d17e3706a9414ACc48029EE9Bae4C9b65", + "on_ramp": "0xeA6d4a24B262aB3e61a8A62f018A30beCD086f82", "deployed_at": 0 }, "Optimism Mainnet": { - "on_ramp": "0x86B47d8411006874eEf8E4584BdFD7be8e5549d1", + "on_ramp": "0x3455D8E039736944e66e19eAc77a42e8077B07bf", "deployed_at": 0 }, "Polygon Mainnet": { - "on_ramp": "0x35F0ca9Be776E4B38659944c257bDd0ba75F1B8B", + "on_ramp": "0x15a9D79d6b3485F70bF82bC49dDD1fcB37A7149c", "deployed_at": 0 }, "WeMix Mainnet": { - "on_ramp": "0xCbE7e5DA76dC99Ac317adF6d99137005FDA4E2C4", + "on_ramp": "0xdEFeADd30D5BFD403d86245b43e39a73d76423cC", "deployed_at": 0 }, "ZKSync Mainnet": { - "on_ramp": "0xD54C93A99CBCb8D865E13DA321B540171795A89f", + "on_ramp": "0x9B14AE850653dD0E30fBC93ab7f77D0d638a365B", "deployed_at": 0 } }, "dest_contracts": { "Arbitrum Mainnet": { - "off_ramp": "0xeFC4a18af59398FF23bfe7325F2401aD44286F4d", - "commit_store": "0x9B2EEd6A1e16cB50Ed4c876D2dD69468B21b7749", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xdf615eF8D4C64d0ED8Fd7824BBEd2f6a10245aC9", + "commit_store": "0xf7B343A17445F175f2Dd9f5CB29BAf0a8dE75ed3", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Avalanche Mainnet": { - "off_ramp": "0x569940e02D4425eac61A7601632eC00d69f75c17", - "commit_store": "0x2aa101BF99CaeF7fc1355D4c493a1fe187A007cE", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xd98E80C79a15E4dbaF4C40B6cCDF690fe619BFBb", + "commit_store": "0xA9f9bF2b643348c0884f2eBA4F712E833DA9a2b8", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "BSC Mainnet": { - "off_ramp": "0x7Afe7088aff57173565F4b034167643AA8b9171c", - "commit_store": "0x87c55D48DF6EF7B08153Ab079e76bFEcbb793D75", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x66d84fedED0e51aeB47ceD1BB2fc0221Ae8D7C12", + "commit_store": "0x9B9Ec8E26955c034828bBD78E22ab258d983dCdb", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Base Mainnet": { - "off_ramp": "0xdf85c8381954694E74abD07488f452b4c2Cddfb3", - "commit_store": "0x8DC27D621c41a32140e22E2a4dAf1259639BAe04", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x6B4B6359Dd5B47Cdb030E5921456D2a0625a9EbD", + "commit_store": "0xDaC3A82Cc5e7C137bF28e6EF4F68f29D66205ffe", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Blast Mainnet": { - "off_ramp": "0x1a904DbbaDdE629a1460e2F6E2E485Ce06Ed7599", - "commit_store": "0x3CB2A81bb8a188C5353CdFa9994ed8666556FC53", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xF4468E56179e6EF59d6f5B133D9355AAD91Ea9ae", + "commit_store": "0x52275dC17f9eD92230C8C4d57fD36d128701f694", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Celo": { - "off_ramp": "0xd5083684eE92dDeA117636ae5E2F1cb7fE4dfd46", - "commit_store": "0x831097033C88c82a7F1897b168Aa88cC44540C8f", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x794aE32b63b8a82a6e2Ec5017bbC6bfbddA5ce96", + "commit_store": "0x95deB0c4bB9168202d50E874865f9A1842b82D64", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Gnosis Mainnet": { - "off_ramp": "0xE93ec2A57e38C8541c893348cCafEAB01F7D47d4", - "commit_store": "0x118a9389960F86390A4F14ce4C95D6ff076C6bFC", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x70C705ff3eCAA04c8c61d581a59a168a1c49c2ec", + "commit_store": "0x9D93D536Ced80871Bf3DA5Bb47bAedE62c794f8A", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Metis Andromeda": { - "off_ramp": "0xCe6364dBe64D2789D916180131fAda2ABFF702E8", - "commit_store": "0x3d8a95adA63D406ee8232562AbD83CEdb0B90466", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x330349112e13232131Da51f9f3b153d825f65e61", + "commit_store": "0x0f89C7c0586536B618e0469402e1c8234bc52959", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Mode Mainnet": { - "off_ramp": "0xE8af3b68eDfFf65Ce48648009982380701f09B92", - "commit_store": "0x76264869a3eBF51a59FCa5ABa84ee2867c7F190e", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xb57D52F7Cb7BBD19a117585bbaf712108E56dd8f", + "commit_store": "0x01346721418045A6c07b71052e452eF8615e9084", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Optimism Mainnet": { - "off_ramp": "0xB095900fB91db00E6abD247A5A5AD1cee3F20BF7", - "commit_store": "0x4af4B497c998007eF83ad130318eB2b925a79dc8", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x562a2025E60AA19Aa03Ea41D70ea1FD3286d1D3B", + "commit_store": "0x83F3DA5aa2C7534d694B0acde7624573c830250D", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Polygon Mainnet": { - "off_ramp": "0x0af338F0E314c7551bcE0EF516d46d855b0Ee395", - "commit_store": "0xD37a60E8C36E802D2E1a6321832Ee85556Beeb76", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x718672076D6d51E4c76142B37bC99E4945d704a3", + "commit_store": "0x57b548C9c213EA2bcf60193E3D7fd2d2b53Fb9b3", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "WeMix Mainnet": { - "off_ramp": "0x3a129e6C18b23d18BA9E6Aa14Dc2e79d1f91c6c5", - "commit_store": "0x31f6ab382DDeb9A316Ab61C3945a5292a50a89AB", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xc1EcCE580B2C96f4fd202fB7c2a259ECe19a1bF2", + "commit_store": "0xA4755Cd68CA2092447c8c842659a2931f9110320", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "ZKSync Mainnet": { - "off_ramp": "0xb368c8946D9fa5A497cDe1Dff7213f9CdfD143Bf", - "commit_store": "0xa4d264470a67D9f6682EE12Bdc9c35Df44e3F194", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x6868FefbEFDc2B2FB75E6ED216dB1BeC02563D69", + "commit_store": "0x0d26BaE784c8986502E072F4e73B6168e2052045", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" } } }, @@ -616,69 +616,69 @@ Data = """ "wrapped_native": "0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d", "src_contracts": { "Arbitrum Mainnet": { - "on_ramp": "0x7A36511202f54a8A3Bc62Cc1df24bd391f7c9864", + "on_ramp": "0x140E6D5ba903F684944Dd27369d767DdEf958c9B", "deployed_at": 0 }, "Avalanche Mainnet": { - "on_ramp": "0x732753869bc6bB07Ec81A403F926bbF6fC2FeaE2", + "on_ramp": "0xB707a6D1d32CE99D5c669DeE71D30d25a066D32c", "deployed_at": 0 }, "BSC Mainnet": { - "on_ramp": "0xD5d33bc0BF395B39514B7f9f8F66ebc9D8e650Cb", + "on_ramp": "0xb485634dd2E545091722b9d4843d3644addf97e3", "deployed_at": 0 }, "Base Mainnet": { - "on_ramp": "0x400eFb50480a73FEc02b115b53F0Ec6EcFf03C67", + "on_ramp": "0xAAb6D9fc00aAc37373206e91789CcDE1E851b3E4", "deployed_at": 0 }, "Ethereum Mainnet": { - "on_ramp": "0x0F246651F1c2275B4E14d8ae166D1fd3Af05c405", + "on_ramp": "0x014ABcfDbCe9F67d0Df34574664a6C0A241Ec03A", "deployed_at": 0 }, "Optimism Mainnet": { - "on_ramp": "0x391516732884d3F8Eec3301C19b819E6e6044C17", + "on_ramp": "0x9379b446fcA75CA57834a4dA33f64ae317Be05e4", "deployed_at": 0 }, "Polygon Mainnet": { - "on_ramp": "0x566c7A2Cb557c36082301B97E998721D14E4bF7d", + "on_ramp": "0xD7a49AfEA62E77Ad6BEB2ed64673026271aae188", "deployed_at": 0 } }, "dest_contracts": { "Arbitrum Mainnet": { - "off_ramp": "0x1bee1FD97824288a36B725f9CF20E07A67d5113b", - "commit_store": "0xB3a48e8664C5dE26822ae44577b100b717C36a54", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x2C1539696E29012806a15Bcd9845Ed1278a9fd63", + "commit_store": "0x5b1762a6023157edaf2c46c818f447B1940765D6", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Avalanche Mainnet": { - "off_ramp": "0x633c19cCD7A818770f7BF59eB9C5AB632CDbc4D5", - "commit_store": "0xbbC073fb2D424eA45A571cc4dd91745E45d0aC73", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xe596D90EF0AEe10257109AC8394a85F8944bF6D0", + "commit_store": "0xd6Dc07804AE06f575C28094F99aCdDC1535904e7", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "BSC Mainnet": { - "off_ramp": "0x4D90524de5783257fd64d1a20689a5b9Bad25de0", - "commit_store": "0xAae8De9f1B7e2FFF0563c2BBf0c69593BD517b52", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x972a85d7ba0209F1896992B2687cC728cf769e50", + "commit_store": "0x5FB18729651f1EDA5ed5ac67594FD94Fa3DBcd29", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Base Mainnet": { - "off_ramp": "0x9118303DE7f4342F9B057f6EC1Be282aa543D99C", - "commit_store": "0xa75f463b8a1d8bf7694Ac13E02938894F45eFbaA", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xbeEDd1C5C13C5886c3d600e94Ff9e82C04A53C38", + "commit_store": "0x392304E3cb636f75Dc95340672F3b8A2359d5Ebc", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Ethereum Mainnet": { - "off_ramp": "0xFF61E57A2eE83FA262006C2DaF0D5fB2b36F3070", - "commit_store": "0xF433De9A293553c133E2dB90e226c2F2911f435C", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x658d9ae41A9c291De423d3B4B6C064f6dD0e7Ed2", + "commit_store": "0xd23391fCBb8a41b971f90bC6e95CC8beaD885221", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Optimism Mainnet": { - "off_ramp": "0x9D3aA479525a5BcE776dD83769e9F9b5B4dD4193", - "commit_store": "0x2B721632693A8BbABa3bA5F125C8cD33D66F28F7", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xd84E2316634ab6516Ecc829E2367633bfB3e4B6D", + "commit_store": "0x9d432DaF8aF8803baF6Cf560CF0f115c7D7b7f16", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Polygon Mainnet": { - "off_ramp": "0x9714098CDdAc380D4443293C55B6CBf6D6bbDbEb", - "commit_store": "0x4338f204C7698eE678d6c44117503f812ca1FA69", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x6d6a4a60E0E23dbea089c0fEbbA9c5912f02bc57", + "commit_store": "0x9CBe49E232aEF27B9d98aC752354879efd7b1E70", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" } } }, @@ -691,15 +691,15 @@ Data = """ "wrapped_native": "0x4200000000000000000000000000000000000001", "src_contracts": { "WeMix Mainnet": { - "on_ramp": "0x3C5Ab46fA1dB1dECD854224654313a69bf9fcAD3", + "on_ramp": "0xf3baf38136b55F656CC5fdd4417EB6C160877104", "deployed_at": 0 } }, "dest_contracts": { "WeMix Mainnet": { - "off_ramp": "0x2B555774B3D1dcbcd76efb7751F3c5FbCFABC5C4", - "commit_store": "0x213124614aAf31eBCE7c612A12aac5f8aAD77DE4", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xcB154Bb4ed63FC30C416Dd16A2d1C64D8DE8DfD5", + "commit_store": "0x6091D319080D06e1b656F83Ff001DAc124C55613", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" } } }, @@ -712,24 +712,24 @@ Data = """ "wrapped_native": "0x75cb093E4D61d2A2e65D8e0BBb01DE8d89b53481", "src_contracts": { "Arbitrum Mainnet": { - "on_ramp": "0x87353b87A373E1551D27EDacDaC1644741c6499F", + "on_ramp": "0x8d3039fE2400151c06Ae84a18CAf38dD9b6Ce58b", "deployed_at": 0 }, "Ethereum Mainnet": { - "on_ramp": "0xE43f9eD3146d76E627C2504E5140005027992De6", + "on_ramp": "0xdF5394c57A0570ECe45DE0c0fA2e722A672B9198", "deployed_at": 0 } }, "dest_contracts": { "Arbitrum Mainnet": { - "off_ramp": "0x2cc33de75dAFDb3F8F4f24244a9C420374e2C001", - "commit_store": "0x67fE38dB73be154a1f1a63221F898B9d5EE4eF63", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xc6bA5a79991b3775F28259BA551b30eCb0b6D499", + "commit_store": "0xb81b0EE9675879a2Dcaa70CCC3b2c2D38fa404b0", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Ethereum Mainnet": { - "off_ramp": "0xc2B1A8c931582D041ba5fF30AEB9fA828B30754d", - "commit_store": "0x90073Ea7A1Ee4Fe5d638B4216Bc60479Eba52001", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x1fd37Bf813D0723BEF614bC93d9D2Ce1AcB3228f", + "commit_store": "0x7C1efda9F744a2B4f88b924B03C6d6B53E3E390F", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" } } }, @@ -742,51 +742,51 @@ Data = """ "wrapped_native": "0x4200000000000000000000000000000000000006", "src_contracts": { "Arbitrum Mainnet": { - "on_ramp": "0x65Ad802d80aD6a96C5a4bc9e57E16099de99Dc7F", + "on_ramp": "0xb2e694efcDa0aeB81700019c3047F92fC3bb520E", "deployed_at": 0 }, "BSC Mainnet": { - "on_ramp": "0x8C5149ff7Cfd99dd561caE9B7abFAA0Ef79eAbeC", + "on_ramp": "0xeb7E8c40E95Cd31666359AaeB1F2CccaAB935643", "deployed_at": 0 }, "Base Mainnet": { - "on_ramp": "0x71dB32eF442c29d8cbf72a9AFcb1Ef12B35b0BF4", + "on_ramp": "0x347A070EA1B04bc2b4A8f14320688C277022C90e", "deployed_at": 0 }, "Ethereum Mainnet": { - "on_ramp": "0xbD5F9C193a7fEF5D578C55Ddfe4d08d6BCc15648", + "on_ramp": "0x7d2aF78868993a5a86676BA639eC0412709707D9", "deployed_at": 0 }, "Optimism Mainnet": { - "on_ramp": "0x659303e8d4306D3ea8676FB034d56FB6f37E19d9", + "on_ramp": "0x7AB4329D19A0255DA90Ee8dbAA60f8f0cB7950C1", "deployed_at": 0 } }, "dest_contracts": { "Arbitrum Mainnet": { - "off_ramp": "0x8d3E1b15ebC96cec1ffc092cEcAeA6c1DD00aF9b", - "commit_store": "0x1f1DEa0210aE346A20E270a1C3355d99b0B949D2", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x0Cb870C12013c2d5743585F85b298e129cE57203", + "commit_store": "0x682Af2Cfaa5aE554eF222728fF7C7168232e2Ea5", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "BSC Mainnet": { - "off_ramp": "0x7a57670Fa0Cf1Bc2665a1Ae0f5031b9f5a43dD3a", - "commit_store": "0x18ffb74D94175d00D8bB67B70737dE2cE45eed07", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xdfA601DA2163Ca2C77Eb32126E6B7A97024f6181", + "commit_store": "0xb88F947C85b1c6B1E2A0C22792BA58C40c07a644", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Base Mainnet": { - "off_ramp": "0xEfa90cE6289A2777cd5B8fb991B2D0Be44cA5067", - "commit_store": "0xACa5f0942Bb7fF297A7c25E8364373702D81bb3f", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x30612D8fb7EcD05ECb863560BA8806d88e8BbFAF", + "commit_store": "0xf84d023CCFF8b74e565117cBc034859D06EA1976", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Ethereum Mainnet": { - "off_ramp": "0xdF8f09AB4DfB49dEC8a0B8b7f1B7F4134252D3e9", - "commit_store": "0x8Ae635d264f20f1dbC0dea03712C194AdbeF50D1", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xb1caBa234721b8F12C545B3dC25B3F87f6a9c91B", + "commit_store": "0x67Ff921DA5d0B61a9b05BDFa92d9f5f992d7861a", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Optimism Mainnet": { - "off_ramp": "0xE4D6AAF678b986D3E6B7A85FA33d0519716a5525", - "commit_store": "0xBF80E30c8c013Ec0d05e2a959CF8000407C813EC", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x4adcD1FB4ec76A3c9960E048f81C19A51B2eAC49", + "commit_store": "0x7B58aF65DFD717fC0d044D860c8f9A85Ca6813D6", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" } } }, @@ -795,91 +795,91 @@ Data = """ "fee_token": "0x4200000000000000000000000000000000000006", "arm": "0x1c51b6D5BFcFB7ee82C80949DFD146dB157a7E49", "router": "0x3206695CaE29952f4b0c22a169725a865bc8Ce0f", - "price_registry": "0x9270AAA75F4B9038f4c25fEc665B02a150a90361", + "price_registry": "0xb52545aECE8C73A97E52a146757EC15b90Ed8488", "wrapped_native": "0x4200000000000000000000000000000000000006", "src_contracts": { "Arbitrum Mainnet": { - "on_ramp": "0x0C9BE7Cfd12c735E5aaE047C1dCB845d54E518C3", + "on_ramp": "0x6bA81b83091A23e8F2AA173B2b939fAf9E320DfB", "deployed_at": 0 }, "Avalanche Mainnet": { - "on_ramp": "0xD0D3E757bFBce7ae1881DDD7F6d798DDcE588445", + "on_ramp": "0xB9D655Ad5ba80036725d6c753Fa6AF0454cBF630", "deployed_at": 0 }, "BSC Mainnet": { - "on_ramp": "0xa3c9544B82846C45BE37593d5d9ACffbE61BF3A6", + "on_ramp": "0xfC51a4CF925f202d86c6092cda879689d2C17201", "deployed_at": 0 }, "Base Mainnet": { - "on_ramp": "0x0b1760A8112183303c5526C6b24569fd3A274f3B", + "on_ramp": "0xfE11cfC957cCa331192EAC60040b442303CcA0a9", "deployed_at": 0 }, "Ethereum Mainnet": { - "on_ramp": "0x55183Db1d2aE0b63e4c92A64bEF2CBfc2032B127", + "on_ramp": "0xE4C51Dc01A4E0aB14c7a7a2ed1655E9CF8A3E698", "deployed_at": 0 }, "Gnosis Mainnet": { - "on_ramp": "0x14aA3CC03583aA557DBca4ce72288Cc5F37DDE34", + "on_ramp": "0x604a9dda2e27D56cfCe457E437a61f4ED0De9dE6", "deployed_at": 0 }, "Mode Mainnet": { - "on_ramp": "0x034eA573B049210315110f7eA11c9618E32F08Ae", + "on_ramp": "0xc6d9Cb39e34D83d21A021504024887A0e96D4e94", "deployed_at": 0 }, "Polygon Mainnet": { - "on_ramp": "0x6B57145e322c877E7D91Ed8E31266eB5c02F7EfC", + "on_ramp": "0x9c725164b60E3f6d4d5b7A2841C63E9FD0988805", "deployed_at": 0 }, "WeMix Mainnet": { - "on_ramp": "0x82e9f4C5ec4a84E310d60D462a12042E5cbA0954", + "on_ramp": "0x6Dbc8D4e5556FD0B82bB0D67c94D0fA1cd288AbD", "deployed_at": 0 } }, "dest_contracts": { "Arbitrum Mainnet": { - "off_ramp": "0xaC8C94242aa8234Bf89682aBcDDf805AE8cff61D", - "commit_store": "0x55028780918330FD00a34a61D9a7Efd3f43ca845", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xEB3d6956BCf7b1E29634C8cd182fC9FA740Bce34", + "commit_store": "0x6569761680DaC4Bf940244E3cF198A069E34E91F", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Avalanche Mainnet": { - "off_ramp": "0x8dc6490A6204dF846BaBE809cB695ba17Df1F9B1", - "commit_store": "0xA190660787B6B183Dd82B243eA10e609327c7308", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xF8E38B4503418659F791F2135c4912F85BFB7988", + "commit_store": "0x23CAc55aDDF28179A999858720E9Fe686372083A", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "BSC Mainnet": { - "off_ramp": "0xE14501F2838F2fA1Ceb52E78ABdA289EcE1705EA", - "commit_store": "0xa8DD25B29787527Df283211C24Ac72B17150A696", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x51f37b538aD2Bcb9Eaf884859BF7C5Ec58AEc885", + "commit_store": "0xF472FEb09544Bf991773f4B94fe3F03e458d1b8d", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Base Mainnet": { - "off_ramp": "0xBAE6560eCa9B77Cb047158C783e36F7735C86037", - "commit_store": "0x6168aDF58e1Ad446BaD45c6275Bef60Ef4FFBAb8", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x519ee6B83f57df95486aeA6E26819cb7b4B8ee99", + "commit_store": "0xCfdF2b21D9777E2B0a221F6b6D8fe176461f058e", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Ethereum Mainnet": { - "off_ramp": "0xd2D98Be6a1C241e86C807e51cED6ABb51d044203", - "commit_store": "0x4d75A5cE454b264b187BeE9e189aF1564a68408D", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x9979c2dfEcA9051Cf7f08274d978984B2dB12C60", + "commit_store": "0x9358663E8f89df8EFE2346a3c4c1D65d03300576", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Gnosis Mainnet": { - "off_ramp": "0x4358640A2419119DBe0933b5F2c288c3EB2c082C", - "commit_store": "0x44d1a05ef6e54a3CB35a1497303bA272f15f45ed", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x01449040D92D75c58FaDc9Bc1c0eadc70C550484", + "commit_store": "0xb63230DfcE291DA76FD946EFbc966549F9300347", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Mode Mainnet": { - "off_ramp": "0xDf9717d724828537902Fb0c3B7C56c641463Fa38", - "commit_store": "0x8aEFF283381914E07Fc371601D59648ab6D2C0B1", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x5a4BEeafd345264360E6894a6bc5F54a70814E68", + "commit_store": "0x4E94a327A38E6F3509a5639dCF933CfF6DE93FFD", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Polygon Mainnet": { - "off_ramp": "0x7c6221880A1D62506b1A08Dab3Bf695A49AcDD22", - "commit_store": "0x0684076EE3595221861C50cDb9Cb66402Ec11Cb9", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x4BA0A3bD1E2b70b2fe165A53219e7eF6376849a4", + "commit_store": "0xA0f02e1F9C641C9610f688be84F889fE518b36e3", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "WeMix Mainnet": { - "off_ramp": "0x3e5B3b7559D39563a74434157b31781322dA712D", - "commit_store": "0x7954372FF6f80908e5A2dC2a19d796A1005f91D2", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x2f40dCCb74d8B2dd7af065232a06778f2D019375", + "commit_store": "0xd1111a601BAb64a6428426095206A43710CaE932", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" } } }, @@ -892,78 +892,78 @@ Data = """ "wrapped_native": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", "src_contracts": { "Arbitrum Mainnet": { - "on_ramp": "0xD16D025330Edb91259EEA8ed499daCd39087c295", + "on_ramp": "0x13263aC754d1e29430930672E3C0019f2BC44Ba2", "deployed_at": 0 }, "Avalanche Mainnet": { - "on_ramp": "0x5FA30697e90eB30954895c45b028F7C0dDD39b12", + "on_ramp": "0x56cb9Cd82553Bd8157e6504020c38f6DA4971717", "deployed_at": 0 }, "BSC Mainnet": { - "on_ramp": "0xF5b5A2fC11BF46B1669C3B19d98B19C79109Dca9", + "on_ramp": "0x164507757F7d5Ab35C6af44EeEB099F5be29Da57", "deployed_at": 0 }, "Base Mainnet": { - "on_ramp": "0x20B028A2e0F6CCe3A11f3CE5F2B8986F932e89b4", + "on_ramp": "0xD26A4E0c664E72e3c29E634867191cB1cb9AF570", "deployed_at": 0 }, "Ethereum Mainnet": { - "on_ramp": "0xFd77c53AA4eF0E3C01f5Ac012BF7Cc7A3ECf5168", + "on_ramp": "0x1DAcBae00c779913e6E9fc1A3323FbA4847ba53C", "deployed_at": 0 }, "Gnosis Mainnet": { - "on_ramp": "0x4616621704C81801A56D29c961F9395ee153d46C", + "on_ramp": "0xcc4A8CFd756895d91B476Dd5461286b300914aBf", "deployed_at": 0 }, "Optimism Mainnet": { - "on_ramp": "0x3111cfbF5e84B5D9BD952dd8e957f4Ca75f728Cf", + "on_ramp": "0x868B71490B36674B3B9006fa8711C6fA26A26631", "deployed_at": 0 }, "WeMix Mainnet": { - "on_ramp": "0x5060eF647a1F66BE6eE27FAe3046faf8D53CeB2d", + "on_ramp": "0x9363330c6d807a1393c1fd35893c64d26931CDe6", "deployed_at": 0 } }, "dest_contracts": { "Arbitrum Mainnet": { - "off_ramp": "0xa8a9eDa2867c2E0CE0d5ECe273961F1EcC3CC25B", - "commit_store": "0xbD4480658dca8496a65046dfD1BDD44EF897Bdb5", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x60f2788225CeE4a94f8E7589931d5A14Cbc4367d", + "commit_store": "0x4DEc80ED383171EC54699B22B869bE098d3cBac9", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Avalanche Mainnet": { - "off_ramp": "0xB9e3680639c9F0C4e0b02FD81C445094426244Ae", - "commit_store": "0x8c63d4e67f7c4af6FEd2f56A34fB4e01CB807CFF", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x35c1Bb5A9c2F3fa8f8dFF470a6bE7d362CeA1ef3", + "commit_store": "0xB3324b80f50a31b12c0C733560D3aA2a32dc5C33", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "BSC Mainnet": { - "off_ramp": "0x592773924741F0Da889a0dfdab71171Dd11E054C", - "commit_store": "0xEC4d35E1A85f770f4D93BA43a462c9d87Ef7017e", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xE58074f8F56E23836f088Ac8b4f3882c1b4CAcbb", + "commit_store": "0x2110a5f138364d788FDF54eCBa25C1688181cb00", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Base Mainnet": { - "off_ramp": "0xD0FA7DE2D18A0c59D3fD7dfC7aB4e913C6Aa7b68", - "commit_store": "0xF88053B9DAC8Dd3039a4eFa8639159aaa3F2D4Cb", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xF4a9Dbb7f3FBa02e3a244B464e459C32B63857F1", + "commit_store": "0x936A0C8635D7087a2D22494762e9a697C3C3D545", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Ethereum Mainnet": { - "off_ramp": "0x45320085fF051361D301eC1044318213A5387A15", - "commit_store": "0x4Dc771B5ef21ef60c33e2987E092345f2b63aE08", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xa06e68a11d5694316Cc819f2FFD02663e3314C7C", + "commit_store": "0xB73d668B26817659E9f48F16b780480B4401cFcE", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Gnosis Mainnet": { - "off_ramp": "0x0A04eC196454825d361886cf4FA113A948164Ef8", - "commit_store": "0x74b72633b63A8f4374a12DB6F609305BC5a1b2d5", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x9e2e4e397226f347d11D3fF8469d0c3FFa750C3B", + "commit_store": "0x75faF05ec32C9dA97E99Eb6fb18b5087DecAAa82", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Optimism Mainnet": { - "off_ramp": "0xBa754ecd3CFA7E9093F688EAc3860cf9D07Fc0AC", - "commit_store": "0x04C0D5302E3D8Ca0A0019141a52a23B59cdb70e4", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x805c292775Be43b10Cc744ea7E81d9939a08cEa4", + "commit_store": "0x52faD8fb48451AA555c0f59accA1dC7C69B9681B", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "WeMix Mainnet": { - "off_ramp": "0xd7c877ea02310Cce9278D9A048Aa1Bb9aF72F00d", - "commit_store": "0x92A1C927E8E10Ab6A40E5A5154e2300D278d1a67", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xd357Bee1Ff4B1cce7dc0d953a9E5613476781732", + "commit_store": "0x784F81E5c2960a7c7e714D6BA383f0d14e93eD65", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" } } }, @@ -976,69 +976,69 @@ Data = """ "wrapped_native": "0x7D72b22a74A216Af4a002a1095C8C707d6eC1C5f", "src_contracts": { "Arbitrum Mainnet": { - "on_ramp": "0x9aBfd6f4C865610692AB6fb1Be862575809fFabf", + "on_ramp": "0xA89c8E2b85a6BeC901C29107E9B640Ff256fc762", "deployed_at": 0 }, "Avalanche Mainnet": { - "on_ramp": "0xbE0Cfae74677F8dd16a246a3a5c8cbB1973118f4", + "on_ramp": "0xEe41778FdE32C19f8f7E0C780838b1cb76bf8aEA", "deployed_at": 0 }, "BSC Mainnet": { - "on_ramp": "0x56657ec4D15C71f7F3C17ba2b21C853A24Dc5381", + "on_ramp": "0x4A62c842f06AC261c93bb5805289c613f55e2Aeb", "deployed_at": 0 }, "Ethereum Mainnet": { - "on_ramp": "0x190bcE84CF2d500B878966F4Cf98a50d78f2675E", + "on_ramp": "0x6c6Dd4fCa5A7B2F11AA3057AB573DD8878C76C5e", "deployed_at": 0 }, "Kroma Mainnet": { - "on_ramp": "0x47E9AE0A815C94836202E696748A5d5476aD8735", + "on_ramp": "0x19e7aD9B0cb28E4604f91376eE2f7dFF0E66318a", "deployed_at": 0 }, "Optimism Mainnet": { - "on_ramp": "0x70f3b0FD7e6a4B9B623e9AB859604A9EE03e48BD", + "on_ramp": "0x96c4e2B1b2c949F570D5992272B7722a3a1d1709", "deployed_at": 0 }, "Polygon Mainnet": { - "on_ramp": "0x777058C1e1dcE4eB8001F38631a1cd9450816e5a", + "on_ramp": "0x728C5d58f6079744E1e41BDAE16200f6c3725954", "deployed_at": 0 } }, "dest_contracts": { "Arbitrum Mainnet": { - "off_ramp": "0x2ba68a395B72a6E3498D312efeD755ed2f3CF223", - "commit_store": "0xdAeC234DA83F68707Bb8AcB2ee6a01a5FD4c2391", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x007b0D0e63B5939E64286F4C4afB2D52c6114025", + "commit_store": "0x4D8BaDA9006A6C1cd724ae6F2E343640a0D9706d", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Avalanche Mainnet": { - "off_ramp": "0xFac907F9a1087B846Faa75A14C5d34A8639233d8", - "commit_store": "0xF2812063446c7deD2CA306c67A68364BdDcbEfc5", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x8Ef00c4B45f7B3D895150F0C5D978AC6949Af174", + "commit_store": "0xF580F5ba66Eec295B8bE3Ea613985b6CEc65D7C8", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "BSC Mainnet": { - "off_ramp": "0x6ec9ca4Cba62cA17c55F05ad2000B46192f02035", - "commit_store": "0x84534BE763366a69710E119c100832955795B34B", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x90fC76fBd6B82eAe27b34e136271b94788237738", + "commit_store": "0xda174CA3c585b260fc5c347c88cA5946Ce0f46E8", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Ethereum Mainnet": { - "off_ramp": "0xF92Fa796F5307b029c65CA26f322a6D86f211194", - "commit_store": "0xbeC110FF43D52be2066B06525304A9924E16b73b", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x76DE34244b92aB9F4e9D550269Ef1CAdE0d1A2E9", + "commit_store": "0xcbCFFD854a2d033019B98f5583FcD5caDc2bb802", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Kroma Mainnet": { - "off_ramp": "0xF886d8DC64E544af4835cbf91e5678A54D95B80e", - "commit_store": "0x8794C9534658fdCC44f2FF6645Bf31cf9F6d2d5D", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x64F833f1347fd8Ac6b07a08adCc844FFeB8dF928", + "commit_store": "0xf79eA7f1D70640A7a8A309465ca29b35D4103c11", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Optimism Mainnet": { - "off_ramp": "0x87220D01DF0fF27149B47227897074653788fd23", - "commit_store": "0xF8dD2be2C6FA43e48A17146380CbEBBB4291807b", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xd76783CF6A98C95F5927b4b98D5E1Efb78CFc563", + "commit_store": "0x3837A341afE24A451d868966114A39715e91C6f6", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Polygon Mainnet": { - "off_ramp": "0x8f0229804513A9Bc00c1308414AB279Dbc718ae1", - "commit_store": "0x3A85D1b8641d83a87957C6ECF1b62151213e0842", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xe22ef88FccfE6C304Fd245005e959837C86B52F6", + "commit_store": "0x98Ebd40E2535D404fFB361A85bf6b82D64Bda151", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" } } }, @@ -1051,24 +1051,24 @@ Data = """ "wrapped_native": "0x5AEa5775959fBC2557Cc8789bC1bf90A239D9a91", "src_contracts": { "Arbitrum Mainnet": { - "on_ramp": "0x9033687a0f03012e015f8f8f2a59da57531d2B43", + "on_ramp": "0x66EcB7c8c122d74f19Fc28b275f213Ef8991B7AB", "deployed_at": 0 }, "Ethereum Mainnet": { - "on_ramp": "0x3B80Fe300c9A611abA0496e2543B66Ff7bD4B9e9", + "on_ramp": "0xD1B33FAd3fF7a793EE39473f865630e3b6371086", "deployed_at": 0 } }, "dest_contracts": { "Arbitrum Mainnet": { - "off_ramp": "0xF0a08aC528668D4fe8C4cF235a8B82cbf242Fa9d", - "commit_store": "0x5a3C9b21b03E4eBcccb57D296e7ff54102F04424", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0xd448c815C421fFBd770C2d3B9a9cBa4E33E3885c", + "commit_store": "0xC64f4b53eDb629B3293eE806D9b2aCBd1dDE4e13", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" }, "Ethereum Mainnet": { - "off_ramp": "0x7c887B97F9Bba9355EC10e2bA949AdB491Ef44Fd", - "commit_store": "0xA42bf0c8794FA8853Ec0F1B24a489972e8CF4C30", - "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + "off_ramp": "0x6BACb854483Ffe310F5Ac08879868E96AE0DC000", + "commit_store": "0x117D1015FD2CBaa32A1fe0e0C913fc02B4D5f115", + "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" } } } @@ -1081,52 +1081,80 @@ TTL = '8h' [CCIP.Env.Network] selected_networks = [ - 'ARBITRUM_MAINNET', - 'AVALANCHE_MAINNET', - 'BSC_MAINNET', - 'BASE_MAINNET', - 'ETHEREUM_MAINNET', - 'KROMA_MAINNET', - 'OPTIMISM_MAINNET', - 'POLYGON_MAINNET', - 'WEMIX_MAINNET', - ] + 'ARBITRUM_MAINNET', + 'AVALANCHE_MAINNET', + 'BASE_MAINNET', + 'BLAST_MAINNET', + 'BSC_MAINNET', + 'CELO_MAINNET', + 'ETHEREUM_MAINNET', + 'GNOSIS_MAINNET', + 'KROMA_MAINNET', + 'METIS_ANDROMEDA', + 'MODE_MAINNET', + 'OPTIMISM_MAINNET', + 'POLYGON_MAINNET', + 'WEMIX_MAINNET', + 'ZKSYNC_MAINNET', +] [CCIP.Groups.load] NetworkPairs = [ - 'ETHEREUM_MAINNET,OPTIMISM_MAINNET', - 'ETHEREUM_MAINNET,AVALANCHE_MAINNET', - 'ETHEREUM_MAINNET,POLYGON_MAINNET', - 'ETHEREUM_MAINNET,BSC_MAINNET', - 'ETHEREUM_MAINNET,ARBITRUM_MAINNET', - 'ETHEREUM_MAINNET,BASE_MAINNET', - 'ETHEREUM_MAINNET,WEMIX_MAINNET', - 'AVALANCHE_MAINNET,POLYGON_MAINNET', - 'BASE_MAINNET,OPTIMISM_MAINNET', - 'BASE_MAINNET,ARBITRUM_MAINNET', - 'AVALANCHE_MAINNET,BSC_MAINNET', - 'BSC_MAINNET,POLYGON_MAINNET', - 'OPTIMISM_MAINNET,POLYGON_MAINNET', - 'BASE_MAINNET,BSC_MAINNET', - 'POLYGON_MAINNET,ARBITRUM_MAINNET', # added as batch 1 - 'ARBITRUM_MAINNET,BSC_MAINNET', # added as batch 1 - 'ARBITRUM_MAINNET,OPTIMISM_MAINNET', # added as batch 1 - 'AVALANCHE_MAINNET,OPTIMISM_MAINNET', # added as batch 2 - 'AVALANCHE_MAINNET,ARBITRUM_MAINNET', # added as batch 2 - 'BASE_MAINNET,POLYGON_MAINNET', # added as batch 2 - 'BSC_MAINNET,OPTIMISM_MAINNET', # added as batch 2 - 'AVALANCHE_MAINNET,BASE_MAINNET', # added as batch 2 - 'WEMIX_MAINNET,KROMA_MAINNET', - 'BSC_MAINNET,WEMIX_MAINNET', # added as batch 2 - 'AVALANCHE_MAINNET,WEMIX_MAINNET', # added as batch 2 - 'POLYGON_MAINNET,WEMIX_MAINNET', # added as batch 2 - 'WEMIX_MAINNET,ARBITRUM_MAINNET', # added as batch 2 - 'OPTIMISM_MAINNET,WEMIX_MAINNET' # added as batch 2 + 'ARBITRUM_MAINNET,BSC_MAINNET', + 'ARBITRUM_MAINNET,OPTIMISM_MAINNET', + 'AVALANCHE_MAINNET,ARBITRUM_MAINNET', + 'AVALANCHE_MAINNET,BASE_MAINNET', + 'AVALANCHE_MAINNET,BSC_MAINNET', + 'AVALANCHE_MAINNET,OPTIMISM_MAINNET', + 'AVALANCHE_MAINNET,POLYGON_MAINNET', + 'AVALANCHE_MAINNET,WEMIX_MAINNET', + 'BASE_MAINNET,ARBITRUM_MAINNET', + 'BASE_MAINNET,BSC_MAINNET', + 'BASE_MAINNET,OPTIMISM_MAINNET', + 'BASE_MAINNET,POLYGON_MAINNET', + 'BLAST_MAINNET,ARBITRUM_MAINNET', + 'BLAST_MAINNET,BASE_MAINNET', + 'BLAST_MAINNET,BSC_MAINNET', + 'BSC_MAINNET,OPTIMISM_MAINNET', + 'BSC_MAINNET,POLYGON_MAINNET', + 'BSC_MAINNET,WEMIX_MAINNET', + 'ETHEREUM_MAINNET,ARBITRUM_MAINNET', + 'ETHEREUM_MAINNET,AVALANCHE_MAINNET', + 'ETHEREUM_MAINNET,BASE_MAINNET', + 'ETHEREUM_MAINNET,BLAST_MAINNET', + 'ETHEREUM_MAINNET,BSC_MAINNET', + 'ETHEREUM_MAINNET,CELO_MAINNET', + 'ETHEREUM_MAINNET,GNOSIS_MAINNET', + 'ETHEREUM_MAINNET,METIS_ANDROMEDA', + 'ETHEREUM_MAINNET,MODE_MAINNET', + 'ETHEREUM_MAINNET,OPTIMISM_MAINNET', + 'ETHEREUM_MAINNET,POLYGON_MAINNET', + 'ETHEREUM_MAINNET,WEMIX_MAINNET', + 'ETHEREUM_MAINNET,ZKSYNC_MAINNET', + 'GNOSIS_MAINNET,ARBITRUM_MAINNET', + 'GNOSIS_MAINNET,AVALANCHE_MAINNET', + 'GNOSIS_MAINNET,BASE_MAINNET', + 'GNOSIS_MAINNET,BSC_MAINNET', + 'GNOSIS_MAINNET,OPTIMISM_MAINNET', + 'GNOSIS_MAINNET,POLYGON_MAINNET', + 'METIS_ANDROMEDA,ARBITRUM_MAINNET', + 'MODE_MAINNET,ARBITRUM_MAINNET', + 'MODE_MAINNET,BASE_MAINNET', + 'MODE_MAINNET,BSC_MAINNET', + 'MODE_MAINNET,OPTIMISM_MAINNET', + 'OPTIMISM_MAINNET,POLYGON_MAINNET', + 'OPTIMISM_MAINNET,WEMIX_MAINNET', + 'POLYGON_MAINNET,ARBITRUM_MAINNET', + 'POLYGON_MAINNET,WEMIX_MAINNET', + 'WEMIX_MAINNET,ARBITRUM_MAINNET', + 'WEMIX_MAINNET,KROMA_MAINNET', + 'ZKSYNC_MAINNET,ARBITRUM_MAINNET' ] BiDirectionalLane = true -PhaseTimeout = '30m' +PhaseTimeout = '20m' ExistingDeployment = true +SkipRequestIfAnotherRequestTriggeredWithin = '40m' [CCIP.Groups.load.TokenConfig] NoOfTokensPerChain = 1 @@ -1137,7 +1165,7 @@ TimeUnit = '1h' TestDuration = '5h' TestRunName = 'Soak_test_mainnet' FailOnFirstErrorInLoad = true -SkipRequestIfAnotherRequestTriggeredWithin = '40m' + [[CCIP.Groups.load.LoadProfile.MsgProfile.MsgDetails]] MsgType = 'Data' @@ -1149,34 +1177,55 @@ AmountPerToken = 1 [CCIP.Groups.smoke] # these are all the valid network pairs NetworkPairs = [ - 'ETHEREUM_MAINNET,OPTIMISM_MAINNET', - 'ETHEREUM_MAINNET,AVALANCHE_MAINNET', - 'ETHEREUM_MAINNET,POLYGON_MAINNET', - 'ETHEREUM_MAINNET,BSC_MAINNET', - 'ETHEREUM_MAINNET,ARBITRUM_MAINNET', - 'ETHEREUM_MAINNET,BASE_MAINNET', - 'ETHEREUM_MAINNET,WEMIX_MAINNET', - 'AVALANCHE_MAINNET,POLYGON_MAINNET', - 'BASE_MAINNET,OPTIMISM_MAINNET', - 'BASE_MAINNET,ARBITRUM_MAINNET', - 'AVALANCHE_MAINNET,BSC_MAINNET', - 'BSC_MAINNET,POLYGON_MAINNET', - 'OPTIMISM_MAINNET,POLYGON_MAINNET', - 'BASE_MAINNET,BSC_MAINNET', - 'POLYGON_MAINNET,ARBITRUM_MAINNET', # added as batch 1 - 'ARBITRUM_MAINNET,BSC_MAINNET', # added as batch 1 - 'ARBITRUM_MAINNET,OPTIMISM_MAINNET', # added as batch 1 - 'AVALANCHE_MAINNET,OPTIMISM_MAINNET', # added as batch 2 - 'AVALANCHE_MAINNET,ARBITRUM_MAINNET', # added as batch 2 - 'BASE_MAINNET,POLYGON_MAINNET', # added as batch 2 - 'BSC_MAINNET,OPTIMISM_MAINNET', # added as batch 2 - 'AVALANCHE_MAINNET,BASE_MAINNET', # added as batch 2 - 'WEMIX_MAINNET,KROMA_MAINNET', - 'BSC_MAINNET,WEMIX_MAINNET', # added as batch 2 - 'AVALANCHE_MAINNET,WEMIX_MAINNET', # added as batch 2 - 'POLYGON_MAINNET,WEMIX_MAINNET', # added as batch 2 - 'WEMIX_MAINNET,ARBITRUM_MAINNET', # added as batch 2 - 'OPTIMISM_MAINNET,WEMIX_MAINNET' # added as batch 2 + 'ARBITRUM_MAINNET,BSC_MAINNET', + 'ARBITRUM_MAINNET,OPTIMISM_MAINNET', + 'AVALANCHE_MAINNET,ARBITRUM_MAINNET', + 'AVALANCHE_MAINNET,BASE_MAINNET', + 'AVALANCHE_MAINNET,BSC_MAINNET', + 'AVALANCHE_MAINNET,OPTIMISM_MAINNET', + 'AVALANCHE_MAINNET,POLYGON_MAINNET', + 'AVALANCHE_MAINNET,WEMIX_MAINNET', + 'BASE_MAINNET,ARBITRUM_MAINNET', + 'BASE_MAINNET,BSC_MAINNET', + 'BASE_MAINNET,OPTIMISM_MAINNET', + 'BASE_MAINNET,POLYGON_MAINNET', + 'BLAST_MAINNET,ARBITRUM_MAINNET', + 'BLAST_MAINNET,BASE_MAINNET', + 'BLAST_MAINNET,BSC_MAINNET', + 'BSC_MAINNET,OPTIMISM_MAINNET', + 'BSC_MAINNET,POLYGON_MAINNET', + 'BSC_MAINNET,WEMIX_MAINNET', + 'ETHEREUM_MAINNET,ARBITRUM_MAINNET', + 'ETHEREUM_MAINNET,AVALANCHE_MAINNET', + 'ETHEREUM_MAINNET,BASE_MAINNET', + 'ETHEREUM_MAINNET,BLAST_MAINNET', + 'ETHEREUM_MAINNET,BSC_MAINNET', + 'ETHEREUM_MAINNET,CELO_MAINNET', + 'ETHEREUM_MAINNET,GNOSIS_MAINNET', + 'ETHEREUM_MAINNET,METIS_ANDROMEDA', + 'ETHEREUM_MAINNET,MODE_MAINNET', + 'ETHEREUM_MAINNET,OPTIMISM_MAINNET', + 'ETHEREUM_MAINNET,POLYGON_MAINNET', + 'ETHEREUM_MAINNET,WEMIX_MAINNET', + 'ETHEREUM_MAINNET,ZKSYNC_MAINNET', + 'GNOSIS_MAINNET,ARBITRUM_MAINNET', + 'GNOSIS_MAINNET,AVALANCHE_MAINNET', + 'GNOSIS_MAINNET,BASE_MAINNET', + 'GNOSIS_MAINNET,BSC_MAINNET', + 'GNOSIS_MAINNET,OPTIMISM_MAINNET', + 'GNOSIS_MAINNET,POLYGON_MAINNET', + 'METIS_ANDROMEDA,ARBITRUM_MAINNET', + 'MODE_MAINNET,ARBITRUM_MAINNET', + 'MODE_MAINNET,BASE_MAINNET', + 'MODE_MAINNET,BSC_MAINNET', + 'MODE_MAINNET,OPTIMISM_MAINNET', + 'OPTIMISM_MAINNET,POLYGON_MAINNET', + 'OPTIMISM_MAINNET,WEMIX_MAINNET', + 'POLYGON_MAINNET,ARBITRUM_MAINNET', + 'POLYGON_MAINNET,WEMIX_MAINNET', + 'WEMIX_MAINNET,ARBITRUM_MAINNET', + 'WEMIX_MAINNET,KROMA_MAINNET', + 'ZKSYNC_MAINNET,ARBITRUM_MAINNET' ] BiDirectionalLane = true @@ -1184,7 +1233,7 @@ PhaseTimeout = '20m' LocalCluster = false ExistingDeployment = true ReuseContracts = true - +SkipRequestIfAnotherRequestTriggeredWithin = '24h' [CCIP.Groups.smoke.TokenConfig] NoOfTokensPerChain = 1 diff --git a/integration-tests/ccip-tests/testconfig/override/mainnet_1.5_B4_native_dataonly_testrouter.toml b/integration-tests/ccip-tests/testconfig/override/mainnet_1.5_B4_native_dataonly_testrouter.toml new file mode 100644 index 00000000000..8f2a6401f0c --- /dev/null +++ b/integration-tests/ccip-tests/testconfig/override/mainnet_1.5_B4_native_dataonly_testrouter.toml @@ -0,0 +1,1214 @@ +[CCIP] +[CCIP.ContractVersions] +PriceRegistry = 'latest' +OffRamp = 'latest' +OnRamp = 'latest' +TokenPool = 'latest' +CommitStore = 'latest' + +[CCIP.Deployments] +Data = """ +{ + "lane_configs": { + "Arbitrum Mainnet": { + "is_mock_arm": true, + "fee_token": "0xf97f4df75117a78c1A5a0DBb814Af92458539FB4", + "arm": "0xC2C5E22a2d9715ed5C5BCC4D8eFf5966cf260744", + "router": "0x33340200b7893fc478Eb2558FfC7B100E5B3869c", + "price_registry": "0x3971cfEf12c4CC6eD14D65B39C9EC6C740C19A40", + "wrapped_native": "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1", + "src_contracts": { + "Avalanche Mainnet": { + "on_ramp": "0xe80cC83B895ada027b722b78949b296Bd1fC5639", + "deployed_at": 0 + }, + "Base Mainnet": { + "on_ramp": "0xc1b6287A3292d6469F2D8545877E40A2f75CA9a6", + "deployed_at": 0 + }, + "BSC Mainnet": { + "on_ramp": "0x14bF7b1Ca6b843f386bfDfa76BFd439919b9378D", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0x67761742ac8A21Ec4D76CA18cbd701e5A6F3Bef3", + "deployed_at": 0 + }, + "Gnosis Mainnet": { + "on_ramp": "0xc7d6B885d8A4286E6311F79227430b7862311cd3", + "deployed_at": 0 + }, + "Metis Andromeda": { + "on_ramp": "0xF1e73c37CDa8E47768De2246AEf5eFD4d76330ae", + "deployed_at": 0 + }, + "Mode Mainnet": { + "on_ramp": "0xd236ea4DDE7de1e594021764E2f6Cd8e8cD7F047", + "deployed_at": 0 + }, + "Optimism Mainnet": { + "on_ramp": "0xAFECc7b67c6a8e606e94ce4e2F70D83C2206C2cb", + "deployed_at": 0 + }, + "Polygon Mainnet": { + "on_ramp": "0x6087d6C33946670232DF09Fe93eECbaEa3D6864d", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Avalanche Mainnet": { + "off_ramp": "0x95095007d5Cc3E7517A1A03c9e228adA5D0bc376", + "commit_store": "0x46679C9E93B7312A9191A9aD12A73b0c86A33623", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Base Mainnet": { + "off_ramp": "0xb62178f8198905D0Fa6d640Bdb188E4E8143Ac4b", + "commit_store": "0x8F60C335a5d2BEC6B32867d3C05C377E88640AaF", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "BSC Mainnet": { + "off_ramp": "0x16B9709F8A23B9EB922E8Dde7EaB1Ede7C79F663", + "commit_store": "0x6c3fD63b9BdE38C414530727a5De858ca023cFc4", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Ethereum Mainnet": { + "off_ramp": "0x91e46cc5590A4B9182e47f40006140A7077Dec31", + "commit_store": "0x86be76A0FA2bD3ECB69330cBb4fd1f62c48F43E3", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Gnosis Mainnet": { + "off_ramp": "0xeE53872d1C695933B34cE0a11B58613CBBf37e20", + "commit_store": "0x5D88518a198b99F096d2893092a568A97F60B8d4", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Metis Andromeda": { + "off_ramp": "0xF1A4DE22FF792b0457306C39f4CB5822Ab47bdAE", + "commit_store": "0x7F20F4374f8d99201F22434ad59f96bE898A9E0B", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Mode Mainnet": { + "off_ramp": "0xa964355d8eBa62E9b043Eb27eEe6d999Ecc69429", + "commit_store": "0x72C3cdA94eCAC06f7605301dd7144815C2F05A03", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Optimism Mainnet": { + "off_ramp": "0x27a971D482335d0f8d1917451390734f7372A4a3", + "commit_store": "0x6642E640321e1Ad01eef2fC2ad5427D84A2Ee269", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Polygon Mainnet": { + "off_ramp": "0xcabc2D71dC3172a154A5A34cD706B050e0ef9b6f", + "commit_store": "0x78B15A57889200F246fc52790c4F3DfC37d82Aa2", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + } + } + }, + "Avalanche Mainnet": { + "is_native_fee_token": true, + "is_mock_arm": true, + "fee_token": "", + "arm": "0x4f6Ec25f06A114ADD3154DC17fb637F750AdaA31", + "router": "0xC485fDa586037F8a312C2492419C9ce25cF7FDD8", + "price_registry": "0x718b6f7454531F6CBdB9eC08F87C8663A7c4FAC2", + "wrapped_native": "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7", + "src_contracts": { + "Arbitrum Mainnet": { + "on_ramp": "0x4e910c8Bbe88DaDF90baa6c1B7850DbeA32c5B29", + "deployed_at": 0 + }, + "Base Mainnet": { + "on_ramp": "0x139D4108C23e66745Eda4ab47c25C83494b7C14d", + "deployed_at": 0 + }, + "BSC Mainnet": { + "on_ramp": "0xe6e161d55019AA5960DcF0Af9bB6e4d574C69F99", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0xe8784c29c583C52FA89144b9e5DD91Df2a1C2587", + "deployed_at": 0 + }, + "Gnosis Mainnet": { + "on_ramp": "0x38fd0DF16F6fD0a2C3Ec6615c73e50F5d027b8bA", + "deployed_at": 0 + }, + "Optimism Mainnet": { + "on_ramp": "0x3e3b4Fba004E7824219e79aE9f676d9D41A216Fa", + "deployed_at": 0 + }, + "Polygon Mainnet": { + "on_ramp": "0x5570a4E979d7460F13b84075ACEF69FAc73914b1", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0x508Ea280D46E4796Ce0f1Acf8BEDa610c4238dB3", + "commit_store": "0x20bEde74Da64C9aE47FFDf4B87613752CD13bE5D", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Base Mainnet": { + "off_ramp": "0x37879EBFCb807f8C397fCe2f42DC0F5329AD6823", + "commit_store": "0xDe615EEaD232BEECF6c9b71c293A387B97814E8D", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "BSC Mainnet": { + "off_ramp": "0x6CDAa2711BdF0B719911BF00588A79FA97bf9264", + "commit_store": "0x4c05E7AB694C602De3135e025aEc7F7de06E80F7", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Ethereum Mainnet": { + "off_ramp": "0xE5F21F43937199D4D57876A83077b3923F68EB76", + "commit_store": "0xf0F791901854fAb16adeBd60F0639b960B6ea0CF", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Gnosis Mainnet": { + "off_ramp": "0x1181A59FF0BAEd1E0EA77e919185cB8C3D5D3125", + "commit_store": "0x60b2Bc7858D6296D8c4370E35a930E5ddF13085E", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Optimism Mainnet": { + "off_ramp": "0x376C0AFC9E64efE0d9202E1F02c3d7f9Dc15e404", + "commit_store": "0xF8728f8Cd9C809287e6a97B71A2cdfD2c3C034cE", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Polygon Mainnet": { + "off_ramp": "0xFf49E35626Eba28Bee1d251782AB75A6cEd91c45", + "commit_store": "0xee2570De22C0D07d0FaBC1169dC5EcA342B838Da", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + } + } + }, + "Base Mainnet": { + "is_native_fee_token": true, + "is_mock_arm": true, + "fee_token": "", + "bridge_tokens": [ + "0x88Fb150BDc53A65fe94Dea0c9BA0a6dAf8C6e196" + ], + "bridge_tokens_pools": [ + "0x1568A4131760231712E59778DAB9EFE67911f4ff" + ], + "arm": "0x91cB19E7c4Ba9B08CF544cDc9143042150B007C3", + "router": "0xcd06f191359cfA6DB55F7D38134C9f89a2D5Ba56", + "price_registry": "0xC792246cF4f41100CA3c67cbF3888D5Cf8FED50B", + "wrapped_native": "0x4200000000000000000000000000000000000006", + "src_contracts": { + "Arbitrum Mainnet": { + "on_ramp": "0x9D0ffA76C7F82C34Be313b5bFc6d42A72dA8CA69", + "deployed_at": 0 + }, + "Avalanche Mainnet": { + "on_ramp": "0x4be6E0F97EA849FF80773af7a317356E6c646FD7", + "deployed_at": 0 + }, + "BSC Mainnet": { + "on_ramp": "0xE5FD5A0ec3657Ad58E875518e73F6264E00Eb754", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0x56b30A0Dcd8dc87Ec08b80FA09502bAB801fa78e", + "deployed_at": 0 + }, + "Gnosis Mainnet": { + "on_ramp": "0xDcFB24AEbcB9Edfb6746a045DDcae402381F984B", + "deployed_at": 0 + }, + "Mode Mainnet": { + "on_ramp": "0xEB50Fc6F57AAc6bf060A2Dfc6479fED592e6e184", + "deployed_at": 0 + }, + "Optimism Mainnet": { + "on_ramp": "0x362E6bE957c18e268ad91046CA6b47EB09AD98C1", + "deployed_at": 0 + }, + "Polygon Mainnet": { + "on_ramp": "0xd3Bde678BB706Cf727A512515C254BcF021dD203", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0x7D38c6363d5E4DFD500a691Bc34878b383F58d93", + "commit_store": "0x17891fe60a577c5E1e4a4Ddd78E642428A56039f", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Avalanche Mainnet": { + "off_ramp": "0x61C3f6d72c80A3D1790b213c4cB58c3d4aaFccDF", + "commit_store": "0x700C6715734111a6D1Cf414F46D85627b298B5dd", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "BSC Mainnet": { + "off_ramp": "0x45d524b6Fe99C005C52C65c578dc0e02d9751083", + "commit_store": "0x1ccD0D49e283789a73E882B0ED4B5b1163675c3C", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Ethereum Mainnet": { + "off_ramp": "0xCA04169671A81E4fB8768cfaD46c347ae65371F1", + "commit_store": "0xb40659aACb709D1D54c80FC0d38b15705358Ce0B", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Gnosis Mainnet": { + "off_ramp": "0x300977dBA924af14E166B31F4926892B1f310661", + "commit_store": "0x932D6D5c6647e6495Ed3473ff0F4e31a6056D837", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Mode Mainnet": { + "off_ramp": "0x639Dc04368006544eba7CbC959f3e4361bfEAB0d", + "commit_store": "0x2D3FC7f8b03718157359266ac06AF6373aFee2f1", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Optimism Mainnet": { + "off_ramp": "0x18095fbD53184A50C2BB3929a6c62Ca328732062", + "commit_store": "0xa8FA8aE51dB9661e7D1c21141d967d07110036cb", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Polygon Mainnet": { + "off_ramp": "0x74d574D11977fC8D40f8590C419504cbE178ADB7", + "commit_store": "0x565f70396Ff82C23d25Dd3E57A9A66367dccdF3B", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + } + } + }, + "BSC Mainnet": { + "is_native_fee_token": true, + "is_mock_arm": true, + "fee_token": "", + "arm": "0x56491A98199aD2e687Ea9D0cFB7b4AC57B4980Fc", + "router": "0x641Fb431CD2dA50fF40e7E0272d2B1e58c1ff236", + "price_registry": "0x2A92BCecd6e702702864E134821FD2DE73C3e180", + "wrapped_native": "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c", + "src_contracts": { + "Arbitrum Mainnet": { + "on_ramp": "0x5577c19bD183e39a007ce4CE236f1D91e9132D5c", + "deployed_at": 0 + }, + "Avalanche Mainnet": { + "on_ramp": "0x43F00dBf0Aa61A099c674A74FBdCb93786564950", + "deployed_at": 0 + }, + "Base Mainnet": { + "on_ramp": "0xdABb6De5eC48dd2fcF28ac85CbEFe3F19E03F1BD", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0x35C724666ba31632A56Bad4390eb69f206ab60C7", + "deployed_at": 0 + }, + "Gnosis Mainnet": { + "on_ramp": "0x83AC865c2E18f2CDc1d10126987FfC465e11c0DF", + "deployed_at": 0 + }, + "Mode Mainnet": { + "on_ramp": "0x9d4d125788A548C2f69fAC7f8C3A64FA21d18C9e", + "deployed_at": 0 + }, + "Optimism Mainnet": { + "on_ramp": "0x3A3649852A518ab180f41f28288c6c9184563616", + "deployed_at": 0 + }, + "Polygon Mainnet": { + "on_ramp": "0x1C88e3Fd2B0a8735D1b19A77AA6e2333555BB95c", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0x2A9C65afF39758CeAa24dBD1ACd1BeB3618e6780", + "commit_store": "0x99C7C97Ed175A3f0BFd4f52526E7B1310bB3fc16", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Avalanche Mainnet": { + "off_ramp": "0xc69a550470bEbC5c3Be98A4C3dD26C6AdD90C64b", + "commit_store": "0x49FeF2978569E8061a7CA5cC676d46970613e9D0", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Base Mainnet": { + "off_ramp": "0x133672C0F0067573254dd7C8C9818a37d6208610", + "commit_store": "0xEc44EFcf3E0aC801C742e444B130918a5a3A87E9", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Ethereum Mainnet": { + "off_ramp": "0xF616733641D420207b8F30db9C4cE39684768991", + "commit_store": "0x7aa39A9c9D539b5E7388872a193b3447D34bf11F", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Gnosis Mainnet": { + "off_ramp": "0x53AF5cE4534C39582E6a5E3fD77946E0c3BFe870", + "commit_store": "0xe7a0Ffc182E2330d19fF79adEEC637094c02dcA3", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Mode Mainnet": { + "off_ramp": "0xFc2278eBc27B9d205e3DC9F1b88D6D863D71190D", + "commit_store": "0x92eeb265F465Aff3AE708117ba7aE35279227845", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Optimism Mainnet": { + "off_ramp": "0x3c5E62cdFD08e23a0961ff2A3155CaBb96cbc89D", + "commit_store": "0xDC39E05264D0C17eD16F2Db363364B127Cf56d75", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Polygon Mainnet": { + "off_ramp": "0x21159ebdA3E6A2437bCD6ef39853042ACC436D2D", + "commit_store": "0x018Bb120265672C699969a9e2193755d4CF1ca16", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + } + } + }, + "Blast Mainnet": { + "is_native_fee_token": true, + "is_mock_arm": true, + "fee_token": "", + "arm": "0xfb83C9eE574f456F5d68Da2643b1122675681B3c", + "router": "0x12e0B8E349C6fb7E6E40713E8125C3cF1127ea8C", + "price_registry": "0x4f66d9e65af0d3DC27897E29f571f933291bb07c", + "wrapped_native": "", + "src_contracts": { + "Ethereum Mainnet": { + "on_ramp": "0xBD9bf9AA79adF083BB7100848Eb15F4e8282E27e", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Ethereum Mainnet": { + "off_ramp": "0x1a904DbbaDdE629a1460e2F6E2E485Ce06Ed7599", + "commit_store": "0x3CB2A81bb8a188C5353CdFa9994ed8666556FC53", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + } + } + }, + "Celo": { + "is_native_fee_token": true, + "is_mock_arm": true, + "fee_token": "", + "bridge_tokens": [ + "0xd07294e6E917e07dfDcee882dd1e2565085C2ae0" + ], + "bridge_tokens_pools": [ + "0x11825e5d99234bAB7ad1f3972fF6E55eBf3D6E20" + ], + "arm": "0xAFB3e62dD82E7648C64eFe2450D7c3B76DB24e1B", + "router": "0xfB48f15480926A4ADf9116Dca468bDd2EE6C5F62", + "price_registry": "0xD9FcEEA20dBB3Dfb91763B301819C9666429DC26", + "wrapped_native": "0x2021B12D8138e2D63cF0895eccABC0DFc92416c6", + "src_contracts": { + "Ethereum Mainnet": { + "on_ramp": "0x27C96A8a2f70a8408aD6c620717a3bDaA54bb10b", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Ethereum Mainnet": { + "off_ramp": "0xd5083684eE92dDeA117636ae5E2F1cb7fE4dfd46", + "commit_store": "0x831097033C88c82a7F1897b168Aa88cC44540C8f", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + } + } + }, + "Ethereum Mainnet": { + "is_mock_arm": true, + "fee_token": "0x514910771AF9Ca656af840dff83E8264EcF986CA", + "bridge_tokens": [ + "0x514910771AF9Ca656af840dff83E8264EcF986CA" + ], + "bridge_tokens_pools": [ + "0xC2291992A08eBFDfedfE248F2CCD34Da63570DF4" + ], + "arm": "0xdCD48419bD5Cd9d1b097695F2af4Ee125aADF84F", + "router": "0x8C6d31FC27770Ebcc5593c9D10adB9211181ed46", + "price_registry": "0xEd1a8c49bbD5618fa6CC952C509557F816d2D4F5", + "wrapped_native": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", + "src_contracts": { + "Arbitrum Mainnet": { + "on_ramp": "0x69eCC4E2D8ea56E2d0a05bF57f4Fd6aEE7f2c284", + "deployed_at": 0 + }, + "Avalanche Mainnet": { + "on_ramp": "0xaFd31C0C78785aDF53E4c185670bfd5376249d8A", + "deployed_at": 0 + }, + "Base Mainnet": { + "on_ramp": "0xb8a882f3B88bd52D1Ff56A873bfDB84b70431937", + "deployed_at": 0 + }, + "BSC Mainnet": { + "on_ramp": "0x948306C220Ac325fa9392A6E601042A3CD0b480d", + "deployed_at": 0 + }, + "Blast Mainnet": { + "on_ramp": "0x4545F9a17DA50110632C14704a15d893BF9CBD27", + "deployed_at": 0 + }, + "Celo": { + "on_ramp": "0xEd5bE9508ae56531cc0EDe6A3bD588Eb9E2e3cfa", + "deployed_at": 0 + }, + "Gnosis Mainnet": { + "on_ramp": "0xf50B9A46C394bD98491ce163d420222d8030F6F0", + "deployed_at": 0 + }, + "linea-mainnet": { + "on_ramp": "0x626189C882A80fF0D036d8D9f6447555e81F78E9", + "deployed_at": 0 + }, + "Metis Andromeda": { + "on_ramp": "0x75d536eED32f4c8Bb39F4B0c992163f5BA49B84e", + "deployed_at": 0 + }, + "Mode Mainnet": { + "on_ramp": "0xeA6d4a24B262aB3e61a8A62f018A30beCD086f82", + "deployed_at": 0 + }, + "Optimism Mainnet": { + "on_ramp": "0x3455D8E039736944e66e19eAc77a42e8077B07bf", + "deployed_at": 0 + }, + "Polygon Mainnet": { + "on_ramp": "0x15a9D79d6b3485F70bF82bC49dDD1fcB37A7149c", + "deployed_at": 0 + }, + "scroll-mainnet": { + "on_ramp": "0x362A221C3cfd7F992DFE221687323F0BA9BA8187", + "deployed_at": 0 + }, + "wemix-mainnet": { + "on_ramp": "0xCbE7e5DA76dC99Ac317adF6d99137005FDA4E2C4", + "deployed_at": 0 + }, + "zksync-mainnet": { + "on_ramp": "0xD54C93A99CBCb8D865E13DA321B540171795A89f", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0xdf615eF8D4C64d0ED8Fd7824BBEd2f6a10245aC9", + "commit_store": "0xf7B343A17445F175f2Dd9f5CB29BAf0a8dE75ed3", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Avalanche Mainnet": { + "off_ramp": "0xd98E80C79a15E4dbaF4C40B6cCDF690fe619BFBb", + "commit_store": "0xA9f9bF2b643348c0884f2eBA4F712E833DA9a2b8", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Base Mainnet": { + "off_ramp": "0x6B4B6359Dd5B47Cdb030E5921456D2a0625a9EbD", + "commit_store": "0xDaC3A82Cc5e7C137bF28e6EF4F68f29D66205ffe", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "BSC Mainnet": { + "off_ramp": "0x66d84fedED0e51aeB47ceD1BB2fc0221Ae8D7C12", + "commit_store": "0x9B9Ec8E26955c034828bBD78E22ab258d983dCdb", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Blast Mainnet": { + "off_ramp": "0x4e0092bBC8EfAb6Eca295caB66986193b90a1Bb9", + "commit_store": "0xd7cA96B58EE33FdB3aa1392c30eD02645b1F28e2", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Celo": { + "off_ramp": "0x90902C0AEE857F3A42f2beBEa38724cE7b7a0cff", + "commit_store": "0x25adA90B241143DD5Df04Fb06C1fF6E7f7624ad9", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Gnosis Mainnet": { + "off_ramp": "0x70C705ff3eCAA04c8c61d581a59a168a1c49c2ec", + "commit_store": "0x9D93D536Ced80871Bf3DA5Bb47bAedE62c794f8A", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "linea-mainnet": { + "off_ramp": "0x418dcbCf229897d0CCf1B8B464Db06C23879FBB4", + "commit_store": "0x9f592c28590595F3F78a8881E8Dbb9984ed705cD", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Metis Andromeda": { + "off_ramp": "0x330349112e13232131Da51f9f3b153d825f65e61", + "commit_store": "0x0f89C7c0586536B618e0469402e1c8234bc52959", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Mode Mainnet": { + "off_ramp": "0xb57D52F7Cb7BBD19a117585bbaf712108E56dd8f", + "commit_store": "0x01346721418045A6c07b71052e452eF8615e9084", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Optimism Mainnet": { + "off_ramp": "0x562a2025E60AA19Aa03Ea41D70ea1FD3286d1D3B", + "commit_store": "0x83F3DA5aa2C7534d694B0acde7624573c830250D", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Polygon Mainnet": { + "off_ramp": "0x718672076D6d51E4c76142B37bC99E4945d704a3", + "commit_store": "0x57b548C9c213EA2bcf60193E3D7fd2d2b53Fb9b3", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "scroll-mainnet": { + "off_ramp": "0x26a10137A54F4Ea01D20758Ac5AdBf9326340Fc3", + "commit_store": "0x57d6cD9CD44770C807b2763Dbe4CFDA0113dd114", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "wemix-mainnet": { + "off_ramp": "0xF92Fa796F5307b029c65CA26f322a6D86f211194", + "commit_store": "0xbeC110FF43D52be2066B06525304A9924E16b73b", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "zksync-mainnet": { + "off_ramp": "0x7c887B97F9Bba9355EC10e2bA949AdB491Ef44Fd", + "commit_store": "0xA42bf0c8794FA8853Ec0F1B24a489972e8CF4C30", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + } + } + }, + "Gnosis Mainnet": { + "is_native_fee_token": true, + "is_mock_arm": true, + "fee_token": "0x0000000000000000000000000000000000000000", + "arm": "0x2ab5ff904CFFdD37f19cC34597cF425916F2DAcA", + "router": "0xe6A934D3754797bCe4375368F5f12b94DBc19Fcc", + "price_registry": "0x03aF5C79b0D49C040413FdA1e7B2cAa54a0fa5F4", + "wrapped_native": "0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d", + "src_contracts": { + "Arbitrum Mainnet": { + "on_ramp": "0x140E6D5ba903F684944Dd27369d767DdEf958c9B", + "deployed_at": 0 + }, + "Avalanche Mainnet": { + "on_ramp": "0xB707a6D1d32CE99D5c669DeE71D30d25a066D32c", + "deployed_at": 0 + }, + "Base Mainnet": { + "on_ramp": "0xAAb6D9fc00aAc37373206e91789CcDE1E851b3E4", + "deployed_at": 0 + }, + "BSC Mainnet": { + "on_ramp": "0xb485634dd2E545091722b9d4843d3644addf97e3", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0x014ABcfDbCe9F67d0Df34574664a6C0A241Ec03A", + "deployed_at": 0 + }, + "Optimism Mainnet": { + "on_ramp": "0x9379b446fcA75CA57834a4dA33f64ae317Be05e4", + "deployed_at": 0 + }, + "Polygon Mainnet": { + "on_ramp": "0xD7a49AfEA62E77Ad6BEB2ed64673026271aae188", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0x2C1539696E29012806a15Bcd9845Ed1278a9fd63", + "commit_store": "0x5b1762a6023157edaf2c46c818f447B1940765D6", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Avalanche Mainnet": { + "off_ramp": "0xe596D90EF0AEe10257109AC8394a85F8944bF6D0", + "commit_store": "0xd6Dc07804AE06f575C28094F99aCdDC1535904e7", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Base Mainnet": { + "off_ramp": "0xbeEDd1C5C13C5886c3d600e94Ff9e82C04A53C38", + "commit_store": "0x392304E3cb636f75Dc95340672F3b8A2359d5Ebc", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "BSC Mainnet": { + "off_ramp": "0x972a85d7ba0209F1896992B2687cC728cf769e50", + "commit_store": "0x5FB18729651f1EDA5ed5ac67594FD94Fa3DBcd29", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Ethereum Mainnet": { + "off_ramp": "0x658d9ae41A9c291De423d3B4B6C064f6dD0e7Ed2", + "commit_store": "0xd23391fCBb8a41b971f90bC6e95CC8beaD885221", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Optimism Mainnet": { + "off_ramp": "0xd84E2316634ab6516Ecc829E2367633bfB3e4B6D", + "commit_store": "0x9d432DaF8aF8803baF6Cf560CF0f115c7D7b7f16", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Polygon Mainnet": { + "off_ramp": "0x6d6a4a60E0E23dbea089c0fEbbA9c5912f02bc57", + "commit_store": "0x9CBe49E232aEF27B9d98aC752354879efd7b1E70", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + } + } + }, + "kroma-mainnet": { + "is_native_fee_token": true, + "is_mock_arm": true, + "fee_token": "", + "bridge_tokens": [ + "0xC1F6f7622ad37C3f46cDF6F8AA0344ADE80BF450" + ], + "bridge_tokens_pools": [ + "0xd9547B702673c61c84bb2dF6FDf6D2F5309fE536" + ], + "arm": "0xB59779d3364BC6d71168245f9ebb96469E5a5a98", + "router": "0xE93E8B0d1b1CEB44350C8758ed1E2799CCee31aB", + "price_registry": "0x8155B4710e7bbC90924E957104F94Afd4f95Eca2", + "wrapped_native": "", + "src_contracts": { + "wemix-mainnet": { + "on_ramp": "0x3C5Ab46fA1dB1dECD854224654313a69bf9fcAD3", + "deployed_at": 0 + } + }, + "dest_contracts": { + "wemix-mainnet": { + "off_ramp": "0xF886d8DC64E544af4835cbf91e5678A54D95B80e", + "commit_store": "0x8794C9534658fdCC44f2FF6645Bf31cf9F6d2d5D", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + } + } + }, + "linea-mainnet": { + "is_native_fee_token": true, + "is_mock_arm": true, + "fee_token": "", + "arm": "0xB75C45986892fDBFe1e4Ef9f2e83Fd65471300f3", + "router": "0xcACf1F067BF807B77AE8cadE8854236BbA67C8a7", + "price_registry": "0x3B9e77E257A9C8b5F53e88dB87874188fB558460", + "wrapped_native": "", + "src_contracts": { + "Ethereum Mainnet": { + "on_ramp": "0x69AbB6043BBEA2467f41CCD0144d1b3b4ECd20f4", + "deployed_at": 0 + }, + "scroll-mainnet": { + "on_ramp": "0x30ebb71dAa827bEAE71EE325A77Ca47dAED7Ec9B", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Ethereum Mainnet": { + "off_ramp": "0x656e2aA127Cb15815a90Ef70c6AA7Ed449D689ce", + "commit_store": "0xD8850C39D6785d9DdA555b7d81df50609c73c495", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "scroll-mainnet": { + "off_ramp": "0xa3Ea5eB15711041fd28950438b5a682392b54e6C", + "commit_store": "0x9d75617B79cB12e7c3085b2DA38fa47aaD23f0bA", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + } + } + }, + "Metis Andromeda": { + "is_native_fee_token": true, + "is_mock_arm": true, + "fee_token": "", + "arm": "0xC4BFAc3D31C524A4958c5d5d1e68394d8DEbbE69", + "router": "0x4c6811BE5f08D9E748C85FDB0050DE49B21F77c9", + "price_registry": "0x2C4A017f587574b3d6EEBF6463aE6824Dc43C365", + "wrapped_native": "", + "src_contracts": { + "Arbitrum Mainnet": { + "on_ramp": "0x8d3039fE2400151c06Ae84a18CAf38dD9b6Ce58b", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0xdF5394c57A0570ECe45DE0c0fA2e722A672B9198", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0xc6bA5a79991b3775F28259BA551b30eCb0b6D499", + "commit_store": "0xb81b0EE9675879a2Dcaa70CCC3b2c2D38fa404b0", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Ethereum Mainnet": { + "off_ramp": "0x1fd37Bf813D0723BEF614bC93d9D2Ce1AcB3228f", + "commit_store": "0x7C1efda9F744a2B4f88b924B03C6d6B53E3E390F", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + } + } + }, + "Mode Mainnet": { + "is_native_fee_token": true, + "is_mock_arm": true, + "fee_token": "", + "arm": "0x77EAF440c5d24e25D1834CBBF623bFd83b8b5dA1", + "router": "0x4F45E0061fecADa52F0d2F0328b7cA7bD6261fB5", + "price_registry": "0x0708505E66DA43B34BB0C429e0F1fE5bfC3A73cd", + "wrapped_native": "0x4200000000000000000000000000000000000006", + "src_contracts": { + "Arbitrum Mainnet": { + "on_ramp": "0xb2e694efcDa0aeB81700019c3047F92fC3bb520E", + "deployed_at": 0 + }, + "Base Mainnet": { + "on_ramp": "0x347A070EA1B04bc2b4A8f14320688C277022C90e", + "deployed_at": 0 + }, + "BSC Mainnet": { + "on_ramp": "0xeb7E8c40E95Cd31666359AaeB1F2CccaAB935643", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0x7d2aF78868993a5a86676BA639eC0412709707D9", + "deployed_at": 0 + }, + "Optimism Mainnet": { + "on_ramp": "0x7AB4329D19A0255DA90Ee8dbAA60f8f0cB7950C1", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0x0Cb870C12013c2d5743585F85b298e129cE57203", + "commit_store": "0x682Af2Cfaa5aE554eF222728fF7C7168232e2Ea5", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Base Mainnet": { + "off_ramp": "0x30612D8fb7EcD05ECb863560BA8806d88e8BbFAF", + "commit_store": "0xf84d023CCFF8b74e565117cBc034859D06EA1976", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "BSC Mainnet": { + "off_ramp": "0xdfA601DA2163Ca2C77Eb32126E6B7A97024f6181", + "commit_store": "0xb88F947C85b1c6B1E2A0C22792BA58C40c07a644", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Ethereum Mainnet": { + "off_ramp": "0xb1caBa234721b8F12C545B3dC25B3F87f6a9c91B", + "commit_store": "0x67Ff921DA5d0B61a9b05BDFa92d9f5f992d7861a", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Optimism Mainnet": { + "off_ramp": "0x4adcD1FB4ec76A3c9960E048f81C19A51B2eAC49", + "commit_store": "0x7B58aF65DFD717fC0d044D860c8f9A85Ca6813D6", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + } + } + }, + "Optimism Mainnet": { + "is_mock_arm": true, + "fee_token": "0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6", + "bridge_tokens": [ + "0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6" + ], + "bridge_tokens_pools": [ + "0x841b32B5309ba30cFbf4534667fC3D99EdF05B7A" + ], + "arm": "0x1c51b6D5BFcFB7ee82C80949DFD146dB157a7E49", + "router": "0x0E6137E72CC322b0f3b7eD172f7BD7b5Ac798d05", + "price_registry": "0xF1cB3E957D7271Ac788010b2e6146E6ceF8FB9BA", + "wrapped_native": "0x4200000000000000000000000000000000000006", + "src_contracts": { + "Arbitrum Mainnet": { + "on_ramp": "0x6bA81b83091A23e8F2AA173B2b939fAf9E320DfB", + "deployed_at": 0 + }, + "Avalanche Mainnet": { + "on_ramp": "0xB9D655Ad5ba80036725d6c753Fa6AF0454cBF630", + "deployed_at": 0 + }, + "Base Mainnet": { + "on_ramp": "0xfE11cfC957cCa331192EAC60040b442303CcA0a9", + "deployed_at": 0 + }, + "BSC Mainnet": { + "on_ramp": "0xfC51a4CF925f202d86c6092cda879689d2C17201", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0xE4C51Dc01A4E0aB14c7a7a2ed1655E9CF8A3E698", + "deployed_at": 0 + }, + "Gnosis Mainnet": { + "on_ramp": "0x604a9dda2e27D56cfCe457E437a61f4ED0De9dE6", + "deployed_at": 0 + }, + "Mode Mainnet": { + "on_ramp": "0xc6d9Cb39e34D83d21A021504024887A0e96D4e94", + "deployed_at": 0 + }, + "Polygon Mainnet": { + "on_ramp": "0x9c725164b60E3f6d4d5b7A2841C63E9FD0988805", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0xEB3d6956BCf7b1E29634C8cd182fC9FA740Bce34", + "commit_store": "0x6569761680DaC4Bf940244E3cF198A069E34E91F", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Avalanche Mainnet": { + "off_ramp": "0xF8E38B4503418659F791F2135c4912F85BFB7988", + "commit_store": "0x23CAc55aDDF28179A999858720E9Fe686372083A", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Base Mainnet": { + "off_ramp": "0x519ee6B83f57df95486aeA6E26819cb7b4B8ee99", + "commit_store": "0xCfdF2b21D9777E2B0a221F6b6D8fe176461f058e", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "BSC Mainnet": { + "off_ramp": "0x51f37b538aD2Bcb9Eaf884859BF7C5Ec58AEc885", + "commit_store": "0xF472FEb09544Bf991773f4B94fe3F03e458d1b8d", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Ethereum Mainnet": { + "off_ramp": "0x9979c2dfEcA9051Cf7f08274d978984B2dB12C60", + "commit_store": "0x9358663E8f89df8EFE2346a3c4c1D65d03300576", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Gnosis Mainnet": { + "off_ramp": "0x01449040D92D75c58FaDc9Bc1c0eadc70C550484", + "commit_store": "0xb63230DfcE291DA76FD946EFbc966549F9300347", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Mode Mainnet": { + "off_ramp": "0x5a4BEeafd345264360E6894a6bc5F54a70814E68", + "commit_store": "0x4E94a327A38E6F3509a5639dCF933CfF6DE93FFD", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Polygon Mainnet": { + "off_ramp": "0x4BA0A3bD1E2b70b2fe165A53219e7eF6376849a4", + "commit_store": "0xA0f02e1F9C641C9610f688be84F889fE518b36e3", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + } + } + }, + "Polygon Mainnet": { + "is_native_fee_token": true, + "is_mock_arm": true, + "fee_token": "", + "bridge_tokens": [ + "0xb0897686c545045aFc77CF20eC7A532E3120E0F1" + ], + "bridge_tokens_pools": [ + "0x086892015567fb8764d02c6845C85C25C8FcA389" + ], + "arm": "0x569a295a09634Ac9414c3efe4E8931986d68F937", + "router": "0x10ea937A855268E5336F78B262B4d82ad1Cb84BC", + "price_registry": "0xd6D571B37B26Ee1b99FDFa097034Ea4B9E3b76BA", + "wrapped_native": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", + "src_contracts": { + "Arbitrum Mainnet": { + "on_ramp": "0x13263aC754d1e29430930672E3C0019f2BC44Ba2", + "deployed_at": 0 + }, + "Avalanche Mainnet": { + "on_ramp": "0x56cb9Cd82553Bd8157e6504020c38f6DA4971717", + "deployed_at": 0 + }, + "Base Mainnet": { + "on_ramp": "0xD26A4E0c664E72e3c29E634867191cB1cb9AF570", + "deployed_at": 0 + }, + "BSC Mainnet": { + "on_ramp": "0x164507757F7d5Ab35C6af44EeEB099F5be29Da57", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0x1DAcBae00c779913e6E9fc1A3323FbA4847ba53C", + "deployed_at": 0 + }, + "Gnosis Mainnet": { + "on_ramp": "0xcc4A8CFd756895d91B476Dd5461286b300914aBf", + "deployed_at": 0 + }, + "Optimism Mainnet": { + "on_ramp": "0x868B71490B36674B3B9006fa8711C6fA26A26631", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0x60f2788225CeE4a94f8E7589931d5A14Cbc4367d", + "commit_store": "0x4DEc80ED383171EC54699B22B869bE098d3cBac9", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Avalanche Mainnet": { + "off_ramp": "0x35c1Bb5A9c2F3fa8f8dFF470a6bE7d362CeA1ef3", + "commit_store": "0xB3324b80f50a31b12c0C733560D3aA2a32dc5C33", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Base Mainnet": { + "off_ramp": "0xF4a9Dbb7f3FBa02e3a244B464e459C32B63857F1", + "commit_store": "0x936A0C8635D7087a2D22494762e9a697C3C3D545", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "BSC Mainnet": { + "off_ramp": "0xE58074f8F56E23836f088Ac8b4f3882c1b4CAcbb", + "commit_store": "0x2110a5f138364d788FDF54eCBa25C1688181cb00", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Ethereum Mainnet": { + "off_ramp": "0xa06e68a11d5694316Cc819f2FFD02663e3314C7C", + "commit_store": "0xB73d668B26817659E9f48F16b780480B4401cFcE", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Gnosis Mainnet": { + "off_ramp": "0x9e2e4e397226f347d11D3fF8469d0c3FFa750C3B", + "commit_store": "0x75faF05ec32C9dA97E99Eb6fb18b5087DecAAa82", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "Optimism Mainnet": { + "off_ramp": "0x805c292775Be43b10Cc744ea7E81d9939a08cEa4", + "commit_store": "0x52faD8fb48451AA555c0f59accA1dC7C69B9681B", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + } + } + }, + "scroll-mainnet": { + "is_native_fee_token": true, + "is_mock_arm": true, + "fee_token": "", + "arm": "0x323BFa80a6941C419fB6397698dA816A382CAe53", + "router": "0x9bE7a66B3Dec08e111E038Dc34bD7F1AF5cEedA5", + "price_registry": "0xd587D08b62CDE7897DA37fB1915F7F6b1D749d96", + "wrapped_native": "", + "src_contracts": { + "Ethereum Mainnet": { + "on_ramp": "0x28cCF73F7982c1786b84e243FFbD47F4fB8ae43d", + "deployed_at": 0 + }, + "linea-mainnet": { + "on_ramp": "0x05d472b114D57E6035089A58Fa997A7940D29a23", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Ethereum Mainnet": { + "off_ramp": "0x77601F272dd2d6481Ac3a13942075388097245Fb", + "commit_store": "0x1c338D27F36452358611936fc8418849910B1C59", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "linea-mainnet": { + "off_ramp": "0x5834e1C639418A4973391126576f550A6996836a", + "commit_store": "0x3BD2d806e9cBD3440cb74626BE819d337b70F7De", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + } + } + }, + "wemix-mainnet": { + "is_native_fee_token": true, + "is_mock_arm": true, + "fee_token": "", + "bridge_tokens": [ + "0x80f1FcdC96B55e459BF52b998aBBE2c364935d69" + ], + "bridge_tokens_pools": [ + "0x80282dF25600c08Bde7560f6c1E509366c1BfBFC" + ], + "arm": "0x07aaC8B69A62dB5bd3d244091916EbF2fac17b76", + "router": "0x7798b795Fde864f4Cd1b124a38Ba9619B7F8A442", + "price_registry": "0x252863688762aD86868D3d3076233Eacd80c7055", + "wrapped_native": "0x7D72b22a74A216Af4a002a1095C8C707d6eC1C5f", + "src_contracts": { + "Ethereum Mainnet": { + "on_ramp": "0x190bcE84CF2d500B878966F4Cf98a50d78f2675E", + "deployed_at": 0 + }, + "kroma-mainnet": { + "on_ramp": "0x47E9AE0A815C94836202E696748A5d5476aD8735", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Ethereum Mainnet": { + "off_ramp": "0x3a129e6C18b23d18BA9E6Aa14Dc2e79d1f91c6c5", + "commit_store": "0x31f6ab382DDeb9A316Ab61C3945a5292a50a89AB", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + }, + "kroma-mainnet": { + "off_ramp": "0x2B555774B3D1dcbcd76efb7751F3c5FbCFABC5C4", + "commit_store": "0x213124614aAf31eBCE7c612A12aac5f8aAD77DE4", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + } + } + }, + "zksync-mainnet": { + "is_native_fee_token": true, + "is_mock_arm": true, + "fee_token": "", + "arm": "0x2438AF3167c8f8db49215B96A9A5F5131C4B9718", + "router": "0x748Fd769d81F5D94752bf8B0875E9301d0ba71bB", + "price_registry": "0xa0C6E00a9Fa10A04989c237dF6dfDCe2AaceE4A3", + "wrapped_native": "", + "src_contracts": { + "Ethereum Mainnet": { + "on_ramp": "0x3B80Fe300c9A611abA0496e2543B66Ff7bD4B9e9", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Ethereum Mainnet": { + "off_ramp": "0xb368c8946D9fa5A497cDe1Dff7213f9CdfD143Bf", + "commit_store": "0xa4d264470a67D9f6682EE12Bdc9c35Df44e3F194", + "receiver_dapp": "0x09e4897E068A5Fc4fc22D86867FC1906E6cde563" + } + } + } + } +} +""" + +[CCIP.Env] +TTL = '8h' + +[CCIP.Env.Network] +selected_networks = [ + 'ARBITRUM_MAINNET', + 'AVALANCHE_MAINNET', + 'BASE_MAINNET', +# 'BLAST_MAINNET', + 'BSC_MAINNET', +# 'CELO_MAINNET', + 'ETHEREUM_MAINNET', + 'GNOSIS_MAINNET', +# 'KROMA_MAINNET', +# 'METIS_ANDROMEDA', + 'MODE_MAINNET', + 'OPTIMISM_MAINNET', + 'POLYGON_MAINNET', +# 'WEMIX_MAINNET', +# 'ZKSYNC_MAINNET', +] + + +[CCIP.Groups.smoke] +# these are all the valid network pairs +NetworkPairs = [ +# 'WEMIX_MAINNET,ARBITRUM_MAINNET', +# 'WEMIX_MAINNET,AVALANCHE_MAINNET', +# 'WEMIX_MAINNET,BSC_MAINNET', +# 'WEMIX_MAINNET,OPTIMISM_MAINNET', +# 'WEMIX_MAINNET,ETHEREUM_MAINNET', +# 'WEMIX_MAINNET,POLYGON_MAINNET', +# 'WEMIX_MAINNET,KROMA_MAINNET', +# 'ZKSYNC_MAINNET,ETHEREUM_MAINNET', +# 'CELO_MAINNET,ETHEREUM_MAINNET', + + 'ARBITRUM_MAINNET,BSC_MAINNET', + 'ARBITRUM_MAINNET,OPTIMISM_MAINNET', + 'AVALANCHE_MAINNET,ARBITRUM_MAINNET', + 'AVALANCHE_MAINNET,BASE_MAINNET', + 'AVALANCHE_MAINNET,BSC_MAINNET', + 'AVALANCHE_MAINNET,OPTIMISM_MAINNET', + 'AVALANCHE_MAINNET,POLYGON_MAINNET', +# 'AVALANCHE_MAINNET,WEMIX_MAINNET', + 'BASE_MAINNET,ARBITRUM_MAINNET', + 'BASE_MAINNET,BSC_MAINNET', + 'BASE_MAINNET,OPTIMISM_MAINNET', + 'BASE_MAINNET,POLYGON_MAINNET', +# 'BLAST_MAINNET,ARBITRUM_MAINNET', +# 'BLAST_MAINNET,BASE_MAINNET', +# 'BLAST_MAINNET,BSC_MAINNET', + 'BSC_MAINNET,OPTIMISM_MAINNET', + 'BSC_MAINNET,POLYGON_MAINNET', +# 'BSC_MAINNET,WEMIX_MAINNET', + 'ETHEREUM_MAINNET,ARBITRUM_MAINNET', + 'ETHEREUM_MAINNET,AVALANCHE_MAINNET', + 'ETHEREUM_MAINNET,BASE_MAINNET', +# 'ETHEREUM_MAINNET,BLAST_MAINNET', + 'ETHEREUM_MAINNET,BSC_MAINNET', +# 'ETHEREUM_MAINNET,CELO_MAINNET', + 'ETHEREUM_MAINNET,GNOSIS_MAINNET', +# 'ETHEREUM_MAINNET,METIS_ANDROMEDA', + 'ETHEREUM_MAINNET,MODE_MAINNET', + 'ETHEREUM_MAINNET,OPTIMISM_MAINNET', + 'ETHEREUM_MAINNET,POLYGON_MAINNET', +# 'ETHEREUM_MAINNET,WEMIX_MAINNET', +# 'ETHEREUM_MAINNET,ZKSYNC_MAINNET', + 'GNOSIS_MAINNET,ARBITRUM_MAINNET', + 'GNOSIS_MAINNET,AVALANCHE_MAINNET', + 'GNOSIS_MAINNET,BASE_MAINNET', + 'GNOSIS_MAINNET,BSC_MAINNET', + 'GNOSIS_MAINNET,OPTIMISM_MAINNET', + 'GNOSIS_MAINNET,POLYGON_MAINNET', +# 'METIS_ANDROMEDA,ARBITRUM_MAINNET', + 'MODE_MAINNET,ARBITRUM_MAINNET', + 'MODE_MAINNET,BASE_MAINNET', + 'MODE_MAINNET,BSC_MAINNET', + 'MODE_MAINNET,OPTIMISM_MAINNET', + 'OPTIMISM_MAINNET,POLYGON_MAINNET', +# 'OPTIMISM_MAINNET,WEMIX_MAINNET', + 'POLYGON_MAINNET,ARBITRUM_MAINNET', +# 'POLYGON_MAINNET,WEMIX_MAINNET', +# 'WEMIX_MAINNET,ARBITRUM_MAINNET', +# 'WEMIX_MAINNET,KROMA_MAINNET', +# 'ZKSYNC_MAINNET,ARBITRUM_MAINNET' +] + +BiDirectionalLane = true +PhaseTimeout = '20m' +LocalCluster = false +ExistingDeployment = true +ReuseContracts = true +SkipRequestIfAnotherRequestTriggeredWithin = '24h' + +[CCIP.Groups.smoke.TokenConfig] +NoOfTokensPerChain = 1 +CCIPOwnerTokens = true + +[CCIP.Groups.smoke.MsgDetails] +MsgType = 'Data' +DestGasLimit = 0 +DataLength = 100 +NoOfTokens = 1 +AmountPerToken = 1 + +[CCIP.Groups.load] +NetworkPairs = [ + 'ARBITRUM_MAINNET,BSC_MAINNET', + 'ARBITRUM_MAINNET,OPTIMISM_MAINNET', + 'AVALANCHE_MAINNET,ARBITRUM_MAINNET', + 'AVALANCHE_MAINNET,BASE_MAINNET', + 'AVALANCHE_MAINNET,BSC_MAINNET', + 'AVALANCHE_MAINNET,OPTIMISM_MAINNET', + 'AVALANCHE_MAINNET,POLYGON_MAINNET', + 'BASE_MAINNET,ARBITRUM_MAINNET', + 'BASE_MAINNET,BSC_MAINNET', + 'BASE_MAINNET,OPTIMISM_MAINNET', + 'BASE_MAINNET,POLYGON_MAINNET', + 'BSC_MAINNET,OPTIMISM_MAINNET', + 'BSC_MAINNET,POLYGON_MAINNET', + 'ETHEREUM_MAINNET,ARBITRUM_MAINNET', + 'ETHEREUM_MAINNET,AVALANCHE_MAINNET', + 'ETHEREUM_MAINNET,BASE_MAINNET', + 'ETHEREUM_MAINNET,BSC_MAINNET', + 'ETHEREUM_MAINNET,GNOSIS_MAINNET', + 'ETHEREUM_MAINNET,MODE_MAINNET', + 'ETHEREUM_MAINNET,OPTIMISM_MAINNET', + 'ETHEREUM_MAINNET,POLYGON_MAINNET', + 'GNOSIS_MAINNET,ARBITRUM_MAINNET', + 'GNOSIS_MAINNET,AVALANCHE_MAINNET', + 'GNOSIS_MAINNET,BASE_MAINNET', + 'GNOSIS_MAINNET,BSC_MAINNET', + 'GNOSIS_MAINNET,OPTIMISM_MAINNET', + 'GNOSIS_MAINNET,POLYGON_MAINNET', + 'MODE_MAINNET,ARBITRUM_MAINNET', + 'MODE_MAINNET,BASE_MAINNET', + 'MODE_MAINNET,BSC_MAINNET', + 'MODE_MAINNET,OPTIMISM_MAINNET', + 'OPTIMISM_MAINNET,POLYGON_MAINNET', + 'POLYGON_MAINNET,ARBITRUM_MAINNET', +] + +BiDirectionalLane = true +PhaseTimeout = '50m' +LocalCluster = false +ExistingDeployment = true +ReuseContracts = true + +[CCIP.Groups.load.TokenConfig] +NoOfTokensPerChain = 1 + +[CCIP.Groups.load.LoadProfile] +RequestPerUnitTime = [1] +TimeUnit = '30m' +TestDuration = '2h' +TestRunName = 'SoakTest_mainnet_test_router' +FailOnFirstErrorInLoad = false + +[[CCIP.Groups.load.LoadProfile.MsgProfile.MsgDetails]] +MsgType = 'Data' +DestGasLimit = 0 +DataLength = 100 +NoOfTokens = 1 +AmountPerToken = 1 \ No newline at end of file diff --git a/integration-tests/ccip-tests/testconfig/tomls/beta-testnet/testnet-beta-workinglane.toml b/integration-tests/ccip-tests/testconfig/tomls/beta-testnet/testnet-beta-workinglane.toml index 592cb046ad3..5b3c1c26c79 100644 --- a/integration-tests/ccip-tests/testconfig/tomls/beta-testnet/testnet-beta-workinglane.toml +++ b/integration-tests/ccip-tests/testconfig/tomls/beta-testnet/testnet-beta-workinglane.toml @@ -13,41 +13,29 @@ Data = """ "Arbitrum Sepolia": { "is_mock_arm": true, "fee_token": "0xb1D4538B4571d411F07960EF2838Ce337FE1E80E", - "bridge_tokens": null, - "bridge_tokens_pools": null, - "price_aggregators": null, - "arm": "0x2aE6d5495fc20226F433be50e37D59c05D186AaA", - "router": "0x0fF6b6F3Ad10D66600Fd5CC25b98542A05Aa7Bc2", - "price_registry": "0x25d997d8618e1299418b3D905E40bC353ec89F61", + "arm": "0x5261Eac6b2A158b1eafed0144B4894f41b67b01f", + "router": "0x32C3C32B1b3858e45AFc53e1D0D4607463d47d1C", + "price_registry": "0x845A8190d31602fD0862467880468339E04d885b", "wrapped_native": "0xE591bf0A0CF924A0674d7792db046B23CEbF5f34", "src_contracts": { - "Base Sepolia": { - "on_ramp": "0x6BD0f1efA261Ea84DB219c1284b538A65E530ea1", - "deployed_at": 29428386 + "Avalanche Fuji": { + "on_ramp": "0x59f2492ebDfdD3E99b9198A2313AB0A4113014c8", + "deployed_at": 85949437 }, "Optimism Sepolia": { - "on_ramp": "0x94cd0d171eF08924F0008305e5Bb90b0fC1b61AB", - "deployed_at": 13945916 - }, - "Sepolia Testnet": { - "on_ramp": "0x44225eb3B73B1b52Dd2ecD258F9b63418eC6Bf79", - "deployed_at": 13730868 + "on_ramp": "0x3FF2852A4597E6Ac363340Cadbf1666C4246b4B9", + "deployed_at": 87452680 } }, "dest_contracts": { - "Base Sepolia": { - "off_ramp": "0x21560B4ACAEdb8AA2Dd935618F15da43197bdc12", - "commit_store": "0x27B882c393151ADD910F3557849AF0bb09c7d5A6", + "Avalanche Fuji": { + "off_ramp": "0x1b3841f8923195F1E438B471D0415bBE8b3c133D", + "commit_store": "0x55F4a33AC60D994c2F1A3b400Fc2C40140CF50D9", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Optimism Sepolia": { - "off_ramp": "0xAE32FD8Ae148BD88E3da6FaE8Cd7561Eed3ec5Cc", - "commit_store": "0x1f1160Ac7828B647A85c9a6b3A58A232C59D67Ab", - "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" - }, - "Sepolia Testnet": { - "off_ramp": "0xc136114F379b812345bb7e467ECDdb6D0c87De8b", - "commit_store": "0x42b3EbEA14F6CB803e3C7df84392Efb85CE90168", + "off_ramp": "0x695C84498573AEE9A2Be410Aaf7C275535A337D7", + "commit_store": "0xCBDdCEaE1d51F9C40640fa17fb7a2FeEB51DB702", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -55,47 +43,20 @@ Data = """ "Avalanche Fuji": { "is_mock_arm": true, "fee_token": "0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846", - "bridge_tokens": null, - "bridge_tokens_pools": null, - "price_aggregators": null, - "arm": "0xD4A51dC0F5C680A8A18eA4Ec3A2f25C6db9424B7", - "router": "0xa62e685aDFF45f38eC94378513D128F168964E99", - "price_registry": "0xdbeA1a10AC6a2B729bF128aE9281Ed420dbE7113", + "arm": "0xd550342aE3f8d5D3D38509900034C8b01f556f0e", + "router": "0x13b766d0fe3e01fa5b02b378DF31724dD5368B37", + "price_registry": "0xAEc164EDF7Be32c6d38565BD09c24DAAA5b5887f", "wrapped_native": "0xd00ae08403B9bbb9124bB305C09058E32C39A48c", "src_contracts": { - "BSC Testnet": { - "on_ramp": "0xe4f1F7750352f1c37C15C4A314554d6A79d7d146", - "deployed_at": 31437550 - } - }, - "dest_contracts": { - "BSC Testnet": { - "off_ramp": "0x796D720ea9D4326ff356eadE13b123B267C03C80", - "commit_store": "0xaDb37cFd91fa9b6Df1DaAcbAfB4cDFF41e06c956", - "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" - } - } - }, - "BSC Testnet": { - "is_mock_arm": true, - "fee_token": "0x84b9B910527Ad5C03A9Ca831909E21e236EA7b06", - "bridge_tokens": null, - "bridge_tokens_pools": null, - "price_aggregators": null, - "arm": "0xbBF534D89d9640e3886db25FE1ffE603Fe160D75", - "router": "0x9CdA5b77eA23459eBaf2e3092c570a6B5605850A", - "price_registry": "0x9213967a47FC3F15A16A0b813208e8Ccb63Dbba6", - "wrapped_native": "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd", - "src_contracts": { - "Avalanche Fuji": { - "on_ramp": "0x0B4F541a7fcE5c251993Bc19D5A40B661e0463f5", - "deployed_at": 39097639 + "Arbitrum Sepolia": { + "on_ramp": "0x2Df17a22794499963EC0DDD43699B1020fdDD4d3", + "deployed_at": 36151865 } }, "dest_contracts": { - "Avalanche Fuji": { - "off_ramp": "0x41E59DCdDec18d7f79DA5F76Ce567d2c5e301E6B", - "commit_store": "0x9487C01D4b3Ae1c9Ac8740A07f3862D646548A14", + "Arbitrum Sepolia": { + "off_ramp": "0xFFBf82f59e5A7E1f92CE3565A6d6C835dEA19D1A", + "commit_store": "0x79357546378F29Ffcf3B7f3492Ee2Bcb9dB4d847", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -103,29 +64,17 @@ Data = """ "Base Sepolia": { "is_mock_arm": true, "fee_token": "0xE4aB69C077896252FAFBD49EFD26B5D171A32410", - "bridge_tokens": null, - "bridge_tokens_pools": null, - "price_aggregators": null, "arm": "0x866faB92E04bAE5EDa238A9cbFf1e56E09508Ade", "router": "0x2aE6d5495fc20226F433be50e37D59c05D186AaA", "price_registry": "0xD886E2286Fd1073df82462ea1822119600Af80b6", "wrapped_native": "0x4200000000000000000000000000000000000006", "src_contracts": { - "Arbitrum Sepolia": { - "on_ramp": "0xAE32FD8Ae148BD88E3da6FaE8Cd7561Eed3ec5Cc", - "deployed_at": 8133125 - }, "Optimism Sepolia": { "on_ramp": "0x9213967a47FC3F15A16A0b813208e8Ccb63Dbba6", "deployed_at": 11607777 } }, "dest_contracts": { - "Arbitrum Sepolia": { - "off_ramp": "0x34433469A4d6c8b1B0a1a7B91a5C5C2Dd74c67Fb", - "commit_store": "0xFEE7c8E229F538a98437b9A7D0Dd8fCd8A1Ab569", - "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" - }, "Optimism Sepolia": { "off_ramp": "0x0f30449bcCaCCaA7221B3f7C3304c4AaD68068E8", "commit_store": "0x17a5746c9cf7eAf23533F060F395B2E38eb976ea", @@ -136,75 +85,30 @@ Data = """ "Optimism Sepolia": { "is_mock_arm": true, "fee_token": "0xE4aB69C077896252FAFBD49EFD26B5D171A32410", - "bridge_tokens": null, - "bridge_tokens_pools": null, - "price_aggregators": null, - "arm": "0x2aE6d5495fc20226F433be50e37D59c05D186AaA", - "router": "0x0fF6b6F3Ad10D66600Fd5CC25b98542A05Aa7Bc2", - "price_registry": "0x3B80b7Ef5c00Eb892CBe72800C028C47AD6380EF", + "arm": "0xb665817485727D670dABD0F03A155401778C26ea", + "router": "0xF66f5c1417159eb38F622006eDE421BbF5262905", + "price_registry": "0x2dF2c61821A7BCcC851B15ee26BB06307d3bEE2d", "wrapped_native": "0x4200000000000000000000000000000000000006", "src_contracts": { "Arbitrum Sepolia": { - "on_ramp": "0x622CB640F52bFfA68b78b2BD12c1940Ca4899621", - "deployed_at": 8020540 + "on_ramp": "0x21ce68614782BF139bF21d7D2566A0d900c8638C", + "deployed_at": 18379535 }, "Base Sepolia": { "on_ramp": "0x12c164d0778E215873A062cEE2814507417339cB", "deployed_at": 13590651 - }, - "Sepolia Testnet": { - "on_ramp": "0x0c2c8D4266C98f1b9333D5E1a42f3f775A0005d4", - "deployed_at": 8020948 } }, "dest_contracts": { "Arbitrum Sepolia": { - "off_ramp": "0x37004c1245a2D5541377e87cA29699492a4114D5", - "commit_store": "0x51158Ca439feA9E809Bc063CfA6701747b05254e", + "off_ramp": "0xbeBD1F1f92a739810C102E5E5dc844E7efDbd747", + "commit_store": "0x39DEf7c3E3F2306012B96C1a4Cb1D574CA912CCa", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Base Sepolia": { "off_ramp": "0xB3F3f362FbeD49fA0086B434051C822B55BaADbD", "commit_store": "0xD4995B99c484CCABc868b26c0B2C2Ef10ecde3d7", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" - }, - "Sepolia Testnet": { - "off_ramp": "0x80C2aa80F202FeFdFEEF80f516cFd89768c54057", - "commit_store": "0xc1fE981A040D679511ccb9139ca107aCA67520ef", - "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" - } - } - }, - "Sepolia Testnet": { - "is_mock_arm": true, - "fee_token": "0x779877A7B0D9E8603169DdbD7836e478b4624789", - "bridge_tokens": null, - "bridge_tokens_pools": null, - "price_aggregators": null, - "arm": "0x9912a7389382ff55f85A29C9378B38F7B992c4aE", - "router": "0x1E1F3d8Ac7Df65fCcFcc52dbF03929cEE95430ac", - "price_registry": "0x4358e81f88bB27222779c1BC85003A11A1c66f6F", - "wrapped_native": "0x097D90c9d3E0B50Ca60e1ae45F6A81010f9FB534", - "src_contracts": { - "Arbitrum Sepolia": { - "on_ramp": "0x420a7B5ABB8CF27A70E1906F797e24509B11093D", - "deployed_at": 5275652 - }, - "Optimism Sepolia": { - "on_ramp": "0xEb4EBC1930bA81416A48a59142D89722163D85ae", - "deployed_at": 5281150 - } - }, - "dest_contracts": { - "Arbitrum Sepolia": { - "off_ramp": "0x224D1eB3aB2b7F23b66f093F9cBBC68dA77a1986", - "commit_store": "0x35c54cF12FF9B29dBa60dc23EdD1de0F13CC7fc5", - "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" - }, - "Optimism Sepolia": { - "off_ramp": "0xF21d01D6Ef822FBC56FC6c8F23f74fE3A0cb39aa", - "commit_store": "0x7F6AF440Bcc54f70Fd8AC2E534d37196c0bA1A38", - "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } } @@ -219,10 +123,8 @@ TTL = '8h' selected_networks = [ 'ARBITRUM_SEPOLIA', 'AVALANCHE_FUJI', - 'BASE_SEPOLIA', - 'BSC_TESTNET', +# 'BASE_SEPOLIA', 'OPTIMISM_SEPOLIA', - 'SEPOLIA' ] @@ -230,12 +132,14 @@ selected_networks = [ [CCIP.Groups.smoke] # these are all the valid network pairs NetworkPairs = [ - 'BSC_TESTNET,AVALANCHE_FUJI', - 'SEPOLIA,ARBITRUM_SEPOLIA', - 'BASE_SEPOLIA,OPTIMISM_SEPOLIA' +# 'ARBITRUM_SEPOLIA,AVALANCHE_FUJI', + 'ARBITRUM_SEPOLIA,OPTIMISM_SEPOLIA', + 'OPTIMISM_SEPOLIA,ARBITRUM_SEPOLIA', + 'AVALANCHE_FUJI,ARBITRUM_SEPOLIA', +# 'BASE_SEPOLIA,OPTIMISM_SEPOLIA' ] -BiDirectionalLane = true +BiDirectionalLane = false PhaseTimeout = '40m' LocalCluster = false ExistingDeployment = true @@ -255,8 +159,7 @@ AmountPerToken = 1 [CCIP.Groups.load] NetworkPairs = [ - 'AVALANCHE_FUJI,BSC_TESTNET', - 'SEPOLIA,ARBITRUM_SEPOLIA', + 'ARBITRUM_SEPOLIA,AVALANCHE_FUJI', 'BASE_SEPOLIA,OPTIMISM_SEPOLIA' ] @@ -272,7 +175,7 @@ NoOfTokensPerChain = 1 RequestPerUnitTime = [1] TimeUnit = '6m' TestDuration = '3h' -TestRunName = 'BetaSoakTest_CCIPV1dot5' +TestRunName = 'BetaSoakTest_CCIPV1dot5dot4' FailOnFirstErrorInLoad = true [[CCIP.Groups.load.LoadProfile.MsgProfile.MsgDetails]] diff --git a/integration-tests/ccip-tests/testconfig/tomls/beta-testnet/testnet-beta-workinglane_native.toml b/integration-tests/ccip-tests/testconfig/tomls/beta-testnet/testnet-beta-workinglane_native.toml index fcc063c7659..f3a43550d98 100644 --- a/integration-tests/ccip-tests/testconfig/tomls/beta-testnet/testnet-beta-workinglane_native.toml +++ b/integration-tests/ccip-tests/testconfig/tomls/beta-testnet/testnet-beta-workinglane_native.toml @@ -11,129 +11,73 @@ Data = """ { "lane_configs": { "Arbitrum Sepolia": { - "is_native_fee_token": true, "is_mock_arm": true, + "is_native_fee_token": true, "fee_token": "0xE591bf0A0CF924A0674d7792db046B23CEbF5f34", - "bridge_tokens": null, - "bridge_tokens_pools": null, - "price_aggregators": null, - "arm": "0x2aE6d5495fc20226F433be50e37D59c05D186AaA", - "router": "0x0fF6b6F3Ad10D66600Fd5CC25b98542A05Aa7Bc2", - "price_registry": "0x25d997d8618e1299418b3D905E40bC353ec89F61", + "arm": "0x5261Eac6b2A158b1eafed0144B4894f41b67b01f", + "router": "0x32C3C32B1b3858e45AFc53e1D0D4607463d47d1C", + "price_registry": "0x845A8190d31602fD0862467880468339E04d885b", "wrapped_native": "0xE591bf0A0CF924A0674d7792db046B23CEbF5f34", "src_contracts": { - "Base Sepolia": { - "on_ramp": "0x6BD0f1efA261Ea84DB219c1284b538A65E530ea1", - "deployed_at": 29428386 + "Avalanche Fuji": { + "on_ramp": "0x59f2492ebDfdD3E99b9198A2313AB0A4113014c8", + "deployed_at": 85949437 }, "Optimism Sepolia": { - "on_ramp": "0x94cd0d171eF08924F0008305e5Bb90b0fC1b61AB", - "deployed_at": 13945916 - }, - "Sepolia Testnet": { - "on_ramp": "0x44225eb3B73B1b52Dd2ecD258F9b63418eC6Bf79", - "deployed_at": 13730868 + "on_ramp": "0x3FF2852A4597E6Ac363340Cadbf1666C4246b4B9", + "deployed_at": 87452680 } }, "dest_contracts": { - "Base Sepolia": { - "off_ramp": "0x21560B4ACAEdb8AA2Dd935618F15da43197bdc12", - "commit_store": "0x27B882c393151ADD910F3557849AF0bb09c7d5A6", + "Avalanche Fuji": { + "off_ramp": "0x1b3841f8923195F1E438B471D0415bBE8b3c133D", + "commit_store": "0x55F4a33AC60D994c2F1A3b400Fc2C40140CF50D9", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Optimism Sepolia": { - "off_ramp": "0xAE32FD8Ae148BD88E3da6FaE8Cd7561Eed3ec5Cc", - "commit_store": "0x1f1160Ac7828B647A85c9a6b3A58A232C59D67Ab", - "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" - }, - "Sepolia Testnet": { - "off_ramp": "0xc136114F379b812345bb7e467ECDdb6D0c87De8b", - "commit_store": "0x42b3EbEA14F6CB803e3C7df84392Efb85CE90168", + "off_ramp": "0x695C84498573AEE9A2Be410Aaf7C275535A337D7", + "commit_store": "0xCBDdCEaE1d51F9C40640fa17fb7a2FeEB51DB702", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } }, "Avalanche Fuji": { - "is_native_fee_token": true, "is_mock_arm": true, + "is_native_fee_token": true, "fee_token": "0xd00ae08403B9bbb9124bB305C09058E32C39A48c", - "bridge_tokens": [ - "0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846" - ], - "bridge_tokens_pools": [ - "0x156943ae87AaF63eA9272902Cb05407ec7bc9464" - ], - "price_aggregators": null, - "arm": "0xD4A51dC0F5C680A8A18eA4Ec3A2f25C6db9424B7", - "router": "0xa62e685aDFF45f38eC94378513D128F168964E99", - "price_registry": "0xdbeA1a10AC6a2B729bF128aE9281Ed420dbE7113", + "arm": "0xd550342aE3f8d5D3D38509900034C8b01f556f0e", + "router": "0x13b766d0fe3e01fa5b02b378DF31724dD5368B37", + "price_registry": "0xAEc164EDF7Be32c6d38565BD09c24DAAA5b5887f", "wrapped_native": "0xd00ae08403B9bbb9124bB305C09058E32C39A48c", "src_contracts": { - "BSC Testnet": { - "on_ramp": "0xe4f1F7750352f1c37C15C4A314554d6A79d7d146", - "deployed_at": 31437550 - } - }, - "dest_contracts": { - "BSC Testnet": { - "off_ramp": "0x796D720ea9D4326ff356eadE13b123B267C03C80", - "commit_store": "0xaDb37cFd91fa9b6Df1DaAcbAfB4cDFF41e06c956", - "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" - } - } - }, - "BSC Testnet": { - "is_native_fee_token": true, - "is_mock_arm": true, - "fee_token": "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd", - "bridge_tokens": null, - "bridge_tokens_pools": null, - "price_aggregators": null, - "arm": "0xbBF534D89d9640e3886db25FE1ffE603Fe160D75", - "router": "0x9CdA5b77eA23459eBaf2e3092c570a6B5605850A", - "price_registry": "0x9213967a47FC3F15A16A0b813208e8Ccb63Dbba6", - "wrapped_native": "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd", - "src_contracts": { - "Avalanche Fuji": { - "on_ramp": "0x0B4F541a7fcE5c251993Bc19D5A40B661e0463f5", - "deployed_at": 39097639 + "Arbitrum Sepolia": { + "on_ramp": "0x2Df17a22794499963EC0DDD43699B1020fdDD4d3", + "deployed_at": 36151865 } }, "dest_contracts": { - "Avalanche Fuji": { - "off_ramp": "0x41E59DCdDec18d7f79DA5F76Ce567d2c5e301E6B", - "commit_store": "0x9487C01D4b3Ae1c9Ac8740A07f3862D646548A14", + "Arbitrum Sepolia": { + "off_ramp": "0xFFBf82f59e5A7E1f92CE3565A6d6C835dEA19D1A", + "commit_store": "0x79357546378F29Ffcf3B7f3492Ee2Bcb9dB4d847", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } }, "Base Sepolia": { - "is_native_fee_token": true, "is_mock_arm": true, + "is_native_fee_token": true, "fee_token": "0x4200000000000000000000000000000000000006", - "bridge_tokens": null, - "bridge_tokens_pools": null, - "price_aggregators": null, "arm": "0x866faB92E04bAE5EDa238A9cbFf1e56E09508Ade", "router": "0x2aE6d5495fc20226F433be50e37D59c05D186AaA", "price_registry": "0xD886E2286Fd1073df82462ea1822119600Af80b6", "wrapped_native": "0x4200000000000000000000000000000000000006", "src_contracts": { - "Arbitrum Sepolia": { - "on_ramp": "0xAE32FD8Ae148BD88E3da6FaE8Cd7561Eed3ec5Cc", - "deployed_at": 8133125 - }, "Optimism Sepolia": { "on_ramp": "0x9213967a47FC3F15A16A0b813208e8Ccb63Dbba6", "deployed_at": 11607777 } }, "dest_contracts": { - "Arbitrum Sepolia": { - "off_ramp": "0x34433469A4d6c8b1B0a1a7B91a5C5C2Dd74c67Fb", - "commit_store": "0xFEE7c8E229F538a98437b9A7D0Dd8fCd8A1Ab569", - "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" - }, "Optimism Sepolia": { "off_ramp": "0x0f30449bcCaCCaA7221B3f7C3304c4AaD68068E8", "commit_store": "0x17a5746c9cf7eAf23533F060F395B2E38eb976ea", @@ -142,79 +86,33 @@ Data = """ } }, "Optimism Sepolia": { - "is_native_fee_token": true, "is_mock_arm": true, + "is_native_fee_token": true, "fee_token": "0x4200000000000000000000000000000000000006", - "bridge_tokens": null, - "bridge_tokens_pools": null, - "price_aggregators": null, - "arm": "0x2aE6d5495fc20226F433be50e37D59c05D186AaA", - "router": "0x0fF6b6F3Ad10D66600Fd5CC25b98542A05Aa7Bc2", - "price_registry": "0x3B80b7Ef5c00Eb892CBe72800C028C47AD6380EF", + "arm": "0xb665817485727D670dABD0F03A155401778C26ea", + "router": "0xF66f5c1417159eb38F622006eDE421BbF5262905", + "price_registry": "0x2dF2c61821A7BCcC851B15ee26BB06307d3bEE2d", "wrapped_native": "0x4200000000000000000000000000000000000006", "src_contracts": { "Arbitrum Sepolia": { - "on_ramp": "0x622CB640F52bFfA68b78b2BD12c1940Ca4899621", - "deployed_at": 8020540 + "on_ramp": "0x21ce68614782BF139bF21d7D2566A0d900c8638C", + "deployed_at": 18379535 }, "Base Sepolia": { "on_ramp": "0x12c164d0778E215873A062cEE2814507417339cB", "deployed_at": 13590651 - }, - "Sepolia Testnet": { - "on_ramp": "0x0c2c8D4266C98f1b9333D5E1a42f3f775A0005d4", - "deployed_at": 8020948 } }, "dest_contracts": { "Arbitrum Sepolia": { - "off_ramp": "0x37004c1245a2D5541377e87cA29699492a4114D5", - "commit_store": "0x51158Ca439feA9E809Bc063CfA6701747b05254e", + "off_ramp": "0xbeBD1F1f92a739810C102E5E5dc844E7efDbd747", + "commit_store": "0x39DEf7c3E3F2306012B96C1a4Cb1D574CA912CCa", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Base Sepolia": { "off_ramp": "0xB3F3f362FbeD49fA0086B434051C822B55BaADbD", "commit_store": "0xD4995B99c484CCABc868b26c0B2C2Ef10ecde3d7", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" - }, - "Sepolia Testnet": { - "off_ramp": "0x80C2aa80F202FeFdFEEF80f516cFd89768c54057", - "commit_store": "0xc1fE981A040D679511ccb9139ca107aCA67520ef", - "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" - } - } - }, - "Sepolia Testnet": { - "is_native_fee_token": true, - "is_mock_arm": true, - "fee_token": "0x097D90c9d3E0B50Ca60e1ae45F6A81010f9FB534", - "bridge_tokens": null, - "bridge_tokens_pools": null, - "price_aggregators": null, - "arm": "0x9912a7389382ff55f85A29C9378B38F7B992c4aE", - "router": "0x1E1F3d8Ac7Df65fCcFcc52dbF03929cEE95430ac", - "price_registry": "0x4358e81f88bB27222779c1BC85003A11A1c66f6F", - "wrapped_native": "0x097D90c9d3E0B50Ca60e1ae45F6A81010f9FB534", - "src_contracts": { - "Arbitrum Sepolia": { - "on_ramp": "0x420a7B5ABB8CF27A70E1906F797e24509B11093D", - "deployed_at": 5275652 - }, - "Optimism Sepolia": { - "on_ramp": "0xEb4EBC1930bA81416A48a59142D89722163D85ae", - "deployed_at": 5281150 - } - }, - "dest_contracts": { - "Arbitrum Sepolia": { - "off_ramp": "0x224D1eB3aB2b7F23b66f093F9cBBC68dA77a1986", - "commit_store": "0x35c54cF12FF9B29dBa60dc23EdD1de0F13CC7fc5", - "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" - }, - "Optimism Sepolia": { - "off_ramp": "0xF21d01D6Ef822FBC56FC6c8F23f74fE3A0cb39aa", - "commit_store": "0x7F6AF440Bcc54f70Fd8AC2E534d37196c0bA1A38", - "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } } @@ -229,26 +127,24 @@ TTL = '8h' selected_networks = [ 'ARBITRUM_SEPOLIA', 'AVALANCHE_FUJI', - 'BASE_SEPOLIA', - 'BSC_TESTNET', + # 'BASE_SEPOLIA', 'OPTIMISM_SEPOLIA', - 'SEPOLIA', ] -[CCIP.Env.NewCLCluster.Common.ChainlinkImage] -version = "sha-17ce920" [CCIP.Groups.smoke] # these are all the valid network pairs NetworkPairs = [ - 'AVALANCHE_FUJI,BSC_TESTNET', - 'SEPOLIA,ARBITRUM_SEPOLIA', - 'BASE_SEPOLIA,OPTIMISM_SEPOLIA', + # 'ARBITRUM_SEPOLIA,AVALANCHE_FUJI', + 'ARBITRUM_SEPOLIA,OPTIMISM_SEPOLIA', + 'OPTIMISM_SEPOLIA,ARBITRUM_SEPOLIA', + 'AVALANCHE_FUJI,ARBITRUM_SEPOLIA', + # 'BASE_SEPOLIA,OPTIMISM_SEPOLIA' ] -BiDirectionalLane = true -PhaseTimeout = '30m' +BiDirectionalLane = false +PhaseTimeout = '40m' LocalCluster = false ExistingDeployment = true ReuseContracts = true @@ -267,8 +163,7 @@ AmountPerToken = 1 [CCIP.Groups.load] NetworkPairs = [ - 'AVALANCHE_FUJI,BSC_TESTNET', - 'SEPOLIA,ARBITRUM_SEPOLIA', + 'ARBITRUM_SEPOLIA,AVALANCHE_FUJI', 'BASE_SEPOLIA,OPTIMISM_SEPOLIA' ] @@ -284,7 +179,7 @@ NoOfTokensPerChain = 1 RequestPerUnitTime = [1] TimeUnit = '6m' TestDuration = '3h' -TestRunName = 'BetaSoakTest_V2.14.0-1.5.1' +TestRunName = 'BetaSoakTest_CCIPV1dot5dot4' FailOnFirstErrorInLoad = true [[CCIP.Groups.load.LoadProfile.MsgProfile.MsgDetails]] diff --git a/integration-tests/ccip-tests/testconfig/tomls/ccip-default.toml b/integration-tests/ccip-tests/testconfig/tomls/ccip-default.toml index 89858a94ddb..41367c45fb0 100644 --- a/integration-tests/ccip-tests/testconfig/tomls/ccip-default.toml +++ b/integration-tests/ccip-tests/testconfig/tomls/ccip-default.toml @@ -218,6 +218,10 @@ BlockHistorySize = 200 EIP1559FeeCapBufferBlocks = 0 """ +# Run by default using latest version from `ccip-develop` branch, override this value to use a specific version +[CCIP.Env.NewCLCluster.Common.ChainlinkImage] +version = "ccip-develop" + # the following configs are specific to each test type, smoke, load , chaos, etc... [CCIP.Groups] [CCIP.Groups.smoke] @@ -228,9 +232,8 @@ EIP1559FeeCapBufferBlocks = 0 KeepEnvAlive = false # if true, the test will not tear down the test environment after the test is finished CommitAndExecuteOnSameDON = true # if true, and the test is building the env from scratch, same chainlink nodes will be used for Commit and Execution jobs. -AllowOutOfOrder = false # if true, all the lanes will allow out of order execution and it -# overrides settings from lane_config. To allow out of order execution per lane, then send "allow_out_of_order":true, similar to is_native_fee_token variable. # Otherwise Commit and execution jobs will be set up in different nodes based on the number of nodes specified in NoOfCommitNodes and CCIP.Env.NewCLCluster.NoOfNodes +AllowOutOfOrder = false # if true, all lanes will set all transactions to allow out of order execution. This setting overrides individual settings from lane_config. To allow out of order execution per lane, then send "allow_out_of_order":true, similar to is_native_fee_token variable. BiDirectionalLane = true # True uses both the lanes. If bidirectional is false only one way lane is set up. NoOfCommitNodes = 5 # no of chainlink nodes with Commit job PhaseTimeout = '10m' # Duration to wait for the each phase validation(SendRequested, Commit, RMN Blessing, Execution) to time-out. @@ -361,7 +364,7 @@ CCIPOwnerTokens = false # if true, the test will use deploy the tokens by the CC # Uncomment the following if you want to run your tests with updated OCR params # otherwise test will use default OCR params from - -# https://github.com/smartcontractkit/chainlink/blob/develop/integration-tests/ccip-tests/contracts/contract_deployer.go#L729-L751 +# https://github.com/smartcontractkit/ccip/blob/ccip-develop/integration-tests/ccip-tests/contracts/contract_deployer.go#L729-L751 ## OCR Params #CommitInflightExpiry = '2m' #ExecInflightExpiry = '2m' diff --git a/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress/baseline.toml b/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress/baseline.toml index d48c0b0f797..d78cd125958 100644 --- a/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress/baseline.toml +++ b/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress/baseline.toml @@ -1,5 +1,5 @@ ## Baseline performance test on simulated environment (with chaos) -## 40 chains / 400 lanes +## 30 chains / 300 lanes ## historyDepth 200 / finalityDepth 200 ## block_time = 1s ## throughput 1msg / 5s @@ -7,8 +7,15 @@ ## ## make test_load_ccip testimage=.dkr.ecr..amazonaws.com/chainlink-ccip-tests:ccip-develop \ ## testname=TestLoadCCIPStableRequestTriggeringWithNetworkChaos \ -## override_toml=./testconfig/tomls/ccip-1.4-stress/baseline.toml \ -## secret_toml=./testconfig/tomls/secrets.toml +## override_toml=./testconfig/tomls/ccip-1.4-stress/baseline.toml + +## Adjust this value depending on what you want to test. +# Using releases and git tag requires changing the image name to the correct one in `~/.testsecrets`, e.g. +# E2E_TEST_CHAINLINK_IMAGE="public.ecr.aws/w0i8p0z9/chainlink-ccip" +# If you want to use a specific commit or a branch you need to switch to the internal ECR in `~/.testsecrets` +# E2E_TEST_CHAINLINK_IMAGE=".dkr.ecr..amazonaws.com/chainlink-ccip" +[CCIP.Env.NewCLCluster.Common.ChainlinkImage] +version = "2.14.0-ccip1.5.0" [CCIP] [CCIP.ContractVersions] @@ -19,10 +26,10 @@ TokenPool = '1.4.0' CommitStore = '1.2.0' [CCIP.Env] -TTL = '8h' +TTL = '10h' [CCIP.Env.Network] -selected_networks= ['PRIVATE-CHAIN-1', 'PRIVATE-CHAIN-2'] +selected_networks = ['PRIVATE-CHAIN-1', 'PRIVATE-CHAIN-2'] [CCIP.Env.Network.EVMNetworks.PRIVATE-CHAIN-1] evm_name = 'private-chain-1' @@ -66,7 +73,7 @@ block_time = 1 [CCIP.Env.NewCLCluster] NoOfNodes = 17 NodeMemory = '10Gi' -NodeCPU = '6' +NodeCPU = '4' DBMemory = '16Gi' DBCPU = '4' DBStorageClass = 'gp3' @@ -124,6 +131,8 @@ DeltaReconcile = '5s' """ CommonChainConfigTOML = """ +LogPollInterval = '1s' + [HeadTracker] HistoryDepth = 200 @@ -139,9 +148,9 @@ KeepEnvAlive = true NoOfCommitNodes = 16 PhaseTimeout = '40m' NodeFunding = 1000.0 -NoOfRoutersPerPair = 2 -NoOfNetworks = 40 -MaxNoOfLanes = 400 +NoOfRoutersPerPair = 1 +NoOfNetworks = 30 +MaxNoOfLanes = 300 [CCIP.Groups.load.OffRampConfig] BatchGasLimit = 11000000 @@ -150,11 +159,11 @@ BatchGasLimit = 11000000 TimeoutForPriceUpdate = '15m' NoOfTokensPerChain = 10 NoOfTokensWithDynamicPrice = 10 -DynamicPriceUpdateInterval ='15s' +DynamicPriceUpdateInterval = '15s' CCIPOwnerTokens = true [CCIP.Groups.load.LoadProfile] -TestDuration = '4h' +TestDuration = '6h' TimeUnit = '5s' RequestPerUnitTime = [1] OptimizeSpace = true @@ -162,7 +171,7 @@ NetworkChaosDelay = '100ms' # to represent 20%, 60%, 15%, 5% of the total messages [CCIP.Groups.load.LoadProfile.MsgProfile] -Frequencies = [4,12,3,1] +Frequencies = [4, 12, 3, 1] [[CCIP.Groups.load.LoadProfile.MsgProfile.MsgDetails]] MsgType = 'Token' @@ -186,4 +195,4 @@ DataLength = 10000 [[CCIP.Groups.load.LoadProfile.MsgProfile.MsgDetails]] MsgType = 'Data' DestGasLimit = 2500000 -DataLength = 10000 +DataLength = 10000 \ No newline at end of file diff --git a/integration-tests/ccip-tests/testconfig/tomls/lbtc_mock_deployment_with_32bytes_data.toml b/integration-tests/ccip-tests/testconfig/tomls/lbtc_mock_deployment_with_32bytes_data.toml new file mode 100644 index 00000000000..6f755456932 --- /dev/null +++ b/integration-tests/ccip-tests/testconfig/tomls/lbtc_mock_deployment_with_32bytes_data.toml @@ -0,0 +1,11 @@ +[CCIP] +[CCIP.Groups] +[CCIP.Groups.smoke] +LBTCMockDeployment = true +LBTCDestPoolDataAs32Bytes = true + +[CCIP.Groups.smoke.TokenConfig] +NoOfTokensPerChain = 1 + +[CCIP.Groups.smoke.MsgDetails] +NoOfTokens = 1 \ No newline at end of file diff --git a/integration-tests/ccip-tests/testconfig/tomls/lbtc_mock_deployment_with_non32bytes_data.toml b/integration-tests/ccip-tests/testconfig/tomls/lbtc_mock_deployment_with_non32bytes_data.toml new file mode 100644 index 00000000000..21210acbaf6 --- /dev/null +++ b/integration-tests/ccip-tests/testconfig/tomls/lbtc_mock_deployment_with_non32bytes_data.toml @@ -0,0 +1,11 @@ +[CCIP] +[CCIP.Groups] +[CCIP.Groups.smoke] +LBTCMockDeployment = true +LBTCDestPoolDataAs32Bytes = false + +[CCIP.Groups.smoke.TokenConfig] +NoOfTokensPerChain = 1 + +[CCIP.Groups.smoke.MsgDetails] +NoOfTokens = 1 \ No newline at end of file diff --git a/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/load-prod-testnet.toml b/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/load-prod-testnet.toml index f13965d5e67..c6902eaf490 100644 --- a/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/load-prod-testnet.toml +++ b/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/load-prod-testnet.toml @@ -1,898 +1,169 @@ [CCIP] [CCIP.ContractVersions] -PriceRegistry = '1.2.0' -OffRamp = '1.2.0' -OnRamp = '1.2.0' -TokenPool = '1.4.0' -CommitStore = '1.2.0' +PriceRegistry = 'latest' +OffRamp = 'latest' +OnRamp = 'latest' +CommitStore = 'latest' +TokenPool = 'latest' [CCIP.Deployments] Data = """ { "lane_configs": { - "Arbitrum Sepolia": { - "is_native_fee_token": true, - "fee_token": "0xb1D4538B4571d411F07960EF2838Ce337FE1E80E", - "bridge_tokens": [ - ], - "bridge_tokens_pools": [ - ], - "price_aggregators": null, - "arm": "0x5EF7a726Fd21Fd9D77D34E3C56cfDD8691F7F0ac", - "router": "0x2a9C5afB0d0e4BAb2BCdaE109EC4b0c4Be15a165", - "price_registry": "0x89D5b13908b9063abCC6791dc724bF7B7c93634C", - "wrapped_native": "0xE591bf0A0CF924A0674d7792db046B23CEbF5f34", - "src_contracts": { - "Avalanche Fuji": { - "on_ramp": "0x1Cb56374296ED19E86F68fA437ee679FD7798DaA", - "deployed_at": 33999325 - }, - "Base Sepolia": { - "on_ramp": "0x7854E73C73e7F9bb5b0D5B4861E997f4C6E8dcC6", - "deployed_at": 9199926 - }, - "Gnosis Chiado": { - "on_ramp": "0x973CbE752258D32AE82b60CD1CB656Eebb588dF0", - "deployed_at": 42809650 - }, - "Optimism Sepolia": { - "on_ramp": "0x701Fe16916dd21EFE2f535CA59611D818B017877", - "deployed_at": 35180131 - }, - "Sepolia Testnet": { - "on_ramp": "0x4205E1Ca0202A248A5D42F5975A8FE56F3E302e9", - "deployed_at": 35180131 - }, - "WeMix Testnet": { - "on_ramp": "0xBD4106fBE4699FE212A34Cc21b10BFf22b02d959", - "deployed_at": 18816676 - } - }, - "dest_contracts": { - "Avalanche Fuji": { - "off_ramp": "0xcab0EF91Bee323d1A617c0a027eE753aFd6997E4", - "commit_store": "0x0d90b9b96cBFa0D01635ce12982ccE1b70827c7a", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Base Sepolia": { - "off_ramp": "0xc1982985720B959E66c19b64F783361Eb9B60F26", - "commit_store": "0x28F66bB336f6db713d6ad2a3bd1B7a531282A159", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Gnosis Chiado": { - "off_ramp": "0x935C26F9a9122E5F9a27f2d3803e74c75B94f5a3", - "commit_store": "0xEdb963Ec5c2E5AbdFdCF137eF44A445a7fa4787A", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Optimism Sepolia": { - "off_ramp": "0xfD404A89e1d195F0c65be1A9042C77745197659e", - "commit_store": "0x84B7B012c95f8A152B44Ab3e952f2dEE424fA8e1", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Sepolia Testnet": { - "off_ramp": "0x1c71f141b4630EBE52d6aF4894812960abE207eB", - "commit_store": "0xaB0c8Ba51E7Fa3E5693a4Fbb39473520FD85d173", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "WeMix Testnet": { - "off_ramp": "0x262e16C8D42aa07bE13e58F81e7D9F62F6DE2830", - "commit_store": "0xc132eFAf929299E5ee704Fa6D9796CFa23Bb8b2C", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, "Avalanche Fuji": { - "fee_token": "0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846", - "bridge_tokens": [ - ], - "bridge_tokens_pools": [ - ], - "price_aggregators": null, - "arm": "0x0ea0D7B2b78DD3A926fC76d6875a287F0AEB158F", + "is_native_fee_token": true, + "fee_token": "0xd00ae08403B9bbb9124bB305C09058E32C39A48c", + "arm": "0x7e28DD790214139798446A121cFe950B51304684", "router": "0xF694E193200268f9a4868e4Aa017A0118C9a8177", "price_registry": "0x19e157E5fb1DAec1aE4BaB113fdf077F980704AA", "wrapped_native": "0xd00ae08403B9bbb9124bB305C09058E32C39A48c", "src_contracts": { - "Arbitrum Sepolia": { - "on_ramp": "0x8bB16BEDbFd62D1f905ACe8DBBF2954c8EEB4f66", - "deployed_at": 31888860 - }, - "BSC Testnet": { - "on_ramp": "0xF25ECF1Aad9B2E43EDc2960cF66f325783245535", - "deployed_at": 33214865 - }, "Base Sepolia": { - "on_ramp": "0x1A674645f3EB4147543FCA7d40C5719cbd997362", - "deployed_at": 31235262 - }, - "Gnosis Chiado": { - "on_ramp": "0x1532e5b204ee2b2244170c78E743CB9c168F4DF9", - "deployed_at": 32817266 + "on_ramp": "0x0aEc1AC9F6D0c21332d7a66dDF1Fbcb32cF3B0B3", + "deployed_at": 0 }, "Optimism Sepolia": { - "on_ramp": "0xC334DE5b020e056d0fE766dE46e8d9f306Ffa1E2", - "deployed_at": 30396804 - }, - "Polygon Amoy": { - "on_ramp": "0x610F76A35E17DA4542518D85FfEa12645eF111Fc", - "deployed_at": 31982368 + "on_ramp": "0x2a9EFdc9F93D9b822129038EFCa4B63Adf3f7FB5", + "deployed_at": 0 }, "Sepolia Testnet": { - "on_ramp": "0x5724B4Cc39a9690135F7273b44Dfd3BA6c0c69aD", - "deployed_at": 33214865 - }, - "WeMix Testnet": { - "on_ramp": "0x677B5ab5C8522d929166c064d5700F147b15fa33", - "deployed_at": 30436465 + "on_ramp": "0x75b9a75Ee1fFef6BE7c4F842a041De7c6153CF4E", + "deployed_at": 0 } }, "dest_contracts": { - "Arbitrum Sepolia": { - "off_ramp": "0x90A74072e7B0c2d59e13aB4d8f93c8198c413194", - "commit_store": "0xf3458CFd2fdf4a6CF0Ce296d520DD21eB194828b", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Testnet": { - "off_ramp": "0x10b28009E5D776F1f5AAA73941CE8953B8f42d26", - "commit_store": "0xacDD582F271eCF22FAd6764cCDe1c4a534b732A8", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, "Base Sepolia": { - "off_ramp": "0xdBdE8510226d1E060A3bf982b67705C67f5697e2", - "commit_store": "0x8Ee73BC9492b4182D289E5C1e66e40CD876CC00F", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Gnosis Chiado": { - "off_ramp": "0x56dF55aF5F0A4689f3364230587a68eD6A314fAd", - "commit_store": "0xabA7ff98094c4cc7A075812EefF2CD21f6400235", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" + "off_ramp": "0xf8de9d5924CFD28e31a53B63B4903436D9818d69", + "commit_store": "0xDD7CfECE1bb4e8aC2E8b8281CFE1D44247119471", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Optimism Sepolia": { - "off_ramp": "0x3d7CbC95DCC33257F14D6Eb780c88Bd56C6335BB", - "commit_store": "0x1fcDC02edDfb405f378ba53cF9E6104feBcB7542", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Amoy": { - "off_ramp": "0x3e33290B90fD0FF30a3FA138934DF028E4eCA348", - "commit_store": "0xCFe3556Aa42d40be09BD23aa80448a19443BE5B1", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Sepolia Testnet": { - "off_ramp": "0x9e5e4324F8608D54A50a317832d456a392E4F8C2", - "commit_store": "0x92A51eD3F041B39EbD1e464C1f7cb1e8f8A8c63f", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "WeMix Testnet": { - "off_ramp": "0xD0D338318bC6837b091FC7AB5F2a94B7783507d5", - "commit_store": "0xd9D479208235c7355848ff4aF26eB5aacfDC30c6", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "BSC Testnet": { - "is_native_fee_token": true, - "fee_token": "0x84b9B910527Ad5C03A9Ca831909E21e236EA7b06", - "bridge_tokens": [ - ], - "bridge_tokens_pools": [ - ], - "price_aggregators": null, - "arm": "0xF9a21B587111e7E8745Fb8b13750014f19DB0014", - "router": "0xE1053aE1857476f36A3C62580FF9b016E8EE8F6f", - "price_registry": "0xCCDf022c9d31DC26Ebab4FB92432724a5b79809a", - "wrapped_native": "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd", - "src_contracts": { - "Avalanche Fuji": { - "on_ramp": "0xa2515683E99F50ADbE177519A46bb20FfdBaA5de", - "deployed_at": 40500000 - }, - "Base Sepolia": { - "on_ramp": "0x3E807220Ca84b997c0d1928162227b46C618e0c5", - "deployed_at": 37115558 - }, - "Gnosis Chiado": { - "on_ramp": "0x8735f991d41eA9cA9D2CC75cD201e4B7C866E63e", - "deployed_at": 40228352 - }, - "Polygon Amoy": { - "on_ramp": "0xf37CcbfC04adc1B56a46B36F811D52C744a1AF78", - "deployed_at": 39572254 - }, - "Sepolia Testnet": { - "on_ramp": "0xB1DE44B04C00eaFe9915a3C07a0CaeA4410537dF", - "deployed_at": 38150066 - }, - "WeMix Testnet": { - "on_ramp": "0x89268Afc1BEA0782a27ba84124E3F42b196af927", - "deployed_at": 38184995 - } - }, - "dest_contracts": { - "Avalanche Fuji": { - "off_ramp": "0x6e6fFCb6B4BED91ff0CC8C2e57EC029dA7DB80C2", - "commit_store": "0x38Bc38Bd824b6eE87571f9D3CFbe6D6E28E3Dc62", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Base Sepolia": { - "off_ramp": "0x2C61FD7E93Dc79422861282145c59B56dFbc3a8c", - "commit_store": "0x42fAe5B3605804CF6d08632d7A25864e24F792Ae", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Gnosis Chiado": { - "off_ramp": "0x71a44a60832B0F8B63232C9516e7E6aEc3A373Dc", - "commit_store": "0xAC24299a91b72d1Cb5B31147e3CF54964D896974", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Amoy": { - "off_ramp": "0x63440C7747d37bc6154b5538AE32b54FE0965AfA", - "commit_store": "0xAD22fA198CECfC534927aE1D480c460d5bB3460F", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" + "off_ramp": "0x1DF9D94C6916918C935E60d2Cb4Ed265Bf778005", + "commit_store": "0xE7eeBE5882609d28C015d0A89DE1ba4f506F4a03", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { - "off_ramp": "0xf1c128Fe52Ea78CcAAB407509292E61ce38C1523", - "commit_store": "0x59dFD870dC4bd76A7B879A4f705Fdcd2595f85f9", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "WeMix Testnet": { - "off_ramp": "0xfd9B19c3725da5B517aA705B848ff3f21F98280e", - "commit_store": "0x3c1F1412563188aBc8FE3fd53E8F1Cb601CaB4f9", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" + "off_ramp": "0x01e3D835b4C4697D7F81B9d7Abc89A6E478E4a2f", + "commit_store": "0x4EC313c1Eb620432f42FB5f4Df27f8A566523c1C", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } }, "Base Sepolia": { "is_native_fee_token": true, - "fee_token": "0xE4aB69C077896252FAFBD49EFD26B5D171A32410", - "bridge_tokens": [ - ], - "bridge_tokens_pools": [ - ], - "price_aggregators": null, - "arm": "0x5aA82cA372782d6CC33AA4C830Df2a91017A7e1b", + "fee_token": "0x4200000000000000000000000000000000000006", + "arm": "0x7827dD0481EE18DB646bD250d20A8eA43da52146", "router": "0xD3b06cEbF099CE7DA4AcCf578aaebFDBd6e88a93", "price_registry": "0x4D20536e60832bE579Cd38E89Dc03d11E1741FbA", "wrapped_native": "0x4200000000000000000000000000000000000006", "src_contracts": { - "Arbitrum Sepolia": { - "on_ramp": "0x58622a80c6DdDc072F2b527a99BE1D0934eb2b50", - "deployed_at": 5146539 - }, "Avalanche Fuji": { - "on_ramp": "0xAbA09a1b7b9f13E05A6241292a66793Ec7d43357", - "deployed_at": 7810235 - }, - "BSC Testnet": { - "on_ramp": "0xD806966beAB5A3C75E5B90CDA4a6922C6A9F0c9d", - "deployed_at": 5144127 - }, - "Gnosis Chiado": { - "on_ramp": "0x2Eff2d1BF5C557d6289D208a7a43608f5E3FeCc2", - "deployed_at": 9817141 + "on_ramp": "0x212e8Fd9cCC330ab54E8141FA7d33967eF1eDafF", + "deployed_at": 0 }, "Optimism Sepolia": { - "on_ramp": "0x3b39Cd9599137f892Ad57A4f54158198D445D147", - "deployed_at": 5147649 + "on_ramp": "0x2945D35F428CE564F5455AD0AF28BDFCa67e76Ab", + "deployed_at": 0 }, "Sepolia Testnet": { - "on_ramp": "0x6486906bB2d85A6c0cCEf2A2831C11A2059ebfea", - "deployed_at": 7810235 - }, - "ethereum-testnet-sepolia-mode-1": { - "on_ramp": "0x3d0115386C01436870a2c47e6297962284E70BA6", - "deployed_at": 10409731 + "on_ramp": "0x29A1F4ecE9246F0042A9062FB89803fA8B1830cB", + "deployed_at": 0 } }, "dest_contracts": { - "Arbitrum Sepolia": { - "off_ramp": "0xd364C06ac99a82a00d3eFF9F2F78E4Abe4b9baAA", - "commit_store": "0xdE8d0f47a71eA3fDFBD3162271652f2847939097", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, "Avalanche Fuji": { - "off_ramp": "0xAd91214efFee446500940c764DF77AF18427294F", - "commit_store": "0x1242b6c5e0e349b8d4BCf0938f961C4B4f7EA3Fa", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Testnet": { - "off_ramp": "0xd5E9508921434e8758f4540D55c1c066b7cc1598", - "commit_store": "0x1a86b29364D1B3fA3386329A361aA98A104b2742", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Gnosis Chiado": { - "off_ramp": "0x9Bb7e398ef9Acfe9cA584C39B1E233Cba62BB9f7", - "commit_store": "0x1F4B82cDebaC5e3a0Dd53183D47e51808B4a64cB", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" + "off_ramp": "0x3Ab3a3d35cAC95FfcFCcc127eF01eA8D87b0A64e", + "commit_store": "0x51313B8C068B5227fa7364E6eCB1382Fb751976F", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Optimism Sepolia": { - "off_ramp": "0x86a3910908eCaAA31Fcd9F0fC8841D8E98f1511d", - "commit_store": "0xE99a87C9b5ed4D2b6060195DEea5106ffF655736", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" + "off_ramp": "0x8718d1cc138421Dbc1B489CB7884FF68DE7ad867", + "commit_store": "0x3291D453c880E5b59EEd04E600c85268Cd378b7f", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { - "off_ramp": "0x189F61D9B886Dd2975D5Abc893c8Cf5f5effda71", - "commit_store": "0xEE7e27346DCD1e711348D0F7f7ECB53a9a3a08a7", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "ethereum-testnet-sepolia-mode-1": { - "off_ramp": "0xB26647A23e8b4284375e5C74b77c9557aE709D03", - "commit_store": "0x4b4fEB401d3E613e1D6242E155C83A80BF9ac2C9", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "Gnosis Chiado": { - "is_native_fee_token": true, - "fee_token": "0xDCA67FD8324990792C0bfaE95903B8A64097754F", - "bridge_tokens": [ - ], - "bridge_tokens_pools": [ - ], - "price_aggregators": null, - "arm": "0xb6f1Fe2CDE891eFd5Efd2A563C4C2F2549163718", - "router": "0x19b1bac554111517831ACadc0FD119D23Bb14391", - "price_registry": "0x2F4ACd1f8986c6B1788159C4c9a5fC3fceCCE363", - "wrapped_native": "0x18c8a7ec7897177E4529065a7E7B0878358B3BfF", - "src_contracts": { - "Arbitrum Sepolia": { - "on_ramp": "0x473b49fb592B54a4BfCD55d40E048431982879C9", - "deployed_at": 9718588 - }, - "Avalanche Fuji": { - "on_ramp": "0x610F76A35E17DA4542518D85FfEa12645eF111Fc", - "deployed_at": 9718676 - }, - "BSC Testnet": { - "on_ramp": "0xE48E6AA1fc7D0411acEA95F8C6CaD972A37721D4", - "deployed_at": 9718302 - }, - "Base Sepolia": { - "on_ramp": "0x41b4A51cAfb699D9504E89d19D71F92E886028a8", - "deployed_at": 9718513 - }, - "Optimism Sepolia": { - "on_ramp": "0xAae733212981e06D9C978Eb5148F8af03F54b6EF", - "deployed_at": 9718420 - }, - "Polygon Amoy": { - "on_ramp": "0x01800fCDd892e37f7829937271840A6F041bE62E", - "deployed_at": 9718194 - }, - "Sepolia Testnet": { - "on_ramp": "0x4ac7FBEc2A7298AbDf0E0F4fDC45015836C4bAFe", - "deployed_at": 8487681 - } - }, - "dest_contracts": { - "Arbitrum Sepolia": { - "off_ramp": "0x9aA82DBB53bf02096B771D40e9432A323a78fB26", - "commit_store": "0x5CdbA91aBC0cD81FC56bc10Ad1835C9E5fB38e5F", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Avalanche Fuji": { - "off_ramp": "0x3e33290B90fD0FF30a3FA138934DF028E4eCA348", - "commit_store": "0xCFe3556Aa42d40be09BD23aa80448a19443BE5B1", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Testnet": { - "off_ramp": "0xbc4AD54e91b213D4279af92c0C5518c0b96cf62D", - "commit_store": "0xff84e8Dd4Fd17eaBb23b6AeA6e1981830e54389C", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Base Sepolia": { - "off_ramp": "0x4117953A5ceeF12f5B8C1E973b470ab83a8CebA6", - "commit_store": "0x94ad41296186E81f31e1ed0B1BcF5fa9e1721C27", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Optimism Sepolia": { - "off_ramp": "0x33d2898F8fb7714FD1661791766f40754982a343", - "commit_store": "0x55d6Df194472f02CD481e506A277c4A29D0D1bCc", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Amoy": { - "off_ramp": "0x450543b1d85ca79885851D7b74dc982981b78229", - "commit_store": "0x23B79d940A769FE31b4C867A8BAE80117f24Ca81", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Sepolia Testnet": { - "off_ramp": "0xbf9036529123DE264bFA0FC7362fE25B650D4B16", - "commit_store": "0x5f7F1abD5c5EdaF2636D58B980e85355AF0Ef80d", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "Kroma Sepolia": { - "is_native_fee_token": true, - "fee_token": "0xa75cCA5b404ec6F4BB6EC4853D177FE7057085c8", - "bridge_tokens": [ - ], - "bridge_tokens_pools": [ - ], - "price_aggregators": null, - "arm": "0x1E4e4e0d6f6631A45C616F71a1A5cF208DB9eCDe", - "router": "0xA8C0c11bf64AF62CDCA6f93D3769B88BdD7cb93D", - "price_registry": "0xa1ed3A3aA29166C9c8448654A8cA6b7916BC8379", - "wrapped_native": "0x4200000000000000000000000000000000000001", - "src_contracts": { - "WeMix Testnet": { - "on_ramp": "0x6ea155Fc77566D9dcE01B8aa5D7968665dc4f0C5", - "deployed_at": 10290904 - } - }, - "dest_contracts": { - "WeMix Testnet": { - "off_ramp": "0xB602B6E5Caf08ac0C920EAE585aed100a8cF6f3B", - "commit_store": "0x89D5b13908b9063abCC6791dc724bF7B7c93634C", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" + "off_ramp": "0x0ecA23Ef70B828fEDd0A84d2692cB0527B52396A", + "commit_store": "0xA7F84Ec616F8e9Fa593339944E76bda90A9737fE", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } }, "Optimism Sepolia": { "is_native_fee_token": true, - "fee_token": "0xE4aB69C077896252FAFBD49EFD26B5D171A32410", - "bridge_tokens": [ - ], - "bridge_tokens_pools": [ - ], - "price_aggregators": null, - "arm": "0xf06Ff5D2084295909119ca541E93635E7D582FFc", + "fee_token": "0x4200000000000000000000000000000000000006", + "arm": "0xF51366F72184E22cF4a7a8362508DB0d3370392d", "router": "0x114A20A10b43D4115e5aeef7345a1A71d2a60C57", "price_registry": "0x782a7Ba95215f2F7c3dD4C153cbB2Ae3Ec2d3215", "wrapped_native": "0x4200000000000000000000000000000000000006", "src_contracts": { - "Arbitrum Sepolia": { - "on_ramp": "0x1a86b29364D1B3fA3386329A361aA98A104b2742", - "deployed_at": 10841494 - }, "Avalanche Fuji": { - "on_ramp": "0x6b38CC6Fa938D5AB09Bdf0CFe580E226fDD793cE", - "deployed_at": 8677537 + "on_ramp": "0x91a144F570ABA7FB7079Fb187A267390E0cc7367", + "deployed_at": 0 }, "Base Sepolia": { - "on_ramp": "0xe284D2315a28c4d62C419e8474dC457b219DB969", - "deployed_at": 7130524 - }, - "Gnosis Chiado": { - "on_ramp": "0x835a5b8e6CA17c2bB5A336c93a4E22478E6F1C8A", - "deployed_at": 11799783 - }, - "Polygon Amoy": { - "on_ramp": "0x2Cf26fb01E9ccDb831414B766287c0A9e4551089", - "deployed_at": 10813146 + "on_ramp": "0x6D22953cdEf8B0C9F0976Cfa52c33B198fEc5881", + "deployed_at": 0 }, "Sepolia Testnet": { - "on_ramp": "0xC8b93b46BF682c39B3F65Aa1c135bC8A95A5E43a", - "deployed_at": 12165583 - }, - "WeMix Testnet": { - "on_ramp": "0xc7E53f6aB982af7A7C3e470c8cCa283d3399BDAd", - "deployed_at": 8733017 + "on_ramp": "0x54b32C2aCb4451c6cF66bcbd856d8A7Cc2263531", + "deployed_at": 0 } }, "dest_contracts": { - "Arbitrum Sepolia": { - "off_ramp": "0xDc2c7A3d8068C6F09F0F3648d24C84e372F6014d", - "commit_store": "0xb1aFb5cbE3c29b5Db71F21442BA9EfD450BC23C3", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, "Avalanche Fuji": { - "off_ramp": "0x1F350718e015EB20E5065C09F4A7a3f66888aEeD", - "commit_store": "0x98650A8EB59f75D93563aB34FcF603b1A30e4CBF", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" + "off_ramp": "0xCb2266c2118b1f30D15CBeB3a885531ABaA1b556", + "commit_store": "0x5Ded92E2CF71a8fF7644a67850F061c38B31BfB4", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Base Sepolia": { - "off_ramp": "0x0a750ca77369e03613d7640548F4b2b1c695c3Bb", - "commit_store": "0x8fEBC74C26129C8d7E60288C6dCCc75eb494aA3C", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Gnosis Chiado": { - "off_ramp": "0xCE2CE7F940B7c839384e5D7e079A6aE80e8AD6dB", - "commit_store": "0x1b9D78Ec1CEEC439F0b7eA6C428A1a607D9FA7e4", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Amoy": { - "off_ramp": "0xD667b5706592D0b040C78fEe5EE17D243b7dCB41", - "commit_store": "0x96101BA5250EE9295c193693C1e08A55bC593664", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" + "off_ramp": "0x960c62A491C30d0a60fD74a59d35B9C02697AdaA", + "commit_store": "0x06963745B3839B998288D1a46a46Ec25991A3D5E", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { - "off_ramp": "0x260AF9b83e0d2Bb6C9015fC9f0BfF8858A0CCE68", - "commit_store": "0x7a0bB92Bc8663abe6296d0162A9b41a2Cb2E0358", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "WeMix Testnet": { - "off_ramp": "0x9C08B7712af0344188aa5087D9e6aD0f47191037", - "commit_store": "0x4BE6DB0B884169a6A207fe5cad01eB4C025a13dB", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "Polygon Amoy": { - "is_native_fee_token": true, - "fee_token": "0x0Fd9e8d3aF1aaee056EB9e802c3A762a667b1904", - "bridge_tokens": [ - ], - "bridge_tokens_pools": [ - ], - "price_aggregators": null, - "arm": "0x50b023c5b33AEe5Adef15C2E95C2fEC690a52fa1", - "router": "0x9C32fCB86BF0f4a1A8921a9Fe46de3198bb884B2", - "price_registry": "0xfb2f2A207dC428da81fbAFfDDe121761f8Be1194", - "wrapped_native": "0x360ad4f9a9A8EFe9A8DCB5f461c4Cc1047E1Dcf9", - "src_contracts": { - "Avalanche Fuji": { - "on_ramp": "0x8Fb98b3837578aceEA32b454f3221FE18D7Ce903", - "deployed_at": 6004551 - }, - "BSC Testnet": { - "on_ramp": "0xC6683ac4a0F62803Bec89a5355B36495ddF2C38b", - "deployed_at": 6005330 - }, - "Gnosis Chiado": { - "on_ramp": "0x2331F6D614C9Fd613Ff59a1aB727f1EDf6c37A68", - "deployed_at": 6897885 - }, - "Optimism Sepolia": { - "on_ramp": "0xA52cDAeb43803A80B3c0C2296f5cFe57e695BE11", - "deployed_at": 6004902 - }, - "Sepolia Testnet": { - "on_ramp": "0x35347A2fC1f2a4c5Eae03339040d0b83b09e6FDA", - "deployed_at": 6004056 - }, - "WeMix Testnet": { - "on_ramp": "0x26546096F64B5eF9A1DcDAe70Df6F4f8c2E10C61", - "deployed_at": 6005611 - } - }, - "dest_contracts": { - "Avalanche Fuji": { - "off_ramp": "0xa733ce82a84335b2E9D864312225B0F3D5d80600", - "commit_store": "0x09B0F93fC2111aE439e853884173AC5b2F809885", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Testnet": { - "off_ramp": "0x948dfaa4842fc23e0e362Fe8D4396AaE4E6DF7EA", - "commit_store": "0x7F4e739D40E58BBd59dAD388171d18e37B26326f", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Gnosis Chiado": { - "off_ramp": "0x17c542a28e08AEF5697251601C7b2B621d153D42", - "commit_store": "0x811250c20fAB9a1b7ca245453aC214ba637fBEB5", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Optimism Sepolia": { - "off_ramp": "0xfFdE9E8c34A27BEBeaCcAcB7b3044A0A364455C9", - "commit_store": "0x74ED442ad211050e9C05Dc9A267E037E3d74A03B", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Sepolia Testnet": { - "off_ramp": "0xFb04129aD1EEDB741CC705ebC1978a7aB63e51f6", - "commit_store": "0x63f875240149d29136053C954Ca164a9BfA81F77", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "WeMix Testnet": { - "off_ramp": "0xdE8451E952Eb43350614839cCAA84f7C8701a09C", - "commit_store": "0xaCdaBa07ECad81dc634458b98673931DD9d3Bc14", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" + "off_ramp": "0x2aF9B10A5972D0c36f4d8F85773052c104E319B2", + "commit_store": "0x82FCF55b9e9bAb3066c2863F12a02bBc2Ba33F2F", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } }, "Sepolia Testnet": { "is_native_fee_token": true, - "fee_token": "0x779877A7B0D9E8603169DdbD7836e478b4624789", - "bridge_tokens": [ - ], - "bridge_tokens_pools": [ - ], - "price_aggregators": null, - "arm": "0xB4d360459F32Dd641Ef5A6985fFbAC5c4e5521aA", + "fee_token": "0x097D90c9d3E0B50Ca60e1ae45F6A81010f9FB534", + "arm": "0x27Da8735d8d1402cEc072C234759fbbB4dABBC4A", "router": "0x0BF3dE8c5D3e8A2B34D2BEeB17ABfCeBaf363A59", "price_registry": "0x9EF7D57a4ea30b9e37794E55b0C75F2A70275dCc", "wrapped_native": "0x097D90c9d3E0B50Ca60e1ae45F6A81010f9FB534", "src_contracts": { - "Arbitrum Sepolia": { - "on_ramp": "0xe4Dd3B16E09c016402585a8aDFdB4A18f772a07e", - "deployed_at": 5737506 - }, "Avalanche Fuji": { - "on_ramp": "0x0477cA0a35eE05D3f9f424d88bC0977ceCf339D4", - "deployed_at": 5944649 - }, - "BSC Testnet": { - "on_ramp": "0xD990f8aFA5BCB02f95eEd88ecB7C68f5998bD618", - "deployed_at": 5383500 + "on_ramp": "0x12492154714fBD28F28219f6fc4315d19de1025B", + "deployed_at": 0 }, "Base Sepolia": { - "on_ramp": "0x2B70a05320cB069e0fB55084D402343F832556E7", - "deployed_at": 5619657 - }, - "Gnosis Chiado": { - "on_ramp": "0x3E842E3A79A00AFdd03B52390B1caC6306Ea257E", - "deployed_at": 5386355 + "on_ramp": "0x8F35B097022135E0F46831f798a240Cc8c4b0B01", + "deployed_at": 0 }, "Optimism Sepolia": { - "on_ramp": "0x69CaB5A0a08a12BaFD8f5B195989D709E396Ed4d", - "deployed_at": 5937506 - }, - "Polygon Amoy": { - "on_ramp": "0x9f656e0361Fb5Df2ac446102c8aB31855B591692", - "deployed_at": 5723315 - }, - "WeMix Testnet": { - "on_ramp": "0xedFc22336Eb0B9B11Ff37C07777db27BCcDe3C65", - "deployed_at": 5393931 - }, - "celo-testnet-alfajores": { - "on_ramp": "0x3C86d16F52C10B2ff6696a0e1b8E0BcfCC085948", - "deployed_at": 5704643 - }, - "ethereum-testnet-sepolia-blast-1": { - "on_ramp": "0xDB75E9D9ca7577CcBd7232741be954cf26194a66", - "deployed_at": 6040848 - }, - "ethereum-testnet-sepolia-metis-1": { - "on_ramp": "0x1C4640914cd57c5f02a68048A0fbb0E12d904223", - "deployed_at": 6002793 - }, - "ethereum-testnet-sepolia-mode-1": { - "on_ramp": "0xc630fbD4D0F6AEB00aD0793FB827b54fBB78e981", - "deployed_at": 5970819 + "on_ramp": "0xACDfd7a98d853FA3914047Cd46e7f5D53BBC9FbB", + "deployed_at": 0 } }, "dest_contracts": { - "Arbitrum Sepolia": { - "off_ramp": "0xF18896AB20a09A29e64fdEbA99FDb8EC328f43b1", - "commit_store": "0x93Ff9Dd39Dc01eac1fc4d2c9211D95Ee458CAB94", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, "Avalanche Fuji": { - "off_ramp": "0x000b26f604eAadC3D874a4404bde6D64a97d95ca", - "commit_store": "0x2dD9273F8208B8393350508131270A6574A69784", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Testnet": { - "off_ramp": "0xdE2d8E126e08d675fCD7fFa5a6CE49925f3Dc692", - "commit_store": "0x0050ac355a82caB31194507f94174297bf0655A7", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" + "off_ramp": "0x1DEBa99dC8e2A77832461BD386d83D9FCb133137", + "commit_store": "0x139E06b6dBB1a0C41A1686C091795879c943765A", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Base Sepolia": { - "off_ramp": "0x31c0B81832B333419f0DfD36A69F502cF9094aed", - "commit_store": "0xDFcde9d698a2B32DB2537DC9B752Cadd1D846a52", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Gnosis Chiado": { - "off_ramp": "0x7db0115A0b3AAb01d30bf81123c5DD7B0C41Add5", - "commit_store": "0x6640723Ea801178c4383FA016b9781e7ef1016EF", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" + "off_ramp": "0x662738DC7DE4f7eC63d9f73Cdf9BeA5A58DdcC15", + "commit_store": "0x1e46bAC486Dd878cD57B62845530A52343e39693", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Optimism Sepolia": { - "off_ramp": "0xD50590D4438411EDe47029b0FD7901A7145E5Df6", - "commit_store": "0xe85EEE9Fd434A7b8a586Ee086E828abF41839479", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Amoy": { - "off_ramp": "0x5032cbC0C4aEeD25bb6E45D8B3fAF05DB0688C5d", - "commit_store": "0xe6201C9996Cc7B6E828E10CbE937E693d577D318", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "WeMix Testnet": { - "off_ramp": "0x46b639a3C1a4CBfD326b94a2dB7415c27157282f", - "commit_store": "0x7b74554678816b045c1e7409327E086bD436aa46", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "celo-testnet-alfajores": { - "off_ramp": "0xB435E0f73c18C5a12C324CA1d02F81F2C3e6e761", - "commit_store": "0xbc5d74957F171e75F92c8F0E1C317A25a56a416D", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "ethereum-testnet-sepolia-blast-1": { - "off_ramp": "0x4e897e5cF3aC307F0541B2151A88bCD781c153a3", - "commit_store": "0xB656652841F347178e193951C4663652aCe36B74", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "ethereum-testnet-sepolia-metis-1": { - "off_ramp": "0x4DB693A93E9d5196ECD42EC56CDEAe99dFC652ED", - "commit_store": "0xBfACd78F1412B6f93Ac23409bf456aFec1ABd845", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "ethereum-testnet-sepolia-mode-1": { - "off_ramp": "0xbEfd8D65F6643De54F0b1268A3bf4618ff85dcB4", - "commit_store": "0x0C161D3470b45Cc677661654C30ce4AdE6aCD288", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "WeMix Testnet": { - "is_native_fee_token": true, - "fee_token": "0x3580c7A817cCD41f7e02143BFa411D4EeAE78093", - "bridge_tokens": [ - ], - "bridge_tokens_pools": [ - ], - "price_aggregators": null, - "arm": "0x46fF31494651593973D9b38a872ED5B06f45A693", - "router": "0xA8C0c11bf64AF62CDCA6f93D3769B88BdD7cb93D", - "price_registry": "0x89D17571DB7C9540eeB36760E3c749C8fb984569", - "wrapped_native": "0xbE3686643c05f00eC46e73da594c78098F7a9Ae7", - "src_contracts": { - "Arbitrum Sepolia": { - "on_ramp": "0xA9DE3F7A617D67bC50c56baaCb9E0373C15EbfC6", - "deployed_at": 51216113 - }, - "Avalanche Fuji": { - "on_ramp": "0xC4aC84da458ba8e40210D2dF94C76E9a41f70069", - "deployed_at": 51214769 - }, - "BSC Testnet": { - "on_ramp": "0x5AD6eed6Be0ffaDCA4105050CF0E584D87E0c2F1", - "deployed_at": 51213771 - }, - "Kroma Sepolia": { - "on_ramp": "0x428C4dc89b6Bf908B82d77C9CBceA786ea8cc7D0", - "deployed_at": 51239062 - }, - "Optimism Sepolia": { - "on_ramp": "0x1961a7De751451F410391c251D4D4F98D71B767D", - "deployed_at": 51216748 - }, - "Polygon Amoy": { - "on_ramp": "0xd55148e841e76265B484d399eC71b7076ecB1216", - "deployed_at": 55378685 - }, - "Sepolia Testnet": { - "on_ramp": "0x4d57C6d8037C65fa66D6231844785a428310a735", - "deployed_at": 51239309 - } - }, - "dest_contracts": { - "Arbitrum Sepolia": { - "off_ramp": "0xeB1dFaB2464Bf0574D43e764E0c758f92e7ecAFb", - "commit_store": "0xcEaCa2B7890065c485f3E58657358a185Ad33791", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Avalanche Fuji": { - "off_ramp": "0x98e811Df9D2512f1aaf58D534607F583D6c54A4F", - "commit_store": "0x8e538351F6E5B2daF3c90C565C3738bca69a2716", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Testnet": { - "off_ramp": "0xB0e7f0fCcD3c961C473E7c44D939C1cDb4Cec1cB", - "commit_store": "0x4B56D8d53f1A6e0117B09700067De99581aA5542", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Kroma Sepolia": { - "off_ramp": "0xD685D2d224dd6D0Db2D56497db6270D77D9a7966", - "commit_store": "0x7e062D6880779a0347e7742058C1b1Ee4AA0B137", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Optimism Sepolia": { - "off_ramp": "0xA5f97Bc69Bf06e7C37B93265c5457420A92c5F4b", - "commit_store": "0xd48b9213583074f518D8f4336FDf35370D450132", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Amoy": { - "off_ramp": "0x6c8f5999B06FDE17B11E4e3C1062b761766F960f", - "commit_store": "0x957c3c2056192e58A8485eF31165fC490d474239", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Sepolia Testnet": { - "off_ramp": "0x8AB103843ED9D28D2C5DAf5FdB9c3e1CE2B6c876", - "commit_store": "0x7d5297c5506ee2A7Ef121Da9bE02b6a6AD30b392", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "celo-testnet-alfajores": { - "is_native_fee_token": true, - "fee_token": "0x32E08557B14FaD8908025619797221281D439071", - "bridge_tokens": [ - ], - "bridge_tokens_pools": [ - ], - "price_aggregators": null, - "arm": "0xbE8FD4b84ca8CC2cFAeeEf8dc1388E44860eeEeb", - "router": "0xb00E95b773528E2Ea724DB06B75113F239D15Dca", - "price_registry": "0x8F048206D11B2c69b8963E2EBd5968D141e022f4", - "wrapped_native": "0x99604d0e2EfE7ABFb58BdE565b5330Bb46Ab3Dca", - "src_contracts": { - "Sepolia Testnet": { - "on_ramp": "0x16a020c4bbdE363FaB8481262D30516AdbcfcFc8", - "deployed_at": 23561364 - } - }, - "dest_contracts": { - "Sepolia Testnet": { - "off_ramp": "0xa1b97F92D806BA040daf419AFC2765DC723683a4", - "commit_store": "0xcd92C0599Ac515e7588865cC45Eee21A74816aFc", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "ethereum-testnet-sepolia-blast-1": { - "is_native_fee_token": true, - "fee_token": "0x02c359ebf98fc8BF793F970F9B8302bb373BdF32", - "bridge_tokens": [ - ], - "bridge_tokens_pools": [ - ], - "price_aggregators": null, - "arm": "0x9C32fCB86BF0f4a1A8921a9Fe46de3198bb884B2", - "router": "0xfb2f2A207dC428da81fbAFfDDe121761f8Be1194", - "price_registry": "0xc8acE9dF450FaD007755C6C9AB4f0e9c8626E29C", - "wrapped_native": "0x4200000000000000000000000000000000000023", - "src_contracts": { - "Sepolia Testnet": { - "on_ramp": "0x85Ef19FC4C63c70744995DC38CAAEC185E0c619f", - "deployed_at": 6429339 - } - }, - "dest_contracts": { - "Sepolia Testnet": { - "off_ramp": "0x92cD24C278D34C726f377703E50875d8f9535dC2", - "commit_store": "0xcE1b4D50CeD56850182Bd58Ace91171cB249B873", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "ethereum-testnet-sepolia-metis-1": { - "is_native_fee_token": true, - "fee_token": "0x9870D6a0e05F867EAAe696e106741843F7fD116D", - "bridge_tokens": [ - ], - "bridge_tokens_pools": [ - ], - "price_aggregators": null, - "arm": "0x26546096F64B5eF9A1DcDAe70Df6F4f8c2E10C61", - "router": "0xaCdaBa07ECad81dc634458b98673931DD9d3Bc14", - "price_registry": "0x5DCE866b3ae6E0Ed153f0e149D7203A1B266cdF5", - "wrapped_native": "0x5c48e07062aC4E2Cf4b9A768a711Aef18e8fbdA0", - "src_contracts": { - "Sepolia Testnet": { - "on_ramp": "0x2Eff2d1BF5C557d6289D208a7a43608f5E3FeCc2", - "deployed_at": 858864 - } - }, - "dest_contracts": { - "Sepolia Testnet": { - "off_ramp": "0x9Bb7e398ef9Acfe9cA584C39B1E233Cba62BB9f7", - "commit_store": "0x1F4B82cDebaC5e3a0Dd53183D47e51808B4a64cB", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "ethereum-testnet-sepolia-mode-1": { - "is_native_fee_token": true, - "fee_token": "0x925a4bfE64AE2bFAC8a02b35F78e60C29743755d", - "bridge_tokens": [ - ], - "bridge_tokens_pools": [ - ], - "price_aggregators": null, - "arm": "0x11545812A8d64e4A3A0Ec36b6F70D87b42Ce4a01", - "router": "0xc49ec0eB4beb48B8Da4cceC51AA9A5bD0D0A4c43", - "price_registry": "0xa733ce82a84335b2E9D864312225B0F3D5d80600", - "wrapped_native": "0x4200000000000000000000000000000000000006", - "src_contracts": { - "Base Sepolia": { - "on_ramp": "0x73f7E074bd7291706a0C5412f51DB46441B1aDCB", - "deployed_at": 14359909 - }, - "Sepolia Testnet": { - "on_ramp": "0xfFdE9E8c34A27BEBeaCcAcB7b3044A0A364455C9", - "deployed_at": 14359680 - } - }, - "dest_contracts": { - "Base Sepolia": { - "off_ramp": "0x137a38c6b1Ad20101F93516aB2159Df525309168", - "commit_store": "0x8F43d867969F14619895d71E0A5b89E0bb20bF70", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Sepolia Testnet": { - "off_ramp": "0xcD44cec849B6a8eBd5551D6DFeEcA452257Dfe4d", - "commit_store": "0xbA66f08733E6715D33edDfb5a5947676bb45d0e0", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" + "off_ramp": "0xbfa6f6AAE31acB3A285e80026d6475C1a50d1d0F", + "commit_store": "0xB5FbA97Dc61ec68771a92a15360d9C32c9d054E7", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } } @@ -901,26 +172,20 @@ Data = """ """ [CCIP.Env] -TTL = '8h' +TTL = '2h' [CCIP.Env.Network] selected_networks = [ - 'ARBITRUM_SEPOLIA', - 'AVALANCHE_FUJI', - 'OPTIMISM_SEPOLIA', - 'BASE_SEPOLIA', - 'BSC_TESTNET', - 'WEMIX_TESTNET', - 'SEPOLIA', - 'POLYGON_AMOY', - 'KROMA_SEPOLIA', - 'BLAST_SEPOLIA' + 'AVALANCHE_FUJI', + 'OPTIMISM_SEPOLIA', + 'BASE_SEPOLIA', + 'SEPOLIA', ] [CCIP.Groups.load] NetworkPairs = [ - 'AVALANCHE_FUJI,SEPOLIA', - 'OPTIMISM_SEPOLIA,BASE_SEPOLIA' + 'AVALANCHE_FUJI,SEPOLIA', + 'OPTIMISM_SEPOLIA,BASE_SEPOLIA' ] BiDirectionalLane = true @@ -929,15 +194,21 @@ ExistingDeployment = true NoOfTokensPerChain = 1 +# 1msg/5sec = 12msg/min [CCIP.Groups.load.LoadProfile] -RequestPerUnitTime = [1] -TimeUnit = '5s' +RequestPerUnitTime = [12] +TimeUnit = '1m' TestDuration = '1h' TestRunName = 'ccip-prod-testnet-stress' +# There is slower exec rounds in Sepolia/Ethereum, therefore reducing the frequency +# 1msg/12sec = 5msg/min +[CCIP.Groups.load.LoadProfile.FrequencyByDestination.sepolia-testnet] +RequestPerUnitTime = [5] + # to represent 20%, 60%, 15%, 5% of the total messages [CCIP.Groups.load.LoadProfile.MsgProfile] -Frequencies = [4,12,3,1] +Frequencies = [4, 12, 3, 1] [[CCIP.Groups.load.LoadProfile.MsgProfile.MsgDetails]] MsgType = 'Token' diff --git a/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/smoke-release-testing_native.toml b/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/smoke-release-testing_native.toml index 24e7cbc9c88..6281274eacf 100644 --- a/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/smoke-release-testing_native.toml +++ b/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/smoke-release-testing_native.toml @@ -14,71 +14,74 @@ Data = """ "Arbitrum Sepolia": { "is_native_fee_token": true, "fee_token": "0xE591bf0A0CF924A0674d7792db046B23CEbF5f34", - "bridge_tokens": [ - "0xA8C0c11bf64AF62CDCA6f93D3769B88BdD7cb93D" - ], - "bridge_tokens_pools": [ - "0x99685281Ec520a003F1A726A5a8078c2124c1477" - ], "arm": "0xbcBDf0aDEDC9a33ED5338Bdb4B6F7CE664DC2e8B", "router": "0x2a9C5afB0d0e4BAb2BCdaE109EC4b0c4Be15a165", "price_registry": "0x89D5b13908b9063abCC6791dc724bF7B7c93634C", "wrapped_native": "0xE591bf0A0CF924A0674d7792db046B23CEbF5f34", "src_contracts": { "Avalanche Fuji": { - "on_ramp": "0x1Cb56374296ED19E86F68fA437ee679FD7798DaA", + "on_ramp": "0x20C8c9F13C6AA402F2545AD15fB7a9CdE9108618", "deployed_at": 0 }, "Base Sepolia": { - "on_ramp": "0x7854E73C73e7F9bb5b0D5B4861E997f4C6E8dcC6", + "on_ramp": "0xF1623862e4c9f9Fba1Ac0181C4fF53B4f958F065", "deployed_at": 0 }, "Gnosis Chiado": { - "on_ramp": "0x973CbE752258D32AE82b60CD1CB656Eebb588dF0", + "on_ramp": "0xEfe02eB139D2A82e38184d28E3b65bb176F26ebD", + "deployed_at": 0 + }, + "Metis Sepolia": { + "on_ramp": "0x46a79a6a4B07FD3FC14ea8299A99FE29576776E2", "deployed_at": 0 }, "Optimism Sepolia": { - "on_ramp": "0x701Fe16916dd21EFE2f535CA59611D818B017877", + "on_ramp": "0x0B0c08Bb2fA2EbDe25817009ee39eA1ad9bCaC58", "deployed_at": 0 }, "Sepolia Testnet": { - "on_ramp": "0x4205E1Ca0202A248A5D42F5975A8FE56F3E302e9", + "on_ramp": "0x64d78F20aD987c7D52FdCB8FB0777bD00de53210", "deployed_at": 0 }, "WeMix Testnet": { - "on_ramp": "0xBD4106fBE4699FE212A34Cc21b10BFf22b02d959", + "on_ramp": "0x2F3Daf77A663603826c7750E956b6555DE6f8250", "deployed_at": 0 } }, "dest_contracts": { "Avalanche Fuji": { - "off_ramp": "0xcab0EF91Bee323d1A617c0a027eE753aFd6997E4", - "commit_store": "0x0d90b9b96cBFa0D01635ce12982ccE1b70827c7a", + "off_ramp": "0x7245a5947E2F32B66aF74F4dAF91718ea19afaDf", + "commit_store": "0x490AC77BbB26f4FFf876Ded07bCAE6DBe685be98", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Base Sepolia": { - "off_ramp": "0xc1982985720B959E66c19b64F783361Eb9B60F26", - "commit_store": "0x28F66bB336f6db713d6ad2a3bd1B7a531282A159", + "off_ramp": "0xF2aB55Ed448A6fAD75013900568B6a927f52e5e0", + "commit_store": "0x833E5995A7422120f445f9B8dD1b9BD1037c68E5", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Gnosis Chiado": { - "off_ramp": "0x935C26F9a9122E5F9a27f2d3803e74c75B94f5a3", - "commit_store": "0xEdb963Ec5c2E5AbdFdCF137eF44A445a7fa4787A", + "off_ramp": "0xc1Cb31493fB2386aDC1Ea01F935F2bd8a8dCA388", + "commit_store": "0xe21896657A65c8959F16E1c3Ee5713E85d9EA020", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Metis Sepolia": { + "off_ramp": "0xc47143147Fd62A09618C695c7C03714aCe8db1Cf", + "commit_store": "0x2F42e7B22eE5885158916624Ff00608f4C82313D", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Optimism Sepolia": { - "off_ramp": "0xfD404A89e1d195F0c65be1A9042C77745197659e", - "commit_store": "0x84B7B012c95f8A152B44Ab3e952f2dEE424fA8e1", + "off_ramp": "0x4a7E91EF68758aaC66AeD656267bbCD0f9b6c019", + "commit_store": "0xb0A09D6A15FF7A0142DF3F62b2C4D1e11D763Ed0", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { - "off_ramp": "0x1c71f141b4630EBE52d6aF4894812960abE207eB", - "commit_store": "0xaB0c8Ba51E7Fa3E5693a4Fbb39473520FD85d173", + "off_ramp": "0xBed6e9131916d724418C8a6FE810F727302a5c00", + "commit_store": "0xdDb61B6bDa1B46d88f556440fABFe219F6da4F3a", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "WeMix Testnet": { - "off_ramp": "0x262e16C8D42aa07bE13e58F81e7D9F62F6DE2830", - "commit_store": "0xc132eFAf929299E5ee704Fa6D9796CFa23Bb8b2C", + "off_ramp": "0x11d486E92d291704D1E25cDbAeee687237247826", + "commit_store": "0xece9353095aC79Db9DD5bf2022690Fa6BffeBCAc", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -86,89 +89,83 @@ Data = """ "Avalanche Fuji": { "is_native_fee_token": true, "fee_token": "0xd00ae08403B9bbb9124bB305C09058E32C39A48c", - "bridge_tokens": [ - "0xD21341536c5cF5EB1bcb58f6723cE26e8D8E90e4" - ], - "bridge_tokens_pools": [ - "0xEC1062cbDf4fBf31B3A6Aac62B6F6F123bb70E12" - ], "arm": "0x7e28DD790214139798446A121cFe950B51304684", "router": "0xF694E193200268f9a4868e4Aa017A0118C9a8177", "price_registry": "0x19e157E5fb1DAec1aE4BaB113fdf077F980704AA", "wrapped_native": "0xd00ae08403B9bbb9124bB305C09058E32C39A48c", "src_contracts": { "Arbitrum Sepolia": { - "on_ramp": "0x8bB16BEDbFd62D1f905ACe8DBBF2954c8EEB4f66", + "on_ramp": "0xa9946BA30DAeC98745755e4410d6e8E894Edc53B", "deployed_at": 0 }, "BSC Testnet": { - "on_ramp": "0xF25ECF1Aad9B2E43EDc2960cF66f325783245535", + "on_ramp": "0x906BC7D10947A94ba0252e8C2E34868A466c03ED", "deployed_at": 0 }, "Base Sepolia": { - "on_ramp": "0x1A674645f3EB4147543FCA7d40C5719cbd997362", + "on_ramp": "0x0aEc1AC9F6D0c21332d7a66dDF1Fbcb32cF3B0B3", "deployed_at": 0 }, "Gnosis Chiado": { - "on_ramp": "0x1532e5b204ee2b2244170c78E743CB9c168F4DF9", + "on_ramp": "0x3dda45E731EC1db18B95651d1AF1868aa878468D", "deployed_at": 0 }, "Optimism Sepolia": { - "on_ramp": "0xC334DE5b020e056d0fE766dE46e8d9f306Ffa1E2", + "on_ramp": "0x2a9EFdc9F93D9b822129038EFCa4B63Adf3f7FB5", "deployed_at": 0 }, "Polygon Amoy": { - "on_ramp": "0x610F76A35E17DA4542518D85FfEa12645eF111Fc", + "on_ramp": "0xA82b9ACAcFA6FaB1FD721e7a748A30E3001351F9", "deployed_at": 0 }, "Sepolia Testnet": { - "on_ramp": "0x5724B4Cc39a9690135F7273b44Dfd3BA6c0c69aD", + "on_ramp": "0x75b9a75Ee1fFef6BE7c4F842a041De7c6153CF4E", "deployed_at": 0 }, "WeMix Testnet": { - "on_ramp": "0x677B5ab5C8522d929166c064d5700F147b15fa33", + "on_ramp": "0x1ff99E67986E83bb5BA34143BaA2735853e5738c", "deployed_at": 0 } }, "dest_contracts": { "Arbitrum Sepolia": { - "off_ramp": "0x90A74072e7B0c2d59e13aB4d8f93c8198c413194", - "commit_store": "0xf3458CFd2fdf4a6CF0Ce296d520DD21eB194828b", + "off_ramp": "0xd88CBA0612f2Ce611BF6d073A94C8FD7E70B4fBd", + "commit_store": "0x9b8279E352bC167F714eef96A4C436bE996643cE", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "BSC Testnet": { - "off_ramp": "0x10b28009E5D776F1f5AAA73941CE8953B8f42d26", - "commit_store": "0xacDD582F271eCF22FAd6764cCDe1c4a534b732A8", + "off_ramp": "0x9c40A73F5C7454BB7C178AFa56Ee30bFB2DCf7E6", + "commit_store": "0xE5611af1d63340b711B0468a976651Fb79B17870", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Base Sepolia": { - "off_ramp": "0xdBdE8510226d1E060A3bf982b67705C67f5697e2", - "commit_store": "0x8Ee73BC9492b4182D289E5C1e66e40CD876CC00F", + "off_ramp": "0xf8de9d5924CFD28e31a53B63B4903436D9818d69", + "commit_store": "0xDD7CfECE1bb4e8aC2E8b8281CFE1D44247119471", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Gnosis Chiado": { - "off_ramp": "0x56dF55aF5F0A4689f3364230587a68eD6A314fAd", - "commit_store": "0xabA7ff98094c4cc7A075812EefF2CD21f6400235", + "off_ramp": "0x3F5035039C23cDAF032C64c084Dc70F811E62ddD", + "commit_store": "0xf5B0245c7B9e15f0cB0B85FF2B6799a45D61CbaA", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Optimism Sepolia": { - "off_ramp": "0x3d7CbC95DCC33257F14D6Eb780c88Bd56C6335BB", - "commit_store": "0x1fcDC02edDfb405f378ba53cF9E6104feBcB7542", + "off_ramp": "0x1DF9D94C6916918C935E60d2Cb4Ed265Bf778005", + "commit_store": "0xE7eeBE5882609d28C015d0A89DE1ba4f506F4a03", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Polygon Amoy": { - "off_ramp": "0x3e33290B90fD0FF30a3FA138934DF028E4eCA348", - "commit_store": "0xCFe3556Aa42d40be09BD23aa80448a19443BE5B1", + "off_ramp": "0xbeD7F478Ef5627FB2B891fDA29Ca0131f6796D9D", + "commit_store": "0x27a319f58c01380056c86938798aCEAA1AC529e2", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { - "off_ramp": "0x9e5e4324F8608D54A50a317832d456a392E4F8C2", - "commit_store": "0x92A51eD3F041B39EbD1e464C1f7cb1e8f8A8c63f", + "off_ramp": "0x01e3D835b4C4697D7F81B9d7Abc89A6E478E4a2f", + "commit_store": "0x4EC313c1Eb620432f42FB5f4Df27f8A566523c1C", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "WeMix Testnet": { - "off_ramp": "0xD0D338318bC6837b091FC7AB5F2a94B7783507d5", - "commit_store": "0xd9D479208235c7355848ff4aF26eB5aacfDC30c6", + "off_ramp": "0x15CcAbf0e3484D4872e25b883163D8cB724d4832", + "commit_store": "0x859f3477B7b4ECc19aDD8cCb19740932F21bD76b", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -176,71 +173,74 @@ Data = """ "BSC Testnet": { "is_native_fee_token": true, "fee_token": "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd", - "bridge_tokens": [ - "0xbFA2ACd33ED6EEc0ed3Cc06bF1ac38d22b36B9e9" - ], - "bridge_tokens_pools": [ - "0x31eDe84776DA37e2404eE88d71c234e92cB672e5" - ], "arm": "0x7D899D26F2E94fFcd4b440C3008B0C6BEfcD3cca", "router": "0xE1053aE1857476f36A3C62580FF9b016E8EE8F6f", "price_registry": "0xCCDf022c9d31DC26Ebab4FB92432724a5b79809a", "wrapped_native": "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd", "src_contracts": { "Avalanche Fuji": { - "on_ramp": "0xa2515683E99F50ADbE177519A46bb20FfdBaA5de", + "on_ramp": "0x2A6f8Ed2e7b222163ef6EcC2327171B479399ab2", "deployed_at": 0 }, "Base Sepolia": { - "on_ramp": "0x3E807220Ca84b997c0d1928162227b46C618e0c5", + "on_ramp": "0x97856Bf888F6eEDBBd322B28133BCcF9CA9038f6", + "deployed_at": 0 + }, + "Blast Sepolia": { + "on_ramp": "0xd0049BfFc8e2689Df9236FfA393Ccbf7eae4FbbC", "deployed_at": 0 }, "Gnosis Chiado": { - "on_ramp": "0x8735f991d41eA9cA9D2CC75cD201e4B7C866E63e", + "on_ramp": "0x98dEa9e498F2A7aF6c74C915c88A17FbA09b73C2", "deployed_at": 0 }, "Polygon Amoy": { - "on_ramp": "0xf37CcbfC04adc1B56a46B36F811D52C744a1AF78", + "on_ramp": "0x363EB789fE31F08547a847D8C38d9b55C7Cf1903", "deployed_at": 0 }, "Sepolia Testnet": { - "on_ramp": "0xB1DE44B04C00eaFe9915a3C07a0CaeA4410537dF", + "on_ramp": "0xC1C6438D60AbE9bF4b1F10460184CE9bD312e328", "deployed_at": 0 }, "WeMix Testnet": { - "on_ramp": "0x89268Afc1BEA0782a27ba84124E3F42b196af927", + "on_ramp": "0xbc85704EDb79ea84E9D3C18965F7f6A16B0a0440", "deployed_at": 0 } }, "dest_contracts": { "Avalanche Fuji": { - "off_ramp": "0x6e6fFCb6B4BED91ff0CC8C2e57EC029dA7DB80C2", - "commit_store": "0x38Bc38Bd824b6eE87571f9D3CFbe6D6E28E3Dc62", + "off_ramp": "0x95b66acfaaDF122f4EccE52C0aD4Fd997DD1150C", + "commit_store": "0x3af04b1c1e79A6B8A4577Bb47EC33eD2E66AeB47", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Base Sepolia": { - "off_ramp": "0x2C61FD7E93Dc79422861282145c59B56dFbc3a8c", - "commit_store": "0x42fAe5B3605804CF6d08632d7A25864e24F792Ae", + "off_ramp": "0x0a5147e1Ac38C79c77031194ef64C8B5353F6EE9", + "commit_store": "0x103864D60b33a479EA7D0e23a37e0ce07198f0A9", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Blast Sepolia": { + "off_ramp": "0xe1e8473218acCB82FBc24Ccd3C5D2dF166cd04f3", + "commit_store": "0x020B047A5Ca88fDB1ad3bAD9A082760fC7F770b6", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Gnosis Chiado": { - "off_ramp": "0x71a44a60832B0F8B63232C9516e7E6aEc3A373Dc", - "commit_store": "0xAC24299a91b72d1Cb5B31147e3CF54964D896974", + "off_ramp": "0x1F7FEBCBb10420E039C333A60A444c1a442d826C", + "commit_store": "0x23Ae763a64D39d6038431a64Bbc4A670C89d82b9", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Polygon Amoy": { - "off_ramp": "0x63440C7747d37bc6154b5538AE32b54FE0965AfA", - "commit_store": "0xAD22fA198CECfC534927aE1D480c460d5bB3460F", + "off_ramp": "0xAAe325adbc9C5a28e4e94Fef170D55de2CA9aA01", + "commit_store": "0xD173Df3A1b23ec42eA5C4669b9c956Bef230efd1", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { - "off_ramp": "0xf1c128Fe52Ea78CcAAB407509292E61ce38C1523", - "commit_store": "0x59dFD870dC4bd76A7B879A4f705Fdcd2595f85f9", + "off_ramp": "0xB513523aee87f838e78b32d2Bacaaf2e94D9f0f9", + "commit_store": "0x21A49164890576504C1f1c4DC9442c42C98771D7", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "WeMix Testnet": { - "off_ramp": "0xfd9B19c3725da5B517aA705B848ff3f21F98280e", - "commit_store": "0x3c1F1412563188aBc8FE3fd53E8F1Cb601CaB4f9", + "off_ramp": "0xc985571900DCa62387f93F882AB550472531f5DB", + "commit_store": "0xac5DACfAb1a512E33c49EFE42502863FC1a4BAB3", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -248,80 +248,74 @@ Data = """ "Base Sepolia": { "is_native_fee_token": true, "fee_token": "0x4200000000000000000000000000000000000006", - "bridge_tokens": [ - "0x88A2d74F47a237a62e7A51cdDa67270CE381555e" - ], - "bridge_tokens_pools": [ - "0x875207858c691F192C606068f417dCf666b2EC6B" - ], "arm": "0x7827dD0481EE18DB646bD250d20A8eA43da52146", "router": "0xD3b06cEbF099CE7DA4AcCf578aaebFDBd6e88a93", "price_registry": "0x4D20536e60832bE579Cd38E89Dc03d11E1741FbA", "wrapped_native": "0x4200000000000000000000000000000000000006", "src_contracts": { "Arbitrum Sepolia": { - "on_ramp": "0x58622a80c6DdDc072F2b527a99BE1D0934eb2b50", + "on_ramp": "0xb52eF669d3fCeBee1f31418Facc02a16A6F6B0e5", "deployed_at": 0 }, "Avalanche Fuji": { - "on_ramp": "0xAbA09a1b7b9f13E05A6241292a66793Ec7d43357", + "on_ramp": "0x212e8Fd9cCC330ab54E8141FA7d33967eF1eDafF", "deployed_at": 0 }, "BSC Testnet": { - "on_ramp": "0xD806966beAB5A3C75E5B90CDA4a6922C6A9F0c9d", + "on_ramp": "0xd54B44811AE99a18Cb95B4704ba04a65C0163751", "deployed_at": 0 }, "Gnosis Chiado": { - "on_ramp": "0x2Eff2d1BF5C557d6289D208a7a43608f5E3FeCc2", + "on_ramp": "0xdd0Ee1F20E93a93634AAcE56105E19423881Df56", "deployed_at": 0 }, "Mode Sepolia": { - "on_ramp": "0x3d0115386C01436870a2c47e6297962284E70BA6", + "on_ramp": "0xc59689dFDEF9D953cEFbb58912b304bb38408476", "deployed_at": 0 }, "Optimism Sepolia": { - "on_ramp": "0x3b39Cd9599137f892Ad57A4f54158198D445D147", + "on_ramp": "0x2945D35F428CE564F5455AD0AF28BDFCa67e76Ab", "deployed_at": 0 }, "Sepolia Testnet": { - "on_ramp": "0x6486906bB2d85A6c0cCEf2A2831C11A2059ebfea", + "on_ramp": "0x29A1F4ecE9246F0042A9062FB89803fA8B1830cB", "deployed_at": 0 } }, "dest_contracts": { "Arbitrum Sepolia": { - "off_ramp": "0xd364C06ac99a82a00d3eFF9F2F78E4Abe4b9baAA", - "commit_store": "0xdE8d0f47a71eA3fDFBD3162271652f2847939097", + "off_ramp": "0x814E735c5DD19240c85E2513DD926Bc3a39f7140", + "commit_store": "0xFc24B204bfA5C65eD8e2Fc02fDe4FeCb62eA8Ac5", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Avalanche Fuji": { - "off_ramp": "0xAd91214efFee446500940c764DF77AF18427294F", - "commit_store": "0x1242b6c5e0e349b8d4BCf0938f961C4B4f7EA3Fa", + "off_ramp": "0x3Ab3a3d35cAC95FfcFCcc127eF01eA8D87b0A64e", + "commit_store": "0x51313B8C068B5227fa7364E6eCB1382Fb751976F", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "BSC Testnet": { - "off_ramp": "0xd5E9508921434e8758f4540D55c1c066b7cc1598", - "commit_store": "0x1a86b29364D1B3fA3386329A361aA98A104b2742", + "off_ramp": "0x827CF69409307Cd4c979e652894C297ad5124ab7", + "commit_store": "0x547eBe6077305c3fdF8dA66c66cc14b0779CE00C", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Gnosis Chiado": { - "off_ramp": "0x9Bb7e398ef9Acfe9cA584C39B1E233Cba62BB9f7", - "commit_store": "0x1F4B82cDebaC5e3a0Dd53183D47e51808B4a64cB", + "off_ramp": "0x8bB08Bc19771C69E739a2078894523b3DC05a05e", + "commit_store": "0xf163Da63bDB8b9C355d41C755E03125988650109", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Mode Sepolia": { - "off_ramp": "0xB26647A23e8b4284375e5C74b77c9557aE709D03", - "commit_store": "0x4b4fEB401d3E613e1D6242E155C83A80BF9ac2C9", + "off_ramp": "0x11E16c71D76E43acbcb496A70966380d905B1E32", + "commit_store": "0xEe19f039FaE3EF0F94971f0B7B187223D952ac13", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Optimism Sepolia": { - "off_ramp": "0x86a3910908eCaAA31Fcd9F0fC8841D8E98f1511d", - "commit_store": "0xE99a87C9b5ed4D2b6060195DEea5106ffF655736", + "off_ramp": "0x8718d1cc138421Dbc1B489CB7884FF68DE7ad867", + "commit_store": "0x3291D453c880E5b59EEd04E600c85268Cd378b7f", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { - "off_ramp": "0x189F61D9B886Dd2975D5Abc893c8Cf5f5effda71", - "commit_store": "0xEE7e27346DCD1e711348D0F7f7ECB53a9a3a08a7", + "off_ramp": "0x0ecA23Ef70B828fEDd0A84d2692cB0527B52396A", + "commit_store": "0xA7F84Ec616F8e9Fa593339944E76bda90A9737fE", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -329,26 +323,29 @@ Data = """ "Blast Sepolia": { "is_native_fee_token": true, "fee_token": "0x4200000000000000000000000000000000000023", - "bridge_tokens": [ - "0x8D122C3e8ce9C8B62b87d3551bDfD8C259Bb0771" - ], - "bridge_tokens_pools": [ - "0xFb04129aD1EEDB741CC705ebC1978a7aB63e51f6" - ], "arm": "0x09c1Ed4b112Fb33e594F2aACfEF407e2F14d7F9b", "router": "0xfb2f2A207dC428da81fbAFfDDe121761f8Be1194", "price_registry": "0xc8acE9dF450FaD007755C6C9AB4f0e9c8626E29C", "wrapped_native": "0x4200000000000000000000000000000000000023", "src_contracts": { + "BSC Testnet": { + "on_ramp": "0x6eA6f63b689b5597A0C06a5Eb8DcDFD86383857A", + "deployed_at": 0 + }, "Sepolia Testnet": { - "on_ramp": "0x85Ef19FC4C63c70744995DC38CAAEC185E0c619f", + "on_ramp": "0x154aDEF773a848da8229D81De73a7b0844400ebd", "deployed_at": 0 } }, "dest_contracts": { + "BSC Testnet": { + "off_ramp": "0xd9dE4aCD27E814bfe70CA33d2A4d079e740626Bd", + "commit_store": "0xe8fF7e22c54f76F453d6072A9d3a12B1D9AbA137", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, "Sepolia Testnet": { - "off_ramp": "0x92cD24C278D34C726f377703E50875d8f9535dC2", - "commit_store": "0xcE1b4D50CeD56850182Bd58Ace91171cB249B873", + "off_ramp": "0x46DD4e3e2b8a18409646F1C15bf3799a481e67f6", + "commit_store": "0x8250f9E992dda66791dd8b5d356B867ae53382cF", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -356,26 +353,20 @@ Data = """ "Celo Alfajores": { "is_native_fee_token": true, "fee_token": "0x99604d0e2EfE7ABFb58BdE565b5330Bb46Ab3Dca", - "bridge_tokens": [ - "0x7e503dd1dAF90117A1b79953321043d9E6815C72" - ], - "bridge_tokens_pools": [ - "0xC6683ac4a0F62803Bec89a5355B36495ddF2C38b" - ], "arm": "0xEbe35aA4F5e707485484c992AF2069a457b9bBB1", "router": "0xb00E95b773528E2Ea724DB06B75113F239D15Dca", "price_registry": "0x8F048206D11B2c69b8963E2EBd5968D141e022f4", "wrapped_native": "0x99604d0e2EfE7ABFb58BdE565b5330Bb46Ab3Dca", "src_contracts": { "Sepolia Testnet": { - "on_ramp": "0x16a020c4bbdE363FaB8481262D30516AdbcfcFc8", + "on_ramp": "0x68A4f57A499563192C606a898BAf503A43fcDB4D", "deployed_at": 0 } }, "dest_contracts": { "Sepolia Testnet": { - "off_ramp": "0xa1b97F92D806BA040daf419AFC2765DC723683a4", - "commit_store": "0xcd92C0599Ac515e7588865cC45Eee21A74816aFc", + "off_ramp": "0xF6dB68333D14f6a0c1123cc420ea60980aEDA0Eb", + "commit_store": "0x8f9B63c40891CdF7d1C795625d4260a29bE2bBa0", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -383,80 +374,74 @@ Data = """ "Gnosis Chiado": { "is_native_fee_token": true, "fee_token": "0x18c8a7ec7897177E4529065a7E7B0878358B3BfF", - "bridge_tokens": [ - "0xA189971a2c5AcA0DFC5Ee7a2C44a2Ae27b3CF389" - ], - "bridge_tokens_pools": [ - "0xF9a21B587111e7E8745Fb8b13750014f19DB0014" - ], "arm": "0xfE4fB161D870D0F672Ed9C5A898569603f77983F", "router": "0x19b1bac554111517831ACadc0FD119D23Bb14391", "price_registry": "0x2F4ACd1f8986c6B1788159C4c9a5fC3fceCCE363", "wrapped_native": "0x18c8a7ec7897177E4529065a7E7B0878358B3BfF", "src_contracts": { "Arbitrum Sepolia": { - "on_ramp": "0x473b49fb592B54a4BfCD55d40E048431982879C9", + "on_ramp": "0x94967Ea06C6543Aaba5B90C52B655003ef82e521", "deployed_at": 0 }, "Avalanche Fuji": { - "on_ramp": "0x610F76A35E17DA4542518D85FfEa12645eF111Fc", + "on_ramp": "0x4f3576585e7fCCE5Fc502Bcf3CAdaD22E1194834", "deployed_at": 0 }, "BSC Testnet": { - "on_ramp": "0xE48E6AA1fc7D0411acEA95F8C6CaD972A37721D4", + "on_ramp": "0xB2642B54580140C375c9024e273C575a5f53d02d", "deployed_at": 0 }, "Base Sepolia": { - "on_ramp": "0x41b4A51cAfb699D9504E89d19D71F92E886028a8", + "on_ramp": "0x0E9504907be794620229C196F82CB062A66B7480", "deployed_at": 0 }, "Optimism Sepolia": { - "on_ramp": "0xAae733212981e06D9C978Eb5148F8af03F54b6EF", + "on_ramp": "0xeb86B5b6f5C66eCb58e4Cf98E607b238126505DC", "deployed_at": 0 }, "Polygon Amoy": { - "on_ramp": "0x01800fCDd892e37f7829937271840A6F041bE62E", + "on_ramp": "0xd86F5DF82A2500137Ddeef963028d60E3b5A354D", "deployed_at": 0 }, "Sepolia Testnet": { - "on_ramp": "0x4ac7FBEc2A7298AbDf0E0F4fDC45015836C4bAFe", + "on_ramp": "0x03691D63C687D09368360e957AFB2F7B4d1651d4", "deployed_at": 0 } }, "dest_contracts": { "Arbitrum Sepolia": { - "off_ramp": "0x9aA82DBB53bf02096B771D40e9432A323a78fB26", - "commit_store": "0x5CdbA91aBC0cD81FC56bc10Ad1835C9E5fB38e5F", + "off_ramp": "0x3633Cce99186217d4C7ed64FD455d218b8Cd5D4c", + "commit_store": "0x6e096286548451828c97F1B3E49C402a4934F39a", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Avalanche Fuji": { - "off_ramp": "0x3e33290B90fD0FF30a3FA138934DF028E4eCA348", - "commit_store": "0xCFe3556Aa42d40be09BD23aa80448a19443BE5B1", + "off_ramp": "0x5E4DB2A3c965B9B2A850a75697Bb6a00b4e35ac5", + "commit_store": "0x2489c5a802fE63943f7E3185A0362327B55DDF67", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "BSC Testnet": { - "off_ramp": "0xbc4AD54e91b213D4279af92c0C5518c0b96cf62D", - "commit_store": "0xff84e8Dd4Fd17eaBb23b6AeA6e1981830e54389C", + "off_ramp": "0x2BA72Ba392C08750328635E36757A2c29a9165CA", + "commit_store": "0x08ebd7Cf4ABDC819c74cB45CbA4e291728538D7C", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Base Sepolia": { - "off_ramp": "0x4117953A5ceeF12f5B8C1E973b470ab83a8CebA6", - "commit_store": "0x94ad41296186E81f31e1ed0B1BcF5fa9e1721C27", + "off_ramp": "0x269D28B25Ee081ae5340e2BFE99850E92F1cd522", + "commit_store": "0x8dC9329BD221C89c4989d98c38Ff2Cc3dF92d14b", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Optimism Sepolia": { - "off_ramp": "0x33d2898F8fb7714FD1661791766f40754982a343", - "commit_store": "0x55d6Df194472f02CD481e506A277c4A29D0D1bCc", + "off_ramp": "0xd93B571ae9CaF43d70b2b53fFD55e035Db641e31", + "commit_store": "0x42C1093b9DdE8d0CD58859C610dc239B66bE26de", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Polygon Amoy": { - "off_ramp": "0x450543b1d85ca79885851D7b74dc982981b78229", - "commit_store": "0x23B79d940A769FE31b4C867A8BAE80117f24Ca81", + "off_ramp": "0x87F9b8382611ACD01d5696a1f5b05B888e55B0Cc", + "commit_store": "0x29AC46227908d31A9BdDe82c0A4a6c52D802f145", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { - "off_ramp": "0xbf9036529123DE264bFA0FC7362fE25B650D4B16", - "commit_store": "0x5f7F1abD5c5EdaF2636D58B980e85355AF0Ef80d", + "off_ramp": "0x9aa734100C425309091dAE18154e0356B82d477a", + "commit_store": "0x7cDd533B82f4c32FAE7f551C37b1490909817C45", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -464,26 +449,20 @@ Data = """ "Kroma Sepolia": { "is_native_fee_token": true, "fee_token": "0x4200000000000000000000000000000000000001", - "bridge_tokens": [ - "0x6AC3e353D1DDda24d5A5416024d6E436b8817A4e" - ], - "bridge_tokens_pools": [ - "0x0eE8add19554C7bb1920A183Ed47b4FAB9Eb7601" - ], "arm": "0x08f9Af992368FAc58C936A2c5eBc9092894CEa9b", "router": "0xA8C0c11bf64AF62CDCA6f93D3769B88BdD7cb93D", "price_registry": "0xa1ed3A3aA29166C9c8448654A8cA6b7916BC8379", "wrapped_native": "0x4200000000000000000000000000000000000001", "src_contracts": { "WeMix Testnet": { - "on_ramp": "0x6ea155Fc77566D9dcE01B8aa5D7968665dc4f0C5", + "on_ramp": "0xa81418c332d3E04338B058Ab39b1baf53029F638", "deployed_at": 0 } }, "dest_contracts": { "WeMix Testnet": { - "off_ramp": "0xB602B6E5Caf08ac0C920EAE585aed100a8cF6f3B", - "commit_store": "0x89D5b13908b9063abCC6791dc724bF7B7c93634C", + "off_ramp": "0x42Dde725C4f05C237a00B582Bb7457e208d3A17C", + "commit_store": "0xb116E9a90534354dA59CF93a87c1E9711c0Aaa2c", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -491,26 +470,29 @@ Data = """ "Metis Sepolia": { "is_native_fee_token": true, "fee_token": "0x5c48e07062aC4E2Cf4b9A768a711Aef18e8fbdA0", - "bridge_tokens": [ - "0x20Aa09AAb761e2E600d65c6929A9fd1E59821D3f" - ], - "bridge_tokens_pools": [ - "0xdE8451E952Eb43350614839cCAA84f7C8701a09C" - ], "arm": "0xf0607A9BDdB5F54dB59ACaA0837aFec2D1c95df6", "router": "0xaCdaBa07ECad81dc634458b98673931DD9d3Bc14", "price_registry": "0x5DCE866b3ae6E0Ed153f0e149D7203A1B266cdF5", "wrapped_native": "0x5c48e07062aC4E2Cf4b9A768a711Aef18e8fbdA0", "src_contracts": { + "Arbitrum Sepolia": { + "on_ramp": "0x2eb69889cc979c0Be120813FcE2f1558efF4ceB5", + "deployed_at": 0 + }, "Sepolia Testnet": { - "on_ramp": "0x2Eff2d1BF5C557d6289D208a7a43608f5E3FeCc2", + "on_ramp": "0xE0dFc15C0CDf607b2088D0B641E00eA0B418124C", "deployed_at": 0 } }, "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0x839b5dEA3e084790F580E9DfCE8CCfDf49c5835e", + "commit_store": "0xdF38C8aD34C379165f98A75a6894790bB5a16b1D", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, "Sepolia Testnet": { - "off_ramp": "0x9Bb7e398ef9Acfe9cA584C39B1E233Cba62BB9f7", - "commit_store": "0x1F4B82cDebaC5e3a0Dd53183D47e51808B4a64cB", + "off_ramp": "0x72130De9A85e9C61151253aFF8801Bb3242A00a9", + "commit_store": "0x8F6D64280C379F680Ff0c3278f340D72a465FAAc", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -518,35 +500,29 @@ Data = """ "Mode Sepolia": { "is_native_fee_token": true, "fee_token": "0x4200000000000000000000000000000000000006", - "bridge_tokens": [ - "0xB9d4e1141E67ECFedC8A8139b5229b7FF2BF16F5" - ], - "bridge_tokens_pools": [ - "0x20bBc874bE3Cd94C3E4689EDD5D89dD1cE8Cb7C4" - ], "arm": "0x9eC8a0AbC75ce08978FAf67958482461bCd93B18", "router": "0xc49ec0eB4beb48B8Da4cceC51AA9A5bD0D0A4c43", "price_registry": "0xa733ce82a84335b2E9D864312225B0F3D5d80600", "wrapped_native": "0x4200000000000000000000000000000000000006", "src_contracts": { "Base Sepolia": { - "on_ramp": "0x73f7E074bd7291706a0C5412f51DB46441B1aDCB", + "on_ramp": "0x48ACE2319f643584B77C21476a6c664D7F13a107", "deployed_at": 0 }, "Sepolia Testnet": { - "on_ramp": "0xfFdE9E8c34A27BEBeaCcAcB7b3044A0A364455C9", + "on_ramp": "0xb821885731414497d705dc56325f18AA33e612dC", "deployed_at": 0 } }, "dest_contracts": { "Base Sepolia": { - "off_ramp": "0x137a38c6b1Ad20101F93516aB2159Df525309168", - "commit_store": "0x8F43d867969F14619895d71E0A5b89E0bb20bF70", + "off_ramp": "0xC6b69Fa9eeBc55e64eBc68371Fbd41ff73756F17", + "commit_store": "0xaA6691EA9110409a29C2E665174b4b2fe694cE67", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { - "off_ramp": "0xcD44cec849B6a8eBd5551D6DFeEcA452257Dfe4d", - "commit_store": "0xbA66f08733E6715D33edDfb5a5947676bb45d0e0", + "off_ramp": "0x35dE2C381a2fF8a26c8ae94145be3A9cA8C83600", + "commit_store": "0xE7e60DAee094416b8ab2083047a893c4c4290c48", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -554,80 +530,74 @@ Data = """ "Optimism Sepolia": { "is_native_fee_token": true, "fee_token": "0x4200000000000000000000000000000000000006", - "bridge_tokens": [ - "0x8aF4204e30565DF93352fE8E1De78925F6664dA7" - ], - "bridge_tokens_pools": [ - "0x3Cc9364260D80F09ccAC1eE6B07366dB598900E6" - ], "arm": "0xF51366F72184E22cF4a7a8362508DB0d3370392d", "router": "0x114A20A10b43D4115e5aeef7345a1A71d2a60C57", "price_registry": "0x782a7Ba95215f2F7c3dD4C153cbB2Ae3Ec2d3215", "wrapped_native": "0x4200000000000000000000000000000000000006", "src_contracts": { "Arbitrum Sepolia": { - "on_ramp": "0x1a86b29364D1B3fA3386329A361aA98A104b2742", + "on_ramp": "0x6B36c9CD74E760088817a047C3460dEdFfe9a11A", "deployed_at": 0 }, "Avalanche Fuji": { - "on_ramp": "0x6b38CC6Fa938D5AB09Bdf0CFe580E226fDD793cE", + "on_ramp": "0x91a144F570ABA7FB7079Fb187A267390E0cc7367", "deployed_at": 0 }, "Base Sepolia": { - "on_ramp": "0xe284D2315a28c4d62C419e8474dC457b219DB969", + "on_ramp": "0x6D22953cdEf8B0C9F0976Cfa52c33B198fEc5881", "deployed_at": 0 }, "Gnosis Chiado": { - "on_ramp": "0x835a5b8e6CA17c2bB5A336c93a4E22478E6F1C8A", + "on_ramp": "0xec7D9A84A6d4556056975BE50Cdc97bAa9313632", "deployed_at": 0 }, "Polygon Amoy": { - "on_ramp": "0x2Cf26fb01E9ccDb831414B766287c0A9e4551089", + "on_ramp": "0x9E09C2A7D6B9F88c62f0E2Af4cd62dF3F4c326F1", "deployed_at": 0 }, "Sepolia Testnet": { - "on_ramp": "0xC8b93b46BF682c39B3F65Aa1c135bC8A95A5E43a", + "on_ramp": "0x54b32C2aCb4451c6cF66bcbd856d8A7Cc2263531", "deployed_at": 0 }, "WeMix Testnet": { - "on_ramp": "0xc7E53f6aB982af7A7C3e470c8cCa283d3399BDAd", + "on_ramp": "0xB9Ef21C04d8340b223e9C1d7a09f332609c70300", "deployed_at": 0 } }, "dest_contracts": { "Arbitrum Sepolia": { - "off_ramp": "0xDc2c7A3d8068C6F09F0F3648d24C84e372F6014d", - "commit_store": "0xb1aFb5cbE3c29b5Db71F21442BA9EfD450BC23C3", + "off_ramp": "0xF35e2d1457749374453e44B06268aD3f78b133b3", + "commit_store": "0x4bd755d86E25dD4093CAa5639CfDab81571259CA", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Avalanche Fuji": { - "off_ramp": "0x1F350718e015EB20E5065C09F4A7a3f66888aEeD", - "commit_store": "0x98650A8EB59f75D93563aB34FcF603b1A30e4CBF", + "off_ramp": "0xCb2266c2118b1f30D15CBeB3a885531ABaA1b556", + "commit_store": "0x5Ded92E2CF71a8fF7644a67850F061c38B31BfB4", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Base Sepolia": { - "off_ramp": "0x0a750ca77369e03613d7640548F4b2b1c695c3Bb", - "commit_store": "0x8fEBC74C26129C8d7E60288C6dCCc75eb494aA3C", + "off_ramp": "0x960c62A491C30d0a60fD74a59d35B9C02697AdaA", + "commit_store": "0x06963745B3839B998288D1a46a46Ec25991A3D5E", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Gnosis Chiado": { - "off_ramp": "0xCE2CE7F940B7c839384e5D7e079A6aE80e8AD6dB", - "commit_store": "0x1b9D78Ec1CEEC439F0b7eA6C428A1a607D9FA7e4", + "off_ramp": "0x7d6721c2E85560F0A233255D3d332AcF6f850d96", + "commit_store": "0xaC00661cAB5161d9B4746DFb7A028d97981aB2c5", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Polygon Amoy": { - "off_ramp": "0xD667b5706592D0b040C78fEe5EE17D243b7dCB41", - "commit_store": "0x96101BA5250EE9295c193693C1e08A55bC593664", + "off_ramp": "0x4cEeFa55AF23dFD27Cf926e8eFB1D1bCcD24526E", + "commit_store": "0xaD3943BdECbf4ae7d6E51aB0FD06bbC604bB7b95", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { - "off_ramp": "0x260AF9b83e0d2Bb6C9015fC9f0BfF8858A0CCE68", - "commit_store": "0x7a0bB92Bc8663abe6296d0162A9b41a2Cb2E0358", + "off_ramp": "0x2aF9B10A5972D0c36f4d8F85773052c104E319B2", + "commit_store": "0x82FCF55b9e9bAb3066c2863F12a02bBc2Ba33F2F", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "WeMix Testnet": { - "off_ramp": "0x9C08B7712af0344188aa5087D9e6aD0f47191037", - "commit_store": "0x4BE6DB0B884169a6A207fe5cad01eB4C025a13dB", + "off_ramp": "0x0FA15Bc42D4999d964CBf0161489Bd392DEE834e", + "commit_store": "0x37760F99a5b91884C9D89a06408f532aEbb0e674", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -635,71 +605,65 @@ Data = """ "Polygon Amoy": { "is_native_fee_token": true, "fee_token": "0x360ad4f9a9A8EFe9A8DCB5f461c4Cc1047E1Dcf9", - "bridge_tokens": [ - "0xcab0EF91Bee323d1A617c0a027eE753aFd6997E4" - ], - "bridge_tokens_pools": [ - "0x3064fB3EA546EE09A63AB3bD93E83D8B8525C636" - ], "arm": "0x8b88C39D2875157aB4CE4AD3814409523d539ee1", "router": "0x9C32fCB86BF0f4a1A8921a9Fe46de3198bb884B2", "price_registry": "0xfb2f2A207dC428da81fbAFfDDe121761f8Be1194", "wrapped_native": "0x360ad4f9a9A8EFe9A8DCB5f461c4Cc1047E1Dcf9", "src_contracts": { "Avalanche Fuji": { - "on_ramp": "0x8Fb98b3837578aceEA32b454f3221FE18D7Ce903", + "on_ramp": "0xad6A94CFB51e7DE30FD21F417E4cBf70D3AdaD30", "deployed_at": 0 }, "BSC Testnet": { - "on_ramp": "0xC6683ac4a0F62803Bec89a5355B36495ddF2C38b", + "on_ramp": "0x28EC0a9C90360F55C2a9DaD5901b074C257904ca", "deployed_at": 0 }, "Gnosis Chiado": { - "on_ramp": "0x2331F6D614C9Fd613Ff59a1aB727f1EDf6c37A68", + "on_ramp": "0x9DF611536f124278Ce968c476BDb10A66E54ecfE", "deployed_at": 0 }, "Optimism Sepolia": { - "on_ramp": "0xA52cDAeb43803A80B3c0C2296f5cFe57e695BE11", + "on_ramp": "0x600f00aef9b8ED8EDBd7284B5F04a1932c3408aF", "deployed_at": 0 }, "Sepolia Testnet": { - "on_ramp": "0x35347A2fC1f2a4c5Eae03339040d0b83b09e6FDA", + "on_ramp": "0x719Aef2C63376AdeCD62D2b59D54682aFBde914a", "deployed_at": 0 }, "WeMix Testnet": { - "on_ramp": "0x26546096F64B5eF9A1DcDAe70Df6F4f8c2E10C61", + "on_ramp": "0x7D6c93E49E46cc983a677c283EAb27CbbC94e3C4", "deployed_at": 0 } }, "dest_contracts": { "Avalanche Fuji": { - "off_ramp": "0xa733ce82a84335b2E9D864312225B0F3D5d80600", - "commit_store": "0x09B0F93fC2111aE439e853884173AC5b2F809885", + "off_ramp": "0xAc56Df7F5fbde0DeeB1C0d397A150EDD5EE68625", + "commit_store": "0x8AF56D1c76B8c8CeE451a0a654D130e4050B993e", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "BSC Testnet": { - "off_ramp": "0x948dfaa4842fc23e0e362Fe8D4396AaE4E6DF7EA", - "commit_store": "0x7F4e739D40E58BBd59dAD388171d18e37B26326f", + "off_ramp": "0x40Ba47ea59D80DDd35E3a997AA520FBa0553dddc", + "commit_store": "0x8afe532517b39bA109d1A768E1Ad8b5C6485abF5", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Gnosis Chiado": { - "off_ramp": "0x17c542a28e08AEF5697251601C7b2B621d153D42", - "commit_store": "0x811250c20fAB9a1b7ca245453aC214ba637fBEB5", + "off_ramp": "0x7B968B2aDFd31765dAAD80d66c83F9D7006BFFd5", + "commit_store": "0xBc70551B5624BaF8cdCB84136198561C9cf5C176", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Optimism Sepolia": { - "off_ramp": "0xfFdE9E8c34A27BEBeaCcAcB7b3044A0A364455C9", - "commit_store": "0x74ED442ad211050e9C05Dc9A267E037E3d74A03B", + "off_ramp": "0xAA755Ef570986feEb6522377077e549e3013843E", + "commit_store": "0x5C7827EcE6a51AdaC36ef71aC01706deb1C7130d", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { - "off_ramp": "0xFb04129aD1EEDB741CC705ebC1978a7aB63e51f6", - "commit_store": "0x63f875240149d29136053C954Ca164a9BfA81F77", + "off_ramp": "0x7Ad494C173f5845c6B4028a06cDcC6d3108bc960", + "commit_store": "0x104A1c8b05D37fE732094595Fe696AFc7EAB8668", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "WeMix Testnet": { - "off_ramp": "0xdE8451E952Eb43350614839cCAA84f7C8701a09C", - "commit_store": "0xaCdaBa07ECad81dc634458b98673931DD9d3Bc14", + "off_ramp": "0xa85481273f8C112e96ED7476202F06D6131cf069", + "commit_store": "0x9FdF1D555e37dB09B0d151FEa53c134C88C4DeFd", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -707,134 +671,128 @@ Data = """ "Sepolia Testnet": { "is_native_fee_token": true, "fee_token": "0x097D90c9d3E0B50Ca60e1ae45F6A81010f9FB534", - "bridge_tokens": [ - "0xFd57b4ddBf88a4e07fF4e34C487b99af2Fe82a05" - ], - "bridge_tokens_pools": [ - "0x38d1ef9619Cd40cf5482C045660Ae7C82Ada062c" - ], "arm": "0x27Da8735d8d1402cEc072C234759fbbB4dABBC4A", "router": "0x0BF3dE8c5D3e8A2B34D2BEeB17ABfCeBaf363A59", "price_registry": "0x9EF7D57a4ea30b9e37794E55b0C75F2A70275dCc", "wrapped_native": "0x097D90c9d3E0B50Ca60e1ae45F6A81010f9FB534", "src_contracts": { "Arbitrum Sepolia": { - "on_ramp": "0xe4Dd3B16E09c016402585a8aDFdB4A18f772a07e", + "on_ramp": "0xBc09627e58989Ba8F1eDA775e486467d2A00944F", "deployed_at": 0 }, "Avalanche Fuji": { - "on_ramp": "0x0477cA0a35eE05D3f9f424d88bC0977ceCf339D4", + "on_ramp": "0x12492154714fBD28F28219f6fc4315d19de1025B", "deployed_at": 0 }, "BSC Testnet": { - "on_ramp": "0xD990f8aFA5BCB02f95eEd88ecB7C68f5998bD618", + "on_ramp": "0x7a75b3818412fe0028590feE8270ba9E3fd01DBe", "deployed_at": 0 }, "Base Sepolia": { - "on_ramp": "0x2B70a05320cB069e0fB55084D402343F832556E7", + "on_ramp": "0x8F35B097022135E0F46831f798a240Cc8c4b0B01", "deployed_at": 0 }, "Blast Sepolia": { - "on_ramp": "0xDB75E9D9ca7577CcBd7232741be954cf26194a66", + "on_ramp": "0x4ADA60556dA05FcF53a79359e37a3E13FebA22Bf", "deployed_at": 0 }, "Celo Alfajores": { - "on_ramp": "0x3C86d16F52C10B2ff6696a0e1b8E0BcfCC085948", + "on_ramp": "0x1163D1F7D75eEb1C4f4c6912d3cF9642027aFD30", "deployed_at": 0 }, "Gnosis Chiado": { - "on_ramp": "0x3E842E3A79A00AFdd03B52390B1caC6306Ea257E", + "on_ramp": "0x831A7DbE6af8601427A0ADa89b642d4b59007eED", "deployed_at": 0 }, "Metis Sepolia": { - "on_ramp": "0x1C4640914cd57c5f02a68048A0fbb0E12d904223", + "on_ramp": "0xabB5A4f99DFEb4a3912e8Acc0660A008c76dA8c3", "deployed_at": 0 }, "Mode Sepolia": { - "on_ramp": "0xc630fbD4D0F6AEB00aD0793FB827b54fBB78e981", + "on_ramp": "0x2Eb0842925fb7aA6045e951e98e8b4b3aFFaBB54", "deployed_at": 0 }, "Optimism Sepolia": { - "on_ramp": "0x69CaB5A0a08a12BaFD8f5B195989D709E396Ed4d", + "on_ramp": "0xACDfd7a98d853FA3914047Cd46e7f5D53BBC9FbB", "deployed_at": 0 }, "Polygon Amoy": { - "on_ramp": "0x9f656e0361Fb5Df2ac446102c8aB31855B591692", + "on_ramp": "0xf9765c80F6448e6d4d02BeF4a6b4152131A2F513", "deployed_at": 0 }, "WeMix Testnet": { - "on_ramp": "0xedFc22336Eb0B9B11Ff37C07777db27BCcDe3C65", + "on_ramp": "0xd72c3c132B76F5D232C37dF3bF8f04392D552e0F", "deployed_at": 0 }, "ZKSync Sepolia": { - "on_ramp": "0x1Acb3A885feA37bdA30AB99b99327b14391f500F", + "on_ramp": "0xA2865E4f36760f5fa5c8F958336120f2DF0d974b", "deployed_at": 0 } }, "dest_contracts": { "Arbitrum Sepolia": { - "off_ramp": "0xF18896AB20a09A29e64fdEbA99FDb8EC328f43b1", - "commit_store": "0x93Ff9Dd39Dc01eac1fc4d2c9211D95Ee458CAB94", + "off_ramp": "0xD2f5edfD4561d6E7599F6c6888Bd353cAFd0c55E", + "commit_store": "0x240420BC6bCDc067e668c7492D69fe06B3CF80cE", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Avalanche Fuji": { - "off_ramp": "0x000b26f604eAadC3D874a4404bde6D64a97d95ca", - "commit_store": "0x2dD9273F8208B8393350508131270A6574A69784", + "off_ramp": "0x1DEBa99dC8e2A77832461BD386d83D9FCb133137", + "commit_store": "0x139E06b6dBB1a0C41A1686C091795879c943765A", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "BSC Testnet": { - "off_ramp": "0xdE2d8E126e08d675fCD7fFa5a6CE49925f3Dc692", - "commit_store": "0x0050ac355a82caB31194507f94174297bf0655A7", + "off_ramp": "0x04305BD9D9CA6730517f79c3D9c6828BC2D25Ecb", + "commit_store": "0x32edD59840CD9e474A280cf1707439F2Bd5872d4", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Base Sepolia": { - "off_ramp": "0x31c0B81832B333419f0DfD36A69F502cF9094aed", - "commit_store": "0xDFcde9d698a2B32DB2537DC9B752Cadd1D846a52", + "off_ramp": "0x662738DC7DE4f7eC63d9f73Cdf9BeA5A58DdcC15", + "commit_store": "0x1e46bAC486Dd878cD57B62845530A52343e39693", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Blast Sepolia": { - "off_ramp": "0x4e897e5cF3aC307F0541B2151A88bCD781c153a3", - "commit_store": "0xB656652841F347178e193951C4663652aCe36B74", + "off_ramp": "0x049A424cF894709f044bc70177F8F6b792adc3F6", + "commit_store": "0x496fE96E440Fc683478a08Df92A1c5E23E412b1C", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Celo Alfajores": { - "off_ramp": "0xB435E0f73c18C5a12C324CA1d02F81F2C3e6e761", - "commit_store": "0xbc5d74957F171e75F92c8F0E1C317A25a56a416D", + "off_ramp": "0x4F146d34Be5E273e576ef158Bd7070eC22708D20", + "commit_store": "0xEeB665281c7ab51d25423898f730Ab078c69dd42", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Gnosis Chiado": { - "off_ramp": "0x7db0115A0b3AAb01d30bf81123c5DD7B0C41Add5", - "commit_store": "0x6640723Ea801178c4383FA016b9781e7ef1016EF", + "off_ramp": "0xB424365EEEEA58A36C7EC858f926f4e8275dDEb3", + "commit_store": "0xE95c2135e3330E953BB49068d32Fcba368Acd456", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Metis Sepolia": { - "off_ramp": "0x4DB693A93E9d5196ECD42EC56CDEAe99dFC652ED", - "commit_store": "0xBfACd78F1412B6f93Ac23409bf456aFec1ABd845", + "off_ramp": "0x46DE6201c258f5948135cd0262f91e48Cb8e3828", + "commit_store": "0x3A27Fd059A4eF0e96B0643283A44a56A8d6CF34A", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Mode Sepolia": { - "off_ramp": "0xbEfd8D65F6643De54F0b1268A3bf4618ff85dcB4", - "commit_store": "0x0C161D3470b45Cc677661654C30ce4AdE6aCD288", + "off_ramp": "0x052E52fdd48719A6084366eA184FC44cb8C25DC2", + "commit_store": "0xBBb9baA314eB023E3F9291Aaf4107B6708341B50", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Optimism Sepolia": { - "off_ramp": "0xD50590D4438411EDe47029b0FD7901A7145E5Df6", - "commit_store": "0xe85EEE9Fd434A7b8a586Ee086E828abF41839479", + "off_ramp": "0xbfa6f6AAE31acB3A285e80026d6475C1a50d1d0F", + "commit_store": "0xB5FbA97Dc61ec68771a92a15360d9C32c9d054E7", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Polygon Amoy": { - "off_ramp": "0x5032cbC0C4aEeD25bb6E45D8B3fAF05DB0688C5d", - "commit_store": "0xe6201C9996Cc7B6E828E10CbE937E693d577D318", + "off_ramp": "0xC3e550B6aaFA5539df8bbCc5B0991e587f438e75", + "commit_store": "0xd57866D97ca26dfaE34088a3EeE4657BAFaac5f9", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "WeMix Testnet": { - "off_ramp": "0x46b639a3C1a4CBfD326b94a2dB7415c27157282f", - "commit_store": "0x7b74554678816b045c1e7409327E086bD436aa46", + "off_ramp": "0x445F41C6aa7e910021786e860d7cfe3E7fcC6640", + "commit_store": "0x307dDE3c696E399b5837456FbCe03b1Ad76D46E3", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "ZKSync Sepolia": { - "off_ramp": "0xBaABd4166C892a1081a26535875A8fA3f22937b2", - "commit_store": "0xfda2e83F4D3f42B7629134ecD6E4b29FB8A7A07B", + "off_ramp": "0x9f5dC467A5c97068A1c2987486B8b768275627eD", + "commit_store": "0x6e4601DA99a046e4bde60d051568E3E1F35E3097", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -842,80 +800,74 @@ Data = """ "WeMix Testnet": { "is_native_fee_token": true, "fee_token": "0xbE3686643c05f00eC46e73da594c78098F7a9Ae7", - "bridge_tokens": [ - "0xF4E4057FbBc86915F4b2d63EEFFe641C03294ffc" - ], - "bridge_tokens_pools": [ - "0x82A92B2863F93Be70D20660088Ec060720bA2fdb" - ], "arm": "0x8f6cb63eD5e379722580DFF0A051C140C64F9619", "router": "0xA8C0c11bf64AF62CDCA6f93D3769B88BdD7cb93D", "price_registry": "0x89D17571DB7C9540eeB36760E3c749C8fb984569", "wrapped_native": "0xbE3686643c05f00eC46e73da594c78098F7a9Ae7", "src_contracts": { "Arbitrum Sepolia": { - "on_ramp": "0xA9DE3F7A617D67bC50c56baaCb9E0373C15EbfC6", + "on_ramp": "0xa5Be8C619F61505548992D9820c5c485b030C7B0", "deployed_at": 0 }, "Avalanche Fuji": { - "on_ramp": "0xC4aC84da458ba8e40210D2dF94C76E9a41f70069", + "on_ramp": "0x7802B6804bbE7486229ac6D3519f0057c50b40a9", "deployed_at": 0 }, "BSC Testnet": { - "on_ramp": "0x5AD6eed6Be0ffaDCA4105050CF0E584D87E0c2F1", + "on_ramp": "0xd25B8c70CB43022Bdc3aC417E2Cf5159294d95A1", "deployed_at": 0 }, "Kroma Sepolia": { - "on_ramp": "0x428C4dc89b6Bf908B82d77C9CBceA786ea8cc7D0", + "on_ramp": "0x1De2Ca07eEee7F524Fe5edA6C8FFFb79F67b05E9", "deployed_at": 0 }, "Optimism Sepolia": { - "on_ramp": "0x1961a7De751451F410391c251D4D4F98D71B767D", + "on_ramp": "0xB37607C6BD4562F32967dE87D14663D59e3f655d", "deployed_at": 0 }, "Polygon Amoy": { - "on_ramp": "0xd55148e841e76265B484d399eC71b7076ecB1216", + "on_ramp": "0x0c972752F9aC3255cE45b440f9bBC6500676c4e6", "deployed_at": 0 }, "Sepolia Testnet": { - "on_ramp": "0x4d57C6d8037C65fa66D6231844785a428310a735", + "on_ramp": "0x1CD55c65f85681Dfae47c62e6D93340D25006BbB", "deployed_at": 0 } }, "dest_contracts": { "Arbitrum Sepolia": { - "off_ramp": "0xeB1dFaB2464Bf0574D43e764E0c758f92e7ecAFb", - "commit_store": "0xcEaCa2B7890065c485f3E58657358a185Ad33791", + "off_ramp": "0xB5492C8A71130B486fAD1091Db683584767A3957", + "commit_store": "0x1e151ED27E2F48EcFBd5b4374d0fc4869e07c397", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Avalanche Fuji": { - "off_ramp": "0x98e811Df9D2512f1aaf58D534607F583D6c54A4F", - "commit_store": "0x8e538351F6E5B2daF3c90C565C3738bca69a2716", + "off_ramp": "0x60536c757c2BBf72cC68A1933F7e336d03Bb68fe", + "commit_store": "0x2fF725556A04b47eB40BbA11d9F51e8fbbee9F07", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "BSC Testnet": { - "off_ramp": "0xB0e7f0fCcD3c961C473E7c44D939C1cDb4Cec1cB", - "commit_store": "0x4B56D8d53f1A6e0117B09700067De99581aA5542", + "off_ramp": "0xb858077FbE1E55cD7a9092Eb6d5403e068c14EAf", + "commit_store": "0x0EF13C7c95C27A9EA477363a26a09Cff44ba38F9", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Kroma Sepolia": { - "off_ramp": "0xD685D2d224dd6D0Db2D56497db6270D77D9a7966", - "commit_store": "0x7e062D6880779a0347e7742058C1b1Ee4AA0B137", + "off_ramp": "0x78d8154e1216F4791086bFa078Aaf07dcD2bD3C6", + "commit_store": "0xe67AAfbE6025e730Cf47a414BEFf2106FF231dB1", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Optimism Sepolia": { - "off_ramp": "0xA5f97Bc69Bf06e7C37B93265c5457420A92c5F4b", - "commit_store": "0xd48b9213583074f518D8f4336FDf35370D450132", + "off_ramp": "0x995Fc17FC12b67f75D3cBf3bC71BD9af65671E78", + "commit_store": "0xD0825e3D8e61b67a06A93426749d38bCF73Ddb02", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Polygon Amoy": { - "off_ramp": "0x6c8f5999B06FDE17B11E4e3C1062b761766F960f", - "commit_store": "0x957c3c2056192e58A8485eF31165fC490d474239", + "off_ramp": "0xd7b5B4F8FF7a87cC92f7B3058365862859d9E057", + "commit_store": "0xa8f2bb4e831caA5E2794AaD014030E378208d4Bc", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { - "off_ramp": "0x8AB103843ED9D28D2C5DAf5FdB9c3e1CE2B6c876", - "commit_store": "0x7d5297c5506ee2A7Ef121Da9bE02b6a6AD30b392", + "off_ramp": "0xa7E2F97Be7798327A49CACD022f33c0E7EfD4897", + "commit_store": "0x6fe69eE4eC9FD768193a40129A3Ba3dF140b2208", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -929,14 +881,14 @@ Data = """ "wrapped_native": "0x4317b2eCD41851173175005783322D29E9bAee9E", "src_contracts": { "Sepolia Testnet": { - "on_ramp": "0x79a9a5e9e318e8e109776569574814bbf935125a", + "on_ramp": "0xC38536521fde8556351aB7C4D3ea23b64AFbBbab", "deployed_at": 0 } }, "dest_contracts": { "Sepolia Testnet": { - "off_ramp": "0x18FF69051479796175852578725Fc74F58E963F8", - "commit_store": "0xF694b4FD7889480dca3CD41244e8e3395a9EFBa0", + "off_ramp": "0x19Ea9A42cd3682928aF19990dDb3904250D00a1D", + "commit_store": "0x20BF9037927bFadaF028D43ae07d1afccfB8fa85", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -1006,7 +958,7 @@ NetworkPairs = [ 'BASE_SEPOLIA,OPTIMISM_SEPOLIA', 'BASE_SEPOLIA,GNOSIS_CHIADO', - 'KROMA_SEPOLIA,WEMIX_TESTNET', +# 'KROMA_SEPOLIA,WEMIX_TESTNET', 'OPTIMISM_SEPOLIA,POLYGON_AMOY', 'OPTIMISM_SEPOLIA,WEMIX_TESTNET', diff --git a/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/smoke-release-testing_token_transfer_native.toml b/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/smoke-release-testing_token_transfer_native.toml index b1549377fda..17372a68681 100644 --- a/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/smoke-release-testing_token_transfer_native.toml +++ b/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/smoke-release-testing_token_transfer_native.toml @@ -26,59 +26,68 @@ Data = """ "wrapped_native": "0xE591bf0A0CF924A0674d7792db046B23CEbF5f34", "src_contracts": { "Avalanche Fuji": { - "on_ramp": "0x1Cb56374296ED19E86F68fA437ee679FD7798DaA", + "on_ramp": "0x20C8c9F13C6AA402F2545AD15fB7a9CdE9108618", "deployed_at": 0 }, "Base Sepolia": { - "on_ramp": "0x7854E73C73e7F9bb5b0D5B4861E997f4C6E8dcC6", + "on_ramp": "0xF1623862e4c9f9Fba1Ac0181C4fF53B4f958F065", "deployed_at": 0 }, "Gnosis Chiado": { - "on_ramp": "0x973CbE752258D32AE82b60CD1CB656Eebb588dF0", + "on_ramp": "0xEfe02eB139D2A82e38184d28E3b65bb176F26ebD", + "deployed_at": 0 + }, + "Metis Sepolia": { + "on_ramp": "0x46a79a6a4B07FD3FC14ea8299A99FE29576776E2", "deployed_at": 0 }, "Optimism Sepolia": { - "on_ramp": "0x701Fe16916dd21EFE2f535CA59611D818B017877", + "on_ramp": "0x0B0c08Bb2fA2EbDe25817009ee39eA1ad9bCaC58", "deployed_at": 0 }, "Sepolia Testnet": { - "on_ramp": "0x4205E1Ca0202A248A5D42F5975A8FE56F3E302e9", + "on_ramp": "0x64d78F20aD987c7D52FdCB8FB0777bD00de53210", "deployed_at": 0 }, "WeMix Testnet": { - "on_ramp": "0xBD4106fBE4699FE212A34Cc21b10BFf22b02d959", + "on_ramp": "0x2F3Daf77A663603826c7750E956b6555DE6f8250", "deployed_at": 0 } }, "dest_contracts": { "Avalanche Fuji": { - "off_ramp": "0xcab0EF91Bee323d1A617c0a027eE753aFd6997E4", - "commit_store": "0x0d90b9b96cBFa0D01635ce12982ccE1b70827c7a", + "off_ramp": "0x7245a5947E2F32B66aF74F4dAF91718ea19afaDf", + "commit_store": "0x490AC77BbB26f4FFf876Ded07bCAE6DBe685be98", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Base Sepolia": { - "off_ramp": "0xc1982985720B959E66c19b64F783361Eb9B60F26", - "commit_store": "0x28F66bB336f6db713d6ad2a3bd1B7a531282A159", + "off_ramp": "0xF2aB55Ed448A6fAD75013900568B6a927f52e5e0", + "commit_store": "0x833E5995A7422120f445f9B8dD1b9BD1037c68E5", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Gnosis Chiado": { - "off_ramp": "0x935C26F9a9122E5F9a27f2d3803e74c75B94f5a3", - "commit_store": "0xEdb963Ec5c2E5AbdFdCF137eF44A445a7fa4787A", + "off_ramp": "0xc1Cb31493fB2386aDC1Ea01F935F2bd8a8dCA388", + "commit_store": "0xe21896657A65c8959F16E1c3Ee5713E85d9EA020", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Metis Sepolia": { + "off_ramp": "0xc47143147Fd62A09618C695c7C03714aCe8db1Cf", + "commit_store": "0x2F42e7B22eE5885158916624Ff00608f4C82313D", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Optimism Sepolia": { - "off_ramp": "0xfD404A89e1d195F0c65be1A9042C77745197659e", - "commit_store": "0x84B7B012c95f8A152B44Ab3e952f2dEE424fA8e1", + "off_ramp": "0x4a7E91EF68758aaC66AeD656267bbCD0f9b6c019", + "commit_store": "0xb0A09D6A15FF7A0142DF3F62b2C4D1e11D763Ed0", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { - "off_ramp": "0x1c71f141b4630EBE52d6aF4894812960abE207eB", - "commit_store": "0xaB0c8Ba51E7Fa3E5693a4Fbb39473520FD85d173", + "off_ramp": "0xBed6e9131916d724418C8a6FE810F727302a5c00", + "commit_store": "0xdDb61B6bDa1B46d88f556440fABFe219F6da4F3a", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "WeMix Testnet": { - "off_ramp": "0x262e16C8D42aa07bE13e58F81e7D9F62F6DE2830", - "commit_store": "0xc132eFAf929299E5ee704Fa6D9796CFa23Bb8b2C", + "off_ramp": "0x11d486E92d291704D1E25cDbAeee687237247826", + "commit_store": "0xece9353095aC79Db9DD5bf2022690Fa6BffeBCAc", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -98,77 +107,77 @@ Data = """ "wrapped_native": "0xd00ae08403B9bbb9124bB305C09058E32C39A48c", "src_contracts": { "Arbitrum Sepolia": { - "on_ramp": "0x8bB16BEDbFd62D1f905ACe8DBBF2954c8EEB4f66", + "on_ramp": "0xa9946BA30DAeC98745755e4410d6e8E894Edc53B", "deployed_at": 0 }, "BSC Testnet": { - "on_ramp": "0xF25ECF1Aad9B2E43EDc2960cF66f325783245535", + "on_ramp": "0x906BC7D10947A94ba0252e8C2E34868A466c03ED", "deployed_at": 0 }, "Base Sepolia": { - "on_ramp": "0x1A674645f3EB4147543FCA7d40C5719cbd997362", + "on_ramp": "0x0aEc1AC9F6D0c21332d7a66dDF1Fbcb32cF3B0B3", "deployed_at": 0 }, "Gnosis Chiado": { - "on_ramp": "0x1532e5b204ee2b2244170c78E743CB9c168F4DF9", + "on_ramp": "0x3dda45E731EC1db18B95651d1AF1868aa878468D", "deployed_at": 0 }, "Optimism Sepolia": { - "on_ramp": "0xC334DE5b020e056d0fE766dE46e8d9f306Ffa1E2", + "on_ramp": "0x2a9EFdc9F93D9b822129038EFCa4B63Adf3f7FB5", "deployed_at": 0 }, "Polygon Amoy": { - "on_ramp": "0x610F76A35E17DA4542518D85FfEa12645eF111Fc", + "on_ramp": "0xA82b9ACAcFA6FaB1FD721e7a748A30E3001351F9", "deployed_at": 0 }, "Sepolia Testnet": { - "on_ramp": "0x5724B4Cc39a9690135F7273b44Dfd3BA6c0c69aD", + "on_ramp": "0x75b9a75Ee1fFef6BE7c4F842a041De7c6153CF4E", "deployed_at": 0 }, "WeMix Testnet": { - "on_ramp": "0x677B5ab5C8522d929166c064d5700F147b15fa33", + "on_ramp": "0x1ff99E67986E83bb5BA34143BaA2735853e5738c", "deployed_at": 0 } }, "dest_contracts": { "Arbitrum Sepolia": { - "off_ramp": "0x90A74072e7B0c2d59e13aB4d8f93c8198c413194", - "commit_store": "0xf3458CFd2fdf4a6CF0Ce296d520DD21eB194828b", + "off_ramp": "0xd88CBA0612f2Ce611BF6d073A94C8FD7E70B4fBd", + "commit_store": "0x9b8279E352bC167F714eef96A4C436bE996643cE", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "BSC Testnet": { - "off_ramp": "0x10b28009E5D776F1f5AAA73941CE8953B8f42d26", - "commit_store": "0xacDD582F271eCF22FAd6764cCDe1c4a534b732A8", + "off_ramp": "0x9c40A73F5C7454BB7C178AFa56Ee30bFB2DCf7E6", + "commit_store": "0xE5611af1d63340b711B0468a976651Fb79B17870", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Base Sepolia": { - "off_ramp": "0xdBdE8510226d1E060A3bf982b67705C67f5697e2", - "commit_store": "0x8Ee73BC9492b4182D289E5C1e66e40CD876CC00F", + "off_ramp": "0xf8de9d5924CFD28e31a53B63B4903436D9818d69", + "commit_store": "0xDD7CfECE1bb4e8aC2E8b8281CFE1D44247119471", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Gnosis Chiado": { - "off_ramp": "0x56dF55aF5F0A4689f3364230587a68eD6A314fAd", - "commit_store": "0xabA7ff98094c4cc7A075812EefF2CD21f6400235", + "off_ramp": "0x3F5035039C23cDAF032C64c084Dc70F811E62ddD", + "commit_store": "0xf5B0245c7B9e15f0cB0B85FF2B6799a45D61CbaA", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Optimism Sepolia": { - "off_ramp": "0x3d7CbC95DCC33257F14D6Eb780c88Bd56C6335BB", - "commit_store": "0x1fcDC02edDfb405f378ba53cF9E6104feBcB7542", + "off_ramp": "0x1DF9D94C6916918C935E60d2Cb4Ed265Bf778005", + "commit_store": "0xE7eeBE5882609d28C015d0A89DE1ba4f506F4a03", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Polygon Amoy": { - "off_ramp": "0x3e33290B90fD0FF30a3FA138934DF028E4eCA348", - "commit_store": "0xCFe3556Aa42d40be09BD23aa80448a19443BE5B1", + "off_ramp": "0xbeD7F478Ef5627FB2B891fDA29Ca0131f6796D9D", + "commit_store": "0x27a319f58c01380056c86938798aCEAA1AC529e2", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { - "off_ramp": "0x9e5e4324F8608D54A50a317832d456a392E4F8C2", - "commit_store": "0x92A51eD3F041B39EbD1e464C1f7cb1e8f8A8c63f", + "off_ramp": "0x01e3D835b4C4697D7F81B9d7Abc89A6E478E4a2f", + "commit_store": "0x4EC313c1Eb620432f42FB5f4Df27f8A566523c1C", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "WeMix Testnet": { - "off_ramp": "0xD0D338318bC6837b091FC7AB5F2a94B7783507d5", - "commit_store": "0xd9D479208235c7355848ff4aF26eB5aacfDC30c6", + "off_ramp": "0x15CcAbf0e3484D4872e25b883163D8cB724d4832", + "commit_store": "0x859f3477B7b4ECc19aDD8cCb19740932F21bD76b", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -188,59 +197,68 @@ Data = """ "wrapped_native": "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd", "src_contracts": { "Avalanche Fuji": { - "on_ramp": "0xa2515683E99F50ADbE177519A46bb20FfdBaA5de", + "on_ramp": "0x2A6f8Ed2e7b222163ef6EcC2327171B479399ab2", "deployed_at": 0 }, "Base Sepolia": { - "on_ramp": "0x3E807220Ca84b997c0d1928162227b46C618e0c5", + "on_ramp": "0x97856Bf888F6eEDBBd322B28133BCcF9CA9038f6", + "deployed_at": 0 + }, + "Blast Sepolia": { + "on_ramp": "0xd0049BfFc8e2689Df9236FfA393Ccbf7eae4FbbC", "deployed_at": 0 }, "Gnosis Chiado": { - "on_ramp": "0x8735f991d41eA9cA9D2CC75cD201e4B7C866E63e", + "on_ramp": "0x98dEa9e498F2A7aF6c74C915c88A17FbA09b73C2", "deployed_at": 0 }, "Polygon Amoy": { - "on_ramp": "0xf37CcbfC04adc1B56a46B36F811D52C744a1AF78", + "on_ramp": "0x363EB789fE31F08547a847D8C38d9b55C7Cf1903", "deployed_at": 0 }, "Sepolia Testnet": { - "on_ramp": "0xB1DE44B04C00eaFe9915a3C07a0CaeA4410537dF", + "on_ramp": "0xC1C6438D60AbE9bF4b1F10460184CE9bD312e328", "deployed_at": 0 }, "WeMix Testnet": { - "on_ramp": "0x89268Afc1BEA0782a27ba84124E3F42b196af927", + "on_ramp": "0xbc85704EDb79ea84E9D3C18965F7f6A16B0a0440", "deployed_at": 0 } }, "dest_contracts": { "Avalanche Fuji": { - "off_ramp": "0x6e6fFCb6B4BED91ff0CC8C2e57EC029dA7DB80C2", - "commit_store": "0x38Bc38Bd824b6eE87571f9D3CFbe6D6E28E3Dc62", + "off_ramp": "0x95b66acfaaDF122f4EccE52C0aD4Fd997DD1150C", + "commit_store": "0x3af04b1c1e79A6B8A4577Bb47EC33eD2E66AeB47", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Base Sepolia": { - "off_ramp": "0x2C61FD7E93Dc79422861282145c59B56dFbc3a8c", - "commit_store": "0x42fAe5B3605804CF6d08632d7A25864e24F792Ae", + "off_ramp": "0x0a5147e1Ac38C79c77031194ef64C8B5353F6EE9", + "commit_store": "0x103864D60b33a479EA7D0e23a37e0ce07198f0A9", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Blast Sepolia": { + "off_ramp": "0xe1e8473218acCB82FBc24Ccd3C5D2dF166cd04f3", + "commit_store": "0x020B047A5Ca88fDB1ad3bAD9A082760fC7F770b6", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Gnosis Chiado": { - "off_ramp": "0x71a44a60832B0F8B63232C9516e7E6aEc3A373Dc", - "commit_store": "0xAC24299a91b72d1Cb5B31147e3CF54964D896974", + "off_ramp": "0x1F7FEBCBb10420E039C333A60A444c1a442d826C", + "commit_store": "0x23Ae763a64D39d6038431a64Bbc4A670C89d82b9", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Polygon Amoy": { - "off_ramp": "0x63440C7747d37bc6154b5538AE32b54FE0965AfA", - "commit_store": "0xAD22fA198CECfC534927aE1D480c460d5bB3460F", + "off_ramp": "0xAAe325adbc9C5a28e4e94Fef170D55de2CA9aA01", + "commit_store": "0xD173Df3A1b23ec42eA5C4669b9c956Bef230efd1", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { - "off_ramp": "0xf1c128Fe52Ea78CcAAB407509292E61ce38C1523", - "commit_store": "0x59dFD870dC4bd76A7B879A4f705Fdcd2595f85f9", + "off_ramp": "0xB513523aee87f838e78b32d2Bacaaf2e94D9f0f9", + "commit_store": "0x21A49164890576504C1f1c4DC9442c42C98771D7", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "WeMix Testnet": { - "off_ramp": "0xfd9B19c3725da5B517aA705B848ff3f21F98280e", - "commit_store": "0x3c1F1412563188aBc8FE3fd53E8F1Cb601CaB4f9", + "off_ramp": "0xc985571900DCa62387f93F882AB550472531f5DB", + "commit_store": "0xac5DACfAb1a512E33c49EFE42502863FC1a4BAB3", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -260,68 +278,68 @@ Data = """ "wrapped_native": "0x4200000000000000000000000000000000000006", "src_contracts": { "Arbitrum Sepolia": { - "on_ramp": "0x58622a80c6DdDc072F2b527a99BE1D0934eb2b50", + "on_ramp": "0xb52eF669d3fCeBee1f31418Facc02a16A6F6B0e5", "deployed_at": 0 }, "Avalanche Fuji": { - "on_ramp": "0xAbA09a1b7b9f13E05A6241292a66793Ec7d43357", + "on_ramp": "0x212e8Fd9cCC330ab54E8141FA7d33967eF1eDafF", "deployed_at": 0 }, "BSC Testnet": { - "on_ramp": "0xD806966beAB5A3C75E5B90CDA4a6922C6A9F0c9d", + "on_ramp": "0xd54B44811AE99a18Cb95B4704ba04a65C0163751", "deployed_at": 0 }, "Gnosis Chiado": { - "on_ramp": "0x2Eff2d1BF5C557d6289D208a7a43608f5E3FeCc2", + "on_ramp": "0xdd0Ee1F20E93a93634AAcE56105E19423881Df56", "deployed_at": 0 }, "Mode Sepolia": { - "on_ramp": "0x3d0115386C01436870a2c47e6297962284E70BA6", + "on_ramp": "0xc59689dFDEF9D953cEFbb58912b304bb38408476", "deployed_at": 0 }, "Optimism Sepolia": { - "on_ramp": "0x3b39Cd9599137f892Ad57A4f54158198D445D147", + "on_ramp": "0x2945D35F428CE564F5455AD0AF28BDFCa67e76Ab", "deployed_at": 0 }, "Sepolia Testnet": { - "on_ramp": "0x6486906bB2d85A6c0cCEf2A2831C11A2059ebfea", + "on_ramp": "0x29A1F4ecE9246F0042A9062FB89803fA8B1830cB", "deployed_at": 0 } }, "dest_contracts": { "Arbitrum Sepolia": { - "off_ramp": "0xd364C06ac99a82a00d3eFF9F2F78E4Abe4b9baAA", - "commit_store": "0xdE8d0f47a71eA3fDFBD3162271652f2847939097", + "off_ramp": "0x814E735c5DD19240c85E2513DD926Bc3a39f7140", + "commit_store": "0xFc24B204bfA5C65eD8e2Fc02fDe4FeCb62eA8Ac5", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Avalanche Fuji": { - "off_ramp": "0xAd91214efFee446500940c764DF77AF18427294F", - "commit_store": "0x1242b6c5e0e349b8d4BCf0938f961C4B4f7EA3Fa", + "off_ramp": "0x3Ab3a3d35cAC95FfcFCcc127eF01eA8D87b0A64e", + "commit_store": "0x51313B8C068B5227fa7364E6eCB1382Fb751976F", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "BSC Testnet": { - "off_ramp": "0xd5E9508921434e8758f4540D55c1c066b7cc1598", - "commit_store": "0x1a86b29364D1B3fA3386329A361aA98A104b2742", + "off_ramp": "0x827CF69409307Cd4c979e652894C297ad5124ab7", + "commit_store": "0x547eBe6077305c3fdF8dA66c66cc14b0779CE00C", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Gnosis Chiado": { - "off_ramp": "0x9Bb7e398ef9Acfe9cA584C39B1E233Cba62BB9f7", - "commit_store": "0x1F4B82cDebaC5e3a0Dd53183D47e51808B4a64cB", + "off_ramp": "0x8bB08Bc19771C69E739a2078894523b3DC05a05e", + "commit_store": "0xf163Da63bDB8b9C355d41C755E03125988650109", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Mode Sepolia": { - "off_ramp": "0xB26647A23e8b4284375e5C74b77c9557aE709D03", - "commit_store": "0x4b4fEB401d3E613e1D6242E155C83A80BF9ac2C9", + "off_ramp": "0x11E16c71D76E43acbcb496A70966380d905B1E32", + "commit_store": "0xEe19f039FaE3EF0F94971f0B7B187223D952ac13", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Optimism Sepolia": { - "off_ramp": "0x86a3910908eCaAA31Fcd9F0fC8841D8E98f1511d", - "commit_store": "0xE99a87C9b5ed4D2b6060195DEea5106ffF655736", + "off_ramp": "0x8718d1cc138421Dbc1B489CB7884FF68DE7ad867", + "commit_store": "0x3291D453c880E5b59EEd04E600c85268Cd378b7f", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { - "off_ramp": "0x189F61D9B886Dd2975D5Abc893c8Cf5f5effda71", - "commit_store": "0xEE7e27346DCD1e711348D0F7f7ECB53a9a3a08a7", + "off_ramp": "0x0ecA23Ef70B828fEDd0A84d2692cB0527B52396A", + "commit_store": "0xA7F84Ec616F8e9Fa593339944E76bda90A9737fE", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -340,15 +358,24 @@ Data = """ "price_registry": "0xc8acE9dF450FaD007755C6C9AB4f0e9c8626E29C", "wrapped_native": "0x4200000000000000000000000000000000000023", "src_contracts": { + "BSC Testnet": { + "on_ramp": "0x6eA6f63b689b5597A0C06a5Eb8DcDFD86383857A", + "deployed_at": 0 + }, "Sepolia Testnet": { - "on_ramp": "0x85Ef19FC4C63c70744995DC38CAAEC185E0c619f", + "on_ramp": "0x154aDEF773a848da8229D81De73a7b0844400ebd", "deployed_at": 0 } }, "dest_contracts": { + "BSC Testnet": { + "off_ramp": "0xd9dE4aCD27E814bfe70CA33d2A4d079e740626Bd", + "commit_store": "0xe8fF7e22c54f76F453d6072A9d3a12B1D9AbA137", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, "Sepolia Testnet": { - "off_ramp": "0x92cD24C278D34C726f377703E50875d8f9535dC2", - "commit_store": "0xcE1b4D50CeD56850182Bd58Ace91171cB249B873", + "off_ramp": "0x46DD4e3e2b8a18409646F1C15bf3799a481e67f6", + "commit_store": "0x8250f9E992dda66791dd8b5d356B867ae53382cF", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -368,14 +395,14 @@ Data = """ "wrapped_native": "0x99604d0e2EfE7ABFb58BdE565b5330Bb46Ab3Dca", "src_contracts": { "Sepolia Testnet": { - "on_ramp": "0x16a020c4bbdE363FaB8481262D30516AdbcfcFc8", + "on_ramp": "0x68A4f57A499563192C606a898BAf503A43fcDB4D", "deployed_at": 0 } }, "dest_contracts": { "Sepolia Testnet": { - "off_ramp": "0xa1b97F92D806BA040daf419AFC2765DC723683a4", - "commit_store": "0xcd92C0599Ac515e7588865cC45Eee21A74816aFc", + "off_ramp": "0xF6dB68333D14f6a0c1123cc420ea60980aEDA0Eb", + "commit_store": "0x8f9B63c40891CdF7d1C795625d4260a29bE2bBa0", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -395,68 +422,68 @@ Data = """ "wrapped_native": "0x18c8a7ec7897177E4529065a7E7B0878358B3BfF", "src_contracts": { "Arbitrum Sepolia": { - "on_ramp": "0x473b49fb592B54a4BfCD55d40E048431982879C9", + "on_ramp": "0x94967Ea06C6543Aaba5B90C52B655003ef82e521", "deployed_at": 0 }, "Avalanche Fuji": { - "on_ramp": "0x610F76A35E17DA4542518D85FfEa12645eF111Fc", + "on_ramp": "0x4f3576585e7fCCE5Fc502Bcf3CAdaD22E1194834", "deployed_at": 0 }, "BSC Testnet": { - "on_ramp": "0xE48E6AA1fc7D0411acEA95F8C6CaD972A37721D4", + "on_ramp": "0xB2642B54580140C375c9024e273C575a5f53d02d", "deployed_at": 0 }, "Base Sepolia": { - "on_ramp": "0x41b4A51cAfb699D9504E89d19D71F92E886028a8", + "on_ramp": "0x0E9504907be794620229C196F82CB062A66B7480", "deployed_at": 0 }, "Optimism Sepolia": { - "on_ramp": "0xAae733212981e06D9C978Eb5148F8af03F54b6EF", + "on_ramp": "0xeb86B5b6f5C66eCb58e4Cf98E607b238126505DC", "deployed_at": 0 }, "Polygon Amoy": { - "on_ramp": "0x01800fCDd892e37f7829937271840A6F041bE62E", + "on_ramp": "0xd86F5DF82A2500137Ddeef963028d60E3b5A354D", "deployed_at": 0 }, "Sepolia Testnet": { - "on_ramp": "0x4ac7FBEc2A7298AbDf0E0F4fDC45015836C4bAFe", + "on_ramp": "0x03691D63C687D09368360e957AFB2F7B4d1651d4", "deployed_at": 0 } }, "dest_contracts": { "Arbitrum Sepolia": { - "off_ramp": "0x9aA82DBB53bf02096B771D40e9432A323a78fB26", - "commit_store": "0x5CdbA91aBC0cD81FC56bc10Ad1835C9E5fB38e5F", + "off_ramp": "0x3633Cce99186217d4C7ed64FD455d218b8Cd5D4c", + "commit_store": "0x6e096286548451828c97F1B3E49C402a4934F39a", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Avalanche Fuji": { - "off_ramp": "0x3e33290B90fD0FF30a3FA138934DF028E4eCA348", - "commit_store": "0xCFe3556Aa42d40be09BD23aa80448a19443BE5B1", + "off_ramp": "0x5E4DB2A3c965B9B2A850a75697Bb6a00b4e35ac5", + "commit_store": "0x2489c5a802fE63943f7E3185A0362327B55DDF67", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "BSC Testnet": { - "off_ramp": "0xbc4AD54e91b213D4279af92c0C5518c0b96cf62D", - "commit_store": "0xff84e8Dd4Fd17eaBb23b6AeA6e1981830e54389C", + "off_ramp": "0x2BA72Ba392C08750328635E36757A2c29a9165CA", + "commit_store": "0x08ebd7Cf4ABDC819c74cB45CbA4e291728538D7C", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Base Sepolia": { - "off_ramp": "0x4117953A5ceeF12f5B8C1E973b470ab83a8CebA6", - "commit_store": "0x94ad41296186E81f31e1ed0B1BcF5fa9e1721C27", + "off_ramp": "0x269D28B25Ee081ae5340e2BFE99850E92F1cd522", + "commit_store": "0x8dC9329BD221C89c4989d98c38Ff2Cc3dF92d14b", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Optimism Sepolia": { - "off_ramp": "0x33d2898F8fb7714FD1661791766f40754982a343", - "commit_store": "0x55d6Df194472f02CD481e506A277c4A29D0D1bCc", + "off_ramp": "0xd93B571ae9CaF43d70b2b53fFD55e035Db641e31", + "commit_store": "0x42C1093b9DdE8d0CD58859C610dc239B66bE26de", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Polygon Amoy": { - "off_ramp": "0x450543b1d85ca79885851D7b74dc982981b78229", - "commit_store": "0x23B79d940A769FE31b4C867A8BAE80117f24Ca81", + "off_ramp": "0x87F9b8382611ACD01d5696a1f5b05B888e55B0Cc", + "commit_store": "0x29AC46227908d31A9BdDe82c0A4a6c52D802f145", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { - "off_ramp": "0xbf9036529123DE264bFA0FC7362fE25B650D4B16", - "commit_store": "0x5f7F1abD5c5EdaF2636D58B980e85355AF0Ef80d", + "off_ramp": "0x9aa734100C425309091dAE18154e0356B82d477a", + "commit_store": "0x7cDd533B82f4c32FAE7f551C37b1490909817C45", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -476,14 +503,14 @@ Data = """ "wrapped_native": "0x4200000000000000000000000000000000000001", "src_contracts": { "WeMix Testnet": { - "on_ramp": "0x6ea155Fc77566D9dcE01B8aa5D7968665dc4f0C5", + "on_ramp": "0xa81418c332d3E04338B058Ab39b1baf53029F638", "deployed_at": 0 } }, "dest_contracts": { "WeMix Testnet": { - "off_ramp": "0xB602B6E5Caf08ac0C920EAE585aed100a8cF6f3B", - "commit_store": "0x89D5b13908b9063abCC6791dc724bF7B7c93634C", + "off_ramp": "0x42Dde725C4f05C237a00B582Bb7457e208d3A17C", + "commit_store": "0xb116E9a90534354dA59CF93a87c1E9711c0Aaa2c", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -502,15 +529,24 @@ Data = """ "price_registry": "0x5DCE866b3ae6E0Ed153f0e149D7203A1B266cdF5", "wrapped_native": "0x5c48e07062aC4E2Cf4b9A768a711Aef18e8fbdA0", "src_contracts": { + "Arbitrum Sepolia": { + "on_ramp": "0x2eb69889cc979c0Be120813FcE2f1558efF4ceB5", + "deployed_at": 0 + }, "Sepolia Testnet": { - "on_ramp": "0x2Eff2d1BF5C557d6289D208a7a43608f5E3FeCc2", + "on_ramp": "0xE0dFc15C0CDf607b2088D0B641E00eA0B418124C", "deployed_at": 0 } }, "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0x839b5dEA3e084790F580E9DfCE8CCfDf49c5835e", + "commit_store": "0xdF38C8aD34C379165f98A75a6894790bB5a16b1D", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, "Sepolia Testnet": { - "off_ramp": "0x9Bb7e398ef9Acfe9cA584C39B1E233Cba62BB9f7", - "commit_store": "0x1F4B82cDebaC5e3a0Dd53183D47e51808B4a64cB", + "off_ramp": "0x72130De9A85e9C61151253aFF8801Bb3242A00a9", + "commit_store": "0x8F6D64280C379F680Ff0c3278f340D72a465FAAc", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -530,23 +566,23 @@ Data = """ "wrapped_native": "0x4200000000000000000000000000000000000006", "src_contracts": { "Base Sepolia": { - "on_ramp": "0x73f7E074bd7291706a0C5412f51DB46441B1aDCB", + "on_ramp": "0x48ACE2319f643584B77C21476a6c664D7F13a107", "deployed_at": 0 }, "Sepolia Testnet": { - "on_ramp": "0xfFdE9E8c34A27BEBeaCcAcB7b3044A0A364455C9", + "on_ramp": "0xb821885731414497d705dc56325f18AA33e612dC", "deployed_at": 0 } }, "dest_contracts": { "Base Sepolia": { - "off_ramp": "0x137a38c6b1Ad20101F93516aB2159Df525309168", - "commit_store": "0x8F43d867969F14619895d71E0A5b89E0bb20bF70", + "off_ramp": "0xC6b69Fa9eeBc55e64eBc68371Fbd41ff73756F17", + "commit_store": "0xaA6691EA9110409a29C2E665174b4b2fe694cE67", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { - "off_ramp": "0xcD44cec849B6a8eBd5551D6DFeEcA452257Dfe4d", - "commit_store": "0xbA66f08733E6715D33edDfb5a5947676bb45d0e0", + "off_ramp": "0x35dE2C381a2fF8a26c8ae94145be3A9cA8C83600", + "commit_store": "0xE7e60DAee094416b8ab2083047a893c4c4290c48", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -566,68 +602,68 @@ Data = """ "wrapped_native": "0x4200000000000000000000000000000000000006", "src_contracts": { "Arbitrum Sepolia": { - "on_ramp": "0x1a86b29364D1B3fA3386329A361aA98A104b2742", + "on_ramp": "0x6B36c9CD74E760088817a047C3460dEdFfe9a11A", "deployed_at": 0 }, "Avalanche Fuji": { - "on_ramp": "0x6b38CC6Fa938D5AB09Bdf0CFe580E226fDD793cE", + "on_ramp": "0x91a144F570ABA7FB7079Fb187A267390E0cc7367", "deployed_at": 0 }, "Base Sepolia": { - "on_ramp": "0xe284D2315a28c4d62C419e8474dC457b219DB969", + "on_ramp": "0x6D22953cdEf8B0C9F0976Cfa52c33B198fEc5881", "deployed_at": 0 }, "Gnosis Chiado": { - "on_ramp": "0x835a5b8e6CA17c2bB5A336c93a4E22478E6F1C8A", + "on_ramp": "0xec7D9A84A6d4556056975BE50Cdc97bAa9313632", "deployed_at": 0 }, "Polygon Amoy": { - "on_ramp": "0x2Cf26fb01E9ccDb831414B766287c0A9e4551089", + "on_ramp": "0x9E09C2A7D6B9F88c62f0E2Af4cd62dF3F4c326F1", "deployed_at": 0 }, "Sepolia Testnet": { - "on_ramp": "0xC8b93b46BF682c39B3F65Aa1c135bC8A95A5E43a", + "on_ramp": "0x54b32C2aCb4451c6cF66bcbd856d8A7Cc2263531", "deployed_at": 0 }, "WeMix Testnet": { - "on_ramp": "0xc7E53f6aB982af7A7C3e470c8cCa283d3399BDAd", + "on_ramp": "0xB9Ef21C04d8340b223e9C1d7a09f332609c70300", "deployed_at": 0 } }, "dest_contracts": { "Arbitrum Sepolia": { - "off_ramp": "0xDc2c7A3d8068C6F09F0F3648d24C84e372F6014d", - "commit_store": "0xb1aFb5cbE3c29b5Db71F21442BA9EfD450BC23C3", + "off_ramp": "0xF35e2d1457749374453e44B06268aD3f78b133b3", + "commit_store": "0x4bd755d86E25dD4093CAa5639CfDab81571259CA", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Avalanche Fuji": { - "off_ramp": "0x1F350718e015EB20E5065C09F4A7a3f66888aEeD", - "commit_store": "0x98650A8EB59f75D93563aB34FcF603b1A30e4CBF", + "off_ramp": "0xCb2266c2118b1f30D15CBeB3a885531ABaA1b556", + "commit_store": "0x5Ded92E2CF71a8fF7644a67850F061c38B31BfB4", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Base Sepolia": { - "off_ramp": "0x0a750ca77369e03613d7640548F4b2b1c695c3Bb", - "commit_store": "0x8fEBC74C26129C8d7E60288C6dCCc75eb494aA3C", + "off_ramp": "0x960c62A491C30d0a60fD74a59d35B9C02697AdaA", + "commit_store": "0x06963745B3839B998288D1a46a46Ec25991A3D5E", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Gnosis Chiado": { - "off_ramp": "0xCE2CE7F940B7c839384e5D7e079A6aE80e8AD6dB", - "commit_store": "0x1b9D78Ec1CEEC439F0b7eA6C428A1a607D9FA7e4", + "off_ramp": "0x7d6721c2E85560F0A233255D3d332AcF6f850d96", + "commit_store": "0xaC00661cAB5161d9B4746DFb7A028d97981aB2c5", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Polygon Amoy": { - "off_ramp": "0xD667b5706592D0b040C78fEe5EE17D243b7dCB41", - "commit_store": "0x96101BA5250EE9295c193693C1e08A55bC593664", + "off_ramp": "0x4cEeFa55AF23dFD27Cf926e8eFB1D1bCcD24526E", + "commit_store": "0xaD3943BdECbf4ae7d6E51aB0FD06bbC604bB7b95", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { - "off_ramp": "0x260AF9b83e0d2Bb6C9015fC9f0BfF8858A0CCE68", - "commit_store": "0x7a0bB92Bc8663abe6296d0162A9b41a2Cb2E0358", + "off_ramp": "0x2aF9B10A5972D0c36f4d8F85773052c104E319B2", + "commit_store": "0x82FCF55b9e9bAb3066c2863F12a02bBc2Ba33F2F", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "WeMix Testnet": { - "off_ramp": "0x9C08B7712af0344188aa5087D9e6aD0f47191037", - "commit_store": "0x4BE6DB0B884169a6A207fe5cad01eB4C025a13dB", + "off_ramp": "0x0FA15Bc42D4999d964CBf0161489Bd392DEE834e", + "commit_store": "0x37760F99a5b91884C9D89a06408f532aEbb0e674", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -647,59 +683,59 @@ Data = """ "wrapped_native": "0x360ad4f9a9A8EFe9A8DCB5f461c4Cc1047E1Dcf9", "src_contracts": { "Avalanche Fuji": { - "on_ramp": "0x8Fb98b3837578aceEA32b454f3221FE18D7Ce903", + "on_ramp": "0xad6A94CFB51e7DE30FD21F417E4cBf70D3AdaD30", "deployed_at": 0 }, "BSC Testnet": { - "on_ramp": "0xC6683ac4a0F62803Bec89a5355B36495ddF2C38b", + "on_ramp": "0x28EC0a9C90360F55C2a9DaD5901b074C257904ca", "deployed_at": 0 }, "Gnosis Chiado": { - "on_ramp": "0x2331F6D614C9Fd613Ff59a1aB727f1EDf6c37A68", + "on_ramp": "0x9DF611536f124278Ce968c476BDb10A66E54ecfE", "deployed_at": 0 }, "Optimism Sepolia": { - "on_ramp": "0xA52cDAeb43803A80B3c0C2296f5cFe57e695BE11", + "on_ramp": "0x600f00aef9b8ED8EDBd7284B5F04a1932c3408aF", "deployed_at": 0 }, "Sepolia Testnet": { - "on_ramp": "0x35347A2fC1f2a4c5Eae03339040d0b83b09e6FDA", + "on_ramp": "0x719Aef2C63376AdeCD62D2b59D54682aFBde914a", "deployed_at": 0 }, "WeMix Testnet": { - "on_ramp": "0x26546096F64B5eF9A1DcDAe70Df6F4f8c2E10C61", + "on_ramp": "0x7D6c93E49E46cc983a677c283EAb27CbbC94e3C4", "deployed_at": 0 } }, "dest_contracts": { "Avalanche Fuji": { - "off_ramp": "0xa733ce82a84335b2E9D864312225B0F3D5d80600", - "commit_store": "0x09B0F93fC2111aE439e853884173AC5b2F809885", + "off_ramp": "0xAc56Df7F5fbde0DeeB1C0d397A150EDD5EE68625", + "commit_store": "0x8AF56D1c76B8c8CeE451a0a654D130e4050B993e", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "BSC Testnet": { - "off_ramp": "0x948dfaa4842fc23e0e362Fe8D4396AaE4E6DF7EA", - "commit_store": "0x7F4e739D40E58BBd59dAD388171d18e37B26326f", + "off_ramp": "0x40Ba47ea59D80DDd35E3a997AA520FBa0553dddc", + "commit_store": "0x8afe532517b39bA109d1A768E1Ad8b5C6485abF5", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Gnosis Chiado": { - "off_ramp": "0x17c542a28e08AEF5697251601C7b2B621d153D42", - "commit_store": "0x811250c20fAB9a1b7ca245453aC214ba637fBEB5", + "off_ramp": "0x7B968B2aDFd31765dAAD80d66c83F9D7006BFFd5", + "commit_store": "0xBc70551B5624BaF8cdCB84136198561C9cf5C176", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Optimism Sepolia": { - "off_ramp": "0xfFdE9E8c34A27BEBeaCcAcB7b3044A0A364455C9", - "commit_store": "0x74ED442ad211050e9C05Dc9A267E037E3d74A03B", + "off_ramp": "0xAA755Ef570986feEb6522377077e549e3013843E", + "commit_store": "0x5C7827EcE6a51AdaC36ef71aC01706deb1C7130d", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { - "off_ramp": "0xFb04129aD1EEDB741CC705ebC1978a7aB63e51f6", - "commit_store": "0x63f875240149d29136053C954Ca164a9BfA81F77", + "off_ramp": "0x7Ad494C173f5845c6B4028a06cDcC6d3108bc960", + "commit_store": "0x104A1c8b05D37fE732094595Fe696AFc7EAB8668", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "WeMix Testnet": { - "off_ramp": "0xdE8451E952Eb43350614839cCAA84f7C8701a09C", - "commit_store": "0xaCdaBa07ECad81dc634458b98673931DD9d3Bc14", + "off_ramp": "0xa85481273f8C112e96ED7476202F06D6131cf069", + "commit_store": "0x9FdF1D555e37dB09B0d151FEa53c134C88C4DeFd", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -719,122 +755,122 @@ Data = """ "wrapped_native": "0x097D90c9d3E0B50Ca60e1ae45F6A81010f9FB534", "src_contracts": { "Arbitrum Sepolia": { - "on_ramp": "0xe4Dd3B16E09c016402585a8aDFdB4A18f772a07e", + "on_ramp": "0xBc09627e58989Ba8F1eDA775e486467d2A00944F", "deployed_at": 0 }, "Avalanche Fuji": { - "on_ramp": "0x0477cA0a35eE05D3f9f424d88bC0977ceCf339D4", + "on_ramp": "0x12492154714fBD28F28219f6fc4315d19de1025B", "deployed_at": 0 }, "BSC Testnet": { - "on_ramp": "0xD990f8aFA5BCB02f95eEd88ecB7C68f5998bD618", + "on_ramp": "0x7a75b3818412fe0028590feE8270ba9E3fd01DBe", "deployed_at": 0 }, "Base Sepolia": { - "on_ramp": "0x2B70a05320cB069e0fB55084D402343F832556E7", + "on_ramp": "0x8F35B097022135E0F46831f798a240Cc8c4b0B01", "deployed_at": 0 }, "Blast Sepolia": { - "on_ramp": "0xDB75E9D9ca7577CcBd7232741be954cf26194a66", + "on_ramp": "0x4ADA60556dA05FcF53a79359e37a3E13FebA22Bf", "deployed_at": 0 }, "Celo Alfajores": { - "on_ramp": "0x3C86d16F52C10B2ff6696a0e1b8E0BcfCC085948", + "on_ramp": "0x1163D1F7D75eEb1C4f4c6912d3cF9642027aFD30", "deployed_at": 0 }, "Gnosis Chiado": { - "on_ramp": "0x3E842E3A79A00AFdd03B52390B1caC6306Ea257E", + "on_ramp": "0x831A7DbE6af8601427A0ADa89b642d4b59007eED", "deployed_at": 0 }, "Metis Sepolia": { - "on_ramp": "0x1C4640914cd57c5f02a68048A0fbb0E12d904223", + "on_ramp": "0xabB5A4f99DFEb4a3912e8Acc0660A008c76dA8c3", "deployed_at": 0 }, "Mode Sepolia": { - "on_ramp": "0xc630fbD4D0F6AEB00aD0793FB827b54fBB78e981", + "on_ramp": "0x2Eb0842925fb7aA6045e951e98e8b4b3aFFaBB54", "deployed_at": 0 }, "Optimism Sepolia": { - "on_ramp": "0x69CaB5A0a08a12BaFD8f5B195989D709E396Ed4d", + "on_ramp": "0xACDfd7a98d853FA3914047Cd46e7f5D53BBC9FbB", "deployed_at": 0 }, "Polygon Amoy": { - "on_ramp": "0x9f656e0361Fb5Df2ac446102c8aB31855B591692", + "on_ramp": "0xf9765c80F6448e6d4d02BeF4a6b4152131A2F513", "deployed_at": 0 }, "WeMix Testnet": { - "on_ramp": "0xedFc22336Eb0B9B11Ff37C07777db27BCcDe3C65", + "on_ramp": "0xd72c3c132B76F5D232C37dF3bF8f04392D552e0F", "deployed_at": 0 }, "ZKSync Sepolia": { - "on_ramp": "0x1Acb3A885feA37bdA30AB99b99327b14391f500F", + "on_ramp": "0xA2865E4f36760f5fa5c8F958336120f2DF0d974b", "deployed_at": 0 } }, "dest_contracts": { "Arbitrum Sepolia": { - "off_ramp": "0xF18896AB20a09A29e64fdEbA99FDb8EC328f43b1", - "commit_store": "0x93Ff9Dd39Dc01eac1fc4d2c9211D95Ee458CAB94", + "off_ramp": "0xD2f5edfD4561d6E7599F6c6888Bd353cAFd0c55E", + "commit_store": "0x240420BC6bCDc067e668c7492D69fe06B3CF80cE", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Avalanche Fuji": { - "off_ramp": "0x000b26f604eAadC3D874a4404bde6D64a97d95ca", - "commit_store": "0x2dD9273F8208B8393350508131270A6574A69784", + "off_ramp": "0x1DEBa99dC8e2A77832461BD386d83D9FCb133137", + "commit_store": "0x139E06b6dBB1a0C41A1686C091795879c943765A", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "BSC Testnet": { - "off_ramp": "0xdE2d8E126e08d675fCD7fFa5a6CE49925f3Dc692", - "commit_store": "0x0050ac355a82caB31194507f94174297bf0655A7", + "off_ramp": "0x04305BD9D9CA6730517f79c3D9c6828BC2D25Ecb", + "commit_store": "0x32edD59840CD9e474A280cf1707439F2Bd5872d4", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Base Sepolia": { - "off_ramp": "0x31c0B81832B333419f0DfD36A69F502cF9094aed", - "commit_store": "0xDFcde9d698a2B32DB2537DC9B752Cadd1D846a52", + "off_ramp": "0x662738DC7DE4f7eC63d9f73Cdf9BeA5A58DdcC15", + "commit_store": "0x1e46bAC486Dd878cD57B62845530A52343e39693", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Blast Sepolia": { - "off_ramp": "0x4e897e5cF3aC307F0541B2151A88bCD781c153a3", - "commit_store": "0xB656652841F347178e193951C4663652aCe36B74", + "off_ramp": "0x049A424cF894709f044bc70177F8F6b792adc3F6", + "commit_store": "0x496fE96E440Fc683478a08Df92A1c5E23E412b1C", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Celo Alfajores": { - "off_ramp": "0xB435E0f73c18C5a12C324CA1d02F81F2C3e6e761", - "commit_store": "0xbc5d74957F171e75F92c8F0E1C317A25a56a416D", + "off_ramp": "0x4F146d34Be5E273e576ef158Bd7070eC22708D20", + "commit_store": "0xEeB665281c7ab51d25423898f730Ab078c69dd42", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Gnosis Chiado": { - "off_ramp": "0x7db0115A0b3AAb01d30bf81123c5DD7B0C41Add5", - "commit_store": "0x6640723Ea801178c4383FA016b9781e7ef1016EF", + "off_ramp": "0xB424365EEEEA58A36C7EC858f926f4e8275dDEb3", + "commit_store": "0xE95c2135e3330E953BB49068d32Fcba368Acd456", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Metis Sepolia": { - "off_ramp": "0x4DB693A93E9d5196ECD42EC56CDEAe99dFC652ED", - "commit_store": "0xBfACd78F1412B6f93Ac23409bf456aFec1ABd845", + "off_ramp": "0x46DE6201c258f5948135cd0262f91e48Cb8e3828", + "commit_store": "0x3A27Fd059A4eF0e96B0643283A44a56A8d6CF34A", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Mode Sepolia": { - "off_ramp": "0xbEfd8D65F6643De54F0b1268A3bf4618ff85dcB4", - "commit_store": "0x0C161D3470b45Cc677661654C30ce4AdE6aCD288", + "off_ramp": "0x052E52fdd48719A6084366eA184FC44cb8C25DC2", + "commit_store": "0xBBb9baA314eB023E3F9291Aaf4107B6708341B50", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Optimism Sepolia": { - "off_ramp": "0xD50590D4438411EDe47029b0FD7901A7145E5Df6", - "commit_store": "0xe85EEE9Fd434A7b8a586Ee086E828abF41839479", + "off_ramp": "0xbfa6f6AAE31acB3A285e80026d6475C1a50d1d0F", + "commit_store": "0xB5FbA97Dc61ec68771a92a15360d9C32c9d054E7", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Polygon Amoy": { - "off_ramp": "0x5032cbC0C4aEeD25bb6E45D8B3fAF05DB0688C5d", - "commit_store": "0xe6201C9996Cc7B6E828E10CbE937E693d577D318", + "off_ramp": "0xC3e550B6aaFA5539df8bbCc5B0991e587f438e75", + "commit_store": "0xd57866D97ca26dfaE34088a3EeE4657BAFaac5f9", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "WeMix Testnet": { - "off_ramp": "0x46b639a3C1a4CBfD326b94a2dB7415c27157282f", - "commit_store": "0x7b74554678816b045c1e7409327E086bD436aa46", + "off_ramp": "0x445F41C6aa7e910021786e860d7cfe3E7fcC6640", + "commit_store": "0x307dDE3c696E399b5837456FbCe03b1Ad76D46E3", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "ZKSync Sepolia": { - "off_ramp": "0xBaABd4166C892a1081a26535875A8fA3f22937b2", - "commit_store": "0xfda2e83F4D3f42B7629134ecD6E4b29FB8A7A07B", + "off_ramp": "0x9f5dC467A5c97068A1c2987486B8b768275627eD", + "commit_store": "0x6e4601DA99a046e4bde60d051568E3E1F35E3097", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -854,68 +890,68 @@ Data = """ "wrapped_native": "0xbE3686643c05f00eC46e73da594c78098F7a9Ae7", "src_contracts": { "Arbitrum Sepolia": { - "on_ramp": "0xA9DE3F7A617D67bC50c56baaCb9E0373C15EbfC6", + "on_ramp": "0xa5Be8C619F61505548992D9820c5c485b030C7B0", "deployed_at": 0 }, "Avalanche Fuji": { - "on_ramp": "0xC4aC84da458ba8e40210D2dF94C76E9a41f70069", + "on_ramp": "0x7802B6804bbE7486229ac6D3519f0057c50b40a9", "deployed_at": 0 }, "BSC Testnet": { - "on_ramp": "0x5AD6eed6Be0ffaDCA4105050CF0E584D87E0c2F1", + "on_ramp": "0xd25B8c70CB43022Bdc3aC417E2Cf5159294d95A1", "deployed_at": 0 }, "Kroma Sepolia": { - "on_ramp": "0x428C4dc89b6Bf908B82d77C9CBceA786ea8cc7D0", + "on_ramp": "0x1De2Ca07eEee7F524Fe5edA6C8FFFb79F67b05E9", "deployed_at": 0 }, "Optimism Sepolia": { - "on_ramp": "0x1961a7De751451F410391c251D4D4F98D71B767D", + "on_ramp": "0xB37607C6BD4562F32967dE87D14663D59e3f655d", "deployed_at": 0 }, "Polygon Amoy": { - "on_ramp": "0xd55148e841e76265B484d399eC71b7076ecB1216", + "on_ramp": "0x0c972752F9aC3255cE45b440f9bBC6500676c4e6", "deployed_at": 0 }, "Sepolia Testnet": { - "on_ramp": "0x4d57C6d8037C65fa66D6231844785a428310a735", + "on_ramp": "0x1CD55c65f85681Dfae47c62e6D93340D25006BbB", "deployed_at": 0 } }, "dest_contracts": { "Arbitrum Sepolia": { - "off_ramp": "0xeB1dFaB2464Bf0574D43e764E0c758f92e7ecAFb", - "commit_store": "0xcEaCa2B7890065c485f3E58657358a185Ad33791", + "off_ramp": "0xB5492C8A71130B486fAD1091Db683584767A3957", + "commit_store": "0x1e151ED27E2F48EcFBd5b4374d0fc4869e07c397", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Avalanche Fuji": { - "off_ramp": "0x98e811Df9D2512f1aaf58D534607F583D6c54A4F", - "commit_store": "0x8e538351F6E5B2daF3c90C565C3738bca69a2716", + "off_ramp": "0x60536c757c2BBf72cC68A1933F7e336d03Bb68fe", + "commit_store": "0x2fF725556A04b47eB40BbA11d9F51e8fbbee9F07", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "BSC Testnet": { - "off_ramp": "0xB0e7f0fCcD3c961C473E7c44D939C1cDb4Cec1cB", - "commit_store": "0x4B56D8d53f1A6e0117B09700067De99581aA5542", + "off_ramp": "0xb858077FbE1E55cD7a9092Eb6d5403e068c14EAf", + "commit_store": "0x0EF13C7c95C27A9EA477363a26a09Cff44ba38F9", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Kroma Sepolia": { - "off_ramp": "0xD685D2d224dd6D0Db2D56497db6270D77D9a7966", - "commit_store": "0x7e062D6880779a0347e7742058C1b1Ee4AA0B137", + "off_ramp": "0x78d8154e1216F4791086bFa078Aaf07dcD2bD3C6", + "commit_store": "0xe67AAfbE6025e730Cf47a414BEFf2106FF231dB1", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Optimism Sepolia": { - "off_ramp": "0xA5f97Bc69Bf06e7C37B93265c5457420A92c5F4b", - "commit_store": "0xd48b9213583074f518D8f4336FDf35370D450132", + "off_ramp": "0x995Fc17FC12b67f75D3cBf3bC71BD9af65671E78", + "commit_store": "0xD0825e3D8e61b67a06A93426749d38bCF73Ddb02", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Polygon Amoy": { - "off_ramp": "0x6c8f5999B06FDE17B11E4e3C1062b761766F960f", - "commit_store": "0x957c3c2056192e58A8485eF31165fC490d474239", + "off_ramp": "0xd7b5B4F8FF7a87cC92f7B3058365862859d9E057", + "commit_store": "0xa8f2bb4e831caA5E2794AaD014030E378208d4Bc", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { - "off_ramp": "0x8AB103843ED9D28D2C5DAf5FdB9c3e1CE2B6c876", - "commit_store": "0x7d5297c5506ee2A7Ef121Da9bE02b6a6AD30b392", + "off_ramp": "0xa7E2F97Be7798327A49CACD022f33c0E7EfD4897", + "commit_store": "0x6fe69eE4eC9FD768193a40129A3Ba3dF140b2208", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -923,20 +959,26 @@ Data = """ "ZKSync Sepolia": { "is_native_fee_token": true, "fee_token": "0x4317b2eCD41851173175005783322D29E9bAee9E", + "bridge_tokens": [ + "0xFf6d0c1518A8104611f482eb2801CaF4f13c9dEb" + ], + "bridge_tokens_pools": [ + "0xA16cfA090aA6888AE8Beb92F8bfD316DD05767C9" + ], "arm": "0x926b4f90610Aa448f27c8e0Fd0afa4A17B7305F9", "router": "0xA1fdA8aa9A8C4b945C45aD30647b01f07D7A0B16", "price_registry": "0x648B6BB09bE1C5766C8AC578B9B4aC8497eA671F", "wrapped_native": "0x4317b2eCD41851173175005783322D29E9bAee9E", "src_contracts": { "Sepolia Testnet": { - "on_ramp": "0x79a9a5e9e318e8e109776569574814bbf935125a", + "on_ramp": "0xC38536521fde8556351aB7C4D3ea23b64AFbBbab", "deployed_at": 0 } }, "dest_contracts": { "Sepolia Testnet": { - "off_ramp": "0x18FF69051479796175852578725Fc74F58E963F8", - "commit_store": "0xF694b4FD7889480dca3CD41244e8e3395a9EFBa0", + "off_ramp": "0x19Ea9A42cd3682928aF19990dDb3904250D00a1D", + "commit_store": "0x20BF9037927bFadaF028D43ae07d1afccfB8fa85", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -976,7 +1018,7 @@ NetworkPairs = [ 'SEPOLIA,ARBITRUM_SEPOLIA', 'SEPOLIA,BASE_SEPOLIA', 'SEPOLIA,BLAST_SEPOLIA', - 'SEPOLIA,MODE_SEPOLIA', +# 'SEPOLIA,MODE_SEPOLIA', 'SEPOLIA,OPTIMISM_SEPOLIA', 'SEPOLIA,POLYGON_AMOY', 'SEPOLIA,WEMIX_TESTNET', @@ -1002,7 +1044,7 @@ NetworkPairs = [ 'ARBITRUM_SEPOLIA,WEMIX_TESTNET', 'ARBITRUM_SEPOLIA,GNOSIS_CHIADO', - 'BASE_SEPOLIA,MODE_SEPOLIA', +# 'BASE_SEPOLIA,MODE_SEPOLIA', 'BASE_SEPOLIA,OPTIMISM_SEPOLIA', 'BASE_SEPOLIA,GNOSIS_CHIADO', diff --git a/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/soak-release-testing_token_transfer_with_native_feetoken.toml b/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/soak-release-testing_token_transfer_with_native_feetoken.toml index 6a6aa205fce..9c22063f11d 100644 --- a/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/soak-release-testing_token_transfer_with_native_feetoken.toml +++ b/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/soak-release-testing_token_transfer_with_native_feetoken.toml @@ -26,59 +26,68 @@ Data = """ "wrapped_native": "0xE591bf0A0CF924A0674d7792db046B23CEbF5f34", "src_contracts": { "Avalanche Fuji": { - "on_ramp": "0x1Cb56374296ED19E86F68fA437ee679FD7798DaA", + "on_ramp": "0x20C8c9F13C6AA402F2545AD15fB7a9CdE9108618", "deployed_at": 0 }, "Base Sepolia": { - "on_ramp": "0x7854E73C73e7F9bb5b0D5B4861E997f4C6E8dcC6", + "on_ramp": "0xF1623862e4c9f9Fba1Ac0181C4fF53B4f958F065", "deployed_at": 0 }, "Gnosis Chiado": { - "on_ramp": "0x973CbE752258D32AE82b60CD1CB656Eebb588dF0", + "on_ramp": "0xEfe02eB139D2A82e38184d28E3b65bb176F26ebD", + "deployed_at": 0 + }, + "Metis Sepolia": { + "on_ramp": "0x46a79a6a4B07FD3FC14ea8299A99FE29576776E2", "deployed_at": 0 }, "Optimism Sepolia": { - "on_ramp": "0x701Fe16916dd21EFE2f535CA59611D818B017877", + "on_ramp": "0x0B0c08Bb2fA2EbDe25817009ee39eA1ad9bCaC58", "deployed_at": 0 }, "Sepolia Testnet": { - "on_ramp": "0x4205E1Ca0202A248A5D42F5975A8FE56F3E302e9", + "on_ramp": "0x64d78F20aD987c7D52FdCB8FB0777bD00de53210", "deployed_at": 0 }, "WeMix Testnet": { - "on_ramp": "0xBD4106fBE4699FE212A34Cc21b10BFf22b02d959", + "on_ramp": "0x2F3Daf77A663603826c7750E956b6555DE6f8250", "deployed_at": 0 } }, "dest_contracts": { "Avalanche Fuji": { - "off_ramp": "0xcab0EF91Bee323d1A617c0a027eE753aFd6997E4", - "commit_store": "0x0d90b9b96cBFa0D01635ce12982ccE1b70827c7a", + "off_ramp": "0x7245a5947E2F32B66aF74F4dAF91718ea19afaDf", + "commit_store": "0x490AC77BbB26f4FFf876Ded07bCAE6DBe685be98", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Base Sepolia": { - "off_ramp": "0xc1982985720B959E66c19b64F783361Eb9B60F26", - "commit_store": "0x28F66bB336f6db713d6ad2a3bd1B7a531282A159", + "off_ramp": "0xF2aB55Ed448A6fAD75013900568B6a927f52e5e0", + "commit_store": "0x833E5995A7422120f445f9B8dD1b9BD1037c68E5", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Gnosis Chiado": { - "off_ramp": "0x935C26F9a9122E5F9a27f2d3803e74c75B94f5a3", - "commit_store": "0xEdb963Ec5c2E5AbdFdCF137eF44A445a7fa4787A", + "off_ramp": "0xc1Cb31493fB2386aDC1Ea01F935F2bd8a8dCA388", + "commit_store": "0xe21896657A65c8959F16E1c3Ee5713E85d9EA020", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Metis Sepolia": { + "off_ramp": "0xc47143147Fd62A09618C695c7C03714aCe8db1Cf", + "commit_store": "0x2F42e7B22eE5885158916624Ff00608f4C82313D", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Optimism Sepolia": { - "off_ramp": "0xfD404A89e1d195F0c65be1A9042C77745197659e", - "commit_store": "0x84B7B012c95f8A152B44Ab3e952f2dEE424fA8e1", + "off_ramp": "0x4a7E91EF68758aaC66AeD656267bbCD0f9b6c019", + "commit_store": "0xb0A09D6A15FF7A0142DF3F62b2C4D1e11D763Ed0", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { - "off_ramp": "0x1c71f141b4630EBE52d6aF4894812960abE207eB", - "commit_store": "0xaB0c8Ba51E7Fa3E5693a4Fbb39473520FD85d173", + "off_ramp": "0xBed6e9131916d724418C8a6FE810F727302a5c00", + "commit_store": "0xdDb61B6bDa1B46d88f556440fABFe219F6da4F3a", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "WeMix Testnet": { - "off_ramp": "0x262e16C8D42aa07bE13e58F81e7D9F62F6DE2830", - "commit_store": "0xc132eFAf929299E5ee704Fa6D9796CFa23Bb8b2C", + "off_ramp": "0x11d486E92d291704D1E25cDbAeee687237247826", + "commit_store": "0xece9353095aC79Db9DD5bf2022690Fa6BffeBCAc", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -98,77 +107,77 @@ Data = """ "wrapped_native": "0xd00ae08403B9bbb9124bB305C09058E32C39A48c", "src_contracts": { "Arbitrum Sepolia": { - "on_ramp": "0x8bB16BEDbFd62D1f905ACe8DBBF2954c8EEB4f66", + "on_ramp": "0xa9946BA30DAeC98745755e4410d6e8E894Edc53B", "deployed_at": 0 }, "BSC Testnet": { - "on_ramp": "0xF25ECF1Aad9B2E43EDc2960cF66f325783245535", + "on_ramp": "0x906BC7D10947A94ba0252e8C2E34868A466c03ED", "deployed_at": 0 }, "Base Sepolia": { - "on_ramp": "0x1A674645f3EB4147543FCA7d40C5719cbd997362", + "on_ramp": "0x0aEc1AC9F6D0c21332d7a66dDF1Fbcb32cF3B0B3", "deployed_at": 0 }, "Gnosis Chiado": { - "on_ramp": "0x1532e5b204ee2b2244170c78E743CB9c168F4DF9", + "on_ramp": "0x3dda45E731EC1db18B95651d1AF1868aa878468D", "deployed_at": 0 }, "Optimism Sepolia": { - "on_ramp": "0xC334DE5b020e056d0fE766dE46e8d9f306Ffa1E2", + "on_ramp": "0x2a9EFdc9F93D9b822129038EFCa4B63Adf3f7FB5", "deployed_at": 0 }, "Polygon Amoy": { - "on_ramp": "0x610F76A35E17DA4542518D85FfEa12645eF111Fc", + "on_ramp": "0xA82b9ACAcFA6FaB1FD721e7a748A30E3001351F9", "deployed_at": 0 }, "Sepolia Testnet": { - "on_ramp": "0x5724B4Cc39a9690135F7273b44Dfd3BA6c0c69aD", + "on_ramp": "0x75b9a75Ee1fFef6BE7c4F842a041De7c6153CF4E", "deployed_at": 0 }, "WeMix Testnet": { - "on_ramp": "0x677B5ab5C8522d929166c064d5700F147b15fa33", + "on_ramp": "0x1ff99E67986E83bb5BA34143BaA2735853e5738c", "deployed_at": 0 } }, "dest_contracts": { "Arbitrum Sepolia": { - "off_ramp": "0x90A74072e7B0c2d59e13aB4d8f93c8198c413194", - "commit_store": "0xf3458CFd2fdf4a6CF0Ce296d520DD21eB194828b", + "off_ramp": "0xd88CBA0612f2Ce611BF6d073A94C8FD7E70B4fBd", + "commit_store": "0x9b8279E352bC167F714eef96A4C436bE996643cE", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "BSC Testnet": { - "off_ramp": "0x10b28009E5D776F1f5AAA73941CE8953B8f42d26", - "commit_store": "0xacDD582F271eCF22FAd6764cCDe1c4a534b732A8", + "off_ramp": "0x9c40A73F5C7454BB7C178AFa56Ee30bFB2DCf7E6", + "commit_store": "0xE5611af1d63340b711B0468a976651Fb79B17870", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Base Sepolia": { - "off_ramp": "0xdBdE8510226d1E060A3bf982b67705C67f5697e2", - "commit_store": "0x8Ee73BC9492b4182D289E5C1e66e40CD876CC00F", + "off_ramp": "0xf8de9d5924CFD28e31a53B63B4903436D9818d69", + "commit_store": "0xDD7CfECE1bb4e8aC2E8b8281CFE1D44247119471", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Gnosis Chiado": { - "off_ramp": "0x56dF55aF5F0A4689f3364230587a68eD6A314fAd", - "commit_store": "0xabA7ff98094c4cc7A075812EefF2CD21f6400235", + "off_ramp": "0x3F5035039C23cDAF032C64c084Dc70F811E62ddD", + "commit_store": "0xf5B0245c7B9e15f0cB0B85FF2B6799a45D61CbaA", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Optimism Sepolia": { - "off_ramp": "0x3d7CbC95DCC33257F14D6Eb780c88Bd56C6335BB", - "commit_store": "0x1fcDC02edDfb405f378ba53cF9E6104feBcB7542", + "off_ramp": "0x1DF9D94C6916918C935E60d2Cb4Ed265Bf778005", + "commit_store": "0xE7eeBE5882609d28C015d0A89DE1ba4f506F4a03", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Polygon Amoy": { - "off_ramp": "0x3e33290B90fD0FF30a3FA138934DF028E4eCA348", - "commit_store": "0xCFe3556Aa42d40be09BD23aa80448a19443BE5B1", + "off_ramp": "0xbeD7F478Ef5627FB2B891fDA29Ca0131f6796D9D", + "commit_store": "0x27a319f58c01380056c86938798aCEAA1AC529e2", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { - "off_ramp": "0x9e5e4324F8608D54A50a317832d456a392E4F8C2", - "commit_store": "0x92A51eD3F041B39EbD1e464C1f7cb1e8f8A8c63f", + "off_ramp": "0x01e3D835b4C4697D7F81B9d7Abc89A6E478E4a2f", + "commit_store": "0x4EC313c1Eb620432f42FB5f4Df27f8A566523c1C", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "WeMix Testnet": { - "off_ramp": "0xD0D338318bC6837b091FC7AB5F2a94B7783507d5", - "commit_store": "0xd9D479208235c7355848ff4aF26eB5aacfDC30c6", + "off_ramp": "0x15CcAbf0e3484D4872e25b883163D8cB724d4832", + "commit_store": "0x859f3477B7b4ECc19aDD8cCb19740932F21bD76b", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -188,59 +197,68 @@ Data = """ "wrapped_native": "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd", "src_contracts": { "Avalanche Fuji": { - "on_ramp": "0xa2515683E99F50ADbE177519A46bb20FfdBaA5de", + "on_ramp": "0x2A6f8Ed2e7b222163ef6EcC2327171B479399ab2", "deployed_at": 0 }, "Base Sepolia": { - "on_ramp": "0x3E807220Ca84b997c0d1928162227b46C618e0c5", + "on_ramp": "0x97856Bf888F6eEDBBd322B28133BCcF9CA9038f6", + "deployed_at": 0 + }, + "Blast Sepolia": { + "on_ramp": "0xd0049BfFc8e2689Df9236FfA393Ccbf7eae4FbbC", "deployed_at": 0 }, "Gnosis Chiado": { - "on_ramp": "0x8735f991d41eA9cA9D2CC75cD201e4B7C866E63e", + "on_ramp": "0x98dEa9e498F2A7aF6c74C915c88A17FbA09b73C2", "deployed_at": 0 }, "Polygon Amoy": { - "on_ramp": "0xf37CcbfC04adc1B56a46B36F811D52C744a1AF78", + "on_ramp": "0x363EB789fE31F08547a847D8C38d9b55C7Cf1903", "deployed_at": 0 }, "Sepolia Testnet": { - "on_ramp": "0xB1DE44B04C00eaFe9915a3C07a0CaeA4410537dF", + "on_ramp": "0xC1C6438D60AbE9bF4b1F10460184CE9bD312e328", "deployed_at": 0 }, "WeMix Testnet": { - "on_ramp": "0x89268Afc1BEA0782a27ba84124E3F42b196af927", + "on_ramp": "0xbc85704EDb79ea84E9D3C18965F7f6A16B0a0440", "deployed_at": 0 } }, "dest_contracts": { "Avalanche Fuji": { - "off_ramp": "0x6e6fFCb6B4BED91ff0CC8C2e57EC029dA7DB80C2", - "commit_store": "0x38Bc38Bd824b6eE87571f9D3CFbe6D6E28E3Dc62", + "off_ramp": "0x95b66acfaaDF122f4EccE52C0aD4Fd997DD1150C", + "commit_store": "0x3af04b1c1e79A6B8A4577Bb47EC33eD2E66AeB47", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Base Sepolia": { - "off_ramp": "0x2C61FD7E93Dc79422861282145c59B56dFbc3a8c", - "commit_store": "0x42fAe5B3605804CF6d08632d7A25864e24F792Ae", + "off_ramp": "0x0a5147e1Ac38C79c77031194ef64C8B5353F6EE9", + "commit_store": "0x103864D60b33a479EA7D0e23a37e0ce07198f0A9", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Blast Sepolia": { + "off_ramp": "0xe1e8473218acCB82FBc24Ccd3C5D2dF166cd04f3", + "commit_store": "0x020B047A5Ca88fDB1ad3bAD9A082760fC7F770b6", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Gnosis Chiado": { - "off_ramp": "0x71a44a60832B0F8B63232C9516e7E6aEc3A373Dc", - "commit_store": "0xAC24299a91b72d1Cb5B31147e3CF54964D896974", + "off_ramp": "0x1F7FEBCBb10420E039C333A60A444c1a442d826C", + "commit_store": "0x23Ae763a64D39d6038431a64Bbc4A670C89d82b9", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Polygon Amoy": { - "off_ramp": "0x63440C7747d37bc6154b5538AE32b54FE0965AfA", - "commit_store": "0xAD22fA198CECfC534927aE1D480c460d5bB3460F", + "off_ramp": "0xAAe325adbc9C5a28e4e94Fef170D55de2CA9aA01", + "commit_store": "0xD173Df3A1b23ec42eA5C4669b9c956Bef230efd1", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { - "off_ramp": "0xf1c128Fe52Ea78CcAAB407509292E61ce38C1523", - "commit_store": "0x59dFD870dC4bd76A7B879A4f705Fdcd2595f85f9", + "off_ramp": "0xB513523aee87f838e78b32d2Bacaaf2e94D9f0f9", + "commit_store": "0x21A49164890576504C1f1c4DC9442c42C98771D7", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "WeMix Testnet": { - "off_ramp": "0xfd9B19c3725da5B517aA705B848ff3f21F98280e", - "commit_store": "0x3c1F1412563188aBc8FE3fd53E8F1Cb601CaB4f9", + "off_ramp": "0xc985571900DCa62387f93F882AB550472531f5DB", + "commit_store": "0xac5DACfAb1a512E33c49EFE42502863FC1a4BAB3", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -260,68 +278,68 @@ Data = """ "wrapped_native": "0x4200000000000000000000000000000000000006", "src_contracts": { "Arbitrum Sepolia": { - "on_ramp": "0x58622a80c6DdDc072F2b527a99BE1D0934eb2b50", + "on_ramp": "0xb52eF669d3fCeBee1f31418Facc02a16A6F6B0e5", "deployed_at": 0 }, "Avalanche Fuji": { - "on_ramp": "0xAbA09a1b7b9f13E05A6241292a66793Ec7d43357", + "on_ramp": "0x212e8Fd9cCC330ab54E8141FA7d33967eF1eDafF", "deployed_at": 0 }, "BSC Testnet": { - "on_ramp": "0xD806966beAB5A3C75E5B90CDA4a6922C6A9F0c9d", + "on_ramp": "0xd54B44811AE99a18Cb95B4704ba04a65C0163751", "deployed_at": 0 }, "Gnosis Chiado": { - "on_ramp": "0x2Eff2d1BF5C557d6289D208a7a43608f5E3FeCc2", + "on_ramp": "0xdd0Ee1F20E93a93634AAcE56105E19423881Df56", "deployed_at": 0 }, "Mode Sepolia": { - "on_ramp": "0x3d0115386C01436870a2c47e6297962284E70BA6", + "on_ramp": "0xc59689dFDEF9D953cEFbb58912b304bb38408476", "deployed_at": 0 }, "Optimism Sepolia": { - "on_ramp": "0x3b39Cd9599137f892Ad57A4f54158198D445D147", + "on_ramp": "0x2945D35F428CE564F5455AD0AF28BDFCa67e76Ab", "deployed_at": 0 }, "Sepolia Testnet": { - "on_ramp": "0x6486906bB2d85A6c0cCEf2A2831C11A2059ebfea", + "on_ramp": "0x29A1F4ecE9246F0042A9062FB89803fA8B1830cB", "deployed_at": 0 } }, "dest_contracts": { "Arbitrum Sepolia": { - "off_ramp": "0xd364C06ac99a82a00d3eFF9F2F78E4Abe4b9baAA", - "commit_store": "0xdE8d0f47a71eA3fDFBD3162271652f2847939097", + "off_ramp": "0x814E735c5DD19240c85E2513DD926Bc3a39f7140", + "commit_store": "0xFc24B204bfA5C65eD8e2Fc02fDe4FeCb62eA8Ac5", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Avalanche Fuji": { - "off_ramp": "0xAd91214efFee446500940c764DF77AF18427294F", - "commit_store": "0x1242b6c5e0e349b8d4BCf0938f961C4B4f7EA3Fa", + "off_ramp": "0x3Ab3a3d35cAC95FfcFCcc127eF01eA8D87b0A64e", + "commit_store": "0x51313B8C068B5227fa7364E6eCB1382Fb751976F", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "BSC Testnet": { - "off_ramp": "0xd5E9508921434e8758f4540D55c1c066b7cc1598", - "commit_store": "0x1a86b29364D1B3fA3386329A361aA98A104b2742", + "off_ramp": "0x827CF69409307Cd4c979e652894C297ad5124ab7", + "commit_store": "0x547eBe6077305c3fdF8dA66c66cc14b0779CE00C", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Gnosis Chiado": { - "off_ramp": "0x9Bb7e398ef9Acfe9cA584C39B1E233Cba62BB9f7", - "commit_store": "0x1F4B82cDebaC5e3a0Dd53183D47e51808B4a64cB", + "off_ramp": "0x8bB08Bc19771C69E739a2078894523b3DC05a05e", + "commit_store": "0xf163Da63bDB8b9C355d41C755E03125988650109", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Mode Sepolia": { - "off_ramp": "0xB26647A23e8b4284375e5C74b77c9557aE709D03", - "commit_store": "0x4b4fEB401d3E613e1D6242E155C83A80BF9ac2C9", + "off_ramp": "0x11E16c71D76E43acbcb496A70966380d905B1E32", + "commit_store": "0xEe19f039FaE3EF0F94971f0B7B187223D952ac13", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Optimism Sepolia": { - "off_ramp": "0x86a3910908eCaAA31Fcd9F0fC8841D8E98f1511d", - "commit_store": "0xE99a87C9b5ed4D2b6060195DEea5106ffF655736", + "off_ramp": "0x8718d1cc138421Dbc1B489CB7884FF68DE7ad867", + "commit_store": "0x3291D453c880E5b59EEd04E600c85268Cd378b7f", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { - "off_ramp": "0x189F61D9B886Dd2975D5Abc893c8Cf5f5effda71", - "commit_store": "0xEE7e27346DCD1e711348D0F7f7ECB53a9a3a08a7", + "off_ramp": "0x0ecA23Ef70B828fEDd0A84d2692cB0527B52396A", + "commit_store": "0xA7F84Ec616F8e9Fa593339944E76bda90A9737fE", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -340,15 +358,24 @@ Data = """ "price_registry": "0xc8acE9dF450FaD007755C6C9AB4f0e9c8626E29C", "wrapped_native": "0x4200000000000000000000000000000000000023", "src_contracts": { + "BSC Testnet": { + "on_ramp": "0x6eA6f63b689b5597A0C06a5Eb8DcDFD86383857A", + "deployed_at": 0 + }, "Sepolia Testnet": { - "on_ramp": "0x85Ef19FC4C63c70744995DC38CAAEC185E0c619f", + "on_ramp": "0x154aDEF773a848da8229D81De73a7b0844400ebd", "deployed_at": 0 } }, "dest_contracts": { + "BSC Testnet": { + "off_ramp": "0xd9dE4aCD27E814bfe70CA33d2A4d079e740626Bd", + "commit_store": "0xe8fF7e22c54f76F453d6072A9d3a12B1D9AbA137", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, "Sepolia Testnet": { - "off_ramp": "0x92cD24C278D34C726f377703E50875d8f9535dC2", - "commit_store": "0xcE1b4D50CeD56850182Bd58Ace91171cB249B873", + "off_ramp": "0x46DD4e3e2b8a18409646F1C15bf3799a481e67f6", + "commit_store": "0x8250f9E992dda66791dd8b5d356B867ae53382cF", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -368,14 +395,14 @@ Data = """ "wrapped_native": "0x99604d0e2EfE7ABFb58BdE565b5330Bb46Ab3Dca", "src_contracts": { "Sepolia Testnet": { - "on_ramp": "0x16a020c4bbdE363FaB8481262D30516AdbcfcFc8", + "on_ramp": "0x68A4f57A499563192C606a898BAf503A43fcDB4D", "deployed_at": 0 } }, "dest_contracts": { "Sepolia Testnet": { - "off_ramp": "0xa1b97F92D806BA040daf419AFC2765DC723683a4", - "commit_store": "0xcd92C0599Ac515e7588865cC45Eee21A74816aFc", + "off_ramp": "0xF6dB68333D14f6a0c1123cc420ea60980aEDA0Eb", + "commit_store": "0x8f9B63c40891CdF7d1C795625d4260a29bE2bBa0", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -395,68 +422,68 @@ Data = """ "wrapped_native": "0x18c8a7ec7897177E4529065a7E7B0878358B3BfF", "src_contracts": { "Arbitrum Sepolia": { - "on_ramp": "0x473b49fb592B54a4BfCD55d40E048431982879C9", + "on_ramp": "0x94967Ea06C6543Aaba5B90C52B655003ef82e521", "deployed_at": 0 }, "Avalanche Fuji": { - "on_ramp": "0x610F76A35E17DA4542518D85FfEa12645eF111Fc", + "on_ramp": "0x4f3576585e7fCCE5Fc502Bcf3CAdaD22E1194834", "deployed_at": 0 }, "BSC Testnet": { - "on_ramp": "0xE48E6AA1fc7D0411acEA95F8C6CaD972A37721D4", + "on_ramp": "0xB2642B54580140C375c9024e273C575a5f53d02d", "deployed_at": 0 }, "Base Sepolia": { - "on_ramp": "0x41b4A51cAfb699D9504E89d19D71F92E886028a8", + "on_ramp": "0x0E9504907be794620229C196F82CB062A66B7480", "deployed_at": 0 }, "Optimism Sepolia": { - "on_ramp": "0xAae733212981e06D9C978Eb5148F8af03F54b6EF", + "on_ramp": "0xeb86B5b6f5C66eCb58e4Cf98E607b238126505DC", "deployed_at": 0 }, "Polygon Amoy": { - "on_ramp": "0x01800fCDd892e37f7829937271840A6F041bE62E", + "on_ramp": "0xd86F5DF82A2500137Ddeef963028d60E3b5A354D", "deployed_at": 0 }, "Sepolia Testnet": { - "on_ramp": "0x4ac7FBEc2A7298AbDf0E0F4fDC45015836C4bAFe", + "on_ramp": "0x03691D63C687D09368360e957AFB2F7B4d1651d4", "deployed_at": 0 } }, "dest_contracts": { "Arbitrum Sepolia": { - "off_ramp": "0x9aA82DBB53bf02096B771D40e9432A323a78fB26", - "commit_store": "0x5CdbA91aBC0cD81FC56bc10Ad1835C9E5fB38e5F", + "off_ramp": "0x3633Cce99186217d4C7ed64FD455d218b8Cd5D4c", + "commit_store": "0x6e096286548451828c97F1B3E49C402a4934F39a", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Avalanche Fuji": { - "off_ramp": "0x3e33290B90fD0FF30a3FA138934DF028E4eCA348", - "commit_store": "0xCFe3556Aa42d40be09BD23aa80448a19443BE5B1", + "off_ramp": "0x5E4DB2A3c965B9B2A850a75697Bb6a00b4e35ac5", + "commit_store": "0x2489c5a802fE63943f7E3185A0362327B55DDF67", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "BSC Testnet": { - "off_ramp": "0xbc4AD54e91b213D4279af92c0C5518c0b96cf62D", - "commit_store": "0xff84e8Dd4Fd17eaBb23b6AeA6e1981830e54389C", + "off_ramp": "0x2BA72Ba392C08750328635E36757A2c29a9165CA", + "commit_store": "0x08ebd7Cf4ABDC819c74cB45CbA4e291728538D7C", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Base Sepolia": { - "off_ramp": "0x4117953A5ceeF12f5B8C1E973b470ab83a8CebA6", - "commit_store": "0x94ad41296186E81f31e1ed0B1BcF5fa9e1721C27", + "off_ramp": "0x269D28B25Ee081ae5340e2BFE99850E92F1cd522", + "commit_store": "0x8dC9329BD221C89c4989d98c38Ff2Cc3dF92d14b", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Optimism Sepolia": { - "off_ramp": "0x33d2898F8fb7714FD1661791766f40754982a343", - "commit_store": "0x55d6Df194472f02CD481e506A277c4A29D0D1bCc", + "off_ramp": "0xd93B571ae9CaF43d70b2b53fFD55e035Db641e31", + "commit_store": "0x42C1093b9DdE8d0CD58859C610dc239B66bE26de", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Polygon Amoy": { - "off_ramp": "0x450543b1d85ca79885851D7b74dc982981b78229", - "commit_store": "0x23B79d940A769FE31b4C867A8BAE80117f24Ca81", + "off_ramp": "0x87F9b8382611ACD01d5696a1f5b05B888e55B0Cc", + "commit_store": "0x29AC46227908d31A9BdDe82c0A4a6c52D802f145", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { - "off_ramp": "0xbf9036529123DE264bFA0FC7362fE25B650D4B16", - "commit_store": "0x5f7F1abD5c5EdaF2636D58B980e85355AF0Ef80d", + "off_ramp": "0x9aa734100C425309091dAE18154e0356B82d477a", + "commit_store": "0x7cDd533B82f4c32FAE7f551C37b1490909817C45", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -476,14 +503,14 @@ Data = """ "wrapped_native": "0x4200000000000000000000000000000000000001", "src_contracts": { "WeMix Testnet": { - "on_ramp": "0x6ea155Fc77566D9dcE01B8aa5D7968665dc4f0C5", + "on_ramp": "0xa81418c332d3E04338B058Ab39b1baf53029F638", "deployed_at": 0 } }, "dest_contracts": { "WeMix Testnet": { - "off_ramp": "0xB602B6E5Caf08ac0C920EAE585aed100a8cF6f3B", - "commit_store": "0x89D5b13908b9063abCC6791dc724bF7B7c93634C", + "off_ramp": "0x42Dde725C4f05C237a00B582Bb7457e208d3A17C", + "commit_store": "0xb116E9a90534354dA59CF93a87c1E9711c0Aaa2c", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -502,15 +529,24 @@ Data = """ "price_registry": "0x5DCE866b3ae6E0Ed153f0e149D7203A1B266cdF5", "wrapped_native": "0x5c48e07062aC4E2Cf4b9A768a711Aef18e8fbdA0", "src_contracts": { + "Arbitrum Sepolia": { + "on_ramp": "0x2eb69889cc979c0Be120813FcE2f1558efF4ceB5", + "deployed_at": 0 + }, "Sepolia Testnet": { - "on_ramp": "0x2Eff2d1BF5C557d6289D208a7a43608f5E3FeCc2", + "on_ramp": "0xE0dFc15C0CDf607b2088D0B641E00eA0B418124C", "deployed_at": 0 } }, "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0x839b5dEA3e084790F580E9DfCE8CCfDf49c5835e", + "commit_store": "0xdF38C8aD34C379165f98A75a6894790bB5a16b1D", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, "Sepolia Testnet": { - "off_ramp": "0x9Bb7e398ef9Acfe9cA584C39B1E233Cba62BB9f7", - "commit_store": "0x1F4B82cDebaC5e3a0Dd53183D47e51808B4a64cB", + "off_ramp": "0x72130De9A85e9C61151253aFF8801Bb3242A00a9", + "commit_store": "0x8F6D64280C379F680Ff0c3278f340D72a465FAAc", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -530,23 +566,23 @@ Data = """ "wrapped_native": "0x4200000000000000000000000000000000000006", "src_contracts": { "Base Sepolia": { - "on_ramp": "0x73f7E074bd7291706a0C5412f51DB46441B1aDCB", + "on_ramp": "0x48ACE2319f643584B77C21476a6c664D7F13a107", "deployed_at": 0 }, "Sepolia Testnet": { - "on_ramp": "0xfFdE9E8c34A27BEBeaCcAcB7b3044A0A364455C9", + "on_ramp": "0xb821885731414497d705dc56325f18AA33e612dC", "deployed_at": 0 } }, "dest_contracts": { "Base Sepolia": { - "off_ramp": "0x137a38c6b1Ad20101F93516aB2159Df525309168", - "commit_store": "0x8F43d867969F14619895d71E0A5b89E0bb20bF70", + "off_ramp": "0xC6b69Fa9eeBc55e64eBc68371Fbd41ff73756F17", + "commit_store": "0xaA6691EA9110409a29C2E665174b4b2fe694cE67", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { - "off_ramp": "0xcD44cec849B6a8eBd5551D6DFeEcA452257Dfe4d", - "commit_store": "0xbA66f08733E6715D33edDfb5a5947676bb45d0e0", + "off_ramp": "0x35dE2C381a2fF8a26c8ae94145be3A9cA8C83600", + "commit_store": "0xE7e60DAee094416b8ab2083047a893c4c4290c48", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -566,68 +602,68 @@ Data = """ "wrapped_native": "0x4200000000000000000000000000000000000006", "src_contracts": { "Arbitrum Sepolia": { - "on_ramp": "0x1a86b29364D1B3fA3386329A361aA98A104b2742", + "on_ramp": "0x6B36c9CD74E760088817a047C3460dEdFfe9a11A", "deployed_at": 0 }, "Avalanche Fuji": { - "on_ramp": "0x6b38CC6Fa938D5AB09Bdf0CFe580E226fDD793cE", + "on_ramp": "0x91a144F570ABA7FB7079Fb187A267390E0cc7367", "deployed_at": 0 }, "Base Sepolia": { - "on_ramp": "0xe284D2315a28c4d62C419e8474dC457b219DB969", + "on_ramp": "0x6D22953cdEf8B0C9F0976Cfa52c33B198fEc5881", "deployed_at": 0 }, "Gnosis Chiado": { - "on_ramp": "0x835a5b8e6CA17c2bB5A336c93a4E22478E6F1C8A", + "on_ramp": "0xec7D9A84A6d4556056975BE50Cdc97bAa9313632", "deployed_at": 0 }, "Polygon Amoy": { - "on_ramp": "0x2Cf26fb01E9ccDb831414B766287c0A9e4551089", + "on_ramp": "0x9E09C2A7D6B9F88c62f0E2Af4cd62dF3F4c326F1", "deployed_at": 0 }, "Sepolia Testnet": { - "on_ramp": "0xC8b93b46BF682c39B3F65Aa1c135bC8A95A5E43a", + "on_ramp": "0x54b32C2aCb4451c6cF66bcbd856d8A7Cc2263531", "deployed_at": 0 }, "WeMix Testnet": { - "on_ramp": "0xc7E53f6aB982af7A7C3e470c8cCa283d3399BDAd", + "on_ramp": "0xB9Ef21C04d8340b223e9C1d7a09f332609c70300", "deployed_at": 0 } }, "dest_contracts": { "Arbitrum Sepolia": { - "off_ramp": "0xDc2c7A3d8068C6F09F0F3648d24C84e372F6014d", - "commit_store": "0xb1aFb5cbE3c29b5Db71F21442BA9EfD450BC23C3", + "off_ramp": "0xF35e2d1457749374453e44B06268aD3f78b133b3", + "commit_store": "0x4bd755d86E25dD4093CAa5639CfDab81571259CA", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Avalanche Fuji": { - "off_ramp": "0x1F350718e015EB20E5065C09F4A7a3f66888aEeD", - "commit_store": "0x98650A8EB59f75D93563aB34FcF603b1A30e4CBF", + "off_ramp": "0xCb2266c2118b1f30D15CBeB3a885531ABaA1b556", + "commit_store": "0x5Ded92E2CF71a8fF7644a67850F061c38B31BfB4", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Base Sepolia": { - "off_ramp": "0x0a750ca77369e03613d7640548F4b2b1c695c3Bb", - "commit_store": "0x8fEBC74C26129C8d7E60288C6dCCc75eb494aA3C", + "off_ramp": "0x960c62A491C30d0a60fD74a59d35B9C02697AdaA", + "commit_store": "0x06963745B3839B998288D1a46a46Ec25991A3D5E", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Gnosis Chiado": { - "off_ramp": "0xCE2CE7F940B7c839384e5D7e079A6aE80e8AD6dB", - "commit_store": "0x1b9D78Ec1CEEC439F0b7eA6C428A1a607D9FA7e4", + "off_ramp": "0x7d6721c2E85560F0A233255D3d332AcF6f850d96", + "commit_store": "0xaC00661cAB5161d9B4746DFb7A028d97981aB2c5", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Polygon Amoy": { - "off_ramp": "0xD667b5706592D0b040C78fEe5EE17D243b7dCB41", - "commit_store": "0x96101BA5250EE9295c193693C1e08A55bC593664", + "off_ramp": "0x4cEeFa55AF23dFD27Cf926e8eFB1D1bCcD24526E", + "commit_store": "0xaD3943BdECbf4ae7d6E51aB0FD06bbC604bB7b95", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { - "off_ramp": "0x260AF9b83e0d2Bb6C9015fC9f0BfF8858A0CCE68", - "commit_store": "0x7a0bB92Bc8663abe6296d0162A9b41a2Cb2E0358", + "off_ramp": "0x2aF9B10A5972D0c36f4d8F85773052c104E319B2", + "commit_store": "0x82FCF55b9e9bAb3066c2863F12a02bBc2Ba33F2F", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "WeMix Testnet": { - "off_ramp": "0x9C08B7712af0344188aa5087D9e6aD0f47191037", - "commit_store": "0x4BE6DB0B884169a6A207fe5cad01eB4C025a13dB", + "off_ramp": "0x0FA15Bc42D4999d964CBf0161489Bd392DEE834e", + "commit_store": "0x37760F99a5b91884C9D89a06408f532aEbb0e674", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -647,59 +683,59 @@ Data = """ "wrapped_native": "0x360ad4f9a9A8EFe9A8DCB5f461c4Cc1047E1Dcf9", "src_contracts": { "Avalanche Fuji": { - "on_ramp": "0x8Fb98b3837578aceEA32b454f3221FE18D7Ce903", + "on_ramp": "0xad6A94CFB51e7DE30FD21F417E4cBf70D3AdaD30", "deployed_at": 0 }, "BSC Testnet": { - "on_ramp": "0xC6683ac4a0F62803Bec89a5355B36495ddF2C38b", + "on_ramp": "0x28EC0a9C90360F55C2a9DaD5901b074C257904ca", "deployed_at": 0 }, "Gnosis Chiado": { - "on_ramp": "0x2331F6D614C9Fd613Ff59a1aB727f1EDf6c37A68", + "on_ramp": "0x9DF611536f124278Ce968c476BDb10A66E54ecfE", "deployed_at": 0 }, "Optimism Sepolia": { - "on_ramp": "0xA52cDAeb43803A80B3c0C2296f5cFe57e695BE11", + "on_ramp": "0x600f00aef9b8ED8EDBd7284B5F04a1932c3408aF", "deployed_at": 0 }, "Sepolia Testnet": { - "on_ramp": "0x35347A2fC1f2a4c5Eae03339040d0b83b09e6FDA", + "on_ramp": "0x719Aef2C63376AdeCD62D2b59D54682aFBde914a", "deployed_at": 0 }, "WeMix Testnet": { - "on_ramp": "0x26546096F64B5eF9A1DcDAe70Df6F4f8c2E10C61", + "on_ramp": "0x7D6c93E49E46cc983a677c283EAb27CbbC94e3C4", "deployed_at": 0 } }, "dest_contracts": { "Avalanche Fuji": { - "off_ramp": "0xa733ce82a84335b2E9D864312225B0F3D5d80600", - "commit_store": "0x09B0F93fC2111aE439e853884173AC5b2F809885", + "off_ramp": "0xAc56Df7F5fbde0DeeB1C0d397A150EDD5EE68625", + "commit_store": "0x8AF56D1c76B8c8CeE451a0a654D130e4050B993e", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "BSC Testnet": { - "off_ramp": "0x948dfaa4842fc23e0e362Fe8D4396AaE4E6DF7EA", - "commit_store": "0x7F4e739D40E58BBd59dAD388171d18e37B26326f", + "off_ramp": "0x40Ba47ea59D80DDd35E3a997AA520FBa0553dddc", + "commit_store": "0x8afe532517b39bA109d1A768E1Ad8b5C6485abF5", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Gnosis Chiado": { - "off_ramp": "0x17c542a28e08AEF5697251601C7b2B621d153D42", - "commit_store": "0x811250c20fAB9a1b7ca245453aC214ba637fBEB5", + "off_ramp": "0x7B968B2aDFd31765dAAD80d66c83F9D7006BFFd5", + "commit_store": "0xBc70551B5624BaF8cdCB84136198561C9cf5C176", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Optimism Sepolia": { - "off_ramp": "0xfFdE9E8c34A27BEBeaCcAcB7b3044A0A364455C9", - "commit_store": "0x74ED442ad211050e9C05Dc9A267E037E3d74A03B", + "off_ramp": "0xAA755Ef570986feEb6522377077e549e3013843E", + "commit_store": "0x5C7827EcE6a51AdaC36ef71aC01706deb1C7130d", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { - "off_ramp": "0xFb04129aD1EEDB741CC705ebC1978a7aB63e51f6", - "commit_store": "0x63f875240149d29136053C954Ca164a9BfA81F77", + "off_ramp": "0x7Ad494C173f5845c6B4028a06cDcC6d3108bc960", + "commit_store": "0x104A1c8b05D37fE732094595Fe696AFc7EAB8668", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "WeMix Testnet": { - "off_ramp": "0xdE8451E952Eb43350614839cCAA84f7C8701a09C", - "commit_store": "0xaCdaBa07ECad81dc634458b98673931DD9d3Bc14", + "off_ramp": "0xa85481273f8C112e96ED7476202F06D6131cf069", + "commit_store": "0x9FdF1D555e37dB09B0d151FEa53c134C88C4DeFd", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -719,122 +755,122 @@ Data = """ "wrapped_native": "0x097D90c9d3E0B50Ca60e1ae45F6A81010f9FB534", "src_contracts": { "Arbitrum Sepolia": { - "on_ramp": "0xe4Dd3B16E09c016402585a8aDFdB4A18f772a07e", + "on_ramp": "0xBc09627e58989Ba8F1eDA775e486467d2A00944F", "deployed_at": 0 }, "Avalanche Fuji": { - "on_ramp": "0x0477cA0a35eE05D3f9f424d88bC0977ceCf339D4", + "on_ramp": "0x12492154714fBD28F28219f6fc4315d19de1025B", "deployed_at": 0 }, "BSC Testnet": { - "on_ramp": "0xD990f8aFA5BCB02f95eEd88ecB7C68f5998bD618", + "on_ramp": "0x7a75b3818412fe0028590feE8270ba9E3fd01DBe", "deployed_at": 0 }, "Base Sepolia": { - "on_ramp": "0x2B70a05320cB069e0fB55084D402343F832556E7", + "on_ramp": "0x8F35B097022135E0F46831f798a240Cc8c4b0B01", "deployed_at": 0 }, "Blast Sepolia": { - "on_ramp": "0xDB75E9D9ca7577CcBd7232741be954cf26194a66", + "on_ramp": "0x4ADA60556dA05FcF53a79359e37a3E13FebA22Bf", "deployed_at": 0 }, "Celo Alfajores": { - "on_ramp": "0x3C86d16F52C10B2ff6696a0e1b8E0BcfCC085948", + "on_ramp": "0x1163D1F7D75eEb1C4f4c6912d3cF9642027aFD30", "deployed_at": 0 }, "Gnosis Chiado": { - "on_ramp": "0x3E842E3A79A00AFdd03B52390B1caC6306Ea257E", + "on_ramp": "0x831A7DbE6af8601427A0ADa89b642d4b59007eED", "deployed_at": 0 }, "Metis Sepolia": { - "on_ramp": "0x1C4640914cd57c5f02a68048A0fbb0E12d904223", + "on_ramp": "0xabB5A4f99DFEb4a3912e8Acc0660A008c76dA8c3", "deployed_at": 0 }, "Mode Sepolia": { - "on_ramp": "0xc630fbD4D0F6AEB00aD0793FB827b54fBB78e981", + "on_ramp": "0x2Eb0842925fb7aA6045e951e98e8b4b3aFFaBB54", "deployed_at": 0 }, "Optimism Sepolia": { - "on_ramp": "0x69CaB5A0a08a12BaFD8f5B195989D709E396Ed4d", + "on_ramp": "0xACDfd7a98d853FA3914047Cd46e7f5D53BBC9FbB", "deployed_at": 0 }, "Polygon Amoy": { - "on_ramp": "0x9f656e0361Fb5Df2ac446102c8aB31855B591692", + "on_ramp": "0xf9765c80F6448e6d4d02BeF4a6b4152131A2F513", "deployed_at": 0 }, "WeMix Testnet": { - "on_ramp": "0xedFc22336Eb0B9B11Ff37C07777db27BCcDe3C65", + "on_ramp": "0xd72c3c132B76F5D232C37dF3bF8f04392D552e0F", "deployed_at": 0 }, "ZKSync Sepolia": { - "on_ramp": "0x1Acb3A885feA37bdA30AB99b99327b14391f500F", + "on_ramp": "0xA2865E4f36760f5fa5c8F958336120f2DF0d974b", "deployed_at": 0 } }, "dest_contracts": { "Arbitrum Sepolia": { - "off_ramp": "0xF18896AB20a09A29e64fdEbA99FDb8EC328f43b1", - "commit_store": "0x93Ff9Dd39Dc01eac1fc4d2c9211D95Ee458CAB94", + "off_ramp": "0xD2f5edfD4561d6E7599F6c6888Bd353cAFd0c55E", + "commit_store": "0x240420BC6bCDc067e668c7492D69fe06B3CF80cE", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Avalanche Fuji": { - "off_ramp": "0x000b26f604eAadC3D874a4404bde6D64a97d95ca", - "commit_store": "0x2dD9273F8208B8393350508131270A6574A69784", + "off_ramp": "0x1DEBa99dC8e2A77832461BD386d83D9FCb133137", + "commit_store": "0x139E06b6dBB1a0C41A1686C091795879c943765A", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "BSC Testnet": { - "off_ramp": "0xdE2d8E126e08d675fCD7fFa5a6CE49925f3Dc692", - "commit_store": "0x0050ac355a82caB31194507f94174297bf0655A7", + "off_ramp": "0x04305BD9D9CA6730517f79c3D9c6828BC2D25Ecb", + "commit_store": "0x32edD59840CD9e474A280cf1707439F2Bd5872d4", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Base Sepolia": { - "off_ramp": "0x31c0B81832B333419f0DfD36A69F502cF9094aed", - "commit_store": "0xDFcde9d698a2B32DB2537DC9B752Cadd1D846a52", + "off_ramp": "0x662738DC7DE4f7eC63d9f73Cdf9BeA5A58DdcC15", + "commit_store": "0x1e46bAC486Dd878cD57B62845530A52343e39693", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Blast Sepolia": { - "off_ramp": "0x4e897e5cF3aC307F0541B2151A88bCD781c153a3", - "commit_store": "0xB656652841F347178e193951C4663652aCe36B74", + "off_ramp": "0x049A424cF894709f044bc70177F8F6b792adc3F6", + "commit_store": "0x496fE96E440Fc683478a08Df92A1c5E23E412b1C", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Celo Alfajores": { - "off_ramp": "0xB435E0f73c18C5a12C324CA1d02F81F2C3e6e761", - "commit_store": "0xbc5d74957F171e75F92c8F0E1C317A25a56a416D", + "off_ramp": "0x4F146d34Be5E273e576ef158Bd7070eC22708D20", + "commit_store": "0xEeB665281c7ab51d25423898f730Ab078c69dd42", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Gnosis Chiado": { - "off_ramp": "0x7db0115A0b3AAb01d30bf81123c5DD7B0C41Add5", - "commit_store": "0x6640723Ea801178c4383FA016b9781e7ef1016EF", + "off_ramp": "0xB424365EEEEA58A36C7EC858f926f4e8275dDEb3", + "commit_store": "0xE95c2135e3330E953BB49068d32Fcba368Acd456", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Metis Sepolia": { - "off_ramp": "0x4DB693A93E9d5196ECD42EC56CDEAe99dFC652ED", - "commit_store": "0xBfACd78F1412B6f93Ac23409bf456aFec1ABd845", + "off_ramp": "0x46DE6201c258f5948135cd0262f91e48Cb8e3828", + "commit_store": "0x3A27Fd059A4eF0e96B0643283A44a56A8d6CF34A", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Mode Sepolia": { - "off_ramp": "0xbEfd8D65F6643De54F0b1268A3bf4618ff85dcB4", - "commit_store": "0x0C161D3470b45Cc677661654C30ce4AdE6aCD288", + "off_ramp": "0x052E52fdd48719A6084366eA184FC44cb8C25DC2", + "commit_store": "0xBBb9baA314eB023E3F9291Aaf4107B6708341B50", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Optimism Sepolia": { - "off_ramp": "0xD50590D4438411EDe47029b0FD7901A7145E5Df6", - "commit_store": "0xe85EEE9Fd434A7b8a586Ee086E828abF41839479", + "off_ramp": "0xbfa6f6AAE31acB3A285e80026d6475C1a50d1d0F", + "commit_store": "0xB5FbA97Dc61ec68771a92a15360d9C32c9d054E7", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Polygon Amoy": { - "off_ramp": "0x5032cbC0C4aEeD25bb6E45D8B3fAF05DB0688C5d", - "commit_store": "0xe6201C9996Cc7B6E828E10CbE937E693d577D318", + "off_ramp": "0xC3e550B6aaFA5539df8bbCc5B0991e587f438e75", + "commit_store": "0xd57866D97ca26dfaE34088a3EeE4657BAFaac5f9", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "WeMix Testnet": { - "off_ramp": "0x46b639a3C1a4CBfD326b94a2dB7415c27157282f", - "commit_store": "0x7b74554678816b045c1e7409327E086bD436aa46", + "off_ramp": "0x445F41C6aa7e910021786e860d7cfe3E7fcC6640", + "commit_store": "0x307dDE3c696E399b5837456FbCe03b1Ad76D46E3", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "ZKSync Sepolia": { - "off_ramp": "0xBaABd4166C892a1081a26535875A8fA3f22937b2", - "commit_store": "0xfda2e83F4D3f42B7629134ecD6E4b29FB8A7A07B", + "off_ramp": "0x9f5dC467A5c97068A1c2987486B8b768275627eD", + "commit_store": "0x6e4601DA99a046e4bde60d051568E3E1F35E3097", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -854,68 +890,68 @@ Data = """ "wrapped_native": "0xbE3686643c05f00eC46e73da594c78098F7a9Ae7", "src_contracts": { "Arbitrum Sepolia": { - "on_ramp": "0xA9DE3F7A617D67bC50c56baaCb9E0373C15EbfC6", + "on_ramp": "0xa5Be8C619F61505548992D9820c5c485b030C7B0", "deployed_at": 0 }, "Avalanche Fuji": { - "on_ramp": "0xC4aC84da458ba8e40210D2dF94C76E9a41f70069", + "on_ramp": "0x7802B6804bbE7486229ac6D3519f0057c50b40a9", "deployed_at": 0 }, "BSC Testnet": { - "on_ramp": "0x5AD6eed6Be0ffaDCA4105050CF0E584D87E0c2F1", + "on_ramp": "0xd25B8c70CB43022Bdc3aC417E2Cf5159294d95A1", "deployed_at": 0 }, "Kroma Sepolia": { - "on_ramp": "0x428C4dc89b6Bf908B82d77C9CBceA786ea8cc7D0", + "on_ramp": "0x1De2Ca07eEee7F524Fe5edA6C8FFFb79F67b05E9", "deployed_at": 0 }, "Optimism Sepolia": { - "on_ramp": "0x1961a7De751451F410391c251D4D4F98D71B767D", + "on_ramp": "0xB37607C6BD4562F32967dE87D14663D59e3f655d", "deployed_at": 0 }, "Polygon Amoy": { - "on_ramp": "0xd55148e841e76265B484d399eC71b7076ecB1216", + "on_ramp": "0x0c972752F9aC3255cE45b440f9bBC6500676c4e6", "deployed_at": 0 }, "Sepolia Testnet": { - "on_ramp": "0x4d57C6d8037C65fa66D6231844785a428310a735", + "on_ramp": "0x1CD55c65f85681Dfae47c62e6D93340D25006BbB", "deployed_at": 0 } }, "dest_contracts": { "Arbitrum Sepolia": { - "off_ramp": "0xeB1dFaB2464Bf0574D43e764E0c758f92e7ecAFb", - "commit_store": "0xcEaCa2B7890065c485f3E58657358a185Ad33791", + "off_ramp": "0xB5492C8A71130B486fAD1091Db683584767A3957", + "commit_store": "0x1e151ED27E2F48EcFBd5b4374d0fc4869e07c397", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Avalanche Fuji": { - "off_ramp": "0x98e811Df9D2512f1aaf58D534607F583D6c54A4F", - "commit_store": "0x8e538351F6E5B2daF3c90C565C3738bca69a2716", + "off_ramp": "0x60536c757c2BBf72cC68A1933F7e336d03Bb68fe", + "commit_store": "0x2fF725556A04b47eB40BbA11d9F51e8fbbee9F07", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "BSC Testnet": { - "off_ramp": "0xB0e7f0fCcD3c961C473E7c44D939C1cDb4Cec1cB", - "commit_store": "0x4B56D8d53f1A6e0117B09700067De99581aA5542", + "off_ramp": "0xb858077FbE1E55cD7a9092Eb6d5403e068c14EAf", + "commit_store": "0x0EF13C7c95C27A9EA477363a26a09Cff44ba38F9", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Kroma Sepolia": { - "off_ramp": "0xD685D2d224dd6D0Db2D56497db6270D77D9a7966", - "commit_store": "0x7e062D6880779a0347e7742058C1b1Ee4AA0B137", + "off_ramp": "0x78d8154e1216F4791086bFa078Aaf07dcD2bD3C6", + "commit_store": "0xe67AAfbE6025e730Cf47a414BEFf2106FF231dB1", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Optimism Sepolia": { - "off_ramp": "0xA5f97Bc69Bf06e7C37B93265c5457420A92c5F4b", - "commit_store": "0xd48b9213583074f518D8f4336FDf35370D450132", + "off_ramp": "0x995Fc17FC12b67f75D3cBf3bC71BD9af65671E78", + "commit_store": "0xD0825e3D8e61b67a06A93426749d38bCF73Ddb02", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Polygon Amoy": { - "off_ramp": "0x6c8f5999B06FDE17B11E4e3C1062b761766F960f", - "commit_store": "0x957c3c2056192e58A8485eF31165fC490d474239", + "off_ramp": "0xd7b5B4F8FF7a87cC92f7B3058365862859d9E057", + "commit_store": "0xa8f2bb4e831caA5E2794AaD014030E378208d4Bc", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { - "off_ramp": "0x8AB103843ED9D28D2C5DAf5FdB9c3e1CE2B6c876", - "commit_store": "0x7d5297c5506ee2A7Ef121Da9bE02b6a6AD30b392", + "off_ramp": "0xa7E2F97Be7798327A49CACD022f33c0E7EfD4897", + "commit_store": "0x6fe69eE4eC9FD768193a40129A3Ba3dF140b2208", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -923,20 +959,26 @@ Data = """ "ZKSync Sepolia": { "is_native_fee_token": true, "fee_token": "0x4317b2eCD41851173175005783322D29E9bAee9E", + "bridge_tokens": [ + "0xFf6d0c1518A8104611f482eb2801CaF4f13c9dEb" + ], + "bridge_tokens_pools": [ + "0xA16cfA090aA6888AE8Beb92F8bfD316DD05767C9" + ], "arm": "0x926b4f90610Aa448f27c8e0Fd0afa4A17B7305F9", "router": "0xA1fdA8aa9A8C4b945C45aD30647b01f07D7A0B16", "price_registry": "0x648B6BB09bE1C5766C8AC578B9B4aC8497eA671F", "wrapped_native": "0x4317b2eCD41851173175005783322D29E9bAee9E", "src_contracts": { "Sepolia Testnet": { - "on_ramp": "0x79a9a5e9e318e8e109776569574814bbf935125a", + "on_ramp": "0xC38536521fde8556351aB7C4D3ea23b64AFbBbab", "deployed_at": 0 } }, "dest_contracts": { "Sepolia Testnet": { - "off_ramp": "0x18FF69051479796175852578725Fc74F58E963F8", - "commit_store": "0xF694b4FD7889480dca3CD41244e8e3395a9EFBa0", + "off_ramp": "0x19Ea9A42cd3682928aF19990dDb3904250D00a1D", + "commit_store": "0x20BF9037927bFadaF028D43ae07d1afccfB8fa85", "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } @@ -969,30 +1011,54 @@ selected_networks = [ [CCIP.Groups.load] NetworkPairs = [ - 'AVALANCHE_FUJI,ARBITRUM_SEPOLIA', - 'AVALANCHE_FUJI,BASE_SEPOLIA', - 'AVALANCHE_FUJI,OPTIMISM_SEPOLIA', - 'AVALANCHE_FUJI,POLYGON_AMOY', - 'AVALANCHE_FUJI,GNOSIS_CHIADO', + 'SEPOLIA,AVALANCHE_FUJI', +# 'SEPOLIA,BSC_TESTNET', + 'SEPOLIA,CELO_ALFAJORES', + 'SEPOLIA,ARBITRUM_SEPOLIA', + 'SEPOLIA,BASE_SEPOLIA', + 'SEPOLIA,BLAST_SEPOLIA', + 'SEPOLIA,MODE_SEPOLIA', + 'SEPOLIA,OPTIMISM_SEPOLIA', + 'SEPOLIA,POLYGON_AMOY', + 'SEPOLIA,WEMIX_TESTNET', + 'SEPOLIA,GNOSIS_CHIADO', + 'SEPOLIA,METIS_SEPOLIA', + 'SEPOLIA,ZKSYNC_SEPOLIA', + +# 'AVALANCHE_FUJI,BSC_TESTNET', +# 'AVALANCHE_FUJI,ARBITRUM_SEPOLIA', +# 'AVALANCHE_FUJI,BASE_SEPOLIA', +# 'AVALANCHE_FUJI,OPTIMISM_SEPOLIA', +# 'AVALANCHE_FUJI,POLYGON_AMOY', +# 'AVALANCHE_FUJI,WEMIX_TESTNET', +# 'AVALANCHE_FUJI,GNOSIS_CHIADO', + +# 'BSC_TESTNET,BASE_SEPOLIA', +# 'BSC_TESTNET,POLYGON_AMOY', +# 'BSC_TESTNET,WEMIX_TESTNET', +# 'BSC_TESTNET,GNOSIS_CHIADO', + 'ARBITRUM_SEPOLIA,BASE_SEPOLIA', 'ARBITRUM_SEPOLIA,OPTIMISM_SEPOLIA', - 'ARBITRUM_SEPOLIA,SEPOLIA', + 'ARBITRUM_SEPOLIA,WEMIX_TESTNET', 'ARBITRUM_SEPOLIA,GNOSIS_CHIADO', + 'BASE_SEPOLIA,MODE_SEPOLIA', 'BASE_SEPOLIA,OPTIMISM_SEPOLIA', 'BASE_SEPOLIA,GNOSIS_CHIADO', - 'SEPOLIA,MODE_SEPOLIA', - 'SEPOLIA,CELO_ALFAJORES', - 'SEPOLIA,METIS_SEPOLIA', - 'SEPOLIA,BLAST_SEPOLIA', - 'SEPOLIA,ZKSYNC_SEPOLIA', - 'KROMA_SEPOLIA,WEMIX_TESTNET', + + # 'KROMA_SEPOLIA,WEMIX_TESTNET', + + 'OPTIMISM_SEPOLIA,POLYGON_AMOY', + 'OPTIMISM_SEPOLIA,WEMIX_TESTNET', 'OPTIMISM_SEPOLIA,GNOSIS_CHIADO', - 'BSC_TESTNET,GNOSIS_CHIADO', + + 'POLYGON_AMOY,WEMIX_TESTNET', + 'POLYGON_AMOY,GNOSIS_CHIADO', ] BiDirectionalLane = true -PhaseTimeout = '20m' +PhaseTimeout = '45m' ExistingDeployment = true [CCIP.Groups.load.TokenConfig] @@ -1006,7 +1072,7 @@ TestRunName = 'SoakTest_prod_testnet' FailOnFirstErrorInLoad = true [[CCIP.Groups.load.LoadProfile.MsgProfile.MsgDetails]] -MsgType = 'Data' +MsgType = 'DataWithToken' DestGasLimit = 0 DataLength = 100 NoOfTokens = 1 diff --git a/integration-tests/ccip-tests/testsetups/ccip.go b/integration-tests/ccip-tests/testsetups/ccip.go index fbfbc4c1ccd..be736dca1db 100644 --- a/integration-tests/ccip-tests/testsetups/ccip.go +++ b/integration-tests/ccip-tests/testsetups/ccip.go @@ -308,8 +308,8 @@ func (c *CCIPTestConfig) SetNetworkPairs(lggr zerolog.Logger) error { var newNetworkPairs []NetworkPair denselyConnectedNetworks := make(map[string]struct{}) // if densely connected networks are provided, choose all the network pairs containing the networks mentioned in the list for DenselyConnectedNetworkChainIds - if len(c.TestGroupInput.DenselyConnectedNetworkChainIds) > 0 { - for _, n := range c.TestGroupInput.DenselyConnectedNetworkChainIds { + if len(c.TestGroupInput.DenselyConnectedNetworkChainIDs) > 0 { + for _, n := range c.TestGroupInput.DenselyConnectedNetworkChainIDs { denselyConnectedNetworks[n] = struct{}{} } for _, pair := range c.NetworkPairs { @@ -1155,7 +1155,14 @@ func CCIPDefaultTestSetUp( // we need to set it only once for all the lanes as the attestation path uses regex to match the path for // all messages across all lanes err = actions.SetMockServerWithUSDCAttestation(killgrave, setUpArgs.Env.MockServer, false) - require.NoError(t, err, "failed to set up mock server for attestation") + require.NoError(t, err, "failed to set up mock server for USDC attestation") + } + if pointer.GetBool(setUpArgs.Cfg.TestGroupInput.LBTCMockDeployment) { + // if it's a new LBTC deployment, set up mock server for attestation, + // we need to set it only once for all the lanes as the attestation path uses regex to match the path for + // all messages across all lanes + err = actions.SetMockServerWithLBTCAttestation(killgrave, setUpArgs.Env.MockServer) + require.NoError(t, err, "failed to set up mock server for LBTC attestation") } } // deploy all lane specific contracts diff --git a/integration-tests/ccip-tests/testsetups/test_env.go b/integration-tests/ccip-tests/testsetups/test_env.go index 3c3406a3e5a..3feb8abe9a9 100644 --- a/integration-tests/ccip-tests/testsetups/test_env.go +++ b/integration-tests/ccip-tests/testsetups/test_env.go @@ -240,6 +240,7 @@ func ChainlinkChart( return chainlink.New(0, clProps) } clProps["replicas"] = pointer.GetInt(testInputs.EnvInput.NewCLCluster.NoOfNodes) + _, tomlStr, err := SetNodeConfig( nets, testInputs.EnvInput.NewCLCluster.Common.BaseConfigTOML, @@ -293,6 +294,7 @@ func DeployLocalCluster( require.NoError(t, err, "failed to get default chain config: %w", err) } else { chainConfig.ChainID = int(network.ChainID) + eth1 := ctf_config_types.EthereumVersion_Eth1 geth := ctf_config_types.ExecutionLayer_Geth diff --git a/integration-tests/contracts/test_contracts.go b/integration-tests/contracts/test_contracts.go index f8674e2136d..f6ea627ef39 100644 --- a/integration-tests/contracts/test_contracts.go +++ b/integration-tests/contracts/test_contracts.go @@ -11,7 +11,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/smartcontractkit/chainlink/integration-tests/wrappers" - le "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter" + le "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/log_emitter" ) type LogEmitterContract struct { diff --git a/integration-tests/crib/README.md b/integration-tests/crib/README.md index c37cbfec9c9..b3ba2c41823 100644 --- a/integration-tests/crib/README.md +++ b/integration-tests/crib/README.md @@ -6,7 +6,7 @@ It runs OCRv1 and reboots the environment confirming integration with environmen Go to the [CRIB](https://github.com/smartcontractkit/crib) repository and spin up a cluster. ```shell -./scripts/cribbit.sh crib-oh-my-crib +DEVSPACE_NAMESPACE=crib-oh-my-crib crib init devspace deploy --debug --profile local-dev-simulated-core-ocr1 ``` diff --git a/integration-tests/docker/test_env/cl_node_cluster.go b/integration-tests/docker/test_env/cl_node_cluster.go index 596d1ae270b..369038def57 100644 --- a/integration-tests/docker/test_env/cl_node_cluster.go +++ b/integration-tests/docker/test_env/cl_node_cluster.go @@ -16,9 +16,7 @@ import ( "github.com/smartcontractkit/chainlink/deployment/environment/nodeclient" ) -var ( - ErrGetNodeCSAKeys = "failed get CL node CSA keys" -) +var ErrGetNodeCSAKeys = "failed get CL node CSA keys" type ClCluster struct { Nodes []*ClNode `json:"nodes"` diff --git a/integration-tests/docker/test_env/test_env.go b/integration-tests/docker/test_env/test_env.go index a37b7f813a7..06caea59919 100644 --- a/integration-tests/docker/test_env/test_env.go +++ b/integration-tests/docker/test_env/test_env.go @@ -2,6 +2,7 @@ package test_env import ( "context" + "errors" "fmt" "os" "path/filepath" @@ -193,7 +194,7 @@ func (te *CLClusterTestEnv) Cleanup(opts CleanupOpts) error { } if te.ClCluster == nil || len(te.ClCluster.Nodes) == 0 { - return fmt.Errorf("chainlink nodes are nil, unable cleanup chainlink nodes") + return errors.New("chainlink nodes are nil, unable to cleanup chainlink nodes") } te.logWhetherAllContainersAreRunning() diff --git a/integration-tests/go.mod b/integration-tests/go.mod index b5da0a24d2d..02580d20de9 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -12,8 +12,8 @@ replace github.com/smartcontractkit/chainlink/deployment => ../deployment // Using a separate `require` here to avoid surrounding line changes // creating potential merge conflicts. require ( - github.com/smartcontractkit/chainlink/deployment v0.0.0-20241206210521-125d98cdaf66 - github.com/smartcontractkit/chainlink/v2 v2.0.0-20241206210521-125d98cdaf66 + github.com/smartcontractkit/chainlink/deployment v0.0.0-20241212011003-de1a8f5e5b42 + github.com/smartcontractkit/chainlink/v2 v2.0.0-20241212011003-de1a8f5e5b42 ) require ( @@ -38,25 +38,25 @@ require ( github.com/onsi/gomega v1.34.2 github.com/pelletier/go-toml/v2 v2.2.3 github.com/pkg/errors v0.9.1 - github.com/prometheus/common v0.60.0 + github.com/prometheus/common v0.60.1 github.com/rs/zerolog v1.33.0 github.com/scylladb/go-reflectx v1.0.1 github.com/segmentio/ksuid v1.0.4 github.com/shopspring/decimal v1.4.0 github.com/slack-go/slack v0.15.0 - github.com/smartcontractkit/chain-selectors v1.0.34 + github.com/smartcontractkit/chain-selectors v1.0.36 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241213122413-5e8f65dd6b1b - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241214155818-b403079b2805 + github.com/smartcontractkit/chainlink-ccip v0.0.0-20250120130359-cc025272bbff + github.com/smartcontractkit/chainlink-common v0.4.2-0.20250116214855-f49c5c27db51 github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.19 github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.9 github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2 - github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 + github.com/smartcontractkit/libocr v0.0.0-20241223215956-e5b78d8e3919 github.com/spf13/cobra v1.8.1 - github.com/stretchr/testify v1.9.0 + github.com/stretchr/testify v1.10.0 github.com/subosito/gotenv v1.6.0 github.com/test-go/testify v1.1.4 github.com/testcontainers/testcontainers-go v0.34.0 @@ -65,7 +65,7 @@ require ( go.uber.org/multierr v1.11.0 go.uber.org/zap v1.27.0 golang.org/x/crypto v0.31.0 - golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c + golang.org/x/exp v0.0.0-20241210194714-1829a127f884 golang.org/x/sync v0.10.0 golang.org/x/text v0.21.0 google.golang.org/grpc v1.67.1 @@ -74,7 +74,6 @@ require ( ) require ( - contrib.go.opencensus.io/exporter/stackdriver v0.13.5 // indirect cosmossdk.io/api v0.3.1 // indirect cosmossdk.io/core v0.5.1 // indirect cosmossdk.io/depinject v1.0.0-alpha.4 // indirect @@ -127,6 +126,7 @@ require ( github.com/aws/constructs-go/constructs/v10 v10.4.2 // indirect github.com/aws/jsii-runtime-go v1.104.0 // indirect github.com/aws/smithy-go v1.22.0 // indirect + github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3 // indirect github.com/benbjohnson/clock v1.3.5 // indirect @@ -136,10 +136,11 @@ require ( github.com/blang/semver/v4 v4.0.0 // indirect github.com/blendle/zapdriver v1.3.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129 // indirect github.com/buger/jsonparser v1.1.1 // indirect github.com/bytecodealliance/wasmtime-go/v23 v23.0.0 // indirect - github.com/bytedance/sonic v1.11.6 // indirect - github.com/bytedance/sonic/loader v0.1.1 // indirect + github.com/bytedance/sonic v1.12.3 // indirect + github.com/bytedance/sonic/loader v0.2.0 // indirect github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b // indirect github.com/c9s/goprocinfo v0.0.0-20210130143923-c95fcf8c64a8 // indirect github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5 // indirect @@ -183,9 +184,8 @@ require ( github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect github.com/dennwc/varint v1.0.0 // indirect - github.com/dfuse-io/logging v0.0.0-20210109005628-b97a57253f70 // indirect github.com/dgraph-io/badger/v2 v2.2007.4 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect @@ -196,6 +196,7 @@ require ( github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dominikbraun/graph v0.23.0 // indirect + github.com/doyensec/safeurl v0.2.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.7.0 // indirect github.com/edsrzf/mmap-go v1.1.0 // indirect @@ -210,10 +211,11 @@ require ( github.com/fatih/color v1.17.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/gabriel-vasile/mimetype v1.4.3 // indirect - github.com/gagliardetto/binary v0.7.7 // indirect - github.com/gagliardetto/solana-go v1.8.4 // indirect + github.com/gabriel-vasile/mimetype v1.4.6 // indirect + github.com/gagliardetto/binary v0.8.0 // indirect + github.com/gagliardetto/solana-go v1.12.0 // indirect github.com/gagliardetto/treeout v0.1.4 // indirect + github.com/gagliardetto/utilz v0.1.1 // indirect github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/getsentry/sentry-go v0.27.0 // indirect github.com/gin-contrib/sessions v0.0.5 // indirect @@ -240,7 +242,7 @@ require ( github.com/go-openapi/validate v0.23.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.22.0 // indirect + github.com/go-playground/validator/v10 v10.22.1 // indirect github.com/go-redis/redis/v8 v8.11.5 // indirect github.com/go-viper/mapstructure/v2 v2.1.0 // indirect github.com/go-webauthn/webauthn v0.9.4 // indirect @@ -289,6 +291,7 @@ require ( github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/gtank/merlin v0.1.1 // indirect github.com/gtank/ristretto255 v0.1.2 // indirect + github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026 // indirect github.com/hashicorp/consul/api v1.29.2 // indirect github.com/hashicorp/consul/sdk v0.16.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect @@ -353,7 +356,7 @@ require ( github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.14 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect github.com/miekg/dns v1.1.61 // indirect github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect @@ -394,7 +397,7 @@ require ( github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect - github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect + github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect @@ -406,16 +409,17 @@ require ( github.com/prometheus/procfs v0.15.1 // indirect github.com/prometheus/prometheus v0.54.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect - github.com/rivo/uniseg v0.4.4 // indirect + github.com/rivo/uniseg v0.4.7 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect github.com/rogpeppe/go-internal v1.13.1 // indirect github.com/rs/cors v1.10.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/ryanuber/go-glob v1.0.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sanity-io/litter v1.5.5 // indirect github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect - github.com/sasha-s/go-deadlock v0.3.1 // indirect + github.com/sasha-s/go-deadlock v0.3.5 // indirect github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect github.com/sercand/kuberesolver/v5 v5.1.1 // indirect github.com/sethvargo/go-retry v0.2.4 // indirect @@ -424,12 +428,15 @@ require ( github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix // indirect + github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250103152858-8973fd0c912b // indirect github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e // indirect - github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3 // indirect + github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250115135646-ac859d85e7e3 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.1 // indirect + github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250115203616-a2ea5e50b260 // indirect github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241210172617-6fd1891d0fbc // indirect - github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.1-0.20250117143722-fb6416c087a5 // indirect + github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20250117171710-b6481e9fcb34 // indirect + github.com/smartcontractkit/chainlink-testing-framework/framework v0.4.2-0.20250110073248-456673e8eea2 // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de // indirect github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de // indirect @@ -442,12 +449,11 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.19.0 // indirect github.com/status-im/keycard-go v0.2.0 // indirect - github.com/streamingfast/logging v0.0.0-20220405224725-2755dab2ce75 // indirect + github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/supranational/blst v0.3.13 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tendermint/go-amino v0.16.0 // indirect - github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 // indirect github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a // indirect github.com/tidwall/btree v1.6.0 // indirect github.com/tidwall/gjson v1.17.0 // indirect @@ -478,7 +484,6 @@ require ( go.etcd.io/etcd/client/pkg/v3 v3.5.14 // indirect go.etcd.io/etcd/client/v3 v3.5.14 // indirect go.mongodb.org/mongo-driver v1.15.0 // indirect - go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/collector/pdata v1.12.0 // indirect go.opentelemetry.io/collector/semconv v0.105.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 // indirect @@ -506,13 +511,13 @@ require ( go.uber.org/ratelimit v0.3.1 // indirect go4.org/netipx v0.0.0-20230125063823-8449b0a6169f // indirect golang.org/x/arch v0.11.0 // indirect - golang.org/x/mod v0.21.0 // indirect - golang.org/x/net v0.30.0 // indirect + golang.org/x/mod v0.22.0 // indirect + golang.org/x/net v0.32.0 // indirect golang.org/x/oauth2 v0.23.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/term v0.27.0 // indirect golang.org/x/time v0.7.0 // indirect - golang.org/x/tools v0.26.0 // indirect + golang.org/x/tools v0.28.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect gonum.org/v1/gonum v0.15.1 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 71bf4dc9ccb..5b68822add8 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -3,7 +3,6 @@ cel.dev/expr v0.17.0/go.mod h1:HCwbrn+qQoHPXgfz6cl2J0hDybnX2N1sQQkl9EggXx8= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= @@ -54,10 +53,6 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.45.0 h1:5av0QcIVj77t+44mV4gffFC/LscFRUhto6UBMB5SimM= cloud.google.com/go/storage v1.45.0/go.mod h1:wpPblkIuMP5jCB/E48Pz9zIo2S/zD8g+ITmxKkPCITE= -contrib.go.opencensus.io/exporter/stackdriver v0.12.6/go.mod h1:8x999/OcIPy5ivx/wDiV7Gx4D+VUPODf0mWRGRc5kSk= -contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= -contrib.go.opencensus.io/exporter/stackdriver v0.13.5 h1:TNaexHK16gPUoc7uzELKOU7JULqccn1NDuqUxmxSqfo= -contrib.go.opencensus.io/exporter/stackdriver v0.13.5/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= cosmossdk.io/api v0.3.1 h1:NNiOclKRR0AOlO4KIqeaG6PS6kswOMhHD0ir0SscNXE= cosmossdk.io/api v0.3.1/go.mod h1:DfHfMkiNA2Uhy8fj0JJlOCYOBp4eWUUJ1te5zBGNyIw= cosmossdk.io/core v0.5.1 h1:vQVtFrIYOQJDV3f7rw4pjjVqc1id4+mE0L9hHP66pyI= @@ -75,7 +70,6 @@ cosmossdk.io/tools/rosetta v0.2.1/go.mod h1:Pqdc1FdvkNV3LcNIkYWt2RQY6IP1ge6YWZk8 dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -118,8 +112,6 @@ github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/Depado/ginprom v1.8.0 h1:zaaibRLNI1dMiiuj1MKzatm8qrcHzikMlCc1anqOdyo= github.com/Depado/ginprom v1.8.0/go.mod h1:XBaKzeNBqPF4vxJpNLincSQZeMDnZp1tIbU0FU0UKgg= -github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0= -github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 h1:3c8yed4lgqTt+oTQ+JNMDo+F4xprBf+O/il4ZC0nRLw= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0/go.mod h1:obipzmGjfSjam60XLwGfqUkJsfiheAl+TUjG+4yzyPM= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.3 h1:xir5X8TS8UBVPWg2jHL+cSTf0jZgqYQSA54TscSt1/0= @@ -159,7 +151,6 @@ github.com/Workiva/go-datastructures v1.1.0 h1:hu20UpgZneBhQ3ZvwiOGlqJSKIosin2Rd github.com/Workiva/go-datastructures v1.1.0/go.mod h1:1yZL+zfsztete+ePzZz/Zb1/t5BnDuE2Ya2MMGhzP6A= github.com/XSAM/otelsql v0.27.0 h1:i9xtxtdcqXV768a5C6SoT/RkG+ue3JTOgkYInzlTOqs= github.com/XSAM/otelsql v0.27.0/go.mod h1:0mFB3TvLa7NCuhm/2nU7/b2wEtsczkj8Rey8ygO7V+A= -github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -177,7 +168,6 @@ github.com/alicebob/miniredis/v2 v2.30.4/go.mod h1:b25qWj4fCEsBeAAR2mlb0ufImGC6u github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129/go.mod h1:rFgpPQZYZ8vdbc+48xibu8ALc3yeyd64IhHS+PU6Yyg= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA= @@ -204,8 +194,6 @@ github.com/avast/retry-go/v4 v4.6.0 h1:K9xNA+KeB8HHc2aWFuLb25Offp+0iVRXEvFx8IinR github.com/avast/retry-go/v4 v4.6.0/go.mod h1:gvWlPhBVsvBbLkVGDg/KwvBv0bEkCOLRRSHKIr2PyOE= github.com/awalterschulze/gographviz v2.0.3+incompatible h1:9sVEXJBJLwGX7EQVhLm2elIKCm7P2YHFC8v6096G09E= github.com/awalterschulze/gographviz v2.0.3+incompatible/go.mod h1:GEV5wmg4YquNw7v1kkyoX9etIk8yVmXj+AkDHuuETHs= -github.com/aws/aws-sdk-go v1.22.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.54.19 h1:tyWV+07jagrNiCcGRzRhdtVjQs7Vy41NwsuOcl0IbVI= github.com/aws/aws-sdk-go v1.54.19/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= @@ -241,6 +229,10 @@ github.com/aws/jsii-runtime-go v1.104.0 h1:651Sh6J2FtatfnVzlOQ3/Ye1WWPAseZ6E/tSQ github.com/aws/jsii-runtime-go v1.104.0/go.mod h1:7ZmQXxV0AAhhvv/GaHX4n6zbgA1tSRVdnQYAJbIhXHk= github.com/aws/smithy-go v1.22.0 h1:uunKnWlcoL3zO7q+gG2Pk53joueEOsnNB28QdMsmiMM= github.com/aws/smithy-go v1.22.0/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= +github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 h1:WWB576BN5zNSZc/M9d/10pqEx5VHNhaQ/yOVAkmj5Yo= +github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= +github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= +github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df h1:GSoSVRLoBaFpOOds6QyY1L8AX7uoY+Ln3BHc22W40X0= @@ -261,7 +253,6 @@ github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 h1:41iFGWnSlI2 github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= @@ -276,16 +267,19 @@ github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6 github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= +github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129 h1:gfAMKE626QEuKG3si0pdTRcr/YEbBoxY+3GOH3gWvl4= +github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129/go.mod h1:u9UyCz2eTrSGy6fbupqJ54eY5c4IC8gREQ1053dK12U= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/bxcodec/faker v2.0.1+incompatible h1:P0KUpUw5w6WJXwrPfv35oc91i4d8nf40Nwln+M/+faA= github.com/bxcodec/faker v2.0.1+incompatible/go.mod h1:BNzfpVdTwnFJ6GtfYTcQu6l6rHShT+veBxNCnjCx5XM= github.com/bytecodealliance/wasmtime-go/v23 v23.0.0 h1:NJvU4S8KEk1GnF6+FvlnzMD/8wXTj/mYJSG6Q4yu3Pw= github.com/bytecodealliance/wasmtime-go/v23 v23.0.0/go.mod h1:5YIL+Ouiww2zpO7u+iZ1U1G5NvmwQYaXdmCZQGjQM0U= -github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= -github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= -github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= +github.com/bytedance/sonic v1.12.3 h1:W2MGa7RCU1QTeYRTPE3+88mVC0yXmsRQRChiyVocVjU= +github.com/bytedance/sonic v1.12.3/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/bytedance/sonic/loader v0.2.0 h1:zNprn+lsIP06C/IqCHs3gPQIvnvpKbbxyXQP1iU4kWM= +github.com/bytedance/sonic/loader v0.2.0/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b h1:6+ZFm0flnudZzdSE0JxlhR2hKnGPcNB35BjQf4RYQDY= github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M= github.com/c9s/goprocinfo v0.0.0-20210130143923-c95fcf8c64a8 h1:SjZ2GvvOononHOpK84APFuMvxqsk3tEIaKH/z4Rpu3g= @@ -376,9 +370,7 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -389,7 +381,6 @@ github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7 github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= @@ -428,9 +419,8 @@ github.com/creachadair/taskgroup v0.4.2 h1:jsBLdAJE42asreGss2xZGZ8fJra7WtwnHWeJF github.com/creachadair/taskgroup v0.4.2/go.mod h1:qiXUOSrbwAY3u0JPGTzObbE3yf9hcXHDKBZ2ZjpCbgM= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= -github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E= +github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0= +github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= github.com/danielkov/gin-helmet v0.0.0-20171108135313-1387e224435e h1:5jVSh2l/ho6ajWhSPNN84eHEdq3dp0T7+f6r3Tc6hsk= @@ -444,27 +434,22 @@ github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80N github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/dennwc/varint v1.0.0 h1:kGNFFSSw8ToIy3obO/kKr8U9GZYUAxQEVuix4zfDWzE= github.com/dennwc/varint v1.0.0/go.mod h1:hnItb35rvZvJrbTALZtY/iQfDs48JKRG1RPpgziApxA= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= -github.com/dfuse-io/logging v0.0.0-20201110202154-26697de88c79/go.mod h1:V+ED4kT/t/lKtH99JQmKIb0v9WL3VaYkJ36CfHlVECI= -github.com/dfuse-io/logging v0.0.0-20210109005628-b97a57253f70 h1:CuJS05R9jmNlUK8GOxrEELPbfXm0EuGh/30LjkjN5vo= -github.com/dfuse-io/logging v0.0.0-20210109005628-b97a57253f70/go.mod h1:EoK/8RFbMEteaCaz89uessDTnCWjbbcr+DXcBh4el5o= github.com/dgraph-io/badger/v2 v2.2007.4 h1:TRWBQg8UrlUhaFdco01nO2uXwzKS7zd+HVdwV/GHc4o= github.com/dgraph-io/badger/v2 v2.2007.4/go.mod h1:vSw/ax2qojzbN6eXHIx6KPKtCSHJN/Uz0X0VPruTIhk= github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/digitalocean/godo v1.118.0 h1:lkzGFQmACrVCp7UqH1sAi4JK/PWwlc5aaxubgorKmC4= github.com/digitalocean/godo v1.118.0/go.mod h1:Vk0vpCot2HOAJwc5WE8wljZGtJ3ZtWIc8MQ8rF38sdo= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= @@ -479,6 +464,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dominikbraun/graph v0.23.0 h1:TdZB4pPqCLFxYhdyMFb1TBdFxp8XLcJfTTBQucVPgCo= github.com/dominikbraun/graph v0.23.0/go.mod h1:yOjYyogZLY1LSG9E33JWZJiq5k83Qy2C6POAuiViluc= +github.com/doyensec/safeurl v0.2.1 h1:DY15JorEfQsnpBWhBkVQIkaif2jfxCC14PIuGDsjDVs= +github.com/doyensec/safeurl v0.2.1/go.mod h1:wzSXqC/6Z410qHz23jtBWT+wQ8yTxcY0p8bZH/4EZIg= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= @@ -535,16 +522,19 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= -github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= -github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= -github.com/gagliardetto/binary v0.7.7 h1:QZpT38+sgoPg+TIQjH94sLbl/vX+nlIRA37pEyOsjfY= -github.com/gagliardetto/binary v0.7.7/go.mod h1:mUuay5LL8wFVnIlecHakSZMvcdqfs+CsotR5n77kyjM= +github.com/gabriel-vasile/mimetype v1.4.6 h1:3+PzJTKLkvgjeTbts6msPJt4DixhT4YtFNf1gtGe3zc= +github.com/gabriel-vasile/mimetype v1.4.6/go.mod h1:JX1qVKqZd40hUPpAfiNTe0Sne7hdfKSbOqqmkq8GCXc= +github.com/gagliardetto/binary v0.8.0 h1:U9ahc45v9HW0d15LoN++vIXSJyqR/pWw8DDlhd7zvxg= +github.com/gagliardetto/binary v0.8.0/go.mod h1:2tfj51g5o9dnvsc+fL3Jxr22MuWzYXwx9wEoN0XQ7/c= github.com/gagliardetto/gofuzz v1.2.2 h1:XL/8qDMzcgvR4+CyRQW9UGdwPRPMHVJfqQ/uMvSUuQw= github.com/gagliardetto/gofuzz v1.2.2/go.mod h1:bkH/3hYLZrMLbfYWA0pWzXmi5TTRZnu4pMGZBkqMKvY= -github.com/gagliardetto/solana-go v1.8.4 h1:vmD/JmTlonyXGy39bAo0inMhmbdAwV7rXZtLDMZeodE= -github.com/gagliardetto/solana-go v1.8.4/go.mod h1:i+7aAyNDTHG0jK8GZIBSI4OVvDqkt2Qx+LklYclRNG8= +github.com/gagliardetto/hashsearch v0.0.0-20191005111333-09dd671e19f9/go.mod h1:513DXpQPzeRo7d4dsCP3xO3XI8hgvruMl9njxyQeraQ= +github.com/gagliardetto/solana-go v1.12.0 h1:rzsbilDPj6p+/DOPXBMLhwMZeBgeRuXjm5zQFCoXgsg= +github.com/gagliardetto/solana-go v1.12.0/go.mod h1:l/qqqIN6qJJPtxW/G1PF4JtcE3Zg2vD2EliZrr9Gn5k= github.com/gagliardetto/treeout v0.1.4 h1:ozeYerrLCmCubo1TcIjFiOWTTGteOOHND1twdFpgwaw= github.com/gagliardetto/treeout v0.1.4/go.mod h1:loUefvXTrlRG5rYmJmExNryyBRh8f89VZhmMOyCyqok= +github.com/gagliardetto/utilz v0.1.1 h1:/etW4hl607emKg6R6Lj9jRJ9d6ue2AQOyjhuAwjzs1U= +github.com/gagliardetto/utilz v0.1.1/go.mod h1:b+rGFkRHz3HWJD0RYMzat47JyvbTtpE0iEcYTRJTLLA= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813 h1:Uc+IZ7gYqAf/rSGFplbWBSHaGolEQlNLgMgSE3ccnIQ= @@ -621,8 +611,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao= -github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA= +github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/go-resty/resty/v2 v2.15.3 h1:bqff+hcqAflpiF591hhJzNdkRsFhlB96CYfBwSFvql8= @@ -668,7 +658,6 @@ github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVI github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -704,7 +693,6 @@ github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= @@ -789,7 +777,6 @@ github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/rpc v1.2.0/go.mod h1:V4h9r+4sF5HnzqbwIez0fKSpANP0zlYd3qR7p36jkTQ= github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY= @@ -819,15 +806,12 @@ github.com/graph-gophers/graphql-go v1.5.0 h1:fDqblo50TEpD0LY7RXk/LFVYEVqo3+tXMN github.com/graph-gophers/graphql-go v1.5.0/go.mod h1:YtmJZDLbF1YYNrlNAuiO5zAStUWc3XZT07iGsVqe1Os= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= @@ -840,6 +824,8 @@ github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is= github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc= github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o= +github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026 h1:BpJ2o0OR5FV7vrkDYfXYVJQeMNWa8RhklZOpW2ITAIQ= +github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026/go.mod h1:5Scbynm8dF1XAPwIwkGPqzkM/shndPm79Jd1003hTjE= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/api v1.29.2 h1:aYyRn8EdE2mSfG14S1+L9Qkjtz8RzmaWh6AcNGRNwPw= github.com/hashicorp/consul/api v1.29.2/go.mod h1:0YObcaLNDSbtlgzIRtmRXI1ZkeuK0trCBxwZQ4MYnIk= @@ -898,7 +884,6 @@ github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09 github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru v0.6.0 h1:uL2shRDx7RTrOrTCUZEGP/wJUFiUI8QT6E7z5o8jga4= github.com/hashicorp/golang-lru v0.6.0/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= @@ -1003,10 +988,8 @@ github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0f github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= @@ -1017,7 +1000,6 @@ github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4= github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -1042,7 +1024,6 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= @@ -1094,7 +1075,6 @@ github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= @@ -1126,8 +1106,8 @@ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= -github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= @@ -1136,6 +1116,7 @@ github.com/mfridman/interpolate v0.0.2 h1:pnuTK7MQIxxFz1Gr+rjSIx9u7qVjf5VOoM/u6B github.com/mfridman/interpolate v0.0.2/go.mod h1:p+7uk6oE07mpE/Ik1b8EckO0O4ZXiGAfshKBWLUM9Xg= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs= github.com/miekg/dns v1.1.61/go.mod h1:mnAarhS3nWaW+NVP2wTkYVIZyHNJ098SJZUki3eykwQ= @@ -1195,7 +1176,6 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= -github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= @@ -1208,8 +1188,8 @@ github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= -github.com/muesli/termenv v0.12.0 h1:KuQRUE3PgxRFWhq4gHvZtPSLCGDqM5q/cYr1pZ39ytc= -github.com/muesli/termenv v0.12.0/go.mod h1:WCCv32tusQ/EEZ5S8oUIIrC/nIuBcxCVqlN4Xfkv+7A= +github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a h1:2MaM6YC3mGu54x+RKAA6JiFFHlHDY1UbkxqppT7wYOg= +github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a/go.mod h1:hxSnBBYLK21Vtq/PHd0S2FYCxBXzBua8ov5s1RobyRQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -1220,7 +1200,6 @@ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+ github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1 h1:dOYG7LS/WK00RWZc8XGgcUTlTxpp3mKhdR2Q9z9HbXM= github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1/go.mod h1:mpRZBD8SJ55OIICQ3iWH0Yz3cjzA61JdqMLoWXeB2+8= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= @@ -1282,9 +1261,8 @@ github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNH github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= -github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 h1:hDSdbBuw3Lefr6R18ax0tZ2BJeNB3NehB3trOwYBsdU= -github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 h1:Dx7Ovyv/SFnMFw3fD4oEoeorXc6saIiQ23LrGLth0Gw= +github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= @@ -1312,7 +1290,6 @@ github.com/pressly/goose/v3 v3.21.1/go.mod h1:sqthmzV8PitchEkjecFJII//l43dLOCzfW github.com/prometheus/alertmanager v0.27.0 h1:V6nTa2J5V4s8TG4C4HtrBP/WNSebCCTYGGv4qecA/+I= github.com/prometheus/alertmanager v0.27.0/go.mod h1:8Ia/R3urPmbzJ8OsdvmZvIprDwvwmYCmUbwBL+jlPOE= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= @@ -1325,21 +1302,18 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1: github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= -github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= +github.com/prometheus/common v0.60.1 h1:FUas6GcOw66yB/73KC+BOZoFJmbo/1pojoILArPAaSc= +github.com/prometheus/common v0.60.1/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/common/sigv4 v0.1.0 h1:qoVebwtwwEhS85Czm2dSROY5fTo2PAPEVdDeppTwGX4= github.com/prometheus/common/sigv4 v0.1.0/go.mod h1:2Jkxxk9yYvCkE5G1sQT7GuEXm57JrvHu9k5YwTjsNtI= github.com/prometheus/exporter-toolkit v0.11.0 h1:yNTsuZ0aNCNFQ3aFTD2uhPOvr4iD7fdBvKPAEGkNf+g= github.com/prometheus/exporter-toolkit v0.11.0/go.mod h1:BVnENhnNecpwoTLiABx7mrPB/OLRIgN74qlQbV+FK1Q= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= @@ -1348,7 +1322,6 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/prometheus v0.54.1 h1:vKuwQNjnYN2/mDoWfHXDhAsz/68q/dQDb+YbcEqU7MQ= github.com/prometheus/prometheus v0.54.1/go.mod h1:xlLByHhk2g3ycakQGrMaU8K7OySZx98BzeCR99991NY= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= @@ -1356,11 +1329,10 @@ github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqn github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4= github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC5sZ4OhQ3+NtdbZ6oBDKQwq5Ou+FI= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= @@ -1379,6 +1351,8 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= +github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= @@ -1387,8 +1361,8 @@ github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQ github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= -github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= -github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= +github.com/sasha-s/go-deadlock v0.3.5 h1:tNCOEEDG6tBqrNDOX35j/7hL5FcFViG6awUGROb2NsU= +github.com/sasha-s/go-deadlock v0.3.5/go.mod h1:bugP6EGbdGYObIlx7pUZtWqlvo8k9H6vCBBsiChJQ5U= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/scaleway/scaleway-sdk-go v1.0.0-beta.29 h1:BkTk4gynLjguayxrYxZoMZjBnAOh7ntQvUkOFmkMqPU= github.com/scaleway/scaleway-sdk-go v1.0.0-beta.29/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg= @@ -1432,28 +1406,34 @@ github.com/slack-go/slack v0.15.0 h1:LE2lj2y9vqqiOf+qIIy0GvEoxgF1N5yLGZffmEZykt0 github.com/slack-go/slack v0.15.0/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix h1:DPJD++yKLSx0EfT+U14P8vLVxjXFmoIETiCO9lVwQo8= github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= -github.com/smartcontractkit/chain-selectors v1.0.34 h1:MJ17OGu8+jjl426pcKrJkCf3fePb3eCreuAnUA3RBj4= -github.com/smartcontractkit/chain-selectors v1.0.34/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= +github.com/smartcontractkit/chain-selectors v1.0.36 h1:KSpO8I+JOiuyN4FuXsV471sPorGF//PAqwq2Cm4gRK0= +github.com/smartcontractkit/chain-selectors v1.0.36/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241213122413-5e8f65dd6b1b h1:iSQJ6ng4FhEswf8SXunGkaJlVP3E3JlgLB8Oo2f3Ud4= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241213122413-5e8f65dd6b1b/go.mod h1:F8xQAIW0ymb2BZhqn89sWZLXreJhM5KDVF6Qb4y44N0= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241214155818-b403079b2805 h1:Pz8jB/6qe10xT10h2S3LFYJrnebNpG5rJ/w16HZGwPQ= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241214155818-b403079b2805/go.mod h1:yti7e1+G9hhkYhj+L5sVUULn9Bn3bBL5/AxaNqdJ5YQ= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250120130359-cc025272bbff h1:ZEOlcleVdT0/y9V5yjgFJF0j7MpvdrFmKis/xmFNIgE= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250120130359-cc025272bbff/go.mod h1:JJZMCB75aVSAiPNW032F9WUKTlLztTd8bbQB5MEaZa4= +github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250103152858-8973fd0c912b h1:UBXi9Yj8YSMHDDaxQLu273x1fWjyEL9xP58nuJsqZfg= +github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250103152858-8973fd0c912b/go.mod h1:Bmwq4lNb5tE47sydN0TKetcLEGbgl+VxHEWp4S0LI60= +github.com/smartcontractkit/chainlink-common v0.4.2-0.20250116214855-f49c5c27db51 h1:YdjQiEu5uHWM1ApwdV+nLyJmu1+tt3IeiwPKNGoXwBI= +github.com/smartcontractkit/chainlink-common v0.4.2-0.20250116214855-f49c5c27db51/go.mod h1:yti7e1+G9hhkYhj+L5sVUULn9Bn3bBL5/AxaNqdJ5YQ= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3 h1:aeiBdBHGY8QNftps+VqrIk6OnfeeOD5z4jrAabW4ZSc= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3/go.mod h1:AS6zY2BkcRwfiGzNabGbHhfrLSrXrcI/GmjnT4jQ5/s= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250115135646-ac859d85e7e3 h1:GcPYNVFYjB065CNq0h8nK/VeU08nUkHgBX0cJIEpuHY= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250115135646-ac859d85e7e3/go.mod h1:pDZagSGjs9U+l4YIFhveDznMHqxuuz+5vRxvVgpbdr8= github.com/smartcontractkit/chainlink-feeds v0.1.1 h1:JzvUOM/OgGQA1sOqTXXl52R6AnNt+Wg64sVG+XSA49c= github.com/smartcontractkit/chainlink-feeds v0.1.1/go.mod h1:55EZ94HlKCfAsUiKUTNI7QlE/3d3IwTlsU3YNa/nBb4= +github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250115203616-a2ea5e50b260 h1:See2isL6KdrTJDlVKWv8qiyYqWhYUcubU2e5yKXV1oY= +github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250115203616-a2ea5e50b260/go.mod h1:4JqpgFy01LaqG1yM2iFTzwX3ZgcAvW9WdstBZQgPHzU= github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 h1:0ewLMbAz3rZrovdRUCgd028yOXX8KigB4FndAUdI2kM= github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0/go.mod h1:/dVVLXrsp+V0AbcYGJo3XMzKg3CkELsweA/TTopCsKE= github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0 h1:ZBat8EBvE2LpSQR9U1gEbRV6PfAkiFdINmQ8nVnXIAQ= github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241210172617-6fd1891d0fbc h1:dssRwJhmzJkUN/OajaDj2GsxBn+Tupk3bI1BkPEoJg0= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241210172617-6fd1891d0fbc/go.mod h1:p8aUDfJeley6oer7y+Ucd3edOtRlMTnWg3mN6rhaLWo= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 h1:tNS7U9lrxkFvEuyxQv11HHOiV9LPDGC9wYEy+yM/Jv4= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8/go.mod h1:EBrEgcdIbwepqguClkv8Ohy7CbyWSJaE4EC9aBJlQK0= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20250117143722-fb6416c087a5 h1:kDW6Ab8vGRK2y+DPEvvhU2It8UCS9FK5ZQqIVjDfpK4= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20250117143722-fb6416c087a5/go.mod h1:uHVnYLMgJ1rTcNoVxhBpy38t69gXq0j+LN3TkcIVE3U= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20250117171710-b6481e9fcb34 h1:tQCjnIjY88AClWXApaTS+/ihQYM1GVCrbD9W00eh11E= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20250117171710-b6481e9fcb34/go.mod h1:lgG9JT2P19KnYuBheKIis5ZeCO+AaSta+RfzvwDQS2Y= +github.com/smartcontractkit/chainlink-testing-framework/framework v0.4.2-0.20250110073248-456673e8eea2 h1:nTUoe7GZLw17nPLV5t3Vgf4U4pf+VW0Uko5xpNiKdKU= +github.com/smartcontractkit/chainlink-testing-framework/framework v0.4.2-0.20250110073248-456673e8eea2/go.mod h1:mMUqvS3BZfvN1OfK4OFTYf1+T0X6nwmSXJM2keaPsSM= github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 h1:GDGrC5OGiV0RyM1znYWehSQXyZQWTOzrEeJRYmysPCE= github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2/go.mod h1:DsT43c1oTBmp3iQkMcoZOoKThwZvt8X3Pz6UmznJ4GY= github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.19 h1:9PMwKNqFKc5FXf4VchyD3CGzZelnSgi13fgVdT2X7T4= @@ -1466,8 +1446,8 @@ github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2 h1:7bCdbTUW github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2/go.mod h1:MltlNu3jcXm/DyLN98I5TFNtu/o1NNAcaPAFKMXWk70= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA= -github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 h1:NzZGjaqez21I3DU7objl3xExTH4fxYvzTqar8DC6360= -github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= +github.com/smartcontractkit/libocr v0.0.0-20241223215956-e5b78d8e3919 h1:IpGoPTXpvllN38kT2z2j13sifJMz4nbHglidvop7mfg= +github.com/smartcontractkit/libocr v0.0.0-20241223215956-e5b78d8e3919/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de h1:n0w0rKF+SVM+S3WNlup6uabXj2zFlFNfrlsKCMMb/co= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:Sl2MF/Fp3fgJIVzhdGhmZZX2BlnM0oUUyBP4s4xYb6o= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de h1:66VQxXx3lvTaAZrMBkIcdH9VEjujUEvmBQdnyOJnkOc= @@ -1478,7 +1458,6 @@ github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/sony/gobreaker v0.5.0 h1:dRCvqm0P490vZPmy7ppEk2qCnCieBooFJ+YoXGYB+yg= @@ -1497,7 +1476,6 @@ github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= @@ -1507,15 +1485,13 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= -github.com/streamingfast/logging v0.0.0-20220405224725-2755dab2ce75 h1:ZqpS7rAhhKD7S7DnrpEdrnW1/gZcv82ytpMviovkli4= -github.com/streamingfast/logging v0.0.0-20220405224725-2755dab2ce75/go.mod h1:VlduQ80JcGJSargkRU4Sg9Xo63wZD/l8A5NC/Uo1/uU= +github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 h1:RN5mrigyirb8anBEtdjtHFIufXdacyTi6i4KBfeNXeo= +github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091/go.mod h1:VlduQ80JcGJSargkRU4Sg9Xo63wZD/l8A5NC/Uo1/uU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= @@ -1535,8 +1511,9 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= @@ -1546,9 +1523,6 @@ github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDd github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= -github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0= -github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 h1:3SNcvBmEPE1YlB1JpVZouslJpI3GBNoiqW7+wb0Rz7w= -github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0= github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE= github.com/test-go/testify v1.1.4/go.mod h1:rH7cfJo/47vWGdi4GPj16x3/t1xGOj2YxzmNQzk2ghU= github.com/testcontainers/testcontainers-go v0.34.0 h1:5fbgF0vIN5u+nD3IWabQwRybuB4GY8G2HHgCkbMzMHo= @@ -1559,12 +1533,10 @@ github.com/thlib/go-timezone-local v0.0.0-20210907160436-ef149e42d28e h1:Buzhfgf github.com/thlib/go-timezone-local v0.0.0-20210907160436-ef149e42d28e/go.mod h1:/Tnicc6m/lsJE0irFMA0LfIwTBo4QP7A8IfyIv4zZKI= github.com/tidwall/btree v1.6.0 h1:LDZfKfQIBHGHWSwckhXI0RPSXzlo+KYdjK7FWSqOzzg= github.com/tidwall/btree v1.6.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= -github.com/tidwall/gjson v1.9.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM= github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= -github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= @@ -1572,7 +1544,6 @@ github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFA github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= @@ -1599,10 +1570,8 @@ github.com/urfave/cli v1.22.14 h1:ebbhrRiGK2i4naQJr+1Xj92HXZCrK7MsyTS/ob3HnAk= github.com/urfave/cli v1.22.14/go.mod h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA= github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fastjson v1.4.1 h1:hrltpHpIpkaxll8QltMU8c3QZ5+qIiCL8yKqPFJI/yE= github.com/valyala/fastjson v1.4.1/go.mod h1:nV6MsjxL2IMJQUoHDIrjEI7oLyeqK6aBD7EFWPsvP8o= -github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/vektah/gqlparser/v2 v2.5.11 h1:JJxLtXIoN7+3x6MBdtIP59TP1RANnY7pXOaDnADQSf8= github.com/vektah/gqlparser/v2 v2.5.11/go.mod h1:1rCcfwB2ekJofmluGWXMSEnPMZgbxzwj6FaZ/4OT8Cc= github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs= @@ -1611,10 +1580,6 @@ github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/ github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= -github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= -github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= @@ -1622,7 +1587,6 @@ github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGC github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= -github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -1649,7 +1613,6 @@ go.dedis.ch/kyber/v3 v3.1.0/go.mod h1:kXy7p3STAurkADD+/aZcsznZGKVHEqbtmdIzvPfrs1 go.dedis.ch/protobuf v1.0.5/go.mod h1:eIV4wicvi6JK0q/QnfIEGeSFNG0ZeB24kzut5+HaRLo= go.dedis.ch/protobuf v1.0.7/go.mod h1:pv5ysfkDX/EawiPqcW3ikOxsL5t+BqnV6xHSmE79KI4= go.dedis.ch/protobuf v1.0.11/go.mod h1:97QR256dnkimeNdfmURz0wAMNVbd1VmLXhG1CrTYrJ4= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= @@ -1661,12 +1624,10 @@ go.etcd.io/etcd/client/pkg/v3 v3.5.14/go.mod h1:8uMgAokyG1czCtIdsq+AGyYQMvpIKnSv go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= go.etcd.io/etcd/client/v3 v3.5.14 h1:CWfRs4FDaDoSz81giL7zPpZH2Z35tbOrAJkkjMqOupg= go.etcd.io/etcd/client/v3 v3.5.14/go.mod h1:k3XfdV/VIHy/97rqWjoUzrj9tk7GgJGH9J8L4dNXmAk= -go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= go.mongodb.org/mongo-driver v1.15.0 h1:rJCKC8eEliewXjZGf0ddURtl7tTVy1TK3bfl0gkUSLc= go.mongodb.org/mongo-driver v1.15.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -1740,22 +1701,18 @@ go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKY go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/ratelimit v0.2.0/go.mod h1:YYBV4e4naJvhpitQrWJu1vCpgB7CboMe0qhltKt6mUg= go.uber.org/ratelimit v0.3.1 h1:K4qVE+byfv/B3tC+4nYWP7v/6SimcO7HzHekoMNBma0= go.uber.org/ratelimit v0.3.1/go.mod h1:6euWsTB6U/Nb3X++xEUXA8ciPJvr19Q/0h1+oDcJhRk= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go4.org/netipx v0.0.0-20230125063823-8449b0a6169f h1:ketMxHg+vWm3yccyYiq+uK8D3fRmna2Fcj+awpQp84s= go4.org/netipx v0.0.0-20230125063823-8449b0a6169f/go.mod h1:tgPU4N2u9RByaTN3NC2p9xOzyFpte4jYwsIIRF7XlSc= -golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.11.0 h1:KXV8WWKCXm6tRpLirl2szsO5j/oOODwZf4hATmGVNs4= golang.org/x/arch v0.11.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1779,7 +1736,6 @@ golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= @@ -1794,8 +1750,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY= -golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= +golang.org/x/exp v0.0.0-20241210194714-1829a127f884 h1:Y/Mj/94zIQQGHVSv1tTtQBDaQaJe62U9bkDZKKyhPCU= +golang.org/x/exp v0.0.0-20241210194714-1829a127f884/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1824,15 +1780,14 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= +golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -1883,8 +1838,8 @@ golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= -golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= +golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= +golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1920,7 +1875,6 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1937,7 +1891,6 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2014,7 +1967,6 @@ golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -2063,7 +2015,6 @@ golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -2109,8 +2060,8 @@ golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= -golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= -golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= +golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8= +golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -2128,7 +2079,6 @@ google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEt google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.10.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= @@ -2153,7 +2103,6 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= @@ -2164,7 +2113,6 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -2214,7 +2162,6 @@ google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmE google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -2267,16 +2214,13 @@ gopkg.in/guregu/null.v4 v4.0.0/go.mod h1:YoQhUrADuG3i9WqesrCmpNRwm1ypAgSHYqoOcTu gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -2327,7 +2271,6 @@ nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYm pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw= pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= diff --git a/integration-tests/load/automationv2_1/automationv2_1_test.go b/integration-tests/load/automationv2_1/automationv2_1_test.go index 823c1bd8825..8d8135d214f 100644 --- a/integration-tests/load/automationv2_1/automationv2_1_test.go +++ b/integration-tests/load/automationv2_1/automationv2_1_test.go @@ -47,8 +47,8 @@ import ( aconfig "github.com/smartcontractkit/chainlink/integration-tests/testconfig/automation" "github.com/smartcontractkit/chainlink/integration-tests/testreporters" ac "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_compatible_utils" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/simple_log_upkeep_counter_wrapper" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/log_emitter" ) const ( diff --git a/integration-tests/load/automationv2_1/gun.go b/integration-tests/load/automationv2_1/gun.go index aa61562741c..7e26d906456 100644 --- a/integration-tests/load/automationv2_1/gun.go +++ b/integration-tests/load/automationv2_1/gun.go @@ -10,7 +10,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/seth" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/log_emitter" "github.com/smartcontractkit/chainlink/integration-tests/contracts" ) diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 96c3bb1dbce..5e4cbf4d820 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -14,9 +14,9 @@ replace github.com/smartcontractkit/chainlink/integration-tests => ../ // Using a separate `require` here to avoid surrounding line changes // creating potential merge conflicts. require ( - github.com/smartcontractkit/chainlink/deployment v0.0.0-20241206210521-125d98cdaf66 - github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20241206210521-125d98cdaf66 - github.com/smartcontractkit/chainlink/v2 v2.0.0-20241206210521-125d98cdaf66 + github.com/smartcontractkit/chainlink/deployment v0.0.0-20241212011003-de1a8f5e5b42 + github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20241212011003-de1a8f5e5b42 + github.com/smartcontractkit/chainlink/v2 v2.0.0-20241212011003-de1a8f5e5b42 ) require ( @@ -27,19 +27,18 @@ require ( github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.33.0 github.com/slack-go/slack v0.15.0 - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241214155818-b403079b2805 + github.com/smartcontractkit/chainlink-common v0.4.2-0.20250116214855-f49c5c27db51 github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.19 github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.9 github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2 github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de - github.com/stretchr/testify v1.9.0 + github.com/stretchr/testify v1.10.0 github.com/wiremock/go-wiremock v1.9.0 go.uber.org/ratelimit v0.3.1 - golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c + golang.org/x/exp v0.0.0-20241210194714-1829a127f884 ) require ( - contrib.go.opencensus.io/exporter/stackdriver v0.13.5 // indirect cosmossdk.io/api v0.3.1 // indirect cosmossdk.io/core v0.5.1 // indirect cosmossdk.io/depinject v1.0.0-alpha.4 // indirect @@ -96,6 +95,7 @@ require ( github.com/aws/constructs-go/constructs/v10 v10.4.2 // indirect github.com/aws/jsii-runtime-go v1.104.0 // indirect github.com/aws/smithy-go v1.22.0 // indirect + github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df // indirect github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3 // indirect @@ -106,10 +106,11 @@ require ( github.com/blang/semver/v4 v4.0.0 // indirect github.com/blendle/zapdriver v1.3.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129 // indirect github.com/buger/jsonparser v1.1.1 // indirect github.com/bytecodealliance/wasmtime-go/v23 v23.0.0 // indirect - github.com/bytedance/sonic v1.11.6 // indirect - github.com/bytedance/sonic/loader v0.1.1 // indirect + github.com/bytedance/sonic v1.12.3 // indirect + github.com/bytedance/sonic/loader v0.2.0 // indirect github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b // indirect github.com/c9s/goprocinfo v0.0.0-20210130143923-c95fcf8c64a8 // indirect github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5 // indirect @@ -153,9 +154,8 @@ require ( github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect github.com/dennwc/varint v1.0.0 // indirect - github.com/dfuse-io/logging v0.0.0-20210109005628-b97a57253f70 // indirect github.com/dgraph-io/badger/v2 v2.2007.4 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect @@ -166,6 +166,7 @@ require ( github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dominikbraun/graph v0.23.0 // indirect + github.com/doyensec/safeurl v0.2.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.7.0 // indirect github.com/edsrzf/mmap-go v1.1.0 // indirect @@ -181,10 +182,11 @@ require ( github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect - github.com/gabriel-vasile/mimetype v1.4.3 // indirect - github.com/gagliardetto/binary v0.7.7 // indirect - github.com/gagliardetto/solana-go v1.8.4 // indirect + github.com/gabriel-vasile/mimetype v1.4.6 // indirect + github.com/gagliardetto/binary v0.8.0 // indirect + github.com/gagliardetto/solana-go v1.12.0 // indirect github.com/gagliardetto/treeout v0.1.4 // indirect + github.com/gagliardetto/utilz v0.1.1 // indirect github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/getsentry/sentry-go v0.27.0 // indirect github.com/gin-contrib/sessions v0.0.5 // indirect @@ -211,7 +213,7 @@ require ( github.com/go-openapi/validate v0.23.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.22.0 // indirect + github.com/go-playground/validator/v10 v10.22.1 // indirect github.com/go-redis/redis/v8 v8.11.5 // indirect github.com/go-viper/mapstructure/v2 v2.1.0 // indirect github.com/go-webauthn/webauthn v0.9.4 // indirect @@ -263,6 +265,7 @@ require ( github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/gtank/merlin v0.1.1 // indirect github.com/gtank/ristretto255 v0.1.2 // indirect + github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026 // indirect github.com/hashicorp/consul/api v1.29.2 // indirect github.com/hashicorp/consul/sdk v0.16.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect @@ -329,7 +332,7 @@ require ( github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.14 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect github.com/miekg/dns v1.1.61 // indirect github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect @@ -371,29 +374,30 @@ require ( github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect - github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect + github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/prometheus/alertmanager v0.27.0 // indirect github.com/prometheus/client_golang v1.20.5 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.60.0 // indirect + github.com/prometheus/common v0.60.1 // indirect github.com/prometheus/common/sigv4 v0.1.0 // indirect github.com/prometheus/exporter-toolkit v0.11.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/prometheus/prometheus v0.54.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect - github.com/rivo/uniseg v0.4.4 // indirect + github.com/rivo/uniseg v0.4.7 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect github.com/rogpeppe/go-internal v1.13.1 // indirect github.com/rs/cors v1.10.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/ryanuber/go-glob v1.0.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sanity-io/litter v1.5.5 // indirect github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect - github.com/sasha-s/go-deadlock v0.3.1 // indirect + github.com/sasha-s/go-deadlock v0.3.5 // indirect github.com/scylladb/go-reflectx v1.0.1 // indirect github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect github.com/segmentio/ksuid v1.0.4 // indirect @@ -405,19 +409,20 @@ require ( github.com/shoenig/test v0.6.6 // indirect github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/smartcontractkit/chain-selectors v1.0.34 // indirect + github.com/smartcontractkit/chain-selectors v1.0.36 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241213122413-5e8f65dd6b1b // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20250120130359-cc025272bbff // indirect github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e // indirect - github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3 // indirect + github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250115135646-ac859d85e7e3 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.1 // indirect + github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250115203616-a2ea5e50b260 // indirect github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241210172617-6fd1891d0fbc // indirect - github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.1-0.20250117143722-fb6416c087a5 // indirect + github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20250117171710-b6481e9fcb34 // indirect github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 // indirect github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect - github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 // indirect + github.com/smartcontractkit/libocr v0.0.0-20241223215956-e5b78d8e3919 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de // indirect github.com/smartcontractkit/wsrpc v0.8.3 // indirect github.com/soheilhy/cmux v0.1.5 // indirect @@ -429,13 +434,12 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.19.0 // indirect github.com/status-im/keycard-go v0.2.0 // indirect - github.com/streamingfast/logging v0.0.0-20220405224725-2755dab2ce75 // indirect + github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/supranational/blst v0.3.13 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tendermint/go-amino v0.16.0 // indirect - github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 // indirect github.com/test-go/testify v1.1.4 // indirect github.com/testcontainers/testcontainers-go v0.34.0 // indirect github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a // indirect @@ -469,7 +473,6 @@ require ( go.etcd.io/etcd/client/pkg/v3 v3.5.14 // indirect go.etcd.io/etcd/client/v3 v3.5.14 // indirect go.mongodb.org/mongo-driver v1.15.0 // indirect - go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/collector/pdata v1.12.0 // indirect go.opentelemetry.io/collector/semconv v0.105.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 // indirect @@ -500,15 +503,15 @@ require ( go4.org/netipx v0.0.0-20230125063823-8449b0a6169f // indirect golang.org/x/arch v0.11.0 // indirect golang.org/x/crypto v0.31.0 // indirect - golang.org/x/mod v0.21.0 // indirect - golang.org/x/net v0.30.0 // indirect + golang.org/x/mod v0.22.0 // indirect + golang.org/x/net v0.32.0 // indirect golang.org/x/oauth2 v0.23.0 // indirect golang.org/x/sync v0.10.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/term v0.27.0 // indirect golang.org/x/text v0.21.0 // indirect golang.org/x/time v0.7.0 // indirect - golang.org/x/tools v0.26.0 // indirect + golang.org/x/tools v0.28.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect gonum.org/v1/gonum v0.15.1 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 79817cf4311..2fbd92cdb2f 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -3,7 +3,6 @@ cel.dev/expr v0.17.0/go.mod h1:HCwbrn+qQoHPXgfz6cl2J0hDybnX2N1sQQkl9EggXx8= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= @@ -54,10 +53,6 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.45.0 h1:5av0QcIVj77t+44mV4gffFC/LscFRUhto6UBMB5SimM= cloud.google.com/go/storage v1.45.0/go.mod h1:wpPblkIuMP5jCB/E48Pz9zIo2S/zD8g+ITmxKkPCITE= -contrib.go.opencensus.io/exporter/stackdriver v0.12.6/go.mod h1:8x999/OcIPy5ivx/wDiV7Gx4D+VUPODf0mWRGRc5kSk= -contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= -contrib.go.opencensus.io/exporter/stackdriver v0.13.5 h1:TNaexHK16gPUoc7uzELKOU7JULqccn1NDuqUxmxSqfo= -contrib.go.opencensus.io/exporter/stackdriver v0.13.5/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= cosmossdk.io/api v0.3.1 h1:NNiOclKRR0AOlO4KIqeaG6PS6kswOMhHD0ir0SscNXE= cosmossdk.io/api v0.3.1/go.mod h1:DfHfMkiNA2Uhy8fj0JJlOCYOBp4eWUUJ1te5zBGNyIw= cosmossdk.io/core v0.5.1 h1:vQVtFrIYOQJDV3f7rw4pjjVqc1id4+mE0L9hHP66pyI= @@ -75,7 +70,6 @@ cosmossdk.io/tools/rosetta v0.2.1/go.mod h1:Pqdc1FdvkNV3LcNIkYWt2RQY6IP1ge6YWZk8 dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -118,8 +112,6 @@ github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/Depado/ginprom v1.8.0 h1:zaaibRLNI1dMiiuj1MKzatm8qrcHzikMlCc1anqOdyo= github.com/Depado/ginprom v1.8.0/go.mod h1:XBaKzeNBqPF4vxJpNLincSQZeMDnZp1tIbU0FU0UKgg= -github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0= -github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 h1:3c8yed4lgqTt+oTQ+JNMDo+F4xprBf+O/il4ZC0nRLw= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0/go.mod h1:obipzmGjfSjam60XLwGfqUkJsfiheAl+TUjG+4yzyPM= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.3 h1:xir5X8TS8UBVPWg2jHL+cSTf0jZgqYQSA54TscSt1/0= @@ -163,7 +155,6 @@ github.com/Workiva/go-datastructures v1.1.0 h1:hu20UpgZneBhQ3ZvwiOGlqJSKIosin2Rd github.com/Workiva/go-datastructures v1.1.0/go.mod h1:1yZL+zfsztete+ePzZz/Zb1/t5BnDuE2Ya2MMGhzP6A= github.com/XSAM/otelsql v0.27.0 h1:i9xtxtdcqXV768a5C6SoT/RkG+ue3JTOgkYInzlTOqs= github.com/XSAM/otelsql v0.27.0/go.mod h1:0mFB3TvLa7NCuhm/2nU7/b2wEtsczkj8Rey8ygO7V+A= -github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -181,7 +172,6 @@ github.com/alicebob/miniredis/v2 v2.30.4/go.mod h1:b25qWj4fCEsBeAAR2mlb0ufImGC6u github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129/go.mod h1:rFgpPQZYZ8vdbc+48xibu8ALc3yeyd64IhHS+PU6Yyg= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA= @@ -208,8 +198,6 @@ github.com/avast/retry-go/v4 v4.6.0 h1:K9xNA+KeB8HHc2aWFuLb25Offp+0iVRXEvFx8IinR github.com/avast/retry-go/v4 v4.6.0/go.mod h1:gvWlPhBVsvBbLkVGDg/KwvBv0bEkCOLRRSHKIr2PyOE= github.com/awalterschulze/gographviz v2.0.3+incompatible h1:9sVEXJBJLwGX7EQVhLm2elIKCm7P2YHFC8v6096G09E= github.com/awalterschulze/gographviz v2.0.3+incompatible/go.mod h1:GEV5wmg4YquNw7v1kkyoX9etIk8yVmXj+AkDHuuETHs= -github.com/aws/aws-sdk-go v1.22.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.54.19 h1:tyWV+07jagrNiCcGRzRhdtVjQs7Vy41NwsuOcl0IbVI= github.com/aws/aws-sdk-go v1.54.19/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= @@ -245,6 +233,8 @@ github.com/aws/jsii-runtime-go v1.104.0 h1:651Sh6J2FtatfnVzlOQ3/Ye1WWPAseZ6E/tSQ github.com/aws/jsii-runtime-go v1.104.0/go.mod h1:7ZmQXxV0AAhhvv/GaHX4n6zbgA1tSRVdnQYAJbIhXHk= github.com/aws/smithy-go v1.22.0 h1:uunKnWlcoL3zO7q+gG2Pk53joueEOsnNB28QdMsmiMM= github.com/aws/smithy-go v1.22.0/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= +github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 h1:WWB576BN5zNSZc/M9d/10pqEx5VHNhaQ/yOVAkmj5Yo= +github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df h1:GSoSVRLoBaFpOOds6QyY1L8AX7uoY+Ln3BHc22W40X0= @@ -265,7 +255,6 @@ github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 h1:41iFGWnSlI2 github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= @@ -280,16 +269,19 @@ github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6 github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= +github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129 h1:gfAMKE626QEuKG3si0pdTRcr/YEbBoxY+3GOH3gWvl4= +github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129/go.mod h1:u9UyCz2eTrSGy6fbupqJ54eY5c4IC8gREQ1053dK12U= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/bxcodec/faker v2.0.1+incompatible h1:P0KUpUw5w6WJXwrPfv35oc91i4d8nf40Nwln+M/+faA= github.com/bxcodec/faker v2.0.1+incompatible/go.mod h1:BNzfpVdTwnFJ6GtfYTcQu6l6rHShT+veBxNCnjCx5XM= github.com/bytecodealliance/wasmtime-go/v23 v23.0.0 h1:NJvU4S8KEk1GnF6+FvlnzMD/8wXTj/mYJSG6Q4yu3Pw= github.com/bytecodealliance/wasmtime-go/v23 v23.0.0/go.mod h1:5YIL+Ouiww2zpO7u+iZ1U1G5NvmwQYaXdmCZQGjQM0U= -github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= -github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= -github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= +github.com/bytedance/sonic v1.12.3 h1:W2MGa7RCU1QTeYRTPE3+88mVC0yXmsRQRChiyVocVjU= +github.com/bytedance/sonic v1.12.3/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/bytedance/sonic/loader v0.2.0 h1:zNprn+lsIP06C/IqCHs3gPQIvnvpKbbxyXQP1iU4kWM= +github.com/bytedance/sonic/loader v0.2.0/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b h1:6+ZFm0flnudZzdSE0JxlhR2hKnGPcNB35BjQf4RYQDY= github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M= github.com/c9s/goprocinfo v0.0.0-20210130143923-c95fcf8c64a8 h1:SjZ2GvvOononHOpK84APFuMvxqsk3tEIaKH/z4Rpu3g= @@ -370,9 +362,7 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -383,7 +373,6 @@ github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7 github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= @@ -424,7 +413,6 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E= github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= github.com/danielkov/gin-helmet v0.0.0-20171108135313-1387e224435e h1:5jVSh2l/ho6ajWhSPNN84eHEdq3dp0T7+f6r3Tc6hsk= @@ -438,27 +426,22 @@ github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80N github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/dennwc/varint v1.0.0 h1:kGNFFSSw8ToIy3obO/kKr8U9GZYUAxQEVuix4zfDWzE= github.com/dennwc/varint v1.0.0/go.mod h1:hnItb35rvZvJrbTALZtY/iQfDs48JKRG1RPpgziApxA= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= -github.com/dfuse-io/logging v0.0.0-20201110202154-26697de88c79/go.mod h1:V+ED4kT/t/lKtH99JQmKIb0v9WL3VaYkJ36CfHlVECI= -github.com/dfuse-io/logging v0.0.0-20210109005628-b97a57253f70 h1:CuJS05R9jmNlUK8GOxrEELPbfXm0EuGh/30LjkjN5vo= -github.com/dfuse-io/logging v0.0.0-20210109005628-b97a57253f70/go.mod h1:EoK/8RFbMEteaCaz89uessDTnCWjbbcr+DXcBh4el5o= github.com/dgraph-io/badger/v2 v2.2007.4 h1:TRWBQg8UrlUhaFdco01nO2uXwzKS7zd+HVdwV/GHc4o= github.com/dgraph-io/badger/v2 v2.2007.4/go.mod h1:vSw/ax2qojzbN6eXHIx6KPKtCSHJN/Uz0X0VPruTIhk= github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/digitalocean/godo v1.118.0 h1:lkzGFQmACrVCp7UqH1sAi4JK/PWwlc5aaxubgorKmC4= github.com/digitalocean/godo v1.118.0/go.mod h1:Vk0vpCot2HOAJwc5WE8wljZGtJ3ZtWIc8MQ8rF38sdo= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= @@ -473,6 +456,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dominikbraun/graph v0.23.0 h1:TdZB4pPqCLFxYhdyMFb1TBdFxp8XLcJfTTBQucVPgCo= github.com/dominikbraun/graph v0.23.0/go.mod h1:yOjYyogZLY1LSG9E33JWZJiq5k83Qy2C6POAuiViluc= +github.com/doyensec/safeurl v0.2.1 h1:DY15JorEfQsnpBWhBkVQIkaif2jfxCC14PIuGDsjDVs= +github.com/doyensec/safeurl v0.2.1/go.mod h1:wzSXqC/6Z410qHz23jtBWT+wQ8yTxcY0p8bZH/4EZIg= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= @@ -529,16 +514,19 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= -github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= -github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= -github.com/gagliardetto/binary v0.7.7 h1:QZpT38+sgoPg+TIQjH94sLbl/vX+nlIRA37pEyOsjfY= -github.com/gagliardetto/binary v0.7.7/go.mod h1:mUuay5LL8wFVnIlecHakSZMvcdqfs+CsotR5n77kyjM= +github.com/gabriel-vasile/mimetype v1.4.6 h1:3+PzJTKLkvgjeTbts6msPJt4DixhT4YtFNf1gtGe3zc= +github.com/gabriel-vasile/mimetype v1.4.6/go.mod h1:JX1qVKqZd40hUPpAfiNTe0Sne7hdfKSbOqqmkq8GCXc= +github.com/gagliardetto/binary v0.8.0 h1:U9ahc45v9HW0d15LoN++vIXSJyqR/pWw8DDlhd7zvxg= +github.com/gagliardetto/binary v0.8.0/go.mod h1:2tfj51g5o9dnvsc+fL3Jxr22MuWzYXwx9wEoN0XQ7/c= github.com/gagliardetto/gofuzz v1.2.2 h1:XL/8qDMzcgvR4+CyRQW9UGdwPRPMHVJfqQ/uMvSUuQw= github.com/gagliardetto/gofuzz v1.2.2/go.mod h1:bkH/3hYLZrMLbfYWA0pWzXmi5TTRZnu4pMGZBkqMKvY= -github.com/gagliardetto/solana-go v1.8.4 h1:vmD/JmTlonyXGy39bAo0inMhmbdAwV7rXZtLDMZeodE= -github.com/gagliardetto/solana-go v1.8.4/go.mod h1:i+7aAyNDTHG0jK8GZIBSI4OVvDqkt2Qx+LklYclRNG8= +github.com/gagliardetto/hashsearch v0.0.0-20191005111333-09dd671e19f9/go.mod h1:513DXpQPzeRo7d4dsCP3xO3XI8hgvruMl9njxyQeraQ= +github.com/gagliardetto/solana-go v1.12.0 h1:rzsbilDPj6p+/DOPXBMLhwMZeBgeRuXjm5zQFCoXgsg= +github.com/gagliardetto/solana-go v1.12.0/go.mod h1:l/qqqIN6qJJPtxW/G1PF4JtcE3Zg2vD2EliZrr9Gn5k= github.com/gagliardetto/treeout v0.1.4 h1:ozeYerrLCmCubo1TcIjFiOWTTGteOOHND1twdFpgwaw= github.com/gagliardetto/treeout v0.1.4/go.mod h1:loUefvXTrlRG5rYmJmExNryyBRh8f89VZhmMOyCyqok= +github.com/gagliardetto/utilz v0.1.1 h1:/etW4hl607emKg6R6Lj9jRJ9d6ue2AQOyjhuAwjzs1U= +github.com/gagliardetto/utilz v0.1.1/go.mod h1:b+rGFkRHz3HWJD0RYMzat47JyvbTtpE0iEcYTRJTLLA= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813 h1:Uc+IZ7gYqAf/rSGFplbWBSHaGolEQlNLgMgSE3ccnIQ= @@ -615,8 +603,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao= -github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA= +github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/go-resty/resty/v2 v2.15.3 h1:bqff+hcqAflpiF591hhJzNdkRsFhlB96CYfBwSFvql8= @@ -662,7 +650,6 @@ github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVI github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -698,7 +685,6 @@ github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= @@ -783,7 +769,6 @@ github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/rpc v1.2.0/go.mod h1:V4h9r+4sF5HnzqbwIez0fKSpANP0zlYd3qR7p36jkTQ= github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY= @@ -817,15 +802,12 @@ github.com/graph-gophers/graphql-go v1.5.0 h1:fDqblo50TEpD0LY7RXk/LFVYEVqo3+tXMN github.com/graph-gophers/graphql-go v1.5.0/go.mod h1:YtmJZDLbF1YYNrlNAuiO5zAStUWc3XZT07iGsVqe1Os= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= @@ -838,6 +820,8 @@ github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is= github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc= github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o= +github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026 h1:BpJ2o0OR5FV7vrkDYfXYVJQeMNWa8RhklZOpW2ITAIQ= +github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026/go.mod h1:5Scbynm8dF1XAPwIwkGPqzkM/shndPm79Jd1003hTjE= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/api v1.29.2 h1:aYyRn8EdE2mSfG14S1+L9Qkjtz8RzmaWh6AcNGRNwPw= github.com/hashicorp/consul/api v1.29.2/go.mod h1:0YObcaLNDSbtlgzIRtmRXI1ZkeuK0trCBxwZQ4MYnIk= @@ -896,7 +880,6 @@ github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09 github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru v0.6.0 h1:uL2shRDx7RTrOrTCUZEGP/wJUFiUI8QT6E7z5o8jga4= github.com/hashicorp/golang-lru v0.6.0/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= @@ -999,10 +982,8 @@ github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0f github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= @@ -1013,7 +994,6 @@ github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4= github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -1038,7 +1018,6 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= @@ -1088,7 +1067,6 @@ github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/z github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= @@ -1120,8 +1098,8 @@ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= -github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= @@ -1130,6 +1108,7 @@ github.com/mfridman/interpolate v0.0.2 h1:pnuTK7MQIxxFz1Gr+rjSIx9u7qVjf5VOoM/u6B github.com/mfridman/interpolate v0.0.2/go.mod h1:p+7uk6oE07mpE/Ik1b8EckO0O4ZXiGAfshKBWLUM9Xg= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs= github.com/miekg/dns v1.1.61/go.mod h1:mnAarhS3nWaW+NVP2wTkYVIZyHNJ098SJZUki3eykwQ= @@ -1189,7 +1168,6 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= -github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= @@ -1210,7 +1188,6 @@ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+ github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1 h1:dOYG7LS/WK00RWZc8XGgcUTlTxpp3mKhdR2Q9z9HbXM= github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1/go.mod h1:mpRZBD8SJ55OIICQ3iWH0Yz3cjzA61JdqMLoWXeB2+8= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= @@ -1272,9 +1249,8 @@ github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNH github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= -github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 h1:hDSdbBuw3Lefr6R18ax0tZ2BJeNB3NehB3trOwYBsdU= -github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 h1:Dx7Ovyv/SFnMFw3fD4oEoeorXc6saIiQ23LrGLth0Gw= +github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= @@ -1302,7 +1278,6 @@ github.com/pressly/goose/v3 v3.21.1/go.mod h1:sqthmzV8PitchEkjecFJII//l43dLOCzfW github.com/prometheus/alertmanager v0.27.0 h1:V6nTa2J5V4s8TG4C4HtrBP/WNSebCCTYGGv4qecA/+I= github.com/prometheus/alertmanager v0.27.0/go.mod h1:8Ia/R3urPmbzJ8OsdvmZvIprDwvwmYCmUbwBL+jlPOE= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= @@ -1315,21 +1290,18 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1: github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= -github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= +github.com/prometheus/common v0.60.1 h1:FUas6GcOw66yB/73KC+BOZoFJmbo/1pojoILArPAaSc= +github.com/prometheus/common v0.60.1/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/common/sigv4 v0.1.0 h1:qoVebwtwwEhS85Czm2dSROY5fTo2PAPEVdDeppTwGX4= github.com/prometheus/common/sigv4 v0.1.0/go.mod h1:2Jkxxk9yYvCkE5G1sQT7GuEXm57JrvHu9k5YwTjsNtI= github.com/prometheus/exporter-toolkit v0.11.0 h1:yNTsuZ0aNCNFQ3aFTD2uhPOvr4iD7fdBvKPAEGkNf+g= github.com/prometheus/exporter-toolkit v0.11.0/go.mod h1:BVnENhnNecpwoTLiABx7mrPB/OLRIgN74qlQbV+FK1Q= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= @@ -1338,7 +1310,6 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/prometheus v0.54.1 h1:vKuwQNjnYN2/mDoWfHXDhAsz/68q/dQDb+YbcEqU7MQ= github.com/prometheus/prometheus v0.54.1/go.mod h1:xlLByHhk2g3ycakQGrMaU8K7OySZx98BzeCR99991NY= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= @@ -1346,11 +1317,10 @@ github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqn github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4= github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC5sZ4OhQ3+NtdbZ6oBDKQwq5Ou+FI= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= @@ -1369,6 +1339,8 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= +github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= @@ -1377,8 +1349,8 @@ github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQ github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= -github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= -github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= +github.com/sasha-s/go-deadlock v0.3.5 h1:tNCOEEDG6tBqrNDOX35j/7hL5FcFViG6awUGROb2NsU= +github.com/sasha-s/go-deadlock v0.3.5/go.mod h1:bugP6EGbdGYObIlx7pUZtWqlvo8k9H6vCBBsiChJQ5U= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/scaleway/scaleway-sdk-go v1.0.0-beta.29 h1:BkTk4gynLjguayxrYxZoMZjBnAOh7ntQvUkOFmkMqPU= github.com/scaleway/scaleway-sdk-go v1.0.0-beta.29/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg= @@ -1421,30 +1393,28 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/slack-go/slack v0.15.0 h1:LE2lj2y9vqqiOf+qIIy0GvEoxgF1N5yLGZffmEZykt0= github.com/slack-go/slack v0.15.0/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= -github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix h1:DPJD++yKLSx0EfT+U14P8vLVxjXFmoIETiCO9lVwQo8= -github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= -github.com/smartcontractkit/chain-selectors v1.0.34 h1:MJ17OGu8+jjl426pcKrJkCf3fePb3eCreuAnUA3RBj4= -github.com/smartcontractkit/chain-selectors v1.0.34/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= +github.com/smartcontractkit/chain-selectors v1.0.36 h1:KSpO8I+JOiuyN4FuXsV471sPorGF//PAqwq2Cm4gRK0= +github.com/smartcontractkit/chain-selectors v1.0.36/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241213122413-5e8f65dd6b1b h1:iSQJ6ng4FhEswf8SXunGkaJlVP3E3JlgLB8Oo2f3Ud4= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241213122413-5e8f65dd6b1b/go.mod h1:F8xQAIW0ymb2BZhqn89sWZLXreJhM5KDVF6Qb4y44N0= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241214155818-b403079b2805 h1:Pz8jB/6qe10xT10h2S3LFYJrnebNpG5rJ/w16HZGwPQ= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241214155818-b403079b2805/go.mod h1:yti7e1+G9hhkYhj+L5sVUULn9Bn3bBL5/AxaNqdJ5YQ= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250120130359-cc025272bbff h1:ZEOlcleVdT0/y9V5yjgFJF0j7MpvdrFmKis/xmFNIgE= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250120130359-cc025272bbff/go.mod h1:JJZMCB75aVSAiPNW032F9WUKTlLztTd8bbQB5MEaZa4= +github.com/smartcontractkit/chainlink-common v0.4.2-0.20250116214855-f49c5c27db51 h1:YdjQiEu5uHWM1ApwdV+nLyJmu1+tt3IeiwPKNGoXwBI= +github.com/smartcontractkit/chainlink-common v0.4.2-0.20250116214855-f49c5c27db51/go.mod h1:yti7e1+G9hhkYhj+L5sVUULn9Bn3bBL5/AxaNqdJ5YQ= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3 h1:aeiBdBHGY8QNftps+VqrIk6OnfeeOD5z4jrAabW4ZSc= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3/go.mod h1:AS6zY2BkcRwfiGzNabGbHhfrLSrXrcI/GmjnT4jQ5/s= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250115135646-ac859d85e7e3 h1:GcPYNVFYjB065CNq0h8nK/VeU08nUkHgBX0cJIEpuHY= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250115135646-ac859d85e7e3/go.mod h1:pDZagSGjs9U+l4YIFhveDznMHqxuuz+5vRxvVgpbdr8= github.com/smartcontractkit/chainlink-feeds v0.1.1 h1:JzvUOM/OgGQA1sOqTXXl52R6AnNt+Wg64sVG+XSA49c= github.com/smartcontractkit/chainlink-feeds v0.1.1/go.mod h1:55EZ94HlKCfAsUiKUTNI7QlE/3d3IwTlsU3YNa/nBb4= -github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 h1:0ewLMbAz3rZrovdRUCgd028yOXX8KigB4FndAUdI2kM= -github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0/go.mod h1:/dVVLXrsp+V0AbcYGJo3XMzKg3CkELsweA/TTopCsKE= +github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250115203616-a2ea5e50b260 h1:See2isL6KdrTJDlVKWv8qiyYqWhYUcubU2e5yKXV1oY= +github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250115203616-a2ea5e50b260/go.mod h1:4JqpgFy01LaqG1yM2iFTzwX3ZgcAvW9WdstBZQgPHzU= github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0 h1:ZBat8EBvE2LpSQR9U1gEbRV6PfAkiFdINmQ8nVnXIAQ= github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241210172617-6fd1891d0fbc h1:dssRwJhmzJkUN/OajaDj2GsxBn+Tupk3bI1BkPEoJg0= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241210172617-6fd1891d0fbc/go.mod h1:p8aUDfJeley6oer7y+Ucd3edOtRlMTnWg3mN6rhaLWo= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 h1:tNS7U9lrxkFvEuyxQv11HHOiV9LPDGC9wYEy+yM/Jv4= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8/go.mod h1:EBrEgcdIbwepqguClkv8Ohy7CbyWSJaE4EC9aBJlQK0= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20250117143722-fb6416c087a5 h1:kDW6Ab8vGRK2y+DPEvvhU2It8UCS9FK5ZQqIVjDfpK4= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20250117143722-fb6416c087a5/go.mod h1:uHVnYLMgJ1rTcNoVxhBpy38t69gXq0j+LN3TkcIVE3U= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20250117171710-b6481e9fcb34 h1:tQCjnIjY88AClWXApaTS+/ihQYM1GVCrbD9W00eh11E= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20250117171710-b6481e9fcb34/go.mod h1:lgG9JT2P19KnYuBheKIis5ZeCO+AaSta+RfzvwDQS2Y= github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 h1:GDGrC5OGiV0RyM1znYWehSQXyZQWTOzrEeJRYmysPCE= github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2/go.mod h1:DsT43c1oTBmp3iQkMcoZOoKThwZvt8X3Pz6UmznJ4GY= github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.19 h1:9PMwKNqFKc5FXf4VchyD3CGzZelnSgi13fgVdT2X7T4= @@ -1457,8 +1427,8 @@ github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2 h1:7bCdbTUW github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2/go.mod h1:MltlNu3jcXm/DyLN98I5TFNtu/o1NNAcaPAFKMXWk70= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA= -github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 h1:NzZGjaqez21I3DU7objl3xExTH4fxYvzTqar8DC6360= -github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= +github.com/smartcontractkit/libocr v0.0.0-20241223215956-e5b78d8e3919 h1:IpGoPTXpvllN38kT2z2j13sifJMz4nbHglidvop7mfg= +github.com/smartcontractkit/libocr v0.0.0-20241223215956-e5b78d8e3919/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de h1:n0w0rKF+SVM+S3WNlup6uabXj2zFlFNfrlsKCMMb/co= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:Sl2MF/Fp3fgJIVzhdGhmZZX2BlnM0oUUyBP4s4xYb6o= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de h1:66VQxXx3lvTaAZrMBkIcdH9VEjujUEvmBQdnyOJnkOc= @@ -1469,7 +1439,6 @@ github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/sony/gobreaker v0.5.0 h1:dRCvqm0P490vZPmy7ppEk2qCnCieBooFJ+YoXGYB+yg= @@ -1488,7 +1457,6 @@ github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= @@ -1498,15 +1466,13 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= -github.com/streamingfast/logging v0.0.0-20220405224725-2755dab2ce75 h1:ZqpS7rAhhKD7S7DnrpEdrnW1/gZcv82ytpMviovkli4= -github.com/streamingfast/logging v0.0.0-20220405224725-2755dab2ce75/go.mod h1:VlduQ80JcGJSargkRU4Sg9Xo63wZD/l8A5NC/Uo1/uU= +github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 h1:RN5mrigyirb8anBEtdjtHFIufXdacyTi6i4KBfeNXeo= +github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091/go.mod h1:VlduQ80JcGJSargkRU4Sg9Xo63wZD/l8A5NC/Uo1/uU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= @@ -1526,8 +1492,9 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= @@ -1537,9 +1504,6 @@ github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDd github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= -github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0= -github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 h1:3SNcvBmEPE1YlB1JpVZouslJpI3GBNoiqW7+wb0Rz7w= -github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0= github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE= github.com/test-go/testify v1.1.4/go.mod h1:rH7cfJo/47vWGdi4GPj16x3/t1xGOj2YxzmNQzk2ghU= github.com/testcontainers/testcontainers-go v0.34.0 h1:5fbgF0vIN5u+nD3IWabQwRybuB4GY8G2HHgCkbMzMHo= @@ -1548,12 +1512,10 @@ github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a h1:YuO+afVc3eqrj github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a/go.mod h1:/sfW47zCZp9FrtGcWyo1VjbgDaodxX9ovZvgLb/MxaA= github.com/tidwall/btree v1.6.0 h1:LDZfKfQIBHGHWSwckhXI0RPSXzlo+KYdjK7FWSqOzzg= github.com/tidwall/btree v1.6.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= -github.com/tidwall/gjson v1.9.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM= github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= -github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= @@ -1561,7 +1523,6 @@ github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFA github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= @@ -1588,10 +1549,8 @@ github.com/urfave/cli v1.22.14 h1:ebbhrRiGK2i4naQJr+1Xj92HXZCrK7MsyTS/ob3HnAk= github.com/urfave/cli v1.22.14/go.mod h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA= github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fastjson v1.4.1 h1:hrltpHpIpkaxll8QltMU8c3QZ5+qIiCL8yKqPFJI/yE= github.com/valyala/fastjson v1.4.1/go.mod h1:nV6MsjxL2IMJQUoHDIrjEI7oLyeqK6aBD7EFWPsvP8o= -github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/vektah/gqlparser/v2 v2.5.11 h1:JJxLtXIoN7+3x6MBdtIP59TP1RANnY7pXOaDnADQSf8= github.com/vektah/gqlparser/v2 v2.5.11/go.mod h1:1rCcfwB2ekJofmluGWXMSEnPMZgbxzwj6FaZ/4OT8Cc= github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs= @@ -1602,10 +1561,6 @@ github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/ github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= -github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= -github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= @@ -1613,7 +1568,6 @@ github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGC github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= -github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -1640,7 +1594,6 @@ go.dedis.ch/kyber/v3 v3.1.0/go.mod h1:kXy7p3STAurkADD+/aZcsznZGKVHEqbtmdIzvPfrs1 go.dedis.ch/protobuf v1.0.5/go.mod h1:eIV4wicvi6JK0q/QnfIEGeSFNG0ZeB24kzut5+HaRLo= go.dedis.ch/protobuf v1.0.7/go.mod h1:pv5ysfkDX/EawiPqcW3ikOxsL5t+BqnV6xHSmE79KI4= go.dedis.ch/protobuf v1.0.11/go.mod h1:97QR256dnkimeNdfmURz0wAMNVbd1VmLXhG1CrTYrJ4= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= @@ -1652,12 +1605,10 @@ go.etcd.io/etcd/client/pkg/v3 v3.5.14/go.mod h1:8uMgAokyG1czCtIdsq+AGyYQMvpIKnSv go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= go.etcd.io/etcd/client/v3 v3.5.14 h1:CWfRs4FDaDoSz81giL7zPpZH2Z35tbOrAJkkjMqOupg= go.etcd.io/etcd/client/v3 v3.5.14/go.mod h1:k3XfdV/VIHy/97rqWjoUzrj9tk7GgJGH9J8L4dNXmAk= -go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= go.mongodb.org/mongo-driver v1.15.0 h1:rJCKC8eEliewXjZGf0ddURtl7tTVy1TK3bfl0gkUSLc= go.mongodb.org/mongo-driver v1.15.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -1731,22 +1682,18 @@ go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKY go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/ratelimit v0.2.0/go.mod h1:YYBV4e4naJvhpitQrWJu1vCpgB7CboMe0qhltKt6mUg= go.uber.org/ratelimit v0.3.1 h1:K4qVE+byfv/B3tC+4nYWP7v/6SimcO7HzHekoMNBma0= go.uber.org/ratelimit v0.3.1/go.mod h1:6euWsTB6U/Nb3X++xEUXA8ciPJvr19Q/0h1+oDcJhRk= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go4.org/netipx v0.0.0-20230125063823-8449b0a6169f h1:ketMxHg+vWm3yccyYiq+uK8D3fRmna2Fcj+awpQp84s= go4.org/netipx v0.0.0-20230125063823-8449b0a6169f/go.mod h1:tgPU4N2u9RByaTN3NC2p9xOzyFpte4jYwsIIRF7XlSc= -golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.11.0 h1:KXV8WWKCXm6tRpLirl2szsO5j/oOODwZf4hATmGVNs4= golang.org/x/arch v0.11.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1770,7 +1717,6 @@ golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= @@ -1785,8 +1731,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY= -golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= +golang.org/x/exp v0.0.0-20241210194714-1829a127f884 h1:Y/Mj/94zIQQGHVSv1tTtQBDaQaJe62U9bkDZKKyhPCU= +golang.org/x/exp v0.0.0-20241210194714-1829a127f884/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1815,15 +1761,14 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= +golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -1874,8 +1819,8 @@ golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= -golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= +golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= +golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1911,7 +1856,6 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1927,7 +1871,6 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2003,7 +1946,6 @@ golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -2052,7 +1994,6 @@ golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -2098,8 +2039,8 @@ golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= -golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= -golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= +golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8= +golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -2117,7 +2058,6 @@ google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEt google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.10.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= @@ -2142,7 +2082,6 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= @@ -2153,7 +2092,6 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -2203,7 +2141,6 @@ google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmE google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -2256,16 +2193,13 @@ gopkg.in/guregu/null.v4 v4.0.0/go.mod h1:YoQhUrADuG3i9WqesrCmpNRwm1ypAgSHYqoOcTu gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -2316,7 +2250,6 @@ nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYm pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw= pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= diff --git a/integration-tests/smoke/ccip/ccip_add_chain_test.go b/integration-tests/smoke/ccip/ccip_add_chain_test.go new file mode 100644 index 00000000000..aced6e8bef5 --- /dev/null +++ b/integration-tests/smoke/ccip/ccip_add_chain_test.go @@ -0,0 +1,813 @@ +package ccip + +import ( + "math/big" + "slices" + "testing" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" + ccipcs "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" + + "github.com/stretchr/testify/require" + "golang.org/x/exp/maps" +) + +func Test_AddChain(t *testing.T) { + const ( + numChains = 4 + usersPerChain = 2 + ) + + // Set up an env with 4 chains but initially + // only deploy and configure 3 of them. + e, tEnv := testhelpers.NewMemoryEnvironment( + t, + testhelpers.WithNumOfChains(numChains), + testhelpers.WithNumOfNodes(4), + testhelpers.WithPrerequisiteDeploymentOnly(nil), + testhelpers.WithNumOfUsersPerChain(usersPerChain), + testhelpers.WithNoJobsAndContracts(), + testhelpers.WithOCRConfigOverride(func(params *ccipcs.CCIPOCRParams) { + // Only 1 boost (=OCR round) is enough to cover the fee + params.ExecuteOffChainConfig.RelativeBoostPerWaitHour = 1 + }), + ) + + allChains := maps.Keys(e.Env.Chains) + slices.Sort(allChains) + toDeploy := e.Env.AllChainSelectorsExcluding([]uint64{allChains[0]}) + require.Len(t, toDeploy, numChains-1) + remainingChain := allChains[0] + t.Log("initially deploying chains:", toDeploy, "and afterwards adding chain", remainingChain) + + ///////////////////////////////////// + // START Setup initial chains + ///////////////////////////////////// + e = setupChain( + t, + e, + tEnv, + toDeploy, + true, // deployJobs + true, // deployHomeChain + false, // mcmsEnabled + ) + + state, err := ccipcs.LoadOnchainState(e.Env) + require.NoError(t, err) + + // check RMNRemote is up and RMNProxy is correctly wired. + assertRMNRemoteAndProxyState(t, toDeploy, state) + + // Setup densely connected lanes between all chains. + for _, source := range toDeploy { + for _, dest := range toDeploy { + if source == dest { + continue + } + testhelpers.AddLaneWithDefaultPricesAndFeeQuoterConfig( + t, + &e, + state, + source, + dest, + false, // isTestRouter + ) + } + } + + // Transfer ownership of all contracts to the MCMS and renounce the timelock deployer. + transferToMCMSAndRenounceTimelockDeployer( + t, + e, + toDeploy, + state, + false, // onlyChainContracts + ) + + // At this stage we can send some requests and confirm the setup is working. + sendMsgs := func( + sources []uint64, + dests []uint64, + testRouter bool, + ) (gasPricePreUpdate map[testhelpers.SourceDestPair]*big.Int, startBlocks map[uint64]*uint64) { + startBlocks = make(map[uint64]*uint64) + gasPricePreUpdate = make(map[testhelpers.SourceDestPair]*big.Int) + var ( + expectedSeqNum = make(map[testhelpers.SourceDestPair]uint64) + expectedSeqNumExec = make(map[testhelpers.SourceDestPair][]uint64) + ) + for _, source := range sources { + for _, dest := range dests { + if source == dest { + continue + } + + gp, err := state.Chains[source].FeeQuoter.GetDestinationChainGasPrice(&bind.CallOpts{ + Context: tests.Context(t), + }, dest) + require.NoError(t, err) + gasPricePreUpdate[testhelpers.SourceDestPair{ + SourceChainSelector: source, + DestChainSelector: dest, + }] = gp.Value + + latesthdr, err := e.Env.Chains[dest].Client.HeaderByNumber(testcontext.Get(t), nil) + require.NoError(t, err) + block := latesthdr.Number.Uint64() + msgSentEvent := testhelpers.TestSendRequest(t, e.Env, state, source, dest, testRouter, router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(state.Chains[dest].Receiver.Address().Bytes(), 32), + Data: []byte("hello world"), + TokenAmounts: nil, + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: nil, + }) + + startBlocks[dest] = &block + expectedSeqNum[testhelpers.SourceDestPair{ + SourceChainSelector: source, + DestChainSelector: dest, + }] = msgSentEvent.SequenceNumber + expectedSeqNumExec[testhelpers.SourceDestPair{ + SourceChainSelector: source, + DestChainSelector: dest, + }] = append(expectedSeqNumExec[testhelpers.SourceDestPair{ + SourceChainSelector: source, + DestChainSelector: dest, + }], msgSentEvent.SequenceNumber) + } + } + + // Confirm execution of the message + testhelpers.ConfirmCommitForAllWithExpectedSeqNums(t, e.Env, state, expectedSeqNum, startBlocks) + testhelpers.ConfirmExecWithSeqNrsForAll(t, e.Env, state, expectedSeqNumExec, startBlocks) + return gasPricePreUpdate, startBlocks + } + + sendMsgs(toDeploy, toDeploy, false) + + ///////////////////////////////////// + // END Setup initial chains + ///////////////////////////////////// + + // TODO: Not working. Need to fix/figure out why. + // gasPricePreUpdate, startBlocks := sendMsgs(toDeploy) + // for sourceDestPair, preUpdateGp := range gasPricePreUpdate { + // // check that each chain's fee quoter has updated its gas price + // // for all dests. + // err := ConfirmGasPriceUpdated( + // t, + // e.Env.Chains[sourceDestPair.DestChainSelector], + // state.Chains[sourceDestPair.SourceChainSelector].FeeQuoter, + // *startBlocks[sourceDestPair.DestChainSelector], + // preUpdateGp, + // ) + // require.NoError(t, err) + // } + + ///////////////////////////////////// + // START Deploy to the remaining chain. + ///////////////////////////////////// + + // MCMS needs to be enabled because the home chain contracts have been + // transferred to MCMS. + e = setupChain( + t, + e, + tEnv, + []uint64{remainingChain}, + false, // deployJobs + false, // deployHomeChain + true, // mcmsEnabled + ) + + state, err = ccipcs.LoadOnchainState(e.Env) + require.NoError(t, err) + + assertRMNRemoteAndProxyState(t, []uint64{remainingChain}, state) + + // TODO: wait for gas price of new chain to be updated on all other chains. + + ///////////////////////////////////// + // END Deploy to the remaining chain. + ///////////////////////////////////// + + ///////////////////////////////////// + // START Wire up toDeploy -> remainingChain outbound. + ///////////////////////////////////// + e = setupOutboundWiring( + t, + e, + toDeploy, + []uint64{remainingChain}, + true, // testRouterEnabled + true, // mcmsEnabled + ) + + state, err = ccipcs.LoadOnchainState(e.Env) + require.NoError(t, err) + + assertChainWiringOutbound( + t, + state, + remainingChain, + toDeploy, + true, // testRouterEnabled + ) + + // At this point we can send messages from the test router to the new chain. + // These won't be processed yet because the offRamp is not aware of these new sources. + + ///////////////////////////////////// + // END Wire up toDeploy -> remainingChain outbound. + ///////////////////////////////////// + + ///////////////////////////////////// + // START Wire up toDeploy -> remainingChain inbound on remainingChain. + ///////////////////////////////////// + + // UpdateOffRampSourcesConfig called on the new chain to enable existing sources. Also with the test router. + // UpdateRouterRampsConfig to enable the existing sources on the new test router. + // This means we can send messages from toDeploy to remainingChain. + // NOTE: not using MCMS since haven't transferred to timelock yet. + e = setupInboundWiring(t, e, toDeploy, []uint64{remainingChain}, true, false) + + assertChainWiringInbound( + t, + state, + remainingChain, + toDeploy, + true, // testRouterEnabled + ) + + // Send messages from toDeploy to the newly added chain thru the test router. + sendMsgs(toDeploy, []uint64{remainingChain}, true) + + ///////////////////////////////////// + // END Wire up toDeploy -> remainingChain inbound on remainingChain. + ///////////////////////////////////// + + ///////////////////////////////////// + // START Wire up remainingChain -> toDeploy outbound. + ///////////////////////////////////// + + // Now we switch to testing outbound from the new chain. + // This amounts to enabling a new lane on the existing OCR instances + // (assuming by default we want to enable all chains). + e = setupOutboundWiring( + t, + e, + []uint64{remainingChain}, + toDeploy, + true, // testRouterEnabled + false, // mcmsEnabled + ) + + // sanity check that everything is correctly set up. + for _, chain := range toDeploy { + assertChainWiringOutbound(t, state, chain, []uint64{remainingChain}, true) + } + + ///////////////////////////////////// + // END Wire up remainingChain -> toDeploy outbound. + ///////////////////////////////////// + + ///////////////////////////////////// + // START Wire up remainingChain -> toDeploy inbound on toDeploy. + ///////////////////////////////////// + + e = setupInboundWiring(t, e, []uint64{remainingChain}, toDeploy, true, true) + + for _, chain := range toDeploy { + assertChainWiringInbound(t, state, chain, []uint64{remainingChain}, true) + } + + ///////////////////////////////////// + // END Wire up remainingChain -> toDeploy inbound on toDeploy. + ///////////////////////////////////// + + ///////////////////////////////////// + // START send messages from remainingChain to toDeploy. + ///////////////////////////////////// + + // Send messages from remainingChain to toDeploy thru the test router. + sendMsgs([]uint64{remainingChain}, toDeploy, true) + + ///////////////////////////////////// + // END send messages from remainingChain to toDeploy. + ///////////////////////////////////// + + // Transfer the new chain contracts to the timelock ownership. + transferToMCMSAndRenounceTimelockDeployer( + t, + e, + []uint64{remainingChain}, + state, + true, // onlyChainContracts + ) + + // Once verified with the test routers, the last step is to whitelist the new chain on the real routers everywhere with + // UpdateRouterRamps, UpdateOffRampSources and UpdateOnRampDests with TestRouter=False. + // This is basically the same as the wiring done above, just setting testRouterEnabled=false. + + ///////////////////////////////////// + // START Wire up toDeploy -> remainingChain outbound through real router. + ///////////////////////////////////// + e = setupOutboundWiring( + t, + e, + toDeploy, + []uint64{remainingChain}, + false, // testRouterEnabled + true, // mcmsEnabled + ) + + state, err = ccipcs.LoadOnchainState(e.Env) + require.NoError(t, err) + + assertChainWiringOutbound( + t, + state, + remainingChain, + toDeploy, + false, // testRouterEnabled + ) + ///////////////////////////////////// + // END Wire up toDeploy -> remainingChain outbound through real router. + ///////////////////////////////////// + + ///////////////////////////////////// + // START Wire up toDeploy -> remainingChain inbound on remainingChain through real router. + ///////////////////////////////////// + + e = setupInboundWiring( + t, + e, + toDeploy, + []uint64{remainingChain}, + false, // testRouterEnabled + true, // mcmsEnabled + ) + + assertChainWiringInbound( + t, + state, + remainingChain, + toDeploy, + false, // testRouterEnabled + ) + + ///////////////////////////////////// + // END Wire up toDeploy -> remainingChain inbound on remainingChain through real router. + ///////////////////////////////////// + + ///////////////////////////////////// + // START Wire up remainingChain -> toDeploy outbound through real router. + ///////////////////////////////////// + + e = setupOutboundWiring( + t, + e, + []uint64{remainingChain}, + toDeploy, + false, // testRouterEnabled + true, // mcmsEnabled + ) + + // sanity check that everything is correctly set up. + for _, chain := range toDeploy { + assertChainWiringOutbound( + t, + state, + chain, + []uint64{remainingChain}, + false, // testRouterEnabled + ) + } + + ///////////////////////////////////// + // END Wire up remainingChain -> toDeploy outbound through real router. + ///////////////////////////////////// + + ///////////////////////////////////// + // START Wire up remainingChain -> toDeploy inbound on toDeploy through real router. + ///////////////////////////////////// + + e = setupInboundWiring( + t, + e, + []uint64{remainingChain}, + toDeploy, + false, // testRouterEnabled + true, // mcmsEnabled + ) + + for _, chain := range toDeploy { + assertChainWiringInbound( + t, + state, + chain, + []uint64{remainingChain}, + false, // testRouterEnabled + ) + } + + ///////////////////////////////////// + // END Wire up remainingChain -> toDeploy inbound on toDeploy. + ///////////////////////////////////// + + // Send messages from toDeploy to the newly added chain thru the real router. + sendMsgs(toDeploy, []uint64{remainingChain}, false) +} + +// setupInboundWiring sets up the newChain to be able to receive ccip messages from the provided sources. +// This only touches the newChain and does not touch the sources. +func setupInboundWiring( + t *testing.T, + e testhelpers.DeployedEnv, + sources []uint64, + newChains []uint64, + testRouterEnabled, + mcmsEnabled bool, +) testhelpers.DeployedEnv { + var mcmsConfig *ccipcs.MCMSConfig + if mcmsEnabled { + mcmsConfig = &ccipcs.MCMSConfig{ + MinDelay: 0, + } + } + + var err error + e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, e.TimelockContracts(t), []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(ccipcs.UpdateOffRampSourcesChangeset), + Config: ccipcs.UpdateOffRampSourcesConfig{ + UpdatesByChain: offRampSourceUpdates(t, newChains, sources, testRouterEnabled), + MCMS: mcmsConfig, + }, + }, + { + Changeset: commonchangeset.WrapChangeSet(ccipcs.UpdateRouterRampsChangeset), + Config: ccipcs.UpdateRouterRampsConfig{ + TestRouter: testRouterEnabled, + UpdatesByChain: routerOffRampUpdates(t, newChains, sources), + MCMS: mcmsConfig, + }, + }, + }) + require.NoError(t, err) + + return e +} + +// setupOutboundWiring sets up the given sources to be able to request ccip messages to the newChain. +// This only touches the sources and does not touch newChain. +// Therefore any requests to newChain will not be processed until the inbound wiring is set up. +func setupOutboundWiring( + t *testing.T, + e testhelpers.DeployedEnv, + sources []uint64, + newChains []uint64, + testRouterEnabled, + mcmsEnabled bool, +) testhelpers.DeployedEnv { + var mcmsConfig *ccipcs.MCMSConfig + if mcmsEnabled { + mcmsConfig = &ccipcs.MCMSConfig{ + MinDelay: 0, + } + } + + var err error + e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, e.TimelockContracts(t), []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(ccipcs.UpdateOnRampsDestsChangeset), + Config: ccipcs.UpdateOnRampDestsConfig{ + UpdatesByChain: onRampDestUpdates(t, newChains, sources, testRouterEnabled), + MCMS: mcmsConfig, + }, + }, + { + Changeset: commonchangeset.WrapChangeSet(ccipcs.UpdateFeeQuoterPricesChangeset), + Config: ccipcs.UpdateFeeQuoterPricesConfig{ + PricesByChain: feeQuoterPricesByChain(t, newChains, sources), + MCMS: mcmsConfig, + }, + }, + { + Changeset: commonchangeset.WrapChangeSet(ccipcs.UpdateFeeQuoterDestsChangeset), + Config: ccipcs.UpdateFeeQuoterDestsConfig{ + UpdatesByChain: feeQuoterDestUpdates(t, newChains, sources), + MCMS: mcmsConfig, + }, + }, + { + Changeset: commonchangeset.WrapChangeSet(ccipcs.UpdateRouterRampsChangeset), + Config: ccipcs.UpdateRouterRampsConfig{ + TestRouter: testRouterEnabled, + UpdatesByChain: routerOnRampUpdates(t, newChains, sources), + MCMS: mcmsConfig, + }, + }, + }) + require.NoError(t, err) + + return e +} + +// setupChain will deploy the ccip chain contracts to the provided chains. +// Based on the flags provided, it will also deploy the jobs and home chain contracts. +// mcmsEnabled should be set to true if the home chain contracts have been transferred to MCMS. +func setupChain(t *testing.T, e testhelpers.DeployedEnv, tEnv testhelpers.TestEnvironment, chains []uint64, deployJobs, deployHomeChain, mcmsEnabled bool) testhelpers.DeployedEnv { + e = testhelpers.AddCCIPContractsToEnvironment( + t, + chains, + tEnv, + deployJobs, + deployHomeChain, + mcmsEnabled, + ) + + // Need to update what the RMNProxy is pointing to, otherwise plugin will not work. + var err error + e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, e.TimelockContracts(t), []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(ccipcs.SetRMNRemoteOnRMNProxyChangeset), + Config: ccipcs.SetRMNRemoteOnRMNProxyConfig{ + ChainSelectors: chains, + }, + }, + }) + require.NoError(t, err) + + return e +} + +// assertChainWiringInbound checks that the newChain has the existingChains enabled as sources. +// It only checks the inbound wiring on the newChain. +// It doesn't check that the existingChains have the newChain enabled as a dest. +func assertChainWiringInbound( + t *testing.T, + state ccipcs.CCIPOnChainState, + newChain uint64, + existingChains []uint64, + testRouterEnabled bool, +) { + for _, existingChain := range existingChains { + var rtr *router.Router + if testRouterEnabled { + rtr = state.Chains[newChain].TestRouter + } else { + rtr = state.Chains[newChain].Router + } + + // check that the offRamp has the existing chain enabled as a source. + // in addition, check that the onRamp set in the source chain config + // matches the address of the onRamp on the existing chain. + dcc, err := state.Chains[newChain].OffRamp.GetSourceChainConfig(&bind.CallOpts{ + Context: tests.Context(t), + }, existingChain) + require.NoError(t, err) + require.Equal(t, rtr.Address(), dcc.Router) + require.Equal(t, dcc.OnRamp, common.LeftPadBytes(state.Chains[existingChain].OnRamp.Address().Bytes(), 32)) + + // check that the router has the existing chain enabled as a source. + routerOffRamps, err := rtr.GetOffRamps(&bind.CallOpts{ + Context: tests.Context(t), + }) + require.NoError(t, err) + + var found bool + for _, offRamp := range routerOffRamps { + if offRamp.SourceChainSelector == existingChain { + require.Equal(t, state.Chains[newChain].OffRamp.Address(), offRamp.OffRamp) + found = true + break + } + } + require.True(t, found) + } +} + +// assertChainWiringOutbound checks that newChain can be requested from existingChains. +// This only checks the outbound wiring on existingChains. +// It doesn't check that the newChain can process the requests. +func assertChainWiringOutbound( + t *testing.T, + state ccipcs.CCIPOnChainState, + newChain uint64, + existingChains []uint64, + testRouterEnabled bool, +) { + for _, existingChain := range existingChains { + var rtr *router.Router + if testRouterEnabled { + rtr = state.Chains[existingChain].TestRouter + } else { + rtr = state.Chains[existingChain].Router + } + + // check that the onRamp has the new chain enabled as a dest. + dcc, err := state.Chains[existingChain].OnRamp.GetDestChainConfig(&bind.CallOpts{ + Context: tests.Context(t), + }, newChain) + require.NoError(t, err) + require.Equal(t, rtr.Address(), dcc.Router) + + // check that the feeQuoter has the new chain enabled as a dest. + fqdcc, err := state.Chains[existingChain].FeeQuoter.GetDestChainConfig(&bind.CallOpts{ + Context: tests.Context(t), + }, newChain) + require.NoError(t, err) + require.True(t, fqdcc.IsEnabled) + + // check that the router has the new chain enabled as a dest. + routerOnRamp, err := rtr.GetOnRamp(&bind.CallOpts{ + Context: tests.Context(t), + }, newChain) + require.NoError(t, err) + require.Equal(t, state.Chains[existingChain].OnRamp.Address(), routerOnRamp) + } +} + +// routerOffRampUpdates adds the provided sources to the router of the provided dest chain. +func routerOffRampUpdates(t *testing.T, dests []uint64, sources []uint64) (updates map[uint64]ccipcs.RouterUpdates) { + updates = make(map[uint64]ccipcs.RouterUpdates) + for _, source := range sources { + for _, dest := range dests { + require.NotEqual(t, source, dest) + if _, ok := updates[dest]; !ok { + updates[dest] = ccipcs.RouterUpdates{ + OffRampUpdates: map[uint64]bool{ + source: true, + }, + } + } else { + updates[dest].OffRampUpdates[source] = true + } + } + } + return +} + +// routerOnRampUpdates sets each dest selector in the given dest chains slice on the router +// to point to the local onramp on each source chain. +func routerOnRampUpdates(t *testing.T, dests []uint64, sources []uint64) (updates map[uint64]ccipcs.RouterUpdates) { + updates = make(map[uint64]ccipcs.RouterUpdates) + for _, source := range sources { + for _, dest := range dests { + require.NotEqual(t, source, dest) + if _, ok := updates[source]; !ok { + updates[source] = ccipcs.RouterUpdates{ + OnRampUpdates: map[uint64]bool{ + dest: true, + }, + } + } else { + updates[source].OnRampUpdates[dest] = true + } + } + } + return +} + +// feeQuoterDestUpdates adds a fee quoter configuration for the provided dest chains on the fee quoters on the provided sources. +func feeQuoterDestUpdates(t *testing.T, dests []uint64, sources []uint64) (updates map[uint64]map[uint64]fee_quoter.FeeQuoterDestChainConfig) { + updates = make(map[uint64]map[uint64]fee_quoter.FeeQuoterDestChainConfig) + for _, source := range sources { + for _, dest := range dests { + require.NotEqual(t, source, dest) + if _, ok := updates[source]; !ok { + updates[source] = make(map[uint64]fee_quoter.FeeQuoterDestChainConfig) + } + updates[source][dest] = ccipcs.DefaultFeeQuoterDestChainConfig() + } + } + return +} + +// feeQuoterPricesByChain sets the gas price for the provided dests on the fee quoters in the provided sources. +func feeQuoterPricesByChain(t *testing.T, dests []uint64, sources []uint64) (prices map[uint64]ccipcs.FeeQuoterPriceUpdatePerSource) { + prices = make(map[uint64]ccipcs.FeeQuoterPriceUpdatePerSource) + for _, source := range sources { + prices[source] = ccipcs.FeeQuoterPriceUpdatePerSource{ + GasPrices: make(map[uint64]*big.Int), + } + for _, dest := range dests { + require.NotEqual(t, source, dest) + prices[source].GasPrices[dest] = testhelpers.DefaultGasPrice + } + } + return +} + +// onRampDestUpdates adds the provided dests as destination chains to the onRamps on the provided sources. +func onRampDestUpdates(t *testing.T, dests []uint64, sources []uint64, testRouterEnabled bool) (updates map[uint64]map[uint64]ccipcs.OnRampDestinationUpdate) { + updates = make(map[uint64]map[uint64]ccipcs.OnRampDestinationUpdate) + for _, source := range sources { + for _, dest := range dests { + require.NotEqual(t, source, dest) + if _, ok := updates[source]; !ok { + updates[source] = map[uint64]ccipcs.OnRampDestinationUpdate{ + dest: { + IsEnabled: true, + TestRouter: testRouterEnabled, + }, + } + } else { + updates[source][dest] = ccipcs.OnRampDestinationUpdate{ + IsEnabled: true, + TestRouter: testRouterEnabled, + } + } + } + } + return +} + +// offRampSourceUpdates adds the provided sources to the offRamp on the provided dest chains. +func offRampSourceUpdates(t *testing.T, dests []uint64, sources []uint64, testRouterEnabled bool) (updates map[uint64]map[uint64]ccipcs.OffRampSourceUpdate) { + updates = make(map[uint64]map[uint64]ccipcs.OffRampSourceUpdate) + for _, source := range sources { + for _, dest := range dests { + require.NotEqual(t, source, dest) + if _, ok := updates[dest]; !ok { + updates[dest] = make(map[uint64]ccipcs.OffRampSourceUpdate) + } + updates[dest][source] = ccipcs.OffRampSourceUpdate{ + IsEnabled: true, + TestRouter: testRouterEnabled, + } + } + } + return +} + +func assertRMNRemoteAndProxyState(t *testing.T, chains []uint64, state ccipcs.CCIPOnChainState) { + for _, chain := range chains { + require.NotEqual(t, common.Address{}, state.Chains[chain].RMNRemote.Address()) + _, err := state.Chains[chain].RMNRemote.GetCursedSubjects(&bind.CallOpts{ + Context: tests.Context(t), + }) + require.NoError(t, err) + + // check which address RMNProxy is pointing to + rmnAddress, err := state.Chains[chain].RMNProxy.GetARM(&bind.CallOpts{ + Context: tests.Context(t), + }) + require.NoError(t, err) + require.Equal(t, state.Chains[chain].RMNRemote.Address(), rmnAddress) + + t.Log("RMNRemote address for chain", chain, "is:", state.Chains[chain].RMNRemote.Address().Hex()) + t.Log("RMNProxy address for chain", chain, "is:", state.Chains[chain].RMNProxy.Address().Hex()) + } +} + +func transferToMCMSAndRenounceTimelockDeployer( + t *testing.T, + e testhelpers.DeployedEnv, + chains []uint64, + state ccipcs.CCIPOnChainState, + onlyChainContracts bool, +) { + apps := make([]commonchangeset.ChangesetApplication, 0, len(chains)+1) + cfg := testhelpers.GenTestTransferOwnershipConfig(e, chains, state) + if onlyChainContracts { + // filter out the home chain contracts from e.HomeChainSel + var homeChainContracts = map[common.Address]struct{}{ + state.Chains[e.HomeChainSel].CapabilityRegistry.Address(): {}, + state.Chains[e.HomeChainSel].CCIPHome.Address(): {}, + state.Chains[e.HomeChainSel].RMNHome.Address(): {}, + } + var chainContracts []common.Address + for _, contract := range cfg.ContractsByChain[e.HomeChainSel] { + if _, ok := homeChainContracts[contract]; !ok { + chainContracts = append(chainContracts, contract) + } + } + cfg.ContractsByChain[e.HomeChainSel] = chainContracts + } + apps = append(apps, commonchangeset.ChangesetApplication{ + Changeset: commonchangeset.WrapChangeSet(commonchangeset.TransferToMCMSWithTimelock), + Config: cfg, + }) + for _, chain := range chains { + apps = append(apps, commonchangeset.ChangesetApplication{ + Changeset: commonchangeset.WrapChangeSet(commonchangeset.RenounceTimelockDeployer), + Config: commonchangeset.RenounceTimelockDeployerConfig{ + ChainSel: chain, + }, + }) + } + var err error + e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, e.TimelockContracts(t), apps) + require.NoError(t, err) +} diff --git a/integration-tests/smoke/ccip/ccip_batching_test.go b/integration-tests/smoke/ccip/ccip_batching_test.go index 58f4e922ac5..7b5a9092cf1 100644 --- a/integration-tests/smoke/ccip/ccip_batching_test.go +++ b/integration-tests/smoke/ccip/ccip_batching_test.go @@ -1,4 +1,4 @@ -package smoke +package ccip import ( "context" @@ -15,6 +15,7 @@ import ( "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink-common/pkg/merklemulti" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" "github.com/smartcontractkit/chainlink/deployment" @@ -30,7 +31,7 @@ const ( ) type batchTestSetup struct { - e changeset.DeployedEnv + e testhelpers.DeployedEnv state changeset.CCIPOnChainState sourceChain1 uint64 sourceChain2 uint64 @@ -39,11 +40,11 @@ type batchTestSetup struct { func newBatchTestSetup(t *testing.T) batchTestSetup { // Setup 3 chains, with 2 lanes going to the dest. - e, _ := testsetups.NewIntegrationEnvironment( + e, _, _ := testsetups.NewIntegrationEnvironment( t, - changeset.WithMultiCall3(), - changeset.WithChains(3), - changeset.WithUsersPerChain(2), + testhelpers.WithMultiCall3(), + testhelpers.WithNumOfChains(3), + testhelpers.WithNumOfUsersPerChain(2), ) state, err := changeset.LoadOnchainState(e.Env) @@ -63,8 +64,8 @@ func newBatchTestSetup(t *testing.T) batchTestSetup { ) // connect sourceChain1 and sourceChain2 to destChain - require.NoError(t, changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(e.Env, state, sourceChain1, destChain, false)) - require.NoError(t, changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(e.Env, state, sourceChain2, destChain, false)) + testhelpers.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &e, state, sourceChain1, destChain, false) + testhelpers.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &e, state, sourceChain2, destChain, false) return batchTestSetup{e, state, sourceChain1, sourceChain2, destChain} } @@ -72,7 +73,7 @@ func newBatchTestSetup(t *testing.T) batchTestSetup { func Test_CCIPBatching_MaxBatchSizeEVM(t *testing.T) { t.Parallel() - ctx := changeset.Context(t) + ctx := testhelpers.Context(t) setup := newBatchTestSetup(t) sourceChain1, sourceChain2, destChain, e, state := setup.sourceChain1, setup.sourceChain2, setup.destChain, setup.e, setup.state @@ -120,7 +121,7 @@ func Test_CCIPBatching_MaxBatchSizeEVM(t *testing.T) { } } - _, err := changeset.ConfirmCommitWithExpectedSeqNumRange( + _, err := testhelpers.ConfirmCommitWithExpectedSeqNumRange( t, e.Env.Chains[sourceChain], e.Env.Chains[destChain], @@ -141,7 +142,7 @@ func Test_CCIPBatching_MultiSource(t *testing.T) { t.Parallel() // Setup 3 chains, with 2 lanes going to the dest. - ctx := changeset.Context(t) + ctx := testhelpers.Context(t) setup := newBatchTestSetup(t) sourceChain1, sourceChain2, destChain, e, state := setup.sourceChain1, setup.sourceChain2, setup.destChain, setup.e, setup.state @@ -259,7 +260,7 @@ func Test_CCIPBatching_MultiSource(t *testing.T) { // assert that all states are successful for _, states := range execStates { for _, state := range states { - require.Equal(t, changeset.EXECUTION_STATE_SUCCESS, state) + require.Equal(t, testhelpers.EXECUTION_STATE_SUCCESS, state) } } } @@ -268,7 +269,7 @@ func Test_CCIPBatching_SingleSource(t *testing.T) { t.Parallel() // Setup 3 chains, with 2 lanes going to the dest. - ctx := changeset.Context(t) + ctx := testhelpers.Context(t) setup := newBatchTestSetup(t) sourceChain1, sourceChain2, destChain, e, state := setup.sourceChain1, setup.sourceChain2, setup.destChain, setup.e, setup.state @@ -296,7 +297,7 @@ func Test_CCIPBatching_SingleSource(t *testing.T) { ) require.NoError(t, err) - _, err = changeset.ConfirmCommitWithExpectedSeqNumRange( + _, err = testhelpers.ConfirmCommitWithExpectedSeqNumRange( t, e.Env.Chains[sourceChain], e.Env.Chains[destChain], @@ -307,7 +308,7 @@ func Test_CCIPBatching_SingleSource(t *testing.T) { ) require.NoErrorf(t, err, "failed to confirm commit from chain %d", sourceChain) - states, err := changeset.ConfirmExecWithSeqNrs( + states, err := testhelpers.ConfirmExecWithSeqNrs( t, e.Env.Chains[sourceChain], e.Env.Chains[destChain], @@ -318,7 +319,7 @@ func Test_CCIPBatching_SingleSource(t *testing.T) { require.NoError(t, err) // assert that all states are successful for _, state := range states { - require.Equal(t, changeset.EXECUTION_STATE_SUCCESS, state) + require.Equal(t, testhelpers.EXECUTION_STATE_SUCCESS, state) } } @@ -329,7 +330,7 @@ type outputErr[T any] struct { func assertExecAsync( t *testing.T, - e changeset.DeployedEnv, + e testhelpers.DeployedEnv, state changeset.CCIPOnChainState, sourceChainSelector, destChainSelector uint64, @@ -338,7 +339,7 @@ func assertExecAsync( errs chan<- outputErr[map[uint64]int], ) { defer wg.Done() - states, err := changeset.ConfirmExecWithSeqNrs( + states, err := testhelpers.ConfirmExecWithSeqNrs( t, e.Env.Chains[sourceChainSelector], e.Env.Chains[destChainSelector], @@ -352,7 +353,7 @@ func assertExecAsync( func assertCommitReportsAsync( t *testing.T, - e changeset.DeployedEnv, + e testhelpers.DeployedEnv, state changeset.CCIPOnChainState, sourceChainSelector, destChainSelector uint64, @@ -362,7 +363,7 @@ func assertCommitReportsAsync( errs chan<- outputErr[*offramp.OffRampCommitReportAccepted], ) { defer wg.Done() - commitReport, err := changeset.ConfirmCommitWithExpectedSeqNumRange( + commitReport, err := testhelpers.ConfirmCommitWithExpectedSeqNumRange( t, e.Env.Chains[sourceChainSelector], e.Env.Chains[destChainSelector], @@ -378,7 +379,7 @@ func assertCommitReportsAsync( func sendMessagesAsync( ctx context.Context, t *testing.T, - e changeset.DeployedEnv, + e testhelpers.DeployedEnv, state changeset.CCIPOnChainState, sourceChainSelector, destChainSelector uint64, @@ -498,7 +499,7 @@ func genMessages( Data: []byte(fmt.Sprintf("hello world %d", i)), TokenAmounts: nil, FeeToken: common.HexToAddress("0x0"), - ExtraArgs: changeset.MakeEVMExtraArgsV2(50_000, false), + ExtraArgs: testhelpers.MakeEVMExtraArgsV2(50_000, false), } fee, err := sourceRouter.GetFee(&bind.CallOpts{Context: ctx}, destChainSelector, msg) @@ -508,7 +509,7 @@ func genMessages( totalValue.Add(totalValue, fee) - calldata, err := changeset.CCIPSendCalldata(destChainSelector, msg) + calldata, err := testhelpers.CCIPSendCalldata(destChainSelector, msg) if err != nil { return nil, nil, fmt.Errorf("generate calldata: %w", err) } diff --git a/integration-tests/smoke/ccip/ccip_fee_boosting_test.go b/integration-tests/smoke/ccip/ccip_fee_boosting_test.go index 48d9061ec63..67de0f5ffd7 100644 --- a/integration-tests/smoke/ccip/ccip_fee_boosting_test.go +++ b/integration-tests/smoke/ccip/ccip_fee_boosting_test.go @@ -1,15 +1,15 @@ -package smoke +package ccip import ( "context" - "fmt" "math/big" "testing" "time" - "github.com/pkg/errors" + "github.com/smartcontractkit/chainlink-common/pkg/config" - commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" + commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -17,14 +17,12 @@ import ( "github.com/test-go/testify/require" "golang.org/x/exp/maps" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" - cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" @@ -37,22 +35,17 @@ var ( ) func Test_CCIPFeeBoosting(t *testing.T) { - e, _ := testsetups.NewIntegrationEnvironment( + e, _, _ := testsetups.NewIntegrationEnvironment( t, - // TODO check if test should use these overrides - /* changeset.WithOCRConfigOverride(func(params changeset.CCIPOCRParams) changeset.CCIPOCRParams { - // Only 1 boost (=OCR round) is enough to cover the fee - params.ExecuteOffChainConfig.RelativeBoostPerWaitHour = 10 - // Disable token price updates - params.CommitOffChainConfig.TokenPriceBatchWriteFrequency = *config.MustNewDuration(1_000_000 * time.Hour) - // Disable gas price updates - params.CommitOffChainConfig.RemoteGasPriceBatchWriteFrequency = *config.MustNewDuration(1_000_000 * time.Hour) - // Disable token price updates - params.CommitOffChainConfig.TokenInfo = nil - return params - }), - - */ + testhelpers.WithOCRConfigOverride(func(params *changeset.CCIPOCRParams) { + params.ExecuteOffChainConfig.RelativeBoostPerWaitHour = 1 + // Disable token price updates + params.CommitOffChainConfig.TokenPriceBatchWriteFrequency = *config.MustNewDuration(1_000_000 * time.Hour) + // Disable gas price updates + params.CommitOffChainConfig.RemoteGasPriceBatchWriteFrequency = *config.MustNewDuration(1_000_000 * time.Hour) + // Disable token price updates + params.CommitOffChainConfig.TokenInfo = nil + }), ) state, err := changeset.LoadOnchainState(e.Env) @@ -69,7 +62,9 @@ func Test_CCIPFeeBoosting(t *testing.T) { ", dest chain selector:", destChain, ) - fetchedGasPriceDest, err := e.Env.Chains[destChain].Client.SuggestGasPrice(tests.Context(t)) + // TODO: discrepancy between client and the gas estimator gas price to be fixed - hardcoded for now + // fetchedGasPriceDest, err := e.Env.Chains[destChain].Client.SuggestGasPrice(tests.Context(t)) + fetchedGasPriceDest := big.NewInt(20e9) // 20 Gwei = default gas price require.NoError(t, err) originalGasPriceDestUSD := new(big.Int).Div( new(big.Int).Mul(fetchedGasPriceDest, wethPrice), @@ -80,48 +75,52 @@ func Test_CCIPFeeBoosting(t *testing.T) { // Adjust destination gas price on source fee quoter to 95% of the current value adjustedGasPriceDest := new(big.Int).Div( - new(big.Int).Mul(originalGasPriceDestUSD, big.NewInt(95)), + new(big.Int).Mul(originalGasPriceDestUSD, big.NewInt(99)), big.NewInt(100), ) t.Log("Adjusted gas price on dest chain:", adjustedGasPriceDest) - initialPrices := changeset.InitialPrices{ - LinkPrice: linkPrice, - WethPrice: wethPrice, - GasPrice: changeset.ToPackedFee(adjustedGasPriceDest, big.NewInt(0)), - } - - laneCfg := changeset.LaneConfig{ - SourceSelector: sourceChain, - DestSelector: destChain, - InitialPricesBySource: initialPrices, - FeeQuoterDestChain: changeset.DefaultFeeQuoterDestChainConfig(), - TestRouter: false, - } + feeQuoterCfg := changeset.DefaultFeeQuoterDestChainConfig() + // the default adds 10% to the gas price, we want to increase it + // to make sure the fee boosting will be finished in proper time for testing + feeQuoterCfg.GasMultiplierWeiPerEth = 120e16 - e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, nil, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(changeset.AddLanes), - Config: changeset.AddLanesConfig{LaneConfigs: []changeset.LaneConfig{laneCfg}}, + testhelpers.AddLane(t, &e, sourceChain, destChain, false, + map[uint64]*big.Int{ + destChain: testhelpers.ToPackedFee(adjustedGasPriceDest, big.NewInt(0)), }, - }) - require.NoError(t, err) + map[common.Address]*big.Int{ + state.Chains[sourceChain].LinkToken.Address(): linkPrice, + state.Chains[sourceChain].Weth9.Address(): wethPrice, + }, + feeQuoterCfg) // Update token prices in destination chain FeeQuoter - err = updateTokensPrices(e, state, destChain, map[common.Address]*big.Int{ - state.Chains[destChain].LinkToken.Address(): linkPrice, - state.Chains[destChain].Weth9.Address(): wethPrice, + e.Env, err = commoncs.ApplyChangesets(t, e.Env, e.TimelockContracts(t), []commoncs.ChangesetApplication{ + { + Changeset: commoncs.WrapChangeSet(changeset.UpdateFeeQuoterPricesChangeset), + Config: changeset.UpdateFeeQuoterPricesConfig{ + PricesByChain: map[uint64]changeset.FeeQuoterPriceUpdatePerSource{ + destChain: { + TokenPrices: map[common.Address]*big.Int{ + state.Chains[destChain].LinkToken.Address(): linkPrice, + state.Chains[destChain].Weth9.Address(): wethPrice, + }, + }, + }, + }, + }, }) require.NoError(t, err) startBlocks := make(map[uint64]*uint64) - expectedSeqNum := make(map[changeset.SourceDestPair]uint64) - expectedSeqNumExec := make(map[changeset.SourceDestPair][]uint64) + expectedSeqNum := make(map[testhelpers.SourceDestPair]uint64) + expectedSeqNumExec := make(map[testhelpers.SourceDestPair][]uint64) latesthdr, err := e.Env.Chains[sourceChain].Client.HeaderByNumber(testcontext.Get(t), nil) require.NoError(t, err) block := latesthdr.Number.Uint64() - msgSentEvent := changeset.TestSendRequest(t, e.Env, state, sourceChain, destChain, false, router.ClientEVM2AnyMessage{ + msgSentEvent := testhelpers.TestSendRequest(t, e.Env, state, sourceChain, destChain, false, router.ClientEVM2AnyMessage{ Receiver: common.LeftPadBytes(state.Chains[destChain].Receiver.Address().Bytes(), 32), Data: []byte("message that needs fee boosting"), TokenAmounts: nil, @@ -129,21 +128,34 @@ func Test_CCIPFeeBoosting(t *testing.T) { ExtraArgs: nil, }) startBlocks[sourceChain] = &block - expectedSeqNum[changeset.SourceDestPair{ + expectedSeqNum[testhelpers.SourceDestPair{ SourceChainSelector: sourceChain, DestChainSelector: destChain, }] = msgSentEvent.SequenceNumber - expectedSeqNumExec[changeset.SourceDestPair{ + expectedSeqNumExec[testhelpers.SourceDestPair{ SourceChainSelector: sourceChain, DestChainSelector: destChain, }] = []uint64{msgSentEvent.SequenceNumber} - err = updateGasPrice(e, state, sourceChain, destChain, originalGasPriceDestUSD) + e.Env, err = commoncs.ApplyChangesets(t, e.Env, e.TimelockContracts(t), []commoncs.ChangesetApplication{ + { + Changeset: commoncs.WrapChangeSet(changeset.UpdateFeeQuoterPricesChangeset), + Config: changeset.UpdateFeeQuoterPricesConfig{ + PricesByChain: map[uint64]changeset.FeeQuoterPriceUpdatePerSource{ + sourceChain: { + GasPrices: map[uint64]*big.Int{ + destChain: originalGasPriceDestUSD, + }, + }, + }, + }, + }, + }) require.NoError(t, err) // Confirm gas prices are updated srcFeeQuoter := state.Chains[sourceChain].FeeQuoter - err = changeset.ConfirmGasPriceUpdated(t, e.Env.Chains[destChain], srcFeeQuoter, 0, originalGasPriceDestUSD) + err = testhelpers.ConfirmGasPriceUpdated(t, e.Env.Chains[destChain], srcFeeQuoter, 0, originalGasPriceDestUSD) require.NoError(t, err) // Confirm that fee boosting will be triggered @@ -154,11 +166,11 @@ func Test_CCIPFeeBoosting(t *testing.T) { replayBlocks := make(map[uint64]uint64) replayBlocks[sourceChain] = 1 replayBlocks[destChain] = 1 - changeset.ReplayLogs(t, e.Env.Offchain, replayBlocks) + testhelpers.ReplayLogs(t, e.Env.Offchain, replayBlocks) // Confirm that the message is committed and executed - changeset.ConfirmCommitForAllWithExpectedSeqNums(t, e.Env, state, expectedSeqNum, startBlocks) - changeset.ConfirmExecWithSeqNrsForAll(t, e.Env, state, expectedSeqNumExec, startBlocks) + testhelpers.ConfirmCommitForAllWithExpectedSeqNums(t, e.Env, state, expectedSeqNum, startBlocks) + testhelpers.ConfirmExecWithSeqNrsForAll(t, e.Env, state, expectedSeqNumExec, startBlocks) } // TODO: Find a more accurate way to determine if fee boosting will be triggered @@ -271,61 +283,3 @@ func convertToMessage(msg onramp.InternalEVM2AnyRampMessage) cciptypes.Message { TokenAmounts: tokenAmounts, } } - -func updateGasPrice(env changeset.DeployedEnv, state changeset.CCIPOnChainState, srcChain, destChain uint64, gasPrice *big.Int) error { - chainState, exists := state.Chains[srcChain] - if !exists { - return fmt.Errorf("chain state not found for selector: %d", srcChain) - } - - feeQuoter := chainState.FeeQuoter - // Update gas price - auth := env.Env.Chains[srcChain].DeployerKey - tx, err := feeQuoter.UpdatePrices(auth, fee_quoter.InternalPriceUpdates{ - TokenPriceUpdates: nil, - GasPriceUpdates: []fee_quoter.InternalGasPriceUpdate{ - { - DestChainSelector: destChain, - UsdPerUnitGas: gasPrice, - }, - }, - }) - if err != nil { - return errors.Wrapf(err, "updating gas price on chain %d", srcChain) - } - if _, err := deployment.ConfirmIfNoError(env.Env.Chains[srcChain], tx, err); err != nil { - return err - } - - return nil -} - -func updateTokensPrices(env changeset.DeployedEnv, state changeset.CCIPOnChainState, chain uint64, tokenPrices map[common.Address]*big.Int) error { - chainState, exists := state.Chains[chain] - if !exists { - return fmt.Errorf("chain state not found for selector: %d", chain) - } - - feeQuoter := chainState.FeeQuoter - // Update token prices - auth := env.Env.Chains[chain].DeployerKey - tokenPricesUpdates := make([]fee_quoter.InternalTokenPriceUpdate, 0, len(tokenPrices)) - for token, price := range tokenPrices { - tokenPricesUpdates = append(tokenPricesUpdates, fee_quoter.InternalTokenPriceUpdate{ - SourceToken: token, - UsdPerToken: price, - }) - } - tx, err := feeQuoter.UpdatePrices(auth, fee_quoter.InternalPriceUpdates{ - TokenPriceUpdates: tokenPricesUpdates, - GasPriceUpdates: nil, - }) - if err != nil { - return errors.Wrapf(err, "updating token prices on chain %d", chain) - } - if _, err := deployment.ConfirmIfNoError(env.Env.Chains[chain], tx, err); err != nil { - return err - } - - return nil -} diff --git a/integration-tests/smoke/ccip/ccip_fees_test.go b/integration-tests/smoke/ccip/ccip_fees_test.go index 55788a4aa5f..f5b74791bfa 100644 --- a/integration-tests/smoke/ccip/ccip_fees_test.go +++ b/integration-tests/smoke/ccip/ccip_fees_test.go @@ -1,4 +1,4 @@ -package smoke +package ccip import ( "math/big" @@ -14,6 +14,7 @@ import ( "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" @@ -27,7 +28,7 @@ import ( func setupTokens( t *testing.T, state changeset.CCIPOnChainState, - tenv changeset.DeployedEnv, + tenv testhelpers.DeployedEnv, src, dest uint64, transferTokenMintAmount, feeTokenMintAmount *big.Int, @@ -39,7 +40,7 @@ func setupTokens( e := tenv.Env // Deploy the token to test transferring - srcToken, _, dstToken, _, err := changeset.DeployTransferableToken( + srcToken, _, dstToken, _, err := testhelpers.DeployTransferableToken( lggr, tenv.Env.Chains, src, @@ -101,9 +102,9 @@ func setupTokens( func Test_CCIPFees(t *testing.T) { t.Parallel() - tenv, _ := testsetups.NewIntegrationEnvironment( + tenv, _, _ := testsetups.NewIntegrationEnvironment( t, - changeset.WithMultiCall3(), + testhelpers.WithMultiCall3(), ) e := tenv.Env @@ -127,10 +128,10 @@ func Test_CCIPFees(t *testing.T) { ) // Ensure capreg logs are up to date. - changeset.ReplayLogs(t, e.Offchain, tenv.ReplayBlocks) + testhelpers.ReplayLogs(t, e.Offchain, tenv.ReplayBlocks) // Add all lanes - require.NoError(t, changeset.AddLanesForAll(e, state)) + testhelpers.AddLanesForAll(t, &tenv, state) t.Run("Send programmable token transfer pay with Link token", func(t *testing.T) { runFeeTokenTestCase(feeTokenTestCase{ @@ -222,10 +223,10 @@ func Test_CCIPFees(t *testing.T) { ExtraArgs: nil, } - _, _, err = changeset.CCIPSendRequest( + _, _, err = testhelpers.CCIPSendRequest( e, state, - &changeset.CCIPSendReqConfig{ + &testhelpers.CCIPSendReqConfig{ Sender: e.Chains[sourceChain].DeployerKey, IsTestRouter: true, SourceChain: sourceChain, @@ -291,7 +292,7 @@ func Test_CCIPFees(t *testing.T) { type feeTokenTestCase struct { t *testing.T src, dst uint64 - env changeset.DeployedEnv + env testhelpers.DeployedEnv srcToken, dstToken *burn_mint_erc677.BurnMintERC677 tokenAmounts []router.ClientEVMTokenAmount feeToken common.Address @@ -304,8 +305,8 @@ func runFeeTokenTestCase(tc feeTokenTestCase) { ctx := tests.Context(tc.t) // Need to keep track of the block number for each chain so that event subscription can be done from that block. startBlocks := make(map[uint64]*uint64) - expectedSeqNum := make(map[changeset.SourceDestPair]uint64) - expectedSeqNumExec := make(map[changeset.SourceDestPair][]uint64) + expectedSeqNum := make(map[testhelpers.SourceDestPair]uint64) + expectedSeqNumExec := make(map[testhelpers.SourceDestPair][]uint64) srcChain := tc.env.Env.Chains[tc.src] dstChain := tc.env.Env.Chains[tc.dst] @@ -374,7 +375,7 @@ func runFeeTokenTestCase(tc feeTokenTestCase) { tc.t.Logf("fee token balance before: %s, fee token enabled: %s", feeTokenBalanceBefore.String(), tc.feeToken.String()) - msgSentEvent := changeset.TestSendRequest( + msgSentEvent := testhelpers.TestSendRequest( tc.t, tc.env.Env, state, @@ -390,11 +391,11 @@ func runFeeTokenTestCase(tc feeTokenTestCase) { }, ) - expectedSeqNum[changeset.SourceDestPair{ + expectedSeqNum[testhelpers.SourceDestPair{ SourceChainSelector: tc.src, DestChainSelector: tc.dst, }] = msgSentEvent.SequenceNumber - expectedSeqNumExec[changeset.SourceDestPair{ + expectedSeqNumExec[testhelpers.SourceDestPair{ SourceChainSelector: tc.src, DestChainSelector: tc.dst, }] = []uint64{msgSentEvent.SequenceNumber} @@ -427,7 +428,7 @@ func runFeeTokenTestCase(tc feeTokenTestCase) { ) // Wait for all commit reports to land. - changeset.ConfirmCommitForAllWithExpectedSeqNums(tc.t, tc.env.Env, state, expectedSeqNum, startBlocks) + testhelpers.ConfirmCommitForAllWithExpectedSeqNums(tc.t, tc.env.Env, state, expectedSeqNum, startBlocks) // After commit is reported on all chains, token prices should be updated in FeeQuoter. linkAddress := state.Chains[tc.dst].LinkToken.Address() @@ -439,7 +440,7 @@ func runFeeTokenTestCase(tc feeTokenTestCase) { require.Equal(tc.t, changeset.MockLinkPrice, timestampedPrice.Value) // Wait for all exec reports to land - changeset.ConfirmExecWithSeqNrsForAll(tc.t, tc.env.Env, state, expectedSeqNumExec, startBlocks) + testhelpers.ConfirmExecWithSeqNrsForAll(tc.t, tc.env.Env, state, expectedSeqNumExec, startBlocks) if tc.assertTokenBalance { require.Len(tc.t, tc.tokenAmounts, 1) diff --git a/integration-tests/smoke/ccip/ccip_gas_price_updates_test.go b/integration-tests/smoke/ccip/ccip_gas_price_updates_test.go index d11e4304366..42fcacc58f3 100644 --- a/integration-tests/smoke/ccip/ccip_gas_price_updates_test.go +++ b/integration-tests/smoke/ccip/ccip_gas_price_updates_test.go @@ -1,4 +1,4 @@ -package smoke +package ccip import ( "math/big" @@ -15,6 +15,7 @@ import ( "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" ) @@ -22,19 +23,18 @@ import ( // Test_CCIPGasPriceUpdates tests that chain fee price updates are propagated correctly when // price reaches some deviation threshold or when the price has expired. func Test_CCIPGasPriceUpdates(t *testing.T) { - ctx := changeset.Context(t) + ctx := testhelpers.Context(t) callOpts := &bind.CallOpts{Context: ctx} var gasPriceExpiry = 5 * time.Second - e, _ := testsetups.NewIntegrationEnvironment(t, - changeset.WithOCRConfigOverride(func(params changeset.CCIPOCRParams) changeset.CCIPOCRParams { + e, _, _ := testsetups.NewIntegrationEnvironment(t, + testhelpers.WithOCRConfigOverride(func(params *changeset.CCIPOCRParams) { params.CommitOffChainConfig.RemoteGasPriceBatchWriteFrequency = *config.MustNewDuration(gasPriceExpiry) - return params }), ) state, err := changeset.LoadOnchainState(e.Env) require.NoError(t, err) - require.NoError(t, changeset.AddLanesForAll(e.Env, state)) + testhelpers.AddLanesForAll(t, &e, state) allChainSelectors := maps.Keys(e.Env.Chains) assert.GreaterOrEqual(t, len(allChainSelectors), 2, "test requires at least 2 chains") diff --git a/integration-tests/smoke/ccip/ccip_message_limitations_test.go b/integration-tests/smoke/ccip/ccip_message_limitations_test.go index 9398fd9f932..ea775e5445d 100644 --- a/integration-tests/smoke/ccip/ccip_message_limitations_test.go +++ b/integration-tests/smoke/ccip/ccip_message_limitations_test.go @@ -1,4 +1,4 @@ -package smoke +package ccip import ( "math/big" @@ -15,6 +15,7 @@ import ( "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" ) @@ -23,13 +24,13 @@ func Test_CCIPMessageLimitations(t *testing.T) { ctx := testcontext.Get(t) callOpts := &bind.CallOpts{Context: ctx} - testEnv, _ := testsetups.NewIntegrationEnvironment(t) + testEnv, _, _ := testsetups.NewIntegrationEnvironment(t) chains := maps.Keys(testEnv.Env.Chains) onChainState, err := changeset.LoadOnchainState(testEnv.Env) require.NoError(t, err) - require.NoError(t, changeset.AddLanesForAll(testEnv.Env, onChainState)) + testhelpers.AddLanesForAll(t, &testEnv, onChainState) srcToken, _ := setupTokens( t, @@ -82,7 +83,7 @@ func Test_CCIPMessageLimitations(t *testing.T) { Receiver: common.LeftPadBytes(onChainState.Chains[chains[1]].Receiver.Address().Bytes(), 32), Data: []byte(strings.Repeat("0", int(chain0DestConfig.MaxDataBytes))), FeeToken: common.HexToAddress("0x0"), - ExtraArgs: changeset.MakeEVMExtraArgsV2(uint64(chain0DestConfig.MaxPerMsgGasLimit), true), + ExtraArgs: testhelpers.MakeEVMExtraArgsV2(uint64(chain0DestConfig.MaxPerMsgGasLimit), true), }, }, //{ // TODO: exec plugin never executed this message. CCIP-4471 @@ -136,7 +137,7 @@ func Test_CCIPMessageLimitations(t *testing.T) { Data: []byte("abc"), TokenAmounts: []router.ClientEVMTokenAmount{}, FeeToken: common.HexToAddress("0x0"), - ExtraArgs: changeset.MakeEVMExtraArgsV2(uint64(chain0DestConfig.MaxPerMsgGasLimit)+1, true), + ExtraArgs: testhelpers.MakeEVMExtraArgsV2(uint64(chain0DestConfig.MaxPerMsgGasLimit)+1, true), }, expRevert: true, }, @@ -145,18 +146,18 @@ func Test_CCIPMessageLimitations(t *testing.T) { // Need to keep track of the block number for each chain so that event subscription can be done from that block. startBlocks := make(map[uint64]*uint64) // Send a message from each chain to every other chain. - expectedSeqNum := make(map[changeset.SourceDestPair]uint64) - expectedSeqNumExec := make(map[changeset.SourceDestPair][]uint64) + expectedSeqNum := make(map[testhelpers.SourceDestPair]uint64) + expectedSeqNumExec := make(map[testhelpers.SourceDestPair][]uint64) for _, msg := range testMsgs { t.Logf("Sending msg: %s", msg.name) require.NotEqual(t, msg.fromChain, msg.toChain, "fromChain and toChain cannot be the same") startBlocks[msg.toChain] = nil - msgSentEvent, err := changeset.DoSendRequest( + msgSentEvent, err := testhelpers.DoSendRequest( t, testEnv.Env, onChainState, - changeset.WithSourceChain(msg.fromChain), - changeset.WithDestChain(msg.toChain), - changeset.WithTestRouter(false), - changeset.WithEvm2AnyMessage(msg.msg)) + testhelpers.WithSourceChain(msg.fromChain), + testhelpers.WithDestChain(msg.toChain), + testhelpers.WithTestRouter(false), + testhelpers.WithEvm2AnyMessage(msg.msg)) if msg.expRevert { t.Logf("Message reverted as expected") @@ -168,19 +169,19 @@ func Test_CCIPMessageLimitations(t *testing.T) { t.Logf("Message not reverted as expected") - expectedSeqNum[changeset.SourceDestPair{ + expectedSeqNum[testhelpers.SourceDestPair{ SourceChainSelector: msg.fromChain, DestChainSelector: msg.toChain, }] = msgSentEvent.SequenceNumber - expectedSeqNumExec[changeset.SourceDestPair{ + expectedSeqNumExec[testhelpers.SourceDestPair{ SourceChainSelector: msg.fromChain, DestChainSelector: msg.toChain, }] = []uint64{msgSentEvent.SequenceNumber} } // Wait for all commit reports to land. - changeset.ConfirmCommitForAllWithExpectedSeqNums(t, testEnv.Env, onChainState, expectedSeqNum, startBlocks) + testhelpers.ConfirmCommitForAllWithExpectedSeqNums(t, testEnv.Env, onChainState, expectedSeqNum, startBlocks) // Wait for all exec reports to land - changeset.ConfirmExecWithSeqNrsForAll(t, testEnv.Env, onChainState, expectedSeqNumExec, startBlocks) + testhelpers.ConfirmExecWithSeqNrsForAll(t, testEnv.Env, onChainState, expectedSeqNumExec, startBlocks) } diff --git a/integration-tests/smoke/ccip/ccip_messaging_test.go b/integration-tests/smoke/ccip/ccip_messaging_test.go index 13f14fcda16..fc154b848be 100644 --- a/integration-tests/smoke/ccip/ccip_messaging_test.go +++ b/integration-tests/smoke/ccip/ccip_messaging_test.go @@ -1,4 +1,4 @@ -package smoke +package ccip import ( "context" @@ -18,6 +18,7 @@ import ( "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" @@ -27,7 +28,7 @@ import ( type testCaseSetup struct { t *testing.T sender []byte - deployedEnv changeset.DeployedEnv + deployedEnv testhelpers.DeployedEnv onchainState changeset.CCIPOnChainState sourceChain, destChain uint64 } @@ -46,8 +47,8 @@ type messagingTestCaseOutput struct { func Test_CCIPMessaging(t *testing.T) { // Setup 2 chains and a single lane. - ctx := changeset.Context(t) - e, _ := testsetups.NewIntegrationEnvironment(t) + ctx := testhelpers.Context(t) + e, _, _ := testsetups.NewIntegrationEnvironment(t) state, err := changeset.LoadOnchainState(e.Env) require.NoError(t, err) @@ -63,7 +64,7 @@ func Test_CCIPMessaging(t *testing.T) { ", dest chain selector:", destChain, ) // connect a single lane, source to dest - require.NoError(t, changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(e.Env, state, sourceChain, destChain, false)) + testhelpers.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &e, state, sourceChain, destChain, false) var ( replayed bool @@ -88,8 +89,8 @@ func Test_CCIPMessaging(t *testing.T) { }, common.HexToAddress("0xdead"), []byte("hello eoa"), - nil, // default extraArgs - changeset.EXECUTION_STATE_SUCCESS, // success because offRamp won't call an EOA + nil, // default extraArgs + testhelpers.EXECUTION_STATE_SUCCESS, // success because offRamp won't call an EOA ) }) @@ -102,8 +103,8 @@ func Test_CCIPMessaging(t *testing.T) { }, state.Chains[destChain].FeeQuoter.Address(), []byte("hello FeeQuoter"), - nil, // default extraArgs - changeset.EXECUTION_STATE_SUCCESS, // success because offRamp won't call a contract not implementing CCIPReceiver + nil, // default extraArgs + testhelpers.EXECUTION_STATE_SUCCESS, // success because offRamp won't call a contract not implementing CCIPReceiver ) }) @@ -119,7 +120,7 @@ func Test_CCIPMessaging(t *testing.T) { state.Chains[destChain].Receiver.Address(), []byte("hello CCIPReceiver"), nil, // default extraArgs - changeset.EXECUTION_STATE_SUCCESS, + testhelpers.EXECUTION_STATE_SUCCESS, func(t *testing.T) { iter, err := state.Chains[destChain].Receiver.FilterMessageReceived(&bind.FilterOpts{ Context: ctx, @@ -143,8 +144,8 @@ func Test_CCIPMessaging(t *testing.T) { }, state.Chains[destChain].Receiver.Address(), []byte("hello CCIPReceiver with low exec gas"), - changeset.MakeEVMExtraArgsV2(1, false), // 1 gas is too low. - changeset.EXECUTION_STATE_FAILURE, // state would be failed onchain due to low gas + testhelpers.MakeEVMExtraArgsV2(1, false), // 1 gas is too low. + testhelpers.EXECUTION_STATE_FAILURE, // state would be failed onchain due to low gas ) manuallyExecute(ctx, t, latestHead.Number.Uint64(), state, destChain, out, sourceChain, e, sender) @@ -162,7 +163,7 @@ func manuallyExecute( destChain uint64, out messagingTestCaseOutput, sourceChain uint64, - e changeset.DeployedEnv, + e testhelpers.DeployedEnv, sender []byte, ) { merkleRoot := getMerkleRoot( @@ -229,7 +230,7 @@ func manuallyExecute( newExecutionState, err := state.Chains[destChain].OffRamp.GetExecutionState(&bind.CallOpts{Context: ctx}, sourceChain, out.msgSentEvent.SequenceNumber) require.NoError(t, err) - require.Equal(t, uint8(changeset.EXECUTION_STATE_SUCCESS), newExecutionState) + require.Equal(t, uint8(testhelpers.EXECUTION_STATE_SUCCESS), newExecutionState) } func getMerkleRoot( @@ -285,12 +286,12 @@ func getMessageHash( return iter.Event.MessageHash } -func sleepAndReplay(t *testing.T, e changeset.DeployedEnv, sourceChain, destChain uint64) { +func sleepAndReplay(t *testing.T, e testhelpers.DeployedEnv, sourceChain, destChain uint64) { time.Sleep(30 * time.Second) replayBlocks := make(map[uint64]uint64) replayBlocks[sourceChain] = 1 replayBlocks[destChain] = 1 - changeset.ReplayLogs(t, e.Env.Offchain, replayBlocks) + testhelpers.ReplayLogs(t, e.Env.Offchain, replayBlocks) } func runMessagingTestCase( @@ -309,20 +310,20 @@ func runMessagingTestCase( require.Equal(tc.t, tc.nonce, latestNonce) startBlocks := make(map[uint64]*uint64) - msgSentEvent := changeset.TestSendRequest(tc.t, tc.deployedEnv.Env, tc.onchainState, tc.sourceChain, tc.destChain, false, router.ClientEVM2AnyMessage{ + msgSentEvent := testhelpers.TestSendRequest(tc.t, tc.deployedEnv.Env, tc.onchainState, tc.sourceChain, tc.destChain, false, router.ClientEVM2AnyMessage{ Receiver: common.LeftPadBytes(receiver.Bytes(), 32), Data: msgData, TokenAmounts: nil, FeeToken: common.HexToAddress("0x0"), ExtraArgs: extraArgs, }) - expectedSeqNum := map[changeset.SourceDestPair]uint64{ + expectedSeqNum := map[testhelpers.SourceDestPair]uint64{ { SourceChainSelector: tc.sourceChain, DestChainSelector: tc.destChain, }: msgSentEvent.SequenceNumber, } - expectedSeqNumExec := map[changeset.SourceDestPair][]uint64{ + expectedSeqNumExec := map[testhelpers.SourceDestPair][]uint64{ { SourceChainSelector: tc.sourceChain, DestChainSelector: tc.destChain, @@ -336,20 +337,20 @@ func runMessagingTestCase( out.replayed = true } - changeset.ConfirmCommitForAllWithExpectedSeqNums(tc.t, tc.deployedEnv.Env, tc.onchainState, expectedSeqNum, startBlocks) - execStates := changeset.ConfirmExecWithSeqNrsForAll(tc.t, tc.deployedEnv.Env, tc.onchainState, expectedSeqNumExec, startBlocks) + testhelpers.ConfirmCommitForAllWithExpectedSeqNums(tc.t, tc.deployedEnv.Env, tc.onchainState, expectedSeqNum, startBlocks) + execStates := testhelpers.ConfirmExecWithSeqNrsForAll(tc.t, tc.deployedEnv.Env, tc.onchainState, expectedSeqNumExec, startBlocks) require.Equalf( tc.t, expectedExecutionState, - execStates[changeset.SourceDestPair{ + execStates[testhelpers.SourceDestPair{ SourceChainSelector: tc.sourceChain, DestChainSelector: tc.destChain, }][msgSentEvent.SequenceNumber], "wrong execution state for seq nr %d, expected %d, got %d", msgSentEvent.SequenceNumber, expectedExecutionState, - execStates[changeset.SourceDestPair{ + execStates[testhelpers.SourceDestPair{ SourceChainSelector: tc.sourceChain, DestChainSelector: tc.destChain, }][msgSentEvent.SequenceNumber], diff --git a/integration-tests/smoke/ccip/ccip_migration_to_v_1_6_test.go b/integration-tests/smoke/ccip/ccip_migration_to_v_1_6_test.go new file mode 100644 index 00000000000..d70a6e8a3fa --- /dev/null +++ b/integration-tests/smoke/ccip/ccip_migration_to_v_1_6_test.go @@ -0,0 +1,373 @@ +package ccip + +import ( + "context" + "testing" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + + chainselectors "github.com/smartcontractkit/chain-selectors" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" + + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" + v1_5testhelpers "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers/v1_5" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_5" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_contract" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" +) + +func TestMigrateFromV1_5ToV1_6(t *testing.T) { + // Deploy CCIP 1.5 with 3 chains and 4 nodes + 1 bootstrap + // Deploy 1.5 contracts (excluding pools to start, but including MCMS) . + e, _, tEnv := testsetups.NewIntegrationEnvironment( + t, + testhelpers.WithPrerequisiteDeploymentOnly( + &changeset.V1_5DeploymentConfig{ + PriceRegStalenessThreshold: 60 * 60 * 24 * 14, // two weeks + RMNConfig: &rmn_contract.RMNConfig{ + BlessWeightThreshold: 2, + CurseWeightThreshold: 2, + // setting dummy voters, we will permabless this later + Voters: []rmn_contract.RMNVoter{ + { + BlessWeight: 2, + CurseWeight: 2, + BlessVoteAddr: utils.RandomAddress(), + CurseVoteAddr: utils.RandomAddress(), + }, + }, + }, + }), + testhelpers.WithNumOfChains(3), + testhelpers.WithNumOfUsersPerChain(2), + // for in-memory test it is important to set the dest chain id as 1337 otherwise the config digest will not match + // between nodes' calculated digest and the digest set on the contract + testhelpers.WithChainIDs([]uint64{chainselectors.GETH_TESTNET.EvmChainID}), + ) + state, err := changeset.LoadOnchainState(e.Env) + require.NoError(t, err) + allChainsExcept1337 := e.Env.AllChainSelectorsExcluding([]uint64{chainselectors.GETH_TESTNET.Selector}) + require.Contains(t, e.Env.AllChainSelectors(), chainselectors.GETH_TESTNET.Selector) + require.Len(t, allChainsExcept1337, 2) + src1, src2, dest := allChainsExcept1337[0], allChainsExcept1337[1], chainselectors.GETH_TESTNET.Selector + pairs := []testhelpers.SourceDestPair{ + // as mentioned in the comment above, the dest chain id should be 1337 + {SourceChainSelector: src1, DestChainSelector: dest}, + {SourceChainSelector: src2, DestChainSelector: dest}, + } + // wire up all lanes + // deploy onRamp, commit store, offramp , set ocr2config and send corresponding jobs + e.Env = v1_5testhelpers.AddLanes(t, e.Env, state, pairs) + + // permabless the commit stores + e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, e.TimelockContracts(t), []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(v1_5.PermaBlessCommitStoreChangeset), + Config: v1_5.PermaBlessCommitStoreConfig{ + Configs: map[uint64]v1_5.PermaBlessCommitStoreConfigPerDest{ + dest: { + Sources: []v1_5.PermaBlessConfigPerSourceChain{ + { + SourceChainSelector: src1, + PermaBless: true, + }, + { + SourceChainSelector: src2, + PermaBless: true, + }, + }, + }, + }, + }, + }, + }) + require.NoError(t, err) + // reload state after adding lanes + state, err = changeset.LoadOnchainState(e.Env) + require.NoError(t, err) + tEnv.UpdateDeployedEnvironment(e) + // ensure that all lanes are functional + for _, pair := range pairs { + sentEvent, err := v1_5testhelpers.SendRequest(t, e.Env, state, + testhelpers.WithSourceChain(pair.SourceChainSelector), + testhelpers.WithDestChain(pair.DestChainSelector), + testhelpers.WithTestRouter(false), + testhelpers.WithEvm2AnyMessage(router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(state.Chains[pair.DestChainSelector].Receiver.Address().Bytes(), 32), + Data: []byte("hello"), + TokenAmounts: nil, + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: nil, + }), + ) + require.NoError(t, err) + require.NotNil(t, sentEvent) + destChain := e.Env.Chains[pair.DestChainSelector] + destStartBlock, err := destChain.Client.HeaderByNumber(context.Background(), nil) + require.NoError(t, err) + v1_5testhelpers.WaitForCommit(t, e.Env.Chains[pair.SourceChainSelector], destChain, state.Chains[dest].CommitStore[src1], sentEvent.Message.SequenceNumber) + v1_5testhelpers.WaitForExecute(t, e.Env.Chains[pair.SourceChainSelector], destChain, state.Chains[dest].EVM2EVMOffRamp[src1], []uint64{sentEvent.Message.SequenceNumber}, destStartBlock.Number.Uint64()) + } + + // now that all 1.5 lanes work transfer ownership of the contracts to MCMS + contractsByChain := make(map[uint64][]common.Address) + for _, chain := range e.Env.AllChainSelectors() { + contractsByChain[chain] = []common.Address{ + state.Chains[chain].Router.Address(), + state.Chains[chain].RMNProxy.Address(), + state.Chains[chain].PriceRegistry.Address(), + state.Chains[chain].TokenAdminRegistry.Address(), + state.Chains[chain].RMN.Address(), + } + if state.Chains[chain].EVM2EVMOnRamp != nil { + for _, onRamp := range state.Chains[chain].EVM2EVMOnRamp { + contractsByChain[chain] = append(contractsByChain[chain], onRamp.Address()) + } + } + if state.Chains[chain].EVM2EVMOffRamp != nil { + for _, offRamp := range state.Chains[chain].EVM2EVMOffRamp { + contractsByChain[chain] = append(contractsByChain[chain], offRamp.Address()) + } + } + } + + e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, e.TimelockContracts(t), []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.TransferToMCMSWithTimelock), + Config: commonchangeset.TransferToMCMSWithTimelockConfig{ + ContractsByChain: contractsByChain, + MinDelay: 0, + }, + }, + }) + require.NoError(t, err) + // add 1.6 contracts to the environment and send 1.6 jobs + // First we need to deploy Homechain contracts and restart the nodes with updated cap registry + // in this test we have already deployed home chain contracts and the nodes are already running with the deployed cap registry. + e = testhelpers.AddCCIPContractsToEnvironment(t, e.Env.AllChainSelectors(), tEnv, true, true, false) + // Set RMNProxy to point to RMNRemote. + // nonce manager should point to 1.5 ramps + e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, e.TimelockContracts(t), []commonchangeset.ChangesetApplication{ + { + // as we have already transferred ownership for RMNProxy to MCMS, it needs to be done via MCMS proposal + Changeset: commonchangeset.WrapChangeSet(changeset.SetRMNRemoteOnRMNProxyChangeset), + Config: changeset.SetRMNRemoteOnRMNProxyConfig{ + ChainSelectors: e.Env.AllChainSelectors(), + MCMSConfig: &changeset.MCMSConfig{ + MinDelay: 0, + }, + }, + }, + { + Changeset: commonchangeset.WrapChangeSet(changeset.UpdateNonceManagersChangeset), + Config: changeset.UpdateNonceManagerConfig{ + // we only have lanes between src1 --> dest + UpdatesByChain: map[uint64]changeset.NonceManagerUpdate{ + src1: { + PreviousRampsArgs: []changeset.PreviousRampCfg{ + { + RemoteChainSelector: dest, + EnableOnRamp: true, + }, + }, + }, + src2: { + PreviousRampsArgs: []changeset.PreviousRampCfg{ + { + RemoteChainSelector: dest, + EnableOnRamp: true, + }, + }, + }, + dest: { + PreviousRampsArgs: []changeset.PreviousRampCfg{ + { + RemoteChainSelector: src1, + EnableOffRamp: true, + }, + { + RemoteChainSelector: src2, + EnableOffRamp: true, + }, + }, + }, + }, + }, + }, + }) + require.NoError(t, err) + state, err = changeset.LoadOnchainState(e.Env) + require.NoError(t, err) + + // Enable a single 1.6 lane with test router + testhelpers.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &e, state, src1, dest, true) + require.GreaterOrEqual(t, len(e.Users[src1]), 2) + testhelpers.ReplayLogs(t, e.Env.Offchain, e.ReplayBlocks) + startBlocks := make(map[uint64]*uint64) + latesthdr, err := e.Env.Chains[dest].Client.HeaderByNumber(testcontext.Get(t), nil) + require.NoError(t, err) + block := latesthdr.Number.Uint64() + startBlocks[dest] = &block + expectedSeqNumExec := make(map[testhelpers.SourceDestPair][]uint64) + expectedSeqNums := make(map[testhelpers.SourceDestPair]uint64) + msgSentEvent, err := testhelpers.DoSendRequest( + t, e.Env, state, + testhelpers.WithSourceChain(src1), + testhelpers.WithDestChain(dest), + testhelpers.WithTestRouter(true), + // Send traffic across single 1.6 lane with a DIFFERENT ( very important to not mess with real sender nonce) sender + // from test router to ensure 1.6 is working. + testhelpers.WithSender(e.Users[src1][1]), + testhelpers.WithEvm2AnyMessage(router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(state.Chains[dest].Receiver.Address().Bytes(), 32), + Data: []byte("hello"), + TokenAmounts: nil, + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: nil, + })) + require.NoError(t, err) + + expectedSeqNumExec[testhelpers.SourceDestPair{ + SourceChainSelector: src1, + DestChainSelector: dest, + }] = []uint64{msgSentEvent.SequenceNumber} + expectedSeqNums[testhelpers.SourceDestPair{ + SourceChainSelector: src1, + DestChainSelector: dest, + }] = msgSentEvent.SequenceNumber + + // This sleep is needed so that plugins come up and start indexing logs. + // Otherwise test will flake. + time.Sleep(15 * time.Second) + testhelpers.ReplayLogs(t, e.Env.Offchain, map[uint64]uint64{ + src1: msgSentEvent.Raw.BlockNumber, + }) + testhelpers.ConfirmCommitForAllWithExpectedSeqNums(t, e.Env, state, expectedSeqNums, startBlocks) + testhelpers.ConfirmExecWithSeqNrsForAll(t, e.Env, state, expectedSeqNumExec, startBlocks) + + // send a message from real router, the send requested event should be received in 1.5 onRamp + // the request should get delivered to 1.5 offRamp + sentEventBeforeSwitch, err := v1_5testhelpers.SendRequest(t, e.Env, state, + testhelpers.WithSourceChain(src1), + testhelpers.WithDestChain(dest), + testhelpers.WithTestRouter(false), + testhelpers.WithEvm2AnyMessage(router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(state.Chains[dest].Receiver.Address().Bytes(), 32), + Data: []byte("hello"), + TokenAmounts: nil, + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: nil, + }), + ) + require.NoError(t, err) + require.NotNil(t, sentEventBeforeSwitch) + + // now that the 1.6 lane is working, we can enable the real router + e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, e.TimelockContracts(t), []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(changeset.UpdateOnRampsDestsChangeset), + Config: changeset.UpdateOnRampDestsConfig{ + UpdatesByChain: map[uint64]map[uint64]changeset.OnRampDestinationUpdate{ + src1: { + dest: { + IsEnabled: true, + TestRouter: false, + AllowListEnabled: false, + }, + }, + }, + }, + }, + { + Changeset: commonchangeset.WrapChangeSet(changeset.UpdateOffRampSourcesChangeset), + Config: changeset.UpdateOffRampSourcesConfig{ + UpdatesByChain: map[uint64]map[uint64]changeset.OffRampSourceUpdate{ + dest: { + src1: { + IsEnabled: true, + TestRouter: false, + }, + }, + }, + }, + }, + { + // this needs to be MCMS proposal as the router contract is owned by MCMS + Changeset: commonchangeset.WrapChangeSet(changeset.UpdateRouterRampsChangeset), + Config: changeset.UpdateRouterRampsConfig{ + TestRouter: false, + MCMS: &changeset.MCMSConfig{ + MinDelay: 0, + }, + UpdatesByChain: map[uint64]changeset.RouterUpdates{ + // onRamp update on source chain + src1: { + OnRampUpdates: map[uint64]bool{ + dest: true, + }, + }, + // offramp update on dest chain + dest: { + OffRampUpdates: map[uint64]bool{ + src1: true, + }, + }, + }, + }, + }, + }) + require.NoError(t, err) + + // send a message from real router the send requested event should be received in 1.6 onRamp + // the request should get delivered to 1.6 offRamp + destStartBlock, err := e.Env.Chains[dest].Client.HeaderByNumber(context.Background(), nil) + require.NoError(t, err) + sentEventAfterSwitch, err := testhelpers.DoSendRequest( + t, e.Env, state, + testhelpers.WithSourceChain(src1), + testhelpers.WithDestChain(dest), + testhelpers.WithTestRouter(false), + testhelpers.WithEvm2AnyMessage(router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(state.Chains[dest].Receiver.Address().Bytes(), 32), + Data: []byte("hello"), + TokenAmounts: nil, + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: nil, + })) + require.NoError(t, err) + // verify that before switch message is received in 1.5 offRamp + v1_5testhelpers.WaitForExecute(t, e.Env.Chains[src1], e.Env.Chains[dest], state.Chains[dest].EVM2EVMOffRamp[src1], + []uint64{sentEventBeforeSwitch.Message.SequenceNumber}, destStartBlock.Number.Uint64()) + + // verify that after switch message is received in 1.6 offRamp + expectedSeqNumExec[testhelpers.SourceDestPair{ + SourceChainSelector: src1, + DestChainSelector: dest, + }] = []uint64{sentEventAfterSwitch.SequenceNumber} + testhelpers.ConfirmExecWithSeqNrsForAll(t, e.Env, state, expectedSeqNumExec, startBlocks) + + // confirm that the other lane src2->dest is still working with v1.5 + sentEventOnOtherLane, err := v1_5testhelpers.SendRequest(t, e.Env, state, + testhelpers.WithSourceChain(src2), + testhelpers.WithDestChain(dest), + testhelpers.WithTestRouter(false), + testhelpers.WithEvm2AnyMessage(router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(state.Chains[dest].Receiver.Address().Bytes(), 32), + Data: []byte("hello"), + TokenAmounts: nil, + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: nil, + }), + ) + require.NoError(t, err) + require.NotNil(t, sentEventOnOtherLane) + v1_5testhelpers.WaitForExecute(t, e.Env.Chains[src2], e.Env.Chains[dest], state.Chains[dest].EVM2EVMOffRamp[src2], + []uint64{sentEventOnOtherLane.Message.SequenceNumber}, destStartBlock.Number.Uint64()) +} diff --git a/integration-tests/smoke/ccip/ccip_ooo_execution_test.go b/integration-tests/smoke/ccip/ccip_ooo_execution_test.go index 19c36c6e021..6a68ecd9e30 100644 --- a/integration-tests/smoke/ccip/ccip_ooo_execution_test.go +++ b/integration-tests/smoke/ccip/ccip_ooo_execution_test.go @@ -1,4 +1,4 @@ -package smoke +package ccip import ( "fmt" @@ -15,6 +15,7 @@ import ( "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" @@ -33,11 +34,11 @@ import ( func Test_OutOfOrderExecution(t *testing.T) { lggr := logger.TestLogger(t) ctx := tests.Context(t) - tenv, _ := testsetups.NewIntegrationEnvironment( + tenv, _, _ := testsetups.NewIntegrationEnvironment( t, - changeset.WithUSDC(), - changeset.WithUSDCAttestationMissing(), - changeset.WithUsersPerChain(2), + testhelpers.WithUSDC(), + testhelpers.WithUSDCAttestationMissing(), + testhelpers.WithNumOfUsersPerChain(2), ) e := tenv.Env @@ -54,7 +55,7 @@ func Test_OutOfOrderExecution(t *testing.T) { oneE18 := new(big.Int).SetUint64(1e18) - srcToken, _, destToken, _, err := changeset.DeployTransferableToken( + srcToken, _, destToken, _, err := testhelpers.DeployTransferableToken( lggr, tenv.Env.Chains, sourceChain, @@ -67,26 +68,26 @@ func Test_OutOfOrderExecution(t *testing.T) { ) require.NoError(t, err) - srcUSDC, destUSDC, err := changeset.ConfigureUSDCTokenPools(lggr, e.Chains, sourceChain, destChain, state) + srcUSDC, destUSDC, err := testhelpers.ConfigureUSDCTokenPools(lggr, e.Chains, sourceChain, destChain, state) require.NoError(t, err) - err = changeset.UpdateFeeQuoterForUSDC(lggr, e.Chains[sourceChain], state.Chains[sourceChain], destChain, srcUSDC) + err = testhelpers.UpdateFeeQuoterForUSDC(lggr, e.Chains[sourceChain], state.Chains[sourceChain], destChain, srcUSDC) require.NoError(t, err) - err = changeset.UpdateFeeQuoterForUSDC(lggr, e.Chains[destChain], state.Chains[destChain], sourceChain, destUSDC) + err = testhelpers.UpdateFeeQuoterForUSDC(lggr, e.Chains[destChain], state.Chains[destChain], sourceChain, destUSDC) require.NoError(t, err) - changeset.MintAndAllow( + testhelpers.MintAndAllow( t, e, state, - map[uint64][]changeset.MintTokenInfo{ + map[uint64][]testhelpers.MintTokenInfo{ sourceChain: { - changeset.NewMintTokenInfo(ownerSourceChain, srcToken, srcUSDC), - changeset.NewMintTokenWithCustomSender(ownerSourceChain, anotherSender, srcToken), + testhelpers.NewMintTokenInfo(ownerSourceChain, srcToken, srcUSDC), + testhelpers.NewMintTokenWithCustomSender(ownerSourceChain, anotherSender, srcToken), }, }, ) - require.NoError(t, changeset.AddLanesForAll(e, state)) + testhelpers.AddLanesForAll(t, &tenv, state) tokenTransfer := []router.ClientEVMTokenAmount{ { @@ -101,7 +102,7 @@ func Test_OutOfOrderExecution(t *testing.T) { }, } - identifier := changeset.SourceDestPair{ + identifier := testhelpers.SourceDestPair{ SourceChainSelector: sourceChain, DestChainSelector: destChain, } @@ -116,7 +117,7 @@ func Test_OutOfOrderExecution(t *testing.T) { // Out of order execution to the EOA should be properly executed firstReceiver := utils.RandomAddress() - firstMessage, _ := changeset.Transfer( + firstMessage, _ := testhelpers.Transfer( ctx, t, e, @@ -126,16 +127,16 @@ func Test_OutOfOrderExecution(t *testing.T) { tokenTransfer, firstReceiver, nil, - changeset.MakeEVMExtraArgsV2(0, true), + testhelpers.MakeEVMExtraArgsV2(0, true), ) - expectedStatuses[firstMessage.SequenceNumber] = changeset.EXECUTION_STATE_SUCCESS + expectedStatuses[firstMessage.SequenceNumber] = testhelpers.EXECUTION_STATE_SUCCESS t.Logf("Out of order messages sent from chain %d to chain %d with sequence number %d", sourceChain, destChain, firstMessage.SequenceNumber, ) // Ordered execution should fail because attestation is not present secondReceiver := utils.RandomAddress() - secondMsg, _ := changeset.Transfer( + secondMsg, _ := testhelpers.Transfer( ctx, t, e, @@ -153,7 +154,7 @@ func Test_OutOfOrderExecution(t *testing.T) { // Ordered token transfer should fail, because previous message cannot be executed thirdReceiver := utils.RandomAddress() - thirdMessage, _ := changeset.Transfer( + thirdMessage, _ := testhelpers.Transfer( ctx, t, e, @@ -163,7 +164,7 @@ func Test_OutOfOrderExecution(t *testing.T) { tokenTransfer, thirdReceiver, nil, - changeset.MakeEVMExtraArgsV2(0, false), + testhelpers.MakeEVMExtraArgsV2(0, false), ) t.Logf("Ordered token transfer from chain %d to chain %d with sequence number %d", sourceChain, destChain, thirdMessage.SequenceNumber, @@ -171,7 +172,7 @@ func Test_OutOfOrderExecution(t *testing.T) { // Out of order programmable token transfer should be executed fourthReceiver := state.Chains[destChain].Receiver.Address() - fourthMessage, _ := changeset.Transfer( + fourthMessage, _ := testhelpers.Transfer( ctx, t, e, @@ -181,34 +182,34 @@ func Test_OutOfOrderExecution(t *testing.T) { tokenTransfer, fourthReceiver, []byte("this message has enough gas to execute"), - changeset.MakeEVMExtraArgsV2(300_000, true), + testhelpers.MakeEVMExtraArgsV2(300_000, true), ) - expectedStatuses[fourthMessage.SequenceNumber] = changeset.EXECUTION_STATE_SUCCESS + expectedStatuses[fourthMessage.SequenceNumber] = testhelpers.EXECUTION_STATE_SUCCESS t.Logf("Out of order programmable token transfer from chain %d to chain %d with sequence number %d", sourceChain, destChain, fourthMessage.SequenceNumber, ) // Ordered token transfer, but using different sender, should be executed fifthReceiver := utils.RandomAddress() - fifthMessage, err := changeset.DoSendRequest(t, e, state, - changeset.WithSender(anotherSender), - changeset.WithSourceChain(sourceChain), - changeset.WithDestChain(destChain), - changeset.WithEvm2AnyMessage(router.ClientEVM2AnyMessage{ + fifthMessage, err := testhelpers.DoSendRequest(t, e, state, + testhelpers.WithSender(anotherSender), + testhelpers.WithSourceChain(sourceChain), + testhelpers.WithDestChain(destChain), + testhelpers.WithEvm2AnyMessage(router.ClientEVM2AnyMessage{ Receiver: common.LeftPadBytes(fifthReceiver.Bytes(), 32), Data: nil, TokenAmounts: tokenTransfer, FeeToken: common.HexToAddress("0x0"), - ExtraArgs: changeset.MakeEVMExtraArgsV2(0, false), + ExtraArgs: testhelpers.MakeEVMExtraArgsV2(0, false), })) require.NoError(t, err) - expectedStatuses[fifthMessage.SequenceNumber] = changeset.EXECUTION_STATE_SUCCESS + expectedStatuses[fifthMessage.SequenceNumber] = testhelpers.EXECUTION_STATE_SUCCESS t.Logf("Ordered message send by %v from chain %d to chain %d with sequence number %d", anotherSender.From, sourceChain, destChain, fifthMessage.SequenceNumber, ) // All messages are committed, even these which are going to be reverted during the exec - _, err = changeset.ConfirmCommitWithExpectedSeqNumRange( + _, err = testhelpers.ConfirmCommitWithExpectedSeqNumRange( t, e.Chains[sourceChain], e.Chains[destChain], @@ -223,11 +224,11 @@ func Test_OutOfOrderExecution(t *testing.T) { ) require.NoError(t, err) - execStates := changeset.ConfirmExecWithSeqNrsForAll( + execStates := testhelpers.ConfirmExecWithSeqNrsForAll( t, e, state, - map[changeset.SourceDestPair][]uint64{ + map[testhelpers.SourceDestPair][]uint64{ identifier: { firstMessage.SequenceNumber, fourthMessage.SequenceNumber, @@ -240,21 +241,21 @@ func Test_OutOfOrderExecution(t *testing.T) { secondMsgState, err := state.Chains[destChain].OffRamp.GetExecutionState(&bind.CallOpts{Context: ctx}, sourceChain, secondMsg.SequenceNumber) require.NoError(t, err) - require.Equal(t, uint8(changeset.EXECUTION_STATE_UNTOUCHED), secondMsgState) + require.Equal(t, uint8(testhelpers.EXECUTION_STATE_UNTOUCHED), secondMsgState) thirdMsgState, err := state.Chains[destChain].OffRamp.GetExecutionState(&bind.CallOpts{Context: ctx}, sourceChain, thirdMessage.SequenceNumber) require.NoError(t, err) - require.Equal(t, uint8(changeset.EXECUTION_STATE_UNTOUCHED), thirdMsgState) + require.Equal(t, uint8(testhelpers.EXECUTION_STATE_UNTOUCHED), thirdMsgState) - changeset.WaitForTheTokenBalance(ctx, t, destToken.Address(), firstReceiver, e.Chains[destChain], oneE18) - changeset.WaitForTheTokenBalance(ctx, t, destUSDC.Address(), secondReceiver, e.Chains[destChain], big.NewInt(0)) - changeset.WaitForTheTokenBalance(ctx, t, destToken.Address(), thirdReceiver, e.Chains[destChain], big.NewInt(0)) - changeset.WaitForTheTokenBalance(ctx, t, destToken.Address(), fourthReceiver, e.Chains[destChain], oneE18) - changeset.WaitForTheTokenBalance(ctx, t, destToken.Address(), fifthReceiver, e.Chains[destChain], oneE18) + testhelpers.WaitForTheTokenBalance(ctx, t, destToken.Address(), firstReceiver, e.Chains[destChain], oneE18) + testhelpers.WaitForTheTokenBalance(ctx, t, destUSDC.Address(), secondReceiver, e.Chains[destChain], big.NewInt(0)) + testhelpers.WaitForTheTokenBalance(ctx, t, destToken.Address(), thirdReceiver, e.Chains[destChain], big.NewInt(0)) + testhelpers.WaitForTheTokenBalance(ctx, t, destToken.Address(), fourthReceiver, e.Chains[destChain], oneE18) + testhelpers.WaitForTheTokenBalance(ctx, t, destToken.Address(), fifthReceiver, e.Chains[destChain], oneE18) } func pickFirstAvailableUser( - tenv changeset.DeployedEnv, + tenv testhelpers.DeployedEnv, sourceChain uint64, e deployment.Environment, ) (*bind.TransactOpts, error) { diff --git a/integration-tests/contracts/ccipreader_test.go b/integration-tests/smoke/ccip/ccip_reader_test.go similarity index 95% rename from integration-tests/contracts/ccipreader_test.go rename to integration-tests/smoke/ccip/ccip_reader_test.go index 3b0ac1d79a1..4345bd4d894 100644 --- a/integration-tests/contracts/ccipreader_test.go +++ b/integration-tests/smoke/ccip/ccip_reader_test.go @@ -1,4 +1,4 @@ -package contracts +package ccip import ( "context" @@ -18,6 +18,8 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" "github.com/smartcontractkit/chainlink-ccip/plugintypes" @@ -289,6 +291,7 @@ func TestCCIPReader_GetOffRampConfigDigest(t *testing.T) { nil, chainD, addr.Bytes(), + ccipevm.NewExtraArgsCodec(), ) ccipReaderCommitDigest, err := reader.GetOffRampConfigDigest(ctx, consts.PluginTypeCommit) @@ -581,24 +584,24 @@ func TestCCIPReader_NextSeqNum(t *testing.T) { seqNums, err := s.reader.NextSeqNum(ctx, []cciptypes.ChainSelector{chainS1, chainS2, chainS3}) require.NoError(t, err) assert.Len(t, seqNums, 3) - assert.Equal(t, cciptypes.SeqNum(10), seqNums[0]) - assert.Equal(t, cciptypes.SeqNum(20), seqNums[1]) - assert.Equal(t, cciptypes.SeqNum(30), seqNums[2]) + assert.Equal(t, cciptypes.SeqNum(10), seqNums[chainS1]) + assert.Equal(t, cciptypes.SeqNum(20), seqNums[chainS2]) + assert.Equal(t, cciptypes.SeqNum(30), seqNums[chainS3]) } func TestCCIPReader_GetExpectedNextSequenceNumber(t *testing.T) { t.Parallel() ctx := tests.Context(t) //env := NewMemoryEnvironmentContractsOnly(t, logger.TestLogger(t), 2, 4, nil) - env := changeset.NewMemoryEnvironment(t) + env, _ := testhelpers.NewMemoryEnvironment(t) state, err := changeset.LoadOnchainState(env.Env) require.NoError(t, err) selectors := env.Env.AllChainSelectors() destChain, srcChain := selectors[0], selectors[1] - require.NoError(t, changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(env.Env, state, destChain, srcChain, false)) - require.NoError(t, changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(env.Env, state, srcChain, destChain, false)) + testhelpers.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &env, state, destChain, srcChain, false) + testhelpers.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &env, state, srcChain, destChain, false) reader := testSetupRealContracts( ctx, @@ -619,8 +622,8 @@ func TestCCIPReader_GetExpectedNextSequenceNumber(t *testing.T) { maxExpectedSeqNum := uint64(10) var i uint64 for i = 1; i < maxExpectedSeqNum; i++ { - msg := changeset.DefaultRouterMessage(state.Chains[destChain].Receiver.Address()) - msgSentEvent := changeset.TestSendRequest(t, env.Env, state, srcChain, destChain, false, msg) + msg := testhelpers.DefaultRouterMessage(state.Chains[destChain].Receiver.Address()) + msgSentEvent := testhelpers.TestSendRequest(t, env.Env, state, srcChain, destChain, false, msg) require.Equal(t, uint64(i), msgSentEvent.SequenceNumber) require.Equal(t, uint64(i), msgSentEvent.Message.Header.Nonce) // check outbound nonce incremented seqNum, err2 := reader.GetExpectedNextSequenceNumber(ctx, cs(srcChain), cs(destChain)) @@ -700,15 +703,15 @@ func TestCCIPReader_Nonces(t *testing.T) { func Test_GetChainFeePriceUpdates(t *testing.T) { t.Parallel() ctx := tests.Context(t) - env := changeset.NewMemoryEnvironment(t) + env, _ := testhelpers.NewMemoryEnvironment(t) state, err := changeset.LoadOnchainState(env.Env) require.NoError(t, err) selectors := env.Env.AllChainSelectors() chain1, chain2 := selectors[0], selectors[1] - require.NoError(t, changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(env.Env, state, chain1, chain2, false)) - require.NoError(t, changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(env.Env, state, chain2, chain1, false)) + testhelpers.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &env, state, chain1, chain2, false) + testhelpers.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &env, state, chain2, chain1, false) // Change the gas price for chain2 feeQuoter := state.Chains[chain1].FeeQuoter @@ -756,15 +759,15 @@ func Test_GetChainFeePriceUpdates(t *testing.T) { func Test_LinkPriceUSD(t *testing.T) { t.Parallel() ctx := tests.Context(t) - env := changeset.NewMemoryEnvironment(t) + env, _ := testhelpers.NewMemoryEnvironment(t) state, err := changeset.LoadOnchainState(env.Env) require.NoError(t, err) selectors := env.Env.AllChainSelectors() chain1, chain2 := selectors[0], selectors[1] - require.NoError(t, changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(env.Env, state, chain1, chain2, false)) - require.NoError(t, changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(env.Env, state, chain2, chain1, false)) + testhelpers.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &env, state, chain1, chain2, false) + testhelpers.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &env, state, chain2, chain1, false) reader := testSetupRealContracts( ctx, @@ -785,22 +788,22 @@ func Test_LinkPriceUSD(t *testing.T) { linkPriceUSD, err := reader.LinkPriceUSD(ctx) require.NoError(t, err) require.NotNil(t, linkPriceUSD.Int) - require.Equal(t, changeset.DefaultInitialPrices.LinkPrice, linkPriceUSD.Int) + require.Equal(t, testhelpers.DefaultLinkPrice, linkPriceUSD.Int) } func Test_GetMedianDataAvailabilityGasConfig(t *testing.T) { t.Parallel() ctx := tests.Context(t) - env := changeset.NewMemoryEnvironment(t, changeset.WithChains(4)) + env, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithNumOfChains(4)) state, err := changeset.LoadOnchainState(env.Env) require.NoError(t, err) selectors := env.Env.AllChainSelectors() destChain, chain1, chain2, chain3 := selectors[0], selectors[1], selectors[2], selectors[3] - require.NoError(t, changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(env.Env, state, chain1, destChain, false)) - require.NoError(t, changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(env.Env, state, chain2, destChain, false)) - require.NoError(t, changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(env.Env, state, chain3, destChain, false)) + testhelpers.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &env, state, chain1, destChain, false) + testhelpers.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &env, state, chain2, destChain, false) + testhelpers.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &env, state, chain3, destChain, false) boundContracts := map[cciptypes.ChainSelector][]types.BoundContract{} for i, selector := range env.Env.AllChainSelectorsExcluding([]uint64{destChain}) { @@ -850,15 +853,15 @@ func Test_GetMedianDataAvailabilityGasConfig(t *testing.T) { func Test_GetWrappedNativeTokenPriceUSD(t *testing.T) { t.Parallel() ctx := tests.Context(t) - env := changeset.NewMemoryEnvironment(t) + env, _ := testhelpers.NewMemoryEnvironment(t) state, err := changeset.LoadOnchainState(env.Env) require.NoError(t, err) selectors := env.Env.AllChainSelectors() chain1, chain2 := selectors[0], selectors[1] - require.NoError(t, changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(env.Env, state, chain1, chain2, false)) - require.NoError(t, changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(env.Env, state, chain2, chain1, false)) + testhelpers.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &env, state, chain1, chain2, false) + testhelpers.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &env, state, chain2, chain1, false) reader := testSetupRealContracts( ctx, @@ -884,7 +887,7 @@ func Test_GetWrappedNativeTokenPriceUSD(t *testing.T) { // Only chainD has reader contracts bound require.Len(t, prices, 1) - require.Equal(t, changeset.DefaultInitialPrices.WethPrice, prices[cciptypes.ChainSelector(chain1)].Int) + require.Equal(t, testhelpers.DefaultWethPrice, prices[cciptypes.ChainSelector(chain1)].Int) } // Benchmark Results: @@ -1341,7 +1344,7 @@ func testSetupRealContracts( destChain uint64, toBindContracts map[cciptypes.ChainSelector][]types.BoundContract, toMockBindings map[cciptypes.ChainSelector][]types.BoundContract, - env changeset.DeployedEnv, + env testhelpers.DeployedEnv, ) ccipreaderpkg.CCIPReader { db := pgtest.NewSqlxDB(t) lpOpts := logpoller.Opts{ @@ -1408,7 +1411,8 @@ func testSetupRealContracts( contractReaders[chain] = cr } contractWriters := make(map[cciptypes.ChainSelector]types.ContractWriter) - reader := ccipreaderpkg.NewCCIPReaderWithExtendedContractReaders(ctx, lggr, contractReaders, contractWriters, cciptypes.ChainSelector(destChain), nil) + edc := ccipevm.NewExtraArgsCodec() + reader := ccipreaderpkg.NewCCIPReaderWithExtendedContractReaders(ctx, lggr, contractReaders, contractWriters, cciptypes.ChainSelector(destChain), nil, edc) return reader } @@ -1523,7 +1527,8 @@ func testSetup( contractReaders[chain] = cr } contractWriters := make(map[cciptypes.ChainSelector]types.ContractWriter) - reader := ccipreaderpkg.NewCCIPReaderWithExtendedContractReaders(ctx, lggr, contractReaders, contractWriters, params.DestChain, nil) + edc := ccipevm.NewExtraArgsCodec() + reader := ccipreaderpkg.NewCCIPReaderWithExtendedContractReaders(ctx, lggr, contractReaders, contractWriters, params.DestChain, nil, edc) t.Cleanup(func() { require.NoError(t, cr.Close()) diff --git a/integration-tests/smoke/ccip/ccip_rmn_test.go b/integration-tests/smoke/ccip/ccip_rmn_test.go index 166f4422fe6..9a33abc844d 100644 --- a/integration-tests/smoke/ccip/ccip_rmn_test.go +++ b/integration-tests/smoke/ccip/ccip_rmn_test.go @@ -1,11 +1,9 @@ -package smoke +package ccip import ( "context" - "encoding/binary" "errors" "math/big" - "os" "slices" "strconv" "strings" @@ -17,17 +15,16 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/rs/zerolog" "github.com/stretchr/testify/require" + "golang.org/x/sync/errgroup" "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/osutil" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" - "github.com/smartcontractkit/chainlink-ccip/pkg/reader" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/environment/devenv" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_remote" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" @@ -241,14 +238,13 @@ const ( ) func runRmnTestCase(t *testing.T, tc rmnTestCase) { - require.NoError(t, os.Setenv("ENABLE_RMN", "true")) require.NoError(t, tc.validate()) ctx := testcontext.Get(t) t.Logf("Running RMN test case: %s", tc.name) - envWithRMN, rmnCluster := testsetups.NewIntegrationEnvironment(t, - changeset.WithRMNEnabled(len(tc.rmnNodes)), + envWithRMN, rmnCluster, _ := testsetups.NewIntegrationEnvironment(t, + testhelpers.WithRMNEnabled(len(tc.rmnNodes)), ) t.Logf("envWithRmn: %#v", envWithRMN) @@ -275,7 +271,7 @@ func runRmnTestCase(t *testing.T, tc rmnTestCase) { candidateDigest, err := homeChainState.RMNHome.GetCandidateDigest(&bind.CallOpts{Context: ctx}) require.NoError(t, err) - _, err = changeset.NewSetRMNHomeCandidateConfigChangeset(envWithRMN.Env, changeset.SetRMNHomeCandidateConfig{ + _, err = changeset.SetRMNHomeCandidateConfigChangeset(envWithRMN.Env, changeset.SetRMNHomeCandidateConfig{ HomeChainSelector: envWithRMN.HomeChainSel, RMNStaticConfig: staticConfig, RMNDynamicConfig: dynamicConfig, @@ -289,7 +285,7 @@ func runRmnTestCase(t *testing.T, tc rmnTestCase) { t.Logf("RMNHome candidateDigest after setting new candidate: %x", candidateDigest[:]) t.Logf("Promoting RMNHome candidate with candidateDigest: %x", candidateDigest[:]) - _, err = changeset.NewPromoteCandidateConfigChangeset(envWithRMN.Env, changeset.PromoteRMNHomeCandidateConfig{ + _, err = changeset.PromoteRMNHomeCandidateConfigChangeset(envWithRMN.Env, changeset.PromoteRMNHomeCandidateConfig{ HomeChainSelector: envWithRMN.HomeChainSel, DigestToPromote: candidateDigest, }) @@ -314,7 +310,7 @@ func runRmnTestCase(t *testing.T, tc rmnTestCase) { } } - _, err = changeset.NewSetRMNRemoteConfigChangeset(envWithRMN.Env, changeset.SetRMNRemoteConfig{ + _, err = changeset.SetRMNRemoteConfigChangeset(envWithRMN.Env, changeset.SetRMNRemoteConfig{ HomeChainSelector: envWithRMN.HomeChainSel, RMNRemoteConfigs: rmnRemoteConfig, }) @@ -322,19 +318,20 @@ func runRmnTestCase(t *testing.T, tc rmnTestCase) { tc.killMarkedRmnNodes(t, rmnCluster) - changeset.ReplayLogs(t, envWithRMN.Env.Offchain, envWithRMN.ReplayBlocks) - require.NoError(t, changeset.AddLanesForAll(envWithRMN.Env, onChainState)) + testhelpers.ReplayLogs(t, envWithRMN.Env.Offchain, envWithRMN.ReplayBlocks) + testhelpers.AddLanesForAll(t, &envWithRMN, onChainState) disabledNodes := tc.disableOraclesIfThisIsACursingTestCase(ctx, t, envWithRMN) startBlocks, seqNumCommit, seqNumExec := tc.sendMessages(t, onChainState, envWithRMN) t.Logf("Sent all messages, seqNumCommit: %v seqNumExec: %v", seqNumCommit, seqNumExec) + eg := errgroup.Group{} tc.callContractsToCurseChains(ctx, t, onChainState, envWithRMN) - tc.callContractsToCurseAndRevokeCurse(ctx, t, onChainState, envWithRMN) + tc.callContractsToCurseAndRevokeCurse(ctx, &eg, t, onChainState, envWithRMN) tc.enableOracles(ctx, t, envWithRMN, disabledNodes) - expectedSeqNum := make(map[changeset.SourceDestPair]uint64) + expectedSeqNum := make(map[testhelpers.SourceDestPair]uint64) for k, v := range seqNumCommit { cursedSubjectsOfDest, exists := tc.pf.cursedSubjectsPerChainSel[k.DestChainSelector] shouldSkip := exists && (slices.Contains(cursedSubjectsOfDest, globalCurse) || @@ -356,13 +353,13 @@ func runRmnTestCase(t *testing.T, tc rmnTestCase) { commitReportReceived := make(chan struct{}) go func() { if len(expectedSeqNum) > 0 { - changeset.ConfirmCommitForAllWithExpectedSeqNums(t, envWithRMN.Env, onChainState, expectedSeqNum, startBlocks) + testhelpers.ConfirmCommitForAllWithExpectedSeqNums(t, envWithRMN.Env, onChainState, expectedSeqNum, startBlocks) commitReportReceived <- struct{}{} } if len(seqNumCommit) > 0 && len(seqNumCommit) > len(expectedSeqNum) { // wait for a duration and assert that commit reports were not delivered for cursed source chains - changeset.ConfirmCommitForAllWithExpectedSeqNums(t, envWithRMN.Env, onChainState, seqNumCommit, startBlocks) + testhelpers.ConfirmCommitForAllWithExpectedSeqNums(t, envWithRMN.Env, onChainState, seqNumCommit, startBlocks) commitReportReceived <- struct{}{} } }() @@ -390,9 +387,11 @@ func runRmnTestCase(t *testing.T, tc rmnTestCase) { <-commitReportReceived // wait for commit reports t.Logf("✅ Commit report") + require.NoError(t, eg.Wait()) + if tc.waitForExec { t.Logf("⌛ Waiting for exec reports...") - changeset.ConfirmExecWithSeqNrsForAll(t, envWithRMN.Env, onChainState, seqNumExec, startBlocks) + testhelpers.ConfirmExecWithSeqNrsForAll(t, envWithRMN.Env, onChainState, seqNumExec, startBlocks) t.Logf("✅ Exec report") } } @@ -464,7 +463,7 @@ type testCasePopulatedFields struct { revokedCursedSubjectsPerChainSel map[uint64]map[uint64]time.Duration } -func (tc *rmnTestCase) populateFields(t *testing.T, envWithRMN changeset.DeployedEnv, rmnCluster devenv.RMNCluster) { +func (tc *rmnTestCase) populateFields(t *testing.T, envWithRMN testhelpers.DeployedEnv, rmnCluster devenv.RMNCluster) { require.GreaterOrEqual(t, len(envWithRMN.Env.Chains), 2, "test assumes at least two chains") for _, chain := range envWithRMN.Env.Chains { tc.pf.chainSelectors = append(tc.pf.chainSelectors, chain.Selector) @@ -499,7 +498,7 @@ func (tc *rmnTestCase) populateFields(t *testing.T, envWithRMN changeset.Deploye // configure remote chain details on the home contract tc.pf.rmnHomeSourceChains = append(tc.pf.rmnHomeSourceChains, rmn_home.RMNHomeSourceChain{ ChainSelector: tc.pf.chainSelectors[remoteChainIdx], - F: uint64(remoteF), + FObserve: uint64(remoteF), ObserverNodesBitmap: createObserverNodesBitmap(tc.pf.chainSelectors[remoteChainIdx], tc.rmnNodes, tc.pf.chainSelectors), }) } @@ -553,7 +552,7 @@ func (tc rmnTestCase) killMarkedRmnNodes(t *testing.T, rmnCluster devenv.RMNClus } } -func (tc rmnTestCase) disableOraclesIfThisIsACursingTestCase(ctx context.Context, t *testing.T, envWithRMN changeset.DeployedEnv) []string { +func (tc rmnTestCase) disableOraclesIfThisIsACursingTestCase(ctx context.Context, t *testing.T, envWithRMN testhelpers.DeployedEnv) []string { disabledNodes := make([]string, 0) if len(tc.cursedSubjectsPerChain) > 0 { @@ -574,28 +573,28 @@ func (tc rmnTestCase) disableOraclesIfThisIsACursingTestCase(ctx context.Context return disabledNodes } -func (tc rmnTestCase) sendMessages(t *testing.T, onChainState changeset.CCIPOnChainState, envWithRMN changeset.DeployedEnv) (map[uint64]*uint64, map[changeset.SourceDestPair]uint64, map[changeset.SourceDestPair][]uint64) { +func (tc rmnTestCase) sendMessages(t *testing.T, onChainState changeset.CCIPOnChainState, envWithRMN testhelpers.DeployedEnv) (map[uint64]*uint64, map[testhelpers.SourceDestPair]uint64, map[testhelpers.SourceDestPair][]uint64) { startBlocks := make(map[uint64]*uint64) - seqNumCommit := make(map[changeset.SourceDestPair]uint64) - seqNumExec := make(map[changeset.SourceDestPair][]uint64) + seqNumCommit := make(map[testhelpers.SourceDestPair]uint64) + seqNumExec := make(map[testhelpers.SourceDestPair][]uint64) for _, msg := range tc.messagesToSend { fromChain := tc.pf.chainSelectors[msg.fromChainIdx] toChain := tc.pf.chainSelectors[msg.toChainIdx] for i := 0; i < msg.count; i++ { - msgSentEvent := changeset.TestSendRequest(t, envWithRMN.Env, onChainState, fromChain, toChain, false, router.ClientEVM2AnyMessage{ + msgSentEvent := testhelpers.TestSendRequest(t, envWithRMN.Env, onChainState, fromChain, toChain, false, router.ClientEVM2AnyMessage{ Receiver: common.LeftPadBytes(onChainState.Chains[toChain].Receiver.Address().Bytes(), 32), Data: []byte("hello world"), TokenAmounts: nil, FeeToken: common.HexToAddress("0x0"), ExtraArgs: nil, }) - seqNumCommit[changeset.SourceDestPair{ + seqNumCommit[testhelpers.SourceDestPair{ SourceChainSelector: fromChain, DestChainSelector: toChain, }] = msgSentEvent.SequenceNumber - seqNumExec[changeset.SourceDestPair{ + seqNumExec[testhelpers.SourceDestPair{ SourceChainSelector: fromChain, DestChainSelector: toChain, }] = []uint64{msgSentEvent.SequenceNumber} @@ -609,12 +608,12 @@ func (tc rmnTestCase) sendMessages(t *testing.T, onChainState changeset.CCIPOnCh return startBlocks, seqNumCommit, seqNumExec } -func (tc rmnTestCase) callContractsToCurseChains(ctx context.Context, t *testing.T, onChainState changeset.CCIPOnChainState, envWithRMN changeset.DeployedEnv) { +func (tc rmnTestCase) callContractsToCurseChains(ctx context.Context, t *testing.T, onChainState changeset.CCIPOnChainState, envWithRMN testhelpers.DeployedEnv) { for _, remoteCfg := range tc.remoteChainsConfig { remoteSel := tc.pf.chainSelectors[remoteCfg.chainIdx] chState, ok := onChainState.Chains[remoteSel] require.True(t, ok) - chain, ok := envWithRMN.Env.Chains[remoteSel] + _, ok = envWithRMN.Env.Chains[remoteSel] require.True(t, ok) cursedSubjects, ok := tc.cursedSubjectsPerChain[remoteCfg.chainIdx] @@ -623,14 +622,19 @@ func (tc rmnTestCase) callContractsToCurseChains(ctx context.Context, t *testing } for _, subjectDescription := range cursedSubjects { - subj := reader.GlobalCurseSubject - if subjectDescription != globalCurse { - subj = chainSelectorToBytes16(tc.pf.chainSelectors[subjectDescription]) + curseActions := make([]changeset.CurseAction, 0) + + if subjectDescription == globalCurse { + curseActions = append(curseActions, changeset.CurseGloballyOnlyOnChain(remoteSel)) + } else { + curseActions = append(curseActions, changeset.CurseLaneOnlyOnSource(remoteSel, tc.pf.chainSelectors[subjectDescription])) } - t.Logf("cursing subject %d (%d)", subj, subjectDescription) - txCurse, errCurse := chState.RMNRemote.Curse(chain.DeployerKey, subj) - _, errConfirm := deployment.ConfirmIfNoError(chain, txCurse, errCurse) - require.NoError(t, errConfirm) + + _, err := changeset.RMNCurseChangeset(envWithRMN.Env, changeset.RMNCurseConfig{ + CurseActions: curseActions, + Reason: "test curse", + }) + require.NoError(t, err) } cs, err := chState.RMNRemote.GetCursedSubjects(&bind.CallOpts{Context: ctx}) @@ -639,55 +643,66 @@ func (tc rmnTestCase) callContractsToCurseChains(ctx context.Context, t *testing } } -func (tc rmnTestCase) callContractsToCurseAndRevokeCurse(ctx context.Context, t *testing.T, onChainState changeset.CCIPOnChainState, envWithRMN changeset.DeployedEnv) { +func (tc rmnTestCase) callContractsToCurseAndRevokeCurse(ctx context.Context, eg *errgroup.Group, t *testing.T, onChainState changeset.CCIPOnChainState, envWithRMN testhelpers.DeployedEnv) { for _, remoteCfg := range tc.remoteChainsConfig { remoteSel := tc.pf.chainSelectors[remoteCfg.chainIdx] chState, ok := onChainState.Chains[remoteSel] require.True(t, ok) - chain, ok := envWithRMN.Env.Chains[remoteSel] + _, ok = envWithRMN.Env.Chains[remoteSel] require.True(t, ok) - cursedSubjects, ok := tc.revokedCursedSubjectsPerChain[remoteCfg.chainIdx] - if !ok { - continue // nothing to curse on this chain - } + cursedSubjects := tc.revokedCursedSubjectsPerChain[remoteCfg.chainIdx] for subjectDescription, revokeAfter := range cursedSubjects { - subj := reader.GlobalCurseSubject - if subjectDescription != globalCurse { - subj = chainSelectorToBytes16(tc.pf.chainSelectors[subjectDescription]) + curseActions := make([]changeset.CurseAction, 0) + + if subjectDescription == globalCurse { + curseActions = append(curseActions, changeset.CurseGloballyOnlyOnChain(remoteSel)) + } else { + curseActions = append(curseActions, changeset.CurseLaneOnlyOnSource(remoteSel, tc.pf.chainSelectors[subjectDescription])) } - t.Logf("cursing subject %d (%d)", subj, subjectDescription) - txCurse, errCurse := chState.RMNRemote.Curse(chain.DeployerKey, subj) - _, errConfirm := deployment.ConfirmIfNoError(chain, txCurse, errCurse) - require.NoError(t, errConfirm) - go func() { + _, err := changeset.RMNCurseChangeset(envWithRMN.Env, changeset.RMNCurseConfig{ + CurseActions: curseActions, + Reason: "test curse", + }) + require.NoError(t, err) + + eg.Go(func() error { <-time.NewTimer(revokeAfter).C - t.Logf("revoking curse on subject %d (%d)", subj, subjectDescription) - txUncurse, errUncurse := chState.RMNRemote.Uncurse(chain.DeployerKey, subj) - _, errConfirm = deployment.ConfirmIfNoError(chain, txUncurse, errUncurse) - require.NoError(t, errConfirm) - }() + t.Logf("revoking curse on subject %d (%d)", subjectDescription, subjectDescription) + + _, err := changeset.RMNUncurseChangeset(envWithRMN.Env, changeset.RMNCurseConfig{ + CurseActions: curseActions, + Reason: "test uncurse", + }) + if err != nil { + return err + } + return nil + }) } - cs, err := chState.RMNRemote.GetCursedSubjects(&bind.CallOpts{Context: ctx}) require.NoError(t, err) - t.Logf("Cursed subjects: %v", cs) + t.Logf("Cursed subjects: %v, %v", cs, remoteSel) + eg.Go(func() error { + <-time.NewTimer(time.Second * 10).C + cs, err := chState.RMNRemote.GetCursedSubjects(&bind.CallOpts{Context: ctx}) + + if err != nil { + return err + } + + t.Logf("Cursed subjects after revoking: %v, %v", cs, remoteSel) + return nil + }) } } -func (tc rmnTestCase) enableOracles(ctx context.Context, t *testing.T, envWithRMN changeset.DeployedEnv, nodeIDs []string) { +func (tc rmnTestCase) enableOracles(ctx context.Context, t *testing.T, envWithRMN testhelpers.DeployedEnv, nodeIDs []string) { for _, n := range nodeIDs { _, err := envWithRMN.Env.Offchain.EnableNode(ctx, &node.EnableNodeRequest{Id: n}) require.NoError(t, err) t.Logf("node %s enabled", n) } } - -func chainSelectorToBytes16(chainSel uint64) [16]byte { - var result [16]byte - // Convert the uint64 to bytes and place it in the last 8 bytes of the array - binary.BigEndian.PutUint64(result[8:], chainSel) - return result -} diff --git a/integration-tests/smoke/ccip/ccip_token_price_updates_test.go b/integration-tests/smoke/ccip/ccip_token_price_updates_test.go index e3496b6f407..8498417a6b6 100644 --- a/integration-tests/smoke/ccip/ccip_token_price_updates_test.go +++ b/integration-tests/smoke/ccip/ccip_token_price_updates_test.go @@ -1,4 +1,4 @@ -package smoke +package ccip import ( "context" @@ -19,23 +19,23 @@ import ( "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" ) func Test_CCIPTokenPriceUpdates(t *testing.T) { - ctx := changeset.Context(t) + ctx := testhelpers.Context(t) callOpts := &bind.CallOpts{Context: ctx} var tokenPriceExpiry = 5 * time.Second - e, _ := testsetups.NewIntegrationEnvironment(t, - changeset.WithOCRConfigOverride(func(params changeset.CCIPOCRParams) changeset.CCIPOCRParams { + e, _, _ := testsetups.NewIntegrationEnvironment(t, + testhelpers.WithOCRConfigOverride(func(params *changeset.CCIPOCRParams) { params.CommitOffChainConfig.TokenPriceBatchWriteFrequency = *config.MustNewDuration(tokenPriceExpiry) - return params })) state, err := changeset.LoadOnchainState(e.Env) require.NoError(t, err) - require.NoError(t, changeset.AddLanesForAll(e.Env, state)) + testhelpers.AddLanesForAll(t, &e, state) allChainSelectors := maps.Keys(e.Env.Chains) assert.GreaterOrEqual(t, len(allChainSelectors), 2, "test requires at least 2 chains") diff --git a/integration-tests/smoke/ccip/ccip_token_transfer_test.go b/integration-tests/smoke/ccip/ccip_token_transfer_test.go index 2088960639e..f612cba523f 100644 --- a/integration-tests/smoke/ccip/ccip_token_transfer_test.go +++ b/integration-tests/smoke/ccip/ccip_token_transfer_test.go @@ -1,4 +1,4 @@ -package smoke +package ccip import ( "math/big" @@ -12,6 +12,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" @@ -22,8 +23,8 @@ func TestTokenTransfer(t *testing.T) { lggr := logger.TestLogger(t) ctx := tests.Context(t) - tenv, _ := testsetups.NewIntegrationEnvironment(t, - changeset.WithUsersPerChain(3)) + tenv, _, _ := testsetups.NewIntegrationEnvironment(t, + testhelpers.WithNumOfUsersPerChain(3)) e := tenv.Env state, err := changeset.LoadOnchainState(e) @@ -43,7 +44,7 @@ func TestTokenTransfer(t *testing.T) { oneE18 := new(big.Int).SetUint64(1e18) // Deploy tokens and pool by CCIP Owner - srcToken, _, destToken, _, err := changeset.DeployTransferableToken( + srcToken, _, destToken, _, err := testhelpers.DeployTransferableToken( lggr, tenv.Env.Chains, sourceChain, @@ -57,7 +58,7 @@ func TestTokenTransfer(t *testing.T) { require.NoError(t, err) // Deploy Self Serve tokens and pool - selfServeSrcToken, _, selfServeDestToken, _, err := changeset.DeployTransferableToken( + selfServeSrcToken, _, selfServeDestToken, _, err := testhelpers.DeployTransferableToken( lggr, tenv.Env.Chains, sourceChain, @@ -69,25 +70,25 @@ func TestTokenTransfer(t *testing.T) { "SELF_SERVE_TOKEN", ) require.NoError(t, err) - require.NoError(t, changeset.AddLanesForAll(e, state)) + testhelpers.AddLanesForAll(t, &tenv, state) - changeset.MintAndAllow( + testhelpers.MintAndAllow( t, e, state, - map[uint64][]changeset.MintTokenInfo{ + map[uint64][]testhelpers.MintTokenInfo{ sourceChain: { - changeset.NewMintTokenInfo(selfServeSrcTokenPoolDeployer, selfServeSrcToken), - changeset.NewMintTokenInfo(ownerSourceChain, srcToken), + testhelpers.NewMintTokenInfo(selfServeSrcTokenPoolDeployer, selfServeSrcToken), + testhelpers.NewMintTokenInfo(ownerSourceChain, srcToken), }, destChain: { - changeset.NewMintTokenInfo(selfServeDestTokenPoolDeployer, selfServeDestToken), - changeset.NewMintTokenInfo(ownerDestChain, destToken), + testhelpers.NewMintTokenInfo(selfServeDestTokenPoolDeployer, selfServeDestToken), + testhelpers.NewMintTokenInfo(ownerDestChain, destToken), }, }, ) - tcs := []changeset.TestTransferRequest{ + tcs := []testhelpers.TestTransferRequest{ { Name: "Send token to EOA", SourceChain: sourceChain, @@ -102,7 +103,7 @@ func TestTokenTransfer(t *testing.T) { ExpectedTokenBalances: map[common.Address]*big.Int{ destToken.Address(): oneE18, }, - ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, + ExpectedStatus: testhelpers.EXECUTION_STATE_SUCCESS, }, { Name: "Send token to contract", @@ -118,7 +119,7 @@ func TestTokenTransfer(t *testing.T) { ExpectedTokenBalances: map[common.Address]*big.Int{ destToken.Address(): oneE18, }, - ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, + ExpectedStatus: testhelpers.EXECUTION_STATE_SUCCESS, }, { Name: "Send N tokens to contract", @@ -139,12 +140,12 @@ func TestTokenTransfer(t *testing.T) { }, }, Receiver: state.Chains[sourceChain].Receiver.Address(), - ExtraArgs: changeset.MakeEVMExtraArgsV2(300_000, false), + ExtraArgs: testhelpers.MakeEVMExtraArgsV2(300_000, false), ExpectedTokenBalances: map[common.Address]*big.Int{ selfServeSrcToken.Address(): new(big.Int).Add(oneE18, oneE18), srcToken.Address(): oneE18, }, - ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, + ExpectedStatus: testhelpers.EXECUTION_STATE_SUCCESS, }, { Name: "Sending token transfer with custom gasLimits to the EOA is successful", @@ -161,12 +162,12 @@ func TestTokenTransfer(t *testing.T) { }, }, Receiver: utils.RandomAddress(), - ExtraArgs: changeset.MakeEVMExtraArgsV2(1, false), + ExtraArgs: testhelpers.MakeEVMExtraArgsV2(1, false), ExpectedTokenBalances: map[common.Address]*big.Int{ selfServeSrcToken.Address(): oneE18, srcToken.Address(): new(big.Int).Add(oneE18, oneE18), }, - ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, + ExpectedStatus: testhelpers.EXECUTION_STATE_SUCCESS, }, { Name: "Sending PTT with too low gas limit leads to the revert when receiver is a contract", @@ -184,19 +185,19 @@ func TestTokenTransfer(t *testing.T) { }, Receiver: state.Chains[sourceChain].Receiver.Address(), Data: []byte("this should be reverted because gasLimit is too low, no tokens are transferred as well"), - ExtraArgs: changeset.MakeEVMExtraArgsV2(1, false), + ExtraArgs: testhelpers.MakeEVMExtraArgsV2(1, false), ExpectedTokenBalances: map[common.Address]*big.Int{ selfServeSrcToken.Address(): big.NewInt(0), srcToken.Address(): big.NewInt(0), }, - ExpectedStatus: changeset.EXECUTION_STATE_FAILURE, + ExpectedStatus: testhelpers.EXECUTION_STATE_FAILURE, }, } startBlocks, expectedSeqNums, expectedExecutionStates, expectedTokenBalances := - changeset.TransferMultiple(ctx, t, e, state, tcs) + testhelpers.TransferMultiple(ctx, t, e, state, tcs) - err = changeset.ConfirmMultipleCommits( + err = testhelpers.ConfirmMultipleCommits( t, e.Chains, state.Chains, @@ -206,14 +207,14 @@ func TestTokenTransfer(t *testing.T) { ) require.NoError(t, err) - execStates := changeset.ConfirmExecWithSeqNrsForAll( + execStates := testhelpers.ConfirmExecWithSeqNrsForAll( t, e, state, - changeset.SeqNumberRangeToSlice(expectedSeqNums), + testhelpers.SeqNumberRangeToSlice(expectedSeqNums), startBlocks, ) require.Equal(t, expectedExecutionStates, execStates) - changeset.WaitForTokenBalances(ctx, t, e.Chains, expectedTokenBalances) + testhelpers.WaitForTokenBalances(ctx, t, e.Chains, expectedTokenBalances) } diff --git a/integration-tests/smoke/ccip/ccip_usdc_test.go b/integration-tests/smoke/ccip/ccip_usdc_test.go index 174ab941387..acbca534b8f 100644 --- a/integration-tests/smoke/ccip/ccip_usdc_test.go +++ b/integration-tests/smoke/ccip/ccip_usdc_test.go @@ -1,4 +1,4 @@ -package smoke +package ccip import ( "math/big" @@ -14,6 +14,7 @@ import ( "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" @@ -32,10 +33,10 @@ import ( func TestUSDCTokenTransfer(t *testing.T) { lggr := logger.TestLogger(t) ctx := tests.Context(t) - tenv, _ := testsetups.NewIntegrationEnvironment(t, - changeset.WithUsersPerChain(3), - changeset.WithChains(3), - changeset.WithUSDC(), + tenv, _, _ := testsetups.NewIntegrationEnvironment(t, + testhelpers.WithNumOfUsersPerChain(3), + testhelpers.WithNumOfChains(3), + testhelpers.WithUSDC(), ) e := tenv.Env @@ -51,13 +52,13 @@ func TestUSDCTokenTransfer(t *testing.T) { ownerChainC := e.Chains[chainC].DeployerKey ownerChainB := e.Chains[chainB].DeployerKey - aChainUSDC, cChainUSDC, err := changeset.ConfigureUSDCTokenPools(lggr, e.Chains, chainA, chainC, state) + aChainUSDC, cChainUSDC, err := testhelpers.ConfigureUSDCTokenPools(lggr, e.Chains, chainA, chainC, state) require.NoError(t, err) - bChainUSDC, _, err := changeset.ConfigureUSDCTokenPools(lggr, e.Chains, chainB, chainC, state) + bChainUSDC, _, err := testhelpers.ConfigureUSDCTokenPools(lggr, e.Chains, chainB, chainC, state) require.NoError(t, err) - aChainToken, _, cChainToken, _, err := changeset.DeployTransferableToken( + aChainToken, _, cChainToken, _, err := testhelpers.DeployTransferableToken( lggr, tenv.Env.Chains, chainA, @@ -71,21 +72,21 @@ func TestUSDCTokenTransfer(t *testing.T) { require.NoError(t, err) // Add all lanes - require.NoError(t, changeset.AddLanesForAll(e, state)) + testhelpers.AddLanesForAll(t, &tenv, state) - changeset.MintAndAllow( + testhelpers.MintAndAllow( t, e, state, - map[uint64][]changeset.MintTokenInfo{ + map[uint64][]testhelpers.MintTokenInfo{ chainA: { - changeset.NewMintTokenInfo(ownerChainA, aChainUSDC, aChainToken), + testhelpers.NewMintTokenInfo(ownerChainA, aChainUSDC, aChainToken), }, chainB: { - changeset.NewMintTokenInfo(ownerChainB, bChainUSDC), + testhelpers.NewMintTokenInfo(ownerChainB, bChainUSDC), }, chainC: { - changeset.NewMintTokenInfo(ownerChainC, cChainUSDC, cChainToken), + testhelpers.NewMintTokenInfo(ownerChainC, cChainUSDC, cChainToken), }, }, ) @@ -96,7 +97,7 @@ func TestUSDCTokenTransfer(t *testing.T) { // MockE2EUSDCTransmitter always mint 1, see MockE2EUSDCTransmitter.sol for more details tinyOneCoin := new(big.Int).SetUint64(1) - tcs := []changeset.TestTransferRequest{ + tcs := []testhelpers.TestTransferRequest{ { Name: "single USDC token transfer to EOA", Receiver: utils.RandomAddress(), @@ -110,7 +111,7 @@ func TestUSDCTokenTransfer(t *testing.T) { ExpectedTokenBalances: map[common.Address]*big.Int{ aChainUSDC.Address(): tinyOneCoin, }, - ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, + ExpectedStatus: testhelpers.EXECUTION_STATE_SUCCESS, }, { Name: "multiple USDC tokens within the same message", @@ -131,7 +132,7 @@ func TestUSDCTokenTransfer(t *testing.T) { // 2 coins because of the same Receiver aChainUSDC.Address(): new(big.Int).Add(tinyOneCoin, tinyOneCoin), }, - ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, + ExpectedStatus: testhelpers.EXECUTION_STATE_SUCCESS, }, { Name: "USDC token together with another token transferred to EOA", @@ -152,7 +153,7 @@ func TestUSDCTokenTransfer(t *testing.T) { cChainUSDC.Address(): tinyOneCoin, cChainToken.Address(): new(big.Int).Mul(tinyOneCoin, big.NewInt(10)), }, - ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, + ExpectedStatus: testhelpers.EXECUTION_STATE_SUCCESS, }, { Name: "USDC programmable token transfer to valid contract receiver", @@ -169,7 +170,7 @@ func TestUSDCTokenTransfer(t *testing.T) { ExpectedTokenBalances: map[common.Address]*big.Int{ cChainUSDC.Address(): tinyOneCoin, }, - ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, + ExpectedStatus: testhelpers.EXECUTION_STATE_SUCCESS, }, { Name: "USDC programmable token transfer with too little gas", @@ -186,8 +187,8 @@ func TestUSDCTokenTransfer(t *testing.T) { ExpectedTokenBalances: map[common.Address]*big.Int{ bChainUSDC.Address(): new(big.Int).SetUint64(0), }, - ExtraArgs: changeset.MakeEVMExtraArgsV2(1, false), - ExpectedStatus: changeset.EXECUTION_STATE_FAILURE, + ExtraArgs: testhelpers.MakeEVMExtraArgsV2(1, false), + ExpectedStatus: testhelpers.EXECUTION_STATE_FAILURE, }, { Name: "USDC token transfer from a different source chain", @@ -204,14 +205,14 @@ func TestUSDCTokenTransfer(t *testing.T) { ExpectedTokenBalances: map[common.Address]*big.Int{ cChainUSDC.Address(): tinyOneCoin, }, - ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, + ExpectedStatus: testhelpers.EXECUTION_STATE_SUCCESS, }, } startBlocks, expectedSeqNums, expectedExecutionStates, expectedTokenBalances := - changeset.TransferMultiple(ctx, t, e, state, tcs) + testhelpers.TransferMultiple(ctx, t, e, state, tcs) - err = changeset.ConfirmMultipleCommits( + err = testhelpers.ConfirmMultipleCommits( t, e.Chains, state.Chains, @@ -221,16 +222,16 @@ func TestUSDCTokenTransfer(t *testing.T) { ) require.NoError(t, err) - execStates := changeset.ConfirmExecWithSeqNrsForAll( + execStates := testhelpers.ConfirmExecWithSeqNrsForAll( t, e, state, - changeset.SeqNumberRangeToSlice(expectedSeqNums), + testhelpers.SeqNumberRangeToSlice(expectedSeqNums), startBlocks, ) require.Equal(t, expectedExecutionStates, execStates) - changeset.WaitForTokenBalances(ctx, t, e.Chains, expectedTokenBalances) + testhelpers.WaitForTokenBalances(ctx, t, e.Chains, expectedTokenBalances) } func updateFeeQuoters( @@ -242,17 +243,17 @@ func updateFeeQuoters( ) error { updateFeeQtrGrp := errgroup.Group{} updateFeeQtrGrp.Go(func() error { - return changeset.UpdateFeeQuoterForUSDC(lggr, e.Chains[chainA], state.Chains[chainA], chainC, aChainUSDC) + return testhelpers.UpdateFeeQuoterForUSDC(lggr, e.Chains[chainA], state.Chains[chainA], chainC, aChainUSDC) }) updateFeeQtrGrp.Go(func() error { - return changeset.UpdateFeeQuoterForUSDC(lggr, e.Chains[chainB], state.Chains[chainB], chainC, bChainUSDC) + return testhelpers.UpdateFeeQuoterForUSDC(lggr, e.Chains[chainB], state.Chains[chainB], chainC, bChainUSDC) }) updateFeeQtrGrp.Go(func() error { - err1 := changeset.UpdateFeeQuoterForUSDC(lggr, e.Chains[chainC], state.Chains[chainC], chainA, cChainUSDC) + err1 := testhelpers.UpdateFeeQuoterForUSDC(lggr, e.Chains[chainC], state.Chains[chainC], chainA, cChainUSDC) if err1 != nil { return err1 } - return changeset.UpdateFeeQuoterForUSDC(lggr, e.Chains[chainC], state.Chains[chainC], chainB, cChainUSDC) + return testhelpers.UpdateFeeQuoterForUSDC(lggr, e.Chains[chainC], state.Chains[chainC], chainB, cChainUSDC) }) return updateFeeQtrGrp.Wait() } diff --git a/integration-tests/testconfig/default.toml b/integration-tests/testconfig/default.toml index 8180b40ae21..792ee36607a 100644 --- a/integration-tests/testconfig/default.toml +++ b/integration-tests/testconfig/default.toml @@ -356,6 +356,7 @@ gas_price_estimation_enabled = true # how many last blocks to use, when estimating gas for a transaction gas_price_estimation_blocks = 100 # priority of the transaction, can be "fast", "standard" or "slow" (the higher the priority, the higher adjustment factor will be used for gas estimation) [default: "standard"] + gas_price_estimation_tx_priority = "standard" diff --git a/integration-tests/testconfig/testconfig.go b/integration-tests/testconfig/testconfig.go index 19e3f0b7ada..3ec61f42607 100644 --- a/integration-tests/testconfig/testconfig.go +++ b/integration-tests/testconfig/testconfig.go @@ -599,6 +599,17 @@ func (c *TestConfig) readNetworkConfiguration() error { c.PrivateEthereumNetwork.EthereumChainConfig.GenerateGenesisTimestamp() } + for _, network := range networks.MustGetSelectedNetworkConfig(c.Network) { + for _, key := range network.PrivateKeys { + address, err := conversions.PrivateKeyHexToAddress(key) + if err != nil { + return errors.Wrapf(err, "error converting private key to address") + } + c.PrivateEthereumNetwork.EthereumChainConfig.AddressesToFund = append( + c.PrivateEthereumNetwork.EthereumChainConfig.AddressesToFund, address.Hex(), + ) + } + } return nil } diff --git a/integration-tests/testsetups/ccip/test_helpers.go b/integration-tests/testsetups/ccip/test_helpers.go index 514a232bb80..59a9bdb47ed 100644 --- a/integration-tests/testsetups/ccip/test_helpers.go +++ b/integration-tests/testsetups/ccip/test_helpers.go @@ -27,6 +27,7 @@ import ( "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" integrationnodes "github.com/smartcontractkit/chainlink/integration-tests/types/config/node" evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" corechainlink "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -52,18 +53,27 @@ import ( // DeployedLocalDevEnvironment is a helper struct for setting up a local dev environment with docker type DeployedLocalDevEnvironment struct { - changeset.DeployedEnv - testEnv *test_env.CLClusterTestEnv - DON *devenv.DON - devEnvTestCfg tc.TestConfig - devEnvCfg *devenv.EnvironmentConfig + testhelpers.DeployedEnv + testEnv *test_env.CLClusterTestEnv + DON *devenv.DON + GenericTCConfig *testhelpers.TestConfigs + devEnvTestCfg tc.TestConfig + devEnvCfg *devenv.EnvironmentConfig } -func (l *DeployedLocalDevEnvironment) DeployedEnvironment() changeset.DeployedEnv { +func (l *DeployedLocalDevEnvironment) DeployedEnvironment() testhelpers.DeployedEnv { return l.DeployedEnv } -func (l *DeployedLocalDevEnvironment) StartChains(t *testing.T, _ *changeset.TestConfigs) { +func (l *DeployedLocalDevEnvironment) UpdateDeployedEnvironment(env testhelpers.DeployedEnv) { + l.DeployedEnv = env +} + +func (l *DeployedLocalDevEnvironment) TestConfigs() *testhelpers.TestConfigs { + return l.GenericTCConfig +} + +func (l *DeployedLocalDevEnvironment) StartChains(t *testing.T) { lggr := logger.TestLogger(t) ctx := testcontext.Get(t) envConfig, testEnv, cfg := CreateDockerEnv(t) @@ -82,7 +92,7 @@ func (l *DeployedLocalDevEnvironment) StartChains(t *testing.T, _ *changeset.Tes require.NotEmpty(t, feedSel, "feedSel should not be empty") chains, err := devenv.NewChains(lggr, envConfig.Chains) require.NoError(t, err) - replayBlocks, err := changeset.LatestBlocksByChain(ctx, chains) + replayBlocks, err := testhelpers.LatestBlocksByChain(ctx, chains) require.NoError(t, err) l.DeployedEnv.Users = users l.DeployedEnv.Env.Chains = chains @@ -91,7 +101,7 @@ func (l *DeployedLocalDevEnvironment) StartChains(t *testing.T, _ *changeset.Tes l.DeployedEnv.ReplayBlocks = replayBlocks } -func (l *DeployedLocalDevEnvironment) StartNodes(t *testing.T, _ *changeset.TestConfigs, crConfig deployment.CapabilityRegistryConfig) { +func (l *DeployedLocalDevEnvironment) StartNodes(t *testing.T, crConfig deployment.CapabilityRegistryConfig) { require.NotNil(t, l.testEnv, "docker env is empty, start chains first") require.NotEmpty(t, l.devEnvTestCfg, "integration test config is empty, start chains first") require.NotNil(t, l.devEnvCfg, "dev environment config is empty, start chains first") @@ -143,8 +153,8 @@ func (l *DeployedLocalDevEnvironment) RestartChainlinkNodes(t *testing.T) error // if CCIP_V16_TEST_ENV is set to 'docker', it creates a docker environment with test config provided under testconfig/ccip/ccip.toml // It also creates a RMN cluster if the test config has RMN enabled // It returns the deployed environment and RMN cluster ( in case of RMN enabled) -func NewIntegrationEnvironment(t *testing.T, opts ...changeset.TestOps) (changeset.DeployedEnv, devenv.RMNCluster) { - testCfg := changeset.DefaultTestConfigs() +func NewIntegrationEnvironment(t *testing.T, opts ...testhelpers.TestOps) (testhelpers.DeployedEnv, devenv.RMNCluster, testhelpers.TestEnvironment) { + testCfg := testhelpers.DefaultTestConfigs() for _, opt := range opts { opt(testCfg) } @@ -152,13 +162,21 @@ func NewIntegrationEnvironment(t *testing.T, opts ...changeset.TestOps) (changes testCfg.MustSetEnvTypeOrDefault(t) require.NoError(t, testCfg.Validate(), "invalid test config") switch testCfg.Type { - case changeset.Memory: - memEnv := changeset.NewMemoryEnvironment(t, opts...) - return memEnv, devenv.RMNCluster{} - case changeset.Docker: - dockerEnv := &DeployedLocalDevEnvironment{} + case testhelpers.Memory: + dEnv, memEnv := testhelpers.NewMemoryEnvironment(t, opts...) + return dEnv, devenv.RMNCluster{}, memEnv + case testhelpers.Docker: + dockerEnv := &DeployedLocalDevEnvironment{ + GenericTCConfig: testCfg, + } + if testCfg.PrerequisiteDeploymentOnly { + deployedEnv := testhelpers.NewEnvironmentWithPrerequisitesContracts(t, dockerEnv) + require.NotNil(t, dockerEnv.testEnv, "empty docker environment") + dockerEnv.UpdateDeployedEnvironment(deployedEnv) + return deployedEnv, devenv.RMNCluster{}, dockerEnv + } if testCfg.RMNEnabled { - deployedEnv := changeset.NewEnvironmentWithJobsAndContracts(t, testCfg, dockerEnv) + deployedEnv := testhelpers.NewEnvironmentWithJobsAndContracts(t, dockerEnv) l := logging.GetTestLogger(t) require.NotNil(t, dockerEnv.testEnv, "empty docker environment") config := GenerateTestRMNConfig(t, testCfg.NumOfRMNNodes, deployedEnv, MustNetworksToRPCMap(dockerEnv.testEnv.EVMNetworks)) @@ -173,25 +191,29 @@ func NewIntegrationEnvironment(t *testing.T, opts ...changeset.TestOps) (changes dockerEnv.devEnvTestCfg.CCIP.RMNConfig.GetAFN2ProxyVersion(), ) require.NoError(t, err) - return deployedEnv, *rmnCluster + dockerEnv.UpdateDeployedEnvironment(deployedEnv) + return deployedEnv, *rmnCluster, dockerEnv } if testCfg.CreateJobAndContracts { - deployedEnv := changeset.NewEnvironmentWithJobsAndContracts(t, testCfg, dockerEnv) + deployedEnv := testhelpers.NewEnvironmentWithJobsAndContracts(t, dockerEnv) require.NotNil(t, dockerEnv.testEnv, "empty docker environment") - return deployedEnv, devenv.RMNCluster{} + dockerEnv.UpdateDeployedEnvironment(deployedEnv) + return deployedEnv, devenv.RMNCluster{}, dockerEnv } if testCfg.CreateJob { - deployedEnv := changeset.NewEnvironmentWithJobs(t, testCfg, dockerEnv) + deployedEnv := testhelpers.NewEnvironmentWithJobs(t, dockerEnv) require.NotNil(t, dockerEnv.testEnv, "empty docker environment") - return deployedEnv, devenv.RMNCluster{} + dockerEnv.UpdateDeployedEnvironment(deployedEnv) + return deployedEnv, devenv.RMNCluster{}, dockerEnv } - deployedEnv := changeset.NewEnvironment(t, testCfg, dockerEnv) + deployedEnv := testhelpers.NewEnvironment(t, dockerEnv) require.NotNil(t, dockerEnv.testEnv, "empty docker environment") - return deployedEnv, devenv.RMNCluster{} + dockerEnv.UpdateDeployedEnvironment(deployedEnv) + return deployedEnv, devenv.RMNCluster{}, dockerEnv default: - require.Failf(t, "Type %s not supported in integration tests choose between %s and %s", string(testCfg.Type), changeset.Memory, changeset.Docker) + require.Failf(t, "Type %s not supported in integration tests choose between %s and %s", string(testCfg.Type), testhelpers.Memory, testhelpers.Docker) } - return changeset.DeployedEnv{}, devenv.RMNCluster{} + return testhelpers.DeployedEnv{}, devenv.RMNCluster{}, nil } func MustNetworksToRPCMap(evmNetworks []*blockchain.EVMNetwork) map[uint64]string { @@ -222,7 +244,7 @@ func MustCCIPNameToRMNName(a string) string { return v } -func GenerateTestRMNConfig(t *testing.T, nRMNNodes int, tenv changeset.DeployedEnv, rpcMap map[uint64]string) map[string]devenv.RMNConfig { +func GenerateTestRMNConfig(t *testing.T, nRMNNodes int, tenv testhelpers.DeployedEnv, rpcMap map[uint64]string) map[string]devenv.RMNConfig { // Find the bootstrappers. nodes, err := deployment.NodeInfo(tenv.Env.NodeIDs, tenv.Env.Offchain) require.NoError(t, err) @@ -440,10 +462,11 @@ func StartChainlinkNodes( cfg.NodeConfig.CommonChainConfigTOML, cfg.NodeConfig.ChainConfigTOMLByChainID, ) - - toml.Capabilities.ExternalRegistry.NetworkID = ptr.Ptr(registryConfig.NetworkType) - toml.Capabilities.ExternalRegistry.ChainID = ptr.Ptr(strconv.FormatUint(registryConfig.EVMChainID, 10)) - toml.Capabilities.ExternalRegistry.Address = ptr.Ptr(registryConfig.Contract.String()) + if registryConfig.Contract != (common.Address{}) { + toml.Capabilities.ExternalRegistry.NetworkID = ptr.Ptr(registryConfig.NetworkType) + toml.Capabilities.ExternalRegistry.ChainID = ptr.Ptr(strconv.FormatUint(registryConfig.EVMChainID, 10)) + toml.Capabilities.ExternalRegistry.Address = ptr.Ptr(registryConfig.Contract.String()) + } if err != nil { return err diff --git a/integration-tests/types/config/node/defaults/ccip.toml b/integration-tests/types/config/node/defaults/ccip.toml new file mode 100644 index 00000000000..13081a2ca1f --- /dev/null +++ b/integration-tests/types/config/node/defaults/ccip.toml @@ -0,0 +1,23 @@ +[Feature] +LogPoller = true +CCIP = true + +[Database] +MaxIdleConns = 50 +MaxOpenConns = 50 + +[OCR2] +Enabled = true +DefaultTransactionQueueDepth = 0 + +[OCR] +Enabled = false +DefaultTransactionQueueDepth = 0 + +[P2P] +[P2P.V2] +Enabled = true +ListenAddresses = ['0.0.0.0:6690'] +AnnounceAddresses = ['0.0.0.0:6690'] +DeltaDial = '500ms' +DeltaReconcile = '5s' \ No newline at end of file diff --git a/integration-tests/types/testconfigs.go b/integration-tests/types/testconfigs.go index 7a72e9a1dfa..16f7253a2e3 100644 --- a/integration-tests/types/testconfigs.go +++ b/integration-tests/types/testconfigs.go @@ -3,7 +3,6 @@ package types import ( ctf_config "github.com/smartcontractkit/chainlink-testing-framework/lib/config" "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" - tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) diff --git a/integration-tests/universal/log_poller/helpers.go b/integration-tests/universal/log_poller/helpers.go index 0c127d576c0..c75bff6c0c2 100644 --- a/integration-tests/universal/log_poller/helpers.go +++ b/integration-tests/universal/log_poller/helpers.go @@ -45,7 +45,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" cltypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ac "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_compatible_utils" - le "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter" + le "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/log_emitter" core_logger "github.com/smartcontractkit/chainlink/v2/core/logger" ) diff --git a/operator_ui/TAG b/operator_ui/TAG index b0d5ea37b87..445e69ce11c 100644 --- a/operator_ui/TAG +++ b/operator_ui/TAG @@ -1 +1 @@ -v0.8.0-445b190 +v0.8.0-95aaf5c diff --git a/package.json b/package.json index 67ad90e3e6d..8a0b5a3ed5d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "chainlink", - "version": "2.18.0", + "version": "2.19.0", "description": "node of the decentralized oracle network, bridging on and off-chain computation", "main": "index.js", "scripts": { diff --git a/plugins/chainlink.Dockerfile b/plugins/chainlink.Dockerfile index a17f5df3898..883aa83c9cf 100644 --- a/plugins/chainlink.Dockerfile +++ b/plugins/chainlink.Dockerfile @@ -12,12 +12,18 @@ RUN go mod download # Env vars needed for chainlink build ARG COMMIT_SHA +# Flags for Go Delve debugger +ARG GO_GCFLAGS + COPY . . RUN apt-get update && apt-get install -y jq +# Install Delve for debugging +RUN go install github.com/go-delve/delve/cmd/dlv@latest + # Build the golang binaries -RUN make install-chainlink +RUN make GO_GCFLAGS="${GO_GCFLAGS}" install-chainlink # Install medianpoc binary RUN make install-medianpoc @@ -52,6 +58,7 @@ WORKDIR /chainlink-starknet/relayer COPY --from=buildgo /chainlink-starknet/relayer . RUN go install ./pkg/chainlink/cmd/chainlink-starknet + # Final image: ubuntu with chainlink binary FROM ubuntu:20.04 @@ -65,6 +72,9 @@ RUN curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \ && apt-get update && apt-get install -y postgresql-client-16 \ && apt-get clean all +# Copy Delve debugger from build stage +COPY --from=buildgo /go/bin/dlv /usr/local/bin/dlv + COPY --from=buildgo /go/bin/chainlink /usr/local/bin/ COPY --from=buildgo /go/bin/chainlink-medianpoc /usr/local/bin/ COPY --from=buildgo /go/bin/chainlink-ocr3-capability /usr/local/bin/ diff --git a/shell.nix b/shell.nix index 4065e7e3def..9860ae78cc5 100644 --- a/shell.nix +++ b/shell.nix @@ -6,6 +6,53 @@ with pkgs; let nodePackages = pkgs.nodePackages.override {inherit nodejs;}; pnpm = pnpm_9; + version = "v2.0.18"; + getBinDerivation = + { + name, + filename, + sha256, + }: + pkgs.stdenv.mkDerivation rec { + inherit name; + url = "https://github.com/anza-xyz/agave/releases/download/${version}/${filename}"; + + nativeBuildInputs = [ + autoPatchelfHook + ]; + + autoPatchelfIgnoreMissingDeps = true; + + buildInputs = with pkgs; [stdenv.cc.cc.libgcc stdenv.cc.cc.lib] ++ lib.optionals stdenv.isLinux [ libudev-zero ]; + + src = pkgs.fetchzip { + inherit url sha256; + }; + + installPhase = '' + mkdir -p $out/bin + ls -lah $src + cp -r $src/bin/* $out/bin + ''; + }; + + solanaBinaries = { + x86_64-linux = getBinDerivation { + name = "solana-cli-x86_64-linux"; + filename = "solana-release-x86_64-unknown-linux-gnu.tar.bz2"; + ### BEGIN_LINUX_SHA256 ### + sha256 = "sha256-3FW6IMZeDtyU4GTsRIwT9BFLNzLPEuP+oiQdur7P13s="; + ### END_LINUX_SHA256 ### + }; + aarch64-apple-darwin = getBinDerivation { + name = "solana-cli-aarch64-apple-darwin"; + filename = "solana-release-aarch64-apple-darwin.tar.bz2"; + ### BEGIN_DARWIN_SHA256 ### + sha256 = "sha256-6VjycYU0NU0evXoqtGAZMYGHQEKijofnFQnBJNVsb6Q="; + ### END_DARWIN_SHA256 ### + }; + }; + mkShell' = mkShell.override { # The current nix default sdk for macOS fails to compile go projects, so we use a newer one for now. stdenv = @@ -50,9 +97,12 @@ in pkg-config libudev-zero libusb1 + solanaBinaries.x86_64-linux ] ++ lib.optionals isCrib [ nur.repos.goreleaser.goreleaser-pro patchelf + ] ++ pkgs.lib.optionals (pkgs.stdenv.isDarwin && pkgs.stdenv.hostPlatform.isAarch64) [ + solanaBinaries.aarch64-apple-darwin ]; shellHook = '' @@ -61,11 +111,10 @@ in echo "GORELEASER_KEY must be set in CRIB environments. You can find it in our 1p vault under 'goreleaser-pro-license'." exit 1 fi - ${if stdenv.isDarwin then "source ./nix-darwin-shell-hook.sh" else ""} + ${if stdenv.isDarwin then "source $(git rev-parse --show-toplevel)/nix-darwin-shell-hook.sh" else ""} ''} ''; - GOROOT = "${go}/share/go"; PGDATA = "db"; CL_DATABASE_URL = "postgresql://chainlink:chainlink@localhost:5432/chainlink_test?sslmode=disable"; } diff --git a/testdata/scripts/chains/help.txtar b/testdata/scripts/chains/help.txtar index ccfb54d2928..5d9a8945ad9 100644 --- a/testdata/scripts/chains/help.txtar +++ b/testdata/scripts/chains/help.txtar @@ -14,6 +14,7 @@ COMMANDS: evm Commands for handling evm chains solana Commands for handling solana chains starknet Commands for handling starknet chains + tron Commands for handling tron chains OPTIONS: --help, -h show help diff --git a/testdata/scripts/chains/tron/help.txtar b/testdata/scripts/chains/tron/help.txtar new file mode 100644 index 00000000000..b0af73f1a25 --- /dev/null +++ b/testdata/scripts/chains/tron/help.txtar @@ -0,0 +1,16 @@ +exec chainlink chains tron --help +cmp stdout out.txt + +-- out.txt -- +NAME: + chainlink chains tron - Commands for handling tron chains + +USAGE: + chainlink chains tron command [command options] [arguments...] + +COMMANDS: + list List all existing tron chains + +OPTIONS: + --help, -h show help + diff --git a/testdata/scripts/chains/tron/list/help.txtar b/testdata/scripts/chains/tron/list/help.txtar new file mode 100644 index 00000000000..ce18cf3de6d --- /dev/null +++ b/testdata/scripts/chains/tron/list/help.txtar @@ -0,0 +1,9 @@ +exec chainlink chains tron list --help +cmp stdout out.txt + +-- out.txt -- +NAME: + chainlink chains tron list - List all existing tron chains + +USAGE: + chainlink chains tron list [arguments...] diff --git a/testdata/scripts/config/merge_raw_configs.txtar b/testdata/scripts/config/merge_raw_configs.txtar index efac49f8ef8..08a6aa74a6a 100644 --- a/testdata/scripts/config/merge_raw_configs.txtar +++ b/testdata/scripts/config/merge_raw_configs.txtar @@ -382,7 +382,8 @@ LatestReportDeadline = '5s' CertFile = '' [Mercury.Transmitter] -TransmitQueueMaxSize = 10000 +Protocol = 'wsrpc' +TransmitQueueMaxSize = 100000 TransmitTimeout = '5s' TransmitConcurrency = 100 diff --git a/testdata/scripts/health/default.txtar b/testdata/scripts/health/default.txtar index 73b82bc7e39..e5b3d4176f6 100644 --- a/testdata/scripts/health/default.txtar +++ b/testdata/scripts/health/default.txtar @@ -32,6 +32,7 @@ HTTPPort = $PORT -- out.txt -- ok HeadReporter +ok Heartbeat ok JobSpawner ok Mailbox.Monitor ok Mercury.WSRPCPool @@ -55,6 +56,15 @@ ok WorkflowDBStore "output": "" } }, + { + "type": "checks", + "id": "Heartbeat", + "attributes": { + "name": "Heartbeat", + "status": "passing", + "output": "" + } + }, { "type": "checks", "id": "JobSpawner", diff --git a/testdata/scripts/health/multi-chain-loopp.txtar b/testdata/scripts/health/multi-chain-loopp.txtar new file mode 100644 index 00000000000..6eaa9d9e26e --- /dev/null +++ b/testdata/scripts/health/multi-chain-loopp.txtar @@ -0,0 +1,498 @@ +env CL_SOLANA_CMD=chainlink-solana +env CL_STARKNET_CMD=chainlink-starknet + +# start node +exec sh -c 'eval "echo \"$(cat config.toml.tmpl)\" > config.toml"' +exec chainlink node -c config.toml start -p password -a creds & + +# initialize client +env NODEURL=http://localhost:$PORT +exec curl --retry 10 --retry-max-time 60 --retry-connrefused $NODEURL +exec chainlink --remote-node-url $NODEURL admin login -file creds --bypass-version-check + +exec chainlink --remote-node-url $NODEURL health +cmp stdout out.txt + +exec chainlink --remote-node-url $NODEURL health -json +cp stdout compact.json +exec jq . compact.json +cmp stdout out.json + +exec chainlink --remote-node-url $NODEURL health -failing +cmp stdout out-unhealthy.txt + +exec chainlink --remote-node-url $NODEURL health -f -json +cp stdout compact.json +exec jq . compact.json +cmp stdout out-unhealthy.json + +-- testdb.txt -- +CL_DATABASE_URL +-- testport.txt -- +PORT + +-- password -- +T.tLHkcmwePT/p,]sYuntjwHKAsrhm#4eRs4LuKHwvHejWYAC2JP4M8HimwgmbaZ +-- creds -- +notreal@fakeemail.ch +fj293fbBnlQ!f9vNs + +-- config.toml.tmpl -- +[Webserver] +HTTPPort = $PORT + +[[Cosmos]] +ChainID = 'Foo' + +[[Cosmos.Nodes]] +Name = 'primary' +TendermintURL = 'http://tender.mint' + +[[EVM]] +ChainID = '1' + +[[EVM.Nodes]] +Name = 'fake' +WSURL = 'wss://foo.bar/ws' +HTTPURL = 'https://foo.bar' + +[[Solana]] +ChainID = 'Bar' + +[[Solana.Nodes]] +Name = 'primary' +URL = 'http://solana.web' + +[[Starknet]] +ChainID = 'Baz' + +[[Starknet.Nodes]] +Name = 'primary' +URL = 'http://stark.node' + +-- out.txt -- +ok Cosmos.Foo.Chain +ok Cosmos.Foo.Relayer +ok Cosmos.Foo.Txm +ok EVM.1 +ok EVM.1.BalanceMonitor +ok EVM.1.HeadBroadcaster +ok EVM.1.HeadTracker +! EVM.1.HeadTracker.HeadListener + Listener is not connected +ok EVM.1.LogBroadcaster +ok EVM.1.Relayer +ok EVM.1.Txm +ok EVM.1.Txm.BlockHistoryEstimator +ok EVM.1.Txm.Broadcaster +ok EVM.1.Txm.Confirmer +ok EVM.1.Txm.Finalizer +ok EVM.1.Txm.WrappedEvmEstimator +ok HeadReporter +ok Heartbeat +ok JobSpawner +ok Mailbox.Monitor +ok Mercury.WSRPCPool +ok Mercury.WSRPCPool.CacheSet +ok PipelineORM +ok PipelineRunner +ok PipelineRunner.BridgeCache +ok RetirementReportCache +ok Solana.Bar.RelayerService +ok Solana.Bar.RelayerService.PluginRelayerClient +ok Solana.Bar.RelayerService.PluginRelayerClient.PluginSolana +ok Solana.Bar.RelayerService.PluginRelayerClient.PluginSolana.Chain +ok Solana.Bar.RelayerService.PluginRelayerClient.PluginSolana.Relayer +ok Solana.Bar.RelayerService.PluginRelayerClient.PluginSolana.Txm +ok StarkNet.Baz.RelayerService +ok StarkNet.Baz.RelayerService.PluginRelayerClient +ok StarkNet.Baz.RelayerService.PluginRelayerClient.PluginStarknet +ok StarkNet.Baz.RelayerService.PluginRelayerClient.PluginStarknet.Chain +ok StarkNet.Baz.RelayerService.PluginRelayerClient.PluginStarknet.Relayer +ok StarkNet.Baz.RelayerService.PluginRelayerClient.PluginStarknet.Txm +ok TelemetryManager +ok WorkflowDBStore + +-- out-unhealthy.txt -- +! EVM.1.HeadTracker.HeadListener + Listener is not connected + +-- out.json -- +{ + "data": [ + { + "type": "checks", + "id": "Cosmos.Foo.Chain", + "attributes": { + "name": "Cosmos.Foo.Chain", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Cosmos.Foo.Relayer", + "attributes": { + "name": "Cosmos.Foo.Relayer", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Cosmos.Foo.Txm", + "attributes": { + "name": "Cosmos.Foo.Txm", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1", + "attributes": { + "name": "EVM.1", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1.BalanceMonitor", + "attributes": { + "name": "EVM.1.BalanceMonitor", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1.HeadBroadcaster", + "attributes": { + "name": "EVM.1.HeadBroadcaster", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1.HeadTracker", + "attributes": { + "name": "EVM.1.HeadTracker", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1.HeadTracker.HeadListener", + "attributes": { + "name": "EVM.1.HeadTracker.HeadListener", + "status": "failing", + "output": "Listener is not connected" + } + }, + { + "type": "checks", + "id": "EVM.1.LogBroadcaster", + "attributes": { + "name": "EVM.1.LogBroadcaster", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1.Relayer", + "attributes": { + "name": "EVM.1.Relayer", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1.Txm", + "attributes": { + "name": "EVM.1.Txm", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1.Txm.BlockHistoryEstimator", + "attributes": { + "name": "EVM.1.Txm.BlockHistoryEstimator", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1.Txm.Broadcaster", + "attributes": { + "name": "EVM.1.Txm.Broadcaster", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1.Txm.Confirmer", + "attributes": { + "name": "EVM.1.Txm.Confirmer", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1.Txm.Finalizer", + "attributes": { + "name": "EVM.1.Txm.Finalizer", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1.Txm.WrappedEvmEstimator", + "attributes": { + "name": "EVM.1.Txm.WrappedEvmEstimator", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "HeadReporter", + "attributes": { + "name": "HeadReporter", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Heartbeat", + "attributes": { + "name": "Heartbeat", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "JobSpawner", + "attributes": { + "name": "JobSpawner", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Mailbox.Monitor", + "attributes": { + "name": "Mailbox.Monitor", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Mercury.WSRPCPool", + "attributes": { + "name": "Mercury.WSRPCPool", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Mercury.WSRPCPool.CacheSet", + "attributes": { + "name": "Mercury.WSRPCPool.CacheSet", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "PipelineORM", + "attributes": { + "name": "PipelineORM", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "PipelineRunner", + "attributes": { + "name": "PipelineRunner", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "PipelineRunner.BridgeCache", + "attributes": { + "name": "PipelineRunner.BridgeCache", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "RetirementReportCache", + "attributes": { + "name": "RetirementReportCache", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Solana.Bar.RelayerService", + "attributes": { + "name": "Solana.Bar.RelayerService", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Solana.Bar.RelayerService.PluginRelayerClient", + "attributes": { + "name": "Solana.Bar.RelayerService.PluginRelayerClient", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Solana.Bar.RelayerService.PluginRelayerClient.PluginSolana", + "attributes": { + "name": "Solana.Bar.RelayerService.PluginRelayerClient.PluginSolana", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Solana.Bar.RelayerService.PluginRelayerClient.PluginSolana.Chain", + "attributes": { + "name": "Solana.Bar.RelayerService.PluginRelayerClient.PluginSolana.Chain", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Solana.Bar.RelayerService.PluginRelayerClient.PluginSolana.Relayer", + "attributes": { + "name": "Solana.Bar.RelayerService.PluginRelayerClient.PluginSolana.Relayer", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Solana.Bar.RelayerService.PluginRelayerClient.PluginSolana.Txm", + "attributes": { + "name": "Solana.Bar.RelayerService.PluginRelayerClient.PluginSolana.Txm", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "StarkNet.Baz.RelayerService", + "attributes": { + "name": "StarkNet.Baz.RelayerService", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "StarkNet.Baz.RelayerService.PluginRelayerClient", + "attributes": { + "name": "StarkNet.Baz.RelayerService.PluginRelayerClient", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "StarkNet.Baz.RelayerService.PluginRelayerClient.PluginStarknet", + "attributes": { + "name": "StarkNet.Baz.RelayerService.PluginRelayerClient.PluginStarknet", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "StarkNet.Baz.RelayerService.PluginRelayerClient.PluginStarknet.Chain", + "attributes": { + "name": "StarkNet.Baz.RelayerService.PluginRelayerClient.PluginStarknet.Chain", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "StarkNet.Baz.RelayerService.PluginRelayerClient.PluginStarknet.Relayer", + "attributes": { + "name": "StarkNet.Baz.RelayerService.PluginRelayerClient.PluginStarknet.Relayer", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "StarkNet.Baz.RelayerService.PluginRelayerClient.PluginStarknet.Txm", + "attributes": { + "name": "StarkNet.Baz.RelayerService.PluginRelayerClient.PluginStarknet.Txm", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "TelemetryManager", + "attributes": { + "name": "TelemetryManager", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "WorkflowDBStore", + "attributes": { + "name": "WorkflowDBStore", + "status": "passing", + "output": "" + } + } + ] +} +-- out-unhealthy.json -- +{ + "data": [ + { + "type": "checks", + "id": "EVM.1.HeadTracker.HeadListener", + "attributes": { + "name": "EVM.1.HeadTracker.HeadListener", + "status": "failing", + "output": "Listener is not connected" + } + } + ] +} diff --git a/testdata/scripts/health/multi-chain.txtar b/testdata/scripts/health/multi-chain.txtar index d3a0caf67b5..5fe2759dcc0 100644 --- a/testdata/scripts/health/multi-chain.txtar +++ b/testdata/scripts/health/multi-chain.txtar @@ -86,6 +86,7 @@ ok EVM.1.Txm.Confirmer ok EVM.1.Txm.Finalizer ok EVM.1.Txm.WrappedEvmEstimator ok HeadReporter +ok Heartbeat ok JobSpawner ok Mailbox.Monitor ok Mercury.WSRPCPool @@ -263,6 +264,15 @@ ok WorkflowDBStore "output": "" } }, + { + "type": "checks", + "id": "Heartbeat", + "attributes": { + "name": "Heartbeat", + "status": "passing", + "output": "" + } + }, { "type": "checks", "id": "JobSpawner", diff --git a/testdata/scripts/help-all/help-all.txtar b/testdata/scripts/help-all/help-all.txtar index 078853ef6a5..87d715edcba 100644 --- a/testdata/scripts/help-all/help-all.txtar +++ b/testdata/scripts/help-all/help-all.txtar @@ -34,6 +34,8 @@ chains solana # Commands for handling solana chains chains solana list # List all existing solana chains chains starknet # Commands for handling starknet chains chains starknet list # List all existing starknet chains +chains tron # Commands for handling tron chains +chains tron list # List all existing tron chains config # Commands for the node's configuration config loglevel # Set log level config logsql # Enable/disable SQL statement logging @@ -111,6 +113,12 @@ keys starknet delete # Delete StarkNet key if present keys starknet export # Export StarkNet key to keyfile keys starknet import # Import StarkNet key from keyfile keys starknet list # List the StarkNet keys +keys tron # Remote commands for administering the node's Tron keys +keys tron create # Create a Tron key +keys tron delete # Delete Tron key if present +keys tron export # Export Tron key to keyfile +keys tron import # Import Tron key from keyfile +keys tron list # List the Tron keys keys vrf # Remote commands for administering the node's vrf keys keys vrf create # Create a VRF key keys vrf delete # Archive or delete VRF key from memory and the database, if present. Note that jobs referencing the removed key will also be removed. @@ -144,6 +152,8 @@ nodes solana # Commands for handling solana node configuration nodes solana list # List all existing solana nodes nodes starknet # Commands for handling starknet node configuration nodes starknet list # List all existing starknet nodes +nodes tron # Commands for handling tron node configuration +nodes tron list # List all existing tron nodes txs # Commands for handling transactions txs cosmos # Commands for handling Cosmos transactions txs cosmos create # Send of from node Cosmos account to destination . diff --git a/testdata/scripts/keys/help.txtar b/testdata/scripts/keys/help.txtar index 83253d6906d..e930b928f54 100644 --- a/testdata/scripts/keys/help.txtar +++ b/testdata/scripts/keys/help.txtar @@ -18,6 +18,7 @@ COMMANDS: solana Remote commands for administering the node's Solana keys starknet Remote commands for administering the node's StarkNet keys aptos Remote commands for administering the node's Aptos keys + tron Remote commands for administering the node's Tron keys vrf Remote commands for administering the node's vrf keys OPTIONS: diff --git a/testdata/scripts/keys/tron/help.txtar b/testdata/scripts/keys/tron/help.txtar new file mode 100644 index 00000000000..6e0b8bf31a2 --- /dev/null +++ b/testdata/scripts/keys/tron/help.txtar @@ -0,0 +1,20 @@ +exec chainlink keys tron --help +cmp stdout out.txt + +-- out.txt -- +NAME: + chainlink keys tron - Remote commands for administering the node's Tron keys + +USAGE: + chainlink keys tron command [command options] [arguments...] + +COMMANDS: + create Create a Tron key + import Import Tron key from keyfile + export Export Tron key to keyfile + delete Delete Tron key if present + list List the Tron keys + +OPTIONS: + --help, -h show help + diff --git a/testdata/scripts/node/validate/default.txtar b/testdata/scripts/node/validate/default.txtar index d4e4a188d2a..135b0c1dbb8 100644 --- a/testdata/scripts/node/validate/default.txtar +++ b/testdata/scripts/node/validate/default.txtar @@ -247,7 +247,8 @@ LatestReportDeadline = '5s' CertFile = '' [Mercury.Transmitter] -TransmitQueueMaxSize = 10000 +Protocol = 'wsrpc' +TransmitQueueMaxSize = 100000 TransmitTimeout = '5s' TransmitConcurrency = 100 diff --git a/testdata/scripts/node/validate/defaults-override.txtar b/testdata/scripts/node/validate/defaults-override.txtar index 336f170bd1b..2acde4e13b6 100644 --- a/testdata/scripts/node/validate/defaults-override.txtar +++ b/testdata/scripts/node/validate/defaults-override.txtar @@ -308,7 +308,8 @@ LatestReportDeadline = '5s' CertFile = '' [Mercury.Transmitter] -TransmitQueueMaxSize = 10000 +Protocol = 'wsrpc' +TransmitQueueMaxSize = 100000 TransmitTimeout = '5s' TransmitConcurrency = 100 @@ -393,6 +394,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '9m0s' [EVM.Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -403,6 +405,9 @@ ResendAfterThreshold = '1m0s' [EVM.Transactions.AutoPurge] Enabled = false +[EVM.Transactions.TransactionManagerV2] +Enabled = false + [EVM.BalanceMonitor] Enabled = true diff --git a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar index 677058e1c08..d061e4468ec 100644 --- a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar @@ -291,7 +291,8 @@ LatestReportDeadline = '5s' CertFile = '' [Mercury.Transmitter] -TransmitQueueMaxSize = 10000 +Protocol = 'wsrpc' +TransmitQueueMaxSize = 100000 TransmitTimeout = '5s' TransmitConcurrency = 100 @@ -376,6 +377,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '9m0s' [EVM.Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -386,6 +388,9 @@ ResendAfterThreshold = '1m0s' [EVM.Transactions.AutoPurge] Enabled = false +[EVM.Transactions.TransactionManagerV2] +Enabled = false + [EVM.BalanceMonitor] Enabled = true diff --git a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar index 0e5a78f4a39..b5609655977 100644 --- a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar @@ -291,7 +291,8 @@ LatestReportDeadline = '5s' CertFile = '' [Mercury.Transmitter] -TransmitQueueMaxSize = 10000 +Protocol = 'wsrpc' +TransmitQueueMaxSize = 100000 TransmitTimeout = '5s' TransmitConcurrency = 100 @@ -376,6 +377,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '9m0s' [EVM.Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -386,6 +388,9 @@ ResendAfterThreshold = '1m0s' [EVM.Transactions.AutoPurge] Enabled = false +[EVM.Transactions.TransactionManagerV2] +Enabled = false + [EVM.BalanceMonitor] Enabled = true diff --git a/testdata/scripts/node/validate/disk-based-logging.txtar b/testdata/scripts/node/validate/disk-based-logging.txtar index 7fc05533a47..217a78a7c3c 100644 --- a/testdata/scripts/node/validate/disk-based-logging.txtar +++ b/testdata/scripts/node/validate/disk-based-logging.txtar @@ -291,7 +291,8 @@ LatestReportDeadline = '5s' CertFile = '' [Mercury.Transmitter] -TransmitQueueMaxSize = 10000 +Protocol = 'wsrpc' +TransmitQueueMaxSize = 100000 TransmitTimeout = '5s' TransmitConcurrency = 100 @@ -376,6 +377,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '9m0s' [EVM.Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -386,6 +388,9 @@ ResendAfterThreshold = '1m0s' [EVM.Transactions.AutoPurge] Enabled = false +[EVM.Transactions.TransactionManagerV2] +Enabled = false + [EVM.BalanceMonitor] Enabled = true diff --git a/testdata/scripts/node/validate/fallback-override.txtar b/testdata/scripts/node/validate/fallback-override.txtar new file mode 100644 index 00000000000..5cc001850d6 --- /dev/null +++ b/testdata/scripts/node/validate/fallback-override.txtar @@ -0,0 +1,559 @@ +# test with defaults +env CL_CHAIN_DEFAULTS= +exec chainlink node -c config.toml -s secrets.toml validate +cmp stdout out.txt + +# test with fallback override +env CL_CHAIN_DEFAULTS=default_overrides +exec chainlink node -c config.toml -s secrets.toml validate +! cmp stdout out.txt + +-- default_overrides/evm/fallback.toml -- +AutoCreateKey = true +BlockBackfillDepth = 1000000 +BlockBackfillSkip = false +FinalityDepth = 50 +FinalityTagEnabled = false +LogBackfillBatchSize = 1000 +LogPollInterval = '15s' +LogKeepBlocksDepth = 100000 +LogPrunePageSize = 0 +BackupLogPollerBlockDelay = 100 +MinContractPayment = '.00001 link' +MinIncomingConfirmations = 3 +NonceAutoSync = true +NoNewHeadsThreshold = '3m' +RPCDefaultBatchSize = 250 +RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 +NoNewFinalizedHeadsThreshold = '0' +LogBroadcasterEnabled = true + +[Transactions] +ForwardersEnabled = false +MaxInFlight = 16 +MaxQueued = 250 +ReaperInterval = '1h' +ReaperThreshold = '168h' +ResendAfterThreshold = '1m' + +[Transactions.AutoPurge] +Enabled = false + +[Transactions.TransactionManagerV2] +Enabled = false + +[BalanceMonitor] +Enabled = true + +[GasEstimator] +Mode = 'BlockHistory' +PriceDefault = '20 gwei' +PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' +PriceMin = '1 gwei' +LimitDefault = 500_000 +LimitMax = 500_000 +LimitMultiplier = '1' +LimitTransfer = 21_000 +BumpMin = '5 gwei' +BumpPercent = 20 +BumpThreshold = 3 +EIP1559DynamicFees = false +FeeCapDefault = '100 gwei' +TipCapDefault = '1' +TipCapMin = '1' +EstimateLimit = false + +[GasEstimator.BlockHistory] +BatchSize = 25 +BlockHistorySize = 8 +CheckInclusionBlocks = 12 +CheckInclusionPercentile = 90 +TransactionPercentile = 60 + +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + +[HeadTracker] +HistoryDepth = 100 +MaxBufferSize = 3 +SamplingInterval = '1s' +FinalityTagBypass = true +MaxAllowedFinalityDepth = 10000 +PersistenceEnabled = true + +[NodePool] +PollFailureThreshold = 5 +PollInterval = '10s' +SelectionMode = 'HighestHead' +SyncThreshold = 5 +LeaseDuration = '0s' +NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = true +DeathDeclarationDelay = '1m' +NewHeadsPollInterval = '0s' + +[OCR] +ContractConfirmations = 4 +ContractTransmitterTransmitTimeout = '10s' +DatabaseTimeout = '10s' +DeltaCOverride = '168h' +DeltaCJitterOverride = '1h' +ObservationGracePeriod = '1s' + +[OCR2.Automation] +GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400_000 + +-- config.toml -- +Log.Level = 'debug' + +[[EVM]] +ChainID = '1' + +[[EVM.Nodes]] +Name = 'fake' +WSURL = 'wss://foo.bar/ws' +HTTPURL = 'https://foo.bar' + +-- secrets.toml -- +[Database] +URL = 'postgresql://user:pass1234567890abcd@localhost:5432/dbname?sslmode=disable' + +[Password] +Keystore = 'keystore_pass' + +-- out.txt -- +# Secrets: +[Database] +URL = 'xxxxx' +AllowSimplePasswords = false + +[Password] +Keystore = 'xxxxx' + +# Input Configuration: +[Log] +Level = 'debug' + +[[EVM]] +ChainID = '1' + +[[EVM.Nodes]] +Name = 'fake' +WSURL = 'wss://foo.bar/ws' +HTTPURL = 'https://foo.bar' + +# Effective Configuration, with defaults applied: +InsecureFastScrypt = false +RootDir = '~/.chainlink' +ShutdownGracePeriod = '5s' + +[Feature] +FeedsManager = true +LogPoller = false +UICSAKeys = false +CCIP = true +MultiFeedsManagers = false + +[Database] +DefaultIdleInTxSessionTimeout = '1h0m0s' +DefaultLockTimeout = '15s' +DefaultQueryTimeout = '10s' +LogQueries = false +MaxIdleConns = 10 +MaxOpenConns = 100 +MigrateOnStartup = true + +[Database.Backup] +Dir = '' +Frequency = '1h0m0s' +Mode = 'none' +OnVersionUpgrade = true + +[Database.Listener] +MaxReconnectDuration = '10m0s' +MinReconnectInterval = '1m0s' +FallbackPollInterval = '30s' + +[Database.Lock] +Enabled = true +LeaseDuration = '10s' +LeaseRefreshInterval = '1s' + +[TelemetryIngress] +UniConn = false +Logging = false +BufferSize = 100 +MaxBatchSize = 50 +SendInterval = '500ms' +SendTimeout = '10s' +UseBatchSend = true + +[AuditLogger] +Enabled = false +ForwardToUrl = '' +JsonWrapperKey = '' +Headers = [] + +[Log] +Level = 'debug' +JSONConsole = false +UnixTS = false + +[Log.File] +Dir = '' +MaxSize = '5.12gb' +MaxAgeDays = 0 +MaxBackups = 1 + +[WebServer] +AuthenticationMethod = 'local' +AllowOrigins = 'http://localhost:3000,http://localhost:6688' +BridgeResponseURL = '' +BridgeCacheTTL = '0s' +HTTPWriteTimeout = '10s' +HTTPPort = 6688 +SecureCookies = true +SessionTimeout = '15m0s' +SessionReaperExpiration = '240h0m0s' +HTTPMaxSize = '32.77kb' +StartTimeout = '15s' +ListenIP = '0.0.0.0' + +[WebServer.LDAP] +ServerTLS = true +SessionTimeout = '15m0s' +QueryTimeout = '2m0s' +BaseUserAttr = 'uid' +BaseDN = '' +UsersDN = 'ou=users' +GroupsDN = 'ou=groups' +ActiveAttribute = '' +ActiveAttributeAllowedValue = '' +AdminUserGroupCN = 'NodeAdmins' +EditUserGroupCN = 'NodeEditors' +RunUserGroupCN = 'NodeRunners' +ReadUserGroupCN = 'NodeReadOnly' +UserApiTokenEnabled = false +UserAPITokenDuration = '240h0m0s' +UpstreamSyncInterval = '0s' +UpstreamSyncRateLimit = '2m0s' + +[WebServer.MFA] +RPID = '' +RPOrigin = '' + +[WebServer.RateLimit] +Authenticated = 1000 +AuthenticatedPeriod = '1m0s' +Unauthenticated = 5 +UnauthenticatedPeriod = '20s' + +[WebServer.TLS] +CertPath = '' +ForceRedirect = false +Host = '' +HTTPSPort = 6689 +KeyPath = '' +ListenIP = '0.0.0.0' + +[JobPipeline] +ExternalInitiatorsEnabled = false +MaxRunDuration = '10m0s' +MaxSuccessfulRuns = 10000 +ReaperInterval = '1h0m0s' +ReaperThreshold = '24h0m0s' +ResultWriteQueueDepth = 100 +VerboseLogging = true + +[JobPipeline.HTTPRequest] +DefaultTimeout = '15s' +MaxSize = '32.77kb' + +[FluxMonitor] +DefaultTransactionQueueDepth = 1 +SimulateTransactions = false + +[OCR2] +Enabled = false +ContractConfirmations = 3 +BlockchainTimeout = '20s' +ContractPollInterval = '1m0s' +ContractSubscribeInterval = '2m0s' +ContractTransmitterTransmitTimeout = '10s' +DatabaseTimeout = '10s' +KeyBundleID = '0000000000000000000000000000000000000000000000000000000000000000' +CaptureEATelemetry = false +CaptureAutomationCustomTelemetry = true +DefaultTransactionQueueDepth = 1 +SimulateTransactions = false +TraceLogging = false + +[OCR] +Enabled = false +ObservationTimeout = '5s' +BlockchainTimeout = '20s' +ContractPollInterval = '1m0s' +ContractSubscribeInterval = '2m0s' +DefaultTransactionQueueDepth = 1 +KeyBundleID = '0000000000000000000000000000000000000000000000000000000000000000' +SimulateTransactions = false +TransmitterAddress = '' +CaptureEATelemetry = false +TraceLogging = false + +[P2P] +IncomingMessageBufferSize = 10 +OutgoingMessageBufferSize = 10 +PeerID = '' +TraceLogging = false + +[P2P.V2] +Enabled = true +AnnounceAddresses = [] +DefaultBootstrappers = [] +DeltaDial = '15s' +DeltaReconcile = '1m0s' +ListenAddresses = [] + +[Keeper] +DefaultTransactionQueueDepth = 1 +GasPriceBufferPercent = 20 +GasTipCapBufferPercent = 20 +BaseFeeBufferPercent = 20 +MaxGracePeriod = 100 +TurnLookBack = 1000 + +[Keeper.Registry] +CheckGasOverhead = 200000 +PerformGasOverhead = 300000 +MaxPerformDataSize = 5000 +SyncInterval = '30m0s' +SyncUpkeepQueueSize = 10 + +[AutoPprof] +Enabled = false +ProfileRoot = '' +PollInterval = '10s' +GatherDuration = '10s' +GatherTraceDuration = '5s' +MaxProfileSize = '100.00mb' +CPUProfileRate = 1 +MemProfileRate = 1 +BlockProfileRate = 1 +MutexProfileFraction = 1 +MemThreshold = '4.00gb' +GoroutineThreshold = 5000 + +[Pyroscope] +ServerAddress = '' +Environment = 'mainnet' + +[Sentry] +Debug = false +DSN = '' +Environment = '' +Release = '' + +[Insecure] +DevWebServer = false +OCRDevelopmentMode = false +InfiniteDepthQueries = false +DisableRateLimiting = false + +[Tracing] +Enabled = false +CollectorTarget = '' +NodeID = '' +SamplingRatio = 0.0 +Mode = 'tls' +TLSCertPath = '' + +[Mercury] +VerboseLogging = false + +[Mercury.Cache] +LatestReportTTL = '1s' +MaxStaleAge = '1h0m0s' +LatestReportDeadline = '5s' + +[Mercury.TLS] +CertFile = '' + +[Mercury.Transmitter] +Protocol = 'wsrpc' +TransmitQueueMaxSize = 100000 +TransmitTimeout = '5s' +TransmitConcurrency = 100 + +[Capabilities] +[Capabilities.Peering] +IncomingMessageBufferSize = 10 +OutgoingMessageBufferSize = 10 +PeerID = '' +TraceLogging = false + +[Capabilities.Peering.V2] +Enabled = false +AnnounceAddresses = [] +DefaultBootstrappers = [] +DeltaDial = '15s' +DeltaReconcile = '1m0s' +ListenAddresses = [] + +[Capabilities.Dispatcher] +SupportedVersion = 1 +ReceiverBufferSize = 10000 + +[Capabilities.Dispatcher.RateLimit] +GlobalRPS = 800.0 +GlobalBurst = 1000 +PerSenderRPS = 10.0 +PerSenderBurst = 50 + +[Capabilities.ExternalRegistry] +Address = '' +NetworkID = 'evm' +ChainID = '1' + +[Capabilities.WorkflowRegistry] +Address = '' +NetworkID = 'evm' +ChainID = '1' + +[Capabilities.GatewayConnector] +ChainIDForNodeKey = '' +NodeAddress = '' +DonID = '' +WSHandshakeTimeoutMillis = 0 +AuthMinChallengeLen = 0 +AuthTimestampToleranceSec = 0 + +[[Capabilities.GatewayConnector.Gateways]] +ID = '' +URL = '' + +[Telemetry] +Enabled = false +CACertFile = '' +Endpoint = '' +InsecureConnection = false +TraceSampleRatio = 0.01 +EmitterBatchProcessor = true +EmitterExportTimeout = '1s' + +[[EVM]] +ChainID = '1' +AutoCreateKey = true +BlockBackfillDepth = 10 +BlockBackfillSkip = false +FinalityDepth = 50 +FinalityTagEnabled = true +LinkContractAddress = '0x514910771AF9Ca656af840dff83E8264EcF986CA' +LogBackfillBatchSize = 1000 +LogPollInterval = '15s' +LogKeepBlocksDepth = 100000 +LogPrunePageSize = 0 +BackupLogPollerBlockDelay = 100 +MinIncomingConfirmations = 3 +MinContractPayment = '0.1 link' +NonceAutoSync = true +NoNewHeadsThreshold = '3m0s' +OperatorFactoryAddress = '0x3E64Cd889482443324F91bFA9c84fE72A511f48A' +LogBroadcasterEnabled = true +RPCDefaultBatchSize = 250 +RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 +NoNewFinalizedHeadsThreshold = '9m0s' + +[EVM.Transactions] +Enabled = true +ForwardersEnabled = false +MaxInFlight = 16 +MaxQueued = 250 +ReaperInterval = '1h0m0s' +ReaperThreshold = '168h0m0s' +ResendAfterThreshold = '1m0s' + +[EVM.Transactions.AutoPurge] +Enabled = false + +[EVM.Transactions.TransactionManagerV2] +Enabled = false + +[EVM.BalanceMonitor] +Enabled = true + +[EVM.GasEstimator] +Mode = 'BlockHistory' +PriceDefault = '20 gwei' +PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' +PriceMin = '1 gwei' +LimitDefault = 500000 +LimitMax = 500000 +LimitMultiplier = '1' +LimitTransfer = 21000 +EstimateLimit = false +BumpMin = '5 gwei' +BumpPercent = 20 +BumpThreshold = 3 +EIP1559DynamicFees = true +FeeCapDefault = '100 gwei' +TipCapDefault = '1 wei' +TipCapMin = '1 wei' + +[EVM.GasEstimator.BlockHistory] +BatchSize = 25 +BlockHistorySize = 4 +CheckInclusionBlocks = 12 +CheckInclusionPercentile = 90 +TransactionPercentile = 50 + +[EVM.GasEstimator.FeeHistory] +CacheTimeout = '10s' + +[EVM.HeadTracker] +HistoryDepth = 100 +MaxBufferSize = 3 +SamplingInterval = '1s' +MaxAllowedFinalityDepth = 10000 +FinalityTagBypass = true +PersistenceEnabled = true + +[EVM.NodePool] +PollFailureThreshold = 5 +PollInterval = '10s' +SelectionMode = 'HighestHead' +SyncThreshold = 5 +LeaseDuration = '0s' +NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = true +DeathDeclarationDelay = '1m0s' +NewHeadsPollInterval = '0s' + +[EVM.OCR] +ContractConfirmations = 4 +ContractTransmitterTransmitTimeout = '10s' +DatabaseTimeout = '10s' +DeltaCOverride = '168h0m0s' +DeltaCJitterOverride = '1h0m0s' +ObservationGracePeriod = '1s' + +[EVM.OCR2] +[EVM.OCR2.Automation] +GasLimit = 10500000 + +[EVM.Workflow] +GasLimitDefault = 400000 + +[[EVM.Nodes]] +Name = 'fake' +WSURL = 'wss://foo.bar/ws' +HTTPURL = 'https://foo.bar' + +Valid configuration. diff --git a/testdata/scripts/node/validate/invalid-duplicates.txtar b/testdata/scripts/node/validate/invalid-duplicates.txtar index 84e6c23aa71..d13fff5f620 100644 --- a/testdata/scripts/node/validate/invalid-duplicates.txtar +++ b/testdata/scripts/node/validate/invalid-duplicates.txtar @@ -63,6 +63,19 @@ URL = 'http://stark.node' Name = 'primary' URL = 'http://stark.node' +[[Tron]] +ChainID = '1' + +[[Tron]] +ChainID = '1' + +[[Tron.Nodes]] +Name = 'fake' +URL = 'https://foo.bar' + +[[Tron.Nodes]] +Name = 'fake' +URL = 'https://foo.bar' -- secrets.toml -- [Database] @@ -74,7 +87,7 @@ Keystore = '' -- out.txt -- -- err.txt -- -Error running app: invalid configuration: 4 errors: +Error running app: invalid configuration: 5 errors: - EVM: 4 errors: - 1.ChainID: invalid value (1): duplicate - must be unique - 1.Nodes.1.Name: invalid value (fake): duplicate - must be unique @@ -92,3 +105,6 @@ Error running app: invalid configuration: 4 errors: - 1.ChainID: invalid value (foobar): duplicate - must be unique - 1.Nodes.1.Name: invalid value (primary): duplicate - must be unique - 1.Nodes.1.URL: invalid value (http://stark.node): duplicate - must be unique + - Tron: 2 errors: + - 1.ChainID: invalid value (1): duplicate - must be unique + - 1.Nodes.1.Name: invalid value (fake): duplicate - must be unique diff --git a/testdata/scripts/node/validate/invalid-ocr-p2p.txtar b/testdata/scripts/node/validate/invalid-ocr-p2p.txtar index 2cc7b7afe0e..5bf99757698 100644 --- a/testdata/scripts/node/validate/invalid-ocr-p2p.txtar +++ b/testdata/scripts/node/validate/invalid-ocr-p2p.txtar @@ -276,7 +276,8 @@ LatestReportDeadline = '5s' CertFile = '' [Mercury.Transmitter] -TransmitQueueMaxSize = 10000 +Protocol = 'wsrpc' +TransmitQueueMaxSize = 100000 TransmitTimeout = '5s' TransmitConcurrency = 100 diff --git a/testdata/scripts/node/validate/invalid.txtar b/testdata/scripts/node/validate/invalid.txtar index b048af38a3b..4d42750c96d 100644 --- a/testdata/scripts/node/validate/invalid.txtar +++ b/testdata/scripts/node/validate/invalid.txtar @@ -281,7 +281,8 @@ LatestReportDeadline = '5s' CertFile = '' [Mercury.Transmitter] -TransmitQueueMaxSize = 10000 +Protocol = 'wsrpc' +TransmitQueueMaxSize = 100000 TransmitTimeout = '5s' TransmitConcurrency = 100 @@ -366,6 +367,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '9m0s' [EVM.Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -376,6 +378,9 @@ ResendAfterThreshold = '1m0s' [EVM.Transactions.AutoPurge] Enabled = false +[EVM.Transactions.TransactionManagerV2] +Enabled = false + [EVM.BalanceMonitor] Enabled = true diff --git a/testdata/scripts/node/validate/valid.txtar b/testdata/scripts/node/validate/valid.txtar index bc84a9b2a37..eef870f2280 100644 --- a/testdata/scripts/node/validate/valid.txtar +++ b/testdata/scripts/node/validate/valid.txtar @@ -288,7 +288,8 @@ LatestReportDeadline = '5s' CertFile = '' [Mercury.Transmitter] -TransmitQueueMaxSize = 10000 +Protocol = 'wsrpc' +TransmitQueueMaxSize = 100000 TransmitTimeout = '5s' TransmitConcurrency = 100 @@ -373,6 +374,7 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '9m0s' [EVM.Transactions] +Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -383,6 +385,9 @@ ResendAfterThreshold = '1m0s' [EVM.Transactions.AutoPurge] Enabled = false +[EVM.Transactions.TransactionManagerV2] +Enabled = false + [EVM.BalanceMonitor] Enabled = true diff --git a/testdata/scripts/node/validate/warnings.txtar b/testdata/scripts/node/validate/warnings.txtar index 85b7bc6a253..3174dab46ae 100644 --- a/testdata/scripts/node/validate/warnings.txtar +++ b/testdata/scripts/node/validate/warnings.txtar @@ -270,7 +270,8 @@ LatestReportDeadline = '5s' CertFile = '' [Mercury.Transmitter] -TransmitQueueMaxSize = 10000 +Protocol = 'wsrpc' +TransmitQueueMaxSize = 100000 TransmitTimeout = '5s' TransmitConcurrency = 100 diff --git a/testdata/scripts/nodes/help.txtar b/testdata/scripts/nodes/help.txtar index f9132045d29..c8409d62691 100644 --- a/testdata/scripts/nodes/help.txtar +++ b/testdata/scripts/nodes/help.txtar @@ -14,6 +14,7 @@ COMMANDS: evm Commands for handling evm node configuration solana Commands for handling solana node configuration starknet Commands for handling starknet node configuration + tron Commands for handling tron node configuration OPTIONS: --help, -h show help diff --git a/testdata/scripts/nodes/tron/help.txtar b/testdata/scripts/nodes/tron/help.txtar new file mode 100644 index 00000000000..e35e174e6d8 --- /dev/null +++ b/testdata/scripts/nodes/tron/help.txtar @@ -0,0 +1,16 @@ +exec chainlink nodes tron --help +cmp stdout out.txt + +-- out.txt -- +NAME: + chainlink nodes tron - Commands for handling tron node configuration + +USAGE: + chainlink nodes tron command [command options] [arguments...] + +COMMANDS: + list List all existing tron nodes + +OPTIONS: + --help, -h show help + diff --git a/testdata/scripts/nodes/tron/list/help.txtar b/testdata/scripts/nodes/tron/list/help.txtar new file mode 100644 index 00000000000..08c9d07d56b --- /dev/null +++ b/testdata/scripts/nodes/tron/list/help.txtar @@ -0,0 +1,9 @@ +exec chainlink nodes tron list --help +cmp stdout out.txt + +-- out.txt -- +NAME: + chainlink nodes tron list - List all existing tron nodes + +USAGE: + chainlink nodes tron list [arguments...] diff --git a/tools/bin/go_core_scripts_tests b/tools/bin/go_core_scripts_tests new file mode 100755 index 00000000000..e4380264215 --- /dev/null +++ b/tools/bin/go_core_scripts_tests @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +set -o pipefail +set +e + +SCRIPT_PATH=`dirname "$0"`; SCRIPT_PATH=`eval "cd \"$SCRIPT_PATH\" && pwd"` +OUTPUT_FILE=${OUTPUT_FILE:-"./output.txt"} +EXTRA_FLAGS="" + +cd ./core/scripts || exit +go mod download +echo "Test execution results: ---------------------" +echo "" + +if [[ $GITHUB_EVENT_NAME == "schedule" ]]; then + EXTRA_FLAGS="-covermode=atomic -coverpkg=./... -coverprofile=coverage.txt" +fi +go test ./... $EXTRA_FLAGS | tee $OUTPUT_FILE | grep -Ev '\[no test files\]|\[no tests to run\]' +EXITCODE=${PIPESTATUS[0]} + +# Assert no known sensitive strings present in test logger output +printf "\n----------------------------------------------\n\n" +echo "Beginning check of output logs for sensitive strings" +$SCRIPT_PATH/scrub_logs $OUTPUT_FILE +cd .. +if [[ $? != 0 ]]; then + exit 1 +fi + +echo "Exit code: $EXITCODE" +if [[ $EXITCODE != 0 ]]; then + echo "Encountered test failures." +else + echo "All tests passed!" +fi +echo "go_core_scripts_tests exiting with code $EXITCODE" +exit $EXITCODE diff --git a/tools/bin/go_core_tests b/tools/bin/go_core_tests index 76c15fccd07..3679988a896 100755 --- a/tools/bin/go_core_tests +++ b/tools/bin/go_core_tests @@ -29,4 +29,4 @@ else echo "All tests passed!" fi echo "go_core_tests exiting with code $EXITCODE" -exit $EXITCODE +exit $EXITCODE \ No newline at end of file diff --git a/tools/bin/goreleaser_utils b/tools/bin/goreleaser_utils index 0bf745d5a58..e38acf6494b 100755 --- a/tools/bin/goreleaser_utils +++ b/tools/bin/goreleaser_utils @@ -13,6 +13,7 @@ before_hook() { install_local_plugins install_remote_plugins mkdir -p "$lib_path/plugins" + build_standard_capabilities # Retrieve GOPATH GOPATH=$(go env GOPATH) @@ -71,6 +72,15 @@ get_remote_plugin_paths() { done } +build_standard_capabilities() { + cd ./capabilities + npx nx@19.8.2 init + ./nx run-many -t build + # binaries get put into /bin under /bin/amd64/ and /bin/arm64/ + cp "./bin/$(go env GOARCH)"/* "../$lib_path/plugins" + cd ../ +} + install_remote_plugins() { ldflags=(-ldflags "$(./tools/bin/ldflags)") diff --git a/tools/ci/ccip_lcov_prune b/tools/ci/ccip_lcov_prune index 9ec51e53536..fadb2cc410c 100755 --- a/tools/ci/ccip_lcov_prune +++ b/tools/ci/ccip_lcov_prune @@ -12,7 +12,6 @@ set -e # BurnWithFromMintTokenPool is excluded because Forge doesn't seem to # register coverage, even though it is 100% covered. - lcov --remove $1 -o $2 \ '*/ccip/test/*' \ '*/vendor/*' \ @@ -23,8 +22,6 @@ lcov --remove $1 -o $2 \ 'src/v0.8/ccip/libraries/USDPriceWith18Decimals.sol' \ 'src/v0.8/ccip/libraries/MerkleMultiProof.sol' \ 'src/v0.8/ccip/libraries/Pool.sol' \ - 'src/v0.8/ConfirmedOwnerWithProposal.sol' \ - 'src/v0.8/tests/MockV3Aggregator.sol' \ 'src/v0.8/ccip/applications/CCIPClientExample.sol' \ 'src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol' \ 'src/v0.8/ccip/rmn/RMNHome.sol' \ diff --git a/tools/goreleaser-config/go.mod b/tools/goreleaser-config/go.mod index f46423b660d..d0e66514869 100644 --- a/tools/goreleaser-config/go.mod +++ b/tools/goreleaser-config/go.mod @@ -1,6 +1,6 @@ module github.com/smartcontractkit/chainlink/tools/goreleaser-config -go 1.23.0 +go 1.22.8 require ( github.com/goreleaser/goreleaser-pro/v2 v2.3.2-pro